kernel: explicitly include required header files under kernel/
[deliverable/linux.git] / kernel / irq / manage.c
index 80eab7a0420597ec0c27fe7eaefe12a5868674b9..46e4ad1723f0545377c342c57a988a5ff99fef9c 100644 (file)
@@ -11,6 +11,7 @@
 #include <linux/module.h>
 #include <linux/random.h>
 #include <linux/interrupt.h>
+#include <linux/slab.h>
 
 #include "internals.h"
 
 void synchronize_irq(unsigned int irq)
 {
        struct irq_desc *desc = irq_desc + irq;
+       unsigned int status;
 
        if (irq >= NR_IRQS)
                return;
 
-       while (desc->status & IRQ_INPROGRESS)
-               cpu_relax();
+       do {
+               unsigned long flags;
+
+               /*
+                * Wait until we're out of the critical section.  This might
+                * give the wrong answer due to the lack of memory barriers.
+                */
+               while (desc->status & IRQ_INPROGRESS)
+                       cpu_relax();
+
+               /* Ok, that indicated we're done: double-check carefully. */
+               spin_lock_irqsave(&desc->lock, flags);
+               status = desc->status;
+               spin_unlock_irqrestore(&desc->lock, flags);
+
+               /* Oops, that failed? */
+       } while (status & IRQ_INPROGRESS);
 }
 EXPORT_SYMBOL(synchronize_irq);
 
@@ -463,6 +480,9 @@ void free_irq(unsigned int irq, void *dev_id)
                        return;
                }
                printk(KERN_ERR "Trying to free already-free IRQ %d\n", irq);
+#ifdef CONFIG_DEBUG_SHIRQ
+               dump_stack();
+#endif
                spin_unlock_irqrestore(&desc->lock, flags);
                return;
        }
This page took 0.024346 seconds and 5 git commands to generate.