diff mbox series

riscv: don't stop itself in smp_send_stop

Message ID mvmbm67etfg.fsf@suse.de (mailing list archive)
State New, archived
Headers show
Series riscv: don't stop itself in smp_send_stop | expand

Commit Message

Andreas Schwab Nov. 29, 2018, 4:32 p.m. UTC
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.

Signed-off-by: Andreas Schwab <schwab@suse.de>
---
 arch/riscv/kernel/smp.c | 17 ++++++++++++++++-
 1 file changed, 16 insertions(+), 1 deletion(-)

Comments

Atish Patra Nov. 29, 2018, 6:52 p.m. UTC | #1
On 11/29/18 8:32 AM, Andreas Schwab wrote:
> 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.
> 
> Signed-off-by: Andreas Schwab <schwab@suse.de>
> ---
>   arch/riscv/kernel/smp.c | 17 ++++++++++++++++-
>   1 file changed, 16 insertions(+), 1 deletion(-)
> 
> diff --git a/arch/riscv/kernel/smp.c b/arch/riscv/kernel/smp.c
> index 57b1383e5e..5c6bb5fe5a 100644
> --- a/arch/riscv/kernel/smp.c
> +++ b/arch/riscv/kernel/smp.c
> @@ -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;
> +

No need to do mask copy this, if num_online_cpus() == 1.

> +	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.

> +
> +	/* 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
>   }
>   
>   void smp_send_reschedule(int cpu)
>
Andreas Schwab Dec. 10, 2018, 10:58 a.m. UTC | #2
On Nov 29 2018, Atish Patra <atish.patra@wdc.com> wrote:

>> +	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.

What does that mean?

>> +
>> +	/* 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.
Atish Patra Dec. 11, 2018, 12:06 a.m. UTC | #3
On 12/10/18 2:58 AM, Andreas Schwab wrote:
> On Nov 29 2018, Atish Patra <atish.patra@wdc.com> wrote:
> 
>>> +	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.
> 
> What does that mean?
> 

https://elixir.bootlin.com/linux/v4.20-rc6/source/kernel/smp.c#L617

>>> +
>>> +	/* 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.
> 

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
> Andreas.
>
diff mbox series

Patch

diff --git a/arch/riscv/kernel/smp.c b/arch/riscv/kernel/smp.c
index 57b1383e5e..5c6bb5fe5a 100644
--- a/arch/riscv/kernel/smp.c
+++ b/arch/riscv/kernel/smp.c
@@ -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)