Signed-off-by: Michael Buesch Index: hwrng.fixes/drivers/char/hw_random/core.c =================================================================== Signed-off-by: Andrew Morton --- drivers/char/hw_random/core.c | 53 ++++++++++++++------------------ 1 files changed, 24 insertions(+), 29 deletions(-) diff -puN drivers/char/hw_random/core.c~add-new-generic-hw-rng-core-hw_random-core-rewrite-chrdev-read-method drivers/char/hw_random/core.c --- devel/drivers/char/hw_random/core.c~add-new-generic-hw-rng-core-hw_random-core-rewrite-chrdev-read-method 2006-05-18 00:46:19.000000000 -0700 +++ devel-akpm/drivers/char/hw_random/core.c 2006-05-18 00:46:19.000000000 -0700 @@ -91,10 +91,11 @@ static int rng_dev_open(struct inode *in static ssize_t rng_dev_read(struct file *filp, char __user *buf, size_t size, loff_t *offp) { - int have_data; u32 data; ssize_t ret = 0; int i, err = 0; + int data_present; + int bytes_read; while (size) { err = -ERESTARTSYS; @@ -105,44 +106,38 @@ static ssize_t rng_dev_read(struct file err = -ENODEV; goto out; } - have_data = 0; - if (hwrng_data_present(current_rng)) - have_data = hwrng_data_read(current_rng, &data); + if (filp->f_flags & O_NONBLOCK) { + data_present = hwrng_data_present(current_rng); + } else { + /* Some RNG require some time between data_reads to gather + * new entropy. Poll it. + */ + for (i = 0; i < 20; i++) { + data_present = hwrng_data_present(current_rng); + if (data_present) + break; + udelay(10); + } + } + bytes_read = 0; + if (data_present) + bytes_read = hwrng_data_read(current_rng, &data); mutex_unlock(&rng_mutex); + err = -EAGAIN; + if (!bytes_read) + goto out; + err = -EFAULT; - while (have_data && size) { + while (bytes_read && size) { if (put_user((u8)data, buf++)) goto out; size--; ret++; - have_data--; + bytes_read--; data >>= 8; } - err = -EAGAIN; - if (filp->f_flags & O_NONBLOCK) - goto out; - - err = -ERESTARTSYS; - if (need_resched()) { - if (schedule_timeout_interruptible(1)) - goto out; - } else { - if (mutex_lock_interruptible(&rng_mutex)) - goto out; - if (!current_rng) { - mutex_unlock(&rng_mutex); - err = -ENODEV; - goto out; - } - for (i = 0; i < 20; i++) { - if (hwrng_data_present(current_rng)) - break; - udelay(10); - } - mutex_unlock(&rng_mutex); - } if (signal_pending(current)) goto out; } _