* [PATCH v2] MIPS: DECstation I/O ASIC DMA interrupt handling fix
@ 2013-09-17 15:40 Maciej W. Rozycki
2013-09-17 16:13 ` Ralf Baechle
0 siblings, 1 reply; 3+ messages in thread
From: Maciej W. Rozycki @ 2013-09-17 15:40 UTC (permalink / raw
To: Ralf Baechle; +Cc: linux-mips
This change complements commit d0da7c002f7b2a93582187a9e3f73891a01d8ee4
and brings clear_ioasic_irq back, renaming it to clear_ioasic_dma_irq at
the same time, to make I/O ASIC DMA interrupts functional.
Unlike ordinary I/O ASIC interrupts DMA interrupts need to be deasserted
by software by writing 0 to the respective bit in I/O ASIC's System
Interrupt Register (SIR), similarly to how CP0.Cause.IP0 and CP0.Cause.IP1
bits are handled in the CPU (the difference is SIR DMA interrupt bits are
R/W0C so there's no need for an RMW cycle). Otherwise the handler is
reentered over and over again.
The only current user is the DEC LANCE Ethernet driver and its extremely
uncommon DMA memory error handler that has never cared when exactly the
interrupt is cleared (it has to be investigated whether this is actually
the correct approach though). Anticipating the use of DMA interrupts by
the Zilog SCC driver this change however implements handling for the two
classes of DMA interrupts the I/O ASIC implements, informational and
errors.
Informational DMA interrupts do not stop the transfer and use the
`handle_edge_irq' handler that clears the request right away so that
another request may be recorded while the previous is being handled.
DMA error interrupts stop the transfer and require a corrective action
before DMA can be reenabled. Therefore they use the `handle_fasteoi_irq'
handler that only clears the request on the way out. Because MIPS
processor interrupt inputs, one of which the I/O ASIC's interrupt
controller is cascaded to, are level-triggered it is recommended that
error DMA interrupt action handlers are registered with the IRQF_ONESHOT
flag set so that they are run with the interrupt line masked.
Previously these interrupts were cleared in the .end handler of the
`irq_chip' structure, before it was removed.
Signed-off-by: Maciej W. Rozycki <macro@linux-mips.org>
---
Ralf,
I see you have applied the original change after all; I'd prefer it to be
dropped to avoid cluttering the history, but please let me know if you
need an incremental change instead.
This change was tested at run time, however the LANCE does not work quite
right -- while data is exchanged so that multi-user login can be reached
NFS-rooted, link keeps being dropped all the time. This is not a hardware
problem, because net-booting using the firmware does not exhibit this
behaviour. So interestingly enough FDDI is currently the only reliable
network connection for the DECstation. Well, reliability was the primary
goal FDDI was designed with. ;)
Maciej
linux-dec-ioasic-dma-irq.patch
Index: linux/arch/mips/dec/ioasic-irq.c
===================================================================
--- linux.orig/arch/mips/dec/ioasic-irq.c
+++ linux/arch/mips/dec/ioasic-irq.c
@@ -1,7 +1,7 @@
/*
* DEC I/O ASIC interrupts.
*
- * Copyright (c) 2002, 2003 Maciej W. Rozycki
+ * Copyright (c) 2002, 2003, 2013 Maciej W. Rozycki
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -51,14 +51,51 @@ static struct irq_chip ioasic_irq_type =
.irq_unmask = unmask_ioasic_irq,
};
+static void clear_ioasic_dma_irq(struct irq_data *d)
+{
+ u32 sir;
+
+ sir = ~(1 << (d->irq - ioasic_irq_base));
+ ioasic_write(IO_REG_SIR, sir);
+ fast_iob();
+}
+
static struct irq_chip ioasic_dma_irq_type = {
.name = "IO-ASIC-DMA",
- .irq_ack = ack_ioasic_irq,
+ .irq_ack = clear_ioasic_dma_irq,
.irq_mask = mask_ioasic_irq,
- .irq_mask_ack = ack_ioasic_irq,
.irq_unmask = unmask_ioasic_irq,
+ .irq_eoi = clear_ioasic_dma_irq,
};
+/*
+ * I/O ASIC implements two kinds of DMA interrupts, informational and
+ * error interrupts.
+ *
+ * The formers do not stop DMA and should be cleared as soon as possible
+ * so that if they retrigger before the handler has completed, usually as
+ * a side effect of actions taken by the handler, then they are reissued.
+ * These use the `handle_edge_irq' handler that clears the request right
+ * away.
+ *
+ * The latters stop DMA and do not resume it until the interrupt has been
+ * cleared. This cannot be done until after a corrective action has been
+ * taken and this also means they will not retrigger. Therefore they use
+ * the `handle_fasteoi_irq' handler that only clears the request on the
+ * way out. Because MIPS processor interrupt inputs, one of which the I/O
+ * ASIC is cascaded to, are level-triggered it is recommended that error
+ * DMA interrupt action handlers are registered with the IRQF_ONESHOT flag
+ * set so that they are run with the interrupt line masked.
+ *
+ * This mask has `1' bits in the positions of informational interrupts.
+ */
+#define IO_IRQ_DMA_INFO \
+ (IO_IRQ_MASK(IO_INR_SCC0A_RXDMA) | \
+ IO_IRQ_MASK(IO_INR_SCC1A_RXDMA) | \
+ IO_IRQ_MASK(IO_INR_ISDN_TXDMA) | \
+ IO_IRQ_MASK(IO_INR_ISDN_RXDMA) | \
+ IO_IRQ_MASK(IO_INR_ASC_DMA))
+
void __init init_ioasic_irqs(int base)
{
int i;
@@ -71,7 +108,9 @@ void __init init_ioasic_irqs(int base)
irq_set_chip_and_handler(i, &ioasic_irq_type,
handle_level_irq);
for (; i < base + IO_IRQ_LINES; i++)
- irq_set_chip(i, &ioasic_dma_irq_type);
+ irq_set_chip_and_handler(i, &ioasic_dma_irq_type,
+ 1 << (i - base) & IO_IRQ_DMA_INFO ?
+ handle_edge_irq : handle_fasteoi_irq);
ioasic_irq_base = base;
}
Index: linux/drivers/net/ethernet/amd/declance.c
===================================================================
--- linux.orig/drivers/net/ethernet/amd/declance.c
+++ linux/drivers/net/ethernet/amd/declance.c
@@ -811,7 +811,7 @@ static int lance_open(struct net_device
if (lp->dma_irq >= 0) {
unsigned long flags;
- if (request_irq(lp->dma_irq, lance_dma_merr_int, 0,
+ if (request_irq(lp->dma_irq, lance_dma_merr_int, IRQF_ONESHOT,
"lance error", dev)) {
free_irq(dev->irq, dev);
printk("%s: Can't get DMA IRQ %d\n", dev->name,
^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: [PATCH v2] MIPS: DECstation I/O ASIC DMA interrupt handling fix
2013-09-17 15:40 [PATCH v2] MIPS: DECstation I/O ASIC DMA interrupt handling fix Maciej W. Rozycki
@ 2013-09-17 16:13 ` Ralf Baechle
2013-09-17 17:02 ` Maciej W. Rozycki
0 siblings, 1 reply; 3+ messages in thread
From: Ralf Baechle @ 2013-09-17 16:13 UTC (permalink / raw
To: Maciej W. Rozycki; +Cc: linux-mips
On Tue, Sep 17, 2013 at 04:40:39PM +0100, Maciej W. Rozycki wrote:
> I see you have applied the original change after all; I'd prefer it to be
> dropped to avoid cluttering the history, but please let me know if you
> need an incremental change instead.
The first patch is already upstream in 3.12-rc1, so I will need an
incremental patch.
Thanks,
Ralf
^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: [PATCH v2] MIPS: DECstation I/O ASIC DMA interrupt handling fix
2013-09-17 16:13 ` Ralf Baechle
@ 2013-09-17 17:02 ` Maciej W. Rozycki
0 siblings, 0 replies; 3+ messages in thread
From: Maciej W. Rozycki @ 2013-09-17 17:02 UTC (permalink / raw
To: Ralf Baechle; +Cc: linux-mips
On Tue, 17 Sep 2013, Ralf Baechle wrote:
> > I see you have applied the original change after all; I'd prefer it to be
> > dropped to avoid cluttering the history, but please let me know if you
> > need an incremental change instead.
>
> The first patch is already upstream in 3.12-rc1, so I will need an
> incremental patch.
Argh, that means I'll have to rewrite the explanation... Ran out of time
now, will post later.
Maciej
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2013-09-17 17:02 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2013-09-17 15:40 [PATCH v2] MIPS: DECstation I/O ASIC DMA interrupt handling fix Maciej W. Rozycki
2013-09-17 16:13 ` Ralf Baechle
2013-09-17 17:02 ` Maciej W. Rozycki
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.