irq: further clean up the free_irq() code flow
[safe/jmp/linux-2.6] / kernel / irq / autoprobe.c
index cfdb63e..1de9700 100644 (file)
@@ -10,6 +10,9 @@
 #include <linux/module.h>
 #include <linux/interrupt.h>
 #include <linux/delay.h>
+#include <linux/async.h>
+
+#include "internals.h"
 
 /*
  * Autodetection depends on the fact that any interrupt that
@@ -28,20 +31,29 @@ static DEFINE_MUTEX(probing_active);
 unsigned long probe_irq_on(void)
 {
        struct irq_desc *desc;
-       unsigned long mask;
-       unsigned int i;
+       unsigned long mask = 0;
+       unsigned int status;
+       int i;
 
+       /*
+        * quiesce the kernel, or at least the asynchronous portion
+        */
+       async_synchronize_full();
        mutex_lock(&probing_active);
        /*
         * something may have generated an irq long ago and we want to
         * flush such a longstanding irq before considering it as spurious.
         */
-       for (i = NR_IRQS-1; i > 0; i--) {
-               desc = irq_desc + i;
-
+       for_each_irq_desc_reverse(i, desc) {
                spin_lock_irq(&desc->lock);
                if (!desc->action && !(desc->status & IRQ_NOPROBE)) {
                        /*
+                        * An old-style architecture might still have
+                        * the handle_bad_irq handler there:
+                        */
+                       compat_irq_chip_set_default_handler(desc);
+
+                       /*
                         * Some chips need to know about probing in
                         * progress:
                         */
@@ -60,9 +72,7 @@ unsigned long probe_irq_on(void)
         * (we must startup again here because if a longstanding irq
         * happened in the previous stage, it may have masked itself)
         */
-       for (i = NR_IRQS-1; i > 0; i--) {
-               desc = irq_desc + i;
-
+       for_each_irq_desc_reverse(i, desc) {
                spin_lock_irq(&desc->lock);
                if (!desc->action && !(desc->status & IRQ_NOPROBE)) {
                        desc->status |= IRQ_AUTODETECT | IRQ_WAITING;
@@ -80,11 +90,7 @@ unsigned long probe_irq_on(void)
        /*
         * Now filter out any obviously spurious interrupts
         */
-       mask = 0;
-       for (i = 0; i < NR_IRQS; i++) {
-               unsigned int status;
-
-               desc = irq_desc + i;
+       for_each_irq_desc(i, desc) {
                spin_lock_irq(&desc->lock);
                status = desc->status;
 
@@ -118,14 +124,11 @@ EXPORT_SYMBOL(probe_irq_on);
  */
 unsigned int probe_irq_mask(unsigned long val)
 {
-       unsigned int mask;
+       unsigned int status, mask = 0;
+       struct irq_desc *desc;
        int i;
 
-       mask = 0;
-       for (i = 0; i < NR_IRQS; i++) {
-               struct irq_desc *desc = irq_desc + i;
-               unsigned int status;
-
+       for_each_irq_desc(i, desc) {
                spin_lock_irq(&desc->lock);
                status = desc->status;
 
@@ -163,20 +166,19 @@ EXPORT_SYMBOL(probe_irq_mask);
  */
 int probe_irq_off(unsigned long val)
 {
-       int i, irq_found = 0, nr_irqs = 0;
-
-       for (i = 0; i < NR_IRQS; i++) {
-               struct irq_desc *desc = irq_desc + i;
-               unsigned int status;
+       int i, irq_found = 0, nr_of_irqs = 0;
+       struct irq_desc *desc;
+       unsigned int status;
 
+       for_each_irq_desc(i, desc) {
                spin_lock_irq(&desc->lock);
                status = desc->status;
 
                if (status & IRQ_AUTODETECT) {
                        if (!(status & IRQ_WAITING)) {
-                               if (!nr_irqs)
+                               if (!nr_of_irqs)
                                        irq_found = i;
-                               nr_irqs++;
+                               nr_of_irqs++;
                        }
                        desc->status = status & ~IRQ_AUTODETECT;
                        desc->chip->shutdown(i);
@@ -185,7 +187,7 @@ int probe_irq_off(unsigned long val)
        }
        mutex_unlock(&probing_active);
 
-       if (nr_irqs > 1)
+       if (nr_of_irqs > 1)
                irq_found = -irq_found;
 
        return irq_found;