[PATCH] PCI/MSI: Clear msi_desc::irq in the legacy teardown path
From: Stian Halseth
Date: Tue Sep 29 2026 - 07:10:29 EST
pci_msi_teardown_msi_irqs() runs the legacy teardown and then calls
msi_free_msi_descs(), which refuses to free a descriptor that is still
associated with an interrupt:
/* Leak the descriptor when it is still referenced */
if (WARN_ON_ONCE(msi_desc_match(desc, MSI_DESC_ASSOCIATED)))
continue;
MSI_DESC_ASSOCIATED is msi_desc::irq being non-zero, and nothing in the
legacy path clears it - neither the generic arch_teardown_msi_irqs() nor
the arch_teardown_msi_irq() implementations on sparc and mips/octeon.
Every teardown therefore leaks one descriptor per vector. The check is
WARN_ON_ONCE, so only the first teardown after boot is visible and the
warning understates how often this happens.
Before commit 9fb9eb4b59ac ("PCI/MSI: Let core code free MSI descriptors")
free_msi_irqs() freed the descriptors unconditionally, so a stale
msi_desc::irq was harmless. That commit moved the freeing into the core
and added the precondition without satisfying it here.
powerpc overrides arch_teardown_msi_irqs() and clears msi_desc::irq
itself, so it is unaffected; do the same in the generic implementation.
Reproduced on an UltraSPARC T7-1 (ixgbe, "ethtool -L <if> combined 4")
and on an UltraSPARC T4-1 (igb, unbinding the PCI function). Verified
fixed on the T7-1: repeated MSI-X teardown and setup is clean.
Fixes: 9fb9eb4b59ac ("PCI/MSI: Let core code free MSI descriptors")
Closes: https://github.com/sparclinux/issues/issues/104
Signed-off-by: Stian Halseth <stian@xxxxxx>
---
drivers/pci/msi/legacy.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/drivers/pci/msi/legacy.c b/drivers/pci/msi/legacy.c
index db761adef652b..f174859485552 100644
--- a/drivers/pci/msi/legacy.c
+++ b/drivers/pci/msi/legacy.c
@@ -45,6 +45,7 @@ void __weak arch_teardown_msi_irqs(struct pci_dev *dev)
msi_for_each_desc(desc, &dev->dev, MSI_DESC_ASSOCIATED) {
for (i = 0; i < desc->nvec_used; i++)
arch_teardown_msi_irq(desc->irq + i);
+ desc->irq = 0;
}
}
--
2.43.0