Commit 85cb185dad54be308c3f3a6068dd7d418b8b53e4
Committed by
Martin Schwidefsky
1 parent
f455adcff1
Exists in
master
and in
39 other branches
[S390] smp: __smp_call_function_map vs cpu_online_map fix.
Both smp_call_function() and __smp_call_function_map() access cpu_online_map. Both functions run with preemption disabled which protects for cpus going offline. However new cpus can be added and therefore the cpu_online_map can change unexpectedly. So use the call_lock to protect against changes to the cpu_online_map in start_secondary() and all smp_call_* functions. Signed-off-by: Heiko Carstens <heiko.carstens@de.ibm.com> Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
Showing 1 changed file with 8 additions and 8 deletions Side-by-side Diff
arch/s390/kernel/smp.c
... | ... | @@ -139,7 +139,6 @@ |
139 | 139 | if (wait) |
140 | 140 | data.finished = CPU_MASK_NONE; |
141 | 141 | |
142 | - spin_lock(&call_lock); | |
143 | 142 | call_data = &data; |
144 | 143 | |
145 | 144 | for_each_cpu_mask(cpu, map) |
... | ... | @@ -151,7 +150,6 @@ |
151 | 150 | if (wait) |
152 | 151 | while (!cpus_equal(map, data.finished)) |
153 | 152 | cpu_relax(); |
154 | - spin_unlock(&call_lock); | |
155 | 153 | out: |
156 | 154 | if (local) { |
157 | 155 | local_irq_disable(); |
158 | 156 | |
... | ... | @@ -177,11 +175,11 @@ |
177 | 175 | { |
178 | 176 | cpumask_t map; |
179 | 177 | |
180 | - preempt_disable(); | |
178 | + spin_lock(&call_lock); | |
181 | 179 | map = cpu_online_map; |
182 | 180 | cpu_clear(smp_processor_id(), map); |
183 | 181 | __smp_call_function_map(func, info, nonatomic, wait, map); |
184 | - preempt_enable(); | |
182 | + spin_unlock(&call_lock); | |
185 | 183 | return 0; |
186 | 184 | } |
187 | 185 | EXPORT_SYMBOL(smp_call_function); |
188 | 186 | |
... | ... | @@ -202,10 +200,10 @@ |
202 | 200 | int smp_call_function_single(int cpu, void (*func) (void *info), void *info, |
203 | 201 | int nonatomic, int wait) |
204 | 202 | { |
205 | - preempt_disable(); | |
203 | + spin_lock(&call_lock); | |
206 | 204 | __smp_call_function_map(func, info, nonatomic, wait, |
207 | 205 | cpumask_of_cpu(cpu)); |
208 | - preempt_enable(); | |
206 | + spin_unlock(&call_lock); | |
209 | 207 | return 0; |
210 | 208 | } |
211 | 209 | EXPORT_SYMBOL(smp_call_function_single); |
212 | 210 | |
... | ... | @@ -228,10 +226,10 @@ |
228 | 226 | int smp_call_function_mask(cpumask_t mask, void (*func)(void *), void *info, |
229 | 227 | int wait) |
230 | 228 | { |
231 | - preempt_disable(); | |
229 | + spin_lock(&call_lock); | |
232 | 230 | cpu_clear(smp_processor_id(), mask); |
233 | 231 | __smp_call_function_map(func, info, 0, wait, mask); |
234 | - preempt_enable(); | |
232 | + spin_unlock(&call_lock); | |
235 | 233 | return 0; |
236 | 234 | } |
237 | 235 | EXPORT_SYMBOL(smp_call_function_mask); |
238 | 236 | |
... | ... | @@ -592,7 +590,9 @@ |
592 | 590 | pfault_init(); |
593 | 591 | |
594 | 592 | /* Mark this cpu as online */ |
593 | + spin_lock(&call_lock); | |
595 | 594 | cpu_set(smp_processor_id(), cpu_online_map); |
595 | + spin_unlock(&call_lock); | |
596 | 596 | /* Switch on interrupts */ |
597 | 597 | local_irq_enable(); |
598 | 598 | /* Print info about this processor */ |