diff options
author | Matt Porter <mporter@linaro.org> | 2014-04-10 15:22:10 -0400 |
---|---|---|
committer | Herbert Xu <herbert@gondor.apana.org.au> | 2014-04-10 23:31:13 -0400 |
commit | eb4a5346e777784f1b5ae9fd0c29b96344bdc3ae (patch) | |
tree | 9803168c7b40fd074d3140436547a58c6c0365dd | |
parent | 59ecc26004e77e100c700b1d0da7502b0fdadb46 (diff) |
hwrng: bcm2835 - fix oops when rng h/w is accessed during registration
Commit "d9e7972 hwrng: add randomness to system from rng sources"
exposed a bug in the bcm2835-rng driver resulting in boot failure
on Raspberry Pi due to the following oops:
[ 28.261523] BUG: soft lockup - CPU#0 stuck for 23s! [swapper:1]
[ 28.271058]
[ 28.275958] CPU: 0 PID: 1 Comm: swapper Not tainted 3.14.0+ #11
[ 28.285374] task: db480000 ti: db484000 task.ti: db484000
[ 28.294279] PC is at bcm2835_rng_read+0x28/0x48
[ 28.302276] LR is at hwrng_register+0x1a8/0x238
.
.
.
The RNG h/w is not completely initialized and enabled before
hwrng_register() is called and so the bcm2835_rng_read() fails.
Fix this by making the warmup/enable writes before registering
the RNG source with the hwrng core.
Signed-off-by: Matt Porter <mporter@linaro.org>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
-rw-r--r-- | drivers/char/hw_random/bcm2835-rng.c | 10 |
1 files changed, 5 insertions, 5 deletions
diff --git a/drivers/char/hw_random/bcm2835-rng.c b/drivers/char/hw_random/bcm2835-rng.c index 8c3b255e629a..e900961cdd2e 100644 --- a/drivers/char/hw_random/bcm2835-rng.c +++ b/drivers/char/hw_random/bcm2835-rng.c | |||
@@ -61,18 +61,18 @@ static int bcm2835_rng_probe(struct platform_device *pdev) | |||
61 | } | 61 | } |
62 | bcm2835_rng_ops.priv = (unsigned long)rng_base; | 62 | bcm2835_rng_ops.priv = (unsigned long)rng_base; |
63 | 63 | ||
64 | /* set warm-up count & enable */ | ||
65 | __raw_writel(RNG_WARMUP_COUNT, rng_base + RNG_STATUS); | ||
66 | __raw_writel(RNG_RBGEN, rng_base + RNG_CTRL); | ||
67 | |||
64 | /* register driver */ | 68 | /* register driver */ |
65 | err = hwrng_register(&bcm2835_rng_ops); | 69 | err = hwrng_register(&bcm2835_rng_ops); |
66 | if (err) { | 70 | if (err) { |
67 | dev_err(dev, "hwrng registration failed\n"); | 71 | dev_err(dev, "hwrng registration failed\n"); |
68 | iounmap(rng_base); | 72 | iounmap(rng_base); |
69 | } else { | 73 | } else |
70 | dev_info(dev, "hwrng registered\n"); | 74 | dev_info(dev, "hwrng registered\n"); |
71 | 75 | ||
72 | /* set warm-up count & enable */ | ||
73 | __raw_writel(RNG_WARMUP_COUNT, rng_base + RNG_STATUS); | ||
74 | __raw_writel(RNG_RBGEN, rng_base + RNG_CTRL); | ||
75 | } | ||
76 | return err; | 76 | return err; |
77 | } | 77 | } |
78 | 78 | ||