diff options
author | James Hogan <james.hogan@imgtec.com> | 2013-06-28 10:03:05 -0400 |
---|---|---|
committer | James Hogan <james.hogan@imgtec.com> | 2013-07-02 06:03:52 -0400 |
commit | 9649814432faa9016952895684120942da0d8481 (patch) | |
tree | 3a4c5862e7dd092a030f7276ebb34c34d68090ce /arch | |
parent | 234c7f1ac109ad1af4ae410463d03ccebf3d6657 (diff) |
metag: smp: don't spin waiting for CPU to start
Use a completion to block until a secondary CPU has started up, like ARM
do, instead of a loop of udelays.
On Meta, SMP is really SMT, with each "CPU" being a different hardware
thread on the same Meta processor core, so as well as being more
efficient and latency friendly, using a completion prevents the bogomips
of the secondary CPU from being drastically skewed every time by the
execution of the tight in-cache udelay loop on the other CPU.
Signed-off-by: James Hogan <james.hogan@imgtec.com>
Acked-by: Thomas Gleixner <tglx@linutronix.de>
Reviewed-by: "Srivatsa S. Bhat" <srivatsa.bhat@linux.vnet.ibm.com>
Diffstat (limited to 'arch')
-rw-r--r-- | arch/metag/kernel/smp.c | 16 |
1 files changed, 6 insertions, 10 deletions
diff --git a/arch/metag/kernel/smp.c b/arch/metag/kernel/smp.c index 09979f203a4d..e413875cf6d2 100644 --- a/arch/metag/kernel/smp.c +++ b/arch/metag/kernel/smp.c | |||
@@ -8,6 +8,7 @@ | |||
8 | * published by the Free Software Foundation. | 8 | * published by the Free Software Foundation. |
9 | */ | 9 | */ |
10 | #include <linux/atomic.h> | 10 | #include <linux/atomic.h> |
11 | #include <linux/completion.h> | ||
11 | #include <linux/delay.h> | 12 | #include <linux/delay.h> |
12 | #include <linux/init.h> | 13 | #include <linux/init.h> |
13 | #include <linux/spinlock.h> | 14 | #include <linux/spinlock.h> |
@@ -62,6 +63,8 @@ static DEFINE_PER_CPU(struct ipi_data, ipi_data) = { | |||
62 | 63 | ||
63 | static DEFINE_SPINLOCK(boot_lock); | 64 | static DEFINE_SPINLOCK(boot_lock); |
64 | 65 | ||
66 | static DECLARE_COMPLETION(cpu_running); | ||
67 | |||
65 | /* | 68 | /* |
66 | * "thread" is assumed to be a valid Meta hardware thread ID. | 69 | * "thread" is assumed to be a valid Meta hardware thread ID. |
67 | */ | 70 | */ |
@@ -235,20 +238,12 @@ int __cpuinit __cpu_up(unsigned int cpu, struct task_struct *idle) | |||
235 | */ | 238 | */ |
236 | ret = boot_secondary(thread, idle); | 239 | ret = boot_secondary(thread, idle); |
237 | if (ret == 0) { | 240 | if (ret == 0) { |
238 | unsigned long timeout; | ||
239 | |||
240 | /* | 241 | /* |
241 | * CPU was successfully started, wait for it | 242 | * CPU was successfully started, wait for it |
242 | * to come online or time out. | 243 | * to come online or time out. |
243 | */ | 244 | */ |
244 | timeout = jiffies + HZ; | 245 | wait_for_completion_timeout(&cpu_running, |
245 | while (time_before(jiffies, timeout)) { | 246 | msecs_to_jiffies(1000)); |
246 | if (cpu_online(cpu)) | ||
247 | break; | ||
248 | |||
249 | udelay(10); | ||
250 | barrier(); | ||
251 | } | ||
252 | 247 | ||
253 | if (!cpu_online(cpu)) | 248 | if (!cpu_online(cpu)) |
254 | ret = -EIO; | 249 | ret = -EIO; |
@@ -391,6 +386,7 @@ asmlinkage void secondary_start_kernel(void) | |||
391 | * OK, now it's safe to let the boot CPU continue | 386 | * OK, now it's safe to let the boot CPU continue |
392 | */ | 387 | */ |
393 | set_cpu_online(cpu, true); | 388 | set_cpu_online(cpu, true); |
389 | complete(&cpu_running); | ||
394 | 390 | ||
395 | /* | 391 | /* |
396 | * Enable local interrupts. | 392 | * Enable local interrupts. |