@@ -64,6 +64,9 @@ EXPORT_SYMBOL(cpu_sibling_map);
6464cpumask_t cpu_core_map [NR_CPUS ] __read_mostly ;
6565EXPORT_SYMBOL (cpu_core_map );
6666
67+ static DECLARE_COMPLETION (cpu_starting );
68+ static DECLARE_COMPLETION (cpu_running );
69+
6770/*
6871 * A logcal cpu mask containing only one VPE per core to
6972 * reduce the number of IPIs on large MT systems.
@@ -174,16 +177,25 @@ asmlinkage void start_secondary(void)
174177 cpumask_set_cpu (cpu , & cpu_coherent_mask );
175178 notify_cpu_starting (cpu );
176179
177- cpumask_set_cpu (cpu , & cpu_callin_map );
180+ /* Notify boot CPU that we're starting & ready to sync counters */
181+ complete (& cpu_starting );
182+
178183 synchronise_count_slave (cpu );
179184
185+ /* The CPU is running and counters synchronised, now mark it online */
180186 set_cpu_online (cpu , true);
181187
182188 set_cpu_sibling_map (cpu );
183189 set_cpu_core_map (cpu );
184190
185191 calculate_cpu_foreign_map ();
186192
193+ /*
194+ * Notify boot CPU that we're up & online and it can safely return
195+ * from __cpu_up
196+ */
197+ complete (& cpu_running );
198+
187199 /*
188200 * irq will be enabled in ->smp_finish(), enabling it too early
189201 * is dangerous.
@@ -242,22 +254,23 @@ void smp_prepare_boot_cpu(void)
242254{
243255 set_cpu_possible (0 , true);
244256 set_cpu_online (0 , true);
245- cpumask_set_cpu (0 , & cpu_callin_map );
246257}
247258
248259int __cpu_up (unsigned int cpu , struct task_struct * tidle )
249260{
250261 mp_ops -> boot_secondary (cpu , tidle );
251262
252- /*
253- * Trust is futile. We should really have timeouts ...
254- */
255- while (!cpumask_test_cpu (cpu , & cpu_callin_map )) {
256- udelay (100 );
257- schedule ();
263+ /* Wait for CPU to start and be ready to sync counters */
264+ if (!wait_for_completion_timeout (& cpu_starting ,
265+ msecs_to_jiffies (1000 ))) {
266+ pr_crit ("CPU%u: failed to start\n" , cpu );
267+ return - EIO ;
258268 }
259269
260270 synchronise_count_master (cpu );
271+
272+ /* Wait for CPU to finish startup & mark itself online before return */
273+ wait_for_completion (& cpu_running );
261274 return 0 ;
262275}
263276
0 commit comments