cpu/hotplug: Allow suspend/resume CPU to be specified
authorJames Morse <james.morse@arm.com>
Wed, 17 Aug 2016 12:50:25 +0000 (13:50 +0100)
committerWill Deacon <will.deacon@arm.com>
Fri, 26 Aug 2016 10:20:11 +0000 (11:20 +0100)
disable_nonboot_cpus() assumes that the lowest numbered online CPU is
the boot CPU, and that this is the correct CPU to run any power
management code on.

On x86 this is always correct, as CPU0 cannot (easily) by taken offline.

On arm64 CPU0 can be taken offline. For hibernate/resume this means we
may hibernate on a CPU other than CPU0. If the system is rebooted with
kexec 'CPU0' will be assigned to a different physical CPU. This
complicates hibernate/resume as now we can't trust the CPU numbers.
Arch code can find the correct physical CPU, and ensure it is online
before resume from hibernate begins, but also needs to influence
disable_nonboot_cpus()s choice of CPU.

Rename disable_nonboot_cpus() as freeze_secondary_cpus() and add an
argument indicating which CPU should be left standing. Follow the logic
in migrate_to_reboot_cpu() to use the lowest numbered online CPU if the
requested CPU is not online.
Add disable_nonboot_cpus() as an inline function that has the existing
behaviour.

Cc: Rafael J. Wysocki <rjw@rjwysocki.net>
Reviewed-by: Thomas Gleixner <tglx@linutronix.de>
Signed-off-by: James Morse <james.morse@arm.com>
Signed-off-by: Will Deacon <will.deacon@arm.com>
include/linux/cpu.h
kernel/cpu.c

index 797d9c8e9a1be77b257bfdb77f7158740629c787..ad4f1f33a74e93050cb110fdf6f8f512c0c11499 100644 (file)
@@ -228,7 +228,11 @@ static inline void cpu_hotplug_done(void) {}
 #endif         /* CONFIG_HOTPLUG_CPU */
 
 #ifdef CONFIG_PM_SLEEP_SMP
-extern int disable_nonboot_cpus(void);
+extern int freeze_secondary_cpus(int primary);
+static inline int disable_nonboot_cpus(void)
+{
+       return freeze_secondary_cpus(0);
+}
 extern void enable_nonboot_cpus(void);
 #else /* !CONFIG_PM_SLEEP_SMP */
 static inline int disable_nonboot_cpus(void) { return 0; }
index 341bf80f80bd685d529db77f6c4afdeda05f28ae..ebbf027dd4a13accdfd433d0cc50eb33182aa5cf 100644 (file)
@@ -1024,12 +1024,13 @@ EXPORT_SYMBOL_GPL(cpu_up);
 #ifdef CONFIG_PM_SLEEP_SMP
 static cpumask_var_t frozen_cpus;
 
-int disable_nonboot_cpus(void)
+int freeze_secondary_cpus(int primary)
 {
-       int cpu, first_cpu, error = 0;
+       int cpu, error = 0;
 
        cpu_maps_update_begin();
-       first_cpu = cpumask_first(cpu_online_mask);
+       if (!cpu_online(primary))
+               primary = cpumask_first(cpu_online_mask);
        /*
         * We take down all of the non-boot CPUs in one shot to avoid races
         * with the userspace trying to use the CPU hotplug at the same time
@@ -1038,7 +1039,7 @@ int disable_nonboot_cpus(void)
 
        pr_info("Disabling non-boot CPUs ...\n");
        for_each_online_cpu(cpu) {
-               if (cpu == first_cpu)
+               if (cpu == primary)
                        continue;
                trace_suspend_resume(TPS("CPU_OFF"), cpu, true);
                error = _cpu_down(cpu, 1, CPUHP_OFFLINE);