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)
 
   8         (c) Copyright 2003 Red Hat Inc <jgarzik@redhat.com>
 
  12         Hardware driver for the AMD 768 Random Number Generator (RNG)
 
  13         (c) Copyright 2001 Red Hat Inc <alan@redhat.com>
 
  17         Hardware driver for Intel i810 Random Number Generator (RNG)
 
  18         Copyright 2000,2001 Jeff Garzik <jgarzik@pobox.com>
 
  19         Copyright 2000,2001 Philipp Rumpf <prumpf@mandrakesoft.com>
 
  22         Copyright 2006 Michael Buesch <mbuesch@freenet.de>
 
  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/smp_lock.h>
 
  41 #include <linux/init.h>
 
  42 #include <linux/miscdevice.h>
 
  43 #include <linux/delay.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);
 
  57 static inline int hwrng_init(struct hwrng *rng)
 
  61         return rng->init(rng);
 
  64 static inline void hwrng_cleanup(struct hwrng *rng)
 
  66         if (rng && rng->cleanup)
 
  70 static inline int hwrng_data_present(struct hwrng *rng, int wait)
 
  72         if (!rng->data_present)
 
  74         return rng->data_present(rng, wait);
 
  77 static inline int hwrng_data_read(struct hwrng *rng, u32 *data)
 
  79         return rng->data_read(rng, data);
 
  83 static int rng_dev_open(struct inode *inode, struct file *filp)
 
  85         /* enforce read-only access to this chrdev */
 
  86         if ((filp->f_mode & FMODE_READ) == 0)
 
  88         if (filp->f_mode & FMODE_WRITE)
 
  94 static ssize_t rng_dev_read(struct file *filp, char __user *buf,
 
  95                             size_t size, loff_t *offp)
 
 104                 if (mutex_lock_interruptible(&rng_mutex))
 
 107                         mutex_unlock(&rng_mutex);
 
 113                 if (hwrng_data_present(current_rng,
 
 114                                        !(filp->f_flags & O_NONBLOCK)))
 
 115                         bytes_read = hwrng_data_read(current_rng, &data);
 
 116                 mutex_unlock(&rng_mutex);
 
 119                 if (!bytes_read && (filp->f_flags & O_NONBLOCK))
 
 121                 if (bytes_read < 0) {
 
 127                 while (bytes_read && size) {
 
 128                         if (put_user((u8)data, buf++))
 
 137                         schedule_timeout_interruptible(1);
 
 139                 if (signal_pending(current))
 
 147 static const struct file_operations rng_chrdev_ops = {
 
 148         .owner          = THIS_MODULE,
 
 149         .open           = rng_dev_open,
 
 150         .read           = rng_dev_read,
 
 153 static struct miscdevice rng_miscdev = {
 
 154         .minor          = RNG_MISCDEV_MINOR,
 
 155         .name           = RNG_MODULE_NAME,
 
 156         .fops           = &rng_chrdev_ops,
 
 160 static ssize_t hwrng_attr_current_store(struct device *dev,
 
 161                                         struct device_attribute *attr,
 
 162                                         const char *buf, size_t len)
 
 167         err = mutex_lock_interruptible(&rng_mutex);
 
 171         list_for_each_entry(rng, &rng_list, list) {
 
 172                 if (strcmp(rng->name, buf) == 0) {
 
 173                         if (rng == current_rng) {
 
 177                         err = hwrng_init(rng);
 
 180                         hwrng_cleanup(current_rng);
 
 186         mutex_unlock(&rng_mutex);
 
 191 static ssize_t hwrng_attr_current_show(struct device *dev,
 
 192                                        struct device_attribute *attr,
 
 197         const char *name = "none";
 
 199         err = mutex_lock_interruptible(&rng_mutex);
 
 203                 name = current_rng->name;
 
 204         ret = snprintf(buf, PAGE_SIZE, "%s\n", name);
 
 205         mutex_unlock(&rng_mutex);
 
 210 static ssize_t hwrng_attr_available_show(struct device *dev,
 
 211                                          struct device_attribute *attr,
 
 218         err = mutex_lock_interruptible(&rng_mutex);
 
 222         list_for_each_entry(rng, &rng_list, list) {
 
 223                 strncat(buf, rng->name, PAGE_SIZE - ret - 1);
 
 224                 ret += strlen(rng->name);
 
 225                 strncat(buf, " ", PAGE_SIZE - ret - 1);
 
 228         strncat(buf, "\n", PAGE_SIZE - ret - 1);
 
 230         mutex_unlock(&rng_mutex);
 
 235 static DEVICE_ATTR(rng_current, S_IRUGO | S_IWUSR,
 
 236                    hwrng_attr_current_show,
 
 237                    hwrng_attr_current_store);
 
 238 static DEVICE_ATTR(rng_available, S_IRUGO,
 
 239                    hwrng_attr_available_show,
 
 243 static void unregister_miscdev(void)
 
 245         device_remove_file(rng_miscdev.this_device, &dev_attr_rng_available);
 
 246         device_remove_file(rng_miscdev.this_device, &dev_attr_rng_current);
 
 247         misc_deregister(&rng_miscdev);
 
 250 static int register_miscdev(void)
 
 254         err = misc_register(&rng_miscdev);
 
 257         err = device_create_file(rng_miscdev.this_device,
 
 258                                  &dev_attr_rng_current);
 
 261         err = device_create_file(rng_miscdev.this_device,
 
 262                                  &dev_attr_rng_available);
 
 264                 goto err_remove_current;
 
 269         device_remove_file(rng_miscdev.this_device, &dev_attr_rng_current);
 
 271         misc_deregister(&rng_miscdev);
 
 275 int hwrng_register(struct hwrng *rng)
 
 277         int must_register_misc;
 
 279         struct hwrng *old_rng, *tmp;
 
 281         if (rng->name == NULL ||
 
 282             rng->data_read == NULL)
 
 285         mutex_lock(&rng_mutex);
 
 287         /* Must not register two RNGs with the same name. */
 
 289         list_for_each_entry(tmp, &rng_list, list) {
 
 290                 if (strcmp(tmp->name, rng->name) == 0)
 
 294         must_register_misc = (current_rng == NULL);
 
 295         old_rng = current_rng;
 
 297                 err = hwrng_init(rng);
 
 303         if (must_register_misc) {
 
 304                 err = register_miscdev();
 
 313         INIT_LIST_HEAD(&rng->list);
 
 314         list_add_tail(&rng->list, &rng_list);
 
 316         mutex_unlock(&rng_mutex);
 
 320 EXPORT_SYMBOL_GPL(hwrng_register);
 
 322 void hwrng_unregister(struct hwrng *rng)
 
 326         mutex_lock(&rng_mutex);
 
 328         list_del(&rng->list);
 
 329         if (current_rng == rng) {
 
 331                 if (list_empty(&rng_list)) {
 
 334                         current_rng = list_entry(rng_list.prev, struct hwrng, list);
 
 335                         err = hwrng_init(current_rng);
 
 340         if (list_empty(&rng_list))
 
 341                 unregister_miscdev();
 
 343         mutex_unlock(&rng_mutex);
 
 345 EXPORT_SYMBOL_GPL(hwrng_unregister);
 
 348 MODULE_DESCRIPTION("H/W Random Number Generator (RNG) driver");
 
 349 MODULE_LICENSE("GPL");