2 Added support for the AMD Geode LX RNG
3 (c) Copyright 2004-2005 Advanced Micro Devices, Inc.
7 Hardware driver for the Intel/AMD/VIA Random Number Generators (RNG)
12 Hardware driver for the AMD 768 Random Number Generator (RNG)
17 Hardware driver for Intel i810 Random Number Generator (RNG)
23 Copyright 2005 (c) MontaVista Software, Inc.
25 Please read Documentation/hw_random.txt for details on use.
27 ----------------------------------------------------------
28 This software may be used and distributed according to the terms
29 of the GNU General Public License, incorporated herein by reference.
34 #include <linux/device.h>
35 #include <linux/hw_random.h>
36 #include <linux/module.h>
37 #include <linux/kernel.h>
39 #include <linux/sched.h>
40 #include <linux/miscdevice.h>
41 #include <linux/delay.h>
42 #include <linux/slab.h>
43 #include <linux/random.h>
44 #include <asm/uaccess.h>
47 #define RNG_MODULE_NAME "hw_random"
48 #define PFX RNG_MODULE_NAME ": "
49 #define RNG_MISCDEV_MINOR 183 /* official */
52 static struct hwrng *current_rng;
53 static LIST_HEAD(rng_list);
54 static DEFINE_MUTEX(rng_mutex);
55 static int data_avail;
56 static u8 *rng_buffer;
58 static size_t rng_buffer_size(void)
60 return SMP_CACHE_BYTES < 32 ? 32 : SMP_CACHE_BYTES;
63 static inline int hwrng_init(struct hwrng *rng)
67 return rng->init(rng);
70 static inline void hwrng_cleanup(struct hwrng *rng)
72 if (rng && rng->cleanup)
76 static int rng_dev_open(struct inode *inode, struct file *filp)
78 /* enforce read-only access to this chrdev */
79 if ((filp->f_mode & FMODE_READ) == 0)
81 if (filp->f_mode & FMODE_WRITE)
86 static inline int rng_get_data(struct hwrng *rng, u8 *buffer, size_t size,
91 return rng->read(rng, (void *)buffer, size, wait);
93 if (rng->data_present)
94 present = rng->data_present(rng, wait);
99 return rng->data_read(rng, (u32 *)buffer);
104 static ssize_t rng_dev_read(struct file *filp, char __user *buf,
105 size_t size, loff_t *offp)
112 if (mutex_lock_interruptible(&rng_mutex)) {
123 bytes_read = rng_get_data(current_rng, rng_buffer,
125 !(filp->f_flags & O_NONBLOCK));
126 if (bytes_read < 0) {
130 data_avail = bytes_read;
134 if (filp->f_flags & O_NONBLOCK) {
145 if (copy_to_user(buf + ret, rng_buffer + data_avail,
155 mutex_unlock(&rng_mutex);
158 schedule_timeout_interruptible(1);
160 if (signal_pending(current)) {
168 mutex_unlock(&rng_mutex);
173 static const struct file_operations rng_chrdev_ops = {
174 .owner = THIS_MODULE,
175 .open = rng_dev_open,
176 .read = rng_dev_read,
177 .llseek = noop_llseek,
180 static struct miscdevice rng_miscdev = {
181 .minor = RNG_MISCDEV_MINOR,
182 .name = RNG_MODULE_NAME,
184 .fops = &rng_chrdev_ops,
188 static ssize_t hwrng_attr_current_store(struct device *dev,
189 struct device_attribute *attr,
190 const char *buf, size_t len)
195 err = mutex_lock_interruptible(&rng_mutex);
199 list_for_each_entry(rng, &rng_list, list) {
200 if (strcmp(rng->name, buf) == 0) {
201 if (rng == current_rng) {
205 err = hwrng_init(rng);
208 hwrng_cleanup(current_rng);
214 mutex_unlock(&rng_mutex);
219 static ssize_t hwrng_attr_current_show(struct device *dev,
220 struct device_attribute *attr,
225 const char *name = "none";
227 err = mutex_lock_interruptible(&rng_mutex);
231 name = current_rng->name;
232 ret = snprintf(buf, PAGE_SIZE, "%s\n", name);
233 mutex_unlock(&rng_mutex);
238 static ssize_t hwrng_attr_available_show(struct device *dev,
239 struct device_attribute *attr,
246 err = mutex_lock_interruptible(&rng_mutex);
250 list_for_each_entry(rng, &rng_list, list) {
251 strncat(buf, rng->name, PAGE_SIZE - ret - 1);
252 ret += strlen(rng->name);
253 strncat(buf, " ", PAGE_SIZE - ret - 1);
256 strncat(buf, "\n", PAGE_SIZE - ret - 1);
258 mutex_unlock(&rng_mutex);
263 static DEVICE_ATTR(rng_current, S_IRUGO | S_IWUSR,
264 hwrng_attr_current_show,
265 hwrng_attr_current_store);
266 static DEVICE_ATTR(rng_available, S_IRUGO,
267 hwrng_attr_available_show,
271 static void unregister_miscdev(void)
273 device_remove_file(rng_miscdev.this_device, &dev_attr_rng_available);
274 device_remove_file(rng_miscdev.this_device, &dev_attr_rng_current);
275 misc_deregister(&rng_miscdev);
278 static int register_miscdev(void)
282 err = misc_register(&rng_miscdev);
285 err = device_create_file(rng_miscdev.this_device,
286 &dev_attr_rng_current);
289 err = device_create_file(rng_miscdev.this_device,
290 &dev_attr_rng_available);
292 goto err_remove_current;
297 device_remove_file(rng_miscdev.this_device, &dev_attr_rng_current);
299 misc_deregister(&rng_miscdev);
303 int hwrng_register(struct hwrng *rng)
306 struct hwrng *old_rng, *tmp;
307 unsigned char bytes[16];
310 if (rng->name == NULL ||
311 (rng->data_read == NULL && rng->read == NULL))
314 mutex_lock(&rng_mutex);
316 /* kmalloc makes this safe for virt_to_page() in virtio_rng.c */
319 rng_buffer = kmalloc(rng_buffer_size(), GFP_KERNEL);
324 /* Must not register two RNGs with the same name. */
326 list_for_each_entry(tmp, &rng_list, list) {
327 if (strcmp(tmp->name, rng->name) == 0)
331 old_rng = current_rng;
333 err = hwrng_init(rng);
340 err = register_miscdev();
347 INIT_LIST_HEAD(&rng->list);
348 list_add_tail(&rng->list, &rng_list);
350 bytes_read = rng_get_data(rng, bytes, sizeof(bytes), 1);
352 add_device_randomness(bytes, bytes_read);
354 mutex_unlock(&rng_mutex);
358 EXPORT_SYMBOL_GPL(hwrng_register);
360 void hwrng_unregister(struct hwrng *rng)
364 mutex_lock(&rng_mutex);
366 list_del(&rng->list);
367 if (current_rng == rng) {
369 if (list_empty(&rng_list)) {
372 current_rng = list_entry(rng_list.prev, struct hwrng, list);
373 err = hwrng_init(current_rng);
378 if (list_empty(&rng_list))
379 unregister_miscdev();
381 mutex_unlock(&rng_mutex);
383 EXPORT_SYMBOL_GPL(hwrng_unregister);
385 static void __exit hwrng_exit(void)
387 mutex_lock(&rng_mutex);
390 mutex_unlock(&rng_mutex);
393 module_exit(hwrng_exit);
395 MODULE_DESCRIPTION("H/W Random Number Generator (RNG) driver");
396 MODULE_LICENSE("GPL");