aboutsummaryrefslogtreecommitdiffstats
path: root/arch/um/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'arch/um/drivers')
-rw-r--r--arch/um/drivers/random.c41
1 files changed, 37 insertions, 4 deletions
diff --git a/arch/um/drivers/random.c b/arch/um/drivers/random.c
index 71f0959c1535..f92b7c81eb00 100644
--- a/arch/um/drivers/random.c
+++ b/arch/um/drivers/random.c
@@ -8,16 +8,18 @@
8#include <linux/sched.h> 8#include <linux/sched.h>
9#include <linux/module.h> 9#include <linux/module.h>
10#include <linux/fs.h> 10#include <linux/fs.h>
11#include <linux/interrupt.h>
11#include <linux/miscdevice.h> 12#include <linux/miscdevice.h>
12#include <linux/delay.h> 13#include <linux/delay.h>
13#include <asm/uaccess.h> 14#include <asm/uaccess.h>
15#include "irq_kern.h"
14#include "os.h" 16#include "os.h"
15 17
16/* 18/*
17 * core module and version information 19 * core module and version information
18 */ 20 */
19#define RNG_VERSION "1.0.0" 21#define RNG_VERSION "1.0.0"
20#define RNG_MODULE_NAME "random" 22#define RNG_MODULE_NAME "hw_random"
21 23
22#define RNG_MISCDEV_MINOR 183 /* official */ 24#define RNG_MISCDEV_MINOR 183 /* official */
23 25
@@ -26,6 +28,7 @@
26 * protects against a module being loaded twice at the same time. 28 * protects against a module being loaded twice at the same time.
27 */ 29 */
28static int random_fd = -1; 30static int random_fd = -1;
31static DECLARE_WAIT_QUEUE_HEAD(host_read_wait);
29 32
30static int rng_dev_open (struct inode *inode, struct file *filp) 33static int rng_dev_open (struct inode *inode, struct file *filp)
31{ 34{
@@ -38,6 +41,8 @@ static int rng_dev_open (struct inode *inode, struct file *filp)
38 return 0; 41 return 0;
39} 42}
40 43
44static atomic_t host_sleep_count = ATOMIC_INIT(0);
45
41static ssize_t rng_dev_read (struct file *filp, char __user *buf, size_t size, 46static ssize_t rng_dev_read (struct file *filp, char __user *buf, size_t size,
42 loff_t * offp) 47 loff_t * offp)
43{ 48{
@@ -60,11 +65,26 @@ static ssize_t rng_dev_read (struct file *filp, char __user *buf, size_t size,
60 } 65 }
61 } 66 }
62 else if(n == -EAGAIN){ 67 else if(n == -EAGAIN){
68 DECLARE_WAITQUEUE(wait, current);
69
63 if (filp->f_flags & O_NONBLOCK) 70 if (filp->f_flags & O_NONBLOCK)
64 return ret ? : -EAGAIN; 71 return ret ? : -EAGAIN;
65 72
66 if(need_resched()) 73 atomic_inc(&host_sleep_count);
67 schedule_timeout_interruptible(1); 74 reactivate_fd(random_fd, RANDOM_IRQ);
75 add_sigio_fd(random_fd);
76
77 add_wait_queue(&host_read_wait, &wait);
78 set_task_state(current, TASK_INTERRUPTIBLE);
79
80 schedule();
81 set_task_state(current, TASK_RUNNING);
82 remove_wait_queue(&host_read_wait, &wait);
83
84 if (atomic_dec_and_test(&host_sleep_count)) {
85 ignore_sigio_fd(random_fd);
86 deactivate_fd(random_fd, RANDOM_IRQ);
87 }
68 } 88 }
69 else return n; 89 else return n;
70 if (signal_pending (current)) 90 if (signal_pending (current))
@@ -86,6 +106,13 @@ static struct miscdevice rng_miscdev = {
86 &rng_chrdev_ops, 106 &rng_chrdev_ops,
87}; 107};
88 108
109static irqreturn_t random_interrupt(int irq, void *data)
110{
111 wake_up(&host_read_wait);
112
113 return IRQ_HANDLED;
114}
115
89/* 116/*
90 * rng_init - initialize RNG module 117 * rng_init - initialize RNG module
91 */ 118 */
@@ -99,10 +126,14 @@ static int __init rng_init (void)
99 126
100 random_fd = err; 127 random_fd = err;
101 128
102 err = os_set_fd_block(random_fd, 0); 129 err = um_request_irq(RANDOM_IRQ, random_fd, IRQ_READ, random_interrupt,
130 IRQF_DISABLED | IRQF_SAMPLE_RANDOM, "random",
131 NULL);
103 if(err) 132 if(err)
104 goto err_out_cleanup_hw; 133 goto err_out_cleanup_hw;
105 134
135 sigio_broken(random_fd, 1);
136
106 err = misc_register (&rng_miscdev); 137 err = misc_register (&rng_miscdev);
107 if (err) { 138 if (err) {
108 printk (KERN_ERR RNG_MODULE_NAME ": misc device register failed\n"); 139 printk (KERN_ERR RNG_MODULE_NAME ": misc device register failed\n");
@@ -113,6 +144,7 @@ static int __init rng_init (void)
113 return err; 144 return err;
114 145
115 err_out_cleanup_hw: 146 err_out_cleanup_hw:
147 os_close_file(random_fd);
116 random_fd = -1; 148 random_fd = -1;
117 goto out; 149 goto out;
118} 150}
@@ -122,6 +154,7 @@ static int __init rng_init (void)
122 */ 154 */
123static void __exit rng_cleanup (void) 155static void __exit rng_cleanup (void)
124{ 156{
157 os_close_file(random_fd);
125 misc_deregister (&rng_miscdev); 158 misc_deregister (&rng_miscdev);
126} 159}
127 160