]> bbs.cooldavid.org Git - net-next-2.6.git/commitdiff
generic-ipi: Allow cpus not yet online to call smp_call_function with irqs disabled
authorSuresh Siddha <suresh.b.siddha@intel.com>
Thu, 20 Aug 2009 01:05:35 +0000 (18:05 -0700)
committerH. Peter Anvin <hpa@zytor.com>
Fri, 21 Aug 2009 23:25:43 +0000 (16:25 -0700)
Because of deadlock possiblities smp_call_function() is not allowed to
be called with interrupts disabled. Add an exception for the cpu not
yet online, as no one else can send smp call function interrupt to this
cpu that is not yet online and as such deadlock condition is not possible.

Signed-off-by: Suresh Siddha <suresh.b.siddha@intel.com>
Acked-by: Nick Piggin <npiggin@suse.de>
Signed-off-by: H. Peter Anvin <hpa@zytor.com>
kernel/smp.c

index ad63d8501207836353ad91d15f94fb3aaa4c0c1b..2accdf6712e54dfde91c3f5b7b7b0a1ccaef6b13 100644 (file)
@@ -176,6 +176,11 @@ void generic_smp_call_function_interrupt(void)
        struct call_function_data *data;
        int cpu = get_cpu();
 
+       /*
+        * Shouldn't receive this interrupt on a cpu that is not yet online.
+        */
+       WARN_ON_ONCE(!cpu_online(cpu));
+
        /*
         * Ensure entry is visible on call_function_queue after we have
         * entered the IPI. See comment in smp_call_function_many.
@@ -230,6 +235,11 @@ void generic_smp_call_function_single_interrupt(void)
        unsigned int data_flags;
        LIST_HEAD(list);
 
+       /*
+        * Shouldn't receive this interrupt on a cpu that is not yet online.
+        */
+       WARN_ON_ONCE(!cpu_online(smp_processor_id()));
+
        spin_lock(&q->lock);
        list_replace_init(&q->list, &list);
        spin_unlock(&q->lock);
@@ -285,8 +295,14 @@ int smp_call_function_single(int cpu, void (*func) (void *info), void *info,
         */
        this_cpu = get_cpu();
 
-       /* Can deadlock when called with interrupts disabled */
-       WARN_ON_ONCE(irqs_disabled() && !oops_in_progress);
+       /*
+        * Can deadlock when called with interrupts disabled.
+        * We allow cpu's that are not yet online though, as no one else can
+        * send smp call function interrupt to this cpu and as such deadlocks
+        * can't happen.
+        */
+       WARN_ON_ONCE(cpu_online(this_cpu) && irqs_disabled()
+                    && !oops_in_progress);
 
        if (cpu == this_cpu) {
                local_irq_save(flags);
@@ -329,8 +345,14 @@ void __smp_call_function_single(int cpu, struct call_single_data *data,
 {
        csd_lock(data);
 
-       /* Can deadlock when called with interrupts disabled */
-       WARN_ON_ONCE(wait && irqs_disabled() && !oops_in_progress);
+       /*
+        * Can deadlock when called with interrupts disabled.
+        * We allow cpu's that are not yet online though, as no one else can
+        * send smp call function interrupt to this cpu and as such deadlocks
+        * can't happen.
+        */
+       WARN_ON_ONCE(cpu_online(smp_processor_id()) && wait && irqs_disabled()
+                    && !oops_in_progress);
 
        generic_exec_single(cpu, data, wait);
 }
@@ -365,8 +387,14 @@ void smp_call_function_many(const struct cpumask *mask,
        unsigned long flags;
        int cpu, next_cpu, this_cpu = smp_processor_id();
 
-       /* Can deadlock when called with interrupts disabled */
-       WARN_ON_ONCE(irqs_disabled() && !oops_in_progress);
+       /*
+        * Can deadlock when called with interrupts disabled.
+        * We allow cpu's that are not yet online though, as no one else can
+        * send smp call function interrupt to this cpu and as such deadlocks
+        * can't happen.
+        */
+       WARN_ON_ONCE(cpu_online(this_cpu) && irqs_disabled()
+                    && !oops_in_progress);
 
        /* So, what's a CPU they want? Ignoring this one. */
        cpu = cpumask_first_and(mask, cpu_online_mask);