diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2018-09-09 09:48:06 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2018-09-09 09:48:06 -0400 |
commit | e0a0d05848401df48b10f3defce14a5670a0f9f6 (patch) | |
tree | 294823c4b25452a30e537d3e818689b6ca4f77b0 | |
parent | 3243a89dcbd8f5810b72ee0903d349bd000c4c9d (diff) | |
parent | 69fa6eb7d6a64801ea261025cce9723d9442d773 (diff) |
Merge branch 'smp-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull cpu hotplug fixes from Thomas Gleixner:
"Two fixes for the hotplug state machine code:
- Move the misplaces smb() in the hotplug thread function to the
proper place, otherwise a half update control struct could be
observed
- Prevent state corruption on error rollback, which causes the state
to advance by one and as a consequence skip it in the bringup
sequence"
* 'smp-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
cpu/hotplug: Prevent state corruption on error rollback
cpu/hotplug: Adjust misplaced smb() in cpuhp_thread_fun()
-rw-r--r-- | kernel/cpu.c | 11 |
1 files changed, 6 insertions, 5 deletions
diff --git a/kernel/cpu.c b/kernel/cpu.c index aa7fe85ad62e..0097acec1c71 100644 --- a/kernel/cpu.c +++ b/kernel/cpu.c | |||
@@ -607,15 +607,15 @@ static void cpuhp_thread_fun(unsigned int cpu) | |||
607 | bool bringup = st->bringup; | 607 | bool bringup = st->bringup; |
608 | enum cpuhp_state state; | 608 | enum cpuhp_state state; |
609 | 609 | ||
610 | if (WARN_ON_ONCE(!st->should_run)) | ||
611 | return; | ||
612 | |||
610 | /* | 613 | /* |
611 | * ACQUIRE for the cpuhp_should_run() load of ->should_run. Ensures | 614 | * ACQUIRE for the cpuhp_should_run() load of ->should_run. Ensures |
612 | * that if we see ->should_run we also see the rest of the state. | 615 | * that if we see ->should_run we also see the rest of the state. |
613 | */ | 616 | */ |
614 | smp_mb(); | 617 | smp_mb(); |
615 | 618 | ||
616 | if (WARN_ON_ONCE(!st->should_run)) | ||
617 | return; | ||
618 | |||
619 | cpuhp_lock_acquire(bringup); | 619 | cpuhp_lock_acquire(bringup); |
620 | 620 | ||
621 | if (st->single) { | 621 | if (st->single) { |
@@ -916,7 +916,8 @@ static int cpuhp_down_callbacks(unsigned int cpu, struct cpuhp_cpu_state *st, | |||
916 | ret = cpuhp_invoke_callback(cpu, st->state, false, NULL, NULL); | 916 | ret = cpuhp_invoke_callback(cpu, st->state, false, NULL, NULL); |
917 | if (ret) { | 917 | if (ret) { |
918 | st->target = prev_state; | 918 | st->target = prev_state; |
919 | undo_cpu_down(cpu, st); | 919 | if (st->state < prev_state) |
920 | undo_cpu_down(cpu, st); | ||
920 | break; | 921 | break; |
921 | } | 922 | } |
922 | } | 923 | } |
@@ -969,7 +970,7 @@ static int __ref _cpu_down(unsigned int cpu, int tasks_frozen, | |||
969 | * to do the further cleanups. | 970 | * to do the further cleanups. |
970 | */ | 971 | */ |
971 | ret = cpuhp_down_callbacks(cpu, st, target); | 972 | ret = cpuhp_down_callbacks(cpu, st, target); |
972 | if (ret && st->state > CPUHP_TEARDOWN_CPU && st->state < prev_state) { | 973 | if (ret && st->state == CPUHP_TEARDOWN_CPU && st->state < prev_state) { |
973 | cpuhp_reset_state(st, prev_state); | 974 | cpuhp_reset_state(st, prev_state); |
974 | __cpuhp_kick_ap(st); | 975 | __cpuhp_kick_ap(st); |
975 | } | 976 | } |