aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--kernel/irq/manage.c20
1 files changed, 18 insertions, 2 deletions
diff --git a/kernel/irq/manage.c b/kernel/irq/manage.c
index 80eab7a04205..1f314221d534 100644
--- a/kernel/irq/manage.c
+++ b/kernel/irq/manage.c
@@ -29,12 +29,28 @@
29void synchronize_irq(unsigned int irq) 29void synchronize_irq(unsigned int irq)
30{ 30{
31 struct irq_desc *desc = irq_desc + irq; 31 struct irq_desc *desc = irq_desc + irq;
32 unsigned int status;
32 33
33 if (irq >= NR_IRQS) 34 if (irq >= NR_IRQS)
34 return; 35 return;
35 36
36 while (desc->status & IRQ_INPROGRESS) 37 do {
37 cpu_relax(); 38 unsigned long flags;
39
40 /*
41 * Wait until we're out of the critical section. This might
42 * give the wrong answer due to the lack of memory barriers.
43 */
44 while (desc->status & IRQ_INPROGRESS)
45 cpu_relax();
46
47 /* Ok, that indicated we're done: double-check carefully. */
48 spin_lock_irqsave(&desc->lock, flags);
49 status = desc->status;
50 spin_unlock_irqrestore(&desc->lock, flags);
51
52 /* Oops, that failed? */
53 } while (status & IRQ_INPROGRESS);
38} 54}
39EXPORT_SYMBOL(synchronize_irq); 55EXPORT_SYMBOL(synchronize_irq);
40 56