diff options
author | Caleb Palmer <cnpalmer@us.ibm.com> | 2017-05-04 14:54:01 -0500 |
---|---|---|
committer | Zane C. Shelley <zshelle@us.ibm.com> | 2017-08-25 12:03:07 -0400 |
commit | 3ed90e869af65b09cd37cff0121182167d785926 (patch) | |
tree | 995f981ebfaaa848863862b6dd8e4c0a1288678a | |
parent | 0b0340c113387ff84619ca40c701cc6238535c9c (diff) | |
download | talos-hostboot-3ed90e869af65b09cd37cff0121182167d785926.tar.gz talos-hostboot-3ed90e869af65b09cd37cff0121182167d785926.zip |
Getter function for ATTR_BAD_DQ_BITMAP
Change-Id: I1491786505e282547ae4774cd3349bf17b8413b5
RTC: 173474
CMVC-Prereq: 1032664
Reviewed-on: http://ralgit01.raleigh.ibm.com/gerrit1/40816
Tested-by: Jenkins Server <pfd-jenkins+hostboot@us.ibm.com>
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>
Reviewed-by: JACOB L. HARVEY <jlharvey@us.ibm.com>
Reviewed-by: Zane C. Shelley <zshelle@us.ibm.com>
-rw-r--r-- | src/include/usr/fapi2/attribute_service.H | 39 | ||||
-rw-r--r-- | src/include/usr/fapi2/hwpf_fapi2_reasoncodes.H | 20 | ||||
-rw-r--r-- | src/usr/fapi2/attribute_service.C | 597 | ||||
-rwxr-xr-x | src/usr/fapi2/fapi2.mk | 1 | ||||
-rwxr-xr-x | src/usr/targeting/common/xmltohb/target_types.xml | 3 |
5 files changed, 656 insertions, 4 deletions
diff --git a/src/include/usr/fapi2/attribute_service.H b/src/include/usr/fapi2/attribute_service.H index d4c21af4a..a6e793914 100644 --- a/src/include/usr/fapi2/attribute_service.H +++ b/src/include/usr/fapi2/attribute_service.H @@ -50,7 +50,6 @@ #include <plat_attr_override_sync.H> #include <vpd/spdenums.H> - //****************************************************************************** // Interface //****************************************************************************** @@ -255,6 +254,28 @@ ReturnCode platGetPoundWBucketData(const Target<TARGET_TYPE_ALL>& i_fapiTarget, ReturnCode platGetWOFTableData(const Target<TARGET_TYPE_ALL>& i_fapiTarget, uint8_t * o_wofTableData); +/// +/// @brief This function is called by the FAPI_ATTR_GET macro when getting +/// the Bad DQ Bitmap attribute. It should not be called directly. +/// +/// @param[in] i_fapiTarget DIMM target pointer +/// @param[out] o_data Bad DIMM DQ Bitmap +/// @return ReturnCode. Zero on success, else platform specified error +/// +ReturnCode fapiAttrGetBadDqBitmap( const Target<TARGET_TYPE_ALL>& i_fapiTarget, + ATTR_BAD_DQ_BITMAP_Type (&o_data) ); + +/// +/// @brief This function is called by the FAPI_ATTR_SET macro when setting +/// the Bad DQ Bitmap attribute. It should not be called directly. +/// +/// @param[in] i_fapiTarget DIMM target pointer +/// @param[in] i_data Bad DIMM DQ Bitmap +/// @return ReturnCode. Zero on success, else platform specified error +/// +ReturnCode fapiAttrSetBadDqBitmap( const Target<TARGET_TYPE_ALL>& i_fapiTarget, + ATTR_BAD_DQ_BITMAP_Type (&i_data) ); + // ----------------------------------------------------------------------------- // End TODO: End to be supported functions // ----------------------------------------------------------------------------- @@ -344,4 +365,20 @@ fapiToTargeting::ID, sizeof(VAL), &(VAL)) ? fapi2::ReturnCode() : \ fapi2::platAttrSvc::platGetWOFTableData(TARGET,VAL) +//------------------------------------------------------------------------------ +// MACRO to route ATTR_BAD_DQ_BITMAP read access to the correct HB function +//------------------------------------------------------------------------------ +#define ATTR_BAD_DQ_BITMAP_GETMACRO(ID, TARGET, VAL) \ + AttrOverrideSync::getAttrOverrideFunc(ID, TARGET, &VAL)\ + ? fapi2::ReturnCode() : \ + fapi2::platAttrSvc::fapiAttrGetBadDqBitmap(TARGET, VAL) + +//------------------------------------------------------------------------------ +// MACRO to route ATTR_BAD_DQ_BITMAP write access to the correct HB function +//------------------------------------------------------------------------------ +#define ATTR_BAD_DQ_BITMAP_SETMACRO(ID, TARGET, VAL) \ + AttrOverrideSync::getAttrOverrideFunc(ID, TARGET, &VAL)\ + ? fapi2::ReturnCode() : \ + fapi2::platAttrSvc::fapiAttrSetBadDqBitmap(TARGET, VAL) + #endif // ATTRIBUTESERVICE_H_ diff --git a/src/include/usr/fapi2/hwpf_fapi2_reasoncodes.H b/src/include/usr/fapi2/hwpf_fapi2_reasoncodes.H index cacf48262..73477fc57 100644 --- a/src/include/usr/fapi2/hwpf_fapi2_reasoncodes.H +++ b/src/include/usr/fapi2/hwpf_fapi2_reasoncodes.H @@ -58,6 +58,7 @@ namespace fapi2 MOD_FAPI2_PIB_ERR_MASK = 0x0F, MOD_FAPI2_PLAT_PARSE_WOF_TABLES = 0x10, MOD_FAPI2_CVPD_ACCESS = 0x11, + MOD_FAPI2_BAD_DQ_BITMAP = 0x12, }; /** @@ -124,6 +125,9 @@ namespace fapi2 // HWP generated errors RC_HWP_GENERATED_ERROR = HWPF_COMP_ID | 0x0f, + // DIMM SPD generated errors + RC_BAD_DQ_MFG_MODE_BITS = HWPF_COMP_ID | 0x30, + }; /** @@ -135,6 +139,22 @@ namespace fapi2 HWPF_FAPI2_UDT_HWP_FFDC = 0x02, HWPF_FAPI2_UDT_STEP_ERROR_DETAILS = 0x03, }; + + /** + * @brief Defines the BAD_DQ_BITMAP error log detail data sections + */ + enum fapi2BadDqBitmapDataSection + { + CLEAN_BAD_DQ_BITMAP_RANK0 = 0x01, + CLEAN_BAD_DQ_BITMAP_RANK1 = 0x02, + CLEAN_BAD_DQ_BITMAP_RANK2 = 0x03, + CLEAN_BAD_DQ_BITMAP_RANK3 = 0x04, + CURRENT_BAD_DQ_BITMAP_RANK0 = 0x05, + CURRENT_BAD_DQ_BITMAP_RANK1 = 0x06, + CURRENT_BAD_DQ_BITMAP_RANK2 = 0x07, + CURRENT_BAD_DQ_BITMAP_RANK3 = 0x08, + }; + }; #endif // HWPF_FAPI2_REASONCODES_H_ diff --git a/src/usr/fapi2/attribute_service.C b/src/usr/fapi2/attribute_service.C index 43ebb6bcb..bb8fc94f1 100644 --- a/src/usr/fapi2/attribute_service.C +++ b/src/usr/fapi2/attribute_service.C @@ -60,6 +60,7 @@ #include <targeting/common/predicates/predicatectm.H> #include <targeting/common/utilFilter.H> #include <targeting/common/util.H> +#include <../memory/lib/shared/mss_const.H> //****************************************************************************** // Implementation @@ -516,6 +517,602 @@ ReturnCode platGetWOFTableData(const Target<TARGET_TYPE_ALL>& i_fapiTarget, return rc; } +//****************************************************************************** +// fapi2::platAttrSvc::__getMcsAndPortSlct function +//****************************************************************************** +ReturnCode __getMcsAndPortSlct( const Target<TARGET_TYPE_DIMM>& i_fapiDimm, + TARGETING::TargetHandle_t &o_mcsTarget, + uint32_t o_ps ) +{ + fapi2::ReturnCode l_rc; + errlHndl_t l_errl = nullptr; + + do + { + // determine whether this is a Nimbus or Cumulus chip + TARGETING::Target * masterProc = nullptr; + TARGETING::targetService().masterProcChipTargetHandle(masterProc); + TARGETING::ATTR_MODEL_type procType = + masterProc->getAttr<TARGETING::ATTR_MODEL>(); + + TARGETING::TargetHandle_t l_port = nullptr; + + // If the proc is Cumulus, we need to get the MBA. + if ( TARGETING::MODEL_CUMULUS == procType ) + { + Target<TARGET_TYPE_MBA> l_fapiMba = + i_fapiDimm.getParent<TARGET_TYPE_MBA>(); + l_errl = getTargetingTarget( l_fapiMba, l_port ); + if ( l_errl ) + { + FAPI_ERR( "__getMcsAndPortSlct: Error from " + "getTargetingTarget getting MBA." ); + l_rc.setPlatDataPtr(reinterpret_cast<void *> (l_errl)); + break; + } + + // Get the MCS. + TARGETING::TargetHandleList l_memBufList; + getParentAffinityTargets( l_memBufList, l_port, + TARGETING::CLASS_CHIP, TARGETING::TYPE_MEMBUF ); + + TARGETING::TargetHandleList l_mcsList; + getParentAffinityTargets( l_mcsList, l_memBufList[0], + TARGETING::CLASS_UNIT, TARGETING::TYPE_MCS ); + o_mcsTarget = l_mcsList[0]; + + } + // If the proc is Nimbus, we need to get the MCA. + else + { + Target<TARGET_TYPE_MCA> l_fapiMca = + i_fapiDimm.getParent<TARGET_TYPE_MCA>(); + l_errl = getTargetingTarget( l_fapiMca, l_port ); + if ( l_errl ) + { + FAPI_ERR( "__getMcsAndPortSlct: Error from " + "getTargetingTarget getting MCA." ); + l_rc.setPlatDataPtr(reinterpret_cast<void *> (l_errl)); + break; + } + + // Get the MCS. + Target<TARGET_TYPE_MCS> l_fapiMcs; + l_fapiMcs = l_fapiMca.getParent<TARGET_TYPE_MCS>(); + + l_errl = getTargetingTarget( l_fapiMcs, o_mcsTarget ); + if ( l_errl ) + { + FAPI_ERR( "__getMcsAndPortSlct: Error from " + "getTargetingTarget getting MCS." ); + l_rc.setPlatDataPtr(reinterpret_cast<void *> (l_errl)); + break; + } + + } + + o_ps = l_port->getAttr<TARGETING::ATTR_CHIP_UNIT>() % + mss::PORTS_PER_MCS; + + }while(0); + + return l_rc; +} + + +//****************************************************************************** +// fapi2::platAttrSvc::__badDqBitmapGetHelperAttrs function +//****************************************************************************** +ReturnCode __badDqBitmapGetHelperAttrs( + const TARGETING::TargetHandle_t i_dimmTarget, + uint8_t (&o_wiringData)[mss::PORTS_PER_MCS][mss::MAX_DQ_BITS], + uint64_t &o_allMnfgFlags, uint32_t o_ps ) +{ + fapi2::ReturnCode l_rc; + + do + { + // memset to avoid known syntax issue with previous compiler versions + // and ensure zero initialized array. + memset( o_wiringData, 0, sizeof(o_wiringData) ); + + Target<TARGET_TYPE_DIMM> l_fapiDimm( i_dimmTarget ); + TARGETING::TargetHandle_t l_mcsTarget = nullptr; + + __getMcsAndPortSlct( l_fapiDimm, l_mcsTarget, o_ps ); + + // Get the DQ to DIMM Connector DQ Wiring attribute. + // Note that for C-DIMMs, this will return a simple 1:1 mapping. + // This code cannot tell the difference between C-DIMMs and IS-DIMMs. + l_rc = FAPI_ATTR_GET( fapi2::ATTR_MSS_VPD_DQ_MAP, l_mcsTarget, + o_wiringData ); + if ( l_rc ) + { + FAPI_ERR( "__badDqBitmapGetHelperAttrs: Unable to read attribute - " + "ATTR_MSS_VPD_DQ_MAP" ); + break; + } + + // Manufacturing flags attribute + o_allMnfgFlags = 0; + + // Get the manufacturing flags bitmap to be used in both get and set + l_rc = FAPI_ATTR_GET( fapi2::ATTR_MNFG_FLAGS, + fapi2::Target<fapi2::TARGET_TYPE_SYSTEM>(), + o_allMnfgFlags ); + if ( l_rc ) + { + FAPI_ERR( "__badDqBitmapGetHelperAttrs: Unable to read attribute - " + "ATTR_MNFG_FLAGS" ); + break; + } + + }while(0); + + return l_rc; +} + +//****************************************************************************** +// fapi2::platAttrSvc::__dimmUpdateDqBitmapEccByte function +//****************************************************************************** +errlHndl_t __dimmUpdateDqBitmapEccByte( + TARGETING::TargetHandle_t i_dimm, + uint8_t (&o_data)[mss::MAX_RANK_PER_DIMM][mss::BAD_DQ_BYTE_COUNT] ) +{ + errlHndl_t l_errl = nullptr; + + const uint8_t ECC_DQ_BYTE_NUMBER_INDEX = 8; + const uint8_t ENUM_ATTR_SPD_MODULE_MEMORY_BUS_WIDTH_WE8 = 0x08; + size_t MEM_BUS_WIDTH_SIZE = 0x01; + + do + { + uint8_t *l_eccBits = static_cast<uint8_t*>(malloc(MEM_BUS_WIDTH_SIZE)); + + l_errl = deviceRead( i_dimm, + l_eccBits, + MEM_BUS_WIDTH_SIZE, + DEVICE_SPD_ADDRESS(SPD::MODULE_MEMORY_BUS_WIDTH) ); + if ( l_errl ) + { + FAPI_ERR( "__dimmUpdateDqBitmapEccByte: Failed to get " + "SPD::MODULE_MEMORY_BUS_WIDTH." ); + break; + } + + // The ATTR_SPD_MODULE_MEMORY_BUS_WIDTH contains ENUM values + // for bus widths of 8, 16, 32, and 64 bits both with ECC + // and without ECC. WExx ENUMS denote the ECC extension + // is present, and all have bit 3 set. Therefore, + // it is only required to check against the WE8 = 0x08 ENUM + // value in order to determine if ECC lines are present. + if ( !(ENUM_ATTR_SPD_MODULE_MEMORY_BUS_WIDTH_WE8 & *l_eccBits) ) + { + // Iterate through each rank and set DQ bits in + // caller's data. + for ( uint8_t i = 0; i < mss::MAX_RANK_PER_DIMM; i++ ) + { + // Set DQ bits in caller's data + o_data[i][ECC_DQ_BYTE_NUMBER_INDEX] = 0xFF; + } + } + }while(0); + + return l_errl; +} + +//****************************************************************************** +// fapi2::platAttrSvc::__dimmGetDqBitmapSpareByte function +//****************************************************************************** +ReturnCode __dimmGetDqBitmapSpareByte( TARGETING::TargetHandle_t i_dimm, + uint8_t (&o_spareByte)[mss::MAX_RANK_PER_DIMM]) +{ + ReturnCode l_rc; + + do + { + // Spare DRAM Attribute: Returns spare DRAM availability for + // all DIMMs associated with the target MCS. + uint8_t l_dramSpare[mss::PORTS_PER_MCS][mss::MAX_DIMM_PER_PORT] + [mss::MAX_RANK_PER_DIMM] = {}; + + Target<TARGET_TYPE_DIMM> l_fapiDimm( i_dimm ); + + uint32_t l_ds = i_dimm->getAttr<TARGETING::ATTR_FAPI_POS>() % + mss::MAX_DIMM_PER_PORT; + + TARGETING::TargetHandle_t l_mcsTarget = nullptr; + uint32_t l_ps = 0; + __getMcsAndPortSlct( l_fapiDimm, l_mcsTarget, l_ps ); + + l_rc = FAPI_ATTR_GET( fapi2::ATTR_EFF_DIMM_SPARE, l_mcsTarget, + l_dramSpare ); + if ( l_rc ) + { + FAPI_ERR( "__dimmGetDqBitmapSpareByte: Error getting DRAM Spare " + "data." ); + break; + } + + // Iterate through each rank of this DIMM + for ( uint8_t i = 0; i < mss::MAX_RANK_PER_DIMM; i++ ) + { + // Handle spare DRAM configuration cases + switch ( l_dramSpare[l_ps][l_ds][i] ) + { + case fapi2::ENUM_ATTR_EFF_DIMM_SPARE_NO_SPARE: + // Set DQ bits reflecting unconnected + // spare DRAM in caller's data + o_spareByte[i] = 0xFF; + break; + + case fapi2::ENUM_ATTR_EFF_DIMM_SPARE_LOW_NIBBLE: + o_spareByte[i] = 0x0F; + break; + + case fapi2::ENUM_ATTR_EFF_DIMM_SPARE_HIGH_NIBBLE: + o_spareByte[i] = 0xF0; + break; + + // As erroneous value will not be encountered. + case fapi2::ENUM_ATTR_EFF_DIMM_SPARE_FULL_BYTE: + default: + o_spareByte[i] = 0x0; + break; + } + } + + }while(0); + + return l_rc; + +} + +//****************************************************************************** +// fapi2::platAttrSvc::__dimmUpdateDqBitmapSpareByte function +//****************************************************************************** +ReturnCode __dimmUpdateDqBitmapSpareByte( + TARGETING::TargetHandle_t i_dimm, + uint8_t (&o_data)[mss::MAX_RANK_PER_DIMM][mss::BAD_DQ_BYTE_COUNT] ) +{ + ReturnCode l_rc; + const uint8_t SPARE_DRAM_DQ_BYTE_NUMBER_INDEX = 9; + + do + { + uint8_t spareByte[mss::MAX_RANK_PER_DIMM]; + memset( spareByte, 0, sizeof(spareByte) ); + + l_rc = __dimmGetDqBitmapSpareByte( i_dimm, spareByte ); + + if ( l_rc ) + { + FAPI_ERR("__dimmUpdateDqBitmapSpareByte: Error getting spare byte"); + break; + } + + for ( uint32_t i = 0; i < mss::MAX_RANK_PER_DIMM; i++ ) + { + o_data[i][SPARE_DRAM_DQ_BYTE_NUMBER_INDEX] |= spareByte[i]; + } + + }while(0); + + return l_rc; +} + +//****************************************************************************** +// fapi2::platAttrSvc::__compareEccAndSpare function +//****************************************************************************** +ReturnCode __compareEccAndSpare(TARGETING::TargetHandle_t i_dimm, + bool & o_mfgModeBadBitsPresent, + uint8_t i_callersData[mss::MAX_RANK_PER_DIMM][mss::BAD_DQ_BYTE_COUNT], + uint8_t (&o_eccSpareBitmap)[mss::MAX_RANK_PER_DIMM][mss::BAD_DQ_BYTE_COUNT]) +{ + + // This function will compare o_eccSpareBitmap, which represents a bad dq + // bitmap with the appropriate spare/ECC bits set (if any) and all other DQ + // lines functional, to the caller's data. If discrepancies are found, we + // know this is the result of a manufacturing mode process and these bits + // should not be recorded. + + ReturnCode l_rc; + errlHndl_t l_errl = nullptr; + + do + { + // Zero-initialize the o_eccSpareBitmap bad dq bitmap. + memset( o_eccSpareBitmap, 0, sizeof(o_eccSpareBitmap) ); + + // Check ECC. + l_errl = __dimmUpdateDqBitmapEccByte(i_dimm, o_eccSpareBitmap); + if ( l_errl ) + { + FAPI_ERR( "__compareEccAndSpare: Error getting ECC data " + "(Mfg mode)" ); + l_rc = fapi2::FAPI2_RC_INVALID_ATTR_GET; + break; + } + + // Check spare DRAM. + l_rc = __dimmUpdateDqBitmapSpareByte(i_dimm, o_eccSpareBitmap); + if ( l_rc ) + { + FAPI_ERR( "__compareEccAndSpare: Error getting spare DRAM data " + "(Mfg mode)" ); + break; + } + + // Compare o_eccSpareBitmap to i_callersData. + for ( uint8_t i = 0; i < mss::MAX_RANK_PER_DIMM; i++ ) + { + for (uint8_t j = 0; j < mss::BAD_DQ_BYTE_COUNT; j++) + { + if ( i_callersData[i][j] != + o_eccSpareBitmap[i][j] ) + { + o_mfgModeBadBitsPresent = true; + break; + } + } + if ( o_mfgModeBadBitsPresent ) break; + } + + // Create and log error if discrepancies were found. + if ( o_mfgModeBadBitsPresent ) + { + FAPI_ERR( "__compareEccAndSpare: Read/write requested while in " + "DISABLE_DRAM_REPAIRS mode found extra bad bits set for " + "DIMM" ); + + /*@ + * @errortype + * @moduleid MOD_FAPI2_BAD_DQ_BITMAP + * @reasoncode RC_BAD_DQ_MFG_MODE_BITS + * @userdata1 DIMM Target HUID + * @userdata2 <unused> + * @devdesc Extra bad bits set for DIMM + * @custdesc Read/write requested while in + * DISABLE_DRAM_REPAIRS mode found + * extra bad bits set for DIMM + */ + l_errl = new ERRORLOG::ErrlEntry( + ERRORLOG::ERRL_SEV_INFORMATIONAL, + MOD_FAPI2_BAD_DQ_BITMAP, + RC_BAD_DQ_MFG_MODE_BITS, + TARGETING::get_huid(i_dimm) ); + + l_errl->addFFDC( HWPF_COMP_ID, &o_eccSpareBitmap[0], + sizeof(o_eccSpareBitmap[0]), 1, + CLEAN_BAD_DQ_BITMAP_RANK0 ); + + l_errl->addFFDC( HWPF_COMP_ID, &o_eccSpareBitmap[1], + sizeof(o_eccSpareBitmap[1]), 1, + CLEAN_BAD_DQ_BITMAP_RANK1 ); + + l_errl->addFFDC( HWPF_COMP_ID, &o_eccSpareBitmap[2], + sizeof(o_eccSpareBitmap[2]), 1, + CLEAN_BAD_DQ_BITMAP_RANK2 ); + + l_errl->addFFDC( HWPF_COMP_ID, &o_eccSpareBitmap[3], + sizeof(o_eccSpareBitmap[3]), 1, + CLEAN_BAD_DQ_BITMAP_RANK3 ); + + l_errl->addFFDC( HWPF_COMP_ID, &i_callersData[0], + sizeof(i_callersData[0]), 1, + CURRENT_BAD_DQ_BITMAP_RANK0 ); + + l_errl->addFFDC( HWPF_COMP_ID, &i_callersData[1], + sizeof(i_callersData[1]), 1, + CURRENT_BAD_DQ_BITMAP_RANK1 ); + + l_errl->addFFDC( HWPF_COMP_ID, &i_callersData[2], + sizeof(i_callersData[2]), 1, + CURRENT_BAD_DQ_BITMAP_RANK2 ); + + l_errl->addFFDC( HWPF_COMP_ID, &i_callersData[3], + sizeof(i_callersData[3]), 1, + CURRENT_BAD_DQ_BITMAP_RANK3 ); + + errlCommit( l_errl, HWPF_COMP_ID ); + } + }while(0); + + return l_rc; +} + +//****************************************************************************** +// fapi2::platAttrSvc::fapiAttrGetBadDqBitmap function +//****************************************************************************** +ReturnCode fapiAttrGetBadDqBitmap( + const Target<TARGET_TYPE_ALL>& i_dimmFapiTarget, + ATTR_BAD_DQ_BITMAP_Type (&o_data) ) +{ + FAPI_INF(">>fapiAttrGetBadDqBitmap: Getting bitmap"); + + // define structure for the format of DIMM_BAD_DQ_DATA + struct dimmBadDqDataFormat + { + uint32_t iv_magicNumber; + uint8_t iv_version; + uint8_t iv_reserved1; + uint8_t iv_reserved2; + uint8_t iv_reserved3; + uint8_t iv_bitmaps[mss::MAX_RANK_PER_DIMM][mss::BAD_DQ_BYTE_COUNT]; + }; + + // constant definitions + const uint32_t DIMM_BAD_DQ_MAGIC_NUMBER = 0xbadd4471; + const uint8_t DIMM_BAD_DQ_VERSION = 1; + size_t DIMM_BAD_DQ_SIZE_BYTES = 0x50; + + fapi2::ReturnCode l_rc; + errlHndl_t l_errl = nullptr; + TARGETING::TargetHandle_t l_dimmTarget = nullptr; + + do + { + l_errl = getTargetingTarget( i_dimmFapiTarget, l_dimmTarget ); + if ( l_errl ) + { + FAPI_ERR( "fapiAttrGetBadDqBitmap: Error from getTargetingTarget" ); + l_rc.setPlatDataPtr(reinterpret_cast<void *> (l_errl)); + break; + } + + uint8_t l_wiringData[mss::PORTS_PER_MCS][mss::MAX_DQ_BITS]; + uint64_t l_allMnfgFlags; + uint32_t l_ps = 0; + + l_rc = __badDqBitmapGetHelperAttrs( l_dimmTarget, l_wiringData, + l_allMnfgFlags, l_ps ); + if ( l_rc ) + { + FAPI_ERR( "fapiAttrGetBadDqBitmap: Error - unable to read " + "attributes" ); + break; + } + + uint8_t * l_badDqData = + static_cast<uint8_t*>( malloc(DIMM_BAD_DQ_SIZE_BYTES) ); + + l_errl = deviceRead(l_dimmTarget, l_badDqData, + DIMM_BAD_DQ_SIZE_BYTES, + DEVICE_SPD_ADDRESS(SPD::DIMM_BAD_DQ_DATA)); + if ( l_errl ) + { + FAPI_ERR( "fapiAttrGetBadDqBitmap: Failed to read DIMM Bad DQ " + "data." ); + l_rc.setPlatDataPtr(reinterpret_cast<void *> (l_errl)); + break; + } + + dimmBadDqDataFormat l_spdData; + memcpy( &l_spdData, l_badDqData, sizeof(dimmBadDqDataFormat) ); + + // Zero caller's data + memset(o_data, 0, sizeof(o_data)); + + // Check the magic number and version number. Note that the + // magic number is stored in SPD in big endian format and + // platforms of any endianness can access it + if ( (be32toh(l_spdData.iv_magicNumber) != + DIMM_BAD_DQ_MAGIC_NUMBER) || + (l_spdData.iv_version != DIMM_BAD_DQ_VERSION) ) + { + FAPI_INF( "fapiAttrGetBadDqBitmap: SPD DQ not initialized." ); + } + else + { + // Translate bitmap from DIMM DQ to Centaur DQ point of view + // for each rank + for (uint8_t i = 0; i < mss::MAX_RANK_PER_DIMM; i++) + { + // Iterate through all the DQ bits in the rank + for (uint8_t j = 0; j < mss::MAX_DQ_BITS; j++) + { + // There is a byte for each 8 DQs, j/8 gives the + // byte number. The MSB in each byte is the lowest + // DQ, (0x80 >> (j % 8)) gives the bit mask + // corresponding to the DQ within the byte + if ((l_spdData.iv_bitmaps[i][j/8]) & + (0x80 >> (j % 8))) + { + // DIMM DQ bit is set in SPD data. + // Set Centaur DQ bit in caller's data. + // The wiring data maps Centaur DQ to DIMM DQ + // Find the Centaur DQ that maps to this DIMM DQ + uint8_t k = 0; + for (; k < mss::MAX_DQ_BITS; k++) + { + if (l_wiringData[l_ps][k] == j) + { + o_data[i][k/8] |= (0x80 >> (k % 8)); + break; + } + } + + if (k == mss::MAX_DQ_BITS) + { + FAPI_INF( "fapiAttrGetBadDqBitmap: " + "Centaur DQ not found for %d!",j); + } + } + } + } + + // Set bits for any unconnected DQs. + // First, check ECC. + l_errl = __dimmUpdateDqBitmapEccByte( l_dimmTarget, o_data ); + if ( l_errl ) + { + FAPI_ERR( "fapiAttrGetBadDqBitmap: Error getting ECC data" ); + l_rc.setPlatDataPtr(reinterpret_cast<void *> (l_errl)); + break; + } + + // Check spare DRAM. + l_rc = __dimmUpdateDqBitmapSpareByte( l_dimmTarget, o_data ); + if ( l_rc ) + { + FAPI_ERR( "fapiAttrGetBadDqBitmap: Error getting spare DRAM " + "data" ); + break; + } + + if ( l_allMnfgFlags & + fapi2::ENUM_ATTR_MNFG_FLAGS_MNFG_DISABLE_DRAM_REPAIRS ) + { + // Flag to set if the discrepancies are found. + bool mfgModeBadBitsPresent = false; + + uint8_t l_eccSpareBitmap[mss::MAX_RANK_PER_DIMM] + [mss::BAD_DQ_BYTE_COUNT]; + + l_rc = __compareEccAndSpare( l_dimmTarget, + mfgModeBadBitsPresent, o_data, + l_eccSpareBitmap); + if ( l_rc ) + { + FAPI_ERR( "fapiAttrGetBadDqBitmap: Error comparing bitmap " + "with ECC/Spare bits set with caller's data" ); + break; + } + + if ( mfgModeBadBitsPresent ) + { + // correct the output bit map + for (uint8_t i = 0; i < mss::MAX_RANK_PER_DIMM; i++) + { + for ( uint8_t j=0; j < (mss::BAD_DQ_BYTE_COUNT); + j++ ) + { + o_data[i][j] = l_eccSpareBitmap[i][j]; + } + } + } + } + + } + + }while(0); + + return l_rc; +} + +//****************************************************************************** +// fapi2::platAttrSvc::fapiAttrSetBadDqBitmap function +//****************************************************************************** +ReturnCode fapiAttrSetBadDqBitmap( + const Target<TARGET_TYPE_ALL>& i_mcsFapiTarget, + ATTR_BAD_DQ_BITMAP_Type (&i_data) ) +{ + fapi2::ReturnCode l_rc; + + // TODO RTC 173476 + + return l_rc; +} } // End platAttrSvc namespace diff --git a/src/usr/fapi2/fapi2.mk b/src/usr/fapi2/fapi2.mk index 243ddf0f2..963bd4a30 100755 --- a/src/usr/fapi2/fapi2.mk +++ b/src/usr/fapi2/fapi2.mk @@ -36,6 +36,7 @@ HWP_PATH += ${HWP_PATH_1}/ ${HWP_PATH_2}/ EXTRAINCDIR += ${ROOTPATH}/src/import/hwpf/fapi2/include/ EXTRAINCDIR += ${ROOTPATH}/src/include/usr EXTRAINCDIR += ${ROOTPATH}/src/include/usr/fapi2/ +EXTRAINCDIR += ${ROOTPATH}/src/import/ EXTRAINCDIR += ${ROOTPATH}/src/import/chips/p9/utils/ EXTRAINCDIR += ${ROOTPATH}/src/import/chips/centaur/common/include/ EXTRAINCDIR += ${ROOTPATH}/src/import/chips/p9/utils/imageProcs/ diff --git a/src/usr/targeting/common/xmltohb/target_types.xml b/src/usr/targeting/common/xmltohb/target_types.xml index 5aca00eef..c2e69737d 100755 --- a/src/usr/targeting/common/xmltohb/target_types.xml +++ b/src/usr/targeting/common/xmltohb/target_types.xml @@ -3483,9 +3483,6 @@ <id>EFF_DRAM_TRRD_DLR</id> </attribute> <attribute> - <id>BAD_DQ_BITMAP</id> - </attribute> - <attribute> <id>MSS_DIMM_THERMAL_LIMIT</id> </attribute> <attribute> |