summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/import/chips/ocmb/explorer/procedures/hwp/memory/exp_scrub.C3
-rw-r--r--src/import/chips/ocmb/explorer/procedures/hwp/memory/lib/dimm/exp_rank.H31
-rw-r--r--src/import/chips/ocmb/explorer/procedures/hwp/memory/lib/mc/exp_port.H5
-rw-r--r--src/import/chips/ocmb/explorer/procedures/hwp/memory/lib/mcbist/exp_mcbist.H4
-rw-r--r--src/import/chips/ocmb/explorer/procedures/hwp/memory/lib/mcbist/exp_mcbist_traits.H2
-rw-r--r--src/import/chips/p9/procedures/hwp/memory/lib/dimm/ddr4/nvdimm_utils.C6
-rw-r--r--src/import/chips/p9/procedures/hwp/memory/lib/dimm/rank.C21
-rw-r--r--src/import/chips/p9/procedures/hwp/memory/lib/mc/port.C250
-rw-r--r--src/import/chips/p9/procedures/hwp/memory/lib/mc/port.H435
-rw-r--r--src/import/chips/p9/procedures/hwp/memory/lib/mcbist/mcbist.H4
-rw-r--r--src/import/chips/p9/procedures/hwp/memory/lib/phy/mss_training.C16
-rw-r--r--src/import/generic/memory/lib/ecc/ecc.H17
-rw-r--r--src/import/generic/memory/lib/ecc/fw_mark_store.H10
-rw-r--r--src/import/generic/memory/lib/utils/mc/gen_mss_port.H698
-rw-r--r--src/import/generic/memory/lib/utils/mcbist/gen_mss_mcbist.H28
-rw-r--r--src/import/generic/memory/lib/utils/mss_rank.H20
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 <lib/shared/exp_defaults.H>
#include <exp_scrub.H>
+#include <lib/utils/mss_exp_conversions.H>
#include <lib/mcbist/exp_memdiags.H>
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<mss::mc_type::EXPLORER>(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>&
+ i_dimm_target,
+ std::vector<uint64_t>& o_ranks)
+{
+ std::vector<uint64_t> l_ranks;
+ std::vector<mss::rank::info<>> l_vect;
+
+ FAPI_TRY( mss::rank::ranks_on_dimm<mss::mc_type::EXPLORER>(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 <explorer_scom_addresses_fld.H>
#include <explorer_scom_addresses_fld_fixes.H>
#include <lib/exp_attribute_accessors_manual.H>
+#include <lib/utils/mss_exp_conversions.H>
+#include <mss_explorer_attribute_getters.H>
#include <lib/shared/exp_consts.H>
#include <lib/dimm/exp_rank.H>
#include <generic/memory/lib/utils/mc/gen_mss_port.H>
#include <generic/memory/lib/utils/shared/mss_generic_consts.H>
#include <mss_generic_attribute_getters.H>
-#include <mss_explorer_attribute_getters.H>
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 <lib/shared/exp_consts.H>
#include <lib/ecc/ecc_traits_explorer.H>
+#include <lib/mcbist/exp_mcbist_traits.H>
#include <lib/mc/exp_port.H>
#include <lib/utils/mss_exp_conversions.H>
-#include <lib/mcbist/exp_mcbist_traits.H>
#include <generic/memory/lib/utils/poll.H>
#include <generic/memory/lib/utils/memory_size.H>
#include <generic/memory/lib/utils/mcbist/gen_mss_mcbist_patterns.H>
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 <lib/shared/exp_consts.H>
#include <generic/memory/lib/utils/shared/mss_generic_consts.H>
#include <generic/memory/lib/utils/mcbist/gen_mss_mcbist_address.H>
-#include <generic/memory/lib/utils/mcbist/gen_mss_mcbist_traits.H>
+#include <generic/memory/lib/utils/mcbist/gen_mss_mcbist.H>
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 <lib/mc/mc.H>
#include <lib/dimm/rank.H>
#include <lib/mss_attribute_accessors.H>
+#include <lib/mcbist/mcbist.H>
+#include <lib/utils/mss_nimbus_conversions.H>
#include <generic/memory/lib/utils/poll.H>
#include <generic/memory/lib/utils/count_dimm.H>
#include <generic/memory/lib/utils/mc/gen_mss_port.H>
#include <lib/mcbist/address.H>
#include <lib/mcbist/memdiags.H>
-#include <lib/mcbist/mcbist.H>
#include <lib/mcbist/settings.H>
-#include <lib/utils/mss_nimbus_conversions.H>
#include <generic/memory/lib/utils/pos.H>
#include <lib/mc/port.H>
#include <lib/phy/dp16.H>
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<mss::mc_type::NIMBUS>(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>&
+ i_dimm_target,
+ std::vector<uint64_t>& o_ranks)
+{
+ std::vector<uint64_t> 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. */
/* */
/* */
@@ -307,210 +307,6 @@ fapi_try_exit:
}
///
-/// @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<uint64_t> bad_bit_helper(const uint8_t i_bad_bits, const size_t i_nibble)
-{
- std::vector<uint64_t> l_output;
- fapi2::buffer<uint8_t> 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<fapi2::TARGET_TYPE_DIMM>& i_target,
- const uint64_t i_rank,
- const uint64_t i_dq)
-{
- const auto& l_mca = mss::find_target<fapi2::TARGET_TYPE_MCA>(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<uint8_t>(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<fapi2::TARGET_TYPE_DIMM>& i_target,
- const uint64_t i_rank,
- const uint64_t i_dq)
-{
- const auto& l_mca = mss::find_target<fapi2::TARGET_TYPE_MCA>(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<uint8_t>(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<fapi2::TARGET_TYPE_DIMM, BAD_BITS_RANKS, BAD_DQ_BYTE_COUNT>(
- const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target,
- const uint8_t i_bad_bits[BAD_BITS_RANKS][BAD_DQ_BYTE_COUNT],
- fapi2::buffer<uint8_t>& o_repairs_applied,
- fapi2::buffer<uint8_t>& o_repairs_exceeded)
-{
- FAPI_INF("%s Restore repair marks from bad DQ data", mss::c_str(i_target));
-
- std::vector<uint64_t> 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<fapi2::TARGET_TYPE_DIMM> 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<fapi2::TARGET_TYPE_MCA>& i_target,
- fapi2::buffer<uint8_t>& o_repairs_applied,
- fapi2::buffer<uint8_t>& 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<fapi2::TARGET_TYPE_DIMM>(i_target))
- {
- FAPI_TRY( mss::bad_dq_bitmap(l_dimm, &(l_bad_bits[0][0])) );
-
- FAPI_TRY( (restore_repairs_helper<fapi2::TARGET_TYPE_DIMM, BAD_BITS_RANKS, BAD_DQ_BYTE_COUNT>(
- 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<T>::set_state(repair_state_machine<T>& io_machine, std::shared_ptr<repair_state<T>> 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
/// @param[in,out] io_machine the repair state machine
@@ -803,48 +599,4 @@ fapi2::ReturnCode chip_and_symbol_mark<fapi2::TARGET_TYPE_DIMM>::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<T>::one_bad_dq(const fapi2::Target<T>& i_target,
- const uint64_t i_rank,
- const uint64_t i_dq,
- fapi2::buffer<uint8_t>& io_repairs_applied,
- fapi2::buffer<uint8_t>& 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<T>::multiple_bad_dq(const fapi2::Target<T>& i_target,
- const uint64_t i_rank,
- const uint64_t i_dq,
- fapi2::buffer<uint8_t>& io_repairs_applied,
- fapi2::buffer<uint8_t>& 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 <lib/mss_attribute_accessors.H>
#include <lib/shared/mss_const.H>
+#include <lib/utils/mss_nimbus_conversions.H>
#include <generic/memory/lib/utils/scom.H>
#include <generic/memory/lib/utils/c_str.H>
#include <generic/memory/lib/utils/mc/gen_mss_port.H>
#include <p9_mc_scom_addresses.H>
#include <p9_mc_scom_addresses_fld.H>
-#include <lib/utils/mss_nimbus_conversions.H>
#include <lib/dimm/rank.H>
#include <lib/mcbist/address.H>
@@ -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<uint64_t> 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<T>& 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<T>& 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<T>& io_machine,
- const fapi2::Target<T>& i_target,
- const uint64_t i_rank,
- const uint64_t i_dq,
- fapi2::buffer<uint8_t>& io_repairs_applied,
- fapi2::buffer<uint8_t>& 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<T>& io_machine,
- const fapi2::Target<T>& i_target,
- const uint64_t i_rank,
- const uint64_t i_dq,
- fapi2::buffer<uint8_t>& io_repairs_applied,
- fapi2::buffer<uint8_t>& 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<T>& io_machine, std::shared_ptr<repair_state<T>> 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<T>
-{
- 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<T>& io_machine,
- const fapi2::Target<T>& i_target,
- const uint64_t i_rank,
- const uint64_t i_dq,
- fapi2::buffer<uint8_t>& io_repairs_applied,
- fapi2::buffer<uint8_t>& 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<T>& io_machine,
- const fapi2::Target<T>& i_target,
- const uint64_t i_rank,
- const uint64_t i_dq,
- fapi2::buffer<uint8_t>& io_repairs_applied,
- fapi2::buffer<uint8_t>& 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<T>
-{
- 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<T>& io_machine,
- const fapi2::Target<T>& i_target,
- const uint64_t i_rank,
- const uint64_t i_dq,
- fapi2::buffer<uint8_t>& io_repairs_applied,
- fapi2::buffer<uint8_t>& 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<T>& io_machine,
- const fapi2::Target<T>& i_target,
- const uint64_t i_rank,
- const uint64_t i_dq,
- fapi2::buffer<uint8_t>& io_repairs_applied,
- fapi2::buffer<uint8_t>& 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<T>
-{
- 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<T>& io_machine,
- const fapi2::Target<T>& i_target,
- const uint64_t i_rank,
- const uint64_t i_dq,
- fapi2::buffer<uint8_t>& io_repairs_applied,
- fapi2::buffer<uint8_t>& 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<T>& io_machine,
- const fapi2::Target<T>& i_target,
- const uint64_t i_rank,
- const uint64_t i_dq,
- fapi2::buffer<uint8_t>& io_repairs_applied,
- fapi2::buffer<uint8_t>& 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<T>
-{
- 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<T>& io_machine,
- const fapi2::Target<T>& i_target,
- const uint64_t i_rank,
- const uint64_t i_dq,
- fapi2::buffer<uint8_t>& io_repairs_applied,
- fapi2::buffer<uint8_t>& 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<T>& io_machine,
- const fapi2::Target<T>& i_target,
- const uint64_t i_rank,
- const uint64_t i_dq,
- fapi2::buffer<uint8_t>& io_repairs_applied,
- fapi2::buffer<uint8_t>& 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<T>
-{
- 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<T>& io_machine,
- const fapi2::Target<T>& i_target,
- const uint64_t i_rank,
- const uint64_t i_dq,
- fapi2::buffer<uint8_t>& io_repairs_applied,
- fapi2::buffer<uint8_t>& 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<T>& io_machine,
- const fapi2::Target<T>& i_target,
- const uint64_t i_rank,
- const uint64_t i_dq,
- fapi2::buffer<uint8_t>& io_repairs_applied,
- fapi2::buffer<uint8_t>& 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<no_fails<T>>()) {}
-
- /// @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<T>& i_target,
- const uint64_t i_rank,
- const uint64_t i_dq,
- fapi2::buffer<uint8_t>& io_repairs_applied,
- fapi2::buffer<uint8_t>& 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<T>& i_target,
- const uint64_t i_rank,
- const uint64_t i_dq,
- fapi2::buffer<uint8_t>& io_repairs_applied,
- fapi2::buffer<uint8_t>& 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<repair_state<T>> i_state)
- {
- iv_repair_state = i_state;
- }
-
- private:
- std::shared_ptr<repair_state<T>> 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<T>& i_target,
- const uint8_t i_bad_bits[R][B],
- fapi2::buffer<uint8_t>& io_repairs_applied,
- fapi2::buffer<uint8_t>& 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<T>& i_target,
- fapi2::buffer<uint8_t>& o_repairs_applied,
- fapi2::buffer<uint8_t>& 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 <lib/utils/bit_count.H>
#include <lib/dimm/nimbus_kind.H>
#include <lib/mcbist/mcbist_traits.H>
+#include <lib/workarounds/mcbist_workarounds.H>
#include <generic/memory/lib/utils/num.H>
#include <generic/memory/lib/utils/poll.H>
#include <generic/memory/lib/utils/memory_size.H>
@@ -55,7 +56,6 @@
#include <generic/memory/lib/utils/mcbist/gen_mss_mcbist_settings.H>
#include <generic/memory/lib/utils/mcbist/gen_mss_mcbist.H>
#include <generic/memory/lib/utils/dump_regs.H>
-#include <lib/workarounds/mcbist_workarounds.H>
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 <lib/dimm/ddr4/pda.H>
#include <lib/phy/seq.H>
#include <lib/phy/read_cntrl.H>
+#include <lib/mss_attribute_accessors.H>
#ifdef LRDIMM_CAPABLE
#include <lib/phy/mss_dwl.H>
@@ -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<mss::mc_type::NIMBUS>(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& 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 <fapi2.H>
-#include <generic/memory/lib/utils/mcbist/gen_mss_mcbist.H>
#include <generic/memory/lib/utils/mcbist/gen_mss_mcbist_address.H>
#include <generic/memory/lib/utils/shared/mss_generic_consts.H>
+#include <generic/memory/lib/utils/mcbist/gen_mss_mcbist.H>
#include <generic/memory/lib/ecc/ecc_traits.H>
#include <generic/memory/lib/ecc/galois.H>
#include <generic/memory/lib/ecc/hw_mark_store.H>
@@ -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<T>& 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<uint64_t>& 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<DEFAULT_MC_TYPE, T> >
+template< mss::mc_type MC = DEFAULT_MC_TYPE, fapi2::TargetType T = DEFAULT_MEM_PORT_TARGET, typename TT = eccTraits<DEFAULT_MC_TYPE, T> >
inline void set_address( fapi2::buffer<uint64_t>& 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<MC, T, TT>(i_address);
io_data.insert<TT::FIRMWARE_MS_ADDRESS, TT::FIRMWARE_MS_ADDRESS_LEN, TT::FIRMWARE_MS_ADDRESS>(l_addr);
FAPI_INF("set_address: 0x%016lx", uint64_t(l_addr));
}
@@ -569,11 +569,11 @@ inline void set_address( fapi2::buffer<uint64_t>& 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<DEFAULT_MC_TYPE, T> >
+template< mss::mc_type MC = DEFAULT_MC_TYPE, fapi2::TargetType T = DEFAULT_MEM_PORT_TARGET, typename TT = eccTraits<DEFAULT_MC_TYPE, T> >
inline void get_address( const fapi2::buffer<uint64_t>& 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<MC, T, TT>(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 <generic/memory/lib/utils/mc/gen_mss_port_traits.H>
#include <generic/memory/lib/utils/scom.H>
#include <generic/memory/lib/utils/c_str.H>
+#include <generic/memory/lib/ecc/ecc.H>
+#include <generic/memory/lib/utils/mss_bad_bits.H>
+#include <generic/memory/lib/utils/mss_rank.H>
namespace mss
{
@@ -163,11 +166,10 @@ void get_bw_snapshot( const fapi2::buffer<uint64_t>& i_data, uint64_t& o_bw_snap
/// @param[in] const ref to the fapi2::Target<fapi2::TargetType>
/// @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<MC> >
+inline fapi2::ReturnCode place_symbol_mark(const fapi2::Target<T>& i_target,
+ const uint64_t i_rank,
+ const uint64_t i_dq)
+{
+ const auto& l_port = mss::find_target<TT::PORT_TYPE>(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<uint8_t>(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<MC> >
+inline fapi2::ReturnCode place_chip_mark(const fapi2::Target<T>& i_target,
+ const uint64_t i_rank,
+ const uint64_t i_dq)
+{
+ const auto& l_port = mss::find_target<TT::PORT_TYPE>(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<uint8_t>(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<T>& io_machine,
+ const fapi2::Target<T>& i_target,
+ const uint64_t i_rank,
+ const uint64_t i_dq,
+ fapi2::buffer<uint8_t>& io_repairs_applied,
+ fapi2::buffer<uint8_t>& 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<T>& io_machine,
+ const fapi2::Target<T>& i_target,
+ const uint64_t i_rank,
+ const uint64_t i_dq,
+ fapi2::buffer<uint8_t>& io_repairs_applied,
+ fapi2::buffer<uint8_t>& 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<T>& io_machine, std::shared_ptr<repair_state<T>> 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<T>
+{
+ 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<T>& io_machine,
+ const fapi2::Target<T>& i_target,
+ const uint64_t i_rank,
+ const uint64_t i_dq,
+ fapi2::buffer<uint8_t>& io_repairs_applied,
+ fapi2::buffer<uint8_t>& 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<T>& io_machine,
+ const fapi2::Target<T>& i_target,
+ const uint64_t i_rank,
+ const uint64_t i_dq,
+ fapi2::buffer<uint8_t>& io_repairs_applied,
+ fapi2::buffer<uint8_t>& 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<T>
+{
+ 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<T>& io_machine,
+ const fapi2::Target<T>& i_target,
+ const uint64_t i_rank,
+ const uint64_t i_dq,
+ fapi2::buffer<uint8_t>& io_repairs_applied,
+ fapi2::buffer<uint8_t>& 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<T>& io_machine,
+ const fapi2::Target<T>& i_target,
+ const uint64_t i_rank,
+ const uint64_t i_dq,
+ fapi2::buffer<uint8_t>& io_repairs_applied,
+ fapi2::buffer<uint8_t>& 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<chip_and_symbol_mark<fapi2::TARGET_TYPE_DIMM>>();
+ mss::repair_state<T>::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<T>
+{
+ 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<T>& io_machine,
+ const fapi2::Target<T>& i_target,
+ const uint64_t i_rank,
+ const uint64_t i_dq,
+ fapi2::buffer<uint8_t>& io_repairs_applied,
+ fapi2::buffer<uint8_t>& io_repairs_exceeded)
+ {
+ // leave an unrepaired DQ
+ const auto new_state = std::make_shared< symbol_mark_plus_unrepaired_dq<T> >();
+ mss::repair_state<T>::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<T>& io_machine,
+ const fapi2::Target<T>& i_target,
+ const uint64_t i_rank,
+ const uint64_t i_dq,
+ fapi2::buffer<uint8_t>& io_repairs_applied,
+ fapi2::buffer<uint8_t>& 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<T> >();
+ mss::repair_state<T>::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<T>
+{
+ 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<T>& io_machine,
+ const fapi2::Target<T>& i_target,
+ const uint64_t i_rank,
+ const uint64_t i_dq,
+ fapi2::buffer<uint8_t>& io_repairs_applied,
+ fapi2::buffer<uint8_t>& 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<chip_and_symbol_mark<fapi2::TARGET_TYPE_DIMM>>();
+ mss::repair_state<T>::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<T>& io_machine,
+ const fapi2::Target<T>& i_target,
+ const uint64_t i_rank,
+ const uint64_t i_dq,
+ fapi2::buffer<uint8_t>& io_repairs_applied,
+ fapi2::buffer<uint8_t>& 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<T>
+{
+ 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<T>& io_machine,
+ const fapi2::Target<T>& i_target,
+ const uint64_t i_rank,
+ const uint64_t i_dq,
+ fapi2::buffer<uint8_t>& io_repairs_applied,
+ fapi2::buffer<uint8_t>& 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<symbol_mark_only<fapi2::TARGET_TYPE_DIMM>>();
+ mss::repair_state<T>::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<T>& io_machine,
+ const fapi2::Target<T>& i_target,
+ const uint64_t i_rank,
+ const uint64_t i_dq,
+ fapi2::buffer<uint8_t>& io_repairs_applied,
+ fapi2::buffer<uint8_t>& 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_mark_only<fapi2::TARGET_TYPE_DIMM>>();
+ mss::repair_state<T>::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<no_fails<T>>()) {}
+
+ /// @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<T>& i_target,
+ const uint64_t i_rank,
+ const uint64_t i_dq,
+ fapi2::buffer<uint8_t>& io_repairs_applied,
+ fapi2::buffer<uint8_t>& 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<T>& i_target,
+ const uint64_t i_rank,
+ const uint64_t i_dq,
+ fapi2::buffer<uint8_t>& io_repairs_applied,
+ fapi2::buffer<uint8_t>& 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<repair_state<T>> i_state)
+ {
+ iv_repair_state = i_state;
+ }
+
+ private:
+ std::shared_ptr<repair_state<T>> 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<T>& i_target, uint8_t& o_value);
+fapi2::ReturnCode reorder_queue_setting(const fapi2::Target<T>& 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<uint64_t> bad_bit_helper(const uint8_t i_bad_bits, const size_t i_nibble)
+{
+ std::vector<uint64_t> l_output;
+ fapi2::buffer<uint8_t> 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<T>& i_target,
+ const uint8_t i_bad_bits[R][B],
+ fapi2::buffer<uint8_t>& io_repairs_applied,
+ fapi2::buffer<uint8_t>& io_repairs_exceeded)
+{
+ FAPI_INF("%s Restore repair marks from bad DQ data", mss::c_str(i_target));
+
+ using MCT = mss::mcbistMCTraits<MC>;
+ using MT = mss::mcbistTraits<MC, MCT::MC_TARGET_TYPE>;
+
+ std::vector<uint64_t> 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<MC>(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<fapi2::TARGET_TYPE_DIMM> 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<T>& i_target,
+ fapi2::buffer<uint8_t>& io_repairs_applied,
+ fapi2::buffer<uint8_t>& 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<fapi2::TARGET_TYPE_DIMM>(i_target))
+ {
+ FAPI_TRY( mss::get_bad_dq_bitmap<MC>(l_dimm, l_bad_bits) );
+
+ FAPI_TRY( (restore_repairs_helper<MC, fapi2::TARGET_TYPE_DIMM, BAD_BITS_RANKS, BAD_DQ_BYTE_COUNT>(
+ 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 <generic/memory/lib/utils/poll.H>
#include <generic/memory/lib/utils/memory_size.H>
+#include <generic/memory/lib/utils/mc/gen_mss_port.H>
#include <generic/memory/lib/utils/mcbist/gen_mss_mcbist_patterns.H>
#include <generic/memory/lib/utils/mcbist/gen_mss_mcbist_settings.H>
#include <generic/memory/lib/utils/mcbist/gen_mss_mcbist_traits.H>
+#include <generic/memory/lib/utils/conversions.H>
#include <generic/memory/lib/utils/num.H>
-#include <generic/memory/lib/utils/mc/gen_mss_port.H>
namespace mss
{
@@ -2129,7 +2130,7 @@ class program
inline fapi2::ReturnCode process_errors( const fapi2::Target<T> i_target ) const
{
// MCBIST error traits
- using ET = mcbistMCTraits<DEFAULT_MC_TYPE>;
+ using ET = mcbistMCTraits<MC>;
// 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<T>& 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<T>& 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 <mss::mc_type MC = DEFAULT_MC_TYPE>
class rankTraits;
///
/// @brief Rank info class
+/// @tparam MC the memory controller type
+/// @tparam TT the class traits for the port
///
template <mss::mc_type MC = DEFAULT_MC_TYPE, typename TT = rankTraits<MC>>
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<mss::mc_type MC>
+fapi2::ReturnCode ranks_on_dimm_helper(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_dimm_target,
+ std::vector<uint64_t>& o_ranks);
+
} // rank
} // mss
#endif
OpenPOWER on IntegriCloud