summaryrefslogtreecommitdiffstats
path: root/drivers/pci
diff options
context:
space:
mode:
authorHeiner Kallweit <hkallweit1@gmail.com>2018-08-05 22:31:03 +0200
committerBjorn Helgaas <bhelgaas@google.com>2018-08-14 16:11:02 -0500
commit923aa4c378f9c7bbe2dff6f5632f95815b7700e9 (patch)
tree2244c8b36cea2440b44d6348c3ca43155d8f5aca /drivers/pci
parentce397d215ccd07b8ae3f71db689aedb85d56ab40 (diff)
downloadlinux-923aa4c378f9c7bbe2dff6f5632f95815b7700e9.tar.bz2
PCI/MSI: Set IRQCHIP_ONESHOT_SAFE for PCI-MSI irqchips
If flag IRQCHIP_ONESHOT_SAFE isn't set for an irqchip and we have a threaded interrupt with no primary handler, flag IRQF_ONESHOT needs to be set for the interrupt, causing some overhead in the threaded interrupt handler. For more detailed explanation also check following comment in __setup_irq(): The interrupt was requested with handler = NULL, so we use the default primary handler for it. But it does not have the oneshot flag set. In combination with level interrupts this is deadly, because the default primary handler just wakes the thread, then the irq lines is reenabled, but the device still has the level irq asserted. Rinse and repeat.... While this works for edge type interrupts, we play it safe and reject unconditionally because we can't say for sure which type this interrupt really has. The type flags are unreliable as the underlying chip implementation can override them. Another comment in __setup_irq() gives a hint already that this overhead can be avoided for PCI-MSI: 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. Following this let's mark all PCI-MSI irqchips as oneshot-safe. See also discussion here: https://lkml.kernel.org/r/alpine.DEB.2.21.1808032136490.1658@nanos.tec.linutronix.de Signed-off-by: Heiner Kallweit <hkallweit1@gmail.com> Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
Diffstat (limited to 'drivers/pci')
-rw-r--r--drivers/pci/msi.c3
1 files changed, 3 insertions, 0 deletions
diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c
index 4d88afdfc843..f2ef896464b3 100644
--- a/drivers/pci/msi.c
+++ b/drivers/pci/msi.c
@@ -1446,6 +1446,9 @@ struct irq_domain *pci_msi_create_irq_domain(struct fwnode_handle *fwnode,
if (IS_ENABLED(CONFIG_GENERIC_IRQ_RESERVATION_MODE))
info->flags |= MSI_FLAG_MUST_REACTIVATE;
+ /* PCI-MSI is oneshot-safe */
+ info->chip->flags |= IRQCHIP_ONESHOT_SAFE;
+
domain = msi_create_irq_domain(fwnode, info, parent);
if (!domain)
return NULL;