]> git.kernelconcepts.de Git - karo-tx-linux.git/blobdiff - drivers/char/hw_random/core.c
Merge tag 'random_for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tytso...
[karo-tx-linux.git] / drivers / char / hw_random / core.c
index 33fd6633586d1a3e269217865af4027c9b941282..6e02ec103cc7e08df76b223168b773798a46eafa 100644 (file)
@@ -68,20 +68,40 @@ MODULE_PARM_DESC(default_quality,
 
 static void start_khwrngd(void);
 
+static inline int rng_get_data(struct hwrng *rng, u8 *buffer, size_t size,
+                              int wait);
+
 static size_t rng_buffer_size(void)
 {
        return SMP_CACHE_BYTES < 32 ? 32 : SMP_CACHE_BYTES;
 }
 
-static inline int hwrng_init(struct hwrng *rng)
+static void add_early_randomness(struct hwrng *rng)
 {
-       int err;
+       unsigned char bytes[16];
+       int bytes_read;
+
+       /*
+        * Currently only virtio-rng cannot return data during device
+        * probe, and that's handled in virtio-rng.c itself.  If there
+        * are more such devices, this call to rng_get_data can be
+        * made conditional here instead of doing it per-device.
+        */
+       bytes_read = rng_get_data(rng, bytes, sizeof(bytes), 1);
+       if (bytes_read > 0)
+               add_device_randomness(bytes, bytes_read);
+}
 
+static inline int hwrng_init(struct hwrng *rng)
+{
        if (rng->init) {
-               err = rng->init(rng);
-               if (err)
-                       return err;
+               int ret;
+
+               ret =  rng->init(rng);
+               if (ret)
+                       return ret;
        }
+       add_early_randomness(rng);
 
        current_quality = rng->quality ? : default_quality;
        current_quality &= 1023;
@@ -361,8 +381,6 @@ int hwrng_register(struct hwrng *rng)
 {
        int err = -EINVAL;
        struct hwrng *old_rng, *tmp;
-       unsigned char bytes[16];
-       int bytes_read;
 
        if (rng->name == NULL ||
            (rng->data_read == NULL && rng->read == NULL))
@@ -411,9 +429,17 @@ int hwrng_register(struct hwrng *rng)
        INIT_LIST_HEAD(&rng->list);
        list_add_tail(&rng->list, &rng_list);
 
-       bytes_read = rng_get_data(rng, bytes, sizeof(bytes), 1);
-       if (bytes_read > 0)
-               add_device_randomness(bytes, bytes_read);
+       if (old_rng && !rng->init) {
+               /*
+                * Use a new device's input to add some randomness to
+                * the system.  If this rng device isn't going to be
+                * used right away, its init function hasn't been
+                * called yet; so only use the randomness from devices
+                * that don't need an init callback.
+                */
+               add_early_randomness(rng);
+       }
+
 out_unlock:
        mutex_unlock(&rng_mutex);
 out: