summaryrefslogtreecommitdiff
path: root/kernel/cpu.c
diff options
context:
space:
mode:
authorLinus Walleij <linus.walleij@linaro.org>2019-04-08 13:03:09 +0200
committerLinus Walleij <linus.walleij@linaro.org>2019-04-08 13:03:09 +0200
commit26af34079f1d8299932303cfd2b376b9cf55a35c (patch)
treef1a9824855fae569aa51c2109a5929715143093d /kernel/cpu.c
parent27157af66324d529b43231c12b5d1e1a3e9fa620 (diff)
parent79a3aaa7b82e3106be97842dedfd8429248896e6 (diff)
Merge tag 'v5.1-rc3' into devel
Linux 5.1-rc3
Diffstat (limited to 'kernel/cpu.c')
-rw-r--r--kernel/cpu.c20
1 files changed, 18 insertions, 2 deletions
diff --git a/kernel/cpu.c b/kernel/cpu.c
index 025f419d16f6..6754f3ecfd94 100644
--- a/kernel/cpu.c
+++ b/kernel/cpu.c
@@ -564,6 +564,20 @@ static void undo_cpu_up(unsigned int cpu, struct cpuhp_cpu_state *st)
cpuhp_invoke_callback(cpu, st->state, false, NULL, NULL);
}
+static inline bool can_rollback_cpu(struct cpuhp_cpu_state *st)
+{
+ if (IS_ENABLED(CONFIG_HOTPLUG_CPU))
+ return true;
+ /*
+ * When CPU hotplug is disabled, then taking the CPU down is not
+ * possible because takedown_cpu() and the architecture and
+ * subsystem specific mechanisms are not available. So the CPU
+ * which would be completely unplugged again needs to stay around
+ * in the current state.
+ */
+ return st->state <= CPUHP_BRINGUP_CPU;
+}
+
static int cpuhp_up_callbacks(unsigned int cpu, struct cpuhp_cpu_state *st,
enum cpuhp_state target)
{
@@ -574,8 +588,10 @@ static int cpuhp_up_callbacks(unsigned int cpu, struct cpuhp_cpu_state *st,
st->state++;
ret = cpuhp_invoke_callback(cpu, st->state, true, NULL, NULL);
if (ret) {
- st->target = prev_state;
- undo_cpu_up(cpu, st);
+ if (can_rollback_cpu(st)) {
+ st->target = prev_state;
+ undo_cpu_up(cpu, st);
+ }
break;
}
}