Skip to content

Commit 8df3e07

Browse files
committed
cpu/hotplug: Let upcoming cpu bring itself fully up
Let the upcoming cpu kick the hotplug thread and let itself complete the bringup. That way the controll side can just wait for the completion or later when we made the hotplug machinery async not care at all. Signed-off-by: Thomas Gleixner <[email protected]> Cc: [email protected] Cc: Rik van Riel <[email protected]> Cc: Rafael Wysocki <[email protected]> Cc: "Srivatsa S. Bhat" <[email protected]> Cc: Peter Zijlstra <[email protected]> Cc: Arjan van de Ven <[email protected]> Cc: Sebastian Siewior <[email protected]> Cc: Rusty Russell <[email protected]> Cc: Steven Rostedt <[email protected]> Cc: Oleg Nesterov <[email protected]> Cc: Tejun Heo <[email protected]> Cc: Andrew Morton <[email protected]> Cc: Paul McKenney <[email protected]> Cc: Linus Torvalds <[email protected]> Cc: Paul Turner <[email protected]> Link: http://lkml.kernel.org/r/[email protected] Signed-off-by: Thomas Gleixner <[email protected]>
1 parent fc6d73d commit 8df3e07

File tree

3 files changed

+45
-32
lines changed

3 files changed

+45
-32
lines changed

include/linux/cpuhotplug.h

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,6 @@ enum cpuhp_state {
1010
CPUHP_AP_NOTIFY_STARTING,
1111
CPUHP_AP_ONLINE,
1212
CPUHP_TEARDOWN_CPU,
13-
CPUHP_CPU_SET_ACTIVE,
14-
CPUHP_KICK_AP_THREAD,
15-
CPUHP_BP_ONLINE,
1613
CPUHP_AP_ONLINE_IDLE,
1714
CPUHP_AP_SMPBOOT_THREADS,
1815
CPUHP_AP_NOTIFY_ONLINE,
@@ -86,4 +83,10 @@ static inline void cpuhp_remove_state_nocalls(enum cpuhp_state state)
8683
__cpuhp_remove_state(state, false);
8784
}
8885

86+
#ifdef CONFIG_SMP
87+
void cpuhp_online_idle(enum cpuhp_state state);
88+
#else
89+
static inline void cpuhp_online_idle(enum cpuhp_state state) { }
90+
#endif
91+
8992
#endif

kernel/cpu.c

Lines changed: 37 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -329,6 +329,14 @@ static int notify_starting(unsigned int cpu)
329329
return 0;
330330
}
331331

332+
static int bringup_wait_for_ap(unsigned int cpu)
333+
{
334+
struct cpuhp_cpu_state *st = per_cpu_ptr(&cpuhp_state, cpu);
335+
336+
wait_for_completion(&st->done);
337+
return st->result;
338+
}
339+
332340
static int bringup_cpu(unsigned int cpu)
333341
{
334342
struct task_struct *idle = idle_thread_get(cpu);
@@ -340,8 +348,9 @@ static int bringup_cpu(unsigned int cpu)
340348
cpu_notify(CPU_UP_CANCELED, cpu);
341349
return ret;
342350
}
351+
ret = bringup_wait_for_ap(cpu);
343352
BUG_ON(!cpu_online(cpu));
344-
return 0;
353+
return ret;
345354
}
346355

347356
/*
@@ -470,7 +479,7 @@ static void cpuhp_thread_fun(unsigned int cpu)
470479
}
471480
} else {
472481
/* Cannot happen .... */
473-
BUG_ON(st->state < CPUHP_KICK_AP_THREAD);
482+
BUG_ON(st->state < CPUHP_AP_ONLINE_IDLE);
474483

475484
/* Regular hotplug work */
476485
if (st->state < st->target)
@@ -780,7 +789,7 @@ static int __ref _cpu_down(unsigned int cpu, int tasks_frozen,
780789
* If the current CPU state is in the range of the AP hotplug thread,
781790
* then we need to kick the thread.
782791
*/
783-
if (st->state >= CPUHP_KICK_AP_THREAD) {
792+
if (st->state > CPUHP_TEARDOWN_CPU) {
784793
ret = cpuhp_kick_ap_work(cpu);
785794
/*
786795
* The AP side has done the error rollback already. Just
@@ -793,11 +802,11 @@ static int __ref _cpu_down(unsigned int cpu, int tasks_frozen,
793802
* We might have stopped still in the range of the AP hotplug
794803
* thread. Nothing to do anymore.
795804
*/
796-
if (st->state >= CPUHP_KICK_AP_THREAD)
805+
if (st->state > CPUHP_TEARDOWN_CPU)
797806
goto out;
798807
}
799808
/*
800-
* The AP brought itself down below CPUHP_KICK_AP_THREAD. So we need
809+
* The AP brought itself down to CPUHP_TEARDOWN_CPU. So we need
801810
* to do the further cleanups.
802811
*/
803812
ret = cpuhp_down_callbacks(cpu, st, cpuhp_bp_states, target);
@@ -859,18 +868,32 @@ void notify_cpu_starting(unsigned int cpu)
859868

860869
/*
861870
* Called from the idle task. We need to set active here, so we can kick off
862-
* the stopper thread.
871+
* the stopper thread and unpark the smpboot threads. If the target state is
872+
* beyond CPUHP_AP_ONLINE_IDLE we kick cpuhp thread and let it bring up the
873+
* cpu further.
863874
*/
864-
static int cpuhp_set_cpu_active(unsigned int cpu)
875+
void cpuhp_online_idle(enum cpuhp_state state)
865876
{
866-
struct cpuhp_cpu_state *st = per_cpu_ptr(&cpuhp_state, cpu);
877+
struct cpuhp_cpu_state *st = this_cpu_ptr(&cpuhp_state);
878+
unsigned int cpu = smp_processor_id();
879+
880+
/* Happens for the boot cpu */
881+
if (state != CPUHP_AP_ONLINE_IDLE)
882+
return;
883+
884+
st->state = CPUHP_AP_ONLINE_IDLE;
867885

868886
/* The cpu is marked online, set it active now */
869887
set_cpu_active(cpu, true);
870-
/* Unpark the stopper thread and the hotplug thread */
888+
/* Unpark the stopper thread and the hotplug thread of this cpu */
871889
stop_machine_unpark(cpu);
872890
kthread_unpark(st->thread);
873-
return 0;
891+
892+
/* Should we go further up ? */
893+
if (st->target > CPUHP_AP_ONLINE_IDLE)
894+
__cpuhp_kick_ap_work(st);
895+
else
896+
complete(&st->done);
874897
}
875898

876899
/* Requires cpu_add_remove_lock to be held */
@@ -910,7 +933,7 @@ static int _cpu_up(unsigned int cpu, int tasks_frozen, enum cpuhp_state target)
910933
* If the current CPU state is in the range of the AP hotplug thread,
911934
* then we need to kick the thread once more.
912935
*/
913-
if (st->state >= CPUHP_KICK_AP_THREAD) {
936+
if (st->state > CPUHP_BRINGUP_CPU) {
914937
ret = cpuhp_kick_ap_work(cpu);
915938
/*
916939
* The AP side has done the error rollback already. Just
@@ -922,10 +945,10 @@ static int _cpu_up(unsigned int cpu, int tasks_frozen, enum cpuhp_state target)
922945

923946
/*
924947
* Try to reach the target state. We max out on the BP at
925-
* CPUHP_KICK_AP_THREAD. After that the AP hotplug thread is
948+
* CPUHP_BRINGUP_CPU. After that the AP hotplug thread is
926949
* responsible for bringing it up to the target state.
927950
*/
928-
target = min((int)target, CPUHP_KICK_AP_THREAD);
951+
target = min((int)target, CPUHP_BRINGUP_CPU);
929952
ret = cpuhp_up_callbacks(cpu, st, cpuhp_bp_states, target);
930953
out:
931954
cpu_hotplug_done();
@@ -1146,22 +1169,7 @@ static struct cpuhp_step cpuhp_bp_states[] = {
11461169
.teardown = takedown_cpu,
11471170
.cant_stop = true,
11481171
},
1149-
[CPUHP_CPU_SET_ACTIVE] = {
1150-
.name = "cpu:active",
1151-
.startup = cpuhp_set_cpu_active,
1152-
.teardown = NULL,
1153-
},
1154-
[CPUHP_KICK_AP_THREAD] = {
1155-
.name = "cpuhp:kickthread",
1156-
.startup = cpuhp_kick_ap_work,
1157-
.teardown = cpuhp_kick_ap_work,
1158-
},
11591172
#endif
1160-
[CPUHP_BP_ONLINE] = {
1161-
.name = "online",
1162-
.startup = NULL,
1163-
.teardown = NULL,
1164-
},
11651173
};
11661174

11671175
/* Application processor state steps */
@@ -1204,7 +1212,7 @@ static bool cpuhp_is_ap_state(enum cpuhp_state state)
12041212
{
12051213
if (state >= CPUHP_AP_OFFLINE && state <= CPUHP_AP_ONLINE)
12061214
return true;
1207-
return state > CPUHP_BP_ONLINE;
1215+
return state > CPUHP_BRINGUP_CPU;
12081216
}
12091217

12101218
static struct cpuhp_step *cpuhp_get_step(enum cpuhp_state state)

kernel/sched/idle.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
#include <linux/sched.h>
55
#include <linux/cpu.h>
66
#include <linux/cpuidle.h>
7+
#include <linux/cpuhotplug.h>
78
#include <linux/tick.h>
89
#include <linux/mm.h>
910
#include <linux/stackprotector.h>
@@ -291,5 +292,6 @@ void cpu_startup_entry(enum cpuhp_state state)
291292
boot_init_stack_canary();
292293
#endif
293294
arch_cpu_idle_prepare();
295+
cpuhp_online_idle(state);
294296
cpu_idle_loop();
295297
}

0 commit comments

Comments
 (0)