diff options
author | Qais Yousef <qais.yousef@arm.com> | 2020-03-23 13:50:55 +0000 |
---|---|---|
committer | Thomas Gleixner <tglx@linutronix.de> | 2020-03-25 12:59:31 +0100 |
commit | 0441a5597c5d02ed7abed1d989eaaa1595dedac5 (patch) | |
tree | d5014aec6251f4733d0740fc9a632850fad9d9a5 /kernel | |
parent | 93ef1429e556f739a208e3968883ed51480580e8 (diff) |
cpu/hotplug: Create a new function to shutdown nonboot cpus
This function will be used later in machine_shutdown() for some
architectures.
disable_nonboot_cpus() is not safe to use when doing machine_down(),
because it relies on freeze_secondary_cpus() which in turn is a
suspend/resume related freeze and could abort if the logic detects any
pending activities that can prevent finishing the offlining process.
Signed-off-by: Qais Yousef <qais.yousef@arm.com>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Link: https://lkml.kernel.org/r/20200323135110.30522-3-qais.yousef@arm.com
Diffstat (limited to 'kernel')
-rw-r--r-- | kernel/cpu.c | 42 |
1 files changed, 42 insertions, 0 deletions
diff --git a/kernel/cpu.c b/kernel/cpu.c index 069802f7010f..03c727195b65 100644 --- a/kernel/cpu.c +++ b/kernel/cpu.c @@ -1069,6 +1069,48 @@ int remove_cpu(unsigned int cpu) } EXPORT_SYMBOL_GPL(remove_cpu); +void smp_shutdown_nonboot_cpus(unsigned int primary_cpu) +{ + unsigned int cpu; + int error; + + cpu_maps_update_begin(); + + /* + * Make certain the cpu I'm about to reboot on is online. + * + * This is inline to what migrate_to_reboot_cpu() already do. + */ + if (!cpu_online(primary_cpu)) + primary_cpu = cpumask_first(cpu_online_mask); + + for_each_online_cpu(cpu) { + if (cpu == primary_cpu) + continue; + + error = cpu_down_maps_locked(cpu, CPUHP_OFFLINE); + if (error) { + pr_err("Failed to offline CPU%d - error=%d", + cpu, error); + break; + } + } + + /* + * Ensure all but the reboot CPU are offline. + */ + BUG_ON(num_online_cpus() > 1); + + /* + * Make sure the CPUs won't be enabled by someone else after this + * point. Kexec will reboot to a new kernel shortly resetting + * everything along the way. + */ + cpu_hotplug_disabled++; + + cpu_maps_update_done(); +} + #else #define takedown_cpu NULL #endif /*CONFIG_HOTPLUG_CPU*/ |