diff options
author | Dan Crowell <dcrowell@us.ibm.com> | 2019-07-03 08:28:24 -0500 |
---|---|---|
committer | Daniel M Crowell <dcrowell@us.ibm.com> | 2019-07-16 10:29:35 -0500 |
commit | d0e2fddc76ff2b6e80870fc233e4ce679a90db3b (patch) | |
tree | cfc20f21a3b3834cc4b300638d344c241d400bd6 /src/usr | |
parent | a22884e079eb16b2aaac1ae06c7a5963943ee2eb (diff) | |
download | blackbird-hostboot-d0e2fddc76ff2b6e80870fc233e4ce679a90db3b.tar.gz blackbird-hostboot-d0e2fddc76ff2b6e80870fc233e4ce679a90db3b.zip |
Add option to factory reset nvdimms
Added a factory reset function along with a overridable attribute
(ATTR_FORCE_NVDIMM_RESET) to trigger the reset during boot.
Change-Id: Ib39675e53d693ede897ace0f4432e104dcf8062e
Reviewed-on: http://rchgit01.rchland.ibm.com/gerrit1/80293
Tested-by: Jenkins Server <pfd-jenkins+hostboot@us.ibm.com>
Tested-by: Jenkins OP Build CI <op-jenkins+hostboot@us.ibm.com>
Tested-by: Jenkins OP HW <op-hw-jenkins+hostboot@us.ibm.com>
Tested-by: FSP CI Jenkins <fsp-CI-jenkins+hostboot@us.ibm.com>
Reviewed-by: Daniel M Crowell <dcrowell@us.ibm.com>
Diffstat (limited to 'src/usr')
-rw-r--r-- | src/usr/isteps/nvdimm/nvdimm.C | 112 | ||||
-rw-r--r-- | src/usr/isteps/nvdimm/nvdimm.H | 6 | ||||
-rw-r--r-- | src/usr/targeting/common/xmltohb/attribute_types.xml | 15 | ||||
-rw-r--r-- | src/usr/targeting/common/xmltohb/target_types.xml | 3 |
4 files changed, 131 insertions, 5 deletions
diff --git a/src/usr/isteps/nvdimm/nvdimm.C b/src/usr/isteps/nvdimm/nvdimm.C index 2b3b5d42d..53f5ae5fd 100644 --- a/src/usr/isteps/nvdimm/nvdimm.C +++ b/src/usr/isteps/nvdimm/nvdimm.C @@ -47,6 +47,8 @@ #ifdef __HOSTBOOT_RUNTIME #include <runtime/hbrt_utilities.H> #include <usr/runtime/rt_targeting.H> +#else +#include <initservice/istepdispatcherif.H> #endif using namespace TARGETING; @@ -1581,6 +1583,93 @@ void nvdimm_restore(TargetHandleList &i_nvdimmList) } /** + * @brief Force a factory reset of the NV logic and flash + * + * @param[in] i_nvdimm - NVDIMM Target + */ +errlHndl_t nvdimm_factory_reset(Target *i_nvdimm) +{ + TRACFCOMP(g_trac_nvdimm, ENTER_MRK"nvdimm_factory_reset() nvdimm[%X]", + get_huid(i_nvdimm)); + errlHndl_t l_err = nullptr; + + do + { + // Send the reset command + l_err = nvdimmWriteReg(i_nvdimm, NVDIMM_FUNC_CMD, FACTORY_DEFAULT); + if( l_err ) + { + break; + } + + // Poll 2 minutes for completion + // We could get the timeout value from the dimm but since we're + // doing a hard reset anyway I just want to use a big number that + // can handle any lies that the controller might tell us. + uint8_t l_data = 0; + constexpr uint64_t MAX_POLL_SECONDS = 120; + uint64_t poll = 0; + for( poll = 0; poll < MAX_POLL_SECONDS; poll++ ) + { + l_err = nvdimmReadReg(i_nvdimm, NVDIMM_CMD_STATUS0, l_data); + if( l_err ) + { + break; + } + + if( l_data != FACTORY_RESET_IN_PROGRESS ) + { + break; + } + +#ifndef __HOSTBOOT_RUNTIME + // kick the watchdog since this can take awhile + INITSERVICE::sendProgressCode(); +#endif + + // sleep 1 second + nanosleep(1, 0); + } + if( l_err ) { break; } + + // Make an error if it never finished + if( poll >= MAX_POLL_SECONDS ) + { + TRACFCOMP(g_trac_nvdimm, ERR_MRK"nvdimm_factory_reset() nvdimm[%X] - factory reset never completed[%d]", + get_huid(i_nvdimm), l_data); + /*@ + *@errortype + *@reasoncode NVDIMM_NOT_READY + *@severity ERRORLOG_SEV_UNRECOVERABLE + *@moduleid NVDIMM_FACTORY_RESET + *@userdata1[0:31] Ret value from ready register + *@userdata1[32:63] Target Huid + *@userdata2 Number of seconds waited + *@devdesc NVDIMM factory reset never completed + *@custdesc NVDIMM still in reset + */ + l_err = new ERRORLOG::ErrlEntry( + ERRORLOG::ERRL_SEV_UNRECOVERABLE, + NVDIMM_FACTORY_RESET, + NVDIMM_NOT_READY, + NVDIMM_SET_USER_DATA_1(l_data, get_huid(i_nvdimm)), + MAX_POLL_SECONDS, + ERRORLOG::ErrlEntry::NO_SW_CALLOUT ); + + l_err->collectTrace(NVDIMM_COMP_NAME); + + // If nvdimm is not ready for access by now, this is + // a failing indication on the NV controller + l_err->addPartCallout( i_nvdimm, + HWAS::NV_CONTROLLER_PART_TYPE, + HWAS::SRCI_PRIORITY_HIGH); + } + } while(0); + + return l_err; +} + +/** * @brief NVDIMM initialization * - Checks for ready state * - Gathers timeout values @@ -1600,12 +1689,29 @@ void nvdimm_init(Target *i_nvdimm) do { + // Force a factory reset if told to via attribute override + // This will allow us to recover from bad images, lost keys, etc + Target* l_sys = nullptr; + targetService().getTopLevelTarget( l_sys ); + assert(l_sys, "nvdimm_init: no TopLevelTarget"); + if( l_sys->getAttr<ATTR_FORCE_NVDIMM_RESET>() ) + { + l_err = nvdimm_factory_reset(i_nvdimm); + if (l_err) + { + nvdimmSetStatusFlag(i_nvdimm, NSTD_ERR); + TRACFCOMP(g_trac_nvdimm, ERR_MRK"nvdimm_init() nvdimm[%X], factory reset failed", + get_huid(i_nvdimm)); + errlCommit(l_err, NVDIMM_COMP_ID); + } + } + l_err = nvdimmReady(i_nvdimm); if (l_err) { nvdimmSetStatusFlag(i_nvdimm, NSTD_ERR); - TRACFCOMP(g_trac_nvdimm, ERR_MRK"nvdimm_int() nvdimm[%X], controller not ready", + TRACFCOMP(g_trac_nvdimm, ERR_MRK"nvdimm_init() nvdimm[%X], controller not ready", get_huid(i_nvdimm)); errlCommit(l_err, NVDIMM_COMP_ID); break; @@ -1616,7 +1722,7 @@ void nvdimm_init(Target *i_nvdimm) if (l_err) { nvdimmSetStatusFlag(i_nvdimm, NSTD_ERR); - TRACFCOMP(g_trac_nvdimm, ERR_MRK"nvdimm_int() nvdimm[%X], error retrieving timeout values", + TRACFCOMP(g_trac_nvdimm, ERR_MRK"nvdimm_init() nvdimm[%X], error retrieving timeout values", get_huid(i_nvdimm)); errlCommit(l_err, NVDIMM_COMP_ID); break; @@ -1629,7 +1735,7 @@ void nvdimm_init(Target *i_nvdimm) if (l_err) { nvdimmSetStatusFlag(i_nvdimm, NSTD_ERR_NOPRSV); - TRACFCOMP(g_trac_nvdimm, ERR_MRK"nvdimm_int() nvdimm[%X], error backing up the DRAM!", + TRACFCOMP(g_trac_nvdimm, ERR_MRK"nvdimm_init() nvdimm[%X], error backing up the DRAM!", get_huid(i_nvdimm)); errlCommit(l_err, NVDIMM_COMP_ID); break; diff --git a/src/usr/isteps/nvdimm/nvdimm.H b/src/usr/isteps/nvdimm/nvdimm.H index 1eb9f89dc..d5253889d 100644 --- a/src/usr/isteps/nvdimm/nvdimm.H +++ b/src/usr/isteps/nvdimm/nvdimm.H @@ -122,11 +122,11 @@ enum i2cReg : uint16_t SET_ES_POLICY_STATUS = 0x070, FIRMWARE_OPS_STATUS = 0x071, OPERATIONAL_UNIT_OPS_STATUS = 0x072, - RESTORE_FAIL_INFO = 0x088, - OPERATIONAL_UNIT_FAIL_INFO = 0x08F, CSAVE_INFO = 0x080, CSAVE_FAIL_INFO0 = 0x084, CSAVE_FAIL_INFO1 = 0x085, + RESTORE_FAIL_INFO = 0x088, + OPERATIONAL_UNIT_FAIL_INFO = 0x08F, NVM_LIFETIME_ERROR_THRESHOLD = 0x090, ES_LIFETIME_ERROR_THRESHOLD = 0x091, ES_TEMP_ERROR_HIGH_THRESHOLD0 = 0x094, @@ -320,6 +320,7 @@ enum i2c_in_values : uint8_t RESET_CTRLR = 0x01, VALID_IMAGE = 0x01, RESET_CONTROLLER = 0x01, + FACTORY_DEFAULT = 0x01, }; enum i2c_out_values : uint8_t @@ -336,6 +337,7 @@ enum i2c_out_values : uint8_t ES_SUCCESS = 0x05, CHARGE_SUCCESS = 0x00, NV_READY = 0xA5, + FACTORY_RESET_IN_PROGRESS = 0x03, }; // Timeout-related enum diff --git a/src/usr/targeting/common/xmltohb/attribute_types.xml b/src/usr/targeting/common/xmltohb/attribute_types.xml index ff9abf83b..b000c92d5 100644 --- a/src/usr/targeting/common/xmltohb/attribute_types.xml +++ b/src/usr/targeting/common/xmltohb/attribute_types.xml @@ -1734,6 +1734,21 @@ </attribute> <attribute> + <description> + Lab-only trigger to force a factory reset of the NVDIMMs. + NOTE: This will erase any saved image and encryption keys. + </description> + <id>FORCE_NVDIMM_RESET</id> + <persistency>volatile-zeroed</persistency> + <readable/> + <simpleType> + <uint8_t> + <default>0</default> + </uint8_t> + </simpleType> + </attribute> + + <attribute> <id>FREQ_CORE_CEILING_MHZ</id> <description> The maximum core frequency in MHz. diff --git a/src/usr/targeting/common/xmltohb/target_types.xml b/src/usr/targeting/common/xmltohb/target_types.xml index ef5fbc8d6..083819728 100644 --- a/src/usr/targeting/common/xmltohb/target_types.xml +++ b/src/usr/targeting/common/xmltohb/target_types.xml @@ -1848,6 +1848,9 @@ <id>FIELD_TH_P8EX_L3_LINE_DELETES</id> </attribute> <attribute> + <id>FORCE_NVDIMM_RESET</id> + </attribute> + <attribute> <id>FREQ_CORE_CEILING_MHZ</id> </attribute> <attribute> |