aboutsummaryrefslogtreecommitdiff
path: root/hw/ipmi
diff options
context:
space:
mode:
authorAlistair Popple <alistair@popple.id.au>2015-05-12 14:49:30 +1000
committerStewart Smith <stewart@linux.vnet.ibm.com>2015-05-12 14:56:28 +1000
commit8b5fca359a8cfecb9d66ca436a553b46e7b5cc4b (patch)
treedd975bd27a3954fd897e549164ad6d76995e7f47 /hw/ipmi
parent101d094f22da42b178b325d0710c140079e00af3 (diff)
downloadskiboot-8b5fca359a8cfecb9d66ca436a553b46e7b5cc4b.zip
skiboot-8b5fca359a8cfecb9d66ca436a553b46e7b5cc4b.tar.gz
skiboot-8b5fca359a8cfecb9d66ca436a553b46e7b5cc4b.tar.bz2
ipmi/wdt: Stop calling synchronous message functions from timers
The current watchdog code calls ipmi_queue_msg_sync from a timer which leads to calling a opal_poll_events() recursively and consequently an abort(). This patch ensures we don't send synchronous messages from a timer. Signed-off-by: Alistair Popple <alistair@popple.id.au> Signed-off-by: Stewart Smith <stewart@linux.vnet.ibm.com>
Diffstat (limited to 'hw/ipmi')
-rw-r--r--hw/ipmi/ipmi-watchdog.c33
1 files changed, 24 insertions, 9 deletions
diff --git a/hw/ipmi/ipmi-watchdog.c b/hw/ipmi/ipmi-watchdog.c
index a3db53b..498d4c6 100644
--- a/hw/ipmi/ipmi-watchdog.c
+++ b/hw/ipmi/ipmi-watchdog.c
@@ -78,21 +78,34 @@ static void set_wdt(uint8_t action, uint16_t count, uint8_t pretimeout)
ipmi_queue_msg(ipmi_msg);
}
-static void reset_wdt(struct timer *t __unused, void *data)
+static struct ipmi_msg *wdt_reset_mkmsg(void)
{
struct ipmi_msg *ipmi_msg;
ipmi_msg = ipmi_mkmsg(IPMI_DEFAULT_INTERFACE, IPMI_RESET_WDT,
- ipmi_wdt_complete, data, NULL, 0, 0);
+ ipmi_wdt_complete, NULL, NULL, 0, 0);
if (!ipmi_msg) {
prerror("Unable to allocate reset wdt message\n");
- return;
+ return NULL;
}
- if (!data)
+ return ipmi_msg;
+}
+
+static void sync_reset_wdt(void)
+{
+ struct ipmi_msg *ipmi_msg;
+
+ if ((ipmi_msg = wdt_reset_mkmsg()))
ipmi_queue_msg_sync(ipmi_msg);
- else
- ipmi_queue_msg(ipmi_msg);
+}
+
+static void reset_wdt(struct timer *t __unused, void *data __unused)
+{
+ struct ipmi_msg *ipmi_msg;
+
+ if ((ipmi_msg = wdt_reset_mkmsg()))
+ ipmi_queue_msg_head(ipmi_msg);
}
void ipmi_wdt_stop(void)
@@ -122,12 +135,14 @@ void ipmi_wdt_init(void)
init_timer(&wdt_timer, reset_wdt, NULL);
set_wdt(WDT_POWER_CYCLE_ACTION, WDT_TIMEOUT, 0);
- /* Start the WDT */
- reset_wdt(NULL, NULL);
+ /* Start the WDT. We do it synchronously to make sure it has
+ * started before skiboot continues booting. Otherwise we
+ * could crash before the wdt has actually been started. */
+ sync_reset_wdt();
/* For some reason we have to reset it twice to get it to
* actually start the first time. */
- reset_wdt(NULL, NULL);
+ sync_reset_wdt();
return;
}