MIPS: kexec: CPS systems to halt nonboot CPUs
authorDengcheng Zhu <dzhu@wavecomp.com>
Tue, 11 Sep 2018 21:49:22 +0000 (14:49 -0700)
committerPaul Burton <paul.burton@mips.com>
Sat, 22 Sep 2018 17:32:33 +0000 (10:32 -0700)
Share code between play_dead() and cps_kexec_nonboot_cpu(). Register the
latter to mp_ops for kexec.

Signed-off-by: Dengcheng Zhu <dzhu@wavecomp.com>
Signed-off-by: Paul Burton <paul.burton@mips.com>
Patchwork: https://patchwork.linux-mips.org/patch/20567/
Cc: pburton@wavecomp.com
Cc: ralf@linux-mips.org
Cc: linux-mips@linux-mips.org
Cc: rachel.mozes@intel.com
arch/mips/kernel/smp-cps.c

index 03f1026ad14841f902f40aa61c8bbcbd1af46eb9..faccfa4b280ba375620edb5bb955757918cb0e0b 100644 (file)
@@ -398,6 +398,55 @@ static void cps_smp_finish(void)
        local_irq_enable();
 }
 
+#if defined(CONFIG_HOTPLUG_CPU) || defined(CONFIG_KEXEC)
+
+enum cpu_death {
+       CPU_DEATH_HALT,
+       CPU_DEATH_POWER,
+};
+
+static void cps_shutdown_this_cpu(enum cpu_death death)
+{
+       unsigned int cpu, core, vpe_id;
+
+       cpu = smp_processor_id();
+       core = cpu_core(&cpu_data[cpu]);
+
+       if (death == CPU_DEATH_HALT) {
+               vpe_id = cpu_vpe_id(&cpu_data[cpu]);
+
+               pr_debug("Halting core %d VP%d\n", core, vpe_id);
+               if (cpu_has_mipsmt) {
+                       /* Halt this TC */
+                       write_c0_tchalt(TCHALT_H);
+                       instruction_hazard();
+               } else if (cpu_has_vp) {
+                       write_cpc_cl_vp_stop(1 << vpe_id);
+
+                       /* Ensure that the VP_STOP register is written */
+                       wmb();
+               }
+       } else {
+               pr_debug("Gating power to core %d\n", core);
+               /* Power down the core */
+               cps_pm_enter_state(CPS_PM_POWER_GATED);
+       }
+}
+
+#ifdef CONFIG_KEXEC
+
+static void cps_kexec_nonboot_cpu(void)
+{
+       if (cpu_has_mipsmt || cpu_has_vp)
+               cps_shutdown_this_cpu(CPU_DEATH_HALT);
+       else
+               cps_shutdown_this_cpu(CPU_DEATH_POWER);
+}
+
+#endif /* CONFIG_KEXEC */
+
+#endif /* CONFIG_HOTPLUG_CPU || CONFIG_KEXEC */
+
 #ifdef CONFIG_HOTPLUG_CPU
 
 static int cps_cpu_disable(void)
@@ -421,19 +470,15 @@ static int cps_cpu_disable(void)
 }
 
 static unsigned cpu_death_sibling;
-static enum {
-       CPU_DEATH_HALT,
-       CPU_DEATH_POWER,
-} cpu_death;
+static enum cpu_death cpu_death;
 
 void play_dead(void)
 {
-       unsigned int cpu, core, vpe_id;
+       unsigned int cpu;
 
        local_irq_disable();
        idle_task_exit();
        cpu = smp_processor_id();
-       core = cpu_core(&cpu_data[cpu]);
        cpu_death = CPU_DEATH_POWER;
 
        pr_debug("CPU%d going offline\n", cpu);
@@ -456,25 +501,7 @@ void play_dead(void)
        /* This CPU has chosen its way out */
        (void)cpu_report_death();
 
-       if (cpu_death == CPU_DEATH_HALT) {
-               vpe_id = cpu_vpe_id(&cpu_data[cpu]);
-
-               pr_debug("Halting core %d VP%d\n", core, vpe_id);
-               if (cpu_has_mipsmt) {
-                       /* Halt this TC */
-                       write_c0_tchalt(TCHALT_H);
-                       instruction_hazard();
-               } else if (cpu_has_vp) {
-                       write_cpc_cl_vp_stop(1 << vpe_id);
-
-                       /* Ensure that the VP_STOP register is written */
-                       wmb();
-               }
-       } else {
-               pr_debug("Gating power to core %d\n", core);
-               /* Power down the core */
-               cps_pm_enter_state(CPS_PM_POWER_GATED);
-       }
+       cps_shutdown_this_cpu(cpu_death);
 
        /* This should never be reached */
        panic("Failed to offline CPU %u", cpu);
@@ -593,6 +620,9 @@ static const struct plat_smp_ops cps_smp_ops = {
        .cpu_disable            = cps_cpu_disable,
        .cpu_die                = cps_cpu_die,
 #endif
+#ifdef CONFIG_KEXEC
+       .kexec_nonboot_cpu      = cps_kexec_nonboot_cpu,
+#endif
 };
 
 bool mips_cps_smp_in_use(void)