]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - kernel/irq/spurious.c
drm: cleanup DRM_DEBUG() parameters
[linux-2.6-omap-h63xx.git] / kernel / irq / spurious.c
index 9d8c79b48823fdfb44d27fe3a3bf1c7adc9cdbc7..a6b2bc831dd05be5ee9cbff347566bf410870c26 100644 (file)
@@ -10,6 +10,7 @@
 #include <linux/module.h>
 #include <linux/kallsyms.h>
 #include <linux/interrupt.h>
+#include <linux/moduleparam.h>
 
 static int irqfixup __read_mostly;
 
@@ -135,22 +136,62 @@ 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)
 {
        if (unlikely(action_ret != IRQ_HANDLED)) {
-               desc->irqs_unhandled++;
+               /*
+                * If we are seeing only the odd spurious IRQ caused by
+                * bus asynchronicity then don't eventually trigger an error,
+                * otherwise the couter becomes a doomsday timer for otherwise
+                * working systems
+                */
+               if (jiffies - desc->last_unhandled > HZ/10)
+                       desc->irqs_unhandled = 1;
+               else
+                       desc->irqs_unhandled++;
+               desc->last_unhandled = jiffies;
                if (unlikely(action_ret != IRQ_NONE))
                        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);
-                       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++;
@@ -185,6 +226,8 @@ int noirqdebug_setup(char *str)
 }
 
 __setup("noirqdebug", noirqdebug_setup);
+module_param(noirqdebug, bool, 0644);
+MODULE_PARM_DESC(noirqdebug, "Disable irq lockup detection when true");
 
 static int __init irqfixup_setup(char *str)
 {
@@ -196,6 +239,8 @@ static int __init irqfixup_setup(char *str)
 }
 
 __setup("irqfixup", irqfixup_setup);
+module_param(irqfixup, int, 0644);
+MODULE_PARM_DESC("irqfixup", "0: No fixup, 1: irqfixup mode 2: irqpoll mode");
 
 static int __init irqpoll_setup(char *str)
 {