diff options
Diffstat (limited to 'src/import/chips/p9/procedures/hwp')
9 files changed, 647 insertions, 1258 deletions
diff --git a/src/import/chips/p9/procedures/hwp/memory/lib/eff_config/attr_setters.C b/src/import/chips/p9/procedures/hwp/memory/lib/eff_config/attr_setters.C index aeb61f126..ce42c0b28 100644 --- a/src/import/chips/p9/procedures/hwp/memory/lib/eff_config/attr_setters.C +++ b/src/import/chips/p9/procedures/hwp/memory/lib/eff_config/attr_setters.C @@ -61,35 +61,5 @@ fapi_try_exit: return fapi2::current_err; } -/// -/// @brief Sets pre_eff_config attributes -/// @param[in] i_target the DIMM target -/// @param[in] i_spd_decoder SPD decoder -/// @return FAPI2_RC_SUCCESS iff ok -/// -fapi2::ReturnCode set_pre_init_attrs( const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target, - const spd::facade& i_spd_decoder ) -{ - fapi2::ReturnCode l_rc(fapi2::FAPI2_RC_SUCCESS); - mss::pre_data_engine<mss::NIMBUS> l_data_engine(i_target, i_spd_decoder, l_rc); - FAPI_TRY(l_rc, "Failed to instantiate pre_data_engine object for %s", spd::c_str(i_target)); - - // Set attributes needed before eff_config - // DIMM type and DRAM gen are needed for c_str to aid debugging - FAPI_TRY(l_data_engine.set_dimm_type(), "Failed to set DIMM type %s", spd::c_str(i_target) ); - FAPI_TRY(l_data_engine.set_dram_gen(), "Failed to set DRAM gen %s", spd::c_str(i_target) ); - - // Hybrid and hybrid media help detect hybrid modules, specifically NVDIMMs for Nimbus - FAPI_TRY(l_data_engine.set_hybrid(), "Failed to set Hybrid %s", spd::c_str(i_target) ); - FAPI_TRY(l_data_engine.set_hybrid_media(), "Failed to set Hybrid Media %s", spd::c_str(i_target) ); - - // Number of master ranks needed for VPD decoding - // and dimm_ranks_configured is a PRD attr... - FAPI_TRY(l_data_engine.set_master_ranks(), "Failed to set Master ranks %s", spd::c_str(i_target) ); - FAPI_TRY(l_data_engine.set_dimm_ranks_configured(), "Failed to set DIMM ranks configured %s", spd::c_str(i_target) ); - -fapi_try_exit: - return fapi2::current_err; -} } // mss diff --git a/src/import/chips/p9/procedures/hwp/memory/lib/eff_config/attr_setters.H b/src/import/chips/p9/procedures/hwp/memory/lib/eff_config/attr_setters.H index 976c1077d..8b703f72e 100644 --- a/src/import/chips/p9/procedures/hwp/memory/lib/eff_config/attr_setters.H +++ b/src/import/chips/p9/procedures/hwp/memory/lib/eff_config/attr_setters.H @@ -37,7 +37,6 @@ #define _MSS_ATTR_SETTERS_H_ #include <fapi2.H> -#include <generic/memory/lib/spd/spd_facade.H> namespace mss { @@ -53,15 +52,6 @@ namespace mss fapi2::ReturnCode set_voltage_attributes(const fapi2::Target<fapi2::TARGET_TYPE_MCS>& i_target_mcs, uint32_t i_selected_dram_voltage, uint32_t i_selected_dram_voltage_vpp); - -/// -/// @brief Sets pre_eff_config attributes -/// @param[in] i_target the DIMM target -/// @param[in] i_spd_decoder SPD decoder -/// @return FAPI2_RC_SUCCESS iff ok -/// -fapi2::ReturnCode set_pre_init_attrs( const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target, - const spd::facade& i_spd_decoder ); } // mss #endif diff --git a/src/import/chips/p9/procedures/hwp/memory/lib/eff_config/nimbus_pre_data_engine.C b/src/import/chips/p9/procedures/hwp/memory/lib/eff_config/nimbus_pre_data_engine.C index eba1fcac0..c93559ed5 100644 --- a/src/import/chips/p9/procedures/hwp/memory/lib/eff_config/nimbus_pre_data_engine.C +++ b/src/import/chips/p9/procedures/hwp/memory/lib/eff_config/nimbus_pre_data_engine.C @@ -25,7 +25,7 @@ /// /// @file nimbus_pre_data_engine.C -/// @brief pre_data_engine implimentation for Nimbus +/// @brief pre_data_engine implimentation for mss::proc_type::NIMBUS /// // *HWP HWP Owner: Andre Marin <aamarin@us.ibm.com> // *HWP FW Owner: Stephen Glancy <sglancy@us.ibm.com> @@ -42,11 +42,287 @@ namespace mss { +/// +/// @brief Traits for pre_data_engine +/// @class preDataInitTraits +/// @note NIMBUS, DIMM_TYPE specialization +/// +template<> +class preDataInitTraits<mss::proc_type::NIMBUS, DIMM_TYPE> +{ + public: + using attr_type = fapi2::ATTR_EFF_DIMM_TYPE_Type; + static const fapi2::TargetType TARGET_TYPE = fapi2::ATTR_EFF_DIMM_TYPE_TargetType; + + /// + /// @brief attribute getter + /// @param[in] i_target the MCS target + /// @param[out] o_setting array to populate + /// @return FAPI2_RC_SUCCESS iff okay + /// + static fapi2::ReturnCode get_attr(const fapi2::Target<TARGET_TYPE>& i_target, + attr_type& o_setting) + { + FAPI_TRY( FAPI_ATTR_GET(fapi2::ATTR_EFF_DIMM_TYPE, i_target, o_setting) ); + + fapi_try_exit: + return fapi2::current_err; + } + + /// + /// @brief attribute setter + /// @param[in] i_target the MCS target + /// @param[in] i_setting array to set + /// @return FAPI2_RC_SUCCESS iff okay + /// + static fapi2::ReturnCode set_attr(const fapi2::Target<TARGET_TYPE>& i_target, + const attr_type& i_setting) + { + attr_type l_data = {}; + memcpy(l_data, i_setting, sizeof(l_data)); + FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_DIMM_TYPE, i_target, l_data) ); + + fapi_try_exit: + return fapi2::current_err; + } +}; + +/// +/// @brief Traits for pre_data_engine +/// @class preDataInitTraits +/// @note NIMBUS, DRAM_GEN specialization +/// +template<> +class preDataInitTraits<mss::proc_type::NIMBUS, DRAM_GEN> +{ + public: + using attr_type = fapi2::ATTR_EFF_DRAM_GEN_Type; + static const fapi2::TargetType TARGET_TYPE = fapi2::ATTR_EFF_DRAM_GEN_TargetType; + + /// + /// @brief attribute getter + /// @param[in] i_target the MCS target + /// @param[out] o_setting array to populate + /// @return FAPI2_RC_SUCCESS iff okay + /// + static fapi2::ReturnCode get_attr(const fapi2::Target<TARGET_TYPE>& i_target, + attr_type& o_setting) + { + FAPI_TRY( FAPI_ATTR_GET(fapi2::ATTR_EFF_DRAM_GEN, i_target, o_setting) ); + + fapi_try_exit: + return fapi2::current_err; + } + + /// + /// @brief attribute setter + /// @param[in] i_target the MCS target + /// @param[in] i_setting array to set + /// @return FAPI2_RC_SUCCESS iff okay + /// + static fapi2::ReturnCode set_attr(const fapi2::Target<TARGET_TYPE>& i_target, + const attr_type& i_setting) + { + attr_type l_data = {}; + memcpy(l_data, i_setting, sizeof(l_data)); + + FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_DRAM_GEN, i_target, l_data) ); + + fapi_try_exit: + return fapi2::current_err; + } +}; + +/// +/// @brief Traits for pre_data_engine +/// @class preDataInitTraits +/// @note NIMBUS, HYBRID specialization +/// +template<> +class preDataInitTraits<mss::proc_type::NIMBUS, HYBRID> +{ + public: + using attr_type = fapi2::ATTR_EFF_HYBRID_Type; + static const fapi2::TargetType TARGET_TYPE = fapi2::ATTR_EFF_HYBRID_TargetType; + + /// + /// @brief attribute getter + /// @param[in] i_target the MCS target + /// @param[out] o_setting array to populate + /// @return FAPI2_RC_SUCCESS iff okay + /// + static fapi2::ReturnCode get_attr(const fapi2::Target<TARGET_TYPE>& i_target, + attr_type& o_setting) + { + FAPI_TRY( FAPI_ATTR_GET(fapi2::ATTR_EFF_HYBRID, i_target, o_setting) ); + + fapi_try_exit: + return fapi2::current_err; + } + + /// + /// @brief attribute setter + /// @param[in] i_target the MCS target + /// @param[in] i_setting array to set + /// @return FAPI2_RC_SUCCESS iff okay + /// + static fapi2::ReturnCode set_attr(const fapi2::Target<TARGET_TYPE>& i_target, + const attr_type& i_setting) + { + attr_type l_data = {}; + memcpy(l_data, i_setting, sizeof(l_data)); + + FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_HYBRID, i_target, l_data) ); + + fapi_try_exit: + return fapi2::current_err; + } +}; + +/// +/// @brief Traits for pre_data_engine +/// @class preDataInitTraits +/// @note NIMBUS, HYBRID_MEDIA specialization +/// +template<> +class preDataInitTraits<mss::proc_type::NIMBUS, HYBRID_MEDIA> +{ + public: + using attr_type = fapi2::ATTR_EFF_HYBRID_MEMORY_TYPE_Type; + static const fapi2::TargetType TARGET_TYPE = fapi2::ATTR_EFF_HYBRID_MEMORY_TYPE_TargetType; + + /// + /// @brief attribute getter + /// @param[in] i_target the MCS target + /// @param[out] o_setting array to populate + /// @return FAPI2_RC_SUCCESS iff okay + /// + static fapi2::ReturnCode get_attr(const fapi2::Target<TARGET_TYPE>& i_target, + attr_type& o_setting) + { + FAPI_TRY( FAPI_ATTR_GET(fapi2::ATTR_EFF_HYBRID_MEMORY_TYPE, i_target, o_setting) ); + + fapi_try_exit: + return fapi2::current_err; + } + + /// + /// @brief attribute setter + /// @param[in] i_target the MCS target + /// @param[in] i_setting array to set + /// @return FAPI2_RC_SUCCESS iff okay + /// + static fapi2::ReturnCode set_attr(const fapi2::Target<TARGET_TYPE>& i_target, + const attr_type& i_setting) + { + attr_type l_data = {}; + memcpy(l_data, i_setting, sizeof(l_data)); + + FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_HYBRID_MEMORY_TYPE, i_target, l_data) ); + + fapi_try_exit: + return fapi2::current_err; + } +}; + +/// +/// @brief Traits for pre_data_engine +/// @class preDataInitTraits +/// @note NIMBUS, MRANKS specialization +/// +template<> +class preDataInitTraits<mss::proc_type::NIMBUS, MRANKS> +{ + public: + using attr_type = fapi2::ATTR_EFF_NUM_MASTER_RANKS_PER_DIMM_Type; + static const fapi2::TargetType TARGET_TYPE = fapi2::ATTR_EFF_NUM_MASTER_RANKS_PER_DIMM_TargetType; + + /// + /// @brief attribute getter + /// @param[in] i_target the MCS target + /// @param[out] o_setting array to populate + /// @return FAPI2_RC_SUCCESS iff okay + /// + static fapi2::ReturnCode get_attr(const fapi2::Target<TARGET_TYPE>& i_target, + attr_type& o_setting) + { + FAPI_TRY( FAPI_ATTR_GET(fapi2::ATTR_EFF_NUM_MASTER_RANKS_PER_DIMM, i_target, o_setting) ); + + fapi_try_exit: + return fapi2::current_err; + } + + /// + /// @brief attribute setter + /// @param[in] i_target the MCS target + /// @param[in] i_setting array to set + /// @return FAPI2_RC_SUCCESS iff okay + /// + static fapi2::ReturnCode set_attr(const fapi2::Target<TARGET_TYPE>& i_target, + const attr_type& i_setting) + { + attr_type l_data = {}; + memcpy(l_data, i_setting, sizeof(l_data)); + + FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_NUM_MASTER_RANKS_PER_DIMM, i_target, l_data) ); + + fapi_try_exit: + return fapi2::current_err; + } +}; + +/// +/// @brief Traits for pre_data_engine +/// @class preDataInitTraits +/// @note NIMBUS, DIMM_RANKS_CNFG specialization +/// +template<> +class preDataInitTraits<mss::proc_type::NIMBUS, DIMM_RANKS_CNFG> +{ + public: + using attr_type = fapi2::ATTR_EFF_DIMM_RANKS_CONFIGED_Type; + static const fapi2::TargetType TARGET_TYPE = fapi2::ATTR_EFF_NUM_MASTER_RANKS_PER_DIMM_TargetType; + + /// + /// @brief attribute getter + /// @param[in] i_target the MCS target + /// @param[out] o_setting array to populate + /// @return FAPI2_RC_SUCCESS iff okay + /// + static fapi2::ReturnCode get_attr(const fapi2::Target<TARGET_TYPE>& i_target, + attr_type& o_setting) + { + FAPI_TRY( FAPI_ATTR_GET(fapi2::ATTR_EFF_DIMM_RANKS_CONFIGED, i_target, o_setting) ); + + fapi_try_exit: + return fapi2::current_err; + } + + /// + /// @brief attribute setter + /// @param[in] i_target the MCS target + /// @param[in] i_setting array to set + /// @return FAPI2_RC_SUCCESS iff okay + /// + static fapi2::ReturnCode set_attr(const fapi2::Target<TARGET_TYPE>& i_target, + const attr_type& i_setting) + { + attr_type l_data = {}; + memcpy(l_data, i_setting, sizeof(l_data)); + + FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_DIMM_RANKS_CONFIGED, i_target, l_data) ); + + fapi_try_exit: + return fapi2::current_err; + } +}; + // ========================================================= // DDR4 SPD Document Release 4 // Byte 2 (0x002): Key Byte / DRAM Device Type // ========================================================= -const std::vector< std::pair<uint8_t, uint8_t> > pre_data_engine<NIMBUS>::DRAM_GEN_MAP = +template<> +const std::vector< std::pair<uint8_t, uint8_t> > pre_data_engine<mss::proc_type::NIMBUS>::DRAM_GEN_MAP = { //{key value, dram gen} {0x0C, fapi2::ENUM_ATTR_EFF_DRAM_GEN_DDR4} @@ -57,7 +333,8 @@ const std::vector< std::pair<uint8_t, uint8_t> > pre_data_engine<NIMBUS>::DRAM_G // DDR4 SPD Document Release 4 // Byte 3 (0x003): Key Byte / Module Type - Hybrid // ========================================================= -const std::vector< std::pair<uint8_t, uint8_t> > pre_data_engine<NIMBUS>::HYBRID_MAP = +template<> +const std::vector< std::pair<uint8_t, uint8_t> > pre_data_engine<mss::proc_type::NIMBUS>::HYBRID_MAP = { //{key byte, dimm type} {0, fapi2::ENUM_ATTR_EFF_HYBRID_NOT_HYBRID}, @@ -70,7 +347,8 @@ const std::vector< std::pair<uint8_t, uint8_t> > pre_data_engine<NIMBUS>::HYBRID // DDR4 SPD Document Release 4 // Byte 3 (0x003): Key Byte / Module Type - Hybrid // ========================================================= -const std::vector< std::pair<uint8_t, uint8_t> > pre_data_engine<NIMBUS>::HYBRID_MEMORY_TYPE_MAP = +template<> +const std::vector< std::pair<uint8_t, uint8_t> > pre_data_engine<mss::proc_type::NIMBUS>::HYBRID_MEMORY_TYPE_MAP = { //{key byte, dimm type} @@ -83,7 +361,8 @@ const std::vector< std::pair<uint8_t, uint8_t> > pre_data_engine<NIMBUS>::HYBRID // DDR4 SPD Document Release 4 // Byte 3 (0x003): Key Byte / Module Type // ========================================================= -const std::vector< std::pair<uint8_t, uint8_t> > pre_data_engine<NIMBUS>::BASE_MODULE_TYPE_MAP = +template<> +const std::vector< std::pair<uint8_t, uint8_t> > pre_data_engine<mss::proc_type::NIMBUS>::BASE_MODULE_TYPE_MAP = { //{key byte, dimm type} {1, fapi2::ENUM_ATTR_EFF_DIMM_TYPE_RDIMM}, @@ -96,7 +375,8 @@ const std::vector< std::pair<uint8_t, uint8_t> > pre_data_engine<NIMBUS>::BASE_M // DDR4 SPD Document Release 4 // Byte 12 (0x00C): Module Organization // ========================================================= -const std::vector< std::pair<uint8_t, uint8_t> > pre_data_engine<NIMBUS>::NUM_PACKAGE_RANKS_MAP = +template<> +const std::vector< std::pair<uint8_t, uint8_t> > pre_data_engine<mss::proc_type::NIMBUS>::NUM_PACKAGE_RANKS_MAP = { // {key byte, num of package ranks per DIMM (package ranks)} {0, fapi2::ENUM_ATTR_EFF_NUM_MASTER_RANKS_PER_DIMM_1R}, @@ -105,42 +385,18 @@ const std::vector< std::pair<uint8_t, uint8_t> > pre_data_engine<NIMBUS>::NUM_PA }; /// -/// @brief ctor -/// @param[in] i_target the DIMM target -/// @param[in] i_spd_data SPD data -/// @param[out] o_rc ReturnCode for failure to init object -/// -pre_data_engine<NIMBUS>::pre_data_engine(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target, - const spd::facade& i_spd_data, - fapi2::ReturnCode& o_rc): - iv_dimm(i_target), - iv_spd_data(i_spd_data) -{ - // Sets up commonly used member variables - uint8_t l_master_ranks = 0; - FAPI_TRY(iv_spd_data.num_package_ranks_per_dimm(l_master_ranks)); - FAPI_TRY(lookup_table_check(i_target, NUM_PACKAGE_RANKS_MAP, PRE_DATA_ENGINE_CTOR, l_master_ranks, iv_master_ranks)); - - o_rc = fapi2::FAPI2_RC_SUCCESS; - return; - -fapi_try_exit: - o_rc = fapi2::current_err; - return; -} - -/// /// @brief Set ATTR_EFF_DIMM_TYPE /// @return FAPI2_RC_SUCCESS iff ok /// -fapi2::ReturnCode pre_data_engine<NIMBUS>::set_dimm_type() +template<> +fapi2::ReturnCode pre_data_engine<mss::proc_type::NIMBUS>::set_dimm_type() { uint8_t l_base_module_type = 0; uint8_t l_dimm_type = 0; FAPI_TRY(iv_spd_data.base_module(l_base_module_type)); FAPI_TRY(lookup_table_check(iv_dimm, BASE_MODULE_TYPE_MAP, SET_ATTR_DIMM_TYPE, l_base_module_type, l_dimm_type)); - FAPI_TRY( (set_field<NIMBUS, DIMM_TYPE>(iv_dimm, l_dimm_type)) ); + FAPI_TRY( (set_field<mss::proc_type::NIMBUS, DIMM_TYPE>(iv_dimm, l_dimm_type)) ); fapi_try_exit: return fapi2::current_err; @@ -150,7 +406,8 @@ fapi_try_exit: /// @brief Set ATTR_EFF_DRAM_GEN /// @return FAPI2_RC_SUCCESS iff ok /// -fapi2::ReturnCode pre_data_engine<NIMBUS>::set_dram_gen() +template<> +fapi2::ReturnCode pre_data_engine<mss::proc_type::NIMBUS>::set_dram_gen() { uint8_t l_device_type = 0; uint8_t l_dram_gen = 0; @@ -158,7 +415,7 @@ fapi2::ReturnCode pre_data_engine<NIMBUS>::set_dram_gen() FAPI_TRY(iv_spd_data.device_type(l_device_type)); FAPI_TRY(lookup_table_check(iv_dimm, DRAM_GEN_MAP, SET_ATTR_DRAM_GEN, l_device_type, l_dram_gen)); - FAPI_TRY( (set_field<NIMBUS, DRAM_GEN>(iv_dimm, l_dram_gen)) ); + FAPI_TRY( (set_field<mss::proc_type::NIMBUS, DRAM_GEN>(iv_dimm, l_dram_gen)) ); fapi_try_exit: return fapi2::current_err; @@ -168,7 +425,8 @@ fapi_try_exit: /// @brief Set ATTR_EFF_HYBRID /// @return FAPI2_RC_SUCCESS iff ok /// -fapi2::ReturnCode pre_data_engine<NIMBUS>::set_hybrid() +template<> +fapi2::ReturnCode pre_data_engine<mss::proc_type::NIMBUS>::set_hybrid() { uint8_t l_spd_hybrid_type = 0; uint8_t l_hybrid = 0; @@ -176,7 +434,7 @@ fapi2::ReturnCode pre_data_engine<NIMBUS>::set_hybrid() FAPI_TRY(iv_spd_data.hybrid(l_spd_hybrid_type)); FAPI_TRY(lookup_table_check(iv_dimm, HYBRID_MAP, SET_ATTR_HYBRID, l_spd_hybrid_type, l_hybrid)); - FAPI_TRY( (set_field<NIMBUS, HYBRID>(iv_dimm, l_hybrid)) ); + FAPI_TRY( (set_field<mss::proc_type::NIMBUS, HYBRID>(iv_dimm, l_hybrid)) ); fapi_try_exit: return fapi2::current_err; @@ -186,7 +444,8 @@ fapi_try_exit: /// @brief Set ATTR_EFF_HYBRID_MEMORY_TYPE /// @return FAPI2_RC_SUCCESS iff ok /// -fapi2::ReturnCode pre_data_engine<NIMBUS>::set_hybrid_media() +template<> +fapi2::ReturnCode pre_data_engine<mss::proc_type::NIMBUS>::set_hybrid_media() { uint8_t l_hybrid_media = 0; uint8_t l_spd_hybrid_media = 0; @@ -194,7 +453,7 @@ fapi2::ReturnCode pre_data_engine<NIMBUS>::set_hybrid_media() FAPI_TRY(iv_spd_data.hybrid_media(l_spd_hybrid_media)); FAPI_TRY(lookup_table_check(iv_dimm, HYBRID_MAP, SET_ATTR_HYBRID, l_spd_hybrid_media, l_hybrid_media)); - FAPI_TRY( (set_field<NIMBUS, HYBRID_MEDIA>(iv_dimm, l_hybrid_media)) ); + FAPI_TRY( (set_field<mss::proc_type::NIMBUS, HYBRID_MEDIA>(iv_dimm, l_hybrid_media)) ); fapi_try_exit: return fapi2::current_err; @@ -204,9 +463,18 @@ fapi_try_exit: /// @brief Set ATTR_EFF_NUM_MASTER_RANKS_PER_DIMM /// @return FAPI2_RC_SUCCESS iff ok /// -fapi2::ReturnCode pre_data_engine<NIMBUS>::set_master_ranks() +template<> +fapi2::ReturnCode pre_data_engine<mss::proc_type::NIMBUS>::set_master_ranks() { - FAPI_TRY( (set_field<NIMBUS, MRANKS>(iv_dimm, iv_master_ranks)) ); + // Sets up commonly used member variables + uint8_t l_master_ranks_spd = 0; + uint8_t l_master_ranks_to_set = 0; + FAPI_TRY(iv_spd_data.num_package_ranks_per_dimm(l_master_ranks_spd), + "%s failed to get number of package ranks from SPD", spd::c_str(iv_dimm)); + FAPI_TRY(lookup_table_check(iv_dimm, NUM_PACKAGE_RANKS_MAP, PRE_DATA_ENGINE_CTOR, l_master_ranks_spd, + l_master_ranks_to_set), "%s failed MASTER_RANKS lookup check", spd::c_str(iv_dimm)); + + FAPI_TRY( (set_field<mss::proc_type::NIMBUS, MRANKS>(iv_dimm, l_master_ranks_to_set)) ); fapi_try_exit: return fapi2::current_err; @@ -216,16 +484,23 @@ fapi_try_exit: /// @brief Sets ATTR_EFF_DIMM_RANKS_CONFIGED /// @return FAPI2_RC_SUCCESS iff okay /// -fapi2::ReturnCode pre_data_engine<NIMBUS>::set_dimm_ranks_configured() +template<> +fapi2::ReturnCode pre_data_engine<mss::proc_type::NIMBUS>::set_dimm_ranks_configured() { // Set configed ranks. Set the bit representing the master rank configured (0 being left most.) So, // a 4R DIMM would be 0b11110000 (0xF0). This is used by PRD. fapi2::buffer<uint8_t> l_ranks_configed; + uint8_t l_master_ranks = 0; + + // Make sure the number of master ranks is setup + FAPI_TRY( set_master_ranks(), "%s Failed to set the number of master ranks", spd::c_str(iv_dimm) ); + FAPI_TRY( eff_num_master_ranks_per_dimm(iv_dimm, l_master_ranks), + "%s Failed to get the number of master ranks", spd::c_str(iv_dimm) ); - FAPI_TRY( l_ranks_configed.setBit(0, iv_master_ranks), + FAPI_TRY( l_ranks_configed.setBit(0, l_master_ranks), "%s. Failed to setBit", spd::c_str(iv_dimm) ); - FAPI_TRY( (set_field<NIMBUS, DIMM_RANKS_CNFG>(iv_dimm, uint8_t(l_ranks_configed))) ); + FAPI_TRY( (set_field<mss::proc_type::NIMBUS, DIMM_RANKS_CNFG>(iv_dimm, uint8_t(l_ranks_configed))) ); fapi_try_exit: return fapi2::current_err; diff --git a/src/import/chips/p9/procedures/hwp/memory/lib/freq/nimbus_mss_freq.C b/src/import/chips/p9/procedures/hwp/memory/lib/freq/nimbus_mss_freq.C index ee00486be..688875f34 100644 --- a/src/import/chips/p9/procedures/hwp/memory/lib/freq/nimbus_mss_freq.C +++ b/src/import/chips/p9/procedures/hwp/memory/lib/freq/nimbus_mss_freq.C @@ -22,3 +22,281 @@ /* permissions and limitations under the License. */ /* */ /* IBM_PROLOG_END_TAG */ + +/// +/// @file nimbus_mss_freq.C +/// @brief Nimbus specializations for frequency library +/// +// *HWP HWP Owner: Stephen Glancy <sglancy@us.ibm.com> +// *HWP HWP Backup: Louis Stermole <stermole@us.ibm.com> +// *HWP Team: Memory +// *HWP Level: 3 +// *HWP Consumed by: HB:FSP + +#include <fapi2.H> +#include <vpd_access.H> +#include <vector> + +// Memory libraries +#include <lib/mss_attribute_accessors.H> +#include <lib/utils/assert_noexit.H> +#include <lib/shared/mss_const.H> +#include <lib/freq/sync.H> +#include <lib/workarounds/freq_workarounds.H> + +// Generic libraries +#include <generic/memory/lib/utils/count_dimm.H> +#include <generic/memory/lib/utils/freq/gen_mss_freq_traits.H> +#include <generic/memory/lib/utils/freq/gen_mss_freq.H> +#include <generic/memory/lib/utils/freq/mss_freq_scoreboard.H> + +namespace mss +{ + +const std::vector< uint64_t > frequency_traits<mss::proc_type::NIMBUS>::SUPPORTED_FREQS = +{ + mss::DIMM_SPEED_1866, + mss::DIMM_SPEED_2133, + mss::DIMM_SPEED_2400, + mss::DIMM_SPEED_2666, +}; + +/// +/// @brief Sets DRAM CAS latency attributes - specialization for NIMBUS and MCA +/// @param[in] i_target the controller target the cas_latency value +/// @param[in] i_cas_latency cas latency to update +/// @return FAPI2_RC_SUCCESS iff ok +/// +template<> +fapi2::ReturnCode set_CL_attr<mss::proc_type::NIMBUS>( + const fapi2::Target<fapi2::TARGET_TYPE_MCA>& i_target, + const uint64_t i_cas_latency) +{ + // I wish I could do the reinterpret cast or set the pointer to the vector :( + // But no can do, manual copy pasta + uint8_t l_temp [mss::PORTS_PER_MCS] = {0}; + + // Local variable instead of calling it three times. Hopefully compiler can optimize this better + const auto l_index = mss::index(i_target); + const auto& l_mcs = mss::find_target<fapi2::TARGET_TYPE_MCS>(i_target); + + if ( l_index >= PORTS_PER_MCS) + { + FAPI_ERR("%s mss::index returned a value greater than PORTS_PER_MCS", mss::c_str(i_target) ); + fapi2::Assert(false); + } + + FAPI_TRY(mss::eff_dram_cl(l_mcs, l_temp), "%s failed to get cas latency attribute", mss::c_str(i_target)); + + l_temp[l_index] = i_cas_latency; + + //Check for rounding issues. Going from a uint64_t to a uint8_t + FAPI_ASSERT( l_temp[l_index] == i_cas_latency, + fapi2::MSS_BAD_CL_CAST() + .set_CL(i_cas_latency) + .set_MCA_TARGET(i_target), + "%s bad cast for cas latency from %d to %d", + mss::c_str(i_target), + i_cas_latency, + l_temp[l_index]); + + FAPI_INF( "Final Chosen CL: %d for %s", l_temp[l_index], mss::c_str(i_target)); + + // set CAS latency attribute + // casts vector into the type FAPI_ATTR_SET is expecting by deduction + FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_DRAM_CL, + l_mcs, + l_temp) , + "%s Failed to set CAS latency attribute", mss::c_str(i_target)); + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Sets the frequency value - specialization for NIMBUS and MCBIST +/// @param[in] i_target the target on which to set the frequency values +/// @param[in] i_freq frequency value to set +/// @return FAPI2_RC_SUCCESS iff ok +/// +template<> +fapi2::ReturnCode set_freq<mss::proc_type::NIMBUS>( + const fapi2::Target<fapi2::TARGET_TYPE_MCBIST>& i_target, + const uint64_t i_freq) +{ + // Local variable to avoid compile fails - ATTR_SET cannot operate on consts + auto l_freq = i_freq; + return FAPI_ATTR_SET(fapi2::ATTR_MSS_FREQ, i_target, l_freq); +} + +/// +/// @brief Gets the number of master ranks per DIMM - specialization for NIMBUS and MCA +/// @param[in] i_target the target on which to set the frequency values +/// @param[out] o_master_ranks number of master ranks per DIMM +/// @return FAPI2_RC_SUCCESS iff ok +/// +template<> +fapi2::ReturnCode get_master_rank_per_dimm<mss::proc_type::NIMBUS>( + const fapi2::Target<fapi2::TARGET_TYPE_MCA>& i_target, + uint8_t* o_master_ranks) +{ + return mss::eff_num_master_ranks_per_dimm(i_target, o_master_ranks); +} + +/// +/// @brief Gets the attribute for the maximum - specialization for NIMBUS +/// @param[out] o_allowed_dimm_freq allowed dimm frequency +/// @return FAPI2_RC_SUCCESS iff ok +/// +template<> +fapi2::ReturnCode max_allowed_dimm_freq<mss::proc_type::NIMBUS>(uint32_t* o_allowed_dimm_freq) +{ + return mss::max_allowed_dimm_freq(o_allowed_dimm_freq); +} + +/// +/// @brief Update supported frequency scoreboard according to processor limits - specialization for NIMBUS and MCBIST +/// @param[in] i_target processor frequency domain +/// @param[in,out] io_scoreboard scoreboard of port targets supporting each frequency +/// @return FAPI2_RC_SUCCESS iff ok +/// +template<> +fapi2::ReturnCode limit_freq_by_processor<mss::proc_type::NIMBUS>( + const fapi2::Target<fapi2::TARGET_TYPE_MCBIST>& i_target, + freq_scoreboard& io_scoreboard) +{ + uint8_t l_req_sync_mode = 0; + FAPI_TRY( mss::required_synch_mode(l_req_sync_mode) ); + FAPI_TRY( limit_freq_by_processor(i_target, l_req_sync_mode == fapi2::ENUM_ATTR_REQUIRED_SYNCH_MODE_ALWAYS, + io_scoreboard) ); + + return fapi2::FAPI2_RC_SUCCESS; + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Gets the number of master ranks on each DIMM - specialization for the NIMBUS processor type +/// @param[in] i_target DIMM target +/// @param[out] o_master_ranks number of master ranks +/// @return FAPI2_RC_SUCCESS iff ok +/// +template<> +fapi2::ReturnCode num_master_ranks_per_dimm<mss::proc_type::NIMBUS>(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& + i_target, uint8_t& o_master_ranks) +{ + return mss::eff_num_master_ranks_per_dimm(i_target, o_master_ranks); +} + +/// +/// @brief Calls out the target if no DIMM frequencies are supported - specialization for NIMBUS and MCBIST +/// @param[in] i_target target on which to operate +/// @param[in] i_supported_freq true if any FREQ's are supported +/// @param[in,out] io_scoreboard scoreboard of port targets supporting each frequency +/// @return FAPI2_RC_SUCCESS iff ok +/// +template<> +fapi2::ReturnCode callout_no_common_freq<mss::proc_type::NIMBUS>(const fapi2::Target<fapi2::TARGET_TYPE_MCBIST>& + i_target, + const bool l_supported_freq, + const uint64_t i_num_ports) +{ + std::vector<uint32_t> l_max_mrw_freqs(NUM_MAX_FREQS, 0); + uint8_t l_req_sync_mode = 0; + FAPI_TRY( mss::required_synch_mode(l_req_sync_mode) ); + FAPI_TRY( max_allowed_dimm_freq(l_max_mrw_freqs.data()) ); + { + const bool l_sync_mode = l_req_sync_mode == fapi2::ENUM_ATTR_REQUIRED_SYNCH_MODE_ALWAYS; + FAPI_ASSERT(l_supported_freq, + fapi2::MSS_NO_SUPPORTED_FREQ() + .set_REQUIRED_SYNC_MODE(l_sync_mode) + .set_MCBIST_TARGET(i_target) + .set_NUM_PORTS(i_num_ports) + .set_MRW_MAX_FREQ_0(l_max_mrw_freqs[0]) + .set_MRW_MAX_FREQ_1(l_max_mrw_freqs[1]) + .set_MRW_MAX_FREQ_2(l_max_mrw_freqs[2]) + .set_MRW_MAX_FREQ_3(l_max_mrw_freqs[3]) + .set_MRW_MAX_FREQ_4(l_max_mrw_freqs[4]), + "%s didn't find a frequency that was supported on any ports", mss::c_str(i_target)); + } + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Calls out the target if no DIMM frequencies are supported - specialization for NIMBUS and MCBIST +/// @param[in] i_target target on which to operate +/// @param[in] i_vpd_supported_freqs VPD supported frequencies for the callout +/// @return FAPI2_RC_SUCCESS iff ok +/// +template<> +fapi2::ReturnCode callout_max_freq_empty_set<mss::proc_type::NIMBUS>(const fapi2::Target<fapi2::TARGET_TYPE_MCBIST>& + i_target, + const std::vector<std::vector<uint32_t>>& i_vpd_supported_freqs) +{ + + std::vector<uint32_t> l_port_vpd_max_freq; + + // Get the max freq supported on each port + for ( const auto& l_port_supported_freqs : i_vpd_supported_freqs ) + { + l_port_vpd_max_freq.push_back(l_port_supported_freqs.back()); + } + + std::vector<uint32_t> l_max_mrw_freqs(NUM_MAX_FREQS, 0); + uint8_t l_req_sync_mode = 0; + FAPI_TRY( mss::required_synch_mode(l_req_sync_mode) ); + FAPI_TRY( max_allowed_dimm_freq(l_max_mrw_freqs.data()) ); + + { + // TK Louis and I will be checking on this - I think we need this to be 4 instead of 8 and will need a mustfix + const bool l_sync_mode = l_req_sync_mode == fapi2::ENUM_ATTR_REQUIRED_SYNCH_MODE_ALWAYS; + FAPI_ASSERT(false, + fapi2::MSS_MRW_FREQ_MAX_FREQ_EMPTY_SET() + .set_MSS_VPD_FREQ_0(l_port_vpd_max_freq[0]) + .set_MSS_VPD_FREQ_1(l_port_vpd_max_freq[1]) + .set_MSS_VPD_FREQ_2(l_port_vpd_max_freq[2]) + .set_MSS_VPD_FREQ_3(l_port_vpd_max_freq[3]) + .set_MSS_MAX_FREQ_0(l_max_mrw_freqs[0]) + .set_MSS_MAX_FREQ_1(l_max_mrw_freqs[1]) + .set_MSS_MAX_FREQ_2(l_max_mrw_freqs[2]) + .set_MSS_MAX_FREQ_3(l_max_mrw_freqs[3]) + .set_MSS_MAX_FREQ_4(l_max_mrw_freqs[4]) + .set_MSS_NEST_FREQ_0(fapi2::ENUM_ATTR_FREQ_PB_MHZ_1600) + .set_MSS_NEST_FREQ_1(fapi2::ENUM_ATTR_FREQ_PB_MHZ_1866) + .set_MSS_NEST_FREQ_2(fapi2::ENUM_ATTR_FREQ_PB_MHZ_2000) + .set_MSS_NEST_FREQ_3(fapi2::ENUM_ATTR_FREQ_PB_MHZ_2133) + .set_MSS_NEST_FREQ_4(fapi2::ENUM_ATTR_FREQ_PB_MHZ_2400) + .set_REQUIRED_SYNC_MODE(l_sync_mode) + .set_MCBIST_TARGET(i_target), + "%s didn't find a common frequency for all ports", mss::c_str(i_target)); + } +fapi_try_exit: + return fapi2::current_err; +} +namespace check +{ + +/// +/// @brief Checks the final frequency for the system type - NIMBUS and MCBIST specialization +/// @param[in] i_target the target on which to operate +/// @return FAPI2_RC_SUCCESS iff okay +/// +template<> +fapi2::ReturnCode final_freq<mss::proc_type::NIMBUS>(const fapi2::Target<fapi2::TARGET_TYPE_MCBIST>& i_target) +{ + uint64_t l_mss_freq = 0; + uint32_t l_nest_freq = 0; + FAPI_TRY( mss::freq_pb_mhz(l_nest_freq) ); + FAPI_TRY( mss::freq(i_target, l_mss_freq) ); + FAPI_TRY( mss::workarounds::check_dimm_nest_freq_ratio(i_target, l_mss_freq, l_nest_freq) ); + +fapi_try_exit: + return fapi2::current_err; +} + +} // ns check + +} // ns mss diff --git a/src/import/chips/p9/procedures/hwp/memory/lib/freq/sync.C b/src/import/chips/p9/procedures/hwp/memory/lib/freq/sync.C index 4de154092..9b864695a 100644 --- a/src/import/chips/p9/procedures/hwp/memory/lib/freq/sync.C +++ b/src/import/chips/p9/procedures/hwp/memory/lib/freq/sync.C @@ -38,14 +38,21 @@ #include <algorithm> #include <vector> #include <map> + +// Memory libraries #include <lib/freq/sync.H> -#include <generic/memory/lib/utils/find.H> +#include <lib/mss_attribute_accessors.H> #include <lib/utils/assert_noexit.H> + +// Generic libraries +#include <generic/memory/lib/utils/find.H> #include <generic/memory/lib/utils/count_dimm.H> #include <generic/memory/lib/spd/spd_facade.H> #include <generic/memory/lib/spd/spd_utils.H> #include <generic/memory/lib/utils/conversions.H> -#include <lib/mss_attribute_accessors.H> +#include <generic/memory/lib/utils/freq/gen_mss_freq_traits.H> +#include <generic/memory/lib/utils/freq/gen_mss_freq.H> +#include <generic/memory/lib/utils/freq/mss_freq_scoreboard.H> using fapi2::TARGET_TYPE_DIMM; using fapi2::TARGET_TYPE_MCS; @@ -314,774 +321,4 @@ fapi_try_exit: #endif } -/// -/// @brief Create a vector of support freq based on VPD config -/// @param[in] i_target MCBIST target for which to get the DIMM configs -/// @param[out] o_vpd_supported_freqs reference to a 2 dimensional vector of supported VPD frequencies for each MCA -/// @return FAPI2_RC_SUCCESS iff ok -/// -fapi2::ReturnCode vpd_supported_freqs( const fapi2::Target<fapi2::TARGET_TYPE_MCBIST>& i_target, - std::vector<std::vector<uint32_t>>& o_vpd_supported_freqs) -{ - uint8_t l_rank_count_dimm[MAX_DIMM_PER_PORT] = {}; - uint8_t l_mr_blob[mss::VPD_KEYWORD_MAX] = {}; - - // This bitmap will keep track of the ports we visit. - // Any we don't are not configured, so will support all frequencies in the scoreboard - fapi2::buffer<uint8_t> configured_ports; - - // Clearing output Just.In.Case - o_vpd_supported_freqs.clear(); - - for ( size_t l_index = 0; l_index < PORTS_PER_MCBIST; ++l_index ) - { - o_vpd_supported_freqs.push_back(std::vector<uint32_t>()); - } - - fapi2::VPDInfo<fapi2::TARGET_TYPE_MCS> l_vpd_info(fapi2::MemVpdData::MR); - - for( const auto& mcs : mss::find_targets<TARGET_TYPE_MCS>(i_target) ) - { - for( const auto& p : mss::find_targets<TARGET_TYPE_MCA>(mcs) ) - { - const auto l_port_pos = mss::relative_pos<fapi2::TARGET_TYPE_MCBIST>(p); - FAPI_TRY( configured_ports.setBit(l_port_pos) ); - - if( mss::count_dimm(p) == 0 ) - { - // Cronus lets you have an MCA w/no DIMMs. In this case, we say the port supports all frequencies - for( const auto& freq : NIMBUS_SUPPORTED_FREQS ) - { - o_vpd_supported_freqs[l_port_pos].push_back(freq); - } - - continue; - } - - FAPI_TRY( mss::eff_num_master_ranks_per_dimm(p, &(l_rank_count_dimm[0])) ); - - l_vpd_info.iv_rank_count_dimm_0 = l_rank_count_dimm[0]; - l_vpd_info.iv_rank_count_dimm_1 = l_rank_count_dimm[1]; - l_vpd_info.iv_is_config_ffdc_enabled = false; - - // Iterate through all Nimbus supported freqs - for( const auto& freq : NIMBUS_SUPPORTED_FREQS ) - { - l_vpd_info.iv_freq_mhz = freq; - - FAPI_INF("%s. VPD info - frequency: %d MT/s, rank count for dimm_0: %d, dimm_1: %d", - mss::c_str(p), l_vpd_info.iv_freq_mhz, l_vpd_info.iv_rank_count_dimm_0, l_vpd_info.iv_rank_count_dimm_1); - - // In order to retrieve the VPD contents we first need the keyword size. - // If we are unable to retrieve the keyword size then this speed isn't - // supported in the VPD in Cronus (but not FW) and we skip to the next - // possible speed bin. - if( fapi2::getVPD(mcs, l_vpd_info, nullptr) != fapi2::FAPI2_RC_SUCCESS ) - { - FAPI_INF("Couldn't retrieve MR size from VPD for this config %s -- skipping freq %d MT/s", mss::c_str(p), freq ); - - fapi2::current_err = fapi2::FAPI2_RC_SUCCESS; - continue; - } - - FAPI_ASSERT( l_vpd_info.iv_size <= mss::VPD_KEYWORD_MAX, - fapi2::MSS_INVALID_VPD_KEYWORD_MAX(). - set_MAX(mss::VPD_KEYWORD_MAX). - set_ACTUAL(l_vpd_info.iv_size). - set_KEYWORD(fapi2::MemVpdData::MR). - set_MCS_TARGET(i_target), - "VPD MR keyword size retrieved: %d, is larger than max: %d for %s", - l_vpd_info.iv_size, mss::VPD_KEYWORD_MAX, mss::c_str(i_target)); - - // Firmware doesn't do the VPD lookup in the size check so repeat the logic here - if( fapi2::getVPD(mcs, l_vpd_info, &(l_mr_blob[0])) != fapi2::FAPI2_RC_SUCCESS ) - { - FAPI_INF("Couldn't retrieve MR data from VPD for this config %s -- skipping freq %d MT/s", mss::c_str(p), freq ); - - fapi2::current_err = fapi2::FAPI2_RC_SUCCESS; - continue; - } - - // Add supported freqs to our output - FAPI_INF("VPD supported freq added: %d for %s", freq, mss::c_str(p) ); - o_vpd_supported_freqs[l_port_pos].push_back(freq); - }// freqs - }// mca - }//mcs - - // Mark any ports we didn't visit as supporting all frequencies - for ( uint64_t l_port_pos = 0; l_port_pos < PORTS_PER_MCBIST; ++l_port_pos ) - { - if ( !configured_ports.getBit(l_port_pos) ) - { - for ( const auto l_freq : NIMBUS_SUPPORTED_FREQS ) - { - o_vpd_supported_freqs[l_port_pos].push_back(l_freq); - } - } - } - - for ( auto& l_freqs : o_vpd_supported_freqs ) - { - std::sort( l_freqs.begin(), l_freqs.end() ); - } - - return fapi2::FAPI2_RC_SUCCESS; - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Retrieves max frequency each port supports due to DIMM SPD -/// @param[in] i_target the MCBIST target -/// @param[out] o_supported_freqs reference to vector of max SPD supported freq for each port -/// @return FAPI2_RC_SUCCESS iff okay -/// -fapi2::ReturnCode spd_supported_freq(const fapi2::Target<TARGET_TYPE_MCBIST>& i_target, - std::vector<uint32_t>& o_supported_freqs) -{ - uint64_t l_largest_tck = 0; - - // Start with a really high value so we can use std::min to reduce it below - o_supported_freqs = std::vector<uint32_t>(PORTS_PER_MCBIST, ~(0)); - - // Get cached decoder - std::vector< mss::spd::facade > l_spd_facades; - FAPI_TRY( get_spd_decoder_list(i_target, l_spd_facades), "%s get decoder - spd", mss::c_str(i_target) ); - - // Looking for the biggest application period on an MC. - // This will further reduce supported frequencies the system can run on. - for ( const auto& l_cache : l_spd_facades ) - { - const auto l_dimm = l_cache.get_dimm_target(); - const auto l_mca = mss::find_target<TARGET_TYPE_MCA>(l_dimm); - const auto l_port_pos = mss::relative_pos<fapi2::TARGET_TYPE_MCBIST>(l_mca); - uint64_t l_tckmax_in_ps = 0; - uint64_t l_tck_min_in_ps = 0; - uint32_t l_dimm_freq = 0; - - FAPI_TRY( spd::get_tckmax(l_cache, l_tckmax_in_ps), - "%s. Failed to get tCKmax", mss::c_str(l_dimm) ); - FAPI_TRY( spd::get_tckmin(l_cache, l_tck_min_in_ps), - "%s. Failed to get tCKmin", mss::c_str(l_dimm) ); - - // Determine a proposed tCK value that is greater than or equal tCKmin - // But less than tCKmax - l_largest_tck = std::max(l_largest_tck, l_tck_min_in_ps); - l_largest_tck = std::min(l_largest_tck, l_tckmax_in_ps); - - FAPI_TRY( mss::ps_to_freq(l_largest_tck, l_dimm_freq), "%s ps to freq %lu", mss::c_str(i_target), l_largest_tck ); - FAPI_INF("Biggest freq supported from SPD %d MT/s for %s", - l_dimm_freq, mss::c_str(l_dimm)); - - o_supported_freqs[l_port_pos] = std::min(l_dimm_freq, o_supported_freqs[l_port_pos]); - } - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Create and sort a vector of supported MT/s (freq) -/// @param[in] i_target MCBIST target for which to get the DIMM configs -/// @param[out] o_freqs reference to a std::vector to put the sorted vector -/// @return FAPI2_RC_SUCCESS iff ok -/// @note Taken from VPD supported freqs. The result is sorted so such that the min -/// supported freq is std::vector<>.begin and the max is std::vector<>.end - 1. You can -/// search the resulting vector for valid frequencies as it is sorted. -/// -fapi2::ReturnCode supported_freqs(const fapi2::Target<TARGET_TYPE_MCBIST>& i_target, - std::vector<uint32_t>& o_freqs) -{ - o_freqs.clear(); - - freq_scoreboard l_scoreboard; - std::vector<uint32_t> l_max_freqs(NUM_MAX_FREQS, 0); - std::vector<std::vector<uint32_t>> l_vpd_supported_freqs; - std::vector<uint32_t> l_spd_supported_freq(NUM_MAX_FREQS, 0); - uint8_t l_req_sync_mode = 0; - std::vector<uint8_t> l_deconfigured = {0}; - - // Retrieve system MRW, SPD, and VPD constraints - FAPI_TRY( mss::max_allowed_dimm_freq(l_max_freqs.data()), "%s max_allowed_dimm_freq", mss::c_str(i_target) ); - FAPI_TRY( spd_supported_freq(i_target, l_spd_supported_freq), "%s spd supported freqs", mss::c_str(i_target) ); - FAPI_TRY( vpd_supported_freqs(i_target, l_vpd_supported_freqs), "%s vpd supported freqs", mss::c_str(i_target) ); - - // Limit frequency scoreboard according to MRW constraints - FAPI_TRY( limit_freq_by_mrw(i_target, l_max_freqs, l_scoreboard) ); - - // Limit frequency scoreboard according to VPD constraints - FAPI_TRY( limit_freq_by_vpd(i_target, l_vpd_supported_freqs, l_scoreboard) ); - - // Limit frequency scoreboard according to SPD (DIMM) constraints - FAPI_TRY( limit_freq_by_spd(i_target, l_spd_supported_freq, l_scoreboard) ); - - // Callout the fewest number of MCAs to achieve a common shared freq - FAPI_TRY( mss::required_synch_mode(l_req_sync_mode) ); - FAPI_TRY( l_scoreboard.resolve(i_target, - l_req_sync_mode == fapi2::ENUM_ATTR_REQUIRED_SYNCH_MODE_ALWAYS, - l_vpd_supported_freqs, - l_deconfigured, - o_freqs) ); - - FAPI_INF("%s supported freqs:", mss::c_str(i_target)); - - for (const auto l_freq : o_freqs) - { - FAPI_INF("%s %d", mss::c_str(i_target), l_freq); - } - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Update supported frequency scoreboard according to MRW/config limits -/// @param[in] i_target MCBIST target for which to get the DIMM configs -/// @param[in] i_max_mrw_freqs vector of max allowed freqs -/// @param[in,out] io_scoreboard scoreboard of MCA targets supporting each frequency -/// @return FAPI2_RC_SUCCESS iff ok -/// @note This helper allows us to use the attributes for the main path but -/// have a path for testing -/// -fapi2::ReturnCode limit_freq_by_mrw(const fapi2::Target<TARGET_TYPE_MCBIST>& i_target, - const std::vector<uint32_t>& i_max_mrw_freqs, - freq_scoreboard& io_scoreboard) -{ - // Indexes into the ATTR_MAX_ALLOWED_DIMM_FREQ arrary. e.g., [0][0] is 1R 1 drop - constexpr size_t l_indexes[MAX_DIMM_PER_PORT][MAX_PRIMARY_RANKS_PER_PORT] = - { - {0, 1, 0xFF, 2}, - {3, 4, 0xFF, 0xFF} - }; - - // This is the number of elements in the max_allowed_dimm_freq attribute, not the frequencies of - // the system. - FAPI_ASSERT( i_max_mrw_freqs.size() == NUM_MAX_FREQS, - fapi2::MSS_MAX_FREQ_ATTR_SIZE_CHANGED() - .set_ACTUAL_SIZE(i_max_mrw_freqs.size()) - .set_SUPPOSED_SIZE(NUM_MAX_FREQS) - .set_MCA_TARGET(i_target), - "%s Incorrect number of max frequencies in attribute for (%d)", - mss::c_str(i_target), - i_max_mrw_freqs.size()); - - FAPI_INF("attribute supported max allowed dimm freqs %d %d %d %d %d for %s", - i_max_mrw_freqs[0], i_max_mrw_freqs[1], i_max_mrw_freqs[2], i_max_mrw_freqs[3], i_max_mrw_freqs[4], - mss::c_str(i_target)); - - for( const auto& p : mss::find_targets<fapi2::TARGET_TYPE_MCA>(i_target) ) - { - const auto l_port_pos = mss::relative_pos<fapi2::TARGET_TYPE_MCBIST>(p); - const auto l_dimms = mss::find_targets<TARGET_TYPE_DIMM>(p); - const uint64_t l_dimms_on_port = l_dimms.size(); - - // Holds the max freq allowed for this port. This is the minimum of maximum - // frequencies allowed by the DIMM. So, we start way off the charts so std::min can do the lifting for us. - uint32_t l_mca_max_freq = ~(0); - - FAPI_ASSERT( (l_dimms_on_port <= MAX_DIMM_PER_PORT), - fapi2::MSS_TOO_MANY_DIMMS_ON_PORT() - .set_DIMM_COUNT(l_dimms_on_port) - .set_MCA_TARGET(p), - "Seeing %d DIMM on port %s", - l_dimms_on_port, - mss::c_str(p)); - - // Find the max supported frequency for this port - for (const auto& d : l_dimms) - { - uint8_t l_num_master_ranks = 0; - size_t l_index = 0xFF; - - FAPI_TRY( mss::eff_num_master_ranks_per_dimm(d, l_num_master_ranks) ); - - // Just a quick check but we're in deep yogurt if this triggers - FAPI_ASSERT( (l_num_master_ranks <= MAX_PRIMARY_RANKS_PER_PORT), - fapi2::MSS_TOO_MANY_PRIMARY_RANKS_ON_DIMM() - .set_RANK_COUNT(l_num_master_ranks) - .set_DIMM_TARGET(d), - "seeing %d primary ranks on DIMM %s", - l_dimms_on_port, - mss::c_str(d)); - - l_index = l_indexes[l_dimms_on_port - 1][l_num_master_ranks - 1]; - - FAPI_ASSERT( (l_index < NUM_MAX_FREQS), - fapi2::MSS_FREQ_INDEX_TOO_LARGE() - .set_INDEX(l_index) - .set_NUM_MAX_FREQS(NUM_MAX_FREQS), - "seeing %d index for %d DIMM and %d ranks on DIMM %s", - l_index, - l_dimms_on_port, - l_num_master_ranks, - mss::c_str(d)); - - FAPI_INF("%s rank config %d drop %d yields max freq attribute index of %d (%d)", - mss::c_str(d), l_num_master_ranks, l_dimms_on_port, - l_indexes[l_dimms_on_port - 1][l_num_master_ranks - 1], - i_max_mrw_freqs[l_index] ); - - l_mca_max_freq = std::min(l_mca_max_freq, i_max_mrw_freqs[l_index]); - }// dimm - - // Remove any frequencies bigger than this port's max from the scoreboard - io_scoreboard.remove_freqs_above_limit(l_port_pos, l_mca_max_freq); - - FAPI_INF("%s after processing MRW, max freq is %d", mss::c_str(p), l_mca_max_freq); - }// mca - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Update supported frequency scoreboard according to VPD limits -/// @param[in] i_target MCBIST target for which to get the DIMM configs -/// @param[in] i_hw_freqs vector of hardware supported freqs -- from VPD -/// @param[in,out] io_scoreboard scoreboard of MCA targets supporting each frequency -/// @return FAPI2_RC_SUCCESS iff ok -/// @note This helper allows us to use the attributes for the main path but -/// have a path for testing -/// -fapi2::ReturnCode limit_freq_by_vpd(const fapi2::Target<TARGET_TYPE_MCBIST>& i_target, - const std::vector<std::vector<uint32_t>>& i_hw_freqs, - freq_scoreboard& io_scoreboard) -{ - FAPI_ASSERT(i_hw_freqs.size() == PORTS_PER_MCBIST, - fapi2::MSS_INVALID_VPD_FREQ_LIST_PASSED() - .set_SIZE(i_hw_freqs.size()) - .set_EXPECTED(PORTS_PER_MCBIST), - "Wrong size VPD frequency vector passed to limit_freq_by_vpd (got %d, expected %d)", - i_hw_freqs.size(), PORTS_PER_MCBIST); - - for( const auto& p : mss::find_targets<fapi2::TARGET_TYPE_MCA>(i_target) ) - { - const auto l_port_pos = mss::relative_pos<fapi2::TARGET_TYPE_MCBIST>(p); - const auto& l_port_freqs = i_hw_freqs[l_port_pos]; - - // This is the list of supported frequencies for VPD - FAPI_ASSERT( !l_port_freqs.empty(), - fapi2::MSS_EMPTY_VECTOR(). - set_FUNCTION(LIMIT_FREQ_BY_VPD). - set_TARGET(p), - "Supported system freqs from VPD are empty for %s", - mss::c_str(p)); - - for( const auto& freq : l_port_freqs ) - { - FAPI_DBG("VPD supported freqs %d for %s", freq, mss::c_str(p) ); - } - - // Remove any frequencies that aren't in this port's list from the scoreboard - io_scoreboard.remove_freqs_not_on_list(l_port_pos, l_port_freqs); - - uint32_t l_max_freq = 0; - FAPI_TRY( io_scoreboard.max_supported_freq(l_port_pos, l_max_freq) ); - FAPI_INF("%s after processing VPD, max freq is %d", mss::c_str(p), l_max_freq); - }// mca - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Update supported frequency scoreboard according to SPD limits -/// @param[in] i_target MCBIST target for which to get the DIMM configs -/// @param[in] i_hw_freqs vector of hardware supported freqs -- from SPD -/// @param[in,out] io_scoreboard scoreboard of MCA targets supporting each frequency -/// @return FAPI2_RC_SUCCESS iff ok -/// @note This helper allows us to use the attributes for the main path but -/// have a path for testing -/// -fapi2::ReturnCode limit_freq_by_spd(const fapi2::Target<TARGET_TYPE_MCBIST>& i_target, - const std::vector<uint32_t>& i_hw_freqs, - freq_scoreboard& io_scoreboard) -{ - for( const auto& p : mss::find_targets<fapi2::TARGET_TYPE_MCA>(i_target) ) - { - const auto l_port_pos = mss::relative_pos<fapi2::TARGET_TYPE_MCBIST>(p); - - // Remove any frequencies that aren't in this port's list from the scoreboard - io_scoreboard.remove_freqs_above_limit(l_port_pos, i_hw_freqs); - - uint32_t l_max_freq = 0; - FAPI_TRY( io_scoreboard.max_supported_freq(l_port_pos, l_max_freq) ); - FAPI_INF("%s after processing SPD, max freq is %d", mss::c_str(p), l_max_freq); - }// mca - - return fapi2::FAPI2_RC_SUCCESS; - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Remove frequencies above a limit from the scoreboard -/// @param[in] i_port_pos position index of port within parent MCBIST -/// @param[in] i_freq_limit upper limit for frequency -/// @return FAPI2_RC_SUCCESS if successful -/// -fapi2::ReturnCode freq_scoreboard::remove_freqs_above_limit(const uint64_t i_port_pos, - const uint32_t i_freq_limit) -{ - FAPI_ASSERT(i_port_pos < PORTS_PER_MCBIST, - fapi2::MSS_INVALID_PORT_INDEX_PASSED() - .set_INDEX(i_port_pos) - .set_FUNCTION(ffdc_function_codes::FREQ_SCOREBOARD_REMOVE_FREQS_ABOVE_LIMIT), - "Invalid port index passed to remove_freqs_above_limit (%d)", - i_port_pos); - - { - auto& l_port_supported_freqs = iv_freq_mca_supported[i_port_pos]; - - // Can't do a ranged for loop here because we need the index to get the frequency out of NIMBUS_SUPPORTED_FREQS - for ( size_t l_index = 0; l_index < l_port_supported_freqs.size(); ++l_index ) - { - const auto l_scoreboard_freq = NIMBUS_SUPPORTED_FREQS[l_index]; - - if ( l_scoreboard_freq > i_freq_limit ) - { - FAPI_INF("Removing freq %d on port %d since it's above the limit %d", l_scoreboard_freq, i_port_pos, i_freq_limit); - l_port_supported_freqs[l_index] = false; - } - } - } - - return fapi2::FAPI2_RC_SUCCESS; - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Remove frequencies above a limit from the scoreboard -/// @param[in] i_port_pos position index of port within parent MCBIST -/// @param[in] i_freq_limits reference to vector of upper limits for frequency per port -/// @return FAPI2_RC_SUCCESS if successful -/// -fapi2::ReturnCode freq_scoreboard::remove_freqs_above_limit(const uint64_t i_port_pos, - const std::vector<uint32_t> i_freq_limits) -{ - FAPI_ASSERT(i_port_pos < PORTS_PER_MCBIST, - fapi2::MSS_INVALID_PORT_INDEX_PASSED() - .set_INDEX(i_port_pos) - .set_FUNCTION(ffdc_function_codes::FREQ_SCOREBOARD_REMOVE_FREQS_ABOVE_LIMIT_VECTOR), - "Invalid port index passed to remove_freqs_above_limit (%d)", - i_port_pos); - - FAPI_ASSERT(i_freq_limits.size() == PORTS_PER_MCBIST, - fapi2::MSS_INVALID_FREQ_LIST_PASSED() - .set_SIZE(i_freq_limits.size()) - .set_EXPECTED(PORTS_PER_MCBIST), - "Invalid frequency list passed to remove_freqs_above_limit (size should be %d but got %d)", - PORTS_PER_MCBIST, i_freq_limits.size()); - - { - const auto l_freq_limit = i_freq_limits[i_port_pos]; - FAPI_TRY( this->remove_freqs_above_limit(i_port_pos, l_freq_limit) ); - } - - return fapi2::FAPI2_RC_SUCCESS; - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Remove frequencies not on a given list from the scoreboard -/// @param[in] i_port_pos position index of port within parent MCBIST -/// @param[in] i_freq_list vector of supported frequencies -/// @return FAPI2_RC_SUCCESS if successful -/// -fapi2::ReturnCode freq_scoreboard::remove_freqs_not_on_list(const uint64_t i_port_pos, - const std::vector<uint32_t>& i_freq_list) -{ - FAPI_ASSERT(i_port_pos < PORTS_PER_MCBIST, - fapi2::MSS_INVALID_PORT_INDEX_PASSED() - .set_INDEX(i_port_pos) - .set_FUNCTION(ffdc_function_codes::FREQ_SCOREBOARD_REMOVE_FREQS_NOT_ON_LIST), - "Invalid port index passed to remove_freqs_not_on_list (%d)", - i_port_pos); - - for ( size_t l_index = 0; l_index < NIMBUS_SUPPORTED_FREQS.size(); ++l_index ) - { - const auto l_it = std::find(i_freq_list.begin(), i_freq_list.end(), NIMBUS_SUPPORTED_FREQS[l_index]); - - if (l_it == i_freq_list.end()) - { - FAPI_INF("Removing freq %d on port %d since it's not supported", NIMBUS_SUPPORTED_FREQS[l_index], i_port_pos); - iv_freq_mca_supported[i_port_pos][l_index] = false; - } - } - - return fapi2::FAPI2_RC_SUCCESS; - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Return the maximum supported frequency for a given port -/// @param[in] i_port_pos position index of port within parent MCBIST -/// @param[out] o_freq max supported frequency -/// @return FAPI2_RC_SUCCESS if successful -/// -fapi2::ReturnCode freq_scoreboard::max_supported_freq(const uint64_t i_port_pos, - uint32_t& o_freq) const -{ - FAPI_ASSERT(i_port_pos < PORTS_PER_MCBIST, - fapi2::MSS_INVALID_PORT_INDEX_PASSED() - .set_INDEX(i_port_pos) - .set_FUNCTION(ffdc_function_codes::FREQ_SCOREBOARD_MAX_SUPPORTED_FREQ), - "Invalid port index passed to max_supported_freq (%d)", - i_port_pos); - - { - std::vector<uint32_t> l_supported_freqs; - FAPI_TRY( this->supported_freqs(i_port_pos, l_supported_freqs) ); - - o_freq = l_supported_freqs.empty() ? 0 : l_supported_freqs.back(); - } - - return fapi2::FAPI2_RC_SUCCESS; - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Return a list of supported frequencies for a given port -/// @param[in] i_port_pos position index of port within parent MCBIST -/// @param[out] o_freq vector of supported frequencies -/// @return FAPI2_RC_SUCCESS if successful -/// -fapi2::ReturnCode freq_scoreboard::supported_freqs(const uint64_t i_port_pos, - std::vector<uint32_t>& o_freqs) const -{ - FAPI_ASSERT(i_port_pos < PORTS_PER_MCBIST, - fapi2::MSS_INVALID_PORT_INDEX_PASSED() - .set_INDEX(i_port_pos) - .set_FUNCTION(ffdc_function_codes::FREQ_SCOREBOARD_SUPPORTED_FREQS), - "Invalid port index passed to supported_freqs (%d)", - i_port_pos); - - { - o_freqs.clear(); - auto& l_port_supported_freqs = iv_freq_mca_supported[i_port_pos]; - - for ( size_t l_index = 0; l_index < NIMBUS_SUPPORTED_FREQS.size(); ++l_index ) - { - if (l_port_supported_freqs[l_index]) - { - o_freqs.push_back(NIMBUS_SUPPORTED_FREQS[l_index]); - } - } - } - - return fapi2::FAPI2_RC_SUCCESS; - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Resolve frequency scoreboard by deconfiguring any non-conforming ports -/// and return a list of the supported frequencies -/// @param[in] i_target MCBIST target -/// @param[in] i_req_sync_mode bool whether or not we're forced into sync mode -/// @param[in] i_vpd_supported_freqs vector of hardware supported freqs -- from VPD -/// @param[out] o_deconfigured vector of port positions that were deconfigured by this function -/// @param[out] o_freqs vector of frequencies supported by all ports -/// @return FAPI2_RC_SUCCESS if successful -/// -fapi2::ReturnCode freq_scoreboard::resolve(const fapi2::Target<fapi2::TARGET_TYPE_MCBIST>& i_target, - const bool i_req_sync_mode, - const std::vector<std::vector<uint32_t>>& i_vpd_supported_freqs, - std::vector<uint8_t>& o_deconfigured, - std::vector<uint32_t>& o_freqs) -{ - // This vector will hold the number of ports that support each frequency in NIMBUS_SUPPORTED_FREQS - std::vector<uint64_t> l_support_counts(NIMBUS_SUPPORTED_FREQS.size(), 0); - - o_freqs.clear(); - FAPI_INF("%s Attribute required sync mode %d", mss::c_str(i_target), i_req_sync_mode); - - const auto l_mcas = mss::find_targets<fapi2::TARGET_TYPE_MCA>(i_target); - const auto l_port_count = l_mcas.size(); - - // empty_port_count is the number of MCA that are deconfigured - // We use it later to make sure our common freq is supported by at least one configured port - const auto l_empty_port_count = PORTS_PER_MCBIST - l_port_count; - - // Get a count of how many ports support each frequency - for ( size_t l_index = 0; l_index < NIMBUS_SUPPORTED_FREQS.size(); ++l_index ) - { - size_t l_pos = 0; - - for ( const auto& l_supported : iv_freq_mca_supported ) - { - if (l_supported[l_index]) - { - FAPI_INF("%s Frequency %d is supported by port%d", mss::c_str(i_target), NIMBUS_SUPPORTED_FREQS[l_index], l_pos); - // Add this freq if we're not in sync mode, or, if we are, add it if it matches a nest freq - - if( i_req_sync_mode && !is_nest_freq_valid(NIMBUS_SUPPORTED_FREQS[l_index]) ) - { - FAPI_INF("%s Frequency %d is not supported by the nest logic", mss::c_str(i_target), NIMBUS_SUPPORTED_FREQS[l_index]); - ++l_pos; - continue; - } - - ++l_support_counts[l_index]; - } - - // Add any frequencies supported by all configured ports to our output list - // Note that deconfigured ports will support all frequencies due to the way the scoreboard is built - if (l_support_counts[l_index] == PORTS_PER_MCBIST) - { - FAPI_INF("%s Frequency %d is supported by all ports", mss::c_str(i_target), NIMBUS_SUPPORTED_FREQS[l_index]); - o_freqs.push_back(NIMBUS_SUPPORTED_FREQS[l_index]); - } - - ++l_pos; - } - } - - // If we have at least one common frequency, we're done - if (!o_freqs.empty()) - { - return fapi2::FAPI2_RC_SUCCESS; - } - - // If we made it here, that means we don't have a common supported freq for all ports - // So let's deconfigure the least number of ports to get a common freq - - // Find the last instance of the most ports that support a given frequency - // That way we get the highest frequency supported by the most ports - // Note: this may be inefficient, but this is a small vector and HB doesn't support reverse iterators - uint64_t l_common_ports = 0; - size_t l_best_freq_index = 0; - - for ( size_t l_index = 0; l_index < l_support_counts.size(); ++l_index ) - { - if (l_support_counts[l_index] >= l_common_ports) - { - l_common_ports = l_support_counts[l_index]; - l_best_freq_index = l_index; - } - } - - FAPI_INF("%s Max ports supporting a common frequency is %d", mss::c_str(i_target), l_common_ports); - FAPI_INF("%s Fastest common frequency is %d", mss::c_str(i_target), NIMBUS_SUPPORTED_FREQS[l_best_freq_index]); - - // Assert if we don't have any frequencies supported by at least one configured port - // Note: we know max_allowed_dimm_freq is size 5 because we checked it in limit_freq_by_mrw - std::vector<uint32_t> l_max_mrw_freqs(NUM_MAX_FREQS, 0); - FAPI_TRY( mss::max_allowed_dimm_freq(l_max_mrw_freqs.data()) ); - FAPI_ASSERT(l_common_ports > l_empty_port_count, - fapi2::MSS_NO_SUPPORTED_FREQ() - .set_REQUIRED_SYNC_MODE(i_req_sync_mode) - .set_MCBIST_TARGET(i_target) - .set_NUM_PORTS(l_port_count) - .set_MRW_MAX_FREQ_0(l_max_mrw_freqs[0]) - .set_MRW_MAX_FREQ_1(l_max_mrw_freqs[1]) - .set_MRW_MAX_FREQ_2(l_max_mrw_freqs[2]) - .set_MRW_MAX_FREQ_3(l_max_mrw_freqs[3]) - .set_MRW_MAX_FREQ_4(l_max_mrw_freqs[4]), - "%s didn't find a frequency that was supported on any ports", mss::c_str(i_target)); - - // Now find and deconfigure all ports that don't support our selected frequency - o_deconfigured.clear(); - - for ( size_t l_pos = 0; l_pos < PORTS_PER_MCBIST; ++l_pos ) - { - // Find the MCA with this position - const auto l_it_mca = std::find_if(l_mcas.begin(), - l_mcas.end(), - [l_pos]( const fapi2::Target<fapi2::TARGET_TYPE_MCA>& i_rhs) -> bool - { - return (mss::relative_pos<fapi2::TARGET_TYPE_MCBIST>(i_rhs) != l_pos); - }); - - // If we didn't find an MCA for a given position, there wasn't one configured there - if (l_it_mca == l_mcas.end()) - { - continue; - } - - // and call it out if it doesn't support the selected freq - const auto& p = *l_it_mca; - FAPI_INF("Checking if port %d (%s) supports common frequency", l_pos, mss::c_str(p)); - - if (!iv_freq_mca_supported[l_pos][l_best_freq_index]) - { - FAPI_INF("Port %d (%s) does not support the common frequency so will be deconfigured", l_pos, mss::c_str(p)); - auto& l_port_supported_freqs = iv_freq_mca_supported[l_pos]; - - o_deconfigured.push_back(l_pos); - FAPI_ASSERT_NOEXIT( false, - fapi2::MSS_PORT_DOES_NOT_SUPPORT_MAJORITY_FREQ() - .set_MCBIST_TARGET(i_target) - .set_MCA_TARGET(p) - .set_FREQUENCY(NIMBUS_SUPPORTED_FREQS[l_best_freq_index]), - "%s does not support the majority frequency (%d) so will be deconfigured", - mss::c_str(p), NIMBUS_SUPPORTED_FREQS[l_best_freq_index] ); - - // Now mark all frequencies as supported by that port since it was deconfigured - for ( size_t l_index = 0; l_index < l_port_supported_freqs.size(); ++l_index ) - { - l_port_supported_freqs[l_index] = true; - } - } - } - - // Now find all the frequencies supported by the ports that are left over - FAPI_TRY(this->resolve(i_target, i_req_sync_mode, i_vpd_supported_freqs, o_deconfigured, o_freqs)); - -#ifndef __HOSTBOOT_MODULE - - // Cronus doesn't deconfigure, so let's bail out if we didn't find a common frequency - if (!o_deconfigured.empty()) - { - std::vector<uint32_t> l_port_vpd_max_freq; - - { - // Get the max freq supported on each port - for ( const auto& l_port_supported_freqs : i_vpd_supported_freqs ) - { - l_port_vpd_max_freq.push_back(l_port_supported_freqs.back()); - } - - FAPI_ASSERT(false, - fapi2::MSS_MRW_FREQ_MAX_FREQ_EMPTY_SET() - .set_MSS_VPD_FREQ_0(l_port_vpd_max_freq[0]) - .set_MSS_VPD_FREQ_1(l_port_vpd_max_freq[1]) - .set_MSS_VPD_FREQ_2(l_port_vpd_max_freq[2]) - .set_MSS_VPD_FREQ_3(l_port_vpd_max_freq[3]) - .set_MSS_MAX_FREQ_0(l_max_mrw_freqs[0]) - .set_MSS_MAX_FREQ_1(l_max_mrw_freqs[1]) - .set_MSS_MAX_FREQ_2(l_max_mrw_freqs[2]) - .set_MSS_MAX_FREQ_3(l_max_mrw_freqs[3]) - .set_MSS_MAX_FREQ_4(l_max_mrw_freqs[4]) - .set_MSS_NEST_FREQ_0(fapi2::ENUM_ATTR_FREQ_PB_MHZ_1600) - .set_MSS_NEST_FREQ_1(fapi2::ENUM_ATTR_FREQ_PB_MHZ_1866) - .set_MSS_NEST_FREQ_2(fapi2::ENUM_ATTR_FREQ_PB_MHZ_2000) - .set_MSS_NEST_FREQ_3(fapi2::ENUM_ATTR_FREQ_PB_MHZ_2133) - .set_MSS_NEST_FREQ_4(fapi2::ENUM_ATTR_FREQ_PB_MHZ_2400) - .set_REQUIRED_SYNC_MODE(i_req_sync_mode) - .set_MCBIST_TARGET(i_target), - "%s didn't find a common frequency for all ports", mss::c_str(i_target)); - } - } - -#endif - - return fapi2::FAPI2_RC_SUCCESS; - -fapi_try_exit: - return fapi2::current_err; -} - }// mss diff --git a/src/import/chips/p9/procedures/hwp/memory/lib/freq/sync.H b/src/import/chips/p9/procedures/hwp/memory/lib/freq/sync.H index 4e46f0b1e..7a780c310 100644 --- a/src/import/chips/p9/procedures/hwp/memory/lib/freq/sync.H +++ b/src/import/chips/p9/procedures/hwp/memory/lib/freq/sync.H @@ -40,23 +40,21 @@ #include <fapi2.H> #include <lib/shared/mss_const.H> +#include <generic/memory/lib/utils/freq/mss_freq_scoreboard.H> +#include <generic/memory/lib/utils/c_str.H> namespace mss { -enum class speed_equality : uint8_t -{ - NOT_EQUAL_DIMM_SPEEDS = 0, ///< denotes all DIMMs don't have the same speed - EQUAL_DIMM_SPEEDS = 1, ///< denotes all DIMMs have the same speed -}; - -// DDR4 speed NIMBUS supports -static const std::vector<uint32_t> NIMBUS_SUPPORTED_FREQS = +// List of the nest frequencies for nimbus +// Note: these need to be sorted so binary search works +static const std::vector<uint64_t> NIMBUS_NEST_FREQS = { - fapi2::ENUM_ATTR_MSS_FREQ_MT1866, - fapi2::ENUM_ATTR_MSS_FREQ_MT2133, - fapi2::ENUM_ATTR_MSS_FREQ_MT2400, - fapi2::ENUM_ATTR_MSS_FREQ_MT2666, + fapi2::ENUM_ATTR_FREQ_PB_MHZ_1600, + fapi2::ENUM_ATTR_FREQ_PB_MHZ_1866, + fapi2::ENUM_ATTR_FREQ_PB_MHZ_2000, + fapi2::ENUM_ATTR_FREQ_PB_MHZ_2133, + fapi2::ENUM_ATTR_FREQ_PB_MHZ_2400 }; /// @@ -66,102 +64,13 @@ static const std::vector<uint32_t> NIMBUS_SUPPORTED_FREQS = /// inline bool is_nest_freq_valid (const uint64_t i_proposed_freq) { - std::vector<uint64_t> l_nest_freqs_supported = { fapi2::ENUM_ATTR_FREQ_PB_MHZ_1600, - fapi2::ENUM_ATTR_FREQ_PB_MHZ_1866, - fapi2::ENUM_ATTR_FREQ_PB_MHZ_2000, - fapi2::ENUM_ATTR_FREQ_PB_MHZ_2133, - fapi2::ENUM_ATTR_FREQ_PB_MHZ_2400 - }; - - std::sort(l_nest_freqs_supported.begin(), l_nest_freqs_supported.end()); - return ( std::binary_search(l_nest_freqs_supported.begin(), l_nest_freqs_supported.end(), i_proposed_freq) ); + return ( std::binary_search(NIMBUS_NEST_FREQS.begin(), NIMBUS_NEST_FREQS.end(), i_proposed_freq) ); } -/// -/// @class freq_scoreboard -/// @brief class that encapsulates MCA supported frequencies -/// -class freq_scoreboard +enum class speed_equality : uint8_t { - public: - /// - /// @brief Create a new frequency scoreboard - /// - freq_scoreboard() - { - iv_freq_mca_supported = std::vector<std::vector<bool>>(PORTS_PER_MCBIST, - std::vector<bool>(NIMBUS_SUPPORTED_FREQS.size(), true)); - } - - /// - /// @brief default destructor - /// - ~freq_scoreboard() = default; - - /// - /// @brief Remove frequencies above a limit from the scoreboard - /// @param[in] i_port_pos position index of port within parent MCBIST - /// @param[in] i_freq_limit upper limit for frequency - /// @return FAPI2_RC_SUCCESS if successful - /// - fapi2::ReturnCode remove_freqs_above_limit(const uint64_t i_port_pos, - const uint32_t i_freq_limit); - - /// - /// @brief Remove frequencies above a limit from the scoreboard - /// @param[in] i_port_pos position index of port within parent MCBIST - /// @param[in] i_freq_limits reference to vector of upper limits for frequency per port - /// @return FAPI2_RC_SUCCESS if successful - /// - fapi2::ReturnCode remove_freqs_above_limit(const uint64_t i_port_pos, - const std::vector<uint32_t> i_freq_limits); - - /// - /// @brief Remove frequencies not on a given list from the scoreboard - /// @param[in] i_port_pos position index of port within parent MCBIST - /// @param[in] i_freq_list vector of supported frequencies - /// @return FAPI2_RC_SUCCESS if successful - /// - fapi2::ReturnCode remove_freqs_not_on_list(const uint64_t i_port_pos, - const std::vector<uint32_t>& i_freq_list); - - /// - /// @brief Return the maximum supported frequency for a given port - /// @param[in] i_port_pos position index of port within parent MCBIST - /// @param[out] o_freq max supported frequency - /// @return FAPI2_RC_SUCCESS if successful - /// - fapi2::ReturnCode max_supported_freq(const uint64_t i_port_pos, - uint32_t& o_freq) const; - - /// - /// @brief Return a list of supported frequencies for a given port - /// @param[in] i_port_pos position index of port within parent MCBIST - /// @param[out] o_freq vector of supported frequencies - /// @return FAPI2_RC_SUCCESS if successful - /// - fapi2::ReturnCode supported_freqs(const uint64_t i_port_pos, - std::vector<uint32_t>& o_freqs) const; - - /// - /// @brief Resolve frequency scoreboard by deconfiguring any non-conforming ports - /// and return a list of the supported frequencies - /// @param[in] i_target MCBIST target - /// @param[in] i_req_sync_mode bool whether or not we're forced into sync mode - /// @param[in] i_vpd_supported_freqs vector of hardware supported freqs -- from VPD - /// @param[out] o_deconfigured vector of port positions that were deconfigured by this function - /// @param[out] o_freqs vector of frequencies supported by all ports - /// @return FAPI2_RC_SUCCESS if successful - /// - fapi2::ReturnCode resolve(const fapi2::Target<fapi2::TARGET_TYPE_MCBIST>& i_target, - const bool i_req_sync_mode, - const std::vector<std::vector<uint32_t>>& i_vpd_supported_freqs, - std::vector<uint8_t>& o_deconfigured, - std::vector<uint32_t>& o_freqs); - - private: - std::vector<std::vector<bool>> iv_freq_mca_supported; - + NOT_EQUAL_DIMM_SPEEDS = 0, ///< denotes all DIMMs don't have the same speed + EQUAL_DIMM_SPEEDS = 1, ///< denotes all DIMMs have the same speed }; /// @@ -204,76 +113,36 @@ fapi2::ReturnCode select_sync_mode(const std::map< fapi2::Target<fapi2::TARGET_T uint64_t& o_selected_freq); /// -/// @brief Create a vector of support freq based on VPD config -/// @param[in] i_target MCBIST target for which to get the DIMM configs -/// @param[out] reference to a 2 dimensional std::vector of supported VPD frequencies for each MCA -/// @return FAPI2_RC_SUCCESS iff ok -/// -fapi2::ReturnCode vpd_supported_freqs( const fapi2::Target<fapi2::TARGET_TYPE_MCBIST>& i_target, - std::vector<std::vector<uint32_t>>& o_vpd_supported_freqs); - -/// -/// @brief Retrieves max frequency each port supports due to DIMM SPD -/// @param[in] i_target the MCBIST target -/// @param[out] o_supported_freqs reference to vector of max SPD supported freq for each port -/// @return FAPI2_RC_SUCCESS iff okay -/// -fapi2::ReturnCode spd_supported_freq(const fapi2::Target<fapi2::TARGET_TYPE_MCBIST>& i_target, - std::vector<uint32_t>& o_supported_freqs); - -/// -/// @brief Create and sort a vector of supported MT/s (freq) -/// @param[in] i_target MCA target for which to get the DIMM configs -/// @param[out] o_freqs reference to a std::vector to put the sorted vector -/// @return FAPI2_RC_SUCCESS iff ok -/// @note Taken from VPD supported freqs. The result is sorted so such that the min -/// supported freq is std::vector<>.begin and the max is std::vector<>.end - 1. You can -/// search the resulting vector for valid frequencies as it is sorted. -/// -fapi2::ReturnCode supported_freqs(const fapi2::Target<fapi2::TARGET_TYPE_MCBIST>& i_target, - std::vector<uint32_t>& o_freqs); - -/// -/// @brief Update supported frequency scoreboard according to MRW/config limits -/// @param[in] i_target MCBIST target for which to get the DIMM configs -/// @param[in] i_max_mrw_freqs vector of max allowed freqs -/// @param[in,out] io_scoreboard scoreboard of MCA targets supporting each frequency -/// @return FAPI2_RC_SUCCESS iff ok -/// @note the attributes which drive this are read-only so they're hard to change when -/// testing. So this helper allows us to use the attributes for the main path but -/// have a path for testing -/// -fapi2::ReturnCode limit_freq_by_mrw(const fapi2::Target<fapi2::TARGET_TYPE_MCBIST>& i_target, - const std::vector<uint32_t>& i_max_mrw_freqs, - freq_scoreboard& io_scoreboard); - -/// -/// @brief Update supported frequency scoreboard according to VPD limits -/// @param[in] i_target MCBIST target for which to get the DIMM configs -/// @param[in] i_hw_freqs vector of hardware supported freqs -- from VPD -/// @param[in,out] io_scoreboard scoreboard of MCA targets supporting each frequency -/// @return FAPI2_RC_SUCCESS iff ok -/// @note the attributes which drive this are read-only so they're hard to change when -/// testing. So this helper allows us to use the attributes for the main path but -/// have a path for testing -/// -fapi2::ReturnCode limit_freq_by_vpd(const fapi2::Target<fapi2::TARGET_TYPE_MCBIST>& i_target, - const std::vector<std::vector<uint32_t>>& i_hw_freqs, - freq_scoreboard& io_scoreboard); - -/// -/// @brief Update supported frequency scoreboard according to SPD limits -/// @param[in] i_target MCBIST target for which to get the DIMM configs -/// @param[in] i_hw_freqs vector of hardware supported freqs -- from SPD -/// @param[in,out] io_scoreboard scoreboard of MCA targets supporting each frequency +/// @brief Update supported frequency scoreboard according to whether the processor is in sync mode or not +/// @param[in] i_target processor frequency domain +/// @param[in,out] io_scoreboard scoreboard of port targets supporting each frequency /// @return FAPI2_RC_SUCCESS iff ok /// @note the attributes which drive this are read-only so they're hard to change when /// testing. So this helper allows us to use the attributes for the main path but /// have a path for testing /// -fapi2::ReturnCode limit_freq_by_spd(const fapi2::Target<fapi2::TARGET_TYPE_MCBIST>& i_target, - const std::vector<uint32_t>& i_hw_freqs, - freq_scoreboard& io_scoreboard); +inline fapi2::ReturnCode limit_freq_by_processor(const fapi2::Target<fapi2::TARGET_TYPE_MCBIST>& i_target, + const bool i_sync_mode, + freq_scoreboard& io_scoreboard) +{ + // If we're not in sync mode, just exit + if(!i_sync_mode) + { + FAPI_INF("%s is not in sync mode, skipping the sync mode check", mss::c_str(i_target)); + return fapi2::FAPI2_RC_SUCCESS; + } + + // Loop through all potential ports + for(uint64_t l_port_pos = 0; l_port_pos < PORTS_PER_MCBIST; ++l_port_pos) + { + FAPI_TRY(io_scoreboard.remove_freqs_not_on_list(l_port_pos, NIMBUS_NEST_FREQS)); + } + + return fapi2::FAPI2_RC_SUCCESS; + +fapi_try_exit: + return fapi2::current_err; +} }// mss diff --git a/src/import/chips/p9/procedures/hwp/memory/lib/shared/mss_const.H b/src/import/chips/p9/procedures/hwp/memory/lib/shared/mss_const.H index 04c84f68c..8238a888c 100644 --- a/src/import/chips/p9/procedures/hwp/memory/lib/shared/mss_const.H +++ b/src/import/chips/p9/procedures/hwp/memory/lib/shared/mss_const.H @@ -69,7 +69,6 @@ enum sizes MAX_DRAMS_X4 = MAX_DQ_BITS / BITS_PER_NIBBLE, ///< For x4's there are 18 DRAM for 72 bits NUM_MRW_FREQS = 4, ///< Used for ATTR_MSS_MRW_SUPPORTED_FREQ - NUM_MAX_FREQS = 5, ///< Used for ATTR_MAX_ALLOWED_DIMM_FREQ MARK_STORE_COUNT = 8, ///< Elements in a VPD mark/store array @@ -195,14 +194,6 @@ enum ffdc_function_codes // WR VREF functions DRAM_TO_RP_REG = 101, - // mss_freq functions - FREQ_SCOREBOARD_REMOVE_FREQS_ABOVE_LIMIT = 110, - FREQ_SCOREBOARD_REMOVE_FREQS_ABOVE_LIMIT_VECTOR = 111, - FREQ_SCOREBOARD_REMOVE_FREQS_NOT_ON_LIST = 112, - FREQ_SCOREBOARD_MAX_SUPPORTED_FREQ = 113, - FREQ_SCOREBOARD_SUPPORTED_FREQS = 114, - LIMIT_FREQ_BY_VPD = 115, - // eff_dimm.C PRIMARY_STACK_TYPE = 116, }; diff --git a/src/import/chips/p9/procedures/hwp/memory/p9_mss_freq.C b/src/import/chips/p9/procedures/hwp/memory/p9_mss_freq.C index d66924504..34eae3e9b 100644 --- a/src/import/chips/p9/procedures/hwp/memory/p9_mss_freq.C +++ b/src/import/chips/p9/procedures/hwp/memory/p9_mss_freq.C @@ -45,16 +45,8 @@ #include <fapi2.H> // mss lib -#include <generic/memory/lib/spd/spd_facade.H> -#include <generic/memory/lib/utils/freq/cas_latency.H> -#include <lib/freq/sync.H> -#include <lib/workarounds/freq_workarounds.H> -#include <generic/memory/lib/utils/c_str.H> -#include <generic/memory/lib/utils/find.H> #include <generic/memory/lib/utils/count_dimm.H> -#include <generic/memory/lib/utils/index.H> -#include <lib/shared/mss_const.H> -#include <lib/eff_config/attr_setters.H> +#include <generic/memory/lib/utils/freq/gen_mss_freq.H> using fapi2::TARGET_TYPE_MCS; using fapi2::TARGET_TYPE_MCA; @@ -81,11 +73,6 @@ extern "C" // twice for every MC. However, attribute access is cheap so this will suffice for // the time being. const auto l_mcbist = mss::find_target<fapi2::TARGET_TYPE_MCBIST>(i_target); - std::vector< std::vector<uint64_t> > l_min_dimm_freq(mss::MCS_PER_MC, std::vector<uint64_t> (mss::PORTS_PER_MCS, 0) ); - std::vector<uint32_t> l_supported_freqs; - - uint64_t l_mss_freq = 0; - uint32_t l_nest_freq = 0; // If there are no DIMM, we can just get out. if (mss::count_dimm(l_mcbist) == 0) @@ -94,98 +81,7 @@ extern "C" return FAPI2_RC_SUCCESS; } - // We will first set pre-eff_config attributes - for( const auto& d : mss::find_targets<fapi2::TARGET_TYPE_DIMM>(l_mcbist)) - { - std::vector<uint8_t> l_raw_spd; - FAPI_TRY(mss::spd::get_raw_data(d, l_raw_spd)); - - { - fapi2::ReturnCode l_rc(fapi2::FAPI2_RC_SUCCESS); - mss::spd::facade l_spd_decoder(d, l_raw_spd, l_rc); - - FAPI_TRY(l_rc, "Failed to initialize SPD facade for %s", mss::spd::c_str(d)); - FAPI_TRY(mss::set_pre_init_attrs(d, l_spd_decoder), "%s failed to set pre init attrs", mss::c_str(d) ); - } - } - - // Get supported freqs for this MCBIST - FAPI_TRY( mss::supported_freqs(l_mcbist, l_supported_freqs), "%s failed to get supported frequencies", - mss::c_str(i_target) ); - - for (const auto& l_mcs : mss::find_targets<TARGET_TYPE_MCS>(l_mcbist)) - { - const auto l_mcs_index = mss::index(l_mcs); - - std::vector< std::pair< uint64_t, fapi2::Target<fapi2::TARGET_TYPE_MCA>> > l_desired_cas_latency; - - for (const auto& l_mca : mss::find_targets<TARGET_TYPE_MCA>(l_mcs) ) - { - const auto l_mca_index = mss::index(l_mca); - fapi2::ReturnCode l_rc; - - // Get cached decoder - std::vector< mss::spd::facade > l_spd_facades; - FAPI_TRY( get_spd_decoder_list(l_mca, l_spd_facades) ); - - // Instantiation of class that calculates CL algorithm - mss::cas_latency<mss::mc_type::NIMBUS> l_cas_latency( l_mca, l_spd_facades, l_supported_freqs, l_rc ); - - FAPI_TRY( l_rc, "%s. Failed to initialize cas_latency ctor", mss::c_str(l_mca) ); - - if(l_cas_latency.iv_dimm_list_empty) - { - // Cannot fail out for an empty DIMM configuration, so default values are set - FAPI_INF("%s. DIMM list is empty! Setting default values for CAS latency and DIMM speed.", - mss::c_str(l_mca) ); - } - - else - { - // We set this to a non-0 so we avoid divide-by-zero errors in the conversions which - // go from clocks to time (and vice versa.) We have other bugs if there was really - // no MT/s determined and there really is a DIMM installed, so this is ok. - // We pick the maximum frequency supported by the system as the default. - uint64_t l_desired_cl = 0; - - l_min_dimm_freq[l_mcs_index][l_mca_index] = fapi2::ENUM_ATTR_MSS_FREQ_MT2666; - - uint64_t l_tCKmin = 0; - - // Find CAS latency using JEDEC algorithm - FAPI_TRY( l_cas_latency.find_cl(l_desired_cl, l_tCKmin), "%s failed to find a cas latency", mss::c_str(i_target) ); - - FAPI_INF("%s. Result from CL algorithm, CL (nck): %d, tCK (ps): %d", - mss::c_str(l_mca), l_desired_cl, l_tCKmin); - - l_desired_cas_latency.push_back(std::make_pair(l_desired_cl, l_mca) ); - - // Find dimm transfer speed from selected tCK - FAPI_TRY( mss::ps_to_freq(l_tCKmin, l_min_dimm_freq[l_mcs_index][l_mca_index]), - "%s. Failed ps_to_freq()", mss::c_str(l_mca) ); - - FAPI_INF("DIMM speed from selected tCK (ps): %d for %s", - l_min_dimm_freq[l_mcs_index][l_mca_index], - mss::c_str(l_mca)); - - FAPI_INF("%s. Selected DIMM speed from supported speeds: %d", - mss::c_str(l_mca), l_min_dimm_freq[l_mcs_index][l_mca_index]); - - }// end else - } // mca - - FAPI_TRY(mss::set_CL_attr(l_mcs, l_desired_cas_latency), - "%s. Failed set_CL_attr()", mss::c_str(i_target) ); - - } // close for each mcs - - FAPI_TRY(mss::set_freq_attrs(l_mcbist, l_min_dimm_freq), - "%s. Failed set_freq_attrs()", mss::c_str(i_target) ); - - // Check MEM/NEST frequency ratio - FAPI_TRY( mss::freq_pb_mhz(l_nest_freq) ); - FAPI_TRY( mss::freq(l_mcbist, l_mss_freq) ); - FAPI_TRY( mss::workarounds::check_dimm_nest_freq_ratio(l_mcbist, l_mss_freq, l_nest_freq) ); + FAPI_TRY(mss::generate_freq<mss::proc_type::NIMBUS>(l_mcbist)); fapi_try_exit: return fapi2::current_err; diff --git a/src/import/chips/p9/procedures/hwp/memory/p9_mss_freq.H b/src/import/chips/p9/procedures/hwp/memory/p9_mss_freq.H index 3131dc541..f66257ae0 100644 --- a/src/import/chips/p9/procedures/hwp/memory/p9_mss_freq.H +++ b/src/import/chips/p9/procedures/hwp/memory/p9_mss_freq.H @@ -37,123 +37,6 @@ #define MSS_FREQ_H_ #include <utility> #include <fapi2.H> -#include <lib/shared/mss_const.H> -#include <lib/utils/mss_nimbus_conversions.H> - -namespace mss -{ - -/// -/// @brief Sets DRAM CAS latency attributes -/// @param[in] i_target the controller target the cas_latency vector is for -/// @param[in] i_cas_latency vector of pairs. Contains the two final selected CAS latencies -/// @return FAPI2_RC_SUCCESS iff ok -/// -inline fapi2::ReturnCode set_CL_attr(const fapi2::Target<fapi2::TARGET_TYPE_MCS>& i_target, - const std::vector< std::pair< uint64_t, fapi2::Target<fapi2::TARGET_TYPE_MCA>> >& i_cas_latency) -{ - // I wish I could do the reinterpret cast or set the pointer to the vector :( - // But no can do, manual copy pasta - uint8_t l_temp [mss::PORTS_PER_MCS] = {0}; - - for( const auto& cl : i_cas_latency ) - { - // Local variable instead of calling it three times. Hopefully compiler can optimize this better - const auto l_index = mss::index(cl.second); - - if ( l_index >= PORTS_PER_MCS) - { - FAPI_ERR("%s mss::index returned a value greater than PORTS_PER_MCS", mss::c_str(i_target) ); - fapi2::Assert(false); - } - - l_temp[l_index] = cl.first; - - //Check for rounding issues. Going from a uint64_t to a uint8_t - FAPI_ASSERT( l_temp[l_index] == cl.first, - fapi2::MSS_BAD_CL_CAST() - .set_CL(cl.first) - .set_MCA_TARGET(cl.second), - "%s bad cast for cas latency from %d to %d", - mss::c_str(cl.second), - cl.first, - l_temp[l_index]); - - FAPI_INF( "Final Chosen CL: %d for %s", l_temp[l_index], mss::c_str(cl.second)); - } - - // set CAS latency attribute - // casts vector into the type FAPI_ATTR_SET is expecting by deduction - FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_DRAM_CL, - i_target, - l_temp) , - "Failed to set CAS latency attribute"); - -fapi_try_exit: - return fapi2::current_err; -} - -/// -/// @brief Sets frequency attributes -/// @param[in] i_target the controller target -/// @param[in] i_dimm_freq vector of freqs selected dimm freq in MT/s -/// @return FAPI2_RC_SUCCESS iff ok -/// -inline fapi2::ReturnCode set_freq_attrs(const fapi2::Target<fapi2::TARGET_TYPE_MCBIST>& i_target, - const std::vector< std::vector<uint64_t> >& i_dimm_freq) -{ - // Find the minimum (but non-0) freq in the vector. If we see all 0's we'll write a 0. However, - // we shouldn't as the caller should have been dealing with no DIMM before we got here. - uint64_t l_final_freq = UINT64_MAX; - - // DDR4 speed NIMBUS supports - std::vector<uint64_t> l_supported = { 0, - fapi2::ENUM_ATTR_MSS_FREQ_MT1866, - fapi2::ENUM_ATTR_MSS_FREQ_MT2133, - fapi2::ENUM_ATTR_MSS_FREQ_MT2400, - fapi2::ENUM_ATTR_MSS_FREQ_MT2666, - }; - - std::sort( l_supported.begin(), l_supported.end() ); - - for (const auto l_vec : i_dimm_freq) - { - for (const auto l_freq : l_vec) - { - if (l_freq != 0) - { - l_final_freq = std::min(l_final_freq, l_freq); - } - } - } - - // If we saw all 0's, write a 0. - l_final_freq = (l_final_freq == UINT64_MAX) ? 0 : l_final_freq; - - // Shouldn't be getting 0 here. There have to be DIMMs installed for this code to be executed - // The code would have errored out before if a frequency wasn't found. - FAPI_ASSERT( std::binary_search(l_supported.begin(), l_supported.end(), l_final_freq), - fapi2::MSS_BAD_FREQ_CALCULATED() - .set_MSS_FREQ(l_final_freq) - .set_MCBIST_TARGET(i_target) - .set_SUPPORTED_FREQ_0(fapi2::ENUM_ATTR_MSS_FREQ_MT1866) - .set_SUPPORTED_FREQ_1(fapi2::ENUM_ATTR_MSS_FREQ_MT2133) - .set_SUPPORTED_FREQ_2(fapi2::ENUM_ATTR_MSS_FREQ_MT2400) - .set_SUPPORTED_FREQ_3(fapi2::ENUM_ATTR_MSS_FREQ_MT2666), - "%s: Calculated FREQ (%d) isn't supported", - mss::c_str(i_target), - l_final_freq); - - FAPI_INF( "Final Chosen Frequency: %d (%s)", l_final_freq, mss::c_str(i_target) ); - - FAPI_TRY(FAPI_ATTR_SET(fapi2::ATTR_MSS_FREQ, i_target, l_final_freq), - "Failed to set mss freq attribute"); - -fapi_try_exit: - return fapi2::current_err; -} - -}// mss namespace typedef fapi2::ReturnCode (*p9_mss_freq_FP_t) (const fapi2::Target<fapi2::TARGET_TYPE_MCS>&); |