diff options
| author | Maciej W. Rozycki <macro@linux-mips.org> | 2013-09-22 16:55:19 -0400 |
|---|---|---|
| committer | Ralf Baechle <ralf@linux-mips.org> | 2013-10-29 16:24:42 -0400 |
| commit | 0fabe1021f8bc9cffdede4ddad0dd04d43c5166c (patch) | |
| tree | 0b1c61e3ef7c1858eb17603633b35c32d92933ad /arch/mips | |
| parent | 4e7f72660c39a81cc5745d5c6f23f9500f80d8d8 (diff) | |
MIPS: DECstation I/O ASIC DMA interrupt classes
This change complements commits d0da7c002f7b2a93582187a9e3f73891a01d8ee4
[MIPS: DEC: Convert to new irq_chip functions] and
5359b938c088423a28c41499f183cd10824c1816 [MIPS: DECstation I/O ASIC DMA
interrupt handling fix] and implements automatic handling of 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.
This change removes the export of clear_ioasic_dma_irq that now does not
have to be called by device drivers to clear interrupts explicitly
anymore. Originally 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>
Cc: linux-mips@linux-mips.org
Patchwork: https://patchwork.linux-mips.org/patch/5874/
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
Diffstat (limited to 'arch/mips')
| -rw-r--r-- | arch/mips/dec/ioasic-irq.c | 43 | ||||
| -rw-r--r-- | arch/mips/include/asm/dec/ioasic.h | 2 |
2 files changed, 37 insertions, 8 deletions
diff --git a/arch/mips/dec/ioasic-irq.c b/arch/mips/dec/ioasic-irq.c index 4b3e3a4375a6..e04d973ce5aa 100644 --- a/arch/mips/dec/ioasic-irq.c +++ b/arch/mips/dec/ioasic-irq.c | |||
| @@ -1,7 +1,7 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * DEC I/O ASIC interrupts. | 2 | * DEC I/O ASIC interrupts. |
| 3 | * | 3 | * |
| 4 | * Copyright (c) 2002, 2003 Maciej W. Rozycki | 4 | * Copyright (c) 2002, 2003, 2013 Maciej W. Rozycki |
| 5 | * | 5 | * |
| 6 | * This program is free software; you can redistribute it and/or | 6 | * This program is free software; you can redistribute it and/or |
| 7 | * modify it under the terms of the GNU General Public License | 7 | * modify it under the terms of the GNU General Public License |
| @@ -51,22 +51,51 @@ static struct irq_chip ioasic_irq_type = { | |||
| 51 | .irq_unmask = unmask_ioasic_irq, | 51 | .irq_unmask = unmask_ioasic_irq, |
| 52 | }; | 52 | }; |
| 53 | 53 | ||
| 54 | void clear_ioasic_dma_irq(unsigned int irq) | 54 | static void clear_ioasic_dma_irq(struct irq_data *d) |
| 55 | { | 55 | { |
| 56 | u32 sir; | 56 | u32 sir; |
| 57 | 57 | ||
| 58 | sir = ~(1 << (irq - ioasic_irq_base)); | 58 | sir = ~(1 << (d->irq - ioasic_irq_base)); |
| 59 | ioasic_write(IO_REG_SIR, sir); | 59 | ioasic_write(IO_REG_SIR, sir); |
| 60 | fast_iob(); | ||
| 60 | } | 61 | } |
| 61 | 62 | ||
| 62 | static struct irq_chip ioasic_dma_irq_type = { | 63 | static struct irq_chip ioasic_dma_irq_type = { |
| 63 | .name = "IO-ASIC-DMA", | 64 | .name = "IO-ASIC-DMA", |
| 64 | .irq_ack = ack_ioasic_irq, | 65 | .irq_ack = clear_ioasic_dma_irq, |
| 65 | .irq_mask = mask_ioasic_irq, | 66 | .irq_mask = mask_ioasic_irq, |
| 66 | .irq_mask_ack = ack_ioasic_irq, | ||
| 67 | .irq_unmask = unmask_ioasic_irq, | 67 | .irq_unmask = unmask_ioasic_irq, |
| 68 | .irq_eoi = clear_ioasic_dma_irq, | ||
| 68 | }; | 69 | }; |
| 69 | 70 | ||
| 71 | /* | ||
| 72 | * I/O ASIC implements two kinds of DMA interrupts, informational and | ||
| 73 | * error interrupts. | ||
| 74 | * | ||
| 75 | * The formers do not stop DMA and should be cleared as soon as possible | ||
| 76 | * so that if they retrigger before the handler has completed, usually as | ||
| 77 | * a side effect of actions taken by the handler, then they are reissued. | ||
| 78 | * These use the `handle_edge_irq' handler that clears the request right | ||
| 79 | * away. | ||
| 80 | * | ||
| 81 | * The latters stop DMA and do not resume it until the interrupt has been | ||
| 82 | * cleared. This cannot be done until after a corrective action has been | ||
| 83 | * taken and this also means they will not retrigger. Therefore they use | ||
| 84 | * the `handle_fasteoi_irq' handler that only clears the request on the | ||
| 85 | * way out. Because MIPS processor interrupt inputs, one of which the I/O | ||
| 86 | * ASIC is cascaded to, are level-triggered it is recommended that error | ||
| 87 | * DMA interrupt action handlers are registered with the IRQF_ONESHOT flag | ||
| 88 | * set so that they are run with the interrupt line masked. | ||
| 89 | * | ||
| 90 | * This mask has `1' bits in the positions of informational interrupts. | ||
| 91 | */ | ||
| 92 | #define IO_IRQ_DMA_INFO \ | ||
| 93 | (IO_IRQ_MASK(IO_INR_SCC0A_RXDMA) | \ | ||
| 94 | IO_IRQ_MASK(IO_INR_SCC1A_RXDMA) | \ | ||
| 95 | IO_IRQ_MASK(IO_INR_ISDN_TXDMA) | \ | ||
| 96 | IO_IRQ_MASK(IO_INR_ISDN_RXDMA) | \ | ||
| 97 | IO_IRQ_MASK(IO_INR_ASC_DMA)) | ||
| 98 | |||
| 70 | void __init init_ioasic_irqs(int base) | 99 | void __init init_ioasic_irqs(int base) |
| 71 | { | 100 | { |
| 72 | int i; | 101 | int i; |
| @@ -79,7 +108,9 @@ void __init init_ioasic_irqs(int base) | |||
| 79 | irq_set_chip_and_handler(i, &ioasic_irq_type, | 108 | irq_set_chip_and_handler(i, &ioasic_irq_type, |
| 80 | handle_level_irq); | 109 | handle_level_irq); |
| 81 | for (; i < base + IO_IRQ_LINES; i++) | 110 | for (; i < base + IO_IRQ_LINES; i++) |
| 82 | irq_set_chip(i, &ioasic_dma_irq_type); | 111 | irq_set_chip_and_handler(i, &ioasic_dma_irq_type, |
| 112 | 1 << (i - base) & IO_IRQ_DMA_INFO ? | ||
| 113 | handle_edge_irq : handle_fasteoi_irq); | ||
| 83 | 114 | ||
| 84 | ioasic_irq_base = base; | 115 | ioasic_irq_base = base; |
| 85 | } | 116 | } |
diff --git a/arch/mips/include/asm/dec/ioasic.h b/arch/mips/include/asm/dec/ioasic.h index a6e505a0e44b..be4d62a5a10e 100644 --- a/arch/mips/include/asm/dec/ioasic.h +++ b/arch/mips/include/asm/dec/ioasic.h | |||
| @@ -31,8 +31,6 @@ static inline u32 ioasic_read(unsigned int reg) | |||
| 31 | return ioasic_base[reg / 4]; | 31 | return ioasic_base[reg / 4]; |
| 32 | } | 32 | } |
| 33 | 33 | ||
| 34 | extern void clear_ioasic_dma_irq(unsigned int irq); | ||
| 35 | |||
| 36 | extern void init_ioasic_irqs(int base); | 34 | extern void init_ioasic_irqs(int base); |
| 37 | 35 | ||
| 38 | extern int dec_ioasic_clocksource_init(void); | 36 | extern int dec_ioasic_clocksource_init(void); |
