aboutsummaryrefslogtreecommitdiffstats
path: root/arch/mips/dec/ioasic-irq.c
diff options
context:
space:
mode:
authorMaciej W. Rozycki <macro@linux-mips.org>2013-09-22 16:55:19 -0400
committerRalf Baechle <ralf@linux-mips.org>2013-10-29 16:24:42 -0400
commit0fabe1021f8bc9cffdede4ddad0dd04d43c5166c (patch)
tree0b1c61e3ef7c1858eb17603633b35c32d92933ad /arch/mips/dec/ioasic-irq.c
parent4e7f72660c39a81cc5745d5c6f23f9500f80d8d8 (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/dec/ioasic-irq.c')
-rw-r--r--arch/mips/dec/ioasic-irq.c43
1 files changed, 37 insertions, 6 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
54void clear_ioasic_dma_irq(unsigned int irq) 54static 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
62static struct irq_chip ioasic_dma_irq_type = { 63static 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
70void __init init_ioasic_irqs(int base) 99void __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}