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/init.h>
41 #include <linux/miscdevice.h>
42 #include <linux/delay.h>
43 #include <linux/slab.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)
305 int must_register_misc;
307 struct hwrng *old_rng, *tmp;
309 if (rng->name == NULL ||
310 (rng->data_read == NULL && rng->read == NULL))
313 mutex_lock(&rng_mutex);
315 /* kmalloc makes this safe for virt_to_page() in virtio_rng.c */
318 rng_buffer = kmalloc(rng_buffer_size(), GFP_KERNEL);
323 /* Must not register two RNGs with the same name. */
325 list_for_each_entry(tmp, &rng_list, list) {
326 if (strcmp(tmp->name, rng->name) == 0)
330 must_register_misc = (current_rng == NULL);
331 old_rng = current_rng;
333 err = hwrng_init(rng);
339 if (must_register_misc) {
340 err = register_miscdev();
349 INIT_LIST_HEAD(&rng->list);
350 list_add_tail(&rng->list, &rng_list);
352 mutex_unlock(&rng_mutex);
356 EXPORT_SYMBOL_GPL(hwrng_register);
358 void hwrng_unregister(struct hwrng *rng)
362 mutex_lock(&rng_mutex);
364 list_del(&rng->list);
365 if (current_rng == rng) {
367 if (list_empty(&rng_list)) {
370 current_rng = list_entry(rng_list.prev, struct hwrng, list);
371 err = hwrng_init(current_rng);
376 if (list_empty(&rng_list))
377 unregister_miscdev();
379 mutex_unlock(&rng_mutex);
381 EXPORT_SYMBOL_GPL(hwrng_unregister);
384 MODULE_DESCRIPTION("H/W Random Number Generator (RNG) driver");
385 MODULE_LICENSE("GPL");