1111#include <linux/fs.h>
1212#include <linux/interrupt.h>
1313#include <linux/miscdevice.h>
14+ #include <linux/hw_random.h>
1415#include <linux/delay.h>
1516#include <linux/uaccess.h>
1617#include <init.h>
1718#include <irq_kern.h>
1819#include <os.h>
1920
2021/*
21- * core module and version information
22+ * core module information
2223 */
23- #define RNG_VERSION "1.0.0"
2424#define RNG_MODULE_NAME "hw_random"
2525
2626/* Changed at init time, in the non-modular case, and at module load
2727 * time, in the module case. Presumably, the module subsystem
2828 * protects against a module being loaded twice at the same time.
2929 */
3030static int random_fd = -1 ;
31- static DECLARE_WAIT_QUEUE_HEAD (host_read_wait );
31+ static struct hwrng hwrng = { 0 , };
32+ static DECLARE_COMPLETION (have_data );
3233
33- static int rng_dev_open (struct inode * inode , struct file * filp )
34+ static int rng_dev_read (struct hwrng * rng , void * buf , size_t max , bool block )
3435{
35- /* enforce read-only access to this chrdev */
36- if ((filp -> f_mode & FMODE_READ ) == 0 )
37- return - EINVAL ;
38- if ((filp -> f_mode & FMODE_WRITE ) != 0 )
39- return - EINVAL ;
36+ int ret ;
4037
41- return 0 ;
42- }
43-
44- static atomic_t host_sleep_count = ATOMIC_INIT (0 );
45-
46- static ssize_t rng_dev_read (struct file * filp , char __user * buf , size_t size ,
47- loff_t * offp )
48- {
49- u32 data ;
50- int n , ret = 0 , have_data ;
51-
52- while (size ) {
53- n = os_read_file (random_fd , & data , sizeof (data ));
54- if (n > 0 ) {
55- have_data = n ;
56- while (have_data && size ) {
57- if (put_user ((u8 ) data , buf ++ )) {
58- ret = ret ? : - EFAULT ;
59- break ;
60- }
61- size -- ;
62- ret ++ ;
63- have_data -- ;
64- data >>= 8 ;
65- }
66- }
67- else if (n == - EAGAIN ) {
68- DECLARE_WAITQUEUE (wait , current );
69-
70- if (filp -> f_flags & O_NONBLOCK )
71- return ret ? : - EAGAIN ;
72-
73- atomic_inc (& host_sleep_count );
38+ for (;;) {
39+ ret = os_read_file (random_fd , buf , max );
40+ if (block && ret == - EAGAIN ) {
7441 add_sigio_fd (random_fd );
7542
76- add_wait_queue (& host_read_wait , & wait );
77- set_current_state (TASK_INTERRUPTIBLE );
43+ ret = wait_for_completion_killable (& have_data );
7844
79- schedule ( );
80- remove_wait_queue ( & host_read_wait , & wait );
45+ ignore_sigio_fd ( random_fd );
46+ deactivate_fd ( random_fd , RANDOM_IRQ );
8147
82- if (atomic_dec_and_test ( & host_sleep_count )) {
83- ignore_sigio_fd ( random_fd ) ;
84- deactivate_fd ( random_fd , RANDOM_IRQ );
85- }
48+ if (ret < 0 )
49+ break ;
50+ } else {
51+ break ;
8652 }
87- else
88- return n ;
89-
90- if (signal_pending (current ))
91- return ret ? : - ERESTARTSYS ;
9253 }
93- return ret ;
94- }
9554
96- static const struct file_operations rng_chrdev_ops = {
97- .owner = THIS_MODULE ,
98- .open = rng_dev_open ,
99- .read = rng_dev_read ,
100- .llseek = noop_llseek ,
101- };
102-
103- /* rng_init shouldn't be called more than once at boot time */
104- static struct miscdevice rng_miscdev = {
105- HWRNG_MINOR ,
106- RNG_MODULE_NAME ,
107- & rng_chrdev_ops ,
108- };
55+ return ret != - EAGAIN ? ret : 0 ;
56+ }
10957
11058static irqreturn_t random_interrupt (int irq , void * data )
11159{
112- wake_up ( & host_read_wait );
60+ complete ( & have_data );
11361
11462 return IRQ_HANDLED ;
11563}
@@ -126,18 +74,19 @@ static int __init rng_init (void)
12674 goto out ;
12775
12876 random_fd = err ;
129-
13077 err = um_request_irq (RANDOM_IRQ , random_fd , IRQ_READ , random_interrupt ,
13178 0 , "random" , NULL );
13279 if (err )
13380 goto err_out_cleanup_hw ;
13481
13582 sigio_broken (random_fd , 1 );
83+ hwrng .name = RNG_MODULE_NAME ;
84+ hwrng .read = rng_dev_read ;
85+ hwrng .quality = 1024 ;
13686
137- err = misc_register ( & rng_miscdev );
87+ err = hwrng_register ( & hwrng );
13888 if (err ) {
139- printk (KERN_ERR RNG_MODULE_NAME ": misc device register "
140- "failed\n" );
89+ pr_err (RNG_MODULE_NAME " registering failed (%d)\n" , err );
14190 goto err_out_cleanup_hw ;
14291 }
14392out :
@@ -161,8 +110,8 @@ static void cleanup(void)
161110
162111static void __exit rng_cleanup (void )
163112{
113+ hwrng_unregister (& hwrng );
164114 os_close_file (random_fd );
165- misc_deregister (& rng_miscdev );
166115}
167116
168117module_init (rng_init );
0 commit comments