summaryrefslogtreecommitdiffstats
path: root/arch/arm/kernel/smp.c
diff options
context:
space:
mode:
authorRussell King <rmk+kernel@arm.linux.org.uk>2010-12-02 10:53:54 +0100
committerRussell King <rmk+kernel@arm.linux.org.uk>2010-12-20 16:08:26 +0100
commit28e18293cf0f8d23a0950d7b1d2212d11af494dc (patch)
treefbd27f23bbd1b85ef7b06cf4b5f733f46a929044 /arch/arm/kernel/smp.c
parentARM: SMP: use more sane register allocation for __fixup_smp_on_up (diff)
downloadlinux-28e18293cf0f8d23a0950d7b1d2212d11af494dc.tar.xz
linux-28e18293cf0f8d23a0950d7b1d2212d11af494dc.zip
ARM: SMP: ensure smp_send_stop() waits for CPUs to stop
Wait for CPUs to indicate that they've stopped, after sending the stop IPI, rather than blindly continuing on and hoping that they've stopped in time. Print a warning if we fail to stop the other CPUs. Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
Diffstat (limited to 'arch/arm/kernel/smp.c')
-rw-r--r--arch/arm/kernel/smp.c18
1 files changed, 15 insertions, 3 deletions
diff --git a/arch/arm/kernel/smp.c b/arch/arm/kernel/smp.c
index 1de3e13a42a1..64f2d198c764 100644
--- a/arch/arm/kernel/smp.c
+++ b/arch/arm/kernel/smp.c
@@ -575,10 +575,22 @@ void smp_send_reschedule(int cpu)
void smp_send_stop(void)
{
- cpumask_t mask = cpu_online_map;
- cpu_clear(smp_processor_id(), mask);
- if (!cpus_empty(mask))
+ unsigned long timeout;
+
+ if (num_online_cpus() > 1) {
+ cpumask_t mask = cpu_online_map;
+ cpu_clear(smp_processor_id(), mask);
+
smp_cross_call(&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\n");
}
/*