diff options
Diffstat (limited to 'arch/riscv/kernel/smp.c')
| -rw-r--r-- | arch/riscv/kernel/smp.c | 61 | 
1 files changed, 37 insertions, 24 deletions
diff --git a/arch/riscv/kernel/smp.c b/arch/riscv/kernel/smp.c index 5a9834503a2f..b18cd6c8e8fb 100644 --- a/arch/riscv/kernel/smp.c +++ b/arch/riscv/kernel/smp.c @@ -56,6 +56,7 @@ void riscv_cpuid_to_hartid_mask(const struct cpumask *in, struct cpumask *out)  {  	int cpu; +	cpumask_clear(out);  	for_each_cpu(cpu, in)  		cpumask_set_cpu(cpuid_to_hartid_map(cpu), out);  } @@ -78,13 +79,42 @@ static void ipi_stop(void)  		wait_for_interrupt();  } +static void send_ipi_mask(const struct cpumask *mask, enum ipi_message_type op) +{ +	struct cpumask hartid_mask; +	int cpu; + +	smp_mb__before_atomic(); +	for_each_cpu(cpu, mask) +		set_bit(op, &ipi_data[cpu].bits); +	smp_mb__after_atomic(); + +	riscv_cpuid_to_hartid_mask(mask, &hartid_mask); +	sbi_send_ipi(cpumask_bits(&hartid_mask)); +} + +static void send_ipi_single(int cpu, enum ipi_message_type op) +{ +	int hartid = cpuid_to_hartid_map(cpu); + +	smp_mb__before_atomic(); +	set_bit(op, &ipi_data[cpu].bits); +	smp_mb__after_atomic(); + +	sbi_send_ipi(cpumask_bits(cpumask_of(hartid))); +} + +static inline void clear_ipi(void) +{ +	csr_clear(CSR_SIP, SIE_SSIE); +} +  void riscv_software_interrupt(void)  {  	unsigned long *pending_ipis = &ipi_data[smp_processor_id()].bits;  	unsigned long *stats = ipi_data[smp_processor_id()].stats; -	/* Clear pending IPI */ -	csr_clear(CSR_SIP, SIE_SSIE); +	clear_ipi();  	while (true) {  		unsigned long ops; @@ -118,23 +148,6 @@ void riscv_software_interrupt(void)  	}  } -static void -send_ipi_message(const struct cpumask *to_whom, enum ipi_message_type operation) -{ -	int cpuid, hartid; -	struct cpumask hartid_mask; - -	cpumask_clear(&hartid_mask); -	mb(); -	for_each_cpu(cpuid, to_whom) { -		set_bit(operation, &ipi_data[cpuid].bits); -		hartid = cpuid_to_hartid_map(cpuid); -		cpumask_set_cpu(hartid, &hartid_mask); -	} -	mb(); -	sbi_send_ipi(cpumask_bits(&hartid_mask)); -} -  static const char * const ipi_names[] = {  	[IPI_RESCHEDULE]	= "Rescheduling interrupts",  	[IPI_CALL_FUNC]		= "Function call interrupts", @@ -156,12 +169,12 @@ void show_ipi_stats(struct seq_file *p, int prec)  void arch_send_call_function_ipi_mask(struct cpumask *mask)  { -	send_ipi_message(mask, IPI_CALL_FUNC); +	send_ipi_mask(mask, IPI_CALL_FUNC);  }  void arch_send_call_function_single_ipi(int cpu)  { -	send_ipi_message(cpumask_of(cpu), IPI_CALL_FUNC); +	send_ipi_single(cpu, IPI_CALL_FUNC);  }  void smp_send_stop(void) @@ -176,7 +189,7 @@ void smp_send_stop(void)  		if (system_state <= SYSTEM_RUNNING)  			pr_crit("SMP: stopping secondary CPUs\n"); -		send_ipi_message(&mask, IPI_CPU_STOP); +		send_ipi_mask(&mask, IPI_CPU_STOP);  	}  	/* Wait up to one second for other CPUs to stop */ @@ -191,6 +204,6 @@ void smp_send_stop(void)  void smp_send_reschedule(int cpu)  { -	send_ipi_message(cpumask_of(cpu), IPI_RESCHEDULE); +	send_ipi_single(cpu, IPI_RESCHEDULE);  } - +EXPORT_SYMBOL_GPL(smp_send_reschedule);  |