From 3e16432f929a2516dd35c4d4fa6c5a5570180dd2 Mon Sep 17 00:00:00 2001 From: Zane Shelley Date: Tue, 22 May 2018 11:27:57 -0500 Subject: PRD: TPS startNextPhase() for Centaur Change-Id: I323e2f032904fa9792742c73add0753eead1e365 Reviewed-on: http://ralgit01.raleigh.ibm.com/gerrit1/59182 Tested-by: Jenkins Server Reviewed-by: Caleb N. Palmer Reviewed-by: Benjamin J. Weisenbeck Reviewed-by: Zane C. Shelley Reviewed-on: http://ralgit01.raleigh.ibm.com/gerrit1/59516 Tested-by: Jenkins OP Build CI Tested-by: Jenkins OP HW Tested-by: FSP CI Jenkins --- src/usr/diag/prdf/plat/mem/prdfMemTps_rt.C | 248 ++++++++++++++++++----------- 1 file changed, 154 insertions(+), 94 deletions(-) (limited to 'src/usr') diff --git a/src/usr/diag/prdf/plat/mem/prdfMemTps_rt.C b/src/usr/diag/prdf/plat/mem/prdfMemTps_rt.C index 593e49e55..968bbdd0f 100644 --- a/src/usr/diag/prdf/plat/mem/prdfMemTps_rt.C +++ b/src/usr/diag/prdf/plat/mem/prdfMemTps_rt.C @@ -26,8 +26,10 @@ /** @file prdfMemTps_rt.C */ // Platform includes +#include #include #include +#include #include #include #include @@ -82,6 +84,30 @@ TpsFalseAlarm * __getTpsFalseAlarmCounter( ExtensibleChip * i_chip ) //------------------------------------------------------------------------------ +template +void __getNextPhase( ExtensibleChip * i_chip, const MemRank & i_rank, + STEP_CODE_DATA_STRUCT & io_sc, + TdEntry::Phase & io_phase, uint32_t & o_signature ) +{ + PRDF_ASSERT( TdEntry::Phase::TD_PHASE_0 == io_phase ); + + // Only use phase 2 if the false alarm counter has exceeded threshold. + // Otherwise, use phase 1. + TpsFalseAlarm * faCounter = __getTpsFalseAlarmCounter( i_chip ); + if ( faCounter->count(i_rank, io_sc) >= 1 ) + { + io_phase = TdEntry::Phase::TD_PHASE_2; + o_signature = PRDFSIG_StartTpsPhase2; + } + else + { + io_phase = TdEntry::Phase::TD_PHASE_1; + o_signature = PRDFSIG_StartTpsPhase1; + } +} + +//------------------------------------------------------------------------------ + template bool __badDqCount( MemUtils::MaintSymbols i_nibbleStats, CeCount & io_badDqCount ); @@ -1136,52 +1162,6 @@ uint32_t TpsEvent::analyzePhase( STEP_CODE_DATA_STRUCT & io_sc, //------------------------------------------------------------------------------ -template<> -uint32_t TpsEvent::nextStep( STEP_CODE_DATA_STRUCT & io_sc, - bool & o_done ) -{ - #define PRDF_FUNC "[TpsEvent::nextStep] " - - uint32_t o_rc = SUCCESS; - - o_done = false; - - do - { - // Runtime TPS is slightly different than IPL TPS or any other TD event. - // There really is only one phase, but we use two phases to help - // differentiate between the CE types that are collected. So only one of - // the two phases will be used during a TPS procedure, not both. - // - Phase 1 looks for hard CEs. This is always used first on any rank. - // - Phase 2 looks for all CE types. This phase is only used on a rank - // after phase 1 has exceeded a threshold of false alarms. - - switch ( iv_phase ) - { - case TD_PHASE_0: - o_rc = startNextPhase( io_sc ); - break; - case TD_PHASE_1: - case TD_PHASE_2: - //o_rc = analyzeTpsPhase1_rt( io_sc, o_done ); - break; - default: PRDF_ASSERT( false ); // invalid phase - } - - if ( SUCCESS != o_rc ) - { - PRDF_ERR( PRDF_FUNC "TPS failed: 0x%08x,0x%02x", iv_chip->getHuid(), - getKey() ); - } - }while(0); - - return o_rc; - - #undef PRDF_FUNC -} - -//------------------------------------------------------------------------------ - // TODO: RTC 157888 Actual implementation of this procedure will be done later. template<> uint32_t TpsEvent::nextStep( STEP_CODE_DATA_STRUCT & io_sc, @@ -1200,48 +1180,6 @@ uint32_t TpsEvent::nextStep( STEP_CODE_DATA_STRUCT & io_sc, #undef PRDF_FUNC } -//############################################################################## -// -// Generic template functions -// -//############################################################################## - -template -uint32_t TpsEvent::startNextPhase( STEP_CODE_DATA_STRUCT & io_sc ) -{ - uint32_t signature = 0; - - switch ( iv_phase ) - { - case TD_PHASE_0: - { - // Only use phase 2 if the false alarm counter has exceeded - // threshold. Otherwise, use phase 1. - TpsFalseAlarm * faCounter = __getTpsFalseAlarmCounter(iv_chip); - if ( faCounter->count(iv_rank, io_sc) >= 1 ) - { - iv_phase = TD_PHASE_2; - signature = PRDFSIG_StartTpsPhase2; - } - else - { - iv_phase = TD_PHASE_1; - signature = PRDFSIG_StartTpsPhase1; - } - break; - } - - default: PRDF_ASSERT( false ); // invalid phase - } - - PRDF_TRAC( "[TpsEvent] Starting TPS Phase %d: 0x%08x,0x%02x", - iv_phase, iv_chip->getHuid(), getKey() ); - - io_sc.service_data->AddSignatureList( iv_chip->getTrgt(), signature ); - - return startCmd(); -} - //############################################################################## // // Specializations for MCA @@ -1294,6 +1232,69 @@ uint32_t TpsEvent::startCmd() #undef PRDF_FUNC } +//------------------------------------------------------------------------------ + +template<> +uint32_t TpsEvent::startNextPhase( STEP_CODE_DATA_STRUCT & io_sc ) +{ + uint32_t signature = 0; + + __getNextPhase( iv_chip, iv_rank, io_sc, iv_phase, signature ); + + PRDF_TRAC( "[TpsEvent] Starting TPS Phase %d: 0x%08x,0x%02x", + iv_phase, iv_chip->getHuid(), getKey() ); + + io_sc.service_data->AddSignatureList( iv_chip->getTrgt(), signature ); + + return startCmd(); +} + +//------------------------------------------------------------------------------ + +template<> +uint32_t TpsEvent::nextStep( STEP_CODE_DATA_STRUCT & io_sc, + bool & o_done ) +{ + #define PRDF_FUNC "[TpsEvent::nextStep] " + + uint32_t o_rc = SUCCESS; + + o_done = false; + + do + { + // Runtime TPS is slightly different than IPL TPS or any other TD event. + // There really is only one phase, but we use two phases to help + // differentiate between the CE types that are collected. So only one of + // the two phases will be used during a TPS procedure, not both. + // - Phase 1 looks for hard CEs. This is always used first on any rank. + // - Phase 2 looks for all CE types. This phase is only used on a rank + // after phase 1 has exceeded a threshold of false alarms. + + switch ( iv_phase ) + { + case TD_PHASE_0: + o_rc = startNextPhase( io_sc ); + break; + case TD_PHASE_1: + case TD_PHASE_2: + //o_rc = analyzeTpsPhase1_rt( io_sc, o_done ); + break; + default: PRDF_ASSERT( false ); // invalid phase + } + + if ( SUCCESS != o_rc ) + { + PRDF_ERR( PRDF_FUNC "TPS failed: 0x%08x,0x%02x", iv_chip->getHuid(), + getKey() ); + } + }while(0); + + return o_rc; + + #undef PRDF_FUNC +} + //############################################################################## // // Specializations for MBA @@ -1324,6 +1325,23 @@ uint32_t TpsEvent::analyzePhase( STEP_CODE_DATA_STRUCT & io_sc, // TODO + // Determine if the command stopped on the last address. + bool lastAddr = false; + o_rc = didCmdStopOnLastAddr( iv_chip, SLAVE_RANK, lastAddr ); + if ( SUCCESS != o_rc ) + { + PRDF_ERR( PRDF_FUNC "didCmdStopOnLastAddr(0x%08x) failed", + iv_chip->getHuid() ); + break; + } + + // It is important to initialize iv_canResumeScrub here, so that we will + // know to resume the current phase in startNextPhase() instead of + // starting the next phase. + iv_canResumeScrub = !lastAddr; + + // TODO + } while (0); if ( (SUCCESS == o_rc) && o_done ) @@ -1412,13 +1430,27 @@ uint32_t TpsEvent::startCmd() break; } - // Start the time based scrub procedure on this slave rank. - o_rc = startTdScrub( iv_chip, iv_rank, SLAVE_RANK, stopCond ); - if ( SUCCESS != o_rc ) + if ( iv_canResumeScrub ) { - PRDF_ERR( PRDF_FUNC "startTdScrub(0x%08x,0x%2x) failed", - iv_chip->getHuid(), getKey() ); - break; + // Resume the command from the next address to the end of this + // slave rank. + o_rc = resumeTdScrub( iv_chip, SLAVE_RANK, stopCond ); + if ( SUCCESS != o_rc ) + { + PRDF_ERR( PRDF_FUNC "resumeTdScrub(0x%08x) failed", + iv_chip->getHuid() ); + } + } + else + { + // Start the time based scrub procedure on this slave rank. + o_rc = startTdScrub( iv_chip, iv_rank, SLAVE_RANK, + stopCond ); + if ( SUCCESS != o_rc ) + { + PRDF_ERR( PRDF_FUNC "startTdScrub(0x%08x,0x%2x) failed", + iv_chip->getHuid(), getKey() ); + } } } while(0); @@ -1430,5 +1462,33 @@ uint32_t TpsEvent::startCmd() //------------------------------------------------------------------------------ +template<> +uint32_t TpsEvent::startNextPhase( STEP_CODE_DATA_STRUCT & io_sc ) +{ + + uint32_t signature = 0; + + if ( iv_canResumeScrub ) + { + signature = PRDFSIG_TpsResume; + + PRDF_TRAC( "[TpsEvent] Resuming TPS Phase %d: 0x%08x,0x%02x", + iv_phase, iv_chip->getHuid(), getKey() ); + } + else + { + __getNextPhase( iv_chip, iv_rank, io_sc, iv_phase, signature); + + PRDF_TRAC( "[TpsEvent] Starting TPS Phase %d: 0x%08x,0x%02x", + iv_phase, iv_chip->getHuid(), getKey() ); + } + + io_sc.service_data->AddSignatureList( iv_chip->getTrgt(), signature ); + + return startCmd(); +} + +//------------------------------------------------------------------------------ + } // end namespace PRDF -- cgit v1.2.1