diff options
-rw-r--r-- | src/include/usr/hwpf/hwp/dimmBadDqBitmapAccessHwp.H | 44 | ||||
-rw-r--r-- | src/include/usr/hwpf/hwp/mvpd_accessors/getMBvpdSpareDramData.H | 56 | ||||
-rw-r--r-- | src/include/usr/hwpf/hwpf_reasoncodes.H | 2 | ||||
-rw-r--r-- | src/include/usr/hwpf/plat/fapiPlatAttributeService.H | 75 | ||||
-rw-r--r-- | src/usr/hwpf/hwp/dimmBadDqBitmapAccessHwp.C | 220 | ||||
-rw-r--r-- | src/usr/hwpf/hwp/dimmBadDqBitmapFuncs.C | 30 | ||||
-rw-r--r-- | src/usr/hwpf/hwp/dimm_spd_attributes.xml | 64 | ||||
-rw-r--r-- | src/usr/hwpf/hwp/fapiTestHwpDq.C | 104 | ||||
-rw-r--r-- | src/usr/hwpf/hwp/mvpd_accessors/getMBvpdSpareDramData.C | 210 | ||||
-rw-r--r-- | src/usr/hwpf/hwp/mvpd_accessors/mvpd.mk | 3 | ||||
-rw-r--r-- | src/usr/hwpf/plat/fapiPlatAttributeService.C | 145 |
11 files changed, 805 insertions, 148 deletions
diff --git a/src/include/usr/hwpf/hwp/dimmBadDqBitmapAccessHwp.H b/src/include/usr/hwpf/hwp/dimmBadDqBitmapAccessHwp.H index fc7703ebc..7a3eb9925 100644 --- a/src/include/usr/hwpf/hwp/dimmBadDqBitmapAccessHwp.H +++ b/src/include/usr/hwpf/hwp/dimmBadDqBitmapAccessHwp.H @@ -1,25 +1,25 @@ -// IBM_PROLOG_BEGIN_TAG -// This is an automatically generated prolog. -// -// $Source: src/include/usr/hwpf/hwp/dimmBadDqBitmapAccessHwp.H $ -// -// IBM CONFIDENTIAL -// -// COPYRIGHT International Business Machines Corp. 2012 -// -// p1 -// -// Object Code Only (OCO) source materials -// Licensed Internal Code Source Materials -// IBM HostBoot Licensed Internal Code -// -// The source code for this program is not published or other- -// wise divested of its trade secrets, irrespective of what has -// been deposited with the U.S. Copyright Office. -// -// Origin: 30 -// -// IBM_PROLOG_END +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/include/usr/hwpf/hwp/dimmBadDqBitmapAccessHwp.H $ */ +/* */ +/* IBM CONFIDENTIAL */ +/* */ +/* COPYRIGHT International Business Machines Corp. 2012,2013 */ +/* */ +/* p1 */ +/* */ +/* Object Code Only (OCO) source materials */ +/* Licensed Internal Code Source Materials */ +/* IBM HostBoot Licensed Internal Code */ +/* */ +/* The source code for this program is not published or otherwise */ +/* divested of its trade secrets, irrespective of what has been */ +/* deposited with the U.S. Copyright Office. */ +/* */ +/* Origin: 30 */ +/* */ +/* IBM_PROLOG_END_TAG */ /** * @file dimmBadDqBitmapAccessHwp.H * diff --git a/src/include/usr/hwpf/hwp/mvpd_accessors/getMBvpdSpareDramData.H b/src/include/usr/hwpf/hwp/mvpd_accessors/getMBvpdSpareDramData.H new file mode 100644 index 000000000..6e05fb3f3 --- /dev/null +++ b/src/include/usr/hwpf/hwp/mvpd_accessors/getMBvpdSpareDramData.H @@ -0,0 +1,56 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/include/usr/hwpf/hwp/mvpd_accessors/getMBvpdSpareDramData.H $ */ +/* */ +/* IBM CONFIDENTIAL */ +/* */ +/* COPYRIGHT International Business Machines Corp. 2013 */ +/* */ +/* p1 */ +/* */ +/* Object Code Only (OCO) source materials */ +/* Licensed Internal Code Source Materials */ +/* IBM HostBoot Licensed Internal Code */ +/* */ +/* The source code for this program is not published or otherwise */ +/* divested of its trade secrets, irrespective of what has been */ +/* deposited with the U.S. Copyright Office. */ +/* */ +/* Origin: 30 */ +/* */ +/* IBM_PROLOG_END_TAG */ +#ifndef GETMBVPDSPAREDRAMDATA_H_ +#define GETMBVPDSPAREDRAMDATA_H_ + +#include <fapi.H> +#include <dimmConsts.H> + +typedef fapi::ReturnCode (*getMBvpdSpareDramData_FP_t)( + const fapi::Target &, + const fapi::Target &, + uint8_t &); + +extern "C" +{ + +/** + * @brief FW Team HWP that, for C-DIMMs, queries MBvpd to determine spare DRAM + * availability and, for IS-DIMMS, returns NO_SPARE. + * + * This HWP should be called through the VPD_DIMM_SPARE attribute. + * + * @param[in] i_mba Reference to MBA Target associated with the DIMM. + * @param[in] i_dimm Reference to DIMM Target. + * @param[out] o_data Reference to spare DRAM data. + * + * @return ReturnCode + */ +fapi::ReturnCode getMBvpdSpareDramData( + const fapi::Target & i_mba, + const fapi::Target & i_dimm, + uint8_t &o_data); + +} + +#endif diff --git a/src/include/usr/hwpf/hwpf_reasoncodes.H b/src/include/usr/hwpf/hwpf_reasoncodes.H index ea80fbfc2..871297e4c 100644 --- a/src/include/usr/hwpf/hwpf_reasoncodes.H +++ b/src/include/usr/hwpf/hwpf_reasoncodes.H @@ -60,6 +60,8 @@ namespace fapi MOD_VDDR_PROC_MSG = 0x15, MOD_VDDR_PROC_VDDR_MSG = 0x16, MOD_VDDR_SEND_MSG = 0x17, + MOD_PLAT_ATTR_SVC_GET_MIRR_DATA = 0x18, + MOD_PLAT_ATTR_SVC_GET_SPARE_DATA = 0x19, }; /** diff --git a/src/include/usr/hwpf/plat/fapiPlatAttributeService.H b/src/include/usr/hwpf/plat/fapiPlatAttributeService.H index 89b876a30..670b5125f 100644 --- a/src/include/usr/hwpf/plat/fapiPlatAttributeService.H +++ b/src/include/usr/hwpf/plat/fapiPlatAttributeService.H @@ -36,6 +36,7 @@ * mjjones 06/27/2011 Created. * bofferdn 09/13/2011 Support fapi->hb mapping * thi 01/28/2013 Add SPD CUSTOM attr + * dedahle 06/20/2013 Add Bad DIMM DQ Bitmap attr */ #ifndef FAPIPLATATTRIBUTESERVICE_H_ @@ -57,6 +58,7 @@ #include <hwpf/hwp/mvpd_accessors/getMBvpdAddrMirrorData.H> #include <hwpf/hwp/mvpd_accessors/getMBvpdTermData.H> #include <hwpf/hwp/mvpd_accessors/getMBvpdSlopeInterceptData.H> +#include <hwpf/hwp/mvpd_accessors/getMBvpdSpareDramData.H> #include <vpd/spdenums.H> #include <dimmConsts.H> #include <util/singleton.H> @@ -499,6 +501,59 @@ fapi::ReturnCode fapiPlatGetSlopeInterceptData ( const fapi::Target * i_pTarget, const fapi::MBvpdSlopeIntercept i_attr, uint32_t & o_Val); + +//------------------------------------------------------------------------------ +// Prototypes to support BAD_DQ_BITMAP attribute +// See dimm_spd_attributes.xml for detailed descriptions +//------------------------------------------------------------------------------ + +/** + * @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_pTarget Target pointer + * @param[out] o_data Bad DIMM DQ Bitmap + * @return ReturnCode. Zero on success, else platform specified error + */ +fapi::ReturnCode fapiPlatDimmGetBadDqBitmap ( + const fapi::Target * i_pTarget, + uint8_t (&o_data)[DIMM_DQ_MAX_DIMM_RANKS]\ + [DIMM_DQ_RANK_BITMAP_SIZE]); + +/** + * @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_pTarget Target pointer + * @param[in] i_data Bad DIMM DQ Bitmap + * @return ReturnCode. Zero on success, else platform specified error + */ +fapi::ReturnCode fapiPlatDimmSetBadDqBitmap ( + const fapi::Target * i_pTarget, + uint8_t (&i_data)[DIMM_DQ_MAX_DIMM_RANKS]\ + [DIMM_DQ_RANK_BITMAP_SIZE]); + +//------------------------------------------------------------------------------ +// Prototype to support VPD_DIMM_SPARE attribute +// See dimm_spd_attributes.xml for detailed description +//------------------------------------------------------------------------------ + +/** + * @brief This function is called by the FAPI_ATTR_GET macro when getting + * the VPD DIMM Spare attribute + * It should not be called directly. + * + * @param[in] i_pTarget Target pointer + * @param[out] o_data Spare DRAM availability for DIMM + * @return ReturnCode. Zero on success, else platform specified error + */ +fapi::ReturnCode fapiPlatDimmGetSpareDram ( + const fapi::Target * i_pTarget, + uint8_t &o_data); + + } // namespace platAttrSvc } // namespace fapi @@ -1444,4 +1499,24 @@ fapi::ReturnCode fapiPlatGetSlopeInterceptData ( fapi::platAttrSvc::fapiPlatGetSlopeInterceptData\ (PTARGET, fapi::SUPPLIER_POWER_INTERCEPT , VAL) +//------------------------------------------------------------------------------ +// MACRO to support BAD_DQ_BITMAP Attribute +//------------------------------------------------------------------------------ +#define ATTR_BAD_DQ_BITMAP_GETMACRO(ID, PTARGET, VAL)\ + fapi::AttrOverrideSync::getAttrOverrideFunc(fapi::ID, PTARGET, &VAL) ?\ + fapi::FAPI_RC_SUCCESS : fapi::platAttrSvc::fapiPlatDimmGetBadDqBitmap\ + (PTARGET, VAL) +#define ATTR_BAD_DQ_BITMAP_SETMACRO(ID, PTARGET, VAL)\ + fapi::AttrOverrideSync::setAttrActionsFunc(fapi::ID, PTARGET,\ + sizeof(VAL), &VAL),\ + fapi::platAttrSvc::fapiPlatDimmSetBadDqBitmap(PTARGET, VAL) + +//------------------------------------------------------------------------------ +// MACRO to support VPD_DIMM_SPARE Attribute +//------------------------------------------------------------------------------ +#define ATTR_VPD_DIMM_SPARE_GETMACRO(ID, PTARGET, VAL)\ + fapi::AttrOverrideSync::getAttrOverrideFunc(fapi::ID, PTARGET, &VAL) ?\ + fapi::FAPI_RC_SUCCESS : fapi::platAttrSvc::fapiPlatDimmGetSpareDram\ + (PTARGET, VAL) + #endif // FAPIPLATATTRIBUTESERVICE_H_ diff --git a/src/usr/hwpf/hwp/dimmBadDqBitmapAccessHwp.C b/src/usr/hwpf/hwp/dimmBadDqBitmapAccessHwp.C index 8b3f879ed..439f21ce0 100644 --- a/src/usr/hwpf/hwp/dimmBadDqBitmapAccessHwp.C +++ b/src/usr/hwpf/hwp/dimmBadDqBitmapAccessHwp.C @@ -33,6 +33,7 @@ * mjjones 02/17/2012 Created. * mjjones 01/30/2013 Cope with platform endian * differences + * dedahle 06/22/2013 Show unconnected DQ lines */ #include <dimmBadDqBitmapAccessHwp.H> @@ -40,6 +41,8 @@ // DQ Data format in DIMM SPD const uint32_t DIMM_BAD_DQ_MAGIC_NUMBER = 0xbadd4471; const uint8_t DIMM_BAD_DQ_VERSION = 1; +const uint8_t ECC_DQ_BYTE_NUMBER_INDEX = 8; +const uint8_t SPARE_DRAM_DQ_BYTE_NUMBER_INDEX = 9; struct dimmBadDqDataFormat { @@ -51,6 +54,83 @@ struct dimmBadDqDataFormat uint8_t iv_bitmaps[DIMM_DQ_MAX_DIMM_RANKS][DIMM_DQ_RANK_BITMAP_SIZE]; }; + +extern "C" +{ + +/** + * @brief Called by dimmBadDqBitmapAccessHwp() to query ATR_VPD_DIMM_SPARE + * and set bits for unconnected spare DRAM in caller's data. + * + * + * @param[in] i_dimm Reference to DIMM Target. + * @param[o] o_data Reference to Bad DQ Bitmap set by + * the caller. Only the SPARE_DRAM_DQ_BYTE_NUMBER_INDEX + * byte is modified by this function. + * + * @return ReturnCode + */ + +fapi::ReturnCode dimmUpdateDqBitmapSpareByte( + const fapi::Target & i_dimm, + uint8_t (&o_data)[DIMM_DQ_MAX_DIMM_RANKS][DIMM_DQ_RANK_BITMAP_SIZE]) +{ + fapi::ReturnCode l_rc; + + do + { + // Spare DRAM Attribute + uint8_t l_dimmSpare = 0; + l_rc = FAPI_ATTR_GET(ATTR_VPD_DIMM_SPARE, &i_dimm, l_dimmSpare); + if (l_rc) + { + FAPI_ERR("dimmCheckSpareDram: " + "Error getting DRAM Spare data"); + break; + } + + // Bitmask and beginning bit shift values for decoding + // ATTR_VPD_DIMM_SPARE attribute as described in + // dimm_spd_attributes.xml. + uint8_t l_dimmMask = 0xC0; + uint8_t l_rankBitShift = 6; + + // Iterate through each rank of this DIMM + for (uint8_t i = 0; i < DIMM_DQ_MAX_DIMM_RANKS; i++) + { + // Handle spare DRAM configuration cases + switch ((l_dimmSpare & l_dimmMask) >> l_rankBitShift) + { + case fapi::ENUM_ATTR_VPD_DIMM_SPARE_NO_SPARE: + // Set DQ bits reflecting unconnected + // spare DRAM in caller's data + o_data[i][SPARE_DRAM_DQ_BYTE_NUMBER_INDEX] = 0xFF; + break; + + case fapi::ENUM_ATTR_VPD_DIMM_SPARE_LOW_NIBBLE: + o_data[i][SPARE_DRAM_DQ_BYTE_NUMBER_INDEX] = 0x0F; + break; + + case fapi::ENUM_ATTR_VPD_DIMM_SPARE_HIGH_NIBBLE: + o_data[i][SPARE_DRAM_DQ_BYTE_NUMBER_INDEX] = 0xF0; + break; + + case fapi::ENUM_ATTR_VPD_DIMM_SPARE_FULL_BYTE: + // As erroneous value will not be encountered. + default: + o_data[i][SPARE_DRAM_DQ_BYTE_NUMBER_INDEX] = 0x00; + break; + } + + l_dimmMask >>= 2; + l_rankBitShift -= 2; + } + }while(0); + return l_rc; +} + +} + extern "C" { @@ -82,20 +162,26 @@ fapi::ReturnCode dimmBadDqBitmapAccessHwp( *(reinterpret_cast<uint8_t(*)[DIMM_DQ_SPD_DATA_SIZE]> (new uint8_t[DIMM_DQ_SPD_DATA_SIZE])); + // Memory Bus Width Attribute + uint8_t l_eccBits = 0; + dimmBadDqDataFormat * l_pSpdData = reinterpret_cast<dimmBadDqDataFormat *>(l_spdData); // Get the Centaur 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(ATTR_CEN_DQ_TO_DIMM_CONN_DQ, &i_dimm, l_wiringData); - - if (l_rc) - { - FAPI_ERR("dimmBadDqBitmapAccessHwp: Error getting wiring attribute"); - } - else + do { + l_rc = FAPI_ATTR_GET(ATTR_CEN_DQ_TO_DIMM_CONN_DQ, + &i_dimm, l_wiringData); + + if (l_rc) + { + FAPI_ERR("dimmBadDqBitmapAccessHwp: " + "Error getting wiring attribute"); + break; + } if (i_get) { // Get the SPD DQ attribute @@ -104,62 +190,96 @@ fapi::ReturnCode dimmBadDqBitmapAccessHwp( if (l_rc) { FAPI_ERR("dimmBadDqBitmapAccessHwp: Error getting SPD data"); + break; + } + // Zero caller's data + memset(io_data, 0, sizeof(io_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 ((FAPI_BE32TOH(l_pSpdData->iv_magicNumber) != + DIMM_BAD_DQ_MAGIC_NUMBER) || + (l_pSpdData->iv_version != DIMM_BAD_DQ_VERSION)) + { + FAPI_INF("dimmBadDqBitmapAccessHwp: SPD DQ not initialized"); } else { - // Zero caller's data - memset(io_data, 0, sizeof(io_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 ((FAPI_BE32TOH(l_pSpdData->iv_magicNumber) != - DIMM_BAD_DQ_MAGIC_NUMBER) || - (l_pSpdData->iv_version != DIMM_BAD_DQ_VERSION)) - { - // SPD DQ data not initialized, return zeros - FAPI_INF("dimmBadDqBitmapAccessHwp: 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 < DIMM_DQ_MAX_DIMM_RANKS; i++) { - // Translate bitmap from DIMM DQ to Centaur DQ point of view - // for each rank - for (uint8_t i = 0; i < DIMM_DQ_MAX_DIMM_RANKS; i++) + // Iterate through all the DQ bits in the rank + for (uint8_t j = 0; j < DIMM_DQ_NUM_DQS; j++) { - // Iterate through all the DQ bits in the rank - for (uint8_t j = 0; j < DIMM_DQ_NUM_DQS; 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_pSpdData->iv_bitmaps[i][j/8]) & + (0x80 >> (j % 8))) { - // 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_pSpdData->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 < DIMM_DQ_NUM_DQS; k++) { - // 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 < DIMM_DQ_NUM_DQS; k++) + if (l_wiringData[k] == j) { - if (l_wiringData[k] == j) - { - io_data[i][k/8] |= (0x80 >> (k % 8)); - break; - } + io_data[i][k/8] |= (0x80 >> (k % 8)); + break; } + } - if (k == DIMM_DQ_NUM_DQS) - { - FAPI_ERR("dimmBadDqBitmapAccessHwp: Centaur DQ not found for %d!", - j); - } + if (k == DIMM_DQ_NUM_DQS) + { + FAPI_INF("dimmBadDqBitmapAccessHwp: " + "Centaur DQ not found for %d!",j); } } } } } + // Set bits for any unconnected DQs. + // First, check ECC. + l_rc = FAPI_ATTR_GET(ATTR_SPD_MODULE_MEMORY_BUS_WIDTH, + &i_dimm, l_eccBits); + if (l_rc) + { + FAPI_ERR("dimmBadDqBitmapAccessHwp: " + "Error getting ECC data"); + 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 deonote 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 ECCs are disconnected + if (!(fapi::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 < DIMM_DQ_MAX_DIMM_RANKS; i++) + { + // Set DQ bits in caller's data + io_data[i][ECC_DQ_BYTE_NUMBER_INDEX] = 0xFF; + } + } + // Check spare DRAM + l_rc = dimmUpdateDqBitmapSpareByte(i_dimm, io_data); + if (l_rc) + { + FAPI_ERR("dimmBadDqBitmapAccessHwp: " + "Error getting spare DRAM data"); + break; + } } else { @@ -196,13 +316,13 @@ fapi::ReturnCode dimmBadDqBitmapAccessHwp( if (l_rc) { FAPI_ERR("dimmBadDqBitmapAccessHwp: Error setting SPD data"); + break; } } - } + }while(0); delete [] &l_wiringData; delete [] &l_spdData; - FAPI_INF("<<dimmBadDqBitmapAccessHwp"); return l_rc; } diff --git a/src/usr/hwpf/hwp/dimmBadDqBitmapFuncs.C b/src/usr/hwpf/hwp/dimmBadDqBitmapFuncs.C index 788ee3223..67a4f5640 100644 --- a/src/usr/hwpf/hwp/dimmBadDqBitmapFuncs.C +++ b/src/usr/hwpf/hwp/dimmBadDqBitmapFuncs.C @@ -31,6 +31,9 @@ * Flag Defect/Feature User Date Description * ------ -------------- ---------- ----------- ---------------------------- * mjjones 02/17/2012 Created. + * dedahle 06/20/2013 dimmGetBadDqBitmap/ + * dimmSetBadDqBitmap funcs + * get/set ATTR_BAD_DQ_BITMAP */ #include <dimmBadDqBitmapFuncs.H> @@ -39,16 +42,6 @@ extern "C" { -// TODO -// For the dimmGetBadDqBitmap and dimmSetBadDqBitmap funcs, the original plan to -// get/set the bitmap was to get/set a HWPF attribute called ATTR_BAD_DQ_BITMAP. -// This would automatically call the dimmBadDqBitmapAccessHwp HWP which would -// access the ATTR_SPD_BAD_DQ_DATA HWPF attribute and decode the data. However, -// automatically bridging an attribute request to a HWP turns out to be -// difficult due to the fact that the FAPI_ATTR_GET macro returns a ReturnCode -// and the FAPI_EXEC_HWP macro takes a ReturnCode as parameter. For now call the -// HWP directly and revisit later - //------------------------------------------------------------------------------ // Utility function to check parameters and find a DIMM target @@ -158,20 +151,21 @@ fapi::ReturnCode dimmGetBadDqBitmap(const fapi::Target & i_mba, if (!l_rc) { - // Get the Bad DQ bitmap by calling the dimmBadDqBitmapAccessHwp HWP. + // Get the Bad DQ bitmap by querying ATTR_BAD_DQ_BITMAP. // Use a heap based array to avoid large stack alloc uint8_t (&l_dqBitmap)[DIMM_DQ_MAX_DIMM_RANKS][DIMM_DQ_RANK_BITMAP_SIZE] = *(reinterpret_cast<uint8_t(*)[DIMM_DQ_MAX_DIMM_RANKS][DIMM_DQ_RANK_BITMAP_SIZE]> (new uint8_t[DIMM_DQ_MAX_DIMM_RANKS*DIMM_DQ_RANK_BITMAP_SIZE])); - FAPI_EXEC_HWP(l_rc, dimmBadDqBitmapAccessHwp, l_dimm, l_dqBitmap, true); + l_rc = FAPI_ATTR_GET(ATTR_BAD_DQ_BITMAP, &l_dimm, l_dqBitmap); if (l_rc) { - FAPI_ERR("dimmGetBadDqBitmap: Error from dimmBadDqBitmapAccessHwp"); + FAPI_ERR("dimmGetBadDqBitmap: Error getting ATTR_BAD_DQ_BITMAP for dimm"); } else { + //Write contents of DQ bitmap for specific rank to o_data. memcpy(o_data, l_dqBitmap[i_rank], DIMM_DQ_RANK_BITMAP_SIZE); } @@ -200,28 +194,28 @@ fapi::ReturnCode dimmSetBadDqBitmap( if (!l_rc) { - // Get the Bad DQ bitmap by calling the dimmBadDqBitmapAccessHwp HWP. + // Get the Bad DQ bitmap by querying ATTR_BAD_DQ_BITMAP. // Use a heap based array to avoid large stack alloc uint8_t (&l_dqBitmap)[DIMM_DQ_MAX_DIMM_RANKS][DIMM_DQ_RANK_BITMAP_SIZE] = *(reinterpret_cast<uint8_t(*)[DIMM_DQ_MAX_DIMM_RANKS][DIMM_DQ_RANK_BITMAP_SIZE]> (new uint8_t[DIMM_DQ_MAX_DIMM_RANKS*DIMM_DQ_RANK_BITMAP_SIZE])); - FAPI_EXEC_HWP(l_rc, dimmBadDqBitmapAccessHwp, l_dimm, l_dqBitmap, true); + l_rc = FAPI_ATTR_GET(ATTR_BAD_DQ_BITMAP, &l_dimm, l_dqBitmap); if (l_rc) { - FAPI_ERR("dimmSetBadDqBitmap: Error from dimmBadDqBitmapAccessHwp (get)"); + FAPI_ERR("dimmSetBadDqBitmap: Error getting ATTR_BAD_DQ_BITMAP for dimm"); } else { // Add the rank bitmap to the DIMM bitmap and write the bitmap memcpy(l_dqBitmap[i_rank], i_data, DIMM_DQ_RANK_BITMAP_SIZE); - FAPI_EXEC_HWP(l_rc, dimmBadDqBitmapAccessHwp, l_dimm, l_dqBitmap, false); + l_rc = FAPI_ATTR_SET(ATTR_BAD_DQ_BITMAP, &l_dimm, l_dqBitmap); if (l_rc) { - FAPI_ERR("dimmSetBadDqBitmap: Error from dimmBadDqBitmapAccessHwp (set)"); + FAPI_ERR("dimmSetBadDqBitmap: Error setting ATTR_BAD_DQ_BITMAP for dimm"); } } diff --git a/src/usr/hwpf/hwp/dimm_spd_attributes.xml b/src/usr/hwpf/hwp/dimm_spd_attributes.xml index 12eea1672..38d50c5f6 100644 --- a/src/usr/hwpf/hwp/dimm_spd_attributes.xml +++ b/src/usr/hwpf/hwp/dimm_spd_attributes.xml @@ -485,10 +485,11 @@ The following attributes can be queried from both DDR3 and DDR4 DIMMs <id>ATTR_SPD_BAD_DQ_DATA</id> <targetType>TARGET_TYPE_DIMM</targetType> <description> - Bad DQ pin data stored in DIMM SPD. This data is in a special format. - This must only be called by a firmware HWP that knows how to decode the data. - HWP/PLAT firmware that needs to get/set the Bad DQ Bitmap from a Centaur - DQ point of view must call the dimmBadDqBitmapAccessHwp HWP. + Bad DQ pin data stored in DIMM SPD. This data is in a special fomat. + This must only be called by a firmware HWP that knows how to + decode the data. HWP/PLAT firmware that needs to get/set the + Bad DQ Bitmap from a Centaur DQ point of view must use the + ATTR_BAD_DQ_BITMAP attribute. </description> <valueType>uint8</valueType> <array>80</array> @@ -1298,4 +1299,59 @@ file </attribute> --> + +<attribute> + <id>ATTR_BAD_DQ_BITMAP</id> + <targetType>TARGET_TYPE_DIMM</targetType> + <description> + Bad DQ bitmap from a Centaur:MBA point of view. + The data is a 10 byte bitmap for each of 4 possible ranks. + The bad DQ data is stored in DIMM SPD, it is stored in a special format + and is translated to a DIMM Connector point of view for IS-DIMMs. + All of these details are hidden from the user of this attribute. + </description> + <valueType>uint8</valueType> + <array>4 10</array> + <platInit/> + <writeable/> +</attribute> + +<attribute> + <id>ATTR_VPD_DIMM_SPARE</id> + <targetType>TARGET_TYPE_DIMM</targetType> + <description> + Spare DRAM availability for each rank on the DIMM. + There are 8 DQ lines to spare DRAMs. + - NO_SPARE: No spare DRAMs + - LOW_NIBBLE: x4 DRAMs in use, one spare DRAM connected to SP_DQ0-3 + - HIGH_NIBBLE: x4 DRAMs in use, one spare DRAM connected to SP_DQ4-7 + - FULL_BYTE: Either + 1/ x4 DRAMs in use, two spare DRAMs connected to SP_DQ0-7 + 2/ x8 DRAMs in use, one spare DRAM connected to SP_DQ0-7 + For C-DIMMs, this is in a VPD field : Record:VSPD, Keyword:AM + For IS-DIMMs, the platform should return 0 indicating + no spares for any rank. + The top 2 bits are for rank 0 e.g: + if (((val AND 0xc0) >> 6) == + ENUM_ATTR_VPD_DIMM_SPARE_LOW_NIBBLE) {...} + The next 2 bits are for rank 1 e.g: + if (((val AND 0x30) >> 4) == + ENUM_ATTR_VPD_DIMM_SPARE_NO_SPARE) {...} + The next 2 bits are for rank 2 e.g: + if (((val AND 0x0c) >> 2) == + ENUM_ATTR_VPD_DIMM_SPARE_HIGH_NIBBLE) {...} + The bottom 2 bits are for rank 3 e.g: + if ((val AND 0x03) == + ENUM_ATTR_VPD_DIMM_SPARE_FULL_BYTE) {...} + </description> + <valueType>uint8</valueType> + <enum> + NO_SPARE = 0x00, + LOW_NIBBLE = 0x01, + HIGH_NIBBLE = 0x02, + FULL_BYTE = 0x03 + </enum> + <platInit/> +</attribute> + </attributes> diff --git a/src/usr/hwpf/hwp/fapiTestHwpDq.C b/src/usr/hwpf/hwp/fapiTestHwpDq.C index 9ea23ec89..6fadbe27d 100644 --- a/src/usr/hwpf/hwp/fapiTestHwpDq.C +++ b/src/usr/hwpf/hwp/fapiTestHwpDq.C @@ -1,26 +1,25 @@ -/* IBM_PROLOG_BEGIN_TAG - * This is an automatically generated prolog. - * - * $Source: src/usr/hwpf/hwp/fapiTestHwpDq.C $ - * - * IBM CONFIDENTIAL - * - * COPYRIGHT International Business Machines Corp. 2012 - * - * p1 - * - * Object Code Only (OCO) source materials - * Licensed Internal Code Source Materials - * IBM HostBoot Licensed Internal Code - * - * The source code for this program is not published or other- - * wise divested of its trade secrets, irrespective of what has - * been deposited with the U.S. Copyright Office. - * - * Origin: 30 - * - * IBM_PROLOG_END_TAG - */ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/usr/hwpf/hwp/fapiTestHwpDq.C $ */ +/* */ +/* IBM CONFIDENTIAL */ +/* */ +/* COPYRIGHT International Business Machines Corp. 2012,2013 */ +/* */ +/* p1 */ +/* */ +/* Object Code Only (OCO) source materials */ +/* Licensed Internal Code Source Materials */ +/* IBM HostBoot Licensed Internal Code */ +/* */ +/* The source code for this program is not published or otherwise */ +/* divested of its trade secrets, irrespective of what has been */ +/* deposited with the U.S. Copyright Office. */ +/* */ +/* Origin: 30 */ +/* */ +/* IBM_PROLOG_END_TAG */ /** * @file fapiTestHwpDq.C * @@ -102,48 +101,51 @@ fapi::ReturnCode fapiTestHwpDq(const fapi::Target & i_mba) break; } - // Get the bad DQ Bitmap for the DIMM, rank 3 - l_rc = dimmGetBadDqBitmap(i_mba, l_port, l_dimm, 3, l_dqBitmap); - - if (l_rc) + // Get the bad DQ Bitmap for all ranks and print any non-zero data + uint8_t l_rank = 0; + for (l_rank = 0; l_rank < 3; l_rank++) { - FAPI_ERR("fapiTestHwpDq: Error from dimmGetBadDqBitmap"); - break; - } - - // If the data is not all zeroes then skip the rest of the test, do not - // want to modify any real Bad DQ records - bool l_nonZeroData = false; + // Get the bad DQ Bitmap for the rank + l_rc = dimmGetBadDqBitmap(i_mba, l_port, l_dimm, l_rank, + l_dqBitmap); - for (uint8_t i = 0; i < DIMM_DQ_RANK_BITMAP_SIZE; i++) - { - if (l_dqBitmap[i] != 0) + if (l_rc) { - FAPI_INF("fapiTestHwpDq: Non-zero DQ data, skipping test"); - l_nonZeroData = true; + FAPI_ERR("fapiTestHwpDq: Error from dimmGetBadDqBitmap"); break; } + + // Trace any bad DQs + for (uint8_t i = 0; i < DIMM_DQ_RANK_BITMAP_SIZE; i++) + { + if (l_dqBitmap[i] != 0) + { + FAPI_INF("fapiTestHwpDq: Non-zero DQ data. Rank:%d, Byte:%d, Val:0x02%x", + l_rank, i, l_dqBitmap[i]); + } + } } - if (l_nonZeroData) + if (l_rc) { break; } + // Record the two bytes of the bad DQ bitmap that this function + // will change so that it can be restored + uint8_t l_origDq2 = l_dqBitmap[2]; + uint8_t l_origDq6 = l_dqBitmap[6]; + // Set 2 bad DQ bits l_dqBitmap[2] = 0x40; l_dqBitmap[6] = 0x20; - // Set the bad DQ Bitmap - l_rc = dimmSetBadDqBitmap(i_mba, 1, 0, 3, l_dqBitmap); + // Set the bad DQ Bitmap for the last rank + l_rc = dimmSetBadDqBitmap(i_mba, l_port, l_dimm, l_rank, l_dqBitmap); if (l_rc) { FAPI_ERR("fapiTestHwpDq: Error from dimmSetBadDqBitmap"); - - // TODO - FAPI_ERR("fapiTestHwpDq: Waiting for SPD DD support for writes (story 35766)"); - l_rc = fapi::FAPI_RC_SUCCESS; break; } @@ -151,7 +153,7 @@ fapi::ReturnCode fapiTestHwpDq(const fapi::Target & i_mba) l_dqBitmap[2] = 0; l_dqBitmap[6] = 0; - l_rc = dimmGetBadDqBitmap(i_mba, 1, 0, 3, l_dqBitmap); + l_rc = dimmGetBadDqBitmap(i_mba, l_port, l_dimm, l_rank, l_dqBitmap); if (l_rc) { @@ -169,11 +171,11 @@ fapi::ReturnCode fapiTestHwpDq(const fapi::Target & i_mba) break; } - // Write the data back to zero - l_dqBitmap[2] = 0; - l_dqBitmap[6] = 0; + // Write the original data back + l_dqBitmap[2] = l_origDq2; + l_dqBitmap[6] = l_origDq6; - l_rc = dimmSetBadDqBitmap(i_mba, 1, 0, 3, l_dqBitmap); + l_rc = dimmSetBadDqBitmap(i_mba, l_port, l_dimm, l_rank, l_dqBitmap); if (l_rc) { diff --git a/src/usr/hwpf/hwp/mvpd_accessors/getMBvpdSpareDramData.C b/src/usr/hwpf/hwp/mvpd_accessors/getMBvpdSpareDramData.C new file mode 100644 index 000000000..665a9e76c --- /dev/null +++ b/src/usr/hwpf/hwp/mvpd_accessors/getMBvpdSpareDramData.C @@ -0,0 +1,210 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/usr/hwpf/hwp/mvpd_accessors/getMBvpdSpareDramData.C $ */ +/* */ +/* IBM CONFIDENTIAL */ +/* */ +/* COPYRIGHT International Business Machines Corp. 2013 */ +/* */ +/* p1 */ +/* */ +/* Object Code Only (OCO) source materials */ +/* Licensed Internal Code Source Materials */ +/* IBM HostBoot Licensed Internal Code */ +/* */ +/* The source code for this program is not published or otherwise */ +/* divested of its trade secrets, irrespective of what has been */ +/* deposited with the U.S. Copyright Office. */ +/* */ +/* Origin: 30 */ +/* */ +/* IBM_PROLOG_END_TAG */ +#include <stdint.h> + +// fapi support +#include <fapi.H> +#include <dimmConsts.H> +#include <getMBvpdSpareDramData.H> + +extern "C" +{ +using namespace fapi; + +fapi::ReturnCode getMBvpdSpareDramData(const fapi::Target &i_mba, + const fapi::Target &i_dimm, + uint8_t &o_data) + +{ + // AM keyword layout + const uint8_t NUM_MBAS = 2; // Two MBAs per Centaur + const uint8_t NUM_PORTS = 2; // Two ports per MBA + const uint8_t NUM_DIMMS = 2; // Two DIMMS per port + const uint8_t NUM_MIRR_BYTES = 4; // Size of address mirror data + + // Struct for AM Keyword buffer + // Contains a simple array for the address mirror data and + // a 2D array for the spare DRAM data. + struct MirrorData + { + uint8_t iv_mirrorData[NUM_MIRR_BYTES]; + }; + struct DimmSpareData + { + // This contains information for all ranks and is returned in o_data + uint8_t iv_dimmSpareData; + }; + struct PortSpareData + { + DimmSpareData iv_dimmSpareData[NUM_DIMMS]; + }; + struct MbaSpareData + { + PortSpareData iv_portSpareData[NUM_PORTS]; + }; + struct AmKeyword + { + MirrorData mirrorData; + MbaSpareData iv_mbaSpareData[NUM_MBAS]; + }; + + // Old VPD without the Spare Data + const uint8_t VPD_WITHOUT_SPARE_DATA_SIZE = sizeof(MirrorData); + + // Current VPD AM keyword size + const uint32_t AM_KEYWORD_SIZE = sizeof(AmKeyword); + fapi::ReturnCode l_rc; + // Centaur target + fapi::Target l_mbTarget; + // MBvpd AM keyword buffer + AmKeyword * l_pAmBuffer = NULL; + uint32_t l_AmBufSize = sizeof(AmKeyword); + + do + { + // Check to see if IS-DIMM + uint8_t l_dimmType = 0; + l_rc = FAPI_ATTR_GET(ATTR_SPD_CUSTOM, &i_dimm, l_dimmType); + if (l_rc) + { + FAPI_ERR("getMBvpdSpareDramData: " + "Error getting ATTR_SPD_CUSTOM"); + break; + } + if (fapi::ENUM_ATTR_SPD_CUSTOM_NO == l_dimmType) + { + //IS-DIMM, return NO_SPARE + o_data = fapi::ENUM_ATTR_VPD_DIMM_SPARE_NO_SPARE; + break; + } + + // find the Centaur memory buffer from the passed MBA + l_rc = fapiGetParentChip (i_mba,l_mbTarget); + if (l_rc) + { + FAPI_ERR("getMBvpdSpareDramData: Finding the parent mb failed "); + break; + } + + // Read AM keyword field + l_pAmBuffer = new AmKeyword; + l_rc = fapiGetMBvpdField(fapi::MBVPD_RECORD_VSPD, + fapi::MBVPD_KEYWORD_AM, + l_mbTarget, + reinterpret_cast<uint8_t *>(l_pAmBuffer), + l_AmBufSize); + + if (l_rc) + { + FAPI_ERR("getMBvpdSpareDramData: Read of AM keyword failed"); + break; + } + + // Check correct amount of data returned + if (l_AmBufSize < AM_KEYWORD_SIZE) + { + + // If Old VPD + if (VPD_WITHOUT_SPARE_DATA_SIZE == l_AmBufSize) + { + // Because prior VPD AM keyword does not contain + // spare DRAM data, the ATTR_SPD_DRAM_WIDTH + // attribute is used to determine spare DRAM availability. + // If x4 configuration, assume LOW_NIBBLE. + // Otherwise, FULL_BYTE. + uint8_t l_dramWidth = 0; + l_rc = FAPI_ATTR_GET(ATTR_SPD_DRAM_WIDTH, &i_dimm, l_dramWidth); + if (l_rc) + { + FAPI_ERR("getMBvpdSpareDramData: " + "Error getting DRAM spare data"); + break; + } + // If x4 configuration, low nibble. + if (fapi::ENUM_ATTR_SPD_DRAM_WIDTH_W4 == l_dramWidth) + { + o_data = fapi::ENUM_ATTR_VPD_DIMM_SPARE_LOW_NIBBLE; + break; + } + // Else, full spare. + else + { + o_data = fapi::ENUM_ATTR_VPD_DIMM_SPARE_FULL_BYTE; + break; + } + } + + else + { + FAPI_ERR("getMBvpdSpareDramData: " + "Insufficient amount of data returned:" + " %u < %u", l_AmBufSize, AM_KEYWORD_SIZE); + const uint32_t & KEYWORD = fapi::MBVPD_KEYWORD_AM; + const uint32_t & RETURNED_SIZE = l_AmBufSize; + FAPI_SET_HWP_ERROR(l_rc, + RC_MBVPD_INSUFFICIENT_VPD_RETURNED); + break; + } + } + + + // Return the spare DRAM availability for particular dimm + // Find the position of the passed mba on the centuar + uint8_t l_mba = 0; + l_rc = FAPI_ATTR_GET(ATTR_CHIP_UNIT_POS, &i_mba, l_mba); + if (l_rc) + { + FAPI_ERR("getMBvpdSpareDramData: Get MBA position failed "); + break; + } + // Find the mba port this dimm is connected to + uint8_t l_mbaPort = 0; + l_rc = FAPI_ATTR_GET(ATTR_MBA_PORT, &i_dimm, l_mbaPort); + if (l_rc) + { + FAPI_ERR("getMBvpdSpareDramData: " + "Error getting MBA port number"); + break; + } + // Find the dimm number associated with this dimm + uint8_t l_dimm = 0; + l_rc = FAPI_ATTR_GET(ATTR_MBA_DIMM, &i_dimm, l_dimm); + if (l_rc) + { + FAPI_ERR("getMBvpdSpareDramData: " + "Error getting dimm number"); + break; + } + + o_data = l_pAmBuffer->iv_mbaSpareData[l_mba].\ + iv_portSpareData[l_mbaPort].\ + iv_dimmSpareData[l_dimm].iv_dimmSpareData; + + }while(0); + + delete l_pAmBuffer; + l_pAmBuffer = NULL; + return l_rc; +} + +} // extern "C" diff --git a/src/usr/hwpf/hwp/mvpd_accessors/mvpd.mk b/src/usr/hwpf/hwp/mvpd_accessors/mvpd.mk index 19ea33724..0f598f554 100644 --- a/src/usr/hwpf/hwp/mvpd_accessors/mvpd.mk +++ b/src/usr/hwpf/hwp/mvpd_accessors/mvpd.mk @@ -32,5 +32,6 @@ OBJS += getMvpdRing.o \ getMBvpdPhaseRotatorData.o \ getMBvpdAddrMirrorData.o \ getMBvpdTermData.o \ - getMBvpdSlopeInterceptData.o + getMBvpdSlopeInterceptData.o \ + getMBvpdSpareDramData.o diff --git a/src/usr/hwpf/plat/fapiPlatAttributeService.C b/src/usr/hwpf/plat/fapiPlatAttributeService.C index 41d69d16b..c3ab3567a 100644 --- a/src/usr/hwpf/plat/fapiPlatAttributeService.C +++ b/src/usr/hwpf/plat/fapiPlatAttributeService.C @@ -46,6 +46,7 @@ #include <hwpf/hwp/mvpd_accessors/getMBvpdAddrMirrorData.H> #include <hwpf/hwp/mvpd_accessors/getMBvpdTermData.H> #include <hwpf/hwp/mvpd_accessors/getMBvpdSlopeInterceptData.H> +#include <hwpf/hwp/mvpd_accessors/getMBvpdSpareDramData.H> // The following file checks at compile time that all HWPF attributes are // handled by Hostboot. This is done to ensure that the HTML file listing @@ -1206,7 +1207,7 @@ fapi::ReturnCode fapiPlatGetAddrMirrorData ( /*@ * @errortype - * @moduleid fapi::MOD_PLAT_ATTR_SVC_GET_TARG_ATTR + * @moduleid fapi::MOD_PLAT_ATTR_SVC_GET_MIRR_DATA * @reasoncode fapi::RC_NO_SINGLE_MBA * @userdata1 Number of MBAs * @devdesc fapiPlatGetAddrMirrorData could not find the @@ -1214,7 +1215,7 @@ fapi::ReturnCode fapiPlatGetAddrMirrorData ( */ errlHndl_t l_pError = new ERRORLOG::ErrlEntry( ERRORLOG::ERRL_SEV_UNRECOVERABLE, - fapi::MOD_PLAT_ATTR_SVC_GET_TARG_ATTR, + fapi::MOD_PLAT_ATTR_SVC_GET_MIRR_DATA, fapi::RC_NO_SINGLE_MBA, l_mbaList.size()); @@ -1318,6 +1319,146 @@ fapi::ReturnCode fapiPlatGetEnableAttr ( fapi::AttributeId i_id, return l_rc; } + +//------------------------------------------------------------------------------ +// Functions to support BAD_DQ_BITMAP_attribute +// See dimm_spd_attributes.xml for detailed descriptions +//------------------------------------------------------------------------------ + + +/** + * @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_pTarget Target pointer + * @param[out] o_data Bad DIMM DQ Bitmap + * @return ReturnCode. Zero on success, else platform specified error + */ +fapi::ReturnCode fapiPlatDimmGetBadDqBitmap ( + const fapi::Target * i_pTarget, + uint8_t (&o_data)[DIMM_DQ_MAX_DIMM_RANKS]\ + [DIMM_DQ_RANK_BITMAP_SIZE]) +{ + fapi::ReturnCode l_rc; + FAPI_EXEC_HWP(l_rc, dimmBadDqBitmapAccessHwp, *i_pTarget, o_data, true); + + if (l_rc) + { + FAPI_ERR("dimmGetBadDqBitmap: " + "Error from dimmBadDqBitmapAccessHwp (get)"); + } + return l_rc; +} + + +/** + * @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_pTarget Target pointer + * @param[in] i_data Bad DIMM DQ Bitmap + * @return ReturnCode. Zero on success, else platform specified error + */ +fapi::ReturnCode fapiPlatDimmSetBadDqBitmap ( + const fapi::Target * i_pTarget, + uint8_t (&i_data)[DIMM_DQ_MAX_DIMM_RANKS]\ + [DIMM_DQ_RANK_BITMAP_SIZE]) +{ + fapi::ReturnCode l_rc; + FAPI_EXEC_HWP(l_rc, dimmBadDqBitmapAccessHwp, *i_pTarget, i_data, false); + + if (l_rc) + { + FAPI_ERR("dimmSetBadDqBitmap: " + "Error from dimmBadDqBitmapAccessHwp (set)"); + } + return l_rc; +} + +//------------------------------------------------------------------------------ +// Function to support VPD_DIMM_SPARE attribute +// See dimm_spd_attributes.xml for detailed description +//------------------------------------------------------------------------------ + +/** + * @brief This function is called by the FAPI_ATTR_GET macro when getting + * the VPD DIMM Spare attribute + * It should not be called directly. + * + * @param[in] i_pTarget Target pointer + * @param[out] o_data Spare DRAM availability for DIMM + * @return ReturnCode. Zero on success, else platform specified error + */ +fapi::ReturnCode fapiPlatDimmGetSpareDram ( + const fapi::Target * i_pTarget, + uint8_t &o_data) +{ + + fapi::ReturnCode l_rc; + TARGETING::Target * l_pTarget = NULL; + TARGETING::TargetHandleList l_mbaList; + do + { + // Get the Targeting Target + l_rc = getTargetingTarget(i_pTarget, l_pTarget); + if (l_rc) + { + FAPI_ERR("fapiPlatDimmGetSpareDram:Error from getTargetingTarget"); + break; + } + + // Find MBA target from DIMM target + getParentAffinityTargets(l_mbaList, l_pTarget, TARGETING::CLASS_UNIT, + TARGETING::TYPE_MBA, false); + + + if (l_mbaList.size() != 1 ) + { + FAPI_ERR("fapiPlatDimmGetSpareDram: expect 1 mba %d ", + l_mbaList.size()); + + /*@ + * @errortype + * @moduleid fapi::MOD_PLAT_ATTR_SVC_GET_SPARE_DATA + * @reasoncode fapi::RC_NO_SINGLE_MBA + * @userdata1 Number of MBAs + * @devdesc fapiPlatDimmGetSpareDram could not find the + * expected 1 mba from the passed dimm target + */ + errlHndl_t l_pError = new ERRORLOG::ErrlEntry( + ERRORLOG::ERRL_SEV_UNRECOVERABLE, + fapi::MOD_PLAT_ATTR_SVC_GET_SPARE_DATA, + fapi::RC_NO_SINGLE_MBA, + l_mbaList.size()); + + // Attach the error log to the fapi::ReturnCode + l_rc.setPlatError(reinterpret_cast<void *> (l_pError)); + break; + } + + + // Create the Fapi Target + fapi::Target l_mbaTarget(TARGET_TYPE_MBA_CHIPLET, + static_cast<void *>(l_mbaList[0])); + + + FAPI_EXEC_HWP(l_rc, getMBvpdSpareDramData, l_mbaTarget, *i_pTarget, + o_data); + + if (l_rc) + { + FAPI_ERR("fapiPlatDimmGetSpareDram: " + "Error from getMBvpdSpareDramData"); + break; + } + + }while(0); + + return l_rc; +} + } // End platAttrSvc namespace } // End fapi namespace |