diff options
| -rw-r--r-- | kernel/cpu.c | 20 |
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) | |||
| 564 | cpuhp_invoke_callback(cpu, st->state, false, NULL, NULL); | 564 | cpuhp_invoke_callback(cpu, st->state, false, NULL, NULL); |
| 565 | } | 565 | } |
| 566 | 566 | ||
| 567 | static inline bool can_rollback_cpu(struct cpuhp_cpu_state *st) | ||
| 568 | { | ||
| 569 | if (IS_ENABLED(CONFIG_HOTPLUG_CPU)) | ||
| 570 | return true; | ||
| 571 | /* | ||
| 572 | * When CPU hotplug is disabled, then taking the CPU down is not | ||
| 573 | * possible because takedown_cpu() and the architecture and | ||
| 574 | * subsystem specific mechanisms are not available. So the CPU | ||
| 575 | * which would be completely unplugged again needs to stay around | ||
| 576 | * in the current state. | ||
| 577 | */ | ||
| 578 | return st->state <= CPUHP_BRINGUP_CPU; | ||
| 579 | } | ||
| 580 | |||
| 567 | static int cpuhp_up_callbacks(unsigned int cpu, struct cpuhp_cpu_state *st, | 581 | static int cpuhp_up_callbacks(unsigned int cpu, struct cpuhp_cpu_state *st, |
| 568 | enum cpuhp_state target) | 582 | enum cpuhp_state target) |
| 569 | { | 583 | { |
| @@ -574,8 +588,10 @@ static int cpuhp_up_callbacks(unsigned int cpu, struct cpuhp_cpu_state *st, | |||
| 574 | st->state++; | 588 | st->state++; |
| 575 | ret = cpuhp_invoke_callback(cpu, st->state, true, NULL, NULL); | 589 | ret = cpuhp_invoke_callback(cpu, st->state, true, NULL, NULL); |
| 576 | if (ret) { | 590 | if (ret) { |
| 577 | st->target = prev_state; | 591 | if (can_rollback_cpu(st)) { |
| 578 | undo_cpu_up(cpu, st); | 592 | st->target = prev_state; |
| 593 | undo_cpu_up(cpu, st); | ||
| 594 | } | ||
| 579 | break; | 595 | break; |
| 580 | } | 596 | } |
| 581 | } | 597 | } |
