summaryrefslogtreecommitdiffstats
path: root/src/usr/diag/prdf/plat/mem/prdfMemDsd_rt.C
diff options
context:
space:
mode:
Diffstat (limited to 'src/usr/diag/prdf/plat/mem/prdfMemDsd_rt.C')
-rw-r--r--src/usr/diag/prdf/plat/mem/prdfMemDsd_rt.C191
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
OpenPOWER on IntegriCloud