Skip to content

Commit 4f27c00

Browse files
Alan-CoxLinus Torvalds
authored and
Linus Torvalds
committed
Improve behaviour of spurious IRQ detect
Currently we handle spurious IRQ activity based upon seeing a lot of invalid interrupts, and we clear things back on the base of lots of valid interrupts. Unfortunately in some cases you get legitimate invalid interrupts caused by timing asynchronicity between the PCI bus and the APIC bus when disabling interrupts and pulling other tricks. In this case although the spurious IRQs are not a problem our unhandled counters didn't clear and they act as a slow running timebomb. (This is effectively what the serial port/tty problem that was fixed by clearing counters when registering a handler showed up) It's easy enough to add a second parameter - time. This means that if we see a regular stream of harmless spurious interrupts which are not harming processing we don't go off and do something stupid like disable the IRQ after a month of running. OTOH lockups and performance killers show up a lot more than 10/second [[email protected]: cleanup] Signed-off-by: Alan Cox <[email protected]> Cc: Ingo Molnar <[email protected]> Cc: Thomas Gleixner <[email protected]> Signed-off-by: Andrew Morton <[email protected]> Signed-off-by: Linus Torvalds <[email protected]>
1 parent f3dc8c1 commit 4f27c00

File tree

2 files changed

+12
-1
lines changed

2 files changed

+12
-1
lines changed

include/linux/irq.h

+1
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,7 @@ struct irq_desc {
161161
unsigned int wake_depth; /* nested wake enables */
162162
unsigned int irq_count; /* For detecting broken IRQs */
163163
unsigned int irqs_unhandled;
164+
unsigned long last_unhandled; /* Aging timer for unhandled count */
164165
spinlock_t lock;
165166
#ifdef CONFIG_SMP
166167
cpumask_t affinity;

kernel/irq/spurious.c

+11-1
Original file line numberDiff line numberDiff line change
@@ -172,7 +172,17 @@ void note_interrupt(unsigned int irq, struct irq_desc *desc,
172172
irqreturn_t action_ret)
173173
{
174174
if (unlikely(action_ret != IRQ_HANDLED)) {
175-
desc->irqs_unhandled++;
175+
/*
176+
* If we are seeing only the odd spurious IRQ caused by
177+
* bus asynchronicity then don't eventually trigger an error,
178+
* otherwise the couter becomes a doomsday timer for otherwise
179+
* working systems
180+
*/
181+
if (jiffies - desc->last_unhandled > HZ/10)
182+
desc->irqs_unhandled = 1;
183+
else
184+
desc->irqs_unhandled++;
185+
desc->last_unhandled = jiffies;
176186
if (unlikely(action_ret != IRQ_NONE))
177187
report_bad_irq(irq, desc, action_ret);
178188
}

0 commit comments

Comments
 (0)