aboutsummaryrefslogtreecommitdiffstats
path: root/arch/mips/kernel/smp.c
diff options
context:
space:
mode:
authorMatt Redfearn <matt.redfearn@imgtec.com>2016-09-22 12:15:47 -0400
committerRalf Baechle <ralf@linux-mips.org>2016-09-24 19:43:52 -0400
commit8f46cca1e6c06a058374816887059bcc017b382f (patch)
tree0208125c0c12aac63194f8864e79cd26a39c4e2f /arch/mips/kernel/smp.c
parent7e956304eb8a285304a78582e4537e72c6365f20 (diff)
MIPS: SMP: Fix possibility of deadlock when bringing CPUs online
This patch fixes the possibility of a deadlock when bringing up secondary CPUs. The deadlock occurs because the set_cpu_online() is called before synchronise_count_slave(). This can cause a deadlock if the boot CPU, having scheduled another thread, attempts to send an IPI to the secondary CPU, which it sees has been marked online. The secondary is blocked in synchronise_count_slave() waiting for the boot CPU to enter synchronise_count_master(), but the boot cpu is blocked in smp_call_function_many() waiting for the secondary to respond to it's IPI request. Fix this by marking the CPU online in cpu_callin_map and synchronising counters before declaring the CPU online and calculating the maps for IPIs. Signed-off-by: Matt Redfearn <matt.redfearn@imgtec.com> Reported-by: Justin Chen <justinpopo6@gmail.com> Tested-by: Justin Chen <justinpopo6@gmail.com> Cc: Florian Fainelli <f.fainelli@gmail.com> Cc: stable@vger.kernel.org # v4.1+ Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/14302/ Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
Diffstat (limited to 'arch/mips/kernel/smp.c')
-rw-r--r--arch/mips/kernel/smp.c7
1 files changed, 3 insertions, 4 deletions
diff --git a/arch/mips/kernel/smp.c b/arch/mips/kernel/smp.c
index f95f094f36e4..b0baf48951fa 100644
--- a/arch/mips/kernel/smp.c
+++ b/arch/mips/kernel/smp.c
@@ -322,6 +322,9 @@ asmlinkage void start_secondary(void)
322 cpumask_set_cpu(cpu, &cpu_coherent_mask); 322 cpumask_set_cpu(cpu, &cpu_coherent_mask);
323 notify_cpu_starting(cpu); 323 notify_cpu_starting(cpu);
324 324
325 cpumask_set_cpu(cpu, &cpu_callin_map);
326 synchronise_count_slave(cpu);
327
325 set_cpu_online(cpu, true); 328 set_cpu_online(cpu, true);
326 329
327 set_cpu_sibling_map(cpu); 330 set_cpu_sibling_map(cpu);
@@ -329,10 +332,6 @@ asmlinkage void start_secondary(void)
329 332
330 calculate_cpu_foreign_map(); 333 calculate_cpu_foreign_map();
331 334
332 cpumask_set_cpu(cpu, &cpu_callin_map);
333
334 synchronise_count_slave(cpu);
335
336 /* 335 /*
337 * irq will be enabled in ->smp_finish(), enabling it too early 336 * irq will be enabled in ->smp_finish(), enabling it too early
338 * is dangerous. 337 * is dangerous.