浏览代码

ipmi: Don't flush messages in sender() in run-to-completion mode

When flushing queued messages in run-to-completion mode,
smi_event_handler() is recursively called.

flush_messages()
 smi_event_handler()
  handle_transaction_done()
   deliver_recv_msg()
    ipmi_smi_msg_received()
     smi_recv_tasklet()
      sender()
       flush_messages()
        smi_event_handler()
         ...

The depth of the recursive call depends on the number of queued
messages, so it can cause a stack overflow if many messages have
been queued.

To solve this problem, this patch removes flush_messages()
from sender()@ipmi_si_intf.c.  Instead, add flush_messages() to
caller side of sender() if needed.  Additionally, to implement this,
add new handler flush_messages to struct ipmi_smi_handlers.

Signed-off-by: Hidehiro Kawai <hidehiro.kawai.ez@hitachi.com>

Fixed up a comment and some spacing issues.

Signed-off-by: Corey Minyard <cminyard@mvista.com>
Hidehiro Kawai 10 年之前
父节点
当前提交
82802f968b
共有 3 个文件被更改,包括 13 次插入5 次删除
  1. 3 0
      drivers/char/ipmi/ipmi_msghandler.c
  2. 5 5
      drivers/char/ipmi/ipmi_si_intf.c
  3. 5 0
      include/linux/ipmi_smi.h

+ 3 - 0
drivers/char/ipmi/ipmi_msghandler.c

@@ -4295,6 +4295,9 @@ static void ipmi_panic_request_and_wait(ipmi_smi_t           intf,
 			    0, 1); /* Don't retry, and don't wait. */
 			    0, 1); /* Don't retry, and don't wait. */
 	if (rv)
 	if (rv)
 		atomic_sub(2, &panic_done_count);
 		atomic_sub(2, &panic_done_count);
+	else if (intf->handlers->flush_messages)
+		intf->handlers->flush_messages(intf->send_info);
+
 	while (atomic_read(&panic_done_count) != 0)
 	while (atomic_read(&panic_done_count) != 0)
 		ipmi_poll(intf);
 		ipmi_poll(intf);
 }
 }

+ 5 - 5
drivers/char/ipmi/ipmi_si_intf.c

@@ -924,8 +924,9 @@ static void check_start_timer_thread(struct smi_info *smi_info)
 	}
 	}
 }
 }
 
 
-static void flush_messages(struct smi_info *smi_info)
+static void flush_messages(void *send_info)
 {
 {
+	struct smi_info *smi_info = send_info;
 	enum si_sm_result result;
 	enum si_sm_result result;
 
 
 	/*
 	/*
@@ -949,12 +950,10 @@ static void sender(void                *send_info,
 
 
 	if (smi_info->run_to_completion) {
 	if (smi_info->run_to_completion) {
 		/*
 		/*
-		 * If we are running to completion, start it and run
-		 * transactions until everything is clear.
+		 * If we are running to completion, start it.  Upper
+		 * layer will call flush_messages to clear it out.
 		 */
 		 */
 		smi_info->waiting_msg = msg;
 		smi_info->waiting_msg = msg;
-
-		flush_messages(smi_info);
 		return;
 		return;
 	}
 	}
 
 
@@ -1260,6 +1259,7 @@ static const struct ipmi_smi_handlers handlers = {
 	.set_need_watch		= set_need_watch,
 	.set_need_watch		= set_need_watch,
 	.set_maintenance_mode   = set_maintenance_mode,
 	.set_maintenance_mode   = set_maintenance_mode,
 	.set_run_to_completion  = set_run_to_completion,
 	.set_run_to_completion  = set_run_to_completion,
+	.flush_messages		= flush_messages,
 	.poll			= poll,
 	.poll			= poll,
 };
 };
 
 

+ 5 - 0
include/linux/ipmi_smi.h

@@ -115,6 +115,11 @@ struct ipmi_smi_handlers {
 	   implement it. */
 	   implement it. */
 	void (*set_need_watch)(void *send_info, bool enable);
 	void (*set_need_watch)(void *send_info, bool enable);
 
 
+	/*
+	 * Called when flushing all pending messages.
+	 */
+	void (*flush_messages)(void *send_info);
+
 	/* Called when the interface should go into "run to
 	/* Called when the interface should go into "run to
 	   completion" mode.  If this call sets the value to true, the
 	   completion" mode.  If this call sets the value to true, the
 	   interface should make sure that all messages are flushed
 	   interface should make sure that all messages are flushed