From 85351118f1aa6d7cacca6b1085b1d965eeb492c4 Mon Sep 17 00:00:00 2001 From: Chris Cain Date: Fri, 5 Dec 2014 11:06:54 -0600 Subject: Move OCCs to active state Change-Id: I99918d0e1a27ed5cf7cb438e3e8e7f580c5306c7 RTC: 115922 Reviewed-on: http://gfw160.aus.stglabs.ibm.com:8080/gerrit/14740 Tested-by: Jenkins Server Reviewed-by: Douglas R. Gilbert Reviewed-by: A. Patrick Williams III --- src/usr/htmgt/htmgt.C | 107 ++++++++---- src/usr/htmgt/htmgt_activate.C | 89 +++++----- src/usr/htmgt/htmgt_activate.H | 14 -- src/usr/htmgt/htmgt_cfgdata.C | 186 +++++++++++++++++++++ src/usr/htmgt/htmgt_cfgdata.H | 52 ++++++ src/usr/htmgt/htmgt_common.mk | 2 + src/usr/htmgt/htmgt_occ.C | 254 ++++++++++++++++++++++++++--- src/usr/htmgt/htmgt_occ.H | 112 ++++++++++--- src/usr/htmgt/htmgt_occcmd.C | 357 +++++++++++++++++++++-------------------- src/usr/htmgt/htmgt_occcmd.H | 5 +- src/usr/htmgt/htmgt_poll.C | 229 ++++++++++++++++++++------ src/usr/htmgt/htmgt_poll.H | 31 ++-- src/usr/htmgt/htmgt_utility.C | 38 ++++- src/usr/htmgt/htmgt_utility.H | 13 +- src/usr/htmgt/occError.C | 289 +++++++++++++++++++++++++++++++++ src/usr/htmgt/occError.H | 227 ++++++++++++++++++++++++++ src/usr/hwpf/hwp/occ/makefile | 1 - src/usr/hwpf/hwp/occ/occ.C | 22 +-- src/usr/hwpf/hwp/occ/occ.mk | 2 + 19 files changed, 1652 insertions(+), 378 deletions(-) create mode 100644 src/usr/htmgt/occError.C create mode 100644 src/usr/htmgt/occError.H (limited to 'src/usr') diff --git a/src/usr/htmgt/htmgt.C b/src/usr/htmgt/htmgt.C index 5ed8be6c7..64307591f 100644 --- a/src/usr/htmgt/htmgt.C +++ b/src/usr/htmgt/htmgt.C @@ -31,6 +31,9 @@ #ifndef __HOSTBOOT_RUNTIME #include "genPstate.H" #endif +#include "htmgt_memthrottles.H" +#include "htmgt_poll.H" +#include // Targeting support #include @@ -39,16 +42,20 @@ #include +#include + namespace HTMGT { + const uint32_t HTMGT_DELAY_BEFORE_COMM = 5; + + // Move the OCCs to active state or log unrecoverable error and // stay in safe mode void processOccStartStatus(const bool i_startCompleted, TARGETING::Target * i_failedOccTarget) { errlHndl_t l_err = NULL; - uint32_t l_huid = 0; if (i_failedOccTarget) { @@ -59,36 +66,81 @@ namespace HTMGT if (i_startCompleted) { // Query functional OCCs - if (occMgr::instance().buildOccs() > 0) + const uint8_t numOccs = occMgr::instance().buildOccs(); + if (numOccs > 0) { - do + if (NULL != occMgr::instance().getMasterOcc()) { - //Pstatetable only built once at boot time. -#ifndef __HOSTBOOT_RUNTIME - l_err = genPstateTables(); - if(l_err) - { - break; - } -#endif - - // Calc memory throttles - // TODO RTC 116306 - - // Send ALL config data - sendOccConfigData(); - - // Wait for all OCCs to go active - l_err = waitForOccsActive(); - if( l_err ) + do { - break; - } + // Delay before communication with OCCs to make sure + // they are ready (since there is no initial attention) + nanosleep(HTMGT_DELAY_BEFORE_COMM, 0); - //Set active sensors for all OCCs so BMC can start comm - l_err = setOccActiveSensors(); +#ifndef __HOSTBOOT_RUNTIME + if (false == occMgr::instance().iv_configDataBuilt) + { + // Build pstate tables (once per IPL) + l_err = genPstateTables(); + if(l_err) + { + break; + } + + // Calc memory throttles (once per IPL) + calcMemThrottles(); + + occMgr::instance().iv_configDataBuilt = true; + } +#endif - } while(0); + // Send poll to establish comm + TMGT_INF("Send initial poll to all OCCs to" + " establish comm"); + errlHndl_t l_err = sendOccPoll(); + if (l_err) + { + // Continue even if failed (poll will be retried) + ERRORLOG::errlCommit(l_err, HTMGT_COMP_ID); + l_err = NULL; + } + + // Send ALL config data + sendOccConfigData(); + + // Wait for all OCCs to go active + l_err = waitForOccsActive(); + if ( l_err ) + { + break; + } + + // Set active sensors for all OCCs, + // so BMC can start communication with OCCs + l_err = setOccActiveSensors(); + if (l_err) + { + // Continue even if failed to update sensor + ERRORLOG::errlCommit(l_err, HTMGT_COMP_ID); + l_err = NULL; + } + } 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[0:7] number of OCCs + * @devdesc No OCC master was found + */ + bldErrLog(l_err, HTMGT_MOD_LOAD_START_STATUS, + HTMGT_RC_OCC_MASTER_NOT_FOUND, + numOccs, 0, 0, 0, + ERRORLOG::ERRL_SEV_INFORMATIONAL); + } } else { @@ -151,7 +203,6 @@ namespace HTMGT HWAS::SRCI_PRIORITY_MED); ERRORLOG::errlCommit(l_err, HTMGT_COMP_ID); - } } // end processOccStartStatus() @@ -169,7 +220,6 @@ namespace HTMGT - // Notify HTMGT that an OCC has failed and needs to be reset void processOccReset(TARGETING::Target * i_failedOccTarget) { @@ -180,5 +230,6 @@ namespace HTMGT } // end processOccReset() + } diff --git a/src/usr/htmgt/htmgt_activate.C b/src/usr/htmgt/htmgt_activate.C index ec9a7035c..66337bb31 100644 --- a/src/usr/htmgt/htmgt_activate.C +++ b/src/usr/htmgt/htmgt_activate.C @@ -37,6 +37,7 @@ #include #include +#include namespace HTMGT { @@ -47,54 +48,72 @@ namespace HTMGT #endif - // Send all config data to the OCCs - // (see ToifNode::toif_manager_config() in src/tmgt/fsp/tmgt_toifnode.C) - void sendOccConfigData() - { - TMGT_INF("sendOccConfigData: STUB"); - // TODO RTC 109066 - } - - - // Wait for all OCCs to reach active ready state - // (see ToifNode::wait_for_occ_ready() in tmgt_toifnode.C) errlHndl_t waitForOccReady() { errlHndl_t l_err = NULL; - l_err = sendOccPoll(); + const uint8_t OCC_NONE = 0xFF; + uint8_t waitingForInstance = OCC_NONE; + const size_t MAX_POLL = 40; + const size_t MSEC_BETWEEN_POLLS = 250; + size_t numPolls = 0; + std::vector occList = occMgr::instance().getOccArray(); - // TODO RTC 109066 - if (NULL == l_err) + do + { + // Poll all OCCs + l_err = sendOccPoll(); + ++numPolls; + if (NULL != l_err) + { + TMGT_ERR("waitForOccReady: Poll #%d failed w/rc=0x%04X", + numPolls, l_err->reasonCode()); + break; + } + + // Check each OCC for ready state + waitingForInstance = OCC_NONE; + for (std::vector::iterator itr = occList.begin(); + (itr < occList.end()); + ++itr) + { + Occ * occ = (*itr); + if (false == occ->statusBitSet(OCC_STATUS_ACTIVE_READY)) + { + waitingForInstance = occ->getInstance(); + break; + } + } + + if ((OCC_NONE != waitingForInstance) && (numPolls < MAX_POLL)) + { + // Still waiting for at least one OCC, delay and try again + nanosleep(0, NS_PER_MSEC * MSEC_BETWEEN_POLLS); + } + } while ((OCC_NONE != waitingForInstance) && (numPolls < MAX_POLL)); + + if ((OCC_NONE != waitingForInstance) && (NULL == l_err)) { - TMGT_ERR("waitForOccReady: Stub forcing failure"); + TMGT_ERR("waitForOccReady: OCC%d is not in ready state", + waitingForInstance); /*@ * @errortype - * @reasoncode HTMGT_RC_OCC_UNAVAILABLE - * @moduleid HTMGT_MOD_WAIT_FOR_OCC_READY - * @devdesc OCCs did not reach active ready state + * @reasoncode HTMGT_RC_OCC_NOT_READY + * @moduleid HTMGT_MOD_WAIT_FOR_OCC_READY + * @userdata1[0-15] OCC instance + * @userdata1[16-31] poll attempts + * @devdesc OCC not ready for active state */ bldErrLog(l_err, HTMGT_MOD_WAIT_FOR_OCC_READY, - HTMGT_RC_OCC_UNAVAILABLE, - 0, 0, 0, 0, + HTMGT_RC_OCC_NOT_READY, + waitingForInstance, numPolls, 0, 0, ERRORLOG::ERRL_SEV_INFORMATIONAL); } return l_err; - } - - - errlHndl_t setOccState(const occStateId i_state) - { - errlHndl_t l_err = NULL; - - TMGT_INF("setOccState: STUB"); - // TODO RTC 109066 - - return l_err; - } + } // end waitForOccReady() @@ -105,14 +124,12 @@ namespace HTMGT TMGT_INF("wait_for_occs_active called"); - // Wait for attns - not needed? - // Wait for all OCCs to be ready for active state l_err = waitForOccReady(); if (NULL == l_err) { // Send Set State (ACTIVE) to master - l_err = setOccState(OCC_STATE_ACTIVE); + l_err = occMgr::instance().setOccState(OCC_STATE_ACTIVE); if (NULL == l_err) { TMGT_INF("waitForOccsActive: OCCs are all active"); @@ -135,7 +152,7 @@ namespace HTMGT errlHndl_t l_err = NULL; TMGT_INF("setOccActiveSensors: STUB"); - // TODO RTC 109066 + // TODO RTC 119073 return l_err; } diff --git a/src/usr/htmgt/htmgt_activate.H b/src/usr/htmgt/htmgt_activate.H index 6e85dfd17..335615aa6 100644 --- a/src/usr/htmgt/htmgt_activate.H +++ b/src/usr/htmgt/htmgt_activate.H @@ -38,16 +38,6 @@ namespace HTMGT { - /** - * @brief Set the OCC state - * - * @param[in] i_state Desired OCC state - * - * @return NULL if success, else error handle - */ - errlHndl_t setOccState(const occStateId i_state); - - /** * @brief Wait for all OCCs to go to active state * @@ -63,10 +53,6 @@ namespace HTMGT */ errlHndl_t setOccActiveSensors(); - /** - * @brief send all occ configuration messages to the OCCs - */ - void sendOccConfigData(); } // end namespace #endif diff --git a/src/usr/htmgt/htmgt_cfgdata.C b/src/usr/htmgt/htmgt_cfgdata.C index d0a1151c0..baf4f5819 100644 --- a/src/usr/htmgt/htmgt_cfgdata.C +++ b/src/usr/htmgt/htmgt_cfgdata.C @@ -27,6 +27,7 @@ #include #include "htmgt_cfgdata.H" #include "htmgt_utility.H" +#include "htmgt_poll.H" using namespace TARGETING; @@ -38,6 +39,191 @@ using namespace TARGETING; namespace HTMGT { + // Send config format data to all OCCs + void sendOccConfigData(const occCfgDataFormat i_requestedFormat) + { + if (G_debug_trace & DEBUG_TRACE_VERBOSE) + { + TMGT_INF("sendOccConfigData called"); + } + + uint8_t cmdData[OCC_MAX_DATA_LENGTH] = {0}; + uint64_t cmdDataLen = OCC_MAX_DATA_LENGTH; + + const occCfgDataTable_t* start = &occCfgDataTable[0]; + const occCfgDataTable_t* end = + &occCfgDataTable[OCC_CONFIG_TABLE_SIZE]; + bool validFormat = true; + if (OCC_CFGDATA_CLEAR_ALL != i_requestedFormat) + { + const occCfgDataTable_t * target = + std::find(start, end, i_requestedFormat); + if (target != end) + { + // only need to send a single packet + start = target; + end = start+1; + } + else + { + TMGT_ERR("sendOccConfigData: Invalid cfg format supplied %d", + i_requestedFormat); + validFormat = false; + } + } + + if (validFormat) + { + // Loop through all functional OCCs + std::vector occList = occMgr::instance().getOccArray(); + for (std::vector::iterator itr = occList.begin(); + itr < occList.end(); + itr++) + { + Occ * occ = (*itr); + const uint8_t occInstance = occ->getInstance(); + const occRole role = occ->getRole(); + + // Loop through all config data types + for (const occCfgDataTable_t *itr = start; itr < end; ++itr) + { + const occCfgDataFormat format = itr->format; + bool sendData = true; + + // Make sure format is supported by this OCC + if (TARGET_MASTER == itr->targets) + { + if (OCC_ROLE_MASTER != role) + { + sendData = false; + } + } + + // Make sure data is supported in the current state + const occStateId state = occ->getState(); + if (CFGSTATE_STANDBY == itr->supportedStates) + { + if (OCC_STATE_STANDBY != state) + { + sendData = false; + } + } + else if (CFGSTATE_SBYOBS == itr->supportedStates) + { + if ((OCC_STATE_STANDBY != state) && + (OCC_STATE_OBSERVATION != state)) + { + sendData = false; + } + } + + if (sendData) + { + cmdDataLen = OCC_MAX_DATA_LENGTH; + switch(format) + { + case OCC_CFGDATA_PSTATE_SSTRUCT: + getPstateTableMessageData(occ->getTarget(), + cmdData, + cmdDataLen); + break; + + case OCC_CFGDATA_FREQ_POINT: + getFrequencyPointMessageData(cmdData, + cmdDataLen); + break; + + case OCC_CFGDATA_OCC_ROLE: + getOCCRoleMessageData(OCC_ROLE_MASTER == + occ->getRole(), + OCC_ROLE_FIR_MASTER == + occ->getRole(), + cmdData, cmdDataLen); + break; + + case OCC_CFGDATA_APSS_CONFIG: + getApssMessageData(cmdData, cmdDataLen); + break; + + case OCC_CFGDATA_MEM_CONFIG: + getMemConfigMessageData(occ->getTarget(), true, + cmdData, cmdDataLen); + break; + + case OCC_CFGDATA_FIR_SCOMS: + TMGT_ERR("NO FIR SCOMS AVAILABLE YET"); + cmdDataLen = 0; + break; + + case OCC_CFGDATA_PCAP_CONFIG: + getPowerCapMessageData(cmdData, cmdDataLen); + break; + + case OCC_CFGDATA_SYS_CONFIG: + getSystemConfigMessageData(cmdData, cmdDataLen); + break; + + case OCC_CFGDATA_MEM_THROTTLE: + getMemThrottleMessageData(occ->getTarget(), + cmdData, cmdDataLen); + break; + + case OCC_CFGDATA_TCT_CONFIG: + getThermalControlMessageData(cmdData, + cmdDataLen); + break; + + default: + TMGT_ERR("send_occ_config_data: Unsupported" + " format type 0x%02X", + format); + cmdDataLen = 0; + } + + if (cmdDataLen > 0) + { + TMGT_INF("send_occ_config_data: Sending config" + " 0x%02X to OCC%d", + format, occInstance); + OccCmd cmd(occ, OCC_CMD_SETUP_CFG_DATA, + cmdDataLen, cmdData); + errlHndl_t l_err = cmd.sendOccCmd(); + if (l_err != NULL) + { + TMGT_ERR("send_occ_config_data: OCC%d cfg " + "format 0x%02X failed with rc=0x%04X", + occInstance, format, + l_err->reasonCode()); + ERRORLOG::errlCommit(l_err, HTMGT_COMP_ID); + } + else + { + if (OCC_RC_SUCCESS != cmd.getRspStatus()) + { + TMGT_ERR("send_occ_config_data: OCC%d cfg " + "format 0x%02X had bad rsp status" + " 0x%02X for sysConfig", + occInstance, format, + cmd.getRspStatus()); + } + } + + // Send poll between config packets to flush errors + l_err = sendOccPoll(); + if (l_err) + { + ERRORLOG::errlCommit(l_err, HTMGT_COMP_ID); + } + } + } // if (sendData) + + } // for each config format + + } // for each OCC + } + + } // end send_occ_config_data() + /** OCC configuration data message versions */ enum occCfgDataVersion diff --git a/src/usr/htmgt/htmgt_cfgdata.H b/src/usr/htmgt/htmgt_cfgdata.H index 5b6d30f5a..b1c32f80f 100644 --- a/src/usr/htmgt/htmgt_cfgdata.H +++ b/src/usr/htmgt/htmgt_cfgdata.H @@ -67,6 +67,58 @@ namespace HTMGT }; + enum cfgTargets + { + TARGET_ALL = 0x00, + TARGET_MASTER = 0x01, + }; + + enum cfgSupStates + { + CFGSTATE_ALL = 0x00, + CFGSTATE_STANDBY = 0x01, + CFGSTATE_SBYOBS = 0x02 + }; + + const uint32_t TO_20SEC = 20; + + struct occCfgDataTable_t + { + occCfgDataFormat format; + cfgTargets targets; + uint16_t timeout; // in seconds + cfgSupStates supportedStates; + + bool operator==(const occCfgDataFormat& i_format) const + { + return (i_format == format); + } + }; + + const occCfgDataTable_t occCfgDataTable[] = + { + { OCC_CFGDATA_SYS_CONFIG, TARGET_ALL, TO_20SEC, CFGSTATE_ALL }, + { OCC_CFGDATA_APSS_CONFIG, TARGET_ALL, TO_20SEC, CFGSTATE_ALL }, + { OCC_CFGDATA_OCC_ROLE, TARGET_ALL, TO_20SEC, CFGSTATE_STANDBY }, + { OCC_CFGDATA_PSTATE_SSTRUCT, TARGET_ALL, TO_20SEC, CFGSTATE_SBYOBS }, + { OCC_CFGDATA_FREQ_POINT, TARGET_MASTER, TO_20SEC, CFGSTATE_ALL }, + { OCC_CFGDATA_MEM_CONFIG, TARGET_ALL, TO_20SEC, CFGSTATE_ALL }, + { OCC_CFGDATA_PCAP_CONFIG, TARGET_MASTER, TO_20SEC, CFGSTATE_ALL }, + { OCC_CFGDATA_MEM_THROTTLE, TARGET_ALL, TO_20SEC, CFGSTATE_ALL }, + { OCC_CFGDATA_TCT_CONFIG, TARGET_ALL, TO_20SEC, CFGSTATE_ALL } + }; + const size_t OCC_CONFIG_TABLE_SIZE = sizeof(occCfgDataTable) / + sizeof(occCfgDataTable_t); + + /** + * @brief Send config format data to all OCCs + * + * @param[in] config format to send. Default is to send + * all config formats. + */ + void sendOccConfigData(const occCfgDataFormat i_requestedFormat = + OCC_CFGDATA_CLEAR_ALL); + /** * Fills in the Memory Config Configuration Data message buffer, * including the format and version numbers. diff --git a/src/usr/htmgt/htmgt_common.mk b/src/usr/htmgt/htmgt_common.mk index 38ad4db39..5b33c6097 100644 --- a/src/usr/htmgt/htmgt_common.mk +++ b/src/usr/htmgt/htmgt_common.mk @@ -30,8 +30,10 @@ OBJS += htmgt_occcmd.o OBJS += htmgt_poll.o OBJS += htmgt_utility.o OBJS += htmgt_cfgdata.o +OBJS += occError.o EXTRAINCDIR += ${ROOTPATH}/src/include/usr/ecmddatabuffer EXTRAINCDIR += ${ROOTPATH}/src/include/usr/hwpf/fapi EXTRAINCDIR += ${ROOTPATH}/src/include/usr/hwpf/plat EXTRAINCDIR += ${ROOTPATH}/src/include/usr/hwpf/hwp +EXTRAINCDIR += ${ROOTPATH}/src/usr/hwpf/hwp/mc_config/mss_eff_config diff --git a/src/usr/htmgt/htmgt_occ.C b/src/usr/htmgt/htmgt_occ.C index 7722563ea..61cb04e71 100644 --- a/src/usr/htmgt/htmgt_occ.C +++ b/src/usr/htmgt/htmgt_occ.C @@ -29,6 +29,7 @@ #include "htmgt_occcmd.H" #include "htmgt_cfgdata.H" #include "htmgt_occ.H" +#include "htmgt_poll.H" // Targeting support #include @@ -37,9 +38,6 @@ #include -using namespace HTMGT; - - namespace HTMGT { @@ -48,21 +46,19 @@ namespace HTMGT uint8_t * i_homer, TARGETING::TargetHandle_t i_target, const occRole i_role) - :instance(i_instance), - masterCapable(i_masterCapable), - role(i_role), - state(OCC_STATE_UNKNOWN), - commEstablished(false), - needsReset(false), - failed(false), - seqNumber(0), - homer(i_homer), - target(i_target), - lastPollValid(false), - version(0x01) + :iv_instance(i_instance), + iv_masterCapable(i_masterCapable), + iv_role(i_role), + iv_state(OCC_STATE_UNKNOWN), + iv_commEstablished(false), + iv_needsReset(false), + iv_failed(false), + iv_seqNumber(0), + iv_homer(i_homer), + iv_target(i_target), + iv_lastPollValid(false), + iv_version(0x01) { - // Probably not needed... - huid = i_target->getAttr(); } Occ::~Occ() @@ -70,8 +66,99 @@ namespace HTMGT } + // Return true if specified status bit is set in last poll response + bool Occ::statusBitSet(const uint8_t i_statusBit) + { + bool isSet = false; + + if (iv_lastPollValid) + { + const occPollRspStruct_t *lastPoll = + (occPollRspStruct_t*)iv_lastPollResponse; + isSet = ((lastPoll->status & i_statusBit) == i_statusBit); + } + + return isSet; + } + + + // Set state of the OCC + errlHndl_t Occ::setState(const occStateId i_state) + { + errlHndl_t l_err = NULL; + + if (OCC_ROLE_MASTER == iv_role) + { + const uint8_t l_cmdData[3] = + { + 0x00, // version + i_state, + 0x00 // reserved + }; + + OccCmd cmd(this, OCC_CMD_SET_STATE, + sizeof(l_cmdData), l_cmdData); + l_err = cmd.sendOccCmd(); + if (l_err != NULL) + { + TMGT_ERR("setState: Failed to set OCC%d state, rc=0x%04X", + iv_instance, l_err->reasonCode()); + } + else + { + if (OCC_RC_SUCCESS != cmd.getRspStatus()) + { + TMGT_ERR("setState: Set OCC%d state failed" + " with OCC status 0x%02X", + iv_instance, cmd.getRspStatus()); + /*@ + * @errortype + * @moduleid HTMGT_MOD_OCC_SET_STATE + * @reasoncode HTMGT_RC_OCC_CMD_FAIL + * @userdata1[0-15] OCC instance + * @userdata1[16-31] Requested state + * @userdata2[0-15] OCC response status + * @userdata2[16-31] current OCC state + * @devdesc Set of OCC state failed + */ + bldErrLog(l_err, HTMGT_MOD_OCC_SET_STATE, + HTMGT_RC_OCC_CMD_FAIL, + iv_instance, i_state, + cmd.getRspStatus(), iv_state, + ERRORLOG::ERRL_SEV_INFORMATIONAL); + } + } + } + else + { + TMGT_ERR("setState: State only allowed to be set on master OCC"); + /*@ + * @errortype + * @moduleid HTMGT_MOD_OCC_SET_STATE + * @reasoncode HTMGT_RC_INTERNAL_ERROR + * @userdata1[0-15] OCC instance + * @userdata1[16-31] Requested state + * @devdesc Set state only allowed on master OCC + */ + bldErrLog(l_err, HTMGT_MOD_OCC_SET_STATE, + HTMGT_RC_INTERNAL_ERROR, + iv_instance, i_state, 0, 0, + ERRORLOG::ERRL_SEV_INFORMATIONAL); + } + + return l_err; + + } // end Occ::setState() + + + + ///////////////////////////////////////////////////////////////// + + + OccManager::OccManager() - :iv_occMaster(NULL), + :iv_configDataBuilt(false), + iv_occMaster(NULL), iv_state(OCC_STATE_UNKNOWN) { } @@ -128,7 +215,10 @@ namespace HTMGT // Get HOMER virtual address uint8_t * homer = (uint8_t*) ((*proc)->getAttr()); - TMGT_INF("buildOccs: homer = 0x%08X (from proc 0)", homer); + const uint8_t * homerPhys = (uint8_t*) + ((*proc)->getAttr()); + TMGT_INF("buildOccs: homer = 0x%08X (virt) / 0x%08X (phys)" + " for Proc%d", homer, homerPhys, instance); #ifdef SIMICS_TESTING // Starting of OCCs is not supported in SIMICS, so fake out // HOMER memory area for testing @@ -140,7 +230,7 @@ namespace HTMGT { // Allocate a fake HOMER area G_simicsHomerBuffer = - new uint8_t [HTMGT_OCC_CMD_ADDR+0x2000]; + new uint8_t [OCC_CMD_ADDR+0x2000]; } homer = G_simicsHomerBuffer; TMGT_ERR("buildOccs: Using hardcoded HOMER of 0x%08lX", @@ -183,7 +273,7 @@ namespace HTMGT - /* Add a functional OCC to be monitored */ + // Add a functional OCC to be monitored void OccManager::_addOcc(const uint8_t i_instance, const bool i_masterCapable, uint8_t * i_homer, @@ -224,6 +314,121 @@ namespace HTMGT } // end OccManager::_addOcc() + // Set the OCC state + errlHndl_t OccManager::_setOccState(const occStateId i_state) + { + errlHndl_t l_err = NULL; + + + if ((i_state == OCC_STATE_ACTIVE) || + (i_state == OCC_STATE_OBSERVATION)) + { + if (NULL != iv_occMaster) + { + TMGT_INF("_setOccState(state=0x%02X)", i_state); + + const uint8_t occInstance = iv_occMaster->getInstance(); + bool needsRetry = false; + do + { + l_err = iv_occMaster->setState(i_state); + if (NULL == l_err) + { + needsRetry = false; + } + else + { + TMGT_ERR("_setOccState: Failed to set OCC%d state," + " rc=0x%04X", + occInstance, l_err->reasonCode()); + if (false == needsRetry) + { + ERRORLOG::errlCommit(l_err, HTMGT_COMP_ID); + l_err = NULL; + needsRetry = true; + } + else + { + // Only one retry, return error handle + needsRetry = false; + } + } + } + while (needsRetry); + } + else + { + /*@ + * @errortype + * @moduleid HTMGT_MOD_OCCMGR_SET_STATE + * @reasoncode HTMGT_RC_INTERNAL_ERROR + * @devdesc Unable to set state of master OCC + */ + bldErrLog(l_err, HTMGT_MOD_OCCMGR_SET_STATE, + HTMGT_RC_INTERNAL_ERROR, + 0, 0, 0, 0, + ERRORLOG::ERRL_SEV_INFORMATIONAL); + } + + if (NULL == l_err) + { + // Send poll to query state of all OCCs + // and flush any errors reported by the OCCs + errlHndl_t l_err = sendOccPoll(true); + if (l_err) + { + TMGT_ERR("_setOccState: Poll all OCCs failed"); + ERRORLOG::errlCommit(l_err, HTMGT_COMP_ID); + } + + // Make sure all OCCs went to active state + for (std::vector::iterator pOcc = iv_occArray.begin(); + pOcc < iv_occArray.end(); + pOcc++) + { + if (i_state != (*pOcc)->getState()) + { + TMGT_ERR("_setOccState: OCC%d is not in 0x%02X state", + (*pOcc)->getInstance(), i_state); + /*@ + * @errortype + * @moduleid HTMGT_MOD_OCCMGR_SET_STATE + * @reasoncode HTMGT_RC_OCC_UNEXPECTED_STATE + * @userdata1[0-15] requested state + * @userdata1[16-31] OCC state + * @userdata2[0-15] OCC instance + * @devdesc OCC did not change to requested state + */ + bldErrLog(l_err, HTMGT_MOD_OCCMGR_SET_STATE, + HTMGT_RC_OCC_UNEXPECTED_STATE, + i_state, (*pOcc)->getState(), + (*pOcc)->getInstance(), 0, + ERRORLOG::ERRL_SEV_INFORMATIONAL); + break; + } + } + } + } + else + { + TMGT_ERR("_setOccState: Invalid state 0x%02X requested", i_state); + /*@ + * @errortype + * @moduleid HTMGT_MOD_OCCMGR_SET_STATE + * @reasoncode HTMGT_RC_INVALID_DATA + * @userdata1[0-15] requested state + * @devdesc Invalid OCC state requested + */ + bldErrLog(l_err, HTMGT_MOD_OCCMGR_SET_STATE, + HTMGT_RC_INVALID_DATA, + i_state, 0, 0, 0, + ERRORLOG::ERRL_SEV_INFORMATIONAL); + } + + return l_err; + + } // end OccManager::_setOccState() + uint8_t OccManager::getNumOccs() { @@ -249,9 +454,14 @@ namespace HTMGT } + errlHndl_t OccManager::setOccState(const occStateId i_state) + { + return Singleton::instance()._setOccState(i_state); + } + #if 0 - // TODO: RTC 109066 + // TODO: RTC 115296 void update_occ_data() { if (occMgr::instance().getNumOccs() > 0) diff --git a/src/usr/htmgt/htmgt_occ.H b/src/usr/htmgt/htmgt_occ.H index 9ac7b350e..ec0216aa6 100644 --- a/src/usr/htmgt/htmgt_occ.H +++ b/src/usr/htmgt/htmgt_occ.H @@ -103,15 +103,21 @@ namespace HTMGT * * @return instance number for this OCC */ - const uint8_t getInstance() { return instance; }; + uint8_t getInstance() { return iv_instance; }; /** * @brief Return pointer to the last poll response * - * @return pointer to last poll response + * @param[out] o_pollRspPtr pointer to last poll rsp data + * + * @return true if data is valid, else false */ - const uint8_t *getLastPollRsp() { return lastPollResponse; }; + bool getLastPollRsp(const uint8_t * & o_pollRspPtr) + { + o_pollRspPtr = iv_lastPollResponse; + return iv_lastPollValid; + }; /** @@ -119,42 +125,87 @@ namespace HTMGT * * @return pointer to last poll response */ - TARGETING::TargetHandle_t getTarget() { return target; }; + TARGETING::TargetHandle_t getTarget() { return iv_target; }; + + + /** + * @brief Process an OCC poll response + * + * @param[in] i_pollResponse pointer to the response + * @param[in] i_pollResponseSize length of the poll response + */ + void pollRspHandler(const uint8_t * i_pollResponse, + const uint16_t i_pollResponseSize); + + + /** + * @brief Return true if the specified status bit was set in + * the last poll response + * + * @param[in] i_statusBit Bit(s) to check in the poll response + * + * @return true if the bit(s) are set, else false + */ + bool statusBitSet(const uint8_t i_statusBit); + + + /** + * @brief Set the state of the OCC. + * This is only allowed on the master OCC + * + * @param[in] i_state Desired OCC state + * + * @return NULL on success, or error handle on failure + */ + errlHndl_t setState(const occStateId i_state); + + + /** + * @brief Return OCC role + * + * @return role of this OCC + */ + occRole getRole() { return iv_role; }; + + + /** + * @brief Return OCC state + * + * @return state of this OCC + */ + occStateId getState() { return iv_state; }; protected: // Instance number of this OCC: 0 = first physical OCC - uint8_t instance; + uint8_t iv_instance; // true if this OCC is capable of Master role (wired to APSS) - bool masterCapable; + bool iv_masterCapable; // Role of this OCC - occRole role; + occRole iv_role; // State of this OCC - occStateId state; + occStateId iv_state; // true if communication to this OCC has been established - bool commEstablished; + bool iv_commEstablished; // true if OCC needs to be reset - bool needsReset; + bool iv_needsReset; // true if OCC failed - bool failed; + bool iv_failed; // Sequence number of last/current OCC command - uint8_t seqNumber; + uint8_t iv_seqNumber; // HOMER base address - uint8_t * homer; + uint8_t * iv_homer; // OCC target - TARGETING::TargetHandle_t target; + TARGETING::TargetHandle_t iv_target; // Last poll response (excluding sensor data) - uint8_t lastPollResponse[OCC_POLL_DATA_MIN_SIZE]; + uint8_t iv_lastPollResponse[OCC_POLL_DATA_MIN_SIZE]; // true if lastPollResponse contains valid data - bool lastPollValid; - - // HOM Unit Id of this OCC - TARGETING::ATTR_HUID_type huid; + bool iv_lastPollValid; private: // Version of data stored (0 = not written) - uint8_t version; + uint8_t iv_version; }; @@ -174,6 +225,14 @@ namespace HTMGT friend class Occ; public: + /** + * @brief true if the required config data has been built + * This must be persisted across IPL/RT + * TODO: RTC 115296 + */ + bool iv_configDataBuilt; + + /** * @brief Constructor */ @@ -218,6 +277,16 @@ namespace HTMGT static Occ * getMasterOcc(); + /** + * @brief Set the state of the OCCs + * + * @param[in] i_state Desired OCC state + * + * @return NULL on success, or error handle on failure + */ + errlHndl_t setOccState(const occStateId i_state); + + private: Occ * iv_occMaster; std::vector iv_occArray; @@ -260,6 +329,9 @@ namespace HTMGT Occ * _getMasterOcc() { return iv_occMaster; }; + /* See setOccState() above */ + errlHndl_t _setOccState(const occStateId i_state); + }; typedef Singleton occMgr; diff --git a/src/usr/htmgt/htmgt_occcmd.C b/src/usr/htmgt/htmgt_occcmd.C index 97ae2564e..e21fdc10c 100644 --- a/src/usr/htmgt/htmgt_occcmd.C +++ b/src/usr/htmgt/htmgt_occcmd.C @@ -36,45 +36,13 @@ #include #include +#include #include #include #include #include -// TODO RTC 115922 -#ifdef __HOSTBOOT_RUNTIME -#include -#endif - - - -// TODO: RTC 115922 -#if 0 -#include -#else -namespace HBOCC -{ - - /** - * @brief Write OCC Circular Buffer - * - * @param[in] i_pTarget PROC or OCC target pointer - * @param[in] i_dataBuf Reference to data buffer - * @return errlHndl_t Error log if operation failed - */ - errlHndl_t writeCircularBuffer(const TARGETING::Target*i_pTarget, - ecmdDataBufferBase & i_dataBuf) - { - errlHndl_t l_err = NULL; - TRACFCOMP( HTMGT::g_trac_htmgt, "writeCircularBuffer(STUB): " - "setting status to 0xFF"); - return l_err; - } // end writeCircularBuffer() - -} //end OCC namespace -#endif - namespace HTMGT @@ -82,6 +50,8 @@ namespace HTMGT uint8_t g_cmd = 0; uint8_t g_seq = 0; + const uint16_t MAX_FFDC = 512; + struct occCircBufferCmd_t { uint8_t senderId; @@ -92,7 +62,6 @@ namespace HTMGT // Note: Read length must be 8 byte aligned (for SRAM reads) const uint16_t RD_MAX = (OCC_MAX_DATA_LENGTH - 8); - const uint16_t TO_20SEC = 20 * 1000; const occCommandTable_t OccCmd::cv_occCommandTable[] = { // Command Support RspCheck @@ -131,7 +100,7 @@ namespace HTMGT { uint8_t l_index = 0; - // TODO RTC 109066 - convert to use lower_bound + // TODO RTC 109224 - convert to use lower_bound //= find(&cv_occCommandTable[0], // &cv_occCommandTable[OCC_CMDTABLE_SIZE-1], // i_cmd); @@ -183,7 +152,7 @@ namespace HTMGT }; uint8_t l_idx = 0; - // TODO RTC 109066 + // TODO RTC 109224 for (l_idx=0; l_idx < STATUS_STRING_COUNT; l_idx++) { if (i_status == L_status_string[l_idx].str_num) @@ -241,7 +210,7 @@ namespace HTMGT bool OccCmd::traceCommand() { bool o_cmdWasTraced = true; - const uint8_t l_instance = iv_Occ->instance; + const uint8_t l_instance = iv_Occ->iv_instance; const uint8_t l_cmd_index = getCmdIndex(iv_OccCmd.cmdType); if (OCC_CMD_END_OF_TABLE != cv_occCommandTable[l_cmd_index].cmdType) @@ -313,7 +282,7 @@ namespace HTMGT void OccCmd::traceResponse() { char l_rsp_status_string[64] = ""; - const uint8_t l_instance = iv_Occ->instance; + const uint8_t l_instance = iv_Occ->iv_instance; if (iv_OccRsp.returnStatus != OCC_RC_SUCCESS) { @@ -337,7 +306,7 @@ namespace HTMGT void OccCmd::processOccResponse(errlHndl_t & io_errlHndl, const bool i_traceRsp) { - const uint8_t l_instance = iv_Occ->instance; + const uint8_t l_instance = iv_Occ->iv_instance; const bool alreadyRetriedOnce = iv_RetryCmd; iv_RetryCmd = false; @@ -356,12 +325,8 @@ namespace HTMGT if ((alreadyRetriedOnce == false) && (OCC_RC_PRESENT_STATE_PROHIBITS != iv_OccRsp.returnStatus)) { - // A retry has not been sent yet, commit/delete the error - // and retry. Add OCC command data to user details - // TODO RTC 115922 - //io_errlHndl->addUsrDtls(iv_OccCmd.cmdData, - // iv_OccCmd.dataLength, HTMGT_COMP_ID, - // 0/*version*/, TMGT_OCC_CMD_DATA); + // A retry has not been sent yet, commit the error + // and retry. ERRORLOG::errlCommit(io_errlHndl, HTMGT_COMP_ID); iv_RetryCmd = true; // Clear/init the response data structure @@ -389,9 +354,9 @@ namespace HTMGT TMGT_ERR("processOccResponse: OCC%d response had" " checksum or internal error," " need to RESET OCC", l_instance); - iv_Occ->needsReset = true; + iv_Occ->iv_needsReset = true; // Mark OCC as failed - iv_Occ->failed = true; + iv_Occ->iv_failed = true; } } } @@ -407,9 +372,9 @@ namespace HTMGT // sent... reset OCC TMGT_ERR("Sending OCC%d command failed twice, need to RESET" " OCC", l_instance); - iv_Occ->needsReset = true; + iv_Occ->iv_needsReset = true; // Unable to communicate with OCC, mark as failed - iv_Occ->failed = true; + iv_Occ->iv_failed = true; } else { @@ -418,11 +383,6 @@ namespace HTMGT { // A retry has not been sent yet, commit the error // and retry. - // Add OCC command data to user details - // TODO RTC 115922 - //io_errlHndl->addUsrDtls(iv_OccCmd.cmdData, - //iv_OccCmd.dataLength, HTMGT_COMP_ID, - //0/*version*/, TMGT_OCC_CMD_DATA); ERRORLOG::errlCommit(io_errlHndl, HTMGT_COMP_ID); iv_RetryCmd = true; @@ -451,9 +411,9 @@ namespace HTMGT TMGT_ERR("processOccResponse: OCC%d response had" " checksum or internal error," " need to RESET OCC", l_instance); - iv_Occ->needsReset = true; + iv_Occ->iv_needsReset = true; // Unable to communicate with OCC, mark as failed - iv_Occ->failed = true; + iv_Occ->iv_failed = true; } } } @@ -470,13 +430,15 @@ namespace HTMGT if (iv_Occ != NULL) { - const occStateId l_occState = iv_Occ->state; + const occStateId l_occState = iv_Occ->iv_state; l_cmd_index = getCmdIndex(iv_OccCmd.cmdType); if (OCC_CMD_END_OF_TABLE!=cv_occCommandTable[l_cmd_index].cmdType) { const bool cmdTraced = traceCommand(); - const bool l_commEstablished = iv_Occ->commEstablished; + // Only allow commands if comm has been established, + // or this is a poll command + const bool l_commEstablished = iv_Occ->iv_commEstablished; if ( (true == l_commEstablished) || ((false == l_commEstablished) && (OCC_CMD_POLL == iv_OccCmd.cmdType)) ) @@ -553,10 +515,11 @@ namespace HTMGT if (l_errlHndl) { // Add OCC command data to user details - // TODO RTC 115922 - //l_errlHndl->addUsrDtls(iv_OccCmd.cmdData, - // iv_OccCmd.dataLength, HTMGT_COMP_ID, - // 0/*version*/, TMGT_OCC_CMD_DATA); + l_errlHndl->addFFDC(HTMGT_COMP_ID, + iv_OccCmd.cmdData, + std::min(iv_OccCmd.dataLength, MAX_FFDC), + 1, // version + SUBSEC_OCC_CMD_DATA); } return l_errlHndl; @@ -572,7 +535,7 @@ namespace HTMGT static uint8_t L_state = 0; static uint8_t L_prior_status = 0x00; static uint8_t L_prior_sequence = 0x00; - uint8_t * const rspBuffer = iv_Occ->homer + HTMGT_OCC_RSP_ADDR; + uint8_t * const rspBuffer = iv_Occ->iv_homer + OCC_RSP_ADDR; if (0 == L_state) { @@ -668,7 +631,7 @@ namespace HTMGT { TMGT_INF("fakeOccResponse: sequence updated to 0x%02X" " (expecting=0x%02X)", - rspBuffer[0], iv_Occ->seqNumber); + rspBuffer[0], iv_Occ->iv_seqNumber); L_prior_sequence = rspBuffer[0]; } @@ -680,7 +643,7 @@ namespace HTMGT // Returns true if timeout waiting for response bool OccCmd::waitForOccRsp(uint32_t i_timeout) { - const uint8_t * const rspBuffer = iv_Occ->homer + HTMGT_OCC_RSP_ADDR; + const uint8_t * const rspBuffer = iv_Occ->iv_homer + OCC_RSP_ADDR; uint16_t rspLength = 0; if (G_debug_trace & DEBUG_TRACE_VERBOSE) { @@ -688,9 +651,10 @@ namespace HTMGT } bool l_time_expired = true; - const uint32_t OCC_RSP_SAMPLE_TIME = 100; // in milliseconds - uint32_t l_msec_remaining = std::max(i_timeout, OCC_RSP_SAMPLE_TIME); - while (l_msec_remaining > 0) + const int64_t OCC_RSP_SAMPLE_TIME = 100; // in milliseconds + int64_t l_msec_remaining = + std::max(int64_t(i_timeout * 1000), OCC_RSP_SAMPLE_TIME); + while (l_msec_remaining >= 0) { #ifdef SIMICS_TESTING fakeOccResponse(); @@ -704,7 +668,7 @@ namespace HTMGT // Note: Need to check the sequence number to be sure we are // processing the expected response if ((OCC_COMMAND_IN_PROGRESS != rspBuffer[2]) && - (iv_Occ->seqNumber == rspBuffer[0])) + (iv_Occ->iv_seqNumber == rspBuffer[0])) { // Need an 'isync' here to ensure that previous instructions // have completed before the code continues on. This is a type @@ -719,39 +683,68 @@ namespace HTMGT rspLength = OCC_RSP_HDR_LENGTH + rspDataLen; if (G_debug_trace & DEBUG_TRACE_OCCCMD) { - TMGT_INF("waitForOccRsp: OCC%d rsp (huid=0x%08X," - " rsp length=%d)", - iv_Occ->instance, iv_Occ->huid, rspLength); - TMGT_BIN("waitForOccRsp: OCC rsp data (up to 256 bytes)", - rspBuffer, std::min(rspLength, (uint16_t)256)); + TMGT_INF("waitForOccRsp: OCC%d rsp (rsp length=%d)", + iv_Occ->iv_instance, rspLength); + TMGT_BIN("waitForOccRsp: OCC rsp data (up to 300 bytes)", + rspBuffer, std::min(rspLength, (uint16_t)300)); } l_time_expired = false; break; } - // delay before next check - const uint32_t l_sleep_msec = std::min(l_msec_remaining, - OCC_RSP_SAMPLE_TIME); - - // TODO RTC 115922 -#ifndef __HOSTBOOT_RUNTIME - nanosleep( 0, NS_PER_MSEC * l_sleep_msec ); -#else - if(g_hostInterfaces && g_hostInterfaces->nanosleep) + if (l_msec_remaining > 0) { - g_hostInterfaces->nanosleep(0, NS_PER_MSEC * l_sleep_msec); + // delay before next check + const int64_t l_sleep_msec = std::min(l_msec_remaining, + OCC_RSP_SAMPLE_TIME); + nanosleep( 0, NS_PER_MSEC * l_sleep_msec ); + l_msec_remaining -= l_sleep_msec; } + else + { + // time expired + l_msec_remaining = -1; + + // Read SRAM response buffer to check for exception + // (On exception, data may not be copied to HOMER) + const uint16_t l_length = 4*KILOBYTE; + uint8_t l_sram_data[l_length]; + ecmdDataBufferBase l_buffer(l_length*8); // convert to bits +// HBOCC is only defined for HTMGT +#ifdef CONFIG_HTMGT + errlHndl_t l_err = HBOCC::readSRAM(iv_Occ->getTarget(), + OCC_RSP_SRAM_ADDR, + l_buffer); + if (NULL == l_err) #endif - l_msec_remaining -= l_sleep_msec; + { + const uint32_t l_flatSize = l_buffer.flattenSize(); + l_buffer.flatten(l_sram_data, l_flatSize); + // Skip 8 byte ecmd header + const uint8_t *sramRspPtr = &l_sram_data[8]; + // Check response status for exception + if (0xE0 == (sramRspPtr[2] & 0xE0)) + { + TMGT_ERR("waitForOccRsp: OCC%d timeout waiting for" + " response, and OCC 0x%02X exception found", + iv_Occ->iv_instance, sramRspPtr[2]); + // Exception found, copy data to rsp buffer + uint8_t * const rspBuffer = iv_Occ->iv_homer + + OCC_RSP_ADDR; + memcpy(rspBuffer, sramRspPtr, l_length); + TMGT_BIN("SRAM Rsp Buffer (32 bytes)", sramRspPtr, 32); + } + } + } - } // while + } // while(time remaining) if (l_time_expired) { // timeout waiting for response TMGT_ERR("waitForOccRsp: OCC%d timeout waiting for response" " (%d sec)", - iv_Occ->instance, i_timeout/1000); + iv_Occ->iv_instance, i_timeout/1000); } return l_time_expired; @@ -770,7 +763,7 @@ namespace HTMGT TMGT_ERR("handleOccException: OCC%d returned abnormal rsp status of" " 0x%02X, rsp len=%d", - iv_Occ->instance, iv_OccRsp.returnStatus, + iv_Occ->iv_instance, iv_OccRsp.returnStatus, l_exceptionDataLength); if (l_exceptionDataLength > 4*KILOBYTE) { @@ -785,23 +778,19 @@ namespace HTMGT * @moduleid HTMGT_MOD_HANLDE_OCC_EXCEPTION * @userdata1[0-15] rsp status * @userdata1[16-31] exception data length - * @userdata2[0-15] huid - * @userdata2[16-31] * @devdesc OCC reported exception */ errlHndl_t l_excErr = NULL; bldErrLog(l_excErr, HTMGT_MOD_HANLDE_OCC_EXCEPTION, (htmgtReasonCode)(OCCC_COMP_ID | iv_OccRsp.returnStatus), - iv_OccRsp.returnStatus, iv_OccRsp.dataLength, - iv_Occ->huid, 0, - ERRORLOG::ERRL_SEV_INFORMATIONAL //, - //false, // dont skip traces - // OCCC_COMP_ID); - // TODO RTC 115922 - //l_excErr->addUsrDtls(l_excp_buffer, l_excp_length, - // OCCC_COMP_ID, 1 /*version*/, - // iv_OccRsp.returnStatus/*type*/ - ); + iv_OccRsp.returnStatus, iv_OccRsp.dataLength, 0, 0, + ERRORLOG::ERRL_SEV_INFORMATIONAL); + const uint8_t * const exceptionData = iv_Occ->iv_homer + OCC_RSP_ADDR; + l_excErr->addFFDC(OCCC_COMP_ID, + exceptionData, + std::min(l_exceptionDataLength, (uint32_t)MAX_FFDC), + 1, // version + iv_OccRsp.returnStatus); // subsection == exception rc ERRORLOG::errlCommit(l_excErr, HTMGT_COMP_ID); } // end OccCmd::handleOccException() @@ -836,84 +825,95 @@ namespace HTMGT { TMGT_INF("writeOccCmd: Calling writeCircularBuffer()"); } - l_err = HBOCC::writeCircularBuffer(iv_Occ->target, l_circ_buffer); +#ifdef CONFIG_HTMGT + l_err = HBOCC::writeCircularBuffer(iv_Occ->iv_target, l_circ_buffer); if (NULL != l_err) { - TMGT_ERR("writeOccCmd: Error writing to OCC Circular Buffer"); + TMGT_ERR("writeOccCmd: Error writing to OCC Circular Buffer," + " rc=0x%04X", l_err->reasonCode()); } - else - { - // Wait for response from the OCC - const uint8_t l_instance = iv_Occ->instance; - const uint8_t l_index = getCmdIndex(iv_OccCmd.cmdType); - // l_index should be valid since validation was done in sendOccCmd() - const uint16_t l_read_timeout = cv_occCommandTable[l_index].timeout; +#endif - // Wait for OCC to process command and send response - waitForOccRsp(l_read_timeout); + // Continue to try to read response buffer, in case an + // exception happened... - // Parse the OCC response (called even on timeout to collect - // rsp buffer) - l_err = parseOccResponse(); + // Wait for response from the OCC + const uint8_t l_instance = iv_Occ->iv_instance; + const uint8_t l_index = getCmdIndex(iv_OccCmd.cmdType); + const uint16_t l_read_timeout = cv_occCommandTable[l_index].timeout; - bool l_timeout = false; - if (OCC_COMMAND_IN_PROGRESS != iv_OccRsp.returnStatus) + // Wait for OCC to process command and send response + waitForOccRsp(l_read_timeout); + + // Parse the OCC response (called even on timeout to collect + // rsp buffer) + l_err = parseOccResponse(); + + bool l_timeout = false; + if (OCC_COMMAND_IN_PROGRESS != iv_OccRsp.returnStatus) + { + // Status of 0xE0-EF are reserved for OCC exceptions, + // must collect data for these + if (0xE0 == (iv_OccRsp.returnStatus & 0xF0)) { - // Status of 0xE0-EF are reserved for OCC exceptions, - // must collect data for these - if (0xE0 == (iv_OccRsp.returnStatus & 0xF0)) - { - handleOccException(); - } - else - { - if (iv_OccRsp.sequenceNumber != - iv_OccCmd.sequenceNumber) - { - // Sequence number mismatch - TMGT_ERR("writeOccCmd: OCC%d sequence number mismatch" - " (from cmd: 0x%02X, rsp: 0x%02X)", - l_instance, iv_OccCmd.sequenceNumber, - iv_OccRsp.sequenceNumber); - l_timeout = true; - } - } + handleOccException(); + l_timeout = true; } else { - // OCC must not have completed processing the command before - // timeout - l_timeout = true; + if (iv_OccRsp.sequenceNumber != + iv_OccCmd.sequenceNumber) + { + // Sequence number mismatch + TMGT_ERR("writeOccCmd: OCC%d sequence number mismatch" + " (from cmd: 0x%02X, rsp: 0x%02X)", + l_instance, iv_OccCmd.sequenceNumber, + iv_OccRsp.sequenceNumber); + l_timeout = true; + } } + } + else + { + // OCC must not have completed processing the command before + // timeout + l_timeout = true; + } - if (l_timeout) - { - /*@ - * @errortype - * @reasoncode HTMGT_RC_TIMEOUT - * @moduleid HTMGT_MOD_WRITE_OCC_CMD - * @userdata1[0-15] command - * @userdata1[16-31] read timeout - * @userdata2[0-15] response sequence number - * @userdata2[16-31] response status - * @devdesc Timeout waiting for OCC response - */ - bldErrLog(l_err, HTMGT_MOD_WRITE_OCC_CMD, HTMGT_RC_TIMEOUT, - iv_OccCmd.cmdType, l_read_timeout, - iv_OccRsp.sequenceNumber, - iv_OccRsp.returnStatus, - ERRORLOG::ERRL_SEV_INFORMATIONAL); - - // The response buffer did not contain correct sequence number, - // or staus is still in progress save 1K rsp data - // TODO RTC 115922 - //l_err->addUsrDtls(l_err, l_excp_length, - // OCCC_COMP_ID, 1 /*version*/, 0xF0 /*type*/); + if (l_timeout) + { + /*@ + * @errortype + * @refcode LIC_REFCODE + * @subsys EPUB_FIRMWARE_SP + * @reasoncode HTMGT_RC_TIMEOUT + * @moduleid HTMGT_MOD_WRITE_OCC_CMD + * @userdata1[0-15] command + * @userdata1[16-31] read timeout + * @userdata2[0-15] response sequence number + * @userdata2[16-31] response status + * @devdesc Timeout waiting for OCC response + */ + bldErrLog(l_err, HTMGT_MOD_WRITE_OCC_CMD, HTMGT_RC_TIMEOUT, + iv_OccCmd.cmdType, l_read_timeout, + iv_OccRsp.sequenceNumber, + iv_OccRsp.returnStatus, + ERRORLOG::ERRL_SEV_INFORMATIONAL); - // timeout waiting for response (no data to return) - iv_OccRsp.dataLength = 0; - } // end timeout - } + // The response buffer did not contain correct sequence number, + // or status is still in progress ==> timeout + const uint8_t * const rspBuffer = iv_Occ->iv_homer + OCC_RSP_ADDR; + const uint16_t rspLen = OCC_RSP_HDR_LENGTH + + UINT16_GET(&rspBuffer[3]); + l_err->addFFDC(HTMGT_COMP_ID, + rspBuffer, + std::min(rspLen, MAX_FFDC), + 1, + SUBSEC_OCC_RSP_DATA); + + // timeout waiting for response (no data to return) + iv_OccRsp.dataLength = 0; + } // end timeout return l_err; @@ -924,15 +924,15 @@ namespace HTMGT // Copy OCC command into command buffer in HOMER uint16_t OccCmd::buildOccCmdBuffer() { - uint8_t * const cmdBuffer = iv_Occ->homer + HTMGT_OCC_CMD_ADDR; + uint8_t * const cmdBuffer = iv_Occ->iv_homer + OCC_CMD_ADDR; uint16_t l_send_length = 0; - if (0 == ++iv_Occ->seqNumber) + if (0 == ++iv_Occ->iv_seqNumber) { // Do not use 0 for sequence number - ++iv_Occ->seqNumber; + ++iv_Occ->iv_seqNumber; } - iv_OccCmd.sequenceNumber = iv_Occ->seqNumber; + iv_OccCmd.sequenceNumber = iv_Occ->iv_seqNumber; cmdBuffer[l_send_length++] = iv_OccCmd.sequenceNumber; cmdBuffer[l_send_length++] = iv_OccCmd.cmdType; cmdBuffer[l_send_length++] = (iv_OccCmd.dataLength >> 8) & 0xFF; @@ -982,7 +982,7 @@ namespace HTMGT { errlHndl_t l_errlHndl = NULL; uint16_t l_index = 0; - const uint8_t * const rspBuffer = iv_Occ->homer + HTMGT_OCC_RSP_ADDR; + const uint8_t * const rspBuffer = iv_Occ->iv_homer + OCC_RSP_ADDR; const uint16_t rspLen = OCC_RSP_HDR_LENGTH + UINT16_GET(&rspBuffer[3]); if ((NULL != rspBuffer) && (rspLen >= OCC_RSP_HDR_LENGTH)) @@ -1046,9 +1046,11 @@ namespace HTMGT if (l_errlHndl) { // Add full OCC response to user details - // TODO RTC 115922 - //l_errlHndl->addUsrDtls(rspBuffer, rspLen, HTMGT_COMP_ID, - // 0/*version*/, TMGT_OCC_RSP_DATA); + l_errlHndl->addFFDC(HTMGT_COMP_ID, + rspBuffer, + std::min(rspLen, MAX_FFDC), + 1, // version + SUBSEC_OCC_RSP_DATA); } return l_errlHndl; @@ -1195,10 +1197,11 @@ namespace HTMGT if (l_errlHndl) { // Add OCC response data to user details - // TODO RTC 115922 - // l_errlHndl->addUsrDtls(iv_OccRsp.rspData, - // iv_OccRsp.dataLength, HTMGT_COMP_ID, - // 0/*version*/, TMGT_OCC_RSP_DATA); + l_errlHndl->addFFDC(HTMGT_COMP_ID, + iv_OccRsp.rspData, + std::min(iv_OccRsp.dataLength,MAX_FFDC), + 1, // version + SUBSEC_OCC_RSP_DATA); } return(l_errlHndl); diff --git a/src/usr/htmgt/htmgt_occcmd.H b/src/usr/htmgt/htmgt_occcmd.H index 6bc5d75fc..252fc3852 100644 --- a/src/usr/htmgt/htmgt_occcmd.H +++ b/src/usr/htmgt/htmgt_occcmd.H @@ -36,9 +36,10 @@ namespace HTMGT { - const uint32_t HTMGT_OCC_CMD_ADDR = 0x001EE000; - const uint32_t HTMGT_OCC_RSP_ADDR = 0x001EF000; + const uint32_t OCC_CMD_ADDR = 0x001EE000; + const uint32_t OCC_RSP_ADDR = 0x001EF000; const uint32_t OCC_MAX_DATA_LENGTH = 0x00001000; + const uint32_t OCC_RSP_SRAM_ADDR = 0xFFFF7000; // The following header lengths include the 2 byte checksum const uint16_t OCC_CMD_HDR_LENGTH = 6; diff --git a/src/usr/htmgt/htmgt_poll.C b/src/usr/htmgt/htmgt_poll.C index bd9780a95..6cf0a5e63 100644 --- a/src/usr/htmgt/htmgt_poll.C +++ b/src/usr/htmgt/htmgt_poll.C @@ -30,6 +30,7 @@ #include "htmgt_poll.H" #include "htmgt_occcmd.H" #include "htmgt_cfgdata.H" +#include "occError.H" // Targeting support #include @@ -38,14 +39,11 @@ #include -using namespace HTMGT; - - namespace HTMGT { - // Send a single poll command to OCC - errlHndl_t sendOccPoll() + // Send a poll command to all OCCs + errlHndl_t sendOccPoll(const bool i_flushAllErrors) { errlHndl_t l_err = NULL; uint8_t * l_poll_rsp = NULL; @@ -58,46 +56,65 @@ namespace HTMGT { Occ * occ = (*itr); const uint8_t occInstance = occ->getInstance(); - TMGT_INF("sendOccPoll: to OCC%d", occInstance); - - // create 1 byte buffer for poll command data - const uint8_t l_cmdData[1] = { 0x10 /*version*/ }; - OccCmd cmd(occ, OCC_CMD_POLL, sizeof(l_cmdData), l_cmdData); - l_err = cmd.sendOccCmd(); - if (l_err != NULL) - { - // Poll failed - TMGT_ERR("sendOccPoll: OCC%d poll failed with rc=0x%04X", - occInstance, l_err->reasonCode()); - } - else + bool continuePolling = false; + do { - // Poll succeeded, check response - uint32_t l_poll_rsp_size = cmd.getResponseData(l_poll_rsp); - if (l_poll_rsp_size >= OCC_POLL_DATA_MIN_SIZE) + // create 1 byte buffer for poll command data + const uint8_t l_cmdData[1] = { 0x10 /*version*/ }; + + OccCmd cmd(occ, OCC_CMD_POLL, sizeof(l_cmdData), l_cmdData); + l_err = cmd.sendOccCmd(); + if (l_err != NULL) { - poll_rsp_handler(occ, l_poll_rsp, l_poll_rsp_size); + // Poll failed + TMGT_ERR("sendOccPoll: OCC%d poll failed with rc=0x%04X", + occInstance, l_err->reasonCode()); } else { - TMGT_ERR("sendOccPoll: OCC%d poll command response " - "failed with invalid data length %d", - occInstance, l_poll_rsp_size); - /*@ - * @errortype - * @reasoncode HTMGT_RC_INVALID_LENGTH - * @moduleid HTMGT_MOD_OCC_POLL - * @userdata1 OCC instance - * @devdesc Invalid POLL response length - */ - bldErrLog(l_err, HTMGT_MOD_OCC_POLL, - HTMGT_RC_INVALID_LENGTH, - occInstance, 0, 0, 0, - ERRORLOG::ERRL_SEV_INFORMATIONAL); + // Poll succeeded, check response + uint32_t l_poll_rsp_size = cmd.getResponseData(l_poll_rsp); + if (l_poll_rsp_size >= OCC_POLL_DATA_MIN_SIZE) + { + if (i_flushAllErrors) + { + const occPollRspStruct_t *currentPollRsp = + (occPollRspStruct_t *) l_poll_rsp; + if (currentPollRsp->errorId != 0) + { + // An error was returned, keep polling OCC + continuePolling = true; + } + else + { + continuePolling = false; + } + } + occ->pollRspHandler(l_poll_rsp, l_poll_rsp_size); + } + else + { + TMGT_ERR("sendOccPoll: OCC%d poll command response " + "failed with invalid data length %d", + occInstance, l_poll_rsp_size); + /*@ + * @errortype + * @reasoncode HTMGT_RC_INVALID_LENGTH + * @moduleid HTMGT_MOD_OCC_POLL + * @userdata1 OCC instance + * @devdesc Invalid POLL response length + */ + bldErrLog(l_err, HTMGT_MOD_OCC_POLL, + HTMGT_RC_INVALID_LENGTH, + occInstance, 0, 0, 0, + ERRORLOG::ERRL_SEV_INFORMATIONAL); + } } } - } + while (continuePolling); + + } // for each OCC return l_err; @@ -106,33 +123,139 @@ namespace HTMGT // Handle OCC poll response - void poll_rsp_handler(Occ * i_occ, - const uint8_t * i_pollResponse, - const uint16_t i_pollResponseSize) + void Occ::pollRspHandler(const uint8_t * i_pollResponse, + const uint16_t i_pollResponseSize) { + static uint32_t L_elog_retry_count = 0; TMGT_DBG("OCC Poll Response", i_pollResponse, i_pollResponseSize); - const occPollRspStruct_t *pollRspData = + const occPollRspStruct_t *pollRsp = (occPollRspStruct_t *) i_pollResponse; + const occPollRspStruct_t *lastPollRsp = + (occPollRspStruct_t *) iv_lastPollResponse; // Trace if any data changed - if (memcmp(pollRspData, - i_occ->getLastPollRsp(), - OCC_POLL_DATA_MIN_SIZE) != 0) + if ((false == iv_lastPollValid) || + (memcmp(pollRsp, + lastPollRsp, + OCC_POLL_DATA_MIN_SIZE) != 0)) { TMGT_INF("OCC%d Poll change: Status:%04X Occs:%02X Cfg:%02X " "State:%02X Error:%06X/%08X", - i_occ->getInstance(), - (pollRspData->status << 8) | pollRspData->extStatus, - pollRspData->occsPresent, - pollRspData->requestedCfg, pollRspData->state, - (pollRspData->errorId<<16) | pollRspData->errorLength, - pollRspData->errorAddress); - TMGT_INF(" Code: \"%s\", NumSensors: 0x%02X", - pollRspData->codeLevel, pollRspData->numBlocks); + iv_instance, + (pollRsp->status << 8) | pollRsp->extStatus, + pollRsp->occsPresent, + pollRsp->requestedCfg, pollRsp->state, + (pollRsp->errorId<<16) | pollRsp->errorLength, + pollRsp->errorAddress); + } + + do + { + if (false == iv_commEstablished) + { + // 1st poll response, so comm has been established for this OCC + iv_commEstablished = true; + TMGT_INF("pollRspHandler: FW Level for OCC%d: %.16s", + iv_instance, pollRsp->codeLevel); + } + + // Check for Error Logs + if (pollRsp->errorId != 0) + { + if ((pollRsp->errorId != lastPollRsp->errorId) || + (L_elog_retry_count < 3)) + + { + if (pollRsp->errorId == lastPollRsp->errorId) + { + // Only retry same errorId a few times... + L_elog_retry_count++; + TMGT_ERR("pollRspHandler: Requesting elog 0x%02X" + " (retry %d)", + pollRsp->errorId, L_elog_retry_count); + } + else + { + L_elog_retry_count = 0; + } + + // Handle a new error log from the OCC + occProcessElog(this, + pollRsp->errorId, + pollRsp->errorAddress, + pollRsp->errorLength); + if (iv_needsReset) + { + // Update state if changed... + // (since dropping out of poll rsp handler) + if (iv_state != pollRsp->state) + { + iv_state = (occStateId)pollRsp->state; + TMGT_INF("pollRspHandler: updating OCC%d state" + " to %s", + iv_instance, state_string(iv_state)); + } + break; + } + } + } + + if ((OCC_STATE_ACTIVE == pollRsp->state) || + (OCC_STATE_OBSERVATION == pollRsp->state)) + { + // Check role status + if (((OCC_ROLE_SLAVE == iv_role) && + ((pollRsp->status & OCC_STATUS_MASTER) != 0)) || + ((OCC_ROLE_MASTER == iv_role) && + ((pollRsp->status & OCC_STATUS_MASTER) == 0))) + { + TMGT_ERR("pollRspHandler: OCC%d Status role mismatch" + " (role:0x%02X, status:0x%02X 0x%02X)", + iv_instance, iv_role, pollRsp->status, + pollRsp->extStatus); + iv_needsReset = true; + // TODO RTC 109224 + //iv_resetReason = OCC_RESET_REASON_ERROR; + break; + } + } + + //iv_requestedFormat = (occCfgDataFormat)pollRsp->requestedCfg; + if (pollRsp->requestedCfg != 0x00) + { + TMGT_INF("pollRspHandler: OCC%d is requesting cfg format" + " 0x%02X", iv_instance, + pollRsp->requestedCfg); + } + + // Check for state change + if (iv_state != pollRsp->state) + { + iv_state = (occStateId)pollRsp->state; + TMGT_INF("pollRspHandler: updating OCC%d state to %s", + iv_instance, state_string(iv_state)); + } + + // Copy rspData to lastPollResponse + memcpy(iv_lastPollResponse, pollRsp, OCC_POLL_DATA_MIN_SIZE); + iv_lastPollValid = true; + } + while(0); + + // NOTE: When breaking out of the above while loop, the new poll + // response is NOT copied to lastPollResponse (should only + // break when reset required) + + if (true == iv_needsReset) + { + // Save full poll response + memcpy(iv_lastPollResponse, pollRsp, OCC_POLL_DATA_MIN_SIZE); + iv_lastPollValid = true; + iv_state = (occStateId)pollRsp->state; } - } + } // end Occ::pollRspHandler() } // end namespace diff --git a/src/usr/htmgt/htmgt_poll.H b/src/usr/htmgt/htmgt_poll.H index 62eabf885..631a1d365 100644 --- a/src/usr/htmgt/htmgt_poll.H +++ b/src/usr/htmgt/htmgt_poll.H @@ -33,6 +33,20 @@ namespace HTMGT { + + // OCC Status bits + const uint8_t OCC_STATUS_MASTER = 0x80; + const uint8_t OCC_STATUS_FIR_MASTER = 0x40; + const uint8_t OCC_STATUS_ATTN_ENABLE = 0x08; + const uint8_t OCC_STATUS_OBS_READY = 0x02; + const uint8_t OCC_STATUS_ACTIVE_READY = 0x01; + + // OCC Extended Status bits + const uint8_t OCC_XSTATUS_DVFS_OT = 0x80; + const uint8_t OCC_XSTATUS_DVFS_PWR = 0x40; + const uint8_t OCC_XSTATUS_MEM_THROT_OT = 0x20; + const uint8_t OCC_XSTATUS_N_POWER = 0x10; + struct occPollRspStruct_t { uint8_t status; @@ -58,21 +72,16 @@ namespace HTMGT /** * @brief Send a poll command to each OCC * + * @param[in] i_flushAllErrors If set to true, TMGT will send poll cmds + * to each OCC as long as that OCC continues + * to report errors. If false, only one + * poll will be send to each OCC. + * * @return NULL on success, else error handle */ - errlHndl_t sendOccPoll(); + errlHndl_t sendOccPoll(const bool i_flushAllErrors = false); - /** - * @brief Handle OCC poll response - * - * @param[in] i_occ pointer to the OCC - * @param[in] i_pollResponse pointer to the response - * @param[in] i_pollResponseSize length of the poll response - */ - void poll_rsp_handler(Occ * i_occ, - const uint8_t * i_pollResponse, - const uint16_t i_pollResponseSize); } // end namespace #endif diff --git a/src/usr/htmgt/htmgt_utility.C b/src/usr/htmgt/htmgt_utility.C index ef086c592..8a2d61813 100644 --- a/src/usr/htmgt/htmgt_utility.C +++ b/src/usr/htmgt/htmgt_utility.C @@ -36,7 +36,7 @@ namespace HTMGT // Debug flags uint32_t G_debug_data = 0; - uint32_t G_debug_trace = DEBUG_TRACE_FULL_NONVERBOSE; // TODO RTC 115922 + uint32_t G_debug_trace = DEBUG_TRACE_FULL_NONVERBOSE; // TODO RTC 117248 // Create/Build an Error log and add HTMGT component trace @@ -70,11 +70,27 @@ namespace HTMGT } else { + // TODO RTC 109224: + // - collectTrace will not filter dup traces and no way to clear + // - no way to add secondary SRC to elog io_err->collectTrace("HTMGT"); + + uint32_t additionalSrc[] = + { + uint32_t(HTMGT_COMP_ID | i_rc), uint32_t(i_modid), + uint32_t(i_sev), uint32_t(i_addFwCallout?1:0), + i_data1, i_data2, i_data3, i_data4 + }; + io_err->addFFDC(HTMGT_COMP_ID, + additionalSrc, + sizeof(additionalSrc), + 1, // version + SUBSEC_ADDITIONAL_SRC); } } + // TODO RTC 109224 - refactor/optimize trace strings // Internal utility to convert OCC command type to a string const char *command_string(const uint8_t i_cmd) @@ -98,7 +114,7 @@ namespace HTMGT const uint8_t l_total = sizeof(L_cmd_string) / sizeof(struct string_data_t); - // TODO RTC 109066 + // TODO RTC 109224 uint8_t l_idx = 0; for (l_idx=0; l_idx +#include +#include "htmgt_utility.H" +#include "occError.H" +#include "htmgt_occcmd.H" + +#include +#include + + +namespace HTMGT +{ + + // Process elog entry from OCC poll response + void occProcessElog(Occ * i_occ, + const uint8_t i_id, + const uint32_t i_address, + const uint16_t i_length) + { + errlHndl_t l_errlHndl = NULL; + + // Read data from SRAM (length must be multiple of 8 bytes) + const uint16_t l_length = (i_length + 8) & 0xFFF8; + uint8_t l_sram_data[8 + l_length]; + ecmdDataBufferBase l_buffer(l_length*8); // convert to bits +// HBOCC is only defined for HTMGT +#ifdef CONFIG_HTMGT + l_errlHndl = HBOCC::readSRAM(i_occ->getTarget(), i_address, l_buffer); +#endif + if (NULL == l_errlHndl) + { + const uint32_t l_flatSize = l_buffer.flattenSize(); + l_buffer.flatten(l_sram_data, l_flatSize); + // Skip 8 byte ecmd header + const occErrlEntry_t *l_occElog=(occErrlEntry_t *)&l_sram_data[8]; + + TMGT_BIN("OCC ELOG", l_occElog, 64); + + const uint32_t l_occSrc = OCCC_COMP_ID | l_occElog->reasonCode; + ERRORLOG::errlSeverity_t l_errlSeverity = + ERRORLOG::ERRL_SEV_INFORMATIONAL; +#if 0 + // TODO: RTC 109224 - determine correct severity/actions + + // Process Severity + const uint8_t l_occSeverity = l_occElog->severity; + const uint8_t l_occActions = l_occElog->actions; + if (l_occSeverity < OCC_SEV_ACTION_XLATE_SIZE) + { + l_errlSeverity = + occSeverityErrorActionXlate[l_occSeverity].occErrlSeverity; + } + else + { + TMGT_ERR("occProcessElog: Severity translate failure" + " (severity = 0x%02X)", l_occElog->severity); + } + + // Process elog Actions + bool l_occReset = false; + elogProcessActions(l_occActions, l_occReset, l_errlSeverity); + if (l_occReset == true) + { + iv_needsReset = true; + UPDATE_SAFE_MODE_REASON(l_occSrc, iv_huid, true); + } +#endif + + // Create OCC error log + // NOTE: word 4 (used by extended reason code) to save off OCC + // sub component value which is needed to correctly parse + // srcs which have similar uniqueness + // NOTE: SRC tags are NOT required here as these logs will get + // parsed with the OCC src tags + const occErrlUsrDtls_t *l_usrDtls_ptr = (occErrlUsrDtls_t *) + ((uint8_t*)l_occElog+sizeof(occErrlEntry_t)+ + (l_occElog->numCallouts * sizeof(occErrlCallout_t)) ); + bldErrLog(l_errlHndl, + (htmgtModuleId)(l_usrDtls_ptr->modId & 0x00FF), + (htmgtReasonCode)l_occSrc, // occ reason code + l_usrDtls_ptr->userData1, + l_usrDtls_ptr->userData2, + l_usrDtls_ptr->userData3, + ((l_usrDtls_ptr->modId & 0xFF00) << 16 ) | + l_occElog->userData4, // extended reason code + l_errlSeverity); + +#if 0 + // TODO: RTC 109224 + // Add callout information + bool l_bad_fru_data = false; + uint8_t l_callout_num = 0; + if (! ((ERRL_SEV_INFORMATIONAL == l_errlSeverity) && + (TMGT_ERRL_ACTIONS_MANUFACTURING_ERROR & l_occActions)) ) + { + // Only add callouts if this is MFG error and system not in + // MFG (in MFG severity would not be Info) + uint8_t l_index = 0; + uint8_t l_count = 1; + + const uint8_t l_max_callout = l_occElog->numCallouts; + // The beginning address of callout data + l_index = sizeof(occErrlEntry_t); + do { + occErrlCallout_t *l_callout_ptr = NULL; + l_callout_ptr = (occErrlCallout_t *) + ((uint8_t*)l_occElog+l_index); + if (l_callout_ptr->type != 0) + { + srciPriority l_priority; + bool l_success = true; + l_success = + elogXlateSrciPriority(l_callout_ptr->priority, + l_priority); + if (l_success == true) + { + l_success = elogAddCallout(l_errlHndl, + l_errlSeverity, + l_priority, + *l_callout_ptr, + l_callout_num); + if (l_success == false) + { + l_bad_fru_data = true; + } + } + else + { + l_bad_fru_data = true; + TMGT_ERR("occProcessElog: Priority translate" + " failure (priority = 0x%02X)", + l_callout_ptr->priority); + } + l_index += sizeof(occErrlCallout_t); + } // if (l_type != 0) + else + { // make sure all the remaining callout data are zeros, + // otherwise mark bad fru data + uint8_t *l_ptr = (uint8_t*)l_occElog+l_index; + uint8_t l_len = (l_max_callout-l_count+1)* + sizeof(occErrlCallout_t); + while (l_len != 0) + { + if (*l_ptr != 0x00) + { + TMGT_ERR("occProcessElog: The remaining" + " callout data should be all zeros"); + l_bad_fru_data = true; + break; + } + l_len--; + l_ptr++; + } + break; + } + l_count++; + } while (l_count <= l_max_callout); + } + else + { + TMGT_ERR("MFG error found outside MFG; callouts will not be" + " added to log (OCC severity=0x%02X, actions=0x%02X)", + l_occSeverity, l_occActions); + const uint8_t l_callout_length = l_occElog->numCallouts * 12; + const char *l_callout_ptr = (char *)((uint8_t*)l_occElog+ + sizeof(occErrlEntry_t)); + // Add raw callout data from the OCC + l_errlHndl->addUsrDtls(l_callout_ptr, + l_callout_length, + TMGT_COMP_ID, + TMGT_VERSION, + TMGT_ERROR_DATA_TYPE); + } + + // Any bad fru data found ? + errlHndl_t l_errlHndl2 = NULL; + if (l_bad_fru_data == true) + { + /*@ + * @errortype + * @refcode LIC_REFCODE + * @subsys EPUB_FIRMWARE_SP + * @reasoncode HTMGT_RC_OCC_ERROR_LOG + * @moduleid HTMGT_MOD_BAD_FRU_CALLOUTS + * @userdata1 OCC elog id + * @userdata2 Number of good callouts + * @devdesc Bad FRU data received in OCC error log + */ + bldErrLog(l_errlHndl2, HTMGT_MOD_BAD_FRU_CALLOUTS, + HTMGT_RC_OCC_ERROR_LOG, + i_id, l_callout_num, 0, 0, ERRL_SEV_INFORMATIONAL); + ERRORLOG::errlCommit(l_errlHndl2, HTMGT_COMP_ID); + } + + // Check callout number and severity + if ((l_callout_num == 0) && + (l_errlSeverity != ERRL_SEV_INFORMATIONAL)) + { + TMGT_ERR("occProcessElog: No FRU callouts found for OCC%d" + " elog_id:0x%02X, severity:0x%0X", + iv_instance, i_id, l_errlSeverity); + /*@ + * @errortype + * @refcode LIC_REFCODE + * @subsys EPUB_FIRMWARE_SP + * @reasoncode HTMGT_RC_OCC_ERROR_LOG + * @moduleid HTMGT_MOD_MISMATCHING_SEVERITY + * @userdata1 OCC elog id + * @userdata2 OCC severity + * @userdata3 + * @userdata4 + * @devdesc No FRU callouts found for non-info OCC Error Log + */ + bldErrLog(l_errlHndl2, HTMGT_MOD_MISMATCHING_SEVERITY, + HTMGT_RC_OCC_ERROR_LOG, + i_id, l_errlSeverity, 0, 0, ERRL_SEV_INFORMATIONAL); + ERRORLOG::errlCommit(l_errlHndl2, HTMGT_COMP_ID); + } +#endif + + // Add full OCC error log data as a User Details section + l_errlHndl->addFFDC(OCCC_COMP_ID, + l_occElog, + i_length, + 1, // version + 0); // subsection + +#if 0 + // TODO: RTC 109224 + // Add additional data + addTmgtElogData(l_errlHndl); + addThermalElogData(l_errlHndl); +#endif + + // Commit Error (or terminate if required) + ERRORLOG::errlCommit(l_errlHndl, HTMGT_COMP_ID); + + // Clear elog + const uint8_t l_cmdData[1] = {i_id}; + OccCmd l_cmd(i_occ, OCC_CMD_CLEAR_ERROR_LOG, + sizeof(l_cmdData), l_cmdData); + l_errlHndl = l_cmd.sendOccCmd(); + if (l_errlHndl != NULL) + { + TMGT_ERR("occProcessElog: Failed to clear elog id %d to" + " OCC%d (rc=0x%04X)", + i_id, i_occ, l_errlHndl->reasonCode()); + ERRORLOG::errlCommit(l_errlHndl, HTMGT_COMP_ID); + } + } + else + { + TMGT_ERR("occProcessElog: Unable to read elog %d from SRAM" + " address (0x%08X) length (0x%04X), rc=0x%04X", + i_id, i_address, i_length, l_errlHndl->reasonCode()); + ERRORLOG::errlCommit(l_errlHndl, HTMGT_COMP_ID); + } + } // end Occ::occProcessElog() + + +} // end namespace + + + diff --git a/src/usr/htmgt/occError.H b/src/usr/htmgt/occError.H new file mode 100644 index 000000000..095d37d57 --- /dev/null +++ b/src/usr/htmgt/occError.H @@ -0,0 +1,227 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/usr/htmgt/htmgt_error.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 OCCERROR_H +#define OCCERROR_H + +#include +#include "htmgt_occ.H" + +namespace HTMGT +{ + // Error Severity + enum occSeverityType + { + OCC_SEV_INFORMATIONAL = 0x00, + OCC_SEV_RECOVERABLE = 0x01, + OCC_SEV_UNRECOVERABLE = 0x02 + }; + + // Error Actions + enum tmgtErrlActionsType + { + TMGT_ERRL_ACTIONS_CONSOLIDATE_ERRORS = 0x01, + TMGT_ERRL_ACTIONS_MANUFACTURING_ERROR = 0x08, + TMGT_ERRL_ACTIONS_UNRECOVERABLE_CPM_ERROR = 0x10, + TMGT_ERRL_ACTIONS_SAFE_MODE_REQUIRED = 0x40, + TMGT_ERRL_ACTIONS_RESET_REQUIRED = 0x80, + }; + + // Type of Callout + enum occCalloutType + { + OCC_CALLOUT_TYPE_HUID = 0x01, + OCC_CALLOUT_TYPE_COMPONENT_ID = 0x02, + }; + + // TMGT-OCC Component Ids + enum occCompIdType + { + OCC_COMPONENT_ID_FIRMWARE = 0x01, + OCC_COMPONENT_ID_OVER_TEMPERATURE = 0x04, + OCC_COMPONENT_ID_OVERSUBSCRIPTION = 0x05, + OCC_COMPONENT_ID_NONE = 0xFF, + }; + + // Callout Data Type, this was ported forward from P7 + enum tmgtCompxlateType + { + TMGT_COMP_DATA_RID = 0x00, + TMGT_COMP_DATA_PROC_RID = 0x01, + TMGT_COMP_DATA_PROCEDURE = 0x02, + TMGT_COMP_DATA_POWR_VRM_NUM = 0x03, + TMGT_COMP_DATA_MEMORY_TABLE_NUM = 0x04, + TMGT_COMP_DATA_POWR_DCA_NUM = 0x05, + TMGT_COMP_DATA_IOHUB_TABLE_NUM = 0x06, + TMGT_COMP_DATA_SYMBOLIC_FRU = 0x07, + TMGT_COMP_DATA_SN_TABLE_NUM = 0x08, + TMGT_COMP_DATA_VDD_PROC_RID = 0x0A, + TMGT_COMP_DATA_END_OF_TABLE = 0xFF + }; + +#if 0 + // TODO: RTC 109224 + struct occSrciPriorityXlate + { + uint8_t occPriority; + srciPriority errlPriority; + } __attribute__ ((__packed__)); + typedef struct occSrciPriorityXlate occSrciPriorityXlate_t; + + const occSrciPriorityXlate_t occPriorityXlateTbl[] = + { + {0x01, SRCI_PRIORITY_LOW}, + {0x02, SRCI_PRIORITY_MED}, + {0x03, SRCI_PRIORITY_HIGH}, + }; + const uint8_t OCC_SRCI_PRIORITY_XLATE_SIZE = + (sizeof(occPriorityXlateTbl) /sizeof(occSrciPriorityXlate_t)); +#endif + + // OCC Usr Dtls Structure + struct occErrlUsrDtls + { + uint8_t version; // User Details Version + uint8_t reserved; // Reserved + uint16_t modId; // Module Id + uint32_t fwLevel; // Firmware Level + uint64_t timeStamp; // Time Stamp + uint8_t occId; // OCC ID + uint8_t occRole; // OCC Role + uint8_t operatingState; // OCC State + uint8_t committed; // Log Committed? + uint32_t userData1; // User Data Word 1 + uint32_t userData2; // User Data Word 2 + uint32_t userData3; // User Data Word 3 + uint16_t entrySize; // Log Size + uint16_t userDetailEntrySize; // User Details Size + } __attribute__ ((__packed__)); + typedef struct occErrlUsrDtls occErrlUsrDtls_t; + + // OCC Callout Structure + struct occErrlCallout + { + uint8_t type; + uint64_t calloutValue; + uint8_t priority; + uint16_t reserved1; + } __attribute__ ((__packed__)); + typedef struct occErrlCallout occErrlCallout_t; + + // User Detail Entry Structure + struct occUserDetailsEntry + { + uint8_t version; // User Details Entry Version + uint8_t type; // User Details Entry Type + // Note: Users must use ERRL_USR_DETAIL_TYPE enum + uint16_t size; // User Details Entry Size + } __attribute__ ((__packed__)); + typedef struct occUserDetailsEntry occUserDetailsEntry_t; + +#define ERRL_MAX_CALLOUTS 6 + + // OCC Error Log Structure + struct occErrlEntry + { + // Log CheckSum + uint16_t checkSum; + // Log Version + uint8_t version; + // Log Entry ID + uint8_t entryId; + // Log Reason Code + uint8_t reasonCode; + // Log Severity + uint8_t severity; + // Actions to process the errors + uint8_t actions; + // Reserved + uint32_t userData4; + // Log Callout Number + uint8_t numCallouts; + } __attribute__ ((__packed__)); + typedef struct occErrlEntry occErrlEntry_t; + + +#if 0 + // TODO: RTC 109224 + // OCC Severity and Action + struct occSeverityActionXlate + { + occSeverityType occSeverity; + errlSeverity occErrlSeverity; + errlActions occErrlAction; + }; + typedef struct occSeverityActionXlate occSeverityActionXlate_t; + + // Translate Severity and Actios + const occSeverityActionXlate_t occSeverityErrorActionXlate[] = + { + {OCC_SEV_INFORMATIONAL, ERRL_SEV_INFORMATIONAL, ERRL_ACTION_HIDDEN}, + {OCC_SEV_RECOVERABLE, ERRL_SEV_PREDICTIVE, ERRL_ACTION_REPORT}, + {OCC_SEV_UNRECOVERABLE, ERRL_SEV_UNRECOVERABLE, ERRL_ACTION_REPORT}, + }; + const uint8_t OCC_SEV_ACTION_XLATE_SIZE = + (sizeof(occSeverityErrorActionXlate)/sizeof(occSeverityActionXlate_t)); +#endif + + struct tmgtCompXlate + { + uint8_t compId; + tmgtCompxlateType dataType; + uint32_t data; + }; + typedef struct tmgtCompXlate tmgtCompXlate_t; + + const uint16_t TMGT_MAX_COMP_IDS = 4; + + const uint32_t OVERTMP = 0x05; + const uint32_t TPMD_OV = 0x06; + + const tmgtCompXlate_t tmgt_compXlateTable[TMGT_MAX_COMP_IDS] = + { + { 0x01, TMGT_COMP_DATA_PROCEDURE, ERRORLOG::EPUB_FIRMWARE_SP}, // FW + { 0x04, TMGT_COMP_DATA_SYMBOLIC_FRU, OVERTMP}, // over temperature + { 0x05, TMGT_COMP_DATA_SYMBOLIC_FRU, TPMD_OV}, // oversub throttling + { 0xFF, TMGT_COMP_DATA_END_OF_TABLE, 0}, // none + }; + + + + /** + * @brief Process elog entry from OCC poll response + * + * @param[in] i_occ OCC instance number reporting error + * @param[in] i_id OCC Error Log ID to retrieve (from the poll response) + * @param[in] i_address OCC Error Log Address to read + * @param[in] i_length OCC Error Log Length + */ + void occProcessElog(Occ * i_occ, + const uint8_t i_id, + const uint32_t i_address, + const uint16_t i_length); + + +} // end namespace +#endif diff --git a/src/usr/hwpf/hwp/occ/makefile b/src/usr/hwpf/hwp/occ/makefile index 306b142b3..9eb68e669 100644 --- a/src/usr/hwpf/hwp/occ/makefile +++ b/src/usr/hwpf/hwp/occ/makefile @@ -30,7 +30,6 @@ SUBDIRS += runtime.d ## Objects unique to HB IPL OBJS += occ.o -OBJS += $(if $(CONFIG_HTMGT),occAccess.o) ## Objects common to HB IPL and HBRT include occ.mk diff --git a/src/usr/hwpf/hwp/occ/occ.C b/src/usr/hwpf/hwp/occ/occ.C index 0aea6a1aa..13fcbf949 100644 --- a/src/usr/hwpf/hwp/occ/occ.C +++ b/src/usr/hwpf/hwp/occ/occ.C @@ -53,6 +53,8 @@ #include #include +#include + // Procedures #include #include @@ -106,7 +108,7 @@ namespace HBOCC HOMER_OFFSET_TO_OCC_IMG; uint64_t i_homerVirtAddr = reinterpret_cast (i_homerVirtAddrBase) + tmpOffset + - HOMER_OFFSET_TO_OCC_IMG;; + HOMER_OFFSET_TO_OCC_IMG; uint64_t i_commonPhysAddr = i_homerPhysAddrBase + VMM_HOMER_REGION_SIZE; @@ -412,13 +414,17 @@ namespace HBOCC TRACUCOMP( g_fapiTd,ENTER_MRK"activateOCC" ); errlHndl_t l_errl = NULL; TARGETING::Target* l_failedOccTarget = NULL; - //uint8_t l_errStatus = 0; +#ifdef CONFIG_HTMGT + bool occStartSuccess = true; +#endif l_errl = loadnStartAllOccs (l_failedOccTarget); if (l_errl) { errlCommit (l_errl, HWPF_COMP_ID); - //l_errStatus = 1; +#ifdef CONFIG_HTMGT + occStartSuccess = false; +#endif } //TODO RTC:116027 @@ -426,14 +432,10 @@ namespace HBOCC //TODO RTC:115636 //HB enables the scon-via-i2c logic on the OCCs + #ifdef CONFIG_HTMGT - //TODO RTC:115585 - //HTMGT::htmgtOccLoadStartStatus - // (l_errStatus,l_failedOccTarget); - if (l_errl) - { - errlCommit (l_errl, HWPF_COMP_ID); - } + // Report OCC status to HTMGT + HTMGT::processOccStartStatus(occStartSuccess,l_failedOccTarget); #endif TRACUCOMP( g_fapiTd,EXIT_MRK"activateOCC" ); return l_errl; diff --git a/src/usr/hwpf/hwp/occ/occ.mk b/src/usr/hwpf/hwp/occ/occ.mk index 1a513002d..0425824c3 100644 --- a/src/usr/hwpf/hwp/occ/occ.mk +++ b/src/usr/hwpf/hwp/occ/occ.mk @@ -73,6 +73,8 @@ OBJS += p8_ocb_indir_setup_linear.o #common occ functions between ipl and runtime OBJS += occ_common.o +OBJS += $(if $(CONFIG_HTMGT),occAccess.o) + ## NOTE: add a new directory onto the vpaths when you add a new HWP ## EXAMPLE: # VPATH += ${ROOTPATH}/src/usr/hwpf/hwp/occ/ -- cgit v1.2.1