diff options
author | Chris Cain <cjcain@us.ibm.com> | 2016-05-24 15:28:27 -0500 |
---|---|---|
committer | Daniel M. Crowell <dcrowell@us.ibm.com> | 2016-05-25 18:38:01 -0400 |
commit | 834bccc4c031d20d7c4b56f9d10b1cb91cc617db (patch) | |
tree | e24b640c5be1c649484502fdf094757402d95eca /src/usr/htmgt | |
parent | ea83d6f50bdf030f18fab0e03bdf77183d2ba41a (diff) | |
download | talos-hostboot-834bccc4c031d20d7c4b56f9d10b1cb91cc617db.tar.gz talos-hostboot-834bccc4c031d20d7c4b56f9d10b1cb91cc617db.zip |
Add internal flag support to prevent OCC resets and query pstate tables
Change-Id: Ifd30c8bf36aa82c168afa3e34de7fd8f4d4e4cab
RTC: 152379
Reviewed-on: http://ralgit01.raleigh.ibm.com/gerrit1/24987
Tested-by: Jenkins Server
Reviewed-by: Martha Broyles <mbroyles@us.ibm.com>
Tested-by: FSP CI Jenkins
Reviewed-by: Sheldon R. Bailey <baileysh@us.ibm.com>
Reviewed-by: Daniel M. Crowell <dcrowell@us.ibm.com>
Diffstat (limited to 'src/usr/htmgt')
-rw-r--r-- | src/usr/htmgt/genPstate.C | 67 | ||||
-rw-r--r-- | src/usr/htmgt/genPstate.H | 7 | ||||
-rw-r--r-- | src/usr/htmgt/htmgt.C | 664 | ||||
-rw-r--r-- | src/usr/htmgt/htmgt_occ.C | 222 | ||||
-rw-r--r-- | src/usr/htmgt/htmgt_utility.C | 42 | ||||
-rw-r--r-- | src/usr/htmgt/htmgt_utility.H | 51 | ||||
-rw-r--r-- | src/usr/htmgt/occError.C | 14 |
7 files changed, 680 insertions, 387 deletions
diff --git a/src/usr/htmgt/genPstate.C b/src/usr/htmgt/genPstate.C index a4fb2680f..7ceb6de5d 100644 --- a/src/usr/htmgt/genPstate.C +++ b/src/usr/htmgt/genPstate.C @@ -5,7 +5,7 @@ /* */ /* OpenPOWER HostBoot Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2014,2015 */ +/* Contributors Listed Below - COPYRIGHT 2014,2016 */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -120,4 +120,69 @@ errlHndl_t genPstateTables(bool i_normalTables) } return err; } + + +bool getPstateTable(const bool i_normalTables, + const uint8_t i_proc, + uint16_t & o_dataLen, + uint8_t * o_dataPtr) +{ + bool copied = false; + + TargetHandleList processors; + getChipResources(processors, + TYPE_PROC, + UTIL_FILTER_FUNCTIONAL); + for(TargetHandleList::const_iterator + procItr = processors.begin(); + procItr != processors.end(); + ++procItr) + { + Target * procTarget = *procItr; + const uint8_t procInstance = + procTarget->getAttr<TARGETING::ATTR_POSITION>(); + if (i_proc == procInstance) + { + const uint8_t l_occ = 0; + TargetHandleList occs; + getChildChiplets(occs, + procTarget, + TYPE_OCC, + true); + Target * occTarget = occs[l_occ]; + ATTR_HUID_type huid = occTarget->getAttr<ATTR_HUID>(); + // Read data from attribute for specified occ + if (i_normalTables) + { + TMGT_INF("Dumping PStateTable for Proc%d OCC%d (HUID 0x%08X)", + i_proc, l_occ, huid); + ATTR_PSTATE_TABLE_type * pstateDataPtr = + reinterpret_cast<ATTR_PSTATE_TABLE_type*>(o_dataPtr); + + occTarget->tryGetAttr<ATTR_PSTATE_TABLE>(*pstateDataPtr); + o_dataLen = sizeof(ATTR_PSTATE_TABLE_type); + copied = true; + } + else + { + TMGT_INF("Dumping MFG PStateTable for Proc%d OCC%d" + " (HUID 0x%08X)", i_proc, l_occ, huid); + ATTR_PSTATE_TABLE_MFG_type * pstateDataPtr = + reinterpret_cast<ATTR_PSTATE_TABLE_MFG_type*>(o_dataPtr); + + occTarget->tryGetAttr<ATTR_PSTATE_TABLE_MFG>(*pstateDataPtr); + o_dataLen = sizeof(ATTR_PSTATE_TABLE_MFG_type); + copied = true; + } + + // Just dump for first OCC + break; + } + } + + return copied; + +} // end getPstateTable() + + }; // end namespace diff --git a/src/usr/htmgt/genPstate.H b/src/usr/htmgt/genPstate.H index 6b302131f..46512d4a9 100644 --- a/src/usr/htmgt/genPstate.H +++ b/src/usr/htmgt/genPstate.H @@ -5,7 +5,7 @@ /* */ /* OpenPOWER HostBoot Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2014,2015 */ +/* Contributors Listed Below - COPYRIGHT 2014,2016 */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -42,5 +42,10 @@ namespace HTMGT */ errlHndl_t genPstateTables(bool i_normalTables); +bool getPstateTable(const bool i_normalTables, + const uint8_t i_proc, + uint16_t & o_dataLen, + uint8_t * o_dataPtr); + }; #endif diff --git a/src/usr/htmgt/htmgt.C b/src/usr/htmgt/htmgt.C index 502b661e0..fb23ee008 100644 --- a/src/usr/htmgt/htmgt.C +++ b/src/usr/htmgt/htmgt.C @@ -44,8 +44,8 @@ // HBOCC support #include <hwpf/hwp/occ/occ_common.H> - #include <sys/time.h> +#include <targeting/common/attributeTank.H> namespace HTMGT { @@ -55,7 +55,7 @@ namespace HTMGT void processOccStartStatus(const bool i_startCompleted, TARGETING::Target * i_failedOccTarget) { - TMGT_INF(">>processOccStartStatus(%d,%p)", + TMGT_INF(">>processOccStartStatus(%d,0x%p)", i_startCompleted, i_failedOccTarget); errlHndl_t l_err = NULL; uint32_t l_huid = 0; @@ -65,156 +65,170 @@ namespace HTMGT } TMGT_INF("processOccStartStatus(Start Success=%c, failedOcc=0x%08X)", i_startCompleted?'y':'n', l_huid); - if (i_startCompleted) + if (false == int_flags_set(FLAG_HOLD_OCCS_IN_RESET)) { - // Query functional OCCs - l_err = OccManager::buildOccs(); - if (NULL == l_err) + if (i_startCompleted) { - if (NULL != OccManager::getMasterOcc()) + // Query functional OCCs + l_err = OccManager::buildOccs(); + if (NULL == l_err) { - do + if (NULL != OccManager::getMasterOcc()) { -#ifndef __HOSTBOOT_RUNTIME - // Build normal pstate tables (once per IPL) - l_err = genPstateTables(true); - if(l_err) + do { - break; - } +#ifndef __HOSTBOOT_RUNTIME + // Build normal pstate tables (once per IPL) + l_err = genPstateTables(true); + if(l_err) + { + break; + } - // Calc memory throttles (once per IPL) - calcMemThrottles(); + // Calc memory throttles (once per IPL) + calcMemThrottles(); #endif - // Make sure OCCs are ready for communication - l_err = OccManager::waitForOccCheckpoint(); - if (l_err) - { - break; - } + // Make sure OCCs are ready for communication + OccManager::waitForOccCheckpoint(); #ifdef __HOSTBOOT_RUNTIME - // TODO RTC 124738 Final solution TBD - // Perhapse POLL scom 0x6a214 until bit 31 is set? - nanosleep(1,0); + // TODO RTC 124738 Final solution TBD + // Perhapse POLL scom 0x6a214 until bit 31 is set? + nanosleep(1,0); #endif - // Send poll to establish comm - TMGT_INF("Send initial poll to all OCCs to" - " establish comm"); - l_err = OccManager::sendOccPoll(); - if (l_err) - { - if (OccManager::occNeedsReset()) + // Send poll to establish comm + TMGT_INF("Send initial poll to all OCCs to" + " establish comm"); + l_err = OccManager::sendOccPoll(); + if (l_err) { - // No need to continue if reset is required - TMGT_ERR("sendOccConfigData(): OCCs need " - "to be reset"); - break; - } - else - { - // Continue even if failed (will be retried) - ERRORLOG::errlCommit(l_err, HTMGT_COMP_ID); + if (OccManager::occNeedsReset()) + { + // No need to continue if reset is required + TMGT_ERR("sendOccConfigData(): OCCs need " + "to be reset"); + break; + } + else + { + // Continue even if failed (will be retried) + ERRORLOG::errlCommit(l_err, HTMGT_COMP_ID); + } } - } - // Send ALL config data - sendOccConfigData(); + // Send ALL config data + sendOccConfigData(); - // Set the User PCAP - l_err = sendOccUserPowerCap(); - if (l_err) - { - break; - } + // Set the User PCAP + l_err = sendOccUserPowerCap(); + if (l_err) + { + break; + } - // Wait for all OCCs to go to the target state - l_err = waitForOccState(); - if ( l_err ) - { - break; - } + // Wait for all OCCs to go to the target state + l_err = waitForOccState(); + if ( l_err ) + { + break; + } - // Set active sensors for all OCCs, - // so BMC can start communication with OCCs - l_err = setOccActiveSensors(true); - if (l_err) - { - // Continue even if failed to update sensor - ERRORLOG::errlCommit(l_err, HTMGT_COMP_ID); - } + // Set active sensors for all OCCs, + // so BMC can start communication with OCCs + l_err = setOccActiveSensors(true); + if (l_err) + { + // Continue even if failed to update sensor + ERRORLOG::errlCommit(l_err, HTMGT_COMP_ID); + } - } while(0); + } while(0); + } + else + { + TMGT_ERR("Unable to find any Master capable OCCs"); + /*@ + * @errortype + * @reasoncode HTMGT_RC_OCC_MASTER_NOT_FOUND + * @moduleid HTMGT_MOD_LOAD_START_STATUS + * @userdata1 number of OCCs + * @devdesc No OCC master was found + */ + bldErrLog(l_err, HTMGT_MOD_LOAD_START_STATUS, + HTMGT_RC_OCC_MASTER_NOT_FOUND, + 0, OccManager::getNumOccs(), 0, 0, + ERRORLOG::ERRL_SEV_INFORMATIONAL); + } } else { - TMGT_ERR("Unable to find any Master capable OCCs"); - /*@ - * @errortype - * @reasoncode HTMGT_RC_OCC_MASTER_NOT_FOUND - * @moduleid HTMGT_MOD_LOAD_START_STATUS - * @userdata1 number of OCCs - * @devdesc No OCC master was found - */ - bldErrLog(l_err, HTMGT_MOD_LOAD_START_STATUS, - HTMGT_RC_OCC_MASTER_NOT_FOUND, - 0, OccManager::getNumOccs(), 0, 0, - ERRORLOG::ERRL_SEV_INFORMATIONAL); + // Failed to find functional OCCs, no need to try again + // Set original error log as unrecoverable and commit + l_err->setSev(ERRORLOG::ERRL_SEV_UNRECOVERABLE); + ERRORLOG::errlCommit(l_err, HTMGT_COMP_ID); } } else { - // Failed to find functional OCCs, no need to try again - // Set original error log as unrecoverable and commit - l_err->setSev(ERRORLOG::ERRL_SEV_UNRECOVERABLE); - ERRORLOG::errlCommit(l_err, HTMGT_COMP_ID); + TMGT_ERR("All OCCs were not loaded/started successfully"); + /*@ + * @errortype + * @reasoncode HTMGT_RC_OCC_START_FAIL + * @moduleid HTMGT_MOD_LOAD_START_STATUS + * @userdata1 Failing OCC HUID + * @devdesc OCCs were not loaded/started successfully + */ + bldErrLog(l_err, HTMGT_MOD_LOAD_START_STATUS, + HTMGT_RC_OCC_START_FAIL, + 0, l_huid, 0, 0, + ERRORLOG::ERRL_SEV_INFORMATIONAL); } - } - else - { - TMGT_ERR("All OCCs were not loaded/started successfully"); - /*@ - * @errortype - * @reasoncode HTMGT_RC_OCC_START_FAIL - * @moduleid HTMGT_MOD_LOAD_START_STATUS - * @userdata1 Failing OCC HUID - * @devdesc OCCs were not loaded/started successfully - */ - bldErrLog(l_err, HTMGT_MOD_LOAD_START_STATUS, - HTMGT_RC_OCC_START_FAIL, - 0, l_huid, 0, 0, - ERRORLOG::ERRL_SEV_INFORMATIONAL); - } - if (NULL != l_err) - { - TMGT_ERR("OCCs not all active (rc=0x%04X). Attempting OCC " - "Reset", l_err->reasonCode()); - TMGT_CONSOLE("OCCs are not active (rc=0x%04X). " - "Attempting OCC Reset", - l_err->reasonCode()); - TMGT_INF("processOccStartStatus: Calling resetOccs"); - errlHndl_t err2 = OccManager::resetOccs(NULL); - if(err2) + if (NULL != l_err) { - TMGT_ERR("OccManager::resetOccs failed with 0x%04X", - err2->reasonCode()); + TMGT_ERR("OCCs not all active (rc=0x%04X). Attempting OCC " + "Reset", l_err->reasonCode()); + TMGT_CONSOLE("OCCs are not active (rc=0x%04X). " + "Attempting OCC Reset", + l_err->reasonCode()); + TMGT_INF("processOccStartStatus: Calling resetOccs"); + errlHndl_t err2 = OccManager::resetOccs(NULL); + if(err2) + { + TMGT_ERR("OccManager::resetOccs failed with 0x%04X", + err2->reasonCode()); - // Set original error log as unrecoverable and commit - l_err->setSev(ERRORLOG::ERRL_SEV_UNRECOVERABLE); - ERRORLOG::errlCommit(l_err, HTMGT_COMP_ID); + // Set original error log as unrecoverable and commit + l_err->setSev(ERRORLOG::ERRL_SEV_UNRECOVERABLE); + ERRORLOG::errlCommit(l_err, HTMGT_COMP_ID); - // Commit occReset error - ERRORLOG::errlCommit(err2, HTMGT_COMP_ID); + // Commit occReset error + ERRORLOG::errlCommit(err2, HTMGT_COMP_ID); + } + else + { + // retry worked - commit original error as informational + l_err->setSev(ERRORLOG::ERRL_SEV_INFORMATIONAL); + ERRORLOG::errlCommit(l_err, HTMGT_COMP_ID); + } } - else + } + else + { + TMGT_INF("processOccStartStatus: Skipping start of OCCS due to " + "internal flags 0x%08X", get_int_flags()); + // Reset all OCCs + TMGT_INF("processOccStartStatus: Calling HBOCC::stopAllOCCs"); + l_err = HBOCC::stopAllOCCs(); + if(l_err) { - // retry worked - commit original error as informational l_err->setSev(ERRORLOG::ERRL_SEV_INFORMATIONAL); + l_err->collectTrace("HTMGT"); ERRORLOG::errlCommit(l_err, HTMGT_COMP_ID); } + } TMGT_INF("<<processOccStartStatus()"); @@ -226,7 +240,7 @@ namespace HTMGT // Notify HTMGT that an OCC has an error to report void processOccError(TARGETING::Target * i_procTarget) { - TMGT_INF(">>processOccError(%p)", i_procTarget); + TMGT_INF(">>processOccError(0x%p)", i_procTarget); TARGETING::Target* sys = NULL; TARGETING::targetService().getTopLevelTarget(sys); @@ -302,7 +316,7 @@ namespace HTMGT // Notify HTMGT that an OCC has failed and needs to be reset void processOccReset(TARGETING::Target * i_proc) { - TMGT_INF(">>processOccReset(%p)", i_proc); + TMGT_INF(">>processOccReset(0x%p)", i_proc); errlHndl_t errl = NULL; TARGETING::Target * failedOccTarget = NULL; @@ -318,14 +332,12 @@ namespace HTMGT return; } - if (i_proc) + // Get functional OCC (one per proc) + TARGETING::TargetHandleList pOccs; + getChildChiplets(pOccs, i_proc, TARGETING::TYPE_OCC); + if (pOccs.size() > 0) { - TARGETING::TargetHandleList pOccs; - getChildChiplets(pOccs, i_proc, TARGETING::TYPE_OCC); - if (pOccs.size() > 0) - { - failedOccTarget = pOccs[0]; - } + failedOccTarget = pOccs[0]; } if(NULL != failedOccTarget) @@ -359,12 +371,21 @@ namespace HTMGT ERRORLOG::errlCommit(errl, HTMGT_COMP_ID); // sets errl to NULL } - errl = OccManager::resetOccs(failedOccTarget); - if(errl) + if (false == int_flags_set(FLAG_EXT_RESET_DISABLED)) { - ERRORLOG::errlCommit(errl, HTMGT_COMP_ID); // sets errl to NULL + errl = OccManager::resetOccs(failedOccTarget); + if(errl) + { + ERRORLOG::errlCommit(errl, HTMGT_COMP_ID); // sets errl to NULL + } + } + else + { + TMGT_INF("processOccReset: Skipping external reset due to " + "internal flags 0x%08X", get_int_flags()); } TMGT_INF("<<processOccReset()"); + } // end processOccReset() @@ -460,6 +481,57 @@ namespace HTMGT + errlHndl_t dumpAttribute(const uint16_t i_length, + const uint8_t * i_data, + uint16_t & o_attrLength, + uint8_t * o_attrData) + { + errlHndl_t err = NULL; + uint32_t attrId = 0; + + if ((i_data[0] == ATTR_RAW) && (i_length == 5)) + { + // Dump attribute based on raw ID + + attrId = UINT32_GET(&i_data[1]); + TMGT_INF("Attempting to read attribute 0x%08X", attrId); + //if (TARGETING::AttributeTank::attributeExists(attrId)) + //{ + // if (TARGETING::AttributeTank::getAttribute(attrId, + // TARGETING::TYPE_SYS, AttributeTank::ATTR_POS_NA, + // AttributeTank::ATTR_UNIT_POS_NA, + // AttributeTank::ATTR_NODE_NA, attrPtr)) + // { + // // // Got attribute! + // } + //} + } + else if ((i_data[0] == ATTR_PSTATE) || (i_data[0] == ATTR_PSTATE_MFG)) + { + uint8_t selectedOcc = 0; + if (i_length >= 2) + { + selectedOcc = i_data[1]; + } + getPstateTable((i_data[0] == ATTR_PSTATE), + selectedOcc, o_attrLength, o_attrData); + } + else + { + TMGT_ERR("dumpAttribute: Invalid attribute specified 0x%02X " + "(length %d)", i_data[0], i_length); + bldErrLog(err, HTMGT_MOD_PASS_THRU, + HTMGT_RC_INVALID_PARAMETER, + UINT32_GET(&i_data[0]), + UINT32_GET(&i_data[4]), + 0, i_length, + ERRORLOG::ERRL_SEV_INFORMATIONAL); + } + return err; + } + + + // Send pass-thru command to HTMGT errlHndl_t passThruCommand(uint16_t i_cmdLength, uint8_t * i_cmdData, @@ -470,190 +542,223 @@ namespace HTMGT htmgtReasonCode failingSrc = HTMGT_RC_NO_ERROR; o_rspLength = 0; - err = OccManager::buildOccs(); - if (NULL == err) + if ((i_cmdLength > 0) && (NULL != i_cmdData)) { - if ((i_cmdLength > 0) && (NULL != i_cmdData)) + switch (i_cmdData[0]) { - switch (i_cmdData[0]) - { - case PASSTHRU_OCC_STATUS: - TMGT_INF("passThruCommand: OCC Status"); - OccManager::getOccData(o_rspLength, o_rspData); - break; + case PASSTHRU_OCC_STATUS: + TMGT_INF("passThruCommand: OCC Status"); + OccManager::getOccData(o_rspLength, o_rspData); + break; + + case PASSTHRU_GENERATE_MFG_PSTATE: + if (i_cmdLength == 1) + { + TMGT_INF("passThruCommand: Generate MFG pstate tables", + i_cmdData[1]); + err = genPstateTables(false); + } + else + { + TMGT_ERR("passThruCommand: invalid generate pstate " + "command length %d", i_cmdLength); + /*@ + * @errortype + * @reasoncode HTMGT_RC_INVALID_LENGTH + * @moduleid HTMGT_MOD_PASS_THRU + * @userdata1 command data[0-7] + * @userdata2 command data length + * @devdesc Invalid pass thru command data length + */ + failingSrc = HTMGT_RC_INVALID_LENGTH; + } + break; - case PASSTHRU_GENERATE_MFG_PSTATE: - if (i_cmdLength == 1) + case PASSTHRU_LOAD_PSTATE: + if (i_cmdLength == 2) + { + const uint8_t pstateType = i_cmdData[1]; + if ((0 == pstateType) || (1 == pstateType)) { - TMGT_INF("passThruCommand: Generate MFG pstate " - "tables", i_cmdData[1]); - err = genPstateTables(false); + TMGT_INF("passThruCommand: Load pstate tables " + "(type: %d)", pstateType); + // 0 = Normal Pstate Tables + err = OccManager::loadPstates(0 == pstateType); } else { - TMGT_ERR("passThruCommand: invalid generate pstate " - "command length %d", i_cmdLength); + TMGT_ERR("passThruCommand: invalid pstate type " + "specified: %d", pstateType); /*@ * @errortype - * @reasoncode HTMGT_RC_INVALID_LENGTH + * @reasoncode HTMGT_RC_INVALID_PARAMETER * @moduleid HTMGT_MOD_PASS_THRU * @userdata1 command data[0-7] * @userdata2 command data length - * @devdesc Invalid pass thru command data len + * @devdesc Invalid load pstate table type */ - failingSrc = HTMGT_RC_INVALID_LENGTH; + failingSrc = HTMGT_RC_INVALID_PARAMETER; } - break; + } + else + { + TMGT_ERR("passThruCommand: invalid load pstate " + "command length %d", i_cmdLength); + failingSrc = HTMGT_RC_INVALID_LENGTH; + } + break; + + case PASSTHRU_INTERNAL_FLAG: + if (i_cmdLength == 1) + { + // get internal flag value + o_rspLength = 4; + UINT32_PUT(o_rspData, get_int_flags()); + } + else if (i_cmdLength == 5) + { + // set internal flag value + TMGT_INF("passThruCommand: Updating internal flags " + "from 0x%08X to 0x%08X", + get_int_flags(), UINT32_GET(&i_cmdData[1])); + set_int_flags(UINT32_GET(&i_cmdData[1])); + } + else + { + TMGT_ERR("passThruCommand: invalid internal flag " + "length %d", i_cmdLength); + failingSrc = HTMGT_RC_INVALID_LENGTH; + } + break; - case PASSTHRU_LOAD_PSTATE: - if (i_cmdLength == 2) + case PASSTHRU_SEND_OCC_COMMAND: + if (i_cmdLength >= 3) + { + const uint8_t occInstance = i_cmdData[1]; + const occCommandType occCmd = + (occCommandType)i_cmdData[2]; + const uint16_t dataLen = i_cmdLength-3; + Occ *occPtr = OccManager::getOcc(occInstance); + if (occPtr) { - const uint8_t pstateType = i_cmdData[1]; - if ((0 == pstateType) || (1 == pstateType)) + TMGT_INF("passThruCommand: Send OCC%d command " + "0x%02X (%d bytes)", + occInstance, occCmd, dataLen); + OccCmd cmd(occPtr, occCmd, dataLen, &i_cmdData[3]); + err = cmd.sendOccCmd(); + if (err != NULL) { - TMGT_INF("passThruCommand: Load pstate tables " - "(type: %d)", pstateType); - // 0 = Normal Pstate Tables - err = OccManager::loadPstates(0 == pstateType); + TMGT_ERR("passThruCommand: OCC%d cmd 0x%02X " + "failed with rc 0x%04X", + occInstance, occCmd, + err->reasonCode()); } else { - TMGT_ERR("passThruCommand: invalid pstate " - "type specified: %d", pstateType); - /*@ - * @errortype - * @reasoncode HTMGT_RC_INVALID_PARAMETER - * @moduleid HTMGT_MOD_PASS_THRU - * @userdata1 command data[0-7] - * @userdata2 command data length - * @devdesc Invalid load pstate table type - */ - failingSrc = HTMGT_RC_INVALID_PARAMETER; + uint8_t *rspPtr = NULL; + o_rspLength = cmd.getResponseData(rspPtr); + memcpy(o_rspData, rspPtr, o_rspLength); + TMGT_INF("passThruCommand: OCC%d rsp status " + "0x%02X (%d bytes)", occInstance, + o_rspData[2], o_rspLength); } } else { - TMGT_ERR("passThruCommand: invalid load pstate " - "command length %d", i_cmdLength); - failingSrc = HTMGT_RC_INVALID_LENGTH; + TMGT_ERR("passThruCommand: Unable to find OCC%d", + occInstance); + /*@ + * @errortype + * @reasoncode HTMGT_RC_OCC_UNAVAILABLE + * @moduleid HTMGT_MOD_PASS_THRU + * @userdata1 command data[0-7] + * @userdata2 command data length + * @devdesc Specified OCC not available + */ + failingSrc = HTMGT_RC_OCC_UNAVAILABLE; } - break; + } + else + { + TMGT_ERR("passThruCommand: invalid OCC command " + "length %d", i_cmdLength); + failingSrc = HTMGT_RC_INVALID_LENGTH; + } + break; - case PASSTHRU_SEND_OCC_COMMAND: - if (i_cmdLength >= 3) + case PASSTHRU_CLEAR_RESET_COUNTS: + TMGT_INF("passThruCommand: Clear all OCC reset counts"); + OccManager::clearResetCounts(); + break; + + case PASSTHRU_EXIT_SAFE_MODE: + { + TMGT_INF("passThruCommand: Clear Safe Mode"); + // Clear OCC reset counts and failed flags + OccManager::clearResetCounts(); + // Clear safe mode reason + OccManager::updateSafeModeReason(0, 0); + // Clear system safe mode flag/attribute + TARGETING::Target* sys = NULL; + TARGETING::targetService().getTopLevelTarget(sys); + const uint8_t safeMode = 0; + // Mark system as NOT being in safe mode + if(sys) { - const uint8_t occInstance = i_cmdData[1]; - const occCommandType occCmd = - (occCommandType)i_cmdData[2]; - const uint16_t dataLen = i_cmdLength-3; - Occ *occPtr = OccManager::getOcc(occInstance); - if (occPtr) - { - TMGT_INF("passThruCommand: Send OCC%d command " - "0x%02X (%d bytes)", - occInstance, occCmd, dataLen); - OccCmd cmd(occPtr, occCmd, dataLen, - &i_cmdData[3]); - err = cmd.sendOccCmd(); - if (err != NULL) - { - TMGT_ERR("passThruCommand: OCC%d cmd " - "0x%02X failed with rc 0x%04X", - occInstance, occCmd, - err->reasonCode()); - } - else - { - uint8_t *rspPtr = NULL; - o_rspLength = cmd.getResponseData(rspPtr); - memcpy(o_rspData, rspPtr, o_rspLength); - TMGT_INF("passThruCommand: OCC%d rsp " - "status 0x%02X (%d bytes)", - occInstance, o_rspData[2], - o_rspLength); - } - } - else - { - TMGT_ERR("passThruCommand: Unable to find " - "OCC%d", occInstance); - /*@ - * @errortype - * @reasoncode HTMGT_RC_OCC_UNAVAILABLE - * @moduleid HTMGT_MOD_PASS_THRU - * @userdata1 command data[0-7] - * @userdata2 command data length - * @devdesc Specified OCC not available - */ - failingSrc = HTMGT_RC_OCC_UNAVAILABLE; - } + sys->setAttr<TARGETING::ATTR_HTMGT_SAFEMODE> + (safeMode); } - else + // Reset the OCCs (do not increment reset count + // or attempt comm with OCC since they are in reset) + TMGT_INF("passThruCommand: Calling resetOccs"); + err = OccManager::resetOccs(NULL, true, true); + if (err != NULL) { - TMGT_ERR("passThruCommand: invalid OCC command " - "length %d", i_cmdLength); - failingSrc = HTMGT_RC_INVALID_LENGTH; + TMGT_ERR("passThruCommand: resetOccs failed " + "with rc 0x%04X", err->reasonCode()); } - break; - - case PASSTHRU_CLEAR_RESET_COUNTS: - TMGT_INF("passThruCommand: Clear all OCC reset counts"); - OccManager::clearResetCounts(); - break; + } + break; - case PASSTHRU_EXIT_SAFE_MODE: - { - TMGT_INF("passThruCommand: Clear Safe Mode"); - // Clear OCC reset counts and failed flags - OccManager::clearResetCounts(); - // Clear safe mode reason - OccManager::updateSafeModeReason(0, 0); - // Clear system safe mode flag/attribute - TARGETING::Target* sys = NULL; - TARGETING::targetService().getTopLevelTarget(sys); - const uint8_t safeMode = 0; - if(sys) - { - sys->setAttr<TARGETING::ATTR_HTMGT_SAFEMODE> - (safeMode); - } - // Reset the OCCs (do not increment reset count - // or attempt comm with OCC since they are in reset) - TMGT_INF("passThruCommand: Calling resetOccs"); - err = OccManager::resetOccs(NULL, true, true); - if (err != NULL) - { - TMGT_ERR("passThruCommand: resetOccs failed " - "with rc 0x%04X", err->reasonCode()); - } - } - break; + case PASSTHRU_DUMP_ATTRIBUTE: + if (i_cmdLength >= 2) + { + TMGT_INF("passThruCommand: Dump Attribute 0x%02X", + i_cmdData[1]); + err = dumpAttribute(i_cmdLength-1, &i_cmdData[1], + o_rspLength, o_rspData); + } + else + { + TMGT_ERR("passThruCommand: invalid dump attribute " + "command length %d", i_cmdLength); + failingSrc = HTMGT_RC_INVALID_LENGTH; + } + break; - default: - TMGT_ERR("passThruCommand: Invalid command 0x%08X " - "(%d bytes)", - UINT32_GET(i_cmdData), i_cmdLength); - /*@ - * @errortype - * @reasoncode HTMGT_RC_INVALID_DATA - * @moduleid HTMGT_MOD_PASS_THRU - * @userdata1 command data[0-7] - * @userdata2 command data length - * @devdesc Invalid pass thru command - */ - failingSrc = HTMGT_RC_INVALID_DATA; - break; - } + default: + TMGT_ERR("passThruCommand: Invalid command 0x%08X " + "(%d bytes)", UINT32_GET(i_cmdData), i_cmdLength); + /*@ + * @errortype + * @reasoncode HTMGT_RC_INVALID_DATA + * @moduleid HTMGT_MOD_PASS_THRU + * @userdata1 command data[0-7] + * @userdata2 command data length + * @devdesc Invalid pass thru command + */ + failingSrc = HTMGT_RC_INVALID_DATA; + break; + } - if ((HTMGT_RC_NO_ERROR != failingSrc) && (NULL == err)) - { - bldErrLog(err, HTMGT_MOD_PASS_THRU, - failingSrc, - UINT32_GET(i_cmdData), - UINT32_GET(&i_cmdData[4]), - 0, i_cmdLength, - ERRORLOG::ERRL_SEV_INFORMATIONAL); - } + if ((HTMGT_RC_NO_ERROR != failingSrc) && (NULL == err)) + { + bldErrLog(err, HTMGT_MOD_PASS_THRU, + failingSrc, + UINT32_GET(i_cmdData), + UINT32_GET(&i_cmdData[4]), + 0, i_cmdLength, + ERRORLOG::ERRL_SEV_INFORMATIONAL); } } @@ -662,4 +767,3 @@ namespace HTMGT } // end passThruCommand() } - diff --git a/src/usr/htmgt/htmgt_occ.C b/src/usr/htmgt/htmgt_occ.C index 8b34c525a..ee9639dfe 100644 --- a/src/usr/htmgt/htmgt_occ.C +++ b/src/usr/htmgt/htmgt_occ.C @@ -730,138 +730,154 @@ namespace HTMGT err = _buildOccs(); // if not a already built. if (NULL == err) { - err = setOccActiveSensors(false); // Set OCC sensor to inactive - if( err ) + if (false == int_flags_set(FLAG_RESET_DISABLED)) { - TMGT_ERR("_resetOccs: Set OCC sensors to inactive failed."); - // log and continue - ERRORLOG::errlCommit(err, HTMGT_COMP_ID); - } - - if (false == i_skipComm) - { - // Send poll cmd to all OCCs to establish comm - err = _sendOccPoll(false,NULL); - if (err) + err = setOccActiveSensors(false); // Set OCC sensor to inactive + if( err ) { - TMGT_ERR("_resetOccs: Poll OCCs failed."); - // Proceed with reset even if failed + TMGT_ERR("_resetOccs: Set OCC sensors to inactive failed."); + // log and continue ERRORLOG::errlCommit(err, HTMGT_COMP_ID); } - } - for(occList_t::const_iterator occ = iv_occArray.begin(); - occ != iv_occArray.end(); - ++occ) - { - if((*occ)->getTarget() == i_failedOccTarget) + if (false == i_skipComm) { - (*occ)->failed(true); + // Send poll cmd to all OCCs to establish comm + err = _sendOccPoll(false,NULL); + if (err) + { + TMGT_ERR("_resetOccs: Poll OCCs failed."); + // Proceed with reset even if failed + ERRORLOG::errlCommit(err, HTMGT_COMP_ID); + } } - - if (false == i_skipComm) + for(occList_t::const_iterator occ = iv_occArray.begin(); + occ != iv_occArray.end(); + ++occ) { - // Send reset prep cmd to all OCCs - if((*occ)->resetPrep()) + if((*occ)->getTarget() == i_failedOccTarget) { - atThreshold = true; + (*occ)->failed(true); + } + + if (false == i_skipComm) + { + // Send reset prep cmd to all OCCs + if((*occ)->resetPrep()) + { + atThreshold = true; + } } } - } - if ((false == i_skipCountIncrement) && (false == _occFailed())) - { - // No OCC has been marked failed, increment sys reset count - ++iv_resetCount; + if ((false == i_skipCountIncrement) && (false == _occFailed())) + { + // No OCC has been marked failed, increment sys reset count + ++iv_resetCount; - TMGT_INF("_resetOCCs: Incrementing system OCC reset count" - " to %d", iv_resetCount); + TMGT_INF("_resetOCCs: Incrementing system OCC reset count" + " to %d", iv_resetCount); - if(iv_resetCount > OCC_RESET_COUNT_THRESHOLD) - { - atThreshold = true; + if(iv_resetCount > OCC_RESET_COUNT_THRESHOLD) + { + atThreshold = true; + } } - } - // else failed OCC reset count will be incremented automatically - - // Update OCC states to RESET - for(occList_t::const_iterator occ = iv_occArray.begin(); - occ != iv_occArray.end(); - ++occ) - { - (*occ)->iv_state = OCC_STATE_RESET; - } + // else failed OCC reset count will be incremented automatically - uint64_t retryCount = OCC_RESET_COUNT_THRESHOLD; - while(retryCount) - { - // Reset all OCCs - TMGT_INF("_resetOccs: Calling HBOCC::stopAllOCCs"); - err = HBOCC::stopAllOCCs(); - if(!err) + // Update OCC states to RESET + for(occList_t::const_iterator occ = iv_occArray.begin(); + occ != iv_occArray.end(); + ++occ) { - break; + (*occ)->iv_state = OCC_STATE_RESET; } - --retryCount; - if(retryCount) + uint64_t retryCount = OCC_RESET_COUNT_THRESHOLD; + while(retryCount) { - // log if not last retry - ERRORLOG::errlCommit(err, HTMGT_COMP_ID); + // Reset all OCCs + TMGT_INF("_resetOccs: Calling HBOCC::stopAllOCCs"); + err = HBOCC::stopAllOCCs(); + if(!err) + { + break; + } + --retryCount; + + if (int_flags_set(FLAG_HALT_ON_RESET_FAIL)) + { + TMGT_ERR("_resetOCCs: stopAllOCCs failed with 0x%04X " + "and HALT_ON_RESET_FAIL is set. Resets will " + "be disabled", err->reasonCode()); + set_int_flags(get_int_flags() | FLAG_RESET_DISABLED); + break; + } + + if(retryCount) + { + // log if not last retry + ERRORLOG::errlCommit(err, HTMGT_COMP_ID); + } + else + { + TMGT_ERR("_resetOCCs: stopAllOCCs failed. " + "Leaving OCCs in reset state"); + // pass err handle back + err->collectTrace("HTMGT"); + } } - else + + if(!atThreshold && !err) { - TMGT_ERR("_resetOCCs: stopAllOCCs failed. " - "Leaving OCCs in reset state"); - // pass err handle back - err->collectTrace("HTMGT"); - } - } + for(occList_t::const_iterator occ = iv_occArray.begin(); + occ != iv_occArray.end(); + ++occ) + { + // After OCCs have been reset, clear flags + (*occ)->postResetClear(); + } - if(!atThreshold && !err) - { - for(occList_t::const_iterator occ = iv_occArray.begin(); - occ != iv_occArray.end(); - ++occ) + TMGT_INF("_resetOccs: Calling HBOCC::activateOCCs"); + err = HBOCC::activateOCCs(); + if(err) + { + TMGT_ERR("_resetOCCs: activateOCCs failed. "); + err->collectTrace("HTMGT"); + } + } + else if (!err) // Reset Threshold reached and no other err { - // After OCCs have been reset, clear flags - (*occ)->postResetClear(); + // Create threshold error + TMGT_ERR("_resetOCCs: Retry Threshold reached. " + "Leaving OCCs in reset state"); + /*@ + * @errortype + * @moduleid HTMGT_MOD_OCC_RESET + * @reasoncode HTMGT_RC_OCC_RESET_THREHOLD + * @userdata1 return code triggering safe mode + * @userdata2 OCC instance + * @devdesc OCC reset threshold reached. + * Leaving OCCs in reset state + */ + bldErrLog(err, + HTMGT_MOD_OCC_RESET, + HTMGT_RC_OCC_CRIT_FAILURE, + 0, cv_safeReturnCode, 0, cv_safeOccInstance, + ERRORLOG::ERRL_SEV_UNRECOVERABLE); } - TMGT_INF("_resetOccs: Calling HBOCC::activateOCCs"); - err = HBOCC::activateOCCs(); + // Any error at this point means OCCs were not reactivated if(err) { - TMGT_ERR("_resetOCCs: activateOCCs failed. "); - err->collectTrace("HTMGT"); + updateForSafeMode(err); } } - else if (!err) // Reset Threshold reached and no other err - { - // Create threshold error - TMGT_ERR("_resetOCCs: Retry Threshold reached. " - "Leaving OCCs in reset state"); - /*@ - * @errortype - * @moduleid HTMGT_MOD_OCC_RESET - * @reasoncode HTMGT_RC_OCC_RESET_THREHOLD - * @userdata1 return code triggering safe mode - * @userdata2 OCC instance - * @devdesc OCC reset threshold reached. - * Leaving OCCs in reset state - */ - bldErrLog(err, - HTMGT_MOD_OCC_RESET, - HTMGT_RC_OCC_CRIT_FAILURE, - 0, cv_safeReturnCode, 0, cv_safeOccInstance, - ERRORLOG::ERRL_SEV_UNRECOVERABLE); - } - - // Any error at this point means OCCs were not reactivated - if(err) + else { - updateForSafeMode(err); + TMGT_INF("_resetOccs: Skipping OCC reset due to " + "internal flags 0x%08X", get_int_flags()); } } @@ -1008,8 +1024,8 @@ namespace HTMGT { ERRORLOG::errlCommit(l_err, HTMGT_COMP_ID); } - - (*pOcc)->failed(true); + TMGT_ERR("waitForOccCheckpoint OCC%d still NOT ready!", + (*pOcc)->getInstance()); } } } @@ -1168,6 +1184,7 @@ namespace HTMGT return err; } + // Consolidate all OCC states void OccManager::_syncOccStates() { @@ -1230,6 +1247,7 @@ namespace HTMGT } } } + if (iv_resetCount != 0) { TMGT_INF("_clearResetCounts: Clearing system reset count " diff --git a/src/usr/htmgt/htmgt_utility.C b/src/usr/htmgt/htmgt_utility.C index e880d5a0c..5edbc512b 100644 --- a/src/usr/htmgt/htmgt_utility.C +++ b/src/usr/htmgt/htmgt_utility.C @@ -5,7 +5,7 @@ /* */ /* OpenPOWER HostBoot Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2014,2015 */ +/* Contributors Listed Below - COPYRIGHT 2014,2016 */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -179,4 +179,44 @@ namespace HTMGT } + // Retrieve the internalFlags + uint32_t get_int_flags() + { + uint32_t flags = 0; + TARGETING::Target* sys = NULL; + TARGETING::targetService().getTopLevelTarget(sys); + if (sys) + { + sys->tryGetAttr<TARGETING::ATTR_HTMGT_INTERNAL_FLAGS>(flags); + } + return flags; + } + + + // Set the internal flags value + void set_int_flags(const uint32_t i_value) + { + TARGETING::Target* sys = NULL; + TARGETING::targetService().getTopLevelTarget(sys); + if (sys) + { + sys->trySetAttr<TARGETING::ATTR_HTMGT_INTERNAL_FLAGS>(i_value); + } + } + + + // Query if specified internal flag(s) are set + bool int_flags_set(const uint32_t i_mask) + { + bool flags_are_set = false; + + const uint32_t flags = get_int_flags(); + if ((flags & i_mask) == i_mask) + { + flags_are_set = true; + } + + return flags_are_set; + } + } // end namespace diff --git a/src/usr/htmgt/htmgt_utility.H b/src/usr/htmgt/htmgt_utility.H index ad93a0575..d0c70ec20 100644 --- a/src/usr/htmgt/htmgt_utility.H +++ b/src/usr/htmgt/htmgt_utility.H @@ -101,6 +101,20 @@ namespace HTMGT }; extern uint32_t G_debug_trace; + enum internalFlagTypes + { + FLAG_HALT_ON_OCC_SRC = 0x00800000, // Prevent resets after SRC + FLAG_HALT_ON_RESET_FAIL = 0x00000100, // Stop additional resets + FLAG_EXT_RESET_DISABLED = 0x00000080, // Ignore opal-prd/BMC resets + FLAG_DISABLE_MEM_THROTTLE = 0x00000040, + FLAG_IGNORE_OCC_STATE = 0x00000020, + FLAG_HOLD_OCCS_IN_RESET = 0x00000010, // Ignore load/start status + FLAG_LOAD_REQUEST_DISABLED = 0x00000008, + FLAG_TERMINATE_ON_ERROR = 0x00000004, + FLAG_RESET_DISABLED = 0x00000002, // Ignore any OCC reset + FLAG_EXTERNAL_OVERRIDE = 0x00000001 + }; + enum tmgtElogSubsecTypes { // Values selected to be common with FSP from tmgt_elog_parser.H @@ -123,11 +137,20 @@ namespace HTMGT enum htmgtPassThruCmds { PASSTHRU_OCC_STATUS = 0x01, + PASSTHRU_INTERNAL_FLAG = 0x02, // get or set internal flags PASSTHRU_SEND_OCC_COMMAND = 0x03, // send raw OCC command PASSTHRU_CLEAR_RESET_COUNTS = 0x04, PASSTHRU_EXIT_SAFE_MODE = 0x05, PASSTHRU_GENERATE_MFG_PSTATE = 0x81, - PASSTHRU_LOAD_PSTATE = 0x82 + PASSTHRU_LOAD_PSTATE = 0x82, + PASSTHRU_DUMP_ATTRIBUTE = 0x83 + }; + + enum htmgtAttrName + { + ATTR_PSTATE = 0x01, + ATTR_PSTATE_MFG = 0x02, + ATTR_RAW = 0xFF }; /** @@ -187,5 +210,31 @@ namespace HTMGT const char *state_string(const uint8_t i_state); + /** + * @brief Retrieve the internal flag (attribute) value + * + * @return the flag value (on error will return 0) + */ + uint32_t get_int_flags(); + + + /** + * @brief Update internal flags to specified value + * + * @param[in] i_value - new value for internal flags + */ + void set_int_flags(const uint32_t i_value); + + + /** + * @brief Query if specified internal flag(s) are set + * + * @param[in] i_mask - bits to query the internalFlags + * + * @return true if all of the bits of i_mask are set in internalFlags + */ + bool int_flags_set(const uint32_t i_mask); + + } // end namespace #endif diff --git a/src/usr/htmgt/occError.C b/src/usr/htmgt/occError.C index 00e4cc0e1..9af585c17 100644 --- a/src/usr/htmgt/occError.C +++ b/src/usr/htmgt/occError.C @@ -5,7 +5,7 @@ /* */ /* OpenPOWER HostBoot Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2014,2015 */ +/* Contributors Listed Below - COPYRIGHT 2014,2016 */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -255,6 +255,18 @@ namespace HTMGT ERRORLOG::errlCommit(err2, HTMGT_COMP_ID); } + if (int_flags_set(FLAG_HALT_ON_OCC_SRC)) + { + // Check if OCC SRC matches our trigger SRC + if ((l_occSrc & 0xFF) == (get_int_flags() >> 24)) + { + TMGT_ERR("occProcessElog: OCC%d reported 0x%04X and " + "HALT_ON_SRC is set. Resets will be disabled", + iv_instance, l_occSrc); + set_int_flags(get_int_flags() | FLAG_RESET_DISABLED); + } + } + // Add full OCC error log data as a User Details section l_errlHndl->addFFDC(OCCC_COMP_ID, l_occElog, |