Merge branches 's390', 'arm/renesas', 'arm/msm', 'arm/shmobile', 'arm/smmu', 'x86...
[cascardo/linux.git] / arch / powerpc / platforms / powernv / opal-irqchip.c
index 0a00e2a..e505223 100644 (file)
@@ -83,7 +83,19 @@ static void opal_event_unmask(struct irq_data *d)
        set_bit(d->hwirq, &opal_event_irqchip.mask);
 
        opal_poll_events(&events);
-       opal_handle_events(be64_to_cpu(events));
+       last_outstanding_events = be64_to_cpu(events);
+
+       /*
+        * We can't just handle the events now with opal_handle_events().
+        * If we did we would deadlock when opal_event_unmask() is called from
+        * handle_level_irq() with the irq descriptor lock held, because
+        * calling opal_handle_events() would call generic_handle_irq() and
+        * then handle_level_irq() which would try to take the descriptor lock
+        * again. Instead queue the events for later.
+        */
+       if (last_outstanding_events & opal_event_irqchip.mask)
+               /* Need to retrigger the interrupt */
+               irq_work_queue(&opal_event_irq_work);
 }
 
 static int opal_event_set_type(struct irq_data *d, unsigned int flow_type)