diff options
author | Corey Swenson <cswenson@us.ibm.com> | 2018-03-09 00:27:54 -0600 |
---|---|---|
committer | William G. Hoffa <wghoffa@us.ibm.com> | 2018-03-20 18:29:47 -0400 |
commit | ed84b08afa873008e71fb617146e536d2e9fe9b3 (patch) | |
tree | e015fe122af99c85ba5c42ed048dd93dd1cbe7eb /src/usr/ibscom | |
parent | 0e69501ebe5b6e31e52cfb765bdeef1a219cf4e1 (diff) | |
download | talos-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.C | 180 |
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; } |