summaryrefslogtreecommitdiffstats
path: root/src/usr/diag/prdf/plat
diff options
context:
space:
mode:
authorCaleb Palmer <cnpalmer@us.ibm.com>2016-12-19 09:37:52 -0600
committerZane C. Shelley <zshelle@us.ibm.com>2017-02-10 13:22:08 -0500
commit97dcd092f4e72e2b67f2b97b6aac3cd57944d05e (patch)
tree4590ce315156b50cfa54d5515ce3ac11cd3f53fe /src/usr/diag/prdf/plat
parent2df37e971282522423f114880f99501f0728116f (diff)
downloadtalos-hostboot-97dcd092f4e72e2b67f2b97b6aac3cd57944d05e.tar.gz
talos-hostboot-97dcd092f4e72e2b67f2b97b6aac3cd57944d05e.zip
PRD: Update MemUtils File
Change-Id: I90add0fc0222e1f6f9ef4cdc4a657824c52df492 RTC: 159627 Reviewed-on: http://ralgit01.raleigh.ibm.com/gerrit1/34055 Reviewed-by: Brian J. Stegmiller <bjs@us.ibm.com> Tested-by: Jenkins Server <pfd-jenkins+hostboot@us.ibm.com> Reviewed-by: Benjamin J. Weisenbeck <bweisenb@us.ibm.com> Reviewed-by: Zane C. Shelley <zshelle@us.ibm.com> Reviewed-on: http://ralgit01.raleigh.ibm.com/gerrit1/36073 Tested-by: Jenkins OP Build CI <op-jenkins+hostboot@us.ibm.com> Tested-by: FSP CI Jenkins <fsp-CI-jenkins+hostboot@us.ibm.com>
Diffstat (limited to 'src/usr/diag/prdf/plat')
-rwxr-xr-xsrc/usr/diag/prdf/plat/mem/prdfMemUtils.C667
-rwxr-xr-xsrc/usr/diag/prdf/plat/mem/prdfMemUtils.H153
-rw-r--r--src/usr/diag/prdf/plat/mem/prdf_plat_mem_hb_only.mk3
3 files changed, 822 insertions, 1 deletions
diff --git a/src/usr/diag/prdf/plat/mem/prdfMemUtils.C b/src/usr/diag/prdf/plat/mem/prdfMemUtils.C
new file mode 100755
index 000000000..dffdf7fbc
--- /dev/null
+++ b/src/usr/diag/prdf/plat/mem/prdfMemUtils.C
@@ -0,0 +1,667 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/usr/diag/prdf/plat/mem/prdfMemUtils.C $ */
+/* */
+/* OpenPOWER HostBoot Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 2013,2017 */
+/* [+] 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 */
+
+/** @file prdfMemUtils.C
+ * @brief Utility functions related to memory
+ */
+
+#include <prdfMemUtils.H>
+#include <prdfExtensibleChip.H>
+#include <prdfPlatServices.H>
+#include <prdfParserUtils.H>
+
+#if defined(__HOSTBOOT_RUNTIME) || !defined(__HOSTBOOT_MODULE)
+// #include <prdfCenMbaDynMemDealloc_rt.H>
+#endif
+
+using namespace TARGETING;
+
+namespace PRDF
+{
+
+namespace MemUtils
+{
+
+using namespace PlatServices;
+using namespace PARSERUTILS;
+using namespace CEN_SYMBOL;
+
+const uint8_t CE_REGS_PER_PORT = 9;
+const uint8_t SYMBOLS_PER_CE_REG = 8;
+
+//TODO RTC 166802
+/*
+static const char *mbsCeStatReg[][ CE_REGS_PER_PORT ] = {
+ { "MBA0_MBSSYMEC0", "MBA0_MBSSYMEC1","MBA0_MBSSYMEC2",
+ "MBA0_MBSSYMEC3", "MBA0_MBSSYMEC4", "MBA0_MBSSYMEC5",
+ "MBA0_MBSSYMEC6", "MBA0_MBSSYMEC7", "MBA0_MBSSYMEC8" },
+ { "MBA1_MBSSYMEC0", "MBA1_MBSSYMEC1","MBA1_MBSSYMEC2",
+ "MBA1_MBSSYMEC3", "MBA1_MBSSYMEC4", "MBA1_MBSSYMEC5",
+ "MBA1_MBSSYMEC6", "MBA1_MBSSYMEC7", "MBA1_MBSSYMEC8" }
+ };
+*/
+
+static const char *mcbCeStatReg[CE_REGS_PER_PORT] =
+ {
+ "MCB_MBSSYMEC0", "MCB_MBSSYMEC1", "MCB_MBSSYMEC2",
+ "MCB_MBSSYMEC3", "MCB_MBSSYMEC4", "MCB_MBSSYMEC5",
+ "MCB_MBSSYMEC6", "MCB_MBSSYMEC7", "MCB_MBSSYMEC8"
+ };
+
+//------------------------------------------------------------------------------
+
+// Helper structs for collectCeStats()
+struct DramCount_t
+{
+ uint8_t totalCount; uint8_t symbolCount;
+ DramCount_t() : totalCount(0), symbolCount(0) {}
+};
+typedef std::map<uint32_t, DramCount_t> DramCountMap;
+
+//------------------------------------------------------------------------------
+template<>
+int32_t collectCeStats<TYPE_MCA>( ExtensibleChip * i_chip,
+ const MemRank & i_rank, MaintSymbols & o_maintStats,
+ MemSymbol & o_chipMark, uint8_t i_thr )
+{
+ #define PRDF_FUNC "[MemUtils::collectCeStats<TYPE_MCA>] "
+
+ int32_t o_rc = SUCCESS;
+ o_chipMark = MemSymbol(); // Initially invalid.
+
+ do
+ {
+ PRDF_ASSERT( 0 != i_thr );
+
+ TargetHandle_t mcaTrgt = i_chip->getTrgt();
+ ExtensibleChip * mcbChip = getConnectedParent( i_chip, TYPE_MCBIST );
+
+ uint8_t mcaPos = getTargetPosition( mcaTrgt );
+
+ PRDF_ASSERT( MAX_MCA_PER_MCBIST > mcaPos );
+
+ const bool isX4 = isDramWidthX4(mcaTrgt);
+
+ // 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 = mcbCeStatReg[regIdx];
+ reg = mcbChip->getRegister( reg_str );
+
+ o_rc = reg->Read();
+ if ( SUCCESS != o_rc )
+ {
+ PRDF_ERR( PRDF_FUNC "Read() failed on %s", reg_str );
+ break;
+ }
+
+ uint8_t baseSymbol = SYMBOLS_PER_CE_REG * regIdx;
+
+ for ( uint8_t i = 0; i < SYMBOLS_PER_CE_REG; i++ )
+ {
+ uint8_t count = reg->GetBitFieldJustified( (i*8), 8 );
+
+ if ( 0 == count ) continue; // nothing to do
+
+ uint8_t sym = baseSymbol + i;
+ uint8_t dram = isX4 ? symbol2Nibble<TYPE_MCA>( sym )
+ : symbol2Byte <TYPE_MCA>( 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( mcaTrgt, i_rank,
+ sym, CEN_SYMBOL::BOTH_SYMBOL_DQS );
+ 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_MCA>( highestDram )
+ : byte2Symbol <TYPE_MCA>( highestDram );
+ o_chipMark = MemSymbol::fromSymbol( mcaTrgt, 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,
+ const MemRank & i_rank, MaintSymbols & o_maintStats,
+ MemSymbol & o_chipMark, uint8_t i_thr )
+{
+ #define PRDF_FUNC "[MemUtils::collectCeStats<TYPE_MBA>] "
+
+ int32_t o_rc = SUCCESS;
+
+ //TODO RTC 166802
+ /*
+ o_chipMark = CenSymbol(); // Initially invalid.
+
+ do
+ {
+ if ( 0 == i_thr ) // Must be non-zero
+ {
+ PRDF_ERR( PRDF_FUNC "i_thr %d is invalid", i_thr );
+ o_rc = FAIL; break;
+ }
+
+ TargetHandle_t mbaTrgt = i_mbaChip->getTrgt();
+ CenMbaDataBundle * mbadb = getMbaDataBundle( i_mbaChip );
+ ExtensibleChip * membufChip = mbadb->getMembChip();
+ if ( NULL == membufChip )
+ {
+ PRDF_ERR( PRDF_FUNC "getMembChip() failed" );
+ o_rc = FAIL; break;
+ }
+
+ uint8_t mbaPos = getTargetPosition( mbaTrgt );
+ if ( MAX_MBA_PER_MEMBUF <= mbaPos )
+ {
+ PRDF_ERR( PRDF_FUNC "mbaPos %d is invalid", mbaPos );
+ o_rc = FAIL; break;
+ }
+
+ const bool isX4 = isDramWidthX4(mbaTrgt);
+
+ // Get the current spares on this rank.
+ CenSymbol sp0, sp1, ecc;
+ o_rc = mssGetSteerMux( mbaTrgt, i_rank, sp0, sp1, ecc );
+ if ( SUCCESS != o_rc )
+ {
+ PRDF_ERR( PRDF_FUNC "mssGetSteerMux() failed." );
+ break;
+ }
+
+ // 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_MBA; regIdx++ )
+ {
+ reg_str = mbsCeStatReg[mbaPos][regIdx];
+ reg = membufChip->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;
+ uint8_t dram = symbol2Dram( sym, isX4 );
+
+ // 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 = CenSymbol::fromSymbol( mbaTrgt, i_rank,
+ sym, CEN_SYMBOL::BOTH_SYMBOL_DQS );
+ if ( !symData.symbol.isValid() )
+ {
+ PRDF_ERR( PRDF_FUNC "CenSymbol() failed: symbol=%d",
+ sym );
+ o_rc = FAIL;
+ break;
+ }
+ else
+ {
+ // Check if this symbol is on any of the spares.
+ if ( ( sp0.isValid() &&
+ (sp0.getDram() == symData.symbol.getDram()) ) ||
+ ( sp1.isValid() &&
+ (sp1.getDram() == symData.symbol.getDram()) ) )
+ {
+ symData.symbol.setDramSpared();
+ }
+ if ( ecc.isValid() &&
+ (ecc.getDram() == symData.symbol.getDram()) )
+ {
+ symData.symbol.setEccSpared();
+ }
+
+ // 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 = dram2Symbol( highestDram, isX4 );
+ o_chipMark = CenSymbol::fromSymbol( mbaTrgt, i_rank, sym );
+
+ // Check if this symbol is on any of the spares.
+ if ( ( sp0.isValid() && (sp0.getDram() == o_chipMark.getDram()) ) ||
+ ( sp1.isValid() && (sp1.getDram() == o_chipMark.getDram()) ) )
+ {
+ o_chipMark.setDramSpared();
+ }
+ if ( ecc.isValid() && (ecc.getDram() == o_chipMark.getDram()) )
+ {
+ o_chipMark.setEccSpared();
+ }
+ }
+
+ } while(0);
+
+ if ( SUCCESS != o_rc )
+ {
+ PRDF_ERR( PRDF_FUNC "Failed: i_mbaChip=0x%08x i_rank=m%ds%d i_thr=%d",
+ i_mbaChip->GetId(), i_rank.getMaster(), i_rank.getSlave(),
+ i_thr );
+ }
+ */
+ return o_rc;
+
+ #undef PRDF_FUNC
+}
+
+//------------------------------------------------------------------------------
+
+template<>
+uint8_t getDramSize<TYPE_MCA>(ExtensibleChip *i_chip, uint8_t i_dimmSlct)
+{
+ #define PRDF_FUNC "[MemUtils::getDramSize] "
+
+ PRDF_ASSERT( TYPE_MCA == i_chip->getType() );
+ PRDF_ASSERT( i_dimmSlct < DIMM_SLCT_PER_PORT );
+
+ TargetHandle_t mcaTrgt = i_chip->getTrgt();
+ TargetHandle_t mcsTrgt = getConnectedParent( mcaTrgt, TYPE_MCS );
+
+ PRDF_ASSERT( nullptr != mcsTrgt );
+
+ uint8_t mcaPos = i_chip->getPos();
+
+ uint8_t tmp[MAX_MCA_PER_MCS][DIMM_SLCT_PER_PORT];
+
+ if ( !mcsTrgt->tryGetAttr<TARGETING::ATTR_EFF_DRAM_DENSITY>(tmp) )
+ {
+ PRDF_ERR( PRDF_FUNC "Failed to get ATTR_EFF_DRAM_DENSITY" );
+ PRDF_ASSERT( false );
+ }
+
+ return tmp[mcaPos][i_dimmSlct];
+
+ #undef PRDF_FUNC
+}
+
+template<>
+uint8_t getDramSize<TYPE_MBA>(ExtensibleChip *i_chip, uint8_t i_dimmSlct)
+{
+ #define PRDF_FUNC "[MemUtils::getDramSize] "
+
+ uint8_t o_rc = 0;
+
+ //TODO RTC 166802
+ //do
+ //{
+ // CenMbaDataBundle * mbadb = getMbaDataBundle( i_chip );
+ // ExtensibleChip * membufChip = mbadb->getMembChip();
+ // if ( NULL == membufChip )
+ // {
+ // PRDF_ERR( PRDF_FUNC "getMembChip() failed: MBA=0x%08x",
+ // getHuid(mbaTrgt) );
+ // o_rc = FAIL; break;
+ // }
+
+ // uint32_t pos = getTargetPosition(mbaTrgt);
+ // // If we will still be using the register values for centaur, we will
+ // // need to convert them to the appropriate enum
+ // const char * reg_str = (0 == pos) ? "MBA0_MBAXCR" : "MBA1_MBAXCR";
+
+ // SCAN_COMM_REGISTER_CLASS * reg = membufChip->getRegister( reg_str );
+ // o_rc = reg->Read();
+ // if ( SUCCESS != o_rc )
+ // {
+ // PRDF_ERR( PRDF_FUNC "Read() failed on %s. Target=0x%08x",
+ // reg_str, getHuid(mbaTrgt) );
+ // break;
+ // }
+ // o_size = reg->GetBitFieldJustified( 6, 2 );
+
+ //} while(0);
+
+ return o_rc;
+
+ #undef PRDF_FUNC
+
+}
+
+//TODO RTC 166802
+//------------------------------------------------------------------------------
+/*
+int32_t checkMcsChannelFail( ExtensibleChip * i_mcsChip,
+ STEP_CODE_DATA_STRUCT & io_sc )
+{
+ #define PRDF_FUNC "[MemUtils::checkMcsChannelFail] "
+
+ int32_t o_rc = SUCCESS;
+
+ do
+ {
+ // Skip if already handling unit checkstop.
+ if ( io_sc.service_data->IsUnitCS() )
+ break;
+
+ // Must be an MCS.
+ if ( TYPE_MCS != getTargetType(i_mcsChip->GetChipHandle()) )
+ {
+ PRDF_ERR( PRDF_FUNC "i_mcsChip is not TYPE_MCS" );
+ o_rc = FAIL; break;
+ }
+
+ // Check MCIFIR[31] for presence of channel fail.
+ SCAN_COMM_REGISTER_CLASS * mcifir = i_mcsChip->getRegister("MCIFIR");
+ o_rc = mcifir->Read();
+ if ( SUCCESS != o_rc )
+ {
+ PRDF_ERR( PRDF_FUNC "Read() failed on MCIFIR" );
+ break;
+ }
+
+ if ( !mcifir->IsBitSet(31) ) break; // No channel fail, so exit.
+
+ // Set unit checkstop flag and cause attention type.
+ io_sc.service_data->setFlag(ServiceDataCollector::UNIT_CS);
+ io_sc.service_data->setSecondaryAttnType(UNIT_CS);
+ io_sc.service_data->SetThresholdMaskId(0);
+
+ // Indicate that cleanup is required.
+ P8McsDataBundle * mcsdb = getMcsDataBundle( i_mcsChip );
+ ExtensibleChip * membChip = mcsdb->getMembChip();
+ if ( NULL == membChip )
+ {
+ PRDF_ERR( PRDF_FUNC "getMembChip() returned NULL" );
+ o_rc = FAIL; break;
+ }
+ CenMembufDataBundle * mbdb = getMembufDataBundle( membChip );
+ mbdb->iv_doChnlFailCleanup = true;
+
+ } while (0);
+
+ if ( SUCCESS != o_rc )
+ {
+ PRDF_ERR( PRDF_FUNC "Failed: i_mcsChip=0x%08x", i_mcsChip->GetId() );
+ }
+
+ return o_rc;
+
+ #undef PRDF_FUNC
+}
+
+//------------------------------------------------------------------------------
+
+int32_t chnlCsCleanup( ExtensibleChip *i_mbChip,
+ STEP_CODE_DATA_STRUCT & i_sc )
+{
+ #define PRDF_FUNC "[MemUtils::chnlCsCleanup] "
+
+ int32_t o_rc = SUCCESS;
+
+ do
+ {
+ if( ( NULL == i_mbChip ) ||
+ ( TYPE_MEMBUF != getTargetType( i_mbChip->GetChipHandle() )))
+ {
+ PRDF_ERR( PRDF_FUNC "Invalid parameters" );
+ o_rc = FAIL; break;
+ }
+
+ if (( ! i_sc.service_data->IsUnitCS() ) ||
+ (CHECK_STOP == i_sc.service_data->getPrimaryAttnType()) )
+ break;
+
+ CenMembufDataBundle * mbdb = getMembufDataBundle( i_mbChip );
+ if ( !mbdb->iv_doChnlFailCleanup )
+ break; // Cleanup has already been done.
+
+ // Set it as SUE generation point.
+ i_sc.service_data->SetUERE();
+
+ ExtensibleChip * mcsChip = mbdb->getMcsChip();
+ if ( NULL == mcsChip )
+ {
+ PRDF_ERR( PRDF_FUNC "MCS chip is NULL for Membuf:0x%08X",
+ i_mbChip->GetId() );
+ o_rc = FAIL; break;
+ }
+
+ TargetHandle_t mcs = mcsChip->GetChipHandle();
+ ExtensibleChip * procChip = NULL;
+ uint8_t pos = getTargetPosition( mcs );
+ TargetHandle_t proc = getParentChip ( mcs );
+
+ if ( NULL == proc )
+ {
+ PRDF_ERR( PRDF_FUNC "Proc is NULL for Mcs:0x%08X", getHuid( mcs ) );
+ o_rc = FAIL; break;
+ }
+
+ procChip = (ExtensibleChip *)systemPtr->GetChip( proc );
+
+ if( NULL == procChip )
+ {
+ PRDF_ERR( PRDF_FUNC "Can not find Proc chip for HUID:0x%08X",
+ getHuid( proc) );
+ o_rc = FAIL; break;
+ }
+
+ // This is a cleanup function. If we get any error from scom
+ // operations, we will still continue with cleanup.
+ SCAN_COMM_REGISTER_CLASS * l_tpMask =
+ procChip->getRegister("TP_CHIPLET_FIR_MASK");
+ o_rc |= l_tpMask->Read();
+ if ( SUCCESS == o_rc )
+ {
+ // Bits 5-12 maps to attentions from MCS0-MCS7.
+ l_tpMask->SetBit( 5 + pos );
+ o_rc |= l_tpMask->Write();
+ }
+
+ // Mask attentions from the Centaur
+ const char *iomcFirMask = ( pos < 4 )?
+ "IOMCFIR_0_MASK_OR":"IOMCFIR_1_MASK_OR";
+
+ SCAN_COMM_REGISTER_CLASS * iomcMask =
+ procChip->getRegister( iomcFirMask);
+ if ( pos >= 4 ) pos -= 4;
+
+ // 8 bits are reserved for each Centaur in IOMCFIR.
+ // There are total 4 ( for P system ) centaur supported
+ // in MCS. Bits for first centaur starts from bit 8.
+
+ iomcMask->SetBitFieldJustified( 8+ ( pos*8 ), 8, 0xff);
+
+ o_rc |= iomcMask->Write();
+
+ SCAN_COMM_REGISTER_CLASS * l_tpfirmask = NULL;
+ SCAN_COMM_REGISTER_CLASS * l_nestfirmask = NULL;
+ SCAN_COMM_REGISTER_CLASS * l_memfirmask = NULL;
+ SCAN_COMM_REGISTER_CLASS * l_memspamask = NULL;
+
+ l_tpfirmask = i_mbChip->getRegister("TP_CHIPLET_FIR_MASK");
+ l_nestfirmask = i_mbChip->getRegister("NEST_CHIPLET_FIR_MASK");
+ l_memfirmask = i_mbChip->getRegister("MEM_CHIPLET_FIR_MASK");
+ l_memspamask = i_mbChip->getRegister("MEM_CHIPLET_SPA_MASK");
+
+ l_tpfirmask->setAllBits(); o_rc |= l_tpfirmask->Write();
+ l_nestfirmask->setAllBits(); o_rc |= l_nestfirmask->Write();
+ l_memfirmask->setAllBits(); o_rc |= l_memfirmask->Write();
+ l_memspamask->setAllBits(); o_rc |= l_memspamask->Write();
+
+
+ for ( uint32_t i = 0; i < MAX_MBA_PER_MEMBUF; i++ )
+ {
+ ExtensibleChip * mbaChip = mbdb->getMbaChip( i );
+ if( NULL != mbaChip )
+ {
+ TargetHandle_t mba = mbaChip->GetChipHandle();
+ if ( NULL != mba )
+ {
+ #if defined(__HOSTBOOT_MODULE) && \
+ !defined(__HOSTBOOT_RUNTIME)
+ // This is very small platform specific code. So not
+ // creating a separate file for this.
+ int32_t l_rc = mdiaSendEventMsg( mba, MDIA::SKIP_MBA );
+ if ( SUCCESS != l_rc )
+ {
+ PRDF_ERR( PRDF_FUNC "mdiaSendEventMsg(0x%08x, SKIP_MBA)"
+ " failed", getHuid( mba ) );
+ o_rc |= l_rc;
+ }
+ #else
+ int32_t l_rc = DEALLOC::mbaGard( mbaChip );
+ if ( SUCCESS != l_rc )
+ {
+ PRDF_ERR( PRDF_FUNC "mbaGard failed. HUID: 0x%08x",
+ getHuid( mba ) );
+ o_rc |= l_rc;
+ }
+ #endif // __HOSTBOOT_MODULE
+ }
+ }
+ }
+
+ // Clean up complete an is no longer required.
+ mbdb->iv_doChnlFailCleanup = false;
+
+ } while(0);
+
+ return o_rc;
+
+ #undef PRDF_FUNC
+}
+
+//------------------------------------------------------------------------------
+*/
+} // end namespace MemUtils
+
+} // end namespace PRDF
diff --git a/src/usr/diag/prdf/plat/mem/prdfMemUtils.H b/src/usr/diag/prdf/plat/mem/prdfMemUtils.H
new file mode 100755
index 000000000..aaadc1827
--- /dev/null
+++ b/src/usr/diag/prdf/plat/mem/prdfMemUtils.H
@@ -0,0 +1,153 @@
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/usr/diag/prdf/plat/mem/prdfMemUtils.H $ */
+/* */
+/* OpenPOWER HostBoot Project */
+/* */
+/* Contributors Listed Below - COPYRIGHT 2013,2017 */
+/* [+] International Business Machines Corp. */
+/* */
+/* */
+/* Licensed under the Apache License, Version 2.0 (the "License"); */
+/* you may not use this file except in compliance with the License. */
+/* You may obtain a copy of the License at */
+/* */
+/* http://www.apache.org/licenses/LICENSE-2.0 */
+/* */
+/* Unless required by applicable law or agreed to in writing, software */
+/* distributed under the License is distributed on an "AS IS" BASIS, */
+/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */
+/* implied. See the License for the specific language governing */
+/* permissions and limitations under the License. */
+/* */
+/* IBM_PROLOG_END_TAG */
+
+#ifndef prdfMemUtils_H
+#define prdfMemUtils_H
+
+/** @file prdfMemUtils.H
+ * @brief General utility functions for memory
+ */
+
+//------------------------------------------------------------------------------
+// Includes
+//------------------------------------------------------------------------------
+
+#include <vector>
+#include <prdfMemSymbol.H>
+#include <prdfParserEnums.H>
+
+namespace PRDF
+{
+
+class ExtensibleChip;
+struct STEP_CODE_DATA_STRUCT;
+
+namespace MemUtils
+{
+
+//==============================================================================
+// Maintenance statistics
+//==============================================================================
+
+/**
+ * @brief Collects CE symbol data.
+ */
+struct SymbolData
+{
+ MemSymbol symbol;
+ uint8_t count;
+ SymbolData() : count(0) {}
+};
+
+typedef std::vector<SymbolData> MaintSymbols;
+
+/** Functor for MaintSymbols to sort by count. */
+inline bool sortSymDataCount( const SymbolData & i, const SymbolData & j )
+{
+ return i.count < j.count;
+}
+
+/**
+ * @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_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
+ * placed, if necessary, based on the following:
+ * - In x4 mode, this represents the DRAM with the
+ * highest total per symbol count with at least 1
+ * symbol that has exceeded threshold.
+ * - In x8 mode, this represents the DRAM with the
+ * highest total per symbol count with at least 2
+ * symbols that have exceeded threshold.
+ * It is possible that there will be symbols returned in
+ * o_maintStats that do not meet the criteria stated
+ * above. Therefore, the user must check if o_chipMark is
+ * valid before using it.
+ * @param i_thr The count threshold. Each symbol count must be greater
+ * than or equal to this value to be added to the list.
+ * The default is 1, which means all non-zero counts will
+ * be added to the list. A value of 0 will result in a bad
+ * return code.
+ * @return Non-SUCCESS if an internal function fails, SUCCESS otherwise.
+ */
+template<TARGETING::TYPE T>
+int32_t collectCeStats( ExtensibleChip * i_chip, const MemRank & i_rank,
+ MaintSymbols & o_maintStats, MemSymbol & o_chipMark,
+ uint8_t i_thr = 1 );
+
+/**
+ * @brief Gets DRAM size for an MBA or MCA.
+ * @param i_chip MBA or MCA chip.
+ * @param i_dimmSlct DIMM select.
+ * @return size for a DRAM
+ */
+template<TARGETING::TYPE T>
+uint8_t getDramSize( ExtensibleChip * i_chip, uint8_t i_dimmSlct );
+
+/**
+ * @brief Check for channel fail attentions on the MCS side of the DMI bus.
+ * @param i_mcsChip An MCS chip.
+ * @param io_sc The step code data struct.
+ * @return Non-SUCCESS if an internal function fails, SUCCESS otherwise.
+ */
+int32_t checkMcsChannelFail( ExtensibleChip * i_mcsChip,
+ STEP_CODE_DATA_STRUCT & io_sc );
+
+/**
+ * @brief Cleanup for channel CS.
+ * @param i_mbChip Membuf chip.
+ * @param i_sc Service Data Collector.
+ * @return Non-SUCCESS if an internal function fails, SUCCESS otherwise.
+ */
+int32_t chnlCsCleanup( ExtensibleChip *i_mbChip,
+ STEP_CODE_DATA_STRUCT & i_sc );
+
+/**
+ * @brief determines the type of Centaur based raw card associated with MBA.
+ * @param i_mba mba target
+ * @param o_type raw card type.
+ * @return Non-SUCCESS if an internal function fails, SUCCESS otherwise.
+ * @note Function is not intended for IS DIMM.
+ */
+int32_t getRawCardType( TARGETING::TargetHandle_t i_mba,
+ CEN_SYMBOL::WiringType & o_type );
+
+/**
+ * @brief Cleanup MCIFIR bits on proc side for hostboot.
+ * @param i_mbChip Membuf chip.
+ * @param i_sc Service Data Collector.
+ * @return Non-SUCCESS if an internal function fails, SUCCESS otherwise.
+ */
+int32_t mcifirCleanup( ExtensibleChip *i_mbChip,
+ STEP_CODE_DATA_STRUCT & i_sc );
+
+} // end namespace MemUtils
+
+} // end namespace PRDF
+
+#endif
diff --git a/src/usr/diag/prdf/plat/mem/prdf_plat_mem_hb_only.mk b/src/usr/diag/prdf/plat/mem/prdf_plat_mem_hb_only.mk
index 9a28bdb3d..b753dc50a 100644
--- a/src/usr/diag/prdf/plat/mem/prdf_plat_mem_hb_only.mk
+++ b/src/usr/diag/prdf/plat/mem/prdf_plat_mem_hb_only.mk
@@ -5,7 +5,7 @@
#
# OpenPOWER HostBoot Project
#
-# Contributors Listed Below - COPYRIGHT 2016
+# Contributors Listed Below - COPYRIGHT 2016,2017
# [+] International Business Machines Corp.
#
#
@@ -40,6 +40,7 @@ prd_incpath += ${PRD_SRC_PATH}/plat/mem
# plat/mem/ (non-rule plugin related)
prd_obj += prdfMemScrubUtils.o
prd_obj += prdfMemTdCtlr.o
+prd_obj += prdfMemUtils.o
# plat/mem/ (rule plugin related)
prd_rule_plugin += prdfP9Mca.o
OpenPOWER on IntegriCloud