Commit 70433c01 authored by Thomas Gleixner's avatar Thomas Gleixner

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: default avatarIngo Molnar <mingo@elte.hu>
Signed-off-by: default avatarThomas Gleixner <tglx@linutronix.de>
parent 8fff39e0
...@@ -54,24 +54,26 @@ static void warn_no_thread(unsigned int irq, struct irqaction *action) ...@@ -54,24 +54,26 @@ static void warn_no_thread(unsigned int irq, struct irqaction *action)
irqreturn_t irqreturn_t
handle_irq_event_percpu(struct irq_desc *desc, struct irqaction *action) 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; unsigned int random = 0, irq = desc->irq_data.irq;
do { do {
irqreturn_t res;
trace_irq_handler_entry(irq, action); trace_irq_handler_entry(irq, action);
ret = action->handler(irq, action->dev_id); res = action->handler(irq, action->dev_id);
trace_irq_handler_exit(irq, action, ret); trace_irq_handler_exit(irq, action, res);
if (WARN_ON_ONCE(!irqs_disabled())) if (WARN_ON_ONCE(!irqs_disabled()))
local_irq_disable(); local_irq_disable();
switch (ret) { switch (res) {
case IRQ_WAKE_THREAD: case IRQ_WAKE_THREAD:
/* /*
* Set result to handled so the spurious check * Set result to handled so the spurious check
* does not trigger. * does not trigger.
*/ */
ret = IRQ_HANDLED; res = IRQ_HANDLED;
/* /*
* Catch drivers which return WAKE_THREAD but * Catch drivers which return WAKE_THREAD but
...@@ -105,7 +107,7 @@ handle_irq_event_percpu(struct irq_desc *desc, struct irqaction *action) ...@@ -105,7 +107,7 @@ handle_irq_event_percpu(struct irq_desc *desc, struct irqaction *action)
break; break;
} }
retval |= ret; retval |= res;
action = action->next; action = action->next;
} while (action); } while (action);
...@@ -113,7 +115,7 @@ handle_irq_event_percpu(struct irq_desc *desc, struct irqaction *action) ...@@ -113,7 +115,7 @@ handle_irq_event_percpu(struct irq_desc *desc, struct irqaction *action)
add_interrupt_randomness(irq); add_interrupt_randomness(irq);
if (!noirqdebug) if (!noirqdebug)
note_interrupt(irq, desc, ret); note_interrupt(irq, desc, retval);
return retval; return retval;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment