diff options
Diffstat (limited to 'arch/loongarch/kernel/smp.c')
| -rw-r--r-- | arch/loongarch/kernel/smp.c | 122 | 
1 files changed, 69 insertions, 53 deletions
diff --git a/arch/loongarch/kernel/smp.c b/arch/loongarch/kernel/smp.c index 2b49d30eb7c0..aabee0b280fe 100644 --- a/arch/loongarch/kernel/smp.c +++ b/arch/loongarch/kernel/smp.c @@ -88,6 +88,73 @@ void show_ipi_list(struct seq_file *p, int prec)  	}  } +static inline void set_cpu_core_map(int cpu) +{ +	int i; + +	cpumask_set_cpu(cpu, &cpu_core_setup_map); + +	for_each_cpu(i, &cpu_core_setup_map) { +		if (cpu_data[cpu].package == cpu_data[i].package) { +			cpumask_set_cpu(i, &cpu_core_map[cpu]); +			cpumask_set_cpu(cpu, &cpu_core_map[i]); +		} +	} +} + +static inline void set_cpu_sibling_map(int cpu) +{ +	int i; + +	cpumask_set_cpu(cpu, &cpu_sibling_setup_map); + +	for_each_cpu(i, &cpu_sibling_setup_map) { +		if (cpus_are_siblings(cpu, i)) { +			cpumask_set_cpu(i, &cpu_sibling_map[cpu]); +			cpumask_set_cpu(cpu, &cpu_sibling_map[i]); +		} +	} +} + +static inline void clear_cpu_sibling_map(int cpu) +{ +	int i; + +	for_each_cpu(i, &cpu_sibling_setup_map) { +		if (cpus_are_siblings(cpu, i)) { +			cpumask_clear_cpu(i, &cpu_sibling_map[cpu]); +			cpumask_clear_cpu(cpu, &cpu_sibling_map[i]); +		} +	} + +	cpumask_clear_cpu(cpu, &cpu_sibling_setup_map); +} + +/* + * Calculate a new cpu_foreign_map mask whenever a + * new cpu appears or disappears. + */ +void calculate_cpu_foreign_map(void) +{ +	int i, k, core_present; +	cpumask_t temp_foreign_map; + +	/* Re-calculate the mask */ +	cpumask_clear(&temp_foreign_map); +	for_each_online_cpu(i) { +		core_present = 0; +		for_each_cpu(k, &temp_foreign_map) +			if (cpus_are_siblings(i, k)) +				core_present = 1; +		if (!core_present) +			cpumask_set_cpu(i, &temp_foreign_map); +	} + +	for_each_online_cpu(i) +		cpumask_andnot(&cpu_foreign_map[i], +			       &temp_foreign_map, &cpu_sibling_map[i]); +} +  /* Send mailbox buffer via Mail_Send */  static void csr_mail_send(uint64_t data, int cpu, int mailbox)  { @@ -303,6 +370,7 @@ int loongson_cpu_disable(void)  	numa_remove_cpu(cpu);  #endif  	set_cpu_online(cpu, false); +	clear_cpu_sibling_map(cpu);  	calculate_cpu_foreign_map();  	local_irq_save(flags);  	irq_migrate_all_off_this_cpu(); @@ -337,6 +405,7 @@ void __noreturn arch_cpu_idle_dead(void)  		addr = iocsr_read64(LOONGARCH_IOCSR_MBUF0);  	} while (addr == 0); +	local_irq_disable();  	init_fn = (void *)TO_CACHE(addr);  	iocsr_write32(0xffffffff, LOONGARCH_IOCSR_IPI_CLEAR); @@ -379,59 +448,6 @@ static int __init ipi_pm_init(void)  core_initcall(ipi_pm_init);  #endif -static inline void set_cpu_sibling_map(int cpu) -{ -	int i; - -	cpumask_set_cpu(cpu, &cpu_sibling_setup_map); - -	for_each_cpu(i, &cpu_sibling_setup_map) { -		if (cpus_are_siblings(cpu, i)) { -			cpumask_set_cpu(i, &cpu_sibling_map[cpu]); -			cpumask_set_cpu(cpu, &cpu_sibling_map[i]); -		} -	} -} - -static inline void set_cpu_core_map(int cpu) -{ -	int i; - -	cpumask_set_cpu(cpu, &cpu_core_setup_map); - -	for_each_cpu(i, &cpu_core_setup_map) { -		if (cpu_data[cpu].package == cpu_data[i].package) { -			cpumask_set_cpu(i, &cpu_core_map[cpu]); -			cpumask_set_cpu(cpu, &cpu_core_map[i]); -		} -	} -} - -/* - * Calculate a new cpu_foreign_map mask whenever a - * new cpu appears or disappears. - */ -void calculate_cpu_foreign_map(void) -{ -	int i, k, core_present; -	cpumask_t temp_foreign_map; - -	/* Re-calculate the mask */ -	cpumask_clear(&temp_foreign_map); -	for_each_online_cpu(i) { -		core_present = 0; -		for_each_cpu(k, &temp_foreign_map) -			if (cpus_are_siblings(i, k)) -				core_present = 1; -		if (!core_present) -			cpumask_set_cpu(i, &temp_foreign_map); -	} - -	for_each_online_cpu(i) -		cpumask_andnot(&cpu_foreign_map[i], -			       &temp_foreign_map, &cpu_sibling_map[i]); -} -  /* Preload SMP state for boot cpu */  void smp_prepare_boot_cpu(void)  {  |