Fix a deadlock in the IPMI driver
PATCH 1/1 Fix a deadlock in the IPMI driver
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 <[email protected]>
Signed-off-by Corey Minyard <[email protected]>
drivers/char/ipmi/ipmi_msghandler.c +21 -15
@@ -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);