aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorCorey Minyard <minyard@acm.org>2005-05-01 11:59:12 -0400
committerLinus Torvalds <torvalds@ppc970.osdl.org>2005-05-01 11:59:12 -0400
commit882fe011a92fa4fc31ca6cc95b279f7e4e52935c (patch)
treeda1fc3fab16f937c79a83024c552813f8d61602f
parent9dbf68f97d585265eaadd15aea308efd9ae39d34 (diff)
[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: David Griego <dgriego@mvista.com> Signed-off-by: Corey Minyard <minyard@acm.org> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
-rw-r--r--drivers/char/ipmi/ipmi_msghandler.c36
1 files changed, 21 insertions, 15 deletions
diff --git a/drivers/char/ipmi/ipmi_msghandler.c b/drivers/char/ipmi/ipmi_msghandler.c
index a6606a1aced7..d7fb452af7f9 100644
--- a/drivers/char/ipmi/ipmi_msghandler.c
+++ b/drivers/char/ipmi/ipmi_msghandler.c
@@ -2588,28 +2588,20 @@ handle_msg_timeout(struct ipmi_recv_msg *msg)
2588 deliver_response(msg); 2588 deliver_response(msg);
2589} 2589}
2590 2590
2591static void 2591static struct ipmi_smi_msg *
2592send_from_recv_msg(ipmi_smi_t intf, struct ipmi_recv_msg *recv_msg, 2592smi_from_recv_msg(ipmi_smi_t intf, struct ipmi_recv_msg *recv_msg,
2593 struct ipmi_smi_msg *smi_msg, 2593 unsigned char seq, long seqid)
2594 unsigned char seq, long seqid)
2595{ 2594{
2596 if (!smi_msg) 2595 struct ipmi_smi_msg *smi_msg = ipmi_alloc_smi_msg();
2597 smi_msg = ipmi_alloc_smi_msg();
2598 if (!smi_msg) 2596 if (!smi_msg)
2599 /* If we can't allocate the message, then just return, we 2597 /* If we can't allocate the message, then just return, we
2600 get 4 retries, so this should be ok. */ 2598 get 4 retries, so this should be ok. */
2601 return; 2599 return NULL;
2602 2600
2603 memcpy(smi_msg->data, recv_msg->msg.data, recv_msg->msg.data_len); 2601 memcpy(smi_msg->data, recv_msg->msg.data, recv_msg->msg.data_len);
2604 smi_msg->data_size = recv_msg->msg.data_len; 2602 smi_msg->data_size = recv_msg->msg.data_len;
2605 smi_msg->msgid = STORE_SEQ_IN_MSGID(seq, seqid); 2603 smi_msg->msgid = STORE_SEQ_IN_MSGID(seq, seqid);
2606 2604
2607 /* Send the new message. We send with a zero priority. It
2608 timed out, I doubt time is that critical now, and high
2609 priority messages are really only for messages to the local
2610 MC, which don't get resent. */
2611 intf->handlers->sender(intf->send_info, smi_msg, 0);
2612
2613#ifdef DEBUG_MSGING 2605#ifdef DEBUG_MSGING
2614 { 2606 {
2615 int m; 2607 int m;
@@ -2619,6 +2611,7 @@ send_from_recv_msg(ipmi_smi_t intf, struct ipmi_recv_msg *recv_msg,
2619 printk("\n"); 2611 printk("\n");
2620 } 2612 }
2621#endif 2613#endif
2614 return smi_msg;
2622} 2615}
2623 2616
2624static void 2617static void
@@ -2683,14 +2676,13 @@ ipmi_timeout_handler(long timeout_period)
2683 intf->timed_out_ipmb_commands++; 2676 intf->timed_out_ipmb_commands++;
2684 spin_unlock(&intf->counter_lock); 2677 spin_unlock(&intf->counter_lock);
2685 } else { 2678 } else {
2679 struct ipmi_smi_msg *smi_msg;
2686 /* More retries, send again. */ 2680 /* More retries, send again. */
2687 2681
2688 /* Start with the max timer, set to normal 2682 /* Start with the max timer, set to normal
2689 timer after the message is sent. */ 2683 timer after the message is sent. */
2690 ent->timeout = MAX_MSG_TIMEOUT; 2684 ent->timeout = MAX_MSG_TIMEOUT;
2691 ent->retries_left--; 2685 ent->retries_left--;
2692 send_from_recv_msg(intf, ent->recv_msg, NULL,
2693 j, ent->seqid);
2694 spin_lock(&intf->counter_lock); 2686 spin_lock(&intf->counter_lock);
2695 if (ent->recv_msg->addr.addr_type 2687 if (ent->recv_msg->addr.addr_type
2696 == IPMI_LAN_ADDR_TYPE) 2688 == IPMI_LAN_ADDR_TYPE)
@@ -2698,6 +2690,20 @@ ipmi_timeout_handler(long timeout_period)
2698 else 2690 else
2699 intf->retransmitted_ipmb_commands++; 2691 intf->retransmitted_ipmb_commands++;
2700 spin_unlock(&intf->counter_lock); 2692 spin_unlock(&intf->counter_lock);
2693 smi_msg = smi_from_recv_msg(intf,
2694 ent->recv_msg, j, ent->seqid);
2695 if(!smi_msg)
2696 continue;
2697
2698 spin_unlock_irqrestore(&(intf->seq_lock),flags);
2699 /* Send the new message. We send with a zero
2700 * priority. It timed out, I doubt time is
2701 * that critical now, and high priority
2702 * messages are really only for messages to the
2703 * local MC, which don't get resent. */
2704 intf->handlers->sender(intf->send_info,
2705 smi_msg, 0);
2706 spin_lock_irqsave(&(intf->seq_lock), flags);
2701 } 2707 }
2702 } 2708 }
2703 spin_unlock_irqrestore(&(intf->seq_lock), flags); 2709 spin_unlock_irqrestore(&(intf->seq_lock), flags);