diff options
author | Hidehiro Kawai <hidehiro.kawai.ez@hitachi.com> | 2015-07-27 07:55:16 +0200 |
---|---|---|
committer | Corey Minyard <cminyard@mvista.com> | 2015-09-03 22:02:28 +0200 |
commit | 82802f968bd3118af04eaeb3814c21d9813be527 (patch) | |
tree | dd26a8d2a0d96b013938814083144654bf30db71 /drivers | |
parent | ipmi: Factor out message flushing procedure (diff) | |
download | linux-82802f968bd3118af04eaeb3814c21d9813be527.tar.xz linux-82802f968bd3118af04eaeb3814c21d9813be527.zip |
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>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/char/ipmi/ipmi_msghandler.c | 3 | ||||
-rw-r--r-- | drivers/char/ipmi/ipmi_si_intf.c | 10 |
2 files changed, 8 insertions, 5 deletions
diff --git a/drivers/char/ipmi/ipmi_msghandler.c b/drivers/char/ipmi/ipmi_msghandler.c index 5e31c339062e..6e191ff910e6 100644 --- a/drivers/char/ipmi/ipmi_msghandler.c +++ b/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. */ 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); } diff --git a/drivers/char/ipmi/ipmi_si_intf.c b/drivers/char/ipmi/ipmi_si_intf.c index 5bd6d5b974cd..2f4cf6e78f72 100644 --- a/drivers/char/ipmi/ipmi_si_intf.c +++ b/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; /* @@ -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, }; |