summaryrefslogtreecommitdiffstats
path: root/kernel/cpu.c
diff options
context:
space:
mode:
authorThomas Gleixner <tglx@linutronix.de>2019-05-06 12:04:12 +0200
committerThomas Gleixner <tglx@linutronix.de>2019-05-06 12:04:12 +0200
commitfb4e0592654adb31bc6f3a738d6499b816a655d6 (patch)
treee6edaf18cf3a7f49e93fb51de5a47f4b9e786f53 /kernel/cpu.c
parent471ba0e686cb13752bc1ff3216c54b69a2d250ea (diff)
parent16e32c3cde7763ab875b9030b443ecbc8e352d8a (diff)
downloadlinux-fb4e0592654adb31bc6f3a738d6499b816a655d6.tar.gz
linux-fb4e0592654adb31bc6f3a738d6499b816a655d6.tar.bz2
linux-fb4e0592654adb31bc6f3a738d6499b816a655d6.zip
Merge tag 'irqchip-5.2' of git://git.kernel.org/pub/scm/linux/kernel/git/maz/arm-platforms into irq/core
Pull irqchip updates from Marc Zyngier - The huge (and terrifying) TI INTR/INTA set of drivers - Rewrite of the stm32mp1-exti driver as a platform driver - Update the IOMMU MSI mapping API to be RT friendly - A number of cleanups and other low impact fixes
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;
}
}