aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPatrick McHardy <kaber@trash.net>2007-11-20 23:24:45 -0500
committerHerbert Xu <herbert@gondor.apana.org.au>2008-01-10 16:16:16 -0500
commit984e976f5382ff09351ddd3b023937611396d739 (patch)
tree2fcce0de19b06547772f015b8409efc3d2c8d52a
parent2407d60872dd2a95404c6048f775f3b64d438f4b (diff)
[HWRNG]: move status polling loop to data_present callbacks
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>
-rw-r--r--drivers/char/hw_random/amd-rng.c12
-rw-r--r--drivers/char/hw_random/core.c24
-rw-r--r--drivers/char/hw_random/geode-rng.c12
-rw-r--r--drivers/char/hw_random/intel-rng.c15
-rw-r--r--drivers/char/hw_random/omap-rng.c13
-rw-r--r--drivers/char/hw_random/pasemi-rng.c14
-rw-r--r--drivers/char/hw_random/via-rng.c19
-rw-r--r--include/linux/hw_random.h2
8 files changed, 73 insertions, 38 deletions
diff --git a/drivers/char/hw_random/amd-rng.c b/drivers/char/hw_random/amd-rng.c
index 556fd81fa815..c422e870dc52 100644
--- a/drivers/char/hw_random/amd-rng.c
+++ b/drivers/char/hw_random/amd-rng.c
@@ -28,6 +28,7 @@
28#include <linux/kernel.h> 28#include <linux/kernel.h>
29#include <linux/pci.h> 29#include <linux/pci.h>
30#include <linux/hw_random.h> 30#include <linux/hw_random.h>
31#include <linux/delay.h>
31#include <asm/io.h> 32#include <asm/io.h>
32 33
33 34
@@ -52,11 +53,18 @@ MODULE_DEVICE_TABLE(pci, pci_tbl);
52static struct pci_dev *amd_pdev; 53static struct pci_dev *amd_pdev;
53 54
54 55
55static int amd_rng_data_present(struct hwrng *rng) 56static int amd_rng_data_present(struct hwrng *rng, int wait)
56{ 57{
57 u32 pmbase = (u32)rng->priv; 58 u32 pmbase = (u32)rng->priv;
59 int data, i;
58 60
59 return !!(inl(pmbase + 0xF4) & 1); 61 for (i = 0; i < 20; i++) {
62 data = !!(inl(pmbase + 0xF4) & 1);
63 if (data || !wait)
64 break;
65 udelay(10);
66 }
67 return data;
60} 68}
61 69
62static int amd_rng_data_read(struct hwrng *rng, u32 *data) 70static int amd_rng_data_read(struct hwrng *rng, u32 *data)
diff --git a/drivers/char/hw_random/core.c b/drivers/char/hw_random/core.c
index 26a860adcb38..0118b9817a95 100644
--- a/drivers/char/hw_random/core.c
+++ b/drivers/char/hw_random/core.c
@@ -66,11 +66,11 @@ static inline void hwrng_cleanup(struct hwrng *rng)
66 rng->cleanup(rng); 66 rng->cleanup(rng);
67} 67}
68 68
69static inline int hwrng_data_present(struct hwrng *rng) 69static inline int hwrng_data_present(struct hwrng *rng, int wait)
70{ 70{
71 if (!rng->data_present) 71 if (!rng->data_present)
72 return 1; 72 return 1;
73 return rng->data_present(rng); 73 return rng->data_present(rng, wait);
74} 74}
75 75
76static inline int hwrng_data_read(struct hwrng *rng, u32 *data) 76static inline int hwrng_data_read(struct hwrng *rng, u32 *data)
@@ -94,8 +94,7 @@ static ssize_t rng_dev_read(struct file *filp, char __user *buf,
94{ 94{
95 u32 data; 95 u32 data;
96 ssize_t ret = 0; 96 ssize_t ret = 0;
97 int i, err = 0; 97 int err = 0;
98 int data_present;
99 int bytes_read; 98 int bytes_read;
100 99
101 while (size) { 100 while (size) {
@@ -107,21 +106,10 @@ static ssize_t rng_dev_read(struct file *filp, char __user *buf,
107 err = -ENODEV; 106 err = -ENODEV;
108 goto out; 107 goto out;
109 } 108 }
110 if (filp->f_flags & O_NONBLOCK) { 109
111 data_present = hwrng_data_present(current_rng);
112 } else {
113 /* Some RNG require some time between data_reads to gather
114 * new entropy. Poll it.
115 */
116 for (i = 0; i < 20; i++) {
117 data_present = hwrng_data_present(current_rng);
118 if (data_present)
119 break;
120 udelay(10);
121 }
122 }
123 bytes_read = 0; 110 bytes_read = 0;
124 if (data_present) 111 if (hwrng_data_present(current_rng,
112 !(filp->f_flags & O_NONBLOCK)))
125 bytes_read = hwrng_data_read(current_rng, &data); 113 bytes_read = hwrng_data_read(current_rng, &data);
126 mutex_unlock(&rng_mutex); 114 mutex_unlock(&rng_mutex);
127 115
diff --git a/drivers/char/hw_random/geode-rng.c b/drivers/char/hw_random/geode-rng.c
index 8e8658dcd2e3..fed4ef5569f5 100644
--- a/drivers/char/hw_random/geode-rng.c
+++ b/drivers/char/hw_random/geode-rng.c
@@ -28,6 +28,7 @@
28#include <linux/kernel.h> 28#include <linux/kernel.h>
29#include <linux/pci.h> 29#include <linux/pci.h>
30#include <linux/hw_random.h> 30#include <linux/hw_random.h>
31#include <linux/delay.h>
31#include <asm/io.h> 32#include <asm/io.h>
32 33
33 34
@@ -61,11 +62,18 @@ static int geode_rng_data_read(struct hwrng *rng, u32 *data)
61 return 4; 62 return 4;
62} 63}
63 64
64static int geode_rng_data_present(struct hwrng *rng) 65static int geode_rng_data_present(struct hwrng *rng, int wait)
65{ 66{
66 void __iomem *mem = (void __iomem *)rng->priv; 67 void __iomem *mem = (void __iomem *)rng->priv;
68 int data, i;
67 69
68 return !!(readl(mem + GEODE_RNG_STATUS_REG)); 70 for (i = 0; i < 20; i++) {
71 data = !!(readl(mem + GEODE_RNG_STATUS_REG));
72 if (data || !wait)
73 break;
74 udelay(10);
75 }
76 return data;
69} 77}
70 78
71 79
diff --git a/drivers/char/hw_random/intel-rng.c b/drivers/char/hw_random/intel-rng.c
index 753f46052b87..5cc651ef75eb 100644
--- a/drivers/char/hw_random/intel-rng.c
+++ b/drivers/char/hw_random/intel-rng.c
@@ -29,6 +29,7 @@
29#include <linux/module.h> 29#include <linux/module.h>
30#include <linux/pci.h> 30#include <linux/pci.h>
31#include <linux/stop_machine.h> 31#include <linux/stop_machine.h>
32#include <linux/delay.h>
32#include <asm/io.h> 33#include <asm/io.h>
33 34
34 35
@@ -162,11 +163,19 @@ static inline u8 hwstatus_set(void __iomem *mem,
162 return hwstatus_get(mem); 163 return hwstatus_get(mem);
163} 164}
164 165
165static int intel_rng_data_present(struct hwrng *rng) 166static int intel_rng_data_present(struct hwrng *rng, int wait)
166{ 167{
167 void __iomem *mem = (void __iomem *)rng->priv; 168 void __iomem *mem = (void __iomem *)rng->priv;
168 169 int data, i;
169 return !!(readb(mem + INTEL_RNG_STATUS) & INTEL_RNG_DATA_PRESENT); 170
171 for (i = 0; i < 20; i++) {
172 data = !!(readb(mem + INTEL_RNG_STATUS) &
173 INTEL_RNG_DATA_PRESENT);
174 if (data || !wait)
175 break;
176 udelay(10);
177 }
178 return data;
170} 179}
171 180
172static int intel_rng_data_read(struct hwrng *rng, u32 *data) 181static int intel_rng_data_read(struct hwrng *rng, u32 *data)
diff --git a/drivers/char/hw_random/omap-rng.c b/drivers/char/hw_random/omap-rng.c
index 3f35a1c562b1..7e319951fa41 100644
--- a/drivers/char/hw_random/omap-rng.c
+++ b/drivers/char/hw_random/omap-rng.c
@@ -29,6 +29,7 @@
29#include <linux/err.h> 29#include <linux/err.h>
30#include <linux/platform_device.h> 30#include <linux/platform_device.h>
31#include <linux/hw_random.h> 31#include <linux/hw_random.h>
32#include <linux/delay.h>
32 33
33#include <asm/io.h> 34#include <asm/io.h>
34 35
@@ -65,9 +66,17 @@ static void omap_rng_write_reg(int reg, u32 val)
65} 66}
66 67
67/* REVISIT: Does the status bit really work on 16xx? */ 68/* REVISIT: Does the status bit really work on 16xx? */
68static int omap_rng_data_present(struct hwrng *rng) 69static int omap_rng_data_present(struct hwrng *rng, int wait)
69{ 70{
70 return omap_rng_read_reg(RNG_STAT_REG) ? 0 : 1; 71 int data, i;
72
73 for (i = 0; i < 20; i++) {
74 data = omap_rng_read_reg(RNG_STAT_REG) ? 0 : 1;
75 if (data || !wait)
76 break;
77 udelay(10);
78 }
79 return data;
71} 80}
72 81
73static int omap_rng_data_read(struct hwrng *rng, u32 *data) 82static int omap_rng_data_read(struct hwrng *rng, u32 *data)
diff --git a/drivers/char/hw_random/pasemi-rng.c b/drivers/char/hw_random/pasemi-rng.c
index fa6040b6c8f2..621adf25e580 100644
--- a/drivers/char/hw_random/pasemi-rng.c
+++ b/drivers/char/hw_random/pasemi-rng.c
@@ -23,6 +23,7 @@
23#include <linux/kernel.h> 23#include <linux/kernel.h>
24#include <linux/platform_device.h> 24#include <linux/platform_device.h>
25#include <linux/hw_random.h> 25#include <linux/hw_random.h>
26#include <linux/delay.h>
26#include <asm/of_platform.h> 27#include <asm/of_platform.h>
27#include <asm/io.h> 28#include <asm/io.h>
28 29
@@ -44,9 +45,16 @@
44static int pasemi_rng_data_present(struct hwrng *rng) 45static int pasemi_rng_data_present(struct hwrng *rng)
45{ 46{
46 void __iomem *rng_regs = (void __iomem *)rng->priv; 47 void __iomem *rng_regs = (void __iomem *)rng->priv;
47 48 int data, i;
48 return (in_le32(rng_regs + SDCRNG_CTL_REG) 49
49 & SDCRNG_CTL_FVLD_M) ? 1 : 0; 50 for (i = 0; i < 20; i++) {
51 data = (in_le32(rng_regs + SDCRNG_CTL_REG)
52 & SDCRNG_CTL_FVLD_M) ? 1 : 0;
53 if (data || !wait)
54 break;
55 udelay(10);
56 }
57 return data;
50} 58}
51 59
52static int pasemi_rng_data_read(struct hwrng *rng, u32 *data) 60static int pasemi_rng_data_read(struct hwrng *rng, u32 *data)
diff --git a/drivers/char/hw_random/via-rng.c b/drivers/char/hw_random/via-rng.c
index ec435cb25c4f..868e39fd42e4 100644
--- a/drivers/char/hw_random/via-rng.c
+++ b/drivers/char/hw_random/via-rng.c
@@ -27,6 +27,7 @@
27#include <linux/module.h> 27#include <linux/module.h>
28#include <linux/kernel.h> 28#include <linux/kernel.h>
29#include <linux/hw_random.h> 29#include <linux/hw_random.h>
30#include <linux/delay.h>
30#include <asm/io.h> 31#include <asm/io.h>
31#include <asm/msr.h> 32#include <asm/msr.h>
32#include <asm/cpufeature.h> 33#include <asm/cpufeature.h>
@@ -77,10 +78,11 @@ static inline u32 xstore(u32 *addr, u32 edx_in)
77 return eax_out; 78 return eax_out;
78} 79}
79 80
80static int via_rng_data_present(struct hwrng *rng) 81static int via_rng_data_present(struct hwrng *rng, int wait)
81{ 82{
82 u32 bytes_out; 83 u32 bytes_out;
83 u32 *via_rng_datum = (u32 *)(&rng->priv); 84 u32 *via_rng_datum = (u32 *)(&rng->priv);
85 int i;
84 86
85 /* We choose the recommended 1-byte-per-instruction RNG rate, 87 /* We choose the recommended 1-byte-per-instruction RNG rate,
86 * for greater randomness at the expense of speed. Larger 88 * for greater randomness at the expense of speed. Larger
@@ -95,12 +97,15 @@ static int via_rng_data_present(struct hwrng *rng)
95 * completes. 97 * completes.
96 */ 98 */
97 99
98 *via_rng_datum = 0; /* paranoia, not really necessary */ 100 for (i = 0; i < 20; i++) {
99 bytes_out = xstore(via_rng_datum, VIA_RNG_CHUNK_1); 101 *via_rng_datum = 0; /* paranoia, not really necessary */
100 bytes_out &= VIA_XSTORE_CNT_MASK; 102 bytes_out = xstore(via_rng_datum, VIA_RNG_CHUNK_1);
101 if (bytes_out == 0) 103 bytes_out &= VIA_XSTORE_CNT_MASK;
102 return 0; 104 if (bytes_out || !wait)
103 return 1; 105 break;
106 udelay(10);
107 }
108 return bytes_out ? 1 : 0;
104} 109}
105 110
106static int via_rng_data_read(struct hwrng *rng, u32 *data) 111static int via_rng_data_read(struct hwrng *rng, u32 *data)
diff --git a/include/linux/hw_random.h b/include/linux/hw_random.h
index 21ea7610e177..85d11916e9ea 100644
--- a/include/linux/hw_random.h
+++ b/include/linux/hw_random.h
@@ -33,7 +33,7 @@ struct hwrng {
33 const char *name; 33 const char *name;
34 int (*init)(struct hwrng *rng); 34 int (*init)(struct hwrng *rng);
35 void (*cleanup)(struct hwrng *rng); 35 void (*cleanup)(struct hwrng *rng);
36 int (*data_present)(struct hwrng *rng); 36 int (*data_present)(struct hwrng *rng, int wait);
37 int (*data_read)(struct hwrng *rng, u32 *data); 37 int (*data_read)(struct hwrng *rng, u32 *data);
38 unsigned long priv; 38 unsigned long priv;
39 39