From 5318cf7e4a01aaca4663fbb04c2ef3dd10277bfc Mon Sep 17 00:00:00 2001 From: Nico Fajardo Date: Wed, 20 Nov 2019 15:45:52 -0600 Subject: Porting repair_state class and related functions Cleaning up ported p9 code; fixing code beauty in exp_port_ut; fixing lingering configure_wrq issues; cleaning up more ported p9 code; fixing include order errors in nvdimm; both p9 & exp build cleanly; fixing 1R DIMM exclusion in explorer_mss_ut; fixing bad call to cycle time with include order change; fixing exp_scrub issue with cycle time; fixing exp UT fail Change-Id: If88a5931c09e305aa115c367b54e2b586db37e58 Reviewed-on: http://rchgit01.rchland.ibm.com/gerrit1/87535 Tested-by: FSP CI Jenkins Tested-by: Jenkins Server Reviewed-by: Louis Stermole Reviewed-by: STEPHEN GLANCY Dev-Ready: STEPHEN GLANCY Tested-by: Hostboot CI Tested-by: HWSV CI Reviewed-by: Mark Pizzutillo Reviewed-by: Jennifer A Stofer Reviewed-on: http://rchgit01.rchland.ibm.com/gerrit1/89104 Tested-by: Jenkins OP Build CI Tested-by: Jenkins OP HW Reviewed-by: Daniel M Crowell --- .../explorer/procedures/hwp/memory/exp_scrub.C | 3 +- .../procedures/hwp/memory/lib/dimm/exp_rank.H | 31 +- .../procedures/hwp/memory/lib/mc/exp_port.H | 5 +- .../procedures/hwp/memory/lib/mcbist/exp_mcbist.H | 4 +- .../hwp/memory/lib/mcbist/exp_mcbist_traits.H | 2 +- .../hwp/memory/lib/dimm/ddr4/nvdimm_utils.C | 6 +- .../chips/p9/procedures/hwp/memory/lib/dimm/rank.C | 21 +- .../chips/p9/procedures/hwp/memory/lib/mc/port.C | 250 +------- .../chips/p9/procedures/hwp/memory/lib/mc/port.H | 435 +------------ .../p9/procedures/hwp/memory/lib/mcbist/mcbist.H | 4 +- .../procedures/hwp/memory/lib/phy/mss_training.C | 16 +- src/import/generic/memory/lib/ecc/ecc.H | 17 +- src/import/generic/memory/lib/ecc/fw_mark_store.H | 10 +- .../generic/memory/lib/utils/mc/gen_mss_port.H | 698 ++++++++++++++++++++- .../memory/lib/utils/mcbist/gen_mss_mcbist.H | 28 +- src/import/generic/memory/lib/utils/mss_rank.H | 20 +- 16 files changed, 822 insertions(+), 728 deletions(-) diff --git a/src/import/chips/ocmb/explorer/procedures/hwp/memory/exp_scrub.C b/src/import/chips/ocmb/explorer/procedures/hwp/memory/exp_scrub.C index 2ea07e54e..ca588d8d2 100644 --- a/src/import/chips/ocmb/explorer/procedures/hwp/memory/exp_scrub.C +++ b/src/import/chips/ocmb/explorer/procedures/hwp/memory/exp_scrub.C @@ -5,7 +5,7 @@ /* */ /* OpenPOWER HostBoot Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2019 */ +/* Contributors Listed Below - COPYRIGHT 2019,2020 */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -35,6 +35,7 @@ #include #include +#include #include extern "C" diff --git a/src/import/chips/ocmb/explorer/procedures/hwp/memory/lib/dimm/exp_rank.H b/src/import/chips/ocmb/explorer/procedures/hwp/memory/lib/dimm/exp_rank.H index d1ed24665..56dc34b4f 100644 --- a/src/import/chips/ocmb/explorer/procedures/hwp/memory/lib/dimm/exp_rank.H +++ b/src/import/chips/ocmb/explorer/procedures/hwp/memory/lib/dimm/exp_rank.H @@ -5,7 +5,7 @@ /* */ /* OpenPOWER HostBoot Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2019 */ +/* Contributors Listed Below - COPYRIGHT 2019,2020 */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -114,6 +114,35 @@ inline size_t get_dimm_from_rank(const uint64_t i_rank) return i_rank / TT::MAX_RANKS_PER_DIMM; } +/// +/// @brief Return a vector of rank numbers which represent the ranks for this dimm +/// @param[in] i_dimm_target TARGET_TYPE_DIMM +/// @param[out] o_ranks a vector of ranks for dimm (numbers) +/// @return FAPI2_RC_SUCCESS iff all is ok +/// +template<> +inline fapi2::ReturnCode ranks_on_dimm_helper(const fapi2::Target& + i_dimm_target, + std::vector& o_ranks) +{ + std::vector l_ranks; + std::vector> l_vect; + + FAPI_TRY( mss::rank::ranks_on_dimm(i_dimm_target, l_vect) ); + + // Loop through and get ranks or each + for (const auto l_rank_info : l_vect) + { + l_ranks.push_back( l_rank_info.get_dimm_rank() ); + } + + o_ranks = l_ranks; + +fapi_try_exit: + return fapi2::current_err; +} + + } // namespace rank } // namespace mss #endif diff --git a/src/import/chips/ocmb/explorer/procedures/hwp/memory/lib/mc/exp_port.H b/src/import/chips/ocmb/explorer/procedures/hwp/memory/lib/mc/exp_port.H index 668d32bfd..568dbbbbc 100644 --- a/src/import/chips/ocmb/explorer/procedures/hwp/memory/lib/mc/exp_port.H +++ b/src/import/chips/ocmb/explorer/procedures/hwp/memory/lib/mc/exp_port.H @@ -5,7 +5,7 @@ /* */ /* OpenPOWER HostBoot Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2019 */ +/* Contributors Listed Below - COPYRIGHT 2019,2020 */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -41,12 +41,13 @@ #include #include #include +#include +#include #include #include #include #include #include -#include namespace mss { diff --git a/src/import/chips/ocmb/explorer/procedures/hwp/memory/lib/mcbist/exp_mcbist.H b/src/import/chips/ocmb/explorer/procedures/hwp/memory/lib/mcbist/exp_mcbist.H index df3b9af2a..13dd0ba6d 100644 --- a/src/import/chips/ocmb/explorer/procedures/hwp/memory/lib/mcbist/exp_mcbist.H +++ b/src/import/chips/ocmb/explorer/procedures/hwp/memory/lib/mcbist/exp_mcbist.H @@ -5,7 +5,7 @@ /* */ /* OpenPOWER HostBoot Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2019 */ +/* Contributors Listed Below - COPYRIGHT 2019,2020 */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -43,9 +43,9 @@ #include #include +#include #include #include -#include #include #include #include diff --git a/src/import/chips/ocmb/explorer/procedures/hwp/memory/lib/mcbist/exp_mcbist_traits.H b/src/import/chips/ocmb/explorer/procedures/hwp/memory/lib/mcbist/exp_mcbist_traits.H index 9b1186c07..0afe9618e 100644 --- a/src/import/chips/ocmb/explorer/procedures/hwp/memory/lib/mcbist/exp_mcbist_traits.H +++ b/src/import/chips/ocmb/explorer/procedures/hwp/memory/lib/mcbist/exp_mcbist_traits.H @@ -44,7 +44,7 @@ #include #include #include -#include +#include namespace mss { diff --git a/src/import/chips/p9/procedures/hwp/memory/lib/dimm/ddr4/nvdimm_utils.C b/src/import/chips/p9/procedures/hwp/memory/lib/dimm/ddr4/nvdimm_utils.C index 0d517ffbc..3a87de12c 100644 --- a/src/import/chips/p9/procedures/hwp/memory/lib/dimm/ddr4/nvdimm_utils.C +++ b/src/import/chips/p9/procedures/hwp/memory/lib/dimm/ddr4/nvdimm_utils.C @@ -5,7 +5,7 @@ /* */ /* OpenPOWER HostBoot Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2018,2019 */ +/* Contributors Listed Below - COPYRIGHT 2018,2020 */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -44,14 +44,14 @@ #include #include #include +#include +#include #include #include #include #include #include -#include #include -#include #include #include #include diff --git a/src/import/chips/p9/procedures/hwp/memory/lib/dimm/rank.C b/src/import/chips/p9/procedures/hwp/memory/lib/dimm/rank.C index 37af40a5b..1026634b1 100644 --- a/src/import/chips/p9/procedures/hwp/memory/lib/dimm/rank.C +++ b/src/import/chips/p9/procedures/hwp/memory/lib/dimm/rank.C @@ -5,7 +5,7 @@ /* */ /* OpenPOWER HostBoot Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2015,2019 */ +/* Contributors Listed Below - COPYRIGHT 2015,2020 */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -902,6 +902,25 @@ fapi_try_exit: return fapi2::current_err; } +/// +/// @brief Return a vector of rank numbers which represent the ranks for this dimm +/// @param[in] i_dimm_target TARGET_TYPE_DIMM +/// @param[out] o_ranks a vector of ranks for dimm (numbers) +/// @return FAPI2_RC_SUCCESS iff all is ok +/// +template<> +fapi2::ReturnCode ranks_on_dimm_helper(const fapi2::Target& + i_dimm_target, + std::vector& o_ranks) +{ + std::vector l_ranks; + FAPI_TRY( mss::rank::ranks(i_dimm_target, l_ranks) ); + o_ranks = l_ranks; + +fapi_try_exit: + return fapi2::current_err; +} + } // namespace rank } // namespace mss diff --git a/src/import/chips/p9/procedures/hwp/memory/lib/mc/port.C b/src/import/chips/p9/procedures/hwp/memory/lib/mc/port.C index 079bdbde2..a07fea3d9 100644 --- a/src/import/chips/p9/procedures/hwp/memory/lib/mc/port.C +++ b/src/import/chips/p9/procedures/hwp/memory/lib/mc/port.C @@ -5,7 +5,7 @@ /* */ /* OpenPOWER HostBoot Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2016,2019 */ +/* Contributors Listed Below - COPYRIGHT 2016,2020 */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -306,210 +306,6 @@ fapi_try_exit: return fapi2::current_err; } -/// -/// @brief Convert a bitmap from the BAD_DQ_BITMAP attribute to a vector of bad DQ indexes -/// @param[in] i_bad_bits an 8-bit bitmap of bad bits -/// @param[in] i_nibble which nibble of the bitmap to convert -/// @return std::vector of DQ bits marked as bad in the bitmap -/// -std::vector bad_bit_helper(const uint8_t i_bad_bits, const size_t i_nibble) -{ - std::vector l_output; - fapi2::buffer l_bit_buffer(i_bad_bits); - - const size_t l_start = (i_nibble == 0) ? 0 : BITS_PER_NIBBLE; - - for (size_t l_offset = 0; l_offset < BITS_PER_NIBBLE; ++l_offset) - { - if (l_bit_buffer.getBit(l_start + l_offset)) - { - l_output.push_back(l_start + l_offset); - } - } - - return l_output; -} - -/// -/// @brief Place a symbol mark in a Firmware Mark Store register -/// @param[in] i_target the DIMM target -/// @param[in] i_rank the rank -/// @param[in] i_dq the bad DQ bit -/// @return FAPI2_RC_SUCCESS if and only if ok -/// -template<> -fapi2::ReturnCode place_symbol_mark(const fapi2::Target& i_target, - const uint64_t i_rank, - const uint64_t i_dq) -{ - const auto& l_mca = mss::find_target(i_target); - const auto l_dimm_idx = mss::index(i_target); - const auto l_rank_idx = mss::index(i_rank); - - uint8_t l_galois = 0; - mss::mcbist::address l_addr; - - // For symbol marks, we set the appropriate Firmware Mark Store reg, with the symbol's - // Galois code, mark_type=SYMBOL, mark_region=MRANK, and the address of the DIMM+MRANK - // TODO RTC:165133 Remove static_cast once Galois API is updated to accept uint64_t input - FAPI_TRY( mss::ecc::dq_to_galois(static_cast(i_dq), l_galois) ); - - l_addr.set_dimm(l_dimm_idx).set_master_rank(l_rank_idx); - - FAPI_INF("%s Setting firmware symbol mark on rank:%d dq:%d galois:0x%02x", - mss::c_str(i_target), i_rank, i_dq, l_galois); - FAPI_TRY( mss::ecc::set_fwms(l_mca, i_rank, l_galois, mss::ecc::fwms::mark_type::SYMBOL, - mss::ecc::fwms::mark_region::MRANK, l_addr) ); - - // Apply workaround for HW474117 if we place a symbol mark - FAPI_TRY( mss::workarounds::disable_bypass(l_mca) ); - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Place a chip mark in a Hardware Mark Store register -/// @param[in] i_target the DIMM target -/// @param[in] i_rank the rank -/// @param[in] i_dq one of the bad DQ bits in the bad nibble -/// @return FAPI2_RC_SUCCESS if and only if ok -/// -template<> -fapi2::ReturnCode place_chip_mark(const fapi2::Target& i_target, - const uint64_t i_rank, - const uint64_t i_dq) -{ - const auto& l_mca = mss::find_target(i_target); - - uint8_t l_galois = 0; - uint8_t l_symbol = 0; - - // For chip marks, we set the appropriate Hardware Mark Store reg, with the Galois code - // of the first (smallest) symbol in the bad nibble, and both confirmed and exit1 bits set - FAPI_TRY( mss::ecc::dq_to_symbol(static_cast(i_dq), l_symbol) ); - - // Round down to the nearest "nibble" to get the correct symbol, then get the Galois code for it - l_symbol = (l_symbol / BITS_PER_NIBBLE) * BITS_PER_NIBBLE; - FAPI_TRY( mss::ecc::symbol_to_galois(l_symbol, l_galois) ); - - FAPI_INF("%s Setting hardware (chip) mark on rank:%d galois:0x%02x", mss::c_str(i_target), i_rank, l_galois); - FAPI_TRY( mss::ecc::set_hwms(l_mca, i_rank, l_galois) ); - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Restore symbol and chip marks according to BAD_DQ_BITMAP attribute, helper function for unit testing -/// Specialization for TARGET_TYPE_DIMM -/// @param[in] i_target the DIMM target -/// @param[in] i_bad_bits the bad bits values from the VPD, for the specified DIMM -/// @param[out] o_repairs_applied 8-bit mask, where a bit set means a rank had repairs applied (bit0-7 = rank0-7) -/// @param[out] o_repairs_exceeded 2-bit mask, where a bit set means a DIMM had more bad bits than could be repaired (bit0-1 = DIMM0-1) -/// @return FAPI2_RC_SUCCESS if and only if ok -/// -template<> -fapi2::ReturnCode restore_repairs_helper( - const fapi2::Target& i_target, - const uint8_t i_bad_bits[BAD_BITS_RANKS][BAD_DQ_BYTE_COUNT], - fapi2::buffer& o_repairs_applied, - fapi2::buffer& o_repairs_exceeded) -{ - FAPI_INF("%s Restore repair marks from bad DQ data", mss::c_str(i_target)); - - std::vector l_ranks; - const auto l_dimm_idx = mss::index(i_target); - - FAPI_TRY( mss::rank::ranks(i_target, l_ranks) ); - - // loop through ranks - for (const auto l_rank : l_ranks) - { - const auto l_rank_idx = mss::index(l_rank); - - repair_state_machine l_machine; - - // loop through bytes - for (uint64_t l_byte = 0; l_byte < (MAX_DQ_NIBBLES / NIBBLES_PER_BYTE); ++l_byte) - { - for (size_t l_nibble = 0; l_nibble < NIBBLES_PER_BYTE; ++l_nibble) - { - const auto l_bad_dq_vector = bad_bit_helper(i_bad_bits[l_rank_idx][l_byte], l_nibble); - FAPI_DBG("Total bad bits on DIMM:%d rank:%d nibble%d: %d", - l_dimm_idx, l_rank, (l_byte * NIBBLES_PER_BYTE) + l_nibble, l_bad_dq_vector.size()); - - // apply repairs and update repair machine state - // if there are no bad bits (l_bad_dq_vector.size() == 0) no action is necessary - if (l_bad_dq_vector.size() == 1) - { - // l_bad_dq_vector is per byte, so multiply up to get the bad dq's index - const uint64_t l_dq = l_bad_dq_vector[0] + (l_byte * BITS_PER_BYTE); - FAPI_TRY( l_machine.one_bad_dq(i_target, l_rank, l_dq, o_repairs_applied, o_repairs_exceeded) ); - } - else if (l_bad_dq_vector.size() > 1) - { - // l_bad_dq_vector is per byte, so multiply up to get the bad dq's index - const uint64_t l_dq = l_bad_dq_vector[0] + (l_byte * BITS_PER_BYTE); - FAPI_TRY( l_machine.multiple_bad_dq(i_target, l_rank, l_dq, o_repairs_applied, o_repairs_exceeded) ); - } - - // if repairs have been exceeded, we're done - if (o_repairs_exceeded.getBit(l_dimm_idx)) - { - FAPI_INF("Repairs exceeded on DIMM %s", mss::c_str(i_target)); - return fapi2::FAPI2_RC_SUCCESS; - } - } // end loop through nibbles - } // end loop through bytes - } // end loop through ranks - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Restore symbol and chip marks according to BAD_DQ_BITMAP attribute -/// Specialization for TARGET_TYPE_MCA -/// @param[in] i_target A target representing a port -/// @param[out] o_repairs_applied 8-bit mask, where a bit set means a rank had repairs applied (bit0-7 = rank0-7) -/// @param[out] o_repairs_exceeded 2-bit mask, where a bit set means a DIMM had more bad bits than could be repaired (bit0-1 = DIMM0-1) -/// @return FAPI2_RC_SUCCESS if and only if ok -/// -template<> -fapi2::ReturnCode restore_repairs( const fapi2::Target& i_target, - fapi2::buffer& o_repairs_applied, - fapi2::buffer& o_repairs_exceeded) -{ - uint8_t l_bad_bits[BAD_BITS_RANKS][BAD_DQ_BYTE_COUNT] = {}; - - o_repairs_applied = 0; - o_repairs_exceeded = 0; - - for (const auto& l_dimm : mss::find_targets(i_target)) - { - FAPI_TRY( mss::bad_dq_bitmap(l_dimm, &(l_bad_bits[0][0])) ); - - FAPI_TRY( (restore_repairs_helper( - l_dimm, l_bad_bits, o_repairs_applied, o_repairs_exceeded)) ); - } - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Set a new state in the repair state machine -/// @tparam T, the fapi2 target type of the DIMM -/// @param[in,out] io_machine the repair state machine -/// @param[in] i_state shared pointer to the new state to set -/// -template< fapi2::TargetType T > -void repair_state::set_state(repair_state_machine& io_machine, std::shared_ptr> i_state) -{ - io_machine.update_state(i_state); -} - /// /// @brief Perform a repair for a single bad DQ bit in a nibble /// Specialization for TARGET_TYPE_DIMM @@ -803,48 +599,4 @@ fapi2::ReturnCode chip_and_symbol_mark::multiple_bad_dq return fapi2::FAPI2_RC_SUCCESS; } -/// -/// @brief Perform a repair for a single bad DQ bit in a nibble -/// @tparam T, the fapi2 target type of the DIMM -/// @param[in] i_target the DIMM target -/// @param[in] i_rank the rank -/// @param[in] i_dq the DQ bit index -/// @param[in,out] io_repairs_applied 8-bit mask, where a bit set means that rank had repairs applied -/// @param[in,out] io_repairs_exceeded 2-bit mask, where a bit set means that DIMM had more bad bits than could be repaired -/// @return FAPI2_RC_SUCCESS if and only if ok -/// -template< fapi2::TargetType T > -fapi2::ReturnCode repair_state_machine::one_bad_dq(const fapi2::Target& i_target, - const uint64_t i_rank, - const uint64_t i_dq, - fapi2::buffer& io_repairs_applied, - fapi2::buffer& io_repairs_exceeded) -{ - FAPI_TRY( iv_repair_state->one_bad_dq(*this, i_target, i_rank, i_dq, io_repairs_applied, io_repairs_exceeded) ); -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Perform a repair for multiple bad DQ bits in a nibble -/// @tparam T, the fapi2 target type of the DIMM -/// @param[in] i_target the DIMM target -/// @param[in] i_rank the rank -/// @param[in] i_dq one of the bad DQ bit indexes -/// @param[in,out] io_repairs_applied 8-bit mask, where a bit set means that rank had repairs applied -/// @param[in,out] io_repairs_exceeded 2-bit mask, where a bit set means that DIMM had more bad bits than could be repaired -/// @return FAPI2_RC_SUCCESS if and only if ok -/// -template< fapi2::TargetType T > -fapi2::ReturnCode repair_state_machine::multiple_bad_dq(const fapi2::Target& i_target, - const uint64_t i_rank, - const uint64_t i_dq, - fapi2::buffer& io_repairs_applied, - fapi2::buffer& io_repairs_exceeded) -{ - FAPI_TRY( iv_repair_state->multiple_bad_dq(*this, i_target, i_rank, i_dq, io_repairs_applied, io_repairs_exceeded) ); -fapi_try_exit: - return fapi2::current_err; -} - } // ns mss diff --git a/src/import/chips/p9/procedures/hwp/memory/lib/mc/port.H b/src/import/chips/p9/procedures/hwp/memory/lib/mc/port.H index bf608ddc6..f11f9aafa 100644 --- a/src/import/chips/p9/procedures/hwp/memory/lib/mc/port.H +++ b/src/import/chips/p9/procedures/hwp/memory/lib/mc/port.H @@ -5,7 +5,7 @@ /* */ /* OpenPOWER HostBoot Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2016,2019 */ +/* Contributors Listed Below - COPYRIGHT 2016,2020 */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -40,12 +40,12 @@ #include #include +#include #include #include #include #include #include -#include #include #include @@ -982,437 +982,6 @@ fapi_try_exit: return fapi2::current_err; } -/// -/// @brief Convert a bitmap from the BAD_DQ_BITMAP attribute to a vector of bad DQ indexes -/// @param[in] i_bad_bits an 8-bit bitmap of bad bits -/// @param[in] i_nibble which nibble of the bitmap to convert -/// @return std::vector of DQ bits marked as bad in the bitmap -/// -std::vector bad_bit_helper(const uint8_t i_bad_bits, const size_t i_nibble); - -/// -/// @brief Place a symbol mark in a Firmware Mark Store register -/// @tparam T, the fapi2 target type of the DIMM (derived) -/// @param[in] i_target the DIMM target -/// @param[in] i_rank the rank -/// @param[in] i_dq the bad DQ bit -/// @return FAPI2_RC_SUCCESS if and only if ok -/// -template< fapi2::TargetType T > -fapi2::ReturnCode place_symbol_mark(const fapi2::Target& i_target, - const uint64_t i_rank, - const uint64_t i_dq); - -/// -/// @brief Place a chip mark in a Hardware Mark Store register -/// @tparam T, the fapi2 target type of the DIMM (derived) -/// @param[in] i_target the DIMM target -/// @param[in] i_rank the rank -/// @param[in] i_dq one of the bad DQ bits in the bad nibble -/// @return FAPI2_RC_SUCCESS if and only if ok -/// -template< fapi2::TargetType T > -fapi2::ReturnCode place_chip_mark(const fapi2::Target& i_target, - const uint64_t i_rank, - const uint64_t i_dq); - -// Forward declaration for use in repair_state classes -template< fapi2::TargetType T > -class repair_state_machine; - -/// -/// @class mss::repair_state -/// @brief A class for keeping track of bad bit repair states in a repair_state_machine -/// @tparam T, the fapi2 target type of the DIMM -/// @note this is a base class -/// -template< fapi2::TargetType T > -class repair_state -{ - public: - /// @brief default contructor - repair_state() = default; - /// @brief default destructor - virtual ~repair_state() = default; - - /// - /// @brief Perform a repair for a single bad DQ bit in a nibble - /// @param[in,out] io_machine the repair state machine - /// @param[in] i_target the DIMM target - /// @param[in] i_rank the rank - /// @param[in] i_dq the DQ bit index - /// @param[in,out] io_repairs_applied 8-bit mask, where a bit set means that rank had repairs applied - /// @param[in,out] io_repairs_exceeded 2-bit mask, where a bit set means that DIMM had more bad bits than could be repaired - /// @return FAPI2_RC_SUCCESS if and only if ok - /// - virtual fapi2::ReturnCode one_bad_dq(repair_state_machine& io_machine, - const fapi2::Target& i_target, - const uint64_t i_rank, - const uint64_t i_dq, - fapi2::buffer& io_repairs_applied, - fapi2::buffer& io_repairs_exceeded) = 0; - - /// - /// @brief Perform a repair for multiple bad DQ bits in a nibble - /// @param[in,out] io_machine the repair state machine - /// @param[in] i_target the DIMM target - /// @param[in] i_rank the rank - /// @param[in] i_dq one of the bad DQ bit indexes - /// @param[in,out] io_repairs_applied 8-bit mask, where a bit set means that rank had repairs applied - /// @param[in,out] io_repairs_exceeded 2-bit mask, where a bit set means that DIMM had more bad bits than could be repaired - /// @return FAPI2_RC_SUCCESS if and only if ok - /// - virtual fapi2::ReturnCode multiple_bad_dq(repair_state_machine& io_machine, - const fapi2::Target& i_target, - const uint64_t i_rank, - const uint64_t i_dq, - fapi2::buffer& io_repairs_applied, - fapi2::buffer& io_repairs_exceeded) = 0; - - protected: - /// - /// @brief Set a new state in the repair state machine - /// @param[in,out] io_machine the repair state machine - /// @param[in] i_state pointer to the new state to set - /// - void set_state(repair_state_machine& io_machine, std::shared_ptr> i_state); -}; - -/// -/// @class mss::no_fails -/// @brief repair_state class for no fails (no marks applied) -/// @tparam T, the fapi2 target type of the DIMM -/// -template< fapi2::TargetType T > -class no_fails : public repair_state -{ - public: - /// @brief default contructor - no_fails() = default; - /// @brief default destructor - ~no_fails() = default; - - /// - /// @brief Perform a repair for a single bad DQ bit in a nibble - /// @param[in,out] io_machine the repair state machine - /// @param[in] i_target the DIMM target - /// @param[in] i_rank the rank - /// @param[in] i_dq the DQ bit index - /// @param[in,out] io_repairs_applied 8-bit mask, where a bit set means that rank had repairs applied - /// @param[in,out] io_repairs_exceeded 2-bit mask, where a bit set means that DIMM had more bad bits than could be repaired - /// @return FAPI2_RC_SUCCESS if and only if ok - /// - fapi2::ReturnCode one_bad_dq(repair_state_machine& io_machine, - const fapi2::Target& i_target, - const uint64_t i_rank, - const uint64_t i_dq, - fapi2::buffer& io_repairs_applied, - fapi2::buffer& io_repairs_exceeded) override; - - /// - /// @brief Perform a repair for multiple bad DQ bits in a nibble - /// @param[in,out] io_machine the repair state machine - /// @param[in] i_target the DIMM target - /// @param[in] i_rank the rank - /// @param[in] i_dq one of the bad DQ bit indexes - /// @param[in,out] io_repairs_applied 8-bit mask, where a bit set means that rank had repairs applied - /// @param[in,out] io_repairs_exceeded 2-bit mask, where a bit set means that DIMM had more bad bits than could be repaired - /// @return FAPI2_RC_SUCCESS if and only if ok - /// - fapi2::ReturnCode multiple_bad_dq(repair_state_machine& io_machine, - const fapi2::Target& i_target, - const uint64_t i_rank, - const uint64_t i_dq, - fapi2::buffer& io_repairs_applied, - fapi2::buffer& io_repairs_exceeded) override; -}; - -/// -/// @class mss::symbol_mark_only -/// @brief repair_state class for when only a symbol mark has been used -/// @tparam T, the fapi2 target type of the DIMM -/// -template< fapi2::TargetType T > -class symbol_mark_only : public repair_state -{ - public: - /// @brief default contructor - symbol_mark_only() = default; - /// @brief default destructor - ~symbol_mark_only() = default; - - /// - /// @brief Perform a repair for a single bad DQ bit in a nibble - /// @param[in,out] io_machine the repair state machine - /// @param[in] i_target the DIMM target - /// @param[in] i_rank the rank - /// @param[in] i_dq the DQ bit index - /// @param[in,out] io_repairs_applied 8-bit mask, where a bit set means that rank had repairs applied - /// @param[in,out] io_repairs_exceeded 2-bit mask, where a bit set means that DIMM had more bad bits than could be repaired - /// @return FAPI2_RC_SUCCESS if and only if ok - /// - fapi2::ReturnCode one_bad_dq(repair_state_machine& io_machine, - const fapi2::Target& i_target, - const uint64_t i_rank, - const uint64_t i_dq, - fapi2::buffer& io_repairs_applied, - fapi2::buffer& io_repairs_exceeded) override; - - /// - /// @brief Perform a repair for multiple bad DQ bits in a nibble - /// @param[in,out] io_machine the repair state machine - /// @param[in] i_target the DIMM target - /// @param[in] i_rank the rank - /// @param[in] i_dq one of the bad DQ bit indexes - /// @param[in,out] io_repairs_applied 8-bit mask, where a bit set means that rank had repairs applied - /// @param[in,out] io_repairs_exceeded 2-bit mask, where a bit set means that DIMM had more bad bits than could be repaired - /// @return FAPI2_RC_SUCCESS if and only if ok - /// - fapi2::ReturnCode multiple_bad_dq(repair_state_machine& io_machine, - const fapi2::Target& i_target, - const uint64_t i_rank, - const uint64_t i_dq, - fapi2::buffer& io_repairs_applied, - fapi2::buffer& io_repairs_exceeded) override; -}; - -/// -/// @class mss::symbol_mark_plus_unrepaired_dq -/// @brief repair_state class for when only a symbol mark has been used, and one DQ bit remains unrepaired -/// @tparam T, the fapi2 target type of the DIMM -/// -template< fapi2::TargetType T > -class symbol_mark_plus_unrepaired_dq : public repair_state -{ - public: - /// @brief default contructor - symbol_mark_plus_unrepaired_dq() = default; - /// @brief default destructor - ~symbol_mark_plus_unrepaired_dq() = default; - - /// - /// @brief Perform a repair for a single bad DQ bit in a nibble - /// @param[in,out] io_machine the repair state machine - /// @param[in] i_target the DIMM target - /// @param[in] i_rank the rank - /// @param[in] i_dq the DQ bit index - /// @param[in,out] io_repairs_applied 8-bit mask, where a bit set means that rank had repairs applied - /// @param[in,out] io_repairs_exceeded 2-bit mask, where a bit set means that DIMM had more bad bits than could be repaired - /// @return FAPI2_RC_SUCCESS if and only if ok - /// - fapi2::ReturnCode one_bad_dq(repair_state_machine& io_machine, - const fapi2::Target& i_target, - const uint64_t i_rank, - const uint64_t i_dq, - fapi2::buffer& io_repairs_applied, - fapi2::buffer& io_repairs_exceeded) override; - - /// - /// @brief Perform a repair for multiple bad DQ bits in a nibble - /// @param[in,out] io_machine the repair state machine - /// @param[in] i_target the DIMM target - /// @param[in] i_rank the rank - /// @param[in] i_dq one of the bad DQ bit indexes - /// @param[in,out] io_repairs_applied 8-bit mask, where a bit set means that rank had repairs applied - /// @param[in,out] io_repairs_exceeded 2-bit mask, where a bit set means that DIMM had more bad bits than could be repaired - /// @return FAPI2_RC_SUCCESS if and only if ok - /// - fapi2::ReturnCode multiple_bad_dq(repair_state_machine& io_machine, - const fapi2::Target& i_target, - const uint64_t i_rank, - const uint64_t i_dq, - fapi2::buffer& io_repairs_applied, - fapi2::buffer& io_repairs_exceeded) override; -}; - -/// -/// @class mss::chip_mark_only -/// @brief repair_state class for when only a chip mark has been used -/// @tparam T, the fapi2 target type of the DIMM -/// -template< fapi2::TargetType T > -class chip_mark_only : public repair_state -{ - public: - /// @brief default contructor - chip_mark_only() = default; - /// @brief default destructor - ~chip_mark_only() = default; - - /// - /// @brief Perform a repair for a single bad DQ bit in a nibble - /// @param[in,out] io_machine the repair state machine - /// @param[in] i_target the DIMM target - /// @param[in] i_rank the rank - /// @param[in] i_dq the DQ bit index - /// @param[in,out] io_repairs_applied 8-bit mask, where a bit set means that rank had repairs applied - /// @param[in,out] io_repairs_exceeded 2-bit mask, where a bit set means that DIMM had more bad bits than could be repaired - /// @return FAPI2_RC_SUCCESS if and only if ok - /// - fapi2::ReturnCode one_bad_dq(repair_state_machine& io_machine, - const fapi2::Target& i_target, - const uint64_t i_rank, - const uint64_t i_dq, - fapi2::buffer& io_repairs_applied, - fapi2::buffer& io_repairs_exceeded) override; - - /// - /// @brief Perform a repair for multiple bad DQ bits in a nibble - /// @param[in,out] io_machine the repair state machine - /// @param[in] i_target the DIMM target - /// @param[in] i_rank the rank - /// @param[in] i_dq one of the bad DQ bit indexes - /// @param[in,out] io_repairs_applied 8-bit mask, where a bit set means that rank had repairs applied - /// @param[in,out] io_repairs_exceeded 2-bit mask, where a bit set means that DIMM had more bad bits than could be repaired - /// @return FAPI2_RC_SUCCESS if and only if ok - /// - fapi2::ReturnCode multiple_bad_dq(repair_state_machine& io_machine, - const fapi2::Target& i_target, - const uint64_t i_rank, - const uint64_t i_dq, - fapi2::buffer& io_repairs_applied, - fapi2::buffer& io_repairs_exceeded) override; -}; - -/// -/// @class mss::chip_mark_only -/// @brief repair_state class for when both a chip mark and a symbol mark have been used -/// @tparam T, the fapi2 target type of the DIMM -/// -template< fapi2::TargetType T > -class chip_and_symbol_mark : public repair_state -{ - public: - /// @brief default contructor - chip_and_symbol_mark() = default; - /// @brief default destructor - ~chip_and_symbol_mark() = default; - - /// - /// @brief Perform a repair for a single bad DQ bit in a nibble - /// @param[in,out] io_machine the repair state machine - /// @param[in] i_target the DIMM target - /// @param[in] i_rank the rank - /// @param[in] i_dq the DQ bit index - /// @param[in,out] io_repairs_applied 8-bit mask, where a bit set means that rank had repairs applied - /// @param[in,out] io_repairs_exceeded 2-bit mask, where a bit set means that DIMM had more bad bits than could be repaired - /// @return FAPI2_RC_SUCCESS if and only if ok - /// - fapi2::ReturnCode one_bad_dq(repair_state_machine& io_machine, - const fapi2::Target& i_target, - const uint64_t i_rank, - const uint64_t i_dq, - fapi2::buffer& io_repairs_applied, - fapi2::buffer& io_repairs_exceeded) override; - - /// - /// @brief Perform a repair for multiple bad DQ bits in a nibble - /// @param[in,out] io_machine the repair state machine - /// @param[in] i_target the DIMM target - /// @param[in] i_rank the rank - /// @param[in] i_dq one of the bad DQ bit indexes - /// @param[in,out] io_repairs_applied 8-bit mask, where a bit set means that rank had repairs applied - /// @param[in,out] io_repairs_exceeded 2-bit mask, where a bit set means that DIMM had more bad bits than could be repaired - /// @return FAPI2_RC_SUCCESS if and only if ok - /// - fapi2::ReturnCode multiple_bad_dq(repair_state_machine& io_machine, - const fapi2::Target& i_target, - const uint64_t i_rank, - const uint64_t i_dq, - fapi2::buffer& io_repairs_applied, - fapi2::buffer& io_repairs_exceeded) override; -}; - -/// -/// @class mss::repair_state_machine -/// @brief state machine class used in restore_repairs_helper -/// @tparam T, the fapi2 target type of the DIMM -/// -template< fapi2::TargetType T > -class repair_state_machine -{ - public: - /// @brief constructor - repair_state_machine() - : iv_repair_state(std::make_shared>()) {} - - /// @brief default destructor - ~repair_state_machine() = default; - - /// - /// @brief Perform a repair for a single bad DQ bit in a nibble - /// @param[in] i_target the DIMM target - /// @param[in] i_rank the rank - /// @param[in] i_dq the DQ bit index - /// @param[in,out] io_repairs_applied 8-bit mask, where a bit set means that rank had repairs applied - /// @param[in,out] io_repairs_exceeded 2-bit mask, where a bit set means that DIMM had more bad bits than could be repaired - /// @return FAPI2_RC_SUCCESS if and only if ok - /// - fapi2::ReturnCode one_bad_dq(const fapi2::Target& i_target, - const uint64_t i_rank, - const uint64_t i_dq, - fapi2::buffer& io_repairs_applied, - fapi2::buffer& io_repairs_exceeded); - - /// - /// @brief Perform a repair for multiple bad DQ bits in a nibble - /// @param[in] i_target the DIMM target - /// @param[in] i_rank the rank - /// @param[in] i_dq one of the bad DQ bit indexes - /// @param[in,out] io_repairs_applied 8-bit mask, where a bit set means that rank had repairs applied - /// @param[in,out] io_repairs_exceeded 2-bit mask, where a bit set means that DIMM had more bad bits than could be repaired - /// @return FAPI2_RC_SUCCESS if and only if ok - /// - fapi2::ReturnCode multiple_bad_dq(const fapi2::Target& i_target, - const uint64_t i_rank, - const uint64_t i_dq, - fapi2::buffer& io_repairs_applied, - fapi2::buffer& io_repairs_exceeded); - - /// - /// @brief Update the state of the state machine - /// @param[in] i_state shared pointer to the new state - /// - void update_state(std::shared_ptr> i_state) - { - iv_repair_state = i_state; - } - - private: - std::shared_ptr> iv_repair_state; -}; - -// TODO RTC: 157753 tparam R can be pulled from an MCA trait once we have it -/// -/// @brief Restore symbol and chip marks according to BAD_DQ_BITMAP attribute, helper function for unit testing -/// @tparam T, the fapi2 target type of the DIMM (derived) -/// @tparam R the maximum rank per DIMM -/// @tparam B the number of bytes per rank in the bad_dq_bitmap attribute -/// @param[in] i_target A target representing a DIMM -/// @param[in] i_bad_bits the bad bits values from the VPD, for the specified DIMM -/// @param[in,out] io_repairs_applied 8-bit mask, where a bit set means that rank had repairs applied -/// @param[in,out] io_repairs_exceeded 2-bit mask, where a bit set means that DIMM had more bad bits than could be repaired -/// @return FAPI2_RC_SUCCESS if and only if ok -/// -template< fapi2::TargetType T, uint64_t R, uint64_t B > -fapi2::ReturnCode restore_repairs_helper( const fapi2::Target& i_target, - const uint8_t i_bad_bits[R][B], - fapi2::buffer& io_repairs_applied, - fapi2::buffer& io_repairs_exceeded); - -/// -/// @brief Restore symbol and chip marks according to BAD_DQ_BITMAP attribute -/// @tparam T, the fapi2 target type of the port (derived) -/// @param[in] i_target A target representing a port -/// @param[out] o_repairs_applied bit mask, where a bit set means a rank had repairs applied (bit0 = rank0, etc) -/// @param[out] o_repairs_exceeded bit mask, where a bit set means a DIMM had more bad bits than could be repaired (bit0 = DIMM0 etc) -/// @return FAPI2_RC_SUCCESS if and only if ok -/// -template< fapi2::TargetType T > -fapi2::ReturnCode restore_repairs( const fapi2::Target& i_target, - fapi2::buffer& o_repairs_applied, - fapi2::buffer& o_repairs_exceeded); - /// @brief Get the attributes for the reorder queue setting /// @param[in] const ref to the mc target /// @param[out] uint8_t& reference to store the value diff --git a/src/import/chips/p9/procedures/hwp/memory/lib/mcbist/mcbist.H b/src/import/chips/p9/procedures/hwp/memory/lib/mcbist/mcbist.H index 02f3a2ba5..f708a8869 100644 --- a/src/import/chips/p9/procedures/hwp/memory/lib/mcbist/mcbist.H +++ b/src/import/chips/p9/procedures/hwp/memory/lib/mcbist/mcbist.H @@ -5,7 +5,7 @@ /* */ /* OpenPOWER HostBoot Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2015,2019 */ +/* Contributors Listed Below - COPYRIGHT 2015,2020 */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -48,6 +48,7 @@ #include #include #include +#include #include #include #include @@ -55,7 +56,6 @@ #include #include #include -#include namespace mss { diff --git a/src/import/chips/p9/procedures/hwp/memory/lib/phy/mss_training.C b/src/import/chips/p9/procedures/hwp/memory/lib/phy/mss_training.C index a7e638093..d48202d17 100644 --- a/src/import/chips/p9/procedures/hwp/memory/lib/phy/mss_training.C +++ b/src/import/chips/p9/procedures/hwp/memory/lib/phy/mss_training.C @@ -5,7 +5,7 @@ /* */ /* OpenPOWER HostBoot Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2017,2019 */ +/* Contributors Listed Below - COPYRIGHT 2017,2020 */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -55,6 +55,7 @@ #include #include #include +#include #ifdef LRDIMM_CAPABLE #include @@ -67,6 +68,19 @@ namespace mss { +/// +/// @brief Bad bit getter - Nimbus specialization +/// @param[in] i_target the fapi2 target oon which training was conducted +/// @param[out] o_array the bad bits +/// @return fapi2::ReturnCode FAPI2_RC_SUCCESS iff success, else error code +/// +template <> +fapi2::ReturnCode get_bad_dq_bitmap(const fapi2::Target& i_target, + uint8_t (&o_array)[BAD_BITS_RANKS][BAD_DQ_BYTE_COUNT]) +{ + return mss::bad_dq_bitmap(i_target, &(o_array[0][0])); +} + namespace training { // Below definitions are used to avoid linker errors diff --git a/src/import/generic/memory/lib/ecc/ecc.H b/src/import/generic/memory/lib/ecc/ecc.H index ebfc37447..610d20489 100644 --- a/src/import/generic/memory/lib/ecc/ecc.H +++ b/src/import/generic/memory/lib/ecc/ecc.H @@ -5,7 +5,7 @@ /* */ /* OpenPOWER HostBoot Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2019 */ +/* Contributors Listed Below - COPYRIGHT 2019,2020 */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -37,9 +37,9 @@ #define _MSS_ECC_H_ #include -#include #include #include +#include #include #include #include @@ -773,19 +773,6 @@ fapi_try_exit: return fapi2::current_err; } -/// -/// @brief Clear all MAINT.ECC counters -/// @tparam T the fapi2::TargetType - derived -/// @param[in] i_target the fapi2 target -/// @return fapi2::ReturnCode FAPI2_RC_SUCCESS if ok -/// -template< fapi2::TargetType T > -inline fapi2::ReturnCode clear_all_counters( const fapi2::Target& i_target ) -{ - return ( mss::mcbist::reset_errors(i_target) ); -} - - } // close namespace ecc } // close namespace mss diff --git a/src/import/generic/memory/lib/ecc/fw_mark_store.H b/src/import/generic/memory/lib/ecc/fw_mark_store.H index 3e840c4d0..28e8668fb 100644 --- a/src/import/generic/memory/lib/ecc/fw_mark_store.H +++ b/src/import/generic/memory/lib/ecc/fw_mark_store.H @@ -5,7 +5,7 @@ /* */ /* OpenPOWER HostBoot Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2019 */ +/* Contributors Listed Below - COPYRIGHT 2019,2020 */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -553,11 +553,11 @@ inline void get_region( const fapi2::buffer& i_data, mark_region& o_va /// @param[in, out] io_data the register value /// @param[in] i_address mcbist::address form of address field /// -template< fapi2::TargetType T = DEFAULT_MEM_PORT_TARGET, typename TT = eccTraits > +template< mss::mc_type MC = DEFAULT_MC_TYPE, fapi2::TargetType T = DEFAULT_MEM_PORT_TARGET, typename TT = eccTraits > inline void set_address( fapi2::buffer& io_data, const mcbist::address& i_address) { // construct fwms::address from mcbist::address - const auto l_addr = address<>(i_address); + const auto l_addr = address(i_address); io_data.insert(l_addr); FAPI_INF("set_address: 0x%016lx", uint64_t(l_addr)); } @@ -569,11 +569,11 @@ inline void set_address( fapi2::buffer& io_data, const mcbist::address /// @param[in] i_data the register value /// @param[out] o_address mcbist::address form of address field /// -template< fapi2::TargetType T = DEFAULT_MEM_PORT_TARGET, typename TT = eccTraits > +template< mss::mc_type MC = DEFAULT_MC_TYPE, fapi2::TargetType T = DEFAULT_MEM_PORT_TARGET, typename TT = eccTraits > inline void get_address( const fapi2::buffer& i_data, mcbist::address& o_address ) { // construct fwms::address from i_data - const auto l_addr = mss::ecc::fwms::address<>(uint64_t(i_data)); + const auto l_addr = mss::ecc::fwms::address(uint64_t(i_data)); // construct mcbist::address from fwms::address o_address = l_addr.operator mss::mcbist::address(); FAPI_INF("get_address: 0x%016lx", uint64_t(l_addr)); diff --git a/src/import/generic/memory/lib/utils/mc/gen_mss_port.H b/src/import/generic/memory/lib/utils/mc/gen_mss_port.H index 01c704e89..435d93a50 100644 --- a/src/import/generic/memory/lib/utils/mc/gen_mss_port.H +++ b/src/import/generic/memory/lib/utils/mc/gen_mss_port.H @@ -5,7 +5,7 @@ /* */ /* OpenPOWER HostBoot Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2018,2019 */ +/* Contributors Listed Below - COPYRIGHT 2018,2020 */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -43,6 +43,9 @@ #include #include #include +#include +#include +#include namespace mss { @@ -163,11 +166,10 @@ void get_bw_snapshot( const fapi2::buffer& i_data, uint64_t& o_bw_snap /// @param[in] const ref to the fapi2::Target /// @param[out] uint32_t* memory to store the value /// @return fapi2::ReturnCode - FAPI2_RC_SUCCESS iff get is OK -/// @note Mark store records from MPVD Lx -/// keyword +/// @note Mark store records from MPVD Lx keyword /// template< mss::mc_type MC = DEFAULT_MC_TYPE, fapi2::TargetType T> -inline fapi2::ReturnCode mvpd_fwms(const fapi2::Target< T>& i_target, uint32_t (&o_array)[MARK_STORE_COUNT]); +fapi2::ReturnCode mvpd_fwms(const fapi2::Target< T>& i_target, uint32_t (&o_array)[MARK_STORE_COUNT]); /// /// @brief Enable power management @@ -604,17 +606,571 @@ fapi_try_exit: return fapi2::current_err; } +/// +/// @brief Place a symbol mark in a Firmware Mark Store register +/// @tparam MC the memory controller type +/// @tparam T the fapi2 target type of the target +/// @tparam TT the class traits for the port +/// @param[in] i_target the DIMM target +/// @param[in] i_rank the rank +/// @param[in] i_dq the bad DQ bit +/// @return FAPI2_RC_SUCCESS if and only if ok +/// +template< mss::mc_type MC = DEFAULT_MC_TYPE, fapi2::TargetType T, typename TT = portTraits > +inline fapi2::ReturnCode place_symbol_mark(const fapi2::Target& i_target, + const uint64_t i_rank, + const uint64_t i_dq) +{ + const auto& l_port = mss::find_target(i_target); + const auto l_dimm_idx = mss::index(i_target); + const auto l_rank_idx = mss::index(i_rank); + + uint8_t l_galois = 0; + mss::mcbist::address l_addr; + + // For symbol marks, we set the appropriate Firmware Mark Store reg, with the symbol's + // Galois code, mark_type=SYMBOL, mark_region=MRANK, and the address of the DIMM+MRANK + // TODO RTC:165133 Remove static_cast once Galois API is updated to accept uint64_t input + FAPI_TRY( mss::ecc::dq_to_galois(static_cast(i_dq), l_galois) ); + + l_addr.set_dimm(l_dimm_idx).set_master_rank(l_rank_idx); + + FAPI_INF("%s Setting firmware symbol mark on rank:%d dq:%d galois:0x%02x", + mss::c_str(i_target), i_rank, i_dq, l_galois); + FAPI_TRY( mss::ecc::set_fwms(l_port, i_rank, l_galois, + mss::ecc::fwms::mark_type::SYMBOL, + mss::ecc::fwms::mark_region::MRANK, + l_addr) ); + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Place a chip mark in a Hardware Mark Store register +/// @tparam MC the memory controller type +/// @tparam T the fapi2 target type of the target +/// @tparam TT the class traits for the port +/// @param[in] i_target the DIMM target +/// @param[in] i_rank the rank +/// @param[in] i_dq one of the bad DQ bits in the bad nibble +/// @return FAPI2_RC_SUCCESS if and only if ok +/// +template< mss::mc_type MC = DEFAULT_MC_TYPE, fapi2::TargetType T, typename TT = portTraits > +inline fapi2::ReturnCode place_chip_mark(const fapi2::Target& i_target, + const uint64_t i_rank, + const uint64_t i_dq) +{ + const auto& l_port = mss::find_target(i_target); + + uint8_t l_galois = 0; + uint8_t l_symbol = 0; + + // For chip marks, we set the appropriate Hardware Mark Store reg, with the Galois code + // of the first (smallest) symbol in the bad nibble, and both confirmed and exit1 bits set + FAPI_TRY( mss::ecc::dq_to_symbol(static_cast(i_dq), l_symbol) ); + + // Round down to the nearest "nibble" to get the correct symbol, then get the Galois code for it + l_symbol = (l_symbol / BITS_PER_NIBBLE) * BITS_PER_NIBBLE; + FAPI_TRY( mss::ecc::symbol_to_galois(l_symbol, l_galois) ); + + FAPI_INF("%s Setting hardware (chip) mark on rank:%d galois:0x%02x", mss::c_str(i_target), i_rank, l_galois); + FAPI_TRY( mss::ecc::set_hwms(l_port, i_rank, l_galois) ); + +fapi_try_exit: + return fapi2::current_err; +} + +// Forward declaration for use in repair_state classes +template< fapi2::TargetType T > +class repair_state_machine; + +/// +/// @class mss::repair_state +/// @brief A class for keeping track of bad bit repair states in a repair_state_machine +/// @tparam T, the fapi2 target type of the DIMM +/// @note this is a base class +/// +template< fapi2::TargetType T > +class repair_state +{ + public: + /// @brief default contructor + repair_state() = default; + /// @brief default destructor + virtual ~repair_state() = default; + + /// + /// @brief Perform a repair for a single bad DQ bit in a nibble + /// @param[in,out] io_machine the repair state machine + /// @param[in] i_target the DIMM target + /// @param[in] i_rank the rank + /// @param[in] i_dq the DQ bit index + /// @param[in,out] io_repairs_applied 8-bit mask, where a bit set means that rank had repairs applied + /// @param[in,out] io_repairs_exceeded 2-bit mask, where a bit set means that DIMM had more bad bits than could be repaired + /// @return FAPI2_RC_SUCCESS if and only if ok + /// + virtual fapi2::ReturnCode one_bad_dq(repair_state_machine& io_machine, + const fapi2::Target& i_target, + const uint64_t i_rank, + const uint64_t i_dq, + fapi2::buffer& io_repairs_applied, + fapi2::buffer& io_repairs_exceeded) = 0; + + /// + /// @brief Perform a repair for multiple bad DQ bits in a nibble + /// @param[in,out] io_machine the repair state machine + /// @param[in] i_target the DIMM target + /// @param[in] i_rank the rank + /// @param[in] i_dq one of the bad DQ bit indexes + /// @param[in,out] io_repairs_applied 8-bit mask, where a bit set means that rank had repairs applied + /// @param[in,out] io_repairs_exceeded 2-bit mask, where a bit set means that DIMM had more bad bits than could be repaired + /// @return FAPI2_RC_SUCCESS if and only if ok + /// + virtual fapi2::ReturnCode multiple_bad_dq(repair_state_machine& io_machine, + const fapi2::Target& i_target, + const uint64_t i_rank, + const uint64_t i_dq, + fapi2::buffer& io_repairs_applied, + fapi2::buffer& io_repairs_exceeded) = 0; + + protected: + /// + /// @brief Set a new state in the repair state machine + /// @param[in,out] io_machine the repair state machine + /// @param[in] i_state pointer to the new state to set + /// + inline void set_state(repair_state_machine& io_machine, std::shared_ptr> i_state) + { + io_machine.update_state(i_state); + } +}; + +/// +/// @class mss::chip_and_symbol_mark +/// @brief repair_state class for when both a chip mark and a symbol mark have been used +/// @tparam T, the fapi2 target type of the DIMM +/// +template< fapi2::TargetType T > +class chip_and_symbol_mark : public repair_state +{ + public: + /// @brief default contructor + chip_and_symbol_mark() = default; + /// @brief default destructor + ~chip_and_symbol_mark() = default; + + /// + /// @brief Perform a repair for a single bad DQ bit in a nibble + /// @param[in,out] io_machine the repair state machine + /// @param[in] i_target the DIMM target + /// @param[in] i_rank the rank + /// @param[in] i_dq the DQ bit index + /// @param[in,out] io_repairs_applied 8-bit mask, where a bit set means that rank had repairs applied + /// @param[in,out] io_repairs_exceeded 2-bit mask, where a bit set means that DIMM had more bad bits than could be repaired + /// @return FAPI2_RC_SUCCESS if and only if ok + /// + fapi2::ReturnCode one_bad_dq(repair_state_machine& io_machine, + const fapi2::Target& i_target, + const uint64_t i_rank, + const uint64_t i_dq, + fapi2::buffer& io_repairs_applied, + fapi2::buffer& io_repairs_exceeded) + { + // repairs exceeded + FAPI_TRY( io_repairs_exceeded.setBit(mss::index(i_target)) ); + FAPI_INF("%s Repairs exceeded (chip mark and symbol mark exist, plus one bad DQ) on rank:%d DQ:%d", + mss::c_str(i_target), i_rank, i_dq); + return fapi2::FAPI2_RC_SUCCESS; + fapi_try_exit: + return fapi2::current_err; + } + + /// + /// @brief Perform a repair for multiple bad DQ bits in a nibble + /// @param[in,out] io_machine the repair state machine + /// @param[in] i_target the DIMM target + /// @param[in] i_rank the rank + /// @param[in] i_dq one of the bad DQ bit indexes + /// @param[in,out] io_repairs_applied 8-bit mask, where a bit set means that rank had repairs applied + /// @param[in,out] io_repairs_exceeded 2-bit mask, where a bit set means that DIMM had more bad bits than could be repaired + /// @return FAPI2_RC_SUCCESS if and only if ok + /// + fapi2::ReturnCode multiple_bad_dq(repair_state_machine& io_machine, + const fapi2::Target& i_target, + const uint64_t i_rank, + const uint64_t i_dq, + fapi2::buffer& io_repairs_applied, + fapi2::buffer& io_repairs_exceeded) + { + // repairs exceeded + FAPI_TRY( io_repairs_exceeded.setBit(mss::index(i_target)) ); + FAPI_INF("%s Repairs exceeded (chip mark and symbol mark exist, plus one bad nibble) on rank:%d DQ:%d", + mss::c_str(i_target), i_rank, i_dq); + return fapi2::FAPI2_RC_SUCCESS; + fapi_try_exit: + return fapi2::current_err; + } +}; + +/// +/// @class mss::symbol_mark_plus_unrepaired_dq +/// @brief repair_state class for when only a symbol mark has been used, and one DQ bit remains unrepaired +/// @tparam T, the fapi2 target type of the DIMM +/// +template< fapi2::TargetType T > +class symbol_mark_plus_unrepaired_dq : public repair_state +{ + public: + /// @brief default contructor + symbol_mark_plus_unrepaired_dq() = default; + /// @brief default destructor + ~symbol_mark_plus_unrepaired_dq() = default; + + /// + /// @brief Perform a repair for a single bad DQ bit in a nibble + /// @param[in,out] io_machine the repair state machine + /// @param[in] i_target the DIMM target + /// @param[in] i_rank the rank + /// @param[in] i_dq the DQ bit index + /// @param[in,out] io_repairs_applied 8-bit mask, where a bit set means that rank had repairs applied + /// @param[in,out] io_repairs_exceeded 2-bit mask, where a bit set means that DIMM had more bad bits than could be repaired + /// @return FAPI2_RC_SUCCESS if and only if ok + /// + fapi2::ReturnCode one_bad_dq(repair_state_machine& io_machine, + const fapi2::Target& i_target, + const uint64_t i_rank, + const uint64_t i_dq, + fapi2::buffer& io_repairs_applied, + fapi2::buffer& io_repairs_exceeded) + { + // repairs exceeded + FAPI_INF("%s Repairs exceeded (symbol mark and unrepaired DQ exist, plus bad DQ) on rank:%d DQ:%d", + mss::c_str(i_target), i_rank, i_dq); + FAPI_TRY( io_repairs_exceeded.setBit(mss::index(i_target)) ); + return fapi2::FAPI2_RC_SUCCESS; + fapi_try_exit: + return fapi2::current_err; + } + + /// + /// @brief Perform a repair for multiple bad DQ bits in a nibble + /// @param[in,out] io_machine the repair state machine + /// @param[in] i_target the DIMM target + /// @param[in] i_rank the rank + /// @param[in] i_dq one of the bad DQ bit indexes + /// @param[in,out] io_repairs_applied 8-bit mask, where a bit set means that rank had repairs applied + /// @param[in,out] io_repairs_exceeded 2-bit mask, where a bit set means that DIMM had more bad bits than could be repaired + /// @return FAPI2_RC_SUCCESS if and only if ok + /// + fapi2::ReturnCode multiple_bad_dq(repair_state_machine& io_machine, + const fapi2::Target& i_target, + const uint64_t i_rank, + const uint64_t i_dq, + fapi2::buffer& io_repairs_applied, + fapi2::buffer& io_repairs_exceeded) + { + // place a chip mark, but also repairs exceeded + FAPI_TRY( place_chip_mark(i_target, i_rank, i_dq) ); + FAPI_TRY( io_repairs_applied.setBit(i_rank) ); + FAPI_TRY( io_repairs_exceeded.setBit(mss::index(i_target)) ); + FAPI_INF("%s Repairs exceeded (symbol mark and unrepaired DQ exist, plus bad nibble) on rank:%d DQ:%d", + mss::c_str(i_target), i_rank, i_dq); + { + const auto new_state = std::make_shared>(); + mss::repair_state::set_state(io_machine, new_state); + } + fapi_try_exit: + return fapi2::current_err; + } + +}; + +/// +/// @class mss::symbol_mark_only +/// @brief repair_state class for when only a symbol mark has been used +/// @tparam T, the fapi2 target type of the DIMM +/// +template< fapi2::TargetType T > +class symbol_mark_only : public repair_state +{ + public: + /// @brief default contructor + symbol_mark_only() = default; + /// @brief default destructor + ~symbol_mark_only() = default; + + /// + /// @brief Perform a repair for a single bad DQ bit in a nibble + /// @param[in,out] io_machine the repair state machine + /// @param[in] i_target the DIMM target + /// @param[in] i_rank the rank + /// @param[in] i_dq the DQ bit index + /// @param[in,out] io_repairs_applied 8-bit mask, where a bit set means that rank had repairs applied + /// @param[in,out] io_repairs_exceeded 2-bit mask, where a bit set means that DIMM had more bad bits than could be repaired + /// @return FAPI2_RC_SUCCESS if and only if ok + /// + fapi2::ReturnCode one_bad_dq(repair_state_machine& io_machine, + const fapi2::Target& i_target, + const uint64_t i_rank, + const uint64_t i_dq, + fapi2::buffer& io_repairs_applied, + fapi2::buffer& io_repairs_exceeded) + { + // leave an unrepaired DQ + const auto new_state = std::make_shared< symbol_mark_plus_unrepaired_dq >(); + mss::repair_state::set_state(io_machine, new_state); + return fapi2::FAPI2_RC_SUCCESS; + } + + /// + /// @brief Perform a repair for multiple bad DQ bits in a nibble + /// @param[in,out] io_machine the repair state machine + /// @param[in] i_target the DIMM target + /// @param[in] i_rank the rank + /// @param[in] i_dq one of the bad DQ bit indexes + /// @param[in,out] io_repairs_applied 8-bit mask, where a bit set means that rank had repairs applied + /// @param[in,out] io_repairs_exceeded 2-bit mask, where a bit set means that DIMM had more bad bits than could be repaired + /// @return FAPI2_RC_SUCCESS if and only if ok + /// + fapi2::ReturnCode multiple_bad_dq(repair_state_machine& io_machine, + const fapi2::Target& i_target, + const uint64_t i_rank, + const uint64_t i_dq, + fapi2::buffer& io_repairs_applied, + fapi2::buffer& io_repairs_exceeded) + { + // place a chip mark + FAPI_TRY( place_chip_mark(i_target, i_rank, i_dq) ); + FAPI_TRY( io_repairs_applied.setBit(i_rank) ); + { + const auto new_state = std::make_shared< chip_and_symbol_mark >(); + mss::repair_state::set_state(io_machine, new_state); + } + fapi_try_exit: + return fapi2::current_err; + } +}; + +/// +/// @class mss::chip_mark_only +/// @brief repair_state class for when only a chip mark has been used +/// @tparam T, the fapi2 target type of the DIMM +/// +template< fapi2::TargetType T > +class chip_mark_only : public repair_state +{ + public: + /// @brief default contructor + chip_mark_only() = default; + /// @brief default destructor + ~chip_mark_only() = default; + + /// + /// @brief Perform a repair for a single bad DQ bit in a nibble + /// @param[in,out] io_machine the repair state machine + /// @param[in] i_target the DIMM target + /// @param[in] i_rank the rank + /// @param[in] i_dq the DQ bit index + /// @param[in,out] io_repairs_applied 8-bit mask, where a bit set means that rank had repairs applied + /// @param[in,out] io_repairs_exceeded 2-bit mask, where a bit set means that DIMM had more bad bits than could be repaired + /// @return FAPI2_RC_SUCCESS if and only if ok + /// + fapi2::ReturnCode one_bad_dq(repair_state_machine& io_machine, + const fapi2::Target& i_target, + const uint64_t i_rank, + const uint64_t i_dq, + fapi2::buffer& io_repairs_applied, + fapi2::buffer& io_repairs_exceeded) + { + // place a symbol mark + FAPI_TRY( place_symbol_mark(i_target, i_rank, i_dq) ); + FAPI_TRY( io_repairs_applied.setBit(i_rank) ); + { + const auto new_state = std::make_shared>(); + mss::repair_state::set_state(io_machine, new_state); + } + fapi_try_exit: + return fapi2::current_err; + } + + /// + /// @brief Perform a repair for multiple bad DQ bits in a nibble + /// @param[in,out] io_machine the repair state machine + /// @param[in] i_target the DIMM target + /// @param[in] i_rank the rank + /// @param[in] i_dq one of the bad DQ bit indexes + /// @param[in,out] io_repairs_applied 8-bit mask, where a bit set means that rank had repairs applied + /// @param[in,out] io_repairs_exceeded 2-bit mask, where a bit set means that DIMM had more bad bits than could be repaired + /// @return FAPI2_RC_SUCCESS if and only if ok + /// + fapi2::ReturnCode multiple_bad_dq(repair_state_machine& io_machine, + const fapi2::Target& i_target, + const uint64_t i_rank, + const uint64_t i_dq, + fapi2::buffer& io_repairs_applied, + fapi2::buffer& io_repairs_exceeded) + { + // repairs exceeded + FAPI_TRY( io_repairs_exceeded.setBit(mss::index(i_target)) ); + FAPI_INF("%s Repairs exceeded (chip mark exists, plus bad nibble) on rank:%d DQ:%d", + mss::c_str(i_target), i_rank, i_dq); + return fapi2::FAPI2_RC_SUCCESS; + fapi_try_exit: + return fapi2::current_err; + } +}; + +/// +/// @class mss::no_fails +/// @brief repair_state class for no fails (no marks applied) +/// @tparam T, the fapi2 target type of the DIMM +/// +template< fapi2::TargetType T > +class no_fails : public repair_state +{ + public: + /// @brief default contructor + no_fails() = default; + /// @brief default destructor + ~no_fails() = default; + + /// + /// @brief Perform a repair for a single bad DQ bit in a nibble + /// @param[in,out] io_machine the repair state machine + /// @param[in] i_target the DIMM target + /// @param[in] i_rank the rank + /// @param[in] i_dq the DQ bit index + /// @param[in,out] io_repairs_applied 8-bit mask, where a bit set means that rank had repairs applied + /// @param[in,out] io_repairs_exceeded 2-bit mask, where a bit set means that DIMM had more bad bits than could be repaired + /// @return FAPI2_RC_SUCCESS if and only if ok + /// + fapi2::ReturnCode one_bad_dq(repair_state_machine& io_machine, + const fapi2::Target& i_target, + const uint64_t i_rank, + const uint64_t i_dq, + fapi2::buffer& io_repairs_applied, + fapi2::buffer& io_repairs_exceeded) + { + // place a symbol mark + FAPI_TRY( place_symbol_mark(i_target, i_rank, i_dq) ); + FAPI_TRY( io_repairs_applied.setBit(i_rank) ); + { + const auto new_state = std::make_shared>(); + mss::repair_state::set_state(io_machine, new_state); + } + fapi_try_exit: + return fapi2::current_err; + } + + /// + /// @brief Perform a repair for multiple bad DQ bits in a nibble + /// @param[in,out] io_machine the repair state machine + /// @param[in] i_target the DIMM target + /// @param[in] i_rank the rank + /// @param[in] i_dq one of the bad DQ bit indexes + /// @param[in,out] io_repairs_applied 8-bit mask, where a bit set means that rank had repairs applied + /// @param[in,out] io_repairs_exceeded 2-bit mask, where a bit set means that DIMM had more bad bits than could be repaired + /// @return FAPI2_RC_SUCCESS if and only if ok + /// + fapi2::ReturnCode multiple_bad_dq(repair_state_machine& io_machine, + const fapi2::Target& i_target, + const uint64_t i_rank, + const uint64_t i_dq, + fapi2::buffer& io_repairs_applied, + fapi2::buffer& io_repairs_exceeded) + { + // place a chip mark + FAPI_TRY( place_chip_mark(i_target, i_rank, i_dq) ); + FAPI_TRY( io_repairs_applied.setBit(i_rank) ); + { + const auto new_state = std::make_shared>(); + mss::repair_state::set_state(io_machine, new_state); + } + fapi_try_exit: + return fapi2::current_err; + } +}; + +/// +/// @class mss::repair_state_machine +/// @brief state machine class used in restore_repairs_helper +/// @tparam T, the fapi2 target type of the DIMM +/// +template< fapi2::TargetType T > +class repair_state_machine +{ + public: + /// @brief constructor + repair_state_machine() + : iv_repair_state(std::make_shared>()) {} + + /// @brief default destructor + ~repair_state_machine() = default; + + /// + /// @brief Perform a repair for a single bad DQ bit in a nibble + /// @param[in] i_target the DIMM target + /// @param[in] i_rank the rank + /// @param[in] i_dq the DQ bit index + /// @param[in,out] io_repairs_applied 8-bit mask, where a bit set means that rank had repairs applied + /// @param[in,out] io_repai:rs_exceeded 2-bit mask, where a bit set means that DIMM had more bad bits than could be repaired + /// @return FAPI2_RC_SUCCESS if and only if ok + /// + fapi2::ReturnCode one_bad_dq(const fapi2::Target& i_target, + const uint64_t i_rank, + const uint64_t i_dq, + fapi2::buffer& io_repairs_applied, + fapi2::buffer& io_repairs_exceeded) + { + FAPI_TRY( iv_repair_state->one_bad_dq(*this, i_target, i_rank, i_dq, io_repairs_applied, io_repairs_exceeded) ); + fapi_try_exit: + return fapi2::current_err; + } + + /// + /// @brief Perform a repair for multiple bad DQ bits in a nibble + /// @param[in] i_target the DIMM target + /// @param[in] i_rank the rank + /// @param[in] i_dq one of the bad DQ bit indexes + /// @param[in,out] io_repairs_applied 8-bit mask, where a bit set means that rank had repairs applied + /// @param[in,out] io_repairs_exceeded 2-bit mask, where a bit set means that DIMM had more bad bits than could be repaired + /// @return FAPI2_RC_SUCCESS if and only if ok + /// + fapi2::ReturnCode multiple_bad_dq(const fapi2::Target& i_target, + const uint64_t i_rank, + const uint64_t i_dq, + fapi2::buffer& io_repairs_applied, + fapi2::buffer& io_repairs_exceeded) + { + FAPI_TRY( iv_repair_state->multiple_bad_dq(*this, i_target, i_rank, i_dq, io_repairs_applied, io_repairs_exceeded) ); + fapi_try_exit: + return fapi2::current_err; + } + + /// + /// @brief Update the state of the state machine + /// @param[in] i_state shared pointer to the new state + /// + void update_state(std::shared_ptr> i_state) + { + iv_repair_state = i_state; + } + + private: + std::shared_ptr> iv_repair_state; +}; /// @brief Get the attributes for the reorder queue setting /// @tparam MC the memory controller type -/// @tparam T, the mc +/// @tparam T, the fapi2 target type of the target /// @param[in] const ref to the mc target /// @param[out] uint8_t& reference to store the value /// @return fapi2::ReturnCode - FAPI2_RC_SUCCESS iff get is OK /// @note Contains the settings for write/read reorder queue /// template< mss::mc_type MC = DEFAULT_MC_TYPE, fapi2::TargetType T > -inline fapi2::ReturnCode reorder_queue_setting(const fapi2::Target& i_target, uint8_t& o_value); +fapi2::ReturnCode reorder_queue_setting(const fapi2::Target& i_target, uint8_t& o_value); /// /// @brief Resets the write/read reorder queue values - needs to be called after MCBIST execution @@ -644,6 +1200,136 @@ fapi_try_exit: return fapi2::current_err; } +/// +/// @brief Convert a bitmap from the BAD_DQ_BITMAP attribute to a vector of bad DQ indexes +/// @param[in] i_bad_bits an 8-bit bitmap of bad bits +/// @param[in] i_nibble which nibble of the bitmap to convert +/// @return std::vector of DQ bits marked as bad in the bitmap +/// +inline std::vector bad_bit_helper(const uint8_t i_bad_bits, const size_t i_nibble) +{ + std::vector l_output; + fapi2::buffer l_bit_buffer(i_bad_bits); + + const size_t l_start = (i_nibble == 0) ? 0 : mss::conversions::BITS_PER_NIBBLE; + + for (size_t l_offset = 0; l_offset < mss::conversions::BITS_PER_NIBBLE; ++l_offset) + { + const size_t l_position_tmp = l_start + l_offset; + + if (l_bit_buffer.getBit(l_position_tmp)) + { + l_output.push_back(l_position_tmp); + } + } + + return l_output; +} + +// TODO: RTC: 157753 tparam R can be pulled from an PORT trait once we have it +// +/// @brief Restore symbol and chip marks according to BAD_DQ_BITMAP attribute, helper function for unit testing +/// @tparam MC the memory controller type +/// @tparam T, the fapi2 target type of the DIMM (derived) +/// @tparam R the maximum rank per DIMM +/// @tparam B the number of bytes per rank in the bad_dq_bitmap attribute +/// @param[in] i_target A target representing a DIMM +/// @param[in] i_bad_bits the bad bits values from the VPD, for the specified DIMM +/// @param[in,out] io_repairs_applied 8-bit mask, where a bit set means that rank had repairs applied +/// @param[in,out] io_repairs_exceeded 2-bit mask, where a bit set means that DIMM had more bad bits than could be repaired +/// @return FAPI2_RC_SUCCESS if and only if ok +/// +template< mss::mc_type MC = DEFAULT_MC_TYPE, fapi2::TargetType T, uint64_t R, uint64_t B > +inline fapi2::ReturnCode restore_repairs_helper( const fapi2::Target& i_target, + const uint8_t i_bad_bits[R][B], + fapi2::buffer& io_repairs_applied, + fapi2::buffer& io_repairs_exceeded) +{ + FAPI_INF("%s Restore repair marks from bad DQ data", mss::c_str(i_target)); + + using MCT = mss::mcbistMCTraits; + using MT = mss::mcbistTraits; + + std::vector l_ranks; + const auto l_dimm_idx = index(i_target); + + // gets all of the ranks to loop over + FAPI_TRY( mss::rank::ranks_on_dimm_helper(i_target, l_ranks) ); + + // loop through ranks + for (const auto l_rank : l_ranks) + { + const auto l_rank_idx = index(l_rank); + + repair_state_machine l_machine; + + for (uint64_t l_byte = 0; l_byte < (MT::MAX_DQ_NIBBLES / mss::conversions::NIBBLES_PER_BYTE); ++l_byte) + { + for (size_t l_nibble = 0; l_nibble < mss::conversions::NIBBLES_PER_BYTE; ++l_nibble) + { + const auto l_bad_dq_vector = bad_bit_helper(i_bad_bits[l_rank_idx][l_byte], l_nibble); + FAPI_DBG("Total bad bits on DIMM:%d rank:%d nibble%d: %d", + l_dimm_idx, l_rank, (l_byte * NIBBLES_PER_BYTE) + l_nibble, l_bad_dq_vector.size()); + + // apply repairs and update repair machine state + // if there are no bad bits (l_bad_dq_vector.size() == 0) no action is necessary + if (l_bad_dq_vector.size() == 1) + { + // l_bad_dq_vector is per byte, so multiply up to get the bad dq's index + const uint64_t l_dq = l_bad_dq_vector[0] + (l_byte * BITS_PER_BYTE); + FAPI_TRY( l_machine.one_bad_dq(i_target, l_rank, l_dq, io_repairs_applied, io_repairs_exceeded) ); + } + else if (l_bad_dq_vector.size() > 1) + { + // l_bad_dq_vector is per byte, so multiply up to get the bad dq's index + const uint64_t l_dq = l_bad_dq_vector[0] + (l_byte * BITS_PER_BYTE); + FAPI_TRY( l_machine.multiple_bad_dq(i_target, l_rank, l_dq, io_repairs_applied, io_repairs_exceeded) ); + } + + // if repairs have been exceeded, we're done + if (io_repairs_exceeded.getBit(l_dimm_idx)) + { + FAPI_INF("Repairs exceeded on DIMM %s", c_str(i_target)); + return fapi2::FAPI2_RC_SUCCESS; + } + } // end loop through nibbles + } // end loop through bytes + } // end loop through ranks + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Restore symbol and chip marks according to BAD_DQ_BITMAP attribute +/// @tparam MC, the memory controller type +/// @tparam T, the fapi2 target type of the port (derived) +/// @param[in] i_target A target representing a port +/// @param[in,out] io_repairs_applied bit mask, where a bit set means a rank had repairs applied (bit0 = rank0, etc) +/// @param[in,out] io_repairs_exceeded bit mask, where a bit set means a DIMM had more bad bits than could be repaired (bit0 = DIMM0 etc) +/// @return FAPI2_RC_SUCCESS if and only if ok +/// +template< mss::mc_type MC = DEFAULT_MC_TYPE, fapi2::TargetType T > +inline fapi2::ReturnCode restore_repairs( const fapi2::Target& i_target, + fapi2::buffer& io_repairs_applied, + fapi2::buffer& io_repairs_exceeded) +{ + uint8_t l_bad_bits[BAD_BITS_RANKS][BAD_DQ_BYTE_COUNT] = {}; + + io_repairs_applied = 0; + io_repairs_exceeded = 0; + + for (const auto& l_dimm : mss::find_targets(i_target)) + { + FAPI_TRY( mss::get_bad_dq_bitmap(l_dimm, l_bad_bits) ); + + FAPI_TRY( (restore_repairs_helper( + l_dimm, l_bad_bits, io_repairs_applied, io_repairs_exceeded)) ); + } + +fapi_try_exit: + return fapi2::current_err; +} }// ns mss diff --git a/src/import/generic/memory/lib/utils/mcbist/gen_mss_mcbist.H b/src/import/generic/memory/lib/utils/mcbist/gen_mss_mcbist.H index 12ffbbef8..ac62cad03 100644 --- a/src/import/generic/memory/lib/utils/mcbist/gen_mss_mcbist.H +++ b/src/import/generic/memory/lib/utils/mcbist/gen_mss_mcbist.H @@ -5,7 +5,7 @@ /* */ /* OpenPOWER HostBoot Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2019 */ +/* Contributors Listed Below - COPYRIGHT 2019,2020 */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -40,11 +40,12 @@ #include #include +#include #include #include #include +#include #include -#include namespace mss { @@ -2129,7 +2130,7 @@ class program inline fapi2::ReturnCode process_errors( const fapi2::Target i_target ) const { // MCBIST error traits - using ET = mcbistMCTraits; + using ET = mcbistMCTraits; // Until reading the error array is documented, comparison errors 'just' result in // a flag indicating there was a problem on port. @@ -3287,8 +3288,8 @@ inline fapi2::ReturnCode load_fifo_mode( const fapi2::Target& i_target, const // Turns on FIFO mode constexpr mss::states FIFO_ON = mss::states::ON; - FAPI_TRY(mss::configure_wrq(i_target, FIFO_ON)); - FAPI_TRY(mss::configure_rrq(i_target, FIFO_ON)); + FAPI_TRY( configure_wrq(i_target, FIFO_ON) ); + FAPI_TRY( configure_rrq(i_target, FIFO_ON) ); fapi_try_exit: return fapi2::current_err; @@ -3725,6 +3726,23 @@ fapi_try_exit: } // namespace mcbist +namespace ecc +{ + +/// +/// @brief Clear all MAINT.ECC counters +/// @tparam T the fapi2::TargetType - derived +/// @param[in] i_target the fapi2 target +/// @return fapi2::ReturnCode FAPI2_RC_SUCCESS if ok +/// +template< fapi2::TargetType T > +inline fapi2::ReturnCode clear_all_counters( const fapi2::Target& i_target ) +{ + return ( mss::mcbist::reset_errors(i_target) ); +} + +} // namespace ecc + } // namespace mss #endif diff --git a/src/import/generic/memory/lib/utils/mss_rank.H b/src/import/generic/memory/lib/utils/mss_rank.H index 4525765c2..f4731df46 100644 --- a/src/import/generic/memory/lib/utils/mss_rank.H +++ b/src/import/generic/memory/lib/utils/mss_rank.H @@ -5,7 +5,7 @@ /* */ /* OpenPOWER HostBoot Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2019 */ +/* Contributors Listed Below - COPYRIGHT 2019,2020 */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -49,12 +49,15 @@ namespace rank /// /// @brief Rank traits class for variations depending on MC +/// @tparam MC the memory controller type /// template class rankTraits; /// /// @brief Rank info class +/// @tparam MC the memory controller type +/// @tparam TT the class traits for the port /// template > class info @@ -245,6 +248,8 @@ class info /// /// @brief Obtains all DIMM ranks on a given port target +/// @tparam MC the memory controller type +/// @tparam TT the class traits for the port /// @param[in] i_port_target port target /// @param[out] o_vect vector of ranks /// @return FAPI2_RC_SUCCESS iff success @@ -288,6 +293,8 @@ fapi_try_exit: /// /// @brief Obtains all ranks on a given DIMM target +/// @tparam MC the memory controller type +/// @tparam TT the class traits for the port /// @param[in] i_target DIMM target /// @param[out] o_vect vector of ranks /// @return FAPI2_RC_SUCCESS iff success @@ -325,6 +332,17 @@ fapi_try_exit: return fapi2::current_err; } +/// +/// @brief Return a vector of rank numbers which represent the ranks for this dimm +/// @tparam MC the memory controller type +/// @param[in] i_dimm_target TARGET_TYPE_DIMM +/// @param[out] o_ranks a vector of ranks for dimm (numbers) +/// @return FAPI2_RC_SUCCESS iff all is ok +/// +template +fapi2::ReturnCode ranks_on_dimm_helper(const fapi2::Target& i_dimm_target, + std::vector& o_ranks); + } // rank } // mss #endif -- cgit v1.2.1