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