From 97dcd092f4e72e2b67f2b97b6aac3cd57944d05e Mon Sep 17 00:00:00 2001 From: Caleb Palmer Date: Mon, 19 Dec 2016 09:37:52 -0600 Subject: PRD: Update MemUtils File Change-Id: I90add0fc0222e1f6f9ef4cdc4a657824c52df492 RTC: 159627 Reviewed-on: http://ralgit01.raleigh.ibm.com/gerrit1/34055 Reviewed-by: Brian J. Stegmiller Tested-by: Jenkins Server Reviewed-by: Benjamin J. Weisenbeck Reviewed-by: Zane C. Shelley Reviewed-on: http://ralgit01.raleigh.ibm.com/gerrit1/36073 Tested-by: Jenkins OP Build CI Tested-by: FSP CI Jenkins --- .../prdf/common/plat/pegasus/prdfCenMemUtils.C | 548 ----------------- .../prdf/common/plat/pegasus/prdfCenMemUtils.H | 204 ------- src/usr/diag/prdf/plat/mem/prdfMemUtils.C | 667 +++++++++++++++++++++ src/usr/diag/prdf/plat/mem/prdfMemUtils.H | 153 +++++ .../diag/prdf/plat/mem/prdf_plat_mem_hb_only.mk | 3 +- 5 files changed, 822 insertions(+), 753 deletions(-) delete mode 100755 src/usr/diag/prdf/common/plat/pegasus/prdfCenMemUtils.C delete mode 100755 src/usr/diag/prdf/common/plat/pegasus/prdfCenMemUtils.H create mode 100755 src/usr/diag/prdf/plat/mem/prdfMemUtils.C create mode 100755 src/usr/diag/prdf/plat/mem/prdfMemUtils.H diff --git a/src/usr/diag/prdf/common/plat/pegasus/prdfCenMemUtils.C b/src/usr/diag/prdf/common/plat/pegasus/prdfCenMemUtils.C deleted file mode 100755 index 798c741e0..000000000 --- a/src/usr/diag/prdf/common/plat/pegasus/prdfCenMemUtils.C +++ /dev/null @@ -1,548 +0,0 @@ -/* IBM_PROLOG_BEGIN_TAG */ -/* This is an automatically generated prolog. */ -/* */ -/* $Source: src/usr/diag/prdf/common/plat/pegasus/prdfCenMemUtils.C $ */ -/* */ -/* OpenPOWER HostBoot Project */ -/* */ -/* Contributors Listed Below - COPYRIGHT 2013,2015 */ -/* [+] 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 prdfCenMemUtils.C - * @brief Utility functions related to Centaur - */ - -#include -#include -#include -#include -#include -#include -#include - -#if defined(__HOSTBOOT_RUNTIME) || !defined(__HOSTBOOT_MODULE) - #include -#endif - -using namespace TARGETING; - -namespace PRDF -{ - -namespace MemUtils -{ - -using namespace PlatServices; -using namespace PARSERUTILS; -using namespace CEN_SYMBOL; - -const uint8_t CE_REGS_PER_MBA = 9; -const uint8_t SYMBOLS_PER_CE_REG = 8; - -static const char *mbsCeStatReg[][ CE_REGS_PER_MBA ] = { - { "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" } - }; - -//------------------------------------------------------------------------------ - -// Helper structs for collectCeStats() -struct DramCount_t -{ - uint8_t totalCount; uint8_t symbolCount; - DramCount_t() : totalCount(0), symbolCount(0) {} -}; -typedef std::map DramCountMap; - -//------------------------------------------------------------------------------ - -int32_t collectCeStats( ExtensibleChip * i_mbaChip, const CenRank & i_rank, - MaintSymbols & o_maintStats, CenSymbol & o_chipMark, - uint8_t i_thr ) -{ - #define PRDF_FUNC "[MemUtils::collectCeStats] " - - int32_t o_rc = SUCCESS; - - 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->GetChipHandle(); - 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 -} - -//------------------------------------------------------------------------------ - -int32_t clearPerSymbolCounters( ExtensibleChip * i_membChip, uint32_t i_mbaPos ) -{ - #define PRDF_FUNC "[MemUtils::clearPerSymbolCounters] " - - int32_t o_rc = SUCCESS; - - do - { - if ( MAX_MBA_PER_MEMBUF <= i_mbaPos ) - { - PRDF_ERR( PRDF_FUNC "i_mbaPos %d is invalid", i_mbaPos ); - o_rc = FAIL; - break; - } - - 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[i_mbaPos][regIdx]; - reg = i_membChip->getRegister( reg_str ); - - reg->clearAllBits(); - - o_rc = reg->Write(); - if ( SUCCESS != o_rc ) - { - PRDF_ERR( PRDF_FUNC "Write() failed on %s", reg_str ); - break; - } - } - - if ( SUCCESS != o_rc ) break; - - } while(0); - - if ( SUCCESS != o_rc ) - { - PRDF_ERR( PRDF_FUNC "Failed. i_membChip=0x%08x i_mbaPos=%d", - i_membChip->GetId(), i_mbaPos ); - } - - return o_rc; - - #undef PRDF_FUNC -} - -//------------------------------------------------------------------------------ - -int32_t getDramSize( ExtensibleChip *i_mbaChip, uint8_t & o_size ) -{ - #define PRDF_FUNC "[MemUtils::getDramSize] " - - int32_t o_rc = SUCCESS; - o_size = SIZE_2GB; - - do - { - TargetHandle_t mbaTrgt = i_mbaChip->GetChipHandle(); - CenMbaDataBundle * mbadb = getMbaDataBundle( i_mbaChip ); - 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); - 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 -} - -//------------------------------------------------------------------------------ - -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/common/plat/pegasus/prdfCenMemUtils.H b/src/usr/diag/prdf/common/plat/pegasus/prdfCenMemUtils.H deleted file mode 100755 index b31d2035f..000000000 --- a/src/usr/diag/prdf/common/plat/pegasus/prdfCenMemUtils.H +++ /dev/null @@ -1,204 +0,0 @@ -/* IBM_PROLOG_BEGIN_TAG */ -/* This is an automatically generated prolog. */ -/* */ -/* $Source: src/usr/diag/prdf/common/plat/pegasus/prdfCenMemUtils.H $ */ -/* */ -/* OpenPOWER HostBoot Project */ -/* */ -/* Contributors Listed Below - COPYRIGHT 2013,2015 */ -/* [+] 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 prdfCenMemUtils_H -#define prdfCenMemUtils_H - -/** @file prdfCenMemUtils.H - * @brief General utility functions for Centaur - */ - -//------------------------------------------------------------------------------ -// Includes -//------------------------------------------------------------------------------ - -#include -#include -#include - -namespace PRDF -{ - -class ExtensibleChip; -struct STEP_CODE_DATA_STRUCT; - -namespace MemUtils -{ - -//============================================================================== -// Constants and Enums -//============================================================================== - -/** - * @brief Lists all possible sizes for a DRAM. - * @note These values must match the definition of MBAXCR[6:7]. They are - * important for calculations. - */ -enum DramSize -{ - SIZE_2GB = 0, - SIZE_4GB = 1, - SIZE_8GB = 2, - SIZE_16GB = 3, -}; - -//============================================================================== -// Maintenance statistics -//============================================================================== - -/** - * @brief Collects CE symbol data. - */ -struct SymbolData -{ - CenSymbol symbol; - uint8_t count; - SymbolData() : count(0) {} -}; - -typedef std::vector MaintSymbols; - -/** Functor for MaintSymbols to sort by count. */ -inline bool sortSymDataCount( const SymbolData & i, const SymbolData & j ) -{ - return i.count < j.count; -} - -/** Functor for MaintSymbols to match a DRAM. */ -class MatchSymDataDram -{ - public: - explicit MatchSymDataDram( const CenSymbol & i_d ) : iv_d(i_d.getDram()) {} - - bool operator() ( const SymbolData & i_data ) const - { return ( iv_d == i_data.symbol.getDram() ); } - - private: - uint8_t iv_d; -}; - -/** Functor for MaintSymbols to match a symbol. */ -class MatchSymDataSymbol -{ - public: - explicit MatchSymDataSymbol( const CenSymbol & i_s ) : iv_s(i_s) {} - - bool operator() ( const SymbolData & i_data ) const - { return ( iv_s == i_data.symbol ); } - - private: - CenSymbol iv_s; -}; - -/** - * @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_mbaChip Target MBA 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. - */ -int32_t collectCeStats( ExtensibleChip * i_mbaChip, const CenRank & i_rank, - MaintSymbols & o_maintStats, CenSymbol & o_chipMark, - uint8_t i_thr = 1 ); - -/** - * @brief Clears the per symbol CE counters on a target MBA (via MEMBUF and MBA - * position number). - * @param i_membChip MEMBUF chip. - * @param i_mbaPos MBA positions number (0-1). - * @return Non-SUCCESS if an internal function fails, SUCCESS otherwise. - */ -int32_t clearPerSymbolCounters( ExtensibleChip * i_membChip, - uint32_t i_mbaPos ); - -/** - * @brief Gets DRAM size for an MBA. - * @param i_mbaChip MBA chip. - * @param o_size size for a DRAM. - * @return Non-SUCCESS if an internal function fails, SUCCESS otherwise. - */ -int32_t getDramSize( ExtensibleChip * i_mbaChip, uint8_t & o_size ); - -/** - * @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 on Centaur. - * @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/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 +#include +#include +#include + +#if defined(__HOSTBOOT_RUNTIME) || !defined(__HOSTBOOT_MODULE) +// #include +#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 DramCountMap; + +//------------------------------------------------------------------------------ +template<> +int32_t collectCeStats( ExtensibleChip * i_chip, + const MemRank & i_rank, MaintSymbols & o_maintStats, + MemSymbol & o_chipMark, uint8_t i_thr ) +{ + #define PRDF_FUNC "[MemUtils::collectCeStats] " + + 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( sym ) + : symbol2Byte ( 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( highestDram ) + : byte2Symbol ( 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( ExtensibleChip * i_chip, + const MemRank & i_rank, MaintSymbols & o_maintStats, + MemSymbol & o_chipMark, uint8_t i_thr ) +{ + #define PRDF_FUNC "[MemUtils::collectCeStats] " + + 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(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(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(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 +#include +#include + +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 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 +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 +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 -- cgit v1.2.3