All of lore.kernel.org
 help / color / mirror / Atom feed
From: Frank Li <Frank.li@oss.nxp.com>
To: Zhijian Han <hanzhijian1991@gmail.com>
Cc: "Richard Zhu" <hongxing.zhu@nxp.com>,
	"Lucas Stach" <l.stach@pengutronix.de>,
	"Lorenzo Pieralisi" <lpieralisi@kernel.org>,
	"Krzysztof Wilczyński" <kwilczynski@kernel.org>,
	"Manivannan Sadhasivam" <mani@kernel.org>,
	"Bjorn Helgaas" <bhelgaas@google.com>,
	"Frank Li" <Frank.Li@nxp.com>,
	"Sascha Hauer" <s.hauer@pengutronix.de>,
	"Rob Herring" <robh@kernel.org>,
	"Pengutronix Kernel Team" <kernel@pengutronix.de>,
	"Fabio Estevam" <festevam@gmail.com>,
	linux-pci@vger.kernel.org, linux-arm-kernel@lists.infradead.org,
	imx@lists.linux.dev, linux-kernel@vger.kernel.org,
	sashiko-bot@kernel.org
Subject: Re: [PATCH v6] PCI: imx6: fix resource leaks in probe error paths
Date: Thu, 3 Sep 2026 14:10:45 -0500	[thread overview]
Message-ID: <apnGNctUMNtaROtr@SMW015318> (raw)
In-Reply-To: <20260903160342.3282199-1-hanzhijian1991@gmail.com>

On Fri, Sep 04, 2026 at 12:03:42AM +0800, Zhijian Han wrote:
> imx_pcie_probe() leaks both pwrctrl devices and power domains on failure:
>
> - imx_pcie_attach_pd() attaches the "pcie" and "pcie_phy" power domains
>   and adds device links to them, but nothing detaches the domains or
>   removes the links on probe failure or deferral, so they leak.
>
> - A failure of devm_pm_runtime_set_active_enabled() returns directly
>   without destroying the pwrctrl devices.
>
> - A partial failure inside imx_pcie_attach_pd() leaks the power domains
>   that were already attached.
>
> Add imx_pcie_detach_pd() to remove the device links and detach the power
> domains in reverse order of acquisition and register it with
> devm_add_action_or_reset() so they are released automatically on probe
> failure.
>
> Reported-by: sashiko-bot@kernel.org
> Link: https://lore.kernel.org/all/20260822013640.182C01F000E9@smtp.kernel.org/
> Fixes: 2c5768344f88 ("PCI: imx6: Move pci_pwrctrl_create_devices() to imx_pcie_probe()")
> Signed-off-by: Zhijian Han <hanzhijian1991@gmail.com>
> ---
> Changes in v6:
> - Keep the device links stateless and remove them with device_link_del()
>   in imx_pcie_detach_pd() instead of using DL_FLAG_AUTOREMOVE_CONSUMER,
>   which creates managed links to power-domain devices that never bind a
>   driver and would trigger a WARN_ON in device_links_driver_bound()
>
> Changes in v5:
> - Register imx_pcie_detach_pd() with devm_add_action_or_reset() instead
>   of calling it manually on the error paths
>
>  drivers/pci/controller/dwc/pci-imx6.c | 58 ++++++++++++++++++++++-----
>  1 file changed, 48 insertions(+), 10 deletions(-)
>
> diff --git a/drivers/pci/controller/dwc/pci-imx6.c b/drivers/pci/controller/dwc/pci-imx6.c
> index 39790e66b98d..7dd22b4f826a 100644
> --- a/drivers/pci/controller/dwc/pci-imx6.c
> +++ b/drivers/pci/controller/dwc/pci-imx6.c
> @@ -180,8 +180,12 @@ struct imx_pcie {
>  	struct imx_lut_data	luts[IMX95_MAX_LUT];
>  	/* power domain for pcie */
>  	struct device		*pd_pcie;
> +	/* device link for pcie power domain */
> +	struct device_link	*pd_link;
>  	/* power domain for pcie phy */
>  	struct device		*pd_pcie_phy;
> +	/* device link for pcie phy power domain */
> +	struct device_link	*pd_phy_link;
>  	struct phy		*phy;
>  	const struct imx_pcie_drvdata *drvdata;
>
> @@ -639,10 +643,34 @@ static int imx6q_pcie_abort_handler(unsigned long addr,
>  }
>  #endif
>
> +static void imx_pcie_detach_pd(struct imx_pcie *imx_pcie)
> +{
> +	if (!IS_ERR_OR_NULL(imx_pcie->pd_phy_link)) {
> +		device_link_del(imx_pcie->pd_phy_link);
> +		imx_pcie->pd_phy_link = NULL;
> +	}
> +	if (!IS_ERR_OR_NULL(imx_pcie->pd_link)) {
> +		device_link_del(imx_pcie->pd_link);
> +		imx_pcie->pd_link = NULL;
> +	}
> +	if (!IS_ERR_OR_NULL(imx_pcie->pd_pcie_phy)) {
> +		dev_pm_domain_detach(imx_pcie->pd_pcie_phy, true);
> +		imx_pcie->pd_pcie_phy = NULL;
> +	}
> +	if (!IS_ERR_OR_NULL(imx_pcie->pd_pcie)) {
> +		dev_pm_domain_detach(imx_pcie->pd_pcie, true);
> +		imx_pcie->pd_pcie = NULL;
> +	}
> +}
> +
> +static void imx_pcie_detach_pd_action(void *data)
> +{
> +	imx_pcie_detach_pd(data);
> +}
> +
>  static int imx_pcie_attach_pd(struct device *dev)
>  {
>  	struct imx_pcie *imx_pcie = dev_get_drvdata(dev);
> -	struct device_link *link;
>
>  	/* Do nothing when in a single power domain */
>  	if (dev->pm_domain)
> @@ -654,25 +682,31 @@ static int imx_pcie_attach_pd(struct device *dev)
>  	/* Do nothing when power domain missing */
>  	if (!imx_pcie->pd_pcie)
>  		return 0;
> -	link = device_link_add(dev, imx_pcie->pd_pcie,
> -			DL_FLAG_STATELESS |
> +	imx_pcie->pd_link = device_link_add(dev, imx_pcie->pd_pcie,
> +					    DL_FLAG_STATELESS |
>  			DL_FLAG_PM_RUNTIME |
>  			DL_FLAG_RPM_ACTIVE);
> -	if (!link) {
> +	if (!imx_pcie->pd_link) {
>  		dev_err(dev, "Failed to add device_link to pcie pd\n");
> +		imx_pcie_detach_pd(imx_pcie);
>  		return -EINVAL;
>  	}
>
>  	imx_pcie->pd_pcie_phy = dev_pm_domain_attach_by_name(dev, "pcie_phy");
> -	if (IS_ERR(imx_pcie->pd_pcie_phy))
> -		return PTR_ERR(imx_pcie->pd_pcie_phy);
> +	if (IS_ERR(imx_pcie->pd_pcie_phy)) {
> +		int ret = PTR_ERR(imx_pcie->pd_pcie_phy);
> +
> +		imx_pcie_detach_pd(imx_pcie);
> +		return ret;
> +	}
>
> -	link = device_link_add(dev, imx_pcie->pd_pcie_phy,
> -			DL_FLAG_STATELESS |
> +	imx_pcie->pd_phy_link = device_link_add(dev, imx_pcie->pd_pcie_phy,
> +						DL_FLAG_STATELESS |
>  			DL_FLAG_PM_RUNTIME |
>  			DL_FLAG_RPM_ACTIVE);
> -	if (!link) {
> +	if (!imx_pcie->pd_phy_link) {
>  		dev_err(dev, "Failed to add device_link to pcie_phy pd\n");
> +		imx_pcie_detach_pd(imx_pcie);
>  		return -EINVAL;
>  	}
>
> @@ -1955,6 +1989,10 @@ static int imx_pcie_probe(struct platform_device *pdev)
>  	if (ret)
>  		return ret;
>
> +	ret = devm_add_action_or_reset(dev, imx_pcie_detach_pd_action, imx_pcie);
> +	if (ret)
> +		return ret;
> +

because there is safe guide in imx_pcie_detac_pd_action(), if move it before
imx_pcie_attach_pd(),  Needn't call imx_pcie_detach_pd() in error path.

Or use goto in for error handle in imx_pcie_attach_pd() instead of duplicate
call each error branch.

Frank

>  	ret = pci_pwrctrl_create_devices(dev);
>  	if (ret)
>  		return dev_err_probe(dev, ret, "failed to create pwrctrl devices\n");
> @@ -1975,7 +2013,7 @@ static int imx_pcie_probe(struct platform_device *pdev)
>  			pm_runtime_no_callbacks(dev);
>  			ret = devm_pm_runtime_set_active_enabled(dev);
>  			if (ret < 0)
> -				return ret;
> +				goto err_pwrctrl_destroy;
>  		}
>
>  		if (imx_check_flag(imx_pcie, IMX_PCIE_FLAG_SKIP_L23_READY))
>


      parent reply	other threads:[~2026-09-03 19:11 UTC|newest]

Thread overview: 3+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-09-03 16:03 [PATCH v6] PCI: imx6: fix resource leaks in probe error paths Zhijian Han
2026-09-03 16:13 ` sashiko-bot
2026-09-03 19:10 ` Frank Li [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=apnGNctUMNtaROtr@SMW015318 \
    --to=frank.li@oss.nxp.com \
    --cc=Frank.Li@nxp.com \
    --cc=bhelgaas@google.com \
    --cc=festevam@gmail.com \
    --cc=hanzhijian1991@gmail.com \
    --cc=hongxing.zhu@nxp.com \
    --cc=imx@lists.linux.dev \
    --cc=kernel@pengutronix.de \
    --cc=kwilczynski@kernel.org \
    --cc=l.stach@pengutronix.de \
    --cc=linux-arm-kernel@lists.infradead.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-pci@vger.kernel.org \
    --cc=lpieralisi@kernel.org \
    --cc=mani@kernel.org \
    --cc=robh@kernel.org \
    --cc=s.hauer@pengutronix.de \
    --cc=sashiko-bot@kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.