On 3 July 2017 at 15:33, Harald Freudenberger <freude@xxxxxxxxxxxxxxxxxx> wrote: > This patch rewoks the hwrng to always use the > rng source with best entropy quality. > > On registation and unregistration the hwrng now > tries to choose the best (= highest quality value) > rng source. The handling of the internal list > of registered rng sources is now always sorted > by quality and the top most rng chosen. > > Signed-off-by: Harald Freudenberger <freude@xxxxxxxxxxxxxxxxxx> > --- > drivers/char/hw_random/core.c | 25 +++++++++++++++++++------ > 1 file changed, 19 insertions(+), 6 deletions(-) > > diff --git a/drivers/char/hw_random/core.c b/drivers/char/hw_random/core.c > index 503a41d..e9dda16 100644 > --- a/drivers/char/hw_random/core.c > +++ b/drivers/char/hw_random/core.c > @@ -29,6 +29,7 @@ > > static struct hwrng *current_rng; > static struct task_struct *hwrng_fill; > +/* list of registered rngs, sorted decending by quality */ > static LIST_HEAD(rng_list); > /* Protects rng_list and current_rng */ > static DEFINE_MUTEX(rng_mutex); > @@ -417,6 +418,7 @@ int hwrng_register(struct hwrng *rng) > { > int err = -EINVAL; > struct hwrng *old_rng, *tmp; > + struct list_head *rng_list_ptr; > > if (!rng->name || (!rng->data_read && !rng->read)) > goto out; > @@ -432,14 +434,25 @@ int hwrng_register(struct hwrng *rng) > 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); > + > old_rng = current_rng; > err = 0; > - if (!old_rng) { > + if (!old_rng || (rng->quality > old_rng->quality)) { > + /* > + * Set new rng as current as the new rng source > + * provides better entropy quality. > + */ > err = set_current_rng(rng); > if (err) > goto out_unlock; > } > - list_add_tail(&rng->list, &rng_list); > > if (old_rng && !rng->init) { > /* > @@ -466,12 +479,12 @@ void hwrng_unregister(struct hwrng *rng) > list_del(&rng->list); > if (current_rng == rng) { > drop_current_rng(); > + /* rng_list is sorted by quality, use the best (=first) one */ > if (!list_empty(&rng_list)) { > - struct hwrng *tail; > - > - tail = list_entry(rng_list.prev, struct hwrng, list); > + struct hwrng *new_rng; > > - set_current_rng(tail); > + new_rng = list_entry(rng_list.next, struct hwrng, list); > + set_current_rng(new_rng); > } > } > > -- > 2.7.4 > Looks good to me. Reviewed-by: PrasannaKumar Muralidharan <prasannatsmkumar@xxxxxxxxx>. Regards, PrasannaKumar