From 00d4530ee3d3cc9dd48b309202212a9215d4d050 Mon Sep 17 00:00:00 2001 From: Mark Pizzutillo Date: Mon, 17 Jun 2019 14:50:52 -0500 Subject: Add rank API support in axone_mss_freq Change-Id: I34c31f9a97f367f1487b8a50d6eddf7622201701 Reviewed-on: http://rchgit01.rchland.ibm.com/gerrit1/79074 Tested-by: Jenkins Server Tested-by: FSP CI Jenkins Tested-by: Hostboot CI Reviewed-by: STEPHEN GLANCY Reviewed-by: Devon A Baughen Reviewed-by: Jennifer A Stofer Reviewed-on: http://rchgit01.rchland.ibm.com/gerrit1/79227 Tested-by: Jenkins OP Build CI Tested-by: Jenkins OP HW Reviewed-by: Christian R Geddes --- .../procedures/hwp/memory/lib/dimm/exp_rank.H | 5 ++ .../hwp/memory/lib/phy/exp_train_display.C | 34 ++++----- .../hwp/memory/lib/freq/axone_mss_freq.C | 85 ++++++++-------------- .../procedures/hwp/memory/lib/freq/axone_sync.H | 12 +++ src/import/generic/memory/lib/utils/mss_rank.H | 51 +++++++++++-- 5 files changed, 109 insertions(+), 78 deletions(-) (limited to 'src/import') 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 8ffe98097..f61dc0db0 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 @@ -44,6 +44,11 @@ class rankTraits static constexpr uint8_t MAX_DIMMS_PER_PORT = 2; static constexpr uint8_t MAX_RANKS_PER_DIMM = 4; static constexpr uint8_t RANK_INDEX_STEP = 4; + + // Note! a configuration of 2 4-rank dimms is not possible. + // In this hypothetical scenario, the value for phy-rank would not + // be valid / does not apply, as there will be some rollover. + static constexpr uint8_t PHY_RANK_INDEX_STEP = 2; }; /// diff --git a/src/import/chips/ocmb/explorer/procedures/hwp/memory/lib/phy/exp_train_display.C b/src/import/chips/ocmb/explorer/procedures/hwp/memory/lib/phy/exp_train_display.C index 477335d6f..fa39f9e5c 100644 --- a/src/import/chips/ocmb/explorer/procedures/hwp/memory/lib/phy/exp_train_display.C +++ b/src/import/chips/ocmb/explorer/procedures/hwp/memory/lib/phy/exp_train_display.C @@ -35,6 +35,8 @@ #include #include +#include +#include #include #include #include @@ -113,29 +115,25 @@ fapi2::ReturnCode display_mrs_info(const fapi2::Target(i_target)) + for (const auto& l_dimm : mss::find_targets(i_target)) { - // Gets the number of DIMM's and x4 vs x8 DRAM - // TK update ranks to use rank API - uint8_t l_num_master_ranks = 0; + // Rank info object for + std::vector> l_rank_info_vect; uint8_t l_dram_width = 0; - FAPI_TRY(mss::attr::get_num_master_ranks_per_dimm(l_dimm, l_num_master_ranks)); + FAPI_TRY(mss::rank::ranks_on_dimm<>(l_dimm, l_rank_info_vect)); FAPI_TRY(mss::attr::get_dram_width(l_dimm, l_dram_width)); // Loops through all of the ranks - for(uint8_t l_dimm_rank = 0; l_dimm_rank < l_num_master_ranks; ++l_dimm_rank) + for (const auto& l_rank_info : l_rank_info_vect) { - // TK update to rank API - constexpr uint8_t DIMM_OFFSET = 2; - const auto l_rank = l_dimm_rank + mss::index(l_dimm) * DIMM_OFFSET; - + const uint8_t l_phy_rank = l_rank_info.get_phy_rank(); // MR0->5 are easy, just display the value - FAPI_DBG("%s rank%u MR%u 0x%04x", mss::c_str(i_target), l_rank, 0, i_training_info.mrs_resp.MR0); - FAPI_DBG("%s rank%u MR%u 0x%04x", mss::c_str(i_target), l_rank, 1, i_training_info.mrs_resp.MR1[l_rank]); - FAPI_DBG("%s rank%u MR%u 0x%04x", mss::c_str(i_target), l_rank, 2, i_training_info.mrs_resp.MR2[l_rank]); - FAPI_DBG("%s rank%u MR%u 0x%04x", mss::c_str(i_target), l_rank, 3, i_training_info.mrs_resp.MR3); - FAPI_DBG("%s rank%u MR%u 0x%04x", mss::c_str(i_target), l_rank, 4, i_training_info.mrs_resp.MR4); - FAPI_DBG("%s rank%u MR%u 0x%04x", mss::c_str(i_target), l_rank, 5, i_training_info.mrs_resp.MR5[l_rank]); + FAPI_DBG("%s rank%u MR%u 0x%04x", mss::c_str(i_target), l_phy_rank, 0, i_training_info.mrs_resp.MR0); + FAPI_DBG("%s rank%u MR%u 0x%04x", mss::c_str(i_target), l_phy_rank, 1, i_training_info.mrs_resp.MR1[l_phy_rank]); + FAPI_DBG("%s rank%u MR%u 0x%04x", mss::c_str(i_target), l_phy_rank, 2, i_training_info.mrs_resp.MR2[l_phy_rank]); + FAPI_DBG("%s rank%u MR%u 0x%04x", mss::c_str(i_target), l_phy_rank, 3, i_training_info.mrs_resp.MR3); + FAPI_DBG("%s rank%u MR%u 0x%04x", mss::c_str(i_target), l_phy_rank, 4, i_training_info.mrs_resp.MR4); + FAPI_DBG("%s rank%u MR%u 0x%04x", mss::c_str(i_target), l_phy_rank, 5, i_training_info.mrs_resp.MR5[l_phy_rank]); // The number of the DRAM's and the position to access each DRAM changes based upon x4 vs x8 const auto l_num_dram = l_dram_width == fapi2::ENUM_ATTR_MEM_EFF_DRAM_WIDTH_X4 ? @@ -148,8 +146,8 @@ fapi2::ReturnCode display_mrs_info(const fapi2::Target #include +// Explorer rank API +#include +#include + // Memory libraries #include #include @@ -130,7 +134,7 @@ fapi_try_exit: return fapi2::current_err; } /// -/// @brief Gets the DIMM type for a specific DIMM - specialization for the NIMBUS processor type +/// @brief Gets the DIMM type for a specific DIMM - specialization for the AXONE processor type /// @param[in] i_target DIMM target /// @param[out] o_dimm_type DIMM type on the DIMM target /// @return FAPI2_RC_SUCCESS iff ok @@ -218,55 +222,18 @@ fapi_try_exit: } /// -/// @brief Return a list of configured ranks on a MEM_PORT -/// @param[in] i_target the port target -/// @param[out] o_ranks list of valid ranks on the port -/// @return FAPI2_RC_SUCCESS iff ok +/// @brief Determines if rank info object is that of an LR dimm /// -// TK this function should get replaced by our rank API when available -fapi2::ReturnCode get_ranks_for_vpd( - const fapi2::Target& i_target, - std::vector& o_ranks) +/// @param[in] i_rank_info rank info object +/// @param[out] l_lr_dimm true if LRDIMM, else false +/// @return fapi2::ReturnCode FAPI2_RC_SUCCESS if success +/// +inline fapi2::ReturnCode rank_is_lr_dimm(const mss::rank::info<> i_rank_info, bool& o_lr_dimm) { - using TT = mss::frequency_traits; - - uint8_t l_rank_count_dimm[TT::MAX_DIMM_PER_PORT] = {}; - uint8_t l_dimm_type[TT::MAX_DIMM_PER_PORT] = {}; + uint8_t l_dimm_type = 0; + FAPI_TRY(mss::attr::get_dimm_type(i_rank_info.get_dimm_target(), l_dimm_type)); - o_ranks.clear(); - - FAPI_TRY( get_master_rank_per_dimm(i_target, &(l_rank_count_dimm[0])) ); - FAPI_TRY( get_dimm_type(i_target, &(l_dimm_type[0])) ); - - // So for LRDIMM, our SI works a bit differently than for non-LRDIMM - // LRDIMM's have buffers that operate on a per-DIMM basis across multiple ranks - // As such, they act as a single load, similar to a 1R DIMM would - // per the IBM signal integrity team, the 1R DIMM settings should be used for LRDIMM's - // So, if we are LRDIMM's and have ranks, we want to only note it as a 1R DIMM for purposes of querying the VPD - FAPI_DBG("%s for DIMM 0 rank count %u dimm type %u %s", - mss::c_str(i_target), l_rank_count_dimm[0], l_dimm_type[0], l_dimm_type[0] == TT::LRDIMM_TYPE ? "LRDIMM" : "RDIMM"); - FAPI_DBG("%s for DIMM 1 rank count %u dimm type %u %s", - mss::c_str(i_target), l_rank_count_dimm[1], l_dimm_type[1], l_dimm_type[1] == TT::LRDIMM_TYPE ? "LRDIMM" : "RDIMM"); - - l_rank_count_dimm[0] = ((l_dimm_type[0] == TT::LRDIMM_TYPE) && (l_rank_count_dimm[0] > 0)) ? 1 : l_rank_count_dimm[0]; - l_rank_count_dimm[1] = ((l_dimm_type[1] == TT::LRDIMM_TYPE) && (l_rank_count_dimm[1] > 0)) ? 1 : l_rank_count_dimm[1]; - - FAPI_DBG("after LR modification %s for DIMM 0 rank count %u dimm type %u %s", - mss::c_str(i_target), l_rank_count_dimm[0], l_dimm_type[0], l_dimm_type[0] == TT::LRDIMM_TYPE ? "LRDIMM" : "RDIMM"); - FAPI_DBG("after LR modification %s for DIMM 1 rank count %u dimm type %u %s", - mss::c_str(i_target), l_rank_count_dimm[1], l_dimm_type[1], l_dimm_type[1] == TT::LRDIMM_TYPE ? "LRDIMM" : "RDIMM"); - - // Add DIMM0's ranks - for (uint64_t l_rank = 0; l_rank < l_rank_count_dimm[0]; ++l_rank) - { - o_ranks.push_back(l_rank); - } - - // Add DIMM1's ranks - for (uint64_t l_rank = 0; l_rank < l_rank_count_dimm[1]; ++l_rank) - { - o_ranks.push_back(l_rank + TT::MAX_PRIMARY_RANK_PER_DIMM); - } + o_lr_dimm = (l_dimm_type == fapi2::ENUM_ATTR_MEM_EFF_DIMM_TYPE_LRDIMM); fapi_try_exit: return fapi2::current_err; @@ -288,7 +255,7 @@ fapi2::ReturnCode check_freq_support_vpd( const fapi2::Ta using TT = mss::frequency_traits; o_supported = false; - std::vector l_ranks; + std::vector> l_ranks; fapi2::VPDInfo l_vpd_info(TT::VPD_BLOB); const auto& l_vpd_target = mss::find_target(i_target); @@ -304,23 +271,33 @@ fapi2::ReturnCode check_freq_support_vpd( const fapi2::Ta // DDIMM SPD can contain different SI settings for each master rank. // To determine which frequencies are supported, we have to check for each valid // master rank on the port's DIMMs - FAPI_TRY(get_ranks_for_vpd(i_target, l_ranks)); + FAPI_TRY(mss::rank::ranks_on_port(i_target, l_ranks)); - for (const auto l_rank : l_ranks) + for (const auto& l_rank : l_ranks) { - l_vpd_info.iv_rank = l_rank; + // We will skip LRDIMMs with ranks > 0 + bool l_is_lr_dimm = false; + FAPI_TRY(rank_is_lr_dimm(l_rank, l_is_lr_dimm)); + + if (rank_not_supported_in_vpd_config(l_is_lr_dimm, l_rank.get_dimm_rank())) + { + FAPI_DBG("LRDIMM ranks > 0 are not supported for check_freq_support_vpd. Skipping this rank. Target: %s", + mss::c_str(i_target)); + continue; + } + + l_vpd_info.iv_rank = l_rank.get_port_rank(); FAPI_INF("%s. VPD info - checking rank: %d", - mss::c_str(i_target), l_rank); + mss::c_str(i_target), l_rank.get_port_rank()); // Check if this VPD configuration is supported FAPI_TRY(is_vpd_config_supported(l_vpd_target, i_proposed_freq, l_vpd_info, o_supported), "%s failed to determine if %u freq is supported", mss::c_str(i_target), i_proposed_freq); - // If we fail any of the ranks, then this VPD configuration is not supported if(o_supported == false) { - FAPI_INF("%s is not supported on rank%u exiting...", mss::c_str(i_target), l_rank); + FAPI_INF("%s is not supported on rank %u exiting...", mss::c_str(i_target), l_rank.get_port_rank()); break; } } diff --git a/src/import/chips/p9a/procedures/hwp/memory/lib/freq/axone_sync.H b/src/import/chips/p9a/procedures/hwp/memory/lib/freq/axone_sync.H index e05415523..29436db00 100644 --- a/src/import/chips/p9a/procedures/hwp/memory/lib/freq/axone_sync.H +++ b/src/import/chips/p9a/procedures/hwp/memory/lib/freq/axone_sync.H @@ -60,6 +60,18 @@ static const std::vector AXONE_OMI_FREQS = 25600, // fapi2::ENUM_ATTR_MSS_OCMB_EXP_BOOT_CONFIG_SERDES_FREQUENCY_SERDES_25_60GBPS, }; +/// +/// @brief determines if rank is not supported in VPD config, will be skipped in check_freq_support_vpd() +/// +/// @param[in] i_is_lr_dimm is LR +/// @param[in] i_dimm_rank DIMM rank +/// @return true if LR & rank > 0, else false +/// +inline bool rank_not_supported_in_vpd_config(const bool i_is_lr_dimm, const uint8_t i_dimm_rank) +{ + return (i_is_lr_dimm && i_dimm_rank > 0); +} + /// /// @brief Converts an OMI frequency attribute enum to the corresponding OMI frequency /// @param[in] i_omi_enum a frequency enum value that is to be converted diff --git a/src/import/generic/memory/lib/utils/mss_rank.H b/src/import/generic/memory/lib/utils/mss_rank.H index caf514a2b..4525765c2 100644 --- a/src/import/generic/memory/lib/utils/mss_rank.H +++ b/src/import/generic/memory/lib/utils/mss_rank.H @@ -37,7 +37,7 @@ #define _MSS_GENERIC_RANK_H_ #include -#include +#include #include #include #include @@ -89,7 +89,8 @@ class info // Ranks iv_dimm_rank = i_index; - iv_port_rank = iv_dimm_rank + ((mss::relative_pos(i_dimm_target) * TT::RANK_INDEX_STEP)); + iv_port_rank = iv_dimm_rank + ((mss::index(i_dimm_target) * TT::RANK_INDEX_STEP)); + iv_phy_rank = iv_dimm_rank + ((mss::index(i_dimm_target) * TT::PHY_RANK_INDEX_STEP)); fapi_try_exit: o_rc = fapi2::current_err; } @@ -131,7 +132,7 @@ class info // throw that error. // If we do find the right dimm, we need to then make sure that the master_ranks_per_dimm attribute // is greater than the expected dimm rank. - if (mss::relative_pos(l_dimm) == l_target_index) + if (mss::index(l_dimm) == l_target_index) { uint8_t l_master_ranks_per_dimm = 0; FAPI_TRY(mss::attr::get_num_master_ranks_per_dimm(l_dimm, l_master_ranks_per_dimm)); @@ -155,6 +156,7 @@ class info // Ranks iv_dimm_rank = i_index % TT::RANK_INDEX_STEP; + iv_phy_rank = get_phy_rank_from_port_rank(i_index); iv_port_rank = i_index; } @@ -170,6 +172,7 @@ class info { return iv_port_rank; } + /// /// @brief Accessor for rank number of DIMM /// @return the number (0-3) of the DIMM @@ -179,6 +182,16 @@ class info return iv_dimm_rank; } + /// + /// @brief Accessor for phy rank + /// @return the phy rank value + /// @note in a hypothetical 2 4-rank dimm configuration (not possible), this value is not valid + /// + inline const uint8_t get_phy_rank() const + { + return iv_phy_rank; + } + /// /// @brief Accessor for DIMM target /// @return the dimm target associated with the rank @@ -197,11 +210,37 @@ class info return iv_port_target; } + /// + /// @brief Calculate phy rank given port rank (unit testable) + /// + /// @param[in] l_port_rank port rank + /// @return phy rank + /// + inline static uint8_t get_phy_rank_from_port_rank(const uint8_t i_port_rank) + { + const uint8_t l_dimm_rank = i_port_rank % TT::RANK_INDEX_STEP; + const uint8_t l_dimm_index = i_port_rank / TT::RANK_INDEX_STEP; + + // Dimm index * 2 sets the center point at 2 + // Add on the dimm rank + // Note that this logic does NOT apply in a hypothetical/impossible 2 4-rank dimm configuration + return ((l_dimm_index * TT::PHY_RANK_INDEX_STEP) + (l_dimm_rank)); + } + private: fapi2::Target iv_dimm_target; fapi2::Target iv_port_target; uint8_t iv_dimm_rank; uint8_t iv_port_rank; + + // Note! a configuration of 2 4-rank dimms is not possible. + // In this hypothetical scenario, the value for phy-rank would not + // be valid / does not apply, as there will be some rollover. + // 1 rank-per-dimm: 0 dimm0 2 dimm1 + // 2 rank-per-dimm: 0/1 dimm0 2/3 dimm1. + // 2 rank single dimm 0/1 + // 4 rank (quad encoded) 0-3. + uint8_t iv_phy_rank; }; /// @@ -229,13 +268,13 @@ fapi2::ReturnCode ranks_on_port(const fapi2::Target& i_ for (const auto& l_dimm : mss::find_targets(i_port_target)) { - const uint8_t l_dimm_pos = mss::relative_pos(l_dimm); - const uint8_t l_port_index_start = l_dimm_pos * TT::RANK_INDEX_STEP; + const uint8_t l_dimm_index = mss::index(l_dimm); + const uint8_t l_port_index_start = l_dimm_index * TT::RANK_INDEX_STEP; fapi2::ReturnCode l_rc = fapi2::FAPI2_RC_SUCCESS; // For each rank index of the dimm from the port's perspective - for (uint8_t l_index = l_port_index_start; l_index < (l_port_index_start + l_master_ranks_per_dimm[l_dimm_pos]); + for (uint8_t l_index = l_port_index_start; l_index < (l_port_index_start + l_master_ranks_per_dimm[l_dimm_index]); ++l_index) { o_vect.push_back(mss::rank::info<>(i_port_target, l_index, l_rc)); -- cgit v1.2.1