diff options
Diffstat (limited to 'arch/powerpc/kernel/smp.c')
-rw-r--r-- | arch/powerpc/kernel/smp.c | 45 |
1 files changed, 29 insertions, 16 deletions
diff --git a/arch/powerpc/kernel/smp.c b/arch/powerpc/kernel/smp.c index d577b71db37..d30f08fa029 100644 --- a/arch/powerpc/kernel/smp.c +++ b/arch/powerpc/kernel/smp.c @@ -152,11 +152,6 @@ static void stop_this_cpu(void *dummy) ; } -void smp_send_stop(void) -{ - smp_call_function(stop_this_cpu, NULL, 1, 0); -} - /* * Structure and data for smp_call_function(). This is designed to minimise * static memory requirements. It also looks cleaner. @@ -198,9 +193,6 @@ int smp_call_function_map(void (*func) (void *info), void *info, int nonatomic, int cpu; u64 timeout; - /* Can deadlock when called with interrupts disabled */ - WARN_ON(irqs_disabled()); - if (unlikely(smp_ops == NULL)) return ret; @@ -212,11 +204,6 @@ int smp_call_function_map(void (*func) (void *info), void *info, int nonatomic, atomic_set(&data.finished, 0); spin_lock(&call_lock); - /* Must grab online cpu count with preempt disabled, otherwise - * it can change. */ - num_cpus = num_online_cpus() - 1; - if (!num_cpus) - goto done; /* remove 'self' from the map */ if (cpu_isset(smp_processor_id(), map)) @@ -224,7 +211,9 @@ int smp_call_function_map(void (*func) (void *info), void *info, int nonatomic, /* sanity check the map, remove any non-online processors. */ cpus_and(map, map, cpu_online_map); - if (cpus_empty(map)) + + num_cpus = cpus_weight(map); + if (!num_cpus) goto done; call_data = &data; @@ -273,10 +262,19 @@ int smp_call_function_map(void (*func) (void *info), void *info, int nonatomic, return ret; } +static int __smp_call_function(void (*func)(void *info), void *info, + int nonatomic, int wait) +{ + return smp_call_function_map(func,info,nonatomic,wait,cpu_online_map); +} + int smp_call_function(void (*func) (void *info), void *info, int nonatomic, int wait) { - return smp_call_function_map(func,info,nonatomic,wait,cpu_online_map); + /* Can deadlock when called with interrupts disabled */ + WARN_ON(irqs_disabled()); + + return __smp_call_function(func, info, nonatomic, wait); } EXPORT_SYMBOL(smp_call_function); @@ -284,7 +282,10 @@ int smp_call_function_single(int cpu, void (*func) (void *info), void *info, int int wait) { cpumask_t map = CPU_MASK_NONE; - int ret = -EBUSY; + int ret = 0; + + /* Can deadlock when called with interrupts disabled */ + WARN_ON(irqs_disabled()); if (!cpu_online(cpu)) return -EINVAL; @@ -292,11 +293,21 @@ int smp_call_function_single(int cpu, void (*func) (void *info), void *info, int cpu_set(cpu, map); if (cpu != get_cpu()) ret = smp_call_function_map(func,info,nonatomic,wait,map); + else { + local_irq_disable(); + func(info); + local_irq_enable(); + } put_cpu(); return ret; } EXPORT_SYMBOL(smp_call_function_single); +void smp_send_stop(void) +{ + __smp_call_function(stop_this_cpu, NULL, 1, 0); +} + void smp_call_function_interrupt(void) { void (*func) (void *info); @@ -558,6 +569,8 @@ int __devinit start_secondary(void *unused) if (system_state > SYSTEM_BOOTING) snapshot_timebase(); + secondary_cpu_time_init(); + spin_lock(&call_lock); cpu_set(cpu, cpu_online_map); spin_unlock(&call_lock); |