Skip to content

Commit f3eac42

Browse files
zx2c4mpe
authored andcommitted
powerpc/powernv: wire up rng during setup_arch
The platform's RNG must be available before random_init() in order to be useful for initial seeding, which in turn means that it needs to be called from setup_arch(), rather than from an init call. Complicating things, however, is that POWER8 systems need some per-cpu state and kmalloc, which isn't available at this stage. So we split things up into an early phase and a later opportunistic phase. This commit also removes some noisy log messages that don't add much. Fixes: a4da0d5 ("powerpc: Implement arch_get_random_long/int() for powernv") Cc: [email protected] # v3.13+ Signed-off-by: Jason A. Donenfeld <[email protected]> Reviewed-by: Christophe Leroy <[email protected]> [mpe: Add of_node_put(), use pnv naming, minor change log editing] Signed-off-by: Michael Ellerman <[email protected]> Link: https://lore.kernel.org/r/[email protected]
1 parent ca5dabc commit f3eac42

File tree

3 files changed

+40
-16
lines changed

3 files changed

+40
-16
lines changed

arch/powerpc/platforms/powernv/powernv.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,4 +42,6 @@ ssize_t memcons_copy(struct memcons *mc, char *to, loff_t pos, size_t count);
4242
u32 __init memcons_get_size(struct memcons *mc);
4343
struct memcons *__init memcons_init(struct device_node *node, const char *mc_prop_name);
4444

45+
void pnv_rng_init(void);
46+
4547
#endif /* _POWERNV_H */

arch/powerpc/platforms/powernv/rng.c

Lines changed: 36 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
#include <asm/prom.h>
1818
#include <asm/machdep.h>
1919
#include <asm/smp.h>
20+
#include "powernv.h"
2021

2122
#define DARN_ERR 0xFFFFFFFFFFFFFFFFul
2223

@@ -28,7 +29,6 @@ struct powernv_rng {
2829

2930
static DEFINE_PER_CPU(struct powernv_rng *, powernv_rng);
3031

31-
3232
int powernv_hwrng_present(void)
3333
{
3434
struct powernv_rng *rng;
@@ -98,9 +98,6 @@ static int __init initialise_darn(void)
9898
return 0;
9999
}
100100
}
101-
102-
pr_warn("Unable to use DARN for get_random_seed()\n");
103-
104101
return -EIO;
105102
}
106103

@@ -163,32 +160,55 @@ static __init int rng_create(struct device_node *dn)
163160

164161
rng_init_per_cpu(rng, dn);
165162

166-
pr_info_once("Registering arch random hook.\n");
167-
168163
ppc_md.get_random_seed = powernv_get_random_long;
169164

170165
return 0;
171166
}
172167

173-
static __init int rng_init(void)
168+
static int __init pnv_get_random_long_early(unsigned long *v)
174169
{
175170
struct device_node *dn;
176-
int rc;
171+
172+
if (!slab_is_available())
173+
return 0;
174+
175+
if (cmpxchg(&ppc_md.get_random_seed, pnv_get_random_long_early,
176+
NULL) != pnv_get_random_long_early)
177+
return 0;
177178

178179
for_each_compatible_node(dn, NULL, "ibm,power-rng") {
179-
rc = rng_create(dn);
180-
if (rc) {
181-
pr_err("Failed creating rng for %pOF (%d).\n",
182-
dn, rc);
180+
if (rng_create(dn))
183181
continue;
184-
}
185-
186182
/* Create devices for hwrng driver */
187183
of_platform_device_create(dn, NULL, NULL);
188184
}
189185

190-
initialise_darn();
186+
if (!ppc_md.get_random_seed)
187+
return 0;
188+
return ppc_md.get_random_seed(v);
189+
}
190+
191+
void __init pnv_rng_init(void)
192+
{
193+
struct device_node *dn;
191194

195+
/* Prefer darn over the rest. */
196+
if (!initialise_darn())
197+
return;
198+
199+
dn = of_find_compatible_node(NULL, NULL, "ibm,power-rng");
200+
if (dn)
201+
ppc_md.get_random_seed = pnv_get_random_long_early;
202+
203+
of_node_put(dn);
204+
}
205+
206+
static int __init pnv_rng_late_init(void)
207+
{
208+
unsigned long v;
209+
/* In case it wasn't called during init for some other reason. */
210+
if (ppc_md.get_random_seed == pnv_get_random_long_early)
211+
pnv_get_random_long_early(&v);
192212
return 0;
193213
}
194-
machine_subsys_initcall(powernv, rng_init);
214+
machine_subsys_initcall(powernv, pnv_rng_late_init);

arch/powerpc/platforms/powernv/setup.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -203,6 +203,8 @@ static void __init pnv_setup_arch(void)
203203
pnv_check_guarded_cores();
204204

205205
/* XXX PMCS */
206+
207+
pnv_rng_init();
206208
}
207209

208210
static void __init pnv_init(void)

0 commit comments

Comments
 (0)