summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorMyeonghun Pak <mhun512@gmail.com>2026-06-23 17:42:23 +0900
committerHerbert Xu <herbert@gondor.apana.org.au>2026-07-05 13:27:15 +0800
commitf8c24e6899e263073fbbeb07fadc1af85ec492f5 (patch)
treedbf4b9b32e9b5b2b4168faf0eb69665b38c2d59c /drivers
parentba088974419326daf46c5dc03e2cf6ab6ab701f7 (diff)
downloadlinux-next-f8c24e6899e263073fbbeb07fadc1af85ec492f5.tar.gz
linux-next-f8c24e6899e263073fbbeb07fadc1af85ec492f5.zip
hwrng: omap - Fix probe error path cleanup
omap_rng_probe() enables runtime PM before acquiring and enabling the functional clocks. Several later error paths returned or unwound without undoing all state acquired so far. If pm_runtime_resume_and_get() failed, the driver returned through the generic ioremap error label and left runtime PM enabled. If either clock lookup returned -EPROBE_DEFER, the function returned directly and skipped the runtime PM cleanup; the register clock defer path could also leave the already enabled functional clock prepared. Route these failures through the existing unwind labels so each path only undoes resources that were acquired successfully. Keep the resume failure path limited to pm_runtime_disable(), and use the later labels only after the runtime PM usage count or clocks have been acquired. This issue was identified during our ongoing static-analysis research while reviewing kernel code. Fixes: 61dc0a446e5d ("hwrng: omap - Fix assumption that runtime_get_sync will always succeed") Fixes: 43ec540e6f9b ("hwrng: omap - move clock related code to omap_rng_probe()") Fixes: b166be004491 ("hwrng: omap - Fix clock resource by adding a register clock") Co-developed-by: Ijae Kim <ae878000@gmail.com> Signed-off-by: Ijae Kim <ae878000@gmail.com> Signed-off-by: Myeonghun Pak <mhun512@gmail.com> Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/char/hw_random/omap-rng.c30
1 files changed, 20 insertions, 10 deletions
diff --git a/drivers/char/hw_random/omap-rng.c b/drivers/char/hw_random/omap-rng.c
index 5e8b50f15db7..a8c0b3dfb133 100644
--- a/drivers/char/hw_random/omap-rng.c
+++ b/drivers/char/hw_random/omap-rng.c
@@ -455,32 +455,40 @@ static int omap_rng_probe(struct platform_device *pdev)
ret = pm_runtime_resume_and_get(&pdev->dev);
if (ret < 0) {
dev_err(&pdev->dev, "Failed to runtime_get device: %d\n", ret);
- goto err_ioremap;
+ goto err_pm_disable;
}
priv->clk = devm_clk_get(&pdev->dev, NULL);
- if (PTR_ERR(priv->clk) == -EPROBE_DEFER)
- return -EPROBE_DEFER;
+ if (PTR_ERR(priv->clk) == -EPROBE_DEFER) {
+ ret = -EPROBE_DEFER;
+ goto err_pm_put;
+ }
if (!IS_ERR(priv->clk)) {
ret = clk_prepare_enable(priv->clk);
if (ret) {
dev_err(&pdev->dev,
"Unable to enable the clk: %d\n", ret);
- goto err_register;
+ goto err_pm_put;
}
+ } else {
+ priv->clk = NULL;
}
priv->clk_reg = devm_clk_get(&pdev->dev, "reg");
- if (PTR_ERR(priv->clk_reg) == -EPROBE_DEFER)
- return -EPROBE_DEFER;
+ if (PTR_ERR(priv->clk_reg) == -EPROBE_DEFER) {
+ ret = -EPROBE_DEFER;
+ goto err_clk;
+ }
if (!IS_ERR(priv->clk_reg)) {
ret = clk_prepare_enable(priv->clk_reg);
if (ret) {
dev_err(&pdev->dev,
"Unable to enable the register clk: %d\n",
ret);
- goto err_register;
+ goto err_clk;
}
+ } else {
+ priv->clk_reg = NULL;
}
ret = (dev->of_node) ? of_get_omap_rng_device_details(priv, pdev) :
@@ -498,12 +506,14 @@ static int omap_rng_probe(struct platform_device *pdev)
return 0;
err_register:
+ clk_disable_unprepare(priv->clk_reg);
+err_clk:
+ clk_disable_unprepare(priv->clk);
+err_pm_put:
priv->base = NULL;
pm_runtime_put_sync(&pdev->dev);
+err_pm_disable:
pm_runtime_disable(&pdev->dev);
-
- clk_disable_unprepare(priv->clk_reg);
- clk_disable_unprepare(priv->clk);
err_ioremap:
dev_err(dev, "initialization failed.\n");
return ret;