diff options
Diffstat (limited to 'arch/sparc/kernel')
-rw-r--r-- | arch/sparc/kernel/smp_64.c | 41 |
1 files changed, 37 insertions, 4 deletions
diff --git a/arch/sparc/kernel/smp_64.c b/arch/sparc/kernel/smp_64.c index 537eb66abd06..ca64d2a86ec0 100644 --- a/arch/sparc/kernel/smp_64.c +++ b/arch/sparc/kernel/smp_64.c | |||
@@ -849,7 +849,7 @@ void smp_tsb_sync(struct mm_struct *mm) | |||
849 | } | 849 | } |
850 | 850 | ||
851 | extern unsigned long xcall_flush_tlb_mm; | 851 | extern unsigned long xcall_flush_tlb_mm; |
852 | extern unsigned long xcall_flush_tlb_pending; | 852 | extern unsigned long xcall_flush_tlb_page; |
853 | extern unsigned long xcall_flush_tlb_kernel_range; | 853 | extern unsigned long xcall_flush_tlb_kernel_range; |
854 | extern unsigned long xcall_fetch_glob_regs; | 854 | extern unsigned long xcall_fetch_glob_regs; |
855 | extern unsigned long xcall_fetch_glob_pmu; | 855 | extern unsigned long xcall_fetch_glob_pmu; |
@@ -1074,23 +1074,56 @@ local_flush_and_out: | |||
1074 | put_cpu(); | 1074 | put_cpu(); |
1075 | } | 1075 | } |
1076 | 1076 | ||
1077 | struct tlb_pending_info { | ||
1078 | unsigned long ctx; | ||
1079 | unsigned long nr; | ||
1080 | unsigned long *vaddrs; | ||
1081 | }; | ||
1082 | |||
1083 | static void tlb_pending_func(void *info) | ||
1084 | { | ||
1085 | struct tlb_pending_info *t = info; | ||
1086 | |||
1087 | __flush_tlb_pending(t->ctx, t->nr, t->vaddrs); | ||
1088 | } | ||
1089 | |||
1077 | void smp_flush_tlb_pending(struct mm_struct *mm, unsigned long nr, unsigned long *vaddrs) | 1090 | void smp_flush_tlb_pending(struct mm_struct *mm, unsigned long nr, unsigned long *vaddrs) |
1078 | { | 1091 | { |
1079 | u32 ctx = CTX_HWBITS(mm->context); | 1092 | u32 ctx = CTX_HWBITS(mm->context); |
1093 | struct tlb_pending_info info; | ||
1080 | int cpu = get_cpu(); | 1094 | int cpu = get_cpu(); |
1081 | 1095 | ||
1096 | info.ctx = ctx; | ||
1097 | info.nr = nr; | ||
1098 | info.vaddrs = vaddrs; | ||
1099 | |||
1082 | if (mm == current->mm && atomic_read(&mm->mm_users) == 1) | 1100 | if (mm == current->mm && atomic_read(&mm->mm_users) == 1) |
1083 | cpumask_copy(mm_cpumask(mm), cpumask_of(cpu)); | 1101 | cpumask_copy(mm_cpumask(mm), cpumask_of(cpu)); |
1084 | else | 1102 | else |
1085 | smp_cross_call_masked(&xcall_flush_tlb_pending, | 1103 | smp_call_function_many(mm_cpumask(mm), tlb_pending_func, |
1086 | ctx, nr, (unsigned long) vaddrs, | 1104 | &info, 1); |
1087 | mm_cpumask(mm)); | ||
1088 | 1105 | ||
1089 | __flush_tlb_pending(ctx, nr, vaddrs); | 1106 | __flush_tlb_pending(ctx, nr, vaddrs); |
1090 | 1107 | ||
1091 | put_cpu(); | 1108 | put_cpu(); |
1092 | } | 1109 | } |
1093 | 1110 | ||
1111 | void smp_flush_tlb_page(struct mm_struct *mm, unsigned long vaddr) | ||
1112 | { | ||
1113 | unsigned long context = CTX_HWBITS(mm->context); | ||
1114 | int cpu = get_cpu(); | ||
1115 | |||
1116 | if (mm == current->mm && atomic_read(&mm->mm_users) == 1) | ||
1117 | cpumask_copy(mm_cpumask(mm), cpumask_of(cpu)); | ||
1118 | else | ||
1119 | smp_cross_call_masked(&xcall_flush_tlb_page, | ||
1120 | context, vaddr, 0, | ||
1121 | mm_cpumask(mm)); | ||
1122 | __flush_tlb_page(context, vaddr); | ||
1123 | |||
1124 | put_cpu(); | ||
1125 | } | ||
1126 | |||
1094 | void smp_flush_tlb_kernel_range(unsigned long start, unsigned long end) | 1127 | void smp_flush_tlb_kernel_range(unsigned long start, unsigned long end) |
1095 | { | 1128 | { |
1096 | start &= PAGE_MASK; | 1129 | start &= PAGE_MASK; |