Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

[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>

authored by

Patrick McHardy and committed by
Herbert Xu
984e976f 2407d608

+71 -36
+10 -2
drivers/char/hw_random/amd-rng.c
··· 28 28 #include <linux/kernel.h> 29 29 #include <linux/pci.h> 30 30 #include <linux/hw_random.h> 31 + #include <linux/delay.h> 31 32 #include <asm/io.h> 32 33 33 34 ··· 53 52 static struct pci_dev *amd_pdev; 54 53 55 54 56 - static int amd_rng_data_present(struct hwrng *rng) 55 + static int amd_rng_data_present(struct hwrng *rng, int wait) 57 56 { 58 57 u32 pmbase = (u32)rng->priv; 58 + int data, i; 59 59 60 - return !!(inl(pmbase + 0xF4) & 1); 60 + for (i = 0; i < 20; i++) { 61 + data = !!(inl(pmbase + 0xF4) & 1); 62 + if (data || !wait) 63 + break; 64 + udelay(10); 65 + } 66 + return data; 61 67 } 62 68 63 69 static int amd_rng_data_read(struct hwrng *rng, u32 *data)
+6 -18
drivers/char/hw_random/core.c
··· 66 66 rng->cleanup(rng); 67 67 } 68 68 69 - static inline int hwrng_data_present(struct hwrng *rng) 69 + static inline int hwrng_data_present(struct hwrng *rng, int wait) 70 70 { 71 71 if (!rng->data_present) 72 72 return 1; 73 - return rng->data_present(rng); 73 + return rng->data_present(rng, wait); 74 74 } 75 75 76 76 static inline int hwrng_data_read(struct hwrng *rng, u32 *data) ··· 94 94 { 95 95 u32 data; 96 96 ssize_t ret = 0; 97 - int i, err = 0; 98 - int data_present; 97 + int err = 0; 99 98 int bytes_read; 100 99 101 100 while (size) { ··· 106 107 err = -ENODEV; 107 108 goto out; 108 109 } 109 - if (filp->f_flags & O_NONBLOCK) { 110 - data_present = hwrng_data_present(current_rng); 111 - } else { 112 - /* Some RNG require some time between data_reads to gather 113 - * new entropy. Poll it. 114 - */ 115 - for (i = 0; i < 20; i++) { 116 - data_present = hwrng_data_present(current_rng); 117 - if (data_present) 118 - break; 119 - udelay(10); 120 - } 121 - } 110 + 122 111 bytes_read = 0; 123 - if (data_present) 112 + if (hwrng_data_present(current_rng, 113 + !(filp->f_flags & O_NONBLOCK))) 124 114 bytes_read = hwrng_data_read(current_rng, &data); 125 115 mutex_unlock(&rng_mutex); 126 116
+10 -2
drivers/char/hw_random/geode-rng.c
··· 28 28 #include <linux/kernel.h> 29 29 #include <linux/pci.h> 30 30 #include <linux/hw_random.h> 31 + #include <linux/delay.h> 31 32 #include <asm/io.h> 32 33 33 34 ··· 62 61 return 4; 63 62 } 64 63 65 - static int geode_rng_data_present(struct hwrng *rng) 64 + static int geode_rng_data_present(struct hwrng *rng, int wait) 66 65 { 67 66 void __iomem *mem = (void __iomem *)rng->priv; 67 + int data, i; 68 68 69 - return !!(readl(mem + GEODE_RNG_STATUS_REG)); 69 + for (i = 0; i < 20; i++) { 70 + data = !!(readl(mem + GEODE_RNG_STATUS_REG)); 71 + if (data || !wait) 72 + break; 73 + udelay(10); 74 + } 75 + return data; 70 76 } 71 77 72 78
+11 -2
drivers/char/hw_random/intel-rng.c
··· 29 29 #include <linux/module.h> 30 30 #include <linux/pci.h> 31 31 #include <linux/stop_machine.h> 32 + #include <linux/delay.h> 32 33 #include <asm/io.h> 33 34 34 35 ··· 163 162 return hwstatus_get(mem); 164 163 } 165 164 166 - static int intel_rng_data_present(struct hwrng *rng) 165 + static int intel_rng_data_present(struct hwrng *rng, int wait) 167 166 { 168 167 void __iomem *mem = (void __iomem *)rng->priv; 168 + int data, i; 169 169 170 - return !!(readb(mem + INTEL_RNG_STATUS) & INTEL_RNG_DATA_PRESENT); 170 + for (i = 0; i < 20; i++) { 171 + data = !!(readb(mem + INTEL_RNG_STATUS) & 172 + INTEL_RNG_DATA_PRESENT); 173 + if (data || !wait) 174 + break; 175 + udelay(10); 176 + } 177 + return data; 171 178 } 172 179 173 180 static int intel_rng_data_read(struct hwrng *rng, u32 *data)
+11 -2
drivers/char/hw_random/omap-rng.c
··· 29 29 #include <linux/err.h> 30 30 #include <linux/platform_device.h> 31 31 #include <linux/hw_random.h> 32 + #include <linux/delay.h> 32 33 33 34 #include <asm/io.h> 34 35 ··· 66 65 } 67 66 68 67 /* REVISIT: Does the status bit really work on 16xx? */ 69 - static int omap_rng_data_present(struct hwrng *rng) 68 + static int omap_rng_data_present(struct hwrng *rng, int wait) 70 69 { 71 - return omap_rng_read_reg(RNG_STAT_REG) ? 0 : 1; 70 + int data, i; 71 + 72 + for (i = 0; i < 20; i++) { 73 + data = omap_rng_read_reg(RNG_STAT_REG) ? 0 : 1; 74 + if (data || !wait) 75 + break; 76 + udelay(10); 77 + } 78 + return data; 72 79 } 73 80 74 81 static int omap_rng_data_read(struct hwrng *rng, u32 *data)
+10 -2
drivers/char/hw_random/pasemi-rng.c
··· 23 23 #include <linux/kernel.h> 24 24 #include <linux/platform_device.h> 25 25 #include <linux/hw_random.h> 26 + #include <linux/delay.h> 26 27 #include <asm/of_platform.h> 27 28 #include <asm/io.h> 28 29 ··· 45 44 static int pasemi_rng_data_present(struct hwrng *rng) 46 45 { 47 46 void __iomem *rng_regs = (void __iomem *)rng->priv; 47 + int data, i; 48 48 49 - return (in_le32(rng_regs + SDCRNG_CTL_REG) 50 - & SDCRNG_CTL_FVLD_M) ? 1 : 0; 49 + for (i = 0; i < 20; i++) { 50 + data = (in_le32(rng_regs + SDCRNG_CTL_REG) 51 + & SDCRNG_CTL_FVLD_M) ? 1 : 0; 52 + if (data || !wait) 53 + break; 54 + udelay(10); 55 + } 56 + return data; 51 57 } 52 58 53 59 static int pasemi_rng_data_read(struct hwrng *rng, u32 *data)
+12 -7
drivers/char/hw_random/via-rng.c
··· 27 27 #include <linux/module.h> 28 28 #include <linux/kernel.h> 29 29 #include <linux/hw_random.h> 30 + #include <linux/delay.h> 30 31 #include <asm/io.h> 31 32 #include <asm/msr.h> 32 33 #include <asm/cpufeature.h> ··· 78 77 return eax_out; 79 78 } 80 79 81 - static int via_rng_data_present(struct hwrng *rng) 80 + static int via_rng_data_present(struct hwrng *rng, int wait) 82 81 { 83 82 u32 bytes_out; 84 83 u32 *via_rng_datum = (u32 *)(&rng->priv); 84 + int i; 85 85 86 86 /* We choose the recommended 1-byte-per-instruction RNG rate, 87 87 * for greater randomness at the expense of speed. Larger ··· 97 95 * completes. 98 96 */ 99 97 100 - *via_rng_datum = 0; /* paranoia, not really necessary */ 101 - bytes_out = xstore(via_rng_datum, VIA_RNG_CHUNK_1); 102 - bytes_out &= VIA_XSTORE_CNT_MASK; 103 - if (bytes_out == 0) 104 - return 0; 105 - return 1; 98 + for (i = 0; i < 20; i++) { 99 + *via_rng_datum = 0; /* paranoia, not really necessary */ 100 + bytes_out = xstore(via_rng_datum, VIA_RNG_CHUNK_1); 101 + bytes_out &= VIA_XSTORE_CNT_MASK; 102 + if (bytes_out || !wait) 103 + break; 104 + udelay(10); 105 + } 106 + return bytes_out ? 1 : 0; 106 107 } 107 108 108 109 static int via_rng_data_read(struct hwrng *rng, u32 *data)
+1 -1
include/linux/hw_random.h
··· 33 33 const char *name; 34 34 int (*init)(struct hwrng *rng); 35 35 void (*cleanup)(struct hwrng *rng); 36 - int (*data_present)(struct hwrng *rng); 36 + int (*data_present)(struct hwrng *rng, int wait); 37 37 int (*data_read)(struct hwrng *rng, u32 *data); 38 38 unsigned long priv; 39 39