]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
irqchip/msi-lib: Honor the MSI_FLAG_PCI_MSI_MASK_PARENT flag
authorMarc Zyngier <maz@kernel.org>
Wed, 3 Sep 2025 14:04:46 +0000 (16:04 +0200)
committerThomas Gleixner <tglx@linutronix.de>
Tue, 9 Sep 2025 12:44:30 +0000 (14:44 +0200)
For systems that implement interrupt masking at the interrupt controller
level, the MSI library offers MSI_FLAG_PCI_MSI_MASK_PARENT.  It indicates
that it isn't enough to only unmask the interrupt at the PCI device level,
but that the interrupt controller must also be involved.

However, the way this is currently done is less than optimal, as the
masking/unmasking is done on both sides, always. It would be far cheaper to
unmask both at the start of times, and then only deal with the interrupt
controller mask, which is cheaper than a round-trip to the PCI endpoint.

Now that the PCI/MSI layer implements irq_startup() and irq_shutdown()
callbacks, which [un]mask at the PCI level and honor the request to
[un]mask the parent, this can be trivially done.

Overwrite the irq_mask/unmask() callbacks of the device domain interrupt
chip with irq_[un]mask_parent() when the parent domain asks for it.

[ tglx: Adopted to the PCI/MSI changes ]

Signed-off-by: Marc Zyngier <maz@kernel.org>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Tested-by: Marc Zyngier <maz@kernel.org>
Acked-by: Marc Zyngier <maz@kernel.org>
Link: https://lore.kernel.org/all/20250903135433.380783272@linutronix.de
drivers/irqchip/irq-msi-lib.c

index 908944009c210bcae7d32d781736651417cdb145..d5eefc3d72155c39b10a72809f2838a95997c459 100644 (file)
@@ -112,6 +112,20 @@ bool msi_lib_init_dev_msi_info(struct device *dev, struct irq_domain *domain,
         */
        if (!chip->irq_set_affinity && !(info->flags & MSI_FLAG_NO_AFFINITY))
                chip->irq_set_affinity = msi_domain_set_affinity;
+
+       /*
+        * If the parent domain insists on being in charge of masking, obey
+        * blindly. The interrupt is un-masked at the PCI level on startup
+        * and masked on shutdown to prevent rogue interrupts after the
+        * driver freed the interrupt. Not masking it at the PCI level
+        * speeds up operation for disable/enable_irq() as it avoids
+        * getting all the way out to the PCI device.
+        */
+       if (info->flags & MSI_FLAG_PCI_MSI_MASK_PARENT) {
+               chip->irq_mask          = irq_chip_mask_parent;
+               chip->irq_unmask        = irq_chip_unmask_parent;
+       }
+
        return true;
 }
 EXPORT_SYMBOL_GPL(msi_lib_init_dev_msi_info);