riscv: don't stop itself in smp_send_stop
PATCH v3 1/1 riscv: don't stop itself in smp_send_stop
Add IPI_CPU_STOP message and use it in smp_send_stop to stop other cpus, but not itself. Mark cpu offline on reception of IPI_CPU_STOP.
---
v3: minor fixes
--- arch/riscv/kernel/smp.c | 43 ++++++++++++++++++++++++++++++++++------- 1 file changed, 36 insertions(+), 7 deletions(-)
arch/riscv/kernel/smp.c +36 -7
@@ -23,6 +23,7 @@#include <linux/smp.h> #include <linux/sched.h> #include <linux/seq_file.h> +#include <linux/delay.h> #include <asm/sbi.h> #include <asm/tlbflush.h>
@@ -31,6 +32,7 @@enum ipi_message_type {IPI_RESCHEDULE ,IPI_CALL_FUNC , +IPI_CPU_STOP ,IPI_MAX };
@@ -66,6 +68,13 @@ int setup_profiling_timer(unsigned int multiplier)return -EINVAL ; } +static void ipi_stop (void ) +{ +set_cpu_online (smp_processor_id (), false); +while (1 ) +wait_for_interrupt (); +} +void riscv_software_interrupt (void ) {unsigned long *pending_ipis = &ipi_data[smp_processor_id ()].bits;
@@ -94,6 +103,11 @@ void riscv_software_interrupt(void)generic_smp_call_function_interrupt (); } +if (ops & (1 <<IPI_CPU_STOP )) { + stats[IPI_CPU_STOP ]++; +ipi_stop (); + } +BUG_ON ((ops >>IPI_MAX ) !=0 );/* Order data access and bit testing. */
@@ -121,6 +135,7 @@ send_ipi_message(const struct cpumask *to_whom, enum ipi_message_type operation)static const char *const ipi_names[] = { [IPI_RESCHEDULE ] ="Rescheduling interrupts" , [IPI_CALL_FUNC ] ="Function call interrupts" , + [IPI_CPU_STOP ] ="CPU stop interrupts" , };void show_ipi_stats (struct seq_file *p,int prec)
@@ -146,15 +161,29 @@ void arch_send_call_function_single_ipi(int cpu)send_ipi_message (cpumask_of (cpu),IPI_CALL_FUNC ); } -static void ipi_stop (void *unused) -{ -while (1 ) -wait_for_interrupt (); -} -void smp_send_stop (void ) { -on_each_cpu (ipi_stop,NULL ,1 ); +unsigned long timeout; + +if (num_online_cpus () >1 ) { +cpumask_t mask; + +cpumask_copy (&mask, cpu_online_mask); +cpumask_clear_cpu (smp_processor_id (), &mask); + +if (system_state <=SYSTEM_RUNNING ) +pr_crit ("SMP: stopping secondary CPUs\n" ); +send_ipi_message (&mask,IPI_CPU_STOP ); + } + +/* Wait up to one second for other CPUs to stop */ + timeout =USEC_PER_SEC ; +while (num_online_cpus () >1 && timeout--) +udelay (1 ); + +if (num_online_cpus () >1 ) +pr_warn ("SMP: failed to stop secondary CPUs %*pbl\n" , +cpumask_pr_args (cpu_online_mask)); }void smp_send_reschedule (int cpu)
Signature · 12 lines
2.20.0 -- Andreas Schwab, SUSE Labs, [email protected] GPG Key fingerprint = 0196 BAD8 1CE9 1970 F4BE 1748 E4D4 88E3 0EEA B9D7 "And now for something completely different." _______________________________________________ linux-riscv mailing list [email protected] http://lists.infradead.org/mailman/listinfo/linux-riscv
Quoted 14 lines
void
smp_send_stop(void)
{arch/riscv/kernel/smp.c +11
-1-on_each_cpu (ipi_stop,NULL ,1 ); +unsigned long timeout; + +if (num_online_cpus () >1 ) { +cpumask_t mask; + +cpumask_copy (&mask, cpu_online_mask); +cpumask_clear_cpu (smp_processor_id (), &mask); + +if (system_state <=SYSTEM_RUNNING ) +pr_crit ("SMP: stopping secondary CPUs\n" ); +send_ipi_message (&mask,IPI_CPU_STOP );
arch/riscv/kernel/smp.c void arch_send_call_function_single_ipi(int cpu) · line 186
Quoted 10 lines
arch/riscv/kernel/smp.c +10
-0+ } + +/* Wait up to one second for other CPUs to stop */ + timeout =USEC_PER_SEC ; +while (num_online_cpus () >1 && timeout--) +udelay (1 ); + +if (num_online_cpus () >1 ) +pr_warn ("SMP: failed to stop secondary CPUs %*pbl\n" , +cpumask_pr_args (cpu_online_mask));
Given that this function doesn't mark the current CPU as not offline it seems we could just exit early for num_online_cpus() == 1?
_______________________________________________
linux-riscv mailing list
[email protected]
http://lists.infradead.org/mailman/listinfo/linux-riscv
Quoted 19 lines · Christoph Hellwig
Quoted 19 lines
void
smp_send_stop(void)
{arch/riscv/kernel/smp.c +16
-1-on_each_cpu (ipi_stop,NULL ,1 ); +unsigned long timeout; + +if (num_online_cpus () >1 ) { +cpumask_t mask; + +cpumask_copy (&mask, cpu_online_mask); +cpumask_clear_cpu (smp_processor_id (), &mask); + +if (system_state <=SYSTEM_RUNNING ) +pr_crit ("SMP: stopping secondary CPUs\n" ); +send_ipi_message (&mask,IPI_CPU_STOP ); + } + +/* Wait up to one second for other CPUs to stop */ + timeout =USEC_PER_SEC ; +while (num_online_cpus () >1 && timeout--)
Quoted 8 lines
arch/riscv/kernel/smp.c void arch_send_call_function_single_ipi(int cpu) · line 186
Quoted 5 lines
arch/riscv/kernel/smp.c +5
-0+udelay (1 ); + +if (num_online_cpus () >1 ) +pr_warn ("SMP: failed to stop secondary CPUs %*pbl\n" , +cpumask_pr_args (cpu_online_mask));Given that this function doesn't mark the current CPU as not offline it seems we could just exit early for
num_online_cpus()== 1?
So much for copying existing implementations.
The only difference it would make is two less calls to num_online_cpus on a single cpu system. Hardly worth it, IMHO.
Andreas.
Signature · 8 lines
Andreas Schwab, SUSE Labs, [email protected] GPG Key fingerprint = 0196 BAD8 1CE9 1970 F4BE 1748 E4D4 88E3 0EEA B9D7 "And now for something completely different." _______________________________________________ linux-riscv mailing list [email protected] http://lists.infradead.org/mailman/listinfo/linux-riscv