diff options
| -rw-r--r-- | arch/i386/kernel/smp.c | 66 |
1 files changed, 66 insertions, 0 deletions
diff --git a/arch/i386/kernel/smp.c b/arch/i386/kernel/smp.c index c10789d7a9d3..304243ed7a30 100644 --- a/arch/i386/kernel/smp.c +++ b/arch/i386/kernel/smp.c | |||
| @@ -634,3 +634,69 @@ fastcall void smp_call_function_interrupt(struct pt_regs *regs) | |||
| 634 | } | 634 | } |
| 635 | } | 635 | } |
| 636 | 636 | ||
| 637 | /* | ||
| 638 | * this function sends a 'generic call function' IPI to one other CPU | ||
| 639 | * in the system. | ||
| 640 | * | ||
| 641 | * cpu is a standard Linux logical CPU number. | ||
| 642 | */ | ||
| 643 | static void | ||
| 644 | __smp_call_function_single(int cpu, void (*func) (void *info), void *info, | ||
| 645 | int nonatomic, int wait) | ||
| 646 | { | ||
| 647 | struct call_data_struct data; | ||
| 648 | int cpus = 1; | ||
| 649 | |||
| 650 | data.func = func; | ||
| 651 | data.info = info; | ||
| 652 | atomic_set(&data.started, 0); | ||
| 653 | data.wait = wait; | ||
| 654 | if (wait) | ||
| 655 | atomic_set(&data.finished, 0); | ||
| 656 | |||
| 657 | call_data = &data; | ||
| 658 | wmb(); | ||
| 659 | /* Send a message to all other CPUs and wait for them to respond */ | ||
| 660 | send_IPI_mask(cpumask_of_cpu(cpu), CALL_FUNCTION_VECTOR); | ||
| 661 | |||
| 662 | /* Wait for response */ | ||
| 663 | while (atomic_read(&data.started) != cpus) | ||
| 664 | cpu_relax(); | ||
| 665 | |||
| 666 | if (!wait) | ||
| 667 | return; | ||
| 668 | |||
| 669 | while (atomic_read(&data.finished) != cpus) | ||
| 670 | cpu_relax(); | ||
| 671 | } | ||
| 672 | |||
| 673 | /* | ||
| 674 | * smp_call_function_single - Run a function on another CPU | ||
| 675 | * @func: The function to run. This must be fast and non-blocking. | ||
| 676 | * @info: An arbitrary pointer to pass to the function. | ||
| 677 | * @nonatomic: Currently unused. | ||
| 678 | * @wait: If true, wait until function has completed on other CPUs. | ||
| 679 | * | ||
| 680 | * Retrurns 0 on success, else a negative status code. | ||
| 681 | * | ||
| 682 | * Does not return until the remote CPU is nearly ready to execute <func> | ||
| 683 | * or is or has executed. | ||
| 684 | */ | ||
| 685 | |||
| 686 | int smp_call_function_single (int cpu, void (*func) (void *info), void *info, | ||
| 687 | int nonatomic, int wait) | ||
| 688 | { | ||
| 689 | /* prevent preemption and reschedule on another processor */ | ||
| 690 | int me = get_cpu(); | ||
| 691 | if (cpu == me) { | ||
| 692 | WARN_ON(1); | ||
| 693 | put_cpu(); | ||
| 694 | return -EBUSY; | ||
| 695 | } | ||
| 696 | spin_lock_bh(&call_lock); | ||
| 697 | __smp_call_function_single(cpu, func, info, nonatomic, wait); | ||
| 698 | spin_unlock_bh(&call_lock); | ||
| 699 | put_cpu(); | ||
| 700 | return 0; | ||
| 701 | } | ||
| 702 | EXPORT_SYMBOL(smp_call_function_single); | ||
