summaryrefslogtreecommitdiffstats
path: root/src/import/chips/p9/procedures/hwp/memory/lib/freq
diff options
context:
space:
mode:
authorStephen Glancy <sglancy@us.ibm.com>2018-09-04 10:57:35 -0500
committerChristian R. Geddes <crgeddes@us.ibm.com>2018-09-19 17:21:05 -0500
commit4f8cfb6e9c07076261fac4b58105bd6863f6c13f (patch)
treebd3133e372feeedfd117aa16c23030cf190d0ca1 /src/import/chips/p9/procedures/hwp/memory/lib/freq
parent8247477571339e0cba2d06d0701378e029628806 (diff)
downloadtalos-hostboot-4f8cfb6e9c07076261fac4b58105bd6863f6c13f.tar.gz
talos-hostboot-4f8cfb6e9c07076261fac4b58105bd6863f6c13f.zip
Moves sync code to generic folder
Change-Id: I440cdb0ea105a6dbdcd0ac26696308e55d56f88b Reviewed-on: http://rchgit01.rchland.ibm.com/gerrit1/65786 Dev-Ready: STEPHEN GLANCY <sglancy@us.ibm.com> Tested-by: HWSV CI <hwsv-ci+hostboot@us.ibm.com> Tested-by: Jenkins Server <pfd-jenkins+hostboot@us.ibm.com> Tested-by: Hostboot CI <hostboot-ci+hostboot@us.ibm.com> Reviewed-by: Louis Stermole <stermole@us.ibm.com> Reviewed-by: ANDRE A. MARIN <aamarin@us.ibm.com> Reviewed-by: Jennifer A. Stofer <stofer@us.ibm.com> Reviewed-on: http://rchgit01.rchland.ibm.com/gerrit1/66323 Tested-by: Jenkins OP Build CI <op-jenkins+hostboot@us.ibm.com> Tested-by: Jenkins OP HW <op-hw-jenkins+hostboot@us.ibm.com> Tested-by: FSP CI Jenkins <fsp-CI-jenkins+hostboot@us.ibm.com> Reviewed-by: Christian R. Geddes <crgeddes@us.ibm.com>
Diffstat (limited to 'src/import/chips/p9/procedures/hwp/memory/lib/freq')
-rw-r--r--src/import/chips/p9/procedures/hwp/memory/lib/freq/nimbus_mss_freq.C278
-rw-r--r--src/import/chips/p9/procedures/hwp/memory/lib/freq/sync.C781
-rw-r--r--src/import/chips/p9/procedures/hwp/memory/lib/freq/sync.H209
3 files changed, 326 insertions, 942 deletions
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
OpenPOWER on IntegriCloud