|
@@ -533,6 +533,20 @@ static void undo_cpu_up(unsigned int cpu, struct cpuhp_cpu_state *st)
|
|
|
cpuhp_invoke_callback(cpu, st->state, false, NULL, NULL);
|
|
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,
|
|
static int cpuhp_up_callbacks(unsigned int cpu, struct cpuhp_cpu_state *st,
|
|
|
enum cpuhp_state target)
|
|
enum cpuhp_state target)
|
|
|
{
|
|
{
|
|
@@ -543,8 +557,10 @@ static int cpuhp_up_callbacks(unsigned int cpu, struct cpuhp_cpu_state *st,
|
|
|
st->state++;
|
|
st->state++;
|
|
|
ret = cpuhp_invoke_callback(cpu, st->state, true, NULL, NULL);
|
|
ret = cpuhp_invoke_callback(cpu, st->state, true, NULL, NULL);
|
|
|
if (ret) {
|
|
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;
|
|
break;
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|