diff options
author | James Hogan <james.hogan@imgtec.com> | 2013-06-28 15:03:05 +0100 |
---|---|---|
committer | James Hogan <james.hogan@imgtec.com> | 2013-07-02 11:03:52 +0100 |
commit | 9649814432faa9016952895684120942da0d8481 (patch) | |
tree | 3a4c5862e7dd092a030f7276ebb34c34d68090ce | |
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>
-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 @@ * published by the Free Software Foundation. */ #include <linux/atomic.h> +#include <linux/completion.h> #include <linux/delay.h> #include <linux/init.h> #include <linux/spinlock.h> @@ -62,6 +63,8 @@ static DEFINE_PER_CPU(struct ipi_data, ipi_data) = { static DEFINE_SPINLOCK(boot_lock); +static DECLARE_COMPLETION(cpu_running); + /* * "thread" is assumed to be a valid Meta hardware thread ID. */ @@ -235,20 +238,12 @@ int __cpuinit __cpu_up(unsigned int cpu, struct task_struct *idle) */ ret = boot_secondary(thread, idle); if (ret == 0) { - unsigned long timeout; - /* * CPU was successfully started, wait for it * to come online or time out. */ - timeout = jiffies + HZ; - while (time_before(jiffies, timeout)) { - if (cpu_online(cpu)) - break; - - udelay(10); - barrier(); - } + wait_for_completion_timeout(&cpu_running, + msecs_to_jiffies(1000)); if (!cpu_online(cpu)) ret = -EIO; @@ -391,6 +386,7 @@ asmlinkage void secondary_start_kernel(void) * OK, now it's safe to let the boot CPU continue */ set_cpu_online(cpu, true); + complete(&cpu_running); /* * Enable local interrupts. |