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>
This commit is contained in:
Hidehiro Kawai 2015-07-27 14:55:16 +09:00 committed by Corey Minyard
parent e45361d733
commit 82802f968b
3 changed files with 13 additions and 5 deletions

View 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. */ 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);
} }

View 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; 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 * If we are running to completion, start it. Upper
* transactions until everything is clear. * 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,
}; };

View File

@ -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