[PATCH] PCI: imx6: fix endpoint init error handling
Zhijian Han <[email protected]>
| Newsgroups | org.infradead.lists.linux-arm-kernel,dev.linux.lists.imx,org.kernel.vger.linux-kernel,org.kernel.vger.linux-pci |
|---|---|
| Message-ID | <[email protected]> |
imx_add_pcie_ep() ignores the return value of imx_pcie_host_init(), so a failure to enable the clocks, regulators, or PHY during endpoint initialization goes unnoticed and the driver proceeds to initialize the endpoint against unpowered hardware. It also returns directly without calling imx_pcie_host_exit() when dw_pcie_ep_init() or dw_pcie_ep_init_registers() fails, leaking the clocks, regulators, and PHY that imx_pcie_host_init() acquired. Check the return value of imx_pcie_host_init() and jump to a new err_host_exit label that calls imx_pcie_host_exit() from the endpoint initialization error paths, mirroring the root port path which releases these resources through the dw_pcie_host_init() framework. Reported-by: [email protected] Link: https://lore.kernel.org/all/[email protected]/ Signed-off-by: Zhijian Han <[email protected]> --- drivers/pci/controller/dwc/pci-imx6.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/drivers/pci/controller/dwc/pci-imx6.c b/drivers/pci/controller/dwc/pci-imx6.c index 39790e66b..1dad93e9d 100644 --- a/drivers/pci/controller/dwc/pci-imx6.c +++ b/drivers/pci/controller/dwc/pci-imx6.c @@ -1634,7 +1634,10 @@ static int imx_add_pcie_ep(struct imx_pcie *imx_pcie, struct dw_pcie_rp *pp = &pci->pp; struct device *dev = pci->dev; - imx_pcie_host_init(pp); + ret = imx_pcie_host_init(pp); + if (ret) + return ret; + ep = &pci->ep; ep->ops = &pcie_ep_ops; @@ -1646,7 +1649,7 @@ static int imx_add_pcie_ep(struct imx_pcie *imx_pcie, ret = dw_pcie_ep_init(ep); if (ret) { dev_err(dev, "failed to initialize endpoint\n"); - return ret; + goto err_host_exit; } imx_pcie_host_post_init(pp); @@ -1654,12 +1657,16 @@ static int imx_add_pcie_ep(struct imx_pcie *imx_pcie, if (ret) { dev_err(dev, "Failed to initialize DWC endpoint registers\n"); dw_pcie_ep_deinit(ep); - return ret; + goto err_host_exit; } pci_epc_init_notify(ep->epc); return 0; + +err_host_exit: + imx_pcie_host_exit(pp); + return ret; } static void imx_pcie_msi_save_restore(struct imx_pcie *imx_pcie, bool save) -- 2.43.0