aboutsummaryrefslogtreecommitdiffstats
path: root/arch/s390/mm/pgtable.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/s390/mm/pgtable.c')
-rw-r--r--arch/s390/mm/pgtable.c23
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
72void rcu_table_freelist_finish(void) 72void 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;
81out:
82 put_cpu_var(rcu_table_freelist);
80} 83}
81 84
82static void smp_sync(void *arg) 85static 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();
162out:
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();
355out:
356 preempt_enable();
348} 357}
349 358
350/* 359/*