|
@@ -66,6 +66,7 @@ EXPORT_SYMBOL(cpu_sibling_map);
|
|
|
cpumask_t cpu_core_map[NR_CPUS] __read_mostly;
|
|
|
EXPORT_SYMBOL(cpu_core_map);
|
|
|
|
|
|
+static DECLARE_COMPLETION(cpu_starting);
|
|
|
static DECLARE_COMPLETION(cpu_running);
|
|
|
|
|
|
/*
|
|
@@ -374,6 +375,12 @@ asmlinkage void start_secondary(void)
|
|
|
cpumask_set_cpu(cpu, &cpu_coherent_mask);
|
|
|
notify_cpu_starting(cpu);
|
|
|
|
|
|
+ /* Notify boot CPU that we're starting & ready to sync counters */
|
|
|
+ complete(&cpu_starting);
|
|
|
+
|
|
|
+ synchronise_count_slave(cpu);
|
|
|
+
|
|
|
+ /* The CPU is running and counters synchronised, now mark it online */
|
|
|
set_cpu_online(cpu, true);
|
|
|
|
|
|
set_cpu_sibling_map(cpu);
|
|
@@ -381,8 +388,11 @@ asmlinkage void start_secondary(void)
|
|
|
|
|
|
calculate_cpu_foreign_map();
|
|
|
|
|
|
+ /*
|
|
|
+ * Notify boot CPU that we're up & online and it can safely return
|
|
|
+ * from __cpu_up
|
|
|
+ */
|
|
|
complete(&cpu_running);
|
|
|
- synchronise_count_slave(cpu);
|
|
|
|
|
|
/*
|
|
|
* 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)
|
|
|
if (err)
|
|
|
return err;
|
|
|
|
|
|
- /*
|
|
|
- * We must check for timeout here, as the CPU will not be marked
|
|
|
- * online until the counters are synchronised.
|
|
|
- */
|
|
|
- if (!wait_for_completion_timeout(&cpu_running,
|
|
|
+ /* Wait for CPU to start and be ready to sync counters */
|
|
|
+ if (!wait_for_completion_timeout(&cpu_starting,
|
|
|
msecs_to_jiffies(1000))) {
|
|
|
pr_crit("CPU%u: failed to start\n", cpu);
|
|
|
return -EIO;
|
|
|
}
|
|
|
|
|
|
synchronise_count_master(cpu);
|
|
|
+
|
|
|
+ /* Wait for CPU to finish startup & mark itself online before return */
|
|
|
+ wait_for_completion(&cpu_running);
|
|
|
return 0;
|
|
|
}
|
|
|
|