summaryrefslogtreecommitdiffstats
path: root/kernel/irq/spurious.c
diff options
context:
space:
mode:
authorThomas Gleixner <tglx@linutronix.de>2011-02-07 09:10:39 +0100
committerThomas Gleixner <tglx@linutronix.de>2011-02-19 12:58:08 +0100
commitfa27271bc8d230355c1f24ddea103824fdc12de6 (patch)
tree311a8b2cb337f9de83047290f72cd511f81b4eae /kernel/irq/spurious.c
parentgenirq: Warn when handler enables interrupts (diff)
downloadlinux-fa27271bc8d230355c1f24ddea103824fdc12de6.tar.xz
linux-fa27271bc8d230355c1f24ddea103824fdc12de6.zip
genirq: Fixup poll handling
try_one_irq() contains redundant code and lots of useless checks for shared interrupts. Check for shared before setting IRQ_INPROGRESS and then call handle_IRQ_event() while pending. Shorter version with the same functionality. Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Diffstat (limited to 'kernel/irq/spurious.c')
-rw-r--r--kernel/irq/spurious.c50
1 files changed, 19 insertions, 31 deletions
diff --git a/kernel/irq/spurious.c b/kernel/irq/spurious.c
index 2fbfda2716e1..0af9e59c82eb 100644
--- a/kernel/irq/spurious.c
+++ b/kernel/irq/spurious.c
@@ -42,48 +42,36 @@ static int try_one_irq(int irq, struct irq_desc *desc)
raw_spin_unlock(&desc->lock);
return ok;
}
- /* Honour the normal IRQ locking */
- desc->status |= IRQ_INPROGRESS;
- action = desc->action;
- raw_spin_unlock(&desc->lock);
-
- while (action) {
- /* Only shared IRQ handlers are safe to call */
- if (action->flags & IRQF_SHARED) {
- if (action->handler(irq, action->dev_id) ==
- IRQ_HANDLED)
- ok = 1;
- }
- action = action->next;
- }
- local_irq_disable();
- /* Now clean up the flags */
- raw_spin_lock(&desc->lock);
- action = desc->action;
-
/*
- * While we were looking for a fixup someone queued a real
- * IRQ clashing with our walk:
+ * All handlers must agree on IRQF_SHARED, so we test just the
+ * first. Check for action->next as well.
*/
- while ((desc->status & IRQ_PENDING) && action) {
- /*
- * Perform real IRQ processing for the IRQ we deferred
- */
- work = 1;
+ action = desc->action;
+ if (!action || !(action->flags & IRQF_SHARED) || !action->next)
+ goto out;
+
+ /* Honour the normal IRQ locking */
+ desc->status |= IRQ_INPROGRESS;
+ do {
+ work++;
+ desc->status &= ~IRQ_PENDING;
raw_spin_unlock(&desc->lock);
- handle_IRQ_event(irq, action);
+ if (handle_IRQ_event(irq, action) != IRQ_NONE)
+ ok = 1;
raw_spin_lock(&desc->lock);
- desc->status &= ~IRQ_PENDING;
- }
+ action = desc->action;
+ } while ((desc->status & IRQ_PENDING) && action);
+
desc->status &= ~IRQ_INPROGRESS;
/*
* If we did actual work for the real IRQ line we must let the
* IRQ controller clean up too
*/
- if (work)
+ if (work > 1)
irq_end(irq, desc);
- raw_spin_unlock(&desc->lock);
+out:
+ raw_spin_unlock(&desc->lock);
return ok;
}