Skip to content

Commit

Permalink
PRDF: Add utilities for checking dram spares
Browse files Browse the repository at this point in the history
Change-Id: Idbf7f5adce94466def8d7ee42a3c8e836fdbd309
RTC: 196073
Reviewed-on: http://rchgit01.rchland.ibm.com/gerrit1/64610
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://rchgit01.rchland.ibm.com/gerrit1/64981
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>
  • Loading branch information
cnpalmer authored and zane131 committed Aug 23, 2018
1 parent 34d3b93 commit 0a6c8e4
Show file tree
Hide file tree
Showing 4 changed files with 177 additions and 39 deletions.
10 changes: 10 additions & 0 deletions src/usr/diag/prdf/common/plat/mem/prdfMemDqBitmap.C
Original file line number Diff line number Diff line change
Expand Up @@ -552,6 +552,16 @@ int32_t MemDqBitmap<DIMMS_PER_RANK::MBA>::isSpareAvailable( uint8_t i_portSlct,
#undef PRDF_FUNC
}

//------------------------------------------------------------------------------
template <>
int32_t MemDqBitmap<DIMMS_PER_RANK::MCA>::isSpareAvailable( uint8_t i_portSlct,
bool & o_dramSpare, bool & o_eccSpare )
{
// spares not supported on MCA
o_dramSpare = false;
o_eccSpare = false;
return SUCCESS;
}
//------------------------------------------------------------------------------
template <>
int32_t MemDqBitmap<DIMMS_PER_RANK::MBA>::setDramSpare( uint8_t i_portSlct,
Expand Down
48 changes: 11 additions & 37 deletions src/usr/diag/prdf/common/plat/mem/prdfMemMark.C
Original file line number Diff line number Diff line change
Expand Up @@ -953,21 +953,13 @@ uint32_t __applyRasPolicies<TYPE_MBA>( ExtensibleChip * i_chip,
const bool isX4 = isDramWidthX4( i_chip->getTrgt() );

// Determine if DRAM sparing is enabled.
bool isEnabled = isX4; // Always an ECC spare in x4 mode.

if ( !isEnabled )
bool isEnabled = false;
o_rc = isDramSparingEnabled<TYPE_MBA>( i_chip->getTrgt(), i_rank, ps,
isEnabled );
if ( SUCCESS != o_rc )
{
// Check for any DRAM spares.
uint8_t cnfg = TARGETING::CEN_VPD_DIMM_SPARE_NO_SPARE;
o_rc = getDimmSpareConfig<TARGETING::TYPE_MBA>( i_chip->getTrgt(),
i_rank, ps, cnfg );
if ( SUCCESS != o_rc )
{
PRDF_ERR( PRDF_FUNC "getDimmSpareConfig(0x%08x,0x%02x,%d) "
"failed", i_chip->getHuid(), i_rank.getKey(), ps );
break;
}
isEnabled = (TARGETING::CEN_VPD_DIMM_SPARE_NO_SPARE != cnfg);
PRDF_ERR( PRDF_FUNC "isDramSparingEnabled() failed." );
break;
}

if ( isEnabled )
Expand Down Expand Up @@ -1003,34 +995,16 @@ uint32_t __applyRasPolicies<TYPE_MBA>( ExtensibleChip * i_chip,

// Certain DIMMs may have had spares intentially made unavailable by
// the manufacturer. Check the VPD for available spares.
bool dramSparePossible = false;
bool eccSparePossible = false;

MemDqBitmap<DIMMS_PER_RANK::MBA> dqBitmap;
o_rc = getBadDqBitmap<DIMMS_PER_RANK::MBA>( i_chip->getTrgt(),
i_rank, dqBitmap );
if ( SUCCESS != o_rc )
{
PRDF_ERR( PRDF_FUNC "getBadDqBitmap() failed" );
break;
}

o_rc = dqBitmap.isSpareAvailable( ps, dramSparePossible,
eccSparePossible );
if ( SUCCESS != o_rc )
{
PRDF_ERR( PRDF_FUNC "isSpareAvailable() failed" );
break;
}

if ( dramSparePossible &&
(0 == ps ? !sp0.isValid() : !sp1.isValid()) )
bool spAvail, eccAvail;
o_rc = isSpareAvailable<TYPE_MBA>( i_chip->getTrgt(), i_rank, ps,
spAvail, eccAvail );
if ( spAvail )
{
// A spare DRAM is available.
o_dsdEvent = new DsdEvent<TYPE_MBA>{ i_chip, i_rank,
i_chipMark };
}
else if ( eccSparePossible && !ecc.isValid() )
else if ( eccAvail )
{
// The ECC spare is available.
o_dsdEvent = new DsdEvent<TYPE_MBA>{ i_chip, i_rank,
Expand Down
133 changes: 132 additions & 1 deletion src/usr/diag/prdf/common/plat/prdfPlatServices_common.C
Original file line number Diff line number Diff line change
Expand Up @@ -880,8 +880,8 @@ int32_t mssSetSteerMux<TYPE_MBA>( TargetHandle_t i_mba, const MemRank & i_rank,
return o_rc;
}


//------------------------------------------------------------------------------

template<>
int32_t getDimmSpareConfig<TYPE_MCA>( TargetHandle_t i_mba, MemRank i_rank,
uint8_t i_ps, uint8_t & o_spareConfig )
Expand Down Expand Up @@ -953,6 +953,137 @@ int32_t getDimmSpareConfig<TYPE_MBA>( TargetHandle_t i_mba, MemRank i_rank,
#undef PRDF_FUNC
}

//------------------------------------------------------------------------------

template<>
uint32_t isDramSparingEnabled<TYPE_MCA>( TARGETING::TargetHandle_t i_trgt,
MemRank i_rank, uint8_t i_ps,
bool & o_spareEnable )
{
// DRAM sparing not supported for MCA
o_spareEnable = false;
return SUCCESS;
}

template<>
uint32_t isDramSparingEnabled<TYPE_MBA>( TARGETING::TargetHandle_t i_trgt,
MemRank i_rank, uint8_t i_ps,
bool & o_spareEnable )
{
#define PRDF_FUNC "[PlatServices::isDramSparingEnabled<TYPE_MBA>] "

uint32_t o_rc = SUCCESS;
o_spareEnable = false;

do
{
const bool isX4 = isDramWidthX4( i_trgt );
if ( isX4 )
{
// Always an ECC spare in x4 mode.
o_spareEnable = true;
break;
}

// Check for any DRAM spares.
uint8_t cnfg = TARGETING::CEN_VPD_DIMM_SPARE_NO_SPARE;
o_rc = getDimmSpareConfig<TYPE_MBA>( i_trgt, i_rank, i_ps, cnfg );
if ( SUCCESS != o_rc )
{
PRDF_ERR( PRDF_FUNC "getDimmSpareConfig(0x%08x,0x%02x,%d) "
"failed", getHuid(i_trgt), i_rank.getKey(), i_ps );
break;
}
o_spareEnable = (TARGETING::CEN_VPD_DIMM_SPARE_NO_SPARE != cnfg);

}while(0);

return o_rc;

#undef PRDF_FUNC
}

//------------------------------------------------------------------------------

template<TARGETING::TYPE T, DIMMS_PER_RANK D>
uint32_t __isSpareAvailable( TARGETING::TargetHandle_t i_trgt, MemRank i_rank,
uint8_t i_ps, bool & o_spAvail, bool & o_eccAvail )
{
#define PRDF_FUNC "[PlatServices::isSpareAvailable] "

uint32_t o_rc = SUCCESS;

o_spAvail = false;
o_eccAvail = false;

do
{
bool dramSparingEnabled = false;
o_rc = isDramSparingEnabled<T>( i_trgt, i_rank, i_ps,
dramSparingEnabled );
if ( SUCCESS != o_rc )
{
PRDF_ERR( PRDF_FUNC "isDramSparingEnabled() failed." );
break;
}

// Break out if dram sparing isn't enabled
if ( !dramSparingEnabled ) break;

// Get the current spares in hardware
MemSymbol sp0, sp1, ecc;
o_rc = mssGetSteerMux<T>( i_trgt, i_rank, sp0, sp1, ecc );
if ( SUCCESS != o_rc )
{
PRDF_ERR( PRDF_FUNC "mssGetSteerMux(0x%08x,0x%02x) failed",
getHuid(i_trgt), i_rank.getKey() );
break;
}

bool dramSparePossible = false;
bool eccSparePossible = false;

// Get the bad dq data
MemDqBitmap<D> dqBitmap;
o_rc = getBadDqBitmap<D>( i_trgt, i_rank, dqBitmap );
if ( SUCCESS != o_rc )
{
PRDF_ERR( PRDF_FUNC "getBadDqBitmap() failed" );
break;
}

o_rc = dqBitmap.isSpareAvailable( i_ps, dramSparePossible,
eccSparePossible );
if ( SUCCESS != o_rc )
{
PRDF_ERR( PRDF_FUNC "isSpareAvailable() failed" );
break;
}

if (dramSparePossible && (0 == i_ps ? !sp0.isValid() : !sp1.isValid()))
{
o_spAvail = true;
}
if ( eccSparePossible && !ecc.isValid() )
{
o_eccAvail = true;
}

}while(0);

return o_rc;

#undef PRDF_FUNC

}

template<>
uint32_t isSpareAvailable<TYPE_MBA>( TARGETING::TargetHandle_t i_trgt,
MemRank i_rank, uint8_t i_ps, bool & o_spAvail, bool & o_eccAvail )
{
return __isSpareAvailable<TYPE_MBA, DIMMS_PER_RANK::MBA>( i_trgt, i_rank,
i_ps, o_spAvail, o_eccAvail );
}

//------------------------------------------------------------------------------

Expand Down
25 changes: 24 additions & 1 deletion src/usr/diag/prdf/common/plat/prdfPlatServices_common.H
Original file line number Diff line number Diff line change
Expand Up @@ -244,7 +244,6 @@ template<TARGETING::TYPE T>
int32_t mssSetSteerMux( TARGETING::TargetHandle_t i_mba, const MemRank & i_rank,
const MemSymbol & i_symbol, bool i_x4EccSpare );


/**
* @brief Get spare DRAM information on a DIMM.
* @param i_mba MBA/MCA target.
Expand All @@ -260,6 +259,30 @@ template<TARGETING::TYPE T>
int32_t getDimmSpareConfig( TARGETING::TargetHandle_t i_mba, MemRank i_rank,
uint8_t i_ps, uint8_t & o_spareConfig );

/**
* @brief Checks if DRAM sparing is enabled.
* @param i_trgt Target MBA
* @param i_rank Target rank
* @param i_ps MBA Port select
* @param o_spareEnable Whether DRAM sparing is enabled or not.
* @return Non-SUCCESS if an internal function fails, SUCCESS otherwise.
*/
template<TARGETING::TYPE T>
uint32_t isDramSparingEnabled( TARGETING::TargetHandle_t i_trgt, MemRank i_rank,
uint8_t i_ps, bool & o_spareEnable );

/**
* @brief Checks to see if the spares are available on given target and port.
* @param i_trgt Target MBA
* @param i_rank Target rank
* @param i_ps Port select
* @param o_spAvail If the spare on inputted port select is available
* @param o_eccAvail If the ecc spare is available
* @return Non-SUCCESS if an internal function fails, SUCCESS otherwise.
*/
template<TARGETING::TYPE T>
uint32_t isSpareAvailable( TARGETING::TargetHandle_t i_trgt, MemRank i_rank,
uint8_t i_ps, bool & o_spAvail, bool & o_eccAvail );

/**
* @brief Returns the raw card type of a buffered DIMM.
Expand Down

0 comments on commit 0a6c8e4

Please sign in to comment.