summaryrefslogtreecommitdiff
path: root/arch/arm/kernel
diff options
context:
space:
mode:
authorLinus Walleij <linus.walleij@linaro.org>2012-04-10 12:37:42 +0100
committerJason Liu <r64343@freescale.com>2012-07-20 13:38:02 +0800
commit451f23dfe1f9ae4915b1c0286fd806f684028da7 (patch)
tree65eb506cc6299c74cfbf3a0d7faeb2c409410cef /arch/arm/kernel
parent610483e25ffb22732f714411bd6432258115d85e (diff)
downloadlinux-451f23dfe1f9ae4915b1c0286fd806f684028da7.tar.gz
ARM: 7359/2: smp_twd: Only wait for reprogramming on active cpus
During booting of cpu1, there is a short window where cpu1 is online, but not active where cpu1 is occupied by waiting to become active. If cpu0 then decides to schedule something on cpu1 and wait for it to complete, before cpu0 has set cpu1 active, we have a deadlock. Typically it's this CPU frequency transition that happens at this time, so let's just not wait for it to happen, it will happen whenever the CPU eventually comes online instead. Cc: Peter Zijlstra <peterz@infradead.org> Cc: stable@kernel.org Signed-off-by: Jonas Aaberg <jonas.aberg@stericsson.com> Reviewed-by: Rickard Andersson <rickard.andersson@stericsson.com> Signed-off-by: Linus Walleij <linus.walleij@linaro.org> Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
Diffstat (limited to 'arch/arm/kernel')
-rw-r--r--arch/arm/kernel/smp_twd.c6
1 files changed, 5 insertions, 1 deletions
diff --git a/arch/arm/kernel/smp_twd.c b/arch/arm/kernel/smp_twd.c
index a5a2f45069d5..31deb5ae0061 100644
--- a/arch/arm/kernel/smp_twd.c
+++ b/arch/arm/kernel/smp_twd.c
@@ -115,10 +115,14 @@ static int twd_cpufreq_transition(struct notifier_block *nb,
* The twd clock events must be reprogrammed to account for the new
* frequency. The timer is local to a cpu, so cross-call to the
* changing cpu.
+ *
+ * Only wait for it to finish, if the cpu is active to avoid
+ * deadlock when cpu1 is spinning on while(!cpu_active(cpu1)) during
+ * booting of that cpu.
*/
if (state == CPUFREQ_POSTCHANGE || state == CPUFREQ_RESUMECHANGE)
smp_call_function_single(freqs->cpu, twd_update_frequency,
- NULL, 1);
+ NULL, cpu_active(freqs->cpu));
return NOTIFY_OK;
}