aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/kernel/smp_64.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/x86/kernel/smp_64.c')
-rw-r--r--arch/x86/kernel/smp_64.c57
1 files changed, 16 insertions, 41 deletions
diff --git a/arch/x86/kernel/smp_64.c b/arch/x86/kernel/smp_64.c
index aa2edb7f3a51..e4494e829dfa 100644
--- a/arch/x86/kernel/smp_64.c
+++ b/arch/x86/kernel/smp_64.c
@@ -354,26 +354,30 @@ static void __smp_call_function(void (*func) (void *info), void *info,
354} 354}
355 355
356 356
357/* 357int native_smp_call_function_mask(cpumask_t mask,
358 * this function sends a 'generic call function' IPI to all other CPU 358 void (*func)(void *), void *info,
359 * of the system defined in the mask. 359 int wait)
360 */
361static int __smp_call_function_mask(cpumask_t mask,
362 void (*func)(void *), void *info,
363 int wait)
364{ 360{
365 struct call_data_struct data; 361 struct call_data_struct data;
366 cpumask_t allbutself; 362 cpumask_t allbutself;
367 int cpus; 363 int cpus;
368 364
365 /* Can deadlock when called with interrupts disabled */
366 WARN_ON(irqs_disabled());
367
368 /* Holding any lock stops cpus from going down. */
369 spin_lock(&call_lock);
370
369 allbutself = cpu_online_map; 371 allbutself = cpu_online_map;
370 cpu_clear(smp_processor_id(), allbutself); 372 cpu_clear(smp_processor_id(), allbutself);
371 373
372 cpus_and(mask, mask, allbutself); 374 cpus_and(mask, mask, allbutself);
373 cpus = cpus_weight(mask); 375 cpus = cpus_weight(mask);
374 376
375 if (!cpus) 377 if (!cpus) {
378 spin_unlock(&call_lock);
376 return 0; 379 return 0;
380 }
377 381
378 data.func = func; 382 data.func = func;
379 data.info = info; 383 data.info = info;
@@ -395,43 +399,14 @@ static int __smp_call_function_mask(cpumask_t mask,
395 while (atomic_read(&data.started) != cpus) 399 while (atomic_read(&data.started) != cpus)
396 cpu_relax(); 400 cpu_relax();
397 401
398 if (!wait) 402 if (wait)
399 return 0; 403 while (atomic_read(&data.finished) != cpus)
404 cpu_relax();
400 405
401 while (atomic_read(&data.finished) != cpus) 406 spin_unlock(&call_lock);
402 cpu_relax();
403 407
404 return 0; 408 return 0;
405} 409}
406/**
407 * smp_call_function_mask(): Run a function on a set of other CPUs.
408 * @mask: The set of cpus to run on. Must not include the current cpu.
409 * @func: The function to run. This must be fast and non-blocking.
410 * @info: An arbitrary pointer to pass to the function.
411 * @wait: If true, wait (atomically) until function has completed on other CPUs.
412 *
413 * Returns 0 on success, else a negative status code.
414 *
415 * If @wait is true, then returns once @func has returned; otherwise
416 * it returns just before the target cpu calls @func.
417 *
418 * You must not call this function with disabled interrupts or from a
419 * hardware interrupt handler or from a bottom half handler.
420 */
421int native_smp_call_function_mask(cpumask_t mask,
422 void (*func)(void *), void *info,
423 int wait)
424{
425 int ret;
426
427 /* Can deadlock when called with interrupts disabled */
428 WARN_ON(irqs_disabled());
429
430 spin_lock(&call_lock);
431 ret = __smp_call_function_mask(mask, func, info, wait);
432 spin_unlock(&call_lock);
433 return ret;
434}
435 410
436static void stop_this_cpu(void *dummy) 411static void stop_this_cpu(void *dummy)
437{ 412{