diff options
Diffstat (limited to 'arch/sparc64/kernel/smp.c')
-rw-r--r-- | arch/sparc64/kernel/smp.c | 87 |
1 files changed, 17 insertions, 70 deletions
diff --git a/arch/sparc64/kernel/smp.c b/arch/sparc64/kernel/smp.c index c099d96f1239..7cf72b4bb108 100644 --- a/arch/sparc64/kernel/smp.c +++ b/arch/sparc64/kernel/smp.c | |||
@@ -788,89 +788,36 @@ static void smp_start_sync_tick_client(int cpu) | |||
788 | 0, 0, 0, mask); | 788 | 0, 0, 0, mask); |
789 | } | 789 | } |
790 | 790 | ||
791 | /* Send cross call to all processors except self. */ | ||
792 | #define smp_cross_call(func, ctx, data1, data2) \ | ||
793 | smp_cross_call_masked(func, ctx, data1, data2, cpu_online_map) | ||
794 | |||
795 | struct call_data_struct { | ||
796 | void (*func) (void *info); | ||
797 | void *info; | ||
798 | atomic_t finished; | ||
799 | int wait; | ||
800 | }; | ||
801 | |||
802 | static struct call_data_struct *call_data; | ||
803 | |||
804 | extern unsigned long xcall_call_function; | 791 | extern unsigned long xcall_call_function; |
805 | 792 | ||
806 | /** | 793 | void arch_send_call_function_ipi(cpumask_t mask) |
807 | * smp_call_function(): Run a function on all other CPUs. | ||
808 | * @func: The function to run. This must be fast and non-blocking. | ||
809 | * @info: An arbitrary pointer to pass to the function. | ||
810 | * @wait: If true, wait (atomically) until function has completed on other CPUs. | ||
811 | * | ||
812 | * Returns 0 on success, else a negative status code. Does not return until | ||
813 | * remote CPUs are nearly ready to execute <<func>> or are or have executed. | ||
814 | * | ||
815 | * You must not call this function with disabled interrupts or from a | ||
816 | * hardware interrupt handler or from a bottom half handler. | ||
817 | */ | ||
818 | static int sparc64_smp_call_function_mask(void (*func)(void *info), void *info, | ||
819 | int wait, cpumask_t mask) | ||
820 | { | 794 | { |
821 | struct call_data_struct data; | ||
822 | int cpus; | ||
823 | |||
824 | /* Can deadlock when called with interrupts disabled */ | ||
825 | WARN_ON(irqs_disabled()); | ||
826 | |||
827 | data.func = func; | ||
828 | data.info = info; | ||
829 | atomic_set(&data.finished, 0); | ||
830 | data.wait = wait; | ||
831 | |||
832 | spin_lock(&call_lock); | ||
833 | |||
834 | cpu_clear(smp_processor_id(), mask); | ||
835 | cpus = cpus_weight(mask); | ||
836 | if (!cpus) | ||
837 | goto out_unlock; | ||
838 | |||
839 | call_data = &data; | ||
840 | mb(); | ||
841 | |||
842 | smp_cross_call_masked(&xcall_call_function, 0, 0, 0, mask); | 795 | smp_cross_call_masked(&xcall_call_function, 0, 0, 0, mask); |
796 | } | ||
843 | 797 | ||
844 | /* Wait for response */ | 798 | extern unsigned long xcall_call_function_single; |
845 | while (atomic_read(&data.finished) != cpus) | ||
846 | cpu_relax(); | ||
847 | 799 | ||
848 | out_unlock: | 800 | void arch_send_call_function_single_ipi(int cpu) |
849 | spin_unlock(&call_lock); | 801 | { |
802 | cpumask_t mask = cpumask_of_cpu(cpu); | ||
850 | 803 | ||
851 | return 0; | 804 | smp_cross_call_masked(&xcall_call_function_single, 0, 0, 0, mask); |
852 | } | 805 | } |
853 | 806 | ||
854 | int smp_call_function(void (*func)(void *info), void *info, int wait) | 807 | /* Send cross call to all processors except self. */ |
855 | { | 808 | #define smp_cross_call(func, ctx, data1, data2) \ |
856 | return sparc64_smp_call_function_mask(func, info, wait, cpu_online_map); | 809 | smp_cross_call_masked(func, ctx, data1, data2, cpu_online_map) |
857 | } | ||
858 | 810 | ||
859 | void smp_call_function_client(int irq, struct pt_regs *regs) | 811 | void smp_call_function_client(int irq, struct pt_regs *regs) |
860 | { | 812 | { |
861 | void (*func) (void *info) = call_data->func; | 813 | clear_softint(1 << irq); |
862 | void *info = call_data->info; | 814 | generic_smp_call_function_interrupt(); |
815 | } | ||
863 | 816 | ||
817 | void smp_call_function_single_client(int irq, struct pt_regs *regs) | ||
818 | { | ||
864 | clear_softint(1 << irq); | 819 | clear_softint(1 << irq); |
865 | if (call_data->wait) { | 820 | generic_smp_call_function_single_interrupt(); |
866 | /* let initiator proceed only after completion */ | ||
867 | func(info); | ||
868 | atomic_inc(&call_data->finished); | ||
869 | } else { | ||
870 | /* let initiator proceed after getting data */ | ||
871 | atomic_inc(&call_data->finished); | ||
872 | func(info); | ||
873 | } | ||
874 | } | 821 | } |
875 | 822 | ||
876 | static void tsb_sync(void *info) | 823 | static void tsb_sync(void *info) |
@@ -890,7 +837,7 @@ static void tsb_sync(void *info) | |||
890 | 837 | ||
891 | void smp_tsb_sync(struct mm_struct *mm) | 838 | void smp_tsb_sync(struct mm_struct *mm) |
892 | { | 839 | { |
893 | sparc64_smp_call_function_mask(tsb_sync, mm, 1, mm->cpu_vm_mask); | 840 | smp_call_function_mask(mm->cpu_vm_mask, tsb_sync, mm, 1); |
894 | } | 841 | } |
895 | 842 | ||
896 | extern unsigned long xcall_flush_tlb_mm; | 843 | extern unsigned long xcall_flush_tlb_mm; |