diff options
author | Sumit Kumar <sumit_kumar@in.ibm.com> | 2018-05-01 00:33:59 -0500 |
---|---|---|
committer | William G. Hoffa <wghoffa@us.ibm.com> | 2018-05-16 09:42:26 -0400 |
commit | 6855bca779b8435856b0f6881480d7a4ed205b6b (patch) | |
tree | 38da6f0d36af4df08408ea58c10b8137bd2e6672 /src/import | |
parent | b0a9477ec9a6d2b297d71cc271d06282163d3963 (diff) | |
download | talos-hostboot-6855bca779b8435856b0f6881480d7a4ed205b6b.tar.gz talos-hostboot-6855bca779b8435856b0f6881480d7a4ed205b6b.zip |
Erepair HWP - Include target type DMI
- Centaur/DMI codes made fapi2 compliant
- Refactored templated functions framework
- Removed 'using namespace' from header files
Change-Id: I690b24e5fdf9ff7413b128efb6f2fc4043bf739a
Reviewed-on: http://ralgit01.raleigh.ibm.com/gerrit1/58065
Tested-by: FSP CI Jenkins <fsp-CI-jenkins+hostboot@us.ibm.com>
Tested-by: Jenkins Server <pfd-jenkins+hostboot@us.ibm.com>
Tested-by: Hostboot CI <hostboot-ci+hostboot@us.ibm.com>
Reviewed-by: Zane C. Shelley <zshelle@us.ibm.com>
Reviewed-by: Benjamin J. Weisenbeck <bweisenb@us.ibm.com>
Reviewed-by: Jennifer A. Stofer <stofer@us.ibm.com>
Reviewed-on: http://ralgit01.raleigh.ibm.com/gerrit1/58067
Tested-by: Jenkins OP Build CI <op-jenkins+hostboot@us.ibm.com>
Tested-by: Jenkins OP HW <op-hw-jenkins+hostboot@us.ibm.com>
Reviewed-by: William G. Hoffa <wghoffa@us.ibm.com>
Diffstat (limited to 'src/import')
9 files changed, 4248 insertions, 3127 deletions
diff --git a/src/import/chips/p9/procedures/hwp/io/p9_io_erepairAccessorHwpFuncs.C b/src/import/chips/p9/procedures/hwp/io/p9_io_erepairAccessorHwpFuncs.C index 4646a3a92..5814e3cc0 100755 --- a/src/import/chips/p9/procedures/hwp/io/p9_io_erepairAccessorHwpFuncs.C +++ b/src/import/chips/p9/procedures/hwp/io/p9_io_erepairAccessorHwpFuncs.C @@ -5,7 +5,7 @@ /* */ /* OpenPOWER HostBoot Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2015,2017 */ +/* Contributors Listed Below - COPYRIGHT 2015,2018 */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -28,77 +28,13 @@ /// //---------------------------------------------------------------------------- #include <fapi2.H> -#include <p9_io_erepairAccessorHwpFuncs.H> #include <string.h> #include <p9_io_erepairConsts.H> -#include <p9_io_erepairSetFailedLanesHwp.H> -#include <p9_io_erepairGetFailedLanesHwp.H> using namespace EREPAIR; using namespace fapi2; -/** Forward Declarations **/ - -/** - * @brief: This function reads the field VPD data to check if there is any - * eRepair data. This function will be called during Mnfg mode IPL - * during which we need to make sure that the Field VPD is clear. - * The Field VPD needs to be clear to enable customers to have - * eRepair capability. - * - * @param [in] i_endp1_target Target of one end the connecting bus - * @param [in] i_endp2_target Target of the other end of the connecting bus - * The VPD of the passed targets are read for - * checking the VPD contents - * @param[in] i_clkGroup Specifies clock group 0:[XOA, X1A,..] 1:[X0B, X1B,..] - * - * @return ReturnCode - */ -template<fapi2::TargetType K, fapi2::TargetType J> -fapi2::ReturnCode mnfgCheckFieldVPD( - const fapi2::Target < K >& i_endp1_target, - const fapi2::Target < J >& i_endp2_target, - const uint8_t i_clkGroup); - - -/** - * @brief: This Function reads the specified VPD (Mnfg or Field) of the passed - * targets and verifies whether there are matching eRepair records. - * The matching eRepair lanes are returned in the passed references - * for vectors. - * - * @param [in] i_endp1_target Target of one end the connecting bus - * @param [in] i_endp2_target Target of the other end of the connecting - * bus - * @param[in] i_clkGroup Specifies clock group 0:[XOA, X1A,..] 1:[X0B, X1B,..] - * @param [out] o_endp1_txFaillanes Reference to vector which will have fail - * lane numbers on Tx side of target passed - * as first param - * @param [out] o_endp1_rxFaillanes Reference to vector which will have fail - * lane numbers on Rx side of target passed - * as first param - * @param [out] o_endp2_txFaillanes Reference to vector which will have fail - * lane numbers on Tx side of target passed - * as fourth param - * @param [out] o_endp2_rxFaillanes Reference to vector which will have fail - * lane numbers on Rx side of target passed - * as fourth param - * @param[in] i_clkGroup Specifies clock group 0:[XOA, X1A,..] 1:[X0B, X1B,..] - * @param [in] i_vpdType Indicates whether to read Mnfg VPD or - * Field VPD - * - * @return ReturnCode - */ -template<fapi2::TargetType K, fapi2::TargetType J> -fapi2::ReturnCode getVerifiedRepairLanes( - const fapi2::Target < K >& i_endp1_target, - const fapi2::Target < J >& i_endp2_target, - const uint8_t i_clkGroup, - std::vector<uint8_t>& o_endp1_txFaillanes, - std::vector<uint8_t>& o_endp1_rxFaillanes, - std::vector<uint8_t>& o_endp2_txFaillanes, - std::vector<uint8_t>& o_endp2_rxFaillanes, - const erepairVpdType i_vpdType); +/***** Function definitions *****/ /** * @brief This function checks to see if the passed vectors have matching @@ -121,793 +57,6 @@ fapi2::ReturnCode getVerifiedRepairLanes( void invalidateNonMatchingFailLanes(std::vector<uint8_t>& io_endp1_txFaillanes, std::vector<uint8_t>& io_endp2_rxFaillanes, bool& o_invalidFails_inTx_Ofendp1, - bool& o_invalidFails_inRx_Ofendp2); - -/** - * @brief This function gets the eRepair threshold value of the passed target - * for the particular IPL type. - * - * @param [in] i_endp_target The target for whose type the threshold value - * is needed - * @param [in] i_mfgModeIPL If TRUE, indicates that this is a MnfgMode IPL - * If FALSE, indicates that this is a Normal IPL - * @param [out] o_threshold The threshold return value - * - * @return ReturnCode - */ -template<fapi2::TargetType K> -fapi2::ReturnCode geteRepairThreshold( - const fapi2::Target < K >& i_endp_target, - const bool i_mfgModeIPL, - uint8_t& o_threshold); - -/** - * @brief This function determines the lane numbers that needs to be spared - * to support Corner testing. - * - * @param [in] i_tgtType The target type(XBus or OBus or DMIBus) for - * which the lanes that need to be spared are - * determined - * @param [out] o_endp1_txFailLanes The reference to the vector which will - * have the Tx side of lanes that need to be - * spared for endp1 - * @param [out] o_endp1_rxFailLanes The reference to the vector which will - * have the Rx side of lanes that need to be - * spared for endp1 - * @param [out] o_endp2_txFailLanes The reference to the vector which will - * have the Tx side of lanes that need to be - * spared for endp2 - * @param [out] o_endp2_rxFailLanes The reference to the vector which will - * have the Rx side of lanes that need to be - * spared for endp2 - * - * @return void - */ -template<fapi2::TargetType K> -void getCornerTestingLanes( - const fapi2::Target < K >& i_tgtType, - std::vector<uint8_t>& o_endp1_txFailLanes, - std::vector<uint8_t>& o_endp1_rxFailLanes, - std::vector<uint8_t>& o_endp2_txFailLanes, - std::vector<uint8_t>& o_endp2_rxFailLanes); - -/** - * @brief This function combines the eRepair lane numbers read from - * Manufacturing VPD and Field VPD - * - * @param [in] i_mnfgFaillanes The eRepair lane numbers read from the - * Manufacturing VPD - * @param [in] i_fieldFaillanes The eRepair lane numbers read from the - * Field VPD - * @param [out] o_allFaillanes The eRepair lane numbers which is the union - * of the Field and Manufacturing eRepair lanes - * passed as first iand second params - * - * @return void - */ -void combineFieldandMnfgLanes(std::vector<uint8_t>& i_mnfgFaillanes, - std::vector<uint8_t>& i_fieldFaillanes, - std::vector<uint8_t>& o_allFailLanes); - - -/***** Function definitions *****/ - -template<fapi2::TargetType K, fapi2::TargetType J> -fapi2::ReturnCode erepairGetRestoreLanes( - const fapi2::Target < K >& i_endp1_target, - const fapi2::Target < J >& i_endp2_target, - const uint8_t i_clkGroup, - std::vector<uint8_t>& o_endp1_txFaillanes, - std::vector<uint8_t>& o_endp1_rxFaillanes, - std::vector<uint8_t>& o_endp2_txFaillanes, - std::vector<uint8_t>& o_endp2_rxFaillanes) -{ - fapi2::ReturnCode l_rc = fapi2::FAPI2_RC_SUCCESS; - fapi2::current_err = fapi2::FAPI2_RC_SUCCESS; - - std::vector<uint8_t> l_endp1_txFieldFaillanes; - std::vector<uint8_t> l_endp1_rxFieldFaillanes; - std::vector<uint8_t> l_endp1_txMnfgFaillanes; - std::vector<uint8_t> l_endp1_rxMnfgFaillanes; - - std::vector<uint8_t> l_endp2_txFieldFaillanes; - std::vector<uint8_t> l_endp2_rxFieldFaillanes; - std::vector<uint8_t> l_endp2_txMnfgFaillanes; - std::vector<uint8_t> l_endp2_rxMnfgFaillanes; - - bool l_mnfgModeIPL = false; - bool l_enableDmiSpares = false; - bool l_enableFabricSpares = false; - bool l_disableFabricERepair = false; - bool l_disableMemoryERepair = false; - bool l_thresholdExceed = false; - uint8_t l_threshold = 0; - uint64_t l_allMnfgFlags = 0; - uint32_t l_numTxFailLanes = 0; - uint32_t l_numRxFailLanes = 0; - fapi2::TargetType l_endp1_tgtType = fapi2::TARGET_TYPE_NONE; - fapi2::TargetType l_endp2_tgtType = fapi2::TARGET_TYPE_NONE; - - FAPI_INF(">>erepairGetRestoreLanes"); - - FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_MNFG_FLAGS, - fapi2::Target<fapi2::TARGET_TYPE_SYSTEM>(), - l_allMnfgFlags)); - - // Check if MNFG_DISABLE_FABRIC_EREPAIR is enabled - l_disableFabricERepair = false; - - if(l_allMnfgFlags & - fapi2::ENUM_ATTR_MNFG_FLAGS_MNFG_DISABLE_FABRIC_eREPAIR) - { - l_disableFabricERepair = true; - } - - // Check if MNFG_DISABLE_MEMORY_EREPAIR is enabled - l_disableMemoryERepair = false; - - if(l_allMnfgFlags & - fapi2::ENUM_ATTR_MNFG_FLAGS_MNFG_DISABLE_MEMORY_eREPAIR) - { - l_disableMemoryERepair = true; - } - - // Check if this is Manufacturing mode IPL. - l_mnfgModeIPL = false; - - if(l_allMnfgFlags & fapi2::ENUM_ATTR_MNFG_FLAGS_MNFG_THRESHOLDS) - { - l_mnfgModeIPL = true; - } - - // Get the type of passed targets - l_endp1_tgtType = i_endp1_target.getType(); - l_endp2_tgtType = i_endp2_target.getType(); - - // Check if the correct target types are passed - if(l_endp1_tgtType == fapi2::TARGET_TYPE_XBUS_ENDPOINT || - l_endp1_tgtType == fapi2::TARGET_TYPE_OBUS) - { - FAPI_ASSERT(l_endp1_tgtType == l_endp2_tgtType, - fapi2::P9_EREPAIR_RESTORE_INVALID_TARGET_PAIR() - .set_TARGET1(l_endp1_tgtType) - .set_TARGET2(l_endp2_tgtType), - "ERROR:erepairGetRestoreLanes: Invalid endpoint target pair"); - - // Check for enablement of Fabric eRepair - if(l_mnfgModeIPL && l_disableFabricERepair) - { - // Fabric eRepair has been disabled using the - // Manufacturing policy flags - FAPI_INF("erepairGetRestoreLanes: Fabric eRepair is disabled"); - goto fapi_try_exit; - } - } - else if(l_endp1_tgtType == fapi2::TARGET_TYPE_MCS_CHIPLET || - l_endp1_tgtType == fapi2::TARGET_TYPE_MEMBUF_CHIP) - { - FAPI_ASSERT( ((l_endp1_tgtType == fapi2::TARGET_TYPE_MCS_CHIPLET) && - (l_endp2_tgtType == fapi2::TARGET_TYPE_MEMBUF_CHIP)) || - ((l_endp1_tgtType == fapi2::TARGET_TYPE_MEMBUF_CHIP) && - (l_endp2_tgtType == fapi2::TARGET_TYPE_MCS_CHIPLET)), - fapi2::P9_EREPAIR_RESTORE_INVALID_TARGET_PAIR() - .set_TARGET1(l_endp1_tgtType) - .set_TARGET2(l_endp2_tgtType), - "ERROR:erepairGetRestoreLanes: Invalid endpoint target pair"); - - // Check for enablement of Memory eRepair - if(l_mnfgModeIPL && l_disableMemoryERepair) - { - // Memory eRepair has been disabled using the - // Manufacturing policy flags - FAPI_INF("erepairGetRestoreLanes: Memory eRepair is disabled"); - goto fapi_try_exit; - } - } - - if(l_mnfgModeIPL) - { - /***** Check Field VPD *****/ - - // Do not allow eRepair data in Field VPD during Mfg Mode IPL - l_rc = mnfgCheckFieldVPD(i_endp1_target, - i_endp2_target, - i_clkGroup); - - if(l_rc) - { - FAPI_DBG("erepairGetRestoreLanes:Error from mnfgCheckFieldVPD"); - fapi2::current_err = l_rc; - goto fapi_try_exit; - } - - /***** Read Manufacturing VPD *****/ - FAPI_TRY( getVerifiedRepairLanes( - i_endp1_target, - i_endp2_target, - i_clkGroup, - o_endp1_txFaillanes, - o_endp1_rxFaillanes, - o_endp2_txFaillanes, - o_endp2_rxFaillanes, - EREPAIR_VPD_MNFG), - "getVerifiedRepairLanes(Mnfg) mnfg mode ipl failed w/rc=0x%x", - (uint64_t)current_err ); - } - else - { - /***** Normal Mode IPL *****/ - // During Normal mode IPL we read both Mnfg and Field VPD - // for restoring eRepair lanes - - /***** Read Manufacturing VPD *****/ - FAPI_TRY( getVerifiedRepairLanes( - i_endp1_target, - i_endp2_target, - i_clkGroup, - l_endp1_txMnfgFaillanes, - l_endp1_rxMnfgFaillanes, - l_endp2_txMnfgFaillanes, - l_endp2_rxMnfgFaillanes, - EREPAIR_VPD_MNFG), - "getVerifiedRepairLanes(Mnfg) normal mode ipl failed w/rc=0x%x", - (uint64_t)current_err ); - - /***** Read Field VPD *****/ - FAPI_TRY( getVerifiedRepairLanes( - i_endp1_target, - i_endp2_target, - i_clkGroup, - l_endp1_txFieldFaillanes, - l_endp1_rxFieldFaillanes, - l_endp2_txFieldFaillanes, - l_endp2_rxFieldFaillanes, - EREPAIR_VPD_FIELD), - "getVerifiedRepairLanes(Field) normal mode ipl failed w/rc=0x%x", - (uint64_t)current_err ); - - /***** Combine the Mnfg and Field eRepair lanes *****/ - - // Combine the Tx side fail lanes of endp1 - combineFieldandMnfgLanes(l_endp1_txMnfgFaillanes, - l_endp1_txFieldFaillanes, - o_endp1_txFaillanes); - - // Combine the Rx side fail lanes of endp1 - combineFieldandMnfgLanes(l_endp1_rxMnfgFaillanes, - l_endp1_rxFieldFaillanes, - o_endp1_rxFaillanes); - - // Combine the Tx side fail lanes of endp2 - combineFieldandMnfgLanes(l_endp2_txMnfgFaillanes, - l_endp2_txFieldFaillanes, - o_endp2_txFaillanes); - - // Combine the Rx side fail lanes of endp1 - combineFieldandMnfgLanes(l_endp2_rxMnfgFaillanes, - l_endp2_rxFieldFaillanes, - o_endp2_rxFaillanes); - - } // end of else block of "if(l_mnfgModeIPL)" - - - /***** Check for threshold exceed conditions *****/ - - // Get the eRepair threshold limit - l_threshold = 0; - FAPI_TRY( geteRepairThreshold( - i_endp1_target, - l_mnfgModeIPL, - l_threshold), - "geteRepairThreshold() failed w/rc=0x%x", - (uint64_t)current_err ); - - // Check if the eRepair threshold has exceeded for Tx side of endp1 - if(o_endp1_txFaillanes.size() > l_threshold) - { - l_thresholdExceed = true; - l_numTxFailLanes = o_endp1_txFaillanes.size(); - - FAPI_DBG("erepairGetRestoreLanes: eRepair threshold exceed error" - " seen in Tx of endp1 target. No.of lanes: %d", l_numTxFailLanes); - } - - // Check if the eRepair threshold has exceeded for Rx side of endp1 - if(o_endp1_rxFaillanes.size() > l_threshold) - { - l_thresholdExceed = true; - l_numRxFailLanes = o_endp1_rxFaillanes.size(); - - FAPI_DBG("erepairGetRestoreLanes: eRepair threshold exceed error" - " seen in Rx of endp1 target. No.of lanes: %d", l_numRxFailLanes); - } - - // Check if the eRepair threshold has exceeded for Tx side of endp2 - if(o_endp2_txFaillanes.size() > l_threshold) - { - l_thresholdExceed = true; - l_numTxFailLanes = o_endp2_txFaillanes.size(); - - FAPI_DBG("erepairGetRestoreLanes: eRepair threshold exceed error" - " seen in Tx of endp2 target. No.of lanes: %d", - l_numTxFailLanes); - } - - // Check if the eRepair threshold has exceeded for Rx side of endp2 - if(o_endp2_rxFaillanes.size() > l_threshold) - { - l_thresholdExceed = true; - l_numRxFailLanes = o_endp2_rxFaillanes.size(); - - FAPI_DBG("erepairGetRestoreLanes: eRepair threshold exceed error" - " seen in Rx of endp2 target. No.of lanes: %d", - l_numRxFailLanes); - } - - FAPI_ASSERT(l_thresholdExceed == false, - fapi2::P9_EREPAIR_THRESHOLD_EXCEED() - .set_TX_NUM_LANES(l_numTxFailLanes) - .set_RX_NUM_LANES(l_numTxFailLanes) - .set_THRESHOLD(l_threshold), - "ERROR:The threshold limit for eRepair has been crossed"); - - if(l_mnfgModeIPL) - { - // Check if MNFG_DMI_DEPLOY_LANE_SPARES is enabled - l_enableDmiSpares = false; - - if(l_allMnfgFlags & - fapi2::ENUM_ATTR_MNFG_FLAGS_MNFG_DMI_DEPLOY_LANE_SPARES) - { - l_enableDmiSpares = true; - } - - // Check if MNFG_FABRIC_DEPLOY_LANE_SPARES is enabled - l_enableFabricSpares = false; - - if(l_allMnfgFlags & - fapi2::ENUM_ATTR_MNFG_FLAGS_MNFG_FABRIC_DEPLOY_LANE_SPARES) - { - l_enableFabricSpares = true; - } - - if(l_enableDmiSpares || l_enableFabricSpares) - { - // This is a Corner testing IPL. - // eRepair Restore the pre-determined memory lanes - getCornerTestingLanes(i_endp1_target, - o_endp1_txFaillanes, - o_endp1_rxFaillanes, - o_endp2_txFaillanes, - o_endp2_rxFaillanes); - } - } // end of if(l_mnfgModeIPL) - -fapi_try_exit: - return fapi2::current_err; -} - -template ReturnCode erepairGetRestoreLanes<TARGET_TYPE_XBUS, TARGET_TYPE_XBUS>( - const fapi2::Target < fapi2::TARGET_TYPE_XBUS >& i_endp1_target, - const fapi2::Target < fapi2::TARGET_TYPE_XBUS >& i_endp2_target, - const uint8_t i_clkGroup, - std::vector<uint8_t>& o_endp1_txFaillanes, - std::vector<uint8_t>& o_endp1_rxFaillanes, - std::vector<uint8_t>& o_endp2_txFaillanes, - std::vector<uint8_t>& o_endp2_rxFaillanes); - - -void combineFieldandMnfgLanes(std::vector<uint8_t>& i_mnfgFaillanes, - std::vector<uint8_t>& i_fieldFaillanes, - std::vector<uint8_t>& o_allFaillanes) -{ - std::vector<uint8_t>::iterator l_it; - - // Merge the Field and Mnfg fail lanes - l_it = o_allFaillanes.begin(); - o_allFaillanes.insert(l_it, - i_mnfgFaillanes.begin(), - i_mnfgFaillanes.end()); - - l_it = o_allFaillanes.end(); - o_allFaillanes.insert(l_it, - i_fieldFaillanes.begin(), - i_fieldFaillanes.end()); - - // Check if Mfg VPD and Field VPD have same fail lanes. - // If found, erase them - std::sort(o_allFaillanes.begin(), o_allFaillanes.end()); - - o_allFaillanes.erase(std::unique(o_allFaillanes.begin(), - o_allFaillanes.end()), - o_allFaillanes.end()); - -} - -template<fapi2::TargetType K> -void getCornerTestingLanes( - const fapi2::Target < K >& i_tgtType, - std::vector<uint8_t>& o_endp1_txFaillanes, - std::vector<uint8_t>& o_endp1_rxFaillanes, - std::vector<uint8_t>& o_endp2_txFaillanes, - std::vector<uint8_t>& o_endp2_rxFaillanes) -{ - std::vector<uint8_t>::iterator l_it; - uint8_t l_deployIndx = 0; - uint8_t l_maxDeploys = 0; - uint8_t* l_deployPtr = NULL; - - uint8_t l_xDeployLanes[XBUS_MAXSPARES_IN_HW] = {XBUS_SPARE_DEPLOY_LANE_1}; - uint8_t l_oDeployLanes[OBUS_MAXSPARES_IN_HW] = {OBUS_SPARE_DEPLOY_LANE_1, - OBUS_SPARE_DEPLOY_LANE_2 - }; - - uint8_t l_dmiDeployLanes[DMIBUS_MAXSPARES_IN_HW] = - { - DMIBUS_SPARE_DEPLOY_LANE_1, - DMIBUS_SPARE_DEPLOY_LANE_2 - }; - - // Idea is to push_back the pre-determined lanes into the Tx and Rx - // vectors of endpoint1 and endpoint2 - switch(i_tgtType.getType()) - { - case fapi2::TARGET_TYPE_XBUS_ENDPOINT: - l_maxDeploys = XBUS_MAXSPARES_IN_HW; - l_deployPtr = l_xDeployLanes; - break; - - case fapi2::TARGET_TYPE_OBUS: - l_maxDeploys = OBUS_MAXSPARES_IN_HW; - l_deployPtr = l_oDeployLanes; - break; - - case fapi2::TARGET_TYPE_MCS_CHIPLET: - case fapi2::TARGET_TYPE_MEMBUF_CHIP: - l_maxDeploys = DMIBUS_MAXSPARES_IN_HW; - l_deployPtr = l_dmiDeployLanes; - break; - - default: - FAPI_ASSERT(false, - fapi2::P9_EREPAIR_RESTORE_INVALID_TARGET() - .set_TARGET(i_tgtType), - "ERROR:getCornerTestingLanes: Invalid target type"); - break; - }; - - std::sort(o_endp1_txFaillanes.begin(), o_endp1_txFaillanes.end()); - - std::sort(o_endp1_rxFaillanes.begin(), o_endp1_rxFaillanes.end()); - - for(l_deployIndx = 0; - ((l_deployIndx < l_maxDeploys) && - (o_endp1_txFaillanes.size() < l_maxDeploys)); - l_deployIndx++) - { - l_it = std::find(o_endp1_txFaillanes.begin(), - o_endp1_txFaillanes.end(), - l_deployPtr[l_deployIndx]); - - if(l_it == o_endp1_txFaillanes.end()) - { - o_endp1_txFaillanes.push_back(l_deployPtr[l_deployIndx]); - } - } - - for(l_deployIndx = 0; - ((o_endp1_rxFaillanes.size() < l_maxDeploys) && - (l_deployIndx < l_maxDeploys)); - l_deployIndx++) - { - l_it = std::find(o_endp1_rxFaillanes.begin(), - o_endp1_rxFaillanes.end(), - l_deployPtr[l_deployIndx]); - - if(l_it == o_endp1_rxFaillanes.end()) - { - o_endp1_rxFaillanes.push_back(l_deployPtr[l_deployIndx]); - } - } - - // We can cassign the lanes of endpoint1 to endpoint2 because any - // existing faillanes in endpoint2 have already been matched with - // endpoint1. This means that there cannot be any faillanes in - // endpoint2 that do not have equivalent lanes in endpoint1. - o_endp2_txFaillanes = o_endp1_txFaillanes; - o_endp2_rxFaillanes = o_endp1_rxFaillanes; - -fapi_try_exit: - return; -} - -template<fapi2::TargetType K> -fapi2::ReturnCode geteRepairThreshold( - const fapi2::Target < K >& i_endp_target, - const bool i_mfgModeIPL, - uint8_t& o_threshold) -{ - fapi2::current_err = fapi2::FAPI2_RC_SUCCESS; - fapi2::TargetType l_tgtType = fapi2::TARGET_TYPE_NONE; - - o_threshold = 0; - l_tgtType = i_endp_target.getType(); - - if(i_mfgModeIPL) - { - switch(l_tgtType) - { - case fapi2::TARGET_TYPE_XBUS_ENDPOINT: - FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_X_EREPAIR_THRESHOLD_MNFG, - fapi2::Target<fapi2::TARGET_TYPE_SYSTEM>(), - o_threshold)); - break; - - case fapi2::TARGET_TYPE_OBUS: - FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_O_EREPAIR_THRESHOLD_MNFG, - fapi2::Target<fapi2::TARGET_TYPE_SYSTEM>(), - o_threshold)); - break; - - case fapi2::TARGET_TYPE_MCS_CHIPLET: - case fapi2::TARGET_TYPE_MEMBUF_CHIP: - FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_DMI_EREPAIR_THRESHOLD_MNFG, - fapi2::Target<fapi2::TARGET_TYPE_SYSTEM>(), - o_threshold)); - break; - - default: - FAPI_ASSERT(false, - fapi2::P9_EREPAIR_RESTORE_INVALID_TARGET() - .set_TARGET(l_tgtType), - "ERROR:geteRepairThreshold: Invalid target type"); - break; - }; - } - else - { - switch(l_tgtType) - { - case fapi2::TARGET_TYPE_XBUS_ENDPOINT: - FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_X_EREPAIR_THRESHOLD_FIELD, - fapi2::Target<fapi2::TARGET_TYPE_SYSTEM>(), - o_threshold)); - break; - - case fapi2::TARGET_TYPE_OBUS: - FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_O_EREPAIR_THRESHOLD_FIELD, - fapi2::Target<fapi2::TARGET_TYPE_SYSTEM>(), - o_threshold)); - break; - - case fapi2::TARGET_TYPE_MCS_CHIPLET: - case fapi2::TARGET_TYPE_MEMBUF_CHIP: - FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_DMI_EREPAIR_THRESHOLD_FIELD, - fapi2::Target<fapi2::TARGET_TYPE_SYSTEM>(), - o_threshold)); - break; - - default: - FAPI_ASSERT(false, - fapi2::P9_EREPAIR_RESTORE_INVALID_TARGET() - .set_TARGET(l_tgtType), - "ERROR:geteRepairThreshold: Invalid target type"); - break; - }; - } - -fapi_try_exit: - FAPI_INF("geteRepairThreshold: o_threshold = %d", o_threshold); - return fapi2::current_err; -} - -template<fapi2::TargetType K, fapi2::TargetType J> -fapi2::ReturnCode mnfgCheckFieldVPD( - const fapi2::Target < K >& i_endp1_target, - const fapi2::Target < J >& i_endp2_target, - const uint8_t i_clkGroup) -{ - fapi2::current_err = fapi2::FAPI2_RC_SUCCESS; - std::vector<uint8_t> l_endp1_txFaillanes; - std::vector<uint8_t> l_endp1_rxFaillanes; - std::vector<uint8_t> l_endp2_txFaillanes; - std::vector<uint8_t> l_endp2_rxFaillanes; - bool l_fieldVPDClear = true; - - l_fieldVPDClear = true; - - /***** Read Field VPD *****/ - - // During Mfg mode IPL, field VPD need to be clear. - - // Get failed lanes for endp1 - FAPI_TRY( erepairGetFieldFailedLanes( - i_endp1_target, - i_clkGroup, - l_endp1_txFaillanes, - l_endp1_rxFaillanes), - "erepairGetFieldFailedLanes endp1 target failed w/rc=0x%x", - (uint64_t)current_err ); - - // If there are fail lanes in Field VPD on endpoint1, create an - // error log and return - if(l_endp1_txFaillanes.size() || - l_endp1_rxFaillanes.size()) - { - l_fieldVPDClear = false; - FAPI_DBG("mnfgCheckFieldVPD: eRepair records found in Field VPD in Tx during Manufacturing mode IPL"); - } - - // Get failed lanes for endp2 - FAPI_TRY( erepairGetFieldFailedLanes( - i_endp2_target, - i_clkGroup, - l_endp2_txFaillanes, - l_endp2_rxFaillanes), - "erepairGetFieldFailedLanes endp2 target failed w/rc=0x%x", - (uint64_t)current_err ); - - // If there are fail lanes in Field VPD on endpoint2, create an - // error log and return - if(l_endp2_txFaillanes.size() || - l_endp2_rxFaillanes.size()) - { - l_fieldVPDClear = false; - FAPI_DBG("mnfgCheckFieldVPD: eRepair records found in Field VPD in Rx during Manufacturing mode IPL"); - } - - FAPI_ASSERT(l_fieldVPDClear == true, - fapi2::P9_EREPAIR_RESTORE_FIELD_VPD_NOT_CLEAR() - .set_TARGET1(i_endp1_target) - .set_TARGET2(i_endp2_target), - "ERROR: mnfgCheckFieldVPD: Field VPD need to be clear during Mnfg mode IPL"); - -fapi_try_exit: - return fapi2::current_err; -} - -template<fapi2::TargetType K, fapi2::TargetType J> -fapi2::ReturnCode getVerifiedRepairLanes( - const fapi2::Target < K >& i_endp1_target, - const fapi2::Target < J >& i_endp2_target, - const uint8_t i_clkGroup, - std::vector<uint8_t>& o_endp1_txFaillanes, - std::vector<uint8_t>& o_endp1_rxFaillanes, - std::vector<uint8_t>& o_endp2_txFaillanes, - std::vector<uint8_t>& o_endp2_rxFaillanes, - const erepairVpdType i_vpdType) -{ - fapi2::current_err = fapi2::FAPI2_RC_SUCCESS; - - getLanes_t<K> l_getLanes = NULL; - setLanes_t<K> l_setLanes = NULL; - - fapi2::Target < K > l_target[2] = {i_endp1_target, i_endp2_target}; - bool l_invalidFails_inTx_OfTgt[2] = {false, false}; - bool l_invalidFails_inRx_OfTgt[2] = {false, false}; - uint8_t l_tgtIndx = 0; - - std::vector<uint8_t> l_emptyVector; - std::vector<uint8_t> l_txFaillanes; - std::vector<uint8_t> l_rxFaillanes; - - FAPI_INF(">> getVerifiedRepairLanes: vpdType: %s", - i_vpdType == EREPAIR_VPD_FIELD ? "Field" : "Mnfg"); - - /***** Read VPD *****/ - - if(i_vpdType == EREPAIR_VPD_FIELD) - { - l_getLanes = &erepairGetFieldFailedLanes; - l_setLanes = &erepairSetFieldFailedLanes; - } - else if(i_vpdType == EREPAIR_VPD_MNFG) - { - l_getLanes = &erepairGetMnfgFailedLanes; - l_setLanes = &erepairSetMnfgFailedLanes; - } - - for(l_tgtIndx = 0; l_tgtIndx < 2; l_tgtIndx++) - { - // Get failed lanes for endp1 and endp2 - FAPI_TRY( l_getLanes( - l_target[l_tgtIndx], - i_clkGroup, - l_txFaillanes, - l_rxFaillanes), - "getVerifiedRepairLanes() from Accessor HWP failed w/rc=0x%x", - (uint64_t)current_err ); - - if(l_tgtIndx == 0) - { - o_endp1_txFaillanes = l_txFaillanes; - o_endp1_rxFaillanes = l_rxFaillanes; - } - else - { - o_endp2_txFaillanes = l_txFaillanes; - o_endp2_rxFaillanes = l_rxFaillanes; - } - - l_txFaillanes.clear(); - l_rxFaillanes.clear(); - } // end of for(l_tgtIndx) - - // Check if matching fail lanes exists on the sub-interfaces - // connecting the two end points - if(o_endp1_txFaillanes.size() || o_endp2_rxFaillanes.size()) - { - invalidateNonMatchingFailLanes(o_endp1_txFaillanes, - o_endp2_rxFaillanes, - l_invalidFails_inTx_OfTgt[0], - l_invalidFails_inRx_OfTgt[1]); - } - - if(o_endp2_txFaillanes.size() || o_endp1_rxFaillanes.size()) - { - invalidateNonMatchingFailLanes(o_endp2_txFaillanes, - o_endp1_rxFaillanes, - l_invalidFails_inTx_OfTgt[1], - l_invalidFails_inRx_OfTgt[0]); - } - - /***** Correct eRepair data of endp1 in VPD *****/ - - for(l_tgtIndx = 0; l_tgtIndx < 2; l_tgtIndx++) - { - if(l_tgtIndx == 0) - { - l_txFaillanes = o_endp1_txFaillanes; - l_rxFaillanes = o_endp1_rxFaillanes; - } - else - { - l_txFaillanes = o_endp2_txFaillanes; - l_rxFaillanes = o_endp2_rxFaillanes; - } - - // Update endp1 and endp2 VPD to invalidate fail lanes that do - // not have matching fail lanes on the other end - if(l_invalidFails_inTx_OfTgt[l_tgtIndx] && - l_invalidFails_inRx_OfTgt[l_tgtIndx]) - { - FAPI_TRY( l_setLanes( - l_target[l_tgtIndx], - i_clkGroup, - l_txFaillanes, - l_rxFaillanes), - "getVerifiedRepairLanes() tx/rx from Accessor HWP failed w/rc=0x%x", - (uint64_t)current_err ); - } - else if(l_invalidFails_inTx_OfTgt[l_tgtIndx]) - { - FAPI_TRY( l_setLanes( - l_target[l_tgtIndx], - i_clkGroup, - l_txFaillanes, - l_emptyVector), - "getVerifiedRepairLanes() tx from Accessor HWP failed w/rc=0x%x", - (uint64_t)current_err ); - } - else if(l_invalidFails_inRx_OfTgt[l_tgtIndx]) - { - FAPI_TRY( l_setLanes( - l_target[l_tgtIndx], - i_clkGroup, - l_emptyVector, - l_rxFaillanes), - "getVerifiedRepairLanes() rx from Accessor HWP failed w/rc=0x%x", - (uint64_t)current_err ); - } - } // end of for loop - -fapi_try_exit: - return current_err; -} - -void invalidateNonMatchingFailLanes(std::vector<uint8_t>& io_endp1_txFaillanes, - std::vector<uint8_t>& io_endp2_rxFaillanes, - bool& o_invalidFails_inTx_Ofendp1, bool& o_invalidFails_inRx_Ofendp2) { std::vector<uint8_t>::iterator l_it; @@ -980,302 +129,44 @@ void invalidateNonMatchingFailLanes(std::vector<uint8_t>& io_endp1_txFaillanes, } } - -template<fapi2::TargetType K> -fapi2::ReturnCode erepairGetFailedLanes( - const fapi2::Target < K >& i_endp_target, - const uint8_t i_clkGroup, - std::vector<uint8_t>& o_txFailLanes, - std::vector<uint8_t>& o_rxFailLanes) +/** + * @brief This function combines the eRepair lane numbers read from + * Manufacturing VPD and Field VPD + * + * @param [in] i_mnfgFaillanes The eRepair lane numbers read from the + * Manufacturing VPD + * @param [in] i_fieldFaillanes The eRepair lane numbers read from the + * Field VPD + * @param [out] o_allFaillanes The eRepair lane numbers which is the union + * of the Field and Manufacturing eRepair lanes + * passed as first iand second params + * + * @return void + */ +void combineFieldandMnfgLanes(std::vector<uint8_t>& i_mnfgFaillanes, + std::vector<uint8_t>& i_fieldFaillanes, + std::vector<uint8_t>& o_allFaillanes) { - fapi2::current_err = fapi2::FAPI2_RC_SUCCESS; - std::vector<uint8_t> l_txFailLanes; - std::vector<uint8_t> l_rxFailLanes; std::vector<uint8_t>::iterator l_it; - FAPI_INF(">> erepairGetFailedLaness"); - - // Get the erepair lanes from Field VPD - FAPI_TRY( erepairGetFieldFailedLanes( - i_endp_target, - i_clkGroup, - l_txFailLanes, - l_rxFailLanes), - "erepairGetFieldFailedLanes() failed w/rc=0x%x", - (uint64_t)current_err ); - - o_txFailLanes = l_txFailLanes; - o_rxFailLanes = l_rxFailLanes; - - // Get the erepair lanes from Manufacturing VPD - l_txFailLanes.clear(); - l_rxFailLanes.clear(); - FAPI_TRY( erepairGetMnfgFailedLanes( - i_endp_target, - i_clkGroup, - l_txFailLanes, - l_rxFailLanes), - "erepairGetMnfgFailedLanes() failed w/rc=0x%x", - (uint64_t)current_err ); - - // Merge the Mnfg lanes with the Field lanes - l_it = o_txFailLanes.end(); - o_txFailLanes.insert(l_it, l_txFailLanes.begin(), l_txFailLanes.end()); - - l_it = o_rxFailLanes.end(); - o_rxFailLanes.insert(l_it, l_rxFailLanes.begin(), l_rxFailLanes.end()); - -fapi_try_exit: - return fapi2::current_err; -} - -template fapi2::ReturnCode erepairGetFailedLanes<TARGET_TYPE_XBUS>( - const fapi2::Target < TARGET_TYPE_XBUS >& i_endp_target, - const uint8_t i_clkGroup, - std::vector<uint8_t>& o_txFailLanes, - std::vector<uint8_t>& o_rxFailLanes); - - -template<fapi2::TargetType K> -fapi2::ReturnCode erepairGetFieldFailedLanes( - const fapi2::Target < K >& i_endp_target, - const uint8_t i_clkGroup, - std::vector<uint8_t>& o_txFailLanes, - std::vector<uint8_t>& o_rxFailLanes) -{ - fapi2::current_err = fapi2::FAPI2_RC_SUCCESS; - - FAPI_DBG(">> erepairGetFieldFailedLanes"); - - // Execute the Accessor HWP to retrieve the failed lanes from the VPD - FAPI_TRY( p9_io_erepairGetFailedLanesHwp( - i_endp_target, - EREPAIR_VPD_FIELD, - i_clkGroup, - o_txFailLanes, - o_rxFailLanes), - "erepairGetFieldFailedLanes() from Accessor HWP failed w/rc=0x%x", - (uint64_t)current_err ); - -fapi_try_exit: - return fapi2::current_err; -} - - -template<fapi2::TargetType K> -fapi2::ReturnCode erepairGetMnfgFailedLanes( - const fapi2::Target < K >& i_endp_target, - const uint8_t i_clkGroup, - std::vector<uint8_t>& o_txFailLanes, - std::vector<uint8_t>& o_rxFailLanes) -{ - fapi2::current_err = fapi2::FAPI2_RC_SUCCESS; - - FAPI_DBG(">> erepairGetMnfgFailedLanes"); - - // Execute the Accessor HWP to retrieve the failed lanes from the VPD - FAPI_TRY( p9_io_erepairGetFailedLanesHwp( - i_endp_target, - EREPAIR_VPD_MNFG, - i_clkGroup, - o_txFailLanes, - o_rxFailLanes), - "erepairGetMnfgFailedLanes() from Accessor HWP failed w/rc=0x%x", - (uint64_t)current_err ); - -fapi_try_exit: - return fapi2::current_err; -} - -template<fapi2::TargetType K, fapi2::TargetType J> -fapi2::ReturnCode erepairSetFailedLanes( - const fapi2::Target < K >& i_txEndp_target, - const fapi2::Target < J >& i_rxEndp_target, - const uint8_t i_clkGroup, - const std::vector<uint8_t>& i_rxFailLanes, - bool& o_thresholdExceed) -{ - fapi2::current_err = fapi2::FAPI2_RC_SUCCESS; - uint64_t l_allMnfgFlags = 0; - bool l_mnfgModeIPL = false; - uint8_t l_threshold = 0; - setLanes_t<K> l_setLanes = NULL; - getLanes_t<K> l_getLanes = NULL; - std::vector<uint8_t> l_txFaillanes; - std::vector<uint8_t> l_rxFaillanes; - std::vector<uint8_t> l_emptyVector; - std::vector<uint8_t> l_throwAway; - - FAPI_INF(">> erepairSetFailedLanes"); - - o_thresholdExceed = false; - - // Get the Manufacturing Policy flags - FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_MNFG_FLAGS, - fapi2::Target<fapi2::TARGET_TYPE_SYSTEM>(), - l_allMnfgFlags), - "erepairSetFailedLanes: Unable to read attribute ATTR_MNFG_FLAGS"); - - // Check if this is a Mnfg mode IPL - if(l_allMnfgFlags & fapi2::ENUM_ATTR_MNFG_FLAGS_MNFG_THRESHOLDS) - { - l_mnfgModeIPL = true; - } - - if(l_mnfgModeIPL) - { - l_setLanes = &erepairSetMnfgFailedLanes; - l_getLanes = &erepairGetMnfgFailedLanes; - } - else - { - l_setLanes = &erepairSetFieldFailedLanes; - l_getLanes = &erepairGetFieldFailedLanes; - } - - /*** Check if we have crossed the repair threshold ***/ - // Get the eRepair threshold limit - l_threshold = 0; - FAPI_TRY( geteRepairThreshold( - i_rxEndp_target, - l_mnfgModeIPL, - l_threshold), - "geteRepairThreshold() from Accessor HWP failed w/rc=0x%x", - (uint64_t)current_err ); - - // Check if the new fails have crossed the threshold - if(i_rxFailLanes.size() > l_threshold) - { - o_thresholdExceed = true; - goto fapi_try_exit; - } - - // Get existing fail lanes that are in the VPD of rx endpoint - FAPI_TRY( l_getLanes( - i_rxEndp_target, - i_clkGroup, - l_throwAway, - l_rxFaillanes), - "rx l_getLanes() from Accessor HWP failed w/rc=0x%x", - (uint64_t)current_err ); - - // Get existing fail lanes that are in the VPD of tx endpoint - FAPI_TRY( l_getLanes( - i_txEndp_target, - i_clkGroup, - l_txFaillanes, - l_throwAway), - "tx l_getLanes() from Accessor HWP failed w/rc=0x%x", - (uint64_t)current_err ); - - // Lets combine the new and old fail lanes of Rx side - l_rxFaillanes.insert(l_rxFaillanes.end(), - i_rxFailLanes.begin(), - i_rxFailLanes.end()); - - // Remove duplicate lanes if any on the Rx side - std::sort(l_rxFaillanes.begin(), l_rxFaillanes.end()); - - l_rxFaillanes.erase(std::unique(l_rxFaillanes.begin(), - l_rxFaillanes.end()), - l_rxFaillanes.end()); - - // Lets combine the new and old fail lanes of Tx side - l_txFaillanes.insert(l_txFaillanes.end(), - i_rxFailLanes.begin(), - i_rxFailLanes.end()); - - // Remove duplicate lanes if any on the Tx side - std::sort(l_txFaillanes.begin(), l_txFaillanes.end()); - - l_txFaillanes.erase(std::unique(l_txFaillanes.begin(), - l_txFaillanes.end()), - l_txFaillanes.end()); - - // Check if the sum of old and new fail lanes have crossed the threshold - if((l_txFaillanes.size() > l_threshold) || - (l_rxFaillanes.size() > l_threshold)) - { - o_thresholdExceed = true; - goto fapi_try_exit; - } - - /*** Update the VPD ***/ - - // Lets write the VPD of endpoint1 with faillanes on Rx side - FAPI_TRY( l_setLanes( - i_rxEndp_target, - i_clkGroup, - l_emptyVector, - l_rxFaillanes), - "rx l_setLanes() from Accessor HWP failed w/rc=0x%x", - (uint64_t)current_err ); - - // Lets write the VPD of endpoint2 with faillanes on Tx side - FAPI_TRY( l_setLanes( - i_txEndp_target, - i_clkGroup, - l_txFaillanes, - l_emptyVector), - "tx l_setLanes() from Accessor HWP failed w/rc=0x%x", - (uint64_t)current_err ); - -fapi_try_exit: - FAPI_INF("<< erepairSetFailedLanes"); - return fapi2::current_err; -} - -template ReturnCode erepairSetFailedLanes<TARGET_TYPE_XBUS, TARGET_TYPE_XBUS>( - const fapi2::Target < TARGET_TYPE_XBUS >& i_txEndp_target, - const fapi2::Target < TARGET_TYPE_XBUS >& i_rxEndp_target, - const uint8_t i_clkGroup, - const std::vector<uint8_t>& i_rxFailLanes, - bool& o_thresholdExceed); - - -template<fapi2::TargetType K> -fapi2::ReturnCode erepairSetFieldFailedLanes( - const fapi2::Target < K >& i_endp_target, - const uint8_t i_clkGroup, - const std::vector<uint8_t>& i_txFailLanes, - const std::vector<uint8_t>& i_rxFailLanes) -{ - fapi2::current_err = fapi2::FAPI2_RC_SUCCESS; - - // Execute the Accessor HWP to write the fail lanes to Field VPD - FAPI_TRY( p9_io_erepairSetFailedLanesHwp( - i_endp_target, - EREPAIR_VPD_FIELD, - i_clkGroup, - i_txFailLanes, - i_rxFailLanes), - "erepairSetFieldFailedLanes() from Accessor HWP failed w/rc=0x%x", - (uint64_t)current_err ); + // Merge the Field and Mnfg fail lanes + l_it = o_allFaillanes.begin(); + o_allFaillanes.insert(l_it, + i_mnfgFaillanes.begin(), + i_mnfgFaillanes.end()); -fapi_try_exit: - return fapi2::current_err; -} + l_it = o_allFaillanes.end(); + o_allFaillanes.insert(l_it, + i_fieldFaillanes.begin(), + i_fieldFaillanes.end()); -template<fapi2::TargetType K> -fapi2::ReturnCode erepairSetMnfgFailedLanes( - const fapi2::Target < K >& i_endp_target, - const uint8_t i_clkGroup, - const std::vector<uint8_t>& i_txFailLanes, - const std::vector<uint8_t>& i_rxFailLanes) -{ - fapi2::current_err = fapi2::FAPI2_RC_SUCCESS; + // Check if Mfg VPD and Field VPD have same fail lanes. + // If found, erase them + std::sort(o_allFaillanes.begin(), o_allFaillanes.end()); - // Execute the Accessor HWP to write the fail lanes to Mnfg VPD - FAPI_TRY( p9_io_erepairSetFailedLanesHwp( - i_endp_target, - EREPAIR_VPD_MNFG, - i_clkGroup, - i_txFailLanes, - i_rxFailLanes), - "erepairSetMnfgFailedLanes() from Accessor HWP failed w/rc=0x%x", - (uint64_t)current_err ); + o_allFaillanes.erase(std::unique(o_allFaillanes.begin(), + o_allFaillanes.end()), + o_allFaillanes.end()); -fapi_try_exit: - return fapi2::current_err; } diff --git a/src/import/chips/p9/procedures/hwp/io/p9_io_erepairAccessorHwpFuncs.H b/src/import/chips/p9/procedures/hwp/io/p9_io_erepairAccessorHwpFuncs.H index 246857af3..f23c079b8 100755 --- a/src/import/chips/p9/procedures/hwp/io/p9_io_erepairAccessorHwpFuncs.H +++ b/src/import/chips/p9/procedures/hwp/io/p9_io_erepairAccessorHwpFuncs.H @@ -5,7 +5,7 @@ /* */ /* OpenPOWER HostBoot Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2015,2017 */ +/* Contributors Listed Below - COPYRIGHT 2015,2018 */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -28,14 +28,16 @@ /// //---------------------------------------------------------------------------- - #ifndef P9_IO_EREPAIRACCESSORHWPFUNCS_H_ #define P9_IO_EREPAIRACCESSORHWPFUNCS_H_ #include <fapi2.H> -#include <algorithm> +#include <string.h> +#include <p9_io_erepairConsts.H> +#include <p9_io_erepairSetFailedLanesHwp.H> +#include <p9_io_erepairGetFailedLanesHwp.H> -const uint8_t EREPAIR_MAX_CENTAUR_PER_MCS = 1; +const uint8_t EREPAIR_MAX_CENTAUR_PER_DMI = 1; template<fapi2::TargetType K> using getLanes_t = fapi2::ReturnCode (*)( @@ -52,26 +54,218 @@ using setLanes_t = fapi2::ReturnCode (*)( const std::vector<uint8_t>& o_rxFailLanes); +/***** Function definitions *****/ + /** - * @brief FW Team Utility function that gets eRepair data from the VPD - * This function gets the eRepair data from both the Field VPD - * and the Manufacturing VPD. + * @brief This function determines the lane numbers that needs to be spared + * to support Corner testing. * - * @param[in] i_endp_target Reference to X-Bus or O-Bus or MCS or memBuf Target - * @param[in] i_clkGroup Specifies clock group 0:[XOA, X1A,..] 1:[X0B, X1B,..] - * @param[out] o_txFailLanes Reference to a Vector that will contain the fail - * lanes read from the VPD for Drive side - * @param[out] o_rxFailLanes Reference to a Vector that will contain the fail - * lanes read from the VPD for Receive side - * @return ReturnCode + * @param [in] i_tgtType The target type(XBus or OBus or DMIBus) for + * which the lanes that need to be spared are + * determined + * @param [out] o_endp1_txFailLanes The reference to the vector which will + * have the Tx side of lanes that need to be + * spared for endp1 + * @param [out] o_endp1_rxFailLanes The reference to the vector which will + * have the Rx side of lanes that need to be + * spared for endp1 + * @param [out] o_endp2_txFailLanes The reference to the vector which will + * have the Tx side of lanes that need to be + * spared for endp2 + * @param [out] o_endp2_rxFailLanes The reference to the vector which will + * have the Rx side of lanes that need to be + * spared for endp2 * + * @return void */ template<fapi2::TargetType K> -fapi2::ReturnCode erepairGetFailedLanes( - const fapi2::Target < K >& i_endp_target, - const uint8_t i_clkGroup, - std::vector<uint8_t>& o_txFailLanes, - std::vector<uint8_t>& o_rxFailLanes); +void getCornerTestingLanes( + const fapi2::Target < K >& i_tgtType, + std::vector<uint8_t>& o_endp1_txFaillanes, + std::vector<uint8_t>& o_endp1_rxFaillanes, + std::vector<uint8_t>& o_endp2_txFaillanes, + std::vector<uint8_t>& o_endp2_rxFaillanes) +{ + std::vector<uint8_t>::iterator l_it; + uint8_t l_deployIndx = 0; + uint8_t l_maxDeploys = 0; + uint8_t* l_deployPtr = NULL; + + uint8_t l_xDeployLanes[EREPAIR::XBUS_MAXSPARES_IN_HW] = {EREPAIR::XBUS_SPARE_DEPLOY_LANE_1}; + uint8_t l_oDeployLanes[EREPAIR::OBUS_MAXSPARES_IN_HW] = {EREPAIR::OBUS_SPARE_DEPLOY_LANE_1, + EREPAIR::OBUS_SPARE_DEPLOY_LANE_2 + }; + + uint8_t l_dmiDeployLanes[EREPAIR::DMIBUS_MAXSPARES_IN_HW] = + { + EREPAIR::DMIBUS_SPARE_DEPLOY_LANE_1, + EREPAIR::DMIBUS_SPARE_DEPLOY_LANE_2 + }; + + // Idea is to push_back the pre-determined lanes into the Tx and Rx + // vectors of endpoint1 and endpoint2 + switch(i_tgtType.getType()) + { + case fapi2::TARGET_TYPE_XBUS_ENDPOINT: + l_maxDeploys = EREPAIR::XBUS_MAXSPARES_IN_HW; + l_deployPtr = l_xDeployLanes; + break; + + case fapi2::TARGET_TYPE_OBUS: + l_maxDeploys = EREPAIR::OBUS_MAXSPARES_IN_HW; + l_deployPtr = l_oDeployLanes; + break; + + case fapi2::TARGET_TYPE_MEMBUF_CHIP: + case fapi2::TARGET_TYPE_DMI: + l_maxDeploys = EREPAIR::DMIBUS_MAXSPARES_IN_HW; + l_deployPtr = l_dmiDeployLanes; + break; + + default: + FAPI_ASSERT(false, + fapi2::P9_EREPAIR_RESTORE_INVALID_TARGET() + .set_TARGET(i_tgtType), + "ERROR:getCornerTestingLanes: Invalid target type"); + break; + }; + + std::sort(o_endp1_txFaillanes.begin(), o_endp1_txFaillanes.end()); + + std::sort(o_endp1_rxFaillanes.begin(), o_endp1_rxFaillanes.end()); + + for(l_deployIndx = 0; + ((l_deployIndx < l_maxDeploys) && + (o_endp1_txFaillanes.size() < l_maxDeploys)); + l_deployIndx++) + { + l_it = std::find(o_endp1_txFaillanes.begin(), + o_endp1_txFaillanes.end(), + l_deployPtr[l_deployIndx]); + + if(l_it == o_endp1_txFaillanes.end()) + { + o_endp1_txFaillanes.push_back(l_deployPtr[l_deployIndx]); + } + } + + for(l_deployIndx = 0; + ((o_endp1_rxFaillanes.size() < l_maxDeploys) && + (l_deployIndx < l_maxDeploys)); + l_deployIndx++) + { + l_it = std::find(o_endp1_rxFaillanes.begin(), + o_endp1_rxFaillanes.end(), + l_deployPtr[l_deployIndx]); + + if(l_it == o_endp1_rxFaillanes.end()) + { + o_endp1_rxFaillanes.push_back(l_deployPtr[l_deployIndx]); + } + } + + // We can cassign the lanes of endpoint1 to endpoint2 because any + // existing faillanes in endpoint2 have already been matched with + // endpoint1. This means that there cannot be any faillanes in + // endpoint2 that do not have equivalent lanes in endpoint1. + o_endp2_txFaillanes = o_endp1_txFaillanes; + o_endp2_rxFaillanes = o_endp1_rxFaillanes; + +fapi_try_exit: + return; +} + +/** + * @brief This function gets the eRepair threshold value of the passed target + * for the particular IPL type. + * + * @param [in] i_endp_target The target for whose type the threshold value + * is needed + * @param [in] i_mfgModeIPL If TRUE, indicates that this is a MnfgMode IPL + * If FALSE, indicates that this is a Normal IPL + * @param [out] o_threshold The threshold return value + * + * @return ReturnCode + */ +template<fapi2::TargetType K> +fapi2::ReturnCode geteRepairThreshold( + const fapi2::Target < K >& i_endp_target, + const bool i_mfgModeIPL, + uint8_t& o_threshold) +{ + fapi2::current_err = fapi2::FAPI2_RC_SUCCESS; + fapi2::TargetType l_tgtType = fapi2::TARGET_TYPE_NONE; + + o_threshold = 0; + l_tgtType = i_endp_target.getType(); + + if(i_mfgModeIPL) + { + switch(l_tgtType) + { + case fapi2::TARGET_TYPE_XBUS_ENDPOINT: + FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_X_EREPAIR_THRESHOLD_MNFG, + fapi2::Target<fapi2::TARGET_TYPE_SYSTEM>(), + o_threshold)); + break; + + case fapi2::TARGET_TYPE_OBUS: + FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_O_EREPAIR_THRESHOLD_MNFG, + fapi2::Target<fapi2::TARGET_TYPE_SYSTEM>(), + o_threshold)); + break; + + case fapi2::TARGET_TYPE_MEMBUF_CHIP: + case fapi2::TARGET_TYPE_DMI: + FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_DMI_EREPAIR_THRESHOLD_MNFG, + fapi2::Target<fapi2::TARGET_TYPE_SYSTEM>(), + o_threshold)); + break; + + default: + FAPI_ASSERT(false, + fapi2::P9_EREPAIR_RESTORE_INVALID_TARGET() + .set_TARGET(l_tgtType), + "ERROR:geteRepairThreshold: Invalid target type"); + break; + }; + } + else + { + switch(l_tgtType) + { + case fapi2::TARGET_TYPE_XBUS_ENDPOINT: + FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_X_EREPAIR_THRESHOLD_FIELD, + fapi2::Target<fapi2::TARGET_TYPE_SYSTEM>(), + o_threshold)); + break; + + case fapi2::TARGET_TYPE_OBUS: + FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_O_EREPAIR_THRESHOLD_FIELD, + fapi2::Target<fapi2::TARGET_TYPE_SYSTEM>(), + o_threshold)); + break; + + case fapi2::TARGET_TYPE_MEMBUF_CHIP: + case fapi2::TARGET_TYPE_DMI: + FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_DMI_EREPAIR_THRESHOLD_FIELD, + fapi2::Target<fapi2::TARGET_TYPE_SYSTEM>(), + o_threshold)); + break; + + default: + FAPI_ASSERT(false, + fapi2::P9_EREPAIR_RESTORE_INVALID_TARGET() + .set_TARGET(l_tgtType), + "ERROR:geteRepairThreshold: Invalid target type"); + break; + }; + } + +fapi_try_exit: + FAPI_INF("geteRepairThreshold: o_threshold = %d", o_threshold); + return fapi2::current_err; +} /** * @brief FW Team Utility function that gets eRepair data @@ -90,10 +284,146 @@ fapi2::ReturnCode erepairGetFailedLanes( */ template<fapi2::TargetType K> fapi2::ReturnCode erepairGetFieldFailedLanes( - const fapi2::Target < K >& i_endp_target, + const fapi2::Target < K >& i_endp_target, const uint8_t i_clkGroup, std::vector<uint8_t>& o_txFailLanes, - std::vector<uint8_t>& o_rxFailLanes); + std::vector<uint8_t>& o_rxFailLanes) +{ + fapi2::current_err = fapi2::FAPI2_RC_SUCCESS; + + FAPI_DBG(">> erepairGetFieldFailedLanes"); + + // Execute the Accessor HWP to retrieve the failed lanes from the VPD + FAPI_TRY( p9_io_erepairGetFailedLanesHwp( + i_endp_target, + EREPAIR::EREPAIR_VPD_FIELD, + i_clkGroup, + o_txFailLanes, + o_rxFailLanes), + "erepairGetFieldFailedLanes() from Accessor HWP failed w/rc=0x%x", + (uint64_t)fapi2::current_err ); + +fapi_try_exit: + return fapi2::current_err; +} + +/** + * @brief FW Team Utility function that sets eRepair data in Field VPD + * + * This is a wrapper function for the Accessor HWP which writes failed lane + * numbers to the Field VPD + * + * @param[in] i_endp_target Reference to X-Bus or O-Bus or MCS or memBuf Target + * @param[in] i_clkGroup Specifies clock group 0:[XOA, X1A,..] 1:[X0B, X1B,..] + * @param[in] i_txFailLanes Vector that will contain the fail lane + * to be written to Field VPD for Drive side + * @param[in] i_rxFailLanes Vector that will contain the fail lanes + * to be written to Field VPD for Receive side + * + * @return ReturnCode + */ +template<fapi2::TargetType K> +fapi2::ReturnCode erepairSetFieldFailedLanes( + const fapi2::Target < K >& i_endp_target, + const uint8_t i_clkGroup, + const std::vector<uint8_t>& i_txFailLanes, + const std::vector<uint8_t>& i_rxFailLanes) +{ + fapi2::current_err = fapi2::FAPI2_RC_SUCCESS; + + // Execute the Accessor HWP to write the fail lanes to Field VPD + FAPI_TRY( p9_io_erepairSetFailedLanesHwp( + i_endp_target, + EREPAIR::EREPAIR_VPD_FIELD, + i_clkGroup, + i_txFailLanes, + i_rxFailLanes), + "erepairSetFieldFailedLanes() from Accessor HWP failed w/rc=0x%x", + (uint64_t)fapi2::current_err ); + +fapi_try_exit: + return fapi2::current_err; +} + +/** + * @brief: This function reads the field VPD data to check if there is any + * eRepair data. This function will be called during Mnfg mode IPL + * during which we need to make sure that the Field VPD is clear. + * The Field VPD needs to be clear to enable customers to have + * eRepair capability. + * + * @param [in] i_endp1_target Target of one end the connecting bus + * @param [in] i_endp2_target Target of the other end of the connecting bus + * The VPD of the passed targets are read for + * checking the VPD contents + * @param[in] i_clkGroup Specifies clock group 0:[XOA, X1A,..] 1:[X0B, X1B,..] + * + * @return ReturnCode + */ +template<fapi2::TargetType K, fapi2::TargetType J> +fapi2::ReturnCode mnfgCheckFieldVPD( + const fapi2::Target < K >& i_endp1_target, + const fapi2::Target < J >& i_endp2_target, + const uint8_t i_clkGroup) +{ + fapi2::current_err = fapi2::FAPI2_RC_SUCCESS; + std::vector<uint8_t> l_endp1_txFaillanes; + std::vector<uint8_t> l_endp1_rxFaillanes; + std::vector<uint8_t> l_endp2_txFaillanes; + std::vector<uint8_t> l_endp2_rxFaillanes; + bool l_fieldVPDClear = true; + + l_fieldVPDClear = true; + + /***** Read Field VPD *****/ + + // During Mfg mode IPL, field VPD need to be clear. + + // Get failed lanes for endp1 + FAPI_TRY( erepairGetFieldFailedLanes( + i_endp1_target, + i_clkGroup, + l_endp1_txFaillanes, + l_endp1_rxFaillanes), + "erepairGetFieldFailedLanes endp1 target failed w/rc=0x%x", + (uint64_t)fapi2::current_err ); + + // If there are fail lanes in Field VPD on endpoint1, create an + // error log and return + if(l_endp1_txFaillanes.size() || + l_endp1_rxFaillanes.size()) + { + l_fieldVPDClear = false; + FAPI_DBG("mnfgCheckFieldVPD: eRepair records found in Field VPD in Tx during Manufacturing mode IPL"); + } + + // Get failed lanes for endp2 + FAPI_TRY( erepairGetFieldFailedLanes( + i_endp2_target, + i_clkGroup, + l_endp2_txFaillanes, + l_endp2_rxFaillanes), + "erepairGetFieldFailedLanes endp2 target failed w/rc=0x%x", + (uint64_t)fapi2::current_err ); + + // If there are fail lanes in Field VPD on endpoint2, create an + // error log and return + if(l_endp2_txFaillanes.size() || + l_endp2_rxFaillanes.size()) + { + l_fieldVPDClear = false; + FAPI_DBG("mnfgCheckFieldVPD: eRepair records found in Field VPD in Rx during Manufacturing mode IPL"); + } + + FAPI_ASSERT(l_fieldVPDClear == true, + fapi2::P9_EREPAIR_RESTORE_FIELD_VPD_NOT_CLEAR() + .set_TARGET1(i_endp1_target) + .set_TARGET2(i_endp2_target), + "ERROR: mnfgCheckFieldVPD: Field VPD need to be clear during Mnfg mode IPL"); + +fapi_try_exit: + return fapi2::current_err; +} /** * @brief FW Team Utility function that gets eRepair data @@ -115,7 +445,292 @@ fapi2::ReturnCode erepairGetMnfgFailedLanes( const fapi2::Target < K >& i_endp_target, const uint8_t i_clkGroup, std::vector<uint8_t>& o_txFailLanes, - std::vector<uint8_t>& o_rxFailLanes); + std::vector<uint8_t>& o_rxFailLanes) +{ + fapi2::current_err = fapi2::FAPI2_RC_SUCCESS; + + FAPI_DBG(">> erepairGetMnfgFailedLanes"); + + // Execute the Accessor HWP to retrieve the failed lanes from the VPD + FAPI_TRY( p9_io_erepairGetFailedLanesHwp( + i_endp_target, + EREPAIR::EREPAIR_VPD_MNFG, + i_clkGroup, + o_txFailLanes, + o_rxFailLanes), + "erepairGetMnfgFailedLanes() from Accessor HWP failed w/rc=0x%x", + (uint64_t)fapi2::current_err ); + +fapi_try_exit: + return fapi2::current_err; +} + +/** + * @brief FW Team Utility function that sets eRepair data in Manufacturing VPD + * + * This is a wrapper function for the Accessor HWP which writes failed lane + * numbers to the Manufacturing VPD + * + * @param[in] i_endp_target Reference to X-Bus or O-Bus or MCS or memBuf Target + * @param[in] i_clkGroup Specifies clock group 0:[XOA, X1A,..] 1:[X0B, X1B,..] + * @param[in] i_txFailLanes Vector that will contain the fail lane + * to be written to Mnfg VPD for Drive side + * @param[in] i_rxFailLanes Vector that will contain the fail lanes + * to be written to Mnfg VPD for Receive side + * + * @return ReturnCode + */ +template<fapi2::TargetType K> +fapi2::ReturnCode erepairSetMnfgFailedLanes( + const fapi2::Target < K >& i_endp_target, + const uint8_t i_clkGroup, + const std::vector<uint8_t>& i_txFailLanes, + const std::vector<uint8_t>& i_rxFailLanes) +{ + fapi2::current_err = fapi2::FAPI2_RC_SUCCESS; + + // Execute the Accessor HWP to write the fail lanes to Mnfg VPD + FAPI_TRY( p9_io_erepairSetFailedLanesHwp( + i_endp_target, + EREPAIR::EREPAIR_VPD_MNFG, + i_clkGroup, + i_txFailLanes, + i_rxFailLanes), + "erepairSetMnfgFailedLanes() from Accessor HWP failed w/rc=0x%x", + (uint64_t)fapi2::current_err ); + +fapi_try_exit: + return fapi2::current_err; +} + +/** + * @brief: This Function reads the specified VPD (Mnfg or Field) of the passed + * targets and verifies whether there are matching eRepair records. + * The matching eRepair lanes are returned in the passed references + * for vectors. + * + * @param [in] i_endp1_target Target of one end the connecting bus + * @param [in] i_endp2_target Target of the other end of the connecting + * bus + * @param[in] i_clkGroup Specifies clock group 0:[XOA, X1A,..] 1:[X0B, X1B,..] + * @param [out] o_endp1_txFaillanes Reference to vector which will have fail + * lane numbers on Tx side of target passed + * as first param + * @param [out] o_endp1_rxFaillanes Reference to vector which will have fail + * lane numbers on Rx side of target passed + * as first param + * @param [out] o_endp2_txFaillanes Reference to vector which will have fail + * lane numbers on Tx side of target passed + * as fourth param + * @param [out] o_endp2_rxFaillanes Reference to vector which will have fail + * lane numbers on Rx side of target passed + * as fourth param + * @param[in] i_clkGroup Specifies clock group 0:[XOA, X1A,..] 1:[X0B, X1B,..] + * @param [in] i_vpdType Indicates whether to read Mnfg VPD or + * Field VPD + * + * @return ReturnCode + */ +template<fapi2::TargetType K, fapi2::TargetType J> +fapi2::ReturnCode getVerifiedRepairLanes( + const fapi2::Target < K >& i_endp1_target, + const fapi2::Target < J >& i_endp2_target, + const uint8_t i_clkGroup, + std::vector<uint8_t>& o_endp1_txFaillanes, + std::vector<uint8_t>& o_endp1_rxFaillanes, + std::vector<uint8_t>& o_endp2_txFaillanes, + std::vector<uint8_t>& o_endp2_rxFaillanes, + const EREPAIR::erepairVpdType i_vpdType) +{ + fapi2::current_err = fapi2::FAPI2_RC_SUCCESS; + + getLanes_t<K> l_getLanes = NULL; + setLanes_t<K> l_setLanes = NULL; + + fapi2::Target < K > l_target[2] = {i_endp1_target, i_endp2_target}; + bool l_invalidFails_inTx_OfTgt[2] = {false, false}; + bool l_invalidFails_inRx_OfTgt[2] = {false, false}; + uint8_t l_tgtIndx = 0; + + std::vector<uint8_t> l_emptyVector; + std::vector<uint8_t> l_txFaillanes; + std::vector<uint8_t> l_rxFaillanes; + + FAPI_INF(">> getVerifiedRepairLanes: vpdType: %s", + i_vpdType == EREPAIR::EREPAIR_VPD_FIELD ? "Field" : "Mnfg"); + + /***** Read VPD *****/ + + if(i_vpdType == EREPAIR::EREPAIR_VPD_FIELD) + { + l_getLanes = &erepairGetFieldFailedLanes; + l_setLanes = &erepairSetFieldFailedLanes; + } + else if(i_vpdType == EREPAIR::EREPAIR_VPD_MNFG) + { + l_getLanes = &erepairGetMnfgFailedLanes; + l_setLanes = &erepairSetMnfgFailedLanes; + } + + for(l_tgtIndx = 0; l_tgtIndx < 2; l_tgtIndx++) + { + // Get failed lanes for endp1 and endp2 + FAPI_TRY( l_getLanes( + l_target[l_tgtIndx], + i_clkGroup, + l_txFaillanes, + l_rxFaillanes), + "getVerifiedRepairLanes() from Accessor HWP failed w/rc=0x%x", + (uint64_t)fapi2::current_err ); + + if(l_tgtIndx == 0) + { + o_endp1_txFaillanes = l_txFaillanes; + o_endp1_rxFaillanes = l_rxFaillanes; + } + else + { + o_endp2_txFaillanes = l_txFaillanes; + o_endp2_rxFaillanes = l_rxFaillanes; + } + + l_txFaillanes.clear(); + l_rxFaillanes.clear(); + } // end of for(l_tgtIndx) + + // Check if matching fail lanes exists on the sub-interfaces + // connecting the two end points + if(o_endp1_txFaillanes.size() || o_endp2_rxFaillanes.size()) + { + invalidateNonMatchingFailLanes(o_endp1_txFaillanes, + o_endp2_rxFaillanes, + l_invalidFails_inTx_OfTgt[0], + l_invalidFails_inRx_OfTgt[1]); + } + + if(o_endp2_txFaillanes.size() || o_endp1_rxFaillanes.size()) + { + invalidateNonMatchingFailLanes(o_endp2_txFaillanes, + o_endp1_rxFaillanes, + l_invalidFails_inTx_OfTgt[1], + l_invalidFails_inRx_OfTgt[0]); + } + + /***** Correct eRepair data of endp1 in VPD *****/ + + for(l_tgtIndx = 0; l_tgtIndx < 2; l_tgtIndx++) + { + if(l_tgtIndx == 0) + { + l_txFaillanes = o_endp1_txFaillanes; + l_rxFaillanes = o_endp1_rxFaillanes; + } + else + { + l_txFaillanes = o_endp2_txFaillanes; + l_rxFaillanes = o_endp2_rxFaillanes; + } + + // Update endp1 and endp2 VPD to invalidate fail lanes that do + // not have matching fail lanes on the other end + if(l_invalidFails_inTx_OfTgt[l_tgtIndx] && + l_invalidFails_inRx_OfTgt[l_tgtIndx]) + { + FAPI_TRY( l_setLanes( + l_target[l_tgtIndx], + i_clkGroup, + l_txFaillanes, + l_rxFaillanes), + "getVerifiedRepairLanes() tx/rx from Accessor HWP failed w/rc=0x%x", + (uint64_t)fapi2::current_err ); + } + else if(l_invalidFails_inTx_OfTgt[l_tgtIndx]) + { + FAPI_TRY( l_setLanes( + l_target[l_tgtIndx], + i_clkGroup, + l_txFaillanes, + l_emptyVector), + "getVerifiedRepairLanes() tx from Accessor HWP failed w/rc=0x%x", + (uint64_t)fapi2::current_err ); + } + else if(l_invalidFails_inRx_OfTgt[l_tgtIndx]) + { + FAPI_TRY( l_setLanes( + l_target[l_tgtIndx], + i_clkGroup, + l_emptyVector, + l_rxFaillanes), + "getVerifiedRepairLanes() rx from Accessor HWP failed w/rc=0x%x", + (uint64_t)fapi2::current_err ); + } + } // end of for loop + +fapi_try_exit: + return fapi2::current_err; +} + +/** + * @brief FW Team Utility function that gets eRepair data from the VPD + * This function gets the eRepair data from both the Field VPD + * and the Manufacturing VPD. + * + * @param[in] i_endp_target Reference to X-Bus or O-Bus or MCS or memBuf Target + * @param[in] i_clkGroup Specifies clock group 0:[XOA, X1A,..] 1:[X0B, X1B,..] + * @param[out] o_txFailLanes Reference to a Vector that will contain the fail + * lanes read from the VPD for Drive side + * @param[out] o_rxFailLanes Reference to a Vector that will contain the fail + * lanes read from the VPD for Receive side + * @return ReturnCode + * + */ +template<fapi2::TargetType K> +fapi2::ReturnCode erepairGetFailedLanes( + const fapi2::Target < K >& i_endp_target, + const uint8_t i_clkGroup, + std::vector<uint8_t>& o_txFailLanes, + std::vector<uint8_t>& o_rxFailLanes) +{ + fapi2::current_err = fapi2::FAPI2_RC_SUCCESS; + std::vector<uint8_t> l_txFailLanes; + std::vector<uint8_t> l_rxFailLanes; + std::vector<uint8_t>::iterator l_it; + + FAPI_INF(">> erepairGetFailedLaness"); + + // Get the erepair lanes from Field VPD + FAPI_TRY( erepairGetFieldFailedLanes( + i_endp_target, + i_clkGroup, + l_txFailLanes, + l_rxFailLanes), + "erepairGetFieldFailedLanes() failed w/rc=0x%x", + (uint64_t)fapi2::current_err ); + + o_txFailLanes = l_txFailLanes; + o_rxFailLanes = l_rxFailLanes; + + // Get the erepair lanes from Manufacturing VPD + l_txFailLanes.clear(); + l_rxFailLanes.clear(); + FAPI_TRY( erepairGetMnfgFailedLanes( + i_endp_target, + i_clkGroup, + l_txFailLanes, + l_rxFailLanes), + "erepairGetMnfgFailedLanes() failed w/rc=0x%x", + (uint64_t)fapi2::current_err ); + + // Merge the Mnfg lanes with the Field lanes + l_it = o_txFailLanes.end(); + o_txFailLanes.insert(l_it, l_txFailLanes.begin(), l_txFailLanes.end()); + + l_it = o_rxFailLanes.end(); + o_rxFailLanes.insert(l_it, l_rxFailLanes.begin(), l_rxFailLanes.end()); + +fapi_try_exit: + return fapi2::current_err; +} /** * @brief FW Team Utility function that sets eRepair data in the VPD. @@ -131,9 +746,9 @@ fapi2::ReturnCode erepairGetMnfgFailedLanes( * @param[in] i_rxEndp_target Reference to X-Bus or O-Bus or MCS or memBuf * Target. This is the target on which the * badlanes were found + * @param[in] i_clkGroup Specifies clock group 0:[XOA, X1A,..] 1:[X0B, X1B,..] * @param[in] i_rxFailLanes Vector that will contain the fail lanes * to be written to VPD for Receive side - * @param[in] i_clkGroup Specifies clock group 0:[XOA, X1A,..] 1:[X0B, X1B,..] * @param[out] o_thresholdExceed If TRUE, indicates that the eRepair threshold * has exceeded, FALSE otherwise. * @@ -145,51 +760,137 @@ fapi2::ReturnCode erepairSetFailedLanes( const fapi2::Target < J >& i_rxEndp_target, const uint8_t i_clkGroup, const std::vector<uint8_t>& i_rxFailLanes, - bool& o_thresholdExceed); + bool& o_thresholdExceed) +{ + fapi2::current_err = fapi2::FAPI2_RC_SUCCESS; + uint64_t l_allMnfgFlags = 0; + bool l_mnfgModeIPL = false; + uint8_t l_threshold = 0; + setLanes_t<K> l_setLanes = NULL; + getLanes_t<K> l_getLanes = NULL; + std::vector<uint8_t> l_txFaillanes; + std::vector<uint8_t> l_rxFaillanes; + std::vector<uint8_t> l_emptyVector; + std::vector<uint8_t> l_throwAway; -/** - * @brief FW Team Utility function that sets eRepair data in Field VPD - * - * This is a wrapper function for the Accessor HWP which writes failed lane - * numbers to the Field VPD - * - * @param[in] i_endp_target Reference to X-Bus or O-Bus or MCS or memBuf Target - * @param[in] i_clkGroup Specifies clock group 0:[XOA, X1A,..] 1:[X0B, X1B,..] - * @param[in] i_txFailLanes Vector that will contain the fail lane - * to be written to Field VPD for Drive side - * @param[in] i_rxFailLanes Vector that will contain the fail lanes - * to be written to Field VPD for Receive side - * - * @return ReturnCode - */ -template<fapi2::TargetType K> -fapi2::ReturnCode erepairSetFieldFailedLanes( - const fapi2::Target < K >& i_endp_target, - const uint8_t i_clkGroup, - const std::vector<uint8_t>& i_txFailLanes, - const std::vector<uint8_t>& i_rxFailLanes); + FAPI_INF(">> erepairSetFailedLanes"); -/** - * @brief FW Team Utility function that sets eRepair data in Manufacturing VPD - * - * This is a wrapper function for the Accessor HWP which writes failed lane - * numbers to the Manufacturing VPD - * - * @param[in] i_endp_target Reference to X-Bus or O-Bus or MCS or memBuf Target - * @param[in] i_clkGroup Specifies clock group 0:[XOA, X1A,..] 1:[X0B, X1B,..] - * @param[in] i_txFailLanes Vector that will contain the fail lane - * to be written to Mnfg VPD for Drive side - * @param[in] i_rxFailLanes Vector that will contain the fail lanes - * to be written to Mnfg VPD for Receive side - * - * @return ReturnCode - */ -template<fapi2::TargetType K> -fapi2::ReturnCode erepairSetMnfgFailedLanes( - const fapi2::Target < K >& i_endp_target, - const uint8_t i_clkGroup, - const std::vector<uint8_t>& i_txFailLanes, - const std::vector<uint8_t>& i_rxFailLanes); + o_thresholdExceed = false; + + // Get the Manufacturing Policy flags + FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_MNFG_FLAGS, + fapi2::Target<fapi2::TARGET_TYPE_SYSTEM>(), + l_allMnfgFlags), + "erepairSetFailedLanes: Unable to read attribute ATTR_MNFG_FLAGS"); + + // Check if this is a Mnfg mode IPL + if(l_allMnfgFlags & fapi2::ENUM_ATTR_MNFG_FLAGS_MNFG_THRESHOLDS) + { + l_mnfgModeIPL = true; + } + + if(l_mnfgModeIPL) + { + l_setLanes = &erepairSetMnfgFailedLanes; + l_getLanes = &erepairGetMnfgFailedLanes; + } + else + { + l_setLanes = &erepairSetFieldFailedLanes; + l_getLanes = &erepairGetFieldFailedLanes; + } + + /*** Check if we have crossed the repair threshold ***/ + // Get the eRepair threshold limit + l_threshold = 0; + FAPI_TRY( geteRepairThreshold( + i_rxEndp_target, + l_mnfgModeIPL, + l_threshold), + "geteRepairThreshold() from Accessor HWP failed w/rc=0x%x", + (uint64_t)fapi2::current_err ); + + // Check if the new fails have crossed the threshold + if(i_rxFailLanes.size() > l_threshold) + { + o_thresholdExceed = true; + goto fapi_try_exit; + } + + // Get existing fail lanes that are in the VPD of rx endpoint + FAPI_TRY( l_getLanes( + i_rxEndp_target, + i_clkGroup, + l_throwAway, + l_rxFaillanes), + "rx l_getLanes() from Accessor HWP failed w/rc=0x%x", + (uint64_t)fapi2::current_err ); + + // Get existing fail lanes that are in the VPD of tx endpoint + FAPI_TRY( l_getLanes( + i_txEndp_target, + i_clkGroup, + l_txFaillanes, + l_throwAway), + "tx l_getLanes() from Accessor HWP failed w/rc=0x%x", + (uint64_t)fapi2::current_err ); + + // Lets combine the new and old fail lanes of Rx side + l_rxFaillanes.insert(l_rxFaillanes.end(), + i_rxFailLanes.begin(), + i_rxFailLanes.end()); + + // Remove duplicate lanes if any on the Rx side + std::sort(l_rxFaillanes.begin(), l_rxFaillanes.end()); + + l_rxFaillanes.erase(std::unique(l_rxFaillanes.begin(), + l_rxFaillanes.end()), + l_rxFaillanes.end()); + + // Lets combine the new and old fail lanes of Tx side + l_txFaillanes.insert(l_txFaillanes.end(), + i_rxFailLanes.begin(), + i_rxFailLanes.end()); + + // Remove duplicate lanes if any on the Tx side + std::sort(l_txFaillanes.begin(), l_txFaillanes.end()); + + l_txFaillanes.erase(std::unique(l_txFaillanes.begin(), + l_txFaillanes.end()), + l_txFaillanes.end()); + + // Check if the sum of old and new fail lanes have crossed the threshold + if((l_txFaillanes.size() > l_threshold) || + (l_rxFaillanes.size() > l_threshold)) + { + o_thresholdExceed = true; + goto fapi_try_exit; + } + + /*** Update the VPD ***/ + + // Lets write the VPD of endpoint1 with faillanes on Rx side + FAPI_TRY( l_setLanes( + i_rxEndp_target, + i_clkGroup, + l_emptyVector, + l_rxFaillanes), + "rx l_setLanes() from Accessor HWP failed w/rc=0x%x", + (uint64_t)fapi2::current_err ); + + // Lets write the VPD of endpoint2 with faillanes on Tx side + FAPI_TRY( l_setLanes( + i_txEndp_target, + i_clkGroup, + l_txFaillanes, + l_emptyVector), + "tx l_setLanes() from Accessor HWP failed w/rc=0x%x", + (uint64_t)fapi2::current_err ); + +fapi_try_exit: + FAPI_INF("<< erepairSetFailedLanes"); + return fapi2::current_err; +} /** * @brief Function which retrieves the lanes that need to be restored for the @@ -233,9 +934,294 @@ fapi2::ReturnCode erepairGetRestoreLanes( const fapi2::Target < K >& i_endp1_target, const fapi2::Target < J >& i_endp2_target, const uint8_t i_clkGroup, - std::vector<uint8_t>& o_endp1_txFaillanes, - std::vector<uint8_t>& o_endp1_rxFaillanes, - std::vector<uint8_t>& o_endp2_txFaillanes, - std::vector<uint8_t>& o_endp2_rxFaillanes); + std::vector<uint8_t>& o_endp1_txFaillanes, + std::vector<uint8_t>& o_endp1_rxFaillanes, + std::vector<uint8_t>& o_endp2_txFaillanes, + std::vector<uint8_t>& o_endp2_rxFaillanes) +{ + fapi2::ReturnCode l_rc = fapi2::FAPI2_RC_SUCCESS; + fapi2::current_err = fapi2::FAPI2_RC_SUCCESS; + + std::vector<uint8_t> l_endp1_txFieldFaillanes; + std::vector<uint8_t> l_endp1_rxFieldFaillanes; + std::vector<uint8_t> l_endp1_txMnfgFaillanes; + std::vector<uint8_t> l_endp1_rxMnfgFaillanes; + + std::vector<uint8_t> l_endp2_txFieldFaillanes; + std::vector<uint8_t> l_endp2_rxFieldFaillanes; + std::vector<uint8_t> l_endp2_txMnfgFaillanes; + std::vector<uint8_t> l_endp2_rxMnfgFaillanes; + + bool l_mnfgModeIPL = false; + bool l_enableDmiSpares = false; + bool l_enableFabricSpares = false; + bool l_disableFabricERepair = false; + bool l_disableMemoryERepair = false; + bool l_thresholdExceed = false; + uint8_t l_threshold = 0; + uint64_t l_allMnfgFlags = 0; + uint32_t l_numTxFailLanes = 0; + uint32_t l_numRxFailLanes = 0; + fapi2::TargetType l_endp1_tgtType = fapi2::TARGET_TYPE_NONE; + fapi2::TargetType l_endp2_tgtType = fapi2::TARGET_TYPE_NONE; + + FAPI_INF(">>erepairGetRestoreLanes"); + + FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_MNFG_FLAGS, + fapi2::Target<fapi2::TARGET_TYPE_SYSTEM>(), + l_allMnfgFlags)); + + // Check if MNFG_DISABLE_FABRIC_EREPAIR is enabled + l_disableFabricERepair = false; + + if(l_allMnfgFlags & + fapi2::ENUM_ATTR_MNFG_FLAGS_MNFG_DISABLE_FABRIC_eREPAIR) + { + l_disableFabricERepair = true; + } + + // Check if MNFG_DISABLE_MEMORY_EREPAIR is enabled + l_disableMemoryERepair = false; + + if(l_allMnfgFlags & + fapi2::ENUM_ATTR_MNFG_FLAGS_MNFG_DISABLE_MEMORY_eREPAIR) + { + l_disableMemoryERepair = true; + } + + // Check if this is Manufacturing mode IPL. + l_mnfgModeIPL = false; + + if(l_allMnfgFlags & fapi2::ENUM_ATTR_MNFG_FLAGS_MNFG_THRESHOLDS) + { + l_mnfgModeIPL = true; + } + + // Get the type of passed targets + l_endp1_tgtType = i_endp1_target.getType(); + l_endp2_tgtType = i_endp2_target.getType(); + + // Check if the correct target types are passed + if(l_endp1_tgtType == fapi2::TARGET_TYPE_XBUS_ENDPOINT || + l_endp1_tgtType == fapi2::TARGET_TYPE_OBUS) + { + FAPI_ASSERT(l_endp1_tgtType == l_endp2_tgtType, + fapi2::P9_EREPAIR_RESTORE_INVALID_TARGET_PAIR() + .set_TARGET1(l_endp1_tgtType) + .set_TARGET2(l_endp2_tgtType), + "ERROR:erepairGetRestoreLanes: Invalid endpoint target pair"); + + // Check for enablement of Fabric eRepair + if(l_mnfgModeIPL && l_disableFabricERepair) + { + // Fabric eRepair has been disabled using the + // Manufacturing policy flags + FAPI_INF("erepairGetRestoreLanes: Fabric eRepair is disabled"); + goto fapi_try_exit; + } + } + else if(l_endp1_tgtType == fapi2::TARGET_TYPE_MEMBUF_CHIP || + l_endp1_tgtType == fapi2::TARGET_TYPE_DMI) + { + FAPI_ASSERT( ((l_endp1_tgtType == fapi2::TARGET_TYPE_MEMBUF_CHIP) && + (l_endp2_tgtType == fapi2::TARGET_TYPE_DMI)) || + ((l_endp1_tgtType == fapi2::TARGET_TYPE_DMI) && + (l_endp2_tgtType == fapi2::TARGET_TYPE_MEMBUF_CHIP)), + fapi2::P9_EREPAIR_RESTORE_INVALID_TARGET_PAIR() + .set_TARGET1(l_endp1_tgtType) + .set_TARGET2(l_endp2_tgtType), + "ERROR:erepairGetRestoreLanes: Invalid endpoint target pair"); + + // Check for enablement of Memory eRepair + if(l_mnfgModeIPL && l_disableMemoryERepair) + { + // Memory eRepair has been disabled using the + // Manufacturing policy flags + FAPI_INF("erepairGetRestoreLanes: Memory eRepair is disabled"); + goto fapi_try_exit; + } + } + + if(l_mnfgModeIPL) + { + /***** Check Field VPD *****/ + + // Do not allow eRepair data in Field VPD during Mfg Mode IPL + l_rc = mnfgCheckFieldVPD(i_endp1_target, + i_endp2_target, + i_clkGroup); + + if(l_rc) + { + FAPI_DBG("erepairGetRestoreLanes:Error from mnfgCheckFieldVPD"); + fapi2::current_err = l_rc; + goto fapi_try_exit; + } + + /***** Read Manufacturing VPD *****/ + FAPI_TRY( getVerifiedRepairLanes( + i_endp1_target, + i_endp2_target, + i_clkGroup, + o_endp1_txFaillanes, + o_endp1_rxFaillanes, + o_endp2_txFaillanes, + o_endp2_rxFaillanes, + EREPAIR::EREPAIR_VPD_MNFG), + "getVerifiedRepairLanes(Mnfg) mnfg mode ipl failed w/rc=0x%x", + (uint64_t)fapi2::current_err ); + } + else + { + /***** Normal Mode IPL *****/ + // During Normal mode IPL we read both Mnfg and Field VPD + // for restoring eRepair lanes + + /***** Read Manufacturing VPD *****/ + FAPI_TRY( getVerifiedRepairLanes( + i_endp1_target, + i_endp2_target, + i_clkGroup, + l_endp1_txMnfgFaillanes, + l_endp1_rxMnfgFaillanes, + l_endp2_txMnfgFaillanes, + l_endp2_rxMnfgFaillanes, + EREPAIR::EREPAIR_VPD_MNFG), + "getVerifiedRepairLanes(Mnfg) normal mode ipl failed w/rc=0x%x", + (uint64_t)fapi2::current_err ); + + /***** Read Field VPD *****/ + FAPI_TRY( getVerifiedRepairLanes( + i_endp1_target, + i_endp2_target, + i_clkGroup, + l_endp1_txFieldFaillanes, + l_endp1_rxFieldFaillanes, + l_endp2_txFieldFaillanes, + l_endp2_rxFieldFaillanes, + EREPAIR::EREPAIR_VPD_FIELD), + "getVerifiedRepairLanes(Field) normal mode ipl failed w/rc=0x%x", + (uint64_t)fapi2::current_err ); + + /***** Combine the Mnfg and Field eRepair lanes *****/ + + // Combine the Tx side fail lanes of endp1 + combineFieldandMnfgLanes(l_endp1_txMnfgFaillanes, + l_endp1_txFieldFaillanes, + o_endp1_txFaillanes); + + // Combine the Rx side fail lanes of endp1 + combineFieldandMnfgLanes(l_endp1_rxMnfgFaillanes, + l_endp1_rxFieldFaillanes, + o_endp1_rxFaillanes); + + // Combine the Tx side fail lanes of endp2 + combineFieldandMnfgLanes(l_endp2_txMnfgFaillanes, + l_endp2_txFieldFaillanes, + o_endp2_txFaillanes); + + // Combine the Rx side fail lanes of endp1 + combineFieldandMnfgLanes(l_endp2_rxMnfgFaillanes, + l_endp2_rxFieldFaillanes, + o_endp2_rxFaillanes); + + } // end of else block of "if(l_mnfgModeIPL)" + + + /***** Check for threshold exceed conditions *****/ + + // Get the eRepair threshold limit + l_threshold = 0; + FAPI_TRY( geteRepairThreshold( + i_endp1_target, + l_mnfgModeIPL, + l_threshold), + "geteRepairThreshold() failed w/rc=0x%x", + (uint64_t)fapi2::current_err ); + + // Check if the eRepair threshold has exceeded for Tx side of endp1 + if(o_endp1_txFaillanes.size() > l_threshold) + { + l_thresholdExceed = true; + l_numTxFailLanes = o_endp1_txFaillanes.size(); + + FAPI_DBG("erepairGetRestoreLanes: eRepair threshold exceed error" + " seen in Tx of endp1 target. No.of lanes: %d", l_numTxFailLanes); + } + + // Check if the eRepair threshold has exceeded for Rx side of endp1 + if(o_endp1_rxFaillanes.size() > l_threshold) + { + l_thresholdExceed = true; + l_numRxFailLanes = o_endp1_rxFaillanes.size(); + + FAPI_DBG("erepairGetRestoreLanes: eRepair threshold exceed error" + " seen in Rx of endp1 target. No.of lanes: %d", l_numRxFailLanes); + } + + // Check if the eRepair threshold has exceeded for Tx side of endp2 + if(o_endp2_txFaillanes.size() > l_threshold) + { + l_thresholdExceed = true; + l_numTxFailLanes = o_endp2_txFaillanes.size(); + + FAPI_DBG("erepairGetRestoreLanes: eRepair threshold exceed error" + " seen in Tx of endp2 target. No.of lanes: %d", + l_numTxFailLanes); + } + + // Check if the eRepair threshold has exceeded for Rx side of endp2 + if(o_endp2_rxFaillanes.size() > l_threshold) + { + l_thresholdExceed = true; + l_numRxFailLanes = o_endp2_rxFaillanes.size(); + + FAPI_DBG("erepairGetRestoreLanes: eRepair threshold exceed error" + " seen in Rx of endp2 target. No.of lanes: %d", + l_numRxFailLanes); + } + + FAPI_ASSERT(l_thresholdExceed == false, + fapi2::P9_EREPAIR_THRESHOLD_EXCEED() + .set_TX_NUM_LANES(l_numTxFailLanes) + .set_RX_NUM_LANES(l_numTxFailLanes) + .set_THRESHOLD(l_threshold), + "ERROR:The threshold limit for eRepair has been crossed"); + + if(l_mnfgModeIPL) + { + // Check if MNFG_DMI_DEPLOY_LANE_SPARES is enabled + l_enableDmiSpares = false; + + if(l_allMnfgFlags & + fapi2::ENUM_ATTR_MNFG_FLAGS_MNFG_DMI_DEPLOY_LANE_SPARES) + { + l_enableDmiSpares = true; + } + + // Check if MNFG_FABRIC_DEPLOY_LANE_SPARES is enabled + l_enableFabricSpares = false; + + if(l_allMnfgFlags & + fapi2::ENUM_ATTR_MNFG_FLAGS_MNFG_FABRIC_DEPLOY_LANE_SPARES) + { + l_enableFabricSpares = true; + } + + if(l_enableDmiSpares || l_enableFabricSpares) + { + // This is a Corner testing IPL. + // eRepair Restore the pre-determined memory lanes + getCornerTestingLanes(i_endp1_target, + o_endp1_txFaillanes, + o_endp1_rxFaillanes, + o_endp2_txFaillanes, + o_endp2_rxFaillanes); + } + } // end of if(l_mnfgModeIPL) + +fapi_try_exit: + return fapi2::current_err; +} #endif diff --git a/src/import/chips/p9/procedures/hwp/io/p9_io_erepairConsts.H b/src/import/chips/p9/procedures/hwp/io/p9_io_erepairConsts.H index 024beab69..134714929 100755 --- a/src/import/chips/p9/procedures/hwp/io/p9_io_erepairConsts.H +++ b/src/import/chips/p9/procedures/hwp/io/p9_io_erepairConsts.H @@ -5,7 +5,7 @@ /* */ /* OpenPOWER HostBoot Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2015,2017 */ +/* Contributors Listed Below - COPYRIGHT 2015,2018 */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -174,4 +174,46 @@ struct eRepairMemBus uint32_t failBit : 24; // Bit stream value: Bit 0:Lane 0; Bit 1:Lane 1 ... }; +/** + * @brief This function combines the eRepair lane numbers read from + * Manufacturing VPD and Field VPD + * + * @param [in] i_mnfgFaillanes The eRepair lane numbers read from the + * Manufacturing VPD + * @param [in] i_fieldFaillanes The eRepair lane numbers read from the + * Field VPD + * @param [out] o_allFaillanes The eRepair lane numbers which is the union + * of the Field and Manufacturing eRepair lanes + * passed as first iand second params + * + * @return void + */ +void combineFieldandMnfgLanes(std::vector<uint8_t>& i_mnfgFaillanes, + std::vector<uint8_t>& i_fieldFaillanes, + std::vector<uint8_t>& o_allFailLanes); + + +/** + * @brief This function checks to see if the passed vectors have matching + * fail lane numbers. If no matching lane number is found, such lane + * value will be invalidated in the vector + * + * @param [in] io_endp1_txFaillanes Reference to vector which has fail + * lane numbers of Tx side + * @param [in] io_endp2_rxFaillanes Reference to vector which has fail + * lane numbers of Rx side + * @param [out] o_invalidFails_inTx_Ofendp1 If TRUE, indicates that Tx has fail + * lane numbers for which there is no + * matching entry on Rx side + * @param [out] o_invalidFails_inRx_Ofendp2 If TRUE, indicates that Tx has fail + * lane numbers for which there is no + * matching entry on Tx side + * + * @return void + */ +void invalidateNonMatchingFailLanes(std::vector<uint8_t>& io_endp1_txFaillanes, + std::vector<uint8_t>& io_endp2_rxFaillanes, + bool& o_invalidFails_inTx_Ofendp1, + bool& o_invalidFails_inRx_Ofendp2); + #endif diff --git a/src/import/chips/p9/procedures/hwp/io/p9_io_erepairGetFailedLanesHwp.C b/src/import/chips/p9/procedures/hwp/io/p9_io_erepairGetFailedLanesHwp.C deleted file mode 100755 index 8f89f58ec..000000000 --- a/src/import/chips/p9/procedures/hwp/io/p9_io_erepairGetFailedLanesHwp.C +++ /dev/null @@ -1,688 +0,0 @@ -/* IBM_PROLOG_BEGIN_TAG */ -/* This is an automatically generated prolog. */ -/* */ -/* $Source: src/import/chips/p9/procedures/hwp/io/p9_io_erepairGetFailedLanesHwp.C $ */ -/* */ -/* OpenPOWER HostBoot Project */ -/* */ -/* Contributors Listed Below - COPYRIGHT 2015,2017 */ -/* [+] International Business Machines Corp. */ -/* */ -/* */ -/* Licensed under the Apache License, Version 2.0 (the "License"); */ -/* you may not use this file except in compliance with the License. */ -/* You may obtain a copy of the License at */ -/* */ -/* http://www.apache.org/licenses/LICENSE-2.0 */ -/* */ -/* Unless required by applicable law or agreed to in writing, software */ -/* distributed under the License is distributed on an "AS IS" BASIS, */ -/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */ -/* implied. See the License for the specific language governing */ -/* permissions and limitations under the License. */ -/* */ -/* IBM_PROLOG_END_TAG */ -/// -/// @file p9_io_erepairGetFailedLanesHwp.C -/// @brief FW Team HWP that accesses the fail lanes of Fabric and Memory buses. -/// -//---------------------------------------------------------------------------- -// *HWP HWP Owner : Chris Steffen <cwsteffen@us.ibm.com> -// *HWP HWP Backup Owner: Gary Peterson <garyp@us.ibm.com> -// *HWP FW Owner : Sumit Kumar <sumit_kumar@in.ibm.com> -// *HWP Team : IO -// *HWP Level : 2 -// *HWP Consumed by : FSP:HB -//---------------------------------------------------------------------------- -#include <fapi2.H> -#include <p9_io_erepairConsts.H> -#include <p9_io_erepairGetFailedLanesHwp.H> -#include <mvpd_access.H> - -using namespace EREPAIR; -using namespace fapi2; - -/****************************************************************************** - * Forward Declarations - *****************************************************************************/ - -/** - * @brief Function called by the FW Team HWP that reads the data from Field VPD. - * This function makes the actual calls to read the VPD - * It determines the size of the buffer to be read, allocates memory - * of the determined size, calls fapiGetMvpdField to read the eRepair - * records. This buffer is further passed to another routine for - * parsing. - * - * @param[in] i_target Reference to X-Bus or O-Bus or MCS target - * @param[in] i_vpdType Specifies which VPD (MNFG or Field) to access. - * @param[in] i_clkGroup Specifies clock group 0:[XOA, X1A,..] 1:[X0B, X1B,..] - * @param[o] o_txFailLanes Reference to a vector that will hold eRepair fail - * lane numbers of the Tx sub-interface. - * @param[o] o_rxFailLanes Reference to a vector that will hold eRepair fail - * lane numbers of the Rx sub-interface. - * - * @return ReturnCode - */ -template<fapi2::TargetType K> -fapi2::ReturnCode retrieveRepairData( - const fapi2::Target < K >& i_target, - erepairVpdType i_vpdType, - const uint8_t i_clkGroup, - std::vector<uint8_t>& o_txFailLanes, - std::vector<uint8_t>& o_rxFailLanes); - -/** - * @brief Function called by the FW Team HWP that parses the data read from - * Field VPD. This function matches each eRepair record read from the VPD - * and matches it against the attributes of the passed target. - * If a match is found, the corresponding eRepair record is copied into - * the respective failLane vectors to be returned to the caller. - * - * @param[in] i_target Reference to X-Bus or O-Bus or MCS target - * @param[in] i_buf This is the buffer that has the eRepair records - * read from the VPD - * @param[in] i_bufSz This is the size of passed buffer in terms of bytes - * @param[in] i_clkGroup Specifies clock group 0:[XOA, X1A,..] 1:[X0B, X1B,..] - * @param[o] o_txFailLanes Reference to a vector that will hold eRepair fail - * lane numbers of the Tx sub-interface. - * @param[o] o_rxFailLanes Reference to a vector that will hold eRepair fail - * lane numbers of the Rx sub-interface. - * - * @return ReturnCode - */ -template<fapi2::TargetType K> -fapi2::ReturnCode determineRepairLanes( - const fapi2::Target < K >& i_target, - uint8_t* i_buf, - uint32_t i_bufSz, - const uint8_t i_clkGroup, - std::vector<uint8_t>& o_txFailLanes, - std::vector<uint8_t>& o_rxFailLanes); - - -/** - * @brief Function to check if the system has Custom DIMM type (CDIMM). - * Attribute ATTR_EFF_CUSTOM_DIMM is read to determine the type. - * @param[in] i_target Reference to X-Bus or O-Bus or MCS target - * @param[o] o_customDimm Return value - ENUM_ATTR_EFF_CUSTOM_DIMM_NO - * or ENUM_ATTR_EFF_CUSTOM_DIMM_YES - * @return ReturnCode - */ -template<fapi2::TargetType K> -fapi2::ReturnCode getDimmType( - const fapi2::Target < K >& i_target, - uint8_t& o_customDimm); - - -/** - * @brief Function called by the HWP that parses the data read from VPD. - * This function scans through failBit field bit pattern and checks - * for all bits that are set. For bits SET the corresponding bit positions - * marks the failed lane number and is copied into - * the respective failLane vectors to be returned to the caller. - * - * @param[in] i_target Reference to X-Bus or O-Bus or MCS target type - * @param[in] i_busInterface Reference to target sub interface - * @param[in] i_failBit This is the failBit field from the eRepair records - * read from the VPD - * @param[o] o_FailLanes Reference to a vector that will hold eRepair fail - * lane numbers of the Rx/Tx sub-interface. - * - * @return ReturnCode - */ -template<fapi2::TargetType K> -fapi2::ReturnCode decodeFailedLanes( - const fapi2::Target < K >& i_target, - uint8_t i_busInterface, - uint32_t i_failBit, - std::vector<uint8_t>& o_FailLanes); - -/****************************************************************************** - * Accessor HWP - *****************************************************************************/ - -template<fapi2::TargetType K> -fapi2::ReturnCode p9_io_erepairGetFailedLanesHwp( - const fapi2::Target < K >& i_target, - erepairVpdType i_vpdType, - const uint8_t i_clkGroup, - std::vector<uint8_t>& o_txFailLanes, - std::vector<uint8_t>& o_rxFailLanes) -{ - fapi2::current_err = fapi2::FAPI2_RC_SUCCESS; - - FAPI_INF(">> erepairGetFailedLanesHwp"); - - o_txFailLanes.clear(); - o_rxFailLanes.clear(); - - // Retrieve the Field eRepair lane numbers from the VPD - FAPI_TRY( retrieveRepairData( - i_target, - i_vpdType, - i_clkGroup, - o_txFailLanes, - o_rxFailLanes), - "p9_io_erepairGetFailedLanesHwp() failed w/rc=0x%x", - (uint64_t)current_err ); - -fapi_try_exit: - return fapi2::current_err; -} - -template ReturnCode p9_io_erepairGetFailedLanesHwp<TARGET_TYPE_XBUS>( - const fapi2::Target <TARGET_TYPE_XBUS>& i_target, - erepairVpdType i_vpdType, - const uint8_t i_clkGroup, - std::vector<uint8_t>& o_txFailLanes, - std::vector<uint8_t>& o_rxFailLanes); - -template<fapi2::TargetType K> -fapi2::ReturnCode retrieveRepairData( - const fapi2::Target < K >& i_target, - erepairVpdType i_vpdType, - const uint8_t i_clkGroup, - std::vector<uint8_t>& o_txFailLanes, - std::vector<uint8_t>& o_rxFailLanes) -{ - fapi2::ReturnCode l_rc = fapi2::FAPI2_RC_SUCCESS; - fapi2::current_err = fapi2::FAPI2_RC_SUCCESS; - uint8_t* l_retBuf = NULL; - uint32_t l_bufSize = 0; - fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP> l_procTarget; -#ifdef P9_CUMULUS - uint8_t l_customDimm; -#endif - - FAPI_DBG(">> retrieveRepairData"); - - if(i_target.getType() == fapi2::TARGET_TYPE_MEMBUF_CHIP) - { -#ifdef P9_CUMULUS - fapi2::MBvpdRecord l_vpdRecord = fapi2::MBVPD_RECORD_VEIR; - - if(i_vpdType == EREPAIR_VPD_MNFG) - { - l_vpdRecord = fapi2::MBVPD_RECORD_MER0; - } - - // Determine the size of the eRepair data in the VPD - FAPI_TRY( getMBvpdField( - l_vpdRecord, - fapi2::MBVPD_KEYWORD_PDI, - i_target, - NULL, - l_bufSize), - "VPD size read failed w/rc=0x%x", - (uint64_t)current_err ); - - // Check whether we have Memory on a CDIMM - l_rc = getDimmType(i_target, l_customDimm); - - FAPI_ASSERT((uint64_t)l_rc == 0x0, - fapi2::P9_EREPAIR_DIMM_TYPE_CHECK_ERR() - .set_ERROR(l_rc), - "ERROR: DIMM type check"); - - if( (l_customDimm == fapi2::ENUM_ATTR_SPD_CUSTOM_YES) || (l_bufSize == 0) ) - { - if((l_bufSize == 0) || - ((i_vpdType == EREPAIR_VPD_FIELD) && - (l_bufSize > EREPAIR_MEM_FIELD_VPD_SIZE_PER_CENTAUR)) || - ((i_vpdType == EREPAIR_VPD_MNFG) && - (l_bufSize > EREPAIR_MEM_MNFG_VPD_SIZE_PER_CENTAUR))) - { - FAPI_ASSERT(false, - fapi2::P9_EREPAIR_ACCESSOR_HWP_INVALID_MEM_VPD_SIZE_ERR() - .set_ERROR(l_rc), - "ERROR: Invalid MEM VPD size"); - } - } - - // Allocate memory for buffer - l_retBuf = new uint8_t[l_bufSize]; - - FAPI_ASSERT(l_retBuf != NULL, - fapi2::P9_EREPAIR_ACCESSOR_HWP_MEMORY_ALLOC_FAIL_ERR() - .set_BUF_SIZE(l_bufSize), - "ERROR: Failed to allocate memory size"); - - // Retrieve the Field eRepair data from the PNOR - FAPI_TRY( getMBvpdField( - l_vpdRecord, - fapi2::MBVPD_KEYWORD_PDI, - i_target, - l_retBuf, - l_bufSize), - "VPD read failed w/rc=0x%x", - (uint64_t)current_err ); -#endif - } - else - { - // Determine the Processor target - l_procTarget = i_target.template getParent<TARGET_TYPE_PROC_CHIP>(); - - fapi2::MvpdRecord l_vpdRecord = fapi2::MVPD_RECORD_VWML; - - if(i_vpdType == EREPAIR_VPD_MNFG) - { - l_vpdRecord = fapi2::MVPD_RECORD_MER0; - } - - // Determine the size of the eRepair data in the VPD - FAPI_TRY( getMvpdField( - l_vpdRecord, - fapi2::MVPD_KEYWORD_PDI, - l_procTarget, - NULL, - l_bufSize), - "VPD size read failed w/rc=0x%x", - (uint64_t)current_err ); - - if((l_bufSize == 0) || - ((i_vpdType == EREPAIR_VPD_FIELD) && - (l_bufSize > EREPAIR_P9_MODULE_VPD_FIELD_SIZE)) || - ((i_vpdType == EREPAIR_VPD_MNFG) && - (l_bufSize > EREPAIR_P9_MODULE_VPD_MNFG_SIZE))) - { - FAPI_ASSERT(false, - fapi2::P9_EREPAIR_ACCESSOR_HWP_INVALID_FABRIC_VPD_SIZE_ERR() - .set_ERROR(current_err), - "ERROR: Invalid Fabric VPD size"); - } - - // Allocate memory for buffer - l_retBuf = new uint8_t[l_bufSize]; - - FAPI_ASSERT(l_retBuf != NULL, - fapi2::P9_EREPAIR_ACCESSOR_HWP_MEMORY_ALLOC_FAIL_ERR() - .set_BUF_SIZE(l_bufSize), - "ERROR: Failed to allocate memory size"); - - // Retrieve the Field eRepair data from the PNOR - FAPI_TRY( getMvpdField( - l_vpdRecord, - fapi2::MVPD_KEYWORD_PDI, - l_procTarget, - l_retBuf, - l_bufSize), - "VPD read failed w/rc=0x%x", - (uint64_t)current_err ); - } - - // Parse the buffer to determine eRepair lanes and copy the - // fail lane numbers to the return vector - FAPI_TRY( determineRepairLanes( - i_target, - l_retBuf, - l_bufSize, - i_clkGroup, - o_txFailLanes, - o_rxFailLanes), - "Call to determineRepairLanes failed w/rc=0x%x", - (uint64_t)current_err ); - - // Delete the buffer which has Field eRepair data - delete[] l_retBuf; - - FAPI_DBG("<< retrieveRepairData"); - -fapi_try_exit: - return fapi2::current_err; -} - -template<fapi2::TargetType K> -fapi2::ReturnCode determineRepairLanes( - const fapi2::Target < K >& i_target, - uint8_t* i_buf, - uint32_t i_bufSz, - const uint8_t i_clkGroup, - std::vector<uint8_t>& o_txFailLanes, - std::vector<uint8_t>& o_rxFailLanes) -{ - uint32_t l_numRepairs = 0; - uint8_t* l_vpdPtr = NULL; - eRepairHeader* l_vpdHeadPtr = NULL; - uint32_t l_loop = 0; - uint32_t l_bytesParsed = 0; - const uint32_t l_fabricRepairDataSz = sizeof(eRepairPowerBus); -#ifdef P9_CUMULUS - const uint32_t l_memRepairDataSz = sizeof(eRepairMemBus); - uint8_t l_customDimm; -#endif - fapi2::TargetType l_tgtType = fapi2::TARGET_TYPE_NONE; - fapi2::Target<fapi2::TARGET_TYPE_MCS> l_mcsTarget; - fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP> l_chipTarget; - fapi2::ReturnCode l_rc = fapi2::FAPI2_RC_SUCCESS; - fapi2::ATTR_CHIP_UNIT_POS_Type l_busNum; - bool l_bClkGroupFound = false; - fapi2::current_err = fapi2::FAPI2_RC_SUCCESS; - - FAPI_DBG(">> determineRepairLanes"); - - l_tgtType = i_target.getType(); - - // Get the parent chip target - l_chipTarget = i_target.template getParent<TARGET_TYPE_PROC_CHIP>(); - - // Get the chip position - uint32_t l_chipPosition; - FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_POS, - l_chipTarget, - l_chipPosition)); - - // Read the header and count information - l_vpdPtr = i_buf; // point to the start of header data - l_vpdHeadPtr = reinterpret_cast<eRepairHeader*> (l_vpdPtr); - - l_numRepairs = l_vpdHeadPtr->availNumRecord; - - l_bytesParsed = sizeof(eRepairHeader); // we've read the header data - l_vpdPtr += sizeof(eRepairHeader); // point to the start of repair data - - // Parse for Power bus data - if((l_tgtType == fapi2::TARGET_TYPE_XBUS) || - (l_tgtType == fapi2::TARGET_TYPE_OBUS)) - { - eRepairPowerBus* l_fabricBus; - - // Read Power bus eRepair data and get the failed lane numbers - for(l_loop = 0; - l_loop < l_numRepairs; - l_loop++, (l_vpdPtr += l_fabricRepairDataSz)) - { - // Make sure we are not parsing more data than the passed size - l_bytesParsed += l_fabricRepairDataSz; - - if(l_bytesParsed > i_bufSz) - { - break; - } - - l_fabricBus = reinterpret_cast<eRepairPowerBus*>(l_vpdPtr); - -#ifndef _BIG_ENDIAN - // We are on a Little Endian system. - // Need to swap the nibbles of the structure - eRepairPowerBus - - uint8_t l_temp = l_vpdPtr[2]; - l_fabricBus->type = (l_temp >> 4); - l_fabricBus->interface = (l_temp & 0x0F); -#endif - - // We do not need the check of processor ID because - // a MVPD read is specific to a Processor - - // Check if we have the matching the Fabric Bus types - if((l_tgtType == fapi2::TARGET_TYPE_OBUS) && - (l_fabricBus->type != PROCESSOR_OPT)) - { - continue; - } - - if((l_tgtType == fapi2::TARGET_TYPE_XBUS) && - (l_fabricBus->type != PROCESSOR_EDIP)) - { - continue; - } - - // Check if we have the matching fabric bus interface - FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CHIP_UNIT_POS, - i_target, - l_busNum)); - - if(l_fabricBus->device.fabricBus != l_busNum) - { - continue; - } - - if(i_clkGroup > 0 && !l_bClkGroupFound) - { - l_vpdPtr += l_fabricRepairDataSz; - l_bClkGroupFound = true; - continue; - } - - // Copy the fail lane numbers in the vectors - if(l_fabricBus->interface == PBUS_DRIVER) - { - decodeFailedLanes(i_target, l_fabricBus->interface, - l_fabricBus->failBit, o_txFailLanes); - } - else if(l_fabricBus->interface == PBUS_RECEIVER) - { - decodeFailedLanes(i_target, l_fabricBus->interface, - l_fabricBus->failBit, o_rxFailLanes); - } - } // end of for loop - } // end of if(l_tgtType is XBus or OBus) - else if((l_tgtType == fapi2::TARGET_TYPE_MCS_CHIPLET) || - (l_tgtType == fapi2::TARGET_TYPE_MEMBUF_CHIP)) - { -#ifdef P9_CUMULUS - // Parse for Memory bus data - eRepairMemBus* l_memBus; - - if(l_tgtType == fapi2::TARGET_TYPE_MEMBUF_CHIP) - { - l_rc = fapiGetOtherSideOfMemChannel( - i_target, - l_mcsTarget, - fapi2::TARGET_STATE_FUNCTIONAL); - - FAPI_ASSERT((uint64_t)l_rc == 0x0, - fapi2::P9_EREPAIR_UNABLE_CONNECT_MCS_TARGET_ERR() - .set_ERROR(l_rc), - "ERROR: determineRepairLanes: Unable to get the connected to MCS target"); - - // Check whether we have Memory on a CDIMM - l_rc = getDimmType(i_target, l_customDimm); - - FAPI_ASSERT((uint64_t)l_rc == 0x0, - fapi2::P9_EREPAIR_DIMM_TYPE_CHECK_ERR() - .set_ERROR(l_rc), - "ERROR: DIMM type check"); - } - - // Read Power bus eRepair data and get the failed lane numbers - for(l_loop = 0; - l_loop < l_numRepairs; - l_loop++, (l_vpdPtr += l_memRepairDataSz)) - { - // Make sure we are not parsing more data than the passed size - l_bytesParsed += l_memRepairDataSz; - - if(l_bytesParsed > i_bufSz) - { - break; - } - - l_memBus = reinterpret_cast<eRepairMemBus*>(l_vpdPtr); - -#ifndef _BIG_ENDIAN - // We are on a Little Endian system. - // Need to swap the nibbles of the structure - eRepairMemBus - - uint8_t l_temp = l_vpdPtr[2]; - l_memBus->type = (l_temp >> 4); - l_memBus->interface = (l_temp & 0x0F); -#endif - - // Check if we have the correct Centaur ID - // NOTE: We do not prefer to make the check of Centaur ID if the - // system is known to have CDIMMs. This check is applicable - // only for systems with ISDIMM because in the ISDIMM systems - // the Lane eRepair data for multiple Centaurs is maintained in - // a common VPD. - - if((l_tgtType == fapi2::TARGET_TYPE_MEMBUF_CHIP) && - (l_customDimm != fapi2::ENUM_ATTR_SPD_CUSTOM_YES) && - (l_chipPosition != l_memBus->device.proc_centaur_id)) - { - continue; - } - - // Check if we have the matching the Memory Bus types - if(l_memBus->type != MEMORY_EDIP) - { - continue; - } - - // Check if we have the matching memory bus interface - FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CHIP_UNIT_POS, - l_mcsTarget, - l_busNum)); - - if(l_memBus->device.memChannel != l_busNum) - { - continue; - } - - // Copy the fail lane numbers in the vectors - if(l_tgtType == fapi2::TARGET_TYPE_MCS_CHIPLET) - { - if(l_memBus->interface == DMI_MCS_DRIVE) - { - decodeFailedLanes(i_target, l_memBus->interface, - l_memBus->failBit, o_txFailLanes); - } - else if(l_memBus->interface == DMI_MCS_RECEIVE) - { - decodeFailedLanes(i_target, l_memBus->interface, - l_memBus->failBit, o_rxFailLanes); - } - } - else if(l_tgtType == fapi2::TARGET_TYPE_MEMBUF_CHIP) - { - if(l_memBus->interface == DMI_MEMBUF_DRIVE) - { - decodeFailedLanes(i_target, l_memBus->interface, - l_memBus->failBit, o_txFailLanes); - } - else if(l_memBus->interface == DMI_MEMBUF_RECEIVE) - { - decodeFailedLanes(i_target, l_memBus->interface, - l_memBus->failBit, o_rxFailLanes); - } - } - } // end of for loop - -#endif - } // end of if(l_tgtType is MCS) - - FAPI_INF("<< No.of Fail Lanes: tx: %zd, rx: %zd", - o_txFailLanes.size(), o_rxFailLanes.size()); - -fapi_try_exit: - return fapi2::current_err; -} - -template<fapi2::TargetType K> -fapi2::ReturnCode getDimmType( - const fapi2::Target < K >& i_target, - uint8_t& o_customDimm) -{ - fapi2::ReturnCode l_rc = fapi2::FAPI2_RC_SUCCESS; -#ifdef P9_CUMULUS - std::vector<fapi2::Target<fapi2::TARGET_TYPE_MBA_CHIPLET>> l_mbaChiplets; - fapi2::Target<fapi2::TARGET_TYPE_MBA> l_mbaTarget; - std::vector<fapi2::Target<fapi2::TARGET_TYPE_DIMM>> l_target_dimm_array; - - o_customDimm = fapi2::ENUM_ATTR_SPD_CUSTOM_NO; - - // Get the connected MBA chiplet and determine whether we have CDIMM - l_rc = fapiGetChildChiplets(i_target, - fapi2::TARGET_TYPE_MBA_CHIPLET, - l_mbaChiplets, - fapi2::TARGET_STATE_FUNCTIONAL); - - FAPI_ASSERT( ((uint64_t)l_rc == 0x0) || (0 != l_mbaChiplets.size()), - fapi2::P9_EREPAIR_CHILD_MBA_TARGETS_ERR() - .set_ERROR(l_rc), - "ERROR: During get child MBA targets"); - - l_mbaTarget = l_mbaChiplets[0]; - l_rc = fapiGetAssociatedDimms(l_mbaTarget, l_target_dimm_array); - - FAPI_ASSERT( (uint64_t)l_rc == 0x0, - fapi2::P9_EREPAIR_GET_ASSOCIATE_DIMMS_ERR() - .set_ERROR(l_rc), - "ERROR: from fapiGetAssociatedDimms"); - - if(0 != l_target_dimm_array.size()) - { - FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_SPD_CUSTOM, - l_target_dimm_array[0], - o_customDimm)); - } - else - { - o_customDimm = fapi2::ENUM_ATTR_SPD_CUSTOM_NO; - } - -fapi_try_exit: -#endif - return l_rc; -} - -template<fapi2::TargetType K> -fapi2::ReturnCode decodeFailedLanes( - const fapi2::Target < K >& i_target, - uint8_t i_busInterface, - uint32_t i_failBit, - std::vector<uint8_t>& o_FailLanes) -{ - fapi2::ReturnCode l_rc = fapi2::FAPI2_RC_SUCCESS; - uint8_t loop; - uint8_t maxBusLanes = 0; - uint32_t checkBitPosition = (0x80000000); - - FAPI_DBG(">> decodeFailedLanes"); - - // Check for target type and corresponding sub interface - // to get max lanes supported per interface - if(i_target.getType() == fapi2::TARGET_TYPE_OBUS) - { - maxBusLanes = OBUS_MAX_LANE_WIDTH; //OBUS - } - else if(i_target.getType() == fapi2::TARGET_TYPE_XBUS) - { - maxBusLanes = XBUS_MAX_LANE_WIDTH; //XBUS - } - else if((i_target.getType() == fapi2::TARGET_TYPE_MEMBUF_CHIP) || - (i_target.getType() == fapi2::TARGET_TYPE_MCS_CHIPLET) || - (i_target.getType() == fapi2::TARGET_TYPE_MCS)) //DMI - { - if( (i_busInterface == DMI_MCS_RECEIVE) || - (i_busInterface == DMI_MEMBUF_DRIVE) ) - { - maxBusLanes = DMIBUS_DNSTREAM_MAX_LANE_WIDTH; - } - else if( (i_busInterface == DMI_MCS_DRIVE) || - (i_busInterface == DMI_MEMBUF_RECEIVE) ) - { - maxBusLanes = DMIBUS_UPSTREAM_MAX_LANE_WIDTH; - } - } - - //Check for all the failed bit SET in the bit stream and update the vector - //And print the failed lanes - FAPI_INF("No. of Failed Lanes:"); - - for( loop = 0; - loop < maxBusLanes; - loop++ ) - { - if( i_failBit & ( checkBitPosition >> loop ) ) - { - o_FailLanes.push_back(loop); - FAPI_INF("%d", loop); - } - } - - FAPI_DBG("<< decodeFailedLanes"); - return l_rc; -} - diff --git a/src/import/chips/p9/procedures/hwp/io/p9_io_erepairGetFailedLanesHwp.H b/src/import/chips/p9/procedures/hwp/io/p9_io_erepairGetFailedLanesHwp.H index b79f8aff8..0a545fb7f 100755 --- a/src/import/chips/p9/procedures/hwp/io/p9_io_erepairGetFailedLanesHwp.H +++ b/src/import/chips/p9/procedures/hwp/io/p9_io_erepairGetFailedLanesHwp.H @@ -5,7 +5,7 @@ /* */ /* OpenPOWER HostBoot Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2015,2017 */ +/* Contributors Listed Below - COPYRIGHT 2015,2018 */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -40,26 +40,147 @@ #include <fapi2.H> #include <p9_io_erepairConsts.H> +#include <mvpd_access.H> +#include <fapi2_mbvpd_access.H> +/****************************************************************************** + * Accessor HWP + *****************************************************************************/ + +/** + * @brief Function to check if the system has Custom DIMM type (CDIMM). + * Attribute ATTR_EFF_CUSTOM_DIMM is read to determine the type. + * @param[in] i_target Reference to X-Bus or O-Bus or DMI target + * @param[o] o_customDimm Return value - ENUM_ATTR_EFF_CUSTOM_DIMM_NO + * or ENUM_ATTR_EFF_CUSTOM_DIMM_YES + * @return ReturnCode + */ template<fapi2::TargetType K> -using p9_io_erepairGetFailedLanesHwp_FP_t = fapi2::ReturnCode (*)( - const fapi2::Target < K >& i_target, - EREPAIR::erepairVpdType i_vpdType, - const uint8_t i_clkGroup, - std::vector<uint8_t>& o_txFailLanes, - std::vector<uint8_t>& o_rxFailLanes); +fapi2::ReturnCode getDimmType( + const fapi2::Target < K >& i_target, + uint8_t& o_customDimm) +{ + fapi2::ReturnCode l_rc = fapi2::FAPI2_RC_SUCCESS; + std::vector<fapi2::Target<fapi2::TARGET_TYPE_MBA_CHIPLET>> l_mbaChiplets; + fapi2::Target<fapi2::TARGET_TYPE_MBA> l_mbaTarget; + std::vector<fapi2::Target<fapi2::TARGET_TYPE_DIMM>> l_target_dimm_array; + + o_customDimm = fapi2::ENUM_ATTR_CEN_SPD_CUSTOM_NO; + + // Get the connected MBA chiplet and determine whether we have CDIMM + l_mbaChiplets = i_target.template getChildren<fapi2::TARGET_TYPE_MBA_CHIPLET> + (fapi2::TARGET_STATE_FUNCTIONAL); + FAPI_ASSERT( 0 != l_mbaChiplets.size(), + fapi2::P9_EREPAIR_CHILD_MBA_TARGETS_ERR() + .set_ERROR(l_mbaChiplets), + "ERROR: During get child MBA targets"); + + l_mbaTarget = l_mbaChiplets[0]; + l_target_dimm_array = l_mbaTarget.getChildren<fapi2::TARGET_TYPE_DIMM> + (fapi2::TARGET_STATE_FUNCTIONAL); + + if(0 != l_target_dimm_array.size()) + { + FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_SPD_CUSTOM, + l_target_dimm_array[0], + o_customDimm)); + } + else + { + o_customDimm = fapi2::ENUM_ATTR_CEN_SPD_CUSTOM_NO; + } + +fapi_try_exit: + return l_rc; +} /** - * @brief FW Team HWP that retrieves the eRepair fail lanes. - * It retrieves the eRepair data from the P9 MVPD and the Centaur FRU - * VPD sections depending on the passed target type. It then parses the - * eRepair data to determine the fail lane numbers on the sub-interfaces - * (Tx and Rx) of the passed bus target. + * @brief Function called by the HWP that parses the data read from VPD. + * This function scans through failBit field bit pattern and checks + * for all bits that are set. For bits SET the corresponding bit positions + * marks the failed lane number and is copied into + * the respective failLane vectors to be returned to the caller. * - * @param[in] i_tgtHandle Reference to X-Bus or A-Bus or MCS or memBuf Target - * @param[in] i_vpdType Specifies which VPD (MNFG or Field) to access. + * @param[in] i_target Reference to X-Bus or O-Bus or DMI target type + * @param[in] i_busInterface Reference to target sub interface + * @param[in] i_failBit This is the failBit field from the eRepair records + * read from the VPD + * @param[o] o_FailLanes Reference to a vector that will hold eRepair fail + * lane numbers of the Rx/Tx sub-interface. + * + * @return ReturnCode + */ +template<fapi2::TargetType K> +fapi2::ReturnCode decodeFailedLanes( + const fapi2::Target < K >& i_target, + uint8_t i_busInterface, + uint32_t i_failBit, + std::vector<uint8_t>& o_FailLanes) +{ + fapi2::ReturnCode l_rc = fapi2::FAPI2_RC_SUCCESS; + uint8_t loop; + uint8_t maxBusLanes = 0; + uint32_t checkBitPosition = (0x80000000); + + FAPI_DBG(">> decodeFailedLanes"); + + // Check for target type and corresponding sub interface + // to get max lanes supported per interface + if(i_target.getType() == fapi2::TARGET_TYPE_OBUS) + { + maxBusLanes = EREPAIR::OBUS_MAX_LANE_WIDTH; //OBUS + } + else if(i_target.getType() == fapi2::TARGET_TYPE_XBUS) + { + maxBusLanes = EREPAIR::XBUS_MAX_LANE_WIDTH; //XBUS + } + else if((i_target.getType() == fapi2::TARGET_TYPE_MEMBUF_CHIP) || + (i_target.getType() == fapi2::TARGET_TYPE_DMI)) + { + if( (i_busInterface == EREPAIR::DMI_MCS_RECEIVE) || + (i_busInterface == EREPAIR::DMI_MEMBUF_DRIVE) ) + { + maxBusLanes = EREPAIR::DMIBUS_DNSTREAM_MAX_LANE_WIDTH; + } + else if( (i_busInterface == EREPAIR::DMI_MCS_DRIVE) || + (i_busInterface == EREPAIR::DMI_MEMBUF_RECEIVE) ) + { + maxBusLanes = EREPAIR::DMIBUS_UPSTREAM_MAX_LANE_WIDTH; + } + } + + //Check for all the failed bit SET in the bit stream and update the vector + //And print the failed lanes + FAPI_INF("No. of Failed Lanes:"); + + for( loop = 0; + loop < maxBusLanes; + loop++ ) + { + if( i_failBit & ( checkBitPosition >> loop ) ) + { + o_FailLanes.push_back(loop); + FAPI_INF("%d", loop); + } + } + + FAPI_DBG("<< decodeFailedLanes"); + return l_rc; +} + +/** + * @brief Function called by the FW Team HWP that parses the data read from + * Field VPD. This function matches each eRepair record read from the VPD + * and matches it against the attributes of the passed target. + * If a match is found, the corresponding eRepair record is copied into + * the respective failLane vectors to be returned to the caller. + * (For Proc) + * @param[in] i_target Reference to X-Bus or O-Bus target + * @param[in] i_buf This is the buffer that has the eRepair records + * read from the VPD + * @param[in] i_bufSz This is the size of passed buffer in terms of bytes * @param[in] i_clkGroup Specifies clock group 0:[XOA, X1A,..] 1:[X0B, X1B,..] * @param[o] o_txFailLanes Reference to a vector that will hold eRepair fail * lane numbers of the Tx sub-interface. @@ -67,15 +188,828 @@ using p9_io_erepairGetFailedLanesHwp_FP_t = fapi2::ReturnCode (*)( * lane numbers of the Rx sub-interface. * * @return ReturnCode + */ +template<fapi2::TargetType K> +fapi2::ReturnCode determineRepairLanesProc( + const fapi2::Target < K >& i_target, + uint8_t* i_buf, + uint32_t i_bufSz, + const uint8_t i_clkGroup, + std::vector<uint8_t>& o_txFailLanes, + std::vector<uint8_t>& o_rxFailLanes) +{ + uint32_t l_numRepairs = 0; + uint8_t* l_vpdPtr = NULL; + eRepairHeader* l_vpdHeadPtr = NULL; + uint32_t l_loop = 0; + uint32_t l_bytesParsed = 0; + const uint32_t l_fabricRepairDataSz = sizeof(eRepairPowerBus); + fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP> l_chipTarget; + fapi2::ReturnCode l_rc = fapi2::FAPI2_RC_SUCCESS; + fapi2::ATTR_CHIP_UNIT_POS_Type l_busNum; + bool l_bClkGroupFound = false; + fapi2::current_err = fapi2::FAPI2_RC_SUCCESS; + + FAPI_DBG(">> determineRepairLanesProc"); + + // Get the parent chip target + l_chipTarget = i_target.template getParent<fapi2::TARGET_TYPE_PROC_CHIP>(); + + // Get the chip position + uint32_t l_chipPosition; + FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_POS, + l_chipTarget, + l_chipPosition)); + + // Read the header and count information + l_vpdPtr = i_buf; // point to the start of header data + l_vpdHeadPtr = reinterpret_cast<eRepairHeader*> (l_vpdPtr); + + l_numRepairs = l_vpdHeadPtr->availNumRecord; + + l_bytesParsed = sizeof(eRepairHeader); // we've read the header data + l_vpdPtr += sizeof(eRepairHeader); // point to the start of repair data + + // Parse for Power bus data + { + eRepairPowerBus* l_fabricBus; + + // Read Power bus eRepair data and get the failed lane numbers + for(l_loop = 0; + l_loop < l_numRepairs; + l_loop++, (l_vpdPtr += l_fabricRepairDataSz)) + { + // Make sure we are not parsing more data than the passed size + l_bytesParsed += l_fabricRepairDataSz; + + if(l_bytesParsed > i_bufSz) + { + break; + } + + l_fabricBus = reinterpret_cast<eRepairPowerBus*>(l_vpdPtr); + +#ifndef _BIG_ENDIAN + // We are on a Little Endian system. + // Need to swap the nibbles of the structure - eRepairPowerBus + + uint8_t l_temp = l_vpdPtr[2]; + l_fabricBus->type = (l_temp >> 4); + l_fabricBus->interface = (l_temp & 0x0F); +#endif + + // We do not need the check of processor ID because + // a MVPD read is specific to a Processor + + // Check if we have the matching the Fabric Bus types + //if((l_tgtType == fapi2::TARGET_TYPE_OBUS) && + // (l_fabricBus->type != PROCESSOR_OPT)) + //{ + // continue; + //} + + if(l_fabricBus->type != EREPAIR::PROCESSOR_EDIP) + { + continue; + } + + // Check if we have the matching fabric bus interface + FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CHIP_UNIT_POS, + i_target, + l_busNum)); + + if(l_fabricBus->device.fabricBus != l_busNum) + { + continue; + } + + if(i_clkGroup > 0 && !l_bClkGroupFound) + { + l_vpdPtr += l_fabricRepairDataSz; + l_bClkGroupFound = true; + continue; + } + + // Copy the fail lane numbers in the vectors + if(l_fabricBus->interface == EREPAIR::PBUS_DRIVER) + { + decodeFailedLanes(i_target, l_fabricBus->interface, + l_fabricBus->failBit, o_txFailLanes); + } + else if(l_fabricBus->interface == EREPAIR::PBUS_RECEIVER) + { + decodeFailedLanes(i_target, l_fabricBus->interface, + l_fabricBus->failBit, o_rxFailLanes); + } + } // end of for loop + } // end of if(l_tgtType is XBus or OBus) + + FAPI_INF("<< No.of Fail Lanes: tx: %zd, rx: %zd", + o_txFailLanes.size(), o_rxFailLanes.size()); + +fapi_try_exit: + return fapi2::current_err; +} + +/** + * @brief Function called by the FW Team HWP that parses the data read from + * Field VPD. This function matches each eRepair record read from the VPD + * and matches it against the attributes of the passed target. + * If a match is found, the corresponding eRepair record is copied into + * the respective failLane vectors to be returned to the caller. + * (For MemBuf) + * @param[in] i_target Reference to MEMBUF target + * @param[in] i_buf This is the buffer that has the eRepair records + * read from the VPD + * @param[in] i_bufSz This is the size of passed buffer in terms of bytes + * @param[o] o_txFailLanes Reference to a vector that will hold eRepair fail + * lane numbers of the Tx sub-interface. + * @param[o] o_rxFailLanes Reference to a vector that will hold eRepair fail + * lane numbers of the Rx sub-interface. + * + * @return ReturnCode + */ +template<fapi2::TargetType K> +fapi2::ReturnCode determineRepairLanesMemBuf( + const fapi2::Target < K >& i_target, + uint8_t* i_buf, + uint32_t i_bufSz, + std::vector<uint8_t>& o_txFailLanes, + std::vector<uint8_t>& o_rxFailLanes) +{ + uint32_t l_numRepairs = 0; + uint8_t* l_vpdPtr = NULL; + eRepairHeader* l_vpdHeadPtr = NULL; + uint32_t l_loop = 0; + uint32_t l_bytesParsed = 0; + const uint32_t l_memRepairDataSz = sizeof(eRepairMemBus); + uint8_t l_customDimm; + fapi2::Target<fapi2::TARGET_TYPE_DMI> l_dmiTarget; + fapi2::ReturnCode l_rc = fapi2::FAPI2_RC_SUCCESS; + fapi2::ATTR_CHIP_UNIT_POS_Type l_busNum; + fapi2::current_err = fapi2::FAPI2_RC_SUCCESS; + + FAPI_DBG(">> determineRepairLanesMemBuf"); + + // Get the chip position + uint32_t l_chipPosition; + FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_POS, + i_target, + l_chipPosition)); + + // Read the header and count information + l_vpdPtr = i_buf; // point to the start of header data + l_vpdHeadPtr = reinterpret_cast<eRepairHeader*> (l_vpdPtr); + + l_numRepairs = l_vpdHeadPtr->availNumRecord; + + l_bytesParsed = sizeof(eRepairHeader); // we've read the header data + l_vpdPtr += sizeof(eRepairHeader); // point to the start of repair data + + // Parse for Memory bus data + { + eRepairMemBus* l_memBus; + + l_dmiTarget = i_target.template getParent<fapi2::TARGET_TYPE_DMI>(); + + // Check whether we have Memory on a CDIMM + l_rc = getDimmType(i_target, l_customDimm); + + FAPI_ASSERT((uint64_t)l_rc == 0x0, + fapi2::P9_EREPAIR_DIMM_TYPE_CHECK_ERR() + .set_ERROR(l_rc), + "ERROR: DIMM type check"); + + // Read Power bus eRepair data and get the failed lane numbers + for(l_loop = 0; + l_loop < l_numRepairs; + l_loop++, (l_vpdPtr += l_memRepairDataSz)) + { + // Make sure we are not parsing more data than the passed size + l_bytesParsed += l_memRepairDataSz; + + if(l_bytesParsed > i_bufSz) + { + break; + } + + l_memBus = reinterpret_cast<eRepairMemBus*>(l_vpdPtr); + +#ifndef _BIG_ENDIAN + // We are on a Little Endian system. + // Need to swap the nibbles of the structure - eRepairMemBus + + uint8_t l_temp = l_vpdPtr[2]; + l_memBus->type = (l_temp >> 4); + l_memBus->interface = (l_temp & 0x0F); +#endif + + // Check if we have the correct Centaur ID + // NOTE: We do not prefer to make the check of Centaur ID if the + // system is known to have CDIMMs. This check is applicable + // only for systems with ISDIMM because in the ISDIMM systems + // the Lane eRepair data for multiple Centaurs is maintained in + // a common VPD. + + if((l_customDimm != fapi2::ENUM_ATTR_CEN_SPD_CUSTOM_YES) && + (l_chipPosition != l_memBus->device.proc_centaur_id)) + { + continue; + } + + // Check if we have the matching the Memory Bus types + if(l_memBus->type != EREPAIR::MEMORY_EDIP) + { + continue; + } + + // Check if we have the matching memory bus interface + FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CHIP_UNIT_POS, + l_dmiTarget, + l_busNum)); + + if(l_memBus->device.memChannel != l_busNum) + { + continue; + } + + // Copy the fail lane numbers in the vectors + { + if(l_memBus->interface == EREPAIR::DMI_MEMBUF_DRIVE) + { + decodeFailedLanes(i_target, l_memBus->interface, + l_memBus->failBit, o_txFailLanes); + } + else if(l_memBus->interface == EREPAIR::DMI_MEMBUF_RECEIVE) + { + decodeFailedLanes(i_target, l_memBus->interface, + l_memBus->failBit, o_rxFailLanes); + } + } + } // end of for loop + } // end of if(l_tgtType is DMI) + + FAPI_INF("<< No.of Fail Lanes: tx: %zd, rx: %zd", + o_txFailLanes.size(), o_rxFailLanes.size()); + +fapi_try_exit: + return fapi2::current_err; +} + + +/** + * @brief Function called by the FW Team HWP that parses the data read from + * Field VPD. This function matches each eRepair record read from the VPD + * and matches it against the attributes of the passed target. + * If a match is found, the corresponding eRepair record is copied into + * the respective failLane vectors to be returned to the caller. + * (For Memory) + * @param[in] i_target Reference to DMI target + * @param[in] i_buf This is the buffer that has the eRepair records + * read from the VPD + * @param[in] i_bufSz This is the size of passed buffer in terms of bytes + * @param[o] o_txFailLanes Reference to a vector that will hold eRepair fail + * lane numbers of the Tx sub-interface. + * @param[o] o_rxFailLanes Reference to a vector that will hold eRepair fail + * lane numbers of the Rx sub-interface. * + * @return ReturnCode */ template<fapi2::TargetType K> -fapi2::ReturnCode p9_io_erepairGetFailedLanesHwp( +fapi2::ReturnCode determineRepairLanesDMI( const fapi2::Target < K >& i_target, - EREPAIR::erepairVpdType i_vpdType, - const uint8_t i_clkGroup, + uint8_t* i_buf, + uint32_t i_bufSz, std::vector<uint8_t>& o_txFailLanes, - std::vector<uint8_t>& o_rxFailLanes); + std::vector<uint8_t>& o_rxFailLanes) +{ + uint32_t l_numRepairs = 0; + uint8_t* l_vpdPtr = NULL; + eRepairHeader* l_vpdHeadPtr = NULL; + uint32_t l_loop = 0; + uint32_t l_bytesParsed = 0; + const uint32_t l_memRepairDataSz = sizeof(eRepairMemBus); + fapi2::Target<fapi2::TARGET_TYPE_DMI> l_dmiTarget; + fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP> l_chipTarget; + fapi2::ReturnCode l_rc = fapi2::FAPI2_RC_SUCCESS; + fapi2::ATTR_CHIP_UNIT_POS_Type l_busNum; + fapi2::current_err = fapi2::FAPI2_RC_SUCCESS; + + FAPI_DBG(">> determineRepairLanesMemDMI"); + + // Get the parent chip target + l_chipTarget = i_target.template getParent<fapi2::TARGET_TYPE_PROC_CHIP>(); + + // Get the chip position + uint32_t l_chipPosition; + FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_POS, + l_chipTarget, + l_chipPosition)); + + // Read the header and count information + l_vpdPtr = i_buf; // point to the start of header data + l_vpdHeadPtr = reinterpret_cast<eRepairHeader*> (l_vpdPtr); + + l_numRepairs = l_vpdHeadPtr->availNumRecord; + + l_bytesParsed = sizeof(eRepairHeader); // we've read the header data + l_vpdPtr += sizeof(eRepairHeader); // point to the start of repair data + + // Parse for Memory bus data + { + eRepairMemBus* l_memBus; + + // Read Power bus eRepair data and get the failed lane numbers + for(l_loop = 0; + l_loop < l_numRepairs; + l_loop++, (l_vpdPtr += l_memRepairDataSz)) + { + // Make sure we are not parsing more data than the passed size + l_bytesParsed += l_memRepairDataSz; + + if(l_bytesParsed > i_bufSz) + { + break; + } + + l_memBus = reinterpret_cast<eRepairMemBus*>(l_vpdPtr); + +#ifndef _BIG_ENDIAN + // We are on a Little Endian system. + // Need to swap the nibbles of the structure - eRepairMemBus + + uint8_t l_temp = l_vpdPtr[2]; + l_memBus->type = (l_temp >> 4); + l_memBus->interface = (l_temp & 0x0F); +#endif + + // Check if we have the correct Centaur ID + // NOTE: We do not prefer to make the check of Centaur ID if the + // system is known to have CDIMMs. This check is applicable + // only for systems with ISDIMM because in the ISDIMM systems + // the Lane eRepair data for multiple Centaurs is maintained in + // a common VPD. + + // Check if we have the matching the Memory Bus types + if(l_memBus->type != EREPAIR::MEMORY_EDIP) + { + continue; + } + + // Check if we have the matching memory bus interface + FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CHIP_UNIT_POS, + l_dmiTarget, + l_busNum)); + + if(l_memBus->device.memChannel != l_busNum) + { + continue; + } + + // Copy the fail lane numbers in the vectors + if(l_memBus->interface == EREPAIR::DMI_MCS_DRIVE) + { + decodeFailedLanes(i_target, l_memBus->interface, + l_memBus->failBit, o_txFailLanes); + } + else if(l_memBus->interface == EREPAIR::DMI_MCS_RECEIVE) + { + decodeFailedLanes(i_target, l_memBus->interface, + l_memBus->failBit, o_rxFailLanes); + } + } // end of for loop + } // end of if(l_tgtType is DMI) + + FAPI_INF("<< No.of Fail Lanes: tx: %zd, rx: %zd", + o_txFailLanes.size(), o_rxFailLanes.size()); + +fapi_try_exit: + return fapi2::current_err; +} + + +/** + * @brief Function called by the FW Team HWP that reads the data from Field VPD. + * This function makes the actual calls to read the VPD + * It determines the size of the buffer to be read, allocates memory + * of the determined size, calls fapiGetMvpdField to read the eRepair + * records. This buffer is further passed to another routine for + * parsing. (For Proc) + * + * @param[in] i_target Reference to X-Bus or O-Bus target + * @param[in] i_vpdType Specifies which VPD (MNFG or Field) to access. + * @param[in] i_clkGroup Specifies clock group 0:[XOA, X1A,..] 1:[X0B, X1B,..] + * @param[o] o_txFailLanes Reference to a vector that will hold eRepair fail + * lane numbers of the Tx sub-interface. + * @param[o] o_rxFailLanes Reference to a vector that will hold eRepair fail + * lane numbers of the Rx sub-interface. + * + * @return ReturnCode + */ +template<fapi2::TargetType K> +fapi2::ReturnCode retrieveRepairDataProc( + const fapi2::Target < K >& i_target, + EREPAIR::erepairVpdType i_vpdType, + const uint8_t i_clkGroup, + std::vector<uint8_t>& o_txFailLanes, + std::vector<uint8_t>& o_rxFailLanes) +{ + fapi2::ReturnCode l_rc = fapi2::FAPI2_RC_SUCCESS; + fapi2::current_err = fapi2::FAPI2_RC_SUCCESS; + uint8_t* l_retBuf = NULL; + uint32_t l_bufSize = 0; + fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP> l_procTarget; + + FAPI_DBG(">> retrieveRepairDataProc"); + + { + // Determine the Processor target + l_procTarget = i_target.template getParent<fapi2::TARGET_TYPE_PROC_CHIP>(); + + fapi2::MvpdRecord l_vpdRecord = fapi2::MVPD_RECORD_VWML; + + if(i_vpdType == EREPAIR::EREPAIR_VPD_MNFG) + { + l_vpdRecord = fapi2::MVPD_RECORD_MER0; + } + + // Determine the size of the eRepair data in the VPD + FAPI_TRY( getMvpdField( + l_vpdRecord, + fapi2::MVPD_KEYWORD_PDI, + l_procTarget, + NULL, + l_bufSize), + "VPD size read failed w/rc=0x%x", + (uint64_t)fapi2::current_err ); + + if((l_bufSize == 0) || + ((i_vpdType == EREPAIR::EREPAIR_VPD_FIELD) && + (l_bufSize > EREPAIR::EREPAIR_P9_MODULE_VPD_FIELD_SIZE)) || + ((i_vpdType == EREPAIR::EREPAIR_VPD_MNFG) && + (l_bufSize > EREPAIR::EREPAIR_P9_MODULE_VPD_MNFG_SIZE))) + { + FAPI_ASSERT(false, + fapi2::P9_EREPAIR_ACCESSOR_HWP_INVALID_FABRIC_VPD_SIZE_ERR() + .set_ERROR(fapi2::current_err), + "ERROR: Invalid Fabric VPD size"); + } + + // Allocate memory for buffer + l_retBuf = new uint8_t[l_bufSize]; + + FAPI_ASSERT(l_retBuf != NULL, + fapi2::P9_EREPAIR_ACCESSOR_HWP_MEMORY_ALLOC_FAIL_ERR() + .set_BUF_SIZE(l_bufSize), + "ERROR: Failed to allocate memory size"); + + // Retrieve the Field eRepair data from the PNOR + FAPI_TRY( getMvpdField( + l_vpdRecord, + fapi2::MVPD_KEYWORD_PDI, + l_procTarget, + l_retBuf, + l_bufSize), + "VPD read failed w/rc=0x%x", + (uint64_t)fapi2::current_err ); + + // Parse the buffer to determine eRepair lanes and copy the + // fail lane numbers to the return vector + FAPI_TRY( determineRepairLanesProc( + i_target, + l_retBuf, + l_bufSize, + i_clkGroup, + o_txFailLanes, + o_rxFailLanes), + "Call to determineRepairLanes failed w/rc=0x%x", + (uint64_t)fapi2::current_err ); + } + + // Delete the buffer which has Field eRepair data + delete[] l_retBuf; + + FAPI_DBG("<< retrieveRepairDataProc"); + +fapi_try_exit: + return fapi2::current_err; +} + + +/** + * @brief Function called by the FW Team HWP that reads the data from Field VPD. + * This function makes the actual calls to read the VPD + * It determines the size of the buffer to be read, allocates memory + * of the determined size, calls fapiGetMBvpdField to read the eRepair + * records. This buffer is further passed to another routine for + * parsing. (For Memory) + * + * @param[in] i_target Reference to MEMBUF or DMI target + * @param[in] i_vpdType Specifies which VPD (MNFG or Field) to access. + * @param[o] o_txFailLanes Reference to a vector that will hold eRepair fail + * lane numbers of the Tx sub-interface. + * @param[o] o_rxFailLanes Reference to a vector that will hold eRepair fail + * lane numbers of the Rx sub-interface. + * + * @return ReturnCode + */ +template<fapi2::TargetType K> +fapi2::ReturnCode retrieveRepairDataMemBuf( + const fapi2::Target < K >& i_target, + EREPAIR::erepairVpdType i_vpdType, + std::vector<uint8_t>& o_txFailLanes, + std::vector<uint8_t>& o_rxFailLanes) +{ + fapi2::ReturnCode l_rc = fapi2::FAPI2_RC_SUCCESS; + fapi2::current_err = fapi2::FAPI2_RC_SUCCESS; + uint8_t* l_retBuf = NULL; + uint32_t l_bufSize = 0; + size_t l_mBufSize = 0; + uint8_t l_customDimm; + + FAPI_DBG(">> retrieveRepairDataMemBuf"); + + { + fapi2::MBvpdRecord l_vpdRecord = fapi2::MBVPD_RECORD_VEIR; + + if(i_vpdType == EREPAIR::EREPAIR_VPD_MNFG) + { + l_vpdRecord = fapi2::MBVPD_RECORD_MER0; + } + + // Determine the size of the eRepair data in the VPD + FAPI_TRY( getMBvpdField( + l_vpdRecord, + fapi2::MBVPD_KEYWORD_PDI, + i_target, + NULL, + l_mBufSize), + "VPD size read failed w/rc=0x%x", + (uint64_t)fapi2::current_err ); + + // Check whether we have Memory on a CDIMM + l_rc = getDimmType(i_target, l_customDimm); + + FAPI_ASSERT((uint64_t)l_rc == 0x0, + fapi2::P9_EREPAIR_DIMM_TYPE_CHECK_ERR() + .set_ERROR(l_rc), + "ERROR: DIMM type check"); + + if( (l_customDimm == fapi2::ENUM_ATTR_CEN_SPD_CUSTOM_YES) || (l_bufSize == 0) ) + { + if((l_bufSize == 0) || + ((i_vpdType == EREPAIR::EREPAIR_VPD_FIELD) && + (l_bufSize > EREPAIR::EREPAIR_MEM_FIELD_VPD_SIZE_PER_CENTAUR)) || + ((i_vpdType == EREPAIR::EREPAIR_VPD_MNFG) && + (l_bufSize > EREPAIR::EREPAIR_MEM_MNFG_VPD_SIZE_PER_CENTAUR))) + { + FAPI_ASSERT(false, + fapi2::P9_EREPAIR_ACCESSOR_HWP_INVALID_MEM_VPD_SIZE_ERR() + .set_ERROR(l_rc), + "ERROR: Invalid MEM VPD size"); + } + } + + // Allocate memory for buffer + l_retBuf = new uint8_t[l_bufSize]; + + FAPI_ASSERT(l_retBuf != NULL, + fapi2::P9_EREPAIR_ACCESSOR_HWP_MEMORY_ALLOC_FAIL_ERR() + .set_BUF_SIZE(l_bufSize), + "ERROR: Failed to allocate memory size"); + + // Retrieve the Field eRepair data from the PNOR + FAPI_TRY( getMBvpdField( + l_vpdRecord, + fapi2::MBVPD_KEYWORD_PDI, + i_target, + l_retBuf, + l_mBufSize), + "VPD read failed w/rc=0x%x", + (uint64_t)fapi2::current_err ); + + // Parse the buffer to determine eRepair lanes and copy the + // fail lane numbers to the return vector + FAPI_TRY( determineRepairLanesMemBuf( + i_target, + l_retBuf, + l_mBufSize, + o_txFailLanes, + o_rxFailLanes), + "Call to determineRepairLanes failed w/rc=0x%x", + (uint64_t)fapi2::current_err ); + } + + // Delete the buffer which has Field eRepair data + delete[] l_retBuf; + + FAPI_DBG("<< retrieveRepairDataMemBuf"); + +fapi_try_exit: + return fapi2::current_err; +} + + +/** + * @brief Function called by the FW Team HWP that reads the data from Field VPD. + * This function makes the actual calls to read the VPD + * It determines the size of the buffer to be read, allocates memory + * of the determined size, calls fapiGetMvpdField to read the eRepair + * records. This buffer is further passed to another routine for + * parsing. (For DMI) + * + * @param[in] i_target Reference to DMI target + * @param[in] i_vpdType Specifies which VPD (MNFG or Field) to access. + * @param[o] o_txFailLanes Reference to a vector that will hold eRepair fail + * lane numbers of the Tx sub-interface. + * @param[o] o_rxFailLanes Reference to a vector that will hold eRepair fail + * lane numbers of the Rx sub-interface. + * + * @return ReturnCode + */ +template<fapi2::TargetType K> +fapi2::ReturnCode retrieveRepairDataDMI( + const fapi2::Target < K >& i_target, + EREPAIR::erepairVpdType i_vpdType, + std::vector<uint8_t>& o_txFailLanes, + std::vector<uint8_t>& o_rxFailLanes) +{ + fapi2::ReturnCode l_rc = fapi2::FAPI2_RC_SUCCESS; + fapi2::current_err = fapi2::FAPI2_RC_SUCCESS; + uint8_t* l_retBuf = NULL; + uint32_t l_bufSize = 0; + fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP> l_procTarget; + + FAPI_DBG(">> retrieveRepairDataDMI"); + + { + // Determine the Processor target + l_procTarget = i_target.template getParent<fapi2::TARGET_TYPE_PROC_CHIP>(); + + fapi2::MvpdRecord l_vpdRecord = fapi2::MVPD_RECORD_VWML; + + if(i_vpdType == EREPAIR::EREPAIR_VPD_MNFG) + { + l_vpdRecord = fapi2::MVPD_RECORD_MER0; + } + + // Determine the size of the eRepair data in the VPD + FAPI_TRY( getMvpdField( + l_vpdRecord, + fapi2::MVPD_KEYWORD_PDI, + l_procTarget, + NULL, + l_bufSize), + "VPD size read failed w/rc=0x%x", + (uint64_t)fapi2::current_err ); + + if((l_bufSize == 0) || + ((i_vpdType == EREPAIR::EREPAIR_VPD_FIELD) && + (l_bufSize > EREPAIR::EREPAIR_P9_MODULE_VPD_FIELD_SIZE)) || + ((i_vpdType == EREPAIR::EREPAIR_VPD_MNFG) && + (l_bufSize > EREPAIR::EREPAIR_P9_MODULE_VPD_MNFG_SIZE))) + { + FAPI_ASSERT(false, + fapi2::P9_EREPAIR_ACCESSOR_HWP_INVALID_FABRIC_VPD_SIZE_ERR() + .set_ERROR(fapi2::current_err), + "ERROR: Invalid Fabric VPD size"); + } + + // Allocate memory for buffer + l_retBuf = new uint8_t[l_bufSize]; + + FAPI_ASSERT(l_retBuf != NULL, + fapi2::P9_EREPAIR_ACCESSOR_HWP_MEMORY_ALLOC_FAIL_ERR() + .set_BUF_SIZE(l_bufSize), + "ERROR: Failed to allocate memory size"); + + // Retrieve the Field eRepair data from the PNOR + FAPI_TRY( getMvpdField( + l_vpdRecord, + fapi2::MVPD_KEYWORD_PDI, + l_procTarget, + l_retBuf, + l_bufSize), + "VPD read failed w/rc=0x%x", + (uint64_t)fapi2::current_err ); + + // Parse the buffer to determine eRepair lanes and copy the + // fail lane numbers to the return vector + FAPI_TRY( determineRepairLanesDMI( + i_target, + l_retBuf, + l_bufSize, + o_txFailLanes, + o_rxFailLanes), + "Call to determineRepairLanes failed w/rc=0x%x", + (uint64_t)fapi2::current_err ); + } + + // Delete the buffer which has Field eRepair data + delete[] l_retBuf; + + FAPI_DBG("<< retrieveRepairDataDMI"); + +fapi_try_exit: + return fapi2::current_err; +} + + +/** + * @brief Function called by the FW Team HWP that reads the failed lanes + * from VPD. This function calls the retrieveRepairData() that makes + * the actual calls to read the VPD and perform the necessary actions. + * + * @param[in] i_target Reference to X-Bus or O-Bus or DMI target + * @param[in] i_vpdType Specifies which VPD (MNFG or Field) to access. + * @param[in] i_clkGroup Specifies clock group 0:[XOA, X1A,..] 1:[X0B, X1B,..] + * @param[o] o_txFailLanes Reference to a vector that will hold eRepair fail + * lane numbers of the Tx sub-interface. + * @param[o] o_rxFailLanes Reference to a vector that will hold eRepair fail + * lane numbers of the Rx sub-interface. + * + * @return ReturnCode + */ +fapi2::ReturnCode p9_io_erepairGetFailedLanesHwp( + const fapi2::Target < fapi2::TARGET_TYPE_XBUS >& i_target, + EREPAIR::erepairVpdType i_vpdType, + const uint8_t i_clkGroup, + std::vector<uint8_t>& o_txFailLanes, + std::vector<uint8_t>& o_rxFailLanes) +{ + fapi2::current_err = fapi2::FAPI2_RC_SUCCESS; + + FAPI_INF(">> erepairGetFailedLanesHwp - XBUS"); + + o_txFailLanes.clear(); + o_rxFailLanes.clear(); + + // Retrieve the Field eRepair lane numbers from the VPD + FAPI_TRY( retrieveRepairDataProc( + i_target, + i_vpdType, + i_clkGroup, + o_txFailLanes, + o_rxFailLanes), + "p9_io_erepairGetFailedLanesHwp() failed w/rc=0x%x", + (uint64_t)fapi2::current_err ); + +fapi_try_exit: + return fapi2::current_err; +} + +fapi2::ReturnCode p9_io_erepairGetFailedLanesHwp( + const fapi2::Target < fapi2::TARGET_TYPE_MEMBUF_CHIP >& i_target, + EREPAIR::erepairVpdType i_vpdType, + const uint8_t i_clkGroup, + std::vector<uint8_t>& o_txFailLanes, + std::vector<uint8_t>& o_rxFailLanes) +{ + fapi2::current_err = fapi2::FAPI2_RC_SUCCESS; + + FAPI_INF(">> erepairGetFailedLanesHwp - MemBuf"); + + o_txFailLanes.clear(); + o_rxFailLanes.clear(); + + // Retrieve the Field eRepair lane numbers from the VPD + FAPI_TRY( retrieveRepairDataMemBuf( + i_target, + i_vpdType, + o_txFailLanes, + o_rxFailLanes), + "p9_io_erepairGetFailedLanesHwp() failed w/rc=0x%x", + (uint64_t)fapi2::current_err ); + +fapi_try_exit: + return fapi2::current_err; +} + +fapi2::ReturnCode p9_io_erepairGetFailedLanesHwp( + const fapi2::Target < fapi2::TARGET_TYPE_DMI >& i_target, + EREPAIR::erepairVpdType i_vpdType, + const uint8_t i_clkGroup, + std::vector<uint8_t>& o_txFailLanes, + std::vector<uint8_t>& o_rxFailLanes) +{ + fapi2::current_err = fapi2::FAPI2_RC_SUCCESS; + + FAPI_INF(">> erepairGetFailedLanesHwp - DMI"); + + o_txFailLanes.clear(); + o_rxFailLanes.clear(); + + // Retrieve the Field eRepair lane numbers from the VPD + FAPI_TRY( retrieveRepairDataDMI( + i_target, + i_vpdType, + o_txFailLanes, + o_rxFailLanes), + "p9_io_erepairGetFailedLanesHwp() failed w/rc=0x%x", + (uint64_t)fapi2::current_err ); +fapi_try_exit: + return fapi2::current_err; +} #endif diff --git a/src/import/chips/p9/procedures/hwp/io/p9_io_erepairGetFailedLanesHwp.mk b/src/import/chips/p9/procedures/hwp/io/p9_io_erepairGetFailedLanesHwp.mk deleted file mode 100644 index 554d5ecd0..000000000 --- a/src/import/chips/p9/procedures/hwp/io/p9_io_erepairGetFailedLanesHwp.mk +++ /dev/null @@ -1,27 +0,0 @@ -# IBM_PROLOG_BEGIN_TAG -# This is an automatically generated prolog. -# -# $Source: src/import/chips/p9/procedures/hwp/io/p9_io_erepairGetFailedLanesHwp.mk $ -# -# OpenPOWER HostBoot Project -# -# Contributors Listed Below - COPYRIGHT 2015,2017 -# [+] International Business Machines Corp. -# -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or -# implied. See the License for the specific language governing -# permissions and limitations under the License. -# -# IBM_PROLOG_END_TAG - -PROCEDURE=p9_io_erepairGetFailedLanesHwp -$(call BUILD_PROCEDURE) diff --git a/src/import/chips/p9/procedures/hwp/io/p9_io_erepairSetFailedLanesHwp.C b/src/import/chips/p9/procedures/hwp/io/p9_io_erepairSetFailedLanesHwp.C deleted file mode 100755 index 7b32a9766..000000000 --- a/src/import/chips/p9/procedures/hwp/io/p9_io_erepairSetFailedLanesHwp.C +++ /dev/null @@ -1,1134 +0,0 @@ -/* IBM_PROLOG_BEGIN_TAG */ -/* This is an automatically generated prolog. */ -/* */ -/* $Source: src/import/chips/p9/procedures/hwp/io/p9_io_erepairSetFailedLanesHwp.C $ */ -/* */ -/* OpenPOWER HostBoot Project */ -/* */ -/* Contributors Listed Below - COPYRIGHT 2015,2017 */ -/* [+] International Business Machines Corp. */ -/* */ -/* */ -/* Licensed under the Apache License, Version 2.0 (the "License"); */ -/* you may not use this file except in compliance with the License. */ -/* You may obtain a copy of the License at */ -/* */ -/* http://www.apache.org/licenses/LICENSE-2.0 */ -/* */ -/* Unless required by applicable law or agreed to in writing, software */ -/* distributed under the License is distributed on an "AS IS" BASIS, */ -/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */ -/* implied. See the License for the specific language governing */ -/* permissions and limitations under the License. */ -/* */ -/* IBM_PROLOG_END_TAG */ -/// -/// @file p9_io_erepairSetFailedLanesHwp.C -/// @brief FW Team HWP that accesses the fail lanes of Fabric and Memory buses. -/// -//---------------------------------------------------------------------------- -// *HWP HWP Owner : Chris Steffen <cwsteffen@us.ibm.com> -// *HWP HWP Backup Owner: Gary Peterson <garyp@us.ibm.com> -// *HWP FW Owner : Sumit Kumar <sumit_kumar@in.ibm.com> -// *HWP Team : IO -// *HWP Level : 2 -// *HWP Consumed by : FSP:HB -//---------------------------------------------------------------------------- - -#include <fapi2.H> -#include <p9_io_erepairConsts.H> -#include <p9_io_erepairSetFailedLanesHwp.H> -#include <mvpd_access.H> - -using namespace EREPAIR; -using namespace fapi2; - -/****************************************************************************** - * Forward Declarations - *****************************************************************************/ - -/** - * @brief Function called by the FW Team HWP that writes the data to Field VPD. - * This function calls fapiSetMvpdField to write the VPD. - * - * @param[in] i_target Reference to X-Bus or O-Bus or MCS target - * @param[in] i_vpdType Specifies which VPD (MNFG or Field) to access. - * @param[in] i_clkGroup Specifies clock group 0:[XOA, X1A,..] 1:[X0B, X1B,..] - * @param[in] i_txFailLanes Reference to a vector that has eRepair fail - * lane numbers of the Tx sub-interface. - * @param[in] i_rxFailLanes Reference to a vector that has eRepair fail - * lane numbers of the Rx sub-interface. - * - * @return ReturnCode - */ -template<fapi2::TargetType K> -fapi2::ReturnCode writeRepairDataToVPD( - const fapi2::Target < K >& i_target, - erepairVpdType i_vpdType, - const uint8_t i_clkGroup, - const std::vector<uint8_t>& i_txFailLanes, - const std::vector<uint8_t>& i_rxFailLanes); - -/** - * @brief Function called by the FW Team HWP that updates the passed buffer - * with the eRepair faillane numbers. - * - * @param[in] i_target Reference to X-Bus or O-Bus or MCS target - * @param[in] i_txFailLanes Reference to a vector that has the Tx side faillane - * numbers that need to be updated to the o_buf buffer - * @param[in] i_rxFailLanes Reference to a vector that has the Rx side faillane - * numbers that need to be updated to the o_buf buffer - * @param[in] i_bufSz This is the size of passed buffer in terms of bytes - * @param[in] i_clkGroup Specifies clock group 0:[XOA, X1A,..] 1:[X0B, X1B,..] - * @param[o] o_buf This is the buffer that has the eRepair records - * that needs to be written to the VPD - * - * @return ReturnCode - */ -template<fapi2::TargetType K> -fapi2::ReturnCode writeRepairLanesToBuf( - const fapi2::Target < K >& i_target, - const std::vector<uint8_t>& i_txFailLanes, - const std::vector<uint8_t>& i_rxFailLanes, - const uint32_t i_bufSz, - const uint8_t i_clkGroup, - uint8_t* o_buf); - -/** - * @brief Function called by the FW Team HWP that updates the passed buffer - * with the eRepair faillane numbers of a specified interface. - * - * @param[in] i_target Reference to X-Bus or O-Bus or MCS target - * @param[in] i_interface This indicates the sub-interface type the passed - * faillane vector represents - * @param[in] i_bufSz This is the size of passed buffer in terms of bytes - * @param[in] i_clkGroup Specifies clock group 0:[XOA, X1A,..] 1:[X0B, X1B,..] - * @param[in] i_failLanes Reference to a vector that has the faillane numbers - * that need to be updated to the o_buf buffer - * @param[o] o_buf This is the buffer that has the eRepair records - * that needs to be written to the VPD - * - * @return ReturnCode - */ -template<fapi2::TargetType K> -fapi2::ReturnCode updateRepairLanesToBuf( - const fapi2::Target < K >& i_target, - const interfaceType i_interface, - const uint32_t i_bufSz, - const uint8_t i_clkGroup, - const std::vector<uint8_t>& i_failLanes, - uint8_t* o_buf); - -/** - * @brief Function called by the FW Team HWP that updates the passed buffer - * with the eRepair faillane numbers of a specified interface. - * - * @param[in] i_target Reference to X-Bus or O-Bus or MCS target - * @param[in] i_busInterface This indicates the sub-interface type the passed - * faillane vector represents - * @param[in] i_repairLane Reference to the faillane number - * that need to be updated to fail bits field - * @param[o] o_failBit This is the failed lanes data that maintains the - * eRepair record that needs to be updated with fail - * lane number - * - * @return ReturnCode - */ -template<fapi2::TargetType K> -fapi2::ReturnCode gatherRepairLanes( - const fapi2::Target < K >& i_target, - uint8_t i_busInterface, - uint8_t i_repairLane, - uint32_t* o_failBit); - - -/****************************************************************************** - * Accessor HWP - *****************************************************************************/ - -template<fapi2::TargetType K> -fapi2::ReturnCode p9_io_erepairSetFailedLanesHwp( - const fapi2::Target < K >& i_target, - erepairVpdType i_vpdType, - const uint8_t i_clkGroup, - const std::vector<uint8_t>& i_txFailLanes, - const std::vector<uint8_t>& i_rxFailLanes) -{ - fapi2::current_err = fapi2::FAPI2_RC_SUCCESS; - fapi2::Target<fapi2::TARGET_TYPE_MCS> l_mcsTgt; - - FAPI_INF(">> erepairSetFailedLanesHwp"); - - FAPI_ASSERT(( (i_txFailLanes.size() != 0) || (i_rxFailLanes.size() != 0) ), - fapi2::P9_EREPAIR_NO_RX_TX_FAILED_LANES_ERR() - .set_TX_LANE(i_txFailLanes.size()).set_RX_LANE(i_rxFailLanes.size()), - "ERROR: No Tx/Rx fail lanes were provided"); - - FAPI_TRY( writeRepairDataToVPD( - i_target, - i_vpdType, - i_clkGroup, - i_txFailLanes, - i_rxFailLanes), - "p9_io_erepairSetFailedLanesHwp() failed w/rc=0x%x", - (uint64_t)current_err ); - -fapi_try_exit: - return fapi2::current_err; -} - -template ReturnCode p9_io_erepairSetFailedLanesHwp<TARGET_TYPE_XBUS>( - const fapi2::Target <TARGET_TYPE_XBUS>& i_target, - erepairVpdType i_vpdType, - const uint8_t i_clkGroup, - const std::vector<uint8_t>& o_txFailLanes, - const std::vector<uint8_t>& o_rxFailLanes); - -template<fapi2::TargetType K> -fapi2::ReturnCode writeRepairDataToVPD( - const fapi2::Target < K >& i_target, - erepairVpdType i_vpdType, - const uint8_t i_clkGroup, - const std::vector<uint8_t>& i_txFailLanes, - const std::vector<uint8_t>& i_rxFailLanes) -{ - fapi2::ReturnCode l_rc = fapi2::FAPI2_RC_SUCCESS; - fapi2::current_err = fapi2::FAPI2_RC_SUCCESS; - fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP> l_procTarget; - std::vector<fapi2::Target<fapi2::TARGET_TYPE_MBA_CHIPLET>> l_mbaChiplets; - fapi2::Target<fapi2::TARGET_TYPE_MBA> l_mbaTarget; - - uint8_t* l_retBuf = NULL; - uint32_t l_bufSize = 0; -#ifdef P9_CUMULUS - uint8_t l_customDimm; -#endif - FAPI_DBG(">> writeRepairDataToVPD"); - - if(i_target.getType() == TARGET_TYPE_MEMBUF_CHIP) - { -#ifdef P9_CUMULUS - fapi2::MBvpdRecord l_vpdRecord = MBVPD_RECORD_VEIR; - - if(i_vpdType == EREPAIR_VPD_MNFG) - { - l_vpdRecord = MBVPD_RECORD_MER0; - } - - /*** Read the data from the FRU VPD ***/ - - // Determine the size of the eRepair data in the Centaur VPD - FAPI_TRY( getMBvpdField( - l_vpdRecord, - MBVPD_KEYWORD_PDI, - i_target, - NULL, - l_bufSize), - "VPD size read failed w/rc=0x%x", - (uint64_t)current_err ); - - // Get the connected MBA chiplet and determine whether we have CDIMM - l_rc = fapiGetChildChiplets(i_target, - fapi2::TARGET_TYPE_MBA_CHIPLET, - l_mbaChiplets, - fapi2::TARGET_STATE_FUNCTIONAL); - - FAPI_ASSERT( ((uint64_t)l_rc == 0x0) || (0 != l_mbaChiplets.size()), - fapi2::P9_EREPAIR_CHILD_MBA_TARGETS_ERR() - .set_ERROR(l_rc), - "ERROR: During get child MBA targets"); - - l_mbaTarget = l_mbaChiplets[0]; - std::vector<fapi2::Target<fapi2::TARGET_TYPE_DIMM>> l_target_dimm_array; - - FAPI_TRY( fapiGetAssociatedDimms( - l_mbaTarget, - l_target_dimm_array), - "fapiGetAssociatedDimms() failed w/rc=0x%x", - (uint64_t)current_err ); - - if(0 != l_target_dimm_array.size()) - { - FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_SPD_CUSTOM, - l_target_dimm_array[0], - l_customDimm)); - } - else - { - l_customDimm = fapi2::ENUM_ATTR_SPD_CUSTOM_NO; - } - - if( (l_customDimm == fapi2::ENUM_ATTR_SPD_CUSTOM_YES) || (l_bufSize == 0) ) - { - if((l_bufSize == 0) || - ((i_vpdType == EREPAIR_VPD_FIELD) && - (l_bufSize > EREPAIR_MEM_FIELD_VPD_SIZE_PER_CENTAUR)) || - ((i_vpdType == EREPAIR_VPD_MNFG) && - (l_bufSize > EREPAIR_MEM_MNFG_VPD_SIZE_PER_CENTAUR))) - { - FAPI_ASSERT(false, - fapi2::P9_EREPAIR_ACCESSOR_HWP_INVALID_MEM_VPD_SIZE_ERR() - .set_ERROR(current_err), - "ERROR: Invalid MEM VPD size"); - } - } - - // Allocate memory for buffer - l_retBuf = new uint8_t[l_bufSize]; - - FAPI_ASSERT(l_retBuf != NULL, - fapi2::P9_EREPAIR_ACCESSOR_HWP_MEMORY_ALLOC_FAIL_ERR() - .set_BUF_SIZE(l_bufSize), - "ERROR: Failed to allocate memory size"); - - // Retrieve the Field eRepair data from the Centaur FRU VPD - FAPI_TRY( getMBvpdField( - l_vpdRecord, - MBVPD_KEYWORD_PDI, - i_target, - l_retBuf, - l_bufSize), - "Centaur FRU VPD read failed w/rc=0x%x", - (uint64_t)current_err ); - - /*** Update the new eRepair data to the buffer ***/ - FAPI_TRY( writeRepairLanesToBuf( - i_target, - i_txFailLanes, - i_rxFailLanes, - l_bufSize, - i_clkGroup, - l_retBuf), - "Update erepair data to buffer failed w/rc=0x%x", - (uint64_t)current_err ); - - /*** Write the updated eRepair buffer back to Centaur FRU VPD ***/ - FAPI_TRY( setMBvpdField( - l_vpdRecord, - MBVPD_KEYWORD_PDI, - i_target, - l_retBuf, - l_bufSize), - "Update erepair data to VPD failed w/rc=0x%x", - (uint64_t)current_err ); -#endif - } // end of(targetType == MEMBUF) - else - { - // Determine the Processor target - l_procTarget = i_target.template getParent<TARGET_TYPE_PROC_CHIP>(); - - fapi2::MvpdRecord l_vpdRecord = MVPD_RECORD_VWML; - - if(i_vpdType == EREPAIR_VPD_MNFG) - { - l_vpdRecord = MVPD_RECORD_MER0; - } - - /*** Read the data from the Module VPD ***/ - - // Determine the size of the eRepair data in the VPD - FAPI_TRY( getMvpdField( - l_vpdRecord, - MVPD_KEYWORD_PDI, - l_procTarget, - NULL, - l_bufSize), - "VPD size read failed w/rc=0x%x", - (uint64_t)current_err ); - - if((l_bufSize == 0) || - ((i_vpdType == EREPAIR_VPD_FIELD) && - (l_bufSize > EREPAIR_P9_MODULE_VPD_FIELD_SIZE)) || - ((i_vpdType == EREPAIR_VPD_MNFG) && - (l_bufSize > EREPAIR_P9_MODULE_VPD_MNFG_SIZE))) - { - FAPI_ASSERT(false, - fapi2::P9_EREPAIR_ACCESSOR_HWP_INVALID_FABRIC_VPD_SIZE_ERR() - .set_ERROR(current_err), - "ERROR: Invalid Fabric VPD size"); - } - - // Allocate memory for buffer - l_retBuf = new uint8_t[l_bufSize]; - - FAPI_ASSERT(l_retBuf != NULL, - fapi2::P9_EREPAIR_ACCESSOR_HWP_MEMORY_ALLOC_FAIL_ERR() - .set_BUF_SIZE(l_bufSize), - "ERROR: Failed to allocate memory size"); - - // Retrieve the Field eRepair data from the MVPD - FAPI_TRY( getMvpdField( - l_vpdRecord, - MVPD_KEYWORD_PDI, - l_procTarget, - l_retBuf, - l_bufSize), - "VPD read failed w/rc=0x%x", - (uint64_t)current_err ); - - /*** Update the new eRepair data to the buffer ***/ - FAPI_TRY( writeRepairLanesToBuf( - i_target, - i_txFailLanes, - i_rxFailLanes, - l_bufSize, - i_clkGroup, - l_retBuf), - "writeRepairLanesToBuf() failed w/rc=0x%x", - (uint64_t)current_err ); - - /*** Write the updated eRepair buffer back to MVPD ***/ - FAPI_TRY( setMvpdField( - l_vpdRecord, - MVPD_KEYWORD_PDI, - l_procTarget, - l_retBuf, - l_bufSize), - "setMvpdField()-Update erepair data to VPD failed w/rc=0x%x", - (uint64_t)current_err ); - } - - // Delete the buffer which has Field eRepair data - delete[] l_retBuf; - -fapi_try_exit: - return fapi2::current_err; -} - - -template<fapi2::TargetType K> -fapi2::ReturnCode writeRepairLanesToBuf( - const fapi2::Target < K >& i_target, - const std::vector<uint8_t>& i_txFailLanes, - const std::vector<uint8_t>& i_rxFailLanes, - const uint32_t i_bufSz, - const uint8_t i_clkGroup, - uint8_t* o_buf) -{ - fapi2::current_err = fapi2::FAPI2_RC_SUCCESS; - - FAPI_DBG(">> writeRepairLanesToBuf"); - - if(i_txFailLanes.size()) - { - /*** Lets update the tx side fail lane vector to the VPD ***/ - FAPI_TRY( updateRepairLanesToBuf( - i_target, - DRIVE, - i_bufSz, - i_clkGroup, - i_txFailLanes, - o_buf), - "updateRepairLanesToBuf(DRIVE) failed w/rc=0x%x", - (uint64_t)current_err ); - } - - if(i_rxFailLanes.size()) - { - /*** Lets update the rx side fail lane vector to the VPD ***/ - FAPI_TRY( updateRepairLanesToBuf( - i_target, - RECEIVE, - i_bufSz, - i_clkGroup, - i_rxFailLanes, - o_buf), - "updateRepairLanesToBuf(RECEIVE) failed w/rc=0x%x", - (uint64_t)current_err ); - } - -fapi_try_exit: - return fapi2::current_err; -} - -template<fapi2::TargetType K> -fapi2::ReturnCode updateRepairLanesToBuf( - const fapi2::Target < K >& i_target, - const interfaceType i_interface, - const uint32_t i_bufSz, - const uint8_t i_clkGroup, - const std::vector<uint8_t>& i_failLanes, - uint8_t* o_buf) -{ - fapi2::current_err = fapi2::FAPI2_RC_SUCCESS; - uint32_t l_numRepairs = 0; - uint32_t l_newNumRepairs = 0; - uint32_t l_repairCnt = 0; - uint32_t l_bytesParsed = 0; - uint8_t l_repairLane = 0; - uint32_t l_repairDataSz = 0; - uint8_t* l_vpdPtr = NULL; - uint8_t* l_vpdDataPtr = NULL; - uint8_t* l_vpdWritePtr = NULL; - eRepairHeader* l_vpdHeadPtr = NULL; - eRepairPowerBus* l_overWritePtr = NULL; - bool l_overWrite = false; - uint8_t l_chipNum = 0; - uint32_t l_chipPosition = 0; - bool l_bClkGroupFound = false; -#ifdef P9_CUMULUS - fapi2::Target<fapi2::TARGET_TYPE_MCS> l_mcsTarget; -#endif - std::vector<uint8_t>::const_iterator l_it; - ATTR_CHIP_UNIT_POS_Type l_busNum; - - FAPI_DBG(">> updateRepairLanesToBuf, interface: %s", - i_interface == DRIVE ? "Drive" : "Receive"); - - { - l_repairDataSz = sizeof(eRepairPowerBus); // Size of memory Bus and - // fabric Bus eRepair data - // is same. - // Read the header and count information - l_vpdPtr = o_buf; // point to the start of header data - l_vpdHeadPtr = reinterpret_cast<eRepairHeader*> (l_vpdPtr); - - l_numRepairs = l_newNumRepairs = l_vpdHeadPtr->availNumRecord; - - // We've read the header data, increment bytes parsed - l_bytesParsed = sizeof(eRepairHeader); - - // Get a pointer to the start of repair data - l_vpdPtr += sizeof(eRepairHeader); - - if(i_target.getType() == fapi2::TARGET_TYPE_MEMBUF_CHIP) - { -#ifdef P9_CUMULUS - FAPI_TRY( fapiGetOtherSideOfMemChannel( - i_target, - l_mcsTarget, - fapi2::TARGET_STATE_FUNCTIONAL), - "fapiGetOtherSideOfMemChannel() failed w/rc=0x%x", - (uint64_t)current_err ); - - // Get the bus number - FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CHIP_UNIT_POS, - l_mcsTarget, - l_busNum)); -#endif - } - else - { - // Get the bus number - FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CHIP_UNIT_POS, - i_target, - l_busNum)); - } - - // Get the chip target - fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP> l_chipTarget; - l_chipTarget = i_target.template getParent<TARGET_TYPE_PROC_CHIP>(); - - // Get the chip number - FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_POS, - l_chipTarget, - l_chipPosition)); - - - // This is needed because we can only store and compare a uint8_t - // value. For our purpose the value in l_chipPosition (Proc Position and - // Centaur Position) will always be within the range of uint8_t - l_chipNum = l_chipPosition; - - /*** Lets update the fail lane vector to the Buffer ***/ - // Create a structure of eRepair data that we will be matching - // in the buffer. - struct erepairDataMatch - { - interfaceType intType; - fapi2::TargetType tgtType; - union repairData - { - eRepairPowerBus fabBus; - eRepairMemBus memBus; - } bus; - }; - - // Create an array of the above match structure to have all the - // combinations of Fabric and Memory repair data - erepairDataMatch l_repairMatch[14] = - { - { - // index 0 - X0A (clock group 0) - DRIVE, - TARGET_TYPE_XBUS_ENDPOINT, - { - // repairData - { - // fabBus - { - // device - l_chipNum,// processor_id - l_busNum, // fabricBus - }, - PROCESSOR_EDIP, // type - PBUS_DRIVER, // interface - }, - }, - }, - { - // index 1 - X0A (clock group 0) - RECEIVE, - TARGET_TYPE_XBUS_ENDPOINT, - { - // repairData - { - // fabBus - { - // device - l_chipNum,// processor_id - l_busNum, // fabricBus - }, - PROCESSOR_EDIP, // type - PBUS_RECEIVER, // interface - }, - }, - }, - { - // index 2 - X0A (clock group 1) - DRIVE, - TARGET_TYPE_XBUS_ENDPOINT, - { - // repairData - { - // fabBus - { - // device - l_chipNum,// processor_id - l_busNum, // fabricBus - }, - PROCESSOR_EDIP, // type - PBUS_DRIVER, // interface - }, - }, - }, - { - // index 3 - X0A (clock group 1) - RECEIVE, - TARGET_TYPE_XBUS_ENDPOINT, - { - // repairData - { - // fabBus - { - // device - l_chipNum,// processor_id - l_busNum, // fabricBus - }, - PROCESSOR_EDIP, // type - PBUS_RECEIVER, // interface - }, - }, - }, - { - // index 4 - X1A (clock group 0) - DRIVE, - TARGET_TYPE_XBUS_ENDPOINT, - { - // repairData - { - // fabBus - { - // device - l_chipNum,// processor_id - l_busNum, // fabricBus - }, - PROCESSOR_EDIP, // type - PBUS_DRIVER, // interface - }, - }, - }, - { - // index 5 - X1A (clock group 0) - RECEIVE, - TARGET_TYPE_XBUS_ENDPOINT, - { - // repairData - { - // fabBus - { - // device - l_chipNum,// processor_id - l_busNum, // fabricBus - }, - PROCESSOR_EDIP, // type - PBUS_RECEIVER, // interface - }, - }, - }, - { - // index 6 - X1A (clock group 1) - DRIVE, - TARGET_TYPE_XBUS_ENDPOINT, - { - // repairData - { - // fabBus - { - // device - l_chipNum,// processor_id - l_busNum, // fabricBus - }, - PROCESSOR_EDIP, // type - PBUS_DRIVER, // interface - }, - }, - }, - { - // index 7 - X1A (clock group 1) - RECEIVE, - TARGET_TYPE_XBUS_ENDPOINT, - { - // repairData - { - // fabBus - { - // device - l_chipNum,// processor_id - l_busNum, // fabricBus - }, - PROCESSOR_EDIP, // type - PBUS_RECEIVER, // interface - }, - }, - }, - { - // index 8 - DRIVE, - TARGET_TYPE_OBUS, - { - // repairData - { - // fabBus - { - // device - l_chipNum,// processor_id - l_busNum, // fabricBus - }, - PROCESSOR_OPT, // type - PBUS_DRIVER, // interface - }, - }, - }, - { - // index 9 - RECEIVE, - TARGET_TYPE_OBUS, - { - // repairData - { - // fabBus - { - // device - l_chipNum,// processor_id - l_busNum, // fabricBus - }, - PROCESSOR_OPT, // type - PBUS_RECEIVER, // interface - }, - }, - }, - { - // index 10 - DRIVE, - TARGET_TYPE_MCS_CHIPLET, - { - // repairData - { - // fabBus - { - // device - l_chipNum,// proc_centaur_id - l_busNum, // memChannel - }, - MEMORY_EDIP, // type - DMI_MCS_DRIVE,// interface - }, - }, - }, - { - // index 11 - DRIVE, - TARGET_TYPE_MEMBUF_CHIP, - { - // repairData - { - // memBus - { - // device - l_chipNum,// proc_centaur_id - l_busNum, // memChannel - }, - MEMORY_EDIP, // type - DMI_MEMBUF_DRIVE,// interface - }, - }, - }, - { - // index 12 - RECEIVE, - TARGET_TYPE_MCS_CHIPLET, - { - // repairData - { - // memBus - { - // device - l_chipNum,// proc_centaur_id - l_busNum, // memChannel - }, - MEMORY_EDIP, // type - DMI_MCS_RECEIVE, // interface - }, - }, - }, - { - // index 13 - RECEIVE, - TARGET_TYPE_MEMBUF_CHIP, - { - // repairData - { - // memBus - { - // device - l_chipNum,// proc_centaur_id - l_busNum, // memChannel - }, - MEMORY_EDIP, // type - DMI_MEMBUF_RECEIVE, // interface - }, - }, - } - }; - - l_vpdDataPtr = l_vpdPtr; - l_repairCnt = 0; - - // Pick each faillane for copying into buffer - for(l_it = i_failLanes.begin(); - l_it != i_failLanes.end(); - l_it++, (l_vpdDataPtr += l_repairDataSz)) - { - l_repairLane = *l_it; - l_overWrite = false; - l_vpdWritePtr = NULL; - - // Parse the VPD for fabric and memory eRepair records - for(; - (l_repairCnt < l_numRepairs) && (l_bytesParsed <= i_bufSz); - l_repairCnt++, (l_vpdDataPtr += l_repairDataSz)) - { - l_overWritePtr = - reinterpret_cast<eRepairPowerBus*> (l_vpdDataPtr); - - // Lets find the matching fabric - for(uint8_t l_loop = 0; l_loop < 14; l_loop++) - { - if((i_target.getType() == TARGET_TYPE_XBUS) || - (i_target.getType() == TARGET_TYPE_OBUS)) - { - if((i_interface == l_repairMatch[l_loop].intType) && - (i_target.getType() == l_repairMatch[l_loop].tgtType) && - ((l_overWritePtr->device).processor_id == - l_repairMatch[l_loop].bus.fabBus.device.processor_id) && - (l_overWritePtr->type == - l_repairMatch[l_loop].bus.fabBus.type) && - (l_overWritePtr->interface == - l_repairMatch[l_loop].bus.fabBus.interface) && - (l_overWritePtr->device.fabricBus == - l_repairMatch[l_loop].bus.fabBus.device.fabricBus)) - { - if(i_clkGroup > 0 && !l_bClkGroupFound) - { - l_bClkGroupFound = true; - continue; - } - - // update the failBit number - { - uint32_t temp = (uint32_t)(l_overWritePtr->failBit); - uint32_t* tptr = &temp; - FAPI_TRY( gatherRepairLanes( - i_target, - l_overWritePtr->interface, - l_repairLane, - tptr), - "gatherRepairLanes() failed w/rc=0x%x", - (uint64_t)current_err ); - l_overWritePtr->failBit = temp; - } - - // Increment the count of parsed bytes - l_bytesParsed += l_repairDataSz; - - l_repairCnt++; - l_overWrite = true; - - break; - } - } - else if((i_target.getType() == TARGET_TYPE_MCS_CHIPLET) || - (i_target.getType() == TARGET_TYPE_MEMBUF_CHIP) ) - { - if((i_interface == l_repairMatch[l_loop].intType) && - (i_target.getType() == l_repairMatch[l_loop].tgtType) && - ((l_overWritePtr->device).processor_id == - l_repairMatch[l_loop].bus.memBus.device.proc_centaur_id) && - (l_overWritePtr->type == - l_repairMatch[l_loop].bus.memBus.type) && - (l_overWritePtr->interface == - l_repairMatch[l_loop].bus.memBus.interface) && - (l_overWritePtr->device.fabricBus == - l_repairMatch[l_loop].bus.memBus.device.memChannel)) - { - // update the failBit number - { - uint32_t temp = (uint32_t)(l_overWritePtr->failBit); - uint32_t* tptr = &temp; - FAPI_TRY( gatherRepairLanes( - i_target, - l_overWritePtr->interface, - l_repairLane, - tptr), - "gatherRepairLanes() failed w/rc=0x%x", - (uint64_t)current_err ); - l_overWritePtr->failBit = temp; - } - - // Increment the count of parsed bytes - l_bytesParsed += l_repairDataSz; - - l_repairCnt++; - l_overWrite = true; - - break; - } - } - } // end of for(l_loop < 14) - - if(l_overWrite == true) - { - // Go for the next repairLane - break; - } - } // end of for(vpd Parsing) - - // Check if we have parsed more bytes than the passed size - if((l_vpdWritePtr == NULL) && - (l_bytesParsed > i_bufSz) && - (l_repairCnt < l_numRepairs)) - { - FAPI_ASSERT(false, - fapi2::P9_EREPAIR_MVPD_FULL_ERR() - .set_VAL_BYTE_PARSED(l_bytesParsed) - .set_VAL_BUF_SIZE(i_bufSz) - .set_VAL_REPAIR_CNT(l_repairCnt) - .set_VAL_NUM_REPAIR(l_numRepairs), - "ERROR: from updateRepairLanesToBuf - MVPD full"); - } - - // Add at the end - if(l_overWrite == false) - { - if(l_vpdWritePtr == NULL) - { - // We are writing at the end - l_vpdWritePtr = l_vpdDataPtr; - } - - if((i_target.getType() == TARGET_TYPE_XBUS) || - (i_target.getType() == TARGET_TYPE_OBUS)) - { - // Make sure we are not writing more records than the size - // allocated in the VPD - FAPI_ASSERT(l_bytesParsed <= i_bufSz, - fapi2::P9_EREPAIR_MVPD_FULL_ERR() - .set_VAL_BYTE_PARSED(l_bytesParsed) - .set_VAL_BUF_SIZE(i_bufSz) - .set_VAL_REPAIR_CNT(l_repairCnt) - .set_VAL_NUM_REPAIR(l_numRepairs), - "ERROR: from updateRepairLanesToBuf - MVPD full"); - - eRepairPowerBus* l_fabricBus = - reinterpret_cast<eRepairPowerBus*>(l_vpdWritePtr); - - l_fabricBus->device.processor_id = l_chipNum; - l_fabricBus->device.fabricBus = l_busNum; - - if(i_interface == DRIVE) - { - l_fabricBus->interface = PBUS_DRIVER; - } - else if(i_interface == RECEIVE) - { - l_fabricBus->interface = PBUS_RECEIVER; - } - - if(i_target.getType() == TARGET_TYPE_XBUS) - { - l_fabricBus->type = PROCESSOR_EDIP; - } - else if(i_target.getType() == TARGET_TYPE_OBUS) - { - l_fabricBus->type = PROCESSOR_OPT; - } - - { - uint32_t temp = (uint32_t)(l_fabricBus->failBit); - uint32_t* tptr = &temp; - FAPI_TRY( gatherRepairLanes( - i_target, - l_fabricBus->interface, - l_repairLane, - tptr), - "gatherRepairLanes() failed w/rc=0x%x", - (uint64_t)current_err ); - l_fabricBus->failBit = temp; - } - - l_newNumRepairs++; - - // Increment the count of parsed bytes - l_bytesParsed += l_repairDataSz; -#ifndef _BIG_ENDIAN - // We are on a Little Endian system. - // Need to swap the nibbles of structure - eRepairPowerBus - - l_vpdWritePtr[2] = ((l_vpdWritePtr[2] >> 4) | - (l_vpdWritePtr[2] << 4)); -#endif - } - else if((i_target.getType() == TARGET_TYPE_MCS_CHIPLET) || - (i_target.getType() == TARGET_TYPE_MEMBUF_CHIP) ) - { - // Make sure we are not writing more records than the size - // allocated in the VPD - FAPI_ASSERT(l_bytesParsed == i_bufSz, - fapi2::P9_EREPAIR_MBVPD_FULL_ERR() - .set_ERROR(l_bytesParsed), - "ERROR: from updateRepairLanesToBuf - MBVPD full"); - - eRepairMemBus* l_memBus = - reinterpret_cast<eRepairMemBus*>(l_vpdWritePtr); - - l_memBus->device.proc_centaur_id = l_chipNum; - l_memBus->device.memChannel = l_busNum; - l_memBus->type = MEMORY_EDIP; - - if(i_interface == DRIVE) - { - if(i_target.getType() == TARGET_TYPE_MCS_CHIPLET) - { - l_memBus->interface = DMI_MCS_DRIVE; - } - else if(i_target.getType() == TARGET_TYPE_MEMBUF_CHIP) - { - l_memBus->interface = DMI_MEMBUF_DRIVE; - } - } - else if(i_interface == RECEIVE) - { - if(i_target.getType() == TARGET_TYPE_MCS_CHIPLET) - { - l_memBus->interface = DMI_MCS_RECEIVE; - } - else if(i_target.getType() == TARGET_TYPE_MEMBUF_CHIP) - { - l_memBus->interface = DMI_MEMBUF_RECEIVE; - } - } - - { - uint32_t temp = (uint32_t)(l_memBus->failBit); - uint32_t* tptr = &temp; - FAPI_TRY( gatherRepairLanes( - i_target, - l_memBus->interface, - l_repairLane, - tptr), - "gatherRepairLanes() failed w/rc=0x%x", - (uint64_t)current_err ); - l_memBus->failBit = temp; - } - - l_newNumRepairs++; - - // Increment the count of parsed bytes - l_bytesParsed += l_repairDataSz; -#ifndef _BIG_ENDIAN - // We are on a Little Endian system. - // Need to swap the nibbles of structure - eRepairMemBus - - l_vpdWritePtr[2] = ((l_vpdWritePtr[2] >> 4) | - (l_vpdWritePtr[2] << 4)); -#endif - } - } // end of if(l_overWrite == false) - } // end of for(failLanes) - } - // Update the eRepair count - l_vpdHeadPtr->availNumRecord = l_newNumRepairs; - -fapi_try_exit: - return fapi2::current_err; -} - -template<fapi2::TargetType K> -fapi2::ReturnCode gatherRepairLanes( - const fapi2::Target < K >& i_target, - uint8_t i_busInterface, - uint8_t i_repairLane, - uint32_t* o_failBit) -{ - fapi2::ReturnCode l_rc; - uint8_t maxBusLanes = 0; - uint32_t setBitPosition = (0x80000000); - - FAPI_DBG(">> setRepairLanes"); - - // Check for target type and corresponding sub interface - // to get max lanes supported per interface - if(i_target.getType() == fapi2::TARGET_TYPE_OBUS) - { - maxBusLanes = OBUS_MAX_LANE_WIDTH; //OBUS - } - else if(i_target.getType() == fapi2::TARGET_TYPE_XBUS) - { - maxBusLanes = XBUS_MAX_LANE_WIDTH; //XBUS - } - else if((i_target.getType() == fapi2::TARGET_TYPE_MEMBUF_CHIP) || - (i_target.getType() == fapi2::TARGET_TYPE_MCS_CHIPLET)) //DMI - { - if( (i_busInterface == DMI_MCS_RECEIVE) || - (i_busInterface == DMI_MEMBUF_DRIVE) ) - { - maxBusLanes = DMIBUS_DNSTREAM_MAX_LANE_WIDTH; - } - else if( (i_busInterface == DMI_MCS_DRIVE) || - (i_busInterface == DMI_MEMBUF_RECEIVE) ) - { - maxBusLanes = DMIBUS_UPSTREAM_MAX_LANE_WIDTH; - } - } - - // Make sure repair lane value passed is within valid range as per the target type - FAPI_ASSERT(i_repairLane < maxBusLanes, - fapi2::P9_EREPAIR_INVALID_LANE_VALUE_ERR() - .set_ERROR(i_repairLane) - .set_TARGET(i_target), - "ERROR: Invalid erepair lane value"); - - // Update the fail bits data with the repair lane number failed - *o_failBit |= (setBitPosition >> i_repairLane); - - // Get the failed lanes - FAPI_INF("Updated Fail Lanes:%x", *o_failBit); - - FAPI_DBG("<< setRepairLanes"); - -fapi_try_exit: - return l_rc; -} - diff --git a/src/import/chips/p9/procedures/hwp/io/p9_io_erepairSetFailedLanesHwp.H b/src/import/chips/p9/procedures/hwp/io/p9_io_erepairSetFailedLanesHwp.H index ba51290cd..bf4897201 100755 --- a/src/import/chips/p9/procedures/hwp/io/p9_io_erepairSetFailedLanesHwp.H +++ b/src/import/chips/p9/procedures/hwp/io/p9_io_erepairSetFailedLanesHwp.H @@ -5,7 +5,7 @@ /* */ /* OpenPOWER HostBoot Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2015,2017 */ +/* Contributors Listed Below - COPYRIGHT 2015,2018 */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -40,40 +40,2184 @@ #include <fapi2.H> #include <p9_io_erepairConsts.H> +#include <mvpd_access.H> +#include <fapi2_mbvpd_access.H> + +/****************************************************************************** + * Accessor HWP + *****************************************************************************/ + +/** + * @brief Function called by the FW Team HWP that updates the passed buffer + * with the eRepair faillane numbers of a specified interface. + * + * @param[in] i_target Reference to X-Bus or O-Bus or DMI target + * @param[in] i_busInterface This indicates the sub-interface type the passed + * faillane vector represents + * @param[in] i_repairLane Reference to the faillane number + * that need to be updated to fail bits field + * @param[o] o_failBit This is the failed lanes data that maintains the + * eRepair record that needs to be updated with fail + * lane number + * + * @return ReturnCode + */ +template<fapi2::TargetType K> +fapi2::ReturnCode gatherRepairLanes( + const fapi2::Target < K >& i_target, + uint8_t i_busInterface, + uint8_t i_repairLane, + uint32_t* o_failBit) +{ + fapi2::ReturnCode l_rc; + uint8_t maxBusLanes = 0; + uint32_t setBitPosition = (0x80000000); + + FAPI_DBG(">> setRepairLanes"); + + // Check for target type and corresponding sub interface + // to get max lanes supported per interface + if(i_target.getType() == fapi2::TARGET_TYPE_OBUS) + { + maxBusLanes = EREPAIR::OBUS_MAX_LANE_WIDTH; //OBUS + } + else if(i_target.getType() == fapi2::TARGET_TYPE_XBUS) + { + maxBusLanes = EREPAIR::XBUS_MAX_LANE_WIDTH; //XBUS + } + else if((i_target.getType() == fapi2::TARGET_TYPE_MEMBUF_CHIP) || + (i_target.getType() == fapi2::TARGET_TYPE_DMI)) + { + if( (i_busInterface == EREPAIR::DMI_MCS_RECEIVE) || + (i_busInterface == EREPAIR::DMI_MEMBUF_DRIVE) ) + { + maxBusLanes = EREPAIR::DMIBUS_DNSTREAM_MAX_LANE_WIDTH; + } + else if( (i_busInterface == EREPAIR::DMI_MCS_DRIVE) || + (i_busInterface == EREPAIR::DMI_MEMBUF_RECEIVE) ) + { + maxBusLanes = EREPAIR::DMIBUS_UPSTREAM_MAX_LANE_WIDTH; + } + } + + // Make sure repair lane value passed is within valid range as per the target type + FAPI_ASSERT(i_repairLane < maxBusLanes, + fapi2::P9_EREPAIR_INVALID_LANE_VALUE_ERR() + .set_ERROR(i_repairLane) + .set_TARGET(i_target), + "ERROR: Invalid erepair lane value"); + + // Update the fail bits data with the repair lane number failed + *o_failBit |= (setBitPosition >> i_repairLane); + + // Get the failed lanes + FAPI_INF("Updated Fail Lanes:%x", *o_failBit); + + FAPI_DBG("<< setRepairLanes"); + +fapi_try_exit: + return l_rc; +} + +/** + * @brief Function called by the FW Team HWP that updates the passed buffer + * with the eRepair faillane numbers of a specified interface. + * + * @param[in] i_target Reference to X-Bus target + * @param[in] i_interface This indicates the sub-interface type the passed + * faillane vector represents + * @param[in] i_bufSz This is the size of passed buffer in terms of bytes + * @param[in] i_clkGroup Specifies clock group 0:[XOA, X1A,..] 1:[X0B, X1B,..] + * @param[in] i_failLanes Reference to a vector that has the faillane numbers + * that need to be updated to the o_buf buffer + * @param[o] o_buf This is the buffer that has the eRepair records + * that needs to be written to the VPD + * (For Proc) + * @return ReturnCode + */ +template<fapi2::TargetType K> +fapi2::ReturnCode updateRepairLanesToBufProc( + const fapi2::Target < K >& i_target, + const EREPAIR::interfaceType i_interface, + const uint32_t i_bufSz, + const uint8_t i_clkGroup, + const std::vector<uint8_t>& i_failLanes, + uint8_t* o_buf) +{ + fapi2::current_err = fapi2::FAPI2_RC_SUCCESS; + uint32_t l_numRepairs = 0; + uint32_t l_newNumRepairs = 0; + uint32_t l_repairCnt = 0; + uint32_t l_bytesParsed = 0; + uint8_t l_repairLane = 0; + uint32_t l_repairDataSz = 0; + uint8_t* l_vpdPtr = NULL; + uint8_t* l_vpdDataPtr = NULL; + uint8_t* l_vpdWritePtr = NULL; + eRepairHeader* l_vpdHeadPtr = NULL; + eRepairPowerBus* l_overWritePtr = NULL; + bool l_overWrite = false; + uint8_t l_chipNum = 0; + uint32_t l_chipPosition = 0; + bool l_bClkGroupFound = false; + fapi2::Target<fapi2::TARGET_TYPE_DMI> l_dmiTarget; + std::vector<uint8_t>::const_iterator l_it; + fapi2::ATTR_CHIP_UNIT_POS_Type l_busNum; + + FAPI_DBG(">> updateRepairLanesToBuf(XBUS), interface: %s", + i_interface == EREPAIR::DRIVE ? "Drive" : "Receive"); + + { + l_repairDataSz = sizeof(eRepairPowerBus); // Size of memory Bus and + // fabric Bus eRepair data + // is same. + // Read the header and count information + l_vpdPtr = o_buf; // point to the start of header data + l_vpdHeadPtr = reinterpret_cast<eRepairHeader*> (l_vpdPtr); + + l_numRepairs = l_newNumRepairs = l_vpdHeadPtr->availNumRecord; + + // We've read the header data, increment bytes parsed + l_bytesParsed = sizeof(eRepairHeader); + + // Get a pointer to the start of repair data + l_vpdPtr += sizeof(eRepairHeader); + + // Get the bus number + FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CHIP_UNIT_POS, + i_target, + l_busNum)); + + // Get the chip target + fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP> l_chipTarget; + l_chipTarget = i_target.template getParent<fapi2::TARGET_TYPE_PROC_CHIP>(); + + // Get the chip number + FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_POS, + l_chipTarget, + l_chipPosition)); + + + // This is needed because we can only store and compare a uint8_t + // value. For our purpose the value in l_chipPosition (Proc Position and + // Centaur Position) will always be within the range of uint8_t + l_chipNum = l_chipPosition; + + /*** Lets update the fail lane vector to the Buffer ***/ + // Create a structure of eRepair data that we will be matching + // in the buffer. + struct erepairDataMatch + { + EREPAIR::interfaceType intType; + fapi2::TargetType tgtType; + union repairData + { + eRepairPowerBus fabBus; + eRepairMemBus memBus; + } bus; + }; + + // Create an array of the above match structure to have all the + // combinations of Fabric and Memory repair data + erepairDataMatch l_repairMatch[14] = + { + { + // index 0 - X0A (clock group 0) + EREPAIR::DRIVE, + fapi2::TARGET_TYPE_XBUS_ENDPOINT, + { + // repairData + { + // fabBus + { + // device + l_chipNum,// processor_id + l_busNum, // fabricBus + }, + EREPAIR::PROCESSOR_EDIP, // type + EREPAIR::PBUS_DRIVER, // interface + }, + }, + }, + { + // index 1 - X0A (clock group 0) + EREPAIR::RECEIVE, + fapi2::TARGET_TYPE_XBUS_ENDPOINT, + { + // repairData + { + // fabBus + { + // device + l_chipNum,// processor_id + l_busNum, // fabricBus + }, + EREPAIR::PROCESSOR_EDIP, // type + EREPAIR::PBUS_RECEIVER, // interface + }, + }, + }, + { + // index 2 - X0A (clock group 1) + EREPAIR::DRIVE, + fapi2::TARGET_TYPE_XBUS_ENDPOINT, + { + // repairData + { + // fabBus + { + // device + l_chipNum,// processor_id + l_busNum, // fabricBus + }, + EREPAIR::PROCESSOR_EDIP, // type + EREPAIR::PBUS_DRIVER, // interface + }, + }, + }, + { + // index 3 - X0A (clock group 1) + EREPAIR::RECEIVE, + fapi2::TARGET_TYPE_XBUS_ENDPOINT, + { + // repairData + { + // fabBus + { + // device + l_chipNum,// processor_id + l_busNum, // fabricBus + }, + EREPAIR::PROCESSOR_EDIP, // type + EREPAIR::PBUS_RECEIVER, // interface + }, + }, + }, + { + // index 4 - X1A (clock group 0) + EREPAIR::DRIVE, + fapi2::TARGET_TYPE_XBUS_ENDPOINT, + { + // repairData + { + // fabBus + { + // device + l_chipNum,// processor_id + l_busNum, // fabricBus + }, + EREPAIR::PROCESSOR_EDIP, // type + EREPAIR::PBUS_DRIVER, // interface + }, + }, + }, + { + // index 5 - X1A (clock group 0) + EREPAIR::RECEIVE, + fapi2::TARGET_TYPE_XBUS_ENDPOINT, + { + // repairData + { + // fabBus + { + // device + l_chipNum,// processor_id + l_busNum, // fabricBus + }, + EREPAIR::PROCESSOR_EDIP, // type + EREPAIR::PBUS_RECEIVER, // interface + }, + }, + }, + { + // index 6 - X1A (clock group 1) + EREPAIR::DRIVE, + fapi2::TARGET_TYPE_XBUS_ENDPOINT, + { + // repairData + { + // fabBus + { + // device + l_chipNum,// processor_id + l_busNum, // fabricBus + }, + EREPAIR::PROCESSOR_EDIP, // type + EREPAIR::PBUS_DRIVER, // interface + }, + }, + }, + { + // index 7 - X1A (clock group 1) + EREPAIR::RECEIVE, + fapi2::TARGET_TYPE_XBUS_ENDPOINT, + { + // repairData + { + // fabBus + { + // device + l_chipNum,// processor_id + l_busNum, // fabricBus + }, + EREPAIR::PROCESSOR_EDIP, // type + EREPAIR::PBUS_RECEIVER, // interface + }, + }, + }, + { + // index 8 + EREPAIR::DRIVE, + fapi2::TARGET_TYPE_OBUS, + { + // repairData + { + // fabBus + { + // device + l_chipNum,// processor_id + l_busNum, // fabricBus + }, + EREPAIR::PROCESSOR_OPT, // type + EREPAIR::PBUS_DRIVER, // interface + }, + }, + }, + { + // index 9 + EREPAIR::RECEIVE, + fapi2::TARGET_TYPE_OBUS, + { + // repairData + { + // fabBus + { + // device + l_chipNum,// processor_id + l_busNum, // fabricBus + }, + EREPAIR::PROCESSOR_OPT, // type + EREPAIR::PBUS_RECEIVER, // interface + }, + }, + }, + { + // index 10 + EREPAIR::DRIVE, + fapi2::TARGET_TYPE_DMI, + { + // repairData + { + // fabBus + { + // device + l_chipNum,// proc_centaur_id + l_busNum, // memChannel + }, + EREPAIR::MEMORY_EDIP, // type + EREPAIR::DMI_MCS_DRIVE,// interface + }, + }, + }, + { + // index 11 + EREPAIR::DRIVE, + fapi2::TARGET_TYPE_MEMBUF_CHIP, + { + // repairData + { + // memBus + { + // device + l_chipNum,// proc_centaur_id + l_busNum, // memChannel + }, + EREPAIR::MEMORY_EDIP, // type + EREPAIR::DMI_MEMBUF_DRIVE,// interface + }, + }, + }, + { + // index 12 + EREPAIR::RECEIVE, + fapi2::TARGET_TYPE_DMI, + { + // repairData + { + // memBus + { + // device + l_chipNum,// proc_centaur_id + l_busNum, // memChannel + }, + EREPAIR::MEMORY_EDIP, // type + EREPAIR::DMI_MCS_RECEIVE, // interface + }, + }, + }, + { + // index 13 + EREPAIR::RECEIVE, + fapi2::TARGET_TYPE_MEMBUF_CHIP, + { + // repairData + { + // memBus + { + // device + l_chipNum,// proc_centaur_id + l_busNum, // memChannel + }, + EREPAIR::MEMORY_EDIP, // type + EREPAIR::DMI_MEMBUF_RECEIVE, // interface + }, + }, + } + }; + + l_vpdDataPtr = l_vpdPtr; + l_repairCnt = 0; + + // Pick each faillane for copying into buffer + for(l_it = i_failLanes.begin(); + l_it != i_failLanes.end(); + l_it++, (l_vpdDataPtr += l_repairDataSz)) + { + l_repairLane = *l_it; + l_overWrite = false; + l_vpdWritePtr = NULL; + + // Parse the VPD for fabric and memory eRepair records + for(; + (l_repairCnt < l_numRepairs) && (l_bytesParsed <= i_bufSz); + l_repairCnt++, (l_vpdDataPtr += l_repairDataSz)) + { + l_overWritePtr = + reinterpret_cast<eRepairPowerBus*> (l_vpdDataPtr); + + // Lets find the matching fabric + for(uint8_t l_loop = 0; l_loop < 14; l_loop++) + { + { + if((i_interface == l_repairMatch[l_loop].intType) && + (i_target.getType() == l_repairMatch[l_loop].tgtType) && + ((l_overWritePtr->device).processor_id == + l_repairMatch[l_loop].bus.fabBus.device.processor_id) && + (l_overWritePtr->type == + l_repairMatch[l_loop].bus.fabBus.type) && + (l_overWritePtr->interface == + l_repairMatch[l_loop].bus.fabBus.interface) && + (l_overWritePtr->device.fabricBus == + l_repairMatch[l_loop].bus.fabBus.device.fabricBus)) + { + if(i_clkGroup > 0 && !l_bClkGroupFound) + { + l_bClkGroupFound = true; + continue; + } + + // update the failBit number + { + uint32_t temp = (uint32_t)(l_overWritePtr->failBit); + uint32_t* tptr = &temp; + FAPI_TRY( gatherRepairLanes( + i_target, + l_overWritePtr->interface, + l_repairLane, + tptr), + "gatherRepairLanes() failed w/rc=0x%x", + (uint64_t)fapi2::current_err ); + l_overWritePtr->failBit = temp; + } + + // Increment the count of parsed bytes + l_bytesParsed += l_repairDataSz; + + l_repairCnt++; + l_overWrite = true; + + break; + } + } + } // end of for(l_loop < 14) + + if(l_overWrite == true) + { + // Go for the next repairLane + break; + } + } // end of for(vpd Parsing) + + // Check if we have parsed more bytes than the passed size + if((l_vpdWritePtr == NULL) && + (l_bytesParsed > i_bufSz) && + (l_repairCnt < l_numRepairs)) + { + FAPI_ASSERT(false, + fapi2::P9_EREPAIR_MVPD_FULL_ERR() + .set_VAL_BYTE_PARSED(l_bytesParsed) + .set_VAL_BUF_SIZE(i_bufSz) + .set_VAL_REPAIR_CNT(l_repairCnt) + .set_VAL_NUM_REPAIR(l_numRepairs), + "ERROR: from updateRepairLanesToBuf - MVPD full"); + } + + // Add at the end + if(l_overWrite == false) + { + if(l_vpdWritePtr == NULL) + { + // We are writing at the end + l_vpdWritePtr = l_vpdDataPtr; + } + + { + // Make sure we are not writing more records than the size + // allocated in the VPD + FAPI_ASSERT(l_bytesParsed <= i_bufSz, + fapi2::P9_EREPAIR_MVPD_FULL_ERR() + .set_VAL_BYTE_PARSED(l_bytesParsed) + .set_VAL_BUF_SIZE(i_bufSz) + .set_VAL_REPAIR_CNT(l_repairCnt) + .set_VAL_NUM_REPAIR(l_numRepairs), + "ERROR: from updateRepairLanesToBuf - MVPD full"); + + eRepairPowerBus* l_fabricBus = + reinterpret_cast<eRepairPowerBus*>(l_vpdWritePtr); + + l_fabricBus->device.processor_id = l_chipNum; + l_fabricBus->device.fabricBus = l_busNum; + + if(i_interface == EREPAIR::DRIVE) + { + l_fabricBus->interface = EREPAIR::PBUS_DRIVER; + } + else if(i_interface == EREPAIR::RECEIVE) + { + l_fabricBus->interface = EREPAIR::PBUS_RECEIVER; + } + + if(i_target.getType() == fapi2::TARGET_TYPE_XBUS) + { + l_fabricBus->type = EREPAIR::PROCESSOR_EDIP; + } + else if(i_target.getType() == fapi2::TARGET_TYPE_OBUS) + { + l_fabricBus->type = EREPAIR::PROCESSOR_OPT; + } + + { + uint32_t temp = (uint32_t)(l_fabricBus->failBit); + uint32_t* tptr = &temp; + FAPI_TRY( gatherRepairLanes( + i_target, + l_fabricBus->interface, + l_repairLane, + tptr), + "gatherRepairLanes() failed w/rc=0x%x", + (uint64_t)fapi2::current_err ); + l_fabricBus->failBit = temp; + } + + l_newNumRepairs++; + + // Increment the count of parsed bytes + l_bytesParsed += l_repairDataSz; +#ifndef _BIG_ENDIAN + // We are on a Little Endian system. + // Need to swap the nibbles of structure - eRepairPowerBus + + l_vpdWritePtr[2] = ((l_vpdWritePtr[2] >> 4) | + (l_vpdWritePtr[2] << 4)); +#endif + } + } // end of if(l_overWrite == false) + } // end of for(failLanes) + } + // Update the eRepair count + l_vpdHeadPtr->availNumRecord = l_newNumRepairs; + +fapi_try_exit: + return fapi2::current_err; +} + +/** + * @brief Function called by the FW Team HWP that updates the passed buffer + * with the eRepair faillane numbers of a specified interface. + * + * @param[in] i_target Reference to MEMBUF target + * @param[in] i_interface This indicates the sub-interface type the passed + * faillane vector represents + * @param[in] i_bufSz This is the size of passed buffer in terms of bytes + * @param[in] i_clkGroup Specifies clock group 0:[XOA, X1A,..] 1:[X0B, X1B,..] + * @param[in] i_failLanes Reference to a vector that has the faillane numbers + * that need to be updated to the o_buf buffer + * @param[o] o_buf This is the buffer that has the eRepair records + * that needs to be written to the VPD + * (For MemBuf) + * @return ReturnCode + */ template<fapi2::TargetType K> -using p9_io_erepairSetFailedLanesHwp_FP_t = fapi2::ReturnCode (*)( - const fapi2::Target < K >& i_target, - EREPAIR::erepairVpdType i_vpdType, - const uint8_t i_clkGroup, - const std::vector<uint8_t>& i_txFailLanes, - const std::vector<uint8_t>& i_rxFailLanes); +fapi2::ReturnCode updateRepairLanesToBufMemBuf( + const fapi2::Target < K >& i_target, + const EREPAIR::interfaceType i_interface, + const uint32_t i_bufSz, + const uint8_t i_clkGroup, + const std::vector<uint8_t>& i_failLanes, + uint8_t* o_buf) +{ + fapi2::current_err = fapi2::FAPI2_RC_SUCCESS; + uint32_t l_numRepairs = 0; + uint32_t l_newNumRepairs = 0; + uint32_t l_repairCnt = 0; + uint32_t l_bytesParsed = 0; + uint8_t l_repairLane = 0; + uint32_t l_repairDataSz = 0; + uint8_t* l_vpdPtr = NULL; + uint8_t* l_vpdDataPtr = NULL; + uint8_t* l_vpdWritePtr = NULL; + eRepairHeader* l_vpdHeadPtr = NULL; + eRepairPowerBus* l_overWritePtr = NULL; + bool l_overWrite = false; + uint8_t l_chipNum = 0; + uint32_t l_chipPosition = 0; + fapi2::Target<fapi2::TARGET_TYPE_DMI> l_dmiTarget; + std::vector<uint8_t>::const_iterator l_it; + fapi2::ATTR_CHIP_UNIT_POS_Type l_busNum; + + FAPI_DBG(">> updateRepairLanesToBuf(MemBuf), interface: %s", + i_interface == EREPAIR::DRIVE ? "Drive" : "Receive"); + + { + l_repairDataSz = sizeof(eRepairPowerBus); // Size of memory Bus and + // fabric Bus eRepair data + // is same. + // Read the header and count information + l_vpdPtr = o_buf; // point to the start of header data + l_vpdHeadPtr = reinterpret_cast<eRepairHeader*> (l_vpdPtr); + + l_numRepairs = l_newNumRepairs = l_vpdHeadPtr->availNumRecord; + + // We've read the header data, increment bytes parsed + l_bytesParsed = sizeof(eRepairHeader); + + // Get a pointer to the start of repair data + l_vpdPtr += sizeof(eRepairHeader); + + { + l_dmiTarget = i_target.template getParent<fapi2::TARGET_TYPE_DMI>(); + + // Get the bus number + FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CHIP_UNIT_POS, + l_dmiTarget, + l_busNum)); + } + + // Get the chip number + FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_POS, + i_target, + l_chipPosition)); + + + // This is needed because we can only store and compare a uint8_t + // value. For our purpose the value in l_chipPosition (Proc Position and + // Centaur Position) will always be within the range of uint8_t + l_chipNum = l_chipPosition; + + /*** Lets update the fail lane vector to the Buffer ***/ + // Create a structure of eRepair data that we will be matching + // in the buffer. + struct erepairDataMatch + { + EREPAIR::interfaceType intType; + fapi2::TargetType tgtType; + union repairData + { + eRepairPowerBus fabBus; + eRepairMemBus memBus; + } bus; + }; + + // Create an array of the above match structure to have all the + // combinations of Fabric and Memory repair data + erepairDataMatch l_repairMatch[14] = + { + { + // index 0 - X0A (clock group 0) + EREPAIR::DRIVE, + fapi2::TARGET_TYPE_XBUS_ENDPOINT, + { + // repairData + { + // fabBus + { + // device + l_chipNum,// processor_id + l_busNum, // fabricBus + }, + EREPAIR::PROCESSOR_EDIP, // type + EREPAIR::PBUS_DRIVER, // interface + }, + }, + }, + { + // index 1 - X0A (clock group 0) + EREPAIR::RECEIVE, + fapi2::TARGET_TYPE_XBUS_ENDPOINT, + { + // repairData + { + // fabBus + { + // device + l_chipNum,// processor_id + l_busNum, // fabricBus + }, + EREPAIR::PROCESSOR_EDIP, // type + EREPAIR::PBUS_RECEIVER, // interface + }, + }, + }, + { + // index 2 - X0A (clock group 1) + EREPAIR::DRIVE, + fapi2::TARGET_TYPE_XBUS_ENDPOINT, + { + // repairData + { + // fabBus + { + // device + l_chipNum,// processor_id + l_busNum, // fabricBus + }, + EREPAIR::PROCESSOR_EDIP, // type + EREPAIR::PBUS_DRIVER, // interface + }, + }, + }, + { + // index 3 - X0A (clock group 1) + EREPAIR::RECEIVE, + fapi2::TARGET_TYPE_XBUS_ENDPOINT, + { + // repairData + { + // fabBus + { + // device + l_chipNum,// processor_id + l_busNum, // fabricBus + }, + EREPAIR::PROCESSOR_EDIP, // type + EREPAIR::PBUS_RECEIVER, // interface + }, + }, + }, + { + // index 4 - X1A (clock group 0) + EREPAIR::DRIVE, + fapi2::TARGET_TYPE_XBUS_ENDPOINT, + { + // repairData + { + // fabBus + { + // device + l_chipNum,// processor_id + l_busNum, // fabricBus + }, + EREPAIR::PROCESSOR_EDIP, // type + EREPAIR::PBUS_DRIVER, // interface + }, + }, + }, + { + // index 5 - X1A (clock group 0) + EREPAIR::RECEIVE, + fapi2::TARGET_TYPE_XBUS_ENDPOINT, + { + // repairData + { + // fabBus + { + // device + l_chipNum,// processor_id + l_busNum, // fabricBus + }, + EREPAIR::PROCESSOR_EDIP, // type + EREPAIR::PBUS_RECEIVER, // interface + }, + }, + }, + { + // index 6 - X1A (clock group 1) + EREPAIR::DRIVE, + fapi2::TARGET_TYPE_XBUS_ENDPOINT, + { + // repairData + { + // fabBus + { + // device + l_chipNum,// processor_id + l_busNum, // fabricBus + }, + EREPAIR::PROCESSOR_EDIP, // type + EREPAIR::PBUS_DRIVER, // interface + }, + }, + }, + { + // index 7 - X1A (clock group 1) + EREPAIR::RECEIVE, + fapi2::TARGET_TYPE_XBUS_ENDPOINT, + { + // repairData + { + // fabBus + { + // device + l_chipNum,// processor_id + l_busNum, // fabricBus + }, + EREPAIR::PROCESSOR_EDIP, // type + EREPAIR::PBUS_RECEIVER, // interface + }, + }, + }, + { + // index 8 + EREPAIR::DRIVE, + fapi2::TARGET_TYPE_OBUS, + { + // repairData + { + // fabBus + { + // device + l_chipNum,// processor_id + l_busNum, // fabricBus + }, + EREPAIR::PROCESSOR_OPT, // type + EREPAIR::PBUS_DRIVER, // interface + }, + }, + }, + { + // index 9 + EREPAIR::RECEIVE, + fapi2::TARGET_TYPE_OBUS, + { + // repairData + { + // fabBus + { + // device + l_chipNum,// processor_id + l_busNum, // fabricBus + }, + EREPAIR::PROCESSOR_OPT, // type + EREPAIR::PBUS_RECEIVER, // interface + }, + }, + }, + { + // index 10 + EREPAIR::DRIVE, + fapi2::TARGET_TYPE_DMI, + { + // repairData + { + // fabBus + { + // device + l_chipNum,// proc_centaur_id + l_busNum, // memChannel + }, + EREPAIR::MEMORY_EDIP, // type + EREPAIR::DMI_MCS_DRIVE,// interface + }, + }, + }, + { + // index 11 + EREPAIR::DRIVE, + fapi2::TARGET_TYPE_MEMBUF_CHIP, + { + // repairData + { + // memBus + { + // device + l_chipNum,// proc_centaur_id + l_busNum, // memChannel + }, + EREPAIR::MEMORY_EDIP, // type + EREPAIR::DMI_MEMBUF_DRIVE,// interface + }, + }, + }, + { + // index 12 + EREPAIR::RECEIVE, + fapi2::TARGET_TYPE_DMI, + { + // repairData + { + // memBus + { + // device + l_chipNum,// proc_centaur_id + l_busNum, // memChannel + }, + EREPAIR::MEMORY_EDIP, // type + EREPAIR::DMI_MCS_RECEIVE, // interface + }, + }, + }, + { + // index 13 + EREPAIR::RECEIVE, + fapi2::TARGET_TYPE_MEMBUF_CHIP, + { + // repairData + { + // memBus + { + // device + l_chipNum,// proc_centaur_id + l_busNum, // memChannel + }, + EREPAIR::MEMORY_EDIP, // type + EREPAIR::DMI_MEMBUF_RECEIVE, // interface + }, + }, + } + }; + + l_vpdDataPtr = l_vpdPtr; + l_repairCnt = 0; + + // Pick each faillane for copying into buffer + for(l_it = i_failLanes.begin(); + l_it != i_failLanes.end(); + l_it++, (l_vpdDataPtr += l_repairDataSz)) + { + l_repairLane = *l_it; + l_overWrite = false; + l_vpdWritePtr = NULL; + + // Parse the VPD for fabric and memory eRepair records + for(; + (l_repairCnt < l_numRepairs) && (l_bytesParsed <= i_bufSz); + l_repairCnt++, (l_vpdDataPtr += l_repairDataSz)) + { + l_overWritePtr = + reinterpret_cast<eRepairPowerBus*> (l_vpdDataPtr); + // Lets find the matching fabric + for(uint8_t l_loop = 0; l_loop < 14; l_loop++) + { + { + if((i_interface == l_repairMatch[l_loop].intType) && + (i_target.getType() == l_repairMatch[l_loop].tgtType) && + ((l_overWritePtr->device).processor_id == + l_repairMatch[l_loop].bus.memBus.device.proc_centaur_id) && + (l_overWritePtr->type == + l_repairMatch[l_loop].bus.memBus.type) && + (l_overWritePtr->interface == + l_repairMatch[l_loop].bus.memBus.interface) && + (l_overWritePtr->device.fabricBus == + l_repairMatch[l_loop].bus.memBus.device.memChannel)) + { + // update the failBit number + { + uint32_t temp = (uint32_t)(l_overWritePtr->failBit); + uint32_t* tptr = &temp; + FAPI_TRY( gatherRepairLanes( + i_target, + l_overWritePtr->interface, + l_repairLane, + tptr), + "gatherRepairLanes() failed w/rc=0x%x", + (uint64_t)fapi2::current_err ); + l_overWritePtr->failBit = temp; + } + + // Increment the count of parsed bytes + l_bytesParsed += l_repairDataSz; + + l_repairCnt++; + l_overWrite = true; + + break; + } + } + } // end of for(l_loop < 14) + + if(l_overWrite == true) + { + // Go for the next repairLane + break; + } + } // end of for(vpd Parsing) + + // Check if we have parsed more bytes than the passed size + if((l_vpdWritePtr == NULL) && + (l_bytesParsed > i_bufSz) && + (l_repairCnt < l_numRepairs)) + { + FAPI_ASSERT(false, + fapi2::P9_EREPAIR_MVPD_FULL_ERR() + .set_VAL_BYTE_PARSED(l_bytesParsed) + .set_VAL_BUF_SIZE(i_bufSz) + .set_VAL_REPAIR_CNT(l_repairCnt) + .set_VAL_NUM_REPAIR(l_numRepairs), + "ERROR: from updateRepairLanesToBuf - MVPD full"); + } + + // Add at the end + if(l_overWrite == false) + { + if(l_vpdWritePtr == NULL) + { + // We are writing at the end + l_vpdWritePtr = l_vpdDataPtr; + } + + { + // Make sure we are not writing more records than the size + // allocated in the VPD + FAPI_ASSERT(l_bytesParsed == i_bufSz, + fapi2::P9_EREPAIR_MBVPD_FULL_ERR() + .set_ERROR(l_bytesParsed), + "ERROR: from updateRepairLanesToBuf - MBVPD full"); + + eRepairMemBus* l_memBus = + reinterpret_cast<eRepairMemBus*>(l_vpdWritePtr); + + l_memBus->device.proc_centaur_id = l_chipNum; + l_memBus->device.memChannel = l_busNum; + l_memBus->type = EREPAIR::MEMORY_EDIP; + + if(i_interface == EREPAIR::DRIVE) + { + if(i_target.getType() == fapi2::TARGET_TYPE_DMI) + { + l_memBus->interface = EREPAIR::DMI_MCS_DRIVE; + } + else if(i_target.getType() == fapi2::TARGET_TYPE_MEMBUF_CHIP) + { + l_memBus->interface = EREPAIR::DMI_MEMBUF_DRIVE; + } + } + else if(i_interface == EREPAIR::RECEIVE) + { + if(i_target.getType() == fapi2::TARGET_TYPE_DMI) + { + l_memBus->interface = EREPAIR::DMI_MCS_RECEIVE; + } + else if(i_target.getType() == fapi2::TARGET_TYPE_MEMBUF_CHIP) + { + l_memBus->interface = EREPAIR::DMI_MEMBUF_RECEIVE; + } + } + + { + uint32_t temp = (uint32_t)(l_memBus->failBit); + uint32_t* tptr = &temp; + FAPI_TRY( gatherRepairLanes( + i_target, + l_memBus->interface, + l_repairLane, + tptr), + "gatherRepairLanes() failed w/rc=0x%x", + (uint64_t)fapi2::current_err ); + l_memBus->failBit = temp; + } + + l_newNumRepairs++; + + // Increment the count of parsed bytes + l_bytesParsed += l_repairDataSz; +#ifndef _BIG_ENDIAN + // We are on a Little Endian system. + // Need to swap the nibbles of structure - eRepairMemBus + + l_vpdWritePtr[2] = ((l_vpdWritePtr[2] >> 4) | + (l_vpdWritePtr[2] << 4)); +#endif + } + } // end of if(l_overWrite == false) + } // end of for(failLanes) + } + // Update the eRepair count + l_vpdHeadPtr->availNumRecord = l_newNumRepairs; + +fapi_try_exit: + return fapi2::current_err; +} /** - * @brief FW Team HWP that writes the eRepair fail lanes to the VPD. - * The fail lanes will be written to either the P9 MVPD or the - * Centaur FRU VPD depending on the passed target type. + * @brief Function called by the FW Team HWP that updates the passed buffer + * with the eRepair faillane numbers of a specified interface. * - * @param[in] i_target Reference to X-Bus or O-Bus or MCS or memBuf Target + * @param[in] i_target Reference to DMI target + * @param[in] i_interface This indicates the sub-interface type the passed + * faillane vector represents + * @param[in] i_bufSz This is the size of passed buffer in terms of bytes + * @param[in] i_clkGroup Specifies clock group 0:[XOA, X1A,..] 1:[X0B, X1B,..] + * @param[in] i_failLanes Reference to a vector that has the faillane numbers + * that need to be updated to the o_buf buffer + * @param[o] o_buf This is the buffer that has the eRepair records + * that needs to be written to the VPD + * (For DMI) + * @return ReturnCode + */ +template<fapi2::TargetType K> +fapi2::ReturnCode updateRepairLanesToBufDMI( + const fapi2::Target < K >& i_target, + const EREPAIR::interfaceType i_interface, + const uint32_t i_bufSz, + const uint8_t i_clkGroup, + const std::vector<uint8_t>& i_failLanes, + uint8_t* o_buf) +{ + fapi2::current_err = fapi2::FAPI2_RC_SUCCESS; + uint32_t l_numRepairs = 0; + uint32_t l_newNumRepairs = 0; + uint32_t l_repairCnt = 0; + uint32_t l_bytesParsed = 0; + uint8_t l_repairLane = 0; + uint32_t l_repairDataSz = 0; + uint8_t* l_vpdPtr = NULL; + uint8_t* l_vpdDataPtr = NULL; + uint8_t* l_vpdWritePtr = NULL; + eRepairHeader* l_vpdHeadPtr = NULL; + eRepairPowerBus* l_overWritePtr = NULL; + bool l_overWrite = false; + uint8_t l_chipNum = 0; + uint32_t l_chipPosition = 0; + fapi2::Target<fapi2::TARGET_TYPE_DMI> l_dmiTarget; + std::vector<uint8_t>::const_iterator l_it; + fapi2::ATTR_CHIP_UNIT_POS_Type l_busNum; + + FAPI_DBG(">> updateRepairLanesToBuf(DMI), interface: %s", + i_interface == EREPAIR::DRIVE ? "Drive" : "Receive"); + + { + l_repairDataSz = sizeof(eRepairPowerBus); // Size of memory Bus and + // fabric Bus eRepair data + // is same. + // Read the header and count information + l_vpdPtr = o_buf; // point to the start of header data + l_vpdHeadPtr = reinterpret_cast<eRepairHeader*> (l_vpdPtr); + + l_numRepairs = l_newNumRepairs = l_vpdHeadPtr->availNumRecord; + + // We've read the header data, increment bytes parsed + l_bytesParsed = sizeof(eRepairHeader); + + // Get a pointer to the start of repair data + l_vpdPtr += sizeof(eRepairHeader); + + // Get the bus number + FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CHIP_UNIT_POS, + i_target, + l_busNum)); + + // Get the chip target + fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP> l_chipTarget; + l_chipTarget = i_target.template getParent<fapi2::TARGET_TYPE_PROC_CHIP>(); + + // Get the chip number + FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_POS, + l_chipTarget, + l_chipPosition)); + + + // This is needed because we can only store and compare a uint8_t + // value. For our purpose the value in l_chipPosition (Proc Position and + // Centaur Position) will always be within the range of uint8_t + l_chipNum = l_chipPosition; + + /*** Lets update the fail lane vector to the Buffer ***/ + // Create a structure of eRepair data that we will be matching + // in the buffer. + struct erepairDataMatch + { + EREPAIR::interfaceType intType; + fapi2::TargetType tgtType; + union repairData + { + eRepairPowerBus fabBus; + eRepairMemBus memBus; + } bus; + }; + + // Create an array of the above match structure to have all the + // combinations of Fabric and Memory repair data + erepairDataMatch l_repairMatch[14] = + { + { + // index 0 - X0A (clock group 0) + EREPAIR::DRIVE, + fapi2::TARGET_TYPE_XBUS_ENDPOINT, + { + // repairData + { + // fabBus + { + // device + l_chipNum,// processor_id + l_busNum, // fabricBus + }, + EREPAIR::PROCESSOR_EDIP, // type + EREPAIR::PBUS_DRIVER, // interface + }, + }, + }, + { + // index 1 - X0A (clock group 0) + EREPAIR::RECEIVE, + fapi2::TARGET_TYPE_XBUS_ENDPOINT, + { + // repairData + { + // fabBus + { + // device + l_chipNum,// processor_id + l_busNum, // fabricBus + }, + EREPAIR::PROCESSOR_EDIP, // type + EREPAIR::PBUS_RECEIVER, // interface + }, + }, + }, + { + // index 2 - X0A (clock group 1) + EREPAIR::DRIVE, + fapi2::TARGET_TYPE_XBUS_ENDPOINT, + { + // repairData + { + // fabBus + { + // device + l_chipNum,// processor_id + l_busNum, // fabricBus + }, + EREPAIR::PROCESSOR_EDIP, // type + EREPAIR::PBUS_DRIVER, // interface + }, + }, + }, + { + // index 3 - X0A (clock group 1) + EREPAIR::RECEIVE, + fapi2::TARGET_TYPE_XBUS_ENDPOINT, + { + // repairData + { + // fabBus + { + // device + l_chipNum,// processor_id + l_busNum, // fabricBus + }, + EREPAIR::PROCESSOR_EDIP, // type + EREPAIR::PBUS_RECEIVER, // interface + }, + }, + }, + { + // index 4 - X1A (clock group 0) + EREPAIR::DRIVE, + fapi2::TARGET_TYPE_XBUS_ENDPOINT, + { + // repairData + { + // fabBus + { + // device + l_chipNum,// processor_id + l_busNum, // fabricBus + }, + EREPAIR::PROCESSOR_EDIP, // type + EREPAIR::PBUS_DRIVER, // interface + }, + }, + }, + { + // index 5 - X1A (clock group 0) + EREPAIR::RECEIVE, + fapi2::TARGET_TYPE_XBUS_ENDPOINT, + { + // repairData + { + // fabBus + { + // device + l_chipNum,// processor_id + l_busNum, // fabricBus + }, + EREPAIR::PROCESSOR_EDIP, // type + EREPAIR::PBUS_RECEIVER, // interface + }, + }, + }, + { + // index 6 - X1A (clock group 1) + EREPAIR::DRIVE, + fapi2::TARGET_TYPE_XBUS_ENDPOINT, + { + // repairData + { + // fabBus + { + // device + l_chipNum,// processor_id + l_busNum, // fabricBus + }, + EREPAIR::PROCESSOR_EDIP, // type + EREPAIR::PBUS_DRIVER, // interface + }, + }, + }, + { + // index 7 - X1A (clock group 1) + EREPAIR::RECEIVE, + fapi2::TARGET_TYPE_XBUS_ENDPOINT, + { + // repairData + { + // fabBus + { + // device + l_chipNum,// processor_id + l_busNum, // fabricBus + }, + EREPAIR::PROCESSOR_EDIP, // type + EREPAIR::PBUS_RECEIVER, // interface + }, + }, + }, + { + // index 8 + EREPAIR::DRIVE, + fapi2::TARGET_TYPE_OBUS, + { + // repairData + { + // fabBus + { + // device + l_chipNum,// processor_id + l_busNum, // fabricBus + }, + EREPAIR::PROCESSOR_OPT, // type + EREPAIR::PBUS_DRIVER, // interface + }, + }, + }, + { + // index 9 + EREPAIR::RECEIVE, + fapi2::TARGET_TYPE_OBUS, + { + // repairData + { + // fabBus + { + // device + l_chipNum,// processor_id + l_busNum, // fabricBus + }, + EREPAIR::PROCESSOR_OPT, // type + EREPAIR::PBUS_RECEIVER, // interface + }, + }, + }, + { + // index 10 + EREPAIR::DRIVE, + fapi2::TARGET_TYPE_DMI, + { + // repairData + { + // fabBus + { + // device + l_chipNum,// proc_centaur_id + l_busNum, // memChannel + }, + EREPAIR::MEMORY_EDIP, // type + EREPAIR::DMI_MCS_DRIVE,// interface + }, + }, + }, + { + // index 11 + EREPAIR::DRIVE, + fapi2::TARGET_TYPE_MEMBUF_CHIP, + { + // repairData + { + // memBus + { + // device + l_chipNum,// proc_centaur_id + l_busNum, // memChannel + }, + EREPAIR::MEMORY_EDIP, // type + EREPAIR::DMI_MEMBUF_DRIVE,// interface + }, + }, + }, + { + // index 12 + EREPAIR::RECEIVE, + fapi2::TARGET_TYPE_DMI, + { + // repairData + { + // memBus + { + // device + l_chipNum,// proc_centaur_id + l_busNum, // memChannel + }, + EREPAIR::MEMORY_EDIP, // type + EREPAIR::DMI_MCS_RECEIVE, // interface + }, + }, + }, + { + // index 13 + EREPAIR::RECEIVE, + fapi2::TARGET_TYPE_MEMBUF_CHIP, + { + // repairData + { + // memBus + { + // device + l_chipNum,// proc_centaur_id + l_busNum, // memChannel + }, + EREPAIR::MEMORY_EDIP, // type + EREPAIR::DMI_MEMBUF_RECEIVE, // interface + }, + }, + } + }; + + l_vpdDataPtr = l_vpdPtr; + l_repairCnt = 0; + + // Pick each faillane for copying into buffer + for(l_it = i_failLanes.begin(); + l_it != i_failLanes.end(); + l_it++, (l_vpdDataPtr += l_repairDataSz)) + { + l_repairLane = *l_it; + l_overWrite = false; + l_vpdWritePtr = NULL; + + // Parse the VPD for fabric and memory eRepair records + for(; + (l_repairCnt < l_numRepairs) && (l_bytesParsed <= i_bufSz); + l_repairCnt++, (l_vpdDataPtr += l_repairDataSz)) + { + l_overWritePtr = + reinterpret_cast<eRepairPowerBus*> (l_vpdDataPtr); + + // Lets find the matching fabric + for(uint8_t l_loop = 0; l_loop < 14; l_loop++) + { + { + if((i_interface == l_repairMatch[l_loop].intType) && + (i_target.getType() == l_repairMatch[l_loop].tgtType) && + ((l_overWritePtr->device).processor_id == + l_repairMatch[l_loop].bus.memBus.device.proc_centaur_id) && + (l_overWritePtr->type == + l_repairMatch[l_loop].bus.memBus.type) && + (l_overWritePtr->interface == + l_repairMatch[l_loop].bus.memBus.interface) && + (l_overWritePtr->device.fabricBus == + l_repairMatch[l_loop].bus.memBus.device.memChannel)) + { + // update the failBit number + { + uint32_t temp = (uint32_t)(l_overWritePtr->failBit); + uint32_t* tptr = &temp; + FAPI_TRY( gatherRepairLanes( + i_target, + l_overWritePtr->interface, + l_repairLane, + tptr), + "gatherRepairLanes() failed w/rc=0x%x", + (uint64_t)fapi2::current_err ); + l_overWritePtr->failBit = temp; + } + + // Increment the count of parsed bytes + l_bytesParsed += l_repairDataSz; + + l_repairCnt++; + l_overWrite = true; + + break; + } + } + } // end of for(l_loop < 14) + + if(l_overWrite == true) + { + // Go for the next repairLane + break; + } + } // end of for(vpd Parsing) + + // Check if we have parsed more bytes than the passed size + if((l_vpdWritePtr == NULL) && + (l_bytesParsed > i_bufSz) && + (l_repairCnt < l_numRepairs)) + { + FAPI_ASSERT(false, + fapi2::P9_EREPAIR_MVPD_FULL_ERR() + .set_VAL_BYTE_PARSED(l_bytesParsed) + .set_VAL_BUF_SIZE(i_bufSz) + .set_VAL_REPAIR_CNT(l_repairCnt) + .set_VAL_NUM_REPAIR(l_numRepairs), + "ERROR: from updateRepairLanesToBuf - MVPD full"); + } + + // Add at the end + if(l_overWrite == false) + { + if(l_vpdWritePtr == NULL) + { + // We are writing at the end + l_vpdWritePtr = l_vpdDataPtr; + } + + { + // Make sure we are not writing more records than the size + // allocated in the VPD + FAPI_ASSERT(l_bytesParsed == i_bufSz, + fapi2::P9_EREPAIR_MBVPD_FULL_ERR() + .set_ERROR(l_bytesParsed), + "ERROR: from updateRepairLanesToBuf - MBVPD full"); + + eRepairMemBus* l_memBus = + reinterpret_cast<eRepairMemBus*>(l_vpdWritePtr); + + l_memBus->device.proc_centaur_id = l_chipNum; + l_memBus->device.memChannel = l_busNum; + l_memBus->type = EREPAIR::MEMORY_EDIP; + + if(i_interface == EREPAIR::DRIVE) + { + if(i_target.getType() == fapi2::TARGET_TYPE_DMI) + { + l_memBus->interface = EREPAIR::DMI_MCS_DRIVE; + } + else if(i_target.getType() == fapi2::TARGET_TYPE_MEMBUF_CHIP) + { + l_memBus->interface = EREPAIR::DMI_MEMBUF_DRIVE; + } + } + else if(i_interface == EREPAIR::RECEIVE) + { + if(i_target.getType() == fapi2::TARGET_TYPE_DMI) + { + l_memBus->interface = EREPAIR::DMI_MCS_RECEIVE; + } + else if(i_target.getType() == fapi2::TARGET_TYPE_MEMBUF_CHIP) + { + l_memBus->interface = EREPAIR::DMI_MEMBUF_RECEIVE; + } + } + + { + uint32_t temp = (uint32_t)(l_memBus->failBit); + uint32_t* tptr = &temp; + FAPI_TRY( gatherRepairLanes( + i_target, + l_memBus->interface, + l_repairLane, + tptr), + "gatherRepairLanes() failed w/rc=0x%x", + (uint64_t)fapi2::current_err ); + l_memBus->failBit = temp; + } + + l_newNumRepairs++; + + // Increment the count of parsed bytes + l_bytesParsed += l_repairDataSz; +#ifndef _BIG_ENDIAN + // We are on a Little Endian system. + // Need to swap the nibbles of structure - eRepairMemBus + + l_vpdWritePtr[2] = ((l_vpdWritePtr[2] >> 4) | + (l_vpdWritePtr[2] << 4)); +#endif + } + } // end of if(l_overWrite == false) + } // end of for(failLanes) + } + // Update the eRepair count + l_vpdHeadPtr->availNumRecord = l_newNumRepairs; + +fapi_try_exit: + return fapi2::current_err; +} + +/** + * @brief Function called by the FW Team HWP that writes the data to Field VPD. + * This function calls fapiSetMvpdField to write the VPD. + * + * @param[in] i_target Reference to X-Bus target * @param[in] i_vpdType Specifies which VPD (MNFG or Field) to access. * @param[in] i_clkGroup Specifies clock group 0:[XOA, X1A,..] 1:[X0B, X1B,..] - * @param[in] i_txFailLanes Reference to a vector that has the Tx side - * (of i_tgtHandle) fail lane numbers that need - * to be written to the VPD - * @param[in] i_rxFailLanes Reference to a vector that has the Rx side - * (of i_tgtHandle) fail lane numbers that need - * to be written to the VPD + * @param[in] i_txFailLanes Reference to a vector that has eRepair fail + * lane numbers of the Tx sub-interface. + * @param[in] i_rxFailLanes Reference to a vector that has eRepair fail + * lane numbers of the Rx sub-interface. + * (For Proc) + * @return ReturnCode + */ +template<fapi2::TargetType K> +fapi2::ReturnCode writeRepairDataToVPDProc( + const fapi2::Target < K >& i_target, + EREPAIR::erepairVpdType i_vpdType, + const uint8_t i_clkGroup, + const std::vector<uint8_t>& i_txFailLanes, + const std::vector<uint8_t>& i_rxFailLanes) +{ + fapi2::ReturnCode l_rc = fapi2::FAPI2_RC_SUCCESS; + fapi2::current_err = fapi2::FAPI2_RC_SUCCESS; + fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP> l_procTarget; + + uint8_t* l_retBuf = NULL; + uint32_t l_bufSize = 0; + FAPI_DBG(">> writeRepairDataToVPD - Proc"); + + { + // Determine the Processor target + l_procTarget = i_target.template getParent<fapi2::TARGET_TYPE_PROC_CHIP>(); + + fapi2::MvpdRecord l_vpdRecord = fapi2::MVPD_RECORD_VWML; + + if(i_vpdType == EREPAIR::EREPAIR_VPD_MNFG) + { + l_vpdRecord = fapi2::MVPD_RECORD_MER0; + } + + /*** Read the data from the Module VPD ***/ + + // Determine the size of the eRepair data in the VPD + FAPI_TRY( getMvpdField( + l_vpdRecord, + fapi2::MVPD_KEYWORD_PDI, + l_procTarget, + NULL, + l_bufSize), + "VPD size read failed w/rc=0x%x", + (uint64_t)fapi2::current_err ); + + if((l_bufSize == 0) || + ((i_vpdType == EREPAIR::EREPAIR_VPD_FIELD) && + (l_bufSize > EREPAIR::EREPAIR_P9_MODULE_VPD_FIELD_SIZE)) || + ((i_vpdType == EREPAIR::EREPAIR_VPD_MNFG) && + (l_bufSize > EREPAIR::EREPAIR_P9_MODULE_VPD_MNFG_SIZE))) + { + FAPI_ASSERT(false, + fapi2::P9_EREPAIR_ACCESSOR_HWP_INVALID_FABRIC_VPD_SIZE_ERR() + .set_ERROR(fapi2::current_err), + "ERROR: Invalid Fabric VPD size"); + } + + // Allocate memory for buffer + l_retBuf = new uint8_t[l_bufSize]; + + FAPI_ASSERT(l_retBuf != NULL, + fapi2::P9_EREPAIR_ACCESSOR_HWP_MEMORY_ALLOC_FAIL_ERR() + .set_BUF_SIZE(l_bufSize), + "ERROR: Failed to allocate memory size"); + + // Retrieve the Field eRepair data from the MVPD + FAPI_TRY( getMvpdField( + l_vpdRecord, + fapi2::MVPD_KEYWORD_PDI, + l_procTarget, + l_retBuf, + l_bufSize), + "VPD read failed w/rc=0x%x", + (uint64_t)fapi2::current_err ); + + if(i_txFailLanes.size()) + { + /*** Lets update the tx side fail lane vector to the VPD ***/ + FAPI_TRY( updateRepairLanesToBufProc( + i_target, + EREPAIR::DRIVE, + l_bufSize, + i_clkGroup, + i_txFailLanes, + l_retBuf), + "updateRepairLanesToBuf(DRIVE) failed w/rc=0x%x", + (uint64_t)fapi2::current_err ); + } + + if(i_rxFailLanes.size()) + { + /*** Lets update the rx side fail lane vector to the VPD ***/ + FAPI_TRY( updateRepairLanesToBufProc( + i_target, + EREPAIR::RECEIVE, + l_bufSize, + i_clkGroup, + i_rxFailLanes, + l_retBuf), + "updateRepairLanesToBuf(RECEIVE) failed w/rc=0x%x", + (uint64_t)fapi2::current_err ); + } + + /*** Write the updated eRepair buffer back to MVPD ***/ + FAPI_TRY( setMvpdField( + l_vpdRecord, + fapi2::MVPD_KEYWORD_PDI, + l_procTarget, + l_retBuf, + l_bufSize), + "setMvpdField()-Update erepair data to VPD failed w/rc=0x%x", + (uint64_t)fapi2::current_err ); + } + + // Delete the buffer which has Field eRepair data + delete[] l_retBuf; + +fapi_try_exit: + return fapi2::current_err; +} + +/** + * @brief Function called by the FW Team HWP that writes the data to Field VPD. + * This function calls fapiSetMvpdField to write the VPD. * + * @param[in] i_target Reference to MEMBUF target + * @param[in] i_vpdType Specifies which VPD (MNFG or Field) to access. + * @param[in] i_clkGroup Specifies clock group 0:[XOA, X1A,..] 1:[X0B, X1B,..] + * @param[in] i_txFailLanes Reference to a vector that has eRepair fail + * lane numbers of the Tx sub-interface. + * @param[in] i_rxFailLanes Reference to a vector that has eRepair fail + * lane numbers of the Rx sub-interface. + * (For MemBuf) * @return ReturnCode + */ +template<fapi2::TargetType K> +fapi2::ReturnCode writeRepairDataToVPDMemBuf( + const fapi2::Target < K >& i_target, + EREPAIR::erepairVpdType i_vpdType, + const uint8_t i_clkGroup, + const std::vector<uint8_t>& i_txFailLanes, + const std::vector<uint8_t>& i_rxFailLanes) +{ + fapi2::ReturnCode l_rc = fapi2::FAPI2_RC_SUCCESS; + fapi2::current_err = fapi2::FAPI2_RC_SUCCESS; + std::vector<fapi2::Target<fapi2::TARGET_TYPE_MBA_CHIPLET>> l_mbaChiplets; + fapi2::Target<fapi2::TARGET_TYPE_MBA> l_mbaTarget; + + uint8_t* l_retBuf = NULL; + uint32_t l_bufSize = 0; + size_t l_mBufSize = 0; + uint8_t l_customDimm; + FAPI_DBG(">> writeRepairDataToVPD - MemBuf"); + + { + fapi2::MBvpdRecord l_vpdRecord = fapi2::MBVPD_RECORD_VEIR; + + if(i_vpdType == EREPAIR::EREPAIR_VPD_MNFG) + { + l_vpdRecord = fapi2::MBVPD_RECORD_MER0; + } + + /*** Read the data from the FRU VPD ***/ + + // Determine the size of the eRepair data in the Centaur VPD + FAPI_TRY( getMBvpdField( + l_vpdRecord, + fapi2::MBVPD_KEYWORD_PDI, + i_target, + NULL, + l_mBufSize), + "VPD size read failed w/rc=0x%x", + (uint64_t)fapi2::current_err ); + + // Get the connected MBA chiplet and determine whether we have CDIMM + l_mbaChiplets = i_target.template getChildren<fapi2::TARGET_TYPE_MBA_CHIPLET> + (fapi2::TARGET_STATE_FUNCTIONAL); + + FAPI_ASSERT( 0 != l_mbaChiplets.size(), + fapi2::P9_EREPAIR_CHILD_MBA_TARGETS_ERR() + .set_ERROR(l_mbaChiplets), + "ERROR: During get child MBA targets"); + + l_mbaTarget = l_mbaChiplets[0]; + std::vector<fapi2::Target<fapi2::TARGET_TYPE_DIMM>> l_target_dimm_array; + + l_target_dimm_array = l_mbaTarget.getChildren<fapi2::TARGET_TYPE_DIMM> + (fapi2::TARGET_STATE_FUNCTIONAL); + + if(0 != l_target_dimm_array.size()) + { + FAPI_TRY(FAPI_ATTR_GET(fapi2::ATTR_CEN_SPD_CUSTOM, + l_target_dimm_array[0], + l_customDimm)); + } + else + { + l_customDimm = fapi2::ENUM_ATTR_CEN_SPD_CUSTOM_NO; + } + + if( (l_customDimm == fapi2::ENUM_ATTR_CEN_SPD_CUSTOM_YES) || (l_bufSize == 0) ) + { + if((l_bufSize == 0) || + ((i_vpdType == EREPAIR::EREPAIR_VPD_FIELD) && + (l_bufSize > EREPAIR::EREPAIR_MEM_FIELD_VPD_SIZE_PER_CENTAUR)) || + ((i_vpdType == EREPAIR::EREPAIR_VPD_MNFG) && + (l_bufSize > EREPAIR::EREPAIR_MEM_MNFG_VPD_SIZE_PER_CENTAUR))) + { + FAPI_ASSERT(false, + fapi2::P9_EREPAIR_ACCESSOR_HWP_INVALID_MEM_VPD_SIZE_ERR() + .set_ERROR(fapi2::current_err), + "ERROR: Invalid MEM VPD size"); + } + } + + // Allocate memory for buffer + l_retBuf = new uint8_t[l_mBufSize]; + + FAPI_ASSERT(l_retBuf != NULL, + fapi2::P9_EREPAIR_ACCESSOR_HWP_MEMORY_ALLOC_FAIL_ERR() + .set_BUF_SIZE(l_bufSize), + "ERROR: Failed to allocate memory size"); + + // Retrieve the Field eRepair data from the Centaur FRU VPD + FAPI_TRY( getMBvpdField( + l_vpdRecord, + fapi2::MBVPD_KEYWORD_PDI, + i_target, + l_retBuf, + l_mBufSize), + "Centaur FRU VPD read failed w/rc=0x%x", + (uint64_t)fapi2::current_err ); + + if(i_txFailLanes.size()) + { + /*** Lets update the tx side fail lane vector to the VPD ***/ + FAPI_TRY( updateRepairLanesToBufMemBuf( + i_target, + EREPAIR::DRIVE, + l_mBufSize, + i_clkGroup, + i_txFailLanes, + l_retBuf), + "updateRepairLanesToBuf(DRIVE) failed w/rc=0x%x", + (uint64_t)fapi2::current_err ); + } + + if(i_rxFailLanes.size()) + { + /*** Lets update the rx side fail lane vector to the VPD ***/ + FAPI_TRY( updateRepairLanesToBufMemBuf( + i_target, + EREPAIR::RECEIVE, + l_mBufSize, + i_clkGroup, + i_rxFailLanes, + l_retBuf), + "updateRepairLanesToBuf(RECEIVE) failed w/rc=0x%x", + (uint64_t)fapi2::current_err ); + } + + /*** Write the updated eRepair buffer back to Centaur FRU VPD ***/ + FAPI_TRY( setMBvpdField( + l_vpdRecord, + fapi2::MBVPD_KEYWORD_PDI, + i_target, + l_retBuf, + l_mBufSize), + "Update erepair data to VPD failed w/rc=0x%x", + (uint64_t)fapi2::current_err ); + } // end of(targetType == MEMBUF) + + // Delete the buffer which has Field eRepair data + delete[] l_retBuf; + +fapi_try_exit: + return fapi2::current_err; +} + +/** + * @brief Function called by the FW Team HWP that writes the data to Field VPD. + * This function calls fapiSetMvpdField to write the VPD. * + * @param[in] i_target Reference to DMI target + * @param[in] i_vpdType Specifies which VPD (MNFG or Field) to access. + * @param[in] i_clkGroup Specifies clock group 0:[XOA, X1A,..] 1:[X0B, X1B,..] + * @param[in] i_txFailLanes Reference to a vector that has eRepair fail + * lane numbers of the Tx sub-interface. + * @param[in] i_rxFailLanes Reference to a vector that has eRepair fail + * lane numbers of the Rx sub-interface. + * (For DMI) + * @return ReturnCode */ template<fapi2::TargetType K> +fapi2::ReturnCode writeRepairDataToVPDDMI( + const fapi2::Target < K >& i_target, + EREPAIR::erepairVpdType i_vpdType, + const uint8_t i_clkGroup, + const std::vector<uint8_t>& i_txFailLanes, + const std::vector<uint8_t>& i_rxFailLanes) +{ + fapi2::ReturnCode l_rc = fapi2::FAPI2_RC_SUCCESS; + fapi2::current_err = fapi2::FAPI2_RC_SUCCESS; + fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP> l_procTarget; + + uint8_t* l_retBuf = NULL; + uint32_t l_bufSize = 0; + FAPI_DBG(">> writeRepairDataToVPD - DMI"); + + { + // Determine the Processor target + l_procTarget = i_target.template getParent<fapi2::TARGET_TYPE_PROC_CHIP>(); + + fapi2::MvpdRecord l_vpdRecord = fapi2::MVPD_RECORD_VWML; + + if(i_vpdType == EREPAIR::EREPAIR_VPD_MNFG) + { + l_vpdRecord = fapi2::MVPD_RECORD_MER0; + } + + /*** Read the data from the Module VPD ***/ + + // Determine the size of the eRepair data in the VPD + FAPI_TRY( getMvpdField( + l_vpdRecord, + fapi2::MVPD_KEYWORD_PDI, + l_procTarget, + NULL, + l_bufSize), + "VPD size read failed w/rc=0x%x", + (uint64_t)fapi2::current_err ); + + if((l_bufSize == 0) || + ((i_vpdType == EREPAIR::EREPAIR_VPD_FIELD) && + (l_bufSize > EREPAIR::EREPAIR_P9_MODULE_VPD_FIELD_SIZE)) || + ((i_vpdType == EREPAIR::EREPAIR_VPD_MNFG) && + (l_bufSize > EREPAIR::EREPAIR_P9_MODULE_VPD_MNFG_SIZE))) + { + FAPI_ASSERT(false, + fapi2::P9_EREPAIR_ACCESSOR_HWP_INVALID_FABRIC_VPD_SIZE_ERR() + .set_ERROR(fapi2::current_err), + "ERROR: Invalid Fabric VPD size"); + } + + // Allocate memory for buffer + l_retBuf = new uint8_t[l_bufSize]; + + FAPI_ASSERT(l_retBuf != NULL, + fapi2::P9_EREPAIR_ACCESSOR_HWP_MEMORY_ALLOC_FAIL_ERR() + .set_BUF_SIZE(l_bufSize), + "ERROR: Failed to allocate memory size"); + + // Retrieve the Field eRepair data from the MVPD + FAPI_TRY( getMvpdField( + l_vpdRecord, + fapi2::MVPD_KEYWORD_PDI, + l_procTarget, + l_retBuf, + l_bufSize), + "VPD read failed w/rc=0x%x", + (uint64_t)fapi2::current_err ); + + if(i_txFailLanes.size()) + { + /*** Lets update the tx side fail lane vector to the VPD ***/ + FAPI_TRY( updateRepairLanesToBufDMI( + i_target, + EREPAIR::DRIVE, + l_bufSize, + i_clkGroup, + i_txFailLanes, + l_retBuf), + "updateRepairLanesToBuf(DRIVE) failed w/rc=0x%x", + (uint64_t)fapi2::current_err ); + } + + if(i_rxFailLanes.size()) + { + /*** Lets update the rx side fail lane vector to the VPD ***/ + FAPI_TRY( updateRepairLanesToBufDMI( + i_target, + EREPAIR::RECEIVE, + l_bufSize, + i_clkGroup, + i_rxFailLanes, + l_retBuf), + "updateRepairLanesToBuf(RECEIVE) failed w/rc=0x%x", + (uint64_t)fapi2::current_err ); + } + + /*** Write the updated eRepair buffer back to MVPD ***/ + FAPI_TRY( setMvpdField( + l_vpdRecord, + fapi2::MVPD_KEYWORD_PDI, + l_procTarget, + l_retBuf, + l_bufSize), + "setMvpdField()-Update erepair data to VPD failed w/rc=0x%x", + (uint64_t)fapi2::current_err ); + } + + // Delete the buffer which has Field eRepair data + delete[] l_retBuf; + +fapi_try_exit: + return fapi2::current_err; +} + +/** + * @brief Function called by the FW Team HWP that sets the failed lanes to VPD. + * + * @param[in] i_target Reference to X-Bus DMI target + * @param[in] i_vpdType Specifies which VPD (MNFG or Field) to access. + * @param[in] i_clkGroup Specifies clock group 0:[XOA, X1A,..] 1:[X0B, X1B,..] + * @param[in] i_txFailLanes Reference to a vector that has eRepair fail + * lane numbers of the Tx sub-interface. + * @param[in] i_rxFailLanes Reference to a vector that has eRepair fail + * lane numbers of the Rx sub-interface. + * (For Proc) + * @return ReturnCode + */ +fapi2::ReturnCode p9_io_erepairSetFailedLanesHwp( + const fapi2::Target < fapi2::TARGET_TYPE_XBUS >& i_target, + EREPAIR::erepairVpdType i_vpdType, + const uint8_t i_clkGroup, + const std::vector<uint8_t>& i_txFailLanes, + const std::vector<uint8_t>& i_rxFailLanes) +{ + fapi2::current_err = fapi2::FAPI2_RC_SUCCESS; + + FAPI_INF(">> erepairSetFailedLanesHwp for XBUS"); + + FAPI_ASSERT(( (i_txFailLanes.size() != 0) || (i_rxFailLanes.size() != 0) ), + fapi2::P9_EREPAIR_NO_RX_TX_FAILED_LANES_ERR() + .set_TX_LANE(i_txFailLanes.size()).set_RX_LANE(i_rxFailLanes.size()), + "ERROR: No Tx/Rx fail lanes were provided"); + + FAPI_TRY( writeRepairDataToVPDProc( + i_target, + i_vpdType, + i_clkGroup, + i_txFailLanes, + i_rxFailLanes), + "p9_io_erepairSetFailedLanesHwp() failed w/rc=0x%x", + (uint64_t)fapi2::current_err ); + +fapi_try_exit: + return fapi2::current_err; +} + +/** + * @brief Function called by the FW Team HWP that sets the failed lanes to VPD. + * + * @param[in] i_target Reference to MEMBuf target + * @param[in] i_vpdType Specifies which VPD (MNFG or Field) to access. + * @param[in] i_clkGroup Specifies clock group 0:[XOA, X1A,..] 1:[X0B, X1B,..] + * @param[in] i_txFailLanes Reference to a vector that has eRepair fail + * lane numbers of the Tx sub-interface. + * @param[in] i_rxFailLanes Reference to a vector that has eRepair fail + * lane numbers of the Rx sub-interface. + * (For MemBuf) + * @return ReturnCode + */ +fapi2::ReturnCode p9_io_erepairSetFailedLanesHwp( + const fapi2::Target < fapi2::TARGET_TYPE_MEMBUF_CHIP >& i_target, + EREPAIR::erepairVpdType i_vpdType, + const uint8_t i_clkGroup, + const std::vector<uint8_t>& i_txFailLanes, + const std::vector<uint8_t>& i_rxFailLanes) +{ + fapi2::current_err = fapi2::FAPI2_RC_SUCCESS; + + FAPI_INF(">> erepairSetFailedLanesHwp for MemBuf"); + + FAPI_ASSERT(( (i_txFailLanes.size() != 0) || (i_rxFailLanes.size() != 0) ), + fapi2::P9_EREPAIR_NO_RX_TX_FAILED_LANES_ERR() + .set_TX_LANE(i_txFailLanes.size()).set_RX_LANE(i_rxFailLanes.size()), + "ERROR: No Tx/Rx fail lanes were provided"); + + FAPI_TRY( writeRepairDataToVPDMemBuf( + i_target, + i_vpdType, + i_clkGroup, + i_txFailLanes, + i_rxFailLanes), + "p9_io_erepairSetFailedLanesHwp() failed w/rc=0x%x", + (uint64_t)fapi2::current_err ); + +fapi_try_exit: + return fapi2::current_err; +} + +/** + * @brief Function called by the FW Team HWP that sets the failed lanes to VPD. + * + * @param[in] i_target Reference to DMI target + * @param[in] i_vpdType Specifies which VPD (MNFG or Field) to access. + * @param[in] i_clkGroup Specifies clock group 0:[XOA, X1A,..] 1:[X0B, X1B,..] + * @param[in] i_txFailLanes Reference to a vector that has eRepair fail + * lane numbers of the Tx sub-interface. + * @param[in] i_rxFailLanes Reference to a vector that has eRepair fail + * lane numbers of the Rx sub-interface. + * + * @return ReturnCode + */ fapi2::ReturnCode p9_io_erepairSetFailedLanesHwp( - const fapi2::Target < K >& i_target, + const fapi2::Target < fapi2::TARGET_TYPE_DMI >& i_target, EREPAIR::erepairVpdType i_vpdType, const uint8_t i_clkGroup, const std::vector<uint8_t>& i_txFailLanes, - const std::vector<uint8_t>& i_rxFailLanes); + const std::vector<uint8_t>& i_rxFailLanes) +{ + fapi2::current_err = fapi2::FAPI2_RC_SUCCESS; + + FAPI_INF(">> erepairSetFailedLanesHwp for DMI"); + + FAPI_ASSERT(( (i_txFailLanes.size() != 0) || (i_rxFailLanes.size() != 0) ), + fapi2::P9_EREPAIR_NO_RX_TX_FAILED_LANES_ERR() + .set_TX_LANE(i_txFailLanes.size()).set_RX_LANE(i_rxFailLanes.size()), + "ERROR: No Tx/Rx fail lanes were provided"); + + FAPI_TRY( writeRepairDataToVPDDMI( + i_target, + i_vpdType, + i_clkGroup, + i_txFailLanes, + i_rxFailLanes), + "p9_io_erepairSetFailedLanesHwp() failed w/rc=0x%x", + (uint64_t)fapi2::current_err ); + +fapi_try_exit: + return fapi2::current_err; +} #endif diff --git a/src/import/chips/p9/procedures/hwp/io/p9_io_erepairSetFailedLanesHwp.mk b/src/import/chips/p9/procedures/hwp/io/p9_io_erepairSetFailedLanesHwp.mk deleted file mode 100644 index 03988f13d..000000000 --- a/src/import/chips/p9/procedures/hwp/io/p9_io_erepairSetFailedLanesHwp.mk +++ /dev/null @@ -1,27 +0,0 @@ -# IBM_PROLOG_BEGIN_TAG -# This is an automatically generated prolog. -# -# $Source: src/import/chips/p9/procedures/hwp/io/p9_io_erepairSetFailedLanesHwp.mk $ -# -# OpenPOWER HostBoot Project -# -# Contributors Listed Below - COPYRIGHT 2015,2017 -# [+] International Business Machines Corp. -# -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or -# implied. See the License for the specific language governing -# permissions and limitations under the License. -# -# IBM_PROLOG_END_TAG - -PROCEDURE=p9_io_erepairSetFailedLanesHwp -$(call BUILD_PROCEDURE) |