mirror of
https://github.com/torvalds/linux.git
synced 2026-09-24 06:24:02 +02:00
PCI: plda: Fix IRQ domain leaks in the error paths of plda_init_interrupts()
plda_init_interrupts() initializes IRQ domains and creates IRQ mapping but does not unwind them when later step fails. If platform_get_irq() or either irq_create_mapping() fails in plda_init_interrupts(), the domains are never deinitialized. If irq_create_mapping() fails, port->intx_irq stays initialized. Hence, remove the IRQ domains in the error path by calling plda_pcie_irq_domain_deinit(). Since plda_pcie_irq_domain_deinit() now disposes of the intx_irq and msi_irq mappings itself before removing their domains, the msi_irq mapping failure path can go directly to err_irq_domain_deinit instead of disposing of port->intx_irq separately first. This issue was found by automated review of sashiko-bot Fixes:4602c370bd("PCI: microchip: Move IRQ functions to pcie-plda-host.c") Fixes:76c9113968("PCI: plda: Add host init/deinit and map bus functions") Closes: https://lore.kernel.org/linux-pci/20260718120701.DF4111F000E9@smtp.kernel.org/ Signed-off-by: Ali Tariq <alitariq45892@gmail.com> [mani: commit log] Signed-off-by: Manivannan Sadhasivam <manivannan.sadhasivam@oss.qualcomm.com> Cc: stable@vger.kernel.org Link: https://patch.msgid.link/20260723142824.726655-1-alitariq45892@gmail.com
This commit is contained in:
parent
26b73bae01
commit
19a30bbb64
|
|
@ -419,6 +419,8 @@ static int plda_pcie_init_irq_domains(struct plda_pcie_rp *port)
|
|||
return plda_allocate_msi_domains(port);
|
||||
}
|
||||
|
||||
static void plda_pcie_irq_domain_deinit(struct plda_pcie_rp *pcie);
|
||||
|
||||
int plda_init_interrupts(struct platform_device *pdev,
|
||||
struct plda_pcie_rp *port,
|
||||
const struct plda_event *event)
|
||||
|
|
@ -440,14 +442,17 @@ int plda_init_interrupts(struct platform_device *pdev,
|
|||
}
|
||||
|
||||
port->irq = platform_get_irq(pdev, 0);
|
||||
if (port->irq < 0)
|
||||
return -ENODEV;
|
||||
if (port->irq < 0) {
|
||||
ret = -ENODEV;
|
||||
goto err_irq_domain_deinit;
|
||||
}
|
||||
|
||||
for_each_set_bit(i, &port->events_bitmap, port->num_events) {
|
||||
event_irq = irq_create_mapping(port->event_domain, i);
|
||||
if (!event_irq) {
|
||||
dev_err(dev, "failed to map hwirq %d\n", i);
|
||||
return -ENXIO;
|
||||
ret = -ENXIO;
|
||||
goto err_irq_domain_deinit;
|
||||
}
|
||||
|
||||
if (event->request_event_irq)
|
||||
|
|
@ -459,7 +464,7 @@ int plda_init_interrupts(struct platform_device *pdev,
|
|||
|
||||
if (ret) {
|
||||
dev_err(dev, "failed to request IRQ %d\n", event_irq);
|
||||
return ret;
|
||||
goto err_irq_domain_deinit;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -467,7 +472,8 @@ int plda_init_interrupts(struct platform_device *pdev,
|
|||
event->intx_event);
|
||||
if (!port->intx_irq) {
|
||||
dev_err(dev, "failed to map INTx interrupt\n");
|
||||
return -ENXIO;
|
||||
ret = -ENXIO;
|
||||
goto err_irq_domain_deinit;
|
||||
}
|
||||
|
||||
/* Plug the INTx chained handler */
|
||||
|
|
@ -475,8 +481,11 @@ int plda_init_interrupts(struct platform_device *pdev,
|
|||
|
||||
port->msi_irq = irq_create_mapping(port->event_domain,
|
||||
event->msi_event);
|
||||
if (!port->msi_irq)
|
||||
return -ENXIO;
|
||||
if (!port->msi_irq) {
|
||||
dev_err(dev, "failed to map MSI interrupt\n");
|
||||
ret = -ENXIO;
|
||||
goto err_irq_domain_deinit;
|
||||
}
|
||||
|
||||
/* Plug the MSI chained handler */
|
||||
irq_set_chained_handler_and_data(port->msi_irq, plda_handle_msi, port);
|
||||
|
|
@ -485,6 +494,11 @@ int plda_init_interrupts(struct platform_device *pdev,
|
|||
irq_set_chained_handler_and_data(port->irq, plda_handle_event, port);
|
||||
|
||||
return 0;
|
||||
|
||||
err_irq_domain_deinit:
|
||||
plda_pcie_irq_domain_deinit(port);
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(plda_init_interrupts);
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user