summaryrefslogtreecommitdiffstats
path: root/drivers/char/hw_random
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/char/hw_random')
-rw-r--r--drivers/char/hw_random/core.c28
-rw-r--r--drivers/char/hw_random/mxc-rnga.c13
-rw-r--r--drivers/char/hw_random/tx4939-rng.c13
-rw-r--r--drivers/char/hw_random/virtio-rng.c13
4 files changed, 38 insertions, 29 deletions
diff --git a/drivers/char/hw_random/core.c b/drivers/char/hw_random/core.c
index 1bafb40ec8a..a0f7724852e 100644
--- a/drivers/char/hw_random/core.c
+++ b/drivers/char/hw_random/core.c
@@ -40,6 +40,7 @@
#include <linux/init.h>
#include <linux/miscdevice.h>
#include <linux/delay.h>
+#include <linux/slab.h>
#include <asm/uaccess.h>
@@ -52,8 +53,12 @@ static struct hwrng *current_rng;
static LIST_HEAD(rng_list);
static DEFINE_MUTEX(rng_mutex);
static int data_avail;
-static u8 rng_buffer[SMP_CACHE_BYTES < 32 ? 32 : SMP_CACHE_BYTES]
- __cacheline_aligned;
+static u8 *rng_buffer;
+
+static size_t rng_buffer_size(void)
+{
+ return SMP_CACHE_BYTES < 32 ? 32 : SMP_CACHE_BYTES;
+}
static inline int hwrng_init(struct hwrng *rng)
{
@@ -116,7 +121,7 @@ static ssize_t rng_dev_read(struct file *filp, char __user *buf,
if (!data_avail) {
bytes_read = rng_get_data(current_rng, rng_buffer,
- sizeof(rng_buffer),
+ rng_buffer_size(),
!(filp->f_flags & O_NONBLOCK));
if (bytes_read < 0) {
err = bytes_read;
@@ -307,6 +312,14 @@ int hwrng_register(struct hwrng *rng)
mutex_lock(&rng_mutex);
+ /* kmalloc makes this safe for virt_to_page() in virtio_rng.c */
+ err = -ENOMEM;
+ if (!rng_buffer) {
+ rng_buffer = kmalloc(rng_buffer_size(), GFP_KERNEL);
+ if (!rng_buffer)
+ goto out_unlock;
+ }
+
/* Must not register two RNGs with the same name. */
err = -EEXIST;
list_for_each_entry(tmp, &rng_list, list) {
@@ -367,6 +380,15 @@ void hwrng_unregister(struct hwrng *rng)
}
EXPORT_SYMBOL_GPL(hwrng_unregister);
+static void __exit hwrng_exit(void)
+{
+ mutex_lock(&rng_mutex);
+ BUG_ON(current_rng);
+ kfree(rng_buffer);
+ mutex_unlock(&rng_mutex);
+}
+
+module_exit(hwrng_exit);
MODULE_DESCRIPTION("H/W Random Number Generator (RNG) driver");
MODULE_LICENSE("GPL");
diff --git a/drivers/char/hw_random/mxc-rnga.c b/drivers/char/hw_random/mxc-rnga.c
index f05d85713fd..895d0b8fb9a 100644
--- a/drivers/char/hw_random/mxc-rnga.c
+++ b/drivers/char/hw_random/mxc-rnga.c
@@ -228,18 +228,7 @@ static struct platform_driver mxc_rnga_driver = {
.remove = __exit_p(mxc_rnga_remove),
};
-static int __init mod_init(void)
-{
- return platform_driver_probe(&mxc_rnga_driver, mxc_rnga_probe);
-}
-
-static void __exit mod_exit(void)
-{
- platform_driver_unregister(&mxc_rnga_driver);
-}
-
-module_init(mod_init);
-module_exit(mod_exit);
+module_platform_driver_probe(mxc_rnga_driver, mxc_rnga_probe);
MODULE_AUTHOR("Freescale Semiconductor, Inc.");
MODULE_DESCRIPTION("H/W RNGA driver for i.MX");
diff --git a/drivers/char/hw_random/tx4939-rng.c b/drivers/char/hw_random/tx4939-rng.c
index 30991989d65..d34a24a0d48 100644
--- a/drivers/char/hw_random/tx4939-rng.c
+++ b/drivers/char/hw_random/tx4939-rng.c
@@ -166,18 +166,7 @@ static struct platform_driver tx4939_rng_driver = {
.remove = tx4939_rng_remove,
};
-static int __init tx4939rng_init(void)
-{
- return platform_driver_probe(&tx4939_rng_driver, tx4939_rng_probe);
-}
-
-static void __exit tx4939rng_exit(void)
-{
- platform_driver_unregister(&tx4939_rng_driver);
-}
-
-module_init(tx4939rng_init);
-module_exit(tx4939rng_exit);
+module_platform_driver_probe(tx4939_rng_driver, tx4939_rng_probe);
MODULE_DESCRIPTION("H/W Random Number Generator (RNG) driver for TX4939");
MODULE_LICENSE("GPL");
diff --git a/drivers/char/hw_random/virtio-rng.c b/drivers/char/hw_random/virtio-rng.c
index 842e2d55d33..ef46a9cfd83 100644
--- a/drivers/char/hw_random/virtio-rng.c
+++ b/drivers/char/hw_random/virtio-rng.c
@@ -92,14 +92,22 @@ static int probe_common(struct virtio_device *vdev)
{
int err;
+ if (vq) {
+ /* We only support one device for now */
+ return -EBUSY;
+ }
/* We expect a single virtqueue. */
vq = virtio_find_single_vq(vdev, random_recv_done, "input");
- if (IS_ERR(vq))
- return PTR_ERR(vq);
+ if (IS_ERR(vq)) {
+ err = PTR_ERR(vq);
+ vq = NULL;
+ return err;
+ }
err = hwrng_register(&virtio_hwrng);
if (err) {
vdev->config->del_vqs(vdev);
+ vq = NULL;
return err;
}
@@ -112,6 +120,7 @@ static void remove_common(struct virtio_device *vdev)
busy = false;
hwrng_unregister(&virtio_hwrng);
vdev->config->del_vqs(vdev);
+ vq = NULL;
}
static int virtrng_probe(struct virtio_device *vdev)