Commit 882fe011 authored by Corey Minyard's avatar Corey Minyard Committed by Linus Torvalds

[PATCH] ipmi: fix a deadlock

Correct 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: default avatarDavid Griego <dgriego@mvista.com>
Signed-off-by: default avatarCorey Minyard <minyard@acm.org>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent 9dbf68f9
...@@ -2588,28 +2588,20 @@ handle_msg_timeout(struct ipmi_recv_msg *msg) ...@@ -2588,28 +2588,20 @@ handle_msg_timeout(struct ipmi_recv_msg *msg)
deliver_response(msg); deliver_response(msg);
} }
static void static struct ipmi_smi_msg *
send_from_recv_msg(ipmi_smi_t intf, struct ipmi_recv_msg *recv_msg, smi_from_recv_msg(ipmi_smi_t intf, struct ipmi_recv_msg *recv_msg,
struct ipmi_smi_msg *smi_msg, unsigned char seq, long seqid)
unsigned char seq, long seqid)
{ {
if (!smi_msg) struct ipmi_smi_msg *smi_msg = ipmi_alloc_smi_msg();
smi_msg = ipmi_alloc_smi_msg();
if (!smi_msg) if (!smi_msg)
/* If we can't allocate the message, then just return, we /* If we can't allocate the message, then just return, we
get 4 retries, so this should be ok. */ get 4 retries, so this should be ok. */
return; return NULL;
memcpy(smi_msg->data, recv_msg->msg.data, recv_msg->msg.data_len); memcpy(smi_msg->data, recv_msg->msg.data, recv_msg->msg.data_len);
smi_msg->data_size = recv_msg->msg.data_len; smi_msg->data_size = recv_msg->msg.data_len;
smi_msg->msgid = STORE_SEQ_IN_MSGID(seq, seqid); 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 #ifdef DEBUG_MSGING
{ {
int m; int m;
...@@ -2619,6 +2611,7 @@ send_from_recv_msg(ipmi_smi_t intf, struct ipmi_recv_msg *recv_msg, ...@@ -2619,6 +2611,7 @@ send_from_recv_msg(ipmi_smi_t intf, struct ipmi_recv_msg *recv_msg,
printk("\n"); printk("\n");
} }
#endif #endif
return smi_msg;
} }
static void static void
...@@ -2683,14 +2676,13 @@ ipmi_timeout_handler(long timeout_period) ...@@ -2683,14 +2676,13 @@ ipmi_timeout_handler(long timeout_period)
intf->timed_out_ipmb_commands++; intf->timed_out_ipmb_commands++;
spin_unlock(&intf->counter_lock); spin_unlock(&intf->counter_lock);
} else { } else {
struct ipmi_smi_msg *smi_msg;
/* More retries, send again. */ /* More retries, send again. */
/* Start with the max timer, set to normal /* Start with the max timer, set to normal
timer after the message is sent. */ timer after the message is sent. */
ent->timeout = MAX_MSG_TIMEOUT; ent->timeout = MAX_MSG_TIMEOUT;
ent->retries_left--; ent->retries_left--;
send_from_recv_msg(intf, ent->recv_msg, NULL,
j, ent->seqid);
spin_lock(&intf->counter_lock); spin_lock(&intf->counter_lock);
if (ent->recv_msg->addr.addr_type if (ent->recv_msg->addr.addr_type
== IPMI_LAN_ADDR_TYPE) == IPMI_LAN_ADDR_TYPE)
...@@ -2698,6 +2690,20 @@ ipmi_timeout_handler(long timeout_period) ...@@ -2698,6 +2690,20 @@ ipmi_timeout_handler(long timeout_period)
else else
intf->retransmitted_ipmb_commands++; intf->retransmitted_ipmb_commands++;
spin_unlock(&intf->counter_lock); 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); spin_unlock_irqrestore(&(intf->seq_lock), flags);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment