/* Various types of waiters for crng_init->CRNG_READY transition. */
 static DECLARE_WAIT_QUEUE_HEAD(crng_init_wait);
 static struct fasync_struct *fasync;
-static DEFINE_SPINLOCK(random_ready_chain_lock);
-static RAW_NOTIFIER_HEAD(random_ready_chain);
 
 /* Control how we warn userspace. */
 static struct ratelimit_state urandom_warning =
 }
 EXPORT_SYMBOL(wait_for_random_bytes);
 
-/*
- * Add a callback function that will be invoked when the input
- * pool is initialised.
- *
- * returns: 0 if callback is successfully added
- *         -EALREADY if pool is already initialised (callback not called)
- */
-int __cold register_random_ready_notifier(struct notifier_block *nb)
-{
-       unsigned long flags;
-       int ret = -EALREADY;
-
-       if (crng_ready())
-               return ret;
-
-       spin_lock_irqsave(&random_ready_chain_lock, flags);
-       if (!crng_ready())
-               ret = raw_notifier_chain_register(&random_ready_chain, nb);
-       spin_unlock_irqrestore(&random_ready_chain_lock, flags);
-       return ret;
-}
-
-/*
- * Delete a previously registered readiness callback function.
- */
-int __cold unregister_random_ready_notifier(struct notifier_block *nb)
-{
-       unsigned long flags;
-       int ret;
-
-       spin_lock_irqsave(&random_ready_chain_lock, flags);
-       ret = raw_notifier_chain_unregister(&random_ready_chain, nb);
-       spin_unlock_irqrestore(&random_ready_chain_lock, flags);
-       return ret;
-}
-
-static void __cold process_random_ready_list(void)
-{
-       unsigned long flags;
-
-       spin_lock_irqsave(&random_ready_chain_lock, flags);
-       raw_notifier_call_chain(&random_ready_chain, 0, NULL);
-       spin_unlock_irqrestore(&random_ready_chain_lock, flags);
-}
-
 #define warn_unseeded_randomness() \
        if (IS_ENABLED(CONFIG_WARN_ALL_UNSEEDED_RANDOM) && !crng_ready()) \
                printk_deferred(KERN_NOTICE "random: %s called from %pS with crng_init=%d\n", \
        if (orig < POOL_READY_BITS && new >= POOL_READY_BITS) {
                crng_reseed(); /* Sets crng_init to CRNG_READY under base_crng.lock. */
                execute_in_process_context(crng_set_ready, &set_ready);
-               process_random_ready_list();
                wake_up_interruptible(&crng_init_wait);
                kill_fasync(&fasync, SIGIO, POLL_IN);
                pr_notice("crng init done\n");
 
 bool rng_is_initialized(void);
 bool rng_has_arch_random(void);
 int wait_for_random_bytes(void);
-int register_random_ready_notifier(struct notifier_block *nb);
-int unregister_random_ready_notifier(struct notifier_block *nb);
 
 /* Calls wait_for_random_bytes() and then calls get_random_bytes(buf, nbytes).
  * Returns the result of the call to wait_for_random_bytes. */
 
 }
 early_param("debug_boot_weak_hash", debug_boot_weak_hash_enable);
 
-static DEFINE_STATIC_KEY_TRUE(not_filled_random_ptr_key);
-static siphash_key_t ptr_key __read_mostly;
+static DEFINE_STATIC_KEY_FALSE(filled_random_ptr_key);
 
 static void enable_ptr_key_workfn(struct work_struct *work)
 {
-       get_random_bytes(&ptr_key, sizeof(ptr_key));
-       /* Needs to run from preemptible context */
-       static_branch_disable(¬_filled_random_ptr_key);
+       static_branch_enable(&filled_random_ptr_key);
 }
 
-static DECLARE_WORK(enable_ptr_key_work, enable_ptr_key_workfn);
-
-static int fill_random_ptr_key(struct notifier_block *nb,
-                              unsigned long action, void *data)
-{
-       /* This may be in an interrupt handler. */
-       queue_work(system_unbound_wq, &enable_ptr_key_work);
-       return 0;
-}
-
-static struct notifier_block random_ready = {
-       .notifier_call = fill_random_ptr_key
-};
-
-static int __init initialize_ptr_random(void)
-{
-       int ret;
-
-       /* Don't bother waiting for RNG to be ready if RDRAND is mixed in already. */
-       if (rng_has_arch_random()) {
-               enable_ptr_key_workfn(&enable_ptr_key_work);
-               return 0;
-       }
-
-       ret = register_random_ready_notifier(&random_ready);
-       if (!ret) {
-               return 0;
-       } else if (ret == -EALREADY) {
-               /* This is in preemptible context */
-               enable_ptr_key_workfn(&enable_ptr_key_work);
-               return 0;
-       }
-
-       return ret;
-}
-early_initcall(initialize_ptr_random);
-
 /* Maps a pointer to a 32 bit unique identifier. */
 static inline int __ptr_to_hashval(const void *ptr, unsigned long *hashval_out)
 {
+       static siphash_key_t ptr_key __read_mostly;
        unsigned long hashval;
 
-       if (static_branch_unlikely(¬_filled_random_ptr_key))
-               return -EAGAIN;
+       if (!static_branch_likely(&filled_random_ptr_key)) {
+               static bool filled = false;
+               static DEFINE_SPINLOCK(filling);
+               static DECLARE_WORK(enable_ptr_key_work, enable_ptr_key_workfn);
+               unsigned long flags;
+
+               if (!system_unbound_wq ||
+                   (!rng_is_initialized() && !rng_has_arch_random()) ||
+                   !spin_trylock_irqsave(&filling, flags))
+                       return -EAGAIN;
+
+               if (!filled) {
+                       get_random_bytes(&ptr_key, sizeof(ptr_key));
+                       queue_work(system_unbound_wq, &enable_ptr_key_work);
+                       filled = true;
+               }
+               spin_unlock_irqrestore(&filling, flags);
+       }
+
 
 #ifdef CONFIG_64BIT
        hashval = (unsigned long)siphash_1u64((u64)ptr, &ptr_key);