diff options
-rw-r--r-- | src/include/sys/time.h | 10 | ||||
-rw-r--r-- | src/include/usr/ipmi/ipmiif.H | 3 | ||||
-rw-r--r-- | src/include/usr/ipmi/ipmiwatchdog.H | 141 | ||||
-rw-r--r-- | src/usr/diag/mdia/mdiasm.C | 20 | ||||
-rw-r--r-- | src/usr/hwpf/hwp/start_payload/start_payload.C | 44 | ||||
-rw-r--r-- | src/usr/initservice/istepdispatcher/istepdispatcher.C | 32 | ||||
-rw-r--r-- | src/usr/ipmi/ipmiwatchdog.C | 149 | ||||
-rw-r--r-- | src/usr/ipmi/makefile | 1 |
8 files changed, 396 insertions, 4 deletions
diff --git a/src/include/sys/time.h b/src/include/sys/time.h index 51bccfe23..1a0a02ec4 100644 --- a/src/include/sys/time.h +++ b/src/include/sys/time.h @@ -5,7 +5,9 @@ /* */ /* OpenPOWER HostBoot Project */ /* */ -/* COPYRIGHT International Business Machines Corp. 2010,2014 */ +/* Contributors Listed Below - COPYRIGHT 2010,2014 */ +/* [+] International Business Machines Corp. */ +/* */ /* */ /* Licensed under the Apache License, Version 2.0 (the "License"); */ /* you may not use this file except in compliance with the License. */ @@ -30,6 +32,12 @@ // Macros //****************************************************************************** + +/** + * @brief number of milliseconds per second + */ +#define MS_PER_SEC (1000) + /** * @brief Number of nanoseconds per second */ diff --git a/src/include/usr/ipmi/ipmiif.H b/src/include/usr/ipmi/ipmiif.H index 0226eb2dd..ae03f8394 100644 --- a/src/include/usr/ipmi/ipmiif.H +++ b/src/include/usr/ipmi/ipmiif.H @@ -120,6 +120,9 @@ namespace IPMI inline const command_t set_watchdog(void) { return std::make_pair(NETFUN_APP, 0x24); } + inline const command_t reset_watchdog(void) + { return std::make_pair(NETFUN_APP, 0x22); } + inline const command_t get_capabilities(void) { return std::make_pair(NETFUN_APP, 0x36); } diff --git a/src/include/usr/ipmi/ipmiwatchdog.H b/src/include/usr/ipmi/ipmiwatchdog.H new file mode 100644 index 000000000..7c39ac5da --- /dev/null +++ b/src/include/usr/ipmi/ipmiwatchdog.H @@ -0,0 +1,141 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/include/usr/ipmi/ipmiwatchdog.H $ */ +/* */ +/* OpenPOWER HostBoot Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 2014 */ +/* [+] International Business Machines Corp. */ +/* */ +/* */ +/* Licensed under the Apache License, Version 2.0 (the "License"); */ +/* you may not use this file except in compliance with the License. */ +/* You may obtain a copy of the License at */ +/* */ +/* http://www.apache.org/licenses/LICENSE-2.0 */ +/* */ +/* Unless required by applicable law or agreed to in writing, software */ +/* distributed under the License is distributed on an "AS IS" BASIS, */ +/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */ +/* implied. See the License for the specific language governing */ +/* permissions and limitations under the License. */ +/* */ +/* IBM_PROLOG_END_TAG */ +#ifndef __IPMIWATCHDOG_IPMIWATCHDOG_H +#define __IPMIWATCHDOG_IPMIWATCHDOG_H +/** + * @file ipmiwatchdog.H + * + * IPMI watchdog interface launched from the IStep Dispatcher + * + */ + +/******************************************************************************/ +// Includes +/******************************************************************************/ +#include <stdint.h> +#include <errl/errlentry.H> + +namespace IPMIWATCHDOG +{ +/******************************************************************************/ +// Globals/Constants +/******************************************************************************/ +/** + * @brief the default watchdog countdown setting it to 15 secs since progress + * have to be sent every 15 secs. + */ +const uint16_t DEFAULT_WATCHDOG_COUNTDOWN = 15; + +/** + * @brief the default watchdog countdown for transition between hostboot + * and OPAL (value is in seconds) + */ +const uint16_t DEFAULT_HB_OPAL_TRANSITION_COUNTDOWN = 30; + +/******************************************************************************/ +// Typedef/Enumerations +/******************************************************************************/ +/** + * @brief Used in Byte 1 field of the set watchdog command + */ +enum TIMER_USE +{ + DO_NOT_LOG = 0x80, // bit 7 + DO_NOT_STOP = 0x40, // bit 6 + BIOS_FRB2 = 0x01, // bit 0 + BIOS_POST = 0x02, // bit 1 + OS_LOAD = 0x03, // bits 0 & 1 + SMS_OS = 0x04, // bit 2 + OEM = 0x05, // bits 2 & 0 + +}; + +/** + * @brief Used in Byte 2 field of the set watchdog command + */ +enum TIMER_ACTIONS +{ + PRE_TIMEOUT_INT_SMI = 0x10, // bit 4 + PRE_TIMEOUT_INT_NMI = 0x20, // bit 5 + PRE_TIMEOUT_INT_MSG = 0x30, // bits 4 & 5 + TIMEOUT_HARD_RESET = 0x01, // bit 0 + TIMEOUT_PWR_DOWN = 0x02, // bit 1 + TIMEOUT_PWR_CYCLE = 0x03, // bits 0 & 1 + +}; + +/** + * @brief Used in Byte 4 field of the set watchdog command + * set to 1 to clear the flag set to 0 to leave alone + */ +enum TIMER_USE_CLR_FLAGS +{ + OEM_FLAG = 0x20, // bit 5 + SMS_OS_FLAG = 0x10, // bit 4 + OS_LOAD_FLAG = 0x08, // bit 3 + BIOS_POST_FLAG = 0x04, // bit 2 + BIOS_FRB2_FLAG = 0x02, // bit 1 + +}; + + +/******************************************************************************/ +// Functions +/******************************************************************************/ + +/** + * @brief Sets the ipmi watchdog timer on the BMC + * + * Called by hostboot to set a watchdog timer on the BMC + * @param[in] i_countdown_secs, initial countdown in seconds + * @param[in] i_timer_use, Sets watchdog timer use bits. + * @param[in] i_timer_action, Sets watchdog timer experation action. + * @param[in] i_timer_clr_flag, Sets the Watchdog interrupt flag to clear. + * @return none + */ + +errlHndl_t setWatchDogTimer( const uint16_t i_countdown_secs, + const uint8_t i_timer_use + = static_cast<uint8_t>(DO_NOT_STOP | BIOS_FRB2), + const TIMER_ACTIONS i_timer_action + = TIMEOUT_PWR_CYCLE, + const TIMER_USE_CLR_FLAGS i_timer_clr_flag + = BIOS_FRB2_FLAG); + +/** + * @brief Resets the ipmi watchdog timer on the BMC + * + * Called by hostboot to reset a watchdog timer countdown on the BMC. + * If the BMC returns an error code indicating the watchdog timer + * has not been started, this function will start the watchdog timer. + * + * @return error + */ +errlHndl_t resetWatchDogTimer(); + + +} // namespace + +#endif diff --git a/src/usr/diag/mdia/mdiasm.C b/src/usr/diag/mdia/mdiasm.C index eeefd3b05..d6846ff18 100644 --- a/src/usr/diag/mdia/mdiasm.C +++ b/src/usr/diag/mdia/mdiasm.C @@ -43,6 +43,8 @@ #include <targeting/common/utilFilter.H> #include <errl/errludlogregister.H> #include <initservice/istepdispatcherif.H> +#include <ipmi/ipmiwatchdog.H> +#include <config.h> using namespace TARGETING; using namespace ERRORLOG; @@ -1117,10 +1119,22 @@ bool StateMachine::processMaintCommandEvent(const MaintCommandEvent & i_event) eventType = SKIP_MBA; } - switch(eventType) +#ifdef CONFIG_BMC_IPMI + // Reset the watchdog timer after running each pattern + errlHndl_t err_ipmi = IPMIWATCHDOG::resetWatchDogTimer(); + + if(err_ipmi) { - case COMMAND_COMPLETE: + MDIA_FAST("sm executeWorkitem: IPMI reset watchdog failed"); + err_ipmi->collectTrace("MDIA_FAST",1024); + errlCommit(err_ipmi, MDIA_COMP_ID ); + + } +#endif + switch(eventType) + case COMMAND_COMPLETE: + { // command stopped or complete at end of last rank wfp.restartCommand = false; @@ -1129,13 +1143,13 @@ bool StateMachine::processMaintCommandEvent(const MaintCommandEvent & i_event) ++wfp.workItem; + // done with this maint command flags = DELETE_CMD | START_NEXT_CMD; wfp.data = NULL; break; - case COMMAND_STOPPED: // command stopped at end of some other rank diff --git a/src/usr/hwpf/hwp/start_payload/start_payload.C b/src/usr/hwpf/hwp/start_payload/start_payload.C index 2c90b1c7b..9c23ae2f9 100644 --- a/src/usr/hwpf/hwp/start_payload/start_payload.C +++ b/src/usr/hwpf/hwp/start_payload/start_payload.C @@ -86,6 +86,8 @@ #include <sys/mm.h> #include <algorithm> #include <config.h> +#include <ipmi/ipmiwatchdog.H> + // Uncomment these files as they become available: // #include "host_start_payload/host_start_payload.H" @@ -492,6 +494,48 @@ void* call_host_start_payload( void *io_pArgs ) task_affinity_unpin(); +#ifdef CONFIG_BMC_IPMI + + // TODO ISSUE 118082 + // ENABLE CODE BELOW ONCE OPAL COMPLETES ipmi WATCHDOG +#if 0 + //run the ipmi watchdog for a longer period to transition + // to opel + errlHndl_t err_ipmi = IPMIWATCHDOG::setWatchDogTimer( + IPMIWATCHDOG::DEFAULT_HB_OPAL_TRANSITION_COUNTDOWN); + + if(err_ipmi) + { + TRACFCOMP(ISTEPS_TRACE::g_trac_isteps_trace, + "init: ERROR: Set IPMI watchdog Failed"); + err_ipmi->collectTrace("ISTEPS_TRACE",256); + errlCommit(err_ipmi, ISTEP_COMP_ID ); + + } +#endif + + // TODO ISSUE 118082 + // REMOVE CODE BELOW ONCE OPAL COMPLETES IPMI WATCHDOG + // THE CODE BELOW STOPS THE IPMI TIMER FROM RUNNING + // TO PREVENT IT GETTING TRIGGERED DURING HB_OPAL TRANSITION + + // Call setWatchdogTimer without the default DON'T STOP + // flag to stop the watchdog timer + errlHndl_t err_ipmi = IPMIWATCHDOG::setWatchDogTimer( + IPMIWATCHDOG::DEFAULT_HB_OPAL_TRANSITION_COUNTDOWN, + IPMIWATCHDOG::BIOS_FRB2); + + if(err_ipmi) + { + TRACFCOMP(ISTEPS_TRACE::g_trac_isteps_trace, + "init: ERROR: Set IPMI watchdog Failed"); + err_ipmi->collectTrace("ISTEPS_TRACE",256); + errlCommit(err_ipmi, ISTEP_COMP_ID ); + + } + +#endif + // broadcast shutdown to other HB instances. l_errl = broadcastShutdown(this_node); diff --git a/src/usr/initservice/istepdispatcher/istepdispatcher.C b/src/usr/initservice/istepdispatcher/istepdispatcher.C index 6d0df0c3f..97c6d32be 100644 --- a/src/usr/initservice/istepdispatcher/istepdispatcher.C +++ b/src/usr/initservice/istepdispatcher/istepdispatcher.C @@ -65,6 +65,8 @@ #include <console/consoleif.H> #include <hwpisteperror.H> #include <pnor/pnorif.H> +#include <ipmi/ipmiwatchdog.H> //IPMI watchdog timer +#include <config.h> namespace ISTEPS_TRACE { @@ -215,6 +217,22 @@ void IStepDispatcher::init(errlHndl_t &io_rtaskRetErrl) } else { + +#ifdef CONFIG_BMC_IPMI + //run the ipmi watchdog in non istep mode only + errlHndl_t err_ipmi = IPMIWATCHDOG::setWatchDogTimer( + IPMIWATCHDOG::DEFAULT_WATCHDOG_COUNTDOWN); + + if(err_ipmi) + { + TRACFCOMP(g_trac_initsvc, + "init: ERROR: Set IPMI watchdog Failed"); + err_ipmi->collectTrace("INITSVC", 1024); + errlCommit(err_ipmi, INITSVC_COMP_ID ); + + } +#endif + // Non-IStep mode (run all isteps automatically) if(iv_spBaseServicesEnabled) { @@ -1628,6 +1646,20 @@ errlHndl_t IStepDispatcher::sendProgressCode(bool i_needsLock) CONSOLE::flush(); #endif +#ifdef CONFIG_BMC_IPMI + //Reset the watchdog before every istep + errlHndl_t err_ipmi = IPMIWATCHDOG::resetWatchDogTimer(); + + if(err_ipmi) + { + TRACFCOMP(g_trac_initsvc, + "init: ERROR: reset IPMI watchdog Failed"); + err_ipmi->collectTrace("INITSVC", 1024); + errlCommit(err_ipmi, INITSVC_COMP_ID ); + + } +#endif + msg_t * myMsg = msg_allocate(); myMsg->type = IPL_PROGRESS_CODE; myMsg->data[0] = iv_curIStep; diff --git a/src/usr/ipmi/ipmiwatchdog.C b/src/usr/ipmi/ipmiwatchdog.C new file mode 100644 index 000000000..354bd5324 --- /dev/null +++ b/src/usr/ipmi/ipmiwatchdog.C @@ -0,0 +1,149 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/usr/ipmi/ipmiwatchdog.C $ */ +/* */ +/* OpenPOWER HostBoot Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 2014 */ +/* [+] International Business Machines Corp. */ +/* */ +/* */ +/* Licensed under the Apache License, Version 2.0 (the "License"); */ +/* you may not use this file except in compliance with the License. */ +/* You may obtain a copy of the License at */ +/* */ +/* http://www.apache.org/licenses/LICENSE-2.0 */ +/* */ +/* Unless required by applicable law or agreed to in writing, software */ +/* distributed under the License is distributed on an "AS IS" BASIS, */ +/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */ +/* implied. See the License for the specific language governing */ +/* permissions and limitations under the License. */ +/* */ +/* IBM_PROLOG_END_TAG */ +#ifndef __IPMIWATCHDOG_IPMIWATCHDOG_C +#define __IPMIWATCHDOG_IPMIWATCHDOG_C +/** + * @file ipmiwatchdog.C + * + * Ipmi watchdog timer + * + */ + +/******************************************************************************/ +// Includes +/******************************************************************************/ +#include <stdint.h> +#include <errl/errlentry.H> +#include <ipmi/ipmiwatchdog.H> +#include <ipmi/ipmiif.H> +#include <sys/time.h> + +/******************************************************************************/ +// Globals/Constants +/******************************************************************************/ +// Defined in ipmidd.C +extern trace_desc_t * g_trac_ipmi; +#define IPMI_TRAC(printf_string,args...) \ + TRACFCOMP(g_trac_ipmi,"wd: "printf_string,##args) + +namespace IPMIWATCHDOG +{ + +/******************************************************************************/ +// Functions +/******************************************************************************/ + + +errlHndl_t setWatchDogTimer( const uint16_t i_countdown_secs, + const uint8_t i_timer_use, + const TIMER_ACTIONS i_timer_action, + const TIMER_USE_CLR_FLAGS i_timer_clr_flag) +{ + errlHndl_t err_ipmi = NULL; + + // 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; + static const uint8_t bits_to_shift_for_nxt_byte = 8; + static const uint8_t byte_mask = 0xFF; + + uint16_t countdown = (i_countdown_secs * MS_PER_SEC) + / ms_per_count; + + uint8_t init_countdown_lsb = static_cast<uint8_t> + (countdown & byte_mask); + + uint8_t init_countdown_msb = static_cast<uint8_t>( + (countdown >> bits_to_shift_for_nxt_byte) + & byte_mask); + + + size_t len = 6; // IPMI spec has request data at 6 bytes + + //create request data buffer + uint8_t* data = new uint8_t[len]; + + IPMI::completion_code cc = IPMI::CC_UNKBAD; + + data[0] = i_timer_use; // byte 1 timer use + data[1] = i_timer_action; // byte 2 timer actions + data[2] = 0x00; // byte 3 pre-interval timeout in secs + data[3] = i_timer_clr_flag; // byte 4 timer use flags to clear + data[4] = init_countdown_lsb; // byte 5 initial countdown timer LSByte + data[5] = init_countdown_msb; // byte 6 initial countdown timer MSByte + + err_ipmi = IPMI::sendrecv(IPMI::set_watchdog(), cc, len, data); + + //cleanup buffer + delete[] data; data = NULL; + + if(cc != IPMI::CC_OK) + { + IPMI_TRAC("Watchdog: BMC returned not ok CC[%x]",cc); + // should we log error and then retry? + // what happens if the communication is broken + // reset will try and set it again. + } + + return err_ipmi; +} + + +errlHndl_t resetWatchDogTimer() +{ + errlHndl_t err_ipmi = NULL; + + + // reset command does not take any request data + size_t len = 0; + uint8_t* data = NULL; + + + do + { + + // 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); + + if(err_ipmi) + { + //got an error sending IPMI msg + //progate error upstream. + break; + } + + } + while(0); + + return err_ipmi; +} + + +} // namespace + +#endif diff --git a/src/usr/ipmi/makefile b/src/usr/ipmi/makefile index 92cf4362b..730a340d5 100644 --- a/src/usr/ipmi/makefile +++ b/src/usr/ipmi/makefile @@ -31,6 +31,7 @@ OBJS += ipmirp.o OBJS += $(if $(CONFIG_BMC_BT_LPC_IPMI),ipmidd.o) OBJS += ipmiconfig.o OBJS += ipmisensor.o +OBJS += ipmiwatchdog.o #SUBDIRS += test.d |