aboutsummaryrefslogtreecommitdiff
path: root/hw/ipmi
diff options
context:
space:
mode:
authorWilliam A. Kennington III <wak@google.com>2018-05-23 17:13:34 -0700
committerStewart Smith <stewart@linux.ibm.com>2018-06-04 00:02:24 -0500
commit2d2916409639507c0357a9fe22493e1379eb1115 (patch)
tree254156712b06b7a2c63c1e83d400583f9ff5e3db /hw/ipmi
parent7e956e687e644cc4a16d42884d21135cf41cf244 (diff)
downloadskiboot-2d2916409639507c0357a9fe22493e1379eb1115.zip
skiboot-2d2916409639507c0357a9fe22493e1379eb1115.tar.gz
skiboot-2d2916409639507c0357a9fe22493e1379eb1115.tar.bz2
ipmi-watchdog: Support resetting the watchdog after set
This does not create any behavioral change yet, but this will be useful in a future commit that adds support for re-initializing the watchdog. Signed-off-by: William A. Kennington III <wak@google.com> Signed-off-by: Stewart Smith <stewart@linux.ibm.com>
Diffstat (limited to 'hw/ipmi')
-rw-r--r--hw/ipmi/ipmi-watchdog.c34
1 files changed, 27 insertions, 7 deletions
diff --git a/hw/ipmi/ipmi-watchdog.c b/hw/ipmi/ipmi-watchdog.c
index 1a638c8..0de5877 100644
--- a/hw/ipmi/ipmi-watchdog.c
+++ b/hw/ipmi/ipmi-watchdog.c
@@ -33,6 +33,9 @@
#define WDT_RESET_ACTION 0x01
#define WDT_NO_ACTION 0x00
+/* Flags used for IPMI callbacks */
+#define WDT_SET_DO_RESET 0x01
+
/* How long to set the overall watchdog timeout for. In units of
* 100ms. If the timer is not reset within this time the watchdog
* expiration action will occur. */
@@ -48,18 +51,35 @@ static struct timer wdt_timer;
static bool wdt_stopped;
static bool wdt_ticking;
+static void reset_wdt(struct timer *t, void *data, uint64_t now);
+
+static void set_wdt_complete(struct ipmi_msg *msg)
+{
+ const uintptr_t flags = (uintptr_t)msg->user_data;
+
+ if (flags & WDT_SET_DO_RESET)
+ reset_wdt(NULL, NULL, 0);
+
+ ipmi_free_msg(msg);
+}
+
static void set_wdt(uint8_t action, uint16_t count, uint8_t pretimeout,
- bool dont_stop)
+ bool dont_stop, bool do_reset)
{
struct ipmi_msg *ipmi_msg;
+ uintptr_t completion_flags = 0;
+
+ if (do_reset)
+ completion_flags |= WDT_SET_DO_RESET;
ipmi_msg = ipmi_mkmsg(IPMI_DEFAULT_INTERFACE, IPMI_SET_WDT,
- ipmi_free_msg, NULL, NULL, 6, 0);
+ set_wdt_complete, NULL, NULL, 6, 0);
if (!ipmi_msg) {
prerror("Unable to allocate set wdt message\n");
return;
}
- ipmi_msg->error = ipmi_free_msg;
+ ipmi_msg->error = set_wdt_complete;
+ ipmi_msg->user_data = (void *)completion_flags;
ipmi_msg->data[0] = TIMER_USE_POST |
TIMER_USE_DONT_LOG |
(dont_stop ? TIMER_USE_DONT_STOP : 0);
@@ -127,7 +147,7 @@ void ipmi_wdt_stop(void)
* in case the underlying implementation is buggy and times
* out anyway. */
wdt_stopped = true;
- set_wdt(WDT_NO_ACTION, 100, 0, false);
+ set_wdt(WDT_NO_ACTION, 100, 0, false, false);
}
}
@@ -148,10 +168,10 @@ void ipmi_wdt_final_reset(void)
#if 0
/* Configure the watchdog and make sure it is still enabled */
set_wdt(WDT_RESET_ACTION | WDT_PRETIMEOUT_SMI, WDT_TIMEOUT,
- WDT_MARGIN/10, true);
+ WDT_MARGIN/10, true, true);
sync_reset_wdt();
#else
- set_wdt(WDT_NO_ACTION, 100, 0, false);
+ set_wdt(WDT_NO_ACTION, 100, 0, false, false);
#endif
ipmi_set_boot_count();
}
@@ -159,7 +179,7 @@ void ipmi_wdt_final_reset(void)
void ipmi_wdt_init(void)
{
init_timer(&wdt_timer, reset_wdt, NULL);
- set_wdt(WDT_RESET_ACTION, WDT_TIMEOUT, 0, true);
+ set_wdt(WDT_RESET_ACTION, WDT_TIMEOUT, 0, true, false);
/* Start the WDT. We do it synchronously to make sure it has
* started before skiboot continues booting. Otherwise we