Merge to kernel-2.6.20-1.2949.fc6.vs2.2.0.1
[linux-2.6.git] / kernel / irq / spurious.c
index f557fb1..9d8c79b 100644 (file)
 #include <linux/kallsyms.h>
 #include <linux/interrupt.h>
 
-static int irqfixup;
+static int irqfixup __read_mostly;
 
 /*
- *     Recovery handler for misrouted interrupts. 
+ * Recovery handler for misrouted interrupts.
  */
-
-static int misrouted_irq(int irq, struct pt_regs *regs)
+static int misrouted_irq(int irq)
 {
        int i;
-       irq_desc_t *desc;
        int ok = 0;
        int work = 0;   /* Did we do work for a real IRQ */
-       for(i = 1; i < NR_IRQS; i++)
-       {
+
+       for (i = 1; i < NR_IRQS; i++) {
+               struct irq_desc *desc = irq_desc + i;
                struct irqaction *action;
-               if(i == irq)    /* Already tried */
+
+               if (i == irq)   /* Already tried */
                        continue;
-               desc = &irq_desc[i];
+
                spin_lock(&desc->lock);
-               action = desc->action;
                /* Already running on another processor */
-               if(desc->status & IRQ_INPROGRESS)
-               {
-                       /* Already running: If it is shared get the other
-                          CPU to go looking for our mystery interrupt too */
-                       if(desc->action && (desc->action->flags & SA_SHIRQ))
+               if (desc->status & IRQ_INPROGRESS) {
+                       /*
+                        * Already running: If it is shared get the other
+                        * CPU to go looking for our mystery interrupt too
+                        */
+                       if (desc->action && (desc->action->flags & IRQF_SHARED))
                                desc->status |= IRQ_PENDING;
                        spin_unlock(&desc->lock);
                        continue;
                }
                /* Honour the normal IRQ locking */
                desc->status |= IRQ_INPROGRESS;
+               action = desc->action;
                spin_unlock(&desc->lock);
-               while(action)
-               {
+
+               while (action) {
                        /* Only shared IRQ handlers are safe to call */
-                       if(action->flags & SA_SHIRQ)
-                       {
-                               if(action->handler(i, action->dev_id, regs) == IRQ_HANDLED)
+                       if (action->flags & IRQF_SHARED) {
+                               if (action->handler(i, action->dev_id) ==
+                                               IRQ_HANDLED)
                                        ok = 1;
                        }
                        action = action->next;
@@ -59,23 +60,27 @@ static int misrouted_irq(int irq, struct pt_regs *regs)
                spin_lock(&desc->lock);
                action = desc->action;
 
-               /* While we were looking for a fixup someone queued a real
-                  IRQ clashing with our walk */
-
-               while((desc->status & IRQ_PENDING) && action)
-               {
-                       /* Perform real IRQ processing for the IRQ we deferred */
+               /*
+                * While we were looking for a fixup someone queued a real
+                * IRQ clashing with our walk:
+                */
+               while ((desc->status & IRQ_PENDING) && action) {
+                       /*
+                        * Perform real IRQ processing for the IRQ we deferred
+                        */
                        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;
                }
                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)
-                       desc->handler->end(i);
+               /*
+                * If we did actual work for the real IRQ line we must let the
+                * IRQ controller clean up too
+                */
+               if (work && desc->chip && desc->chip->end)
+                       desc->chip->end(i);
                spin_unlock(&desc->lock);
        }
        /* So the caller can adjust the irq error counts */
@@ -94,7 +99,8 @@ static int misrouted_irq(int irq, struct pt_regs *regs)
  */
 
 static void
-__report_bad_irq(unsigned int irq, irq_desc_t *desc, irqreturn_t action_ret)
+__report_bad_irq(unsigned int irq, struct irq_desc *desc,
+                irqreturn_t action_ret)
 {
        struct irqaction *action;
 
@@ -102,10 +108,12 @@ __report_bad_irq(unsigned int irq, irq_desc_t *desc, irqreturn_t action_ret)
                printk(KERN_ERR "irq event %d: bogus return value %x\n",
                                irq, action_ret);
        } else {
-               printk(KERN_ERR "irq %d: nobody cared (try booting with the \"irqpoll\" option.\n", irq);
+               printk(KERN_ERR "irq %d: nobody cared (try booting with "
+                               "the \"irqpoll\" option)\n", irq);
        }
        dump_stack();
        printk(KERN_ERR "handlers:\n");
+
        action = desc->action;
        while (action) {
                printk(KERN_ERR "[<%p>]", action->handler);
@@ -116,7 +124,8 @@ __report_bad_irq(unsigned int irq, irq_desc_t *desc, irqreturn_t action_ret)
        }
 }
 
-void report_bad_irq(unsigned int irq, irq_desc_t *desc, irqreturn_t action_ret)
+static void
+report_bad_irq(unsigned int irq, struct irq_desc *desc, irqreturn_t action_ret)
 {
        static int count = 100;
 
@@ -126,29 +135,30 @@ void report_bad_irq(unsigned int irq, irq_desc_t *desc, irqreturn_t action_ret)
        }
 }
 
-void note_interrupt(unsigned int irq, irq_desc_t *desc, irqreturn_t action_ret, struct pt_regs *regs)
+void note_interrupt(unsigned int irq, struct irq_desc *desc,
+                   irqreturn_t action_ret)
 {
-       if (action_ret != IRQ_HANDLED) {
+       if (unlikely(action_ret != IRQ_HANDLED)) {
                desc->irqs_unhandled++;
-               if (action_ret != IRQ_NONE)
+               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;
-                       ok = misrouted_irq(irq, regs);
-                       if(action_ret == IRQ_NONE)
+       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;
                }
        }
 
        desc->irq_count++;
-       if (desc->irq_count < 100000)
+       if (likely(desc->irq_count < 100000))
                return;
 
        desc->irq_count = 0;
-       if (desc->irqs_unhandled > 99900) {
+       if (unlikely(desc->irqs_unhandled > 99900)) {
                /*
                 * The interrupt is stuck
                 */
@@ -158,17 +168,19 @@ void note_interrupt(unsigned int irq, irq_desc_t *desc, irqreturn_t action_ret,
                 */
                printk(KERN_EMERG "Disabling IRQ #%d\n", irq);
                desc->status |= IRQ_DISABLED;
-               desc->handler->disable(irq);
+               desc->depth = 1;
+               desc->chip->disable(irq);
        }
        desc->irqs_unhandled = 0;
 }
 
-int noirqdebug;
+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");
+
        return 1;
 }
 
@@ -179,6 +191,7 @@ static int __init irqfixup_setup(char *str)
        irqfixup = 1;
        printk(KERN_WARNING "Misrouted IRQ fixup support enabled.\n");
        printk(KERN_WARNING "This may impact system performance.\n");
+
        return 1;
 }
 
@@ -187,8 +200,10 @@ __setup("irqfixup", irqfixup_setup);
 static int __init irqpoll_setup(char *str)
 {
        irqfixup = 2;
-       printk(KERN_WARNING "Misrouted IRQ fixup and polling support enabled.\n");
-       printk(KERN_WARNING "This may significantly impact system performance.\n");
+       printk(KERN_WARNING "Misrouted IRQ fixup and polling support "
+                               "enabled\n");
+       printk(KERN_WARNING "This may significantly impact system "
+                               "performance\n");
        return 1;
 }