diff options
-rw-r--r-- | src/include/usr/i2c/nvdimmif.H | 9 | ||||
-rw-r--r-- | src/include/usr/isteps/nvdimm/nvdimm.H | 60 | ||||
-rw-r--r-- | src/include/usr/targeting/common/util.H | 11 | ||||
-rwxr-xr-x | src/usr/i2c/eepromdd.C | 3 | ||||
-rwxr-xr-x | src/usr/i2c/nvdimmdd.C | 56 | ||||
-rw-r--r-- | src/usr/isteps/istep14/call_mss_power_cleanup.C | 35 | ||||
-rw-r--r-- | src/usr/isteps/nvdimm/makefile | 25 | ||||
-rw-r--r-- | src/usr/isteps/nvdimm/nvdimm.C | 94 | ||||
-rw-r--r-- | src/usr/isteps/nvdimm/nvdimm.H | 17 | ||||
-rw-r--r-- | src/usr/isteps/nvdimm/nvdimm.mk | 46 | ||||
-rw-r--r-- | src/usr/isteps/pm/runtime/makefile | 7 | ||||
-rw-r--r-- | src/usr/isteps/pm/runtime/rt_pm.C | 45 | ||||
-rw-r--r-- | src/usr/targeting/common/util.C | 45 |
13 files changed, 259 insertions, 194 deletions
diff --git a/src/include/usr/i2c/nvdimmif.H b/src/include/usr/i2c/nvdimmif.H index fb875149f..2b60ac4de 100644 --- a/src/include/usr/i2c/nvdimmif.H +++ b/src/include/usr/i2c/nvdimmif.H @@ -30,15 +30,6 @@ namespace NVDIMM { -//TODO: move isNVDIMM() to targeting/common/util.C -/** - * @brief Determine if the given dimm target is an NVDIMM - * - * @param[in] i_target : dimm target to check - * - * @return bool - True if the given target is an NVDIMM - */ -bool isNVDIMM( TARGETING::Target * i_target ); /** * @brief Return a set of information related to every unique diff --git a/src/include/usr/isteps/nvdimm/nvdimm.H b/src/include/usr/isteps/nvdimm/nvdimm.H index 3c448a9ac..bfe39fcd0 100644 --- a/src/include/usr/isteps/nvdimm/nvdimm.H +++ b/src/include/usr/isteps/nvdimm/nvdimm.H @@ -22,14 +22,26 @@ /* permissions and limitations under the License. */ /* */ /* IBM_PROLOG_END_TAG */ -#ifndef NVDIMM_H__ -#define NVDIMM_H__ +#ifndef NVDIMM_EXT_H__ +#define NVDIMM_EXT_H__ #include <targeting/common/util.H> namespace NVDIMM { - +enum +{ + NSTD_VAL_NOPRSV = 0x08, // memory valid, contents not preserved (genesis) + NSTD_VAL_NOPRSV_MASK = 0xF7, + NSTD_VAL_PRSV = 0x04, // memory contents preserved + NSTD_VAL_PRSV_MASK = 0xFB, + NSTD_ERR_NOPRSV = 0x02, // memory failed to preserve contents + NSTD_ERR_NOPRSV_MASK = 0xFD, + NSTD_ERR_NOBKUP = 0x01, // memory unable to preserve future content + NSTD_ERR_NOBKUP_MASK = 0xFE, + NSTD_ERR = 0x03, // NSTD_ERR_NOPRSV+NSTD_ERR_NOBKUP +}; +#ifndef __HOSTBOOT_RUNTIME /** * @brief Entry function to NVDIMM management * - Restore image from NVDIMM NAND flash to DRAM @@ -41,8 +53,48 @@ namespace NVDIMM * **/ void nvdimm_restore(TARGETING::TargetHandleList &i_nvdimmList); +#endif + +/** + * @brief This function arms the trigger to enable backup in the event + * of power loss (DDR Reset_n goes low) + * + * @param[in] i_nvdimm - nvdimm target with NV controller + * + * @return errlHndl_t - Null if successful, otherwise a pointer to + * the error log. + */ +errlHndl_t nvdimmArmResetN(TARGETING::Target *i_nvdimm); + +/** + * @brief This function erases image on the nvdimm target + * + * @param[in] i_nvdimm - nvdimm target with NV controller + * + * @return errlHndl_t - Null if successful, otherwise a pointer to + * the error log. + */ +errlHndl_t nvdimmEraseNF(TARGETING::Target *i_nvdimm); + +/** + * @brief Check nvdimm error state + * + * @param[in] i_nvdimm - nvdimm target + * + * @return bool - true if nvdimm is in any error state, false otherwise + */ +bool nvdimmInErrorState(TARGETING::Target *i_nvdimm); +/** + * @brief Set the status flag + * + * @param[in] i_nvdimm - nvdimm target + * + * @param[in] i_status_flag - status flag to set for each nvdimm + * + */ +void nvdimmSetStatusFlag(TARGETING::Target *i_nvdimm, const uint8_t i_status_flag); } -#endif // NVDIMM_H__ +#endif // NVDIMM_EXT_H__ diff --git a/src/include/usr/targeting/common/util.H b/src/include/usr/targeting/common/util.H index 68b61b1f1..971408d16 100644 --- a/src/include/usr/targeting/common/util.H +++ b/src/include/usr/targeting/common/util.H @@ -172,6 +172,15 @@ bool orderByNodeAndPosition( Target* i_firstProc, */ uint8_t is_fused_mode( ); -} // TARGETING +/** + * @brief Determine if the given dimm target is an NVDIMM + * + * @param[in] i_target : dimm target to check + * + * @return bool - True if the given target is an NVDIMM + */ +bool isNVDIMM( TARGETING::Target * i_target ); + +} #endif // __TARGETING_COMMON_UTIL_H diff --git a/src/usr/i2c/eepromdd.C b/src/usr/i2c/eepromdd.C index c1cbf45c8..8f94e0c3b 100755 --- a/src/usr/i2c/eepromdd.C +++ b/src/usr/i2c/eepromdd.C @@ -43,6 +43,7 @@ #include <errl/errludtarget.H> #include <errl/errludstring.H> #include <targeting/common/targetservice.H> +#include <targeting/common/util.H> #include <devicefw/driverif.H> #include <i2c/eepromddreasoncodes.H> #include <i2c/eepromif.H> @@ -2100,7 +2101,7 @@ void getEEPROMs( std::list<EepromInfo_t>& o_info ) { #ifdef CONFIG_NVDIMM // Skip if this is an NVDIMM as this will get added later - if (NVDIMM::isNVDIMM( *dimm_itr )) + if (TARGETING::isNVDIMM( *dimm_itr )) continue; #endif add_to_list( o_info, *dimm_itr ); diff --git a/src/usr/i2c/nvdimmdd.C b/src/usr/i2c/nvdimmdd.C index 6afac1d18..b70fd0915 100755 --- a/src/usr/i2c/nvdimmdd.C +++ b/src/usr/i2c/nvdimmdd.C @@ -43,6 +43,7 @@ #include <errl/errludstring.H> #include <targeting/common/targetservice.H> #include <targeting/common/utilFilter.H> +#include <targeting/common/util.H> #include <devicefw/driverif.H> #include <i2c/nvdimmddreasoncodes.H> #include <i2c/nvdimmif.H> @@ -75,8 +76,6 @@ TRAC_INIT( & g_trac_nvdimmr, "NVDIMMR", KILOBYTE ); // ---------------------------------------------- #define MAX_BYTE_ADDR 2 #define NVDIMM_MAX_RETRIES 2 -#define MCA_PER_MCS 2 -#define DIMM_PER_MCA 2 // ---------------------------------------------- @@ -498,10 +497,10 @@ errlHndl_t nvdimmReadData( TARGETING::Target * i_target, i_byteAddressSize); // Printing mux info separately, if combined, nothing is displayed - char* l_muxPath = i2cInfo.i2cMuxPath.toString(); + char* l_muxPath = i_i2cInfo.i2cMuxPath.toString(); TRACFCOMP(g_trac_nvdimm, ERR_MRK"nvdimmReadData(): " "muxSelector=0x%X, muxPath=%s", - i2cInfo.i2cMuxBusSelector, + i_i2cInfo.i2cMuxBusSelector, l_muxPath); free(l_muxPath); l_muxPath = nullptr; @@ -535,10 +534,10 @@ errlHndl_t nvdimmReadData( TARGETING::Target * i_target, i_i2cInfo.devAddr ); // Printing mux info separately, if combined, nothing is displayed - char* l_muxPath = i2cInfo.i2cMuxPath.toString(); + char* l_muxPath = i_i2cInfo.i2cMuxPath.toString(); TRACFCOMP(g_trac_nvdimm, ERR_MRK"nvdimmReadData(): " "muxSelector=0x%X, muxPath=%s", - i2cInfo.i2cMuxBusSelector, + i_i2cInfo.i2cMuxBusSelector, l_muxPath); free(l_muxPath); l_muxPath = nullptr; @@ -1459,49 +1458,6 @@ void add_to_list( std::list<EEPROM::EepromInfo_t>& i_list, } /** - * @brief Determine if the given dimm target is an NVDIMM - * - * @param[in] i_target : dimm target to check - * - * @return bool - True if the given target is an NVDIMM - */ -bool isNVDIMM( TARGETING::Target * i_target ) -{ - // Not the most elegant way of doing it but the hybrid attributes - // are at the MCS level. Need to find my way up to MCS and check - // if the dimm is hybrid - - TARGETING::TargetHandleList l_mcaList; - getParentAffinityTargets(l_mcaList, i_target, TARGETING::CLASS_UNIT, TARGETING::TYPE_MCA); - - if (l_mcaList.size()) - { - TARGETING::TargetHandleList l_mcsList; - getParentAffinityTargets(l_mcsList, l_mcaList[0], TARGETING::CLASS_UNIT, TARGETING::TYPE_MCS); - - if(l_mcsList.size()) - { - // 2-D array. [MCA][DIMM] - TARGETING::ATTR_EFF_HYBRID_type l_hybrid; - TARGETING::ATTR_EFF_HYBRID_MEMORY_TYPE_type l_hybrid_type; - - if( l_mcsList[0]->tryGetAttr<TARGETING::ATTR_EFF_HYBRID>(l_hybrid) && - l_mcsList[0]->tryGetAttr<TARGETING::ATTR_EFF_HYBRID_MEMORY_TYPE>(l_hybrid_type) ) - { - //Using huid to lookup the hybrid attribute for the current dimm - const auto l_dimm_huid = TARGETING::get_huid(i_target); - const auto l_mca_huid = TARGETING::get_huid(l_mcaList[0]); - - return (l_hybrid[l_mca_huid%MCA_PER_MCS][l_dimm_huid%DIMM_PER_MCA] == TARGETING::EFF_HYBRID_IS_HYBRID && - l_hybrid_type[l_mca_huid%MCA_PER_MCS][l_dimm_huid%DIMM_PER_MCA] == TARGETING::EFF_HYBRID_MEMORY_TYPE_NVDIMM); - } - } - } - - return false; -} - -/** * @brief Return a set of information related to every unique * NVDIMM in the system */ @@ -1517,7 +1473,7 @@ void getNVDIMMs( std::list<EEPROM::EepromInfo_t>& o_info ) for (auto const l_dimm : l_dimmList) { - if (isNVDIMM(l_dimm)) + if (TARGETING::isNVDIMM(l_dimm)) add_to_list( o_info, l_dimm ); } diff --git a/src/usr/isteps/istep14/call_mss_power_cleanup.C b/src/usr/isteps/istep14/call_mss_power_cleanup.C index 861647e09..5c27dcc67 100644 --- a/src/usr/isteps/istep14/call_mss_power_cleanup.C +++ b/src/usr/isteps/istep14/call_mss_power_cleanup.C @@ -116,40 +116,9 @@ void* call_mss_power_cleanup (void *io_pArgs) // Walk the dimm list and collect all the nvdimm targets for (auto const l_dimm : l_dimmTargetList) { - //@TODO replace this with isNVDIMM() - // Not the most elegant way of doing it but the hybrid attributes - // are at the MCS level. Need to find my way up to MCS and check - // if the dimm is hybrid - TARGETING::TargetHandleList l_mcaList; - getParentAffinityTargets(l_mcaList, l_dimm, TARGETING::CLASS_UNIT, TARGETING::TYPE_MCA); - - if (l_mcaList.size()) + if (TARGETING::isNVDIMM(l_dimm)) { - TARGETING::TargetHandleList l_mcsList; - getParentAffinityTargets(l_mcsList, l_mcaList[0], TARGETING::CLASS_UNIT, TARGETING::TYPE_MCS); - - if(l_mcsList.size()) - { - // 2-D array. [MCA][DIMM] - TARGETING::ATTR_EFF_HYBRID_type l_hybrid; - TARGETING::ATTR_EFF_HYBRID_MEMORY_TYPE_type l_hybrid_type; - - if( l_mcsList[0]->tryGetAttr<TARGETING::ATTR_EFF_HYBRID>(l_hybrid) && - l_mcsList[0]->tryGetAttr<TARGETING::ATTR_EFF_HYBRID_MEMORY_TYPE>(l_hybrid_type) ) - { - //Using huid to lookup the hybrid attribute for the current dimm - const auto l_dimm_huid = TARGETING::get_huid(l_dimm); - const auto l_mca_huid = TARGETING::get_huid(l_mcaList[0]); - const uint8_t MCA_PER_MCS = 2; - const uint8_t DIMM_PER_MCA = 2; - - if (l_hybrid[l_mca_huid%MCA_PER_MCS][l_dimm_huid%DIMM_PER_MCA] == TARGETING::EFF_HYBRID_IS_HYBRID && - l_hybrid_type[l_mca_huid%MCA_PER_MCS][l_dimm_huid%DIMM_PER_MCA] == TARGETING::EFF_HYBRID_MEMORY_TYPE_NVDIMM ) - { - l_nvdimmTargetList.push_back(l_dimm); - } - } - } + l_nvdimmTargetList.push_back(l_dimm); } } diff --git a/src/usr/isteps/nvdimm/makefile b/src/usr/isteps/nvdimm/makefile index a39be6f0e..ae3cae843 100644 --- a/src/usr/isteps/nvdimm/makefile +++ b/src/usr/isteps/nvdimm/makefile @@ -24,30 +24,7 @@ # IBM_PROLOG_END_TAG ROOTPATH = ../../../.. -PROCEDURE_PATH = ${ROOTPATH}/src/import/chips/p9/procedures - -#Add all the extra include paths - -EXTRAINCDIR += ${ROOTPATH}/obj/genfiles/ -EXTRAINCDIR += ${ROOTPATH}/src/import/hwpf/fapi2/include -EXTRAINCDIR += ${ROOTPATH}/src/include/usr/fapi2 -EXTRAINCDIR += ${ROOTPATH}/src/import/chips/common/utils/imageProcs/ -EXTRAINCDIR += ${ROOTPATH}/src/import/ -EXTRAINCDIR += ${PROCEDURE_PATH}/hwp/memory -EXTRAINCDIR += ${ROOTPATH}/src/import/chips/p9/common/include/ -EXTRAINCDIR += ${PROCEDURE_PATH}/hwp/memory/lib/eff_config/ -EXTRAINCDIR += ${PROCEDURE_PATH}/hwp/memory/lib/ -EXTRAINCDIR += ${PROCEDURE_PATH}/hwp/memory/lib/mcbist/ -EXTRAINCDIR += ${PROCEDURE_PATH}/hwp/memory/lib/dimm/ -EXTRAINCDIR += ${PROCEDURE_PATH}/hwp/memory/lib/dimm/ddr4/ -EXTRAINCDIR += ${PROCEDURE_PATH}/hwp/memory/ -EXTRAINCDIR += ${PROCEDURE_PATH}/hwp/ffdc/ - MODULE = nvdimm -OBJS += nvdimm.o - +include nvdimm.mk include ${ROOTPATH}/config.mk - -VPATH += ${PROCEDURE_PATH}/hwp/memory/ -VPATH += ${PROCEDURE_PATH}/hwp/memory/lib/dimm/ddr4/ diff --git a/src/usr/isteps/nvdimm/nvdimm.C b/src/usr/isteps/nvdimm/nvdimm.C index d98397edb..13ecf0af5 100644 --- a/src/usr/isteps/nvdimm/nvdimm.C +++ b/src/usr/isteps/nvdimm/nvdimm.C @@ -5,7 +5,7 @@ /* */ /* OpenPOWER HostBoot Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2014,2018 */ +/* Contributors Listed Below - COPYRIGHT 2014,2019 */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -32,12 +32,12 @@ #include <targeting/common/commontargeting.H> #include <targeting/common/util.H> #include <targeting/common/utilFilter.H> -#include <kernel/timemgr.H> #include <sys/time.h> #include <usr/devicefw/userif.H> #include <fapi2.H> #include <fapi2/plat_hwp_invoker.H> #include <lib/dimm/ddr4/nvdimm_utils.H> +#include <lib/mc/port.H> #include <isteps/nvdimm/nvdimm.H> using namespace TARGETING; @@ -45,7 +45,7 @@ using namespace DeviceFW; using namespace EEPROM; trace_desc_t* g_trac_nvdimm = NULL; -TRAC_INIT(&g_trac_nvdimm, "NVDIMM", 2*KILOBYTE); +TRAC_INIT(&g_trac_nvdimm, NVDIMM_COMP_NAME, 2*KILOBYTE); // Easy macro replace for unit testing // #define TRACUCOMP(args...) TRACFCOMP(args) @@ -61,19 +61,6 @@ namespace NVDIMM #define NVDIMM_SET_USER_DATA_2_TIMEOUT(left_32_polled, right_32_timeout) \ NVDIMM_SET_USER_DATA_1(left_32_polled, right_32_timeout) -enum -{ - NSTD_VAL_NOPRSV = 0x08, // memory valid, contents not preserved (genesis) - NSTD_VAL_NOPRSV_MASK = 0xF7, - NSTD_VAL_PRSV = 0x04, // memory contents preserved - NSTD_VAL_PRSV_MASK = 0xFB, - NSTD_ERR_NOPRSV = 0x02, // memory failed to preserve contents - NSTD_ERR_NOPRSV_MASK = 0xFD, - NSTD_ERR_NOBKUP = 0x01, // memory unable to preserve future content - NSTD_ERR_NOBKUP_MASK = 0xFE, - NSTD_ERR = 0x03, // NSTD_ERR_NOPRSV+NSTD_ERR_NOBKUP -}; - typedef struct ops_timeoutInfo{ const char * desc; uint8_t page; @@ -83,7 +70,10 @@ typedef struct ops_timeoutInfo{ uint8_t status_progress; } ops_timeoutInfo_t; -static bool init = true; +#ifndef __HOSTBOOT_RUNTIME +// Init flag to be used upon initial entry to initialize NV_OPS_TIMEOUT_MSEC +static bool init_nv_timeout = true; +#endif // Table containing register info on the timeout registers for different ops constexpr ops_timeoutInfo_t timeoutInfoTable[] = @@ -686,7 +676,10 @@ errlHndl_t nvdimmCheckArmSuccess(Target *i_nvdimm) /** * @brief This function arms the trigger to enable backup in the event - * of power loss (DDR Reset_n goes low) + * of power loss (DDR Reset_n goes low) in conjunction with + * ATOMIC_SAVE_AND_ERASE. A separate erase command is not required + * as the image will get erased immediately before backup on the + * next catastrophic event. * * @param[in] i_nvdimm - nvdimm target with NV controller * @@ -700,7 +693,10 @@ errlHndl_t nvdimmArmResetN(Target *i_nvdimm) errlHndl_t l_err = nullptr; - l_err = nvdimmWriteReg(i_nvdimm, ARM_CMD, ARM_DIMM); + // Setting ATOMIC_SAVE_AND_ERASE in conjunction with ARM_RESETN. With this, + // the content of the persistent data is not erased until immediately after + // the next catastrophic event has occurred. + l_err = nvdimmWriteReg(i_nvdimm, ARM_CMD, ARM_RESETN_AND_ATOMIC_SAVE_AND_ERASE); if (l_err) { @@ -760,6 +756,7 @@ errlHndl_t nvdimmValidImage(Target *i_nvdimm, bool &o_imgValid) return l_err; } +#ifndef __HOSTBOOT_RUNTIME /** * @brief This function handles all the restore related operations. * SRE -> restore -> SRX/RCD/MRS @@ -775,6 +772,8 @@ errlHndl_t nvdimmRestore(TargetHandleList i_nvdimmList) bool l_imgValid; uint8_t l_rstrValid; uint32_t l_poll = 0; + TARGETING::Target* l_sys = NULL; + targetService().getTopLevelTarget(l_sys); do { @@ -864,9 +863,9 @@ errlHndl_t nvdimmRestore(TargetHandleList i_nvdimmList) //@TODO RTC 199645 - add HW callout on dimm target //Restore is taking longer than the allotted time here. nvdimmSetStatusFlag(l_nvdimm, NSTD_ERR_NOPRSV); - errlCommit(l_err, NVDIMM_COMP_ID); TRACFCOMP(g_trac_nvdimm, ERR_MRK"NDVIMM HUID[%X], error restoring!", TARGETING::get_huid(l_nvdimm)); + errlCommit(l_err, NVDIMM_COMP_ID); break; } } @@ -963,6 +962,7 @@ errlHndl_t nvdimmRestore(TargetHandleList i_nvdimmList) return l_err; } +#endif /** * @brief This function checks the erase status register to make sure @@ -1249,6 +1249,7 @@ errlHndl_t nvdimmGetTimeoutVal(Target* i_nvdimm) return l_err; } +#ifndef __HOSTBOOT_RUNTIME /** * @brief Entry function to NVDIMM management * - Restore image from NVDIMM NAND flash to DRAM @@ -1261,7 +1262,7 @@ errlHndl_t nvdimmGetTimeoutVal(Target* i_nvdimm) */ void nvdimm_restore(TargetHandleList &i_nvdimmList) { - TRACUCOMP(g_trac_nvdimm, ENTER_MRK"nvdimm_restore()"); + TRACFCOMP(g_trac_nvdimm, ENTER_MRK"nvdimm_restore()"); errlHndl_t l_err = nullptr; do @@ -1283,13 +1284,12 @@ void nvdimm_restore(TargetHandleList &i_nvdimmList) if (l_err) { - errlCommit( l_err, NVDIMM_COMP_ID ); - // @TODO-RTC:200275-Make logic generic for all system configs // Because of interleaving, if one is garded the other one // in the pair should be garded by association. So, let's // move on since there is nothing else to do. TRACFCOMP(g_trac_nvdimm, ERR_MRK"nvdimm_restore() - Failing open page"); + errlCommit( l_err, NVDIMM_COMP_ID ); break; } @@ -1310,9 +1310,8 @@ void nvdimm_restore(TargetHandleList &i_nvdimmList) // If this failing right off the bat, // something isn't quite right with // the module - errlCommit(l_err, NVDIMM_COMP_ID); - TRACFCOMP(g_trac_nvdimm, ERR_MRK"nvdimm_restore() - Failing nvdimmReady()"); + errlCommit(l_err, NVDIMM_COMP_ID); break; } @@ -1328,13 +1327,13 @@ void nvdimm_restore(TargetHandleList &i_nvdimmList) // This will prevent future backup, but let's continue // since we can still restore the data if there is any nvdimmSetStatusFlag(l_nvdimm, NSTD_ERR_NOBKUP); - errlCommit( l_err, NVDIMM_COMP_ID ); TRACFCOMP(g_trac_nvdimm, ERR_MRK"nvdimm_restore() - Failing nvdimmSetESPolicy()"); + errlCommit( l_err, NVDIMM_COMP_ID ); } } // Get the timeout values for the major ops at init - if (init){ + if (init_nv_timeout){ for (const auto & l_nvdimm : i_nvdimmList){ l_err = nvdimmGetTimeoutVal(l_nvdimm); if (l_err) @@ -1343,13 +1342,13 @@ void nvdimm_restore(TargetHandleList &i_nvdimmList) break; } } - init = false; + init_nv_timeout = false; } if (l_err) { - errlCommit( l_err, NVDIMM_COMP_ID ); TRACFCOMP(g_trac_nvdimm, ERR_MRK"nvdimm_restore() - Failing nvdimmGetTimeoutVal()"); + errlCommit( l_err, NVDIMM_COMP_ID ); break; } @@ -1368,8 +1367,8 @@ void nvdimm_restore(TargetHandleList &i_nvdimmList) if (l_err) { - errlCommit( l_err, NVDIMM_COMP_ID ); TRACFCOMP(g_trac_nvdimm, ERR_MRK"nvdimm_restore() - Failing open page"); + errlCommit( l_err, NVDIMM_COMP_ID ); break; } @@ -1378,8 +1377,8 @@ void nvdimm_restore(TargetHandleList &i_nvdimmList) if (l_err) { - errlCommit( l_err, NVDIMM_COMP_ID ); TRACFCOMP(g_trac_nvdimm, ERR_MRK"nvdimm_restore() - Failing nvdimmRestore()"); + errlCommit( l_err, NVDIMM_COMP_ID ); break; } @@ -1397,39 +1396,10 @@ void nvdimm_restore(TargetHandleList &i_nvdimmList) } } - // @TODO move arm and erase to pm_common.C, after occ has started - - // From this point forward, we only want to set up the trigger on the - // nvdimm that is not in error state. Any nvdimm in error state will - // get to preserve the data previously saved and recover if needed. - - // Arm the nvdimm to trigger save on RESET_n - // and erase the image - for (const auto & l_nvdimm : i_nvdimmList) - { - // skip if the nvdimm is in error state - if (nvdimmInErrorState(l_nvdimm)) - { - continue; - } - - l_err = nvdimmArmResetN(l_nvdimm); - if (l_err) - { - nvdimmSetStatusFlag(l_nvdimm, NSTD_ERR_NOBKUP); - errlCommit( l_err, NVDIMM_COMP_ID ); - continue; - } - - l_err = nvdimmEraseNF(l_nvdimm); - if (l_err){ - errlCommit( l_err, NVDIMM_COMP_ID ); - nvdimmSetStatusFlag(l_nvdimm, NSTD_ERR_NOBKUP); - } - } }while(0); - TRACUCOMP(g_trac_nvdimm, EXIT_MRK"nvdimm_restore()"); + TRACFCOMP(g_trac_nvdimm, EXIT_MRK"nvdimm_restore()"); } +#endif } // end NVDIMM namespace diff --git a/src/usr/isteps/nvdimm/nvdimm.H b/src/usr/isteps/nvdimm/nvdimm.H index 12a2ee2aa..b365c405b 100644 --- a/src/usr/isteps/nvdimm/nvdimm.H +++ b/src/usr/isteps/nvdimm/nvdimm.H @@ -5,7 +5,7 @@ /* */ /* OpenPOWER HostBoot Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2014,2018 */ +/* Contributors Listed Below - COPYRIGHT 2014,2019 */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -75,13 +75,13 @@ enum page : uint8_t // Enums for inputs/expected output to/from the i2c registers enum i2c_in_values : uint8_t { - ARM_DIMM = 0x04, //0x04 to trigger on RESET_n - ES_DEV_MANAGE = 0x01, //0x01 for device manage - ERASE_IMAGE = 0x08, - RESTORE_IMAGE = 0x04, - RESET_CTRLR = 0x01, - VALID_IMAGE = 0x01, - PAGE_SWITCH_POLL_TIME_NS = 100, + ARM_RESETN_AND_ATOMIC_SAVE_AND_ERASE = 0x84, + ARM_RESETN = 0x04, + ES_DEV_MANAGE = 0x01, //0x01 for device manage + ERASE_IMAGE = 0x08, + RESTORE_IMAGE = 0x04, + RESET_CTRLR = 0x01, + VALID_IMAGE = 0x01, }; enum i2c_out_values : uint8_t @@ -104,6 +104,7 @@ enum i2c_out_values : uint8_t enum timeout : uint32_t { OPS_POLL_TIME_MS = 5000, + PAGE_SWITCH_POLL_TIME_NS = 100, }; // Assign an id to each of the 6 major ops diff --git a/src/usr/isteps/nvdimm/nvdimm.mk b/src/usr/isteps/nvdimm/nvdimm.mk new file mode 100644 index 000000000..0c09584d5 --- /dev/null +++ b/src/usr/isteps/nvdimm/nvdimm.mk @@ -0,0 +1,46 @@ +# IBM_PROLOG_BEGIN_TAG +# This is an automatically generated prolog. +# +# $Source: src/usr/isteps/nvdimm/nvdimm.mk $ +# +# OpenPOWER HostBoot Project +# +# Contributors Listed Below - COPYRIGHT 2018 +# [+] 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 +PROCEDURE_PATH = ${ROOTPATH}/src/import/chips/p9/procedures + +#Add all the extra include paths + +EXTRAINCDIR += ${ROOTPATH}/obj/genfiles/ +EXTRAINCDIR += ${ROOTPATH}/src/import/hwpf/fapi2/include +EXTRAINCDIR += ${ROOTPATH}/src/include/usr/fapi2 +EXTRAINCDIR += ${ROOTPATH}/src/import/chips/common/utils/imageProcs/ +EXTRAINCDIR += ${ROOTPATH}/src/import/ +EXTRAINCDIR += ${PROCEDURE_PATH}/hwp/memory +EXTRAINCDIR += ${ROOTPATH}/src/import/chips/p9/common/include/ +EXTRAINCDIR += ${PROCEDURE_PATH}/hwp/memory/lib/eff_config/ +EXTRAINCDIR += ${PROCEDURE_PATH}/hwp/memory/lib/ +EXTRAINCDIR += ${PROCEDURE_PATH}/hwp/memory/lib/mcbist/ +EXTRAINCDIR += ${PROCEDURE_PATH}/hwp/memory/lib/dimm/ +EXTRAINCDIR += ${PROCEDURE_PATH}/hwp/memory/lib/dimm/ddr4/ +EXTRAINCDIR += ${PROCEDURE_PATH}/hwp/memory/ +EXTRAINCDIR += ${PROCEDURE_PATH}/hwp/ffdc/ + +OBJS += nvdimm.o + +VPATH += ${PROCEDURE_PATH}/hwp/memory/lib/dimm/ddr4/ diff --git a/src/usr/isteps/pm/runtime/makefile b/src/usr/isteps/pm/runtime/makefile index ecffa4f37..c3be1b818 100644 --- a/src/usr/isteps/pm/runtime/makefile +++ b/src/usr/isteps/pm/runtime/makefile @@ -31,12 +31,17 @@ VPATH += ../ MODULE = pm_rt +EXTRAINCDIR += ${ROOTPATH}/src/usr/isteps/nvdimm + ## Objects unique to HBRT OBJS += rt_pm.o +## Dependencies for nvdimm.mk +VPATH += ${ROOTPATH}/src/usr/isteps/nvdimm + SUBDIRS += test.d ## Objects common to HBRT and HB IPL include ../pm.mk - +include ${ROOTPATH}/src/usr/isteps/nvdimm/nvdimm.mk include ${ROOTPATH}/config.mk diff --git a/src/usr/isteps/pm/runtime/rt_pm.C b/src/usr/isteps/pm/runtime/rt_pm.C index 163a78b55..3e5ab8c10 100644 --- a/src/usr/isteps/pm/runtime/rt_pm.C +++ b/src/usr/isteps/pm/runtime/rt_pm.C @@ -5,7 +5,7 @@ /* */ /* OpenPOWER HostBoot Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2016,2018 */ +/* Contributors Listed Below - COPYRIGHT 2016,2019 */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -44,9 +44,12 @@ #include <initservice/isteps_trace.H> // targeting support +#include <targeting/common/util.H> #include <targeting/common/utilFilter.H> #include <targeting/common/targetservice.H> +#include <isteps/nvdimm/nvdimm.H> + #include <scom/scomif.H> #include <scom/wakeup.H> @@ -256,7 +259,47 @@ namespace RTPM l_err->collectTrace(ISTEP_COMP_NAME,1024); errlCommit( l_err, RUNTIME_COMP_ID ); l_err = nullptr; + break; + } + +#ifdef CONFIG_NVDIMM + //@TODO RTC 199645 - additional delay needed to ensure OCC is + // full functional + + // Only run this if PM complex started successfully + // as EPOW save trigger is done by the OCC + TARGETING::TargetHandleList l_dimmTargetList; + getChildAffinityTargets( l_dimmTargetList, proc_target, CLASS_NA, TYPE_DIMM ); + + for (auto const l_dimm : l_dimmTargetList) + { + if (TARGETING::isNVDIMM(l_dimm)) + { + // skip if the nvdimm is in error state + if (NVDIMM::nvdimmInErrorState(l_dimm)) + { + continue; + } + + l_err = NVDIMM::nvdimmArmResetN(l_dimm); + // If we run into any error here we will just + // commit the error log and move on. Let the + // system continue to boot and let the user + // salvage the data + if (l_err) + { + NVDIMM::nvdimmSetStatusFlag(l_dimm, NVDIMM::NSTD_ERR_NOBKUP); + // Committing the error as we don't want the this to interrupt + // the boot. This will notifiy the user that action is needed + // on this module + l_err->setSev(ERRL_SEV_INFORMATIONAL); + l_err->collectTrace(NVDIMM_COMP_NAME,1024); + errlCommit( l_err, NVDIMM_COMP_ID ); + continue; + } + } } +#endif } while(0); if ( l_err ) diff --git a/src/usr/targeting/common/util.C b/src/usr/targeting/common/util.C index c8b8c7c5f..a5a9bb7a9 100644 --- a/src/usr/targeting/common/util.C +++ b/src/usr/targeting/common/util.C @@ -38,6 +38,9 @@ #include <targeting/common/utilFilter.H> #include <targeting/common/trace.H> +#define MCA_PER_MCS 2 +#define DIMM_PER_MCA 2 + namespace TARGETING { @@ -281,4 +284,46 @@ uint8_t is_fused_mode( ) } // end is_fused_mode +/** + * @brief Determine if the given dimm target is an NVDIMM + * + * @param[in] i_target : dimm target to check + * + * @return bool - True if the given target is an NVDIMM + */ +bool isNVDIMM( TARGETING::Target * i_target ) +{ + // Not the most elegant way of doing it but the hybrid attributes + // are at the MCS level. Need to find my way up to MCS and check + // if the dimm is hybrid + TARGETING::TargetHandleList l_mcaList; + getParentAffinityTargets(l_mcaList, i_target, TARGETING::CLASS_UNIT, TARGETING::TYPE_MCA); + + if (l_mcaList.size()) + { + TARGETING::TargetHandleList l_mcsList; + getParentAffinityTargets(l_mcsList, l_mcaList[0], TARGETING::CLASS_UNIT, TARGETING::TYPE_MCS); + + if(l_mcsList.size()) + { + // 2-D array. [MCA][DIMM] + TARGETING::ATTR_EFF_HYBRID_type l_hybrid; + TARGETING::ATTR_EFF_HYBRID_MEMORY_TYPE_type l_hybrid_type; + + if( l_mcsList[0]->tryGetAttr<TARGETING::ATTR_EFF_HYBRID>(l_hybrid) && + l_mcsList[0]->tryGetAttr<TARGETING::ATTR_EFF_HYBRID_MEMORY_TYPE>(l_hybrid_type) ) + { + //Using relative position to lookup the hybrid attribute for the current dimm + TARGETING::ATTR_REL_POS_type l_dimm_rel_pos = i_target->getAttr<ATTR_REL_POS>(); + TARGETING::ATTR_REL_POS_type l_mca_rel_pos = l_mcaList[0]->getAttr<ATTR_REL_POS>(); + + return (l_hybrid[l_mca_rel_pos][l_dimm_rel_pos] == TARGETING::EFF_HYBRID_IS_HYBRID && + l_hybrid_type[l_mca_rel_pos][l_dimm_rel_pos] == TARGETING::EFF_HYBRID_MEMORY_TYPE_NVDIMM); + } + } + } + + return false; +} + } // end namespace TARGETING |