mirror of
				git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
				synced 2025-09-04 20:19:47 +08:00 
			
		
		
		
	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
This commit is contained in:
		
							parent
							
								
									62cac480f3
								
							
						
					
					
						commit
						1447864bee
					
				| @ -398,6 +398,55 @@ static void cps_smp_finish(void) | |||||||
| 	local_irq_enable(); | 	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 | #ifdef CONFIG_HOTPLUG_CPU | ||||||
| 
 | 
 | ||||||
| static int cps_cpu_disable(void) | static int cps_cpu_disable(void) | ||||||
| @ -421,19 +470,15 @@ static int cps_cpu_disable(void) | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static unsigned cpu_death_sibling; | static unsigned cpu_death_sibling; | ||||||
| static enum { | static enum cpu_death cpu_death; | ||||||
| 	CPU_DEATH_HALT, |  | ||||||
| 	CPU_DEATH_POWER, |  | ||||||
| } cpu_death; |  | ||||||
| 
 | 
 | ||||||
| void play_dead(void) | void play_dead(void) | ||||||
| { | { | ||||||
| 	unsigned int cpu, core, vpe_id; | 	unsigned int cpu; | ||||||
| 
 | 
 | ||||||
| 	local_irq_disable(); | 	local_irq_disable(); | ||||||
| 	idle_task_exit(); | 	idle_task_exit(); | ||||||
| 	cpu = smp_processor_id(); | 	cpu = smp_processor_id(); | ||||||
| 	core = cpu_core(&cpu_data[cpu]); |  | ||||||
| 	cpu_death = CPU_DEATH_POWER; | 	cpu_death = CPU_DEATH_POWER; | ||||||
| 
 | 
 | ||||||
| 	pr_debug("CPU%d going offline\n", cpu); | 	pr_debug("CPU%d going offline\n", cpu); | ||||||
| @ -456,25 +501,7 @@ void play_dead(void) | |||||||
| 	/* This CPU has chosen its way out */ | 	/* This CPU has chosen its way out */ | ||||||
| 	(void)cpu_report_death(); | 	(void)cpu_report_death(); | ||||||
| 
 | 
 | ||||||
| 	if (cpu_death == CPU_DEATH_HALT) { | 	cps_shutdown_this_cpu(cpu_death); | ||||||
| 		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); |  | ||||||
| 	} |  | ||||||
| 
 | 
 | ||||||
| 	/* This should never be reached */ | 	/* This should never be reached */ | ||||||
| 	panic("Failed to offline CPU %u", cpu); | 	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_disable		= cps_cpu_disable, | ||||||
| 	.cpu_die		= cps_cpu_die, | 	.cpu_die		= cps_cpu_die, | ||||||
| #endif | #endif | ||||||
|  | #ifdef CONFIG_KEXEC | ||||||
|  | 	.kexec_nonboot_cpu	= cps_kexec_nonboot_cpu, | ||||||
|  | #endif | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| bool mips_cps_smp_in_use(void) | bool mips_cps_smp_in_use(void) | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user
	 Dengcheng Zhu
						Dengcheng Zhu