Commit 039980de authored by Martin Kaiser's avatar Martin Kaiser Committed by Herbert Xu

hwrng: nomadik - keep clock enabled while hwrng is registered

The nomadik 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, nomadik's clock is disabled in the remove function. There's a
short timeframe where nomadik 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: 3e75241b ("hwrng: drivers - Use device-managed registration API")
Signed-off-by: default avatarMartin Kaiser <martin@kaiser.cx>
Signed-off-by: default avatarHerbert Xu <herbert@gondor.apana.org.au>
parent bec61a29
...@@ -13,8 +13,6 @@ ...@@ -13,8 +13,6 @@
#include <linux/clk.h> #include <linux/clk.h>
#include <linux/err.h> #include <linux/err.h>
static struct clk *rng_clk;
static int nmk_rng_read(struct hwrng *rng, void *data, size_t max, bool wait) static int nmk_rng_read(struct hwrng *rng, void *data, size_t max, bool wait)
{ {
void __iomem *base = (void __iomem *)rng->priv; void __iomem *base = (void __iomem *)rng->priv;
...@@ -36,21 +34,20 @@ static struct hwrng nmk_rng = { ...@@ -36,21 +34,20 @@ static struct hwrng nmk_rng = {
static int nmk_rng_probe(struct amba_device *dev, const struct amba_id *id) static int nmk_rng_probe(struct amba_device *dev, const struct amba_id *id)
{ {
struct clk *rng_clk;
void __iomem *base; void __iomem *base;
int ret; int ret;
rng_clk = devm_clk_get(&dev->dev, NULL); rng_clk = devm_clk_get_enabled(&dev->dev, NULL);
if (IS_ERR(rng_clk)) { if (IS_ERR(rng_clk)) {
dev_err(&dev->dev, "could not get rng clock\n"); dev_err(&dev->dev, "could not get rng clock\n");
ret = PTR_ERR(rng_clk); ret = PTR_ERR(rng_clk);
return ret; return ret;
} }
clk_prepare_enable(rng_clk);
ret = amba_request_regions(dev, dev->dev.init_name); ret = amba_request_regions(dev, dev->dev.init_name);
if (ret) if (ret)
goto out_clk; return ret;
ret = -ENOMEM; ret = -ENOMEM;
base = devm_ioremap(&dev->dev, dev->res.start, base = devm_ioremap(&dev->dev, dev->res.start,
resource_size(&dev->res)); resource_size(&dev->res));
...@@ -64,15 +61,12 @@ static int nmk_rng_probe(struct amba_device *dev, const struct amba_id *id) ...@@ -64,15 +61,12 @@ static int nmk_rng_probe(struct amba_device *dev, const struct amba_id *id)
out_release: out_release:
amba_release_regions(dev); amba_release_regions(dev);
out_clk:
clk_disable_unprepare(rng_clk);
return ret; return ret;
} }
static void nmk_rng_remove(struct amba_device *dev) static void nmk_rng_remove(struct amba_device *dev)
{ {
amba_release_regions(dev); amba_release_regions(dev);
clk_disable_unprepare(rng_clk);
} }
static const struct amba_id nmk_rng_ids[] = { static const struct amba_id nmk_rng_ids[] = {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment