From 1d86e29b4a612eb01c39daa48749ab7964e77e03 Mon Sep 17 00:00:00 2001
From: Corey Minyard <cminyard@mvista.com>
Date: Thu, 19 Feb 2015 08:25:49 -0600
Subject: ipmi: Fix a memory ordering issue

From a locking point of view it is safe to check waiting_msg without
a lock, but there is a memory ordering issue that causes it to
possibly not be set right when viewed from another processor.  We are
already claiming a lock right after that, move the check to inside
the lock to enforce the memory ordering.

Signed-off-by: Corey Minyard <cminyard@mvista.com>
---
 drivers/char/ipmi/ipmi_si_intf.c | 14 ++++++++++----
 1 file changed, 10 insertions(+), 4 deletions(-)

(limited to 'drivers/char/ipmi')

diff --git a/drivers/char/ipmi/ipmi_si_intf.c b/drivers/char/ipmi/ipmi_si_intf.c
index 321ecb26df6a..f6646ed3047e 100644
--- a/drivers/char/ipmi/ipmi_si_intf.c
+++ b/drivers/char/ipmi/ipmi_si_intf.c
@@ -932,9 +932,6 @@ static void sender(void                *send_info,
 	enum si_sm_result result;
 	unsigned long     flags;
 
-	BUG_ON(smi_info->waiting_msg);
-	smi_info->waiting_msg = msg;
-
 	debug_timestamp("Enqueue");
 
 	if (smi_info->run_to_completion) {
@@ -942,7 +939,7 @@ static void sender(void                *send_info,
 		 * If we are running to completion, start it and run
 		 * transactions until everything is clear.
 		 */
-		smi_info->curr_msg = smi_info->waiting_msg;
+		smi_info->curr_msg = msg;
 		smi_info->waiting_msg = NULL;
 
 		/*
@@ -960,6 +957,15 @@ static void sender(void                *send_info,
 	}
 
 	spin_lock_irqsave(&smi_info->si_lock, flags);
+	/*
+	 * The following two lines don't need to be under the lock for
+	 * the lock's sake, but they do need SMP memory barriers to
+	 * avoid getting things out of order.  We are already claiming
+	 * the lock, anyway, so just do it under the lock to avoid the
+	 * ordering problem.
+	 */
+	BUG_ON(smi_info->waiting_msg);
+	smi_info->waiting_msg = msg;
 	check_start_timer_thread(smi_info);
 	spin_unlock_irqrestore(&smi_info->si_lock, flags);
 }
-- 
cgit v1.2.3