summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorCaleb Palmer <cnpalmer@us.ibm.com>2019-04-09 15:29:07 -0500
committerZane C. Shelley <zshelle@us.ibm.com>2019-04-18 10:33:07 -0500
commit9d139bd7d99a87c6d11f6569482218badb49cc8b (patch)
treede94afe1294c8faa0acb828b21929746afa1482a
parent36a58f1f80473c1ee39e449c85f78ead269c0348 (diff)
downloadtalos-hostboot-9d139bd7d99a87c6d11f6569482218badb49cc8b.tar.gz
talos-hostboot-9d139bd7d99a87c6d11f6569482218badb49cc8b.zip
PRD: Axone/Explorer Misc Updates needed for TdCtlr/DataBundles
Change-Id: Ia769f949f984c810b998c19fd32c7c3af2e06244 RTC: 207388 Reviewed-on: http://rchgit01.rchland.ibm.com/gerrit1/75791 Tested-by: Jenkins Server <pfd-jenkins+hostboot@us.ibm.com> Reviewed-by: Paul Greenwood <paul.greenwood@ibm.com> Reviewed-by: Brian J. Stegmiller <bjs@us.ibm.com> Reviewed-by: Zane C. Shelley <zshelle@us.ibm.com> Reviewed-on: http://rchgit01.rchland.ibm.com/gerrit1/76086 Tested-by: Jenkins OP Build CI <op-jenkins+hostboot@us.ibm.com> Tested-by: Jenkins OP HW <op-hw-jenkins+hostboot@us.ibm.com> Tested-by: FSP CI Jenkins <fsp-CI-jenkins+hostboot@us.ibm.com>
-rw-r--r--src/usr/diag/prdf/common/plat/explorer/explorer_ocmb_regs.rule225
-rw-r--r--src/usr/diag/prdf/common/plat/mem/prdfMemCeTable.C3
-rwxr-xr-xsrc/usr/diag/prdf/common/plat/mem/prdfMemSymbol.C212
-rwxr-xr-xsrc/usr/diag/prdf/common/plat/mem/prdfMemSymbol.H10
-rwxr-xr-xsrc/usr/diag/prdf/common/plat/mem/prdfMemThresholds.C11
-rwxr-xr-xsrc/usr/diag/prdf/common/plat/mem/prdfMemUtils.C158
-rwxr-xr-xsrc/usr/diag/prdf/common/plat/mem/prdfMemUtils.H8
-rwxr-xr-xsrc/usr/diag/prdf/common/plat/prdfTargetServices.C95
-rwxr-xr-xsrc/usr/diag/prdf/common/plat/prdfTargetServices.H8
-rw-r--r--src/usr/diag/prdf/common/plugins/prdfParserUtils.C56
-rwxr-xr-xsrc/usr/diag/prdf/plat/mem/prdfMemIplCeStats.C24
-rw-r--r--src/usr/diag/prdf/plat/mem/prdfMemScrubUtils.C127
-rw-r--r--src/usr/diag/prdf/plat/mem/prdfMemTdRankList.H31
13 files changed, 913 insertions, 55 deletions
diff --git a/src/usr/diag/prdf/common/plat/explorer/explorer_ocmb_regs.rule b/src/usr/diag/prdf/common/plat/explorer/explorer_ocmb_regs.rule
new file mode 100644
index 000000000..a4a526124
--- /dev/null
+++ b/src/usr/diag/prdf/common/plat/explorer/explorer_ocmb_regs.rule
@@ -0,0 +1,225 @@
+# IBM_PROLOG_BEGIN_TAG
+# This is an automatically generated prolog.
+#
+# $Source: src/usr/diag/prdf/common/plat/explorer/explorer_ocmb_regs.rule $
+#
+# 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
+###############################################################################
+# Additional registers for ocmb, not defined in XML
+###############################################################################
+
+ ###########################################################################
+ # P9 OCMB Modal Symbol Counter Registers
+ ###########################################################################
+
+ register OCMB_MBSSYMEC0
+ {
+ name "MCP.MCBIST.MBA_SCOMFIR.MBSSYMEC0Q";
+ scomaddr 0x08011858;
+ capture group default;
+ };
+
+ register OCMB_MBSSYMEC1
+ {
+ name "MCP.MCBIST.MBA_SCOMFIR.MBSSYMEC1Q";
+ scomaddr 0x08011859;
+ capture group default;
+ };
+
+ register OCMB_MBSSYMEC2
+ {
+ name "MCP.MCBIST.MBA_SCOMFIR.MBSSYMEC2Q";
+ scomaddr 0x0801185A;
+ capture group default;
+ };
+
+ register OCMB_MBSSYMEC3
+ {
+ name "MCP.MCBIST.MBA_SCOMFIR.MBSSYMEC3Q";
+ scomaddr 0x0801185B;
+ capture group default;
+ };
+
+ register OCMB_MBSSYMEC4
+ {
+ name "MCP.MCBIST.MBA_SCOMFIR.MBSSYMEC4Q";
+ scomaddr 0x0801185C;
+ capture group default;
+ };
+
+ register OCMB_MBSSYMEC5
+ {
+ name "MCP.MCBIST.MBA_SCOMFIR.MBSSYMEC5Q";
+ scomaddr 0x0801185D;
+ capture group default;
+ };
+
+ register OCMB_MBSSYMEC6
+ {
+ name "MCP.MCBIST.MBA_SCOMFIR.MBSSYMEC6Q";
+ scomaddr 0x0801185E;
+ capture group default;
+ };
+
+ register OCMB_MBSSYMEC7
+ {
+ name "MCP.MCBIST.MBA_SCOMFIR.MBSSYMEC7Q";
+ scomaddr 0x0801185F;
+ capture group default;
+ };
+
+ register OCMB_MBSSYMEC8
+ {
+ name "MCP.MCBIST.MBA_SCOMFIR.MBSSYMEC8Q";
+ scomaddr 0x08011860;
+ capture group default;
+ };
+
+ ###########################################################################
+ # P9 OCMB Error Vector Trap registers
+ ###########################################################################
+
+ register MBSEVR0
+ {
+ name "P9 MBS Error Vector Trap reg 0 (port 0)";
+ scomaddr 0x0801187E;
+ capture group default;
+ };
+
+ ############################################################################
+ # MBS Memory Scrub/Read Error Count Registers
+ ############################################################################
+
+ register MBSEC0
+ {
+ name "MCP.MCBIST.MBA_SCOMFIR.MBSEC0Q";
+ scomaddr 0x08011855;
+ capture group default;
+ };
+
+ register MBSEC1
+ {
+ name "MCP.MCBIST.MBA_SCOMFIR.MBSEC1Q";
+ scomaddr 0x08011856;
+ capture group default;
+ };
+
+ register MBSMSEC
+ {
+ name "MCP.MCBIST.MBA_SCOMFIR.MBSMSECQ";
+ scomaddr 0x08011869;
+ capture group default;
+ };
+
+ ###########################################################################
+ # P9 MCBIST command registers
+ ###########################################################################
+
+ register MBSTR
+ {
+ name "P9 MCBIST Memory Scrub/Read Error Threshold Register";
+ scomaddr 0x08011857;
+ capture group default;
+ };
+
+ register MCBAGRA
+ {
+ name "P9 MCBIST Address Generator Configuration Register";
+ scomaddr 0x080118D6;
+ capture group default;
+ };
+
+ register MCBMCAT
+ {
+ name "P9 Maint Current Address Trap Register";
+ scomaddr 0x080118D7;
+ capture group default;
+ };
+
+ register MCB_CNTL
+ {
+ name "P9 MCBIST target MCBIST Control Register";
+ scomaddr 0x080118DB;
+ capture group default;
+ };
+
+ register MCB_CNTLSTAT
+ {
+ name "P9 MCBIST Configured Command Sequence Status Register";
+ scomaddr 0x080118DC;
+ capture group default;
+ };
+
+ ############################################################################
+ # P9 OCMB target RDFFIR
+ ############################################################################
+
+ register RDFFIR_AND
+ {
+ name "Explorer chip RDFFIR AND";
+ scomaddr 0x08011c01;
+ capture group never;
+ access write_only;
+ };
+
+ register RDFFIR_MASK_AND
+ {
+ name "Explorer chip RDFFIR MASK AND";
+ scomaddr 0x08011c04;
+ capture group never;
+ access write_only;
+ };
+
+ register RDFFIR_MASK_OR
+ {
+ name "Explorer chip RDFFIR MASK OR";
+ scomaddr 0x08011c05;
+ capture group never;
+ access write_only;
+ };
+
+ ###########################################################################
+ # P9 OCMB target MCBISTFIR
+ ###########################################################################
+
+ register MCBISTFIR_AND
+ {
+ name "P9 OCMB target MCBISTFIR AND";
+ scomaddr 0x08011801;
+ capture group never;
+ access write_only;
+ };
+
+ register MCBISTFIR_OR
+ {
+ name "P9 OCMB target MCBISTFIR OR";
+ scomaddr 0x08011802;
+ capture group never;
+ access write_only;
+ };
+
+ register MCBISTFIR_MASK_OR
+ {
+ name "P9 OCMB target MCBISTFIR MASK OR";
+ scomaddr 0x08011805;
+ capture group never;
+ access write_only;
+ };
diff --git a/src/usr/diag/prdf/common/plat/mem/prdfMemCeTable.C b/src/usr/diag/prdf/common/plat/mem/prdfMemCeTable.C
index fee4f1ff6..16645586b 100644
--- a/src/usr/diag/prdf/common/plat/mem/prdfMemCeTable.C
+++ b/src/usr/diag/prdf/common/plat/mem/prdfMemCeTable.C
@@ -5,7 +5,7 @@
/* */
/* OpenPOWER HostBoot Project */
/* */
-/* Contributors Listed Below - COPYRIGHT 2013,2018 */
+/* Contributors Listed Below - COPYRIGHT 2013,2019 */
/* [+] International Business Machines Corp. */
/* */
/* */
@@ -281,6 +281,7 @@ void MemCeTable<T>::addCapData( CaptureData & io_cd )
// Avoid linker errors with the template.
template class MemCeTable<TYPE_MCA>;
template class MemCeTable<TYPE_MBA>;
+template class MemCeTable<TYPE_MEM_PORT>;
//------------------------------------------------------------------------------
diff --git a/src/usr/diag/prdf/common/plat/mem/prdfMemSymbol.C b/src/usr/diag/prdf/common/plat/mem/prdfMemSymbol.C
index 7f907206a..561c11dda 100755
--- a/src/usr/diag/prdf/common/plat/mem/prdfMemSymbol.C
+++ b/src/usr/diag/prdf/common/plat/mem/prdfMemSymbol.C
@@ -52,7 +52,8 @@ MemSymbol::MemSymbol( TARGETING::TargetHandle_t i_trgt, const MemRank & i_rank,
{
PRDF_ASSERT( nullptr != i_trgt );
PRDF_ASSERT( TYPE_MBA == getTargetType(i_trgt) ||
- TYPE_MCA == getTargetType(i_trgt) );
+ TYPE_MCA == getTargetType(i_trgt) ||
+ TYPE_MEM_PORT == getTargetType(i_trgt) );
// Allowing an invalid symbol. Use isValid() to check validity.
PRDF_ASSERT( i_pins <= CEN_SYMBOL::BOTH_SYMBOL_DQS );
}
@@ -75,17 +76,23 @@ MemSymbol MemSymbol::fromGalois( TargetHandle_t i_trgt, const MemRank & i_rank,
// Get pins from mask.
uint8_t pins = NO_SYMBOL_DQS;
- if ( TYPE_MBA == getTargetType(i_trgt) )
+ TYPE trgtType = getTargetType( i_trgt );
+ if ( TYPE_MBA == trgtType )
{
// 2 pins for MBA.
if ( 0 != (i_mask & 0xaa) ) pins |= EVEN_SYMBOL_DQ;
if ( 0 != (i_mask & 0x55) ) pins |= ODD_SYMBOL_DQ;
}
- else
+ else if ( TYPE_MCA == trgtType || TYPE_MEM_PORT == trgtType )
{
- // 1 pin for MCA.
+ // 1 pin for MCA/MEM_PORT.
if ( 0 != (i_mask & 0xff) ) pins |= ODD_SYMBOL_DQ;
}
+ else
+ {
+ PRDF_ERR( "MemSymbol::fromGalois: Invalid target type" );
+ PRDF_ASSERT(false);
+ }
return MemSymbol( i_trgt, i_rank, symbol, pins );
}
@@ -94,33 +101,88 @@ MemSymbol MemSymbol::fromGalois( TargetHandle_t i_trgt, const MemRank & i_rank,
uint8_t MemSymbol::getDq() const
{
- bool isMba = TYPE_MBA == getTargetType(iv_trgt);
+ uint8_t dq = DQS_PER_DIMM;
+ TYPE trgtType = getTargetType( iv_trgt );
+
+ if ( TYPE_MBA == trgtType )
+ {
+ dq = symbol2Dq<TYPE_MBA>( iv_symbol );
+ }
+ else if ( TYPE_MCA == trgtType )
+ {
+ dq = symbol2Dq<TYPE_MCA>( iv_symbol );
+ }
+ else if ( TYPE_MEM_PORT == trgtType )
+ {
+ dq = symbol2Dq<TYPE_MEM_PORT>( iv_symbol );
+ }
+ else
+ {
+ PRDF_ERR( "MemSymbol::getDq: Invalid target type." );
+ PRDF_ASSERT( false );
+ }
- return isMba ? symbol2Dq<TYPE_MBA>(iv_symbol)
- : symbol2Dq<TYPE_MCA>(iv_symbol);
+ return dq;
}
//------------------------------------------------------------------------------
uint8_t MemSymbol::getPortSlct() const
{
- bool isMba = TYPE_MBA == getTargetType(iv_trgt);
+ uint8_t portSlct = 0;
+ TYPE trgtType = getTargetType( iv_trgt );
+
+ if ( TYPE_MBA == trgtType )
+ {
+ portSlct = symbol2PortSlct<TYPE_MBA>( iv_symbol );
+ }
+ else if ( TYPE_MCA == trgtType )
+ {
+ portSlct = symbol2PortSlct<TYPE_MCA>( iv_symbol );
+ }
+ else if ( TYPE_MEM_PORT == trgtType )
+ {
+ portSlct = symbol2PortSlct<TYPE_MEM_PORT>( iv_symbol );
+ }
+ else
+ {
+ PRDF_ERR( "MemSymbol::getPortSlct: Invalid target type" );
+ PRDF_ASSERT( false );
+ }
- return isMba ? symbol2PortSlct<TYPE_MBA>(iv_symbol)
- : symbol2PortSlct<TYPE_MCA>(iv_symbol);
+ return portSlct;
}
//------------------------------------------------------------------------------
uint8_t MemSymbol::getDram() const
{
- bool isMba = TYPE_MBA == getTargetType(iv_trgt);
+ uint8_t dram = 0;
+ TYPE trgtType = getTargetType( iv_trgt );
bool isX4 = isDramWidthX4( iv_trgt );
- return isMba ? isX4 ? symbol2Nibble<TYPE_MBA>( iv_symbol )
- : symbol2Byte <TYPE_MBA>( iv_symbol )
- : isX4 ? symbol2Nibble<TYPE_MCA>( iv_symbol )
- : symbol2Byte <TYPE_MCA>( iv_symbol );
+ if ( TYPE_MBA == trgtType )
+ {
+ dram = isX4 ? symbol2Nibble<TYPE_MBA>( iv_symbol )
+ : symbol2Byte <TYPE_MBA>( iv_symbol );
+ }
+ else if ( TYPE_MCA == trgtType )
+ {
+ dram = isX4 ? symbol2Nibble<TYPE_MCA>( iv_symbol )
+ : symbol2Byte <TYPE_MCA>( iv_symbol );
+ }
+ else if ( TYPE_MEM_PORT == trgtType )
+ {
+ dram = isX4 ? symbol2Nibble<TYPE_MEM_PORT>( iv_symbol )
+ : symbol2Byte <TYPE_MEM_PORT>( iv_symbol );
+ }
+ else
+ {
+ PRDF_ERR( "MemSymbol::getDram: Invalid target type" );
+ PRDF_ASSERT( false );
+ }
+
+ return dram;
}
//------------------------------------------------------------------------------
@@ -168,12 +230,27 @@ uint8_t MemSymbol::getDramRelCenDqs() const
uint8_t MemSymbol::getDramPins() const
{
- bool isMba = TYPE_MBA == getTargetType(iv_trgt);
+ TYPE trgtType = getTargetType( iv_trgt );
bool isX4 = isDramWidthX4( iv_trgt );
- uint32_t dps = isMba ? MBA_DQS_PER_SYMBOL : MEM_DQS_PER_SYMBOL;
- uint32_t spd = isMba ? isX4 ? MBA_SYMBOLS_PER_NIBBLE : MBA_SYMBOLS_PER_BYTE
- : isX4 ? MEM_SYMBOLS_PER_NIBBLE : MEM_SYMBOLS_PER_BYTE;
+ uint32_t dps = 0;
+ uint32_t spd = 0;
+
+ if ( TYPE_MBA == trgtType )
+ {
+ dps = MBA_DQS_PER_SYMBOL;
+ spd = isX4 ? MBA_SYMBOLS_PER_NIBBLE : MBA_SYMBOLS_PER_BYTE;
+ }
+ else if ( TYPE_MCA == trgtType || TYPE_MEM_PORT == trgtType )
+ {
+ dps = MEM_DQS_PER_SYMBOL;
+ spd = isX4 ? MEM_SYMBOLS_PER_NIBBLE : MEM_SYMBOLS_PER_BYTE;
+ }
+ else
+ {
+ PRDF_ERR( "MemSymbol::getDramPins: Invalid target type" );
+ PRDF_ASSERT( false );
+ }
return iv_pins << (((spd - 1) - (iv_symbol % spd)) * dps);
}
@@ -182,14 +259,33 @@ uint8_t MemSymbol::getDramPins() const
uint8_t MemSymbol::getDramSymbol() const
{
- bool isMba = TYPE_MBA == getTargetType(iv_trgt);
+ uint8_t dramSymbol = SYMBOLS_PER_RANK;
+ TYPE trgtType = getTargetType( iv_trgt );
bool isX4 = isDramWidthX4( iv_trgt );
uint8_t dram = getDram();
- return isMba ? isX4 ? nibble2Symbol<TYPE_MBA>( dram )
- : byte2Symbol <TYPE_MBA>( dram )
- : isX4 ? nibble2Symbol<TYPE_MCA>( dram )
- : byte2Symbol <TYPE_MCA>( dram );
+ if ( TYPE_MBA == trgtType )
+ {
+ dramSymbol = isX4 ? nibble2Symbol<TYPE_MBA>( dram )
+ : byte2Symbol <TYPE_MBA>( dram );
+ }
+ else if ( TYPE_MCA == trgtType )
+ {
+ dramSymbol = isX4 ? nibble2Symbol<TYPE_MCA>( dram )
+ : byte2Symbol <TYPE_MCA>( dram );
+ }
+ else if ( TYPE_MEM_PORT == trgtType )
+ {
+ dramSymbol = isX4 ? nibble2Symbol<TYPE_MEM_PORT>( dram )
+ : byte2Symbol <TYPE_MEM_PORT>( dram );
+ }
+ else
+ {
+ PRDF_ERR( "MemSymbol::getDramSymbol: Invalid target type" );
+ PRDF_ASSERT( false );
+ }
+
+ return dramSymbol;
}
//------------------------------------------------------------------------------
@@ -230,7 +326,7 @@ uint32_t getMemReadSymbol<TYPE_MCA>( ExtensibleChip * i_chip,
const MemRank & i_rank,
MemSymbol & o_sym1, MemSymbol & o_sym2 )
{
- #define PRDF_FUNC "[getMemReadSymbol<TYPE_MBA>] "
+ #define PRDF_FUNC "[getMemReadSymbol<TYPE_MCA>] "
// Check parameters
PRDF_ASSERT( nullptr != i_chip );
@@ -338,4 +434,70 @@ uint32_t getMemReadSymbol<TYPE_MBA>( ExtensibleChip * i_chip,
//------------------------------------------------------------------------------
+template<>
+uint32_t getMemReadSymbol<TYPE_MEM_PORT>( ExtensibleChip * i_chip,
+ const MemRank & i_rank,
+ MemSymbol & o_sym1,
+ MemSymbol & o_sym2 )
+{
+ #define PRDF_FUNC "[getMemReadSymbol<TYPE_MEM_PORT>] "
+
+ // Check parameters
+ PRDF_ASSERT( nullptr != i_chip );
+ PRDF_ASSERT( TYPE_MEM_PORT == i_chip->getType() );
+
+ uint32_t o_rc = SUCCESS;
+
+ o_sym1 = o_sym2 = MemSymbol(); // both initially invalid
+
+ do
+ {
+ // Get the NCE/TCE galois and mask from hardware.
+ ExtensibleChip * ocmbChip = getConnectedParent(i_chip, TYPE_OCMB_CHIP);
+
+ SCAN_COMM_REGISTER_CLASS * reg = ocmbChip->getRegister("MBSEVR0");
+ o_rc = reg->Read();
+ if ( SUCCESS != o_rc )
+ {
+ PRDF_ERR( PRDF_FUNC "Read() failed on MBSEVR0: "
+ "ocmbChip=0x%08x", ocmbChip->getHuid() );
+ break;
+ }
+
+ // MBSEVR[0:7] = mainline NCE galois field
+ // MBSEVR[8:15] = mainline NCE mask field
+ // MBSEVR[16:23] = mainline TCE galois field
+ // MBSEVR[24:31] = mainline TCE mask field
+ uint8_t nceGalois = reg->GetBitFieldJustified( 0, 8 );
+ uint8_t nceMask = reg->GetBitFieldJustified( 8, 8 );
+ uint8_t tceGalois = reg->GetBitFieldJustified( 16, 8 );
+ uint8_t tceMask = reg->GetBitFieldJustified( 24, 8 );
+
+ // Get the NCE/TCE symbol.
+ o_sym1 = MemSymbol::fromGalois( i_chip->getTrgt(), i_rank,
+ nceGalois, nceMask );
+ o_sym2 = MemSymbol::fromGalois( i_chip->getTrgt(), i_rank,
+ tceGalois, tceMask );
+
+ MemSymbol sp0, sp1, ecc;
+ o_rc = mssGetSteerMux<TYPE_MEM_PORT>( i_chip->getTrgt(), i_rank,
+ sp0, sp1, ecc );
+ if ( SUCCESS != o_rc )
+ {
+ PRDF_ERR( PRDF_FUNC "mssGetSteerMux() failed. HUID: 0x%08x "
+ "rank: 0x%02x", i_chip->getHuid(), i_rank.getKey() );
+ break;
+ }
+ o_sym1.updateSpared(sp0, sp1, ecc);
+ o_sym2.updateSpared(sp0, sp1, ecc);
+
+ } while (0);
+
+ return o_rc;
+
+ #undef PRDF_FUNC
+}
+
+//------------------------------------------------------------------------------
+
} // end namespace PRDF
diff --git a/src/usr/diag/prdf/common/plat/mem/prdfMemSymbol.H b/src/usr/diag/prdf/common/plat/mem/prdfMemSymbol.H
index 04b2bfce0..c16972fd8 100755
--- a/src/usr/diag/prdf/common/plat/mem/prdfMemSymbol.H
+++ b/src/usr/diag/prdf/common/plat/mem/prdfMemSymbol.H
@@ -5,7 +5,7 @@
/* */
/* OpenPOWER HostBoot Project */
/* */
-/* Contributors Listed Below - COPYRIGHT 2013,2018 */
+/* Contributors Listed Below - COPYRIGHT 2013,2019 */
/* [+] International Business Machines Corp. */
/* */
/* */
@@ -79,7 +79,7 @@ class MemSymbol
/**
* @brief Creates a MemSymbol from a symbol.
- * @param i_trgt MBA or MCA target.
+ * @param i_trgt MBA, MCA, or MEM_PORT target.
* @param i_rank The rank this symbol is on.
* @param i_symbol The input symbol.
* @param i_pins See enum DqMask.
@@ -95,7 +95,7 @@ class MemSymbol
/**
* @brief Creates a MemSymbol from a Galois field.
- * @param i_trgt MBA or MCA target.
+ * @param i_trgt MBA, MCA, or MEM_PORT target.
* @param i_rank The rank this symbol is on.
* @param i_galois The Galois field.
* @param i_mask The bit mask.
@@ -122,7 +122,7 @@ class MemSymbol
MemRank getRank() const { return iv_rank; };
/** @return The port select for this symbol. Only relevant on MBA. Will
- * always return 0 for MCA. */
+ * always return 0 for MCA and MEM_PORT. */
uint8_t getPortSlct() const;
/** @return The DRAM index for this symbol. */
@@ -218,7 +218,7 @@ class MemSymbol
/**
* @brief Reads the memory NCE/TCE vector trap register from hardware.
- * @param i_chip MCA or MBA.
+ * @param i_chip MCA, MBA, or MEM_PORT.
* @param i_rank The rank this symbol is on.
* @param o_sym1 The first symbol. Should always be valid for both NCE/TCE.
* @param o_sym2 The second symbol. Only valid for TCEs.
diff --git a/src/usr/diag/prdf/common/plat/mem/prdfMemThresholds.C b/src/usr/diag/prdf/common/plat/mem/prdfMemThresholds.C
index 3142df3e3..f6403f219 100755
--- a/src/usr/diag/prdf/common/plat/mem/prdfMemThresholds.C
+++ b/src/usr/diag/prdf/common/plat/mem/prdfMemThresholds.C
@@ -5,7 +5,7 @@
/* */
/* OpenPOWER HostBoot Project */
/* */
-/* Contributors Listed Below - COPYRIGHT 2013,2017 */
+/* Contributors Listed Below - COPYRIGHT 2013,2019 */
/* [+] International Business Machines Corp. */
/* */
/* */
@@ -203,12 +203,16 @@ template
void getMnfgMemCeTh<TYPE_MCA>( ExtensibleChip * i_chip, const MemRank & i_rank,
uint32_t & o_cePerDram, uint32_t & o_cePerRank,
uint32_t & o_cePerDimm );
-
template
void getMnfgMemCeTh<TYPE_MBA>( ExtensibleChip * i_chip, const MemRank & i_rank,
uint32_t & o_cePerDram, uint32_t & o_cePerRank,
uint32_t & o_cePerDimm );
+template
+void getMnfgMemCeTh<TYPE_MEM_PORT>( ExtensibleChip * i_chip,
+ const MemRank & i_rank, uint32_t & o_cePerDram, uint32_t & o_cePerRank,
+ uint32_t & o_cePerDimm );
+
//------------------------------------------------------------------------------
template <TYPE T>
@@ -237,6 +241,9 @@ uint32_t getScrubCeThreshold<TYPE_MCA>( ExtensibleChip * i_chip,
template
uint32_t getScrubCeThreshold<TYPE_MBA>( ExtensibleChip * i_chip,
const MemRank & i_rank );
+template
+uint32_t getScrubCeThreshold<TYPE_MEM_PORT>( ExtensibleChip * i_chip,
+ const MemRank & i_rank );
} // end namespace PRDF
diff --git a/src/usr/diag/prdf/common/plat/mem/prdfMemUtils.C b/src/usr/diag/prdf/common/plat/mem/prdfMemUtils.C
index 57d43d6ad..744e55e69 100755
--- a/src/usr/diag/prdf/common/plat/mem/prdfMemUtils.C
+++ b/src/usr/diag/prdf/common/plat/mem/prdfMemUtils.C
@@ -78,6 +78,12 @@ static const char *mcbCeStatReg[CE_REGS_PER_PORT] =
"MCB_MBSSYMEC6", "MCB_MBSSYMEC7", "MCB_MBSSYMEC8"
};
+static const char *ocmbCeStatReg[CE_REGS_PER_PORT] =
+ {
+ "OCMB_MBSSYMEC0", "OCMB_MBSSYMEC1", "OCMB_MBSSYMEC2",
+ "OCMB_MBSSYMEC3", "OCMB_MBSSYMEC4", "OCMB_MBSSYMEC5",
+ "OCMB_MBSSYMEC6", "OCMB_MBSSYMEC7", "OCMB_MBSSYMEC8"
+ };
//------------------------------------------------------------------------------
// Helper structs for collectCeStats()
@@ -89,6 +95,7 @@ struct DramCount_t
typedef std::map<uint32_t, DramCount_t> DramCountMap;
//------------------------------------------------------------------------------
+
template<>
int32_t collectCeStats<TYPE_MCA>( ExtensibleChip * i_chip,
const MemRank & i_rank, MaintSymbols & o_maintStats,
@@ -216,6 +223,134 @@ int32_t collectCeStats<TYPE_MCA>( ExtensibleChip * i_chip,
}
//------------------------------------------------------------------------------
+template<>
+int32_t collectCeStats<TYPE_MEM_PORT>( ExtensibleChip * i_chip,
+ const MemRank & i_rank,
+ MaintSymbols & o_maintStats,
+ MemSymbol & o_chipMark, uint8_t i_thr )
+{
+ #define PRDF_FUNC "[MemUtils::collectCeStats<TYPE_MEM_PORT>] "
+
+ int32_t o_rc = SUCCESS;
+ o_chipMark = MemSymbol(); // Initially invalid.
+
+ do
+ {
+ PRDF_ASSERT( 0 != i_thr );
+
+ TargetHandle_t memPortTrgt = i_chip->getTrgt();
+ ExtensibleChip * ocmbChip = getConnectedParent(i_chip, TYPE_OCMB_CHIP);
+
+ const bool isX4 = isDramWidthX4(memPortTrgt);
+
+ // Use this map to keep track of the total counts per DRAM.
+ DramCountMap dramCounts;
+
+ const char * reg_str = NULL;
+ SCAN_COMM_REGISTER_CLASS * reg = NULL;
+
+ for ( uint8_t regIdx = 0; regIdx < CE_REGS_PER_PORT; regIdx++ )
+ {
+ reg_str = ocmbCeStatReg[regIdx];
+ reg = ocmbChip->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++ )
+ {
+ uint8_t count = reg->GetBitFieldJustified( (i*8), 8 );
+
+ if ( 0 == count ) continue; // nothing to do
+
+ uint8_t sym = baseSymbol + i;
+ PRDF_ASSERT( sym < SYMBOLS_PER_RANK );
+
+ uint8_t dram = isX4 ? symbol2Nibble<TYPE_MEM_PORT>( sym )
+ : symbol2Byte <TYPE_MEM_PORT>( sym );
+
+ // Keep track of the total DRAM counts.
+ dramCounts[dram].totalCount += count;
+
+ // Add any symbols that have exceeded threshold to the list.
+ if ( i_thr <= count )
+ {
+ // Keep track of the total number of symbols per DRAM that
+ // have exceeded threshold.
+ dramCounts[dram].symbolCount++;
+
+ SymbolData symData;
+ symData.symbol = MemSymbol::fromSymbol( memPortTrgt, i_rank,
+ sym, CEN_SYMBOL::ODD_SYMBOL_DQ );
+ if ( !symData.symbol.isValid() )
+ {
+ PRDF_ERR( PRDF_FUNC "MemSymbol() failed: symbol=%d",
+ sym );
+ o_rc = FAIL;
+ break;
+ }
+ else
+ {
+ // Add the symbol to the list.
+ symData.count = count;
+ o_maintStats.push_back( symData );
+ }
+ }
+ }
+ if ( SUCCESS != o_rc ) break;
+ }
+ if ( SUCCESS != o_rc ) break;
+
+ if ( o_maintStats.empty() ) break; // no need to continue
+
+ // Sort the list of symbols.
+ std::sort( o_maintStats.begin(), o_maintStats.end(), sortSymDataCount );
+
+ // Get the DRAM with the highest count.
+ uint32_t highestDram = 0;
+ uint32_t highestCount = 0;
+ const uint32_t symbolTH = isX4 ? 1 : 2;
+ for ( DramCountMap::iterator it = dramCounts.begin();
+ it != dramCounts.end(); ++it )
+ {
+ if ( (symbolTH <= it->second.symbolCount) &&
+ (highestCount < it->second.totalCount ) )
+ {
+ highestDram = it->first;
+ highestCount = it->second.totalCount;
+ }
+ }
+
+ if ( 0 != highestCount )
+ {
+ uint8_t sym = isX4 ? nibble2Symbol<TYPE_MEM_PORT>( highestDram )
+ : byte2Symbol <TYPE_MEM_PORT>( highestDram );
+ PRDF_ASSERT( sym < SYMBOLS_PER_RANK );
+
+ o_chipMark = MemSymbol::fromSymbol( memPortTrgt, i_rank, sym );
+ }
+
+ } while(0);
+
+ if ( SUCCESS != o_rc )
+ {
+ PRDF_ERR( PRDF_FUNC "Failed: i_chip=0x%08x i_rank=m%ds%d i_thr=%d",
+ i_chip->GetId(), i_rank.getMaster(), i_rank.getSlave(),
+ i_thr );
+ }
+
+ return o_rc;
+
+ #undef PRDF_FUNC
+}
+
+//------------------------------------------------------------------------------
template<>
int32_t collectCeStats<TYPE_MBA>( ExtensibleChip * i_chip,
@@ -443,6 +578,29 @@ uint8_t getDramSize<TYPE_MBA>(ExtensibleChip *i_chip, uint8_t i_dimmSlct)
#undef PRDF_FUNC
}
+template<>
+uint8_t getDramSize<TYPE_MEM_PORT>(ExtensibleChip *i_chip, uint8_t i_dimmSlct)
+{
+ #define PRDF_FUNC "[MemUtils::getDramSize] "
+
+ PRDF_ASSERT( TYPE_MEM_PORT == i_chip->getType() );
+ PRDF_ASSERT( i_dimmSlct < DIMM_SLCT_PER_PORT );
+
+ TargetHandle_t memPortTrgt = i_chip->getTrgt();
+
+ uint8_t tmp[DIMM_SLCT_PER_PORT];
+
+ if ( !memPortTrgt->tryGetAttr<TARGETING::ATTR_MEM_EFF_DRAM_DENSITY>(tmp) )
+ {
+ PRDF_ERR( PRDF_FUNC "Failed to get ATTR_MEM_EFF_DRAM_DENSITY" );
+ PRDF_ASSERT( false );
+ }
+
+ return tmp[i_dimmSlct];
+
+ #undef PRDF_FUNC
+}
+
//------------------------------------------------------------------------------
template<>
diff --git a/src/usr/diag/prdf/common/plat/mem/prdfMemUtils.H b/src/usr/diag/prdf/common/plat/mem/prdfMemUtils.H
index 530706f68..9759cd010 100755
--- a/src/usr/diag/prdf/common/plat/mem/prdfMemUtils.H
+++ b/src/usr/diag/prdf/common/plat/mem/prdfMemUtils.H
@@ -5,7 +5,7 @@
/* */
/* OpenPOWER HostBoot Project */
/* */
-/* Contributors Listed Below - COPYRIGHT 2013,2018 */
+/* Contributors Listed Below - COPYRIGHT 2013,2019 */
/* [+] International Business Machines Corp. */
/* */
/* */
@@ -73,7 +73,7 @@ inline bool sortSymDataCount( const SymbolData & i, const SymbolData & j )
* @brief Queries the per symbol counters and returns a sorted list of symbols
* with a count greater than or equal to the given threshold.
* @note The returned list will be sorted from lowest count to highest count.
- * @param i_chip Target mba or mca chip.
+ * @param i_chip Target mba, mca, or mem_port chip.
* @param i_rank Target rank.
* @param o_maintStats Returns the list of symbols and counts.
* @param o_chipMark This represents the DRAM in which a chip mark should be
@@ -101,8 +101,8 @@ int32_t collectCeStats( ExtensibleChip * i_chip, const MemRank & i_rank,
uint8_t i_thr = 1 );
/**
- * @brief Gets DRAM size for an MBA or MCA.
- * @param i_chip MBA or MCA chip.
+ * @brief Gets DRAM size for an MBA, MCA, or MEM_PORT.
+ * @param i_chip MBA, MCA, or MEM_PORT chip.
* @param i_dimmSlct DIMM select. Optional for MBA chip.
* @return size for a DRAM
*/
diff --git a/src/usr/diag/prdf/common/plat/prdfTargetServices.C b/src/usr/diag/prdf/common/plat/prdfTargetServices.C
index b296bcbb0..65f8b9cdc 100755
--- a/src/usr/diag/prdf/common/plat/prdfTargetServices.C
+++ b/src/usr/diag/prdf/common/plat/prdfTargetServices.C
@@ -1527,11 +1527,31 @@ void __getMasterRanks( TargetHandle_t i_trgt, std::vector<MemRank> & o_ranks,
PRDF_ASSERT( false ); // attribute does not exist for target
}
}
- else if ( !i_trgt->tryGetAttr<ATTR_EFF_DIMM_RANKS_CONFIGED>(info) )
+ else if ( MODEL_NIMBUS == l_procModel )
{
- PRDF_ERR( PRDF_FUNC "tryGetAttr<ATTR_EFF_DIMM_RANKS_CONFIGED> "
- "failed: i_trgt=0x%08x", getHuid(i_trgt) );
- PRDF_ASSERT( false ); // attribute does not exist for target
+ if ( !i_trgt->tryGetAttr<ATTR_EFF_DIMM_RANKS_CONFIGED>(info) )
+ {
+ PRDF_ERR( PRDF_FUNC "tryGetAttr<ATTR_EFF_DIMM_RANKS_CONFIGED> "
+ "failed: i_trgt=0x%08x", getHuid(i_trgt) );
+ PRDF_ASSERT( false ); // attribute does not exist for target
+ }
+ }
+ else if ( MODEL_AXONE == l_procModel )
+ {
+ PRDF_ERR( PRDF_FUNC "Axone attribute not supported yet" );
+ /* TODO RTC 207273 - no targeting support for attr yet
+ if ( !i_trgt->tryGetAttr<ATTR_MEM_EFF_DIMM_RANKS_CONFIGED>(info[0]) )
+ {
+ PRDF_ERR( PRDF_FUNC "tryGetAttr<ATTR_MEM_EFF_DIMM_RANKS_CONFIGED> "
+ "failed: i_trgt=0x%08x", getHuid(i_trgt) );
+ PRDF_ASSERT( false ); // attribute does not exist for target
+ }
+ */
+ }
+ else
+ {
+ PRDF_ERR( PRDF_FUNC "Invalid proc type" );
+ PRDF_ASSERT(false);
}
for ( uint32_t ds = 0; ds < MAX_DIMM_PER_PORT; ds++ )
@@ -1589,8 +1609,7 @@ void getMasterRanks<TYPE_MEM_PORT>( TargetHandle_t i_trgt,
std::vector<MemRank> & o_ranks,
uint8_t i_ds )
{
- // TODO RTC 207273 - no support for ATTR_EFF_DIMM_RANKS_CONFIGED attr yet
- //__getMasterRanks<TYPE_MEM_PORT>( i_trgt, o_ranks, 0, i_ds );
+ __getMasterRanks<TYPE_MEM_PORT>( i_trgt, o_ranks, 0, i_ds );
}
//------------------------------------------------------------------------------
@@ -1653,6 +1672,14 @@ void getSlaveRanks<TYPE_MBA>( TargetHandle_t i_trgt,
__getSlaveRanks<TYPE_MBA>( i_trgt, o_ranks, i_ds );
}
+template<>
+void getSlaveRanks<TYPE_MEM_PORT>( TargetHandle_t i_trgt,
+ std::vector<MemRank> & o_ranks,
+ uint8_t i_ds )
+{
+ __getSlaveRanks<TYPE_MEM_PORT>( i_trgt, o_ranks, i_ds );
+}
+
//------------------------------------------------------------------------------
template<TARGETING::TYPE T>
@@ -1665,7 +1692,7 @@ uint8_t __getNumMasterRanksPerDimm( TargetHandle_t i_trgt,
PRDF_ASSERT( T == getTargetType(i_trgt) );
PRDF_ASSERT( i_pos < 2 );
PRDF_ASSERT( i_ds < MAX_DIMM_PER_PORT );
- uint8_t num;
+ uint8_t num = 0;
ATTR_MODEL_type l_procModel = getChipModel( getMasterProc() );
@@ -1682,7 +1709,7 @@ uint8_t __getNumMasterRanksPerDimm( TargetHandle_t i_trgt,
num = attr[i_pos][i_ds];
}
- else
+ else if ( MODEL_NIMBUS == l_procModel )
{
ATTR_EFF_NUM_MASTER_RANKS_PER_DIMM_type attr;
if ( !i_trgt->tryGetAttr<ATTR_EFF_NUM_MASTER_RANKS_PER_DIMM>(attr) )
@@ -1695,6 +1722,24 @@ uint8_t __getNumMasterRanksPerDimm( TargetHandle_t i_trgt,
num = attr[i_pos][i_ds];
}
+ else if ( MODEL_AXONE == l_procModel )
+ {
+ ATTR_MEM_EFF_NUM_MASTER_RANKS_PER_DIMM_type attr;
+ if ( !i_trgt->tryGetAttr<ATTR_MEM_EFF_NUM_MASTER_RANKS_PER_DIMM>(attr) )
+ {
+ PRDF_ERR( PRDF_FUNC
+ "tryGetAttr<ATTR_MEM_EFF_NUM_MASTER_RANKS_PER_DIMM> "
+ "failed: i_trgt=0x%08x", getHuid(i_trgt) );
+ PRDF_ASSERT( false ); // attribute does not exist for target
+ }
+
+ num = attr[i_ds];
+ }
+ else
+ {
+ PRDF_ERR( PRDF_FUNC "Invalid proc type" );
+ PRDF_ASSERT(false);
+ }
PRDF_ASSERT( num <= MASTER_RANKS_PER_DIMM_SLCT );
@@ -1728,6 +1773,13 @@ uint8_t getNumMasterRanksPerDimm<TYPE_MBA>( TargetHandle_t i_trgt,
return __getNumMasterRanksPerDimm<TYPE_MBA>( i_trgt, 0, i_ds );
}
+template<>
+uint8_t getNumMasterRanksPerDimm<TYPE_MEM_PORT>( TargetHandle_t i_trgt,
+ uint8_t i_ds )
+{
+ return __getNumMasterRanksPerDimm<TYPE_MEM_PORT>( i_trgt, 0, i_ds );
+}
+
//------------------------------------------------------------------------------
template<TARGETING::TYPE T>
@@ -1740,7 +1792,7 @@ uint8_t __getNumRanksPerDimm( TargetHandle_t i_trgt,
PRDF_ASSERT( T == getTargetType(i_trgt) );
PRDF_ASSERT( i_pos < 2 );
PRDF_ASSERT( i_ds < MAX_DIMM_PER_PORT );
- uint8_t num;
+ uint8_t num = 0;
ATTR_MODEL_type l_procModel = getChipModel( getMasterProc() );
if ( MODEL_CUMULUS == l_procModel )
@@ -1756,7 +1808,7 @@ uint8_t __getNumRanksPerDimm( TargetHandle_t i_trgt,
num = attr[i_pos][i_ds];
}
- else
+ else if ( MODEL_NIMBUS == l_procModel )
{
ATTR_EFF_NUM_RANKS_PER_DIMM_type attr;
if ( !i_trgt->tryGetAttr<ATTR_EFF_NUM_RANKS_PER_DIMM>(attr) )
@@ -1768,6 +1820,23 @@ uint8_t __getNumRanksPerDimm( TargetHandle_t i_trgt,
num = attr[i_pos][i_ds];
}
+ else if ( MODEL_AXONE == l_procModel )
+ {
+ ATTR_MEM_EFF_NUM_RANKS_PER_DIMM_type attr;
+ if ( !i_trgt->tryGetAttr<ATTR_MEM_EFF_NUM_RANKS_PER_DIMM>(attr) )
+ {
+ PRDF_ERR( PRDF_FUNC "tryGetAttr<ATTR_MEM_EFF_NUM_RANKS_PER_DIMM> "
+ "failed: i_trgt=0x%08x", getHuid(i_trgt) );
+ PRDF_ASSERT( false ); // attribute does not exist for target
+ }
+
+ num = attr[i_ds];
+ }
+ else
+ {
+ PRDF_ERR( PRDF_FUNC "Invalid proc type" );
+ PRDF_ASSERT(false);
+ }
PRDF_ASSERT( num < MASTER_RANKS_PER_DIMM_SLCT*SLAVE_RANKS_PER_MASTER_RANK );
@@ -1799,6 +1868,12 @@ uint8_t getNumRanksPerDimm<TYPE_MBA>( TargetHandle_t i_trgt, uint8_t i_ds )
return __getNumRanksPerDimm<TYPE_MBA>( i_trgt, 0, i_ds );
}
+template<>
+uint8_t getNumRanksPerDimm<TYPE_MEM_PORT>( TargetHandle_t i_trgt, uint8_t i_ds )
+{
+ return __getNumRanksPerDimm<TYPE_MEM_PORT>( i_trgt, 0, i_ds );
+}
+
//##############################################################################
//##
//## Clock specific functions
diff --git a/src/usr/diag/prdf/common/plat/prdfTargetServices.H b/src/usr/diag/prdf/common/plat/prdfTargetServices.H
index b69806736..8793e8c61 100755
--- a/src/usr/diag/prdf/common/plat/prdfTargetServices.H
+++ b/src/usr/diag/prdf/common/plat/prdfTargetServices.H
@@ -434,7 +434,7 @@ uint8_t getColNumConfig( TARGETING::TargetHandle_t i_trgt );
/**
* @brief Returns a sorted list of configured master ranks for an MCA or MBA.
- * @param i_trgt MCA or MBA target.
+ * @param i_trgt MCA, MBA, or MEM_PORT target.
* @param o_ranks The returned list.
* @param i_ds When used, this function will only return the list of ranks
* for the target DIMM select. Otherwise, the default is to
@@ -450,7 +450,7 @@ void getMasterRanks( TARGETING::TargetHandle_t i_trgt,
/**
* @brief Returns a sorted list of configured slave ranks for an MCA or MBA.
- * @param i_trgt MCA or MBA target.
+ * @param i_trgt MCA, MBA, or MEM_PORT target.
* @param o_ranks The returned list.
* @param i_ds When used, this function will only return the list of ranks
* for the target DIMM select. Otherwise, the default is to
@@ -466,7 +466,7 @@ void getSlaveRanks( TARGETING::TargetHandle_t i_trgt,
/**
* @brief Obtains the number of master ranks per DIMM select.
- * @param i_trgt MCA or MBA target.
+ * @param i_trgt MCA, MBA, or MEM_PORT target.
* @param i_ds DIMM select.
* @return Total number of master ranks configured per DIMM select.
*/
@@ -477,7 +477,7 @@ uint8_t getNumMasterRanksPerDimm( TARGETING::TargetHandle_t i_trgt,
/**
* @brief Obtains the total number of ranks (including slave ranks) per DIMM
* select.
- * @param i_trgt MCA or MBA target.
+ * @param i_trgt MCA, MBA, or MEM_PORT target.
* @param i_ds DIMM select.
* @return Total number of ranks configured per DIMM select.
*/
diff --git a/src/usr/diag/prdf/common/plugins/prdfParserUtils.C b/src/usr/diag/prdf/common/plugins/prdfParserUtils.C
index c2ccd38f2..9d2233e75 100644
--- a/src/usr/diag/prdf/common/plugins/prdfParserUtils.C
+++ b/src/usr/diag/prdf/common/plugins/prdfParserUtils.C
@@ -87,6 +87,15 @@ uint8_t symbol2Dq<TARGETING::TYPE_MCA>( uint8_t i_symbol )
//------------------------------------------------------------------------------
template<>
+uint8_t symbol2Dq<TARGETING::TYPE_MEM_PORT>( uint8_t i_symbol )
+{
+ // MEM_PORT case is identical to MCA
+ return symbol2Dq<TARGETING::TYPE_MCA>(i_symbol);
+}
+
+//------------------------------------------------------------------------------
+
+template<>
uint8_t symbol2PortSlct<TARGETING::TYPE_MBA>( uint8_t i_symbol )
{
uint8_t portSlct = MAX_PORT_PER_MBA;
@@ -113,6 +122,16 @@ uint8_t symbol2PortSlct<TARGETING::TYPE_MCA>( uint8_t i_symbol )
//------------------------------------------------------------------------------
template<>
+uint8_t symbol2PortSlct<TARGETING::TYPE_MEM_PORT>( uint8_t i_symbol )
+{
+ // Port select does not exist on MEM_PORT. Always return 0 so that code will
+ // continue to work.
+ return 0;
+}
+
+//------------------------------------------------------------------------------
+
+template<>
uint8_t dq2Symbol<TARGETING::TYPE_MBA>( uint8_t i_dq, uint8_t i_ps )
{
uint8_t sym = SYMBOLS_PER_RANK;
@@ -199,6 +218,15 @@ uint8_t nibble2Symbol<TARGETING::TYPE_MCA>( uint8_t i_x4Dram )
//------------------------------------------------------------------------------
template<>
+uint8_t nibble2Symbol<TARGETING::TYPE_MEM_PORT>( uint8_t i_x4Dram )
+{
+ // MEM_PORT case is identical to MCA
+ return nibble2Symbol<TARGETING::TYPE_MCA>(i_x4Dram);
+}
+
+//------------------------------------------------------------------------------
+
+template<>
uint8_t byte2Symbol<TARGETING::TYPE_MBA>( uint8_t i_x8Dram )
{
return (MBA_BYTES_PER_RANK > i_x8Dram) ? (i_x8Dram * MBA_SYMBOLS_PER_BYTE)
@@ -230,6 +258,15 @@ uint8_t byte2Symbol<TARGETING::TYPE_MCA>( uint8_t i_x8Dram )
//------------------------------------------------------------------------------
template<>
+uint8_t byte2Symbol<TARGETING::TYPE_MEM_PORT>( uint8_t i_x8Dram )
+{
+ // MEM_PORT case is identical to MCA
+ return byte2Symbol<TARGETING::TYPE_MCA>(i_x8Dram);
+}
+
+//------------------------------------------------------------------------------
+
+template<>
uint8_t symbol2Nibble<TARGETING::TYPE_MBA>( uint8_t i_symbol )
{
return (SYMBOLS_PER_RANK > i_symbol) ? (i_symbol / MBA_SYMBOLS_PER_NIBBLE)
@@ -249,6 +286,15 @@ uint8_t symbol2Nibble<TARGETING::TYPE_MCA>( uint8_t i_symbol )
//------------------------------------------------------------------------------
template<>
+uint8_t symbol2Nibble<TARGETING::TYPE_MEM_PORT>( uint8_t i_symbol )
+{
+ // MEM_PORT case is identical to MCA
+ return symbol2Nibble<TARGETING::TYPE_MCA>(i_symbol);
+}
+
+//------------------------------------------------------------------------------
+
+template<>
uint8_t symbol2Byte<TARGETING::TYPE_MBA>( uint8_t i_symbol )
{
return (SYMBOLS_PER_RANK > i_symbol) ? (i_symbol / MBA_SYMBOLS_PER_BYTE)
@@ -265,6 +311,16 @@ uint8_t symbol2Byte<TARGETING::TYPE_MCA>( uint8_t i_symbol )
: MEM_BYTES_PER_RANK;
}
+//------------------------------------------------------------------------------
+
+template<>
+uint8_t symbol2Byte<TARGETING::TYPE_MEM_PORT>( uint8_t i_symbol )
+{
+ // MEM_PORT case is identical to MCA
+ return symbol2Byte<TARGETING::TYPE_MCA>(i_symbol);
+}
+
+//------------------------------------------------------------------------------
/**
* @brief Find the first symbol of the given DRAM index
diff --git a/src/usr/diag/prdf/plat/mem/prdfMemIplCeStats.C b/src/usr/diag/prdf/plat/mem/prdfMemIplCeStats.C
index 0ae5cec80..869aa92e8 100755
--- a/src/usr/diag/prdf/plat/mem/prdfMemIplCeStats.C
+++ b/src/usr/diag/prdf/plat/mem/prdfMemIplCeStats.C
@@ -5,7 +5,7 @@
/* */
/* OpenPOWER HostBoot Project */
/* */
-/* Contributors Listed Below - COPYRIGHT 2013,2018 */
+/* Contributors Listed Below - COPYRIGHT 2013,2019 */
/* [+] International Business Machines Corp. */
/* */
/* */
@@ -83,6 +83,19 @@ void MemIplCeStats<TYPE_MCA>::banAnalysis( uint8_t i_dimmSlct,
//------------------------------------------------------------------------------
template<>
+void MemIplCeStats<TYPE_MEM_PORT>::banAnalysis( uint8_t i_dimmSlct,
+ uint8_t i_portSlct )
+{
+ PRDF_ASSERT( i_dimmSlct < MAX_DIMM_PER_PORT );
+ PRDF_ASSERT( 0 == i_portSlct );
+
+ DimmKey banKey = { i_dimmSlct, i_portSlct };
+ iv_bannedAnalysis[banKey] = true;
+}
+
+//------------------------------------------------------------------------------
+
+template<>
void MemIplCeStats<TYPE_MBA>::banAnalysis( uint8_t i_dimmSlct )
{
// Two DIMMs per DIMM select on MBA.
@@ -101,6 +114,14 @@ void MemIplCeStats<TYPE_MCA>::banAnalysis( uint8_t i_dimmSlct )
banAnalysis( i_dimmSlct, 0 );
}
+//------------------------------------------------------------------------------
+
+template<>
+void MemIplCeStats<TYPE_MEM_PORT>::banAnalysis( uint8_t i_dimmSlct )
+{
+ // Only one DIMM per DIMM select on MEM_PORT.
+ banAnalysis( i_dimmSlct, 0 );
+}
//------------------------------------------------------------------------------
@@ -460,5 +481,6 @@ void MemIplCeStats<T>::addMruAndCommitErrl( const MemoryMru & i_memmru,
// need these templates to avoid linker errors
template class MemIplCeStats<TYPE_MCA>;
template class MemIplCeStats<TYPE_MBA>;
+template class MemIplCeStats<TYPE_MEM_PORT>;
} // end namespace PRDF
diff --git a/src/usr/diag/prdf/plat/mem/prdfMemScrubUtils.C b/src/usr/diag/prdf/plat/mem/prdfMemScrubUtils.C
index 9d8e00f50..5351b842a 100644
--- a/src/usr/diag/prdf/plat/mem/prdfMemScrubUtils.C
+++ b/src/usr/diag/prdf/plat/mem/prdfMemScrubUtils.C
@@ -188,6 +188,23 @@ uint32_t clearEccCounters<TYPE_MCA>( ExtensibleChip * i_chip )
}
template<>
+uint32_t clearEccCounters<TYPE_OCMB_CHIP>( ExtensibleChip * i_chip )
+{
+ return __clearEccCounters<TYPE_OCMB_CHIP>( i_chip, "MCB_CNTL", 7 );
+}
+
+template<>
+uint32_t clearEccCounters<TYPE_MEM_PORT>( ExtensibleChip * i_chip )
+{
+ PRDF_ASSERT( nullptr != i_chip );
+ PRDF_ASSERT( TYPE_MEM_PORT == i_chip->getType() );
+
+ ExtensibleChip * ocmbChip = getConnectedParent( i_chip, TYPE_OCMB_CHIP );
+
+ return clearEccCounters<TYPE_OCMB_CHIP>( ocmbChip );
+}
+
+template<>
uint32_t clearEccCounters<TYPE_MBA>( ExtensibleChip * i_chip )
{
PRDF_ASSERT( nullptr != i_chip );
@@ -253,6 +270,53 @@ uint32_t clearEccFirs<TYPE_MCA>( ExtensibleChip * i_chip )
}
template<>
+uint32_t clearEccFirs<TYPE_OCMB_CHIP>( ExtensibleChip * i_chip )
+{
+ uint32_t o_rc = SUCCESS;
+
+ do
+ {
+ // Clear MCBISTFIR[5:9]
+ o_rc = __clearFir<TYPE_OCMB_CHIP>( i_chip, "MCBISTFIR_AND",
+ 0xf83fffffffffffffull );
+ if ( SUCCESS != o_rc ) break;
+
+ // Maintenance AUEs/IAUEs will be reported as system checkstops.
+ // Maintenance IMPEs will be reported as recoverable attentions at
+ // all times. Maintence IUEs will be masked during Memory
+ // Diagnostics and handled in the Targeted diagnostics code. After
+ // Memory Diagnostics, maintenance IUEs will be reported as
+ // recoverable in the field (no stop-on-error), but will remain
+ // masked if MNFG thresholds are enabled. In this case, the command
+ // will stop on RCE ETE in order to get a more accuracy callout. So
+ // clear RDFFIR[20:32,34:35,38] always and RDFFIR[37] in MNFG
+ // mode or during Memory Diagnostics.
+ uint64_t mask = 0xfffff0004dffffffull;
+ if ( mfgMode() ) mask &= 0xfffffffffbffffffull;
+ #ifndef __HOSTBOOT_RUNTIME
+ if ( isInMdiaMode() ) mask &= 0xfffffffffbffffffull;
+ #endif
+
+ o_rc = __clearFir<TYPE_OCMB_CHIP>( i_chip, "RDFFIR_AND", mask );
+ if ( SUCCESS != o_rc ) break;
+
+ } while(0);
+
+ return o_rc;
+}
+
+template<>
+uint32_t clearEccFirs<TYPE_MEM_PORT>( ExtensibleChip * i_chip )
+{
+ PRDF_ASSERT( nullptr != i_chip );
+ PRDF_ASSERT( TYPE_MEM_PORT == i_chip->getType() );
+
+ ExtensibleChip * ocmbChip = getConnectedParent( i_chip, TYPE_OCMB_CHIP );
+
+ return clearEccFirs<TYPE_OCMB_CHIP>( ocmbChip );
+}
+
+template<>
uint32_t clearEccFirs<TYPE_MBA>( ExtensibleChip * i_chip )
{
uint32_t o_rc = SUCCESS;
@@ -345,6 +409,69 @@ uint32_t checkEccFirs<TYPE_MCA>( ExtensibleChip * i_chip,
//------------------------------------------------------------------------------
template<>
+uint32_t checkEccFirs<TYPE_MEM_PORT>( ExtensibleChip * i_chip,
+ uint32_t & o_eccAttns )
+{
+ #define PRDF_FUNC "[checkEccFirs<TYPE_MEM_PORT>] "
+
+ uint32_t o_rc = SUCCESS;
+
+ o_eccAttns = MAINT_NO_ERROR;
+
+ PRDF_ASSERT( nullptr != i_chip );
+ PRDF_ASSERT( TYPE_MEM_PORT == i_chip->getType() );
+
+ ExtensibleChip * ocmbChip = getConnectedParent( i_chip, TYPE_OCMB_CHIP );
+
+ SCAN_COMM_REGISTER_CLASS * rdffir = ocmbChip->getRegister( "RDFFIR" );
+ SCAN_COMM_REGISTER_CLASS * mcbistfir = ocmbChip->getRegister( "MCBISTFIR" );
+
+ do
+ {
+ o_rc = rdffir->Read();
+ if ( SUCCESS != o_rc )
+ {
+ PRDF_ERR( PRDF_FUNC "Read() failed on MCAECCFIR: i_chip=0x%08x",
+ i_chip->getHuid() );
+ break;
+ }
+
+ // We can assume that any chip mark placed by a maintenance command was
+ // done on the rank in which the command stopped. So we can blindly
+ // check all bits to determine if there was an MPE on the stopped rank.
+ if ( 0 != rdffir->GetBitFieldJustified(20,8) ) o_eccAttns |= MAINT_MPE;
+
+ if ( rdffir->IsBitSet(28) ) o_eccAttns |= MAINT_NCE;
+ if ( rdffir->IsBitSet(29) ) o_eccAttns |= MAINT_TCE;
+ if ( rdffir->IsBitSet(30) ) o_eccAttns |= MAINT_SCE;
+ if ( rdffir->IsBitSet(31) ) o_eccAttns |= MAINT_MCE;
+ if ( rdffir->IsBitSet(34) ) o_eccAttns |= MAINT_UE;
+ if ( rdffir->IsBitSet(37) ) o_eccAttns |= MAINT_IUE;
+ if ( rdffir->IsBitSet(39) ) o_eccAttns |= MAINT_IMPE;
+
+ o_rc = mcbistfir->Read();
+ if ( SUCCESS != o_rc )
+ {
+ PRDF_ERR( PRDF_FUNC "Read() failed on MCBISTFIR: mcbChip=0x%08x",
+ ocmbChip->getHuid() );
+ break;
+ }
+
+ if ( mcbistfir->IsBitSet(5) ) o_eccAttns |= MAINT_HARD_NCE_ETE;
+ if ( mcbistfir->IsBitSet(6) ) o_eccAttns |= MAINT_SOFT_NCE_ETE;
+ if ( mcbistfir->IsBitSet(7) ) o_eccAttns |= MAINT_INT_NCE_ETE;
+ if ( mcbistfir->IsBitSet(8) ) o_eccAttns |= MAINT_RCE_ETE;
+
+ } while(0);
+
+ return o_rc;
+
+ #undef PRDF_FUNC
+}
+
+//------------------------------------------------------------------------------
+
+template<>
uint32_t checkEccFirs<TYPE_MBA>( ExtensibleChip * i_chip,
uint32_t & o_eccAttns )
{
diff --git a/src/usr/diag/prdf/plat/mem/prdfMemTdRankList.H b/src/usr/diag/prdf/plat/mem/prdfMemTdRankList.H
index ddc9b7390..e61389ea2 100644
--- a/src/usr/diag/prdf/plat/mem/prdfMemTdRankList.H
+++ b/src/usr/diag/prdf/plat/mem/prdfMemTdRankList.H
@@ -5,7 +5,7 @@
/* */
/* OpenPOWER HostBoot Project */
/* */
-/* Contributors Listed Below - COPYRIGHT 2013,2017 */
+/* Contributors Listed Below - COPYRIGHT 2013,2019 */
/* [+] International Business Machines Corp. */
/* */
/* */
@@ -80,8 +80,8 @@ class TdRankListEntry
private:
- ExtensibleChip * iv_chip = nullptr; ///< MCA or MBA chip.
- MemRank iv_rank = MemRank(0); ///< Any rank on the MCA or MBA.
+ ExtensibleChip * iv_chip = nullptr; ///< MCA, MBA, or MEM_PORT chip.
+ MemRank iv_rank = MemRank(0); ///< Any rank on the MCA/MBA/MEM_PORT
};
/**
@@ -183,6 +183,31 @@ inline TdRankList<TARGETING::TYPE_MCBIST>::TdRankList( ExtensibleChip * i_chip )
//------------------------------------------------------------------------------
template<>
+inline TdRankList<TARGETING::TYPE_OCMB_CHIP>::TdRankList(
+ ExtensibleChip * i_chip )
+{
+ using namespace TARGETING;
+ using namespace PlatServices;
+
+ PRDF_ASSERT( TYPE_OCMB_CHIP == i_chip->getType() );
+
+ ExtensibleChipList memPortChipList = getConnected( i_chip, TYPE_MEM_PORT );
+ for ( auto & memPortChip : memPortChipList )
+ {
+ std::vector<MemRank> rankList;
+ getSlaveRanks<TYPE_MEM_PORT>( memPortChip->getTrgt(), rankList );
+ PRDF_ASSERT( !rankList.empty() ); // target configured with no ranks
+
+ for ( auto & rank : rankList )
+ {
+ iv_list.push_back( TdRankListEntry(memPortChip, rank) );
+ }
+ }
+}
+
+//------------------------------------------------------------------------------
+
+template<>
inline TdRankList<TARGETING::TYPE_MBA>::TdRankList( ExtensibleChip * i_chip )
{
using namespace TARGETING;
OpenPOWER on IntegriCloud