summaryrefslogtreecommitdiff
path: root/kernel/irq/spurious.c
diff options
context:
space:
mode:
authorThomas Gleixner <tglx@linutronix.de>2008-04-28 15:01:56 (GMT)
committerThomas Gleixner <tglx@linutronix.de>2008-05-02 11:40:34 (GMT)
commit1adb0850a1254333d81e64121c80af100c6d6e06 (patch)
tree61835b06e78eb6f556c038ceabc706440f339d3a /kernel/irq/spurious.c
parent886c35fbcf6fb2eee15687efc2d64d99b6ad9a4a (diff)
downloadlinux-fsl-qoriq-1adb0850a1254333d81e64121c80af100c6d6e06.tar.xz
genirq: reenable a nobody cared disabled irq when a new driver arrives
Uwe Kleine-Koenig has some strange hardware where one of the shared interrupts can be asserted during boot before the appropriate driver loads. Requesting the shared irq line from another driver result in a spurious interrupt storm which finally disables the interrupt line. I have seen similar behaviour on resume before (the hardware does not work anymore so I can not verify). Change the spurious disable logic to increment the disable depth and mark the interrupt with an extra flag which allows us to reenable the interrupt when a new driver arrives which requests the same irq line. In the worst case this will disable the irq again via the spurious trap, but there is a decent chance that the new driver is the one which can handle the already asserted interrupt and makes the box usable again. Eric Biederman said further: This case also happens on a regular basis in kdump kernels where we deliberately don't shutdown the hardware before starting the new kernel. This patch should reduce the need for using irqpoll in that situation by a small amount. Signed-off-by: Thomas Gleixner <tglx@linutronix.de> Tested-and-Acked-by: Uwe Kleine-König <Uwe.Kleine-Koenig@digi.com>
Diffstat (limited to 'kernel/irq/spurious.c')
-rw-r--r--kernel/irq/spurious.c4
1 files changed, 2 insertions, 2 deletions
diff --git a/kernel/irq/spurious.c b/kernel/irq/spurious.c
index 088dabb..c66d3f1 100644
--- a/kernel/irq/spurious.c
+++ b/kernel/irq/spurious.c
@@ -209,8 +209,8 @@ void note_interrupt(unsigned int irq, struct irq_desc *desc,
* Now kill the IRQ
*/
printk(KERN_EMERG "Disabling IRQ #%d\n", irq);
- desc->status |= IRQ_DISABLED;
- desc->depth = 1;
+ desc->status |= IRQ_DISABLED | IRQ_SPURIOUS_DISABLED;
+ desc->depth++;
desc->chip->disable(irq);
}
desc->irqs_unhandled = 0;