aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/smp.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/smp.c')
-rw-r--r--kernel/smp.c72
1 files changed, 60 insertions, 12 deletions
diff --git a/kernel/smp.c b/kernel/smp.c
index 462c785ca1ee..f362a8553777 100644
--- a/kernel/smp.c
+++ b/kernel/smp.c
@@ -33,7 +33,7 @@ struct call_single_queue {
33 spinlock_t lock; 33 spinlock_t lock;
34}; 34};
35 35
36void __cpuinit init_call_single_data(void) 36static int __cpuinit init_call_single_data(void)
37{ 37{
38 int i; 38 int i;
39 39
@@ -43,7 +43,9 @@ void __cpuinit init_call_single_data(void)
43 spin_lock_init(&q->lock); 43 spin_lock_init(&q->lock);
44 INIT_LIST_HEAD(&q->list); 44 INIT_LIST_HEAD(&q->list);
45 } 45 }
46 return 0;
46} 47}
48early_initcall(init_call_single_data);
47 49
48static void csd_flag_wait(struct call_single_data *data) 50static void csd_flag_wait(struct call_single_data *data)
49{ 51{
@@ -133,7 +135,8 @@ void generic_smp_call_function_interrupt(void)
133 */ 135 */
134 smp_wmb(); 136 smp_wmb();
135 data->csd.flags &= ~CSD_FLAG_WAIT; 137 data->csd.flags &= ~CSD_FLAG_WAIT;
136 } else 138 }
139 if (data->csd.flags & CSD_FLAG_ALLOC)
137 call_rcu(&data->rcu_head, rcu_free_call_data); 140 call_rcu(&data->rcu_head, rcu_free_call_data);
138 } 141 }
139 rcu_read_unlock(); 142 rcu_read_unlock();
@@ -207,8 +210,10 @@ int smp_call_function_single(int cpu, void (*func) (void *info), void *info,
207{ 210{
208 struct call_single_data d; 211 struct call_single_data d;
209 unsigned long flags; 212 unsigned long flags;
210 /* prevent preemption and reschedule on another processor */ 213 /* prevent preemption and reschedule on another processor,
214 as well as CPU removal */
211 int me = get_cpu(); 215 int me = get_cpu();
216 int err = 0;
212 217
213 /* Can deadlock when called with interrupts disabled */ 218 /* Can deadlock when called with interrupts disabled */
214 WARN_ON(irqs_disabled()); 219 WARN_ON(irqs_disabled());
@@ -217,7 +222,7 @@ int smp_call_function_single(int cpu, void (*func) (void *info), void *info,
217 local_irq_save(flags); 222 local_irq_save(flags);
218 func(info); 223 func(info);
219 local_irq_restore(flags); 224 local_irq_restore(flags);
220 } else { 225 } else if ((unsigned)cpu < NR_CPUS && cpu_online(cpu)) {
221 struct call_single_data *data = NULL; 226 struct call_single_data *data = NULL;
222 227
223 if (!wait) { 228 if (!wait) {
@@ -233,10 +238,12 @@ int smp_call_function_single(int cpu, void (*func) (void *info), void *info,
233 data->func = func; 238 data->func = func;
234 data->info = info; 239 data->info = info;
235 generic_exec_single(cpu, data); 240 generic_exec_single(cpu, data);
241 } else {
242 err = -ENXIO; /* CPU not online */
236 } 243 }
237 244
238 put_cpu(); 245 put_cpu();
239 return 0; 246 return err;
240} 247}
241EXPORT_SYMBOL(smp_call_function_single); 248EXPORT_SYMBOL(smp_call_function_single);
242 249
@@ -258,6 +265,42 @@ void __smp_call_function_single(int cpu, struct call_single_data *data)
258 generic_exec_single(cpu, data); 265 generic_exec_single(cpu, data);
259} 266}
260 267
268/* Dummy function */
269static void quiesce_dummy(void *unused)
270{
271}
272
273/*
274 * Ensure stack based data used in call function mask is safe to free.
275 *
276 * This is needed by smp_call_function_mask when using on-stack data, because
277 * a single call function queue is shared by all CPUs, and any CPU may pick up
278 * the data item on the queue at any time before it is deleted. So we need to
279 * ensure that all CPUs have transitioned through a quiescent state after
280 * this call.
281 *
282 * This is a very slow function, implemented by sending synchronous IPIs to
283 * all possible CPUs. For this reason, we have to alloc data rather than use
284 * stack based data even in the case of synchronous calls. The stack based
285 * data is then just used for deadlock/oom fallback which will be very rare.
286 *
287 * If a faster scheme can be made, we could go back to preferring stack based
288 * data -- the data allocation/free is non-zero cost.
289 */
290static void smp_call_function_mask_quiesce_stack(cpumask_t mask)
291{
292 struct call_single_data data;
293 int cpu;
294
295 data.func = quiesce_dummy;
296 data.info = NULL;
297
298 for_each_cpu_mask(cpu, mask) {
299 data.flags = CSD_FLAG_WAIT;
300 generic_exec_single(cpu, &data);
301 }
302}
303
261/** 304/**
262 * smp_call_function_mask(): Run a function on a set of other CPUs. 305 * smp_call_function_mask(): Run a function on a set of other CPUs.
263 * @mask: The set of cpus to run on. 306 * @mask: The set of cpus to run on.
@@ -283,6 +326,7 @@ int smp_call_function_mask(cpumask_t mask, void (*func)(void *), void *info,
283 cpumask_t allbutself; 326 cpumask_t allbutself;
284 unsigned long flags; 327 unsigned long flags;
285 int cpu, num_cpus; 328 int cpu, num_cpus;
329 int slowpath = 0;
286 330
287 /* Can deadlock when called with interrupts disabled */ 331 /* Can deadlock when called with interrupts disabled */
288 WARN_ON(irqs_disabled()); 332 WARN_ON(irqs_disabled());
@@ -304,15 +348,16 @@ int smp_call_function_mask(cpumask_t mask, void (*func)(void *), void *info,
304 return smp_call_function_single(cpu, func, info, wait); 348 return smp_call_function_single(cpu, func, info, wait);
305 } 349 }
306 350
307 if (!wait) { 351 data = kmalloc(sizeof(*data), GFP_ATOMIC);
308 data = kmalloc(sizeof(*data), GFP_ATOMIC); 352 if (data) {
309 if (data) 353 data->csd.flags = CSD_FLAG_ALLOC;
310 data->csd.flags = CSD_FLAG_ALLOC; 354 if (wait)
311 } 355 data->csd.flags |= CSD_FLAG_WAIT;
312 if (!data) { 356 } else {
313 data = &d; 357 data = &d;
314 data->csd.flags = CSD_FLAG_WAIT; 358 data->csd.flags = CSD_FLAG_WAIT;
315 wait = 1; 359 wait = 1;
360 slowpath = 1;
316 } 361 }
317 362
318 spin_lock_init(&data->lock); 363 spin_lock_init(&data->lock);
@@ -329,8 +374,11 @@ int smp_call_function_mask(cpumask_t mask, void (*func)(void *), void *info,
329 arch_send_call_function_ipi(mask); 374 arch_send_call_function_ipi(mask);
330 375
331 /* optionally wait for the CPUs to complete */ 376 /* optionally wait for the CPUs to complete */
332 if (wait) 377 if (wait) {
333 csd_flag_wait(&data->csd); 378 csd_flag_wait(&data->csd);
379 if (unlikely(slowpath))
380 smp_call_function_mask_quiesce_stack(mask);
381 }
334 382
335 return 0; 383 return 0;
336} 384}