[PATCH 37/37] PCI/MSI: Only check is_msi_managed in pcim_setup_msi_release()

Shawn Lin
2026-02-23T15:47:45Z

The function pcim_enable_device() sets the is_managed flag, which
causes the device's IRQ vectors to be automatically managed and released
by the devres framework. If a driver subsequently calls
pci_free_irq_vectors() manually, it can lead to a double-free of the
interrupt resources.

Analysis reveals most PCI drivers call pci_free_irq_vectors()
while also using pcim_enable_device(), making them susceptible to this
double-free issue. In contrast, 35 drivers follow the pattern of
relying on devres to handle the cleanup.

To address this inconsistency and enforce explicit, driver-managed
control of IRQ vectors, this patch removes the pci_is_managed() check
from pcim_setup_msi_release() and let devres help cleanup if is_msi_managed
is true. This change ensures that interrupt vectors are not automatically
freed by the devres machinery when pcim_enable_device() is used, placing
the responsibility for their release squarely on the driver logic via
pci_free_irq_vectors(). If the driver need devres to help cleanup, newly added
pcim_alloc_irq_vectors() and pcim_alloc_irq_vectors_affinity() helpers could be used.

Signed-off-by: Shawn Lin <shawn.lin@rock-chips.com>

---

drivers/pci/msi/msi.c | 4 +---
1 file changed, 1 insertion(+), 3 deletions(-)

diff --git a/drivers/pci/msi/msi.c b/drivers/pci/msi/msi.c
index 81d24a2..0727a0a 100644
--- a/drivers/pci/msi/msi.c
+++ b/drivers/pci/msi/msi.c
@@ -70,7 +70,6 @@ static void pcim_msi_release(void *pcidev)
{
struct pci_dev *dev = pcidev;

- dev->is_msi_managed = false;
pci_free_irq_vectors(dev);
}

@@ -92,14 +91,13 @@ static int pcim_setup_msi_release(struct pci_dev *dev)
{
int ret;

- if (!pci_is_managed(dev) || dev->is_msi_managed)
+ if (!dev->is_msi_managed)
return 0;

ret = devm_add_action(&dev->dev, pcim_msi_release, dev);
if (ret)
return ret;

- dev->is_msi_managed = true;
return 0;
}

--
2.7.4