As this interface becomes more heavily used, it will be painful for callers to always need to check for -EALREADY. Signed-off-by: Jason A. Donenfeld <Jason@xxxxxxxxx> --- drivers/char/random.c | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/drivers/char/random.c b/drivers/char/random.c index 8ad92707e45f..e161acf35d4a 100644 --- a/drivers/char/random.c +++ b/drivers/char/random.c @@ -1556,40 +1556,45 @@ EXPORT_SYMBOL(wait_for_random_bytes); /* * Add a callback function that will be invoked when the nonblocking - * pool is initialised. + * pool is initialised, or calls that function if it already is. * * returns: 0 if callback is successfully added - * -EALREADY if pool is already initialised (callback not called) * -ENOENT if module for callback is not alive */ int add_random_ready_callback(struct random_ready_callback *rdy) { struct module *owner; unsigned long flags; - int err = -EALREADY; - if (crng_ready()) - return err; + BUG_ON(!rdy->func); + + if (crng_ready()) { + rdy->func(rdy); + rdy->func = NULL; + return 0; + } owner = rdy->owner; if (!try_module_get(owner)) return -ENOENT; spin_lock_irqsave(&random_ready_list_lock, flags); - if (crng_ready()) + if (crng_ready()) { + rdy->func(rdy); + rdy->func = NULL; goto out; + } owner = NULL; list_add(&rdy->list, &random_ready_list); - err = 0; out: spin_unlock_irqrestore(&random_ready_list_lock, flags); module_put(owner); - return err; + return 0; } EXPORT_SYMBOL(add_random_ready_callback); @@ -1601,6 +1606,9 @@ void del_random_ready_callback(struct random_ready_callback *rdy) unsigned long flags; struct module *owner = NULL; + if (!rdy->func) + return; + spin_lock_irqsave(&random_ready_list_lock, flags); if (!list_empty(&rdy->list)) { list_del_init(&rdy->list); -- 2.14.2