ipmi: Don't flush messages in sender() in run-to-completion mode
authorHidehiro Kawai <hidehiro.kawai.ez@hitachi.com>
Mon, 27 Jul 2015 05:55:16 +0000 (14:55 +0900)
committerCorey Minyard <cminyard@mvista.com>
Thu, 3 Sep 2015 20:02:28 +0000 (15:02 -0500)
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>
drivers/char/ipmi/ipmi_msghandler.c
drivers/char/ipmi/ipmi_si_intf.c
include/linux/ipmi_smi.h

index 5e31c339062eec8b43ea316d53fb341b4c91bd1d..6e191ff910e6230ea0f955a49d0a4f7585b36593 100644 (file)
@@ -4295,6 +4295,9 @@ static void ipmi_panic_request_and_wait(ipmi_smi_t           intf,
                            0, 1); /* Don't retry, and don't wait. */
        if (rv)
                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)
                ipmi_poll(intf);
 }
index 5bd6d5b974cd7807c97a97f17ad78e10321ee8ed..2f4cf6e78f72e727d11fc417d4f6905eb7da36a1 100644 (file)
@@ -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;
 
        /*
@@ -949,12 +950,10 @@ static void sender(void                *send_info,
 
        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;
-
-               flush_messages(smi_info);
                return;
        }
 
@@ -1260,6 +1259,7 @@ static const struct ipmi_smi_handlers handlers = {
        .set_need_watch         = set_need_watch,
        .set_maintenance_mode   = set_maintenance_mode,
        .set_run_to_completion  = set_run_to_completion,
+       .flush_messages         = flush_messages,
        .poll                   = poll,
 };
 
index 41de0cf34c495cdaf78bcbc4b52b424eebc68554..f8cea14485ddde6f5d73bea2817b9bfa8913dc10 100644 (file)
@@ -115,6 +115,11 @@ struct ipmi_smi_handlers {
           implement it. */
        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
           completion" mode.  If this call sets the value to true, the
           interface should make sure that all messages are flushed