summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/include/usr/isteps/nvdimm/nvdimmreasoncodes.H1
-rw-r--r--src/usr/isteps/nvdimm/nvdimm.C112
-rw-r--r--src/usr/isteps/nvdimm/nvdimm.H6
-rw-r--r--src/usr/targeting/common/xmltohb/attribute_types.xml15
-rw-r--r--src/usr/targeting/common/xmltohb/target_types.xml3
5 files changed, 132 insertions, 5 deletions
diff --git a/src/include/usr/isteps/nvdimm/nvdimmreasoncodes.H b/src/include/usr/isteps/nvdimm/nvdimmreasoncodes.H
index 3e311fa73..938361e54 100644
--- a/src/include/usr/isteps/nvdimm/nvdimmreasoncodes.H
+++ b/src/include/usr/isteps/nvdimm/nvdimmreasoncodes.H
@@ -97,6 +97,7 @@ enum nvdimmModuleId
NVDIMM_KEYIFY_RANDOM_NUMBER = 0x2F,
SET_ATTR_NVDIMM_ENCRYPTION_KEYS_FW = 0x30,
SEND_ATTR_NVDIMM_ARMED = 0x31,
+ NVDIMM_FACTORY_RESET = 0x32,
};
/**
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>
OpenPOWER on IntegriCloud