advk_pcie_setup_phy() initializes and powers on the PHY before the
emulated bridge and IRQ domains are created. If any of those later
initialization steps or pci_host_probe() fails, probe returns without
powering off or exiting the PHY.
Replace the direct returns with staged cleanup labels. Remove IRQ
domains in reverse order, release the emulated bridge allocation only
after successful initialization, and disable the PHY on every failure
after advk_pcie_setup_phy() succeeds. A setup_phy() failure still
returns directly, so its partial internal cleanup is not repeated.
Fixes: 366697018c9a ("PCI: aardvark: Add PHY support")
Co-developed-by: Ijae Kim <redacted>
Signed-off-by: Ijae Kim <redacted>
Signed-off-by: Myeonghun Pak <redacted>
---
drivers/pci/controller/pci-aardvark.c | 31 ++++++++++++++++++-------------
1 file changed, 18 insertions(+), 13 deletions(-)
diff --git a/drivers/pci/controller/pci-aardvark.c b/drivers/pci/controller/pci-aardvark.c
index ecb81ac73019..2bbdb73cfb45 100644
--- a/drivers/pci/controller/pci-aardvark.c
+++ b/drivers/pci/controller/pci-aardvark.c
@@ -1864,28 +1864,25 @@ static int advk_pcie_probe(struct platform_device *pdev)
ret = advk_sw_pci_bridge_init(pcie);
if (ret) {
dev_err(dev, "Failed to register emulated root PCI bridge\n");
- return ret;
+ goto err_disable_phy;
}
ret = advk_pcie_init_irq_domain(pcie);
if (ret) {
dev_err(dev, "Failed to initialize irq\n");
- return ret;
+ goto err_cleanup_bridge;
}
ret = advk_pcie_init_msi_irq_domain(pcie);
if (ret) {
dev_err(dev, "Failed to initialize irq\n");
- advk_pcie_remove_irq_domain(pcie);
- return ret;
+ goto err_remove_irq_domain;
}
ret = advk_pcie_init_rp_irq_domain(pcie);
if (ret) {
dev_err(dev, "Failed to initialize irq\n");
- advk_pcie_remove_msi_irq_domain(pcie);
- advk_pcie_remove_irq_domain(pcie);
- return ret;
+ goto err_remove_msi_irq_domain;
}
bridge->sysdata = pcie;@@ -1893,14 +1890,22 @@ static int advk_pcie_probe(struct platform_device *pdev)
bridge->map_irq = advk_pcie_map_irq;
ret = pci_host_probe(bridge);
- if (ret < 0) {
- advk_pcie_remove_rp_irq_domain(pcie);
- advk_pcie_remove_msi_irq_domain(pcie);
- advk_pcie_remove_irq_domain(pcie);
- return ret;
- }
+ if (ret < 0)
+ goto err_remove_rp_irq_domain;
return 0;
+
+err_remove_rp_irq_domain:
+ advk_pcie_remove_rp_irq_domain(pcie);
+err_remove_msi_irq_domain:
+ advk_pcie_remove_msi_irq_domain(pcie);
+err_remove_irq_domain:
+ advk_pcie_remove_irq_domain(pcie);
+err_cleanup_bridge:
+ pci_bridge_emul_cleanup(&pcie->bridge);
+err_disable_phy:
+ advk_pcie_disable_phy(pcie);
+ return ret;
}
static void advk_pcie_remove(struct platform_device *pdev)
--
2.50.1