powerpc/pseries: Initialise CPU hotplug callbacks earlier
authorMichael Ellerman <mpe@ellerman.id.au>
Wed, 5 Jul 2023 14:51:41 +0000 (16:51 +0200)
committerMichael Ellerman <mpe@ellerman.id.au>
Wed, 2 Aug 2023 12:43:42 +0000 (22:43 +1000)
As part of the generic HOTPLUG_SMT code, there is support for disabling
secondary SMT threads at boot time, by passing "nosmt" on the kernel
command line.

The way that is implemented is the secondary threads are brought partly
online, and then taken back offline again. That is done to support x86
CPUs needing certain initialisation done on all threads. However powerpc
has similar needs, see commit d70a54e2d085 ("powerpc/powernv: Ignore
smt-enabled on Power8 and later").

For that to work the powerpc CPU hotplug callbacks need to be registered
before secondary CPUs are brought online, otherwise __cpu_disable()
fails due to smp_ops->cpu_disable being NULL.

So split the basic initialisation into pseries_cpu_hotplug_init() which
can be called early from setup_arch(). The DLPAR related initialisation
can still be done later, because it needs to do allocations.

Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
Link: https://msgid.link/20230705145143.40545-9-ldufour@linux.ibm.com
arch/powerpc/platforms/pseries/hotplug-cpu.c
arch/powerpc/platforms/pseries/pseries.h
arch/powerpc/platforms/pseries/setup.c

index 1a3cb313976a456d59a07c17acfe01835291d1f8..61fb7cb0088032330d2098eb510ae25b5405af60 100644 (file)
@@ -845,15 +845,9 @@ static struct notifier_block pseries_smp_nb = {
        .notifier_call = pseries_smp_notifier,
 };
 
-static int __init pseries_cpu_hotplug_init(void)
+void __init pseries_cpu_hotplug_init(void)
 {
        int qcss_tok;
-       unsigned int node;
-
-#ifdef CONFIG_ARCH_CPU_PROBE_RELEASE
-       ppc_md.cpu_probe = dlpar_cpu_probe;
-       ppc_md.cpu_release = dlpar_cpu_release;
-#endif /* CONFIG_ARCH_CPU_PROBE_RELEASE */
 
        rtas_stop_self_token = rtas_function_token(RTAS_FN_STOP_SELF);
        qcss_tok = rtas_function_token(RTAS_FN_QUERY_CPU_STOPPED_STATE);
@@ -862,12 +856,22 @@ static int __init pseries_cpu_hotplug_init(void)
                        qcss_tok == RTAS_UNKNOWN_SERVICE) {
                printk(KERN_INFO "CPU Hotplug not supported by firmware "
                                "- disabling.\n");
-               return 0;
+               return;
        }
 
        smp_ops->cpu_offline_self = pseries_cpu_offline_self;
        smp_ops->cpu_disable = pseries_cpu_disable;
        smp_ops->cpu_die = pseries_cpu_die;
+}
+
+static int __init pseries_dlpar_init(void)
+{
+       unsigned int node;
+
+#ifdef CONFIG_ARCH_CPU_PROBE_RELEASE
+       ppc_md.cpu_probe = dlpar_cpu_probe;
+       ppc_md.cpu_release = dlpar_cpu_release;
+#endif /* CONFIG_ARCH_CPU_PROBE_RELEASE */
 
        /* Processors can be added/removed only on LPAR */
        if (firmware_has_feature(FW_FEATURE_LPAR)) {
@@ -886,4 +890,4 @@ static int __init pseries_cpu_hotplug_init(void)
 
        return 0;
 }
-machine_arch_initcall(pseries, pseries_cpu_hotplug_init);
+machine_arch_initcall(pseries, pseries_dlpar_init);
index f8bce40ebd0ce1fcc24d7f219b26ccb2268a2561..f8893ba46e83a90928712ee13b20080ec05e5029 100644 (file)
@@ -75,11 +75,13 @@ static inline int dlpar_hp_pmem(struct pseries_hp_errorlog *hp_elog)
 
 #ifdef CONFIG_HOTPLUG_CPU
 int dlpar_cpu(struct pseries_hp_errorlog *hp_elog);
+void pseries_cpu_hotplug_init(void);
 #else
 static inline int dlpar_cpu(struct pseries_hp_errorlog *hp_elog)
 {
        return -EOPNOTSUPP;
 }
+static inline void pseries_cpu_hotplug_init(void) { }
 #endif
 
 /* PCI root bridge prepare function override for pseries */
index e2a57cfa6c837c7c906ed30d449291b727f78726..41451b76c6e51880b78e2c12168316235e451e44 100644 (file)
@@ -816,6 +816,8 @@ static void __init pSeries_setup_arch(void)
        /* Discover PIC type and setup ppc_md accordingly */
        smp_init_pseries();
 
+       // Setup CPU hotplug callbacks
+       pseries_cpu_hotplug_init();
 
        if (radix_enabled() && !mmu_has_feature(MMU_FTR_GTSE))
                if (!firmware_has_feature(FW_FEATURE_RPT_INVALIDATE))