950-0606-hwrng-bcm2835-sleep-more-intelligently.patch 1.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566
  1. From 3537a855e3858b1f8b6cee545a22b8b67037235c Mon Sep 17 00:00:00 2001
  2. From: Phil Elwell <[email protected]>
  3. Date: Wed, 22 Mar 2023 15:30:38 +0000
  4. Subject: [PATCH] hwrng: bcm2835 - sleep more intelligently
  5. While waiting for random data, use sleeps that are proportional
  6. to the amount of data expected. Prevent indefinite waits by
  7. giving up if nothing is received for a second.
  8. See: https://github.com/raspberrypi/linux/issues/5390
  9. Signed-off-by: Phil Elwell <[email protected]>
  10. ---
  11. drivers/char/hw_random/bcm2835-rng.c | 20 ++++++++++++++------
  12. 1 file changed, 14 insertions(+), 6 deletions(-)
  13. --- a/drivers/char/hw_random/bcm2835-rng.c
  14. +++ b/drivers/char/hw_random/bcm2835-rng.c
  15. @@ -14,6 +14,7 @@
  16. #include <linux/printk.h>
  17. #include <linux/clk.h>
  18. #include <linux/reset.h>
  19. +#include <linux/delay.h>
  20. #define RNG_CTRL 0x0
  21. #define RNG_STATUS 0x4
  22. @@ -28,6 +29,9 @@
  23. #define RNG_INT_OFF 0x1
  24. +#define RNG_FIFO_WORDS 4
  25. +#define RNG_US_PER_WORD 34 /* Tuned for throughput */
  26. +
  27. struct bcm2835_rng_priv {
  28. struct hwrng rng;
  29. void __iomem *base;
  30. @@ -64,19 +68,23 @@ static inline void rng_writel(struct bcm
  31. static int bcm2835_rng_read(struct hwrng *rng, void *buf, size_t max,
  32. bool wait)
  33. {
  34. + u32 retries = 1000000/(RNG_FIFO_WORDS * RNG_US_PER_WORD);
  35. struct bcm2835_rng_priv *priv = to_rng_priv(rng);
  36. u32 max_words = max / sizeof(u32);
  37. u32 num_words, count;
  38. - while ((rng_readl(priv, RNG_STATUS) >> 24) == 0) {
  39. - if (!wait)
  40. + num_words = rng_readl(priv, RNG_STATUS) >> 24;
  41. +
  42. + while (!num_words) {
  43. + if (!wait || !retries)
  44. return 0;
  45. - hwrng_yield(rng);
  46. + retries--;
  47. + usleep_range((u32)RNG_US_PER_WORD,
  48. + (u32)RNG_US_PER_WORD * RNG_FIFO_WORDS);
  49. + num_words = rng_readl(priv, RNG_STATUS) >> 24;
  50. }
  51. - num_words = rng_readl(priv, RNG_STATUS) >> 24;
  52. - if (num_words > max_words)
  53. - num_words = max_words;
  54. + num_words = min(num_words, max_words);
  55. for (count = 0; count < num_words; count++)
  56. ((u32 *)buf)[count] = rng_readl(priv, RNG_DATA);