diff options
Diffstat (limited to 'arch/powerpc/kernel/smp.c')
-rw-r--r-- | arch/powerpc/kernel/smp.c | 34 |
1 files changed, 18 insertions, 16 deletions
diff --git a/arch/powerpc/kernel/smp.c b/arch/powerpc/kernel/smp.c index 22f1ef1b3100..d577b71db375 100644 --- a/arch/powerpc/kernel/smp.c +++ b/arch/powerpc/kernel/smp.c @@ -201,13 +201,6 @@ int smp_call_function_map(void (*func) (void *info), void *info, int nonatomic, /* Can deadlock when called with interrupts disabled */ WARN_ON(irqs_disabled()); - /* remove 'self' from the map */ - if (cpu_isset(smp_processor_id(), map)) - cpu_clear(smp_processor_id(), map); - - /* sanity check the map, remove any non-online processors. */ - cpus_and(map, map, cpu_online_map); - if (unlikely(smp_ops == NULL)) return ret; @@ -222,10 +215,17 @@ int smp_call_function_map(void (*func) (void *info), void *info, int nonatomic, /* Must grab online cpu count with preempt disabled, otherwise * it can change. */ num_cpus = num_online_cpus() - 1; - if (!num_cpus || cpus_empty(map)) { - ret = 0; - goto out; - } + if (!num_cpus) + goto done; + + /* remove 'self' from the map */ + if (cpu_isset(smp_processor_id(), map)) + cpu_clear(smp_processor_id(), map); + + /* sanity check the map, remove any non-online processors. */ + cpus_and(map, map, cpu_online_map); + if (cpus_empty(map)) + goto done; call_data = &data; smp_wmb(); @@ -263,6 +263,7 @@ int smp_call_function_map(void (*func) (void *info), void *info, int nonatomic, } } + done: ret = 0; out: @@ -282,16 +283,17 @@ EXPORT_SYMBOL(smp_call_function); int smp_call_function_single(int cpu, void (*func) (void *info), void *info, int nonatomic, int wait) { - cpumask_t map=CPU_MASK_NONE; + cpumask_t map = CPU_MASK_NONE; + int ret = -EBUSY; if (!cpu_online(cpu)) return -EINVAL; - if (cpu == smp_processor_id()) - return -EBUSY; - cpu_set(cpu, map); - return smp_call_function_map(func,info,nonatomic,wait,map); + if (cpu != get_cpu()) + ret = smp_call_function_map(func,info,nonatomic,wait,map); + put_cpu(); + return ret; } EXPORT_SYMBOL(smp_call_function_single); |