diff options
author | Caleb Palmer <cnpalmer@us.ibm.com> | 2019-04-09 15:29:07 -0500 |
---|---|---|
committer | Zane C. Shelley <zshelle@us.ibm.com> | 2019-04-18 10:33:07 -0500 |
commit | 9d139bd7d99a87c6d11f6569482218badb49cc8b (patch) | |
tree | de94afe1294c8faa0acb828b21929746afa1482a | |
parent | 36a58f1f80473c1ee39e449c85f78ead269c0348 (diff) | |
download | talos-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.rule | 225 | ||||
-rw-r--r-- | src/usr/diag/prdf/common/plat/mem/prdfMemCeTable.C | 3 | ||||
-rwxr-xr-x | src/usr/diag/prdf/common/plat/mem/prdfMemSymbol.C | 212 | ||||
-rwxr-xr-x | src/usr/diag/prdf/common/plat/mem/prdfMemSymbol.H | 10 | ||||
-rwxr-xr-x | src/usr/diag/prdf/common/plat/mem/prdfMemThresholds.C | 11 | ||||
-rwxr-xr-x | src/usr/diag/prdf/common/plat/mem/prdfMemUtils.C | 158 | ||||
-rwxr-xr-x | src/usr/diag/prdf/common/plat/mem/prdfMemUtils.H | 8 | ||||
-rwxr-xr-x | src/usr/diag/prdf/common/plat/prdfTargetServices.C | 95 | ||||
-rwxr-xr-x | src/usr/diag/prdf/common/plat/prdfTargetServices.H | 8 | ||||
-rw-r--r-- | src/usr/diag/prdf/common/plugins/prdfParserUtils.C | 56 | ||||
-rwxr-xr-x | src/usr/diag/prdf/plat/mem/prdfMemIplCeStats.C | 24 | ||||
-rw-r--r-- | src/usr/diag/prdf/plat/mem/prdfMemScrubUtils.C | 127 | ||||
-rw-r--r-- | src/usr/diag/prdf/plat/mem/prdfMemTdRankList.H | 31 |
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; |