aboutsummaryrefslogtreecommitdiffstats
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/Kconfig14
-rw-r--r--drivers/char/hw_random/Makefile1
-rw-r--r--drivers/char/hw_random/core.c110
-rw-r--r--drivers/char/hw_random/intel-rng.c1
-rw-r--r--drivers/char/hw_random/n2-drv.c2
-rw-r--r--drivers/char/hw_random/nomadik-rng.c103
-rw-r--r--drivers/char/hw_random/octeon-rng.c1
-rw-r--r--drivers/char/hw_random/tx4939-rng.c1
-rw-r--r--drivers/char/hw_random/virtio-rng.c82
9 files changed, 216 insertions, 99 deletions
diff --git a/drivers/char/hw_random/Kconfig b/drivers/char/hw_random/Kconfig
index 87060266ef91..d31483c54883 100644
--- a/drivers/char/hw_random/Kconfig
+++ b/drivers/char/hw_random/Kconfig
@@ -114,7 +114,7 @@ config HW_RANDOM_IXP4XX
114 114
115config HW_RANDOM_OMAP 115config HW_RANDOM_OMAP
116 tristate "OMAP Random Number Generator support" 116 tristate "OMAP Random Number Generator support"
117 depends on HW_RANDOM && (ARCH_OMAP16XX || ARCH_OMAP24XX) 117 depends on HW_RANDOM && (ARCH_OMAP16XX || ARCH_OMAP2)
118 default HW_RANDOM 118 default HW_RANDOM
119 ---help--- 119 ---help---
120 This driver provides kernel-side support for the Random Number 120 This driver provides kernel-side support for the Random Number
@@ -186,3 +186,15 @@ config HW_RANDOM_MXC_RNGA
186 module will be called mxc-rnga. 186 module will be called mxc-rnga.
187 187
188 If unsure, say Y. 188 If unsure, say Y.
189
190config HW_RANDOM_NOMADIK
191 tristate "ST-Ericsson Nomadik Random Number Generator support"
192 depends on HW_RANDOM && PLAT_NOMADIK
193 ---help---
194 This driver provides kernel-side support for the Random Number
195 Generator hardware found on ST-Ericsson SoCs (8815 and 8500).
196
197 To compile this driver as a module, choose M here: the
198 module will be called nomadik-rng.
199
200 If unsure, say Y.
diff --git a/drivers/char/hw_random/Makefile b/drivers/char/hw_random/Makefile
index 5eeb1303f0d0..4273308aa1e3 100644
--- a/drivers/char/hw_random/Makefile
+++ b/drivers/char/hw_random/Makefile
@@ -18,3 +18,4 @@ obj-$(CONFIG_HW_RANDOM_VIRTIO) += virtio-rng.o
18obj-$(CONFIG_HW_RANDOM_TX4939) += tx4939-rng.o 18obj-$(CONFIG_HW_RANDOM_TX4939) += tx4939-rng.o
19obj-$(CONFIG_HW_RANDOM_MXC_RNGA) += mxc-rnga.o 19obj-$(CONFIG_HW_RANDOM_MXC_RNGA) += mxc-rnga.o
20obj-$(CONFIG_HW_RANDOM_OCTEON) += octeon-rng.o 20obj-$(CONFIG_HW_RANDOM_OCTEON) += octeon-rng.o
21obj-$(CONFIG_HW_RANDOM_NOMADIK) += nomadik-rng.o
diff --git a/drivers/char/hw_random/core.c b/drivers/char/hw_random/core.c
index 1573aebd54b5..3d9c61e5acbf 100644
--- a/drivers/char/hw_random/core.c
+++ b/drivers/char/hw_random/core.c
@@ -52,7 +52,9 @@
52static struct hwrng *current_rng; 52static struct hwrng *current_rng;
53static LIST_HEAD(rng_list); 53static LIST_HEAD(rng_list);
54static DEFINE_MUTEX(rng_mutex); 54static DEFINE_MUTEX(rng_mutex);
55 55static int data_avail;
56static u8 rng_buffer[SMP_CACHE_BYTES < 32 ? 32 : SMP_CACHE_BYTES]
57 __cacheline_aligned;
56 58
57static inline int hwrng_init(struct hwrng *rng) 59static inline int hwrng_init(struct hwrng *rng)
58{ 60{
@@ -67,19 +69,6 @@ static inline void hwrng_cleanup(struct hwrng *rng)
67 rng->cleanup(rng); 69 rng->cleanup(rng);
68} 70}
69 71
70static inline int hwrng_data_present(struct hwrng *rng, int wait)
71{
72 if (!rng->data_present)
73 return 1;
74 return rng->data_present(rng, wait);
75}
76
77static inline int hwrng_data_read(struct hwrng *rng, u32 *data)
78{
79 return rng->data_read(rng, data);
80}
81
82
83static int rng_dev_open(struct inode *inode, struct file *filp) 72static int rng_dev_open(struct inode *inode, struct file *filp)
84{ 73{
85 /* enforce read-only access to this chrdev */ 74 /* enforce read-only access to this chrdev */
@@ -87,60 +76,93 @@ static int rng_dev_open(struct inode *inode, struct file *filp)
87 return -EINVAL; 76 return -EINVAL;
88 if (filp->f_mode & FMODE_WRITE) 77 if (filp->f_mode & FMODE_WRITE)
89 return -EINVAL; 78 return -EINVAL;
90 cycle_kernel_lock(); 79 return 0;
80}
81
82static inline int rng_get_data(struct hwrng *rng, u8 *buffer, size_t size,
83 int wait) {
84 int present;
85
86 if (rng->read)
87 return rng->read(rng, (void *)buffer, size, wait);
88
89 if (rng->data_present)
90 present = rng->data_present(rng, wait);
91 else
92 present = 1;
93
94 if (present)
95 return rng->data_read(rng, (u32 *)buffer);
96
91 return 0; 97 return 0;
92} 98}
93 99
94static ssize_t rng_dev_read(struct file *filp, char __user *buf, 100static ssize_t rng_dev_read(struct file *filp, char __user *buf,
95 size_t size, loff_t *offp) 101 size_t size, loff_t *offp)
96{ 102{
97 u32 data;
98 ssize_t ret = 0; 103 ssize_t ret = 0;
99 int err = 0; 104 int err = 0;
100 int bytes_read; 105 int bytes_read, len;
101 106
102 while (size) { 107 while (size) {
103 err = -ERESTARTSYS; 108 if (mutex_lock_interruptible(&rng_mutex)) {
104 if (mutex_lock_interruptible(&rng_mutex)) 109 err = -ERESTARTSYS;
105 goto out; 110 goto out;
111 }
112
106 if (!current_rng) { 113 if (!current_rng) {
107 mutex_unlock(&rng_mutex);
108 err = -ENODEV; 114 err = -ENODEV;
109 goto out; 115 goto out_unlock;
110 } 116 }
111 117
112 bytes_read = 0; 118 if (!data_avail) {
113 if (hwrng_data_present(current_rng, 119 bytes_read = rng_get_data(current_rng, rng_buffer,
114 !(filp->f_flags & O_NONBLOCK))) 120 sizeof(rng_buffer),
115 bytes_read = hwrng_data_read(current_rng, &data); 121 !(filp->f_flags & O_NONBLOCK));
116 mutex_unlock(&rng_mutex); 122 if (bytes_read < 0) {
117 123 err = bytes_read;
118 err = -EAGAIN; 124 goto out_unlock;
119 if (!bytes_read && (filp->f_flags & O_NONBLOCK)) 125 }
120 goto out; 126 data_avail = bytes_read;
121 if (bytes_read < 0) {
122 err = bytes_read;
123 goto out;
124 } 127 }
125 128
126 err = -EFAULT; 129 if (!data_avail) {
127 while (bytes_read && size) { 130 if (filp->f_flags & O_NONBLOCK) {
128 if (put_user((u8)data, buf++)) 131 err = -EAGAIN;
129 goto out; 132 goto out_unlock;
130 size--; 133 }
131 ret++; 134 } else {
132 bytes_read--; 135 len = data_avail;
133 data >>= 8; 136 if (len > size)
137 len = size;
138
139 data_avail -= len;
140
141 if (copy_to_user(buf + ret, rng_buffer + data_avail,
142 len)) {
143 err = -EFAULT;
144 goto out_unlock;
145 }
146
147 size -= len;
148 ret += len;
134 } 149 }
135 150
151 mutex_unlock(&rng_mutex);
152
136 if (need_resched()) 153 if (need_resched())
137 schedule_timeout_interruptible(1); 154 schedule_timeout_interruptible(1);
138 err = -ERESTARTSYS; 155
139 if (signal_pending(current)) 156 if (signal_pending(current)) {
157 err = -ERESTARTSYS;
140 goto out; 158 goto out;
159 }
141 } 160 }
142out: 161out:
143 return ret ? : err; 162 return ret ? : err;
163out_unlock:
164 mutex_unlock(&rng_mutex);
165 goto out;
144} 166}
145 167
146 168
@@ -280,7 +302,7 @@ int hwrng_register(struct hwrng *rng)
280 struct hwrng *old_rng, *tmp; 302 struct hwrng *old_rng, *tmp;
281 303
282 if (rng->name == NULL || 304 if (rng->name == NULL ||
283 rng->data_read == NULL) 305 (rng->data_read == NULL && rng->read == NULL))
284 goto out; 306 goto out;
285 307
286 mutex_lock(&rng_mutex); 308 mutex_lock(&rng_mutex);
diff --git a/drivers/char/hw_random/intel-rng.c b/drivers/char/hw_random/intel-rng.c
index 91b53eb1c053..86fe45c19968 100644
--- a/drivers/char/hw_random/intel-rng.c
+++ b/drivers/char/hw_random/intel-rng.c
@@ -30,6 +30,7 @@
30#include <linux/pci.h> 30#include <linux/pci.h>
31#include <linux/stop_machine.h> 31#include <linux/stop_machine.h>
32#include <linux/delay.h> 32#include <linux/delay.h>
33#include <linux/slab.h>
33#include <asm/io.h> 34#include <asm/io.h>
34 35
35 36
diff --git a/drivers/char/hw_random/n2-drv.c b/drivers/char/hw_random/n2-drv.c
index 9b3e09cd41f9..10f868eefaa6 100644
--- a/drivers/char/hw_random/n2-drv.c
+++ b/drivers/char/hw_random/n2-drv.c
@@ -71,7 +71,7 @@ MODULE_VERSION(DRV_MODULE_VERSION);
71 * x22 + x21 + x17 + x15 + x13 + x12 + x11 + x7 + x5 + x + 1 71 * x22 + x21 + x17 + x15 + x13 + x12 + x11 + x7 + x5 + x + 1
72 * 72 *
73 * The RNG_CTL_VCO value of each noise cell must be programmed 73 * The RNG_CTL_VCO value of each noise cell must be programmed
74 * seperately. This is why 4 control register values must be provided 74 * separately. This is why 4 control register values must be provided
75 * to the hypervisor. During a write, the hypervisor writes them all, 75 * to the hypervisor. During a write, the hypervisor writes them all,
76 * one at a time, to the actual RNG_CTL register. The first three 76 * one at a time, to the actual RNG_CTL register. The first three
77 * values are used to setup the desired RNG_CTL_VCO for each entropy 77 * values are used to setup the desired RNG_CTL_VCO for each entropy
diff --git a/drivers/char/hw_random/nomadik-rng.c b/drivers/char/hw_random/nomadik-rng.c
new file mode 100644
index 000000000000..a8b4c4010144
--- /dev/null
+++ b/drivers/char/hw_random/nomadik-rng.c
@@ -0,0 +1,103 @@
1/*
2 * Nomadik RNG support
3 * Copyright 2009 Alessandro Rubini
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 */
10
11#include <linux/kernel.h>
12#include <linux/module.h>
13#include <linux/init.h>
14#include <linux/device.h>
15#include <linux/amba/bus.h>
16#include <linux/hw_random.h>
17#include <linux/io.h>
18
19static int nmk_rng_read(struct hwrng *rng, void *data, size_t max, bool wait)
20{
21 void __iomem *base = (void __iomem *)rng->priv;
22
23 /*
24 * The register is 32 bits and gives 16 random bits (low half).
25 * A subsequent read will delay the core for 400ns, so we just read
26 * once and accept the very unlikely very small delay, even if wait==0.
27 */
28 *(u16 *)data = __raw_readl(base + 8) & 0xffff;
29 return 2;
30}
31
32/* we have at most one RNG per machine, granted */
33static struct hwrng nmk_rng = {
34 .name = "nomadik",
35 .read = nmk_rng_read,
36};
37
38static int nmk_rng_probe(struct amba_device *dev, struct amba_id *id)
39{
40 void __iomem *base;
41 int ret;
42
43 ret = amba_request_regions(dev, dev->dev.init_name);
44 if (ret)
45 return ret;
46 ret = -ENOMEM;
47 base = ioremap(dev->res.start, resource_size(&dev->res));
48 if (!base)
49 goto out_release;
50 nmk_rng.priv = (unsigned long)base;
51 ret = hwrng_register(&nmk_rng);
52 if (ret)
53 goto out_unmap;
54 return 0;
55
56out_unmap:
57 iounmap(base);
58out_release:
59 amba_release_regions(dev);
60 return ret;
61}
62
63static int nmk_rng_remove(struct amba_device *dev)
64{
65 void __iomem *base = (void __iomem *)nmk_rng.priv;
66 hwrng_unregister(&nmk_rng);
67 iounmap(base);
68 amba_release_regions(dev);
69 return 0;
70}
71
72static struct amba_id nmk_rng_ids[] = {
73 {
74 .id = 0x000805e1,
75 .mask = 0x000fffff, /* top bits are rev and cfg: accept all */
76 },
77 {0, 0},
78};
79
80static struct amba_driver nmk_rng_driver = {
81 .drv = {
82 .owner = THIS_MODULE,
83 .name = "rng",
84 },
85 .probe = nmk_rng_probe,
86 .remove = nmk_rng_remove,
87 .id_table = nmk_rng_ids,
88};
89
90static int __init nmk_rng_init(void)
91{
92 return amba_driver_register(&nmk_rng_driver);
93}
94
95static void __devexit nmk_rng_exit(void)
96{
97 amba_driver_unregister(&nmk_rng_driver);
98}
99
100module_init(nmk_rng_init);
101module_exit(nmk_rng_exit);
102
103MODULE_LICENSE("GPL");
diff --git a/drivers/char/hw_random/octeon-rng.c b/drivers/char/hw_random/octeon-rng.c
index 54b0d9ba65cf..9cd0feca318c 100644
--- a/drivers/char/hw_random/octeon-rng.c
+++ b/drivers/char/hw_random/octeon-rng.c
@@ -15,6 +15,7 @@
15#include <linux/device.h> 15#include <linux/device.h>
16#include <linux/hw_random.h> 16#include <linux/hw_random.h>
17#include <linux/io.h> 17#include <linux/io.h>
18#include <linux/gfp.h>
18 19
19#include <asm/octeon/octeon.h> 20#include <asm/octeon/octeon.h>
20#include <asm/octeon/cvmx-rnm-defs.h> 21#include <asm/octeon/cvmx-rnm-defs.h>
diff --git a/drivers/char/hw_random/tx4939-rng.c b/drivers/char/hw_random/tx4939-rng.c
index 544d9085a8e8..0bc0cb70210b 100644
--- a/drivers/char/hw_random/tx4939-rng.c
+++ b/drivers/char/hw_random/tx4939-rng.c
@@ -14,6 +14,7 @@
14#include <linux/io.h> 14#include <linux/io.h>
15#include <linux/platform_device.h> 15#include <linux/platform_device.h>
16#include <linux/hw_random.h> 16#include <linux/hw_random.h>
17#include <linux/gfp.h>
17 18
18#define TX4939_RNG_RCSR 0x00000000 19#define TX4939_RNG_RCSR 0x00000000
19#define TX4939_RNG_ROR(n) (0x00000018 + (n) * 8) 20#define TX4939_RNG_ROR(n) (0x00000018 + (n) * 8)
diff --git a/drivers/char/hw_random/virtio-rng.c b/drivers/char/hw_random/virtio-rng.c
index 915157fcff98..64fe0a793efd 100644
--- a/drivers/char/hw_random/virtio-rng.c
+++ b/drivers/char/hw_random/virtio-rng.c
@@ -16,6 +16,7 @@
16 * along with this program; if not, write to the Free Software 16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 */ 18 */
19
19#include <linux/err.h> 20#include <linux/err.h>
20#include <linux/hw_random.h> 21#include <linux/hw_random.h>
21#include <linux/scatterlist.h> 22#include <linux/scatterlist.h>
@@ -23,78 +24,64 @@
23#include <linux/virtio.h> 24#include <linux/virtio.h>
24#include <linux/virtio_rng.h> 25#include <linux/virtio_rng.h>
25 26
26/* The host will fill any buffer we give it with sweet, sweet randomness. We
27 * give it 64 bytes at a time, and the hwrng framework takes it 4 bytes at a
28 * time. */
29#define RANDOM_DATA_SIZE 64
30
31static struct virtqueue *vq; 27static struct virtqueue *vq;
32static u32 *random_data; 28static unsigned int data_avail;
33static unsigned int data_left;
34static DECLARE_COMPLETION(have_data); 29static DECLARE_COMPLETION(have_data);
30static bool busy;
35 31
36static void random_recv_done(struct virtqueue *vq) 32static void random_recv_done(struct virtqueue *vq)
37{ 33{
38 unsigned int len;
39
40 /* We can get spurious callbacks, e.g. shared IRQs + virtio_pci. */ 34 /* We can get spurious callbacks, e.g. shared IRQs + virtio_pci. */
41 if (!vq->vq_ops->get_buf(vq, &len)) 35 if (!vq->vq_ops->get_buf(vq, &data_avail))
42 return; 36 return;
43 37
44 data_left += len;
45 complete(&have_data); 38 complete(&have_data);
46} 39}
47 40
48static void register_buffer(void) 41/* The host will fill any buffer we give it with sweet, sweet randomness. */
42static void register_buffer(u8 *buf, size_t size)
49{ 43{
50 struct scatterlist sg; 44 struct scatterlist sg;
51 45
52 sg_init_one(&sg, random_data+data_left, RANDOM_DATA_SIZE-data_left); 46 sg_init_one(&sg, buf, size);
47
53 /* There should always be room for one buffer. */ 48 /* There should always be room for one buffer. */
54 if (vq->vq_ops->add_buf(vq, &sg, 0, 1, random_data) < 0) 49 if (vq->vq_ops->add_buf(vq, &sg, 0, 1, buf) < 0)
55 BUG(); 50 BUG();
51
56 vq->vq_ops->kick(vq); 52 vq->vq_ops->kick(vq);
57} 53}
58 54
59/* At least we don't udelay() in a loop like some other drivers. */ 55static int virtio_read(struct hwrng *rng, void *buf, size_t size, bool wait)
60static int virtio_data_present(struct hwrng *rng, int wait)
61{ 56{
62 if (data_left >= sizeof(u32))
63 return 1;
64 57
65again: 58 if (!busy) {
59 busy = true;
60 init_completion(&have_data);
61 register_buffer(buf, size);
62 }
63
66 if (!wait) 64 if (!wait)
67 return 0; 65 return 0;
68 66
69 wait_for_completion(&have_data); 67 wait_for_completion(&have_data);
70 68
71 /* Not enough? Re-register. */ 69 busy = false;
72 if (unlikely(data_left < sizeof(u32))) {
73 register_buffer();
74 goto again;
75 }
76 70
77 return 1; 71 return data_avail;
78} 72}
79 73
80/* virtio_data_present() must have succeeded before this is called. */ 74static void virtio_cleanup(struct hwrng *rng)
81static int virtio_data_read(struct hwrng *rng, u32 *data)
82{ 75{
83 BUG_ON(data_left < sizeof(u32)); 76 if (busy)
84 data_left -= sizeof(u32); 77 wait_for_completion(&have_data);
85 *data = random_data[data_left / 4];
86
87 if (data_left < sizeof(u32)) {
88 init_completion(&have_data);
89 register_buffer();
90 }
91 return sizeof(*data);
92} 78}
93 79
80
94static struct hwrng virtio_hwrng = { 81static struct hwrng virtio_hwrng = {
95 .name = "virtio", 82 .name = "virtio",
96 .data_present = virtio_data_present, 83 .cleanup = virtio_cleanup,
97 .data_read = virtio_data_read, 84 .read = virtio_read,
98}; 85};
99 86
100static int virtrng_probe(struct virtio_device *vdev) 87static int virtrng_probe(struct virtio_device *vdev)
@@ -112,7 +99,6 @@ static int virtrng_probe(struct virtio_device *vdev)
112 return err; 99 return err;
113 } 100 }
114 101
115 register_buffer();
116 return 0; 102 return 0;
117} 103}
118 104
@@ -128,7 +114,7 @@ static struct virtio_device_id id_table[] = {
128 { 0 }, 114 { 0 },
129}; 115};
130 116
131static struct virtio_driver virtio_rng = { 117static struct virtio_driver virtio_rng_driver = {
132 .driver.name = KBUILD_MODNAME, 118 .driver.name = KBUILD_MODNAME,
133 .driver.owner = THIS_MODULE, 119 .driver.owner = THIS_MODULE,
134 .id_table = id_table, 120 .id_table = id_table,
@@ -138,22 +124,12 @@ static struct virtio_driver virtio_rng = {
138 124
139static int __init init(void) 125static int __init init(void)
140{ 126{
141 int err; 127 return register_virtio_driver(&virtio_rng_driver);
142
143 random_data = kmalloc(RANDOM_DATA_SIZE, GFP_KERNEL);
144 if (!random_data)
145 return -ENOMEM;
146
147 err = register_virtio_driver(&virtio_rng);
148 if (err)
149 kfree(random_data);
150 return err;
151} 128}
152 129
153static void __exit fini(void) 130static void __exit fini(void)
154{ 131{
155 kfree(random_data); 132 unregister_virtio_driver(&virtio_rng_driver);
156 unregister_virtio_driver(&virtio_rng);
157} 133}
158module_init(init); 134module_init(init);
159module_exit(fini); 135module_exit(fini);