aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm64/kernel/smp.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm64/kernel/smp.c')
-rw-r--r--arch/arm64/kernel/smp.c68
1 files changed, 46 insertions, 22 deletions
diff --git a/arch/arm64/kernel/smp.c b/arch/arm64/kernel/smp.c
index 538300f2273d..7776922945af 100644
--- a/arch/arm64/kernel/smp.c
+++ b/arch/arm64/kernel/smp.c
@@ -233,7 +233,27 @@ void __init smp_prepare_boot_cpu(void)
233} 233}
234 234
235static void (*smp_cross_call)(const struct cpumask *, unsigned int); 235static void (*smp_cross_call)(const struct cpumask *, unsigned int);
236static phys_addr_t cpu_release_addr[NR_CPUS]; 236
237static const struct smp_enable_ops *enable_ops[] __initconst = {
238 &smp_spin_table_ops,
239 NULL,
240};
241
242static const struct smp_enable_ops *smp_enable_ops[NR_CPUS];
243
244static const struct smp_enable_ops * __init smp_get_enable_ops(const char *name)
245{
246 const struct smp_enable_ops *ops = enable_ops[0];
247
248 while (ops) {
249 if (!strcmp(name, ops->name))
250 return ops;
251
252 ops++;
253 }
254
255 return NULL;
256}
237 257
238/* 258/*
239 * Enumerate the possible CPU set from the device tree. 259 * Enumerate the possible CPU set from the device tree.
@@ -252,22 +272,22 @@ void __init smp_init_cpus(void)
252 * We currently support only the "spin-table" enable-method. 272 * We currently support only the "spin-table" enable-method.
253 */ 273 */
254 enable_method = of_get_property(dn, "enable-method", NULL); 274 enable_method = of_get_property(dn, "enable-method", NULL);
255 if (!enable_method || strcmp(enable_method, "spin-table")) { 275 if (!enable_method) {
256 pr_err("CPU %d: missing or invalid enable-method property: %s\n", 276 pr_err("CPU %d: missing enable-method property\n", cpu);
257 cpu, enable_method);
258 goto next; 277 goto next;
259 } 278 }
260 279
261 /* 280 smp_enable_ops[cpu] = smp_get_enable_ops(enable_method);
262 * Determine the address from which the CPU is polling. 281
263 */ 282 if (!smp_enable_ops[cpu]) {
264 if (of_property_read_u64(dn, "cpu-release-addr", 283 pr_err("CPU %d: invalid enable-method property: %s\n",
265 &cpu_release_addr[cpu])) { 284 cpu, enable_method);
266 pr_err("CPU %d: missing or invalid cpu-release-addr property\n",
267 cpu);
268 goto next; 285 goto next;
269 } 286 }
270 287
288 if (smp_enable_ops[cpu]->init_cpu(dn, cpu))
289 goto next;
290
271 set_cpu_possible(cpu, true); 291 set_cpu_possible(cpu, true);
272next: 292next:
273 cpu++; 293 cpu++;
@@ -281,8 +301,7 @@ next:
281 301
282void __init smp_prepare_cpus(unsigned int max_cpus) 302void __init smp_prepare_cpus(unsigned int max_cpus)
283{ 303{
284 int cpu; 304 int cpu, err;
285 void **release_addr;
286 unsigned int ncores = num_possible_cpus(); 305 unsigned int ncores = num_possible_cpus();
287 306
288 /* 307 /*
@@ -291,30 +310,35 @@ void __init smp_prepare_cpus(unsigned int max_cpus)
291 if (max_cpus > ncores) 310 if (max_cpus > ncores)
292 max_cpus = ncores; 311 max_cpus = ncores;
293 312
313 /* Don't bother if we're effectively UP */
314 if (max_cpus <= 1)
315 return;
316
294 /* 317 /*
295 * Initialise the present map (which describes the set of CPUs 318 * Initialise the present map (which describes the set of CPUs
296 * actually populated at the present time) and release the 319 * actually populated at the present time) and release the
297 * secondaries from the bootloader. 320 * secondaries from the bootloader.
321 *
322 * Make sure we online at most (max_cpus - 1) additional CPUs.
298 */ 323 */
324 max_cpus--;
299 for_each_possible_cpu(cpu) { 325 for_each_possible_cpu(cpu) {
300 if (max_cpus == 0) 326 if (max_cpus == 0)
301 break; 327 break;
302 328
303 if (!cpu_release_addr[cpu]) 329 if (cpu == smp_processor_id())
330 continue;
331
332 if (!smp_enable_ops[cpu])
304 continue; 333 continue;
305 334
306 release_addr = __va(cpu_release_addr[cpu]); 335 err = smp_enable_ops[cpu]->prepare_cpu(cpu);
307 release_addr[0] = (void *)__pa(secondary_holding_pen); 336 if (err)
308 __flush_dcache_area(release_addr, sizeof(release_addr[0])); 337 continue;
309 338
310 set_cpu_present(cpu, true); 339 set_cpu_present(cpu, true);
311 max_cpus--; 340 max_cpus--;
312 } 341 }
313
314 /*
315 * Send an event to wake up the secondaries.
316 */
317 sev();
318} 342}
319 343
320 344