[PATCH 2/3] PCI: altera: fix resource leaks on probe failure

From: Mahesh Vaidya

Date: Fri Apr 24 2026 - 05:50:11 EST


The chained IRQ handler is installed in altera_pcie_parse_dt() but
never unregistered on probe failure. If any subsequent step in
altera_pcie_probe() fails, devm frees the pcie struct while the
handler still references it. A subsequent interrupt would trigger
a use-after-free.

The INTx IRQ domain created in altera_pcie_init_irq_domain() is
similarly leaked on probe failure, since the existing cleanup via
altera_pcie_irq_teardown() is only invoked from the remove path.

Move the handler installation from altera_pcie_parse_dt() into
altera_pcie_probe() after the IRQ domain is created, and add a
goto-based error path so altera_pcie_irq_teardown() is called on
any failure after handler installation.

Fixes: 60f2ee5f1472 ("PCI: altera: Add Agilex support")
Signed-off-by: Mahesh Vaidya <mahesh.vaidya@xxxxxxxxxx>
---
drivers/pci/controller/pcie-altera.c | 17 +++++++++++++++--
1 file changed, 15 insertions(+), 2 deletions(-)

diff --git a/drivers/pci/controller/pcie-altera.c b/drivers/pci/controller/pcie-altera.c
index 3dbb7adc421c..025ba74d1ee2 100644
--- a/drivers/pci/controller/pcie-altera.c
+++ b/drivers/pci/controller/pcie-altera.c
@@ -891,7 +891,6 @@ static int altera_pcie_parse_dt(struct altera_pcie *pcie)
if (pcie->irq < 0)
return pcie->irq;

- irq_set_chained_handler_and_data(pcie->irq, pcie->pcie_data->ops->rp_isr, pcie);
return 0;
}

@@ -1020,6 +1019,11 @@ static int altera_pcie_probe(struct platform_device *pdev)
return ret;
}

+ /* Install chained handler after domain is ready */
+ irq_set_chained_handler_and_data(pcie->irq,
+ pcie->pcie_data->ops->rp_isr,
+ pcie);
+
if (pcie->pcie_data->version == ALTERA_PCIE_V1 ||
pcie->pcie_data->version == ALTERA_PCIE_V2) {
/* clear all interrupts */
@@ -1037,7 +1041,16 @@ static int altera_pcie_probe(struct platform_device *pdev)
bridge->busnr = pcie->root_bus_nr;
bridge->ops = &altera_pcie_ops;

- return pci_host_probe(bridge);
+ ret = pci_host_probe(bridge);
+ if (ret)
+ goto err_teardown_irq;
+
+ return 0;
+
+err_teardown_irq:
+ altera_pcie_irq_teardown(pcie);
+
+ return ret;
}

static void altera_pcie_remove(struct platform_device *pdev)
--
2.34.1