summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorThomas Gleixner <tglx@linutronix.de>2011-02-22 12:50:12 +0100
committerThomas Gleixner <tglx@linutronix.de>2011-02-22 13:02:03 +0100
commit70433c01613c2a44756c7b25f7bdd6c1c77b119f (patch)
tree27fb95b4ccaa498a7bbae135835b8a0472147d1b
parent8fff39e06987492da3d4a0b9ec7cdbd245b6762b (diff)
downloadlinux-stable-70433c01613c2a44756c7b25f7bdd6c1c77b119f.tar.gz
linux-stable-70433c01613c2a44756c7b25f7bdd6c1c77b119f.tar.bz2
linux-stable-70433c01613c2a44756c7b25f7bdd6c1c77b119f.zip
genirq: Use the correct variable for note_interrupt
note_interrupt wants to be called with the combined result of all handlers called, not with the last one. If it's a shared interrupt then the last handler might return IRQ_NONE often enough to trigger the spurious dectector which turns off a perfectly fine working interrupt line. Bug was introduced in commit 1277a532(genirq: Simplify handle_irq_event()). Yes, I really messed up there. First the variable ret should not have been named differently to avoid similarity with retval. Second it should have been declared in the do {} loop. Rename it to res and move it into the do {} loop and vanish under a huge brown paperbag. Reported-bisected-tested-by: Ingo Molnar <mingo@elte.hu> Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
-rw-r--r--kernel/irq/handle.c16
1 files changed, 9 insertions, 7 deletions
diff --git a/kernel/irq/handle.c b/kernel/irq/handle.c
index cb62e2d0df4e..e099e9e9de0b 100644
--- a/kernel/irq/handle.c
+++ b/kernel/irq/handle.c
@@ -54,24 +54,26 @@ static void warn_no_thread(unsigned int irq, struct irqaction *action)
irqreturn_t
handle_irq_event_percpu(struct irq_desc *desc, struct irqaction *action)
{
- irqreturn_t ret, retval = IRQ_NONE;
+ irqreturn_t retval = IRQ_NONE;
unsigned int random = 0, irq = desc->irq_data.irq;
do {
+ irqreturn_t res;
+
trace_irq_handler_entry(irq, action);
- ret = action->handler(irq, action->dev_id);
- trace_irq_handler_exit(irq, action, ret);
+ res = action->handler(irq, action->dev_id);
+ trace_irq_handler_exit(irq, action, res);
if (WARN_ON_ONCE(!irqs_disabled()))
local_irq_disable();
- switch (ret) {
+ switch (res) {
case IRQ_WAKE_THREAD:
/*
* Set result to handled so the spurious check
* does not trigger.
*/
- ret = IRQ_HANDLED;
+ res = IRQ_HANDLED;
/*
* Catch drivers which return WAKE_THREAD but
@@ -105,7 +107,7 @@ handle_irq_event_percpu(struct irq_desc *desc, struct irqaction *action)
break;
}
- retval |= ret;
+ retval |= res;
action = action->next;
} while (action);
@@ -113,7 +115,7 @@ handle_irq_event_percpu(struct irq_desc *desc, struct irqaction *action)
add_interrupt_randomness(irq);
if (!noirqdebug)
- note_interrupt(irq, desc, ret);
+ note_interrupt(irq, desc, retval);
return retval;
}