|
@@ -959,6 +959,18 @@ __setup_irq(unsigned int irq, struct irq_desc *desc, struct irqaction *new)
|
|
|
goto out_thread;
|
|
|
}
|
|
|
|
|
|
+ /*
|
|
|
+ * Drivers are often written to work w/o knowledge about the
|
|
|
+ * underlying irq chip implementation, so a request for a
|
|
|
+ * threaded irq without a primary hard irq context handler
|
|
|
+ * requires the ONESHOT flag to be set. Some irq chips like
|
|
|
+ * MSI based interrupts are per se one shot safe. Check the
|
|
|
+ * chip flags, so we can avoid the unmask dance at the end of
|
|
|
+ * the threaded handler for those.
|
|
|
+ */
|
|
|
+ if (desc->irq_data.chip->flags & IRQCHIP_ONESHOT_SAFE)
|
|
|
+ new->flags &= ~IRQF_ONESHOT;
|
|
|
+
|
|
|
/*
|
|
|
* The following block of code has to be executed atomically
|
|
|
*/
|
|
@@ -1033,7 +1045,8 @@ __setup_irq(unsigned int irq, struct irq_desc *desc, struct irqaction *new)
|
|
|
*/
|
|
|
new->thread_mask = 1 << ffz(thread_mask);
|
|
|
|
|
|
- } else if (new->handler == irq_default_primary_handler) {
|
|
|
+ } else if (new->handler == irq_default_primary_handler &&
|
|
|
+ !(desc->irq_data.chip->flags & IRQCHIP_ONESHOT_SAFE)) {
|
|
|
/*
|
|
|
* The interrupt was requested with handler = NULL, so
|
|
|
* we use the default primary handler for it. But it
|