genirq: Fixup poll handling
authorThomas Gleixner <tglx@linutronix.de>
Mon, 7 Feb 2011 08:10:39 +0000 (09:10 +0100)
committerThomas Gleixner <tglx@linutronix.de>
Sat, 19 Feb 2011 11:58:08 +0000 (12:58 +0100)
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>
kernel/irq/spurious.c

index 2fbfda2716e1253c33aeef02037766723f789760..0af9e59c82ebf8008af6d75778c9d64c9d9a8802 100644 (file)
@@ -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;
 }