aboutsummaryrefslogtreecommitdiffstats
path: root/arch/mips/kernel/smp.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/mips/kernel/smp.c')
-rw-r--r--arch/mips/kernel/smp.c22
1 files changed, 16 insertions, 6 deletions
diff --git a/arch/mips/kernel/smp.c b/arch/mips/kernel/smp.c
index 3cd2f70d1c18..88be966d3e61 100644
--- a/arch/mips/kernel/smp.c
+++ b/arch/mips/kernel/smp.c
@@ -66,6 +66,7 @@ EXPORT_SYMBOL(cpu_sibling_map);
66cpumask_t cpu_core_map[NR_CPUS] __read_mostly; 66cpumask_t cpu_core_map[NR_CPUS] __read_mostly;
67EXPORT_SYMBOL(cpu_core_map); 67EXPORT_SYMBOL(cpu_core_map);
68 68
69static DECLARE_COMPLETION(cpu_starting);
69static DECLARE_COMPLETION(cpu_running); 70static DECLARE_COMPLETION(cpu_running);
70 71
71/* 72/*
@@ -374,6 +375,12 @@ asmlinkage void start_secondary(void)
374 cpumask_set_cpu(cpu, &cpu_coherent_mask); 375 cpumask_set_cpu(cpu, &cpu_coherent_mask);
375 notify_cpu_starting(cpu); 376 notify_cpu_starting(cpu);
376 377
378 /* Notify boot CPU that we're starting & ready to sync counters */
379 complete(&cpu_starting);
380
381 synchronise_count_slave(cpu);
382
383 /* The CPU is running and counters synchronised, now mark it online */
377 set_cpu_online(cpu, true); 384 set_cpu_online(cpu, true);
378 385
379 set_cpu_sibling_map(cpu); 386 set_cpu_sibling_map(cpu);
@@ -381,8 +388,11 @@ asmlinkage void start_secondary(void)
381 388
382 calculate_cpu_foreign_map(); 389 calculate_cpu_foreign_map();
383 390
391 /*
392 * Notify boot CPU that we're up & online and it can safely return
393 * from __cpu_up
394 */
384 complete(&cpu_running); 395 complete(&cpu_running);
385 synchronise_count_slave(cpu);
386 396
387 /* 397 /*
388 * irq will be enabled in ->smp_finish(), enabling it too early 398 * irq will be enabled in ->smp_finish(), enabling it too early
@@ -445,17 +455,17 @@ int __cpu_up(unsigned int cpu, struct task_struct *tidle)
445 if (err) 455 if (err)
446 return err; 456 return err;
447 457
448 /* 458 /* Wait for CPU to start and be ready to sync counters */
449 * We must check for timeout here, as the CPU will not be marked 459 if (!wait_for_completion_timeout(&cpu_starting,
450 * online until the counters are synchronised.
451 */
452 if (!wait_for_completion_timeout(&cpu_running,
453 msecs_to_jiffies(1000))) { 460 msecs_to_jiffies(1000))) {
454 pr_crit("CPU%u: failed to start\n", cpu); 461 pr_crit("CPU%u: failed to start\n", cpu);
455 return -EIO; 462 return -EIO;
456 } 463 }
457 464
458 synchronise_count_master(cpu); 465 synchronise_count_master(cpu);
466
467 /* Wait for CPU to finish startup & mark itself online before return */
468 wait_for_completion(&cpu_running);
459 return 0; 469 return 0;
460} 470}
461 471