aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDengcheng Zhu <dzhu@wavecomp.com>2018-09-11 17:49:22 -0400
committerPaul Burton <paul.burton@mips.com>2018-09-22 13:32:33 -0400
commit1447864bee4cd9ea96fe793ea8fb49a8ea784412 (patch)
tree8c5dfb1d22b4257fcf855016fe239201f7deac71
parent62cac480f33f8f9413d609cb1601b0ee521a86b8 (diff)
MIPS: kexec: CPS systems to halt nonboot CPUs
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
-rw-r--r--arch/mips/kernel/smp-cps.c80
1 files changed, 55 insertions, 25 deletions
diff --git a/arch/mips/kernel/smp-cps.c b/arch/mips/kernel/smp-cps.c
index 03f1026ad148..faccfa4b280b 100644
--- a/arch/mips/kernel/smp-cps.c
+++ b/arch/mips/kernel/smp-cps.c
@@ -398,6 +398,55 @@ static void cps_smp_finish(void)
398 local_irq_enable(); 398 local_irq_enable();
399} 399}
400 400
401#if defined(CONFIG_HOTPLUG_CPU) || defined(CONFIG_KEXEC)
402
403enum cpu_death {
404 CPU_DEATH_HALT,
405 CPU_DEATH_POWER,
406};
407
408static void cps_shutdown_this_cpu(enum cpu_death death)
409{
410 unsigned int cpu, core, vpe_id;
411
412 cpu = smp_processor_id();
413 core = cpu_core(&cpu_data[cpu]);
414
415 if (death == CPU_DEATH_HALT) {
416 vpe_id = cpu_vpe_id(&cpu_data[cpu]);
417
418 pr_debug("Halting core %d VP%d\n", core, vpe_id);
419 if (cpu_has_mipsmt) {
420 /* Halt this TC */
421 write_c0_tchalt(TCHALT_H);
422 instruction_hazard();
423 } else if (cpu_has_vp) {
424 write_cpc_cl_vp_stop(1 << vpe_id);
425
426 /* Ensure that the VP_STOP register is written */
427 wmb();
428 }
429 } else {
430 pr_debug("Gating power to core %d\n", core);
431 /* Power down the core */
432 cps_pm_enter_state(CPS_PM_POWER_GATED);
433 }
434}
435
436#ifdef CONFIG_KEXEC
437
438static void cps_kexec_nonboot_cpu(void)
439{
440 if (cpu_has_mipsmt || cpu_has_vp)
441 cps_shutdown_this_cpu(CPU_DEATH_HALT);
442 else
443 cps_shutdown_this_cpu(CPU_DEATH_POWER);
444}
445
446#endif /* CONFIG_KEXEC */
447
448#endif /* CONFIG_HOTPLUG_CPU || CONFIG_KEXEC */
449
401#ifdef CONFIG_HOTPLUG_CPU 450#ifdef CONFIG_HOTPLUG_CPU
402 451
403static int cps_cpu_disable(void) 452static int cps_cpu_disable(void)
@@ -421,19 +470,15 @@ static int cps_cpu_disable(void)
421} 470}
422 471
423static unsigned cpu_death_sibling; 472static unsigned cpu_death_sibling;
424static enum { 473static enum cpu_death cpu_death;
425 CPU_DEATH_HALT,
426 CPU_DEATH_POWER,
427} cpu_death;
428 474
429void play_dead(void) 475void play_dead(void)
430{ 476{
431 unsigned int cpu, core, vpe_id; 477 unsigned int cpu;
432 478
433 local_irq_disable(); 479 local_irq_disable();
434 idle_task_exit(); 480 idle_task_exit();
435 cpu = smp_processor_id(); 481 cpu = smp_processor_id();
436 core = cpu_core(&cpu_data[cpu]);
437 cpu_death = CPU_DEATH_POWER; 482 cpu_death = CPU_DEATH_POWER;
438 483
439 pr_debug("CPU%d going offline\n", cpu); 484 pr_debug("CPU%d going offline\n", cpu);
@@ -456,25 +501,7 @@ void play_dead(void)
456 /* This CPU has chosen its way out */ 501 /* This CPU has chosen its way out */
457 (void)cpu_report_death(); 502 (void)cpu_report_death();
458 503
459 if (cpu_death == CPU_DEATH_HALT) { 504 cps_shutdown_this_cpu(cpu_death);
460 vpe_id = cpu_vpe_id(&cpu_data[cpu]);
461
462 pr_debug("Halting core %d VP%d\n", core, vpe_id);
463 if (cpu_has_mipsmt) {
464 /* Halt this TC */
465 write_c0_tchalt(TCHALT_H);
466 instruction_hazard();
467 } else if (cpu_has_vp) {
468 write_cpc_cl_vp_stop(1 << vpe_id);
469
470 /* Ensure that the VP_STOP register is written */
471 wmb();
472 }
473 } else {
474 pr_debug("Gating power to core %d\n", core);
475 /* Power down the core */
476 cps_pm_enter_state(CPS_PM_POWER_GATED);
477 }
478 505
479 /* This should never be reached */ 506 /* This should never be reached */
480 panic("Failed to offline CPU %u", cpu); 507 panic("Failed to offline CPU %u", cpu);
@@ -593,6 +620,9 @@ static const struct plat_smp_ops cps_smp_ops = {
593 .cpu_disable = cps_cpu_disable, 620 .cpu_disable = cps_cpu_disable,
594 .cpu_die = cps_cpu_die, 621 .cpu_die = cps_cpu_die,
595#endif 622#endif
623#ifdef CONFIG_KEXEC
624 .kexec_nonboot_cpu = cps_kexec_nonboot_cpu,
625#endif
596}; 626};
597 627
598bool mips_cps_smp_in_use(void) 628bool mips_cps_smp_in_use(void)