diff options
author | Zane Shelley <zshelle@us.ibm.com> | 2018-04-09 15:33:02 -0500 |
---|---|---|
committer | Zane C. Shelley <zshelle@us.ibm.com> | 2018-04-19 16:45:01 -0400 |
commit | 360d83a83ec25acbdb6b40e3c773e017c75b6cb4 (patch) | |
tree | 1f8fab4714fb56001a866a2601f722d50c2e910a | |
parent | d81499bb6b6ed8614a88b2fab1ff1fb439771864 (diff) | |
download | talos-hostboot-360d83a83ec25acbdb6b40e3c773e017c75b6cb4.tar.gz talos-hostboot-360d83a83ec25acbdb6b40e3c773e017c75b6cb4.zip |
PRD: Generic PlatServices functions to start a command on rank
Change-Id: Id2c67e345936a4ed27b1c49f0feef776fe1bfcc6
RTC: 190428
Reviewed-on: http://ralgit01.raleigh.ibm.com/gerrit1/57150
Tested-by: Jenkins Server <pfd-jenkins+hostboot@us.ibm.com>
Reviewed-by: Caleb N. Palmer <cnpalmer@us.ibm.com>
Reviewed-by: Matt Derksen <mderkse1@us.ibm.com>
Reviewed-by: Brian J. Stegmiller <bjs@us.ibm.com>
Reviewed-by: Zane C. Shelley <zshelle@us.ibm.com>
Reviewed-on: http://ralgit01.raleigh.ibm.com/gerrit1/57131
CI-Ready: Zane C. Shelley <zshelle@us.ibm.com>
Tested-by: Jenkins OP Build CI <op-jenkins+hostboot@us.ibm.com>
Tested-by: Jenkins OP HW <op-hw-jenkins+hostboot@us.ibm.com>
Tested-by: FSP CI Jenkins <fsp-CI-jenkins+hostboot@us.ibm.com>
-rw-r--r-- | src/usr/diag/prdf/common/plat/mem/prdfMemAddress.H | 7 | ||||
-rw-r--r-- | src/usr/diag/prdf/plat/prdfPlatServices.C | 163 | ||||
-rw-r--r-- | src/usr/diag/prdf/plat/prdfPlatServices.H | 18 | ||||
-rw-r--r-- | src/usr/diag/prdf/plat/prdfPlatServices_ipl.C | 155 | ||||
-rw-r--r-- | src/usr/diag/prdf/plat/prdfPlatServices_ipl.H | 25 |
5 files changed, 362 insertions, 6 deletions
diff --git a/src/usr/diag/prdf/common/plat/mem/prdfMemAddress.H b/src/usr/diag/prdf/common/plat/mem/prdfMemAddress.H index 142eac1ce..4b1fc07fb 100644 --- a/src/usr/diag/prdf/common/plat/mem/prdfMemAddress.H +++ b/src/usr/diag/prdf/common/plat/mem/prdfMemAddress.H @@ -43,6 +43,13 @@ namespace PRDF class ExtensibleChip; +/** Used to specify target address ranges for functions input. */ +enum AddrRangeType +{ + SLAVE_RANK, ///< Target slave rank only. + MASTER_RANK, ///< Target entire master rank. +}; + //------------------------------------------------------------------------------ // Class MemAddr //------------------------------------------------------------------------------ diff --git a/src/usr/diag/prdf/plat/prdfPlatServices.C b/src/usr/diag/prdf/plat/prdfPlatServices.C index 6e9c45c0c..29acee7e2 100644 --- a/src/usr/diag/prdf/plat/prdfPlatServices.C +++ b/src/usr/diag/prdf/plat/prdfPlatServices.C @@ -605,6 +605,70 @@ uint32_t startBgScrub<TYPE_MCBIST>( ExtensibleChip * i_mcaChip, //------------------------------------------------------------------------------ +template<> +uint32_t startTdScrub<TYPE_MCA>( ExtensibleChip * i_chip, + const MemRank & i_rank, + AddrRangeType i_rangeType, + mss::mcbist::stop_conditions i_stopCond ) +{ + #define PRDF_FUNC "[PlatServices::startTdScrub<TYPE_MCA>] " + + PRDF_ASSERT( nullptr != i_chip ); + PRDF_ASSERT( TYPE_MCA == i_chip->getType() ); + + uint32_t o_rc = SUCCESS; + + // Set stop-on-AUE for all target scrubs. See explanation in startBgScrub() + // for the reasons why. + i_stopCond.set_pause_on_aue(mss::ON); + + do + { + // Get the address range of the given rank. + mss::mcbist::address saddr, eaddr; + o_rc = getMemAddrRange<TYPE_MCA>( i_chip, i_rank, saddr, eaddr, + i_rangeType ); + if ( SUCCESS != o_rc ) + { + PRDF_ERR( PRDF_FUNC "getMemAddrRange(0x%08x,0x%2x) failed", + i_chip->getHuid(), i_rank.getKey() ); + break; + } + + // Get the MCBIST fapi target. + ExtensibleChip * mcbChip = getConnectedParent( i_chip, TYPE_MCBIST ); + fapi2::Target<fapi2::TARGET_TYPE_MCBIST> fapiTrgt (mcbChip->getTrgt()); + + // Clear all of the counters and maintenance ECC attentions. + o_rc = prepareNextCmd<TYPE_MCBIST>( mcbChip ); + if ( SUCCESS != o_rc ) + { + PRDF_ERR( PRDF_FUNC "prepareNextCmd(0x%08x) failed", + i_chip->getHuid() ); + break; + } + + // Start targeted scrub command. + errlHndl_t errl = nullptr; + FAPI_INVOKE_HWP( errl, mss::memdiags::targeted_scrub, fapiTrgt, + i_stopCond, saddr, eaddr, mss::mcbist::NONE ); + if ( nullptr != errl ) + { + PRDF_ERR( PRDF_FUNC "mss::memdiags::targeted_scrub(0x%08x,0x%02x) " + "failed", mcbChip->getHuid(), i_rank.getKey() ); + PRDF_COMMIT_ERRL( errl, ERRL_ACTION_REPORT ); + o_rc = FAIL; break; + } + + } while (0); + + return o_rc; + + #undef PRDF_FUNC +} + +//------------------------------------------------------------------------------ + uint32_t __startTdScrub_mca( ExtensibleChip * i_mcaChip, mss::mcbist::address i_saddr, mss::mcbist::address i_eaddr, @@ -844,6 +908,105 @@ uint32_t startBgScrub<TYPE_MBA>( ExtensibleChip * i_chip, //------------------------------------------------------------------------------ template<> +uint32_t startTdScrub<TYPE_MBA>( ExtensibleChip * i_chip, + const MemRank & i_rank, + AddrRangeType i_rangeType, + uint32_t i_stopCond ) +{ + #define PRDF_FUNC "[PlatServices::startTdScrub<TYPE_MBA>] " + + #ifndef __HOSTBOOT_RUNTIME // IPL only + PRDF_ASSERT( isInMdiaMode() ); // MDIA must be running. + #endif + + PRDF_ASSERT( nullptr != i_chip ); + PRDF_ASSERT( TYPE_MBA == i_chip->getType() ); + + uint32_t o_rc = SUCCESS; + + // Make sure there is a command complete attention when the command stops. + i_stopCond |= mss_MaintCmd::ENABLE_CMD_COMPLETE_ATTENTION; + + // Make sure the command stops on the end address if there are no errors. + i_stopCond |= mss_MaintCmd::STOP_ON_END_ADDRESS; + + // IPL: + // IUEs (reported via RCE ETE) are reported as UEs during read operations. + // Therefore, we will treat IUEs like UEs for scrub operations simply to + // maintain consistency during all of Memory Diagnostics. Note that MDIA + // sets the threshold to 1 when it starts the first command on this MBA + // and that threshold should never change throughout all of Memory + // Diagnostics. + // Runtime: + // The runtime strategy for IUEs (reported via RCE ETE) is slightly + // different than IPL. For the most part we want to ignore them. However, + // we must have a threshold just incase they are causing problems. Note + // that the threshold this is set (field:2047, mnfg:1) when background + // scrubbing is started and that threshold should never change throughout + // all of runtime diagnostics. + + i_stopCond |= mss_MaintCmd::STOP_ON_RETRY_CE_ETE; + + // Default speed is to run as fast as possible. + mss_MaintCmd::TimeBaseSpeed cmdSpeed = mss_MaintCmd::FAST_MAX_BW_IMPACT; + + #ifdef __HOSTBOOT_RUNTIME + + // There is a Centaur bug preventing us from running at full speed because + // it will reduce mainline bandwidth to almost 10%. Customers won't like + // this. So we will have to use a slower speed. + if ( !enableFastBgScrub() ) cmdSpeed = mss_MaintCmd::FAST_MIN_BW_IMPACT; + + #endif + + do + { + // Get the address range of the given rank. + fapi2::buffer<uint64_t> saddr, eaddr; + o_rc = getMemAddrRange<TYPE_MBA>( i_chip, i_rank, saddr, eaddr, + i_rangeType ); + if ( SUCCESS != o_rc ) + { + PRDF_ERR( PRDF_FUNC "getMemAddrRange(0x%08x,0x%2x) failed", + i_chip->getHuid(), i_rank.getKey() ); + break; + } + + // Clear all of the counters and maintenance ECC attentions. + o_rc = prepareNextCmd<TYPE_MBA>( i_chip ); + if ( SUCCESS != o_rc ) + { + PRDF_ERR( PRDF_FUNC "prepareNextCmd(0x%08x) failed", + i_chip->getHuid() ); + break; + } + + // Get the MBA fapi target. + fapi2::Target<fapi2::TARGET_TYPE_MBA> fapiTrgt ( i_chip->getTrgt() ); + + // Start the background scrub command. + mss_TimeBaseScrub cmd { fapiTrgt, saddr, eaddr, cmdSpeed, + i_stopCond, false }; + errlHndl_t errl = nullptr; + FAPI_INVOKE_HWP( errl, cmd.setupAndExecuteCmd ); + if ( nullptr != errl ) + { + PRDF_ERR( PRDF_FUNC "setupAndExecuteCmd() on 0x%08x,0x%02x failed", + i_chip->getHuid(), i_rank.getKey() ); + PRDF_COMMIT_ERRL( errl, ERRL_ACTION_REPORT ); + o_rc = FAIL; break; + } + + } while (0); + + return o_rc; + + #undef PRDF_FUNC +} + +//------------------------------------------------------------------------------ + +template<> uint32_t startTpsRuntime<TYPE_MBA>( ExtensibleChip * i_mbaChip, const MemRank & i_rank, bool i_countAllCes ) diff --git a/src/usr/diag/prdf/plat/prdfPlatServices.H b/src/usr/diag/prdf/plat/prdfPlatServices.H index 0cf7119e8..0a3aa9b1c 100644 --- a/src/usr/diag/prdf/plat/prdfPlatServices.H +++ b/src/usr/diag/prdf/plat/prdfPlatServices.H @@ -106,12 +106,6 @@ uint32_t putScom(TARGETING::TargetHandle_t i_target, BitString& io_bs, //## Memory specific functions //############################################################################## -enum AddrRangeType -{ - SLAVE_RANK, ///< Target slave rank only. - MASTER_RANK, ///< Target entire master rank. -}; - /** * @brief Returns the start and end address of the given rank. * @note The end addresses returned from the MCBIST HWPs give a maximum @@ -167,6 +161,18 @@ template<TARGETING::TYPE T> uint32_t startBgScrub( ExtensibleChip * i_chip, const MemRank & i_rank ); /** + * @brief Starts a scrub command on the target rank. + * @param i_chip MCA or MBA chip. + * @param i_rank Target rank. + * @param i_rangeType See enum AddrRangeType. + * @param i_stopCond The stop conditions for the targeted scrub. + * @return Non-SUCCESS if an internal function fails, otherwise SUCCESS. + */ +template<TARGETING::TYPE TT, typename SCT> +uint32_t startTdScrub( ExtensibleChip * i_chip, const MemRank & i_rank, + AddrRangeType i_rangeType, SCT i_stopCond ); + +/** * @brief Starts a targeted scrub command on the target rank for VCM phase 1. * @param i_chip MCA or MBA chip. * @param i_rank The rank to target. diff --git a/src/usr/diag/prdf/plat/prdfPlatServices_ipl.C b/src/usr/diag/prdf/plat/prdfPlatServices_ipl.C index 206deb85a..374b71bf1 100644 --- a/src/usr/diag/prdf/plat/prdfPlatServices_ipl.C +++ b/src/usr/diag/prdf/plat/prdfPlatServices_ipl.C @@ -486,6 +486,161 @@ uint32_t cleanupSfRead<TYPE_MBA>( ExtensibleChip * i_mbaChip ) //------------------------------------------------------------------------------ template<> +uint32_t startTdSfRead<TYPE_MBA>( ExtensibleChip * i_chip, + const MemRank & i_rank, + AddrRangeType i_rangeType, + uint32_t i_stopCond ) +{ + #define PRDF_FUNC "[PlatServices::startTdSfRead<TYPE_MBA>] " + + PRDF_ASSERT( isInMdiaMode() ); // MDIA must be running. + + PRDF_ASSERT( nullptr != i_chip ); + PRDF_ASSERT( TYPE_MBA == i_chip->getType() ); + + uint32_t o_rc = SUCCESS; + + // Make sure there is a command complete attention when the command stops. + i_stopCond |= mss_MaintCmd::ENABLE_CMD_COMPLETE_ATTENTION; + + // Make sure the command stops on the end address if there are no errors. + i_stopCond |= mss_MaintCmd::STOP_ON_END_ADDRESS; + + do + { + // Get the address range of the given rank. + fapi2::buffer<uint64_t> saddr, eaddr; + o_rc = getMemAddrRange<TYPE_MBA>( i_chip, i_rank, saddr, eaddr, + i_rangeType ); + if ( SUCCESS != o_rc ) + { + PRDF_ERR( PRDF_FUNC "getMemAddrRange(0x%08x,0x%2x) failed", + i_chip->getHuid(), i_rank.getKey() ); + break; + } + + // Clear all of the counters and maintenance ECC attentions. + o_rc = prepareNextCmd<TYPE_MBA>( i_chip ); + if ( SUCCESS != o_rc ) + { + PRDF_ERR( PRDF_FUNC "prepareNextCmd(0x%08x) failed", + i_chip->getHuid() ); + break; + } + + // Get the MBA fapi target. + fapi2::Target<fapi2::TARGET_TYPE_MBA> fapiTrgt ( i_chip->getTrgt() ); + + // Create the new command. Store a pointer to the command in the MBA + // data bundle so that we can call the cleanup function after the + // command has completed. + MbaDataBundle * db = getMbaDataBundle( i_chip ); + PRDF_ASSERT( nullptr == db->iv_sfCmd ); // Code bug. + db->iv_sfCmd = new mss_SuperFastRead { fapiTrgt, saddr, eaddr, + i_stopCond, false }; + + // Start the super fast read command. + errlHndl_t errl = nullptr; + FAPI_INVOKE_HWP( errl, db->iv_sfCmd->setupAndExecuteCmd ); + if ( nullptr != errl ) + { + PRDF_ERR( PRDF_FUNC "setupAndExecuteCmd() on 0x%08x,0x%02x failed", + i_chip->getHuid(), i_rank.getKey() ); + PRDF_COMMIT_ERRL( errl, ERRL_ACTION_REPORT ); + o_rc = FAIL; break; + } + + } while (0); + + return o_rc; + + #undef PRDF_FUNC +} + +//------------------------------------------------------------------------------ + +template<> +uint32_t startTdSteerCleanup<TYPE_MBA>( ExtensibleChip * i_chip, + const MemRank & i_rank, + AddrRangeType i_rangeType, + uint32_t i_stopCond ) +{ + #define PRDF_FUNC "[PlatServices::startTdSteerCleanup<TYPE_MBA>] " + + PRDF_ASSERT( isInMdiaMode() ); // MDIA must be running. + + PRDF_ASSERT( nullptr != i_chip ); + PRDF_ASSERT( TYPE_MBA == i_chip->getType() ); + + uint32_t o_rc = SUCCESS; + + // Make sure there is a command complete attention when the command stops. + i_stopCond |= mss_MaintCmd::ENABLE_CMD_COMPLETE_ATTENTION; + + // Make sure the command stops on the end address if there are no errors. + i_stopCond |= mss_MaintCmd::STOP_ON_END_ADDRESS; + + // Default speed is to run as fast as possible. + mss_MaintCmd::TimeBaseSpeed cmdSpeed = mss_MaintCmd::FAST_MAX_BW_IMPACT; + + // IUEs (reported via RCE ETE) are reported as UEs during read operations. + // Therefore, we will treat IUEs like UEs for scrub operations simply to + // maintain consistency during all of Memory Diagnostics. Note that since we + // set the stop on RCE ETE flag, this requires a threshold in the MBSTR. + // Fortunately, MDIA sets the threshold to 1 when it starts the first + // command on this MBA and that threshold should never change throughout all + // of Memory Diagnostics. + + i_stopCond |= mss_MaintCmd::STOP_ON_RETRY_CE_ETE; + + do + { + // Get the address range of the given rank. + fapi2::buffer<uint64_t> saddr, eaddr; + o_rc = getMemAddrRange<TYPE_MBA>( i_chip, i_rank, saddr, eaddr, + i_rangeType ); + if ( SUCCESS != o_rc ) + { + PRDF_ERR( PRDF_FUNC "getMemAddrRange(0x%08x,0x%2x) failed", + i_chip->getHuid(), i_rank.getKey() ); + break; + } + + // Clear all of the counters and maintenance ECC attentions. + o_rc = prepareNextCmd<TYPE_MBA>( i_chip ); + if ( SUCCESS != o_rc ) + { + PRDF_ERR( PRDF_FUNC "prepareNextCmd(0x%08x) failed", + i_chip->getHuid() ); + break; + } + + // Get the MBA fapi target. + fapi2::Target<fapi2::TARGET_TYPE_MBA> fapiTrgt ( i_chip->getTrgt() ); + + // Start the background scrub command. + mss_TimeBaseSteerCleanup cmd { fapiTrgt, saddr, eaddr, cmdSpeed, + i_stopCond, false }; + errlHndl_t errl = nullptr; + FAPI_INVOKE_HWP( errl, cmd.setupAndExecuteCmd ); + if ( nullptr != errl ) + { + PRDF_ERR( PRDF_FUNC "setupAndExecuteCmd() on 0x%08x,0x%02x failed", + i_chip->getHuid(), i_rank.getKey() ); + PRDF_COMMIT_ERRL( errl, ERRL_ACTION_REPORT ); + o_rc = FAIL; break; + } + + } while (0); + + return o_rc; + + #undef PRDF_FUNC +} + +//------------------------------------------------------------------------------ + +template<> uint32_t startVcmPhase1<TYPE_MBA>( ExtensibleChip * i_chip, const MemRank & i_rank ) { diff --git a/src/usr/diag/prdf/plat/prdfPlatServices_ipl.H b/src/usr/diag/prdf/plat/prdfPlatServices_ipl.H index 61a5ef422..6bf884795 100644 --- a/src/usr/diag/prdf/plat/prdfPlatServices_ipl.H +++ b/src/usr/diag/prdf/plat/prdfPlatServices_ipl.H @@ -34,6 +34,7 @@ * is common between FSP and Hostboot should be in the respective common file. */ +#include <prdfMemAddress.H> #include <diag/mdia/mdia.H> //------------------------------------------------------------------------------ @@ -131,6 +132,30 @@ uint32_t startSfRead( ExtensibleChip * i_chip, const MemRank & i_rank ); template<TARGETING::TYPE T> uint32_t cleanupSfRead( ExtensibleChip * i_chip ); +/** + * @brief Starts a super fast read command on the target rank. + * @param i_chip MBA chip. + * @param i_rank Target rank. + * @param i_rangeType See enum AddrRangeType. + * @param i_stopCond The stop conditions for the targeted scrub. + * @return Non-SUCCESS if an internal function fails, otherwise SUCCESS. + */ +template<TARGETING::TYPE TT, typename VT> +uint32_t startTdSfRead( ExtensibleChip * i_chip, const MemRank & i_rank, + AddrRangeType i_rangeType, VT i_stopCond ); + +/** + * @brief Starts a steer cleanup scrub command on the target rank. + * @param i_chip MBA chip. + * @param i_rank Target rank. + * @param i_rangeType See enum AddrRangeType. + * @param i_stopCond The stop conditions for the targeted scrub. + * @return Non-SUCCESS if an internal function fails, otherwise SUCCESS. + */ +template<TARGETING::TYPE TT, typename VT> +uint32_t startTdSteerCleanup( ExtensibleChip * i_chip, const MemRank & i_rank, + AddrRangeType i_rangeType, VT i_stopCond ); + } // end namespace PlatServices } // end namespace PRDF |