Skip to content

Commit

Permalink
[HWRNG]: move status polling loop to data_present callbacks
Browse files Browse the repository at this point in the history
Handle waiting for new random within the drivers themselves, this allows to
use better suited timeouts for the individual rngs.

Signed-off-by: Patrick McHardy <kaber@trash.net>
Acked-by: Michael Buesch <mb@bu3sch.de>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
  • Loading branch information
Patrick McHardy authored and Herbert Xu committed Jan 10, 2008
1 parent 2407d60 commit 984e976
Show file tree
Hide file tree
Showing 8 changed files with 73 additions and 38 deletions.
12 changes: 10 additions & 2 deletions drivers/char/hw_random/amd-rng.c
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
#include <linux/kernel.h>
#include <linux/pci.h>
#include <linux/hw_random.h>
#include <linux/delay.h>
#include <asm/io.h>


Expand All @@ -52,11 +53,18 @@ MODULE_DEVICE_TABLE(pci, pci_tbl);
static struct pci_dev *amd_pdev;


static int amd_rng_data_present(struct hwrng *rng)
static int amd_rng_data_present(struct hwrng *rng, int wait)
{
u32 pmbase = (u32)rng->priv;
int data, i;

return !!(inl(pmbase + 0xF4) & 1);
for (i = 0; i < 20; i++) {
data = !!(inl(pmbase + 0xF4) & 1);
if (data || !wait)
break;
udelay(10);
}
return data;
}

static int amd_rng_data_read(struct hwrng *rng, u32 *data)
Expand Down
24 changes: 6 additions & 18 deletions drivers/char/hw_random/core.c
Original file line number Diff line number Diff line change
Expand Up @@ -66,11 +66,11 @@ static inline void hwrng_cleanup(struct hwrng *rng)
rng->cleanup(rng);
}

static inline int hwrng_data_present(struct hwrng *rng)
static inline int hwrng_data_present(struct hwrng *rng, int wait)
{
if (!rng->data_present)
return 1;
return rng->data_present(rng);
return rng->data_present(rng, wait);
}

static inline int hwrng_data_read(struct hwrng *rng, u32 *data)
Expand All @@ -94,8 +94,7 @@ static ssize_t rng_dev_read(struct file *filp, char __user *buf,
{
u32 data;
ssize_t ret = 0;
int i, err = 0;
int data_present;
int err = 0;
int bytes_read;

while (size) {
Expand All @@ -107,21 +106,10 @@ static ssize_t rng_dev_read(struct file *filp, char __user *buf,
err = -ENODEV;
goto out;
}
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)
if (hwrng_data_present(current_rng,
!(filp->f_flags & O_NONBLOCK)))
bytes_read = hwrng_data_read(current_rng, &data);
mutex_unlock(&rng_mutex);

Expand Down
12 changes: 10 additions & 2 deletions drivers/char/hw_random/geode-rng.c
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
#include <linux/kernel.h>
#include <linux/pci.h>
#include <linux/hw_random.h>
#include <linux/delay.h>
#include <asm/io.h>


Expand Down Expand Up @@ -61,11 +62,18 @@ static int geode_rng_data_read(struct hwrng *rng, u32 *data)
return 4;
}

static int geode_rng_data_present(struct hwrng *rng)
static int geode_rng_data_present(struct hwrng *rng, int wait)
{
void __iomem *mem = (void __iomem *)rng->priv;
int data, i;

return !!(readl(mem + GEODE_RNG_STATUS_REG));
for (i = 0; i < 20; i++) {
data = !!(readl(mem + GEODE_RNG_STATUS_REG));
if (data || !wait)
break;
udelay(10);
}
return data;
}


Expand Down
15 changes: 12 additions & 3 deletions drivers/char/hw_random/intel-rng.c
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
#include <linux/module.h>
#include <linux/pci.h>
#include <linux/stop_machine.h>
#include <linux/delay.h>
#include <asm/io.h>


Expand Down Expand Up @@ -162,11 +163,19 @@ static inline u8 hwstatus_set(void __iomem *mem,
return hwstatus_get(mem);
}

static int intel_rng_data_present(struct hwrng *rng)
static int intel_rng_data_present(struct hwrng *rng, int wait)
{
void __iomem *mem = (void __iomem *)rng->priv;

return !!(readb(mem + INTEL_RNG_STATUS) & INTEL_RNG_DATA_PRESENT);
int data, i;

for (i = 0; i < 20; i++) {
data = !!(readb(mem + INTEL_RNG_STATUS) &
INTEL_RNG_DATA_PRESENT);
if (data || !wait)
break;
udelay(10);
}
return data;
}

static int intel_rng_data_read(struct hwrng *rng, u32 *data)
Expand Down
13 changes: 11 additions & 2 deletions drivers/char/hw_random/omap-rng.c
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
#include <linux/err.h>
#include <linux/platform_device.h>
#include <linux/hw_random.h>
#include <linux/delay.h>

#include <asm/io.h>

Expand Down Expand Up @@ -65,9 +66,17 @@ static void omap_rng_write_reg(int reg, u32 val)
}

/* REVISIT: Does the status bit really work on 16xx? */
static int omap_rng_data_present(struct hwrng *rng)
static int omap_rng_data_present(struct hwrng *rng, int wait)
{
return omap_rng_read_reg(RNG_STAT_REG) ? 0 : 1;
int data, i;

for (i = 0; i < 20; i++) {
data = omap_rng_read_reg(RNG_STAT_REG) ? 0 : 1;
if (data || !wait)
break;
udelay(10);
}
return data;
}

static int omap_rng_data_read(struct hwrng *rng, u32 *data)
Expand Down
14 changes: 11 additions & 3 deletions drivers/char/hw_random/pasemi-rng.c
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
#include <linux/kernel.h>
#include <linux/platform_device.h>
#include <linux/hw_random.h>
#include <linux/delay.h>
#include <asm/of_platform.h>
#include <asm/io.h>

Expand All @@ -44,9 +45,16 @@
static int pasemi_rng_data_present(struct hwrng *rng)
{
void __iomem *rng_regs = (void __iomem *)rng->priv;

return (in_le32(rng_regs + SDCRNG_CTL_REG)
& SDCRNG_CTL_FVLD_M) ? 1 : 0;
int data, i;

for (i = 0; i < 20; i++) {
data = (in_le32(rng_regs + SDCRNG_CTL_REG)
& SDCRNG_CTL_FVLD_M) ? 1 : 0;
if (data || !wait)
break;
udelay(10);
}
return data;
}

static int pasemi_rng_data_read(struct hwrng *rng, u32 *data)
Expand Down
19 changes: 12 additions & 7 deletions drivers/char/hw_random/via-rng.c
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/hw_random.h>
#include <linux/delay.h>
#include <asm/io.h>
#include <asm/msr.h>
#include <asm/cpufeature.h>
Expand Down Expand Up @@ -77,10 +78,11 @@ static inline u32 xstore(u32 *addr, u32 edx_in)
return eax_out;
}

static int via_rng_data_present(struct hwrng *rng)
static int via_rng_data_present(struct hwrng *rng, int wait)
{
u32 bytes_out;
u32 *via_rng_datum = (u32 *)(&rng->priv);
int i;

/* We choose the recommended 1-byte-per-instruction RNG rate,
* for greater randomness at the expense of speed. Larger
Expand All @@ -95,12 +97,15 @@ static int via_rng_data_present(struct hwrng *rng)
* completes.
*/

*via_rng_datum = 0; /* paranoia, not really necessary */
bytes_out = xstore(via_rng_datum, VIA_RNG_CHUNK_1);
bytes_out &= VIA_XSTORE_CNT_MASK;
if (bytes_out == 0)
return 0;
return 1;
for (i = 0; i < 20; i++) {
*via_rng_datum = 0; /* paranoia, not really necessary */
bytes_out = xstore(via_rng_datum, VIA_RNG_CHUNK_1);
bytes_out &= VIA_XSTORE_CNT_MASK;
if (bytes_out || !wait)
break;
udelay(10);
}
return bytes_out ? 1 : 0;
}

static int via_rng_data_read(struct hwrng *rng, u32 *data)
Expand Down
2 changes: 1 addition & 1 deletion include/linux/hw_random.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ struct hwrng {
const char *name;
int (*init)(struct hwrng *rng);
void (*cleanup)(struct hwrng *rng);
int (*data_present)(struct hwrng *rng);
int (*data_present)(struct hwrng *rng, int wait);
int (*data_read)(struct hwrng *rng, u32 *data);
unsigned long priv;

Expand Down

0 comments on commit 984e976

Please sign in to comment.