From 2b26420e72477835ffeacb2dab9970266ef07566 Mon Sep 17 00:00:00 2001 From: Louis Stermole Date: Thu, 24 Jan 2019 13:36:56 -0500 Subject: Add p9a_mss_freq procedure Change-Id: I764e1ade2f63cabb7f6e5cf2b39e89811ea432c4 Reviewed-on: http://rchgit01.rchland.ibm.com/gerrit1/70989 Tested-by: FSP CI Jenkins Tested-by: HWSV CI Tested-by: Jenkins Server Reviewed-by: STEPHEN GLANCY Reviewed-by: ANDRE A. MARIN Tested-by: Hostboot CI Reviewed-by: Jennifer A. Stofer Reviewed-on: http://rchgit01.rchland.ibm.com/gerrit1/75567 Reviewed-by: Christian R. Geddes Tested-by: Christian R. Geddes --- .../hwp/memory/lib/freq/axone_freq_traits.H | 70 ++++ .../hwp/memory/lib/freq/axone_mss_freq.C | 427 +++++++++++++++++++++ .../procedures/hwp/memory/lib/freq/axone_sync.C | 250 ++++++++++++ .../procedures/hwp/memory/lib/freq/axone_sync.H | 180 +++++++++ .../p9a/procedures/hwp/memory/p9a_mss_eff_config.C | 24 +- .../chips/p9a/procedures/hwp/memory/p9a_mss_freq.C | 28 +- .../chips/p9a/procedures/hwp/memory/p9a_mss_freq.H | 3 +- .../p9a/procedures/hwp/memory/p9a_mss_freq.mk | 4 +- .../procedures/xml/error_info/p9a_freq_errors.xml | 112 ++++++ 9 files changed, 1077 insertions(+), 21 deletions(-) (limited to 'src/import/chips/p9a/procedures') diff --git a/src/import/chips/p9a/procedures/hwp/memory/lib/freq/axone_freq_traits.H b/src/import/chips/p9a/procedures/hwp/memory/lib/freq/axone_freq_traits.H index ae17d925d..1b4f96d0c 100644 --- a/src/import/chips/p9a/procedures/hwp/memory/lib/freq/axone_freq_traits.H +++ b/src/import/chips/p9a/procedures/hwp/memory/lib/freq/axone_freq_traits.H @@ -22,3 +22,73 @@ /* permissions and limitations under the License. */ /* */ /* IBM_PROLOG_END_TAG */ + +/// +/// @file axone_freq_traits.H +/// @brief Contains frequency traits information for Axone +/// +// *HWP HWP Owner: Stephen Glancy +// *HWP FW Owner: Andre Marin +// *HWP Team: Memory +// *HWP Level: 2 +// *HWP Consumed by: CI + +#ifndef _AXONE_FREQ_TRAITS_H_ +#define _AXONE_FREQ_TRAITS_H_ + +#include +#include +#include +#include + +namespace mss +{ + +/// +/// @class Traits and policy class for frequency and synchronous code - specialization for the AXONE processor type +/// +template<> +class frequency_traits +{ + public: + ////////////////////////////////////////////////////////////// + // Target types + ////////////////////////////////////////////////////////////// + static constexpr fapi2::TargetType PORT_TARGET_TYPE = fapi2::TARGET_TYPE_MEM_PORT; + static constexpr fapi2::TargetType FREQ_TARGET_TYPE = fapi2::TARGET_TYPE_MEM_PORT; + static constexpr fapi2::TargetType VPD_TARGET_TYPE = fapi2::TARGET_TYPE_OCMB_CHIP; + + ////////////////////////////////////////////////////////////// + // Traits values + ////////////////////////////////////////////////////////////// + static const std::vector SUPPORTED_FREQS; + // MEM_PORT is our frequency domain. So 1 port per domain + static constexpr uint64_t PORTS_PER_FREQ_DOMAIN = 1; + // Max DIMM's per port + static constexpr uint64_t MAX_DIMM_PER_PORT = 2; + // Maxium number of primary ranks on a DIMM + static constexpr uint64_t MAX_PRIMARY_RANK_PER_DIMM = 4; + // MC type for Axone is constant - EXPLORER + static constexpr mss::mc_type MC = mss::mc_type::EXPLORER; + static constexpr const char* PROC_STR = "AXONE"; + + // VPD traits values + // TK Resolve these when we know what they are for Axone + static constexpr uint64_t VPD_KEYWORD_MAX = 255; + static constexpr const char* VPD_BLOB_NAME = "EFD"; + static constexpr auto VPD_BLOB = fapi2::MemVpdData::EFD; + static constexpr auto LRDIMM_TYPE = fapi2::ENUM_ATTR_EFF_DIMM_TYPE_LRDIMM; + + // Coding minion, why have these explicitly defined frequency values? + // Isn't the supported frequency vector used for this purpose? + // Well, we need to callout the specific frequency values that are allowed on a given system + // As we can't callout a vector in error callouts and each traits might have a different number of allowable traits, + // the below values are hardcoded specifically for the error callouts + static constexpr uint64_t SUPPORTED_FREQ0 = DIMM_SPEED_2666; + static constexpr uint64_t SUPPORTED_FREQ1 = DIMM_SPEED_2933; + static constexpr uint64_t SUPPORTED_FREQ2 = DIMM_SPEED_3200; +}; + + +} // ns mss +#endif 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 d9dcbda4a..23d6481ad 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 @@ -22,3 +22,430 @@ /* permissions and limitations under the License. */ /* */ /* IBM_PROLOG_END_TAG */ + +/// +/// @file axone_mss_freq.C +/// @brief Axone specializations for frequency library +/// +// *HWP HWP Owner: Stephen Glancy +// *HWP HWP Backup: Louis Stermole +// *HWP Team: Memory +// *HWP Level: 3 +// *HWP Consumed by: HB:FSP + +#include +#include +#include + +// Memory libraries +#include +#include +#include + +// Generic libraries +#include +#include +#include +#include +#include +#include +#include + +namespace mss +{ + +const std::vector< uint64_t > frequency_traits::SUPPORTED_FREQS = +{ + mss::DIMM_SPEED_2666, + mss::DIMM_SPEED_2933, + mss::DIMM_SPEED_3200, +}; + +/// +/// @brief Sets DRAM CAS latency attributes - specialization for Axone and MEM_PORT +/// @param[in] i_target the controller target for 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( + const fapi2::Target& i_target, + const uint64_t i_cas_latency) +{ + const auto l_temp = static_cast(i_cas_latency); + + //Check for rounding issues. Going from a uint64_t to a uint8_t + FAPI_ASSERT( l_temp == i_cas_latency, + fapi2::MSS_BAD_CL_CAST() + .set_CL(i_cas_latency) + .set_PORT_TARGET(i_target), + "%s bad cast for cas latency from %d to %d", + mss::c_str(i_target), + i_cas_latency, + l_temp); + + FAPI_INF( "Final Chosen CL: %d for %s", l_temp, mss::c_str(i_target)); + + FAPI_TRY( mss::attr::set_dram_cl(i_target, l_temp) ); + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Sets the frequency value - specialization for Axone and MEM_PORT +/// @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( + const fapi2::Target& i_target, + const uint64_t i_freq) +{ + FAPI_TRY( mss::attr::set_freq(i_target, i_freq) ); + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Gets the number of master ranks per DIMM - specialization for Axone and MEM_PORT +/// @param[in] i_target the target on which to get the number of master ranks per DIMM +/// @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( + const fapi2::Target& i_target, + uint8_t* o_master_ranks) +{ + using TT = mss::frequency_traits; + + uint8_t l_master_ranks[TT::MAX_DIMM_PER_PORT] = {0}; + FAPI_TRY(mss::attr::get_num_master_ranks_per_dimm(i_target, l_master_ranks)); + std::copy(&l_master_ranks[0], &l_master_ranks[0] + TT::MAX_DIMM_PER_PORT, &o_master_ranks[0]); + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Gets the attribute for the maximum - specialization for Axone +/// @param[out] o_allowed_dimm_freq allowed dimm frequency +/// @return FAPI2_RC_SUCCESS iff ok +/// +template<> +fapi2::ReturnCode max_allowed_dimm_freq(uint32_t* o_allowed_dimm_freq) +{ + uint32_t l_allowed_dimm_freq[NUM_MAX_FREQS] = {0}; + FAPI_TRY(mss::attr::get_max_allowed_dimm_freq(l_allowed_dimm_freq)); + std::copy(&l_allowed_dimm_freq[0], &l_allowed_dimm_freq[0] + NUM_MAX_FREQS, &o_allowed_dimm_freq[0]); + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Gets the DIMM type - specialization for Axone and MEM_PORT +/// @param[in] i_target the target on which to get the DIMM types +/// @param[out] o_dimm_type DIMM types +/// @return FAPI2_RC_SUCCESS iff ok +/// +template<> +fapi2::ReturnCode get_dimm_type( + const fapi2::Target& i_target, + uint8_t* o_dimm_type) +{ + using TT = mss::frequency_traits; + + uint8_t l_dimm_type[TT::MAX_DIMM_PER_PORT] = {0}; + FAPI_TRY(mss::attr::get_dimm_type(i_target, l_dimm_type)); + std::copy(&l_dimm_type[0], &l_dimm_type[0] + TT::MAX_DIMM_PER_PORT, &o_dimm_type[0]); + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Calls out the code if we calculated a bad frequency for the domain - specialization for Axone and MEM_PORT +/// @param[in] i_target target on which to operate +/// @param[in] i_final_freq frequency calculated for domain +/// @return FAPI2_RC_SUCCESS iff ok +/// +template<> +fapi2::ReturnCode callout_bad_freq_calculated( + const fapi2::Target& i_target, + const uint64_t i_final_freq) +{ + using TT = mss::frequency_traits; + + // Declaring temporary variables to avoid linker errors associated with FAPI_ASSERT + const auto FREQ0 = TT::SUPPORTED_FREQ0; + const auto FREQ1 = TT::SUPPORTED_FREQ1; + const auto FREQ2 = TT::SUPPORTED_FREQ2; + + // If we don't find a valid frequency OR don't get a 0 (nothing configured on this clock domain), then error out + FAPI_ASSERT( std::binary_search(TT::SUPPORTED_FREQS.begin(), TT::SUPPORTED_FREQS.end(), i_final_freq) || + i_final_freq == 0, + fapi2::P9A_MSS_BAD_FREQ_CALCULATED() + .set_MSS_FREQ(i_final_freq) + .set_TARGET(i_target) + .set_PROC_TYPE(mss::proc_type::AXONE) + .set_SUPPORTED_FREQ_0(FREQ0) + .set_SUPPORTED_FREQ_1(FREQ1) + .set_SUPPORTED_FREQ_2(FREQ2), + "%s: Calculated FREQ (%d) isn't supported", + mss::c_str(i_target), + i_final_freq); + + return fapi2::FAPI2_RC_SUCCESS; + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @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 +/// +// TK this function should get replaced by our rank API when available +fapi2::ReturnCode get_ranks_for_vpd( + const fapi2::Target& i_target, + std::vector& o_ranks) +{ + using TT = mss::frequency_traits; + + uint8_t l_rank_count_dimm[TT::MAX_DIMM_PER_PORT] = {}; + uint8_t l_dimm_type[TT::MAX_DIMM_PER_PORT] = {}; + + o_ranks.clear(); + + FAPI_TRY( get_master_rank_per_dimm(i_target, &(l_rank_count_dimm[0])) ); + FAPI_TRY( get_dimm_type(i_target, &(l_dimm_type[0])) ); + + // So for LRDIMM, our SI works a bit differently than for non-LRDIMM + // LRDIMM's have buffers that operate on a per-DIMM basis across multiple ranks + // As such, they act as a single load, similar to a 1R DIMM would + // per the IBM signal integrity team, the 1R DIMM settings should be used for LRDIMM's + // So, if we are LRDIMM's and have ranks, we want to only note it as a 1R DIMM for purposes of querying the VPD + FAPI_DBG("%s for DIMM 0 rank count %u dimm type %u %s", + mss::c_str(i_target), l_rank_count_dimm[0], l_dimm_type[0], l_dimm_type[0] == TT::LRDIMM_TYPE ? "LRDIMM" : "RDIMM"); + FAPI_DBG("%s for DIMM 1 rank count %u dimm type %u %s", + mss::c_str(i_target), l_rank_count_dimm[1], l_dimm_type[1], l_dimm_type[1] == TT::LRDIMM_TYPE ? "LRDIMM" : "RDIMM"); + + l_rank_count_dimm[0] = ((l_dimm_type[0] == TT::LRDIMM_TYPE) && (l_rank_count_dimm[0] > 0)) ? 1 : l_rank_count_dimm[0]; + l_rank_count_dimm[1] = ((l_dimm_type[1] == TT::LRDIMM_TYPE) && (l_rank_count_dimm[1] > 0)) ? 1 : l_rank_count_dimm[1]; + + FAPI_DBG("after LR modification %s for DIMM 0 rank count %u dimm type %u %s", + mss::c_str(i_target), l_rank_count_dimm[0], l_dimm_type[0], l_dimm_type[0] == TT::LRDIMM_TYPE ? "LRDIMM" : "RDIMM"); + FAPI_DBG("after LR modification %s for DIMM 1 rank count %u dimm type %u %s", + mss::c_str(i_target), l_rank_count_dimm[1], l_dimm_type[1], l_dimm_type[1] == TT::LRDIMM_TYPE ? "LRDIMM" : "RDIMM"); + + // Add DIMM0's ranks + for (uint64_t l_rank = 0; l_rank < l_rank_count_dimm[0]; ++l_rank) + { + o_ranks.push_back(l_rank); + } + + // Add DIMM1's ranks + for (uint64_t l_rank = 0; l_rank < l_rank_count_dimm[1]; ++l_rank) + { + o_ranks.push_back(l_rank + TT::MAX_PRIMARY_RANK_PER_DIMM); + } + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Check VPD config for support of a given freq - Axone specialization +/// @param[in] i_target the target on which to operate +/// @param[in] i_proposed_freq frequency to check for support +/// @param[out] o_supported true if VPD supports the proposed frequency +/// @return FAPI2_RC_SUCCESS iff ok +/// +template<> +fapi2::ReturnCode check_freq_support_vpd( const fapi2::Target& + i_target, + const uint64_t i_proposed_freq, + bool& o_supported) +{ + using TT = mss::frequency_traits; + o_supported = false; + + std::vector l_ranks; + fapi2::VPDInfo l_vpd_info(TT::VPD_BLOB); + + const auto& l_vpd_target = mss::find_target(i_target); + + l_vpd_info.iv_is_config_ffdc_enabled = false; + + FAPI_TRY(convert_ddr_freq_to_omi_freq(i_target, i_proposed_freq, l_vpd_info.iv_omi_freq_mhz)); + FAPI_INF("Setting VPD info OMI frequency: %d Gbps, for DDR frequency %d MT/s", + l_vpd_info.iv_omi_freq_mhz, i_proposed_freq); + + // 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)); + + for (const auto l_rank : l_ranks) + { + l_vpd_info.iv_rank = l_rank; + FAPI_INF("%s. VPD info - checking rank: %d", + mss::c_str(i_target), l_rank); + + // Check if this VPD configuration is supported + FAPI_TRY(is_vpd_config_supported(l_vpd_target, i_proposed_freq, l_vpd_info, o_supported), + "%s failed to determine if %u freq is supported", mss::c_str(i_target), i_proposed_freq); + + + // If we fail any of the ranks, then this VPD configuration is not supported + if(o_supported == false) + { + FAPI_INF("%s is not supported on rank%u exiting...", mss::c_str(i_target), l_rank); + break; + } + } + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Update supported frequency scoreboard according to processor limits - specialization for Axone and MEM_PORT +/// @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( + const fapi2::Target& i_target, + freq_scoreboard& io_scoreboard) +{ + std::vector l_converted_omi_freqs; + + // OCMB always needs to be in sync between OMI and DDR, by the given ratio + // so we convert the supported OMI freqs and remove every other DDR freq + // from the scoreboard + for (const auto l_omi_freq : AXONE_OMI_FREQS) + { + uint64_t l_ddr_freq = 0; + FAPI_TRY(convert_omi_freq_to_ddr_freq(i_target, l_omi_freq, l_ddr_freq)); + l_converted_omi_freqs.push_back(l_ddr_freq); + } + + FAPI_TRY(io_scoreboard.remove_freqs_not_on_list(0, l_converted_omi_freqs)); + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Gets the number of master ranks on each DIMM - specialization for the Axone 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( + const fapi2::Target& i_target, + uint8_t& o_master_ranks) +{ + return mss::attr::get_num_master_ranks_per_dimm(i_target, o_master_ranks); +} + +/// +/// @brief Calls out the target if no DIMM frequencies are supported - specialization for Axone and MEM_PORT +/// @param[in] i_target target on which to operate +/// @param[in] i_supported_freq true if any FREQ's are supported +/// @param[in,out] i_num_ports number of configured ports (always 1 for Axone) +/// @return FAPI2_RC_SUCCESS iff ok +/// +template<> +fapi2::ReturnCode callout_no_common_freq( + const fapi2::Target& i_target, + const bool i_supported_freq, + const uint64_t i_num_ports) +{ + uint32_t l_max_mrw_freqs[NUM_MAX_FREQS] = {0}; + FAPI_TRY( mss::attr::get_max_allowed_dimm_freq(l_max_mrw_freqs) ); + + FAPI_ASSERT(i_supported_freq, + fapi2::P9A_MSS_NO_SUPPORTED_FREQ() + .set_MEM_PORT_TARGET(i_target) + .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 Axone and MEM_PORT +/// @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( + const fapi2::Target& i_target, + const std::vector>& i_vpd_supported_freqs) +{ + + std::vector 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()); + } + + uint32_t l_max_mrw_freqs[NUM_MAX_FREQS] = {0}; + FAPI_TRY( mss::attr::get_max_allowed_dimm_freq(l_max_mrw_freqs) ); + + FAPI_ASSERT(false, + fapi2::P9A_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_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_OMI_FREQ_0(fapi2::ENUM_ATTR_MSS_OCMB_EXP_BOOT_CONFIG_SERDES_FREQUENCY_SERDES_21_33GBPS) + .set_OMI_FREQ_1(fapi2::ENUM_ATTR_MSS_OCMB_EXP_BOOT_CONFIG_SERDES_FREQUENCY_SERDES_23_46GBPS) + .set_OMI_FREQ_2(fapi2::ENUM_ATTR_MSS_OCMB_EXP_BOOT_CONFIG_SERDES_FREQUENCY_SERDES_25_60GBPS) + .set_PORT_TARGET(i_target), + "%s didn't find a supported frequency for the port", mss::c_str(i_target)); + +fapi_try_exit: + return fapi2::current_err; +} +namespace check +{ + +/// +/// @brief Checks the final frequency for the system type - Axone and MEM_PORT specialization +/// @param[in] i_target the target on which to operate +/// @return FAPI2_RC_SUCCESS iff okay +/// @note This function was needed in Nimbus to enforce a frequency limit due to a hardware limitation +/// and is not needed here. +/// +template<> +fapi2::ReturnCode final_freq(const fapi2::Target& i_target) +{ + return fapi2::FAPI2_RC_SUCCESS; +} + +} // ns check + +} // ns mss diff --git a/src/import/chips/p9a/procedures/hwp/memory/lib/freq/axone_sync.C b/src/import/chips/p9a/procedures/hwp/memory/lib/freq/axone_sync.C index a2ea450e7..311e12cf7 100644 --- a/src/import/chips/p9a/procedures/hwp/memory/lib/freq/axone_sync.C +++ b/src/import/chips/p9a/procedures/hwp/memory/lib/freq/axone_sync.C @@ -22,3 +22,253 @@ /* permissions and limitations under the License. */ /* */ /* IBM_PROLOG_END_TAG */ + +/// +/// @file axone_sync.C +/// @brief Synchronous function implementations for Axone +/// +// *HWP HWP Owner: Andre Marin +// *HWP HWP Backup: Louis Stermole +// *HWP Team: Memory +// *HWP Level: 3 +// *HWP Consumed by: HB:FSP + +#include +#include +#include +#include +#include + +// Memory libraries +#include +#include +#include + +// Generic libraries +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace mss +{ + +/// +/// @brief Retrieves a mapping of MSS frequency values per port target +/// @param[in] i_targets vector of port targets +/// @param[out] o_freq_map dimm speed map = (port target, frequency) +/// @param[out] o_is_speed_equal holds whether map dimm speed is equal +/// @return FAPI2_RC_SUCCESS iff successful +/// +fapi2::ReturnCode dimm_speed_map(const std::vector< fapi2::Target >& i_targets, + std::map< fapi2::Target, uint64_t >& o_freq_map, + speed_equality& o_is_speed_equal) +{ + o_freq_map.clear(); + + // The find_if loop is meant to find the "first" good (non-zero) freq value + // so I can compare it against all other freq values from the MEM_PORT vector + // I am checking to make sure I don't get a value of 0 + // Since Cronus can hand me back a MEM_PORT w/no DIMMs + // Which would give ATTR_MSS_FREQ value of 0 in p9_mss_freq + uint64_t l_comparator = 0; + fapi2::ReturnCode l_rc(fapi2::FAPI2_RC_FALSE); + + const auto l_found_comp = std::find_if(i_targets.begin(), i_targets.end(), + [&l_rc, &l_comparator] (const fapi2::Target& i_target)->bool + { + l_rc = mss::attr::get_freq(i_target, l_comparator); + return l_comparator != 0; + }); + + // Getting error cross initializing with the Assert + // find_if should work if passed in an empty vector. begin() and end() will match and it'll exit without trying freq() + FAPI_ASSERT( !i_targets.empty(), + fapi2::MSS_EMPTY_FREQ_TARGET_VECTOR_PASSED(), + "Empty MEM_PORT target vector found when constructing dimm speed mapping!" ); + + FAPI_TRY(l_rc, "Failed accessor mss::freq()"); + + // If all MEM_PORTs are 0 we go no further + // We shouldn't get here though. We check for DIMMS in freq_system. If no DIMMS, we exit + // We can assume if there is a dimm configured at this point (after mss_freq) + // It has a valid freq + // Thus, this shouldn't ever happen, but let's check anyways + FAPI_ASSERT( l_found_comp != i_targets.end(), + fapi2::MSS_ALL_TARGETS_HAVE_0_FREQ() + .set_VECTOR_SIZE(i_targets.size()), + "All MEM_PORTs have 0 MSS_FREQ, but there are dimms?"); + + // DIMM speed is equal until we deduce otherwise + o_is_speed_equal = speed_equality::EQUAL_DIMM_SPEEDS; + + // Make sure to stick the first one we found in the freq map. + o_freq_map.emplace( std::make_pair(*l_found_comp, l_comparator) ); + + // Loop through all MEM_PORTs and store dimm speeds + // Starting from 1st known good freq (non-zero) value + // I found above to avoid double looping target vector + for (auto l_iter = l_found_comp + 1; l_iter != i_targets.end(); ++l_iter) + { + uint64_t l_dimm_speed = 0; + FAPI_TRY( mss::attr::get_freq(*l_iter, l_dimm_speed), "Failed accessor to mss_freq" ); + + // In FW, parents are deconfigured if they have no children + // So there is no way to get a MEM_PORT w/no DIMMs. + // This isn't true for Cronus so I am skipping map + // insertion and check for dimm speed equality + // to avoid incorrect settings + if( l_dimm_speed != 0) + { + // At least one mismatch freq value occurred + if(l_comparator != l_dimm_speed) + { + o_is_speed_equal = speed_equality::NOT_EQUAL_DIMM_SPEEDS; + } + + FAPI_INF("%s: Dimm speed %d MT/s", c_str(*l_iter), l_dimm_speed); + + o_freq_map.emplace( std::make_pair(*l_iter, l_dimm_speed) ); + } + } + + // Idiot check - most certainly a programming error + FAPI_ASSERT( o_freq_map.size() != 0, + fapi2::MSS_ERROR_FINDING_DIMM_SPEED_MAP(), + "freq system freq map is empty? found port: %s", + mss::c_str(*l_found_comp) ); + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Deconfigures MEM_PORT targets +/// @param[in] i_target the port target +/// @param[in] i_dimm_speed dimm speed in MT/s +/// @param[in] i_max_freq maximum dimm freq in MT/s of freq domain +/// @return true if hardware was deconfigured +/// +bool deconfigure(const fapi2::Target& i_target, + const uint64_t i_dimm_speed, + const uint32_t i_max_freq) +{ + bool l_is_hw_deconfigured = (i_dimm_speed != i_max_freq); + + MSS_ASSERT_NOEXIT(!l_is_hw_deconfigured, + fapi2::MSS_FREQ_NOT_EQUAL_MAX_DOMAIN_FREQ() + .set_MSS_FREQ(i_dimm_speed) + .set_DOMAIN_FREQ(i_max_freq) + .set_DOMAIN_TARGET(i_target), + "Deconfiguring %s due to unequal frequencies: this port: %d, Max in freq domain: %d", + mss::c_str(i_target), + i_dimm_speed, + i_max_freq ); + + return l_is_hw_deconfigured; +} + +/// +/// @brief Selects synchronous mode and performs requirements enforced by selected port frequency +/// @param[in] i_freq_map dimm speed mapping +/// @param[in] i_equal_dimm_speed tracks whether map has equal dimm speeds +/// @param[in] i_omi_freq OMI frequency +/// @param[out] o_selected_sync_mode final synchronous mode +/// @param[out] o_selected_omi_freq final freq selected, only valid if final sync mode is in-sync +/// @return FAPI2_RC_SUCCESS iff successful +/// +fapi2::ReturnCode select_sync_mode(const std::map< fapi2::Target, uint64_t >& i_freq_map, + const speed_equality i_equal_dimm_speed, + const uint32_t i_omi_freq, + uint8_t& o_selected_sync_mode, + uint64_t& o_selected_omi_freq) +{ + FAPI_INF("---- In select_sync_mode ----"); + + switch(i_equal_dimm_speed) + { + // If we have a port which has resolved to equal speeds ... + case speed_equality::EQUAL_DIMM_SPEEDS: + { + // Return back the resulting speed. It doesn't matter which we select from the map as they're all equal + // If we end up not in sync in the conditional below, thats ok - this parameter is ignored by the + // caller if we're not in sync mode + const auto l_ddr_freq = i_freq_map.begin()->second; + FAPI_TRY(convert_ddr_freq_to_omi_freq(i_freq_map.begin()->first, l_ddr_freq, o_selected_omi_freq)); + + // When we selected ATTR_MSS_FREQ, we made sure that we didn't + // select a DIMM freq the OMI couldn't support. + o_selected_sync_mode = fapi2::ENUM_ATTR_MC_SYNC_MODE_IN_SYNC; + // On Cronus if the o_selected_omi_freq != i_omi_freq we've got a mismatch. Note that p9a_mss_freq ensures + // we don't select an invalid freq, but doesn't ensure we select the current OMI freq. +#ifndef __HOSTBOOT_MODULE + FAPI_ASSERT(o_selected_omi_freq == i_omi_freq, + fapi2::P9A_MSS_FAILED_SYNC_MODE() + .set_OMI_FREQ(i_omi_freq) + .set_MEM_FREQ(o_selected_omi_freq), + "The DIMM freq (%d) and the OMI freq (%d) don't align", + o_selected_omi_freq, i_omi_freq); +#endif + return fapi2::FAPI2_RC_SUCCESS; + break; + } + + case speed_equality::NOT_EQUAL_DIMM_SPEEDS: + { + // When we selected ATTR_MSS_FREQ, we made sure that we didn't + // select a DIMM freq the OMI couldn't support. That means that the fastest of the ports + // is the one that rules the roost (the OMI can support it too.) So find that, and set it to + // the selected frequency. Then deconfigure the slower port (unless we're in Cronus in which + // case we just bomb out.) +#ifdef __HOSTBOOT_MODULE + uint64_t l_max_dimm_speed = 0; + fapi2::Target l_fastest_port_target = i_freq_map.begin()->first; + std::for_each(i_freq_map.begin(), i_freq_map.end(), + [&l_max_dimm_speed](const std::pair, uint64_t>& m) + { + l_max_dimm_speed = std::max(l_max_dimm_speed, m.second); + l_fastest_port_target = m.first; + }); + + std::for_each(i_freq_map.begin(), i_freq_map.end(), + [&l_max_dimm_speed](const std::pair, uint64_t>& m) + { + deconfigure(m.first, m.second, l_max_dimm_speed); + }); + + o_selected_sync_mode = fapi2::ENUM_ATTR_MC_SYNC_MODE_IN_SYNC; + FAPI_TRY(convert_ddr_freq_to_omi_freq(l_fastest_port_target, l_max_dimm_speed, o_selected_omi_freq)); + return fapi2::FAPI2_RC_SUCCESS; +#else + // Cronus only + FAPI_ASSERT(false, + fapi2::P9A_MSS_FAILED_SYNC_MODE() + .set_OMI_FREQ(i_omi_freq), + "DIMM speeds differ from OMI speed %d", i_omi_freq); +#endif + break; + } + + default: + // Switches on an enum class + // The only valid speed_equality values are NOT_EQUAL and EQUAL. + // If it's something else ,I think it's a code error and really shouldn't be possible, thus fapi2::Assert below + FAPI_ERR("Invalid speed_equality parameter!"); + fapi2::Assert(false); + break; + }// end switch + + return fapi2::FAPI2_RC_SUCCESS; + +#ifndef __HOSTBOOT_MODULE +fapi_try_exit: + return fapi2::current_err; +#endif +} + +}// mss 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 7b8cb4fe9..06345713c 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 @@ -22,3 +22,183 @@ /* permissions and limitations under the License. */ /* */ /* IBM_PROLOG_END_TAG */ + +/// +/// @file axone_sync.H +/// @brief Synchronous function implementations for Axone +/// +// *HWP HWP Owner: Andre Marin +// *HWP HWP Backup: Louis Stermole +// *HWP Team: Memory +// *HWP Level: 3 +// *HWP Consumed by: HB:FSP + +#ifndef _MSS_SYNC_H_ +#define _MSS_SYNC_H_ + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +namespace mss +{ + +// List of the OMI frequencies for Axone +// Note: these need to be sorted so binary search works +static const std::vector AXONE_OMI_FREQS = +{ + 21330, // fapi2::ENUM_ATTR_MSS_OCMB_EXP_BOOT_CONFIG_SERDES_FREQUENCY_SERDES_21_33GBPS, + 23460, // fapi2::ENUM_ATTR_MSS_OCMB_EXP_BOOT_CONFIG_SERDES_FREQUENCY_SERDES_23_46GBPS, + 25600, // fapi2::ENUM_ATTR_MSS_OCMB_EXP_BOOT_CONFIG_SERDES_FREQUENCY_SERDES_25_60GBPS, +}; + +/// +/// @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 +/// +inline uint64_t convert_omi_freq_attr_to_freq(const fapi2::ATTR_MSS_OCMB_EXP_BOOT_CONFIG_SERDES_FREQUENCY_Type + i_omi_enum) +{ + switch (i_omi_enum) + { + case fapi2::ENUM_ATTR_MSS_OCMB_EXP_BOOT_CONFIG_SERDES_FREQUENCY_SERDES_21_33GBPS: + return 21330; + + case fapi2::ENUM_ATTR_MSS_OCMB_EXP_BOOT_CONFIG_SERDES_FREQUENCY_SERDES_23_46GBPS: + return 23460; + + case fapi2::ENUM_ATTR_MSS_OCMB_EXP_BOOT_CONFIG_SERDES_FREQUENCY_SERDES_25_60GBPS: + return 25600; + + default: + FAPI_ASSERT( false, + fapi2::P9A_MSS_UNSUPPORTED_OMI_FREQ() + .set_OMI_FREQ_ENUM(i_omi_enum), + "freq system saw an unsupported OMI frequency with enum value: %d", + i_omi_enum ); + } + +fapi_try_exit: + return 0; +} + +/// +/// @brief Converts a DDR frequency to the corresponding OMI frequency +/// @param[in] i_target the port target +/// @param[in] i_ddr_freq a frequency value that is to be converted +/// @param[out] o_omi_freq the corresponding OMI frequency +/// @return FAPI2_RC_SUCCESS iff successful +/// +inline fapi2::ReturnCode convert_ddr_freq_to_omi_freq(const fapi2::Target& i_target, + const uint64_t i_ddr_freq, + uint64_t& o_omi_freq) +{ + using TT = mss::frequency_traits; + constexpr uint64_t ROUND_UNITS = 10; + + // Get the OMI to DDR freq ratio + uint8_t l_ratio[TT::MAX_DIMM_PER_PORT] = {0}; + FAPI_TRY(mss::attr::get_host_to_ddr_speed_ratio(i_target, l_ratio)); + + // Multiply by the ratio and round to the nearest 10GBPS + FAPI_TRY(mss::divide_and_round((i_ddr_freq * l_ratio[0]), ROUND_UNITS, o_omi_freq)); + o_omi_freq *= ROUND_UNITS; + FAPI_DBG("For ratio %d and DDR freq %d, corresponding OMI freq is %d", l_ratio[0], i_ddr_freq, o_omi_freq); + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Converts an OMI frequency to the corresponding DDR frequency +/// @param[in] i_target the port target +/// @param[in] i_omi_freq a frequency value that is to be converted +/// @param[out] o_ddr_freq the corresponding DDR frequency +/// @return FAPI2_RC_SUCCESS iff successful +/// +inline fapi2::ReturnCode convert_omi_freq_to_ddr_freq(const fapi2::Target& i_target, + const uint64_t i_omi_freq, + uint64_t& o_ddr_freq) +{ + using TT = mss::frequency_traits; + + // Get the OMI to DDR freq ratio + uint8_t l_ratio[TT::MAX_DIMM_PER_PORT] = {0}; + FAPI_TRY(mss::attr::get_host_to_ddr_speed_ratio(i_target, l_ratio)); + + FAPI_TRY(mss::divide_and_round(i_omi_freq, static_cast(l_ratio[0]), o_ddr_freq), + "%s freq system saw a zero Host (OMI) to DDR frequency ratio", mss::c_str(i_target)); + FAPI_DBG( "For ratio %d and OMI freq %d, corresponding DDR freq is %d", l_ratio[0], i_omi_freq, o_ddr_freq); + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Checks to see if a passed in value could be a valid OMI frequency +/// @param[in] i_target the port target +/// @param[in] i_proposed_freq a frequency value that is to be checked +/// @param[out] o_valid boolean whether the value is a valid OMI frequency +/// @return FAPI2_RC_SUCCESS iff successful +/// +inline fapi2::ReturnCode is_omi_freq_valid (const fapi2::Target& i_target, + const uint64_t i_proposed_freq, + uint64_t& o_valid) +{ + uint64_t l_proposed_omi_freq = 0; + FAPI_TRY(convert_ddr_freq_to_omi_freq(i_target, i_proposed_freq, l_proposed_omi_freq)); + + o_valid = std::binary_search(AXONE_OMI_FREQS.begin(), AXONE_OMI_FREQS.end(), l_proposed_omi_freq); + +fapi_try_exit: + return fapi2::current_err; +} + +/// +/// @brief Retrieves a mapping of MSS frequency values per port target +/// @param[in] i_targets vector of port targets +/// @param[out] o_freq_map dimm speed map = (port target, frequency) +/// @param[out] o_is_speed_equal holds whether map dimm speed is equal +/// @return FAPI2_RC_SUCCESS iff successful +/// +fapi2::ReturnCode dimm_speed_map(const std::vector< fapi2::Target >& i_targets, + std::map< fapi2::Target, uint64_t >& o_freq_map, + speed_equality& o_is_speed_equal); + +/// +/// @brief Helper function to deconfigure MEM_PORT target +/// @param[in] i_target the port target +/// @param[in] i_dimm_speed dimm speed in MT/s +/// @param[in] i_omi_freq OMI freq in MHz +/// @return true if hardware was deconfigured +/// +bool deconfigure(const fapi2::Target& i_target, + const uint64_t i_dimm_speed, + const uint32_t i_omi_freq); + +/// +/// @brief Selects synchronous mode and performs requirements enforced by selected port frequency +/// @param[in] i_freq_map dimm speed mapping +/// @param[in] i_equal_dimm_speed tracks whether map has equal dimm speeds +/// @param[in] i_omi_freq OMI frequency +/// @param[out] o_selected_sync_mode final synchronous mode +/// @param[out] o_selected_omi_freq final freq selected, only valid if final sync mode is in-sync +/// @return FAPI2_RC_SUCCESS iff successful +/// +fapi2::ReturnCode select_sync_mode(const std::map< fapi2::Target, uint64_t >& i_freq_map, + const speed_equality i_equal_dimm_speed, + const uint32_t i_omi_freq, + uint8_t& o_selected_sync_mode, + uint64_t& o_selected_omi_freq); + +}// mss + +#endif diff --git a/src/import/chips/p9a/procedures/hwp/memory/p9a_mss_eff_config.C b/src/import/chips/p9a/procedures/hwp/memory/p9a_mss_eff_config.C index 4fc51a28e..75d23c6af 100644 --- a/src/import/chips/p9a/procedures/hwp/memory/p9a_mss_eff_config.C +++ b/src/import/chips/p9a/procedures/hwp/memory/p9a_mss_eff_config.C @@ -5,7 +5,7 @@ /* */ /* OpenPOWER HostBoot Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2018 */ +/* Contributors Listed Below - COPYRIGHT 2018,2019 */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -42,6 +42,8 @@ #include #include #include +#include +#include /// /// @brief Configure the attributes for each controller @@ -53,21 +55,15 @@ fapi2::ReturnCode p9a_mss_eff_config( const fapi2::Target(i_target); - fapi2::MemVpdData_t l_vpd_type(fapi2::EFD); - fapi2::VPDInfo l_vpd_info(l_vpd_type); - FAPI_TRY( fapi2::getVPD(l_ocmb, l_vpd_info, nullptr) ); - FAPI_TRY( mss::attr::get_num_master_ranks_per_dimm(i_target, l_ranks) ); for(const auto& dimm : mss::find_targets(i_target)) { uint8_t l_dimm_index = 0; uint64_t l_freq = 0; + uint64_t l_omi_freq = 0; FAPI_TRY( mss::attr::get_freq(mss::find_target(dimm), l_freq) ); - - FAPI_TRY( mss::attr_derived_engine::set(dimm) ); + FAPI_TRY( mss::convert_ddr_freq_to_omi_freq(mss::find_target(dimm), l_freq, l_omi_freq)); // Quick hack to get the index until DIMM level attrs work FAPI_TRY( FAPI_ATTR_GET(fapi2::ATTR_REL_POS, dimm, l_dimm_index) ); @@ -76,9 +72,15 @@ fapi2::ReturnCode p9a_mss_eff_config( const fapi2::Target l_efd_data; - // Get EFD data + // Get EFD size + const auto l_ocmb = mss::find_target(i_target); + fapi2::MemVpdData_t l_vpd_type(fapi2::MemVpdData::EFD); + fapi2::VPDInfo l_vpd_info(l_vpd_type); l_vpd_info.iv_rank = rank; - l_vpd_info.iv_omi_freq_mhz = l_freq; + l_vpd_info.iv_omi_freq_mhz = l_omi_freq; + FAPI_TRY( fapi2::getVPD(l_ocmb, l_vpd_info, nullptr), "failed getting VPD size from getVPD" ); + + // Get EFD data std::vector l_vpd_raw (l_vpd_info.iv_size, 0); FAPI_TRY( fapi2::getVPD(l_ocmb, l_vpd_info, l_vpd_raw.data()) ); diff --git a/src/import/chips/p9a/procedures/hwp/memory/p9a_mss_freq.C b/src/import/chips/p9a/procedures/hwp/memory/p9a_mss_freq.C index 7591689e2..342523d5a 100644 --- a/src/import/chips/p9a/procedures/hwp/memory/p9a_mss_freq.C +++ b/src/import/chips/p9a/procedures/hwp/memory/p9a_mss_freq.C @@ -5,7 +5,7 @@ /* */ /* OpenPOWER HostBoot Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2018 */ +/* Contributors Listed Below - COPYRIGHT 2018,2019 */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -30,14 +30,23 @@ // *HWP HWP Owner: Andre Marin // *HWP HWP Backup: Louis Stermole // *HWP Team: Memory -// *HWP Level: 1 +// *HWP Level: 2 // *HWP Consumed by: FSP:HB +// fapi2 +#include + +// mss lib #include + +#include #include +#include #include #include #include +#include +#include /// /// @brief Calculate and save off DIMM frequencies @@ -46,6 +55,13 @@ /// fapi2::ReturnCode p9a_mss_freq( const fapi2::Target& i_target ) { + // If there are no DIMM, we can just get out. + if (mss::count_dimm(i_target) == 0) + { + FAPI_INF("Seeing no DIMM on %s, no freq to set", mss::c_str(i_target)); + return fapi2::FAPI2_RC_SUCCESS; + } + // We will first set pre-eff_config attribes for(const auto& d : mss::find_targets(i_target)) { @@ -60,12 +76,12 @@ fapi2::ReturnCode p9a_mss_freq( const fapi2::Target FAPI_TRY( l_rc, "Failed to initialize SPD facade for %s", mss::spd::c_str(d) ); FAPI_TRY( mss::attr_eff_engine::set(l_spd_decoder) ); + FAPI_TRY( mss::attr_derived_engine::set(d) ); } - // TK - Remove hard-code FREQ -- Should we have enums? Louis problem now - uint64_t HARDCODE_FREQ_LOUIS_REMOVE = 25600; - FAPI_TRY( mss::attr::set_freq(i_target, HARDCODE_FREQ_LOUIS_REMOVE) ); - }// dimm + } + + FAPI_TRY(mss::generate_freq(i_target)); fapi_try_exit: return fapi2::current_err; diff --git a/src/import/chips/p9a/procedures/hwp/memory/p9a_mss_freq.H b/src/import/chips/p9a/procedures/hwp/memory/p9a_mss_freq.H index 179292a80..e4e20b050 100644 --- a/src/import/chips/p9a/procedures/hwp/memory/p9a_mss_freq.H +++ b/src/import/chips/p9a/procedures/hwp/memory/p9a_mss_freq.H @@ -5,7 +5,7 @@ /* */ /* OpenPOWER HostBoot Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2018 */ +/* Contributors Listed Below - COPYRIGHT 2018,2019 */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -37,7 +37,6 @@ #define P9A_MSS_FREQ_H_ #include -#include typedef fapi2::ReturnCode (*p9a_mss_freq_FP_t) (const fapi2::Target&); diff --git a/src/import/chips/p9a/procedures/hwp/memory/p9a_mss_freq.mk b/src/import/chips/p9a/procedures/hwp/memory/p9a_mss_freq.mk index bd2a3e083..47d2c11ea 100644 --- a/src/import/chips/p9a/procedures/hwp/memory/p9a_mss_freq.mk +++ b/src/import/chips/p9a/procedures/hwp/memory/p9a_mss_freq.mk @@ -5,7 +5,7 @@ # # OpenPOWER HostBoot Project # -# Contributors Listed Below - COPYRIGHT 2018 +# Contributors Listed Below - COPYRIGHT 2018,2019 # [+] International Business Machines Corp. # # @@ -27,5 +27,5 @@ -include 00p9a_common.mk PROCEDURE=p9a_mss_freq -$(eval $(call ADD_MEMORY_INCDIRS,$(PROCEDURE))) +$(eval $(call ADD_P9A_MEMORY_INCDIRS,$(PROCEDURE))) $(call BUILD_PROCEDURE) diff --git a/src/import/chips/p9a/procedures/xml/error_info/p9a_freq_errors.xml b/src/import/chips/p9a/procedures/xml/error_info/p9a_freq_errors.xml index c83af56bf..37909deb2 100644 --- a/src/import/chips/p9a/procedures/xml/error_info/p9a_freq_errors.xml +++ b/src/import/chips/p9a/procedures/xml/error_info/p9a_freq_errors.xml @@ -24,5 +24,117 @@ + + RC_P9A_MSS_BAD_FREQ_CALCULATED + + No frequency found for MC Either bad mrw attribute or no DIMMS installed? + Should be a code bug if we get here + + MSS_FREQ + SUPPORTED_FREQ_0 + SUPPORTED_FREQ_1 + SUPPORTED_FREQ_2 + TARGET + PROC_TYPE + + CODE + HIGH + + + + + + RC_P9A_MSS_FAILED_SYNC_MODE + + DIMM speeds are different and sync mode is required + + OMI_FREQ + MEM_FREQ + + CODE + HIGH + + + + + RC_P9A_MSS_MRW_FREQ_MAX_FREQ_EMPTY_SET + + When considering the frequencies in the MRW, the OMI frequency, and the max supported + frequencies based on DIMM config (MAX_ALLOWED_DIMM_FREQ), there are no applicable frequencies + remaining + + MSS_VPD_FREQ_0 + MSS_VPD_FREQ_1 + MSS_VPD_FREQ_2 + MSS_MAX_FREQ_0 + MSS_MAX_FREQ_1 + MSS_MAX_FREQ_2 + MSS_MAX_FREQ_3 + MSS_MAX_FREQ_4 + OMI_FREQ_0 + OMI_FREQ_1 + OMI_FREQ_2 + + CODE + HIGH + + + + PORT_TARGET + TARGET_TYPE_DIMM + + MEDIUM + + + + + RC_P9A_MSS_NO_SUPPORTED_FREQ + + When considering the frequencies in the MRW and the max supported + frequencies based on DIMM config, there are no applicable frequencies + remaining + + MEM_PORT_TARGET + MRW_MAX_FREQ_0 + MRW_MAX_FREQ_1 + MRW_MAX_FREQ_2 + MRW_MAX_FREQ_3 + MRW_MAX_FREQ_4 + + CODE + HIGH + + + + MEM_PORT_TARGET + TARGET_TYPE_DIMM + + MEDIUM + + + + + RC_P9A_MSS_UNSUPPORTED_OMI_FREQ + + Unsupported OMI frequency encountered in mss_freq_system + + OMI_FREQ_ENUM + + CODE + HIGH + + + + + RC_P9A_MSS_ZERO_HOST_TO_DDR_FREQ_RATIO + + Zero OMI to DDR frequency ratio encountered in mss_freq_system + + PORT_TARGET + + CODE + HIGH + + -- cgit v1.2.1