diff options
Diffstat (limited to 'src/usr/diag/prdf/plat/mem/prdfMemDsd_rt.C')
-rw-r--r-- | src/usr/diag/prdf/plat/mem/prdfMemDsd_rt.C | 191 |
1 files changed, 159 insertions, 32 deletions
diff --git a/src/usr/diag/prdf/plat/mem/prdfMemDsd_rt.C b/src/usr/diag/prdf/plat/mem/prdfMemDsd_rt.C index 031de5507..f8e8687b0 100644 --- a/src/usr/diag/prdf/plat/mem/prdfMemDsd_rt.C +++ b/src/usr/diag/prdf/plat/mem/prdfMemDsd_rt.C @@ -26,6 +26,7 @@ /** @file prdfMemDsd_rt.C */ // Platform includes +#include <prdfCenMbaExtraSig.H> #include <prdfMemDsd.H> using namespace TARGETING; @@ -37,62 +38,139 @@ using namespace PlatServices; //############################################################################## // -// Generic template functions +// Specializations for MBA // //############################################################################## -template<TARGETING::TYPE T> -uint32_t DsdEvent<T>::analyzePhase( STEP_CODE_DATA_STRUCT & io_sc, - bool & o_done ) +template<> +uint32_t DsdEvent<TYPE_MBA>::checkEcc( const uint32_t & i_eccAttns, + STEP_CODE_DATA_STRUCT & io_sc, + bool & o_done ) { - #define PRDF_FUNC "[DsdEvent::analyzePhase] " + #define PRDF_FUNC "[DsdEvent<TYPE_MBA>::checkEcc] " uint32_t o_rc = SUCCESS; - // TODO: RTC 189221 remove once function is supported - PRDF_ERR( PRDF_FUNC "not supported yet" ); - do { - if ( TD_PHASE_0 == iv_phase ) + if ( i_eccAttns & MAINT_UE ) { - // Before starting the next command, set iv_mark in the steer mux. - /* TODO: RTC 189221 - o_rc = setSteerMux<T>( iv_chip, iv_rank, iv_mark ); + PRDF_TRAC( "[DsdEvent] UE Detected: 0x%08x,0x%02x", + iv_chip->getHuid(), getKey() ); + + io_sc.service_data->setSignature( iv_chip->getHuid(), + PRDFSIG_MaintUE ); + + // At this point we don't actually have an address for the UE. The + // best we can do is get the address in which the command stopped. + MemAddr addr; + o_rc = getMemMaintAddr<TYPE_MBA>( iv_chip, addr ); + if ( SUCCESS != o_rc ) + { + PRDF_ERR( PRDF_FUNC "getMemMaintAddr(0x%08x) failed", + iv_chip->getHuid() ); + break; + } + + o_rc = MemEcc::handleMemUe<TYPE_MBA>( iv_chip, addr, + UE_TABLE::SCRUB_UE, io_sc ); if ( SUCCESS != o_rc ) { - PRDF_ERR( PRDF_FUNC "setSteerMux(0x%08x,0x%2x) failed", + PRDF_ERR( PRDF_FUNC "handleMemUe(0x%08x,0x%02x) failed", iv_chip->getHuid(), getKey() ); break; } - */ - break; // Nothing to analyze yet. + // Leave the mark in place and abort this procedure. + o_done = true; break; } - // TODO: RTC 189221 finish supporting this function. + if ( i_eccAttns & MAINT_RCE_ETE ) + { + io_sc.service_data->setSignature( iv_chip->getHuid(), + PRDFSIG_MaintRETRY_CTE ); + + // Add the rank to the callout list. + MemoryMru mm { iv_chip->getTrgt(), iv_rank, + MemoryMruData::CALLOUT_RANK }; + io_sc.service_data->SetCallout( mm ); - // At this point, we are done with the procedure. - o_done = true; + // Make the error log predictive. + io_sc.service_data->setServiceCall(); + + // Don't abort continue the procedure. + } } while (0); - if ( (SUCCESS == o_rc) && o_done ) + return o_rc; + + #undef PRDF_FUNC +} + +//------------------------------------------------------------------------------ + +template<> +uint32_t DsdEvent<TYPE_MBA>::verifySpare( const uint32_t & i_eccAttns, + STEP_CODE_DATA_STRUCT & io_sc, + bool & o_done ) +{ + #define PRDF_FUNC "[DsdEvent<TYPE_MBA>::verifySpare] " + + uint32_t o_rc = SUCCESS; + + do { - // Clear the ECC FFDC for this master rank. - MemDbUtils::resetEccFfdc<T>( iv_chip, iv_rank, MASTER_RANK ); - } + if ( TD_PHASE_1 != iv_phase ) break; // nothing to do + + // Because of the Centaur workarounds, we will only do one phase for + // DRAM sparing. In that case, we will not look for an MCE because it is + // very likely for those to occur on phase 1. Instead, we will assume + // the spare is good if the command reached the end of the rank without + // error (i.e. a UE). + + bool lastAddr = false; + o_rc = didCmdStopOnLastAddr<TYPE_MBA>( iv_chip, MASTER_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; + + if ( lastAddr ) + { + PRDF_TRAC( "[DsdEvent] DRAM spare applied successfully: " + "0x%08x,0x%02x", iv_chip->getHuid(), getKey() ); + + io_sc.service_data->setSignature( iv_chip->getHuid(), + PRDFSIG_DsdDramSpared ); + // Remove the chip mark. + o_rc = MarkStore::clearChipMark<TYPE_MBA>( iv_chip, iv_rank ); + if ( SUCCESS != o_rc ) + { + PRDF_ERR( PRDF_FUNC "clearChipMark(0x%08x,0x%02x) failed", + iv_chip->getHuid(), getKey() ); + break; + } + + // At this point the procedure is complete. + o_done = true; + } + + } while (0); return o_rc; #undef PRDF_FUNC } -//############################################################################## -// -// Specializations for MBA -// -//############################################################################## +//------------------------------------------------------------------------------ template<> uint32_t DsdEvent<TYPE_MBA>::startCmd() @@ -112,12 +190,26 @@ uint32_t DsdEvent<TYPE_MBA>::startCmd() stopCond |= mss_MaintCmd::STOP_ON_UE; stopCond |= mss_MaintCmd::STOP_IMMEDIATE; - // Start the time based scrub procedure on this master rank. - o_rc = startTdScrub<TYPE_MBA>( iv_chip, iv_rank, MASTER_RANK, stopCond ); - if ( SUCCESS != o_rc ) + if ( iv_canResumeScrub ) { - PRDF_ERR( PRDF_FUNC "startTdScrub(0x%08x,0x%2x) failed", - iv_chip->getHuid(), getKey() ); + // Resume the command from the next address to the end of this master + // rank. + o_rc = resumeTdScrub<TYPE_MBA>( iv_chip, MASTER_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 master rank. + o_rc = startTdScrub<TYPE_MBA>( iv_chip, iv_rank, MASTER_RANK, stopCond); + if ( SUCCESS != o_rc ) + { + PRDF_ERR( PRDF_FUNC "startTdScrub(0x%08x,0x%2x) failed", + iv_chip->getHuid(), getKey() ); + } } return o_rc; @@ -127,5 +219,40 @@ uint32_t DsdEvent<TYPE_MBA>::startCmd() //------------------------------------------------------------------------------ +template<> +uint32_t DsdEvent<TYPE_MBA>::startNextPhase( STEP_CODE_DATA_STRUCT & io_sc ) +{ + uint32_t signature = 0; + + if ( iv_canResumeScrub ) + { + signature = PRDFSIG_DsdResume; + + PRDF_TRAC( "[DsdEvent] Resuming DSD Phase %d: 0x%08x,0x%02x", + iv_phase, iv_chip->getHuid(), getKey() ); + } + else + { + switch ( iv_phase ) + { + case TD_PHASE_0: + iv_phase = TD_PHASE_1; + signature = PRDFSIG_StartVcmPhase1; + break; + + default: PRDF_ASSERT( false ); // invalid phase + } + + PRDF_TRAC( "[DsdEvent] Starting DSD 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 |