|
@@ -271,11 +271,25 @@ void cpu_hotplug_enable(void)
|
|
|
EXPORT_SYMBOL_GPL(cpu_hotplug_enable);
|
|
|
#endif /* CONFIG_HOTPLUG_CPU */
|
|
|
|
|
|
+static void __cpuhp_kick_ap_work(struct cpuhp_cpu_state *st);
|
|
|
+
|
|
|
static int bringup_wait_for_ap(unsigned int cpu)
|
|
|
{
|
|
|
struct cpuhp_cpu_state *st = per_cpu_ptr(&cpuhp_state, cpu);
|
|
|
|
|
|
+ /* Wait for the CPU to reach CPUHP_AP_ONLINE_IDLE */
|
|
|
wait_for_completion(&st->done);
|
|
|
+ BUG_ON(!cpu_online(cpu));
|
|
|
+
|
|
|
+ /* Unpark the stopper thread and the hotplug thread of the target cpu */
|
|
|
+ stop_machine_unpark(cpu);
|
|
|
+ kthread_unpark(st->thread);
|
|
|
+
|
|
|
+ /* Should we go further up ? */
|
|
|
+ if (st->target > CPUHP_AP_ONLINE_IDLE) {
|
|
|
+ __cpuhp_kick_ap_work(st);
|
|
|
+ wait_for_completion(&st->done);
|
|
|
+ }
|
|
|
return st->result;
|
|
|
}
|
|
|
|
|
@@ -296,9 +310,7 @@ static int bringup_cpu(unsigned int cpu)
|
|
|
irq_unlock_sparse();
|
|
|
if (ret)
|
|
|
return ret;
|
|
|
- ret = bringup_wait_for_ap(cpu);
|
|
|
- BUG_ON(!cpu_online(cpu));
|
|
|
- return ret;
|
|
|
+ return bringup_wait_for_ap(cpu);
|
|
|
}
|
|
|
|
|
|
/*
|
|
@@ -767,31 +779,20 @@ void notify_cpu_starting(unsigned int cpu)
|
|
|
}
|
|
|
|
|
|
/*
|
|
|
- * Called from the idle task. We need to set active here, so we can kick off
|
|
|
- * the stopper thread and unpark the smpboot threads. If the target state is
|
|
|
- * beyond CPUHP_AP_ONLINE_IDLE we kick cpuhp thread and let it bring up the
|
|
|
- * cpu further.
|
|
|
+ * Called from the idle task. Wake up the controlling task which brings the
|
|
|
+ * stopper and the hotplug thread of the upcoming CPU up and then delegates
|
|
|
+ * the rest of the online bringup to the hotplug thread.
|
|
|
*/
|
|
|
void cpuhp_online_idle(enum cpuhp_state state)
|
|
|
{
|
|
|
struct cpuhp_cpu_state *st = this_cpu_ptr(&cpuhp_state);
|
|
|
- unsigned int cpu = smp_processor_id();
|
|
|
|
|
|
/* Happens for the boot cpu */
|
|
|
if (state != CPUHP_AP_ONLINE_IDLE)
|
|
|
return;
|
|
|
|
|
|
st->state = CPUHP_AP_ONLINE_IDLE;
|
|
|
-
|
|
|
- /* Unpark the stopper thread and the hotplug thread of this cpu */
|
|
|
- stop_machine_unpark(cpu);
|
|
|
- kthread_unpark(st->thread);
|
|
|
-
|
|
|
- /* Should we go further up ? */
|
|
|
- if (st->target > CPUHP_AP_ONLINE_IDLE)
|
|
|
- __cpuhp_kick_ap_work(st);
|
|
|
- else
|
|
|
- complete(&st->done);
|
|
|
+ complete(&st->done);
|
|
|
}
|
|
|
|
|
|
/* Requires cpu_add_remove_lock to be held */
|