mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 10:40:15 +02:00 
			
		
		
		
	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: Matt Redfearn <matt.redfearn@imgtec.com> Reviewed-by: Paul 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: Ralf Baechle <ralf@linux-mips.org>
This commit is contained in:
		
							parent
							
								
									9736c6152e
								
							
						
					
					
						commit
						0d2808f338
					
				
					 1 changed files with 27 additions and 5 deletions
				
			
		| 
						 | 
				
			
			@ -412,14 +412,16 @@ static enum {
 | 
			
		|||
 | 
			
		||||
void play_dead(void)
 | 
			
		||||
{
 | 
			
		||||
	unsigned cpu, core;
 | 
			
		||||
	unsigned int cpu, core, vpe_id;
 | 
			
		||||
 | 
			
		||||
	local_irq_disable();
 | 
			
		||||
	idle_task_exit();
 | 
			
		||||
	cpu = smp_processor_id();
 | 
			
		||||
	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;
 | 
			
		||||
 | 
			
		||||
		/* Look for another online VPE within the core */
 | 
			
		||||
| 
						 | 
				
			
			@ -440,10 +442,21 @@ void play_dead(void)
 | 
			
		|||
	complete(&cpu_death_chosen);
 | 
			
		||||
 | 
			
		||||
	if (cpu_death == CPU_DEATH_HALT) {
 | 
			
		||||
		/* Halt this TC */
 | 
			
		||||
		write_c0_tchalt(TCHALT_H);
 | 
			
		||||
		instruction_hazard();
 | 
			
		||||
		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);
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			@ -470,6 +483,7 @@ static void wait_for_sibling_halt(void *ptr_cpu)
 | 
			
		|||
static void cps_cpu_die(unsigned int cpu)
 | 
			
		||||
{
 | 
			
		||||
	unsigned core = cpu_data[cpu].core;
 | 
			
		||||
	unsigned int vpe_id = cpu_vpe_id(&cpu_data[cpu]);
 | 
			
		||||
	unsigned stat;
 | 
			
		||||
	int err;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -498,10 +512,12 @@ static void cps_cpu_die(unsigned int cpu)
 | 
			
		|||
		 * in which case the CPC will refuse to power down the core.
 | 
			
		||||
		 */
 | 
			
		||||
		do {
 | 
			
		||||
			mips_cm_lock_other(core, vpe_id);
 | 
			
		||||
			mips_cpc_lock_other(core);
 | 
			
		||||
			stat = read_cpc_co_stat_conf();
 | 
			
		||||
			stat &= CPC_Cx_STAT_CONF_SEQSTATE_MSK;
 | 
			
		||||
			mips_cpc_unlock_other();
 | 
			
		||||
			mips_cm_unlock_other();
 | 
			
		||||
		} while (stat != CPC_Cx_STAT_CONF_SEQSTATE_D0 &&
 | 
			
		||||
			 stat != CPC_Cx_STAT_CONF_SEQSTATE_D2 &&
 | 
			
		||||
			 stat != CPC_Cx_STAT_CONF_SEQSTATE_U2);
 | 
			
		||||
| 
						 | 
				
			
			@ -518,6 +534,12 @@ static void cps_cpu_die(unsigned int cpu)
 | 
			
		|||
					       (void *)(unsigned long)cpu, 1);
 | 
			
		||||
		if (err)
 | 
			
		||||
			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));
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in a new issue