summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChris Cain <cjcain@us.ibm.com>2014-12-05 11:06:54 -0600
committerA. Patrick Williams III <iawillia@us.ibm.com>2014-12-13 10:17:16 -0600
commit85351118f1aa6d7cacca6b1085b1d965eeb492c4 (patch)
tree1b92a4231a77353369ad95250fbd8f4c61498dbf
parent611d91a0295e17ea202f01e0143fc040820eadb8 (diff)
downloadblackbird-hostboot-85351118f1aa6d7cacca6b1085b1d965eeb492c4.tar.gz
blackbird-hostboot-85351118f1aa6d7cacca6b1085b1d965eeb492c4.zip
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 <dgilbert@us.ibm.com> Reviewed-by: A. Patrick Williams III <iawillia@us.ibm.com>
-rwxr-xr-xsrc/build/tools/listdeps.pl2
-rw-r--r--src/include/usr/htmgt/htmgt_reasoncodes.H7
-rw-r--r--src/include/usr/initservice/initsvcstructs.H2
-rw-r--r--src/include/usr/isteps/istep21list.H4
-rw-r--r--src/usr/htmgt/htmgt.C107
-rw-r--r--src/usr/htmgt/htmgt_activate.C89
-rw-r--r--src/usr/htmgt/htmgt_activate.H14
-rw-r--r--src/usr/htmgt/htmgt_cfgdata.C186
-rw-r--r--src/usr/htmgt/htmgt_cfgdata.H52
-rw-r--r--src/usr/htmgt/htmgt_common.mk2
-rw-r--r--src/usr/htmgt/htmgt_occ.C254
-rw-r--r--src/usr/htmgt/htmgt_occ.H112
-rw-r--r--src/usr/htmgt/htmgt_occcmd.C357
-rw-r--r--src/usr/htmgt/htmgt_occcmd.H5
-rw-r--r--src/usr/htmgt/htmgt_poll.C229
-rw-r--r--src/usr/htmgt/htmgt_poll.H31
-rw-r--r--src/usr/htmgt/htmgt_utility.C38
-rw-r--r--src/usr/htmgt/htmgt_utility.H13
-rw-r--r--src/usr/htmgt/occError.C289
-rw-r--r--src/usr/htmgt/occError.H227
-rw-r--r--src/usr/hwpf/hwp/occ/makefile1
-rw-r--r--src/usr/hwpf/hwp/occ/occ.C22
-rw-r--r--src/usr/hwpf/hwp/occ/occ.mk2
23 files changed, 1665 insertions, 380 deletions
diff --git a/src/build/tools/listdeps.pl b/src/build/tools/listdeps.pl
index 2b59a3a29..286adbf35 100755
--- a/src/build/tools/listdeps.pl
+++ b/src/build/tools/listdeps.pl
@@ -38,7 +38,7 @@ use File::Find ();
use File::Path;
use Cwd;
-use constant MAX_DEPENDENT_MODULES => 8;
+use constant MAX_DEPENDENT_MODULES => 9;
# validate the number of input args
if( $#ARGV == -1 || $#ARGV > 4 )
diff --git a/src/include/usr/htmgt/htmgt_reasoncodes.H b/src/include/usr/htmgt/htmgt_reasoncodes.H
index f675a0a23..1c374e3e1 100644
--- a/src/include/usr/htmgt/htmgt_reasoncodes.H
+++ b/src/include/usr/htmgt/htmgt_reasoncodes.H
@@ -35,7 +35,11 @@ namespace HTMGT
HTMGT_MOD_WAIT_FOR_OCC_ACTIVE = 0x01,
HTMGT_MOD_WAIT_FOR_OCC_READY = 0x02,
HTMGT_MOD_MEMTHROTTLE = 0x03,
+ HTMGT_MOD_OCCMGR_SET_STATE = 0x04,
+ HTMGT_MOD_OCC_SET_STATE = 0x05,
HTMGT_MOD_OCC_POLL = 0x76,
+ HTMGT_MOD_BAD_FRU_CALLOUTS = 0x7D,
+ HTMGT_MOD_MISMATCHING_SEVERITY = 0x7F,
HTMGT_MOD_READ_OCC_SRAM = 0x85,
HTMGT_MOD_SEND_OCC_CMD = 0x90,
HTMGT_MOD_WRITE_OCC_CMD = 0x91,
@@ -50,6 +54,7 @@ namespace HTMGT
HTMGT_RC_THROTTLE_UTIL_ERROR = HTMGT_COMP_ID | 0x02,
HTMGT_RC_THROTTLE_INVALID_N = HTMGT_COMP_ID | 0x03,
HTMGT_RC_OT_THROTTLE_INVALID_N = HTMGT_COMP_ID | 0x04,
+ HTMGT_RC_OCC_NOT_READY = HTMGT_COMP_ID | 0x05,
HTMGT_RC_NO_SUPPORT = HTMGT_COMP_ID | 0x0F,
HTMGT_RC_OCC_RESET = HTMGT_COMP_ID | 0x15,
HTMGT_RC_OCC_CRIT_FAILURE = HTMGT_COMP_ID | 0x16,
@@ -61,6 +66,7 @@ namespace HTMGT
HTMGT_RC_INVALID_DATA = HTMGT_COMP_ID | 0x23,
HTMGT_RC_OCC_UNAVAILABLE = HTMGT_COMP_ID | 0x24,
HTMGT_RC_OCC_START_FAIL = HTMGT_COMP_ID | 0x25,
+ HTMGT_RC_OCC_UNEXPECTED_STATE = HTMGT_COMP_ID | 0x26,
HTMGT_RC_PRESENT_STATE_PROHIBITS = HTMGT_COMP_ID | 0x28,
HTMGT_RC_PARAMETER_OUT_OF_RANGE = HTMGT_COMP_ID | 0x29,
HTMGT_RC_OVERSUBSCRIBED = HTMGT_COMP_ID | 0x2D,
@@ -70,6 +76,7 @@ namespace HTMGT
HTMGT_RC_MISSING_DATA = HTMGT_COMP_ID | 0x4F,
HTMGT_RC_ECMD_DBUF_COPY_FAIL = HTMGT_COMP_ID | 0x53,
HTMGT_RC_TARGET_NOT_FUNCTIONAL = HTMGT_COMP_ID | 0x54,
+ HTMGT_RC_OCC_MASTER_NOT_FOUND = HTMGT_COMP_ID | 0x55,
HTMGT_RC_PCAP_CALC_COMPLETE = HTMGT_COMP_ID | 0xB9,
HTMGT_RC_ENERGYSCALE_FFDC = HTMGT_COMP_ID | 0xFD,
};
diff --git a/src/include/usr/initservice/initsvcstructs.H b/src/include/usr/initservice/initsvcstructs.H
index 53f00183c..d9e412973 100644
--- a/src/include/usr/initservice/initsvcstructs.H
+++ b/src/include/usr/initservice/initsvcstructs.H
@@ -40,7 +40,7 @@
#include <initservice/initsvcreasoncodes.H>
// This constant has a corresponding entry in src/build/tools/listdeps.pl.
-#define MAX_DEPENDENT_MODULES 8
+#define MAX_DEPENDENT_MODULES 9
namespace INITSERVICE
diff --git a/src/include/usr/isteps/istep21list.H b/src/include/usr/isteps/istep21list.H
index 1186274d5..52a8311dd 100644
--- a/src/include/usr/isteps/istep21list.H
+++ b/src/include/usr/isteps/istep21list.H
@@ -91,6 +91,10 @@ const DepModInfo g_istep21Dependancies = {
DEP_LIB(libpstates.so),
#endif
DEP_LIB(libocc.so),
+#if defined(CONFIG_HTMGT)
+ DEP_LIB(libhtmgt.so),
+ DEP_LIB(libmc_config.so),
+#endif
NULL
}
};
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 <devicefw/userif.H>
// Targeting support
#include <targeting/common/commontargeting.H>
@@ -39,16 +42,20 @@
#include <targeting/common/targetservice.H>
+#include <sys/time.h>
+
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 <targeting/common/attributes.H>
#include <targeting/common/targetservice.H>
+#include <sys/time.h>
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<Occ*> 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<Occ*>::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
@@ -39,16 +39,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
*
* @return NULL if all OCCs reached active state, else error handle
@@ -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 <targeting/common/utilFilter.H>
#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<Occ*> occList = occMgr::instance().getOccArray();
+ for (std::vector<Occ*>::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 <targeting/common/commontargeting.H>
@@ -37,9 +38,6 @@
#include <targeting/common/targetservice.H>
-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<TARGETING::ATTR_HUID>();
}
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<TARGETING::ATTR_HOMER_VIRT_ADDR>());
- TMGT_INF("buildOccs: homer = 0x%08X (from proc 0)", homer);
+ const uint8_t * homerPhys = (uint8_t*)
+ ((*proc)->getAttr<TARGETING::ATTR_HOMER_PHYS_ADDR>());
+ 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<Occ*>::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<OccManager>::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;
};
@@ -175,6 +226,14 @@ namespace HTMGT
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
*/
OccManager();
@@ -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<Occ*> 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<OccManager> 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 <targeting/common/targetservice.H>
#include <ecmdDataBufferBase.H>
+#include <hwpf/hwp/occ/occAccess.H>
#include <sys/time.h>
#include <trace/interface.H>
#include <errl/errlmanager.H>
#include <stdio.h>
-// TODO RTC 115922
-#ifdef __HOSTBOOT_RUNTIME
-#include <runtime/interface.h>
-#endif
-
-
-
-// TODO: RTC 115922
-#if 0
-#include <hwpf/hwp/occ/occAccess.H>
-#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 <targeting/common/commontargeting.H>
@@ -38,14 +39,11 @@
#include <targeting/common/targetservice.H>
-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<l_total; l_idx++)
{
@@ -119,6 +135,24 @@ namespace HTMGT
} // end command_string()
+ // Internal utility function to convert the OCC state to a string
+ const char *state_string(const uint8_t i_state)
+ {
+ switch(i_state)
+ {
+ case OCC_STATE_NO_CHANGE: return("NO CHANGE"); break;
+ case OCC_STATE_STANDBY: return("STANDBY"); break;
+ case OCC_STATE_OBSERVATION: return("OBSERVATION"); break;
+ case OCC_STATE_ACTIVE: return("ACTIVE"); break;
+ case OCC_STATE_SAFE: return("SAFE"); break;
+ case OCC_STATE_RESET: return("RESET"); break;
+ case OCC_STATE_IN_TRANSITION: return("IN TRANSITION"); break;
+ case OCC_STATE_LOADING: return("LOADING"); break;
+ case OCC_STATE_UNKNOWN: return("UNKNOWN"); break;
+ default: break;
+ }
+ return("UNKNOWN");
+ }
uint8_t getOCCDIMMPos(const TargetHandle_t i_mba,
const TargetHandle_t i_dimm)
diff --git a/src/usr/htmgt/htmgt_utility.H b/src/usr/htmgt/htmgt_utility.H
index 025ab49e7..d8ef14830 100644
--- a/src/usr/htmgt/htmgt_utility.H
+++ b/src/usr/htmgt/htmgt_utility.H
@@ -93,7 +93,6 @@ namespace HTMGT
};
extern uint32_t G_debug_trace;
-
enum tmgtElogSubsecTypes
{
// Values selected to be common with FSP from tmgt_elog_parser.H
@@ -102,7 +101,7 @@ namespace HTMGT
//SUBSEC_ENERGYSCALE_DATA_TYPE = 0x08,
//SUBSEC_OCC_ELOG_DATA_TYPE = 0x0A,
//SUBSEC_OCC_FFDC_DATA_TYPE = 0x0B,
- //SUBSEC_MSG_DATA_TRUNCATED = 0x0C,
+ SUBSEC_ADDITIONAL_SRC = 0x0C,
SUBSEC_OCC_CMD_DATA = 0x0D,
SUBSEC_OCC_RSP_DATA = 0x0E,
//SUBSEC_ELOG_TYPE_TOIF_RESET = 0x10,
@@ -161,5 +160,15 @@ namespace HTMGT
const TARGETING::TargetHandle_t i_dimm);
+ /**
+ * @brief Internal utility function to convert the OCC state to a string
+ *
+ * @param[in] i_state - OCC state
+ *
+ * @return text string description of state
+ */
+ const char *state_string(const uint8_t i_state);
+
+
} // end namespace
#endif
diff --git a/src/usr/htmgt/occError.C b/src/usr/htmgt/occError.C
new file mode 100644
index 000000000..ab200fce4
--- /dev/null
+++ b/src/usr/htmgt/occError.C
@@ -0,0 +1,289 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/usr/htmgt/tmgtutility.C $ */
+/* */
+/* 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 */
+
+#include <htmgt/htmgt.H>
+#include <htmgt/htmgt_reasoncodes.H>
+#include "htmgt_utility.H"
+#include "occError.H"
+#include "htmgt_occcmd.H"
+
+#include <ecmdDataBufferBase.H>
+#include <hwpf/hwp/occ/occAccess.H>
+
+
+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 <stdint.h>
+#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 <vfs/vfs.H>
#include <util/utillidmgr.H>
+#include <htmgt/htmgt.H>
+
// Procedures
#include <p8_pba_init.H>
#include <p8_occ_control.H>
@@ -106,7 +108,7 @@ namespace HBOCC
HOMER_OFFSET_TO_OCC_IMG;
uint64_t i_homerVirtAddr = reinterpret_cast<uint64_t>
(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/<HWP_dir>
OpenPOWER on IntegriCloud