From 9b6bd57a1601335efce6101fcb9e125491f49cf0 Mon Sep 17 00:00:00 2001 From: Nico Fajardo Date: Tue, 18 Feb 2020 16:46:05 -0600 Subject: [PATCH] exp draminit & draminit_mc phase 3 update for PRD logging - Adding firChecklist as a template parameter for firmware fir_or_pll bit checks - Creating helper functions for fir_or_pll fails to check specific masks - Creating unit test for fir_with_mask_helper - Updating NIMBUS code to accept firChecklist template param - Adding CCS fir checklist; to be checked when row repair is implemented into exp_draminit_mc Change-Id: I4fe7e146a3b4c6e2eefa542916b737d613c3ecc3 Reviewed-on: http://rchgit01.rchland.ibm.com/gerrit1/91915 Tested-by: FSP CI Jenkins Reviewed-by: Louis Stermole Reviewed-by: STEPHEN GLANCY Tested-by: Jenkins Server Tested-by: PPE CI Dev-Ready: NICOLAS R FAJARDO Tested-by: Hostboot CI Reviewed-by: Jennifer A Stofer Reviewed-on: http://rchgit01.rchland.ibm.com/gerrit1/92710 Reviewed-by: Christian R Geddes --- .../procedures/hwp/memory/exp_draminit.C | 4 +- .../procedures/hwp/memory/exp_draminit_mc.C | 10 +- .../procedures/hwp/memory/exp_omi_setup.C | 2 +- .../procedures/hwp/memory/exp_omi_train.C | 2 +- .../hwp/memory/lib/ccs/ccs_explorer.C | 4 +- .../procedures/hwp/memory/lib/fir/exp_fir.C | 248 +++++++++++++++--- .../hwp/memory/lib/fir/exp_unmask.C | 2 + .../hwp/memory/lib/ccs/ccs_nimbus.C | 5 +- .../p9/procedures/hwp/memory/lib/fir/check.C | 20 +- .../procedures/hwp/memory/lib/phy/ddr_phy.C | 5 +- .../p9/procedures/hwp/memory/lib/phy/dp16.C | 8 +- .../memory/lib/workarounds/dp16_workarounds.C | 3 +- .../generic/memory/lib/utils/mss_bad_bits.H | 6 +- .../memory/lib/utils/mss_generic_check.H | 57 ++-- 14 files changed, 296 insertions(+), 80 deletions(-) diff --git a/src/import/chips/ocmb/explorer/procedures/hwp/memory/exp_draminit.C b/src/import/chips/ocmb/explorer/procedures/hwp/memory/exp_draminit.C index bc9187fbec9..b725c8d4564 100644 --- a/src/import/chips/ocmb/explorer/procedures/hwp/memory/exp_draminit.C +++ b/src/import/chips/ocmb/explorer/procedures/hwp/memory/exp_draminit.C @@ -43,6 +43,7 @@ #include #include #include +#include extern "C" { @@ -100,6 +101,7 @@ extern "C" // Due to the RAS/PRD requirements, we need to check for FIR's // If any FIR's have lit up, this draminit fail could have been caused by the FIR, rather than bad hardware // So, let PRD retrigger this step to see if we can resolve the issue - return mss::check::fir_or_pll_fail(i_target, fapi2::current_err); + return mss::check::fir_or_pll_fail(i_target, + fapi2::current_err); } } diff --git a/src/import/chips/ocmb/explorer/procedures/hwp/memory/exp_draminit_mc.C b/src/import/chips/ocmb/explorer/procedures/hwp/memory/exp_draminit_mc.C index 8f60141c027..505f35361d5 100644 --- a/src/import/chips/ocmb/explorer/procedures/hwp/memory/exp_draminit_mc.C +++ b/src/import/chips/ocmb/explorer/procedures/hwp/memory/exp_draminit_mc.C @@ -54,7 +54,6 @@ extern "C" { mss::display_git_commit_info("exp_draminit_mc"); - FAPI_INF("%s Start exp_draminit MC", mss::c_str(i_target)); //skip this ocmb_chip if we have no DIMM's configured @@ -100,13 +99,18 @@ extern "C" FAPI_TRY( mss::enable_read_ecc(i_target), "%s Failed enable_read_ecc", mss::c_str(i_target) ); // Apply marks from OCMB VPD - FAPI_TRY( mss::apply_mark_store(i_target), "%s Failed enable_read_ecc", mss::c_str(i_target) ); + FAPI_TRY(mss::apply_mark_store(i_target), "%s Failed apply_mark_store", mss::c_str(i_target)); // Unmask registers after draminit_mc FAPI_TRY(mss::unmask::after_draminit_mc(i_target), "%s Failed after_draminit_mc", mss::c_str(i_target)); - fapi_try_exit: + // TODO: Implement apply row repairs and perform fir_or_pll_fail for firChecklist::CCS + FAPI_INF("%s End exp_draminit MC", mss::c_str(i_target)); + return fapi2::FAPI2_RC_SUCCESS; + + fapi_try_exit: + return fapi2::current_err; } } diff --git a/src/import/chips/ocmb/explorer/procedures/hwp/memory/exp_omi_setup.C b/src/import/chips/ocmb/explorer/procedures/hwp/memory/exp_omi_setup.C index 49bf67ca83f..fb5fb5ebc9b 100644 --- a/src/import/chips/ocmb/explorer/procedures/hwp/memory/exp_omi_setup.C +++ b/src/import/chips/ocmb/explorer/procedures/hwp/memory/exp_omi_setup.C @@ -86,7 +86,7 @@ extern "C" // gets resolved. #ifdef FIRS_AVAIL_AFTER_BOOT_CONFIG_0_FAIL // If BOOT_CONFIG_0 failed or timed out, we need to check some FIRs - FAPI_TRY(mss::check::fir_or_pll_fail(i_target, l_rc)); + FAPI_TRY( (mss::check::fir_or_pll_fail(i_target, l_rc)) ); #else FAPI_TRY(l_rc, "%s BOOT_CONFIG_0 either failed or timed out", mss::c_str(i_target)); #endif diff --git a/src/import/chips/ocmb/explorer/procedures/hwp/memory/exp_omi_train.C b/src/import/chips/ocmb/explorer/procedures/hwp/memory/exp_omi_train.C index 89ac46d6e9f..5dc0cf3e01c 100644 --- a/src/import/chips/ocmb/explorer/procedures/hwp/memory/exp_omi_train.C +++ b/src/import/chips/ocmb/explorer/procedures/hwp/memory/exp_omi_train.C @@ -87,7 +87,7 @@ extern "C" l_rc = mss::exp::i2c::check_fw_status_busy(i_target); // If BOOT_CONFIG_1 failed or timed out, we need to check some FIRs - FAPI_TRY(mss::check::fir_or_pll_fail(i_target, l_rc)); + FAPI_TRY( (mss::check::fir_or_pll_fail(i_target, l_rc)) ); } else { diff --git a/src/import/chips/ocmb/explorer/procedures/hwp/memory/lib/ccs/ccs_explorer.C b/src/import/chips/ocmb/explorer/procedures/hwp/memory/lib/ccs/ccs_explorer.C index 26855282e50..68757686283 100644 --- a/src/import/chips/ocmb/explorer/procedures/hwp/memory/lib/ccs/ccs_explorer.C +++ b/src/import/chips/ocmb/explorer/procedures/hwp/memory/lib/ccs/ccs_explorer.C @@ -5,7 +5,7 @@ /* */ /* OpenPOWER HostBoot Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2015,2019 */ +/* Contributors Listed Below - COPYRIGHT 2015,2020 */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -104,7 +104,7 @@ fapi_try_exit: // Due to the PRD update, we need to check for FIR's // If any FIR's have lit up, this CCS fail could have been caused by the FIR // So, let PRD retrigger this step to see if we can resolve the issue - return mss::check::fir_or_pll_fail(i_target, fapi2::current_err); + return mss::check::fir_or_pll_fail(i_target, fapi2::current_err); } /// diff --git a/src/import/chips/ocmb/explorer/procedures/hwp/memory/lib/fir/exp_fir.C b/src/import/chips/ocmb/explorer/procedures/hwp/memory/lib/fir/exp_fir.C index a0747aa67fd..c553dcdd14d 100644 --- a/src/import/chips/ocmb/explorer/procedures/hwp/memory/lib/fir/exp_fir.C +++ b/src/import/chips/ocmb/explorer/procedures/hwp/memory/lib/fir/exp_fir.C @@ -22,7 +22,6 @@ /* permissions and limitations under the License. */ /* */ /* IBM_PROLOG_END_TAG */ - /// /// @file exp_fir.C /// @brief Memory subsystem FIR support @@ -50,53 +49,77 @@ namespace mss namespace check { -// Declares FIR registers that are re-used between multiple functions -// Vectors of FIR and mask registers to read through -// As check_fir can be called in multiple places, we don't know what the mask may hold -// In order to tell if a FIR is legit or not, we read the FIR and check it against the mask reg -// Note: using a vector here in case we need to expand -static const std::vector> EXPLORER_FIR_REGS = +/// +/// Declares FIR registers that are re-used between multiple functions +/// Vectors of FIR and mask registers to read through +/// As check_fir can be called in multiple places, we don't know what the mask may hold +/// In order to tell if a FIR is legit or not, we read the FIR and check it against the mask reg +/// Note: using a vector here in case we need to expand +/// Note: the format for these vectors is [TARGET_TYPE]_[PROCEDURE]_FIR_REGS +/// Note: if you change the order of the regs, update indicies in bad_fir_bits below +/// +static const std::vector> EXPLORER_OMI_INIT_FIR_REGS = { // Explorer LOCAL_FIR {EXPLR_TP_MB_UNIT_TOP_LOCAL_FIR, EXPLR_TP_MB_UNIT_TOP_LOCAL_FIR_MASK}, // Explorer MC_OMI_FIR_REG {EXPLR_DLX_MC_OMI_FIR_REG, EXPLR_DLX_MC_OMI_FIR_MASK_REG}, + + // Explorer SRQFIR + {EXPLR_SRQ_SRQFIRQ, EXPLR_SRQ_SRQFIR_MASK}, +}; + +static const std::vector> EXPLORER_DRAMINIT_FIR_REGS = +{ + // Explorer SRQFIR + {EXPLR_SRQ_SRQFIRQ, EXPLR_SRQ_SRQFIR_MASK}, + + // Explorer LOCAL_FIR + {EXPLR_TP_MB_UNIT_TOP_LOCAL_FIR, EXPLR_TP_MB_UNIT_TOP_LOCAL_FIR_MASK}, +}; + +static const std::vector> EXPLORER_CCS_FIR_REGS = +{ + // Explorer SRQFIR + {EXPLR_SRQ_SRQFIRQ, EXPLR_SRQ_SRQFIR_MASK}, + + // Explorer MCBISTFIR + {EXPLR_MCBIST_MCBISTFIRQ, EXPLR_MCBIST_MCBISTFIRMASK}, + }; -static const std::vector> MC_FIR_REGS = +static const std::vector> MC_OMI_INIT_FIR_REGS = { // Axone MC_OMI_FIR_REG {P9A_MC_REG0_OMI_FIR, P9A_MC_REG0_OMI_FIR_MASK}, }; -static const std::vector> MCC_FIR_REGS = +static const std::vector> MCC_OMI_INIT_FIR_REGS = { // Axone DSTLFIR {P9A_MCC_DSTLFIR, P9A_MCC_DSTLFIRMASK}, }; /// -/// @brief Checks whether any FIRs have lit up on a target +/// @brief Helper for bad_fir_bits to loop through reg/mask pairs for FIRs +/// @tparam T the fapi2::TargetType that we are targeting for fir reg checking, inherited /// @param[in] i_target - the target on which to operate /// @param[in,out] io_rc - the return code for the function /// @param[out] o_fir_error - true iff a FIR was hit +/// @param[in] i_checklist - the list of vectour reg/mask pairs to search; default exp omi init firs +/// @note i_checklist is last since optional parameter w/ default needs to be end of list /// @return fapi2::ReturnCode FAPI2_RC_SUCCESS iff ok /// -template< > -fapi2::ReturnCode bad_fir_bits( const fapi2::Target& i_target, - fapi2::ReturnCode& io_rc, - bool& o_fir_error ) +template< fapi2::TargetType T > +fapi2::ReturnCode bad_fir_bits_helper(const fapi2::Target& i_target, + fapi2::ReturnCode& io_rc, + bool& o_fir_error, + const std::vector>& i_checklist) { - const auto& l_mcc = mss::find_target(i_target); - const auto& l_mc = mss::find_target(l_mcc); - - // Start by assuming we do not have a FIR - o_fir_error = false; - // Loop, check the scoms, and check the FIR // Note: we return out if any FIR is bad - for(const auto& l_fir_reg : EXPLORER_FIR_REGS) + for(const auto& l_fir_reg : i_checklist) { FAPI_TRY(fir_with_mask(i_target, l_fir_reg, o_fir_error)); @@ -110,37 +133,184 @@ fapi2::ReturnCode bad_fir_bits( const fapi2::Target& i_target, + const uint64_t i_reg_addr, + const fapi2::buffer& i_mask, + fapi2::ReturnCode& io_rc, + bool& o_fir_error) +{ + fapi2::buffer l_reg_data; + + FAPI_TRY(fapi2::getScom(i_target, i_reg_addr, l_reg_data)); + + o_fir_error = fir_with_mask_helper(l_reg_data, i_mask); + + FAPI_INF("%s %s on reg 0x%016lx value 0x%016lx and mask value 0x%016lx", mss::c_str(i_target), + o_fir_error ? "has FIR's set" : "has no FIR's set", + i_reg_addr, l_reg_data, i_mask); + + // Log the error if need be + log_fir_helper(i_target, o_fir_error, io_rc); + + // Exit if we have found a FIR + if(o_fir_error) { - FAPI_TRY(fir_with_mask(l_mc, l_fir_reg, o_fir_error)); + return fapi2::FAPI2_RC_SUCCESS; + } - // Log the error if need be - log_fir_helper(l_mc, o_fir_error, io_rc); +fapi_try_exit: - // Exit if we have found a FIR - if(o_fir_error) - { - return fapi2::FAPI2_RC_SUCCESS; - } + return fapi2::current_err; +} + +/// +/// @brief Checks whether any FIRs have lit up on a target +/// @param[in] i_target - the target on which to operate +/// @param[in,out] io_rc - the return code for the function +/// @param[out] o_fir_error - true iff a FIR was hit +/// @return fapi2::ReturnCode FAPI2_RC_SUCCESS iff ok +/// @note specialization for EXPLORER and fir checklist for OMI regs +/// +template<> +fapi2::ReturnCode bad_fir_bits( const + fapi2::Target& i_target, + fapi2::ReturnCode& io_rc, + bool& o_fir_error) +{ + const auto& l_mcc = mss::find_target(i_target); + const auto& l_mc = mss::find_target(l_mcc); + + // Start by assuming we do not have a FIR; if true at any point, skip other checks to preserve error + o_fir_error = false; + + // For OMI case, we want to check all bits on fir registers (no custom mask) + FAPI_TRY(bad_fir_bits_helper(i_target, io_rc, o_fir_error, EXPLORER_OMI_INIT_FIR_REGS)); + + if (o_fir_error != true) + { + FAPI_TRY(bad_fir_bits_helper(l_mc, io_rc, o_fir_error, MC_OMI_INIT_FIR_REGS)); } - for(const auto& l_fir_reg : MCC_FIR_REGS) + if (o_fir_error != true) { - FAPI_TRY(fir_with_mask(l_mcc, l_fir_reg, o_fir_error)); + FAPI_TRY(bad_fir_bits_helper(l_mcc, io_rc, o_fir_error, MCC_OMI_INIT_FIR_REGS)); + } - // Log the error if need be - log_fir_helper(l_mcc, o_fir_error, io_rc); +fapi_try_exit: + return fapi2::current_err; +} - // Exit if we have found a FIR - if(o_fir_error) - { - return fapi2::FAPI2_RC_SUCCESS; - } +/// +/// @brief Checks whether any FIRs have lit up on a target +/// @param[in] i_target - the target on which to operate +/// @param[in,out] io_rc - the return code for the function +/// @param[out] o_fir_error - true iff a FIR was hit +/// @return fapi2::ReturnCode FAPI2_RC_SUCCESS iff ok +/// @note specialization for EXPLORER and fir checklist for DRAMINIT regs +/// +template<> +fapi2::ReturnCode bad_fir_bits( const + fapi2::Target& i_target, + fapi2::ReturnCode& io_rc, + bool& o_fir_error) +{ + // For draminit case, we want to check SRQFIR[4] and LOCAL_FIR[20,36] only, so unmask checkbits + // NOTE: if you change DRAMINIT_FIR_REGS, you need to update these indices + const uint64_t l_srqfir_reg_addr = EXPLORER_DRAMINIT_FIR_REGS.at(0).first; + const uint64_t l_localfir_reg_addr = EXPLORER_DRAMINIT_FIR_REGS.at(1).first; + fapi2::buffer l_check_mask(0xFFFFFFFFFFFFFFFF); + + // Start by assuming we do not have a FIR; if true at any point, skip other checks to preserve error + o_fir_error = false; + + // Unmask bit 4 + l_check_mask.clearBit(); + FAPI_TRY(bad_fir_bits_helper_with_mask(i_target, l_srqfir_reg_addr, l_check_mask, io_rc, o_fir_error)); + + // Mask all, then unmask bits 20,36 + if (o_fir_error != true) + { + l_check_mask.flush<1>().clearBit() + .clearBit(); + + FAPI_TRY(bad_fir_bits_helper_with_mask(i_target, l_localfir_reg_addr, l_check_mask, io_rc, o_fir_error)); } fapi_try_exit: return fapi2::current_err; } +/// +/// @brief Checks whether any FIRs have lit up on a target +/// @param[in] i_target - the target on which to operate +/// @param[in,out] io_rc - the return code for the function +/// @param[out] o_fir_error - true iff a FIR was hit +/// @return fapi2::ReturnCode FAPI2_RC_SUCCESS iff ok +/// @note specialization for EXPLORER and fir checklist for CCS regs +/// +template<> +fapi2::ReturnCode bad_fir_bits( const + fapi2::Target& i_target, + fapi2::ReturnCode& io_rc, + bool& o_fir_error) +{ + // For draminit_mc case, we want to check SRQFIR[4] and MBISTFIR[2,3] only, so unmask checkbits + // NOTE: if you change DRAMINIT_MC_FIR_REGS, you need to update these indices + const uint64_t l_srqfir_reg_addr = EXPLORER_CCS_FIR_REGS.at(0).first; + const uint64_t l_mcbistfir_reg_addr = EXPLORER_CCS_FIR_REGS.at(1).first; + fapi2::buffer l_check_mask(0xFFFFFFFFFFFFFFFF); + + // Start by assuming we do not have a FIR; if true at any point, skip other checks to preserve error + o_fir_error = false; + + // Unmask bit 4 + l_check_mask.clearBit(); + FAPI_TRY(bad_fir_bits_helper_with_mask(i_target, l_srqfir_reg_addr, l_check_mask, io_rc, o_fir_error)); + + // Mask all, then unmask bits 2,3 + if (o_fir_error != true) + { + l_check_mask.flush<1>().clearBit() + .clearBit(); + + FAPI_TRY(bad_fir_bits_helper_with_mask(i_target, l_mcbistfir_reg_addr, l_check_mask, io_rc, o_fir_error)); + } + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Checks whether any FIRs have lit up on a target +/// @param[in] i_target - the target on which to operate +/// @param[in,out] io_rc - the return code for the function +/// @param[out] o_fir_error - true iff a FIR was hit +/// @return fapi2::ReturnCode FAPI2_RC_SUCCESS iff ok +/// @note specialization for EXPLORER and fir checklist for GENERIC case +/// +template<> +fapi2::ReturnCode bad_fir_bits( const + fapi2::Target& i_target, + fapi2::ReturnCode& io_rc, + bool& o_fir_error) +{ + // NOTE: Redirecting the GENERIC case to the DRAMINIT checks because no FIR checklist is defined for GENERIC. + // GENERIC case required for bad_fir_bits call in mss_bad_bits.H -- update if GENERIC check needed + return bad_fir_bits(i_target, io_rc, o_fir_error); +} + } // end check ns } // end mss ns diff --git a/src/import/chips/ocmb/explorer/procedures/hwp/memory/lib/fir/exp_unmask.C b/src/import/chips/ocmb/explorer/procedures/hwp/memory/lib/fir/exp_unmask.C index b8f1afba9dc..b7d26636043 100644 --- a/src/import/chips/ocmb/explorer/procedures/hwp/memory/lib/fir/exp_unmask.C +++ b/src/import/chips/ocmb/explorer/procedures/hwp/memory/lib/fir/exp_unmask.C @@ -136,6 +136,7 @@ fapi2::ReturnCode after_draminit_mc( const fapi2::Target return fapi2::FAPI2_RC_SUCCESS; fapi_try_exit: + return fapi2::current_err; } @@ -185,6 +186,7 @@ fapi2::ReturnCode after_draminit_training( const fapi2:: return fapi2::FAPI2_RC_SUCCESS; fapi_try_exit: + return fapi2::current_err; } diff --git a/src/import/chips/p9/procedures/hwp/memory/lib/ccs/ccs_nimbus.C b/src/import/chips/p9/procedures/hwp/memory/lib/ccs/ccs_nimbus.C index d3725beee33..9fced1df657 100644 --- a/src/import/chips/p9/procedures/hwp/memory/lib/ccs/ccs_nimbus.C +++ b/src/import/chips/p9/procedures/hwp/memory/lib/ccs/ccs_nimbus.C @@ -5,7 +5,7 @@ /* */ /* OpenPOWER HostBoot Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2019 */ +/* Contributors Listed Below - COPYRIGHT 2019,2020 */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -162,7 +162,8 @@ fapi_try_exit: // Due to the PRD update, we need to check for FIR's // If any FIR's have lit up, this CCS fail could have been caused by the FIR // So, let PRD retrigger this step to see if we can resolve the issue - return mss::check::fir_or_pll_fail(i_target, fapi2::current_err); + return mss::check::fir_or_pll_fail(i_target, + fapi2::current_err); } /// diff --git a/src/import/chips/p9/procedures/hwp/memory/lib/fir/check.C b/src/import/chips/p9/procedures/hwp/memory/lib/fir/check.C index 0dcf0599602..bf7c7a57430 100644 --- a/src/import/chips/p9/procedures/hwp/memory/lib/fir/check.C +++ b/src/import/chips/p9/procedures/hwp/memory/lib/fir/check.C @@ -44,6 +44,7 @@ #include #include #include +#include using fapi2::TARGET_TYPE_MCBIST; using fapi2::TARGET_TYPE_MCA; @@ -231,7 +232,8 @@ fapi2::ReturnCode during_draminit_training( const fapi2::Target( l_mca, fapi2::current_err, l_check_fir); + return mss::check::fir_or_pll_fail( l_mca, fapi2::current_err, + l_check_fir); } // Declares FIR registers that are re-used between multiple functions @@ -339,11 +341,13 @@ fapi_try_exit: /// @param[in,out] io_rc - the return code for the function /// @param[out] o_fir_error - true iff a FIR was hit /// @return fapi2::ReturnCode FAPI2_RC_SUCCESS iff ok +/// @note specialization for Nimbus and fir checklist for GENERIC case /// template< > -fapi2::ReturnCode bad_fir_bits( const fapi2::Target& i_target, - fapi2::ReturnCode& io_rc, - bool& o_fir_error ) +fapi2::ReturnCode bad_fir_bits +( const fapi2::Target& i_target, + fapi2::ReturnCode& io_rc, + bool& o_fir_error ) { // Start by assuming we do not have a FIR o_fir_error = false; @@ -401,11 +405,13 @@ fapi_try_exit: /// @param[in,out] io_rc - the return code for the function /// @param[out] o_fir_error - true iff a FIR was hit /// @return fapi2::ReturnCode FAPI2_RC_SUCCESS iff ok +/// @note specialization for Nimbus and fir checklist for GENERIC case /// template< > -fapi2::ReturnCode bad_fir_bits( const fapi2::Target& i_target, - fapi2::ReturnCode& io_rc, - bool& o_fir_error ) +fapi2::ReturnCode bad_fir_bits +( const fapi2::Target& i_target, + fapi2::ReturnCode& io_rc, + bool& o_fir_error ) { const auto& l_mcbist = mss::find_target(i_target); // Start by assuming we do not have a FIR diff --git a/src/import/chips/p9/procedures/hwp/memory/lib/phy/ddr_phy.C b/src/import/chips/p9/procedures/hwp/memory/lib/phy/ddr_phy.C index 82769de0fc3..5b9141374e4 100644 --- a/src/import/chips/p9/procedures/hwp/memory/lib/phy/ddr_phy.C +++ b/src/import/chips/p9/procedures/hwp/memory/lib/phy/ddr_phy.C @@ -5,7 +5,7 @@ /* */ /* OpenPOWER HostBoot Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2015,2019 */ +/* Contributors Listed Below - COPYRIGHT 2015,2020 */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -724,7 +724,8 @@ fapi_try_exit: mss::c_str(l_mca)); // Checks the FIR's, if need be - return mss::check::fir_or_pll_fail( l_mca, fapi2::current_err, l_check_firs); + return mss::check::fir_or_pll_fail( l_mca, fapi2::current_err, + l_check_firs); } /// diff --git a/src/import/chips/p9/procedures/hwp/memory/lib/phy/dp16.C b/src/import/chips/p9/procedures/hwp/memory/lib/phy/dp16.C index 81b8114ffbc..08b6944cc99 100644 --- a/src/import/chips/p9/procedures/hwp/memory/lib/phy/dp16.C +++ b/src/import/chips/p9/procedures/hwp/memory/lib/phy/dp16.C @@ -5,7 +5,7 @@ /* */ /* OpenPOWER HostBoot Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2015,2019 */ +/* Contributors Listed Below - COPYRIGHT 2015,2020 */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -4324,7 +4324,8 @@ fapi2::ReturnCode process_rdvref_cal_errors( const fapi2::Target( l_mca, fapi2::current_err, l_cal_fail); + return mss::check::fir_or_pll_fail( l_mca, fapi2::current_err, + l_cal_fail); } /// @@ -4426,7 +4427,8 @@ fapi2::ReturnCode process_wrvref_cal_errors( const fapi2::Target( l_mca, fapi2::current_err, l_cal_fail); + return mss::check::fir_or_pll_fail( l_mca, fapi2::current_err, + l_cal_fail); } /// diff --git a/src/import/chips/p9/procedures/hwp/memory/lib/workarounds/dp16_workarounds.C b/src/import/chips/p9/procedures/hwp/memory/lib/workarounds/dp16_workarounds.C index 8195c2eb7ae..c61026ad59f 100644 --- a/src/import/chips/p9/procedures/hwp/memory/lib/workarounds/dp16_workarounds.C +++ b/src/import/chips/p9/procedures/hwp/memory/lib/workarounds/dp16_workarounds.C @@ -736,7 +736,8 @@ fapi2::ReturnCode dqs_align_workaround(const fapi2::Target(i_target, fapi2::current_err, l_cal_fail); + return mss::check::fir_or_pll_fail(i_target, + fapi2::current_err, l_cal_fail); } /// diff --git a/src/import/generic/memory/lib/utils/mss_bad_bits.H b/src/import/generic/memory/lib/utils/mss_bad_bits.H index b39d8485963..90aa1df4838 100644 --- a/src/import/generic/memory/lib/utils/mss_bad_bits.H +++ b/src/import/generic/memory/lib/utils/mss_bad_bits.H @@ -5,7 +5,7 @@ /* */ /* OpenPOWER HostBoot Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2019 */ +/* Contributors Listed Below - COPYRIGHT 2019,2020 */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -91,6 +91,7 @@ inline void combine_bad_bits(const uint8_t (&i_new_bad_bits)[BAD_BITS_RANKS][BAD /// @tparam I Interface class used to abstract converting bad bits into the attribute /// @param[in] i_target the fapi2 target oon which training was conducted /// @return fapi2::ReturnCode FAPI2_RC_SUCCESS if bad bits can be repaired +/// @note calling GENERIC bad_fir_bits to cover this case in HB -- GENERIC firChecklist not specified (see bad_fir_bits for more details) /// template inline fapi2::ReturnCode record_bad_bits( const fapi2::Target& i_target, const I& i_helper ) @@ -103,7 +104,8 @@ inline fapi2::ReturnCode record_bad_bits( const fapi2::Target& i_target, cons // Note: using success here will cause an RC to not be logged // We can still see if we do have a FIR error though fapi2::ReturnCode l_rc(fapi2::FAPI2_RC_SUCCESS); - FAPI_TRY((mss::check::bad_fir_bits(i_target, l_rc, l_fir_error)), "%s took an error while checking FIR's", + FAPI_TRY((mss::check::bad_fir_bits(i_target, l_rc, l_fir_error)), + "%s took an error while checking FIR's", mss::c_str(i_target)); // Exit if we took a FIR error - PRD will handle bad bits diff --git a/src/import/generic/memory/lib/utils/mss_generic_check.H b/src/import/generic/memory/lib/utils/mss_generic_check.H index 22a656acd4d..f36fe064619 100644 --- a/src/import/generic/memory/lib/utils/mss_generic_check.H +++ b/src/import/generic/memory/lib/utils/mss_generic_check.H @@ -59,6 +59,13 @@ namespace mss namespace check { #ifndef __PPE__ + +/// +/// @brief Making an enum for switch/case in bad_fir_bits. Both will need +/// to be updated if additional FIR checklists are needed +/// +enum firChecklist {GENERIC, OMI, DRAMINIT, CCS}; + /// /// @brief Helper function to log an error as related if needed /// @tparam T the target type on which to log the error @@ -82,14 +89,34 @@ inline void log_fir_helper( const fapi2::Target& i_target, /// /// @brief Checks whether any FIRs have lit up on a target /// @tparam MC MC type for which to check FIR's +/// @tparam F the FIR reg checklist to be checked /// @tparam T the fapi2::TargetType which hold the FIR bits /// @param[in] i_target - the target on which to operate /// @param[in,out] io_rc - the return code for the function /// @param[out] o_fir_error - true iff a FIR was hit /// @return fapi2::ReturnCode FAPI2_RC_SUCCESS iff ok /// -template< mss::mc_type MC, fapi2::TargetType T > -fapi2::ReturnCode bad_fir_bits( const fapi2::Target& i_target, fapi2::ReturnCode& io_rc, bool& o_fir_error ); +template< mss::mc_type MC, firChecklist F, fapi2::TargetType T > +fapi2::ReturnCode bad_fir_bits( const fapi2::Target& i_target, fapi2::ReturnCode& io_rc, bool& o_fir_error); + +/// +/// @brief Checks whether the passed in FIRs have any un-masked errors set +/// @param[in] i_fir - the contents of the fir register to be checked +/// @param[in] i_mask - the contents of the fir mask to be checked +/// @return bool return true iff an unmasked fir bit is found +/// +inline bool fir_with_mask_helper( const fapi2::buffer& i_fir, + const fapi2::buffer& i_mask) +{ + fapi2::buffer l_fir_mask(i_mask); + + // The mask register will need to be inverted as a 0 in the mask register means the FIR is legit + // A bitwise and works the opposite way + l_fir_mask.invert(); + + // Return true if any fir is set and unmasked to indicate this is a "new" FIR + return ((i_fir & l_fir_mask) != 0); +} /// /// @brief Checks whether the passed in FIRs have any un-masked errors set @@ -116,14 +143,9 @@ inline fapi2::ReturnCode fir_with_mask( const fapi2::Target& i_target, FAPI_TRY(mss::getScom(i_target, FIR_REG, l_fir)); FAPI_TRY(mss::getScom(i_target, FIR_MASK, l_fir_mask)); - - // The mask register will need to be inverted as a 0 in the mask register means the FIR is legit - // A bitwise and works the opposite way - l_fir_mask.invert(); - - // If we have any unmasked bit, set that we have a FIR error and exit out with success - // Note: we want to set success here as PRD will find the FIR as "new" and retrigger the procedure this way - o_fir_error = ((l_fir & l_fir_mask) != 0); + // If we have any unmasked bit, set that we have a FIR error and exit out with TRUE + // Note: we want to set TRUE here as PRD will find the FIR as "new" and retrigger the procedure this way + o_fir_error = fir_with_mask_helper(l_fir, l_fir_mask); // And print the information for debuggability FAPI_INF("%s %s on reg 0x%016lx value 0x%016lx and mask 0x%016lx value 0x%016lx", mss::c_str(i_target), @@ -136,14 +158,15 @@ fapi_try_exit: /// /// @brief Checks whether a FIR or unlocked PLL could be the root cause of another failure /// @tparam MC MC type for which to check FIR's +/// @tparam F the FIR reg checklist to be checked /// @tparam T the fapi2::TargetType which hold the FIR bits /// @param[in] i_target - the target on which to operate /// @param[in,out] io_rc - the return code for the function /// @return fapi2::ReturnCode FAPI2_RC_SUCCESS iff ok /// @note This is a helper function to enable unit testing /// -template< mss::mc_type MC, fapi2::TargetType T > -fapi2::ReturnCode hostboot_fir_or_pll_fail( const fapi2::Target& i_target, fapi2::ReturnCode& io_rc) +template< mss::mc_type MC, firChecklist F, fapi2::TargetType T > +fapi2::ReturnCode hostboot_fir_or_pll_fail( const fapi2::Target& i_target, fapi2::ReturnCode& io_rc ) { // We didn't have an error, so return success if(io_rc == fapi2::FAPI2_RC_SUCCESS) @@ -157,7 +180,8 @@ fapi2::ReturnCode hostboot_fir_or_pll_fail( const fapi2::Target& i_target, fa FAPI_ERR("%s has a bad return code, time to check some firs!", mss::c_str(i_target)); - l_fircheck_scom_err = bad_fir_bits(i_target, io_rc, l_fir_error); + // Check the fir bits against the mask and return fir status thru fapi2 RC + l_fircheck_scom_err = bad_fir_bits(i_target, io_rc, l_fir_error); FAPI_ERR("%s took a fail. FIR was %s", mss::c_str(i_target), l_fir_error ? "set - returning FIR RC" : "unset - returning inputted RC"); @@ -179,16 +203,17 @@ fapi2::ReturnCode hostboot_fir_or_pll_fail( const fapi2::Target& i_target, fa /// /// @brief Checks whether a FIR or unlocked PLL could be the root cause of another failure, if a check fir boolean is passed in /// @tparam MC MC type for which to check FIR's +/// @tparam F the FIR reg checklist to be checked /// @tparam T the fapi2::TargetType which hold the FIR bits /// @param[in] i_target - the target on which to operate /// @param[in,out] io_rc - the return code for the function /// @param[in] i_check_fir - true IFF the FIR needs to be checked - defaults to true /// @return fapi2::ReturnCode FAPI2_RC_SUCCESS iff ok /// -template< mss::mc_type MC, fapi2::TargetType T > +template< mss::mc_type MC, firChecklist F, fapi2::TargetType T > fapi2::ReturnCode fir_or_pll_fail( const fapi2::Target& i_target, fapi2::ReturnCode& io_rc, - const bool i_check_fir = true) + const bool i_check_fir = true ) { #ifdef __HOSTBOOT_MODULE @@ -198,7 +223,7 @@ fapi2::ReturnCode fir_or_pll_fail( const fapi2::Target& i_target, if(i_check_fir) { // Handle any issues according to PRD FIR scheme, as a FIR could have caused this issue - l_rc = hostboot_fir_or_pll_fail(i_target, l_rc); + l_rc = hostboot_fir_or_pll_fail(i_target, l_rc); } return l_rc;