diff options
Diffstat (limited to 'arch/s390/mm/pgtable.c')
-rw-r--r-- | arch/s390/mm/pgtable.c | 23 |
1 files changed, 16 insertions, 7 deletions
diff --git a/arch/s390/mm/pgtable.c b/arch/s390/mm/pgtable.c index 14c6fae6fe6b..b09763fe5da1 100644 --- a/arch/s390/mm/pgtable.c +++ b/arch/s390/mm/pgtable.c | |||
@@ -71,12 +71,15 @@ static void rcu_table_freelist_callback(struct rcu_head *head) | |||
71 | 71 | ||
72 | void rcu_table_freelist_finish(void) | 72 | void rcu_table_freelist_finish(void) |
73 | { | 73 | { |
74 | struct rcu_table_freelist *batch = __get_cpu_var(rcu_table_freelist); | 74 | struct rcu_table_freelist **batchp = &get_cpu_var(rcu_table_freelist); |
75 | struct rcu_table_freelist *batch = *batchp; | ||
75 | 76 | ||
76 | if (!batch) | 77 | if (!batch) |
77 | return; | 78 | goto out; |
78 | call_rcu(&batch->rcu, rcu_table_freelist_callback); | 79 | call_rcu(&batch->rcu, rcu_table_freelist_callback); |
79 | __get_cpu_var(rcu_table_freelist) = NULL; | 80 | *batchp = NULL; |
81 | out: | ||
82 | put_cpu_var(rcu_table_freelist); | ||
80 | } | 83 | } |
81 | 84 | ||
82 | static void smp_sync(void *arg) | 85 | static void smp_sync(void *arg) |
@@ -141,20 +144,23 @@ void crst_table_free_rcu(struct mm_struct *mm, unsigned long *table) | |||
141 | { | 144 | { |
142 | struct rcu_table_freelist *batch; | 145 | struct rcu_table_freelist *batch; |
143 | 146 | ||
147 | preempt_disable(); | ||
144 | if (atomic_read(&mm->mm_users) < 2 && | 148 | if (atomic_read(&mm->mm_users) < 2 && |
145 | cpumask_equal(mm_cpumask(mm), cpumask_of(smp_processor_id()))) { | 149 | cpumask_equal(mm_cpumask(mm), cpumask_of(smp_processor_id()))) { |
146 | crst_table_free(mm, table); | 150 | crst_table_free(mm, table); |
147 | return; | 151 | goto out; |
148 | } | 152 | } |
149 | batch = rcu_table_freelist_get(mm); | 153 | batch = rcu_table_freelist_get(mm); |
150 | if (!batch) { | 154 | if (!batch) { |
151 | smp_call_function(smp_sync, NULL, 1); | 155 | smp_call_function(smp_sync, NULL, 1); |
152 | crst_table_free(mm, table); | 156 | crst_table_free(mm, table); |
153 | return; | 157 | goto out; |
154 | } | 158 | } |
155 | batch->table[--batch->crst_index] = table; | 159 | batch->table[--batch->crst_index] = table; |
156 | if (batch->pgt_index >= batch->crst_index) | 160 | if (batch->pgt_index >= batch->crst_index) |
157 | rcu_table_freelist_finish(); | 161 | rcu_table_freelist_finish(); |
162 | out: | ||
163 | preempt_enable(); | ||
158 | } | 164 | } |
159 | 165 | ||
160 | #ifdef CONFIG_64BIT | 166 | #ifdef CONFIG_64BIT |
@@ -323,16 +329,17 @@ void page_table_free_rcu(struct mm_struct *mm, unsigned long *table) | |||
323 | struct page *page; | 329 | struct page *page; |
324 | unsigned long bits; | 330 | unsigned long bits; |
325 | 331 | ||
332 | preempt_disable(); | ||
326 | if (atomic_read(&mm->mm_users) < 2 && | 333 | if (atomic_read(&mm->mm_users) < 2 && |
327 | cpumask_equal(mm_cpumask(mm), cpumask_of(smp_processor_id()))) { | 334 | cpumask_equal(mm_cpumask(mm), cpumask_of(smp_processor_id()))) { |
328 | page_table_free(mm, table); | 335 | page_table_free(mm, table); |
329 | return; | 336 | goto out; |
330 | } | 337 | } |
331 | batch = rcu_table_freelist_get(mm); | 338 | batch = rcu_table_freelist_get(mm); |
332 | if (!batch) { | 339 | if (!batch) { |
333 | smp_call_function(smp_sync, NULL, 1); | 340 | smp_call_function(smp_sync, NULL, 1); |
334 | page_table_free(mm, table); | 341 | page_table_free(mm, table); |
335 | return; | 342 | goto out; |
336 | } | 343 | } |
337 | bits = (mm->context.has_pgste) ? 3UL : 1UL; | 344 | bits = (mm->context.has_pgste) ? 3UL : 1UL; |
338 | bits <<= (__pa(table) & (PAGE_SIZE - 1)) / 256 / sizeof(unsigned long); | 345 | bits <<= (__pa(table) & (PAGE_SIZE - 1)) / 256 / sizeof(unsigned long); |
@@ -345,6 +352,8 @@ void page_table_free_rcu(struct mm_struct *mm, unsigned long *table) | |||
345 | batch->table[batch->pgt_index++] = table; | 352 | batch->table[batch->pgt_index++] = table; |
346 | if (batch->pgt_index >= batch->crst_index) | 353 | if (batch->pgt_index >= batch->crst_index) |
347 | rcu_table_freelist_finish(); | 354 | rcu_table_freelist_finish(); |
355 | out: | ||
356 | preempt_enable(); | ||
348 | } | 357 | } |
349 | 358 | ||
350 | /* | 359 | /* |