summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/include/runtime/generic_hbrt_fsp_message.H5
-rw-r--r--src/include/usr/fsiscom/fsiscom_reasoncodes.H17
-rw-r--r--src/include/usr/scom/runtime/rt_scomif.H42
-rw-r--r--src/makefile1
-rw-r--r--src/usr/fsiscom/fsiscom.C22
-rw-r--r--src/usr/fsiscom/makefile5
-rw-r--r--src/usr/fsiscom/runtime/makefile33
-rw-r--r--src/usr/fsiscom/runtime/rt_fsiscom.C595
-rw-r--r--src/usr/scom/runtime/rt_scom.C8
-rw-r--r--src/usr/scom/runtime/test/testscom_rt.H11
-rw-r--r--src/usr/util/runtime/rt_cmds.C222
-rw-r--r--src/usr/xscom/runtime/rt_xscom.C2
12 files changed, 938 insertions, 25 deletions
diff --git a/src/include/runtime/generic_hbrt_fsp_message.H b/src/include/runtime/generic_hbrt_fsp_message.H
index 6daff3cc2..30566290d 100644
--- a/src/include/runtime/generic_hbrt_fsp_message.H
+++ b/src/include/runtime/generic_hbrt_fsp_message.H
@@ -73,7 +73,7 @@ struct TargetDeconfigHbrtFspData_t
*/
struct SingleScomOpHbrtFspData_t
{
- uint8_t scom_op; // 0 == read, 1 == write
+ uint8_t scom_op; // DeviceFW::READ, DeviceFW::WRITE
uint32_t huid; // hardware target
uint64_t scom_addr;
uint64_t scom_data; // SCOM value read by FSP, or
@@ -92,11 +92,12 @@ struct MultiScomReadHbrtFspData_t
uint8_t scom_num; // number of SCOMs to read
uint64_t scom_data; // addresses of SCOMs to read, or
// values of SCOMs in FSP response
+ //
// ** if a SCOM cannot be read, its value **
// ** should be returned as DEADBEEF **
//
// placeholder that can be cast to an array
- // of values (or addresses)
+ // of SCOM addresses (or values)
// uint64_t* mydata =
// (uint64_t*)&(l_generic_msg.data);
// more than 8 bytes of data is possible
diff --git a/src/include/usr/fsiscom/fsiscom_reasoncodes.H b/src/include/usr/fsiscom/fsiscom_reasoncodes.H
index 0c9aa0767..2acee4c72 100644
--- a/src/include/usr/fsiscom/fsiscom_reasoncodes.H
+++ b/src/include/usr/fsiscom/fsiscom_reasoncodes.H
@@ -5,7 +5,9 @@
/* */
/* OpenPOWER HostBoot Project */
/* */
-/* COPYRIGHT International Business Machines Corp. 2011,2014 */
+/* Contributors Listed Below - COPYRIGHT 2011,2018 */
+/* [+] International Business Machines Corp. */
+/* */
/* */
/* Licensed under the Apache License, Version 2.0 (the "License"); */
/* you may not use this file except in compliance with the License. */
@@ -29,19 +31,22 @@ namespace FSISCOM
{
enum FSISCOMModuleId
{
- MOD_FSISCOM_INVALID = 0x00, /**< Zero is an invalid module id */
- MOD_FSISCOM_PERFORMOP = 0x01, /**< fsiscom.C : fsiScomPerformOp */
-
+ MOD_FSISCOM_INVALID = 0x00, // Zero is an invalid module id
+ MOD_FSISCOM_PERFORM_OP = 0x01, // fsiscom.C : fsiScomPerformOp
+ MOD_FSISCOM_RT_SEND_SCOM_TO_FSP = 0x02,
+ MOD_FSISCOM_RT_SEND_MULTI_SCOM_TO_FSP = 0x03,
};
enum FSISCOMReasonCode
{
- RC_INVALID = FSISCOM_COMP_ID | 0x00,
- RC_WRITE_ERROR = FSISCOM_COMP_ID | 0x01,
+ RC_INVALID = FSISCOM_COMP_ID | 0x00,
+ RC_WRITE_ERROR = FSISCOM_COMP_ID | 0x01,
RC_READ_ERROR = FSISCOM_COMP_ID | 0x02,
RC_INVALID_LENGTH = FSISCOM_COMP_ID | 0x03,
RC_INVALID_ADDRESS = FSISCOM_COMP_ID | 0x04,
RC_INVALID_OPTYPE = FSISCOM_COMP_ID | 0x05,
+ RC_RT_INTERFACE_ERR = FSISCOM_COMP_ID | 0x06,
+ RC_RT_NULL_FW_MSG_PTR = FSISCOM_COMP_ID | 0x07,
};
};
diff --git a/src/include/usr/scom/runtime/rt_scomif.H b/src/include/usr/scom/runtime/rt_scomif.H
index 4039f2827..5c645bde0 100644
--- a/src/include/usr/scom/runtime/rt_scomif.H
+++ b/src/include/usr/scom/runtime/rt_scomif.H
@@ -37,7 +37,7 @@ namespace SCOM
* @param[in] i_target Scom target
* @param[in] i_scomAddr Scom address
* @param[in|out] io_buffer Pointer to scom data
- * @return errlHndl_t
+ * @return errlHndl_t
*/
errlHndl_t sendScomToHyp(DeviceFW::OperationType i_opType,
TARGETING::Target * i_target,
@@ -46,4 +46,44 @@ errlHndl_t sendScomToHyp(DeviceFW::OperationType i_opType,
}; // end namespace SCOM
+namespace FSISCOM
+{
+
+/**
+ * @brief DMI channel has checkstopped. Mark it bad and switch to FSP access.
+ *
+ * @param[in] i_target SCOM target
+ * @return None
+ */
+void switchToFspScomAccess(TARGETING::TargetHandle_t i_target);
+
+/**
+ * @brief This function sends the scom op to the FSP
+ *
+ * @param[in] i_opType Scom operation type, see driverif.H
+ * @param[in] i_target Scom target
+ * @param[in] i_scomAddr Scom address
+ * @param[in/out] io_buffer Read: Pointer to output data storage
+ * Write: Pointer to input data storage
+ * @return errlHndl_t
+ */
+errlHndl_t sendScomOpToFsp(DeviceFW::OperationType i_opType,
+ TARGETING::TargetHandle_t i_target,
+ uint64_t i_scomAddr,
+ void * io_buffer);
+
+/**
+ * @brief Ask FSP to read list of SCOMs
+ *
+ * @param[in] i_target Scom target
+ * @param[in] i_scomAddr Scom addresses to read
+ * @param[out] o_scomValue Scom values read (0xDEADBEEF for errors)
+ * @return errlHndl_t
+ */
+errlHndl_t sendMultiScomReadToFsp(TARGETING::TargetHandle_t i_target,
+ std::vector<uint64_t> & i_scomAddr,
+ std::vector<uint64_t> & o_scomValue);
+
+}; // end namespace FSISCOM
+
#endif // end __RT_SCOMIF_H
diff --git a/src/makefile b/src/makefile
index f2b570dcc..5a278a265 100644
--- a/src/makefile
+++ b/src/makefile
@@ -278,6 +278,7 @@ RUNTIME_MODULES += targeting_rt
RUNTIME_MODULES += util_rt
RUNTIME_MODULES += devicefw_rt
RUNTIME_MODULES += xscom_rt
+RUNTIME_MODULES += fsiscom_rt
RUNTIME_MODULES += ibscom_rt
RUNTIME_MODULES += scom_rt
RUNTIME_MODULES += vpd_rt
diff --git a/src/usr/fsiscom/fsiscom.C b/src/usr/fsiscom/fsiscom.C
index 9a35c9b62..dd2b26271 100644
--- a/src/usr/fsiscom/fsiscom.C
+++ b/src/usr/fsiscom/fsiscom.C
@@ -5,7 +5,7 @@
/* */
/* OpenPOWER HostBoot Project */
/* */
-/* Contributors Listed Below - COPYRIGHT 2011,2017 */
+/* Contributors Listed Below - COPYRIGHT 2011,2018 */
/* [+] International Business Machines Corp. */
/* */
/* */
@@ -200,7 +200,7 @@ errlHndl_t fsiScomPerformOp(DeviceFW::OperationType i_opType,
TRACFCOMP( g_trac_fsiscom, ERR_MRK "fsiScomPerformOp> Invalid data length : io_buflen=%d", io_buflen );
/*@
* @errortype
- * @moduleid FSISCOM::MOD_FSISCOM_PERFORMOP
+ * @moduleid FSISCOM::MOD_FSISCOM_PERFORM_OP
* @reasoncode FSISCOM::RC_INVALID_LENGTH
* @userdata1 SCOM Address
* @userdata2 Data Length
@@ -209,7 +209,7 @@ errlHndl_t fsiScomPerformOp(DeviceFW::OperationType i_opType,
* Invalid data length for a SCOM operation.
*/
l_err = new ERRORLOG::ErrlEntry(ERRORLOG::ERRL_SEV_UNRECOVERABLE,
- FSISCOM::MOD_FSISCOM_PERFORMOP,
+ FSISCOM::MOD_FSISCOM_PERFORM_OP,
FSISCOM::RC_INVALID_LENGTH,
l_scomAddr,
TO_UINT64(io_buflen));
@@ -225,7 +225,7 @@ errlHndl_t fsiScomPerformOp(DeviceFW::OperationType i_opType,
TRACFCOMP( g_trac_fsiscom, ERR_MRK "fsiScomPerformOp> Address contains more than 31 bits : l_scomAddr=0x%.16X", l_scomAddr );
/*@
* @errortype
- * @moduleid FSISCOM::MOD_FSISCOM_PERFORMOP
+ * @moduleid FSISCOM::MOD_FSISCOM_PERFORM_OP
* @reasoncode FSISCOM::RC_INVALID_ADDRESS
* @userdata1 SCOM Address
* @userdata2 Target HUID
@@ -235,7 +235,7 @@ errlHndl_t fsiScomPerformOp(DeviceFW::OperationType i_opType,
* Invalid address on a SCOM operation.
*/
l_err = new ERRORLOG::ErrlEntry(ERRORLOG::ERRL_SEV_UNRECOVERABLE,
- FSISCOM::MOD_FSISCOM_PERFORMOP,
+ FSISCOM::MOD_FSISCOM_PERFORM_OP,
FSISCOM::RC_INVALID_ADDRESS,
l_scomAddr,
TARGETING::get_huid(i_target));
@@ -322,7 +322,7 @@ errlHndl_t fsiScomPerformOp(DeviceFW::OperationType i_opType,
TRACFCOMP( g_trac_fsiscom, ERR_MRK"fsiScomPerformOp:Write: PCB/PIB error received: l_status=0x%X)", l_status);
/*@
* @errortype
- * @moduleid FSISCOM::MOD_FSISCOM_PERFORMOP
+ * @moduleid FSISCOM::MOD_FSISCOM_PERFORM_OP
* @reasoncode FSISCOM::RC_WRITE_ERROR
* @userdata1 SCOM Addr
* @userdata2[00:31] Target HUID
@@ -334,7 +334,7 @@ errlHndl_t fsiScomPerformOp(DeviceFW::OperationType i_opType,
*/
l_err = new ERRORLOG::ErrlEntry(
ERRORLOG::ERRL_SEV_UNRECOVERABLE,
- FSISCOM::MOD_FSISCOM_PERFORMOP,
+ FSISCOM::MOD_FSISCOM_PERFORM_OP,
FSISCOM::RC_WRITE_ERROR,
l_scomAddr,
TWO_UINT32_TO_UINT64(
@@ -389,7 +389,7 @@ errlHndl_t fsiScomPerformOp(DeviceFW::OperationType i_opType,
/*@
* @errortype
- * @moduleid FSISCOM::MOD_FSISCOM_PERFORMOP
+ * @moduleid FSISCOM::MOD_FSISCOM_PERFORM_OP
* @reasoncode FSISCOM::RC_READ_ERROR
* @userdata1 SCOM Addr
* @userdata2[00:31] Target HUID
@@ -399,7 +399,7 @@ errlHndl_t fsiScomPerformOp(DeviceFW::OperationType i_opType,
* Error returned from SCOM engine after read.
*/
l_err = new ERRORLOG::ErrlEntry(ERRORLOG::ERRL_SEV_UNRECOVERABLE,
- FSISCOM::MOD_FSISCOM_PERFORMOP,
+ FSISCOM::MOD_FSISCOM_PERFORM_OP,
FSISCOM::RC_READ_ERROR,
l_scomAddr,
TWO_UINT32_TO_UINT64(
@@ -448,7 +448,7 @@ errlHndl_t fsiScomPerformOp(DeviceFW::OperationType i_opType,
/*@
* @errortype
- * @moduleid FSISCOM::MOD_FSISCOM_PERFORMOP
+ * @moduleid FSISCOM::MOD_FSISCOM_PERFORM_OP
* @reasoncode FSISCOM::RC_INVALID_OPTYPE
* @userdata1[0:31] Operation Type (i_opType) : 0=READ, 1=WRITE
* @userdata1[32:64] Input scom address
@@ -458,7 +458,7 @@ errlHndl_t fsiScomPerformOp(DeviceFW::OperationType i_opType,
* Unsupported SCOM operation type.
*/
l_err = new ERRORLOG::ErrlEntry(ERRORLOG::ERRL_SEV_UNRECOVERABLE,
- FSISCOM::MOD_FSISCOM_PERFORMOP,
+ FSISCOM::MOD_FSISCOM_PERFORM_OP,
FSISCOM::RC_INVALID_OPTYPE,
TWO_UINT32_TO_UINT64(i_opType,
l_scomAddr),
diff --git a/src/usr/fsiscom/makefile b/src/usr/fsiscom/makefile
index 19df46488..ba897a677 100644
--- a/src/usr/fsiscom/makefile
+++ b/src/usr/fsiscom/makefile
@@ -5,7 +5,9 @@
#
# OpenPOWER HostBoot Project
#
-# COPYRIGHT International Business Machines Corp. 2011,2014
+# Contributors Listed Below - COPYRIGHT 2011,2018
+# [+] International Business Machines Corp.
+#
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -26,5 +28,6 @@ MODULE = fsiscom
OBJS += fsiscom.o
SUBDIRS += test.d
+SUBDIRS += runtime.d
include ${ROOTPATH}/config.mk
diff --git a/src/usr/fsiscom/runtime/makefile b/src/usr/fsiscom/runtime/makefile
new file mode 100644
index 000000000..48d1ebcb5
--- /dev/null
+++ b/src/usr/fsiscom/runtime/makefile
@@ -0,0 +1,33 @@
+# IBM_PROLOG_BEGIN_TAG
+# This is an automatically generated prolog.
+#
+# $Source: src/usr/fsiscom/runtime/makefile $
+#
+# OpenPOWER HostBoot Project
+#
+# Contributors Listed Below - COPYRIGHT 2018
+# [+] International Business Machines Corp.
+#
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+# implied. See the License for the specific language governing
+# permissions and limitations under the License.
+#
+# IBM_PROLOG_END_TAG
+HOSTBOOT_RUNTIME = 1
+ROOTPATH = ../../../..
+MODULE = fsiscom_rt
+
+OBJS += rt_fsiscom.o
+
+EXTRAINCDIR += ${ROOTPATH}/src/usr/diag/prdf/
+VPATH += ..
+include $(ROOTPATH)/config.mk
diff --git a/src/usr/fsiscom/runtime/rt_fsiscom.C b/src/usr/fsiscom/runtime/rt_fsiscom.C
new file mode 100644
index 000000000..69c4ccd6b
--- /dev/null
+++ b/src/usr/fsiscom/runtime/rt_fsiscom.C
@@ -0,0 +1,595 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/usr/fsiscom/runtime/rt_fsiscom.C $ */
+/* */
+/* OpenPOWER HostBoot Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 2018 */
+/* [+] International Business Machines Corp. */
+/* */
+/* */
+/* Licensed under the Apache License, Version 2.0 (the "License"); */
+/* you may not use this file except in compliance with the License. */
+/* You may obtain a copy of the License at */
+/* */
+/* http://www.apache.org/licenses/LICENSE-2.0 */
+/* */
+/* Unless required by applicable law or agreed to in writing, software */
+/* distributed under the License is distributed on an "AS IS" BASIS, */
+/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */
+/* implied. See the License for the specific language governing */
+/* permissions and limitations under the License. */
+/* */
+/* IBM_PROLOG_END_TAG */
+#include <devicefw/driverif.H>
+#include <trace/interface.H>
+#include <errl/errlentry.H>
+#include <errl/errlmanager.H>
+#include <fsiscom/fsiscom_reasoncodes.H>
+#include "../fsiscom.H"
+#include <scom/scomif.H>
+#include <scom/runtime/rt_scomif.H>
+#include <targeting/common/utilFilter.H>
+
+#include <runtime/hbrt_utilities.H> // createGenericFspMsg
+#include <util/runtime/rt_fwreq_helper.H> // firmware_request_helper
+#include <plat/cen/prdfCenChnlFailCache.H> // chnlFailScomList
+
+#include <map>
+
+// Trace definition
+trace_desc_t* g_trac_fsiscom = NULL;
+TRAC_INIT(&g_trac_fsiscom, FSISCOM_COMP_NAME, 2*KILOBYTE, TRACE::BUFFER_SLOW);
+
+namespace FSISCOM
+{
+
+/**
+ * @brief This function sends the scom op to the FSP
+ *
+ * @param[in] i_opType Scom operation type, see driverif.H
+ * @param[in] i_target Scom target
+ * @param[in] i_scomAddr Scom address
+ * @param[in/out] io_buffer Read: Pointer to output data storage
+ * Write: Pointer to input data storage
+ * @return errlHndl_t
+ */
+errlHndl_t sendScomOpToFsp(DeviceFW::OperationType i_opType,
+ TARGETING::TargetHandle_t i_target,
+ uint64_t i_scomAddr,
+ void * io_buffer)
+{
+ errlHndl_t l_err = nullptr;
+
+ // Handles to the firmware messages
+ hostInterfaces::hbrt_fw_msg *l_req_fw_msg = nullptr;
+ hostInterfaces::hbrt_fw_msg *l_resp_fw_msg = nullptr;
+
+ do
+ {
+ if ((nullptr == g_hostInterfaces) ||
+ (nullptr == g_hostInterfaces->firmware_request))
+ {
+ TRACFCOMP(g_trac_fsiscom, ERR_MRK
+ "Hypervisor firmware_request interface not linked");
+
+ /*@
+ * @errortype
+ * @severity ERRL_SEV_UNRECOVERABLE
+ * @moduleid MOD_FSISCOM_RT_SEND_SCOM_TO_FSP
+ * @reasoncode RC_RT_INTERFACE_ERR
+ * @userdata1 target's HUID
+ * @userdata2 SCOM address
+ * @devdesc Hypervisor firmware request interface not linked
+ */
+ l_err = new ERRORLOG::ErrlEntry(ERRORLOG::ERRL_SEV_UNRECOVERABLE,
+ MOD_FSISCOM_RT_SEND_SCOM_TO_FSP,
+ RC_RT_INTERFACE_ERR,
+ get_huid(i_target),
+ i_scomAddr,
+ ERRORLOG::ErrlEntry::ADD_SW_CALLOUT);
+ break;
+ }
+
+ // Create and initialize to zero a few needed variables
+ uint32_t l_fsp_data_size(0);
+ uint64_t l_req_fw_msg_size(0), l_resp_fw_msg_size(0);
+
+ // Create the dynamic firmware messages
+ createGenericFspMsg(sizeof(SingleScomOpHbrtFspData_t),
+ l_fsp_data_size,
+ l_req_fw_msg_size,
+ l_req_fw_msg,
+ l_resp_fw_msg_size,
+ l_resp_fw_msg);
+
+ // If there was an issue with creating the messages,
+ // create an Error Log entry and exit
+ if (!l_req_fw_msg || !l_resp_fw_msg)
+ {
+ TRACFCOMP(g_trac_fsiscom, ERR_MRK
+ "Unable to allocate firmware request messages");
+
+ /*@
+ * @errortype
+ * @severity ERRL_SEV_UNRECOVERABLE
+ * @moduleid MOD_FSISCOM_RT_SEND_SCOM_TO_FSP
+ * @reasoncode RC_RT_NULL_FW_MSG_PTR
+ * @userdata1 target's HUID
+ * @userdata2 SCOM address
+ * @devdesc Unable to allocate firmware request messages
+ */
+ l_err = new ERRORLOG::ErrlEntry(ERRORLOG::ERRL_SEV_UNRECOVERABLE,
+ MOD_FSISCOM_RT_SEND_SCOM_TO_FSP,
+ RC_RT_NULL_FW_MSG_PTR,
+ get_huid(i_target),
+ i_scomAddr,
+ ERRORLOG::ErrlEntry::ADD_SW_CALLOUT);
+ break;
+ }
+
+ // Populate the request message with given data
+ l_req_fw_msg->generic_msg.msgq = MBOX::FSP_SCOM_OPS_MSGQ;
+ l_req_fw_msg->generic_msg.msgType =
+ GenericFspMboxMessage_t::MSG_SINGLE_SCOM_OP;
+
+ // Create a useful struct to populate the generic_msg::data field
+ // Set the command-specific portion of the FSP message
+ SingleScomOpHbrtFspData_t* l_fspData =
+ reinterpret_cast<SingleScomOpHbrtFspData_t*>
+ (&(l_req_fw_msg->generic_msg.data));
+ l_fspData->scom_op = i_opType;
+ l_fspData->huid = get_huid(i_target);
+ l_fspData->scom_addr = i_scomAddr;
+ l_fspData->scom_data = *((uint64_t *)io_buffer);
+
+ // Make the firmware_request call
+ // Ask the FSP to perform this SCOM operation
+ TRACFCOMP(g_trac_fsiscom, "Sending SINGLE_SCOM_OP firmware_request, "
+ "op=%c, huid=0x%X, addr=%llX",
+ (i_opType == DeviceFW::READ) ? 'r' : 'w',
+ l_fspData->huid, l_fspData->scom_addr);
+ l_err = firmware_request_helper(l_req_fw_msg_size,
+ l_req_fw_msg,
+ &l_resp_fw_msg_size,
+ l_resp_fw_msg);
+
+ if (l_err)
+ {
+ TRACFCOMP(g_trac_fsiscom, ERR_MRK
+ "FSP scom read/write failed. "
+ "target 0x%llX addr 0x%llX r/w %d",
+ get_huid(i_target), i_scomAddr, i_opType);
+
+ break;
+ }
+
+ // Create a useful struct to populate the generic_msg::data field
+ // Get the command-specific portion of the returned FSP message
+ l_fspData =
+ reinterpret_cast<SingleScomOpHbrtFspData_t*>
+ (&(l_resp_fw_msg->generic_msg.data));
+ *((uint64_t *)io_buffer) = l_fspData->scom_data;
+ } while(0);
+
+ // Release the firmware messages and set to NULL
+ delete [] l_req_fw_msg;
+ delete [] l_resp_fw_msg;
+ l_req_fw_msg = l_resp_fw_msg = nullptr;
+
+ return l_err;
+}
+
+
+/**
+ * @brief Ask FSP to read list of SCOMs
+ *
+ * @param[in] i_target Scom target
+ * @param[in] i_scomAddr Scom addresses to read
+ * @param[in/out] o_scomValue Scom values read (0xDEADBEEF for errors)
+ * @return errlHndl_t
+ */
+errlHndl_t sendMultiScomReadToFsp(TARGETING::TargetHandle_t i_target,
+ std::vector<uint64_t> &i_scomAddr,
+ std::vector<uint64_t> &o_scomValue)
+{
+ errlHndl_t l_err = nullptr;
+
+ // Handles to the firmware messages
+ hostInterfaces::hbrt_fw_msg *l_req_fw_msg = nullptr;
+ hostInterfaces::hbrt_fw_msg *l_resp_fw_msg = nullptr;
+
+ do
+ {
+ if ((nullptr == g_hostInterfaces) ||
+ (nullptr == g_hostInterfaces->firmware_request))
+ {
+ TRACFCOMP(g_trac_fsiscom, ERR_MRK
+ "Hypervisor firmware_request interface not linked");
+
+ /*@
+ * @errortype
+ * @severity ERRL_SEV_UNRECOVERABLE
+ * @moduleid MOD_FSISCOM_RT_SEND_MULTI_SCOM_TO_FSP
+ * @reasoncode RC_RT_INTERFACE_ERR
+ * @userdata1 target's HUID
+ * @userdata2 # of SCOMs to read
+ * @devdesc Hypervisor firmware request interface not linked
+ */
+ l_err = new ERRORLOG::ErrlEntry(ERRORLOG::ERRL_SEV_UNRECOVERABLE,
+ MOD_FSISCOM_RT_SEND_MULTI_SCOM_TO_FSP,
+ RC_RT_INTERFACE_ERR,
+ get_huid(i_target),
+ i_scomAddr.size(),
+ ERRORLOG::ErrlEntry::ADD_SW_CALLOUT);
+ break;
+ }
+
+ // Create and initialize to zero a few needed variables
+ uint32_t l_fsp_data_size(0);
+ uint64_t l_req_fw_msg_size(0), l_resp_fw_msg_size(0);
+
+ // Need to add the array of addresses/values
+ size_t l_numScoms = i_scomAddr.size();
+ uint64_t l_msg_size = sizeof(MultiScomReadHbrtFspData_t);
+
+ // Default MultiScomRead message size is for only one SCOM, need to
+ // add any additional SCOMs to the message size in order to have the
+ // additional space at the end of the struct.
+ if (l_numScoms > 1)
+ {
+ l_msg_size += (l_numScoms - 1) * sizeof(uint64_t);
+ }
+
+ // Create the dynamic firmware messages
+ createGenericFspMsg(l_msg_size,
+ l_fsp_data_size,
+ l_req_fw_msg_size,
+ l_req_fw_msg,
+ l_resp_fw_msg_size,
+ l_resp_fw_msg);
+
+ // If there was an issue with creating the messages,
+ // create an Error Log entry and exit
+ if (!l_req_fw_msg || !l_resp_fw_msg)
+ {
+ TRACFCOMP(g_trac_fsiscom, ERR_MRK
+ "Unable to allocate firmware request messages");
+
+ /*@
+ * @errortype
+ * @severity ERRL_SEV_UNRECOVERABLE
+ * @moduleid MOD_FSISCOM_RT_SEND_MULTI_SCOM_TO_FSP
+ * @reasoncode RC_RT_NULL_FW_MSG_PTR
+ * @userdata1 target's HUID
+ * @userdata2 # of SCOMs to read
+ * @devdesc Unable to allocate firmware request messages
+ */
+ l_err = new ERRORLOG::ErrlEntry(ERRORLOG::ERRL_SEV_UNRECOVERABLE,
+ MOD_FSISCOM_RT_SEND_MULTI_SCOM_TO_FSP,
+ RC_RT_NULL_FW_MSG_PTR,
+ get_huid(i_target),
+ i_scomAddr.size(),
+ ERRORLOG::ErrlEntry::ADD_SW_CALLOUT);
+ break;
+ }
+
+ // Populate the request message with given data
+ l_req_fw_msg->generic_msg.msgq = MBOX::FSP_SCOM_OPS_MSGQ;
+ l_req_fw_msg->generic_msg.msgType =
+ GenericFspMboxMessage_t::MSG_MULTI_SCOM_OP;
+
+ // Create a useful struct to populate the generic_msg::data field
+ // Set the command-specific portion of the FSP message
+ MultiScomReadHbrtFspData_t* l_fspData =
+ reinterpret_cast<MultiScomReadHbrtFspData_t*>
+ (&(l_req_fw_msg->generic_msg.data));
+ l_fspData->huid = get_huid(i_target);
+ l_fspData->scom_num = l_numScoms;
+ // copy SCOM addresses into scom_data
+ std::copy(i_scomAddr.begin(), i_scomAddr.end(), &(l_fspData->scom_data));
+
+ // Make the firmware_request call
+ // Ask the FSP to perform this SCOM operation
+ TRACFCOMP(g_trac_fsiscom, "Sending MULTI_SCOM_OP firmware_request");
+ l_err = firmware_request_helper(l_req_fw_msg_size,
+ l_req_fw_msg,
+ &l_resp_fw_msg_size,
+ l_resp_fw_msg);
+
+ if (l_err)
+ {
+ TRACFCOMP(g_trac_fsiscom, ERR_MRK
+ "FSP multi-scom read failed. target 0x%llX",
+ get_huid(i_target));
+
+ break;
+ }
+
+ // Create a useful struct to populate the generic_msg::data field
+ // Get the command-specific portion of the returned FSP message
+ l_fspData =
+ reinterpret_cast<MultiScomReadHbrtFspData_t*>
+ (&(l_resp_fw_msg->generic_msg.data));
+ if (l_fspData->scom_num != l_numScoms)
+ {
+ // Can't continue because we don't know how the returned SCOM values
+ // match with the requested SCOM addresses.
+
+ TRACFCOMP(g_trac_fsiscom, ERR_MRK
+ "FSP multi-scom read failed. target 0x%llX, "
+ "SCOMs requested(%d) != SCOMs read(%d)",
+ get_huid(i_target), l_numScoms, l_fspData->scom_num);
+
+ /*@
+ * @errortype
+ * @severity ERRL_SEV_PREDICTIVE
+ * @moduleid MOD_FSISCOM_RT_SEND_MULTI_SCOM_TO_FSP
+ * @reasoncode RC_INVALID_LENGTH
+ * @userdata1 target's HUID
+ * @userdata2[00:31] # of SCOMs requested
+ * @userdata2[32:63] # of SCOMs returned
+ * @devdesc Multi-SCOM read did not return correct SCOMs
+ */
+ l_err = new ERRORLOG::ErrlEntry(ERRORLOG::ERRL_SEV_PREDICTIVE,
+ MOD_FSISCOM_RT_SEND_MULTI_SCOM_TO_FSP,
+ RC_INVALID_LENGTH,
+ get_huid(i_target),
+ TWO_UINT32_TO_UINT64(
+ l_numScoms,
+ l_fspData->scom_num),
+ ERRORLOG::ErrlEntry::ADD_SW_CALLOUT);
+
+ break;
+ }
+ o_scomValue.insert(o_scomValue.end(),
+ &(l_fspData->scom_data),
+ &(l_fspData->scom_data) + l_numScoms);
+ } while(0);
+
+ // Release the firmware messages and set to NULL
+ delete [] l_req_fw_msg;
+ delete [] l_resp_fw_msg;
+ l_req_fw_msg = l_resp_fw_msg = nullptr;
+
+ return l_err;
+}
+
+// Mark the target and all the target's children as useFsiScom.
+static void markUseFsiScom(TARGETING::TargetHandle_t i_target)
+{
+ // Mark target
+ TARGETING::ScomSwitches l_switches = {0};
+ if (i_target->tryGetAttr<TARGETING::ATTR_SCOM_SWITCHES>(l_switches))
+ {
+ l_switches.useFsiScom = 1;
+ l_switches.useInbandScom = 0;
+ i_target->setAttr<TARGETING::ATTR_SCOM_SWITCHES>(l_switches);
+ }
+
+ // Mark children
+ TARGETING::TargetHandleList pChildList;
+ TARGETING::PredicateHwas isFunctional;
+ isFunctional.functional(true);
+
+ TARGETING::targetService().getAssociated(pChildList, i_target,
+ TARGETING::TargetService::CHILD_BY_AFFINITY,
+ TARGETING::TargetService::ALL, &isFunctional);
+ for (auto& l_child: pChildList)
+ {
+ markUseFsiScom(l_child);
+ }
+}
+
+// This map is used to cache a bulk read of SCOM values that we expect PRD
+// to ask for. A map of translated SCOM addresses and values is mapped to
+// the parent chip target.
+static std::map<TARGETING::Target *, std::map<uint64_t, uint64_t>> g_scomCache;
+
+/**
+ * @brief DMI channel has checkstopped. Mark it bad and switch to FSP access.
+ *
+ * @param[in] i_target membuf target
+ * @return None
+ */
+void switchToFspScomAccess(TARGETING::TargetHandle_t i_target)
+{
+ TRACDCOMP(g_trac_fsiscom,ENTER_MRK"switchToFspScomAccess");
+ errlHndl_t l_err = NULL;
+
+ // Need to mark the target's DMI channel and all targets below it
+ // as "useFsiScom" and bulk SCOM read requests should be sent to
+ // the FSP in order to populate the SCOM cache.
+ TARGETING::PredicateCTM l_dmi(TARGETING::CLASS_UNIT,
+ TARGETING::TYPE_DMI);
+ TARGETING::TargetHandleList l_dmiList;
+
+ TARGETING::targetService().getAssociated(l_dmiList,
+ i_target,
+ TARGETING::TargetService::PARENT_BY_AFFINITY,
+ TARGETING::TargetService::ALL,
+ &l_dmi);
+ if (l_dmiList.size() != 1)
+ {
+ TRACFCOMP(g_trac_fsiscom,ERR_MRK"Unable to find DMI for Centaur.");
+ }
+ else
+ {
+ TARGETING::TargetHandle_t l_dmiParent = nullptr;
+
+ l_dmiParent = *(l_dmiList.begin());
+ markUseFsiScom(l_dmiParent);
+
+ // All of the cached SCOMs will map to the same membuf target (after
+ // SCOM address translation).
+ std::map<uint64_t, uint64_t> l_newmap;
+ TARGETING::TargetHandle_t l_membuf = nullptr;
+
+ if (i_target->getAttr<TARGETING::ATTR_TYPE>() ==
+ TARGETING::TYPE_MEMBUF)
+ {
+ l_membuf = i_target;
+ }
+ else
+ {
+ l_membuf = const_cast<TARGETING::TargetHandle_t>
+ (TARGETING::getParentChip(i_target));
+ }
+
+ // Cache SCOMs that PRD will request. chnlFailScomList is a map of
+ // target types (MEMBUF, MBA, etc) and the associated SCOMs for them.
+ // chnlFailScomList is maintained by PRD and defined in
+ // prdfCenChnlFailCache.H.
+ for (auto& l_typeScoms: PRDF::chnlFailScomList)
+ {
+ // For each target type in chnlFailScomList, find the associated
+ // targets and cache their SCOMs
+ TARGETING::TargetHandleList l_targetList;
+ getChildAffinityTargets(l_targetList, l_dmiParent,
+ TARGETING::CLASS_NA, l_typeScoms.first);
+
+ for (auto& l_target: l_targetList)
+ {
+ std::vector<uint64_t> l_scomVals;
+
+ l_scomVals.clear();
+ l_err = sendMultiScomReadToFsp(l_target,
+ l_typeScoms.second,
+ l_scomVals);
+ if (l_err)
+ {
+ TRACFCOMP(g_trac_fsiscom,ERR_MRK
+ "There was an error caching the SCOMs "
+ "for huid(0x%llX)", get_huid(l_target));
+ errlCommit(l_err, RUNTIME_COMP_ID);
+ continue;
+ }
+
+ // Combine the requested SCOM addrs with the returned values in
+ // a local map, insert into cache keyed by target. Don't save
+ // SCOMs with a returned value of 0xDEADBEEF.
+ for (size_t i = 0;i < l_typeScoms.second.size();++i)
+ {
+ bool l_needsWakeup = false;
+ uint64_t l_relAddr = 0; // relative SCOM address
+ uint64_t l_transAddr = 0; // translated SCOM address
+
+ l_relAddr = l_typeScoms.second[i];
+ l_transAddr = l_relAddr;
+
+ if (l_target != l_membuf) // membuf addresses don't need
+ // translation
+ {
+ l_err = SCOM::scomTranslate(l_target,
+ l_transAddr,
+ l_needsWakeup);
+ }
+
+ if (l_err)
+ {
+ TRACFCOMP(g_trac_fsiscom,ERR_MRK
+ "There was an error translating the SCOM "
+ "address (0x%llX) for huid(0x%llX)",
+ l_relAddr, get_huid(l_target));
+ errlCommit(l_err, RUNTIME_COMP_ID);
+ continue;
+ }
+
+ if (l_scomVals[i] != 0xDEADBEEF)
+ {
+ l_newmap[l_transAddr] = l_scomVals[i];
+ }
+ } // for SCOM address list
+ } // for l_targetList
+ } // for chnlFailScomList
+
+ // Copy local map into cache for later use.
+ g_scomCache[l_membuf] = l_newmap;
+ }
+
+ TRACDCOMP(g_trac_fsiscom,EXIT_MRK"switchToFspScomAccess");
+}
+
+
+// Direct Centaur FSI SCOM calls through this interface at runtime.
+// This is an alternate route for when a DMI channel checkstop has
+// occurred, and PHYP cannot service the operation.
+DEVICE_REGISTER_ROUTE(DeviceFW::WILDCARD,
+ DeviceFW::FSISCOM,
+ TARGETING::TYPE_MEMBUF,
+ fsiScomPerformOp);
+
+/**
+ * @brief Complete the SCOM operation through the FSP.
+ *
+ * @param[in] i_opType Operation type, see driverif.H
+ * @param[in] i_target SCOM target
+ * @param[in/out] io_buffer Read: Pointer to output data storage
+ * Write: Pointer to input data storage
+ * @param[in/out] io_buflen Input: size of io_buffer (in bytes)
+ * Output: Read: Size of output data
+ * Write: Size of data written
+ * @param[in] i_accessType Access type
+ * @param[in] i_args This is an argument list for DD framework.
+ * In this function, there's only one argument,
+ * which is the SCOM address
+ * @return errlHndl_t
+ */
+errlHndl_t fsiScomPerformOp(DeviceFW::OperationType i_opType,
+ TARGETING::TargetHandle_t i_target,
+ void* io_buffer,
+ size_t& io_buflen,
+ int64_t i_accessType,
+ va_list i_args)
+{
+ TRACDCOMP(g_trac_fsiscom,ENTER_MRK"fsiScomPerformOp");
+ errlHndl_t l_err = nullptr;
+ uint64_t l_addr = va_arg(i_args,uint64_t);
+
+ l_err = SCOM::scomOpSanityCheck(i_opType,
+ i_target,
+ io_buffer,
+ io_buflen,
+ l_addr,
+ sizeof(uint64_t));
+
+ if (l_err)
+ {
+ // Trace here - sanity check does not know scom type
+ TRACFCOMP(g_trac_fsiscom,"Runtime FSIScom sanity check failed");
+ }
+ else
+ {
+ bool found = false;
+ auto targ = g_scomCache.find(i_target); // find target, returns map of
+ // SCOM addresses and values
+
+ if (i_opType == DeviceFW::READ && targ != g_scomCache.end())
+ {
+ auto scomVal = targ->second.find(l_addr); // find SCOM address
+
+ if (scomVal != targ->second.end())
+ {
+ // If we found the SCOM in the cache, then erase it from the
+ // cache and return the value.
+ found = true;
+ uint64_t *val = static_cast<uint64_t *>(io_buffer);
+ *val = scomVal->second;
+ io_buflen = sizeof(uint64_t);
+ targ->second.erase(scomVal);
+ }
+ }
+
+ if (i_opType == DeviceFW::WRITE || found == false)
+ {
+ l_err = sendScomOpToFsp(i_opType, i_target, l_addr, io_buffer);
+ }
+ }
+
+ TRACDCOMP(g_trac_fsiscom,EXIT_MRK"fsiScomPerformOp");
+
+ return l_err;
+}
+
+}; // end namespace FSISCOM
diff --git a/src/usr/scom/runtime/rt_scom.C b/src/usr/scom/runtime/rt_scom.C
index 26bac2898..551e9bac9 100644
--- a/src/usr/scom/runtime/rt_scom.C
+++ b/src/usr/scom/runtime/rt_scom.C
@@ -28,6 +28,7 @@
#include <errl/errlmanager.H>
#include <scom/scomreasoncodes.H>
#include <scom/scomif.H>
+#include <scom/runtime/rt_scomif.H>
#include <runtime/interface.h>
#include <runtime/rt_targeting.H>
#include <xscom/piberror.H>
@@ -223,6 +224,13 @@ errlHndl_t sendScomToHyp(DeviceFW::OperationType i_opType,
i_opType),
i_scomAddr);
+ constexpr int MembufFatalError = -0x1008;
+
+ if (rc == MembufFatalError)
+ {
+ FSISCOM::switchToFspScomAccess(i_target);
+ }
+
// attempt to translate rc into a pib error assuming
// the rc is in common format
HbrtRcPiberr_t l_commonRc = static_cast<HbrtRcPiberr_t>(rc);
diff --git a/src/usr/scom/runtime/test/testscom_rt.H b/src/usr/scom/runtime/test/testscom_rt.H
index bfa92afde..901b492f8 100644
--- a/src/usr/scom/runtime/test/testscom_rt.H
+++ b/src/usr/scom/runtime/test/testscom_rt.H
@@ -176,7 +176,7 @@ public:
TRACFCOMP( g_trac_scom, "ScomTest::test_SCOMreadWrite_proc> %d/%d fails", fails, total );
}
-
+ // FSI access in runtime
/**
* @brief SCOM test via FSISCOM to Centaur
*
@@ -186,6 +186,8 @@ public:
TRACFCOMP( g_trac_scom, "ScomTest::test_FSISCOMreadWrite_centaur> Start" );
uint64_t fails = 0;
uint64_t total = 0;
+#if 0 // removing this test from runtime because HB doesn't have any FSI SCOM
+ // access during runtime (except through FSP)
errlHndl_t l_err = NULL;
// Setup some targets to use
@@ -252,8 +254,10 @@ public:
{
continue;
}
- else if (scom_targets[x]->
- getAttr<TARGETING::ATTR_HWAS_STATE>().functional != true)
+ else if ((scom_targets[x]->
+ getAttr<TARGETING::ATTR_HWAS_STATE>().functional != true) ||
+ (scom_targets[x]->
+ getAttr<TARGETING::ATTR_SCOM_SWITCHES>().useFsiScom == 0))
{
TRACDCOMP( g_trac_scom, "ScomTest::test_FSISCOMreadWrite_centaur> Target %d is not functional", x );
scom_targets[x] = NULL; //remove from our list
@@ -347,6 +351,7 @@ public:
}
}
+#endif
TRACFCOMP( g_trac_scom, "ScomTest::test_FSISCOMreadWrite_centaur> %d/%d fails", fails, total );
}
diff --git a/src/usr/util/runtime/rt_cmds.C b/src/usr/util/runtime/rt_cmds.C
index e350e42dc..ce7df1daf 100644
--- a/src/usr/util/runtime/rt_cmds.C
+++ b/src/usr/util/runtime/rt_cmds.C
@@ -43,6 +43,9 @@
#include <isteps/pm/pm_common_ext.H>
#include <p9_hcd_memmap_base.H> // for reload_pm_complex
#include <p9_stop_data_struct.H> // for reload_pm_complex
+#include <scom/runtime/rt_scomif.H> // sendScomOpToFsp,
+ // sendMultiScomReadToFsp,
+ // switchToFspScomAccess
extern char hbi_ImageId;
@@ -994,6 +997,158 @@ void cmd_hbrt_update(char*& o_output)
/**
+ * @brief Mark a target as requiring access to its SCOMs through the FSP
+ * @param[out] o_output Output display buffer, memory allocated here
+ * @param[in] i_huid HUID associated with Target to switch access on
+ */
+void cmd_switchToFspScomAccess( char*& o_output, uint32_t i_huid)
+{
+ UTIL_FT( "cmd_switchToFspScomAccess> huid=%.8X", i_huid );
+
+ TARGETING::Target* l_targ{};
+
+ if(0xFFFFFFFF == i_huid)
+ {
+ TARGETING::targetService().getTopLevelTarget(l_targ);
+ }
+ else
+ {
+ l_targ = getTargetFromHUID(i_huid);
+ }
+
+ o_output = new char[100];
+ if( l_targ == NULL )
+ {
+ sprintf( o_output, "HUID %.8X not found", i_huid );
+ return;
+ }
+
+ FSISCOM::switchToFspScomAccess(l_targ);
+
+ sprintf( o_output, "switchToFspScomAccess executed");
+}
+
+
+/**
+ * @brief Send a scom operation (read/write) to the FSP
+ * @param[out] o_output Output display buffer, memory allocated here
+ * @param[in] i_op Operation: r or w
+ * @param[in] i_huid HUID associated with Target to get the SCOM from
+ * @param[in] i_scomAddr Address of SCOM to read or write
+ * @param[in] io_scomValue Buffer for read SCOM value, or value to write
+ */
+void cmd_sendScomOpToFSP( char*& o_output,
+ char i_op,
+ uint32_t i_huid,
+ uint64_t i_scomAddr,
+ uint64_t *io_scomValue )
+{
+ UTIL_FT( "cmd_getScomFromFSP> op=%c, huid=%.8X, addr=%.8X, size=%d",
+ i_op, i_huid, i_scomAddr, *io_scomValue );
+
+ TARGETING::Target* l_targ{};
+
+ if(0xFFFFFFFF == i_huid)
+ {
+ TARGETING::targetService().getTopLevelTarget(l_targ);
+ }
+ else
+ {
+ l_targ = getTargetFromHUID(i_huid);
+ }
+
+ o_output = new char[100];
+ if( l_targ == NULL )
+ {
+ sprintf( o_output, "HUID %.8X not found", i_huid );
+ return;
+ }
+
+ DeviceFW::OperationType l_op;
+ switch (i_op) {
+ case 'r':
+ case 'R':
+ l_op = DeviceFW::READ;
+ break;
+ case 'w':
+ case 'W':
+ l_op = DeviceFW::WRITE;
+ break;
+ default:
+ sprintf( o_output, "Operation must be r or w: %c", i_op );
+ return;
+ }
+
+ errlHndl_t l_err = nullptr;
+ l_err = FSISCOM::sendScomOpToFsp(l_op, l_targ, i_scomAddr,
+ (void *)io_scomValue);
+ if (l_err)
+ {
+ sprintf( o_output, "Error on call to sendScomOpToFsp, rc=%.4X",
+ ERRL_GETRC_SAFE(l_err) );
+ return;
+ }
+
+ sprintf( o_output, "op=%c, huid=%.16llX, scomAddr=%.16llX, scomValue=%.16llX",
+ i_op, i_huid, i_scomAddr, *io_scomValue);
+}
+
+
+/**
+ * @brief Send a multi scom read to the FSP
+ * @param[out] o_output Output display buffer, memory allocated here
+ * @param[in] i_huid HUID associated with Target to get the SCOMs from
+ * @param[in] i_scomAddr Addresses of SCOMs to read
+ * @param[in] o_scomValue Values of read SCOMs
+ */
+void cmd_sendMultiScomReadToFSP( char* &o_output,
+ uint32_t i_huid,
+ std::vector<uint64_t> &i_scomAddr,
+ std::vector<uint64_t> &o_scomValue )
+{
+ UTIL_FT( "cmd_sendMultiScomReadToFSP> huid=%.8X, num_SCOMs=%d,"
+ " num_outSCOMs=%d",
+ i_huid, i_scomAddr.size(), o_scomValue.size() );
+
+ TARGETING::Target* l_targ{};
+
+ if(0xFFFFFFFF == i_huid)
+ {
+ TARGETING::targetService().getTopLevelTarget(l_targ);
+ }
+ else
+ {
+ l_targ = getTargetFromHUID(i_huid);
+ }
+
+ o_output = new char[500];
+ if( l_targ == NULL )
+ {
+ sprintf( o_output, "HUID %.8X not found", i_huid );
+ return;
+ }
+
+ errlHndl_t l_err = nullptr;
+ l_err = FSISCOM::sendMultiScomReadToFsp( l_targ, i_scomAddr, o_scomValue);
+ if (l_err)
+ {
+ sprintf( o_output, "Error on call to sendMultiScomReadToFsp,"
+ " rc=%.4X", ERRL_GETRC_SAFE(l_err) );
+ return;
+ }
+
+ sprintf( o_output, "num_outSCOMs=%d", o_scomValue.size());
+ for (auto scom: o_scomValue)
+ {
+ char tmp_str[100];
+
+ sprintf( tmp_str, ", %.8llX", scom);
+ strcat( o_output, tmp_str);
+ }
+}
+
+
+/**
* @brief Execute an arbitrary command inside Hostboot Runtime
* @param[in] Number of arguments (standard C args)
* @param[in] Array of argument values (standard C args)
@@ -1254,9 +1409,67 @@ int hbrtCommand( int argc,
"ERROR: hbrt_update\n" );
}
}
+ else if( !strcmp( argv[0], "switchToFspScomAccess" ) )
+ {
+ if (argc == 2)
+ {
+ cmd_switchToFspScomAccess( *l_output,
+ strtou64(argv[1], NULL, 16)); // huid
+ }
+ else
+ {
+ *l_output = new char[100];
+ sprintf(*l_output,
+ "ERROR: switchToFspScomAccess <huid>");
+ }
+ }
+ else if( !strcmp( argv[0], "scomOpToFsp" ) )
+ {
+ if ((argc == 4) || (argc == 5))
+ {
+ uint64_t l_scomValue = 0;
+
+ if (argc == 5)
+ l_scomValue = strtou64( argv[4], NULL, 16 ); // value
+
+ cmd_sendScomOpToFSP( *l_output,
+ argv[1][0], // op
+ strtou64(argv[2], NULL, 16), // huid
+ strtou64(argv[3], NULL, 16), // addr
+ &l_scomValue );
+ }
+ else
+ {
+ *l_output = new char[100];
+ sprintf(*l_output,
+ "ERROR: scomOpToFsp <op> <huid> <scomAddr> [<scomValue>]");
+ }
+ }
+ else if( !strcmp( argv[0], "multiScomReadToFsp" ) )
+ {
+ if (argc >= 3)
+ {
+ std::vector<uint64_t> l_scomAddrs, l_scomValues;
+
+ for (int i = 2;i < argc;++i)
+ l_scomAddrs.push_back(strtou64( argv[i], NULL, 16 ));
+ l_scomValues.reserve(argc - 2);
+
+ cmd_sendMultiScomReadToFSP( *l_output,
+ strtou64(argv[1], NULL, 16), // huid
+ l_scomAddrs,
+ l_scomValues );
+ }
+ else
+ {
+ *l_output = new char[100];
+ sprintf(*l_output,
+ "ERROR: multiScomReadToFsp <huid> <scomAddrs>");
+ }
+ }
else
{
- *l_output = new char[50+100*10];
+ *l_output = new char[50+100*12];
char l_tmpstr[100];
sprintf( *l_output, "HBRT Commands:\n" );
sprintf( l_tmpstr, "testRunCommand <args...>\n" );
@@ -1283,6 +1496,13 @@ int hbrtCommand( int argc,
strcat( *l_output, l_tmpstr );
sprintf( l_tmpstr, "hbrt_update\n");
strcat( *l_output, l_tmpstr );
+ sprintf( l_tmpstr, "switchToFspScomAccess <huid>\n");
+ strcat( *l_output, l_tmpstr );
+ sprintf( l_tmpstr, "scomOpToFsp <op> <huid> <scomAddr> [<scomValue>]\n"
+ " <op> == r|w\n");
+ strcat( *l_output, l_tmpstr );
+ sprintf( l_tmpstr, "multiScomReadToFsp <huid> <scomAddrs>\n");
+ strcat( *l_output, l_tmpstr );
}
if( l_traceOut && (*l_output != NULL) )
diff --git a/src/usr/xscom/runtime/rt_xscom.C b/src/usr/xscom/runtime/rt_xscom.C
index 404753bf0..c38f9ef5b 100644
--- a/src/usr/xscom/runtime/rt_xscom.C
+++ b/src/usr/xscom/runtime/rt_xscom.C
@@ -43,6 +43,7 @@ DEVICE_REGISTER_ROUTE(DeviceFW::WILDCARD,
TARGETING::TYPE_PROC,
xscomPerformOp);
+#if 0
// Also direct fsi scom calls though this interface at runtime
DEVICE_REGISTER_ROUTE(DeviceFW::WILDCARD,
DeviceFW::FSISCOM,
@@ -53,6 +54,7 @@ DEVICE_REGISTER_ROUTE(DeviceFW::WILDCARD,
DeviceFW::FSISCOM,
TARGETING::TYPE_MEMBUF,
xscomPerformOp);
+#endif
/**
OpenPOWER on IntegriCloud