riscv: don't stop itself in smp_send_stop
PATCH 1/1 riscv: don't stop itself in smp_send_stop
Only run ipi_stop on other cpus, not itself. Don't wait for ipi_stop to return, since it never does. Also, mark each cpu offline.
--- arch/riscv/kernel/smp.c | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-)
arch/riscv/kernel/smp.c +16 -1
@@ -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>
@@ -148,13 +149,27 @@ void arch_send_call_function_single_ipi(int cpu)static void ipi_stop (void *unused) { +set_cpu_online (smp_processor_id (), false);while (1 )wait_for_interrupt (); }void smp_send_stop (void ) { -on_each_cpu (ipi_stop,NULL ,1 ); +unsigned long timeout; +struct cpumask mask; + +cpumask_copy (&mask, cpu_online_mask); +cpumask_clear_cpu (smp_processor_id (), &mask); +on_each_cpu_mask (&mask, ipi_stop,NULL ,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\n" ); }void smp_send_reschedule (int cpu)
Signature · 12 lines
2.19.2 -- 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 25 lines · Andreas Schwab
Only run
ipi_stopon other cpus, not itself. Don't wait foripi_stopto return, since it never does. Also, mark each cpu offline.Signed-off-by Andreas Schwab <[email protected]>--- arch/riscv/kernel/smp.c | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-)arch/riscv/kernel/smp.c +2
-0@@ -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> @@ -148,13 +149,27 @@ void arch_send_call_function_single_ipi(int cpu)static void ipi_stop (void *unused) { +set_cpu_online (smp_processor_id (), false);
arch/riscv/kernel/smp.c void arch_send_call_function_single_ipi(int cpu) · line 161
Quoted 10 lines
arch/riscv/kernel/smp.c +3
-1while (1 )wait_for_interrupt (); }void smp_send_stop (void ) { -on_each_cpu (ipi_stop,NULL ,1 ); +unsigned long timeout; +struct cpumask mask; +
No need to do mask copy this, if num_online_cpus() == 1.
arch/riscv/kernel/smp.c void arch_send_call_function_single_ipi(int cpu) · line 164
Quoted 3 lines
arch/riscv/kernel/smp.c +3
-0+cpumask_copy (&mask, cpu_online_mask); +cpumask_clear_cpu (smp_processor_id (), &mask); +on_each_cpu_mask (&mask, ipi_stop,NULL ,0 );
The function header of on_each_cpu_mask says func should be non-blocking. Not sure if that's a hard requirement or not.
If it is, we can introduce an extra IPI_STOP in ipi_names and just send ipi. The receiving CPU can handle the IPI_STOP.
arch/riscv/kernel/smp.c void arch_send_call_function_single_ipi(int cpu) · line 172
Quoted 8 lines
arch/riscv/kernel/smp.c +8
-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\n" );
May be print the remaining online cpus so that we know which one failed ?
Regards,
Atish
arch/riscv/kernel/smp.c void arch_send_call_function_single_ipi(int cpu) · line 175
Quoted 4 lines
arch/riscv/kernel/smp.c +0
-0}void smp_send_reschedule (int cpu)
_______________________________________________
linux-riscv mailing list
[email protected]
http://lists.infradead.org/mailman/listinfo/linux-riscv
Quoted 6 lines · Atish Patra
arch/riscv/kernel/smp.c void arch_send_call_function_single_ipi(int cpu) · line 164
Quoted 3 lines
arch/riscv/kernel/smp.c +3
-0+cpumask_copy (&mask, cpu_online_mask); +cpumask_clear_cpu (smp_processor_id (), &mask); +on_each_cpu_mask (&mask, ipi_stop,NULL ,0 );The function header of
on_each_cpu_masksays func should be non-blocking. Not sure if that's a hard requirement or not.
What does that mean?
Quoted 10 lines
arch/riscv/kernel/smp.c void arch_send_call_function_single_ipi(int cpu) · line 172
Quoted 8 lines
arch/riscv/kernel/smp.c +8
-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\n" );May be print the remaining online cpus so that we know which one failed ?
I have copied that from arm. The only user of smp_send_stop is panic, which can cope with that, and the probability of that happening is very low anyway.
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
Quoted 11 lines · Andreas Schwab
Quoted 6 lines · Atish Patra
arch/riscv/kernel/smp.c void arch_send_call_function_single_ipi(int cpu) · line 164
Quoted 3 lines
arch/riscv/kernel/smp.c +3
-0+cpumask_copy (&mask, cpu_online_mask); +cpumask_clear_cpu (smp_processor_id (), &mask); +on_each_cpu_mask (&mask, ipi_stop,NULL ,0 );The function header of
on_each_cpu_masksays func should be non-blocking. Not sure if that's a hard requirement or not.What does that mean?
https://elixir.bootlin.com/linux/v4.20-rc6/source/kernel/smp.c#L617
Quoted 11 lines
Quoted 10 lines
arch/riscv/kernel/smp.c void arch_send_call_function_single_ipi(int cpu) · line 172
Quoted 8 lines
arch/riscv/kernel/smp.c +8
-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\n" );May be print the remaining online cpus so that we know which one failed ?
Quoted 4 lines
I have copied that from arm. The only user of
smp_send_stopis panic, which can cope with that, and the probability of that happening is very low anyway.
My suggestion was based on arm64 code. IMHO, it makes more sense to follow arm64 code than arm.
https://elixir.bootlin.com/linux/v4.20-rc6/source/arch/arm64/kernel/smp.c#L955
Regards,
Atish
Quoted 2 lines
Andreas.
_______________________________________________
linux-riscv mailing list
[email protected]
http://lists.infradead.org/mailman/listinfo/linux-riscv
PATCH v2 1/1 riscv: don't stop itself in smp_send_stop
In reply to Andreas SchwabAdd 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.
--- 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_warning ("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 90 lines · Andreas Schwab
Add
IPI_CPU_STOPmessage and use it insmp_send_stopto stop other cpus, but not itself. Mark cpu offline on reception ofIPI_CPU_STOP.Signed-off-by Andreas Schwab <[email protected]>--- arch/riscv/kernel/smp.c | 43 ++++++++++++++++++++++++++++++++++------- 1 file changed, 36 insertions(+), 7 deletions(-)arch/riscv/kernel/smp.c +29
-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 */
arch/riscv/kernel/smp.c void arch_send_call_function_single_ipi(int cpu) · line 189
Quoted 10 lines
arch/riscv/kernel/smp.c +7
-0+ timeout =USEC_PER_SEC ; +while (num_online_cpus () >1 && timeout--) +udelay (1 ); + +if (num_online_cpus () >1 ) +pr_warning ("SMP: failed to stop secondary CPUs %*pbl\n" , +cpumask_pr_args (cpu_online_mask)); }void smp_send_reschedule (int cpu)
Checkpatch warnings.
WARNING: space prohibited between function name and open parenthesis '(' #40: FILE: arch/riscv/kernel/smp.c:73:
+ set_cpu_online (smp_processor_id(), false);
WARNING: Prefer pr_warn(... to pr_warning(...
#100: FILE: arch/riscv/kernel/smp.c:185:
+ pr_warning("SMP: failed to stop secondary CPUs %*pbl\n",
Otherwise, Looks good to me.
Regards,
Atish
_______________________________________________
linux-riscv mailing list
[email protected]
http://lists.infradead.org/mailman/listinfo/linux-riscv
Quoted 107 lines · On Thu, 13 Dec 2018 15:27:36 PST (-0800), [email protected] wrote:
Quoted 90 lines · Andreas Schwab
Add
IPI_CPU_STOPmessage and use it insmp_send_stopto stop other cpus, but not itself. Mark cpu offline on reception ofIPI_CPU_STOP.Signed-off-by Andreas Schwab <[email protected]>--- arch/riscv/kernel/smp.c | 43 ++++++++++++++++++++++++++++++++++------- 1 file changed, 36 insertions(+), 7 deletions(-)arch/riscv/kernel/smp.c +29
-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 */ arch/riscv/kernel/smp.c void arch_send_call_function_single_ipi(int cpu) · line 189
Quoted 10 lines
arch/riscv/kernel/smp.c +7
-0+ timeout =USEC_PER_SEC ; +while (num_online_cpus () >1 && timeout--) +udelay (1 ); + +if (num_online_cpus () >1 ) +pr_warning ("SMP: failed to stop secondary CPUs %*pbl\n" , +cpumask_pr_args (cpu_online_mask)); }void smp_send_reschedule (int cpu)Checkpatch warnings.
WARNING: space prohibited between function name and open parenthesis '(' #40: FILE:arch/riscv/kernel/smp.c:73:
+set_cpu_online(smp_processor_id(), false);
Quoted 7 lines
WARNING: Prefer pr_warn(... to pr_warning(...
#100: FILE:arch/riscv/kernel/smp.c:185:
+ pr_warning("SMP: failed to stop secondary CPUs %*pbl\n",Otherwise, Looks good to me.
Reviewed-by Atish Patra <[email protected]>
I've fixed these up and added the patch to my fix queue, it should go up next week.
Thanks!
_______________________________________________
linux-riscv mailing list
[email protected]
http://lists.infradead.org/mailman/listinfo/linux-riscv