diff options
author | Rusty Russell <rusty@rustcorp.com.au> | 2013-03-04 18:37:08 -0500 |
---|---|---|
committer | Rusty Russell <rusty@rustcorp.com.au> | 2013-03-04 18:41:41 -0500 |
commit | f7f154f1246ccc5a0a7e9ce50932627d60a0c878 (patch) | |
tree | 136b9c7b410816bc15795f47fb808bdaca504204 /drivers/char | |
parent | 6dbe51c251a327e012439c4772097a13df43c5b8 (diff) |
hw_random: make buffer usable in scatterlist.
virtio_rng feeds the randomness buffer handed by the core directly
into the scatterlist, since commit bb347d98079a547e80bd4722dee1de61e4dca0e8.
However, if CONFIG_HW_RANDOM=m, the static buffer isn't a linear address
(at least on most archs). We could fix this in virtio_rng, but it's actually
far easier to just do it in the core as virtio_rng would have to allocate
a buffer every time (it doesn't know how much the core will want to read).
Reported-by: Aurelien Jarno <aurelien@aurel32.net>
Tested-by: Aurelien Jarno <aurelien@aurel32.net>
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Cc: stable@kernel.org
Diffstat (limited to 'drivers/char')
-rw-r--r-- | drivers/char/hw_random/core.c | 19 |
1 files changed, 16 insertions, 3 deletions
diff --git a/drivers/char/hw_random/core.c b/drivers/char/hw_random/core.c index 1bafb40ec8a2..69ae5972713c 100644 --- a/drivers/char/hw_random/core.c +++ b/drivers/char/hw_random/core.c | |||
@@ -40,6 +40,7 @@ | |||
40 | #include <linux/init.h> | 40 | #include <linux/init.h> |
41 | #include <linux/miscdevice.h> | 41 | #include <linux/miscdevice.h> |
42 | #include <linux/delay.h> | 42 | #include <linux/delay.h> |
43 | #include <linux/slab.h> | ||
43 | #include <asm/uaccess.h> | 44 | #include <asm/uaccess.h> |
44 | 45 | ||
45 | 46 | ||
@@ -52,8 +53,12 @@ static struct hwrng *current_rng; | |||
52 | static LIST_HEAD(rng_list); | 53 | static LIST_HEAD(rng_list); |
53 | static DEFINE_MUTEX(rng_mutex); | 54 | static DEFINE_MUTEX(rng_mutex); |
54 | static int data_avail; | 55 | static int data_avail; |
55 | static u8 rng_buffer[SMP_CACHE_BYTES < 32 ? 32 : SMP_CACHE_BYTES] | 56 | static u8 *rng_buffer; |
56 | __cacheline_aligned; | 57 | |
58 | static size_t rng_buffer_size(void) | ||
59 | { | ||
60 | return SMP_CACHE_BYTES < 32 ? 32 : SMP_CACHE_BYTES; | ||
61 | } | ||
57 | 62 | ||
58 | static inline int hwrng_init(struct hwrng *rng) | 63 | static inline int hwrng_init(struct hwrng *rng) |
59 | { | 64 | { |
@@ -116,7 +121,7 @@ static ssize_t rng_dev_read(struct file *filp, char __user *buf, | |||
116 | 121 | ||
117 | if (!data_avail) { | 122 | if (!data_avail) { |
118 | bytes_read = rng_get_data(current_rng, rng_buffer, | 123 | bytes_read = rng_get_data(current_rng, rng_buffer, |
119 | sizeof(rng_buffer), | 124 | rng_buffer_size(), |
120 | !(filp->f_flags & O_NONBLOCK)); | 125 | !(filp->f_flags & O_NONBLOCK)); |
121 | if (bytes_read < 0) { | 126 | if (bytes_read < 0) { |
122 | err = bytes_read; | 127 | err = bytes_read; |
@@ -307,6 +312,14 @@ int hwrng_register(struct hwrng *rng) | |||
307 | 312 | ||
308 | mutex_lock(&rng_mutex); | 313 | mutex_lock(&rng_mutex); |
309 | 314 | ||
315 | /* kmalloc makes this safe for virt_to_page() in virtio_rng.c */ | ||
316 | err = -ENOMEM; | ||
317 | if (!rng_buffer) { | ||
318 | rng_buffer = kmalloc(rng_buffer_size(), GFP_KERNEL); | ||
319 | if (!rng_buffer) | ||
320 | goto out_unlock; | ||
321 | } | ||
322 | |||
310 | /* Must not register two RNGs with the same name. */ | 323 | /* Must not register two RNGs with the same name. */ |
311 | err = -EEXIST; | 324 | err = -EEXIST; |
312 | list_for_each_entry(tmp, &rng_list, list) { | 325 | list_for_each_entry(tmp, &rng_list, list) { |