| From 715ccdf18c8c88329a35fdd3c69c07b7e74ada91 Mon Sep 17 00:00:00 2001 |
| From: Sasha Levin <sashal@kernel.org> |
| Date: Fri, 16 Jun 2023 09:58:13 +0100 |
| Subject: hwrng: st - keep clock enabled while hwrng is registered |
| |
| From: Martin Kaiser <martin@kaiser.cx> |
| |
| [ Upstream commit 501e197a02d4aef157f53ba3a0b9049c3e52fedc ] |
| |
| The st-rng driver uses devres to register itself with the hwrng core, |
| the driver will be unregistered from hwrng when its device goes out of |
| scope. This happens after the driver's remove function is called. |
| |
| However, st-rng's clock is disabled in the remove function. There's a |
| short timeframe where st-rng is still registered with the hwrng core |
| although its clock is disabled. I suppose the clock must be active to |
| access the hardware and serve requests from the hwrng core. |
| |
| Switch to devm_clk_get_enabled and let devres disable the clock and |
| unregister the hwrng. This avoids the race condition. |
| |
| Fixes: 3e75241be808 ("hwrng: drivers - Use device-managed registration API") |
| Signed-off-by: Martin Kaiser <martin@kaiser.cx> |
| Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au> |
| Signed-off-by: Sasha Levin <sashal@kernel.org> |
| --- |
| drivers/char/hw_random/st-rng.c | 21 +-------------------- |
| 1 file changed, 1 insertion(+), 20 deletions(-) |
| |
| diff --git a/drivers/char/hw_random/st-rng.c b/drivers/char/hw_random/st-rng.c |
| index 50975e761ca58..f708a99619ecb 100644 |
| --- a/drivers/char/hw_random/st-rng.c |
| +++ b/drivers/char/hw_random/st-rng.c |
| @@ -42,7 +42,6 @@ |
| |
| struct st_rng_data { |
| void __iomem *base; |
| - struct clk *clk; |
| struct hwrng ops; |
| }; |
| |
| @@ -87,26 +86,18 @@ static int st_rng_probe(struct platform_device *pdev) |
| if (IS_ERR(base)) |
| return PTR_ERR(base); |
| |
| - clk = devm_clk_get(&pdev->dev, NULL); |
| + clk = devm_clk_get_enabled(&pdev->dev, NULL); |
| if (IS_ERR(clk)) |
| return PTR_ERR(clk); |
| |
| - ret = clk_prepare_enable(clk); |
| - if (ret) |
| - return ret; |
| - |
| ddata->ops.priv = (unsigned long)ddata; |
| ddata->ops.read = st_rng_read; |
| ddata->ops.name = pdev->name; |
| ddata->base = base; |
| - ddata->clk = clk; |
| - |
| - dev_set_drvdata(&pdev->dev, ddata); |
| |
| ret = devm_hwrng_register(&pdev->dev, &ddata->ops); |
| if (ret) { |
| dev_err(&pdev->dev, "Failed to register HW RNG\n"); |
| - clk_disable_unprepare(clk); |
| return ret; |
| } |
| |
| @@ -115,15 +106,6 @@ static int st_rng_probe(struct platform_device *pdev) |
| return 0; |
| } |
| |
| -static int st_rng_remove(struct platform_device *pdev) |
| -{ |
| - struct st_rng_data *ddata = dev_get_drvdata(&pdev->dev); |
| - |
| - clk_disable_unprepare(ddata->clk); |
| - |
| - return 0; |
| -} |
| - |
| static const struct of_device_id st_rng_match[] __maybe_unused = { |
| { .compatible = "st,rng" }, |
| {}, |
| @@ -136,7 +118,6 @@ static struct platform_driver st_rng_driver = { |
| .of_match_table = of_match_ptr(st_rng_match), |
| }, |
| .probe = st_rng_probe, |
| - .remove = st_rng_remove |
| }; |
| |
| module_platform_driver(st_rng_driver); |
| -- |
| 2.39.2 |
| |