On 3 July 2017 at 15:33, Harald Freudenberger 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
> ---
> 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(>cleanup_done);
> complete(>cleanup_done);
>
> + /* rng_list is sorted by decreasing quality */
> + list_for_each(rng_list_ptr, _list) {
> + tmp = list_entry(rng_list_ptr, struct hwrng, list);
> + if (tmp->quality < rng->quality)
> + break;
> + }
> + list_add_tail(>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(>list, _list);
>
> if (old_rng && !rng->init) {
> /*
> @@ -466,12 +479,12 @@ void hwrng_unregister(struct hwrng *rng)
> list_del(>list);
> if (current_rng == rng) {
> drop_current_rng();
> + /* rng_list is sorted by quality, use the best (=first) one */
> if (!list_empty(_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 .
Regards,
PrasannaKumar