Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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

authored by

Dengcheng Zhu and committed by
Paul Burton
1447864b 62cac480

+55 -25
+55 -25
arch/mips/kernel/smp-cps.c
··· 398 398 local_irq_enable(); 399 399 } 400 400 401 + #if defined(CONFIG_HOTPLUG_CPU) || defined(CONFIG_KEXEC) 402 + 403 + enum cpu_death { 404 + CPU_DEATH_HALT, 405 + CPU_DEATH_POWER, 406 + }; 407 + 408 + static 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 + 438 + static 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 450 #ifdef CONFIG_HOTPLUG_CPU 402 451 403 452 static int cps_cpu_disable(void) ··· 470 421 } 471 422 472 423 static unsigned cpu_death_sibling; 473 - static enum { 474 - CPU_DEATH_HALT, 475 - CPU_DEATH_POWER, 476 - } cpu_death; 424 + static enum cpu_death cpu_death; 477 425 478 426 void play_dead(void) 479 427 { 480 - unsigned int cpu, core, vpe_id; 428 + unsigned int cpu; 481 429 482 430 local_irq_disable(); 483 431 idle_task_exit(); 484 432 cpu = smp_processor_id(); 485 - core = cpu_core(&cpu_data[cpu]); 486 433 cpu_death = CPU_DEATH_POWER; 487 434 488 435 pr_debug("CPU%d going offline\n", cpu); ··· 501 456 /* This CPU has chosen its way out */ 502 457 (void)cpu_report_death(); 503 458 504 - if (cpu_death == CPU_DEATH_HALT) { 505 - vpe_id = cpu_vpe_id(&cpu_data[cpu]); 506 - 507 - pr_debug("Halting core %d VP%d\n", core, vpe_id); 508 - if (cpu_has_mipsmt) { 509 - /* Halt this TC */ 510 - write_c0_tchalt(TCHALT_H); 511 - instruction_hazard(); 512 - } else if (cpu_has_vp) { 513 - write_cpc_cl_vp_stop(1 << vpe_id); 514 - 515 - /* Ensure that the VP_STOP register is written */ 516 - wmb(); 517 - } 518 - } else { 519 - pr_debug("Gating power to core %d\n", core); 520 - /* Power down the core */ 521 - cps_pm_enter_state(CPS_PM_POWER_GATED); 522 - } 459 + cps_shutdown_this_cpu(cpu_death); 523 460 524 461 /* This should never be reached */ 525 462 panic("Failed to offline CPU %u", cpu); ··· 619 592 #ifdef CONFIG_HOTPLUG_CPU 620 593 .cpu_disable = cps_cpu_disable, 621 594 .cpu_die = cps_cpu_die, 595 + #endif 596 + #ifdef CONFIG_KEXEC 597 + .kexec_nonboot_cpu = cps_kexec_nonboot_cpu, 622 598 #endif 623 599 }; 624 600