aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTejun Heo <tj@kernel.org>2011-01-20 06:07:13 -0500
committerIngo Molnar <mingo@elte.hu>2011-01-20 07:32:34 -0500
commitbd924e8cbd4b73ffb7d707a774c04f7e2cae88ed (patch)
tree338d08c708b195acb9c8d6e0bab2e6ea720051a3
parent2ce802f62ba32a7d95748ac92bf351f76affb6ff (diff)
smp: Allow on_each_cpu() to be called while early_boot_irqs_disabled status to init/main.c
percpu may end up calling vfree() during early boot which in turn may call on_each_cpu() for TLB flushes. The function of on_each_cpu() can be done safely while IRQ is disabled during early boot but it assumed that the function is always called with local IRQ enabled which ended up enabling local IRQ prematurely during boot and triggering a couple of warnings. This patch updates on_each_cpu() and smp_call_function_many() such on_each_cpu() can be used safely while early_boot_irqs_disabled is set. Signed-off-by: Tejun Heo <tj@kernel.org> Acked-by: Peter Zijlstra <peterz@infradead.org> Acked-by: Pekka Enberg <penberg@kernel.org> Cc: Linus Torvalds <torvalds@linux-foundation.org> LKML-Reference: <20110120110713.GC6036@htj.dyndns.org> Signed-off-by: Ingo Molnar <mingo@elte.hu> Reported-by: Ingo Molnar <mingo@elte.hu>
-rw-r--r--kernel/smp.c11
1 files changed, 7 insertions, 4 deletions
diff --git a/kernel/smp.c b/kernel/smp.c
index 4ec30e069987..4b83cd6815e2 100644
--- a/kernel/smp.c
+++ b/kernel/smp.c
@@ -430,7 +430,7 @@ void smp_call_function_many(const struct cpumask *mask,
430 * can't happen. 430 * can't happen.
431 */ 431 */
432 WARN_ON_ONCE(cpu_online(this_cpu) && irqs_disabled() 432 WARN_ON_ONCE(cpu_online(this_cpu) && irqs_disabled()
433 && !oops_in_progress); 433 && !oops_in_progress && !early_boot_irqs_disabled);
434 434
435 /* So, what's a CPU they want? Ignoring this one. */ 435 /* So, what's a CPU they want? Ignoring this one. */
436 cpu = cpumask_first_and(mask, cpu_online_mask); 436 cpu = cpumask_first_and(mask, cpu_online_mask);
@@ -533,17 +533,20 @@ void ipi_call_unlock_irq(void)
533#endif /* USE_GENERIC_SMP_HELPERS */ 533#endif /* USE_GENERIC_SMP_HELPERS */
534 534
535/* 535/*
536 * Call a function on all processors 536 * Call a function on all processors. May be used during early boot while
537 * early_boot_irqs_disabled is set. Use local_irq_save/restore() instead
538 * of local_irq_disable/enable().
537 */ 539 */
538int on_each_cpu(void (*func) (void *info), void *info, int wait) 540int on_each_cpu(void (*func) (void *info), void *info, int wait)
539{ 541{
542 unsigned long flags;
540 int ret = 0; 543 int ret = 0;
541 544
542 preempt_disable(); 545 preempt_disable();
543 ret = smp_call_function(func, info, wait); 546 ret = smp_call_function(func, info, wait);
544 local_irq_disable(); 547 local_irq_save(flags);
545 func(info); 548 func(info);
546 local_irq_enable(); 549 local_irq_restore(flags);
547 preempt_enable(); 550 preempt_enable();
548 return ret; 551 return ret;
549} 552}