OSDN Git Service

hwrng: core - do not bother to order list of devices by quality
authorDominik Brodowski <linux@dominikbrodowski.net>
Sun, 13 Feb 2022 20:46:28 +0000 (21:46 +0100)
committerHerbert Xu <herbert@gondor.apana.org.au>
Fri, 18 Feb 2022 05:21:10 +0000 (16:21 +1100)
There is no real reason why this list needs to be kept ordered by
the driver-provided quality value -- a value which is set only by
a handful of hw_random devices anyway.

Cc: Herbert Xu <herbert@gondor.apana.org.au>
Cc: Jason A. Donenfeld <Jason@zx2c4.com>
Signed-off-by: Dominik Brodowski <linux@dominikbrodowski.net>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
drivers/char/hw_random/core.c

index f327f74..6f09f4e 100644 (file)
@@ -31,7 +31,7 @@ static struct hwrng *current_rng;
 /* the current rng has been explicitly chosen by user via sysfs */
 static int cur_rng_set_by_user;
 static struct task_struct *hwrng_fill;
-/* list of registered rngs, sorted decending by quality */
+/* list of registered rngs */
 static LIST_HEAD(rng_list);
 /* Protects rng_list and current_rng */
 static DEFINE_MUTEX(rng_mutex);
@@ -297,24 +297,28 @@ static struct miscdevice rng_miscdev = {
 
 static int enable_best_rng(void)
 {
+       struct hwrng *rng, *new_rng = NULL;
        int ret = -ENODEV;
 
        BUG_ON(!mutex_is_locked(&rng_mutex));
 
-       /* rng_list is sorted by quality, use the best (=first) one */
-       if (!list_empty(&rng_list)) {
-               struct hwrng *new_rng;
-
-               new_rng = list_entry(rng_list.next, struct hwrng, list);
-               ret = ((new_rng == current_rng) ? 0 : set_current_rng(new_rng));
-               if (!ret)
-                       cur_rng_set_by_user = 0;
-       } else {
+       /* no rng to use? */
+       if (list_empty(&rng_list)) {
                drop_current_rng();
                cur_rng_set_by_user = 0;
-               ret = 0;
+               return 0;
        }
 
+       /* use the rng which offers the best quality */
+       list_for_each_entry(rng, &rng_list, list) {
+               if (!new_rng || rng->quality > new_rng->quality)
+                       new_rng = rng;
+       }
+
+       ret = ((new_rng == current_rng) ? 0 : set_current_rng(new_rng));
+       if (!ret)
+               cur_rng_set_by_user = 0;
+
        return ret;
 }
 
@@ -475,7 +479,6 @@ int hwrng_register(struct hwrng *rng)
 {
        int err = -EINVAL;
        struct hwrng *tmp;
-       struct list_head *rng_list_ptr;
        bool is_new_current = false;
 
        if (!rng->name || (!rng->data_read && !rng->read))
@@ -489,18 +492,11 @@ int hwrng_register(struct hwrng *rng)
                if (strcmp(tmp->name, rng->name) == 0)
                        goto out_unlock;
        }
+       list_add_tail(&rng->list, &rng_list);
 
        init_completion(&rng->cleanup_done);
        complete(&rng->cleanup_done);
 
-       /* rng_list is sorted by decreasing quality */
-       list_for_each(rng_list_ptr, &rng_list) {
-               tmp = list_entry(rng_list_ptr, struct hwrng, list);
-               if (tmp->quality < rng->quality)
-                       break;
-       }
-       list_add_tail(&rng->list, rng_list_ptr);
-
        if (!current_rng ||
            (!cur_rng_set_by_user && rng->quality > current_rng->quality)) {
                /*