genirq: Use the correct variable for note_interrupt
authorThomas Gleixner <tglx@linutronix.de>
Tue, 22 Feb 2011 11:50:12 +0000 (12:50 +0100)
committerThomas Gleixner <tglx@linutronix.de>
Tue, 22 Feb 2011 12:02:03 +0000 (13:02 +0100)
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>
kernel/irq/handle.c

index cb62e2d0df4e7c2d495389d48f3d08bf99e86a70..e099e9e9de0ba2509bdcb689b51e884b22c7e374 100644 (file)
@@ -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;
 }