sched: rename idle_type/SCHED_IDLE
[firefly-linux-kernel-4.4.55.git] / kernel / irq / spurious.c
index 417e98092cf20a6e843c6ae973a6ee4c216cd435..bd9e272d55e9f007984b06e0999f6a37bb7208e1 100644 (file)
@@ -16,7 +16,7 @@ static int irqfixup __read_mostly;
 /*
  * Recovery handler for misrouted interrupts.
  */
-static int misrouted_irq(int irq, struct pt_regs *regs)
+static int misrouted_irq(int irq)
 {
        int i;
        int ok = 0;
@@ -49,7 +49,7 @@ static int misrouted_irq(int irq, struct pt_regs *regs)
                while (action) {
                        /* Only shared IRQ handlers are safe to call */
                        if (action->flags & IRQF_SHARED) {
-                               if (action->handler(i, action->dev_id, regs) ==
+                               if (action->handler(i, action->dev_id) ==
                                                IRQ_HANDLED)
                                        ok = 1;
                        }
@@ -70,7 +70,7 @@ static int misrouted_irq(int irq, struct pt_regs *regs)
                         */
                        work = 1;
                        spin_unlock(&desc->lock);
-                       handle_IRQ_event(i, regs, action);
+                       handle_IRQ_event(i, action);
                        spin_lock(&desc->lock);
                        desc->status &= ~IRQ_PENDING;
                }
@@ -135,8 +135,41 @@ report_bad_irq(unsigned int irq, struct irq_desc *desc, irqreturn_t action_ret)
        }
 }
 
+static inline int try_misrouted_irq(unsigned int irq, struct irq_desc *desc, irqreturn_t action_ret)
+{
+       struct irqaction *action;
+
+       if (!irqfixup)
+               return 0;
+
+       /* We didn't actually handle the IRQ - see if it was misrouted? */
+       if (action_ret == IRQ_NONE)
+               return 1;
+
+       /*
+        * But for 'irqfixup == 2' we also do it for handled interrupts if
+        * they are marked as IRQF_IRQPOLL (or for irq zero, which is the
+        * traditional PC timer interrupt.. Legacy)
+        */
+       if (irqfixup < 2)
+               return 0;
+
+       if (!irq)
+               return 1;
+
+       /*
+        * Since we don't get the descriptor lock, "action" can
+        * change under us.  We don't really care, but we don't
+        * want to follow a NULL pointer. So tell the compiler to
+        * just load it once by using a barrier.
+        */
+       action = desc->action;
+       barrier();
+       return action && (action->flags & IRQF_IRQPOLL);
+}
+
 void note_interrupt(unsigned int irq, struct irq_desc *desc,
-                   irqreturn_t action_ret, struct pt_regs *regs)
+                   irqreturn_t action_ret)
 {
        if (unlikely(action_ret != IRQ_HANDLED)) {
                desc->irqs_unhandled++;
@@ -144,13 +177,10 @@ void note_interrupt(unsigned int irq, struct irq_desc *desc,
                        report_bad_irq(irq, desc, action_ret);
        }
 
-       if (unlikely(irqfixup)) {
-               /* Don't punish working computers */
-               if ((irqfixup == 2 && irq == 0) || action_ret == IRQ_NONE) {
-                       int ok = misrouted_irq(irq, regs);
-                       if (action_ret == IRQ_NONE)
-                               desc->irqs_unhandled -= ok;
-               }
+       if (unlikely(try_misrouted_irq(irq, desc, action_ret))) {
+               int ok = misrouted_irq(irq);
+               if (action_ret == IRQ_NONE)
+                       desc->irqs_unhandled -= ok;
        }
 
        desc->irq_count++;
@@ -176,7 +206,7 @@ void note_interrupt(unsigned int irq, struct irq_desc *desc,
 
 int noirqdebug __read_mostly;
 
-int __init noirqdebug_setup(char *str)
+int noirqdebug_setup(char *str)
 {
        noirqdebug = 1;
        printk(KERN_INFO "IRQ lockup detection disabled\n");