#include <asm/prom.h>
 #include <asm/machdep.h>
 #include <asm/smp.h>
+#include "powernv.h"
 
 #define DARN_ERR 0xFFFFFFFFFFFFFFFFul
 
 
 static DEFINE_PER_CPU(struct powernv_rng *, powernv_rng);
 
-
 int powernv_hwrng_present(void)
 {
        struct powernv_rng *rng;
                        return 0;
                }
        }
-
-       pr_warn("Unable to use DARN for get_random_seed()\n");
-
        return -EIO;
 }
 
 
        rng_init_per_cpu(rng, dn);
 
-       pr_info_once("Registering arch random hook.\n");
-
        ppc_md.get_random_seed = powernv_get_random_long;
 
        return 0;
 }
 
-static __init int rng_init(void)
+static int __init pnv_get_random_long_early(unsigned long *v)
 {
        struct device_node *dn;
-       int rc;
+
+       if (!slab_is_available())
+               return 0;
+
+       if (cmpxchg(&ppc_md.get_random_seed, pnv_get_random_long_early,
+                   NULL) != pnv_get_random_long_early)
+               return 0;
 
        for_each_compatible_node(dn, NULL, "ibm,power-rng") {
-               rc = rng_create(dn);
-               if (rc) {
-                       pr_err("Failed creating rng for %pOF (%d).\n",
-                               dn, rc);
+               if (rng_create(dn))
                        continue;
-               }
-
                /* Create devices for hwrng driver */
                of_platform_device_create(dn, NULL, NULL);
        }
 
-       initialise_darn();
+       if (!ppc_md.get_random_seed)
+               return 0;
+       return ppc_md.get_random_seed(v);
+}
+
+void __init pnv_rng_init(void)
+{
+       struct device_node *dn;
 
+       /* Prefer darn over the rest. */
+       if (!initialise_darn())
+               return;
+
+       dn = of_find_compatible_node(NULL, NULL, "ibm,power-rng");
+       if (dn)
+               ppc_md.get_random_seed = pnv_get_random_long_early;
+
+       of_node_put(dn);
+}
+
+static int __init pnv_rng_late_init(void)
+{
+       unsigned long v;
+       /* In case it wasn't called during init for some other reason. */
+       if (ppc_md.get_random_seed == pnv_get_random_long_early)
+               pnv_get_random_long_early(&v);
        return 0;
 }
-machine_subsys_initcall(powernv, rng_init);
+machine_subsys_initcall(powernv, pnv_rng_late_init);