X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=arch%2Fia64%2Fkernel%2Fsmp.c;h=14134f2e3952ce56631850ae0670cad5f1aca62c;hb=a9fdee76789476a10f923f9fb3c84993042da3ac;hp=f75b517bd453d6c2e45992e8aa556450361e073f;hpb=8d40237c730b8be87c1b80a5d96b9c603fefa829;p=linux-2.6.git diff --git a/arch/ia64/kernel/smp.c b/arch/ia64/kernel/smp.c index f75b517bd..14134f2e3 100644 --- a/arch/ia64/kernel/smp.c +++ b/arch/ia64/kernel/smp.c @@ -29,9 +29,9 @@ #include #include #include -#include #include +#include #include #include #include @@ -62,7 +62,7 @@ struct call_data_struct { atomic_t finished; }; -static struct call_data_struct * call_data; +static volatile struct call_data_struct *call_data; #define IPI_CALL_FUNC 0 #define IPI_CPU_STOP 1 @@ -290,11 +290,11 @@ smp_call_function_single (int cpuid, void (*func) (void *info), void *info, int /* Wait for response */ while (atomic_read(&data.started) != cpus) - cpu_relax(); + barrier(); if (wait) while (atomic_read(&data.finished) != cpus) - cpu_relax(); + barrier(); call_data = NULL; spin_unlock_bh(&call_lock); @@ -313,10 +313,7 @@ EXPORT_SYMBOL(smp_call_function_single); * The function to run. This must be fast and non-blocking. * An arbitrary pointer to pass to the function. * currently unused. - * If 1, wait (atomically) until function has complete on other - * CPUs. If 0, wait for the IPI to be received by other CPUs, but - * do not wait for the completion of the IPI on each CPU. If -1, - * do not wait for other CPUs to receive IPI. + * If true, wait (atomically) until function has completed on other CPUs. * [RETURNS] 0 on success, else a negative status code. * * Does not return until remote CPUs are nearly ready to execute or are or have @@ -328,51 +325,36 @@ EXPORT_SYMBOL(smp_call_function_single); int smp_call_function (void (*func) (void *info), void *info, int nonatomic, int wait) { - static struct call_data_struct dumpdata; - struct call_data_struct normaldata; - struct call_data_struct *data; + struct call_data_struct data; int cpus = num_online_cpus()-1; if (!cpus) return 0; /* Can deadlock when called with interrupts disabled */ - /* Only if we are waiting for other CPU to ack */ - WARN_ON(irqs_disabled() && wait >= 0); + WARN_ON(irqs_disabled()); + + data.func = func; + data.info = info; + atomic_set(&data.started, 0); + data.wait = wait; + if (wait) + atomic_set(&data.finished, 0); spin_lock(&call_lock); - if (wait == -1) { - /* if another cpu beat us, they win! */ - if (dumpdata.func) { - spin_unlock(&call_lock); - return 0; - } - data = &dumpdata; - } else - data = &normaldata; - - data->func = func; - data->info = info; - atomic_set(&data->started, 0); - data->wait = wait > 0 ? wait : 0; - if (wait > 0) - atomic_set(&data->finished, 0); - - call_data = data; + + call_data = &data; mb(); /* ensure store to call_data precedes setting of IPI_CALL_FUNC */ send_IPI_allbutself(IPI_CALL_FUNC); /* Wait for response */ - if (wait >= 0) - while (atomic_read(&data->started) != cpus) - cpu_relax(); - - if (wait > 0) - while (atomic_read(&data->finished) != cpus) - cpu_relax(); + while (atomic_read(&data.started) != cpus) + barrier(); - if (wait >= 0) - call_data = NULL; + if (wait) + while (atomic_read(&data.finished) != cpus) + barrier(); + call_data = NULL; spin_unlock(&call_lock); return 0;