diff options
Diffstat (limited to 'arch/mips/kernel/smp.c')
-rw-r--r-- | arch/mips/kernel/smp.c | 22 |
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); | |||
66 | cpumask_t cpu_core_map[NR_CPUS] __read_mostly; | 66 | cpumask_t cpu_core_map[NR_CPUS] __read_mostly; |
67 | EXPORT_SYMBOL(cpu_core_map); | 67 | EXPORT_SYMBOL(cpu_core_map); |
68 | 68 | ||
69 | static DECLARE_COMPLETION(cpu_starting); | ||
69 | static DECLARE_COMPLETION(cpu_running); | 70 | static 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 | ||