summaryrefslogtreecommitdiffstats
path: root/kernel/cpu.c
diff options
context:
space:
mode:
authorJames Morse <james.morse@arm.com>2016-08-17 08:50:25 -0400
committerWill Deacon <will.deacon@arm.com>2016-08-26 06:20:11 -0400
commitd391e552293399396c131544f5b1c2f9b1fb0baa (patch)
tree406375ee8cbe3c5b9061a96164f6910847557bec /kernel/cpu.c
parent40982fd6b975de4a51ce5147bc1d698c3b075634 (diff)
cpu/hotplug: Allow suspend/resume CPU to be specified
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>
Diffstat (limited to 'kernel/cpu.c')
-rw-r--r--kernel/cpu.c9
1 files changed, 5 insertions, 4 deletions
diff --git a/kernel/cpu.c b/kernel/cpu.c
index 341bf80f80bd..ebbf027dd4a1 100644
--- a/kernel/cpu.c
+++ b/kernel/cpu.c
@@ -1024,12 +1024,13 @@ EXPORT_SYMBOL_GPL(cpu_up);
1024#ifdef CONFIG_PM_SLEEP_SMP 1024#ifdef CONFIG_PM_SLEEP_SMP
1025static cpumask_var_t frozen_cpus; 1025static cpumask_var_t frozen_cpus;
1026 1026
1027int disable_nonboot_cpus(void) 1027int freeze_secondary_cpus(int primary)
1028{ 1028{
1029 int cpu, first_cpu, error = 0; 1029 int cpu, error = 0;
1030 1030
1031 cpu_maps_update_begin(); 1031 cpu_maps_update_begin();
1032 first_cpu = cpumask_first(cpu_online_mask); 1032 if (!cpu_online(primary))
1033 primary = cpumask_first(cpu_online_mask);
1033 /* 1034 /*
1034 * We take down all of the non-boot CPUs in one shot to avoid races 1035 * We take down all of the non-boot CPUs in one shot to avoid races
1035 * with the userspace trying to use the CPU hotplug at the same time 1036 * with the userspace trying to use the CPU hotplug at the same time
@@ -1038,7 +1039,7 @@ int disable_nonboot_cpus(void)
1038 1039
1039 pr_info("Disabling non-boot CPUs ...\n"); 1040 pr_info("Disabling non-boot CPUs ...\n");
1040 for_each_online_cpu(cpu) { 1041 for_each_online_cpu(cpu) {
1041 if (cpu == first_cpu) 1042 if (cpu == primary)
1042 continue; 1043 continue;
1043 trace_suspend_resume(TPS("CPU_OFF"), cpu, true); 1044 trace_suspend_resume(TPS("CPU_OFF"), cpu, true);
1044 error = _cpu_down(cpu, 1, CPUHP_OFFLINE); 1045 error = _cpu_down(cpu, 1, CPUHP_OFFLINE);