summaryrefslogtreecommitdiffstats
path: root/arch/powerpc
diff options
context:
space:
mode:
authorNathan Lynch <nathanl@linux.ibm.com>2019-08-02 14:29:24 -0500
committerBen Hutchings <ben@decadent.org.uk>2019-12-10 18:01:13 +0000
commit6a5a5b347ca18a9ee6f93899f62c8e3725fe8a91 (patch)
tree92507f8a54fd93f9e018f4a59aa0b7217738c1fb /arch/powerpc
parent70eefbdc32aa3e75c38ec60ce7493476eb0cb36f (diff)
downloadlinux-stable-6a5a5b347ca18a9ee6f93899f62c8e3725fe8a91.tar.gz
linux-stable-6a5a5b347ca18a9ee6f93899f62c8e3725fe8a91.tar.bz2
linux-stable-6a5a5b347ca18a9ee6f93899f62c8e3725fe8a91.zip
powerpc/rtas: use device model APIs and serialization during LPM
commit a6717c01ddc259f6f73364779df058e2c67309f8 upstream. The LPAR migration implementation and userspace-initiated cpu hotplug can interleave their executions like so: 1. Set cpu 7 offline via sysfs. 2. Begin a partition migration, whose implementation requires the OS to ensure all present cpus are online; cpu 7 is onlined: rtas_ibm_suspend_me -> rtas_online_cpus_mask -> cpu_up This sets cpu 7 online in all respects except for the cpu's corresponding struct device; dev->offline remains true. 3. Set cpu 7 online via sysfs. _cpu_up() determines that cpu 7 is already online and returns success. The driver core (device_online) sets dev->offline = false. 4. The migration completes and restores cpu 7 to offline state: rtas_ibm_suspend_me -> rtas_offline_cpus_mask -> cpu_down This leaves cpu7 in a state where the driver core considers the cpu device online, but in all other respects it is offline and unused. Attempts to online the cpu via sysfs appear to succeed but the driver core actually does not pass the request to the lower-level cpuhp support code. This makes the cpu unusable until the cpu device is manually set offline and then online again via sysfs. Instead of directly calling cpu_up/cpu_down, the migration code should use the higher-level device core APIs to maintain consistent state and serialize operations. Fixes: 120496ac2d2d ("powerpc: Bring all threads online prior to migration/hibernation") Signed-off-by: Nathan Lynch <nathanl@linux.ibm.com> Reviewed-by: Gautham R. Shenoy <ego@linux.vnet.ibm.com> Signed-off-by: Michael Ellerman <mpe@ellerman.id.au> Link: https://lore.kernel.org/r/20190802192926.19277-2-nathanl@linux.ibm.com Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
Diffstat (limited to 'arch/powerpc')
-rw-r--r--arch/powerpc/kernel/rtas.c11
1 files changed, 8 insertions, 3 deletions
diff --git a/arch/powerpc/kernel/rtas.c b/arch/powerpc/kernel/rtas.c
index 79c459a2b684..acf420108a2c 100644
--- a/arch/powerpc/kernel/rtas.c
+++ b/arch/powerpc/kernel/rtas.c
@@ -855,15 +855,17 @@ static int rtas_cpu_state_change_mask(enum rtas_cpu_state state,
return 0;
for_each_cpu(cpu, cpus) {
+ struct device *dev = get_cpu_device(cpu);
+
switch (state) {
case DOWN:
- cpuret = cpu_down(cpu);
+ cpuret = device_offline(dev);
break;
case UP:
- cpuret = cpu_up(cpu);
+ cpuret = device_online(dev);
break;
}
- if (cpuret) {
+ if (cpuret < 0) {
pr_debug("%s: cpu_%s for cpu#%d returned %d.\n",
__func__,
((state == UP) ? "up" : "down"),
@@ -955,6 +957,8 @@ int rtas_ibm_suspend_me(struct rtas_args *args)
data.token = rtas_token("ibm,suspend-me");
data.complete = &done;
+ lock_device_hotplug();
+
/* All present CPUs must be online */
cpumask_andnot(offline_mask, cpu_present_mask, cpu_online_mask);
cpuret = rtas_online_cpus_mask(offline_mask);
@@ -986,6 +990,7 @@ int rtas_ibm_suspend_me(struct rtas_args *args)
__func__);
out:
+ unlock_device_hotplug();
free_cpumask_var(offline_mask);
return atomic_read(&data.error);
}