summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorCaleb Palmer <cnpalmer@us.ibm.com>2018-04-27 14:20:47 -0500
committerZane C. Shelley <zshelle@us.ibm.com>2018-05-23 15:11:48 -0400
commit67499d6a3e8747725083398348f655dedc86b552 (patch)
treeb3b291720e4d7bc65e6f03f7bdd5aa128d29a44e
parent7ff47d2af40b0321d5391956d99d402e8993f5b6 (diff)
downloadtalos-hostboot-67499d6a3e8747725083398348f655dedc86b552.tar.gz
talos-hostboot-67499d6a3e8747725083398348f655dedc86b552.zip
PRD: Runtime VCM support for Centaur
Change-Id: I0dc0361b4d258961e23ff43098261a47feb52834 RTC: 191847 Reviewed-on: http://ralgit01.raleigh.ibm.com/gerrit1/58458 Tested-by: Jenkins Server <pfd-jenkins+hostboot@us.ibm.com> Reviewed-by: Benjamin J. Weisenbeck <bweisenb@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/59235 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/cen/prdfCenMbaExtraSig.H4
-rw-r--r--src/usr/diag/prdf/common/plat/mem/prdfCenMbaDataBundle.H16
-rw-r--r--src/usr/diag/prdf/common/plat/pegasus/prdfCenMbaTdCtlr_common.C194
-rwxr-xr-xsrc/usr/diag/prdf/common/plat/pegasus/prdfCenMbaTdCtlr_rt.C240
-rwxr-xr-xsrc/usr/diag/prdf/plat/mem/prdfMemTdQueue.H5
-rw-r--r--src/usr/diag/prdf/plat/mem/prdfMemVcm_rt.C170
6 files changed, 185 insertions, 444 deletions
diff --git a/src/usr/diag/prdf/common/plat/cen/prdfCenMbaExtraSig.H b/src/usr/diag/prdf/common/plat/cen/prdfCenMbaExtraSig.H
index f094dccb8..7464ba1c6 100644
--- a/src/usr/diag/prdf/common/plat/cen/prdfCenMbaExtraSig.H
+++ b/src/usr/diag/prdf/common/plat/cen/prdfCenMbaExtraSig.H
@@ -32,6 +32,10 @@
PRDR_ERROR_SIGNATURE(CmdComplete_ERROR, 0xeeee0000, "",
"ERROR: command complete analysis failed" );
+PRDR_ERROR_SIGNATURE(VcmResume, 0xbbbb0000, "", "VCM: Resuming procedure");
+PRDR_ERROR_SIGNATURE(TpsResume, 0xbbbb0001, "", "TPS: Resuming procedure");
+PRDR_ERROR_SIGNATURE(DsdResume, 0xbbbb0003, "", "DSD: Resuming procedure");
+
PRDR_ERROR_SIGNATURE(MaintNCE_CTE, 0xbbbb0016, "", "Maint SOFT/INTER CTE");
PRDR_ERROR_SIGNATURE(VcmBadSpare, 0xbbbb0022, "", "VCM: bad DRAM spare");
diff --git a/src/usr/diag/prdf/common/plat/mem/prdfCenMbaDataBundle.H b/src/usr/diag/prdf/common/plat/mem/prdfCenMbaDataBundle.H
index 88d502620..024a08ec3 100644
--- a/src/usr/diag/prdf/common/plat/mem/prdfCenMbaDataBundle.H
+++ b/src/usr/diag/prdf/common/plat/mem/prdfCenMbaDataBundle.H
@@ -74,6 +74,7 @@ class MbaDataBundle : public DataBundle
#ifdef __HOSTBOOT_RUNTIME
+ delete iv_vcmFalseAlarmCounter;
delete iv_tpsFalseAlarmCounter;
#else // IPL only
@@ -105,6 +106,18 @@ class MbaDataBundle : public DataBundle
#ifdef __HOSTBOOT_RUNTIME
+ /** @return The VCM false alarm counter. */
+ VcmFalseAlarm * getVcmFalseAlarmCounter()
+ {
+ if ( nullptr == iv_vcmFalseAlarmCounter )
+ {
+ iv_vcmFalseAlarmCounter = new VcmFalseAlarm(
+ TimeBasedThreshold { 4, ThresholdResolution::ONE_DAY } );
+ }
+
+ return iv_vcmFalseAlarmCounter;
+ }
+
/** @return The TPS false alarm counter. */
TpsFalseAlarm * getTpsFalseAlarmCounter()
{
@@ -146,6 +159,9 @@ class MbaDataBundle : public DataBundle
#ifdef __HOSTBOOT_RUNTIME
+ /** VCM false alarm counter. */
+ VcmFalseAlarm * iv_vcmFalseAlarmCounter = nullptr;
+
/** TPS false alarm counter. */
TpsFalseAlarm * iv_tpsFalseAlarmCounter = nullptr;
diff --git a/src/usr/diag/prdf/common/plat/pegasus/prdfCenMbaTdCtlr_common.C b/src/usr/diag/prdf/common/plat/pegasus/prdfCenMbaTdCtlr_common.C
index 8e81936e1..04a336e8d 100644
--- a/src/usr/diag/prdf/common/plat/pegasus/prdfCenMbaTdCtlr_common.C
+++ b/src/usr/diag/prdf/common/plat/pegasus/prdfCenMbaTdCtlr_common.C
@@ -43,200 +43,6 @@ using namespace PlatServices;
//------------------------------------------------------------------------------
-int32_t CenMbaTdCtlrCommon::handleMCE_VCM2( STEP_CODE_DATA_STRUCT & io_sc )
-{
- #define PRDF_FUNC "[CenMbaTdCtlrCommon::handleMCE_VCM2] "
-
- using namespace fapi; // For spare config macros.
-
- int32_t o_rc = SUCCESS;
-
- iv_isEccSteer = false;
-
- do
- {
- if ( VCM_PHASE_2 != iv_tdState )
- {
- PRDF_ERR( PRDF_FUNC "Invalid state machine configuration" );
- o_rc = FAIL; break;
- }
-
- setTdSignature( io_sc, PRDFSIG_VcmVerified );
-
- if ( areDramRepairsDisabled() )
- {
- iv_tdState = NO_OP; // The TD procedure is complete.
-
- io_sc.service_data->setServiceCall();
-
- break; // nothing else to do.
- }
-
- // If there is a symbol mark on the same DRAM as the newly verified chip
- // mark, remove the symbol mark.
- const uint8_t cmDram = iv_mark.getCM().getDram();
- if ( cmDram == iv_mark.getSM().getDram() )
- {
- iv_mark.clearSM();
- bool blocked; // Won't be blocked because chip mark is in place.
- o_rc = mssSetMarkStore( iv_mbaTrgt, iv_rank, iv_mark, blocked );
- if ( SUCCESS != o_rc )
- {
- PRDF_ERR( PRDF_FUNC "mssSetMarkStore() failed" );
- break;
- }
- }
-
- bool startDsdProcedure = false;
-
- // Read VPD.
- CenDqBitmap bitmap;
- o_rc = getBadDqBitmap( iv_mbaTrgt, iv_rank, bitmap );
- if ( SUCCESS != o_rc )
- {
- PRDF_ERR( PRDF_FUNC "getBadDqBitmap() failed" );
- break;
- }
-
- // The chip mark is considered verified, so set it in VPD.
- o_rc = bitmap.setDram( iv_mark.getCM() );
- if ( SUCCESS != o_rc )
- {
- PRDF_ERR( PRDF_FUNC "setDram() failed" );
- break;
- }
-
- uint8_t ps = iv_mark.getCM().getPortSlct();
- uint8_t spareConfig = ENUM_ATTR_VPD_DIMM_SPARE_NO_SPARE;
- o_rc = getDimmSpareConfig( iv_mbaTrgt, iv_rank, ps,
- spareConfig );
- if ( SUCCESS != o_rc )
- {
- PRDF_ERR( PRDF_FUNC "getDimmSpareConfig() failed" );
- break;
- }
-
- // Check if DRAM spare is present. Also, ECC spares are available on all
- // x4 DIMMS.
- if ( ( ENUM_ATTR_VPD_DIMM_SPARE_NO_SPARE != spareConfig ) || iv_x4Dimm )
- {
- // Get the current spares in hardware.
- CenSymbol sp0, sp1, ecc;
- o_rc = mssGetSteerMux( iv_mbaTrgt, iv_rank, sp0, sp1, ecc );
- if ( SUCCESS != o_rc )
- {
- PRDF_ERR( PRDF_FUNC "mssGetSteerMux() failed" );
- break;
- }
-
- // If the verified chip mark is on a spare then the spare is bad and
- // hardware can not steer it to another DRAM even if one is
- // available (e.g. ECC spare). In this this case, make error log
- // predictive (remember that the chip mark has already been added to
- // the callout list.
- if ( ( cmDram == (0 == ps ? sp0.getDram() : sp1.getDram()) ) ||
- ( cmDram == ecc.getDram() ) )
- {
- setTdSignature( io_sc, PRDFSIG_VcmBadSpare );
- io_sc.service_data->setServiceCall();
- }
- else
- {
- // Certain DIMMs may have had spares intentially made
- // unavailable by the manufacturer. Check the VPD for available
- // spares. Note that a x4 DIMM has DRAM spares and ECC spares,
- // so check for availability on both.
- bool dramSparePossible = false;
- bool eccSparePossible = false;
- o_rc = bitmap.isSpareAvailable( ps, dramSparePossible,
- eccSparePossible );
- if ( SUCCESS != o_rc )
- {
- PRDF_ERR( PRDF_FUNC "isDramSpareAvailable() failed" );
- break;
- }
-
- if ( dramSparePossible &&
- (0 == ps ? !sp0.isValid() : !sp1.isValid()) )
- {
- // A spare DRAM is available.
- startDsdProcedure = true;
- }
- else if ( eccSparePossible && !ecc.isValid() )
- {
- startDsdProcedure = true;
- iv_isEccSteer = true;
- }
- else
- {
- // Chip mark is in place and sparing is not possible.
- setTdSignature( io_sc, PRDFSIG_VcmCmAndSpare );
- io_sc.service_data->setServiceCall();
-
- // The mark has already been added to the callout list.
- // Callout the used spares, if they exists.
- if ( sp0.isValid() )
- {
- MemoryMru memmru ( iv_mbaTrgt, iv_rank, sp0 );
- io_sc.service_data->SetCallout( memmru );
- }
- if ( sp1.isValid() )
- {
- MemoryMru memmru ( iv_mbaTrgt, iv_rank, sp1 );
- io_sc.service_data->SetCallout( memmru );
- }
- if ( ecc.isValid() )
- {
- MemoryMru memmru ( iv_mbaTrgt, iv_rank, ecc );
- io_sc.service_data->SetCallout( memmru );
- }
- }
- }
- }
- else // DRAM spare not supported.
- {
- // Not able to do dram sparing. If there is a symbol mark, there are
- // no repairs available so call it out and set the error log to
- // predictive.
- if ( iv_mark.getSM().isValid() )
- {
- setTdSignature( io_sc, PRDFSIG_VcmCmAndSm );
- io_sc.service_data->setServiceCall();
- }
- }
-
- // Write VPD.
- o_rc = setBadDqBitmap( iv_mbaTrgt, iv_rank, bitmap );
- if ( SUCCESS != o_rc )
- {
- PRDF_ERR( PRDF_FUNC "setBadDqBitmap() failed" );
- break;
- }
-
- // Start DSD Phase 1, if possible.
- if ( startDsdProcedure )
- {
- o_rc = startDsdPhase1( io_sc );
- if ( SUCCESS != o_rc )
- {
- PRDF_ERR( PRDF_FUNC "startDsdPhase1() failed" );
- break;
- }
- }
- else
- {
- iv_tdState = NO_OP; // The TD procedure is complete.
- }
-
- } while(0);
-
- return o_rc;
-
- #undef PRDF_FUNC
-}
-
-//------------------------------------------------------------------------------
-
int32_t CenMbaTdCtlrCommon::handleMCE_DSD2( STEP_CODE_DATA_STRUCT & io_sc )
{
#define PRDF_FUNC "[CenMbaTdCtlrCommon::handleMCE_DSD2] "
diff --git a/src/usr/diag/prdf/common/plat/pegasus/prdfCenMbaTdCtlr_rt.C b/src/usr/diag/prdf/common/plat/pegasus/prdfCenMbaTdCtlr_rt.C
index f3ee6884f..a2bc9ca83 100755
--- a/src/usr/diag/prdf/common/plat/pegasus/prdfCenMbaTdCtlr_rt.C
+++ b/src/usr/diag/prdf/common/plat/pegasus/prdfCenMbaTdCtlr_rt.C
@@ -76,246 +76,6 @@ CenMbaTdCtlr::FUNCS CenMbaTdCtlr::cv_cmdCompleteFuncs[] =
// Private Functions
//------------------------------------------------------------------------------
-int32_t CenMbaTdCtlr::analyzeVcmPhase1( STEP_CODE_DATA_STRUCT & io_sc,
- const CenAddr & i_stopAddr,
- const CenAddr & i_endAddr )
-{
- #define PRDF_FUNC "[CenMbaTdCtlr::analyzeVcmPhase1] "
-
- int32_t o_rc = SUCCESS;
-
- do
- {
- if ( VCM_PHASE_1 != iv_tdState )
- {
- PRDF_ERR( PRDF_FUNC "Invalid state machine configuration" );
- o_rc = FAIL; break;
- }
-
- // Add the mark to the callout list.
- CalloutUtil::calloutMark( iv_mbaTrgt, iv_rank, iv_mark, io_sc );
-
- // Check for any ECC errors that occurred during the procedure.
- uint16_t eccErrorMask = NO_ERROR;
- o_rc = checkEccErrors( eccErrorMask, io_sc );
- if ( SUCCESS != o_rc )
- {
- PRDF_ERR( PRDF_FUNC "checkEccErrors() failed" );
- break;
- }
-
- if ( eccErrorMask & UE )
- {
- o_rc = handleUe_Td( io_sc, i_stopAddr );
- if ( SUCCESS != o_rc )
- {
- PRDF_ERR( PRDF_FUNC "handleUe_Td() failed" );
- break;
- }
-
- // Abort the procedure.
- iv_tdState = NO_OP;
- break;
- }
-
- if ( eccErrorMask & RETRY_CTE )
- {
- o_rc = handleRceEte_Td( io_sc );
- if ( SUCCESS != o_rc )
- {
- PRDF_ERR( PRDF_FUNC "handleRceEte_Td() failed" );
- break;
- }
- }
-
- // If the scrub stopped on the last address of the rank, start the next
- // TD procedure. Otherwise, resume background scrubbing. This is needed
- // for attentions like retry CTEs where, due to a hardware issue, must
- // report the attention immediately and cannot wait for the scrub to get
- // to the end of the rank.
-
- if ( i_endAddr == i_stopAddr )
- {
- // Start VCM Phase 2
- o_rc = startVcmPhase2( io_sc );
- if ( SUCCESS != o_rc )
- {
- PRDF_ERR( PRDF_FUNC "startVcmPhase2() failed" );
- break;
- }
- }
- else
- {
- // Restart the scrub on the next address.
- o_rc = resumeScrub( io_sc, eccErrorMask );
- if ( SUCCESS != o_rc )
- {
- PRDF_ERR( PRDF_FUNC "resumeScrub() failed" );
- break;
- }
- }
-
- } while(0);
-
- // If this TD procedure was aborted, execute TD complete sequence.
- if ( (iv_tdState == NO_OP) && (SUCCESS == o_rc) )
- {
- o_rc = handleTdComplete( io_sc );
- if ( SUCCESS != o_rc )
- {
- PRDF_ERR( PRDF_FUNC "handleTdComplete() failed" );
- }
- }
-
- return o_rc;
-
- #undef PRDF_FUNC
-}
-
-//------------------------------------------------------------------------------
-
-int32_t CenMbaTdCtlr::analyzeVcmPhase2( STEP_CODE_DATA_STRUCT & io_sc,
- const CenAddr & i_stopAddr,
- const CenAddr & i_endAddr )
-{
- #define PRDF_FUNC "[CenMbaTdCtlr::analyzeVcmPhase2] "
-
- int32_t o_rc = SUCCESS;
-
- do
- {
- if ( VCM_PHASE_2 != iv_tdState )
- {
- PRDF_ERR( PRDF_FUNC "Invalid state machine configuration" );
- o_rc = FAIL; break;
- }
-
- // Add the mark to the callout list.
- CalloutUtil::calloutMark( iv_mbaTrgt, iv_rank, iv_mark, io_sc );
-
- // Check for any ECC errors that occurred during the procedure.
- uint16_t eccErrorMask = NO_ERROR;
- o_rc = checkEccErrors( eccErrorMask, io_sc );
- if ( SUCCESS != o_rc )
- {
- PRDF_ERR( PRDF_FUNC "checkEccErrors() failed" );
- break;
- }
-
- if ( eccErrorMask & UE )
- {
- o_rc = handleUe_Td( io_sc, i_stopAddr );
- if ( SUCCESS != o_rc )
- {
- PRDF_ERR( PRDF_FUNC "handleUe_Td() failed" );
- break;
- }
-
- // Abort the procedure.
- iv_tdState = NO_OP;
- break;
- }
-
- if ( eccErrorMask & RETRY_CTE )
- {
- o_rc = handleRceEte_Td( io_sc );
- if ( SUCCESS != o_rc )
- {
- PRDF_ERR( PRDF_FUNC "handleRceEte_Td() failed" );
- break;
- }
- }
-
- if ( eccErrorMask & MCE )
- {
- // Chip mark is verified.
- // Do callouts, VPD updates, and start DRAM sparing, if possible.
- o_rc = handleMCE_VCM2( io_sc );
- if ( SUCCESS != o_rc )
- {
- PRDF_ERR( PRDF_FUNC "handleMCE_VCM2() failed" );
- break;
- }
- }
- else if ( i_endAddr == i_stopAddr )
- {
- // Chip mark verification failed.
- setTdSignature( io_sc, PRDFSIG_VcmFalseAlarm );
-
- // In manufacturing, this error log will be predictive.
- if ( areDramRepairsDisabled() )
- {
- io_sc.service_data->setServiceCall();
- iv_tdState = NO_OP; // Move on to the next TD procedure.
- break;
- }
-
- // Increment the false alarm count and threshold. if needed.
- if ( iv_vcmRankData.incFalseAlarm(iv_rank, io_sc) )
- {
- io_sc.service_data->AddSignatureList( iv_mbaTrgt,
- PRDFSIG_VcmFalseAlarmExceeded );
-
- // Treat the chip mark as verified.
- o_rc = handleMCE_VCM2( io_sc );
- if ( SUCCESS != o_rc )
- {
- PRDF_ERR( PRDF_FUNC "handleMCE_VCM2() failed" );
- }
- }
- else
- {
- // Remove chip mark from hardware.
- iv_mark.clearCM();
-
- // There is small time window where hardware places a chip mark
- // immediately after it is removed, but before the HWP procedure
- // can query the FIR registers. In this case, we will simply
- // allow the write to be 'blocked' and handle the new chip mark
- // in a separate attention.
- bool allowWriteBlocked = true;
- bool blocked; // Currently ignored.
- o_rc = mssSetMarkStore( iv_mbaTrgt, iv_rank, iv_mark, blocked,
- allowWriteBlocked );
- if ( SUCCESS != o_rc )
- {
- PRDF_ERR( PRDF_FUNC "mssSetMarkStore() failed" );
- break;
- }
-
- iv_tdState = NO_OP; // Move on to the next TD procedure.
- }
- }
- else
- {
- // Restart the scrub on the next address.
- o_rc = resumeScrub( io_sc, eccErrorMask );
- if ( SUCCESS != o_rc )
- {
- PRDF_ERR( PRDF_FUNC "resumeScrub() failed" );
- break;
- }
- }
-
- } while(0);
-
- // If this TD procedure was aborted, execute TD complete sequence.
- if ( (iv_tdState == NO_OP) && (SUCCESS == o_rc) )
- {
- o_rc = handleTdComplete( io_sc );
- if ( SUCCESS != o_rc )
- {
- PRDF_ERR( PRDF_FUNC "handleTdComplete() failed" );
- }
- }
-
- return o_rc;
-
- #undef PRDF_FUNC
-}
-
-//------------------------------------------------------------------------------
-
int32_t CenMbaTdCtlr::analyzeDsdPhase1( STEP_CODE_DATA_STRUCT & io_sc,
const CenAddr & i_stopAddr,
const CenAddr & i_endAddr )
diff --git a/src/usr/diag/prdf/plat/mem/prdfMemTdQueue.H b/src/usr/diag/prdf/plat/mem/prdfMemTdQueue.H
index 5e4d32454..56254abe3 100755
--- a/src/usr/diag/prdf/plat/mem/prdfMemTdQueue.H
+++ b/src/usr/diag/prdf/plat/mem/prdfMemTdQueue.H
@@ -150,6 +150,11 @@ class TdEntry
// used for displaying FFDC in the TD controller.
const MemRank iv_rank; ///< The rank in which this event occurred.
+ #ifdef __HOSTBOOT_RUNTIME
+ /** True if the current TD command can be resumed, false otherwise. Resume
+ * only supported for MBA at this time. */
+ bool iv_canResumeScrub = false;
+ #endif
};
//------------------------------------------------------------------------------
diff --git a/src/usr/diag/prdf/plat/mem/prdfMemVcm_rt.C b/src/usr/diag/prdf/plat/mem/prdfMemVcm_rt.C
index b7cb13653..122c54367 100644
--- a/src/usr/diag/prdf/plat/mem/prdfMemVcm_rt.C
+++ b/src/usr/diag/prdf/plat/mem/prdfMemVcm_rt.C
@@ -29,6 +29,8 @@
#include <prdfMemDqBitmap.H>
#include <prdfMemVcm.H>
#include <prdfP9McaDataBundle.H>
+#include <prdfCenMbaDataBundle.H>
+#include <prdfCenMbaExtraSig.H>
using namespace TARGETING;
@@ -55,9 +57,7 @@ VcmFalseAlarm * __getFalseAlarmCounter<TYPE_MCA>( ExtensibleChip * i_chip )
template<>
VcmFalseAlarm * __getFalseAlarmCounter<TYPE_MBA>( ExtensibleChip * i_chip )
{
- // TODO: RTC 157888
- //return getMbaDataBundle(i_chip)->getVcmFalseAlarmCounter();
- return nullptr;
+ return getMbaDataBundle(i_chip)->getVcmFalseAlarmCounter();
}
//##############################################################################
@@ -232,12 +232,26 @@ uint32_t VcmEvent<TYPE_MBA>::startCmd()
if ( TD_PHASE_2 == iv_phase ) stopCond |= mss_MaintCmd::STOP_ON_MCE;
- // 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;
@@ -248,6 +262,48 @@ uint32_t VcmEvent<TYPE_MBA>::startCmd()
//------------------------------------------------------------------------------
template<>
+uint32_t VcmEvent<TYPE_MBA>::startNextPhase( STEP_CODE_DATA_STRUCT & io_sc )
+{
+ uint32_t signature = 0;
+
+ if ( iv_canResumeScrub )
+ {
+ signature = PRDFSIG_VcmResume;
+
+ PRDF_TRAC( "[VcmEvent] Resuming VCM 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;
+
+ case TD_PHASE_1:
+ iv_phase = TD_PHASE_2;
+ signature = PRDFSIG_StartVcmPhase2;
+ break;
+
+ default: PRDF_ASSERT( false ); // invalid phase
+ }
+
+ PRDF_TRAC( "[VcmEvent] Starting VCM Phase %d: 0x%08x,0x%02x",
+ iv_phase, iv_chip->getHuid(), getKey() );
+ }
+
+ io_sc.service_data->AddSignatureList( iv_chip->getTrgt(), signature );
+
+ return startCmd();
+
+ #undef PRDF_FUNC
+}
+
+//------------------------------------------------------------------------------
+
+template<>
uint32_t VcmEvent<TYPE_MBA>::checkEcc( const uint32_t & i_eccAttns,
STEP_CODE_DATA_STRUCT & io_sc,
bool & o_done )
@@ -277,10 +333,8 @@ uint32_t VcmEvent<TYPE_MBA>::checkEcc( const uint32_t & i_eccAttns,
break;
}
- /* TODO: RTC 157888
o_rc = MemEcc::handleMemUe<TYPE_MBA>( iv_chip, addr,
UE_TABLE::SCRUB_UE, io_sc );
- */
if ( SUCCESS != o_rc )
{
PRDF_ERR( PRDF_FUNC "handleMemUe(0x%08x,0x%02x) failed",
@@ -313,6 +367,102 @@ uint32_t VcmEvent<TYPE_MBA>::checkEcc( const uint32_t & i_eccAttns,
#undef PRDF_FUNC
}
+//------------------------------------------------------------------------------
+
+template<>
+uint32_t VcmEvent<TYPE_MBA>::analyzePhase( STEP_CODE_DATA_STRUCT & io_sc,
+ bool & o_done )
+{
+ #define PRDF_FUNC "[VcmEvent::analyzePhase] "
+
+ uint32_t o_rc = SUCCESS;
+
+ do
+ {
+ if ( TD_PHASE_0 == iv_phase ) break; // Nothing to analyze yet.
+
+ // Look for any ECC errors that occurred during the command.
+ uint32_t eccAttns;
+ o_rc = checkEccFirs<TYPE_MBA>( iv_chip, eccAttns );
+ if ( SUCCESS != o_rc )
+ {
+ PRDF_ERR( PRDF_FUNC "checkEccFirs(0x%08x) failed",
+ iv_chip->getHuid() );
+ break;
+ }
+
+ // Analyze the ECC errors, if needed.
+ o_rc = checkEcc( eccAttns, io_sc, o_done );
+ if ( SUCCESS != o_rc )
+ {
+ PRDF_ERR( PRDF_FUNC "checkEcc() failed on 0x%08x",
+ iv_chip->getHuid() );
+ break;
+ }
+
+ if ( o_done ) break; // abort the procedure.
+
+ // Determine if the command stopped on the last address.
+ 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 phase.
+ iv_canResumeScrub = !lastAddr;
+
+ if ( TD_PHASE_2 == iv_phase )
+ {
+ if ( eccAttns & MAINT_MCE )
+ {
+ // The chip mark has been verified.
+ o_rc = verified( io_sc );
+ if ( SUCCESS != o_rc )
+ {
+ PRDF_ERR( PRDF_FUNC "verified() failed on 0x%08x",
+ iv_chip->getHuid() );
+ break;
+ }
+
+ // Procedure is complete.
+ o_done = true;
+ }
+ else if ( !iv_canResumeScrub )
+ {
+ // The chip mark is not verified and the command has reached the
+ // end of the rank. So this is a false alarm.
+ o_rc = falseAlarm( io_sc );
+ if ( SUCCESS != o_rc )
+ {
+ PRDF_ERR( PRDF_FUNC "falseAlarm() failed on 0x%08x",
+ iv_chip->getHuid() );
+ break;
+ }
+
+ // Procedure is complete.
+ o_done = true;
+ }
+ }
+
+ } while (0);
+
+ if ( (SUCCESS == o_rc) && o_done )
+ {
+ // Clear the ECC FFDC for this master rank.
+ MemDbUtils::resetEccFfdc<TYPE_MBA>( iv_chip, iv_rank, MASTER_RANK );
+ }
+
+ return o_rc;
+
+ #undef PRDF_FUNC
+}
+
//##############################################################################
//
// Generic template functions
OpenPOWER on IntegriCloud