summaryrefslogtreecommitdiffstats
path: root/src/import
diff options
context:
space:
mode:
authorMark Pizzutillo <Mark.Pizzutillo@ibm.com>2019-06-17 14:50:52 -0500
committerChristian R Geddes <crgeddes@us.ibm.com>2019-08-12 08:35:25 -0500
commit00d4530ee3d3cc9dd48b309202212a9215d4d050 (patch)
treea1bf144212b113857a8c172303a8f846b6b63419 /src/import
parentaeaa7244858285b898a3dc71edc50ac1ad1bd45c (diff)
downloadtalos-hostboot-00d4530ee3d3cc9dd48b309202212a9215d4d050.tar.gz
talos-hostboot-00d4530ee3d3cc9dd48b309202212a9215d4d050.zip
Add rank API support in axone_mss_freq
Change-Id: I34c31f9a97f367f1487b8a50d6eddf7622201701 Reviewed-on: http://rchgit01.rchland.ibm.com/gerrit1/79074 Tested-by: Jenkins Server <pfd-jenkins+hostboot@us.ibm.com> Tested-by: FSP CI Jenkins <fsp-CI-jenkins+hostboot@us.ibm.com> Tested-by: Hostboot CI <hostboot-ci+hostboot@us.ibm.com> Reviewed-by: STEPHEN GLANCY <sglancy@us.ibm.com> Reviewed-by: Devon A Baughen <devon.baughen1@ibm.com> Reviewed-by: Jennifer A Stofer <stofer@us.ibm.com> Reviewed-on: http://rchgit01.rchland.ibm.com/gerrit1/79227 Tested-by: Jenkins OP Build CI <op-jenkins+hostboot@us.ibm.com> Tested-by: Jenkins OP HW <op-hw-jenkins+hostboot@us.ibm.com> Reviewed-by: Christian R Geddes <crgeddes@us.ibm.com>
Diffstat (limited to 'src/import')
-rw-r--r--src/import/chips/ocmb/explorer/procedures/hwp/memory/lib/dimm/exp_rank.H5
-rw-r--r--src/import/chips/ocmb/explorer/procedures/hwp/memory/lib/phy/exp_train_display.C34
-rw-r--r--src/import/chips/p9a/procedures/hwp/memory/lib/freq/axone_mss_freq.C85
-rw-r--r--src/import/chips/p9a/procedures/hwp/memory/lib/freq/axone_sync.H12
-rw-r--r--src/import/generic/memory/lib/utils/mss_rank.H51
5 files changed, 109 insertions, 78 deletions
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<mss::mc_type::EXPLORER>
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 <fapi2.H>
#include <lib/shared/exp_consts.H>
+#include <lib/shared/exp_defaults.H>
+#include <lib/dimm/exp_rank.H>
#include <generic/memory/lib/utils/shared/mss_generic_consts.H>
#include <generic/memory/lib/utils/index.H>
#include <generic/memory/lib/utils/c_str.H>
@@ -113,29 +115,25 @@ fapi2::ReturnCode display_mrs_info(const fapi2::Target<fapi2::TARGET_TYPE_OCMB_C
const user_response_msdg_t& i_training_info)
{
// Loop through all DIMM's
- for(const auto& l_dimm : mss::find_targets<fapi2::TARGET_TYPE_DIMM>(i_target))
+ for (const auto& l_dimm : mss::find_targets<fapi2::TARGET_TYPE_DIMM>(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<mss::rank::info<>> 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<fapi2::TARGET_TYPE_OCMB_C
for(uint64_t l_dram = 0; l_dram < l_num_dram; ++l_dram)
{
const auto l_dram_pos = l_correction_factor * l_dram;
- FAPI_DBG("%s rank%u MR6 dram%u 0x%04x", mss::c_str(i_target), l_rank, l_dram,
- i_training_info.mrs_resp.MR6[l_rank][l_dram_pos]);
+ FAPI_DBG("%s rank%u MR6 dram%u 0x%04x", mss::c_str(i_target), l_phy_rank, l_dram,
+ i_training_info.mrs_resp.MR6[l_phy_rank][l_dram_pos]);
}
}
}
diff --git a/src/import/chips/p9a/procedures/hwp/memory/lib/freq/axone_mss_freq.C b/src/import/chips/p9a/procedures/hwp/memory/lib/freq/axone_mss_freq.C
index a75af9024..d4c280c2f 100644
--- a/src/import/chips/p9a/procedures/hwp/memory/lib/freq/axone_mss_freq.C
+++ b/src/import/chips/p9a/procedures/hwp/memory/lib/freq/axone_mss_freq.C
@@ -37,6 +37,10 @@
#include <vpd_access.H>
#include <vector>
+// Explorer rank API
+#include <lib/shared/exp_defaults.H>
+#include <lib/dimm/exp_rank.H>
+
// Memory libraries
#include <lib/freq/axone_freq_traits.H>
#include <lib/shared/axone_consts.H>
@@ -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<fapi2::TARGET_TYPE_MEM_PORT>& i_target,
- std::vector<uint64_t>& 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<mss::proc_type::AXONE>;
-
- 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<mss::proc_type::AXONE>(i_target, &(l_rank_count_dimm[0])) );
- FAPI_TRY( get_dimm_type<mss::proc_type::AXONE>(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<mss::proc_type::AXONE>( const fapi2::Ta
using TT = mss::frequency_traits<mss::proc_type::AXONE>;
o_supported = false;
- std::vector<uint64_t> l_ranks;
+ std::vector<mss::rank::info<>> l_ranks;
fapi2::VPDInfo<TT::VPD_TARGET_TYPE> l_vpd_info(TT::VPD_BLOB);
const auto& l_vpd_target = mss::find_target<TT::VPD_TARGET_TYPE>(i_target);
@@ -304,23 +271,33 @@ fapi2::ReturnCode check_freq_support_vpd<mss::proc_type::AXONE>( 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<mss::proc_type::AXONE>(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
@@ -61,6 +61,18 @@ static const std::vector<uint64_t> AXONE_OMI_FREQS =
};
///
+/// @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
/// @return the corresponding OMI frequency
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 <fapi2.H>
-#include <generic/memory/lib/utils/pos.H>
+#include <generic/memory/lib/utils/index.H>
#include <generic/memory/lib/utils/find.H>
#include <generic/memory/lib/mss_generic_attribute_getters.H>
#include <generic/memory/lib/utils/shared/mss_generic_consts.H>
@@ -89,7 +89,8 @@ class info
// Ranks
iv_dimm_rank = i_index;
- iv_port_rank = iv_dimm_rank + ((mss::relative_pos<DEFAULT_MEM_PORT_TARGET>(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<DEFAULT_MEM_PORT_TARGET>(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
@@ -180,6 +183,16 @@ class info
}
///
+ /// @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<fapi2::TARGET_TYPE_DIMM> iv_dimm_target;
fapi2::Target<DEFAULT_MEM_PORT_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<DEFAULT_MEM_PORT_TARGET>& i_
for (const auto& l_dimm : mss::find_targets<fapi2::TARGET_TYPE_DIMM>(i_port_target))
{
- const uint8_t l_dimm_pos = mss::relative_pos<DEFAULT_MEM_PORT_TARGET>(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));
OpenPOWER on IntegriCloud