]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
mmc: sdhci-of-dwcmshc: check bus clock enable result in the probe() method
authorSergey Shtylyov <s.shtylyov@auroraos.dev>
Mon, 1 Jun 2026 14:49:01 +0000 (17:49 +0300)
committerUlf Hansson <ulfh@kernel.org>
Mon, 6 Jul 2026 13:22:11 +0000 (15:22 +0200)
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 <s.shtylyov@auroraos.dev>
Acked-by: Adrian Hunter <adrian.hunter@intel.com>
Cc: stable@vger.kernel.org
Signed-off-by: Ulf Hansson <ulfh@kernel.org>
drivers/mmc/host/sdhci-of-dwcmshc.c

index eef53455b8ee49310887274f4dc35c790ce896a8..c688f3eaf4686f5facd4170816f7a270fdddefb9 100644 (file)
@@ -2433,13 +2433,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);
 
@@ -2453,7 +2456,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
@@ -2499,9 +2502,10 @@ err_setup_host:
 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;
 }