All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] Fix a deadlock in the IPMI driver
@ 2005-04-29 20:12 Corey Minyard
  0 siblings, 0 replies; only message in thread
From: Corey Minyard @ 2005-04-29 20:12 UTC (permalink / raw)
  To: Andrew Morton; +Cc: lkml

[-- Attachment #1: Type: text/plain, Size: 1 bytes --]



[-- Attachment #2: ipmi-deadlock-fix-0426.diff --]
[-- Type: text/x-patch, Size: 3006 bytes --]

This patch corrects an issue with the IPMI message layer taking a lock and
calling  lower layer driver.  If an error occrues at the lower layer the lock
can be taken again causing a deadlock.	The lock is released before calling the
lower layer.

Signed-off-by: David Griego <dgriego@mvista.com>
Signed-off-by: Corey Minyard <minyard@acm.org>

Index: linux-2.6.12-rc2/drivers/char/ipmi/ipmi_msghandler.c
===================================================================
--- linux-2.6.12-rc2.orig/drivers/char/ipmi/ipmi_msghandler.c
+++ linux-2.6.12-rc2/drivers/char/ipmi/ipmi_msghandler.c
@@ -2647,28 +2647,20 @@
 	deliver_response(msg);
 }
 
-static void
-send_from_recv_msg(ipmi_smi_t intf, struct ipmi_recv_msg *recv_msg,
-		   struct ipmi_smi_msg *smi_msg,
-		   unsigned char seq, long seqid)
+static struct ipmi_smi_msg *
+smi_from_recv_msg(ipmi_smi_t intf, struct ipmi_recv_msg *recv_msg,
+		  unsigned char seq, long seqid)
 {
-	if (!smi_msg)
-		smi_msg = ipmi_alloc_smi_msg();
+	struct ipmi_smi_msg *smi_msg = ipmi_alloc_smi_msg();
 	if (!smi_msg)
 		/* If we can't allocate the message, then just return, we
 		   get 4 retries, so this should be ok. */
-		return;
+		return NULL;
 
 	memcpy(smi_msg->data, recv_msg->msg.data, recv_msg->msg.data_len);
 	smi_msg->data_size = recv_msg->msg.data_len;
 	smi_msg->msgid = STORE_SEQ_IN_MSGID(seq, seqid);
 		
-	/* Send the new message.  We send with a zero priority.  It
-	   timed out, I doubt time is that critical now, and high
-	   priority messages are really only for messages to the local
-	   MC, which don't get resent. */
-	intf->handlers->sender(intf->send_info, smi_msg, 0);
-
 #ifdef DEBUG_MSGING
 	{
 		int m;
@@ -2678,6 +2670,7 @@
 		printk("\n");
 	}
 #endif
+	return smi_msg;
 }
 
 static void
@@ -2742,14 +2735,13 @@
 					intf->timed_out_ipmb_commands++;
 				spin_unlock(&intf->counter_lock);
 			} else {
+				struct ipmi_smi_msg *smi_msg;
 				/* More retries, send again. */
 
 				/* Start with the max timer, set to normal
 				   timer after the message is sent. */
 				ent->timeout = MAX_MSG_TIMEOUT;
 				ent->retries_left--;
-				send_from_recv_msg(intf, ent->recv_msg, NULL,
-						   j, ent->seqid);
 				spin_lock(&intf->counter_lock);
 				if (ent->recv_msg->addr.addr_type
 				    == IPMI_LAN_ADDR_TYPE)
@@ -2757,6 +2749,20 @@
 				else
 					intf->retransmitted_ipmb_commands++;
 				spin_unlock(&intf->counter_lock);
+				smi_msg = smi_from_recv_msg(intf, 
+						ent->recv_msg, j, ent->seqid);
+				if(!smi_msg)
+					continue;
+
+				spin_unlock_irqrestore(&(intf->seq_lock),flags);
+				/* Send the new message.  We send with a zero 
+				 * priority.  It timed out, I doubt time is 
+				 * that critical now, and high priority 
+				 * messages are really only for messages to the
+				 * local MC, which don't get resent. */
+				intf->handlers->sender(intf->send_info, 
+							smi_msg, 0);
+				spin_lock_irqsave(&(intf->seq_lock), flags);
 			}
 		}
 		spin_unlock_irqrestore(&(intf->seq_lock), flags);

^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2005-04-29 20:15 UTC | newest]

Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2005-04-29 20:12 [PATCH] Fix a deadlock in the IPMI driver Corey Minyard

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.