diff options
author | Caleb Palmer <cnpalmer@us.ibm.com> | 2016-12-19 09:37:52 -0600 |
---|---|---|
committer | Zane C. Shelley <zshelle@us.ibm.com> | 2017-02-10 13:22:08 -0500 |
commit | 97dcd092f4e72e2b67f2b97b6aac3cd57944d05e (patch) | |
tree | 4590ce315156b50cfa54d5515ce3ac11cd3f53fe /src/usr/diag/prdf/plat | |
parent | 2df37e971282522423f114880f99501f0728116f (diff) | |
download | talos-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-x | src/usr/diag/prdf/plat/mem/prdfMemUtils.C | 667 | ||||
-rwxr-xr-x | src/usr/diag/prdf/plat/mem/prdfMemUtils.H | 153 | ||||
-rw-r--r-- | src/usr/diag/prdf/plat/mem/prdf_plat_mem_hb_only.mk | 3 |
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 |