Commit 0d2808f3 authored by Matt Redfearn's avatar Matt Redfearn Committed by Ralf Baechle

MIPS: smp-cps: Add support for CPU hotplug of MIPSr6 processors

Introduce support for hotplug of Virtual Processors in MIPSr6 systems.
The method is simpler than the VPE parallel from the now-deprecated MT
ASE, it can now simply write the VP_STOP register with the mask of VPs
to halt, and use the VP_RUNNING register to determine when the VP has
halted.
Signed-off-by: default avatarMatt Redfearn <matt.redfearn@imgtec.com>
Reviewed-by: default avatarPaul Burton <paul.burton@imgtec.com>
Cc: Matt Redfearn <matt.redfearn@imgtec.com>
Cc: Qais Yousef <qais.yousef@imgtec.com>
Cc: linux-mips@linux-mips.org
Cc: linux-kernel@vger.kernel.org
Patchwork: https://patchwork.linux-mips.org/patch/13752/Signed-off-by: default avatarRalf Baechle <ralf@linux-mips.org>
parent 9736c615
...@@ -412,14 +412,16 @@ static enum { ...@@ -412,14 +412,16 @@ static enum {
void play_dead(void) void play_dead(void)
{ {
unsigned cpu, core; unsigned int cpu, core, vpe_id;
local_irq_disable(); local_irq_disable();
idle_task_exit(); idle_task_exit();
cpu = smp_processor_id(); cpu = smp_processor_id();
cpu_death = CPU_DEATH_POWER; cpu_death = CPU_DEATH_POWER;
if (cpu_has_mipsmt) { pr_debug("CPU%d going offline\n", cpu);
if (cpu_has_mipsmt || cpu_has_vp) {
core = cpu_data[cpu].core; core = cpu_data[cpu].core;
/* Look for another online VPE within the core */ /* Look for another online VPE within the core */
...@@ -440,10 +442,21 @@ void play_dead(void) ...@@ -440,10 +442,21 @@ void play_dead(void)
complete(&cpu_death_chosen); complete(&cpu_death_chosen);
if (cpu_death == CPU_DEATH_HALT) { 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 */ /* Halt this TC */
write_c0_tchalt(TCHALT_H); write_c0_tchalt(TCHALT_H);
instruction_hazard(); 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 { } else {
pr_debug("Gating power to core %d\n", core);
/* Power down the core */ /* Power down the core */
cps_pm_enter_state(CPS_PM_POWER_GATED); cps_pm_enter_state(CPS_PM_POWER_GATED);
} }
...@@ -470,6 +483,7 @@ static void wait_for_sibling_halt(void *ptr_cpu) ...@@ -470,6 +483,7 @@ static void wait_for_sibling_halt(void *ptr_cpu)
static void cps_cpu_die(unsigned int cpu) static void cps_cpu_die(unsigned int cpu)
{ {
unsigned core = cpu_data[cpu].core; unsigned core = cpu_data[cpu].core;
unsigned int vpe_id = cpu_vpe_id(&cpu_data[cpu]);
unsigned stat; unsigned stat;
int err; int err;
...@@ -498,10 +512,12 @@ static void cps_cpu_die(unsigned int cpu) ...@@ -498,10 +512,12 @@ static void cps_cpu_die(unsigned int cpu)
* in which case the CPC will refuse to power down the core. * in which case the CPC will refuse to power down the core.
*/ */
do { do {
mips_cm_lock_other(core, vpe_id);
mips_cpc_lock_other(core); mips_cpc_lock_other(core);
stat = read_cpc_co_stat_conf(); stat = read_cpc_co_stat_conf();
stat &= CPC_Cx_STAT_CONF_SEQSTATE_MSK; stat &= CPC_Cx_STAT_CONF_SEQSTATE_MSK;
mips_cpc_unlock_other(); mips_cpc_unlock_other();
mips_cm_unlock_other();
} while (stat != CPC_Cx_STAT_CONF_SEQSTATE_D0 && } while (stat != CPC_Cx_STAT_CONF_SEQSTATE_D0 &&
stat != CPC_Cx_STAT_CONF_SEQSTATE_D2 && stat != CPC_Cx_STAT_CONF_SEQSTATE_D2 &&
stat != CPC_Cx_STAT_CONF_SEQSTATE_U2); stat != CPC_Cx_STAT_CONF_SEQSTATE_U2);
...@@ -518,6 +534,12 @@ static void cps_cpu_die(unsigned int cpu) ...@@ -518,6 +534,12 @@ static void cps_cpu_die(unsigned int cpu)
(void *)(unsigned long)cpu, 1); (void *)(unsigned long)cpu, 1);
if (err) if (err)
panic("Failed to call remote sibling CPU\n"); panic("Failed to call remote sibling CPU\n");
} else if (cpu_has_vp) {
do {
mips_cm_lock_other(core, vpe_id);
stat = read_cpc_co_vp_running();
mips_cm_unlock_other();
} while (stat & (1 << vpe_id));
} }
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment