diff options
Diffstat (limited to 'arch/ia64/mm/tlb.c')
-rw-r--r-- | arch/ia64/mm/tlb.c | 23 |
1 files changed, 14 insertions, 9 deletions
diff --git a/arch/ia64/mm/tlb.c b/arch/ia64/mm/tlb.c index 464557e4ed82..c79a9b96d02b 100644 --- a/arch/ia64/mm/tlb.c +++ b/arch/ia64/mm/tlb.c | |||
@@ -77,19 +77,25 @@ wrap_mmu_context (struct mm_struct *mm) | |||
77 | /* can't call flush_tlb_all() here because of race condition with O(1) scheduler [EF] */ | 77 | /* can't call flush_tlb_all() here because of race condition with O(1) scheduler [EF] */ |
78 | { | 78 | { |
79 | int cpu = get_cpu(); /* prevent preemption/migration */ | 79 | int cpu = get_cpu(); /* prevent preemption/migration */ |
80 | for (i = 0; i < NR_CPUS; ++i) | 80 | for_each_online_cpu(i) { |
81 | if (cpu_online(i) && (i != cpu)) | 81 | if (i != cpu) |
82 | per_cpu(ia64_need_tlb_flush, i) = 1; | 82 | per_cpu(ia64_need_tlb_flush, i) = 1; |
83 | } | ||
83 | put_cpu(); | 84 | put_cpu(); |
84 | } | 85 | } |
85 | local_flush_tlb_all(); | 86 | local_flush_tlb_all(); |
86 | } | 87 | } |
87 | 88 | ||
88 | void | 89 | void |
89 | ia64_global_tlb_purge (unsigned long start, unsigned long end, unsigned long nbits) | 90 | ia64_global_tlb_purge (struct mm_struct *mm, unsigned long start, unsigned long end, unsigned long nbits) |
90 | { | 91 | { |
91 | static DEFINE_SPINLOCK(ptcg_lock); | 92 | static DEFINE_SPINLOCK(ptcg_lock); |
92 | 93 | ||
94 | if (mm != current->active_mm) { | ||
95 | flush_tlb_all(); | ||
96 | return; | ||
97 | } | ||
98 | |||
93 | /* HW requires global serialization of ptc.ga. */ | 99 | /* HW requires global serialization of ptc.ga. */ |
94 | spin_lock(&ptcg_lock); | 100 | spin_lock(&ptcg_lock); |
95 | { | 101 | { |
@@ -135,15 +141,12 @@ flush_tlb_range (struct vm_area_struct *vma, unsigned long start, unsigned long | |||
135 | unsigned long size = end - start; | 141 | unsigned long size = end - start; |
136 | unsigned long nbits; | 142 | unsigned long nbits; |
137 | 143 | ||
144 | #ifndef CONFIG_SMP | ||
138 | if (mm != current->active_mm) { | 145 | if (mm != current->active_mm) { |
139 | /* this does happen, but perhaps it's not worth optimizing for? */ | ||
140 | #ifdef CONFIG_SMP | ||
141 | flush_tlb_all(); | ||
142 | #else | ||
143 | mm->context = 0; | 146 | mm->context = 0; |
144 | #endif | ||
145 | return; | 147 | return; |
146 | } | 148 | } |
149 | #endif | ||
147 | 150 | ||
148 | nbits = ia64_fls(size + 0xfff); | 151 | nbits = ia64_fls(size + 0xfff); |
149 | while (unlikely (((1UL << nbits) & purge.mask) == 0) && (nbits < purge.max_bits)) | 152 | while (unlikely (((1UL << nbits) & purge.mask) == 0) && (nbits < purge.max_bits)) |
@@ -153,12 +156,14 @@ flush_tlb_range (struct vm_area_struct *vma, unsigned long start, unsigned long | |||
153 | start &= ~((1UL << nbits) - 1); | 156 | start &= ~((1UL << nbits) - 1); |
154 | 157 | ||
155 | # ifdef CONFIG_SMP | 158 | # ifdef CONFIG_SMP |
156 | platform_global_tlb_purge(start, end, nbits); | 159 | platform_global_tlb_purge(mm, start, end, nbits); |
157 | # else | 160 | # else |
161 | preempt_disable(); | ||
158 | do { | 162 | do { |
159 | ia64_ptcl(start, (nbits<<2)); | 163 | ia64_ptcl(start, (nbits<<2)); |
160 | start += (1UL << nbits); | 164 | start += (1UL << nbits); |
161 | } while (start < end); | 165 | } while (start < end); |
166 | preempt_enable(); | ||
162 | # endif | 167 | # endif |
163 | 168 | ||
164 | ia64_srlz_i(); /* srlz.i implies srlz.d */ | 169 | ia64_srlz_i(); /* srlz.i implies srlz.d */ |