diff options
author | Mark Pizzutillo <Mark.Pizzutillo@ibm.com> | 2019-04-05 17:29:38 -0400 |
---|---|---|
committer | Daniel M. Crowell <dcrowell@us.ibm.com> | 2019-05-07 15:49:43 -0500 |
commit | 32bc3c06a9ba4b9b5037f09febff20b67ada278a (patch) | |
tree | dfbba2a8de9fdf58bd12a0c98d6bff2081f0e454 /src/import/generic | |
parent | 3498e76492e9b23271ed0a446d8ddedd32e70d0a (diff) | |
download | talos-hostboot-32bc3c06a9ba4b9b5037f09febff20b67ada278a.tar.gz talos-hostboot-32bc3c06a9ba4b9b5037f09febff20b67ada278a.zip |
Add API for axone p10 dimm rank
Change-Id: I92ceb8303371368064e0a958fa09846a689c7bd1
Reviewed-on: http://rchgit01.rchland.ibm.com/gerrit1/72725
Tested-by: FSP CI Jenkins <fsp-CI-jenkins+hostboot@us.ibm.com>
Tested-by: Jenkins Server <pfd-jenkins+hostboot@us.ibm.com>
Reviewed-by: STEPHEN GLANCY <sglancy@us.ibm.com>
Reviewed-by: Louis Stermole <stermole@us.ibm.com>
Tested-by: Hostboot CI <hostboot-ci+hostboot@us.ibm.com>
Tested-by: HWSV CI <hwsv-ci+hostboot@us.ibm.com>
Reviewed-by: Jennifer A. Stofer <stofer@us.ibm.com>
Reviewed-on: http://rchgit01.rchland.ibm.com/gerrit1/75501
Reviewed-by: Daniel M. Crowell <dcrowell@us.ibm.com>
Diffstat (limited to 'src/import/generic')
3 files changed, 321 insertions, 2 deletions
diff --git a/src/import/generic/memory/lib/utils/mss_rank.H b/src/import/generic/memory/lib/utils/mss_rank.H index b43e7e6ff..42cd7a25e 100644 --- a/src/import/generic/memory/lib/utils/mss_rank.H +++ b/src/import/generic/memory/lib/utils/mss_rank.H @@ -22,3 +22,270 @@ /* permissions and limitations under the License. */ /* */ /* IBM_PROLOG_END_TAG */ + +/// +/// @file mss_rank.H +/// @brief Tools to obtain rank info from DIMM or PORT target +/// +// *HWP HWP Owner: Mark Pizzutillo <Mark.Pizzutillo@ibm.com> +// *HWP HWP Backup: Stephen Glancy <sglancy@us.ibm.com> +// *HWP Team: Memory +// *HWP Level: 2 +// *HWP Consumed by: HB:FSP + +#ifndef _MSS_RANK_H_ +#define _MSS_RANK_H_ + +#include <fapi2.H> +#include <generic/memory/lib/utils/pos.H> +#include <generic/memory/lib/utils/find.H> +#include <mss_generic_attribute_getters.H> +#include <generic/memory/lib/utils/shared/mss_generic_consts.H> + +namespace mss +{ +namespace rank +{ + +/// +/// @brief Rank traits class for variations depending on MC +/// +template <mss::mc_type MC = DEFAULT_MC_TYPE> +class rankTraits; + +/// +/// @brief Rank info class +/// +template <mss::mc_type MC = DEFAULT_MC_TYPE, typename TT = rankTraits<MC>> +class info +{ + + public: + // Delete default constructor + info() = delete; + + /// + /// @brief Constructor for info object + /// @param[in] i_target DIMM target + /// @param[in] i_index dimm rank index 0-3 + /// @param[out] o_rc return code, FAPI2_RC_SUCCESS if no error + /// + info(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_dimm_target, const uint8_t i_index, fapi2::ReturnCode& o_rc) + { + o_rc = fapi2::FAPI2_RC_SUCCESS; + + uint8_t l_master_ranks_per_dimm = 0; + FAPI_TRY(mss::attr::get_num_master_ranks_per_dimm(i_dimm_target, l_master_ranks_per_dimm)); + + FAPI_ASSERT((i_index < l_master_ranks_per_dimm), + fapi2::MSS_RANK_OUT_OF_RANGE() + .set_TARGET(i_dimm_target) + .set_RANK(i_index), + "Rank %u provided to info constructor for DIMM %s exceeded the number of master ranks per DIMM", + i_index, mss::c_str(i_dimm_target)); + // Targets + iv_dimm_target = i_dimm_target; + iv_port_target = mss::find_target<DEFAULT_MEM_PORT_TARGET>(i_dimm_target); + + // 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)); + fapi_try_exit: + o_rc = fapi2::current_err; + } + + /// + /// @brief Constructor for info object + /// @param[in] i_target PORT target + /// @param[in] i_index port rank index 0-7 + /// @param[out] o_rc return code, FAPI2_RC_SUCCESS if no error + /// + info(const fapi2::Target<DEFAULT_MEM_PORT_TARGET>& i_port_target, const uint8_t i_index, fapi2::ReturnCode& o_rc) + { + o_rc = fapi2::FAPI2_RC_SUCCESS; + + // Dimm Target + const uint8_t l_target_index = i_index / TT::RANK_INDEX_STEP; + const auto l_dimms = mss::find_targets<fapi2::TARGET_TYPE_DIMM>(i_port_target); + + // This assumes that the mc_type max # of dimms per port is correct + FAPI_ASSERT( !l_dimms.empty(), + fapi2::MSS_EMPTY_VECTOR(). + set_FUNCTION(INIT_RANK_INFO). + set_TARGET(i_port_target), + "Empty dimm vector received on port %s", + mss::spd::c_str(i_port_target)); + + { + // This will remain false in two cases: + // Either: + // 1. The corresponding DIMM index is out of range (caused by port index out of range) + // 2. The corresponding DIMMs master_ranks_per_dimm is less than the desired rank + bool l_valid_rank = false; + + for (const auto& l_dimm : l_dimms) + { + // Since we can't guarantee the order of the returned dimms, we iterate through until we (might) find + // the right one. There's a chance it may not exist for example given info(port, rank13) would give us + // a dimm index above 2, which may be out of range, so we could never find a matching dimm, so we will + // 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) + { + 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)); + + // The rank passed in matches one of a valid DIMM + l_valid_rank = (i_index % TT::RANK_INDEX_STEP) < l_master_ranks_per_dimm; + + iv_dimm_target = l_dimm; + } + } + + FAPI_ASSERT(l_valid_rank, + fapi2::MSS_RANK_OUT_OF_RANGE() + .set_TARGET(i_port_target) + .set_RANK(i_index), + "Rank %u provided to rank_info constructor for PORT %s was out of range", + i_index, mss::c_str(i_port_target)); + + // Port Target + iv_port_target = i_port_target; + + // Ranks + iv_dimm_rank = i_index % TT::RANK_INDEX_STEP; + iv_port_rank = i_index; + } + + fapi_try_exit: + o_rc = fapi2::current_err; + } + + /// + /// @brief Accessor for port rank + /// @return the number (0-7) of the rank within its port + /// + inline const uint8_t get_port_rank() const + { + return iv_port_rank; + } + /// + /// @brief Accessor for rank number of DIMM + /// @return the number (0-3) of the DIMM + /// + inline const uint8_t get_dimm_rank() const + { + return iv_dimm_rank; + } + + /// + /// @brief Accessor for DIMM target + /// @return the dimm target associated with the rank + /// + inline const fapi2::Target<fapi2::TARGET_TYPE_DIMM> get_dimm_target() const + { + return iv_dimm_target; + } + + /// + /// @brief Accessor for PORT target + /// @return the port target associated with the rank + /// + inline const fapi2::Target<DEFAULT_MEM_PORT_TARGET> get_port_target() const + { + return iv_port_target; + } + + 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; +}; + +/// +/// @brief Obtains all DIMM ranks on a given port target +/// @param[in] i_port_target port target +/// @param[out] o_vect vector of ranks +/// @return FAPI2_RC_SUCCESS iff success +/// +template <mss::mc_type MC = DEFAULT_MC_TYPE, typename TT = rankTraits<MC>> +fapi2::ReturnCode ranks_on_port(const fapi2::Target<DEFAULT_MEM_PORT_TARGET>& i_port_target, + std::vector<info<MC>>& o_vect) +{ + o_vect.clear(); + + uint8_t l_master_ranks_per_dimm[TT::MAX_DIMMS_PER_PORT] = {0}; + FAPI_TRY(mss::attr::get_num_master_ranks_per_dimm(i_port_target, l_master_ranks_per_dimm)); + + FAPI_ASSERT(((l_master_ranks_per_dimm[0] <= TT::MAX_RANKS_PER_DIMM) && + (l_master_ranks_per_dimm[1] <= TT::MAX_RANKS_PER_DIMM)), + fapi2::MSS_TOO_MANY_PRIMARY_RANKS_ON_PORT() + .set_PORT_TARGET(i_port_target), + "Primary ranks on PORT %s exceeded %u", + mss::c_str(i_port_target), + TT::MAX_RANKS_PER_DIMM); + + 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; + + 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]); + ++l_index) + { + o_vect.push_back(mss::rank::info<>(i_port_target, l_index, l_rc)); + FAPI_TRY(l_rc); + } + } + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Obtains all ranks on a given DIMM target +/// @param[in] i_target DIMM target +/// @param[out] o_vect vector of ranks +/// @return FAPI2_RC_SUCCESS iff success +/// +template <mss::mc_type MC = DEFAULT_MC_TYPE, typename TT = rankTraits<MC>> +fapi2::ReturnCode ranks_on_dimm(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_dimm_target, + std::vector<info<MC>>& o_vect) +{ + o_vect.clear(); + uint8_t l_master_ranks_per_dimm = 0; + FAPI_TRY(mss::attr::get_num_master_ranks_per_dimm(i_dimm_target, l_master_ranks_per_dimm)); + + FAPI_ASSERT(l_master_ranks_per_dimm <= TT::MAX_RANKS_PER_DIMM, + fapi2::MSS_TOO_MANY_PRIMARY_RANKS_ON_DIMM() + .set_RANK_COUNT(l_master_ranks_per_dimm) + .set_DIMM_TARGET(i_dimm_target), + "Seeing %d primary ranks on DIMM %s", + l_master_ranks_per_dimm, + mss::c_str(i_dimm_target)); + { + // Return code for constructor call + fapi2::ReturnCode l_rc = fapi2::FAPI2_RC_SUCCESS; + + // For each rank index from the dimm's perspective + for (uint8_t l_index = 0; l_index < l_master_ranks_per_dimm; l_index++) + { + o_vect.push_back(mss::rank::info<>(i_dimm_target, l_index, l_rc)); + FAPI_TRY(l_rc, "ranks_on_dimm(): Error in rank::info constructor call for DIMM %s and rank %u", + mss::c_str(i_dimm_target), l_index); + } + } + return fapi2::FAPI2_RC_SUCCESS; + +fapi_try_exit: + return fapi2::current_err; +} + +} // rank +} // mss +#endif diff --git a/src/import/generic/memory/lib/utils/shared/mss_generic_consts.H b/src/import/generic/memory/lib/utils/shared/mss_generic_consts.H index 275cb9e82..6fcd73070 100644 --- a/src/import/generic/memory/lib/utils/shared/mss_generic_consts.H +++ b/src/import/generic/memory/lib/utils/shared/mss_generic_consts.H @@ -170,6 +170,7 @@ enum generic_ffdc_codes SET_ATTR_HOST_TO_DDR_SPEED_RATIO = 0x102C, SET_DIMM_RANKS_CNFG = 0x1039, DDIMM_RAWCARD_DECODE = 0x103a, + INIT_RANK_INFO = 0x103B, SET_DRAM_WIDTH = 0x1040, SET_SI_VREF_DRAM_WR = 0x1041, diff --git a/src/import/generic/procedures/xml/error_info/generic_error.xml b/src/import/generic/procedures/xml/error_info/generic_error.xml index 78d852568..f09e3de8f 100644 --- a/src/import/generic/procedures/xml/error_info/generic_error.xml +++ b/src/import/generic/procedures/xml/error_info/generic_error.xml @@ -656,7 +656,7 @@ </callout> </hwpError> - <hwpError> + <hwpError> <rc>RC_MSS_POWER_THERMAL_DIMM_INDEX_OUT_OF_BOUND</rc> <description> The dimm index is out of bound for the port @@ -668,5 +668,56 @@ <priority>HIGH</priority> </callout> </hwpError> - + + <hwpError> + <rc>RC_MSS_TOO_MANY_PRIMARY_RANKS_ON_DIMM</rc> + <description> + Too many primary ranks were seen on the dimm according + to the call to master_ranks_per_dimm</description> + <ffdc>RANK_COUNT</ffdc> + <callout> + <target>DIMM_TARGET</target> + <priority>HIGH</priority> + </callout> + <callout> + <procedure>CODE</procedure> + <priority>MEDIUM</priority> + </callout> + <deconfigure> + <target>DIMM_TARGET</target> + </deconfigure> + </hwpError> + + <hwpError> + <rc>RC_MSS_TOO_MANY_PRIMARY_RANKS_ON_PORT</rc> + <description> + Too many primary ranks were seen on the port according + to the call to master_ranks_per_dimm</description> + <callout> + <target>PORT_TARGET</target> + <priority>HIGH</priority> + </callout> + <callout> + <procedure>CODE</procedure> + <priority>MEDIUM</priority> + </callout> + <deconfigure> + <target>PORT_TARGET</target> + </deconfigure> + </hwpError> + + <hwpError> + <rc>RC_MSS_RANK_OUT_OF_RANGE</rc> + <description> + The rank provided to the rank::info constructor exceeded + the maximum rank for the MC + </description> + <callout> + <procedure>CODE</procedure> + <priority>MEDIUM</priority> + </callout> + <ffdc>TARGET</ffdc> + <ffdc>RANK</ffdc> + </hwpError> + </hwpErrors> |