[<prev] [next>] [thread-next>] [day] [month] [year] [list]
Message-Id: <20250517103011.2573288-1-maz@kernel.org>
Date: Sat, 17 May 2025 11:30:11 +0100
From: Marc Zyngier <maz@...nel.org>
To: linux-kernel@...r.kernel.org,
linux-arm-kernel@...ts.infradead.org
Cc: Thomas Gleixner <tglx@...utronix.de>
Subject: [PATCH] irqchip/msi-lib: Honor the MSI_FLAG_PCI_MSI_MASK_PARENT flag
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 side, 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 likely to be cheaper than a round-trip
to the endpoint.
Implement this by patching up the irq_chip structure associated with
the MSIs to perform the full unmask on .irq_enable(), and the full mask
on .irq_shutdown(). This asymmetry allows the preservation of the
"lazy disable" feature, which relies on the top-level irq_chip not
implementing the .irq_disable() callback. Yes, this is a terrible hack.
Signed-off-by: Marc Zyngier <maz@...nel.org>
---
drivers/irqchip/irq-msi-lib.c | 15 +++++++++++++++
1 file changed, 15 insertions(+)
diff --git a/drivers/irqchip/irq-msi-lib.c b/drivers/irqchip/irq-msi-lib.c
index 246c30205af40..8c62034ab8d92 100644
--- a/drivers/irqchip/irq-msi-lib.c
+++ b/drivers/irqchip/irq-msi-lib.c
@@ -112,6 +112,21 @@ 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 default mask/unmask become the shutdown/enable
+ * callbacks, ensuring that we correctly start/stop the interrupt.
+ * We make a point in not using the irq_disable() in order to
+ * preserve the "lazy disable" behaviour.
+ */
+ if (info->flags & MSI_FLAG_PCI_MSI_MASK_PARENT) {
+ chip->irq_shutdown = chip->irq_mask;
+ chip->irq_enable = chip->irq_unmask;
+ 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);
--
2.39.2
Powered by blists - more mailing lists