When a new CPU is added, the kernel is activating all its threads. This leads to weird, but functional, result when adding CPU on a SMT 4 system for instance.
Here the newly added CPU 1 has 8 threads while the other one has 4 threads active (system has been booted with the 'smt-enabled=4' kernel option): ltcden3-lp12:~ # ppc64_cpu --info Core 0: 0* 1* 2* 3* 4 5 6 7 Core 1: 8* 9* 10* 11* 12* 13* 14* 15* We rely on the newly pseries_smt value which should be updated when changing the SMT level by ppc64_cpu --smt=x and at boot time using the smt-enabled kernel option. This way on a LPAR running in SMT=4, newly added CPU will be running 4 threads, which is what a end user would expect. Cc: Srikar Dronamraju <sri...@linux.vnet.ibm.com> Signed-off-by: Laurent Dufour <lduf...@linux.ibm.com> --- arch/powerpc/platforms/pseries/hotplug-cpu.c | 18 +++++++++++++----- arch/powerpc/platforms/pseries/smp.c | 2 +- 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/arch/powerpc/platforms/pseries/hotplug-cpu.c b/arch/powerpc/platforms/pseries/hotplug-cpu.c index 1a3cb313976a..e623ed8649b3 100644 --- a/arch/powerpc/platforms/pseries/hotplug-cpu.c +++ b/arch/powerpc/platforms/pseries/hotplug-cpu.c @@ -382,7 +382,7 @@ static int dlpar_online_cpu(struct device_node *dn) { int rc = 0; unsigned int cpu; - int len, nthreads, i; + int len, nthreads, i, smt; const __be32 *intserv; u32 thread; @@ -392,6 +392,11 @@ static int dlpar_online_cpu(struct device_node *dn) nthreads = len / sizeof(u32); + smt = READ_ONCE(pseries_smt); + /* We should online at least one thread */ + if (smt < 1) + smt = 1; + cpu_maps_update_begin(); for (i = 0; i < nthreads; i++) { thread = be32_to_cpu(intserv[i]); @@ -400,10 +405,13 @@ static int dlpar_online_cpu(struct device_node *dn) continue; cpu_maps_update_done(); find_and_update_cpu_nid(cpu); - rc = device_online(get_cpu_device(cpu)); - if (rc) { - dlpar_offline_cpu(dn); - goto out; + /* Don't active CPU over the current SMT setting */ + if (smt-- > 0) { + rc = device_online(get_cpu_device(cpu)); + if (rc) { + dlpar_offline_cpu(dn); + goto out; + } } cpu_maps_update_begin(); diff --git a/arch/powerpc/platforms/pseries/smp.c b/arch/powerpc/platforms/pseries/smp.c index 6c382922f8f3..ef8070651846 100644 --- a/arch/powerpc/platforms/pseries/smp.c +++ b/arch/powerpc/platforms/pseries/smp.c @@ -295,7 +295,7 @@ static ssize_t pseries_smt_store(struct class *class, return -EINVAL; } - pseries_smt = smt; + WRITE_ONCE(pseries_smt, smt); return count; } -- 2.40.0