Re: [PATCH v3] mmc: sdhci-of-dwcmshc: check bus clock enable result in the probe() method
Ulf Hansson <[email protected]> Mon, 6 Jul 2026 17:46:10 +0200
| Newsgroups | org.kernel.vger.linux-mmc |
|---|---|
| Message-ID | <CAPx+jO_MxS_qetj1nf_u_AGx63X+2-oZ+no_x769JgLqJirB+A@mail.gmail.com> |
On Mon, Jun 1, 2026 at 4:49 PM Sergey Shtylyov <[email protected]> wrote: > > In the driver's probe() method, clk_disable_unprepare() for the bus clock > is called on the error path even if the prior clk_prepare_enable() call has > failed (and the same thing happens in the remove() method as well) -- that > would cause the prepare/enable counter imbalance. Also, the same problem > can happen in the driver's suspend() method; note that the resume() method > does check the clk_prepare_enable()'s result -- let's be consistent and do > that in probe() method as well. BTW, I don't know for sure what does the > bus clock control -- if it affects the register accesses, the driver will > likely cause (e.g. on ARM) a kernel oops if it fails to prepare/enable the > bus clock in the probe() method... > > Found by Linux Verification Center (linuxtesting.org) with the Svace static > analysis tool. > > Fixes: e438cf49b305 ("mmc: sdhci-of-dwcmshc: add SDHCI OF Synopsys DWC MSHC driver") > Fixes: bccce2ec7790 ("mmc: sdhci-of-dwcmshc: add suspend/resume support") > Signed-off-by: Sergey Shtylyov <[email protected]> Applied for fixes and by adding a stable tag, thanks! Kind regards Uffe > > --- > This patch is against the fixes branch of Ulf Hansson's mmc.git repo. > > Changes in version 3: > - dropped stray comma in the subject; > - dropped unneeded word in the description. > > Changes in version 2: > - mentioned the problem in the remove() method as well, somewhat rephrased > the patch description. > > drivers/mmc/host/sdhci-of-dwcmshc.c | 14 +++++++++----- > 1 file changed, 9 insertions(+), 5 deletions(-) > > diff --git a/drivers/mmc/host/sdhci-of-dwcmshc.c b/drivers/mmc/host/sdhci-of-dwcmshc.c > index b9ecd91f44ad..29af07561a86 100644 > --- a/drivers/mmc/host/sdhci-of-dwcmshc.c > +++ b/drivers/mmc/host/sdhci-of-dwcmshc.c > @@ -2441,13 +2441,16 @@ static int dwcmshc_probe(struct platform_device *pdev) > return err; > > priv->bus_clk = devm_clk_get(dev, "bus"); > - if (!IS_ERR(priv->bus_clk)) > - clk_prepare_enable(priv->bus_clk); > + if (!IS_ERR(priv->bus_clk)) { > + err = clk_prepare_enable(priv->bus_clk); > + if (err) > + goto err_clk; > + } > } > > err = mmc_of_parse(host->mmc); > if (err) > - goto err_clk; > + goto err_bus_clk; > > sdhci_get_of_property(pdev); > > @@ -2461,7 +2464,7 @@ static int dwcmshc_probe(struct platform_device *pdev) > if (pltfm_data->init) { > err = pltfm_data->init(&pdev->dev, host, priv); > if (err) > - goto err_clk; > + goto err_bus_clk; > } > > #ifdef CONFIG_ACPI > @@ -2507,9 +2510,10 @@ static int dwcmshc_probe(struct platform_device *pdev) > err_rpm: > pm_runtime_disable(dev); > pm_runtime_put_noidle(dev); > +err_bus_clk: > + clk_disable_unprepare(priv->bus_clk); > err_clk: > clk_disable_unprepare(pltfm_host->clk); > - clk_disable_unprepare(priv->bus_clk); > clk_bulk_disable_unprepare(priv->num_other_clks, priv->other_clks); > return err; > } > -- > 2.54.0