Subject: smp_call_function: additional memory-order tightening.
From: "Paul E. McKenney" <paulmck@linux.vnet.ibm.com>
Date: Tue, 1 Feb 2011 20:17:40 -0800
Patch-mainline: submitted
References: bnc#658037, bnc#636435, bnc#665663

The csd_lock() and csd_unlock() interaction guarantees that the
smp_call_function_many() function sees the results of interactions
with prior incarnations of the callback, so the check is not needed.
Instead, tighter memory ordering is required in the companion
generic_smp_call_function_interrupt() function to ensure proper
interaction with partially initialized callbacks.

Acked-by: Mike Galbraith <mgalbraith@suse.de>
Signed-off-by: Paul E. McKenney <paulmck@linux.vnet.ibm.com>

---
 kernel/smp.c |   11 ++++++++---
 1 file changed, 8 insertions(+), 3 deletions(-)

Index: linux-3.0-tmp-jikos/kernel/smp.c
===================================================================
--- linux-3.0-tmp-jikos.orig/kernel/smp.c
+++ linux-3.0-tmp-jikos/kernel/smp.c
@@ -179,7 +179,7 @@ void generic_smp_call_function_interrupt
 
 	/*
 	 * Ensure entry is visible on call_function_queue after we have
-	 * entered the IPI. See comment in smp_call_function_many.
+	 * entered the IPI. See comment in smp_call_function_many
 	 * If we don't have this, then we may miss an entry on the list
 	 * and never get another IPI to process it.
 	 */
@@ -206,11 +206,16 @@ void generic_smp_call_function_interrupt
 		if (!cpumask_test_cpu(cpu, data->cpumask))
 			continue;
 
-		smp_rmb();
+		smp_mb(); /* If we see our bit set above, we need to see */
+			  /* all the processing associated with the prior */
+			  /* incarnation of this callback. */
 
 		if (atomic_read(&data->refs) == 0)
 			continue;
 
+		smp_rmb(); /* We need to read ->refs before we read either */
+			   /* ->csd.func and ->csd.info. */
+
 		func = data->csd.func;		/* save for later warn */
 		func(data->csd.info);
 
