summaryrefslogtreecommitdiffstats
path: root/src/usr
diff options
context:
space:
mode:
Diffstat (limited to 'src/usr')
-rw-r--r--src/usr/diag/prdf/common/plat/mem/prdfMemAddress.C235
-rw-r--r--src/usr/diag/prdf/common/plat/mem/prdfMemAddress.H11
-rw-r--r--src/usr/diag/prdf/common/plat/mem/prdfMemCaptureData.C68
-rw-r--r--src/usr/diag/prdf/common/plat/mem/prdfMemDbUtils.H74
-rw-r--r--src/usr/diag/prdf/common/plat/mem/prdfMemEccAnalysis.C155
-rw-r--r--src/usr/diag/prdf/common/plat/mem/prdfMemEccAnalysis.H4
-rw-r--r--src/usr/diag/prdf/common/plat/mem/prdfMemMark.C345
-rw-r--r--src/usr/diag/prdf/common/plat/mem/prdfOcmbDataBundle.H217
-rw-r--r--src/usr/diag/prdf/common/plat/prdfPlatServices_common.C9
-rwxr-xr-xsrc/usr/diag/prdf/common/plat/prdfTargetServices.C12
-rw-r--r--src/usr/diag/prdf/plat/mem/prdfMemDynDealloc.C117
-rw-r--r--src/usr/diag/prdf/plat/mem/prdfMemTdCtlr.C77
-rw-r--r--src/usr/diag/prdf/plat/mem/prdfMemTdCtlr.H12
-rw-r--r--src/usr/diag/prdf/plat/mem/prdfMemTdCtlr_ipl.C16
-rw-r--r--src/usr/diag/prdf/plat/mem/prdfMemTdCtlr_rt.C449
-rw-r--r--src/usr/diag/prdf/plat/mem/prdfMemTps_ipl.C54
-rw-r--r--src/usr/diag/prdf/plat/mem/prdfMemTps_rt.C1070
-rw-r--r--src/usr/diag/prdf/plat/mem/prdfMemVcm.C62
-rw-r--r--src/usr/diag/prdf/plat/mem/prdfMemVcm_ipl.C9
-rw-r--r--src/usr/diag/prdf/plat/mem/prdfMemVcm_rt.C127
-rw-r--r--src/usr/diag/prdf/plat/mem/prdfP9Mcbist.C6
21 files changed, 3093 insertions, 36 deletions
diff --git a/src/usr/diag/prdf/common/plat/mem/prdfMemAddress.C b/src/usr/diag/prdf/common/plat/mem/prdfMemAddress.C
index 1227afeb8..5cf6a75a4 100644
--- a/src/usr/diag/prdf/common/plat/mem/prdfMemAddress.C
+++ b/src/usr/diag/prdf/common/plat/mem/prdfMemAddress.C
@@ -5,7 +5,7 @@
/* */
/* OpenPOWER HostBoot Project */
/* */
-/* Contributors Listed Below - COPYRIGHT 2016,2018 */
+/* Contributors Listed Below - COPYRIGHT 2016,2019 */
/* [+] International Business Machines Corp. */
/* */
/* */
@@ -59,6 +59,19 @@ MemAddr MemAddr::fromReadAddr<TYPE_MCBIST>( uint64_t i_addr )
}
template<>
+MemAddr MemAddr::fromReadAddr<TYPE_OCMB_CHIP>( uint64_t i_addr )
+{
+ uint64_t mrnk = (i_addr >> 59) & 0x7; // 2: 4
+ uint64_t srnk = (i_addr >> 56) & 0x7; // 5: 7
+ uint64_t row = (i_addr >> 38) & 0x3ffff; // 8:25
+ uint64_t col = (i_addr >> 31) & 0x7f; // 26:32
+ uint64_t bnk = (i_addr >> 26) & 0x1f; // 33:37
+
+ return MemAddr( MemRank(mrnk, srnk), bnk, row, col );
+}
+
+
+template<>
MemAddr MemAddr::fromReadAddr<TYPE_MEMBUF>( uint64_t i_addr )
{
uint64_t mrnk = (i_addr >> 60) & 0x7; // 1: 3
@@ -89,6 +102,21 @@ MemAddr MemAddr::fromMaintAddr<TYPE_MCBIST>( uint64_t i_addr )
}
template<>
+MemAddr MemAddr::fromMaintAddr<TYPE_OCMB_CHIP>( uint64_t i_addr )
+{
+ uint64_t rslct = (i_addr >> 59) & 0x3; // 3: 4
+ uint64_t srnk = (i_addr >> 56) & 0x7; // 5: 7
+ uint64_t row = (i_addr >> 38) & 0x3ffff; // 8:25
+ uint64_t col = (i_addr >> 31) & 0x7f; // 26:32
+ uint64_t bnk = (i_addr >> 26) & 0x1f; // 33:37
+ uint64_t dslct = (i_addr >> 23) & 0x1; // 40
+
+ uint64_t mrnk = (dslct << 2) | rslct;
+
+ return MemAddr( MemRank(mrnk, srnk), bnk, row, col );
+}
+
+template<>
MemAddr MemAddr::fromMaintAddr<TYPE_MBA>( uint64_t i_addr )
{
uint64_t mrnk = (i_addr >> 60) & 0x7; // 1: 3
@@ -169,6 +197,60 @@ uint32_t getMemReadAddr<TYPE_MCBIST>( ExtensibleChip * i_chip, uint32_t i_pos,
//------------------------------------------------------------------------------
template<>
+uint32_t getMemReadAddr<TYPE_OCMB_CHIP>( ExtensibleChip * i_chip,
+ MemAddr::ReadReg i_reg,
+ MemAddr & o_addr )
+{
+ #define PRDF_FUNC "[getMemReadAddr<TYPE_OCMB_CHIP>] "
+
+ uint32_t o_rc = SUCCESS;
+
+ PRDF_ERR( PRDF_FUNC "Function not supported yet" );
+ /* TODO RTC 208346
+ // Check parameters
+ PRDF_ASSERT( nullptr != i_chip );
+ PRDF_ASSERT( TYPE_MCBIST == i_chip->getType() );
+ PRDF_ASSERT( i_pos < MAX_MCA_PER_MCBIST );
+
+ // Get the register string.
+ const char * tmp = "";
+ switch ( i_reg )
+ {
+ case MemAddr::READ_NCE_ADDR: tmp = "MBNCER"; break;
+ case MemAddr::READ_RCE_ADDR: tmp = "MBRCER"; break;
+ case MemAddr::READ_MPE_ADDR: tmp = "MBMPER"; break;
+ case MemAddr::READ_UE_ADDR : tmp = "MBUER" ; break;
+ case MemAddr::READ_AUE_ADDR: tmp = "MBAUER"; break;
+ default: PRDF_ASSERT( false );
+ }
+
+ char reg_str[64];
+ sprintf( reg_str, "MCB%d_%s", i_pos, tmp );
+
+ // Read the address register
+ SCAN_COMM_REGISTER_CLASS * reg = i_chip->getRegister( reg_str );
+ uint32_t o_rc = reg->Read();
+ if ( SUCCESS != o_rc )
+ {
+ PRDF_ERR( PRDF_FUNC "Read() failed on %s: i_chip=0x%08x",
+ reg_str, i_chip->getHuid() );
+ }
+ else
+ {
+ // Get the address object.
+ uint64_t addr = reg->GetBitFieldJustified( 0, 64 );
+ o_addr = MemAddr::fromReadAddr<TYPE_MCBIST>( addr );
+ }
+ */
+
+ return o_rc;
+
+ #undef PRDF_FUNC
+}
+
+//------------------------------------------------------------------------------
+
+template<>
uint32_t getMemReadAddr<TYPE_MEMBUF>( ExtensibleChip * i_chip, uint32_t i_pos,
MemAddr::ReadReg i_reg, MemAddr & o_addr )
{
@@ -298,6 +380,57 @@ uint32_t getMemMaintAddr<TYPE_MCA>( ExtensibleChip * i_chip, MemAddr & o_addr )
//------------------------------------------------------------------------------
template<>
+uint32_t getMemMaintAddr<TYPE_OCMB_CHIP>( ExtensibleChip * i_chip,
+ MemAddr & o_addr )
+{
+ #define PRDF_FUNC "[getMemMaintAddr<TYPE_OCMB_CHIP>] "
+
+ // Check parameters
+ PRDF_ASSERT( nullptr != i_chip );
+ PRDF_ASSERT( TYPE_OCMB_CHIP == i_chip->getType() );
+
+ // Read the address register
+ SCAN_COMM_REGISTER_CLASS * reg = i_chip->getRegister( "MCBMCAT" );
+ uint32_t o_rc = reg->Read();
+ if ( SUCCESS != o_rc )
+ {
+ PRDF_ERR( PRDF_FUNC "Read() failed on MCBMCAT: i_chip=0x%08x",
+ i_chip->getHuid() );
+ }
+ else
+ {
+ // Get the address object.
+ uint64_t addr = reg->GetBitFieldJustified( 0, 64 );
+ o_addr = MemAddr::fromMaintAddr<TYPE_OCMB_CHIP>( addr );
+ }
+
+ return o_rc;
+
+ #undef PRDF_FUNC
+}
+
+//------------------------------------------------------------------------------
+
+template<>
+uint32_t getMemMaintAddr<TYPE_MEM_PORT>( ExtensibleChip * i_chip,
+ MemAddr & o_addr )
+{
+ #define PRDF_FUNC "[getMemMaintAddr<TYPE_MEM_PORT>] "
+
+ // Check parameters
+ PRDF_ASSERT( nullptr != i_chip );
+ PRDF_ASSERT( TYPE_MEM_PORT == i_chip->getType() );
+
+ ExtensibleChip * ocmbChip = getConnectedParent( i_chip, TYPE_OCMB_CHIP );
+
+ return getMemMaintAddr<TYPE_OCMB_CHIP>( ocmbChip, o_addr );
+
+ #undef PRDF_FUNC
+}
+
+//------------------------------------------------------------------------------
+
+template<>
uint32_t getMemMaintAddr<TYPE_MBA>( ExtensibleChip * i_chip, MemAddr & o_addr )
{
#define PRDF_FUNC "[getMemMaintAddr<TYPE_MBA>] "
@@ -389,8 +522,9 @@ uint32_t getMemMaintEndAddr<TYPE_MBA>( ExtensibleChip * i_chip,
#ifdef __HOSTBOOT_MODULE
-uint32_t getMcbistMaintPort( ExtensibleChip * i_mcbChip,
- std::vector<ExtensibleChip *> & o_mcaList )
+template<>
+uint32_t getMcbistMaintPort<TYPE_MCBIST>( ExtensibleChip * i_mcbChip,
+ ExtensibleChipList & o_mcaList )
{
#define PRDF_FUNC "[getMcbistMaintPort] "
@@ -402,9 +536,9 @@ uint32_t getMcbistMaintPort( ExtensibleChip * i_mcbChip,
o_mcaList.clear();
- SCAN_COMM_REGISTER_CLASS * mcbagra = i_mcbChip->getRegister( "MCBAGRA" );
- SCAN_COMM_REGISTER_CLASS * mcbmcat = i_mcbChip->getRegister( "MCBMCAT" );
- SCAN_COMM_REGISTER_CLASS * mcb_cntl = i_mcbChip->getRegister( "MCB_CNTL" );
+ SCAN_COMM_REGISTER_CLASS * mcbagra = i_mcbChip->getRegister( "MCBAGRA" );
+ SCAN_COMM_REGISTER_CLASS * mcbmcat = i_mcbChip->getRegister( "MCBMCAT" );
+ SCAN_COMM_REGISTER_CLASS * mcb_cntl = i_mcbChip->getRegister( "MCB_CNTL" );
do
{
@@ -446,7 +580,7 @@ uint32_t getMcbistMaintPort( ExtensibleChip * i_mcbChip,
}
// Get MCAs from all targeted ports.
- for ( uint8_t p = 0; p < 4; p++ )
+ for ( uint8_t p = 0; p < MAX_MCA_PER_MCBIST; p++ )
{
if ( 0 == (portMask & (0x8 >> p)) ) continue;
@@ -477,6 +611,93 @@ uint32_t getMcbistMaintPort( ExtensibleChip * i_mcbChip,
#undef PRDF_FUNC
}
+//------------------------------------------------------------------------------
+
+template<>
+uint32_t getMcbistMaintPort<TYPE_OCMB_CHIP>( ExtensibleChip * i_ocmbChip,
+ ExtensibleChipList & o_portList )
+{
+ #define PRDF_FUNC "[getMcbistMaintPort] "
+
+ // Check parameters
+ PRDF_ASSERT( nullptr != i_ocmbChip );
+ PRDF_ASSERT( TYPE_OCMB_CHIP == i_ocmbChip->getType() );
+
+ uint32_t o_rc = SUCCESS;
+
+ o_portList.clear();
+
+ SCAN_COMM_REGISTER_CLASS * mcbagra = i_ocmbChip->getRegister( "MCBAGRA" );
+ SCAN_COMM_REGISTER_CLASS * mcbmcat = i_ocmbChip->getRegister( "MCBMCAT" );
+ SCAN_COMM_REGISTER_CLASS * mcb_cntl = i_ocmbChip->getRegister( "MCB_CNTL" );
+
+ do
+ {
+ o_rc = mcbagra->Read();
+ if ( SUCCESS != o_rc )
+ {
+ PRDF_ERR( PRDF_FUNC "Read() failed on MCBAGRA: i_ocmbChip=0x%08x",
+ i_ocmbChip->getHuid() );
+ break;
+ }
+
+ // Get a mask of all ports in which the command was executed. Use
+ // MCB_CNTL[2:5] only if MCBAGRA[10] is b0 OR MCBAGRA[10:11] is b11.
+ // Otherwise, use MCBMCAT[38:39].
+ uint8_t portMask = 0;
+ if ( !mcbagra->IsBitSet(10) || mcbagra->IsBitSet(11) ) // broadcast mode
+ {
+ o_rc = mcb_cntl->Read();
+ if ( SUCCESS != o_rc )
+ {
+ PRDF_ERR( PRDF_FUNC "Read() failed on MCB_CNTL: "
+ "i_ocmbChip=0x%08x", i_ocmbChip->getHuid() );
+ break;
+ }
+
+ portMask = mcb_cntl->GetBitFieldJustified( 2, 4 );
+ }
+ else // non-broadcast mode
+ {
+ o_rc = mcbmcat->Read();
+ if ( SUCCESS != o_rc )
+ {
+ PRDF_ERR( PRDF_FUNC "Read() failed on MCBMCAT: "
+ "i_ocmbChip=0x%08x", i_ocmbChip->getHuid() );
+ break;
+ }
+
+ portMask = 0x8 >> mcbmcat->GetBitFieldJustified( 38, 2 );
+ }
+
+ // Get MEM_PORTs from all targeted ports.
+ ExtensibleChipList portList = getConnected( i_ocmbChip, TYPE_MEM_PORT );
+ for ( auto & port : portList )
+ {
+ // Get the MEM_PORT position relative to the OCMB
+ uint8_t portRelPos = port->getTrgt()->getAttr<ATTR_REL_POS>();
+
+ // If the port wasn't targeted by the command, skip to next port
+ if ( 0 == (portMask & (0x8 >> portRelPos)) ) continue;
+
+ o_portList.push_back( port );
+ }
+
+ // The list should never be empty.
+ size_t sz_list = o_portList.size();
+ if ( 0 == sz_list )
+ {
+ PRDF_ERR( PRDF_FUNC "o_portList is empty: i_ocmbChip=0x%08x "
+ "portMask=0x%0x", i_ocmbChip->getHuid(), portMask );
+ PRDF_ASSERT( false ); // mcbist functional but no configured ports
+ }
+
+ } while (0);
+
+ return o_rc;
+
+ #undef PRDF_FUNC
+}
#endif
//------------------------------------------------------------------------------
diff --git a/src/usr/diag/prdf/common/plat/mem/prdfMemAddress.H b/src/usr/diag/prdf/common/plat/mem/prdfMemAddress.H
index 8dc192672..527eab86f 100644
--- a/src/usr/diag/prdf/common/plat/mem/prdfMemAddress.H
+++ b/src/usr/diag/prdf/common/plat/mem/prdfMemAddress.H
@@ -5,7 +5,7 @@
/* */
/* OpenPOWER HostBoot Project */
/* */
-/* Contributors Listed Below - COPYRIGHT 2016,2018 */
+/* Contributors Listed Below - COPYRIGHT 2016,2019 */
/* [+] International Business Machines Corp. */
/* */
/* */
@@ -226,13 +226,14 @@ uint32_t getMemMaintEndAddr( ExtensibleChip * i_chip, MemAddr & o_addr );
* - if there are more than one configured ports behind the MCBIST.
* - if all configured ports have the same geometry.
*
- * @note Only supported for MCBIST.
- * @param i_mcbChip An MCBIST chip.
- * @param o_mcaList A list of all MCAs targeted by the command.
+ * @note Only supported for MCBIST/OCMB.
+ * @param i_mcbChip An MCBIST/OCMB chip.
+ * @param o_portList A list of all MCAs/MEM_PORTs targeted by the command.
* @return Non-SUCCESS if an internal function fails, SUCCESS otherwise.
*/
+template<TARGETING::TYPE T>
uint32_t getMcbistMaintPort( ExtensibleChip * i_mcbChip,
- std::vector<ExtensibleChip *> & o_mcaList );
+ ExtensibleChipList & o_portList );
#endif
diff --git a/src/usr/diag/prdf/common/plat/mem/prdfMemCaptureData.C b/src/usr/diag/prdf/common/plat/mem/prdfMemCaptureData.C
index ebef7ae29..c7cee2abd 100644
--- a/src/usr/diag/prdf/common/plat/mem/prdfMemCaptureData.C
+++ b/src/usr/diag/prdf/common/plat/mem/prdfMemCaptureData.C
@@ -39,6 +39,7 @@
#include <prdfCenMbaDataBundle.H>
#include <prdfPlatServices.H>
#include <prdfP9McaDataBundle.H>
+#include <prdfOcmbDataBundle.H>
#include <prdfMemRowRepair.H>
@@ -172,7 +173,6 @@ void captureDramRepairsData( TARGETING::TargetHandle_t i_trgt,
if( CEN_VPD_DIMM_SPARE_NO_SPARE != spareConfig )
data.header.isSpareDram = true;
-
// Iterate all ranks to get DRAM repair data
for ( auto & rank : masterRanks )
{
@@ -459,6 +459,33 @@ void captureIueCounts<McaDataBundle*>( TARGETING::TargetHandle_t i_trgt,
//------------------------------------------------------------------------------
template<>
+void captureIueCounts<OcmbDataBundle*>( TARGETING::TargetHandle_t i_trgt,
+ OcmbDataBundle * i_db,
+ CaptureData & io_cd )
+{
+ #ifdef __HOSTBOOT_MODULE
+
+ uint8_t sz_capData = i_db->iv_iueTh.size()*2;
+ uint8_t capData[sz_capData] = {};
+ uint8_t idx = 0;
+
+ for ( auto & th_pair : i_db->iv_iueTh )
+ {
+ capData[idx] = th_pair.first;
+ capData[idx+1] = th_pair.second.getCount();
+ idx += 2;
+ }
+
+ // Add data to capture data.
+ BitString bs ( sz_capData*8, (CPU_WORD *) &capData );
+ io_cd.Add( i_trgt, Util::hashString("IUE_COUNTS"), bs );
+
+ #endif
+}
+
+//------------------------------------------------------------------------------
+
+template<>
void addEccData<TYPE_MCA>( ExtensibleChip * i_chip,
STEP_CODE_DATA_STRUCT & io_sc )
{
@@ -497,6 +524,45 @@ void addEccData<TYPE_MCBIST>( ExtensibleChip * i_chip,
}
template<>
+void addEccData<TYPE_MEM_PORT>( ExtensibleChip * i_chip,
+ STEP_CODE_DATA_STRUCT & io_sc )
+{
+ PRDF_ASSERT( TYPE_MEM_PORT == i_chip->getType() );
+
+ CaptureData & cd = io_sc.service_data->GetCaptureData();
+
+ TargetHandle_t trgt = i_chip->getTrgt();
+ ExtensibleChip * ocmb = getConnectedParent( i_chip, TYPE_OCMB_CHIP );
+ OcmbDataBundle * db = getOcmbDataBundle( ocmb );
+
+ // Add DRAM repairs data from hardware.
+ captureDramRepairsData<TYPE_OCMB_CHIP>( ocmb->getTrgt(), cd );
+
+ // Add DRAM repairs data from VPD.
+ captureDramRepairsVpd<TYPE_MEM_PORT>( trgt, cd );
+
+ // Add IUE counts to capture data.
+ captureIueCounts<OcmbDataBundle*>( ocmb->getTrgt(), db, cd );
+
+ // Add CE table to capture data.
+ db->iv_ceTable.addCapData( cd );
+
+ // Add UE table to capture data.
+ db->iv_ueTable.addCapData( cd );
+}
+
+template<>
+void addEccData<TYPE_OCMB_CHIP>( ExtensibleChip * i_chip,
+ STEP_CODE_DATA_STRUCT & io_sc )
+{
+ PRDF_ASSERT( TYPE_OCMB_CHIP == i_chip->getType() );
+
+ // Add data for each connected MEM_PORT.
+ ExtensibleChipList list = getConnected( i_chip, TYPE_MEM_PORT );
+ for ( auto & port : list ) { addEccData<TYPE_MEM_PORT>(port, io_sc); }
+}
+
+template<>
void addEccData<TYPE_MBA>( ExtensibleChip * i_chip,
STEP_CODE_DATA_STRUCT & io_sc )
{
diff --git a/src/usr/diag/prdf/common/plat/mem/prdfMemDbUtils.H b/src/usr/diag/prdf/common/plat/mem/prdfMemDbUtils.H
index 7605a82fa..affd8c5b3 100644
--- a/src/usr/diag/prdf/common/plat/mem/prdfMemDbUtils.H
+++ b/src/usr/diag/prdf/common/plat/mem/prdfMemDbUtils.H
@@ -5,7 +5,7 @@
/* */
/* OpenPOWER HostBoot Project */
/* */
-/* Contributors Listed Below - COPYRIGHT 2018 */
+/* Contributors Listed Below - COPYRIGHT 2018,2019 */
/* [+] International Business Machines Corp. */
/* */
/* */
@@ -28,6 +28,8 @@
#include <prdfCenMbaDataBundle.H>
#include <prdfP9McaDataBundle.H>
+#include <prdfOcmbDataBundle.H>
+#include <prdfTargetServices.H>
namespace PRDF
{
@@ -62,6 +64,16 @@ uint32_t addCeTableEntry<TARGETING::TYPE_MCA>( ExtensibleChip * i_chip,
}
template<> inline
+uint32_t addCeTableEntry<TARGETING::TYPE_OCMB_CHIP>( ExtensibleChip * i_chip,
+ const MemAddr & i_addr,
+ const MemSymbol & i_symbol,
+ bool i_isHard )
+{
+ return getOcmbDataBundle(i_chip)->iv_ceTable.addEntry( i_addr, i_symbol,
+ i_isHard );
+}
+
+template<> inline
uint32_t addCeTableEntry<TARGETING::TYPE_MBA>( ExtensibleChip * i_chip,
const MemAddr & i_addr,
const MemSymbol & i_symbol,
@@ -91,6 +103,14 @@ void addUeTableEntry<TARGETING::TYPE_MCA>( ExtensibleChip * i_chip,
}
template<> inline
+void addUeTableEntry<TARGETING::TYPE_OCMB_CHIP>( ExtensibleChip * i_chip,
+ UE_TABLE::Type i_type,
+ const MemAddr & i_addr )
+{
+ getOcmbDataBundle(i_chip)->iv_ueTable.addEntry( i_type, i_addr );
+}
+
+template<> inline
void addUeTableEntry<TARGETING::TYPE_MBA>( ExtensibleChip * i_chip,
UE_TABLE::Type i_type,
const MemAddr & i_addr )
@@ -118,6 +138,14 @@ void resetEccFfdc<TARGETING::TYPE_MCA>( ExtensibleChip * i_chip,
}
template<> inline
+void resetEccFfdc<TARGETING::TYPE_OCMB_CHIP>( ExtensibleChip * i_chip,
+ const MemRank & i_rank,
+ AddrRangeType i_type )
+{
+ getOcmbDataBundle(i_chip)->iv_ceTable.deactivateRank( i_rank, i_type );
+}
+
+template<> inline
void resetEccFfdc<TARGETING::TYPE_MBA>( ExtensibleChip * i_chip,
const MemRank & i_rank,
AddrRangeType i_type )
@@ -134,7 +162,7 @@ void resetEccFfdc<TARGETING::TYPE_MBA>( ExtensibleChip * i_chip,
/**
* @brief Generic wrapper to push a TdEntry to the Targeted Diagnostics queue.
- * @param i_chip MCA or MBA.
+ * @param i_chip MCA, MBA, or MEM_PORT.
* @param i_entry The new TdEntry.
* @return Non-SUCCESS if an internal function fails, SUCCESS otherwise.
*/
@@ -155,6 +183,13 @@ void pushToQueue<TARGETING::TYPE_MBA>( ExtensibleChip * i_chip,
getMbaDataBundle(i_chip)->getTdCtlr()->pushToQueue( i_entry );
}
+template<> inline
+void pushToQueue<TARGETING::TYPE_OCMB_CHIP>( ExtensibleChip * i_chip,
+ TdEntry * i_entry )
+{
+ getOcmbDataBundle(i_chip)->getTdCtlr()->pushToQueue( i_entry );
+}
+
#endif // Hostboot IPL/Runtime
//##############################################################################
@@ -179,6 +214,13 @@ MemIplCeStats<TARGETING::TYPE_MCA> * getIplCeStats( ExtensibleChip * i_chip )
}
template<> inline
+MemIplCeStats<TARGETING::TYPE_OCMB_CHIP> * getIplCeStats(
+ ExtensibleChip * i_chip )
+{
+ return getOcmbDataBundle(i_chip)->getIplCeStats();
+}
+
+template<> inline
MemIplCeStats<TARGETING::TYPE_MBA> * getIplCeStats( ExtensibleChip * i_chip )
{
return getMbaDataBundle(i_chip)->getIplCeStats();
@@ -211,6 +253,13 @@ uint32_t handleTdEvent<TARGETING::TYPE_MCA>( ExtensibleChip * i_chip,
}
template<> inline
+uint32_t handleTdEvent<TARGETING::TYPE_OCMB_CHIP>(ExtensibleChip * i_chip,
+ STEP_CODE_DATA_STRUCT & io_sc)
+{
+ return getOcmbDataBundle(i_chip)->getTdCtlr()->handleTdEvent( io_sc );
+}
+
+template<> inline
uint32_t handleTdEvent<TARGETING::TYPE_MBA>( ExtensibleChip * i_chip,
STEP_CODE_DATA_STRUCT & io_sc )
{
@@ -242,6 +291,27 @@ void banTps<TARGETING::TYPE_MBA>( ExtensibleChip * i_chip,
getMbaDataBundle(i_chip)->getTdCtlr()->banTps( i_chip, i_rank );
}
+template<> inline
+void banTps<TARGETING::TYPE_OCMB_CHIP>( ExtensibleChip * i_chip,
+ const MemRank & i_rank )
+{
+ // Ban TPS on this rank.
+ getOcmbDataBundle(i_chip)->getTdCtlr()->banTps( i_chip, i_rank );
+ // Permanently mask mainline NCEs and TCEs because of the TPS ban.
+ getOcmbDataBundle(i_chip)->iv_maskMainlineNceTce = true;
+}
+
+template<> inline
+void banTps<TARGETING::TYPE_MEM_PORT>( ExtensibleChip * i_chip,
+ const MemRank & i_rank )
+{
+ // Call banTps for the parent OCMB
+ ExtensibleChip * ocmbChip = PlatServices::getConnectedParent( i_chip,
+ TARGETING::TYPE_OCMB_CHIP );
+ banTps<TARGETING::TYPE_OCMB_CHIP>( ocmbChip, i_rank );
+}
+
+
#endif // Hostboot Runtime only
} // end namespace MemDbUtils
diff --git a/src/usr/diag/prdf/common/plat/mem/prdfMemEccAnalysis.C b/src/usr/diag/prdf/common/plat/mem/prdfMemEccAnalysis.C
index 9869a8c08..fb2abb0c3 100644
--- a/src/usr/diag/prdf/common/plat/mem/prdfMemEccAnalysis.C
+++ b/src/usr/diag/prdf/common/plat/mem/prdfMemEccAnalysis.C
@@ -137,6 +137,61 @@ uint32_t handleMemUe<TYPE_MCA>( ExtensibleChip * i_chip, const MemAddr & i_addr,
}
template<>
+uint32_t handleMemUe<TYPE_OCMB_CHIP>( ExtensibleChip * i_chip,
+ const MemAddr & i_addr,
+ UE_TABLE::Type i_type,
+ STEP_CODE_DATA_STRUCT & io_sc )
+{
+ #define PRDF_FUNC "[MemEcc::handleMemUe<TYPE_OCMB_CHIP>] "
+
+ PRDF_ASSERT( nullptr != i_chip );
+ PRDF_ASSERT( TYPE_OCMB_CHIP == i_chip->getType() );
+
+ uint32_t o_rc = SUCCESS;
+
+ PRDF_ERR( PRDF_FUNC "Function not supported yet" );
+ /* TODO RTC 208211
+ do
+ {
+ // First check to see if this is a side-effect UE.
+ SCAN_COMM_REGISTER_CLASS * fir = i_chip->getRegister("DDRPHYFIR");
+ o_rc = fir->Read();
+ if ( SUCCESS != o_rc )
+ {
+ PRDF_ERR( PRDF_FUNC "Read() failed on DDRPHYFIR: i_chip=0x%08x",
+ i_chip->getHuid() );
+ break;
+ }
+
+ // Check DDRPHYFIR[54:55,57:59] to determine if this is a side-effect.
+ if ( 0 != (fir->GetBitFieldJustified(54,6) & 0x37) )
+ {
+ // This is a side-effect. Callout the MCA.
+ PRDF_TRAC( PRDF_FUNC "Memory UE is side-effect of DDRPHY error" );
+ io_sc.service_data->SetCallout( i_chip->getTrgt() );
+ io_sc.service_data->setServiceCall();
+ }
+ else
+ {
+ // Handle the memory UE.
+ o_rc = __handleMemUe<TYPE_MCA>( i_chip, i_addr, i_type, io_sc );
+ if ( SUCCESS != o_rc )
+ {
+ PRDF_ERR( PRDF_FUNC "__handleMemUe(0x%08x,%d) failed",
+ i_chip->getHuid(), i_type );
+ break;
+ }
+ }
+
+ } while (0);
+ */
+
+ return o_rc;
+
+ #undef PRDF_FUNC
+}
+
+template<>
uint32_t handleMemUe<TYPE_MBA>( ExtensibleChip * i_chip, const MemAddr & i_addr,
UE_TABLE::Type i_type,
STEP_CODE_DATA_STRUCT & io_sc )
@@ -493,6 +548,11 @@ template
uint32_t handleMpe<TYPE_MBA>( ExtensibleChip * i_chip, const MemAddr & i_addr,
UE_TABLE::Type i_type,
STEP_CODE_DATA_STRUCT & io_sc );
+template
+uint32_t handleMpe<TYPE_OCMB_CHIP>( ExtensibleChip * i_chip,
+ const MemAddr & i_addr,
+ UE_TABLE::Type i_type,
+ STEP_CODE_DATA_STRUCT & io_sc );
//------------------------------------------------------------------------------
@@ -581,6 +641,10 @@ template
uint32_t analyzeFetchMpe<TYPE_MBA>( ExtensibleChip * i_chip,
const MemRank & i_rank,
STEP_CODE_DATA_STRUCT & io_sc );
+template
+uint32_t analyzeFetchMpe<TYPE_OCMB_CHIP>( ExtensibleChip * i_chip,
+ const MemRank & i_rank,
+ STEP_CODE_DATA_STRUCT & io_sc );
//------------------------------------------------------------------------------
@@ -794,6 +858,9 @@ uint32_t analyzeFetchNceTce<TYPE_MCA>( ExtensibleChip * i_chip,
template
uint32_t analyzeFetchNceTce<TYPE_MBA>( ExtensibleChip * i_chip,
STEP_CODE_DATA_STRUCT & io_sc );
+template
+uint32_t analyzeFetchNceTce<TYPE_OCMB_CHIP>( ExtensibleChip * i_chip,
+ STEP_CODE_DATA_STRUCT & io_sc );
//------------------------------------------------------------------------------
@@ -958,6 +1025,94 @@ uint32_t handleMemIue<TYPE_MCA>( ExtensibleChip * i_chip,
//------------------------------------------------------------------------------
template<>
+uint32_t handleMemIue<TYPE_OCMB_CHIP>( ExtensibleChip * i_chip,
+ const MemRank & i_rank,
+ STEP_CODE_DATA_STRUCT & io_sc )
+{
+ #define PRDF_FUNC "[MemEcc::handleMemIue] "
+
+ PRDF_ASSERT( nullptr != i_chip );
+ PRDF_ASSERT( TYPE_OCMB_CHIP == i_chip->getType() );
+
+ uint32_t o_rc = SUCCESS;
+
+ PRDF_ERR( PRDF_FUNC "Function not supported yet" );
+ /* TODO RTC 208211
+
+ // Add the DIMM to the callout list.
+ MemoryMru mm { i_chip->getTrgt(), i_rank, MemoryMruData::CALLOUT_RANK };
+ io_sc.service_data->SetCallout( mm );
+
+ #ifdef __HOSTBOOT_MODULE
+
+ do
+ {
+ // Nothing else to do if handling a system checkstop.
+ if ( CHECK_STOP == io_sc.service_data->getPrimaryAttnType() ) break;
+
+ // Get the data bundle from chip.
+ McaDataBundle * db = getMcaDataBundle( i_chip );
+
+ // If we have already caused a port fail, mask the IUE bits.
+ if ( true == db->iv_iuePortFail )
+ {
+ SCAN_COMM_REGISTER_CLASS * mask_or =
+ i_chip->getRegister("MCAECCFIR_MASK_OR");
+
+ mask_or->SetBit(17);
+ mask_or->SetBit(37);
+
+ o_rc = mask_or->Write();
+ if ( SUCCESS != o_rc )
+ {
+ PRDF_ERR( PRDF_FUNC "Write() failed on 0x%08x",
+ i_chip->getHuid() );
+ break;
+ }
+ }
+
+ // Get the DIMM select.
+ uint8_t ds = i_rank.getDimmSlct();
+
+ // Initialize threshold if it doesn't exist yet.
+ if ( 0 == db->iv_iueTh.count(ds) )
+ {
+ db->iv_iueTh[ds] = TimeBasedThreshold( getIueTh() );
+ }
+
+ // Increment the count and check if at threshold.
+ if ( db->iv_iueTh[ds].inc(io_sc) )
+ {
+ // Make the error log predictive.
+ io_sc.service_data->setServiceCall();
+
+ // The port fail will be triggered in the PostAnalysis plugin after
+ // the error log has been committed.
+
+ // Mask off the entire port to avoid collateral.
+ o_rc = MemEcc::maskMemPort<TYPE_MCA>( i_chip );
+ if ( SUCCESS != o_rc )
+ {
+ PRDF_ERR( PRDF_FUNC "MemEcc::maskMemPort(0x%08x) failed",
+ i_chip->getHuid() );
+ break;
+ }
+ }
+
+ } while (0);
+
+ #endif // __HOSTBOOT_MODULE
+
+ */
+
+ return o_rc;
+
+ #undef PRDF_FUNC
+}
+
+//------------------------------------------------------------------------------
+
+template<>
uint32_t analyzeMainlineIue<TYPE_MCA>( ExtensibleChip * i_chip,
STEP_CODE_DATA_STRUCT & io_sc )
{
diff --git a/src/usr/diag/prdf/common/plat/mem/prdfMemEccAnalysis.H b/src/usr/diag/prdf/common/plat/mem/prdfMemEccAnalysis.H
index 735ae436f..f06df3c0f 100644
--- a/src/usr/diag/prdf/common/plat/mem/prdfMemEccAnalysis.H
+++ b/src/usr/diag/prdf/common/plat/mem/prdfMemEccAnalysis.H
@@ -5,7 +5,7 @@
/* */
/* OpenPOWER HostBoot Project */
/* */
-/* Contributors Listed Below - COPYRIGHT 2016,2018 */
+/* Contributors Listed Below - COPYRIGHT 2016,2019 */
/* [+] International Business Machines Corp. */
/* */
/* */
@@ -51,7 +51,7 @@ namespace MemEcc
* @brief Adds the memory CE to the callout list and CE table. Will also issue
* dynamic memory deallocation when appropriate. Returns true if TPS is
* required.
- * @param i_chip MCA or MBA.
+ * @param i_chip MCA, MBA, or MEM_PORT.
* @param i_addr Failed address.
* @param i_symbol Failed symbol.
* @param o_doTps True if TPS is required. False otherwise.
diff --git a/src/usr/diag/prdf/common/plat/mem/prdfMemMark.C b/src/usr/diag/prdf/common/plat/mem/prdfMemMark.C
index 83bff1876..98e72cf43 100644
--- a/src/usr/diag/prdf/common/plat/mem/prdfMemMark.C
+++ b/src/usr/diag/prdf/common/plat/mem/prdfMemMark.C
@@ -110,6 +110,69 @@ uint32_t readChipMark<TYPE_MCA>( ExtensibleChip * i_chip,
#undef PRDF_FUNC
}
+template<>
+uint32_t readChipMark<TYPE_OCMB_CHIP>( ExtensibleChip * i_chip,
+ const MemRank & i_rank,
+ MemMark & o_mark )
+{
+ #define PRDF_FUNC "[readChipMark<TYPE_OCMB_CHIP>] "
+
+ uint32_t o_rc = SUCCESS;
+ PRDF_ERR( PRDF_FUNC "Function not supported yet" );
+ /* TODO RTC 207389
+ o_mark = MemMark(); // ensure invalid
+
+ // get the register name
+ char msName[64];
+ sprintf( msName, "HW_MS%x", i_rank.getMaster() );
+
+ // get the mark store register
+ SCAN_COMM_REGISTER_CLASS * hwms = i_chip->getRegister( msName );
+
+ o_rc = hwms->ForceRead(); // always read latest
+ if ( SUCCESS != o_rc )
+ {
+ PRDF_ERR( PRDF_FUNC "ForceRead() failed on %s: i_chip=0x%08x",
+ msName, i_chip->getHuid() );
+ }
+ else
+ {
+ // HWMSx[0:7] contains the Galois field
+ uint8_t galois = hwms->GetBitFieldJustified(0,8);
+
+ // If the Galois field is zero, do nothing and use the default
+ // constructor for o_mark
+ if (0 != galois)
+ {
+ // get the target
+ TargetHandle_t trgt = i_chip->getTrgt();
+
+ // get the MemMark
+ o_mark = MemMark(trgt, i_rank, galois);
+ }
+ }
+ */
+
+ return o_rc;
+
+ #undef PRDF_FUNC
+}
+
+template<>
+uint32_t readChipMark<TYPE_MEM_PORT>( ExtensibleChip * i_chip,
+ const MemRank & i_rank,
+ MemMark & o_mark )
+{
+ #define PRDF_FUNC "[readChipMark<TYPE_MEM_PORT>] "
+
+ uint32_t o_rc = SUCCESS;
+ PRDF_ERR( PRDF_FUNC "Function not supported yet" );
+ // TODO RTC 207389
+
+ return o_rc;
+
+ #undef PRDF_FUNC
+}
//------------------------------------------------------------------------------
template<>
@@ -188,6 +251,41 @@ uint32_t clearChipMark<TYPE_MCA>( ExtensibleChip * i_chip,
//------------------------------------------------------------------------------
template<>
+uint32_t clearChipMark<TYPE_OCMB_CHIP>( ExtensibleChip * i_chip,
+ const MemRank & i_rank )
+{
+ #define PRDF_FUNC "[clearChipMark<TYPE_OCMB_CHIP>] "
+
+ uint32_t o_rc = SUCCESS;
+
+ PRDF_ERR( PRDF_FUNC "Function not supported yet" );
+ /* TODO RTC 207389
+ // get the register name
+ char msName[64];
+ sprintf( msName, "HW_MS%x", i_rank.getMaster() );
+
+ // get the mark store register
+ SCAN_COMM_REGISTER_CLASS * hwms = i_chip->getRegister( msName );
+
+ // Clear the entire HWMSx register.
+ hwms->clearAllBits();
+
+ o_rc = hwms->Write();
+ if ( SUCCESS != o_rc )
+ {
+ PRDF_ERR( PRDF_FUNC "Write() failed on %s: i_chip=0x%08x",
+ msName, i_chip->getHuid() );
+ }
+ */
+
+ return o_rc;
+
+ #undef PRDF_FUNC
+}
+
+//------------------------------------------------------------------------------
+
+template<>
uint32_t readSymbolMark<TYPE_MCA>( ExtensibleChip * i_chip,
const MemRank & i_rank, MemMark & o_mark )
{
@@ -247,6 +345,88 @@ uint32_t readSymbolMark<TYPE_MCA>( ExtensibleChip * i_chip,
#undef PRDF_FUNC
}
+template<>
+uint32_t readSymbolMark<TYPE_OCMB_CHIP>( ExtensibleChip * i_chip,
+ const MemRank & i_rank,
+ MemMark & o_mark )
+{
+ #define PRDF_FUNC "[readSymbolMark<TYPE_OCMB_CHIP>] "
+
+ uint32_t o_rc = SUCCESS;
+
+ PRDF_ERR( PRDF_FUNC "Function not supported yet" );
+ /* TODO RTC 207389
+ o_mark = MemMark(); // ensure invalid
+
+ // get the register name
+ char msName[64];
+ sprintf( msName, "FW_MS%x", i_rank.getMaster() );
+
+ // get the mark store register
+ SCAN_COMM_REGISTER_CLASS * fwms = i_chip->getRegister( msName );
+
+ o_rc = fwms->ForceRead(); // always read latest
+ if ( SUCCESS != o_rc )
+ {
+ PRDF_ERR( PRDF_FUNC "ForceRead() failed on %s: i_chip=0x%08x",
+ msName, i_chip->getHuid() );
+ }
+ else
+ {
+ // FWMSx[0:7] contains the Galois field
+ uint8_t galois = fwms->GetBitFieldJustified(0,8);
+
+ // If the Galois field is zero, do nothing and use the default
+ // constructor for o_mark
+ if (0 != galois)
+ {
+ // check other fields for accuracy - assert on failure
+
+ // FWMSx[8] should be 1 to indicate a symbol mark.
+ PRDF_ASSERT( fwms->IsBitSet(8) );
+
+ // FWMSx[9:11] should be 0b101 to indicate master rank.
+ PRDF_ASSERT( 0x5 == fwms->GetBitFieldJustified(9,3) );
+
+ // FWMSx[12:14] is the master rank and should match the register
+ // number.
+ PRDF_ASSERT( i_rank.getMaster() ==
+ fwms->GetBitFieldJustified(12,3) );
+
+ // FWMSx[15:22] should be all zeros
+ PRDF_ASSERT( 0x0 == fwms->GetBitFieldJustified(15,8) );
+
+ // get the target
+ TargetHandle_t trgt = i_chip->getTrgt();
+
+ // get the MemMark
+ o_mark = MemMark(trgt, i_rank, galois);
+ }
+ }
+ */
+
+ return o_rc;
+
+ #undef PRDF_FUNC
+}
+
+template<>
+uint32_t readSymbolMark<TYPE_MEM_PORT>( ExtensibleChip * i_chip,
+ const MemRank & i_rank,
+ MemMark & o_mark )
+{
+ #define PRDF_FUNC "[readSymbolMark<TYPE_MEM_PORT>] "
+
+ uint32_t o_rc = SUCCESS;
+
+ PRDF_ERR( PRDF_FUNC "Function not supported yet" );
+ // TODO RTC 207389
+
+ return o_rc;
+
+ #undef PRDF_FUNC
+}
+
//------------------------------------------------------------------------------
template<>
@@ -349,6 +529,41 @@ uint32_t clearSymbolMark<TYPE_MCA>( ExtensibleChip * i_chip,
#undef PRDF_FUNC
}
+//------------------------------------------------------------------------------
+
+template<>
+uint32_t clearSymbolMark<TYPE_OCMB_CHIP>( ExtensibleChip * i_chip,
+ const MemRank & i_rank )
+{
+ #define PRDF_FUNC "[clearSymbolMark<TYPE_OCMB_CHIP>] "
+
+ uint32_t o_rc = SUCCESS;
+
+ PRDF_ERR( PRDF_FUNC "Function not supported yet" );
+ /* TODO RTC 207389
+ // get the register name
+ char msName[64];
+ sprintf( msName, "FW_MS%x", i_rank.getMaster() );
+
+ // get the mark store register
+ SCAN_COMM_REGISTER_CLASS * fwms = i_chip->getRegister( msName );
+
+ // Clear the entire FWMSx register.
+ fwms->clearAllBits();
+
+ o_rc = fwms->Write();
+ if ( SUCCESS != o_rc )
+ {
+ PRDF_ERR( PRDF_FUNC "Write() failed on %s: i_chip=0x%08x",
+ msName, i_chip->getHuid() );
+ }
+ */
+
+ return o_rc;
+
+ #undef PRDF_FUNC
+}
+
//##############################################################################
// Utilities to read/write markstore (MBA)
//##############################################################################
@@ -1136,6 +1351,121 @@ uint32_t __applyRasPolicies<TYPE_MBA>( ExtensibleChip * i_chip,
#undef PRDF_FUNC
}
+template<>
+uint32_t __applyRasPolicies<TYPE_OCMB_CHIP>( ExtensibleChip * i_chip,
+ const MemRank & i_rank,
+ STEP_CODE_DATA_STRUCT & io_sc,
+ const MemMark & i_chipMark,
+ const MemMark & i_symMark,
+ TdEntry * & o_dsdEvent,
+ bool & o_allRepairsUsed )
+{
+ #define PRDF_FUNC "[__applyRasPolicies<TYPE_OCMB_CHIP>] "
+
+ uint32_t o_rc = SUCCESS;
+
+ PRDF_ERR( PRDF_FUNC "Function not supported yet" );
+ /* TODO RTC 207389
+ do
+ {
+ const uint8_t ps = i_chipMark.getSymbol().getPortSlct();
+ const uint8_t dram = i_chipMark.getSymbol().getDram();
+
+ const bool isX4 = isDramWidthX4( i_chip->getTrgt() );
+
+ // Determine if DRAM sparing is enabled.
+ bool isEnabled = false;
+ o_rc = isDramSparingEnabled<TYPE_MBA>( i_chip->getTrgt(), i_rank, ps,
+ isEnabled );
+ if ( SUCCESS != o_rc )
+ {
+ PRDF_ERR( PRDF_FUNC "isDramSparingEnabled() failed." );
+ break;
+ }
+
+ if ( isEnabled )
+ {
+ // Sparing is enabled. Get the current spares in hardware.
+ MemSymbol sp0, sp1, ecc;
+ o_rc = mssGetSteerMux<TARGETING::TYPE_MBA>( i_chip->getTrgt(),
+ i_rank, sp0, sp1, ecc );
+ if ( SUCCESS != o_rc )
+ {
+ PRDF_ERR( PRDF_FUNC "mssGetSteerMux(0x%08x,0x%02x) failed",
+ i_chip->getHuid(), i_rank.getKey() );
+ break;
+ }
+
+ // Add the spares to the callout list if they exist.
+ __addCallout( i_chip, i_rank, sp0, io_sc );
+ __addCallout( i_chip, i_rank, sp1, io_sc );
+ __addCallout( i_chip, i_rank, ecc, io_sc );
+
+ // Add the row repairs to the callout list if they exist
+ o_rc = __addRowRepairCallout<TARGETING::TYPE_MBA>( i_chip, i_rank,
+ io_sc );
+ if ( SUCCESS != o_rc )
+ {
+ PRDF_ERR( PRDF_FUNC "__addRowRepairCallout(0x%08x,0x%02x) "
+ "failed.", i_chip->getHuid(), i_rank.getKey() );
+ break;
+ }
+
+ // If the chip mark is on a spare then the spare is bad and hardware
+ // can not steer it to another DRAM even if one is available (e.g.
+ // the ECC spare). In this this case, make error log predictive.
+ if ( ( (0 == ps) && sp0.isValid() && (dram == sp0.getDram()) ) ||
+ ( (1 == ps) && sp1.isValid() && (dram == sp1.getDram()) ) ||
+ ( isX4 && ecc.isValid() && (dram == ecc.getDram()) ) )
+ {
+ o_allRepairsUsed = true;
+ io_sc.service_data->setSignature( i_chip->getHuid(),
+ PRDFSIG_VcmBadSpare );
+ break; // Nothing more to do.
+ }
+
+ // Certain DIMMs may have had spares intentially made unavailable by
+ // the manufacturer. Check the VPD for available spares.
+ bool spAvail, eccAvail;
+ o_rc = isSpareAvailable<TYPE_MBA>( i_chip->getTrgt(), i_rank, ps,
+ spAvail, eccAvail );
+ if ( spAvail )
+ {
+ // A spare DRAM is available.
+ o_dsdEvent = new DsdEvent<TYPE_MBA>{ i_chip, i_rank,
+ i_chipMark };
+ }
+ else if ( eccAvail )
+ {
+ // The ECC spare is available.
+ o_dsdEvent = new DsdEvent<TYPE_MBA>{ i_chip, i_rank,
+ i_chipMark, true };
+ }
+ else
+ {
+ // Chip mark is in place and sparing is not possible.
+ o_allRepairsUsed = true;
+ io_sc.service_data->setSignature( i_chip->getHuid(),
+ PRDFSIG_AllDramRepairs );
+ }
+ }
+ // There is no DRAM sparing so simply check if both the chip and symbol
+ // mark have been used.
+ else if ( i_chipMark.isValid() && i_symMark.isValid() )
+ {
+ o_allRepairsUsed = true;
+ io_sc.service_data->setSignature( i_chip->getHuid(),
+ PRDFSIG_AllDramRepairs );
+ }
+
+ } while (0);
+ */
+
+ return o_rc;
+
+ #undef PRDF_FUNC
+}
+
//------------------------------------------------------------------------------
template<TARGETING::TYPE T>
@@ -1290,7 +1620,16 @@ uint32_t chipMarkCleanup( ExtensibleChip * i_chip, const MemRank & i_rank,
// Set the chip mark in the DRAM Repairs VPD.
if ( !areDramRepairsDisabled() )
{
- o_rc = setDramInVpd( i_chip, i_rank, chipMark.getSymbol() );
+ if ( TYPE_OCMB_CHIP == i_chip->getType() )
+ {
+ ExtensibleChip * memPort = getConnectedChild( i_chip,
+ TYPE_MEM_PORT, chipMark.getSymbol().getPortSlct() );
+ o_rc = setDramInVpd( memPort, i_rank, chipMark.getSymbol() );
+ }
+ else
+ {
+ o_rc = setDramInVpd( i_chip, i_rank, chipMark.getSymbol() );
+ }
if ( SUCCESS != o_rc )
{
PRDF_ERR( PRDF_FUNC "setDramInVpd(0x%08x,0x%02x) failed",
@@ -1314,6 +1653,10 @@ template
uint32_t chipMarkCleanup<TYPE_MBA>( ExtensibleChip * i_chip,
const MemRank & i_rank,
STEP_CODE_DATA_STRUCT & io_sc );
+template
+uint32_t chipMarkCleanup<TYPE_OCMB_CHIP>( ExtensibleChip * i_chip,
+ const MemRank & i_rank,
+ STEP_CODE_DATA_STRUCT & io_sc );
#endif // not supported on FSP
diff --git a/src/usr/diag/prdf/common/plat/mem/prdfOcmbDataBundle.H b/src/usr/diag/prdf/common/plat/mem/prdfOcmbDataBundle.H
new file mode 100644
index 000000000..d10c56755
--- /dev/null
+++ b/src/usr/diag/prdf/common/plat/mem/prdfOcmbDataBundle.H
@@ -0,0 +1,217 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/usr/diag/prdf/common/plat/mem/prdfOcmbDataBundle.H $ */
+/* */
+/* OpenPOWER HostBoot Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 2019 */
+/* [+] 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 __prdfOcmbDataBundle_H
+#define __prdfOcmbDataBundle_H
+
+/** @file prdfOcmbDataBundle.H
+ * @brief Contains the data bundle for a P9 OCMB_CHIP object.
+ */
+
+// Framework includes
+#include <prdfExtensibleChip.H>
+
+// Platform includes
+#include <prdfPlatServices.H>
+
+#ifdef __HOSTBOOT_MODULE
+
+#include <prdfMemTdFalseAlarm.H>
+#include <prdfMemTdCtlr.H>
+
+#endif // __HOSTBOOT_MODULE
+
+namespace PRDF
+{
+
+/** @brief P9 OCMB data bundle. */
+class OcmbDataBundle : public DataBundle
+{
+ public: // functions
+
+ /**
+ * @brief Constructor.
+ * @param i_ocmbChip The OCMB chip.
+ */
+ explicit OcmbDataBundle( ExtensibleChip * i_ocmbChip ) :
+ iv_chip(i_ocmbChip), iv_ceTable(i_ocmbChip), iv_ueTable(i_ocmbChip)
+ {}
+
+ /** @brief Destructor. */
+ ~OcmbDataBundle()
+ {
+ #ifdef __HOSTBOOT_MODULE
+ #ifdef __HOSTBOOT_RUNTIME
+ delete iv_vcmFalseAlarmCounter;
+ delete iv_tpsFalseAlarmCounter;
+ #else // IPL only
+ delete iv_iplCeStats;
+ #endif
+ delete iv_tdCtlr; iv_tdCtlr = nullptr;
+ #endif // __HOSTBOOT_MODULE
+ }
+
+ // Don't allow copy or assignment.
+ OcmbDataBundle( const OcmbDataBundle & ) = delete;
+ const OcmbDataBundle & operator=( const OcmbDataBundle & ) = delete;
+
+ #ifdef __HOSTBOOT_MODULE
+
+ /** @return The Targeted Diagnostics controller. */
+ MemTdCtlr<TARGETING::TYPE_OCMB_CHIP> * getTdCtlr()
+ {
+ if ( nullptr == iv_tdCtlr )
+ {
+ iv_tdCtlr = new MemTdCtlr<TARGETING::TYPE_OCMB_CHIP>{iv_chip};
+ }
+
+ return iv_tdCtlr;
+ }
+
+ /** @return The IMPE threshold counter. */
+ VcmFalseAlarm * getImpeThresholdCounter()
+ {
+ if ( nullptr == iv_impeThresholdCounter )
+ {
+ iv_impeThresholdCounter = new VcmFalseAlarm(
+ TimeBasedThreshold { getImpeTh() } );
+ }
+
+ return iv_impeThresholdCounter;
+ }
+
+ #ifdef __HOSTBOOT_RUNTIME
+
+ /** @return The VCM false alarm counter. */
+ VcmFalseAlarm * getVcmFalseAlarmCounter()
+ {
+ if ( nullptr == iv_vcmFalseAlarmCounter )
+ {
+ iv_vcmFalseAlarmCounter = new VcmFalseAlarm(
+ TimeBasedThreshold { 4, ThresholdResolution::ONE_DAY } );
+ }
+
+ return iv_vcmFalseAlarmCounter;
+ }
+
+ /** @return The TPS false alarm counter. */
+ TpsFalseAlarm * getTpsFalseAlarmCounter()
+ {
+ if ( nullptr == iv_tpsFalseAlarmCounter )
+ {
+ iv_tpsFalseAlarmCounter = new TpsFalseAlarm(
+ TimeBasedThreshold{ 3, ThresholdResolution::ONE_DAY } );
+ }
+
+ return iv_tpsFalseAlarmCounter;
+ }
+
+ #else // IPL only
+
+ /** @return The IPL CE statistics object. */
+ MemIplCeStats<TARGETING::TYPE_OCMB_CHIP> * getIplCeStats()
+ {
+ if ( nullptr == iv_iplCeStats )
+ {
+ iv_iplCeStats =
+ new MemIplCeStats<TARGETING::TYPE_OCMB_CHIP>( iv_chip );
+ }
+
+ return iv_iplCeStats;
+ }
+
+ #endif
+
+ #endif // __HOSTBOOT_MODULE
+
+ private: // instance variables
+
+ /** The OCMB chip associated with this data bundle. */
+ ExtensibleChip * const iv_chip;
+
+ #ifdef __HOSTBOOT_MODULE
+
+ /** The Targeted Diagnostics controller. */
+ MemTdCtlr<TARGETING::TYPE_OCMB_CHIP> * iv_tdCtlr = nullptr;
+
+ /** IMPE threshold counter. */
+ VcmFalseAlarm * iv_impeThresholdCounter = nullptr;
+
+ #endif // __HOSTBOOT_MODULE
+
+ public: // instance variables
+
+ MemCeTable<TARGETING::TYPE_OCMB_CHIP> iv_ceTable; ///< CE table for FFDC
+ MemUeTable iv_ueTable; ///< UE table for FFDC
+
+ #ifdef __HOSTBOOT_MODULE
+
+ /** Threshold table for RCD parity errors. */
+ TimeBasedThreshold iv_rcdParityTh = TimeBasedThreshold( getRcdParityTh() );
+
+ /** Threshold table for IUEs. Threshold per DIMM */
+ std::map<uint8_t, TimeBasedThreshold> iv_iueTh;
+
+ /** Bool to indicate if we've triggered a port fail because of IUEs. */
+ bool iv_iuePortFail = false;
+
+ #ifdef __HOSTBOOT_RUNTIME
+
+ /** VCM false alarm counter. */
+ VcmFalseAlarm * iv_vcmFalseAlarmCounter = nullptr;
+
+ /** TPS false alarm counter. */
+ TpsFalseAlarm * iv_tpsFalseAlarmCounter = nullptr;
+
+ /** Set to true if mainline NCEs and TCEs should be permanently masked. This
+ * is checked at the end of targeted diagnostics before background
+ * scrubbing is resumed. */
+ bool iv_maskMainlineNceTce = false;
+
+ #else // IPL only
+
+ /** MNFG IPL CE statistics. */
+ MemIplCeStats<TARGETING::TYPE_OCMB_CHIP> * iv_iplCeStats = nullptr;
+
+ #endif
+
+ #endif // __HOSTBOOT_MODULE
+
+};
+
+/**
+ * @brief Wrapper function for the OcmbDataBundle.
+ * @param i_ocmbChip The OCMB chip.
+ * @return This MBA's data bundle.
+ */
+inline OcmbDataBundle * getOcmbDataBundle( ExtensibleChip * i_ocmbChip )
+{
+ return static_cast<OcmbDataBundle *>(i_ocmbChip->getDataBundle());
+}
+
+} // end namespace PRDF
+
+#endif // __prdfOcmbDataBundle_H
+
diff --git a/src/usr/diag/prdf/common/plat/prdfPlatServices_common.C b/src/usr/diag/prdf/common/plat/prdfPlatServices_common.C
index 1b10aa4a0..39040c5de 100644
--- a/src/usr/diag/prdf/common/plat/prdfPlatServices_common.C
+++ b/src/usr/diag/prdf/common/plat/prdfPlatServices_common.C
@@ -1122,6 +1122,15 @@ int32_t getDimmSpareConfig<TYPE_MEM_PORT>( TargetHandle_t i_memPort,
}
template<>
+int32_t getDimmSpareConfig<TYPE_OCMB_CHIP>( TargetHandle_t i_ocmb,
+ MemRank i_rank, uint8_t i_ps, uint8_t & o_spareConfig )
+{
+ TargetHandle_t memPort = getConnectedChild( i_ocmb, TYPE_MEM_PORT, i_ps );
+ return getDimmSpareConfig<TYPE_MEM_PORT>( memPort, i_rank, i_ps,
+ o_spareConfig );
+}
+
+template<>
int32_t getDimmSpareConfig<TYPE_MBA>( TargetHandle_t i_mba, MemRank i_rank,
uint8_t i_ps, uint8_t & o_spareConfig )
{
diff --git a/src/usr/diag/prdf/common/plat/prdfTargetServices.C b/src/usr/diag/prdf/common/plat/prdfTargetServices.C
index ba4a79bc6..571f29f83 100755
--- a/src/usr/diag/prdf/common/plat/prdfTargetServices.C
+++ b/src/usr/diag/prdf/common/plat/prdfTargetServices.C
@@ -1626,6 +1626,18 @@ void getMasterRanks<TYPE_MEM_PORT>( TargetHandle_t i_trgt,
__getMasterRanks<TYPE_MEM_PORT>( i_trgt, o_ranks, 0, i_ds );
}
+template<>
+void getMasterRanks<TYPE_OCMB_CHIP>( TargetHandle_t i_trgt,
+ std::vector<MemRank> & o_ranks,
+ uint8_t i_ds )
+{
+ // TODO RTC 210072 - Explorer only has one port, however, multiple ports
+ // will be supported in the future. Updates will need to be made here so we
+ // can get the relevant port.
+ TargetHandle_t memPort = getConnectedChild( i_trgt, TYPE_MEM_PORT, 0 );
+ __getMasterRanks<TYPE_MEM_PORT>( memPort, o_ranks, 0, i_ds );
+}
+
//------------------------------------------------------------------------------
template<TARGETING::TYPE T>
diff --git a/src/usr/diag/prdf/plat/mem/prdfMemDynDealloc.C b/src/usr/diag/prdf/plat/mem/prdfMemDynDealloc.C
index 41b0de3ea..0cf4bfa7c 100644
--- a/src/usr/diag/prdf/plat/mem/prdfMemDynDealloc.C
+++ b/src/usr/diag/prdf/plat/mem/prdfMemDynDealloc.C
@@ -5,7 +5,7 @@
/* */
/* OpenPOWER HostBoot Project */
/* */
-/* Contributors Listed Below - COPYRIGHT 2017,2018 */
+/* Contributors Listed Below - COPYRIGHT 2017,2019 */
/* [+] International Business Machines Corp. */
/* */
/* */
@@ -474,6 +474,104 @@ int32_t __getPortAddr<TYPE_MCA>( ExtensibleChip * i_chip, MemAddr i_addr,
}
template <>
+int32_t __getPortAddr<TYPE_OCMB_CHIP>( ExtensibleChip * i_chip, MemAddr i_addr,
+ uint64_t & o_addr )
+{
+ int32_t o_rc = SUCCESS;
+
+ o_addr = 0;
+ // TODO RTC 198756
+ // Local vars for address fields
+ uint64_t col = reverseBits(i_addr.getCol(), 7); // C9 C8 C7 C6 C5 C4 C3
+ uint64_t row = reverseBits(i_addr.getRow(), 18); // R17 R16 R15 .. R1 R0
+ uint64_t bnk = i_addr.getBank(); // BG0 BG1 B0 B1 B2
+ uint64_t srnk = i_addr.getRank().getSlave(); // S0 S1 S2
+ uint64_t mrnk = i_addr.getRank().getRankSlct(); // M0 M1
+ uint64_t dslct = i_addr.getRank().getDimmSlct(); // D
+
+ // Determine if a two DIMM config is used. Also, determine how many
+ // mrank (M0-M1), srnk (S0-S2), or extra row (R17-R15) bits are used.
+ bool twoDimmConfig;
+ uint8_t mrnkBits, srnkBits, extraRowBits;
+ o_rc = __getAddrConfig( i_chip, dslct, twoDimmConfig, mrnkBits, srnkBits,
+ extraRowBits );
+ if ( SUCCESS != o_rc ) return o_rc;
+
+ // Mask off the non-configured bits. If this address came from hardware,
+ // this would not be a problem. However, the get_mrank_range() and
+ // get_srank_range() HWPS got lazy just set the entire fields and did not
+ // take into account the actual bit ranges.
+ mrnk = __maskBits( mrnk, mrnkBits );
+ srnk = __maskBits( srnk, srnkBits );
+ row = __maskBits( row, 15 + extraRowBits );
+
+ // Combine master and slave ranks.
+ uint64_t rnk = (mrnk << srnkBits) | srnk;
+ uint8_t rnkBits = mrnkBits + srnkBits;
+
+ // Now split the DIMM select and combined rank into components.
+ uint64_t rnk_pt1 = 0, rnk_pt2 = 0, rnk_pt3 = 0;
+ uint8_t rnkBits_pt1 = 0, rnkBits_pt2 = 0, rnkBits_pt3 = 0;
+
+ if ( 0 == rnkBits )
+ {
+ if ( twoDimmConfig ) // The DIMM select goes into part 3.
+ {
+ rnk_pt3 = dslct; rnkBits_pt3 = 1;
+ }
+ }
+ else // At least one master or slave.
+ {
+ // Put the LSB of the combined rank in part 3 and the rest in part 2.
+ rnk_pt3 = rnk & 0x1; rnkBits_pt3 = 1;
+ rnk_pt2 = rnk >> 1; rnkBits_pt2 = rnkBits - 1;
+
+ if ( twoDimmConfig ) // The DIMM select goes into part 1.
+ {
+ rnk_pt1 = dslct; rnkBits_pt1 = 1;
+ }
+ }
+
+ // Split the row into its components.
+ uint64_t r17_r15 = (row & 0x38000) >> 15;
+ uint64_t r14 = (row & 0x04000) >> 14;
+ uint64_t r13 = (row & 0x02000) >> 13;
+ uint64_t r12_r0 = (row & 0x01fff);
+
+ // Split the column into its components.
+ uint64_t c9_c4 = (col & 0x7e) >> 1;
+ uint64_t c3 = (col & 0x01);
+
+ // Split the bank into its components.
+ uint64_t b0 = (bnk & 0x10) >> 4;
+ uint64_t b1 = (bnk & 0x08) >> 3;
+ // NOTE: B2 is not supported on Nimbus.
+ uint64_t bg0_bg1 = (bnk & 0x03);
+
+ // Now start building the flexible part of the address (bits 0-7,23-33).
+ o_addr = (o_addr << rnkBits_pt1 ) | rnk_pt1;
+ o_addr = (o_addr << extraRowBits) | r17_r15;
+ o_addr = (o_addr << rnkBits_pt2 ) | rnk_pt2;
+ o_addr = (o_addr << 6 ) | c9_c4;
+ o_addr = (o_addr << 1 ) | b0;
+ o_addr = (o_addr << rnkBits_pt3 ) | rnk_pt3;
+ o_addr = (o_addr << 1 ) | b1;
+ o_addr = (o_addr << 2 ) | bg0_bg1;
+ o_addr = (o_addr << 1 ) | c3;
+
+ // C2 is in bit 34, but the Nimbus physical address does not contain a C2.
+ // It will be set to 0 for now. Also, bits 35-39 are the rest of the cache
+ // line address, which we do not need. So, that will be set to 0 as well.
+ o_addr <<= 6;
+
+ // Finally, insert R14,R12-R0,R13 into bits 8-22.
+ o_addr = ((o_addr & 0xfffffe0000ull) << 15) | (o_addr & 0x000001ffffull);
+ o_addr |= ((r14 << 14) | (r12_r0 << 1) | r13) << 17;
+
+ return o_rc;
+}
+
+template <>
int32_t __getPortAddr<TYPE_MBA>( ExtensibleChip * i_chip, MemAddr i_addr,
uint64_t & o_addr )
{
@@ -585,6 +683,22 @@ void __getGrpPrms<TYPE_MCA>( ExtensibleChip * i_chip, uint8_t o_portPos,
}
template<>
+void __getGrpPrms<TYPE_OCMB_CHIP>( ExtensibleChip * i_chip, uint8_t o_portPos,
+ SCAN_COMM_REGISTER_CLASS * &o_mcfgp,
+ SCAN_COMM_REGISTER_CLASS * &o_mcfgpm )
+{
+ PRDF_ERR( "__getGrpPrms: Function not supported yet" );
+ /* TODO RTC 198756
+ // Get the connected MCS chip and MCA target position.
+ ExtensibleChip * mcs_chip = getConnectedParent( i_chip, TYPE_MCS );
+ o_portPos = i_chip->getPos() % MAX_MCA_PER_MCS;
+
+ o_mcfgp = mcs_chip->getRegister("MCFGP");
+ o_mcfgpm = mcs_chip->getRegister("MCFGPM");
+ */
+}
+
+template<>
void __getGrpPrms<TYPE_MBA>( ExtensibleChip * i_chip, uint8_t o_portPos,
SCAN_COMM_REGISTER_CLASS * &o_mcfgp,
SCAN_COMM_REGISTER_CLASS * &o_mcfgpm )
@@ -975,6 +1089,7 @@ int32_t page( ExtensibleChip * i_chip, MemAddr i_addr )
}
template int32_t page<TYPE_MCA>( ExtensibleChip * i_chip, MemAddr i_addr );
template int32_t page<TYPE_MBA>( ExtensibleChip * i_chip, MemAddr i_addr );
+template int32_t page<TYPE_OCMB_CHIP>(ExtensibleChip * i_chip, MemAddr i_addr);
//------------------------------------------------------------------------------
diff --git a/src/usr/diag/prdf/plat/mem/prdfMemTdCtlr.C b/src/usr/diag/prdf/plat/mem/prdfMemTdCtlr.C
index f86110458..6dff91e82 100644
--- a/src/usr/diag/prdf/plat/mem/prdfMemTdCtlr.C
+++ b/src/usr/diag/prdf/plat/mem/prdfMemTdCtlr.C
@@ -5,7 +5,7 @@
/* */
/* OpenPOWER HostBoot Project */
/* */
-/* Contributors Listed Below - COPYRIGHT 2016,2018 */
+/* Contributors Listed Below - COPYRIGHT 2016,2019 */
/* [+] International Business Machines Corp. */
/* */
/* */
@@ -248,8 +248,8 @@ uint32_t __analyzeCmdComplete<TYPE_MCBIST>( ExtensibleChip * i_chip,
do
{
// Get all ports in which the command was run.
- std::vector<ExtensibleChip *> portList;
- o_rc = getMcbistMaintPort( i_chip, portList );
+ ExtensibleChipList portList;
+ o_rc = getMcbistMaintPort<TYPE_MCBIST>( i_chip, portList );
if ( SUCCESS != o_rc )
{
PRDF_ERR( PRDF_FUNC "getMcbistMaintPort(0x%08x) failed",
@@ -291,6 +291,60 @@ uint32_t __analyzeCmdComplete<TYPE_MCBIST>( ExtensibleChip * i_chip,
}
template<>
+uint32_t __analyzeCmdComplete<TYPE_OCMB_CHIP>( ExtensibleChip * i_chip,
+ TdRankListEntry & o_stoppedRank,
+ const MemAddr & i_addr,
+ bool & o_errorsFound,
+ STEP_CODE_DATA_STRUCT & io_sc )
+{
+ #define PRDF_FUNC "[__analyzeCmdComplete] "
+
+ uint32_t o_rc = SUCCESS;
+
+ o_errorsFound = false;
+
+ do
+ {
+ // Get all ports in which the command was run.
+ ExtensibleChipList portList;
+ o_rc = getMcbistMaintPort<TYPE_OCMB_CHIP>( i_chip, portList );
+ if ( SUCCESS != o_rc )
+ {
+ PRDF_ERR( PRDF_FUNC "getMcbistMaintPort(0x%08x) failed",
+ i_chip->getHuid() );
+ break;
+ }
+
+ // In broadcast mode, the rank configuration for all ports will be the
+ // same. In non-broadcast mode, there will only be one MEM_PORT in
+ // the list. Therefore, we can simply use the first MEM_PORT in the
+ // list for all configs.
+ ExtensibleChip * stopChip = portList.front();
+
+ // Update iv_stoppedRank.
+ o_stoppedRank = __getStopRank<TYPE_MEM_PORT>( stopChip, i_addr );
+
+ // Check the OCMB for ECC errors.
+ bool errorsFound;
+ o_rc = __checkEcc<TYPE_OCMB_CHIP>( i_chip, i_addr, errorsFound, io_sc );
+ if ( SUCCESS != o_rc )
+ {
+ PRDF_ERR( PRDF_FUNC "__checkEcc<TYPE_OCMB_CHIP>(0x%08x) failed",
+ i_chip->getHuid() );
+ o_rc |= o_rc;
+ break;
+ }
+
+ if ( errorsFound ) o_errorsFound = true;
+ if ( SUCCESS != o_rc ) break;
+ } while (0);
+
+ return o_rc;
+
+ #undef PRDF_FUNC
+}
+
+template<>
uint32_t __analyzeCmdComplete<TYPE_MBA>( ExtensibleChip * i_chip,
TdRankListEntry & o_stoppedRank,
const MemAddr & i_addr,
@@ -397,9 +451,15 @@ void MemTdCtlr<T>::collectStateCaptureData( STEP_CODE_DATA_STRUCT & io_sc,
// Get the version to use.
uint8_t version = TD_CTLR_DATA::VERSION_1;
+ bool isNimbus = false;
if ( MODEL_NIMBUS == getChipModel(getMasterProc()) )
{
version = TD_CTLR_DATA::VERSION_2;
+ isNimbus = true;
+ }
+ else if ( MODEL_AXONE == getChipModel(getMasterProc()) )
+ {
+ version = TD_CTLR_DATA::VERSION_2;
}
// Get the IPL state.
@@ -443,6 +503,11 @@ void MemTdCtlr<T>::collectStateCaptureData( STEP_CODE_DATA_STRUCT & io_sc,
if ( TD_CTLR_DATA::VERSION_2 == version )
{
curPort = iv_curProcedure->getChip()->getPos() % MAX_MCA_PER_MCBIST;
+ if ( !isNimbus )
+ {
+ TargetHandle_t portTrgt = iv_curProcedure->getChip()->getTrgt();
+ curPort = portTrgt->getAttr<ATTR_REL_POS>();
+ }
}
}
@@ -475,6 +540,11 @@ void MemTdCtlr<T>::collectStateCaptureData( STEP_CODE_DATA_STRUCT & io_sc,
if ( TD_CTLR_DATA::VERSION_2 == version )
{
itPort = queue[n]->getChip()->getPos() % MAX_MCA_PER_MCBIST;
+ if ( !isNimbus )
+ {
+ TargetHandle_t portTrgt = queue[n]->getChip()->getTrgt();
+ itPort = portTrgt->getAttr<ATTR_REL_POS>();
+ }
}
bsb.setFieldJustify( pos, 3, itMrnk ); pos+=3;
@@ -502,6 +572,7 @@ void MemTdCtlr<T>::collectStateCaptureData( STEP_CODE_DATA_STRUCT & io_sc,
// Avoid linker errors with the template.
template class MemTdCtlr<TYPE_MCBIST>;
template class MemTdCtlr<TYPE_MBA>;
+template class MemTdCtlr<TYPE_OCMB_CHIP>;
//------------------------------------------------------------------------------
diff --git a/src/usr/diag/prdf/plat/mem/prdfMemTdCtlr.H b/src/usr/diag/prdf/plat/mem/prdfMemTdCtlr.H
index 332109b48..f1c072eea 100644
--- a/src/usr/diag/prdf/plat/mem/prdfMemTdCtlr.H
+++ b/src/usr/diag/prdf/plat/mem/prdfMemTdCtlr.H
@@ -5,7 +5,7 @@
/* */
/* OpenPOWER HostBoot Project */
/* */
-/* Contributors Listed Below - COPYRIGHT 2016,2018 */
+/* Contributors Listed Below - COPYRIGHT 2016,2019 */
/* [+] International Business Machines Corp. */
/* */
/* */
@@ -54,14 +54,14 @@ class MemTdCtlr
/**
* @brief Constructor
*
- * This contructor will only be called in the MCBIST or MBA data bundle,
- * which already checks for a valid type.
+ * This contructor will only be called in the MCBIST, MBA, or OCMB data
+ * bundle, which already checks for a valid type.
*
* Need to initialize iv_stoppedRank to a valid entry in iv_rankList. Use
* the last entry in the list so that the 'next' rank is the first entry
* in the list.
*
- * @param i_chip An MCBIST or MBA chip.
+ * @param i_chip An MCBIST, MBA, or OCMB chip.
*/
explicit MemTdCtlr( ExtensibleChip * i_chip ) :
iv_chip( i_chip ), iv_rankList( i_chip ),
@@ -122,7 +122,7 @@ class MemTdCtlr
/**
* @brief Bans TPS on the given rank. Any attempts to add a TPS procedure
* to the queue for this rank will be ignored.
- * @param i_chip MCA or MBA chip.
+ * @param i_chip MCA, MBA, or OCMB chip.
* @param i_rank The target slave rank.
*/
void banTps( ExtensibleChip * i_chip, const MemRank & i_rank )
@@ -302,7 +302,7 @@ class MemTdCtlr
private: // instance variables
- /** An MCBIST or MBA chip associated with this TD controller. */
+ /** An MCBIST, MBA, or OCMB chip associated with this TD controller. */
ExtensibleChip * const iv_chip;
/** The TD queue that contains all of the pending TD procedures. */
diff --git a/src/usr/diag/prdf/plat/mem/prdfMemTdCtlr_ipl.C b/src/usr/diag/prdf/plat/mem/prdfMemTdCtlr_ipl.C
index ea04d2964..401a48042 100644
--- a/src/usr/diag/prdf/plat/mem/prdfMemTdCtlr_ipl.C
+++ b/src/usr/diag/prdf/plat/mem/prdfMemTdCtlr_ipl.C
@@ -5,7 +5,7 @@
/* */
/* OpenPOWER HostBoot Project */
/* */
-/* Contributors Listed Below - COPYRIGHT 2016,2018 */
+/* Contributors Listed Below - COPYRIGHT 2016,2019 */
/* [+] International Business Machines Corp. */
/* */
/* */
@@ -160,6 +160,14 @@ bool __mnfgCeCheck<TYPE_MCA>( uint32_t i_eccAttns )
}
template<> inline
+bool __mnfgCeCheck<TYPE_OCMB_CHIP>( uint32_t i_eccAttns )
+{
+ return ( ( 0 != (i_eccAttns & MAINT_HARD_NCE_ETE) ) &&
+ ( (0 != (i_eccAttns & MAINT_NCE)) ||
+ (0 != (i_eccAttns & MAINT_TCE)) ) );
+}
+
+template<> inline
bool __mnfgCeCheck<TYPE_MBA>( uint32_t i_eccAttns )
{
return ( 0 != (i_eccAttns & MAINT_HARD_NCE_ETE) );
@@ -251,12 +259,18 @@ template
uint32_t __checkEcc<TYPE_MBA>( ExtensibleChip * i_chip,
const MemAddr & i_addr, bool & o_errorsFound,
STEP_CODE_DATA_STRUCT & io_sc );
+template
+uint32_t __checkEcc<TYPE_OCMB_CHIP>( ExtensibleChip * i_chip,
+ const MemAddr & i_addr,
+ bool & o_errorsFound,
+ STEP_CODE_DATA_STRUCT & io_sc );
//------------------------------------------------------------------------------
// Avoid linker errors with the template.
template class MemTdCtlr<TYPE_MCBIST>;
template class MemTdCtlr<TYPE_MBA>;
+template class MemTdCtlr<TYPE_OCMB_CHIP>;
//------------------------------------------------------------------------------
diff --git a/src/usr/diag/prdf/plat/mem/prdfMemTdCtlr_rt.C b/src/usr/diag/prdf/plat/mem/prdfMemTdCtlr_rt.C
index d52ef2d1d..356b5b530 100644
--- a/src/usr/diag/prdf/plat/mem/prdfMemTdCtlr_rt.C
+++ b/src/usr/diag/prdf/plat/mem/prdfMemTdCtlr_rt.C
@@ -107,6 +107,36 @@ void __recaptureRegs<TYPE_MCBIST>( STEP_CODE_DATA_STRUCT & io_sc,
}
template<>
+void __recaptureRegs<TYPE_OCMB_CHIP>( STEP_CODE_DATA_STRUCT & io_sc,
+ ExtensibleChip * i_chip )
+{
+ #define PRDF_FUNC "[__recaptureRegs<TYPE_OCMB_CHIP>] "
+
+ RegDataCache & cache = RegDataCache::getCachedRegisters();
+ CaptureData & cd = io_sc.service_data->GetCaptureData();
+
+ // refresh and recapture the ocmb registers
+ const char * ocmbRegs[] =
+ {
+ "MCBISTFIR", "RDFFIR", "MBSEC0", "MBSEC1", "OCMB_MBSSYMEC0",
+ "OCMB_MBSSYMEC1", "OCMB_MBSSYMEC2", "OCMB_MBSSYMEC3",
+ "OCMB_MBSSYMEC4", "OCMB_MBSSYMEC5", "OCMB_MBSSYMEC6",
+ "OCMB_MBSSYMEC7", "OCMB_MBSSYMEC8", "MBSMSEC", "MCBMCAT",
+ };
+
+ for ( uint32_t i = 0; i < sizeof(ocmbRegs)/sizeof(char*); i++ )
+ {
+ SCAN_COMM_REGISTER_CLASS * reg =
+ i_chip->getRegister( ocmbRegs[i] );
+ cache.flush( i_chip, reg );
+ }
+
+ i_chip->CaptureErrorData( cd, Util::hashString("MaintCmdRegs_ocmb") );
+
+ #undef PRDF_FUNC
+}
+
+template<>
void __recaptureRegs<TYPE_MBA>( STEP_CODE_DATA_STRUCT & io_sc,
ExtensibleChip * i_chip )
{
@@ -358,8 +388,9 @@ uint32_t __handleNceEte( ExtensibleChip * i_chip,
uint32_t count = symData.size();
switch ( T )
{
- case TYPE_MCA: PRDF_ASSERT( 1 <= count && count <= 2 ); break;
- case TYPE_MBA: PRDF_ASSERT( 1 == count ); break;
+ case TYPE_MCA: PRDF_ASSERT( 1 <= count && count <= 2 ); break;
+ case TYPE_MBA: PRDF_ASSERT( 1 == count ); break;
+ case TYPE_OCMB_CHIP: PRDF_ASSERT( 1 <= count && count <= 2 ); break;
default: PRDF_ASSERT( false );
}
@@ -408,6 +439,14 @@ uint32_t __handleSoftInterCeEte<TYPE_MCA>( ExtensibleChip * i_chip,
}
template<>
+uint32_t __handleSoftInterCeEte<TYPE_OCMB_CHIP>( ExtensibleChip * i_chip,
+ const MemAddr & i_addr,
+ STEP_CODE_DATA_STRUCT & io_sc )
+{
+ return __handleNceEte<TYPE_OCMB_CHIP>( i_chip, i_addr, io_sc );
+}
+
+template<>
uint32_t __handleSoftInterCeEte<TYPE_MBA>( ExtensibleChip * i_chip,
const MemAddr & i_addr,
STEP_CODE_DATA_STRUCT & io_sc )
@@ -480,6 +519,52 @@ uint32_t __handleRceEte<TYPE_MCA>( ExtensibleChip * i_chip,
}
template<>
+uint32_t __handleRceEte<TYPE_OCMB_CHIP>( ExtensibleChip * i_chip,
+ const MemRank & i_rank,
+ bool & o_errorsFound,
+ STEP_CODE_DATA_STRUCT & io_sc )
+{
+ #define PRDF_FUNC "[__handleRceEte] "
+
+ uint32_t o_rc = SUCCESS;
+
+ // Should only get this attention in MNFG mode.
+ PRDF_ASSERT( mfgMode() );
+
+ do
+ {
+ // The RCE ETE attention could be from IUE, IMPE, or IRCD. Need to check
+ // RDFFIR[37] to determine if there was at least one IUE.
+ SCAN_COMM_REGISTER_CLASS * fir = i_chip->getRegister( "RDFFIR" );
+ o_rc = fir->Read();
+ if ( SUCCESS != o_rc )
+ {
+ PRDF_ERR( PRDF_FUNC "Read() failed on RDFFIR: i_chip=0x%08x",
+ i_chip->getHuid() );
+ break;
+ }
+ if ( !fir->IsBitSet(37) ) break; // nothing else to do
+
+ // Handle the IUE.
+ o_errorsFound = true;
+ io_sc.service_data->AddSignatureList( i_chip->getTrgt(),
+ PRDFSIG_MaintIUE );
+ o_rc = MemEcc::handleMemIue<TYPE_OCMB_CHIP>( i_chip, i_rank, io_sc );
+ if ( SUCCESS != o_rc )
+ {
+ PRDF_ERR( PRDF_FUNC "analyzeMaintIue(0x%08x) failed",
+ i_chip->getHuid() );
+ break;
+ }
+
+ } while (0);
+
+ return o_rc;
+
+ #undef PRDF_FUNC
+}
+
+template<>
uint32_t __handleRceEte<TYPE_MBA>( ExtensibleChip * i_chip,
const MemRank & i_rank, bool & o_errorsFound,
STEP_CODE_DATA_STRUCT & io_sc )
@@ -698,6 +783,11 @@ template
uint32_t __checkEcc<TYPE_MBA>( ExtensibleChip * i_chip,
const MemAddr & i_addr, bool & o_errorsFound,
STEP_CODE_DATA_STRUCT & io_sc );
+template
+uint32_t __checkEcc<TYPE_OCMB_CHIP>( ExtensibleChip * i_chip,
+ const MemAddr & i_addr,
+ bool & o_errorsFound,
+ STEP_CODE_DATA_STRUCT & io_sc );
//------------------------------------------------------------------------------
@@ -786,6 +876,76 @@ uint32_t MemTdCtlr<TYPE_MCBIST>::unmaskEccAttns()
//------------------------------------------------------------------------------
template<>
+uint32_t MemTdCtlr<TYPE_OCMB_CHIP>::maskEccAttns()
+{
+ #define PRDF_FUNC "[MemTdCtlr<TYPE_OCMB_CHIP>::maskEccAttns] "
+
+ uint32_t o_rc = SUCCESS;
+
+ SCAN_COMM_REGISTER_CLASS * mask = iv_chip->getRegister( "RDFFIR_MASK_OR" );
+
+ mask->clearAllBits();
+ mask->SetBit(8); // Mainline read NCE
+ mask->SetBit(9); // Mainline read TCE
+
+ o_rc = mask->Write();
+ if ( SUCCESS != o_rc )
+ {
+ PRDF_ERR( PRDF_FUNC "Write() failed on RDFFIR_MASK_OR" );
+ }
+
+ return o_rc;
+
+ #undef PRDF_FUNC
+}
+
+//------------------------------------------------------------------------------
+
+template<>
+uint32_t MemTdCtlr<TYPE_OCMB_CHIP>::unmaskEccAttns()
+{
+ #define PRDF_FUNC "[MemTdCtlr<TYPE_OCMB_CHIP>::unmaskEccAttns] "
+
+ uint32_t o_rc = SUCCESS;
+
+ // Memory CEs were masked at the beginning of the TD procedure, so
+ // clear and unmask them. Also, it is possible that memory UEs have
+ // thresholded so clear and unmask them as well.
+
+ SCAN_COMM_REGISTER_CLASS * fir = iv_chip->getRegister( "RDFFIR_AND" );
+ SCAN_COMM_REGISTER_CLASS * mask = iv_chip->getRegister( "RDFFIR_MASK_AND" );
+
+ fir->setAllBits(); mask->setAllBits();
+
+ // Do not unmask NCE and TCE attentions if they have been permanently
+ // masked due to certain TPS conditions.
+ if ( !(getOcmbDataBundle(iv_chip)->iv_maskMainlineNceTce) )
+ {
+ fir->ClearBit(8); mask->ClearBit(8); // Mainline read NCE
+ fir->ClearBit(9); mask->ClearBit(9); // Mainline read TCE
+ }
+ fir->ClearBit(14); mask->ClearBit(14); // Mainline read UE
+
+ o_rc = fir->Write();
+ if ( SUCCESS != o_rc )
+ {
+ PRDF_ERR( PRDF_FUNC "Write() failed on RDFFIR_AND" );
+ }
+
+ o_rc = mask->Write();
+ if ( SUCCESS != o_rc )
+ {
+ PRDF_ERR( PRDF_FUNC "Write() failed on RDFFIR_MASK_AND" );
+ }
+
+ return o_rc;
+
+ #undef PRDF_FUNC
+}
+
+//------------------------------------------------------------------------------
+
+template<>
uint32_t MemTdCtlr<TYPE_MBA>::maskEccAttns()
{
#define PRDF_FUNC "[MemTdCtlr<TYPE_MBA>::maskEccAttns] "
@@ -887,6 +1047,21 @@ SCAN_COMM_REGISTER_CLASS * __getEccFirAnd<TYPE_MCA>( ExtensibleChip * i_chip )
}
template<>
+SCAN_COMM_REGISTER_CLASS * __getEccFirAnd<TYPE_OCMB_CHIP>(
+ ExtensibleChip * i_chip )
+{
+ return i_chip->getRegister( "RDFFIR_AND" );
+}
+
+template<>
+SCAN_COMM_REGISTER_CLASS * __getEccFirAnd<TYPE_MEM_PORT>(
+ ExtensibleChip * i_chip )
+{
+ ExtensibleChip * ocmbChip = getConnectedParent( i_chip, TYPE_OCMB_CHIP );
+ return ocmbChip->getRegister( "RDFFIR_AND" );
+}
+
+template<>
SCAN_COMM_REGISTER_CLASS * __getEccFirAnd<TYPE_MBA>( ExtensibleChip * i_chip )
{
ExtensibleChip * membChip = getConnectedParent( i_chip, TYPE_MEMBUF );
@@ -969,6 +1144,85 @@ uint32_t __findChipMarks( TdRankList<TC> & i_rankList )
#undef PRDF_FUNC
}
+template <>
+uint32_t __findChipMarks<TYPE_MEM_PORT>(
+ TdRankList<TYPE_OCMB_CHIP> & i_rankList )
+{
+ #define PRDF_FUNC "[__findChipMarks] "
+
+ uint32_t o_rc = SUCCESS;
+
+ for ( auto & entry : i_rankList.getList() )
+ {
+ ExtensibleChip * memPort = entry.getChip();
+ MemRank rank = entry.getRank();
+
+ ExtensibleChip * ocmb = getConnectedParent( memPort, TYPE_OCMB_CHIP );
+
+ // Call readChipMark to get MemMark.
+ MemMark chipMark;
+ o_rc = MarkStore::readChipMark<TYPE_OCMB_CHIP>( ocmb, rank, chipMark );
+ if ( SUCCESS != o_rc )
+ {
+ PRDF_ERR( PRDF_FUNC "readChipMark(0x%08x,0x%02x) failed",
+ ocmb->getHuid(), rank.getKey() );
+ break;
+ }
+
+ if ( !chipMark.isValid() ) continue; // no chip mark present
+
+ // Get the DQ Bitmap data.
+ MemDqBitmap dqBitmap;
+ o_rc = getBadDqBitmap( memPort->getTrgt(), rank, dqBitmap );
+ if ( SUCCESS != o_rc )
+ {
+ PRDF_ERR( PRDF_FUNC "getBadDqBitmap(0x%08x,0x%02x)",
+ memPort->getHuid(), rank.getKey() );
+ break;
+ }
+
+ // Check if the chip mark is verified or not.
+ bool cmVerified = false;
+ o_rc = dqBitmap.isChipMark( chipMark.getSymbol(), cmVerified );
+ if ( SUCCESS != o_rc )
+ {
+ PRDF_ERR( PRDF_FUNC "dqBitmap.isChipMark() failed on 0x%08x "
+ "0x%02x", memPort->getHuid(), rank.getKey() );
+ break;
+ }
+
+ // If the chip mark is unverified, add a VcmEvent to the TD queue.
+ if ( !cmVerified )
+ {
+ // Chip mark is not present in VPD. Add it to queue.
+ TdEntry * e = new VcmEvent<TYPE_OCMB_CHIP>{ ocmb, rank, chipMark };
+ MemDbUtils::pushToQueue<TYPE_OCMB_CHIP>( ocmb, e );
+
+ // We will want to clear the MPE attention for the unverified chip
+ // mark so we don't get any redundant attentions for chip marks that
+ // are already in the queue. This is reset/reload safe because
+ // initialize() will be called again and we can redetect the
+ // unverified chip marks.
+ SCAN_COMM_REGISTER_CLASS* reg =__getEccFirAnd<TYPE_OCMB_CHIP>(ocmb);
+ reg->setAllBits();
+ reg->ClearBit( 0 + rank.getMaster() ); // fetch
+ reg->ClearBit( 20 + rank.getMaster() ); // scrub
+ o_rc = reg->Write();
+ if ( SUCCESS != o_rc )
+ {
+ PRDF_ERR( PRDF_FUNC "Write() failed on ECC FIR AND: 0x%08x",
+ ocmb->getHuid() );
+ break;
+ }
+ }
+ }
+
+ return o_rc;
+
+ #undef PRDF_FUNC
+}
+
+
template<>
uint32_t MemTdCtlr<TYPE_MCBIST>::initialize()
{
@@ -1009,6 +1263,45 @@ uint32_t MemTdCtlr<TYPE_MCBIST>::initialize()
}
template<>
+uint32_t MemTdCtlr<TYPE_OCMB_CHIP>::initialize()
+{
+ #define PRDF_FUNC "[MemTdCtlr<TYPE_OCMB_CHIP>::initialize] "
+
+ uint32_t o_rc = SUCCESS;
+
+ do
+ {
+ if ( iv_initialized ) break; // nothing to do
+
+ // Unmask the fetch attentions just in case there were masked during a
+ // TD procedure prior to a reset/reload.
+ o_rc = unmaskEccAttns();
+ if ( SUCCESS != o_rc )
+ {
+ PRDF_ERR( PRDF_FUNC "unmaskEccAttns() failed" );
+ break;
+ }
+
+ // Find all unverified chip marks.
+ o_rc = __findChipMarks<TYPE_MEM_PORT>( iv_rankList );
+ if ( SUCCESS != o_rc )
+ {
+ PRDF_ERR( PRDF_FUNC "__findChipMarks() failed on 0x%08x",
+ iv_chip->getHuid() );
+ break;
+ }
+
+ // At this point, the TD controller is initialized.
+ iv_initialized = true;
+
+ } while (0);
+
+ return o_rc;
+
+ #undef PRDF_FUNC
+}
+
+template<>
uint32_t MemTdCtlr<TYPE_MBA>::initialize()
{
#define PRDF_FUNC "[MemTdCtlr<TYPE_MBA>::initialize] "
@@ -1162,6 +1455,119 @@ uint32_t MemTdCtlr<TYPE_MCBIST>::handleRrFo()
//------------------------------------------------------------------------------
template<>
+uint32_t MemTdCtlr<TYPE_OCMB_CHIP>::handleRrFo()
+{
+ #define PRDF_FUNC "[MemTdCtlr<TYPE_OCMB_CHIP>::handleRrFo] "
+
+ uint32_t o_rc = SUCCESS;
+
+ do
+ {
+ // Check if maintenance command complete attention is set.
+ SCAN_COMM_REGISTER_CLASS * mcbistfir =
+ iv_chip->getRegister("MCBISTFIR");
+ o_rc = mcbistfir->Read();
+ if ( SUCCESS != o_rc )
+ {
+ PRDF_ERR( PRDF_FUNC "Read() failed on MCBISTFIR");
+ break;
+ }
+
+ // If there is a command complete attention, nothing to do, break out.
+ if ( mcbistfir->IsBitSet(10) )
+ break;
+
+
+ // Check if a command is not running.
+ // If bit 0 of MCB_CNTLSTAT is on, a mcbist run is in progress.
+ SCAN_COMM_REGISTER_CLASS * mcb_cntlstat =
+ iv_chip->getRegister("MCB_CNTLSTAT");
+ o_rc = mcb_cntlstat->Read();
+ if ( SUCCESS != o_rc )
+ {
+ PRDF_ERR( PRDF_FUNC "Read() failed on MCB_CNTLSTAT" );
+ break;
+ }
+
+ // If a command is not running, set command complete attn, break.
+ if ( !mcb_cntlstat->IsBitSet(0) )
+ {
+ SCAN_COMM_REGISTER_CLASS * mcbistfir_or =
+ iv_chip->getRegister("MCBISTFIR_OR");
+ mcbistfir_or->SetBit( 10 );
+
+ mcbistfir_or->Write();
+ if ( SUCCESS != o_rc )
+ {
+ PRDF_ERR( PRDF_FUNC "Write() failed on MCBISTFIR_OR" );
+ }
+ break;
+ }
+
+ // Check if there are unverified chip marks.
+ std::vector<TdRankListEntry> vectorList = iv_rankList.getList();
+
+ for ( auto & entry : vectorList )
+ {
+ ExtensibleChip * memPortChip = entry.getChip();
+ MemRank rank = entry.getRank();
+
+ // Get the chip mark
+ MemMark chipMark;
+ o_rc = MarkStore::readChipMark<TYPE_MEM_PORT>( memPortChip, rank,
+ chipMark );
+ if ( SUCCESS != o_rc )
+ {
+ PRDF_ERR( PRDF_FUNC "readChipMark<TYPE_MEM_PORT>(0x%08x,%d) "
+ "failed", memPortChip->getHuid(), rank.getMaster() );
+ break;
+ }
+
+ if ( !chipMark.isValid() ) continue; // no chip mark present
+
+ // Get the DQ Bitmap data.
+ TargetHandle_t memPortTrgt = memPortChip->GetChipHandle();
+ MemDqBitmap dqBitmap;
+
+ o_rc = getBadDqBitmap( memPortTrgt, rank, dqBitmap );
+ if ( SUCCESS != o_rc )
+ {
+ PRDF_ERR( PRDF_FUNC "getBadDqBitmap(0x%08x, %d)",
+ getHuid(memPortTrgt), rank.getMaster() );
+ break;
+ }
+
+ // Check if the chip mark is verified or not.
+ bool cmVerified = false;
+ o_rc = dqBitmap.isChipMark( chipMark.getSymbol(), cmVerified );
+ if ( SUCCESS != o_rc )
+ {
+ PRDF_ERR( PRDF_FUNC "dqBitmap.isChipMark failed." );
+ break;
+ }
+
+ // If there are any unverified chip marks, stop the command, break.
+ if ( !cmVerified )
+ {
+ o_rc = stopBgScrub<TYPE_OCMB_CHIP>( iv_chip );
+ if ( SUCCESS != o_rc )
+ {
+ PRDF_ERR( PRDF_FUNC "stopBgScrub<TYPE_OCMB_CHIP>(0x%08x) "
+ "failed", iv_chip->getHuid() );
+ }
+ break;
+ }
+ }
+
+ } while (0);
+
+ return o_rc;
+ #undef PRDF_FUNC
+}
+
+//------------------------------------------------------------------------------
+
+template<>
uint32_t MemTdCtlr<TYPE_MBA>::handleRrFo()
{
#define PRDF_FUNC "[MemTdCtlr<TYPE_MBA>::handleRrFo] "
@@ -1327,6 +1733,44 @@ uint32_t MemTdCtlr<TYPE_MCBIST>::canResumeBgScrub( bool & o_canResume )
}
template<>
+uint32_t MemTdCtlr<TYPE_OCMB_CHIP>::canResumeBgScrub( bool & o_canResume )
+{
+ #define PRDF_FUNC "[MemTdCtlr<TYPE_OCMB_CHIP>::canResumeBgScrub] "
+
+ uint32_t o_rc = SUCCESS;
+
+ o_canResume = false;
+
+ // It is possible that we were running a TD procedure and the PRD service
+ // was reset. Therefore, we must check if background scrubbing was actually
+ // configured. There really is not a good way of doing this. A scrub command
+ // is a scrub command the only difference is the speed. Unfortunately, that
+ // speed can change depending on how the hardware team tunes it. For now, we
+ // can use the stop conditions, which should be unique for background scrub,
+ // to determine if it has been configured.
+
+ SCAN_COMM_REGISTER_CLASS * reg = iv_chip->getRegister( "MBSTR" );
+ o_rc = reg->Read();
+ if ( SUCCESS != o_rc )
+ {
+ PRDF_ERR( PRDF_FUNC "Read() failed on MBSTR: iv_chip=0x%08x",
+ iv_chip->getHuid() );
+ }
+ else if ( 0xf != reg->GetBitFieldJustified(0,4) && // NCE int TH
+ 0xf != reg->GetBitFieldJustified(4,4) && // NCE soft TH
+ 0xf != reg->GetBitFieldJustified(8,4) && // NCE hard TH
+ reg->IsBitSet(34) && // pause on MPE
+ reg->IsBitSet(35) ) // pause on UE
+ {
+ o_canResume = true;
+ }
+
+ return o_rc;
+
+ #undef PRDF_FUNC
+}
+
+template<>
uint32_t MemTdCtlr<TYPE_MBA>::canResumeBgScrub( bool & o_canResume )
{
#define PRDF_FUNC "[MemTdCtlr<TYPE_MBA>::canResumeBgScrub] "
@@ -1365,6 +1809,7 @@ uint32_t MemTdCtlr<TYPE_MBA>::canResumeBgScrub( bool & o_canResume )
// Avoid linker errors with the template.
template class MemTdCtlr<TYPE_MCBIST>;
template class MemTdCtlr<TYPE_MBA>;
+template class MemTdCtlr<TYPE_OCMB_CHIP>;
//------------------------------------------------------------------------------
diff --git a/src/usr/diag/prdf/plat/mem/prdfMemTps_ipl.C b/src/usr/diag/prdf/plat/mem/prdfMemTps_ipl.C
index 5fc67afb4..6aaa2702a 100644
--- a/src/usr/diag/prdf/plat/mem/prdfMemTps_ipl.C
+++ b/src/usr/diag/prdf/plat/mem/prdfMemTps_ipl.C
@@ -125,6 +125,12 @@ bool __iueCheck<TYPE_MCA>( uint32_t i_eccAttns )
}
template<> inline
+bool __iueCheck<TYPE_OCMB_CHIP>( uint32_t i_eccAttns )
+{
+ return ( 0 != (i_eccAttns & MAINT_IUE) );
+}
+
+template<> inline
bool __iueCheck<TYPE_MBA>( uint32_t i_eccAttns )
{
// IUES are reported via RCE ETE on Centaur
@@ -289,6 +295,53 @@ uint32_t TpsEvent<TYPE_MCA>::startCmd()
#undef PRDF_FUNC
}
+template<>
+uint32_t TpsEvent<TYPE_OCMB_CHIP>::startCmd()
+{
+ #define PRDF_FUNC "[TpsEvent::startCmd] "
+
+ uint32_t o_rc = SUCCESS;
+
+ PRDF_ERR( PRDF_FUNC "Function not supported yet" );
+ /* TODO RTC 208263
+ // We don't need to set any stop-on-error conditions or thresholds for
+ // soft/inter/hard CEs during Memory Diagnostics. The design is to let the
+ // command continue to the end of the rank and we do diagnostics on the
+ // CE counts found in the per-symbol counters. Therefore, all we need to do
+ // is tell the hardware which CE types to count.
+
+ mss::mcbist::stop_conditions stopCond;
+
+ switch ( iv_phase )
+ {
+ case TD_PHASE_1:
+ // Set the per symbol counters to count only soft/inter CEs.
+ stopCond.set_nce_soft_symbol_count_enable( mss::ON);
+ stopCond.set_nce_inter_symbol_count_enable(mss::ON);
+ break;
+
+ case TD_PHASE_2:
+ // Set the per symbol counters to count only hard CEs.
+ stopCond.set_nce_hard_symbol_count_enable(mss::ON);
+ break;
+
+ default: PRDF_ASSERT( false ); // invalid phase
+ }
+
+ // Start the time based scrub procedure on this slave rank.
+ o_rc = startTdScrub<TYPE_MCA>( iv_chip, iv_rank, SLAVE_RANK, stopCond );
+ if ( SUCCESS != o_rc )
+ {
+ PRDF_ERR( PRDF_FUNC "startTdScrub(0x%08x,0x%2x) failed",
+ iv_chip->getHuid(), getKey() );
+ }
+ */
+
+ return o_rc;
+
+ #undef PRDF_FUNC
+}
+
//##############################################################################
//
// Specializations for MBA
@@ -367,6 +420,7 @@ uint32_t TpsEvent<TYPE_MBA>::startCmd()
// Avoid linker errors with the template.
template class TpsEvent<TYPE_MCA>;
template class TpsEvent<TYPE_MBA>;
+template class TpsEvent<TYPE_OCMB_CHIP>;
//------------------------------------------------------------------------------
diff --git a/src/usr/diag/prdf/plat/mem/prdfMemTps_rt.C b/src/usr/diag/prdf/plat/mem/prdfMemTps_rt.C
index 635bd0361..e5b3ef74f 100644
--- a/src/usr/diag/prdf/plat/mem/prdfMemTps_rt.C
+++ b/src/usr/diag/prdf/plat/mem/prdfMemTps_rt.C
@@ -66,6 +66,13 @@ TpsFalseAlarm * __getTpsFalseAlarmCounter<TYPE_MCA>( ExtensibleChip * i_chip )
}
template<>
+TpsFalseAlarm * __getTpsFalseAlarmCounter<TYPE_OCMB_CHIP>(
+ ExtensibleChip * i_chip )
+{
+ return getOcmbDataBundle(i_chip)->getTpsFalseAlarmCounter();
+}
+
+template<>
TpsFalseAlarm * __getTpsFalseAlarmCounter<TYPE_MBA>( ExtensibleChip * i_chip )
{
return getMbaDataBundle(i_chip)->getTpsFalseAlarmCounter();
@@ -138,6 +145,45 @@ bool __badDqCount<TYPE_MCA>( MemUtils::MaintSymbols i_nibbleStats,
return badDqFound;
}
+template<>
+bool __badDqCount<TYPE_OCMB_CHIP>( MemUtils::MaintSymbols i_nibbleStats,
+ CeCount & io_badDqCount )
+{
+ bool badDqFound = false;
+
+ PRDF_ERR( "__badDqCount: Function not supported yet" );
+ /* TODO RTC 208263
+ for ( auto symData : i_nibbleStats )
+ {
+ // If one of the four symbols has a count of at least 8.
+ if ( symData.count >= 8 )
+ {
+ // And the sum of the other three symbols is 1 or less.
+ uint8_t sum = 0;
+ for ( auto sumCheck : i_nibbleStats)
+ {
+ if ( !(symData.symbol == sumCheck.symbol) )
+ {
+ // Check for overflow.
+ if ( (sum + sumCheck.count) > 0xFF )
+ sum = 0xFF;
+ else
+ sum += sumCheck.count;
+ }
+ }
+ if ( sum <= 1 )
+ {
+ io_badDqCount.count++;
+ io_badDqCount.symList.push_back(symData);
+ badDqFound = true;
+ break;
+ }
+ }
+ }
+ */
+
+ return badDqFound;
+}
//------------------------------------------------------------------------------
template<TARGETING::TYPE T>
@@ -187,6 +233,53 @@ bool __badChipCount<TYPE_MCA>( MemUtils::MaintSymbols i_nibbleStats,
return badChipFound;
}
+template<>
+bool __badChipCount<TYPE_OCMB_CHIP>( MemUtils::MaintSymbols i_nibbleStats,
+ CeCount & io_badChipCount )
+{
+ bool badChipFound = false;
+
+ PRDF_ERR( "__badChipCount: Function not supported yet" );
+ /* TODO RTC 208263
+ uint8_t nonZeroCount = 0;
+ uint8_t minCountTwo = 0;
+ uint8_t sum = 0;
+ MemUtils::SymbolData highSym;
+
+ for ( auto symData : i_nibbleStats )
+ {
+ // Check for overflow.
+ if ( (sum + symData.count) > 0xFF )
+ sum = 0xFF;
+ else
+ sum += symData.count;
+
+ if ( symData.count > 0 )
+ nonZeroCount++;
+ if ( symData.count >= 2 )
+ minCountTwo++;
+ if ( symData.count > highSym.count )
+ highSym = symData;
+ }
+
+ // If the total sum for all four symbols has a count of at least 5
+ if ( sum >= 5 )
+ {
+ // And either:
+ // 3 or more symbols have a non-zero value.
+ // or 2 symbols, both with a minimum count of 2.
+ if ( nonZeroCount >= 3 || minCountTwo >= 2 )
+ {
+ io_badChipCount.count++;
+ io_badChipCount.symList.push_back(highSym);
+ badChipFound = true;
+ }
+ }
+ */
+
+ return badChipFound;
+}
+
//------------------------------------------------------------------------------
template<TARGETING::TYPE T>
@@ -222,6 +315,38 @@ void __sumAboveOneCount<TYPE_MCA>( MemUtils::MaintSymbols i_nibbleStats,
}
}
+template<>
+void __sumAboveOneCount<TYPE_OCMB_CHIP>( MemUtils::MaintSymbols i_nibbleStats,
+ CeCount & io_sumAboveOneCount )
+{
+ PRDF_ERR( "__sumAboveOneCount: Function not supported yet" );
+ /* TODO RTC 208263
+ uint8_t sum = 0;
+ MemUtils::MaintSymbols symList;
+ for ( auto symData : i_nibbleStats )
+ {
+ if ( symData.count > 0 )
+ {
+ if ( (sum + symData.count) > 0xFF )
+ sum = 0xFF;
+ else
+ sum += symData.count;
+
+ symList.push_back(symData);
+ }
+ }
+ // If the sum is greater than 1
+ if ( sum > 1 )
+ {
+ io_sumAboveOneCount.count++;
+ for ( auto sym : symList )
+ {
+ io_sumAboveOneCount.symList.push_back(sym);
+ }
+ }
+ */
+}
+
//------------------------------------------------------------------------------
template<TARGETING::TYPE T>
@@ -254,6 +379,35 @@ void __singleSymbolCount<TYPE_MCA>( MemUtils::MaintSymbols i_nibbleStats,
io_singleSymCount.count++;
}
+template<>
+void __singleSymbolCount<TYPE_OCMB_CHIP>( MemUtils::MaintSymbols i_nibbleStats,
+ CeCount & io_singleSymCount )
+{
+ PRDF_ERR( "__singleSymbolCount: Function not supported yet" );
+ /* TODO RTC 208263
+ uint8_t count = 0;
+ bool multNonZeroSyms = false;
+
+ for ( auto symData : i_nibbleStats )
+ {
+ if ( symData.count > 0 )
+ {
+ if ( 0 != count )
+ {
+ // There are more than one symbol counts that are non-zero
+ multNonZeroSyms = true;
+ break;
+ }
+ count = symData.count;
+ }
+ }
+
+ // If there is only one symbol with a non-zero count and that count > 1
+ if ( count > 1 && !multNonZeroSyms )
+ io_singleSymCount.count++;
+ */
+}
+
//------------------------------------------------------------------------------
template<TARGETING::TYPE T>
@@ -421,6 +575,114 @@ uint32_t TpsEvent<TYPE_MCA>::analyzeEccErrors( const uint32_t & i_eccAttns,
//------------------------------------------------------------------------------
+template <>
+uint32_t TpsEvent<TYPE_OCMB_CHIP>::analyzeEccErrors(const uint32_t & i_eccAttns,
+ STEP_CODE_DATA_STRUCT & io_sc,
+ bool & o_done)
+{
+ #define PRDF_FUNC "[TpsEvent<TYPE_OCMB_CHIP>::analyzeEccErrors] "
+
+ uint32_t o_rc = SUCCESS;
+ PRDF_ERR( PRDF_FUNC "Function not supported yet" );
+ /* TODO RTC 208263
+ do
+ {
+ // If there was a UE.
+ if ( i_eccAttns & MAINT_UE )
+ {
+ PRDF_TRAC( PRDF_FUNC "UE Detected: 0x%08x,0x%02x",
+ iv_chip->getHuid(), getKey() );
+
+ io_sc.service_data->setSignature( iv_chip->getHuid(),
+ PRDFSIG_MaintUE );
+
+ // At this point we don't actually have an address for the UE. The
+ // best we can do is get the address in which the command stopped.
+ MemAddr addr;
+ o_rc = getMemMaintAddr<TYPE_MCA>( iv_chip, addr );
+ if ( SUCCESS != o_rc )
+ {
+ PRDF_ERR( PRDF_FUNC "getMemMaintAddr(0x%08x) failed",
+ iv_chip->getHuid() );
+ break;
+ }
+
+ o_rc = MemEcc::handleMemUe<TYPE_MCA>( iv_chip, addr,
+ UE_TABLE::SCRUB_UE, io_sc );
+ if ( SUCCESS != o_rc )
+ {
+ PRDF_ERR( PRDF_FUNC "handleMemUe(0x%08x,0x%02x) failed",
+ iv_chip->getHuid(), getKey() );
+ break;
+ }
+
+ // Because of the UE, any further TPS requests will likely have no
+ // effect. So ban all subsequent requests.
+ MemDbUtils::banTps<TYPE_MCA>( iv_chip, addr.getRank() );
+
+ // Abort this procedure because additional repairs will likely
+ // not help (also avoids complication of having UE and MPE at
+ // the same time).
+ o_done = true; break;
+ }
+
+ // If there was an IUE (MNFG only).
+ if ( mfgMode() && (i_eccAttns & MAINT_IUE) )
+ {
+ io_sc.service_data->setSignature( iv_chip->getHuid(),
+ PRDFSIG_MaintIUE );
+
+ o_rc = MemEcc::handleMemIue<TYPE_MCA>( iv_chip, iv_rank, io_sc );
+ if ( SUCCESS != o_rc )
+ {
+ PRDF_ERR( PRDF_FUNC "handleMemIue(0x%08x,0x%02x) failed",
+ iv_chip->getHuid(), getKey() );
+ break;
+ }
+
+ // If service call is set, then IUE threshold was reached.
+ if ( io_sc.service_data->queryServiceCall() )
+ {
+ PRDF_TRAC( PRDF_FUNC "IUE threshold detected: 0x%08x,0x%02x",
+ iv_chip->getHuid(), getKey() );
+
+ // Abort this procedure because port failure will be triggered
+ // after analysis is complete.
+ o_done = true; break;
+ }
+ }
+
+ // If there was an MPE.
+ if ( i_eccAttns & MAINT_MPE )
+ {
+ io_sc.service_data->setSignature( iv_chip->getHuid(),
+ PRDFSIG_MaintMPE );
+
+ o_rc = MemEcc::handleMpe<TYPE_MCA>( iv_chip, iv_rank,
+ UE_TABLE::SCRUB_MPE, io_sc );
+ if ( SUCCESS != o_rc )
+ {
+ PRDF_ERR( PRDF_FUNC "handleMpe<T>(0x%08x, 0x%02x) failed",
+ iv_chip->getHuid(), iv_rank.getKey() );
+ break;
+ }
+
+ // Abort this procedure because the chip mark may have fixed the
+ // symbol that triggered TPS
+ o_done = true; break;
+ }
+
+ }while(0);
+ */
+
+ return o_rc;
+
+ #undef PRDF_FUNC
+
+}
+
+//------------------------------------------------------------------------------
+
template<>
uint32_t TpsEvent<TYPE_MCA>::handleFalseAlarm( STEP_CODE_DATA_STRUCT & io_sc )
{
@@ -443,6 +705,31 @@ uint32_t TpsEvent<TYPE_MCA>::handleFalseAlarm( STEP_CODE_DATA_STRUCT & io_sc )
//------------------------------------------------------------------------------
template<>
+uint32_t TpsEvent<TYPE_OCMB_CHIP>::handleFalseAlarm(
+ STEP_CODE_DATA_STRUCT & io_sc )
+{
+ PRDF_ERR( "handleFalseAlarm: Function not supported yet" );
+ /* TODO RTC 208263
+ io_sc.service_data->setSignature( iv_chip->getHuid(),
+ PRDFSIG_TpsFalseAlarm );
+
+ // Increase false alarm counter and check threshold.
+ if ( __getTpsFalseAlarmCounter<TYPE_MCA>(iv_chip)->inc( iv_rank, io_sc) )
+ {
+ io_sc.service_data->setSignature( iv_chip->getHuid(),
+ PRDFSIG_TpsFalseAlarmTH );
+
+ // Permanently mask mainline NCEs and TCEs
+ getMcaDataBundle(iv_chip)->iv_maskMainlineNceTce = true;
+ }
+ */
+
+ return SUCCESS;
+}
+
+//------------------------------------------------------------------------------
+
+template<>
uint32_t TpsEvent<TYPE_MCA>::analyzeCeSymbolCounts( CeCount i_badDqCount,
CeCount i_badChipCount, CeCount i_sumAboveOneCount,
CeCount i_singleSymCount, STEP_CODE_DATA_STRUCT & io_sc )
@@ -932,6 +1219,497 @@ uint32_t TpsEvent<TYPE_MCA>::analyzeCeSymbolCounts( CeCount i_badDqCount,
//------------------------------------------------------------------------------
template<>
+uint32_t TpsEvent<TYPE_OCMB_CHIP>::analyzeCeSymbolCounts( CeCount i_badDqCount,
+ CeCount i_badChipCount, CeCount i_sumAboveOneCount,
+ CeCount i_singleSymCount, STEP_CODE_DATA_STRUCT & io_sc )
+{
+
+ #define PRDF_FUNC "[TpsEvent<TYPE_OCMB_CHIP>::analyzeCeSymbolCounts] "
+
+ uint32_t o_rc = SUCCESS;
+ PRDF_ERR( PRDF_FUNC "Function not supported yet" );
+ /* TODO RTC 208263
+ do
+ {
+ bool tpsFalseAlarm = false;
+
+ // Get the Bad DQ Bitmap.
+ TargetHandle_t mcaTrgt = iv_chip->getTrgt();
+ MemDqBitmap dqBitmap;
+
+ o_rc = getBadDqBitmap( mcaTrgt, iv_rank, dqBitmap );
+ if ( SUCCESS != o_rc )
+ {
+ PRDF_ERR( PRDF_FUNC "getBadDqBitmap(0x%08x, 0x%02x) failed",
+ getHuid(mcaTrgt), iv_rank.getKey() );
+ break;
+ }
+
+ // Get the symbol mark.
+ MemMark symMark;
+ o_rc = MarkStore::readSymbolMark<TYPE_MCA>( iv_chip, iv_rank, symMark );
+ if ( SUCCESS != o_rc )
+ {
+ PRDF_ERR( PRDF_FUNC "readSymbolMark<TYPE_MCA>(0x%08x, 0x%02x) "
+ "failed", iv_chip->getHuid(), iv_rank.getKey() );
+ break;
+ }
+
+ // Get the chip mark.
+ MemMark chipMark;
+ o_rc = MarkStore::readChipMark<TYPE_MCA>( iv_chip, iv_rank, chipMark );
+ if ( SUCCESS != o_rc )
+ {
+ PRDF_ERR( PRDF_FUNC "readChipMark<TYPE_MCA>(0x%08x, 0x%02x) "
+ "failed", iv_chip->getHuid(), iv_rank.getKey() );
+ break;
+ }
+
+ // If the bad DQ nibble count is 0 and the bad chip nibble count is 0.
+ if ( 0 == i_badDqCount.count && 0 == i_badChipCount.count )
+ {
+ // There is nothing to repair. Any other non-zero counts are
+ // considered acceptable noise.
+ // Set false alarm flag to true.
+ tpsFalseAlarm = true;
+ }
+ // If the bad DQ nibble count is 1 and the bad chip nibble count is 0.
+ else if ( 1 == i_badDqCount.count && 0 == i_badChipCount.count )
+ {
+ // If the symbol mark is available.
+ if ( !symMark.isValid() )
+ {
+ // If the sum above one nibble count is <= 1 or sum above one
+ // nibble count == 2 and single sym nibble count == 2
+ if ( (i_sumAboveOneCount.count <= 1) ||
+ (i_sumAboveOneCount.count == 2 &&
+ i_singleSymCount.count == 2) )
+ {
+ // This means we have a potential future chip kill or
+ // TCE. Both are still correctable after a symbol mark
+ // is placed.
+ // Place a symbol mark on this bad DQ.
+ MemMark newSymMark( mcaTrgt, iv_rank,
+ i_badDqCount.symList[0].symbol );
+ o_rc = MarkStore::writeSymbolMark<TYPE_MCA>( iv_chip,
+ iv_rank, newSymMark );
+ if ( SUCCESS != o_rc )
+ {
+ PRDF_ERR( PRDF_FUNC "writeSymbolMark(0x%08x,0x%02x) "
+ "failed", iv_chip->getHuid(), getKey() );
+ break;
+ }
+
+ io_sc.service_data->setSignature( iv_chip->getHuid(),
+ PRDFSIG_TpsSymbolMark );
+
+ // Update VPD with the symbol mark.
+ o_rc = dqBitmap.setSymbol( i_badDqCount.symList[0].symbol );
+ if ( SUCCESS != o_rc )
+ {
+ PRDF_ERR( PRDF_FUNC "dqBitmap.setSymbol failed." );
+ break;
+ }
+ }
+ else
+ {
+ // Placing a symbol mark risks a UE.
+ // For nibbles under threshold with a sum greater than 1,
+ // update VPD with it's non-zero symbols.
+ o_rc = __updateVpdSumAboveOne(i_sumAboveOneCount, dqBitmap);
+ if ( SUCCESS != o_rc )
+ {
+ PRDF_ERR(PRDF_FUNC "__updateVpdSumAboveOne() failed.");
+ }
+
+ io_sc.service_data->setSignature( iv_chip->getHuid(),
+ PRDFSIG_TpsSymUeRisk );
+
+ // Make the error log predictive.
+ io_sc.service_data->setServiceCall();
+
+ // Permanently mask mainline NCEs and TCEs.
+ getMcaDataBundle(iv_chip)->iv_maskMainlineNceTce = true;
+ }
+ }
+ else
+ {
+ // Otherwise assume the symbol mark is fixing this bad DQ.
+ // Set the false alarm flag to true.
+ tpsFalseAlarm = true;
+ }
+ }
+ // Else if bad DQ nibble count is 2 and bad chip nibble count is 0.
+ else if ( 2 == i_badDqCount.count && 0 == i_badChipCount.count )
+ {
+ // Permanently mask mainline NCEs and TCEs.
+ getMcaDataBundle(iv_chip)->iv_maskMainlineNceTce = true;
+
+ // If the symbol mark is available.
+ if ( !symMark.isValid() )
+ {
+ // If the sum above one nibble count is = 0 or sum above one
+ // nibble count = 1 and single sym nibble count = 1
+ if ( (i_sumAboveOneCount.count == 0) ||
+ (i_sumAboveOneCount.count == 1 &&
+ i_singleSymCount.count == 1) )
+ {
+ // This means we have only one more potential bad DQ, which
+ // is correctable after a symbol mark is placed.
+ // Place a symbol mark on this bad DQ with the highest count
+ MemUtils::SymbolData highSym;
+ for ( auto sym : i_badDqCount.symList )
+ {
+ if ( sym.count > highSym.count )
+ highSym = sym;
+ }
+
+ MemMark newSymMark( mcaTrgt, iv_rank,
+ highSym.symbol );
+ o_rc = MarkStore::writeSymbolMark<TYPE_MCA>( iv_chip,
+ iv_rank, newSymMark );
+ if ( SUCCESS != o_rc )
+ {
+ PRDF_ERR( PRDF_FUNC "writeSymbolMark(0x%08x,0x%02x) "
+ "failed", iv_chip->getHuid(), getKey() );
+ break;
+ }
+
+ io_sc.service_data->setSignature( iv_chip->getHuid(),
+ PRDFSIG_TpsSymbolMark );
+
+ // Update VPD with both symbols.
+ for ( auto sym : i_badDqCount.symList )
+ {
+ o_rc = dqBitmap.setSymbol( sym.symbol );
+ if ( SUCCESS != o_rc )
+ {
+ PRDF_ERR( PRDF_FUNC "dqBitmap.setSymbol failed." );
+ break;
+ }
+ }
+ if ( SUCCESS != o_rc ) break;
+ }
+ else
+ {
+ // Placing a symbol mark risks a UE.
+ // For nibbles under threshold with a sum greater than 1,
+ // update VPD with it's non-zero symbols.
+ o_rc = __updateVpdSumAboveOne(i_sumAboveOneCount, dqBitmap);
+ if ( SUCCESS != o_rc )
+ {
+ PRDF_ERR(PRDF_FUNC "__updateVpdSumAboveOne() failed.");
+ }
+
+ io_sc.service_data->setSignature( iv_chip->getHuid(),
+ PRDFSIG_TpsSymUeRisk );
+
+ // Make the error log predictive.
+ io_sc.service_data->setServiceCall();
+ }
+
+ }
+ else
+ {
+ // Otherwise assume the symbol mark is fixing a bad DQ.
+ // Update VPD with the unrepaired symbol.
+ for ( auto sym : i_badDqCount.symList )
+ {
+ if ( sym.symbol == symMark.getSymbol() ) continue;
+
+ o_rc = dqBitmap.setSymbol( sym.symbol );
+ if ( SUCCESS != o_rc )
+ {
+ PRDF_ERR( PRDF_FUNC "dqBitmap.setSymbol failed." );
+ break;
+ }
+ }
+ if ( SUCCESS != o_rc ) break;
+
+ // Set the false alarm flag to true.
+ tpsFalseAlarm = true;
+ }
+
+ }
+ // Else if bad DQ nibble count is 0 and bad chip nibble count is 1
+ else if ( 0 == i_badDqCount.count && 1 == i_badChipCount.count )
+ {
+ // If the chip mark is available.
+ if ( !chipMark.isValid() )
+ {
+ // If the sum above one nibble count is = 0 or the sum above one
+ // nibble count = 1 and the single sym nibble count = 1
+ if ( (i_sumAboveOneCount.count == 0) ||
+ (i_sumAboveOneCount.count == 1 &&
+ i_singleSymCount.count == 1) )
+ {
+ // This means we have only one more potential bad DQ, which
+ // is still correctable after a chip mark is placed.
+ // Place a chip mark on this bad chip.
+ MemMark newChipMark( mcaTrgt, iv_rank,
+ i_badChipCount.symList[0].symbol );
+ o_rc = MarkStore::writeChipMark<TYPE_MCA>( iv_chip, iv_rank,
+ newChipMark );
+ if ( SUCCESS != o_rc )
+ {
+ PRDF_ERR( PRDF_FUNC "writeChipMark(0x%08x,0x%02x) "
+ "failed", iv_chip->getHuid(), getKey() );
+ break;
+ }
+
+ io_sc.service_data->setSignature( iv_chip->getHuid(),
+ PRDFSIG_TpsChipMark );
+ // Update VPD with the chip mark.
+ o_rc = dqBitmap.setDram( i_badChipCount.symList[0].symbol );
+ if ( SUCCESS != o_rc )
+ {
+ PRDF_ERR( PRDF_FUNC "dqBitmap.setDram failed." );
+ break;
+ }
+ }
+ else
+ {
+ // Placing a mark risks a UE.
+ // For nibbles under threshold with a sum greater than 1,
+ // update VPD with it's non-zero symbols.
+ o_rc = __updateVpdSumAboveOne(i_sumAboveOneCount, dqBitmap);
+ if ( SUCCESS != o_rc )
+ {
+ PRDF_ERR(PRDF_FUNC "__updateVpdSumAboveOne() failed.");
+ }
+
+ io_sc.service_data->setSignature( iv_chip->getHuid(),
+ PRDFSIG_TpsChipUeRisk );
+
+ // Make the error log predictive.
+ io_sc.service_data->setServiceCall();
+
+ // Permanently mask mainline NCEs and TCEs
+ getMcaDataBundle(iv_chip)->iv_maskMainlineNceTce = true;
+ }
+ }
+ else
+ {
+ // Assume the chip mark is being used to fix the bad chip.
+ // Set the false alarm flag to true.
+ tpsFalseAlarm = true;
+ }
+ }
+ // Else if bad DQ nibble count is 1 and bad chip nibble count is 1
+ else if ( 1 == i_badDqCount.count && 1 == i_badChipCount.count )
+ {
+ // If neither chip nor symbol mark is available.
+ if ( chipMark.isValid() && symMark.isValid() )
+ {
+ // Assume the chip and symbol marks are already being used to
+ // fix the bad chip and DQ and some other nibble under
+ // threshold triggered TPS.
+ // Make the error log predictive.
+ io_sc.service_data->setServiceCall();
+
+ // Permanently mask mainline NCEs and TCEs
+ getMcaDataBundle(iv_chip)->iv_maskMainlineNceTce = true;
+ }
+ // If the chip mark is available.
+ if ( !chipMark.isValid() )
+ {
+ // If the sum above one nibble count is 0
+ if ( 0 == i_sumAboveOneCount.count )
+ {
+ // This means we have no more potential bad DQ or bad chips
+ // since we can't correct those after chip mark is placed.
+ // Place a chip mark on the bad chip.
+ MemMark newChipMark( mcaTrgt, iv_rank,
+ i_badChipCount.symList[0].symbol );
+ o_rc = MarkStore::writeChipMark<TYPE_MCA>( iv_chip, iv_rank,
+ newChipMark );
+ if ( SUCCESS != o_rc )
+ {
+ PRDF_ERR( PRDF_FUNC "writeChipMark(0x%08x,0x%02x) "
+ "failed", iv_chip->getHuid(), getKey() );
+ break;
+ }
+
+ // Check if the current symbol mark is on the same DRAM as
+ // this newly placed chip mark.
+ if ( symMark.isValid() &&
+ ( symMark.getSymbol().getDram() ==
+ newChipMark.getSymbol().getDram() ) )
+ {
+ // Since we need to set a symbol mark in addition to
+ // this chip mark, we need to clear the symbol mark now
+ // instead of at the end of the function to make room
+ // for the additional symbol mark.
+ o_rc = MarkStore::clearSymbolMark<TYPE_MCA>( iv_chip,
+ iv_rank );
+ if ( SUCCESS != o_rc )
+ {
+ PRDF_ERR( PRDF_FUNC "MarkStore::clearSymbolMark("
+ "0x%08x,0x%02x) failed",
+ iv_chip->getHuid(), iv_rank.getKey() );
+ break;
+ }
+
+ // Now refresh the symMark variable since the mark has
+ // been removed.
+ symMark = MemMark();
+ }
+
+ io_sc.service_data->setSignature( iv_chip->getHuid(),
+ PRDFSIG_TpsChipMark );
+
+ // Update VPD with the chip mark.
+ o_rc = dqBitmap.setDram( i_badChipCount.symList[0].symbol );
+ if ( SUCCESS != o_rc )
+ {
+ PRDF_ERR( PRDF_FUNC "dqBitmap.setDram failed." );
+ break;
+ }
+
+ // Make the error log predictive.
+ io_sc.service_data->setServiceCall();
+ }
+ else
+ {
+ // Placing a chip mark risks a UE.
+ // For nibbles under threshold with a sum greater than 1,
+ // update VPD with it's non-zero symbols.
+ o_rc = __updateVpdSumAboveOne(i_sumAboveOneCount, dqBitmap);
+ if ( SUCCESS != o_rc )
+ {
+ PRDF_ERR(PRDF_FUNC "__updateVpdSumAboveOne() failed.");
+ }
+
+ io_sc.service_data->setSignature( iv_chip->getHuid(),
+ PRDFSIG_TpsChipUeRisk );
+
+ // Make the error log predictive.
+ io_sc.service_data->setServiceCall();
+
+ // Permanently mask mainline NCEs and TCEs.
+ getMcaDataBundle(iv_chip)->iv_maskMainlineNceTce = true;
+ }
+ }
+ // If the symbol mark is available.
+ if ( !symMark.isValid() )
+ {
+ // If the sum above one nibble count is 0
+ if ( 0 == i_sumAboveOneCount.count )
+ {
+ // This means we have no more potential bad DQ or bad chips
+ // since we can't correct those after symbol mark is placed.
+ // Place a symbol mark on this bad DQ.
+ MemMark newSymMark( mcaTrgt, iv_rank,
+ i_badDqCount.symList[0].symbol );
+ o_rc = MarkStore::writeSymbolMark<TYPE_MCA>( iv_chip,
+ iv_rank, newSymMark );
+ if ( SUCCESS != o_rc )
+ {
+ PRDF_ERR( PRDF_FUNC "writeSymbolMark(0x%08x,0x%02x) "
+ "failed", iv_chip->getHuid(), getKey() );
+ break;
+ }
+
+ io_sc.service_data->setSignature( iv_chip->getHuid(),
+ PRDFSIG_TpsSymbolMark );
+
+ // Update VPD with the symbol mark.
+ o_rc = dqBitmap.setSymbol( i_badDqCount.symList[0].symbol );
+ if ( SUCCESS != o_rc )
+ {
+ PRDF_ERR( PRDF_FUNC "dqBitmap.setSymbol failed." );
+ break;
+ }
+
+ // Make the error log predictive.
+ io_sc.service_data->setServiceCall();
+ }
+ else
+ {
+ // Placing the symbol mark risks a UE.
+ // For nibbles under threshold with a sum greater than 1,
+ // update VPD with it's non-zero symbols.
+ o_rc = __updateVpdSumAboveOne(i_sumAboveOneCount, dqBitmap);
+ if ( SUCCESS != o_rc )
+ {
+ PRDF_ERR(PRDF_FUNC "__updateVpdSumAboveOne() failed.");
+ }
+
+ io_sc.service_data->setSignature( iv_chip->getHuid(),
+ PRDFSIG_TpsSymUeRisk );
+
+ // Make the error log predictive.
+ io_sc.service_data->setServiceCall();
+
+ // Permanently mask mainline NCEs and TCEs.
+ getMcaDataBundle(iv_chip)->iv_maskMainlineNceTce = true;
+ }
+ }
+
+ }
+ else
+ {
+ // There are enough errors that this could be a potential UE.
+ // For nibbles under threshold with a sum greater than 1,
+ // update VPD with it's non-zero symbols.
+ o_rc = __updateVpdSumAboveOne( i_sumAboveOneCount, dqBitmap );
+ if ( SUCCESS != o_rc )
+ {
+ PRDF_ERR( PRDF_FUNC "__updateVpdSumAboveOne() failed." );
+ }
+
+ io_sc.service_data->setSignature( iv_chip->getHuid(),
+ PRDFSIG_TpsPotentialUe );
+
+ // Make the error log predictive.
+ io_sc.service_data->setServiceCall();
+
+ // Permanently mask mainline NCEs and TCEs.
+ getMcaDataBundle(iv_chip)->iv_maskMainlineNceTce = true;
+ }
+
+ // If analysis resulted in a false alarm.
+ if ( tpsFalseAlarm )
+ {
+ o_rc = handleFalseAlarm( io_sc );
+ if ( SUCCESS != o_rc )
+ {
+ PRDF_ERR( PRDF_FUNC "handleFalseAlarm() failed on 0x%08x, "
+ "0x%02x", iv_chip->getHuid(), getKey() );
+ }
+ }
+
+ // Write any updates to VPD.
+ o_rc = setBadDqBitmap( mcaTrgt, iv_rank, dqBitmap );
+ if ( SUCCESS != o_rc )
+ {
+ PRDF_ERR( PRDF_FUNC "setBadDqBitmap(0x%08x, 0x%02x) failed",
+ getHuid(mcaTrgt), iv_rank.getKey() );
+ break;
+ }
+
+ // We may have placed a chip mark so do any necessary cleanup. This must
+ // be called after writing the bad DQ bitmap because the this function
+ // will also write it if necessary.
+ o_rc = MarkStore::chipMarkCleanup<TYPE_MCA>( iv_chip, iv_rank, io_sc );
+ if ( SUCCESS != o_rc )
+ {
+ PRDF_ERR( PRDF_FUNC "MarkStore::chipMarkCleanup(0x%08x,0x%02x) "
+ "failed", iv_chip->getHuid(), getKey() );
+ break;
+ }
+
+ } while (0);
+ */
+
+ return o_rc;
+
+ #undef PRDF_FUNC
+}
+
+//------------------------------------------------------------------------------
+
+template<>
uint32_t TpsEvent<TYPE_MCA>::getSymbolCeCounts( CeCount & io_badDqCount,
CeCount & io_badChipCount, CeCount & io_sumAboveOneCount,
CeCount & io_singleSymCount, STEP_CODE_DATA_STRUCT & io_sc )
@@ -1031,6 +1809,109 @@ uint32_t TpsEvent<TYPE_MCA>::getSymbolCeCounts( CeCount & io_badDqCount,
//------------------------------------------------------------------------------
+template<>
+uint32_t TpsEvent<TYPE_OCMB_CHIP>::getSymbolCeCounts( CeCount & io_badDqCount,
+ CeCount & io_badChipCount, CeCount & io_sumAboveOneCount,
+ CeCount & io_singleSymCount, STEP_CODE_DATA_STRUCT & io_sc )
+{
+ #define PRDF_FUNC "[TpsEvent<TYPE_OCMB_CHIP>::getSymbolCeCounts] "
+
+ uint32_t o_rc = SUCCESS;
+
+ PRDF_ERR( PRDF_FUNC "Function not supported yet" );
+ /* TODO RTC 208263
+ do
+ {
+ // Get the Bad DQ Bitmap.
+ TargetHandle_t mcaTrgt = iv_chip->getTrgt();
+ MemDqBitmap dqBitmap;
+
+ o_rc = getBadDqBitmap( mcaTrgt, iv_rank, dqBitmap );
+ if ( SUCCESS != o_rc )
+ {
+ PRDF_ERR( PRDF_FUNC "getBadDqBitmap(0x%08x,%d) failed",
+ getHuid(mcaTrgt), iv_rank.getMaster() );
+ break;
+ }
+ std::vector<MemSymbol> bmSymList = dqBitmap.getSymbolList();
+
+ ExtensibleChip * mcbChip = getConnectedParent( iv_chip, TYPE_MCBIST );
+ const char * reg_str = nullptr;
+ SCAN_COMM_REGISTER_CLASS * reg = nullptr;
+
+ for ( uint8_t regIdx = 0; regIdx < CE_REGS_PER_PORT; regIdx++ )
+ {
+ reg_str = mcbCeStatReg[regIdx];
+ reg = mcbChip->getRegister( reg_str );
+
+ o_rc = reg->Read();
+ if ( SUCCESS != o_rc )
+ {
+ PRDF_ERR( PRDF_FUNC "Read() failed on %s.", reg_str );
+ break;
+ }
+ uint8_t baseSymbol = SYMBOLS_PER_CE_REG * regIdx;
+
+ for ( uint8_t i = 0; i < SYMBOLS_PER_CE_REG;
+ i += MEM_SYMBOLS_PER_NIBBLE )
+ {
+ MemUtils::MaintSymbols nibbleStats;
+
+ // Get a nibble's worth of symbols.
+ for ( uint8_t n = 0; n < MEM_SYMBOLS_PER_NIBBLE; n++ )
+ {
+ uint8_t sym = baseSymbol + (i+n);
+ PRDF_ASSERT( sym < SYMBOLS_PER_RANK );
+
+ MemUtils::SymbolData symData;
+ symData.symbol = MemSymbol::fromSymbol( mcaTrgt, iv_rank,
+ sym, CEN_SYMBOL::ODD_SYMBOL_DQ );
+ if ( !symData.symbol.isValid() )
+ {
+ PRDF_ERR( PRDF_FUNC "MemSymbol() failed: symbol=%d",
+ sym );
+ o_rc = FAIL;
+ break;
+ }
+
+ // Any symbol set in the DRAM repairs VPD will have an
+ // automatic CE count of 0xFF
+ if ( std::find( bmSymList.begin(), bmSymList.end(),
+ symData.symbol ) != bmSymList.end() )
+ symData.count = 0xFF;
+ else
+ symData.count = reg->GetBitFieldJustified(((i+n)*8), 8);
+
+ nibbleStats.push_back( symData );
+
+ // Add all symbols with non-zero counts to the callout list.
+ if ( symData.count != 0 )
+ {
+ MemoryMru mm { mcaTrgt, iv_rank, symData.symbol };
+ io_sc.service_data->SetCallout( mm );
+ }
+ }
+ if ( SUCCESS != o_rc ) break;
+
+ // Analyze the nibble of symbols.
+ __analyzeNibbleSyms<TYPE_MCA>( nibbleStats, io_badDqCount,
+ io_badChipCount, io_sumAboveOneCount, io_singleSymCount );
+
+ }
+ if ( SUCCESS != o_rc ) break;
+ }
+
+ }while(0);
+ */
+
+ return o_rc;
+
+ #undef PRDF_FUNC
+
+}
+
+//------------------------------------------------------------------------------
+
template <>
uint32_t TpsEvent<TYPE_MCA>::analyzeCeStats( STEP_CODE_DATA_STRUCT & io_sc,
bool & o_done )
@@ -1088,6 +1969,66 @@ uint32_t TpsEvent<TYPE_MCA>::analyzeCeStats( STEP_CODE_DATA_STRUCT & io_sc,
//------------------------------------------------------------------------------
+template <>
+uint32_t TpsEvent<TYPE_OCMB_CHIP>::analyzeCeStats(STEP_CODE_DATA_STRUCT & io_sc,
+ bool & o_done)
+{
+ #define PRDF_FUNC "[TpsEvent<TYPE_OCMB_CHIP>::analyzeCeStats] "
+
+ uint32_t o_rc = SUCCESS;
+
+ PRDF_ERR( PRDF_FUNC "Function not supported yet" );
+ /* TODO RTC 208263
+ do
+ {
+ // The symbol CE counts will be summarized in the following buckets:
+ // Number of nibbles with a bad DQ
+ // Number of nibbles with a bad chip
+ // Number of nibbles under threshold with a sum greater than 1
+ // Number of nibbles under threshold with only a single symbol with a
+ // non-zero count, and that count is > 1
+ CeCount badDqCount, badChipCount, sumAboveOneCount, singleSymCount;
+
+ // Get the symbol CE counts.
+ o_rc = getSymbolCeCounts( badDqCount, badChipCount, sumAboveOneCount,
+ singleSymCount, io_sc );
+ if ( SUCCESS != o_rc )
+ {
+ PRDF_ERR( PRDF_FUNC "getSymbolCeCounts failed." );
+ break;
+ }
+
+ // If DRAM repairs are disabled, make the error log predictive and
+ // abort this procedure.
+ if ( areDramRepairsDisabled() )
+ {
+ io_sc.service_data->setSignature( iv_chip->getHuid(),
+ PRDFSIG_TpsDramDisabled );
+
+ io_sc.service_data->setServiceCall();
+ break;
+ }
+
+ // Analyze the symbol CE counts.
+ o_rc = analyzeCeSymbolCounts(badDqCount, badChipCount, sumAboveOneCount,
+ singleSymCount, io_sc);
+ if ( SUCCESS != o_rc )
+ {
+ PRDF_ERR( PRDF_FUNC "analyzeCeSymbolCounts failed." );
+ break;
+ }
+
+ }while(0);
+ */
+
+ return o_rc;
+
+ #undef PRDF_FUNC
+
+}
+
+//------------------------------------------------------------------------------
+
template<>
uint32_t TpsEvent<TYPE_MCA>::analyzePhase( STEP_CODE_DATA_STRUCT & io_sc,
bool & o_done )
@@ -1143,6 +2084,66 @@ uint32_t TpsEvent<TYPE_MCA>::analyzePhase( STEP_CODE_DATA_STRUCT & io_sc,
#undef PRDF_FUNC
}
+//------------------------------------------------------------------------------
+
+template<>
+uint32_t TpsEvent<TYPE_OCMB_CHIP>::analyzePhase( STEP_CODE_DATA_STRUCT & io_sc,
+ bool & o_done )
+{
+ #define PRDF_FUNC "[TpsEvent::analyzePhase] "
+
+ uint32_t o_rc = SUCCESS;
+
+ PRDF_ERR( PRDF_FUNC "Function not supported yet" );
+ /* TODO RTC 208263
+ do
+ {
+ if ( TD_PHASE_0 == iv_phase ) break; // Nothing to analyze yet.
+
+ // Analyze Ecc Attentions
+ uint32_t eccAttns;
+ o_rc = checkEccFirs<TYPE_MCA>( iv_chip, eccAttns );
+ if ( SUCCESS != o_rc )
+ {
+ PRDF_ERR( PRDF_FUNC "checkEccFirs(0x%08x) failed",
+ iv_chip->getHuid() );
+ break;
+ }
+
+ o_rc = analyzeEccErrors( eccAttns, io_sc, o_done );
+ if ( SUCCESS != o_rc )
+ {
+ PRDF_ERR( PRDF_FUNC "analyzeEccErrors() failed." );
+ break;
+ }
+ if ( o_done ) break;
+
+ // Analyze CEs
+ o_rc = analyzeCeStats( io_sc, o_done );
+ if ( SUCCESS != o_rc )
+ {
+ PRDF_ERR( PRDF_FUNC "analyzeCeStats() failed." );
+ break;
+ }
+ if ( o_done ) break;
+
+ // At this point, we are done with the procedure.
+ o_done = true;
+
+ } while (0);
+
+ if ( (SUCCESS == o_rc) && o_done )
+ {
+ // Clear the ECC FFDC for this master rank.
+ MemDbUtils::resetEccFfdc<TYPE_MCA>( iv_chip, iv_rank, SLAVE_RANK );
+ }
+ */
+
+ return o_rc;
+
+ #undef PRDF_FUNC
+}
+
//##############################################################################
//
// Specializations for MCA
@@ -1195,6 +2196,55 @@ uint32_t TpsEvent<TYPE_MCA>::startCmd()
#undef PRDF_FUNC
}
+template<>
+uint32_t TpsEvent<TYPE_OCMB_CHIP>::startCmd()
+{
+ #define PRDF_FUNC "[TpsEvent::startCmd] "
+
+ uint32_t o_rc = SUCCESS;
+
+ PRDF_ERR( PRDF_FUNC "Function not supported yet" );
+ /* TODO RTC 208263
+ // We don't need to set any stop-on-error conditions or thresholds for
+ // soft/inter/hard CEs at runtime. The design is to let the command continue
+ // to the end of the rank and we do diagnostics on the CE counts found in
+ // the per-symbol counters. Therefore, all we need to do is tell the
+ // hardware which CE types to count.
+
+ mss::mcbist::stop_conditions stopCond;
+
+ switch ( iv_phase )
+ {
+ case TD_PHASE_1:
+ // Set the per symbol counters to count only hard CEs.
+ stopCond.set_nce_hard_symbol_count_enable(mss::ON);
+ break;
+
+ case TD_PHASE_2:
+ // Since there are not enough hard CEs to trigger a symbol mark, set
+ // the per symbol counters to count all CE types.
+ stopCond.set_nce_soft_symbol_count_enable( mss::ON);
+ stopCond.set_nce_inter_symbol_count_enable(mss::ON);
+ stopCond.set_nce_hard_symbol_count_enable( mss::ON);
+ break;
+
+ default: PRDF_ASSERT( false ); // invalid phase
+ }
+
+ // Start the time based scrub procedure on this slave rank.
+ o_rc = startTdScrub<TYPE_MCA>( iv_chip, iv_rank, SLAVE_RANK, stopCond );
+ if ( SUCCESS != o_rc )
+ {
+ PRDF_ERR( PRDF_FUNC "startTdScrub(0x%08x,0x%2x) failed",
+ iv_chip->getHuid(), getKey() );
+ }
+ */
+
+ return o_rc;
+
+ #undef PRDF_FUNC
+}
+
//------------------------------------------------------------------------------
template<>
@@ -1212,6 +2262,26 @@ uint32_t TpsEvent<TYPE_MCA>::startNextPhase( STEP_CODE_DATA_STRUCT & io_sc )
return startCmd();
}
+//------------------------------------------------------------------------------
+
+template<>
+uint32_t TpsEvent<TYPE_OCMB_CHIP>::startNextPhase(STEP_CODE_DATA_STRUCT & io_sc)
+{
+ PRDF_ERR( "startNextPhase: Function not supported yet" );
+ /* TODO RTC 208263
+ uint32_t signature = 0;
+
+ __getNextPhase<TYPE_MCA>( iv_chip, iv_rank, io_sc, iv_phase, signature );
+
+ PRDF_TRAC( "[TpsEvent] Starting TPS Phase %d: 0x%08x,0x%02x",
+ iv_phase, iv_chip->getHuid(), getKey() );
+
+ io_sc.service_data->AddSignatureList( iv_chip->getTrgt(), signature );
+ */
+
+ return startCmd();
+}
+
//##############################################################################
//
// Specializations for MBA
diff --git a/src/usr/diag/prdf/plat/mem/prdfMemVcm.C b/src/usr/diag/prdf/plat/mem/prdfMemVcm.C
index 1bf84ad59..611bd42fa 100644
--- a/src/usr/diag/prdf/plat/mem/prdfMemVcm.C
+++ b/src/usr/diag/prdf/plat/mem/prdfMemVcm.C
@@ -66,6 +66,32 @@ uint32_t VcmEvent<TYPE_MCA>::startCmd()
#undef PRDF_FUNC
}
+template<>
+uint32_t VcmEvent<TYPE_OCMB_CHIP>::startCmd()
+{
+ #define PRDF_FUNC "[VcmEvent::startCmd] "
+
+ uint32_t o_rc = SUCCESS;
+
+ PRDF_ERR( PRDF_FUNC "Function not supported yet" );
+ /* TODO RTC 208262
+ // No stop conditions.
+ mss::mcbist::stop_conditions stopCond;
+
+ // Start the time based scrub procedure on this master rank.
+ o_rc = startTdScrub<TYPE_MCA>( iv_chip, iv_rank, MASTER_RANK, stopCond );
+ if ( SUCCESS != o_rc )
+ {
+ PRDF_ERR( PRDF_FUNC "startTdScrub(0x%08x,0x%2x) failed",
+ iv_chip->getHuid(), getKey() );
+ }
+ */
+
+ return o_rc;
+
+ #undef PRDF_FUNC
+}
+
//------------------------------------------------------------------------------
template<>
@@ -100,6 +126,42 @@ uint32_t VcmEvent<TYPE_MCA>::handlePhaseComplete( const uint32_t & i_eccAttns,
#undef PRDF_FUNC
}
+template<>
+uint32_t VcmEvent<TYPE_OCMB_CHIP>::handlePhaseComplete(
+ const uint32_t & i_eccAttns,
+ STEP_CODE_DATA_STRUCT & io_sc,
+ bool & o_done )
+{
+ #define PRDF_FUNC "[VcmEvent<TYPE_OCMB_CHIP>::handlePhaseComplete] "
+
+ uint32_t o_rc = SUCCESS;
+
+ PRDF_ERR( PRDF_FUNC "Function not supported yet" );
+ /* TODO RTC 208262
+ do
+ {
+ if ( TD_PHASE_2 == iv_phase )
+ {
+ // Determine if the chip mark has been verified.
+ o_rc = (i_eccAttns & MAINT_MCE) ? verified(io_sc)
+ : falseAlarm(io_sc);
+ if ( SUCCESS != o_rc )
+ {
+ PRDF_ERR( PRDF_FUNC "verified()/falseAlarm() failed" );
+ break;
+ }
+
+ o_done = true; // Procedure is complete.
+ }
+
+ } while (0);
+ */
+
+ return o_rc;
+
+ #undef PRDF_FUNC
+}
+
//##############################################################################
//
// Specializations for MBA
diff --git a/src/usr/diag/prdf/plat/mem/prdfMemVcm_ipl.C b/src/usr/diag/prdf/plat/mem/prdfMemVcm_ipl.C
index 26ef1d727..5ffa9a84b 100644
--- a/src/usr/diag/prdf/plat/mem/prdfMemVcm_ipl.C
+++ b/src/usr/diag/prdf/plat/mem/prdfMemVcm_ipl.C
@@ -5,7 +5,7 @@
/* */
/* OpenPOWER HostBoot Project */
/* */
-/* Contributors Listed Below - COPYRIGHT 2016,2018 */
+/* Contributors Listed Below - COPYRIGHT 2016,2019 */
/* [+] International Business Machines Corp. */
/* */
/* */
@@ -92,6 +92,12 @@ bool __iueCheck<TYPE_MCA>( uint32_t i_eccAttns )
}
template<> inline
+bool __iueCheck<TYPE_OCMB_CHIP>( uint32_t i_eccAttns )
+{
+ return ( 0 != (i_eccAttns & MAINT_IUE) );
+}
+
+template<> inline
bool __iueCheck<TYPE_MBA>( uint32_t i_eccAttns )
{
// IUES are reported via RCE ETE on Centaur
@@ -218,6 +224,7 @@ uint32_t VcmEvent<TYPE_MBA>::startCmd()
// Avoid linker errors with the template.
template class VcmEvent<TYPE_MCA>;
template class VcmEvent<TYPE_MBA>;
+template class VcmEvent<TYPE_OCMB_CHIP>;
} // end namespace PRDF
diff --git a/src/usr/diag/prdf/plat/mem/prdfMemVcm_rt.C b/src/usr/diag/prdf/plat/mem/prdfMemVcm_rt.C
index ca4de8e5a..67c64b90a 100644
--- a/src/usr/diag/prdf/plat/mem/prdfMemVcm_rt.C
+++ b/src/usr/diag/prdf/plat/mem/prdfMemVcm_rt.C
@@ -5,7 +5,7 @@
/* */
/* OpenPOWER HostBoot Project */
/* */
-/* Contributors Listed Below - COPYRIGHT 2016,2018 */
+/* Contributors Listed Below - COPYRIGHT 2016,2019 */
/* [+] International Business Machines Corp. */
/* */
/* */
@@ -55,6 +55,12 @@ VcmFalseAlarm * __getFalseAlarmCounter<TYPE_MCA>( ExtensibleChip * i_chip )
}
template<>
+VcmFalseAlarm * __getFalseAlarmCounter<TYPE_OCMB_CHIP>(ExtensibleChip * i_chip)
+{
+ return getOcmbDataBundle(i_chip)->getVcmFalseAlarmCounter();
+}
+
+template<>
VcmFalseAlarm * __getFalseAlarmCounter<TYPE_MBA>( ExtensibleChip * i_chip )
{
return getMbaDataBundle(i_chip)->getVcmFalseAlarmCounter();
@@ -144,6 +150,87 @@ uint32_t VcmEvent<TYPE_MCA>::checkEcc( const uint32_t & i_eccAttns,
#undef PRDF_FUNC
}
+template<>
+uint32_t VcmEvent<TYPE_OCMB_CHIP>::checkEcc( const uint32_t & i_eccAttns,
+ STEP_CODE_DATA_STRUCT & io_sc,
+ bool & o_done )
+{
+ #define PRDF_FUNC "[VcmEvent<TYPE_OCMB_CHIP>::checkEcc] "
+
+ uint32_t o_rc = SUCCESS;
+
+ PRDF_ERR( PRDF_FUNC "Function not supported yet" );
+ /* TODO RTC 208262
+ do
+ {
+ if ( i_eccAttns & MAINT_UE )
+ {
+ PRDF_TRAC( PRDF_FUNC "UE Detected: 0x%08x,0x%02x",
+ iv_chip->getHuid(), getKey() );
+
+ io_sc.service_data->setSignature( iv_chip->getHuid(),
+ PRDFSIG_MaintUE );
+
+ // At this point we don't actually have an address for the UE. The
+ // best we can do is get the address in which the command stopped.
+ MemAddr addr;
+ o_rc = getMemMaintAddr<TYPE_MCA>( iv_chip, addr );
+ if ( SUCCESS != o_rc )
+ {
+ PRDF_ERR( PRDF_FUNC "getMemMaintAddr(0x%08x) failed",
+ iv_chip->getHuid() );
+ break;
+ }
+
+ o_rc = MemEcc::handleMemUe<TYPE_MCA>( iv_chip, addr,
+ UE_TABLE::SCRUB_UE, io_sc );
+ if ( SUCCESS != o_rc )
+ {
+ PRDF_ERR( PRDF_FUNC "handleMemUe(0x%08x,0x%02x) failed",
+ iv_chip->getHuid(), getKey() );
+ break;
+ }
+
+ // Because of the UE, any further TPS requests will likely have no
+ // effect. So ban all subsequent requests.
+ MemDbUtils::banTps<TYPE_MCA>( iv_chip, addr.getRank() );
+
+ // Leave the mark in place and abort this procedure.
+ o_done = true; break;
+ }
+
+ if ( mfgMode() && (i_eccAttns & MAINT_IUE) )
+ {
+ io_sc.service_data->setSignature( iv_chip->getHuid(),
+ PRDFSIG_MaintIUE );
+
+ o_rc = MemEcc::handleMemIue<TYPE_MCA>( iv_chip, iv_rank, io_sc );
+ if ( SUCCESS != o_rc )
+ {
+ PRDF_ERR( PRDF_FUNC "handleMemIue(0x%08x,0x%02x) failed",
+ iv_chip->getHuid(), getKey() );
+ break;
+ }
+
+ // If service call is set, then IUE threshold was reached.
+ if ( io_sc.service_data->queryServiceCall() )
+ {
+ PRDF_TRAC( PRDF_FUNC "IUE threshold detected: 0x%08x,0x%02x",
+ iv_chip->getHuid(), getKey() );
+
+ // Leave the mark in place and abort this procedure.
+ o_done = true; break;
+ }
+ }
+
+ } while (0);
+ */
+
+ return o_rc;
+
+ #undef PRDF_FUNC
+}
+
//------------------------------------------------------------------------------
template<>
@@ -180,6 +267,43 @@ uint32_t VcmEvent<TYPE_MCA>::cleanup( STEP_CODE_DATA_STRUCT & io_sc )
#undef PRDF_FUNC
}
+template<>
+uint32_t VcmEvent<TYPE_OCMB_CHIP>::cleanup( STEP_CODE_DATA_STRUCT & io_sc )
+{
+ #define PRDF_FUNC "[VcmEvent::cleanup] "
+
+ uint32_t o_rc = SUCCESS;
+
+ PRDF_ERR( PRDF_FUNC "Function not supported yet" );
+ /* TODO RTC 208262
+ do
+ {
+ o_rc = MarkStore::chipMarkCleanup<TYPE_MCA>( iv_chip, iv_rank, io_sc );
+ if ( SUCCESS != o_rc )
+ {
+ PRDF_ERR( PRDF_FUNC "chipMarkCleanup(0x%08x,0x%02x) failed",
+ iv_chip->getHuid(), iv_rank.getKey() );
+ break;
+ }
+
+ // The cleanup() function is called by both verified() and falseAlarm().
+ // In either case, the error log should be predictive if there has been
+ // a least one false alarm on any DRAM on this rank other than this
+ // DRAM. This is required on Nimbus because of two symbol correction,
+ // which does not exist on Centaur.
+ VcmFalseAlarm * faCntr = __getFalseAlarmCounter<TYPE_MCA>(iv_chip);
+ uint8_t dram = iv_mark.getSymbol().getDram();
+ if ( faCntr->queryDrams(iv_rank, dram, io_sc) )
+ io_sc.service_data->setServiceCall();
+
+ } while (0);
+ */
+
+ return o_rc;
+
+ #undef PRDF_FUNC
+}
+
//##############################################################################
//
// Specializations for MBA
@@ -386,6 +510,7 @@ uint32_t VcmEvent<T>::falseAlarm( STEP_CODE_DATA_STRUCT & io_sc )
// Avoid linker errors with the template.
template class VcmEvent<TYPE_MCA>;
template class VcmEvent<TYPE_MBA>;
+template class VcmEvent<TYPE_OCMB_CHIP>;
//------------------------------------------------------------------------------
diff --git a/src/usr/diag/prdf/plat/mem/prdfP9Mcbist.C b/src/usr/diag/prdf/plat/mem/prdfP9Mcbist.C
index 4a4391c0c..0e11b1a86 100644
--- a/src/usr/diag/prdf/plat/mem/prdfP9Mcbist.C
+++ b/src/usr/diag/prdf/plat/mem/prdfP9Mcbist.C
@@ -5,7 +5,7 @@
/* */
/* OpenPOWER HostBoot Project */
/* */
-/* Contributors Listed Below - COPYRIGHT 2016,2018 */
+/* Contributors Listed Below - COPYRIGHT 2016,2019 */
/* [+] International Business Machines Corp. */
/* */
/* */
@@ -301,9 +301,9 @@ int32_t commandAddrTimeout( ExtensibleChip * i_chip,
// was executed. Restarting the command will likely fail with the same
// issue. Callout and gard all MCAs in which the command was executed.
- std::vector<ExtensibleChip *> mcaList;
+ ExtensibleChipList mcaList;
- if ( SUCCESS != getMcbistMaintPort(i_chip, mcaList) )
+ if ( SUCCESS != getMcbistMaintPort<TYPE_MCBIST>(i_chip, mcaList) )
{
PRDF_ERR( PRDF_FUNC "getMcbistMaintPort(0x%08x) failed",
i_chip->getHuid() );
OpenPOWER on IntegriCloud