diff options
author | William A. Kennington III <wak@google.com> | 2018-05-20 00:37:49 -0700 |
---|---|---|
committer | Daniel M. Crowell <dcrowell@us.ibm.com> | 2018-07-10 12:27:39 -0400 |
commit | 9a9bc342c9430ee335a948dc69702cadab48a83d (patch) | |
tree | 601de46d77895c1d67b55b87ac8d0a4eb7ed826e /src | |
parent | b24deec9bad7834542ed0e03953789cb887f754d (diff) | |
download | talos-hostboot-9a9bc342c9430ee335a948dc69702cadab48a83d.tar.gz talos-hostboot-9a9bc342c9430ee335a948dc69702cadab48a83d.zip |
ipmiwatchdog: Handle uninitialized errors during reset
The IPMI spec allows for the IPMI watchdog to return an error if the
watchdog was never initialized. This can happen if the daemon restarts
or if the initial setWatchDog command fails for some reason. Instead of
allowing the watchdog to remain uninitialized and disabled, use the
values of the previously issued set command to re-initialize the
watchdog. This is only attempted once per resetWatchDog call, but
periodic calls to the resetWatchDog should eventually re-initialize it.
Resolves #139
Signed-off-by: William A. Kennington III <wak@google.com>
Change-Id: I7b777e2f3b75d5ce38888018c1b74c6ce12ffc19
Reviewed-on: http://ralgit01.raleigh.ibm.com/gerrit1/59163
Tested-by: Jenkins Server <pfd-jenkins+hostboot@us.ibm.com>
Tested-by: Jenkins OP Build CI <op-jenkins+hostboot@us.ibm.com>
Tested-by: FSP CI Jenkins <fsp-CI-jenkins+hostboot@us.ibm.com>
Tested-by: Jenkins OP HW <op-hw-jenkins+hostboot@us.ibm.com>
Reviewed-by: Daniel M. Crowell <dcrowell@us.ibm.com>
Diffstat (limited to 'src')
-rw-r--r-- | src/usr/ipmi/ipmiwatchdog.C | 61 |
1 files changed, 56 insertions, 5 deletions
diff --git a/src/usr/ipmi/ipmiwatchdog.C b/src/usr/ipmi/ipmiwatchdog.C index 2f9f28f74..42da2a5ba 100644 --- a/src/usr/ipmi/ipmiwatchdog.C +++ b/src/usr/ipmi/ipmiwatchdog.C @@ -53,6 +53,14 @@ extern trace_desc_t * g_trac_ipmi; namespace IPMIWATCHDOG { +// Needed for watchdog resets in case the BMC side becomes uninitialized and we +// need to reinitialize it +static bool g_set_once = false; +static uint16_t g_countdown_secs; +static uint8_t g_timer_use; +static TIMER_ACTIONS g_timer_action; +static TIMER_USE_CLR_FLAGS g_timer_clr_flag; + /******************************************************************************/ // Functions /******************************************************************************/ @@ -63,6 +71,14 @@ errlHndl_t setWatchDogTimer( const uint16_t i_countdown_secs, const TIMER_ACTIONS i_timer_action, const TIMER_USE_CLR_FLAGS i_timer_clr_flag) { + // Save the latest values so that reset actions can setup the timer + // if the BMC goes away. + g_set_once = true; + g_countdown_secs = i_countdown_secs; + g_timer_use = i_timer_use; + g_timer_action = i_timer_action; + g_timer_clr_flag = i_timer_clr_flag; + // Convert secs into lsb and msb values // the ipmi spec uses the count which is 100ms/count static const uint16_t ms_per_count = 100; @@ -128,11 +144,9 @@ errlHndl_t resetWatchDogTimer() { IPMI_TRAC( "resetWatchDogTimer" ); - // Don't worry about the return just send the msg over - // If there is an error during the reset - // we don't care about it since the watchdog will trip - //send ipmi command - err_ipmi = IPMI::send(IPMI::reset_watchdog(), len, data); + IPMI::completion_code cc; + err_ipmi = IPMI::sendrecv(IPMI::reset_watchdog(), cc, len, data); + delete[] data; if(err_ipmi) { @@ -141,6 +155,43 @@ errlHndl_t resetWatchDogTimer() break; } + // Make sure we don't have an uninitialized watchdog + // openbmc will always start the watchdog regardless of us + // initializing it. If we don't initialize it, it can eventually + // time out on us + if (g_set_once && cc == IPMI::CC_CMDSPC1) + { + err_ipmi = setWatchDogTimer(g_countdown_secs, + g_timer_use | DO_NOT_STOP, + g_timer_action, g_timer_clr_flag); + + if (err_ipmi) + { + //got an error sending IPMI msg + //progate error upstream. + break; + } + + // Make sure to issue a reset after initialization to start + // the timer if it isn't already. We don't care about the return + // value of this message since we can't recurse forever. If we + // fail here, later resets should handle reconfiguring the + // watchdog if it isn't critically broken. + len = 0; + data = NULL; + err_ipmi = IPMI::send(IPMI::reset_watchdog(), len, data); + + if(err_ipmi) + { + //got an error sending IPMI msg + //progate error upstream. + break; + } + } + + // We don't care about any other types of errors as the watchdog + // will just trip in these cases. + break; } while(0); |