summaryrefslogtreecommitdiffstats
path: root/src/usr/ibscom
diff options
context:
space:
mode:
authorCorey Swenson <cswenson@us.ibm.com>2018-03-09 00:27:54 -0600
committerWilliam G. Hoffa <wghoffa@us.ibm.com>2018-03-20 18:29:47 -0400
commited84b08afa873008e71fb617146e536d2e9fe9b3 (patch)
treee015fe122af99c85ba5c42ed048dd93dd1cbe7eb /src/usr/ibscom
parent0e69501ebe5b6e31e52cfb765bdeef1a219cf4e1 (diff)
downloadtalos-hostboot-ed84b08afa873008e71fb617146e536d2e9fe9b3.tar.gz
talos-hostboot-ed84b08afa873008e71fb617146e536d2e9fe9b3.zip
Inband SCOM clean up
- Addresses review comments from original commit - Adds inband scom multicast workaround Change-Id: Ia17a8e5359227691464f3552ded585ede771813b Reviewed-on: http://ralgit01.raleigh.ibm.com/gerrit1/55305 Tested-by: Jenkins Server <pfd-jenkins+hostboot@us.ibm.com> Tested-by: Jenkins OP Build CI <op-jenkins+hostboot@us.ibm.com> Tested-by: Jenkins OP HW <op-hw-jenkins+hostboot@us.ibm.com> Tested-by: FSP CI Jenkins <fsp-CI-jenkins+hostboot@us.ibm.com> Reviewed-by: Prachi Gupta <pragupta@us.ibm.com> Reviewed-by: Christian R. Geddes <crgeddes@us.ibm.com> Reviewed-by: William G. Hoffa <wghoffa@us.ibm.com>
Diffstat (limited to 'src/usr/ibscom')
-rw-r--r--src/usr/ibscom/ibscom.C180
1 files changed, 152 insertions, 28 deletions
diff --git a/src/usr/ibscom/ibscom.C b/src/usr/ibscom/ibscom.C
index 5aab22d02..b0e18032e 100644
--- a/src/usr/ibscom/ibscom.C
+++ b/src/usr/ibscom/ibscom.C
@@ -55,7 +55,7 @@
// Trace definition
trace_desc_t* g_trac_ibscom = NULL;
-TRAC_INIT(&g_trac_ibscom, IBSCOM_COMP_NAME, 8*KILOBYTE);
+TRAC_INIT(&g_trac_ibscom, IBSCOM_COMP_NAME, KILOBYTE);
using namespace ERRORLOG;
using namespace TARGETING;
@@ -66,8 +66,6 @@ namespace IBSCOM
const uint32_t MBS_FIR = 0x02011400;
const uint32_t MBSIBERR0 = 0x0201141B;
const uint64_t IBSCOM_BASE = 0x0006000000000000;
-const uint64_t BIT_02_MASK = 0x0000000020000000;
-const uint64_t BIT_03_MASK = 0x0000000010000000;
const uint64_t BIT_18_MASK = 0x0000000000002000;
// Register XSCcom access functions to DD framework
@@ -216,7 +214,7 @@ errlHndl_t getParentDMI( Target* i_target, Target*& o_target )
l_dmi_list.size());
/*@
* @errortype
- * @moduleid IBSCOM_GET_PARRENT_DMI
+ * @moduleid IBSCOM_GET_PARENT_DMI
* @reasoncode IBSCOM_INVALID_CONFIG
* @userdata1[0:31] HUID of Centaur Target
* @userdata1[32:63] DMI List Size
@@ -226,7 +224,7 @@ errlHndl_t getParentDMI( Target* i_target, Target*& o_target )
*/
l_err =
new ErrlEntry(ERRL_SEV_UNRECOVERABLE,
- IBSCOM_GET_PARRENT_DMI,
+ IBSCOM_GET_PARENT_DMI,
IBSCOM_INVALID_CONFIG,
TWO_UINT32_TO_UINT64(
get_huid(i_target),
@@ -301,7 +299,7 @@ errlHndl_t getTargetVirtualAddress(Target* i_target,
"getTargetVirtualAddress: Need to compute virtual address for Centaur");
//Get the parent DMI
- Target* parentDMI = NULL;
+ Target* parentDMI = nullptr;
l_err = getParentDMI(i_target, parentDMI);
if( l_err )
@@ -957,39 +955,165 @@ errlHndl_t doIBScom(DeviceFW::OperationType i_opType,
return l_err;
}
-///////////////////////////////////////////////////////////////////////////////
-///////////////////////////////////////////////////////////////////////////////
-errlHndl_t ibscomPerformOp(DeviceFW::OperationType i_opType,
- Target* i_target,
- void* io_buffer,
- size_t& io_buflen,
- int64_t i_accessType,
- va_list i_args)
+/**
+ * @brief Multicast this ibscom address
+ *
+ * @param[in] i_opType read/write
+ * @param[in] i_target target membuf
+ * @param[inout] io_buffer return data
+ * @param[inout] io_buflen return data length
+ * @param[in] i_addr inband scom address
+ * @param[out] o_didWorkaround return indicator
+ *
+ * @return error log on fail
+ */
+errlHndl_t doIBScomMulticast( DeviceFW::OperationType i_opType,
+ Target* i_target,
+ void* io_buffer,
+ size_t& io_buflen,
+ uint64_t i_addr,
+ bool& o_didWorkaround )
{
- errlHndl_t l_err = NULL;
- uint64_t l_addr = va_arg(i_args,uint64_t);
+ errlHndl_t l_err = nullptr;
+ uint64_t* l_summaryReg = reinterpret_cast<uint64_t*>(io_buffer);
+
+ // Chiplet byte info masks
+ constexpr uint64_t IS_MULTICAST = 0x40000000;
+ constexpr uint64_t MULTICAST_GROUP = 0x07000000;
+ constexpr uint64_t MULTICAST_OP = 0x38000000;
+ constexpr uint64_t MULTICAST_OP_BITWISE = 0x10000000;
+ constexpr uint64_t CHIPLET_BYTE = 0xFF000000;
+
+ // Valid groups
+ constexpr uint64_t GROUP_0 = 0x00000000;
+ constexpr uint64_t GROUP_3 = 0x03000000;
+
+ uint64_t l_group = MULTICAST_GROUP & i_addr;
+
+ // Only perform this workaround for:
+ // - reads
+ // - multicast registers
+ // - multicast read option 'bit-wise'
+ // - multicast group 0 or 3
+ if( !((DeviceFW::READ == i_opType)
+ && ((IS_MULTICAST & i_addr) == IS_MULTICAST)
+ && ((MULTICAST_OP & i_addr) == MULTICAST_OP_BITWISE)
+ && ((GROUP_0 == l_group) || (GROUP_3 == l_group)) ) )
+ {
+ o_didWorkaround = false;
+ return nullptr;
+ }
- // Addressses with bit 18 set are not handled correctly
- // by inband scom, reroute to fsi scom
- if( (l_addr & BIT_02_MASK) ||
- (l_addr & BIT_03_MASK) ||
- (l_addr & BIT_18_MASK) )
+ TRACFCOMP( g_trac_ibscom, "doIBScomMulticast on %.8X for %.8X", TARGETING::get_huid(i_target), i_addr );
+
+ // Chiplet numbers
+ constexpr uint64_t CHIPLET_PRV = 1;
+ constexpr uint64_t CHIPLET_NST = 2;
+ constexpr uint64_t CHIPLET_MEM = 3;
+
+ // Start chiplet depends on group, end chiplet is always MEM
+ // - Multicast group 0: PRV NST MEM, chiplets 1 2 3
+ // - Multicast group 3: NST MEM, chiplets 2 3
+ uint64_t l_start_chplt = 0;
+ uint64_t l_end_chplt = CHIPLET_MEM;
+ if( GROUP_0 == l_group )
{
- l_err = deviceOp(i_opType,
- i_target,
- io_buffer,
- io_buflen,
- DEVICE_FSISCOM_ADDRESS(l_addr));
+ l_start_chplt = CHIPLET_PRV;
}
- else
+ else // Must be group 3
{
+ l_start_chplt = CHIPLET_NST;
+ }
+
+ // Do the ibscom for each chiplet and return the combined value
+ for( uint64_t l_chplt = l_start_chplt; l_chplt <= l_end_chplt; l_chplt++ )
+ {
+ // Remove the chiplet byte info from the address
+ uint64_t l_addr = (i_addr & ~CHIPLET_BYTE);
+ uint64_t l_data = 0;
+
+ // Add the chiplet to the address
+ l_addr |= (l_chplt << 24);
+ io_buflen = sizeof(uint64_t);
+
l_err = doIBScom(i_opType,
i_target,
- io_buffer,
+ &l_data,
io_buflen,
l_addr,
false);
+ if( l_err )
+ {
+ break;
+ }
+ // If any bits are set, set this unit's bit in summary reg
+ // note: just check the first bit,
+ // this is good enough for the use-case we have now
+ // but a better implementation would be to actually
+ // check the select regs as well so we know which bit(s)
+ // are the trigger
+ if( l_data & 0x8000000000000000 )
+ {
+ *l_summaryReg |= (0x8000000000000000 >> l_chplt);
+ }
+
}
+
+ o_didWorkaround = true;
+
+ return l_err;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////
+errlHndl_t ibscomPerformOp(DeviceFW::OperationType i_opType,
+ Target* i_target,
+ void* io_buffer,
+ size_t& io_buflen,
+ int64_t i_accessType,
+ va_list i_args)
+{
+ errlHndl_t l_err = NULL;
+ uint64_t l_addr = va_arg(i_args,uint64_t);
+
+ do
+ {
+ // @todo RTC 189385 Remove inband scom bit 18 workaround
+ // Addressses with bit 18 set are not handled correctly
+ // by inband scom, reroute to fsi scom
+ if( l_addr & BIT_18_MASK )
+ {
+ l_err = deviceOp(i_opType,
+ i_target,
+ io_buffer,
+ io_buflen,
+ DEVICE_FSISCOM_ADDRESS(l_addr));
+ }
+ else
+ {
+ // Multicast is not handled correctly by inband scom
+ // Call workaround to complete manually
+ bool l_didWorkaround = false;
+ l_err = doIBScomMulticast(i_opType,
+ i_target,
+ io_buffer,
+ io_buflen,
+ l_addr,
+ l_didWorkaround);
+ if( l_err || l_didWorkaround )
+ {
+ break;
+ }
+
+ l_err = doIBScom(i_opType,
+ i_target,
+ io_buffer,
+ io_buflen,
+ l_addr,
+ false);
+ }
+ } while(0);
+
return l_err;
}
OpenPOWER on IntegriCloud