Merge branch 'pci/controller/altera'

- Do not dispose of the parent IRQ mapping, which belongs to the parent
  interrupt controller (Mahesh Vaidya)

- Fix chained IRQ handler ordering issue and resource leaks on probe
  failure (Mahesh Vaidya)

* pci/controller/altera:
  PCI: altera: Fix resource leaks on probe failure
  PCI: altera: Do not dispose parent IRQ mapping
This commit is contained in:
Bjorn Helgaas 2026-06-23 17:32:05 -05:00
commit bf27eed040

View File

@ -864,11 +864,25 @@ static int altera_pcie_init_irq_domain(struct altera_pcie *pcie)
return 0;
}
static void altera_pcie_disable_irq(struct altera_pcie *pcie)
{
if (pcie->pcie_data->version == ALTERA_PCIE_V1 ||
pcie->pcie_data->version == ALTERA_PCIE_V2) {
/* Disable all P2A interrupts */
cra_writel(pcie, 0, P2A_INT_ENABLE);
} else if (pcie->pcie_data->version == ALTERA_PCIE_V3) {
/* Disable port-level interrupts (CFG_AER, etc.) */
writel(0, pcie->hip_base +
pcie->pcie_data->port_conf_offset +
pcie->pcie_data->port_irq_enable_offset);
}
}
static void altera_pcie_irq_teardown(struct altera_pcie *pcie)
{
altera_pcie_disable_irq(pcie);
irq_set_chained_handler_and_data(pcie->irq, NULL, NULL);
irq_domain_remove(pcie->irq_domain);
irq_dispose_mapping(pcie->irq);
}
static int altera_pcie_parse_dt(struct altera_pcie *pcie)
@ -891,7 +905,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 +1033,14 @@ static int altera_pcie_probe(struct platform_device *pdev)
return ret;
}
/*
* The chained handler uses pcie->irq_domain, so set it only after the
* INTx domain has been created.
*/
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 +1058,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)