summaryrefslogtreecommitdiffstats
path: root/src/import/chips/p9/procedures/hwp/memory/lib/freq/sync.C
diff options
context:
space:
mode:
Diffstat (limited to 'src/import/chips/p9/procedures/hwp/memory/lib/freq/sync.C')
-rw-r--r--src/import/chips/p9/procedures/hwp/memory/lib/freq/sync.C382
1 files changed, 278 insertions, 104 deletions
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 2c0338b64..4e2930711 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
@@ -5,7 +5,7 @@
/* */
/* OpenPOWER HostBoot Project */
/* */
-/* Contributors Listed Below - COPYRIGHT 2016,2017 */
+/* Contributors Listed Below - COPYRIGHT 2016,2018 */
/* [+] International Business Machines Corp. */
/* */
/* */
@@ -28,19 +28,21 @@
/// @brief Synchronous function implementations
///
// *HWP HWP Owner: Andre Marin <aamarin@us.ibm.com>
-// *HWP HWP Backup: Jacob Harvey <jlharvey@us.ibm.com>
+// *HWP HWP Backup: Louis Stermole <stermole@us.ibm.com>
// *HWP Team: Memory
// *HWP Level: 3
// *HWP Consumed by: HB:FSP
-#include <vector>
-#include <map>
-
#include <fapi2.H>
+#include <vpd_access.H>
+#include <algorithm>
+#include <vector>
+#include <map>
#include <mss.H>
#include <lib/freq/sync.H>
#include <generic/memory/lib/utils/find.H>
#include <lib/utils/assert_noexit.H>
+#include <lib/spd/spd_factory.H>
using fapi2::TARGET_TYPE_DIMM;
using fapi2::TARGET_TYPE_MCS;
@@ -310,59 +312,231 @@ fapi_try_exit:
}
///
+/// @brief Return whether a given freq is supported
+/// @param[in] a freq to check for
+/// @param[in] reference to a std::vector of supported freqs (sorted)
+/// @return bool, true iff input freq is supported
+///
+bool is_freq_supported(const uint32_t i_freq, const std::vector<uint32_t>& i_freqs)
+{
+ return std::binary_search(i_freqs.begin(), i_freqs.end(), i_freq);
+}
+
+///
+/// @brief Create a vector of support freq based on VPD config
+/// @param[in] MCBIST target for which to get the DIMM configs
+/// @param[out] reference to a std::vector of supported VPD frequencies
+/// @return FAPI2_RC_SUCCESS iff ok
+///
+fapi2::ReturnCode vpd_supported_freqs( const fapi2::Target<fapi2::TARGET_TYPE_MCBIST>& i_target,
+ 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] = {};
+ bool is_first_supported_freq = true;
+
+ // Clearing output Just.In.Case
+ o_vpd_supported_freqs.clear();
+
+ fapi2::VPDInfo<fapi2::TARGET_TYPE_MCS> l_vpd_info(fapi2::MemVpdData::MR);
+ l_vpd_info.iv_is_config_ffdc_enabled = false;
+
+ for( const auto& mcs : mss::find_targets<TARGET_TYPE_MCS>(i_target) )
+ {
+ for( const auto& p : mss::find_targets<TARGET_TYPE_MCA>(mcs) )
+ {
+ 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];
+
+ // 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
+ // 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 );
+
+ // If we added a freq that was supported in one MCA, but isn't supported for
+ // another MCA under the same MCBIST (such as one port running single drop and another dual drop),
+ // we remove it from the VPD supported freq list.
+ auto l_it = std::find(o_vpd_supported_freqs.begin(), o_vpd_supported_freqs.end(), freq);
+
+ if( l_it != o_vpd_supported_freqs.end() )
+ {
+ o_vpd_supported_freqs.erase(l_it);
+ }
+
+ 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));
+
+ // If we are here then we should have a valid frequency selected from polling the VPD keyword size above.
+ // A hard-fail here means something is wrong and we want to return current_err instead of ignoring it.
+ FAPI_TRY( fapi2::getVPD(mcs, l_vpd_info, &(l_mr_blob[0])),
+ "Failed to retrieve VPD data for %s", mss::c_str(mcs) );
+
+ // Add non-repeating supported freqs
+ auto l_it = std::find(o_vpd_supported_freqs.begin(), o_vpd_supported_freqs.end(), freq);
+
+ if( l_it == o_vpd_supported_freqs.end() || is_first_supported_freq )
+ {
+ is_first_supported_freq = false;
+ FAPI_INF("VPD supported freq added: %d for %s", freq, mss::c_str(p) );
+ o_vpd_supported_freqs.push_back(freq);
+ }
+ }// freqs
+ }// mca
+ }//mcs
+
+ std::sort( o_vpd_supported_freqs.begin(), o_vpd_supported_freqs.end() );
+
+ return fapi2::FAPI2_RC_SUCCESS;
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief Removes frequencies unsupported by SPD from a sorted list of supported freqs -- helper function for testing
+/// @param[in] i_target the MCBIST target
+/// @param[in] i_highest_freq largest SPD supported freq
+/// @param[in,out] io_freqs std::vector of VPD supported freqs (sorted)
+///
+void rm_unsupported_spd_freqs(const fapi2::Target<TARGET_TYPE_MCBIST>& i_target,
+ const uint32_t i_highest_freq,
+ std::vector<uint32_t>& io_freqs)
+{
+
+ // Don't use 'auto' since I want a const iterator and HB compiler
+ // bombs out using 'const auto'...
+ // The idea here is that if SPD across and MC can only support 2133 MT/s,
+ // we remove any supported frequencies in the vector higher than that (e.g. 2400, 2666)
+ auto it = std::upper_bound(io_freqs.begin(), io_freqs.end(), i_highest_freq);
+
+ // Remove all frequencies higher than max supported SPD freq per MCBIST
+ // since we set freq at that level
+ if( it != io_freqs.end() )
+ {
+ io_freqs.erase(it, io_freqs.end());
+ }
+
+ return;
+}
+
+///
+/// @brief Retrieves largest supported frequency the MC supports due to DIMM SPD
+/// @param[in] i_target the MCBIST target
+/// @param[out] o_highest_freq the largest SPD supported freq
+/// @return FAPI2_RC_SUCCESS iff okay
+///
+fapi2::ReturnCode largest_spd_supported_freq(const fapi2::Target<TARGET_TYPE_MCBIST>& i_target,
+ uint32_t& o_highest_freq)
+{
+ uint64_t l_largest_tck = 0;
+
+ // Get cached decoder
+ std::vector< std::shared_ptr<mss::spd::decoder> > l_factory_caches;
+
+ FAPI_TRY( mss::spd::populate_decoder_caches(i_target, l_factory_caches),
+ "%s. Failed to populate decoder cache", 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_factory_caches )
+ {
+ const auto l_dimm = l_cache->iv_target;
+ uint64_t l_tckmax_in_ps = 0;
+ uint64_t l_tck_min_in_ps = 0;
+
+ FAPI_TRY( get_tckmax(l_cache, l_tckmax_in_ps),
+ "%s. Failed to get tCKmax", mss::c_str(l_dimm) );
+ FAPI_TRY( 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, o_highest_freq) );
+ FAPI_INF("Biggest freq supported from SPD %d MT/s for %s",
+ o_highest_freq, mss::c_str(i_target));
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
/// @brief Create and sort a vector of supported MT/s (freq)
-/// @param[in] MCA target for which to get the DIMM configs
-/// @param[out] reference to a std::vector<uint32_t> space to put the sorted vector
+/// @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 ATTR_MSS_MRW_SUPPORTED_FREQ. The result is sorted so such that the min
+/// @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_MCA>& i_target, std::vector<uint32_t>& o_freqs)
+fapi2::ReturnCode supported_freqs(const fapi2::Target<TARGET_TYPE_MCBIST>& i_target,
+ std::vector<uint32_t>& o_freqs)
{
o_freqs.clear();
- std::vector<uint32_t> l_mrw_freqs(NUM_MRW_FREQS, 0);
- std::vector<uint32_t> l_max_freqs(NUM_MAX_FREQS, 0);
+ std::vector<uint32_t> l_vpd_supported_freqs;
+ uint32_t l_largest_spd_freq = 0;
uint8_t l_req_sync_mode = 0;
- FAPI_TRY( mss::mrw_supported_freq(l_mrw_freqs.data()) );
+ // Retrieve system MRW constraints
+ std::vector<uint32_t> l_max_freqs(NUM_MAX_FREQS, 0);
FAPI_TRY( mss::max_allowed_dimm_freq(l_max_freqs.data()) );
- FAPI_TRY( mss::required_synch_mode(l_req_sync_mode) );
-
- FAPI_INF("attribute supported freqs %d %d %d %d",
- l_mrw_freqs[0], l_mrw_freqs[1], l_mrw_freqs[2], l_mrw_freqs[3]);
- FAPI_INF("attribute supported max freqs %d %d %d %d %d",
- l_max_freqs[0], l_max_freqs[1], l_max_freqs[2], l_max_freqs[3], l_max_freqs[4]);
+ // Retrieve frequency constraints due to DIMM SPD and VPD per MCBIST
+ FAPI_TRY( largest_spd_supported_freq(i_target, l_largest_spd_freq) );
+ FAPI_TRY( vpd_supported_freqs(i_target, l_vpd_supported_freqs) );
+ rm_unsupported_spd_freqs(i_target, l_largest_spd_freq, l_vpd_supported_freqs);
- FAPI_INF("attribute required sync mode %d", l_req_sync_mode);
+ FAPI_TRY( mss::required_synch_mode(l_req_sync_mode) );
FAPI_TRY( supported_freqs_helper( i_target,
- l_mrw_freqs,
+ l_vpd_supported_freqs,
l_max_freqs,
l_req_sync_mode == fapi2::ENUM_ATTR_REQUIRED_SYNCH_MODE_ALWAYS,
o_freqs) );
-
fapi_try_exit:
return fapi2::current_err;
}
///
/// @brief Create and sort a vector of supported MT/s (freq) - helper for testing purposes
-/// @param[in] MCA target for which to get the DIMM configs
-/// @param[in] vector of MRW freqs
-/// @param[in] vector of max allowed freqs
-/// @param[in] bool whether or not we're forced into sync mode
-/// @param[out] reference to a std::vector<uint32_t> space to put the sorted vector
+/// @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 and SPD
+/// @param[in] i_max_mrw_freqs vector of max allowed freqs
+/// @param[in] i_req_sync_mode bool whether or not we're forced into sync mode
+/// @param[out] o_freqs reference to a std::vector to put the sorted vector
/// @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 (DFT I think the cool kids call it.)
///
-fapi2::ReturnCode supported_freqs_helper(const fapi2::Target<TARGET_TYPE_MCA>& i_target,
- const std::vector<uint32_t>& i_mrw_freqs,
- const std::vector<uint32_t>& i_max_freqs,
+fapi2::ReturnCode supported_freqs_helper(const fapi2::Target<TARGET_TYPE_MCBIST>& i_target,
+ const std::vector<uint32_t>& i_hw_freqs,
+ const std::vector<uint32_t>& i_max_mrw_freqs,
const bool i_req_sync_mode,
std::vector<uint32_t>& o_freqs)
{
@@ -377,44 +551,46 @@ fapi2::ReturnCode supported_freqs_helper(const fapi2::Target<TARGET_TYPE_MCA>& i
// frequencies allowed by the DIMM. So, we start way off the charts so std::min can do the lifting for us.
uint32_t l_our_max_freq = ~(0);
- // This magic number isn't the number of frequencies supported by the hardware, it's the number
- // of frequencies in the attribute or MRW. They may be different
- FAPI_ASSERT( i_mrw_freqs.size() == NUM_MRW_FREQS,
- fapi2::MSS_MRW_FREQ_SIZE_CHANGED()
- .set_ACTUAL_SIZE(i_mrw_freqs.size())
- .set_SUPPOSED_SIZE(NUM_MRW_FREQS)
- .set_MCA_TARGET(i_target),
- "%s Incorrect number of frequencies (%d)",
- mss::c_str(i_target),
- i_mrw_freqs.size());
-
- FAPI_INF("unsorted supported freqs %d %d %d %d",
- i_mrw_freqs[0], i_mrw_freqs[1], i_mrw_freqs[2], i_mrw_freqs[3]);
-
// This is the number of elements in the max_allowed_dimm_freq attribute, not the frequencies of
- // the system. Hence the magic number.
- FAPI_ASSERT( i_max_freqs.size() == NUM_MAX_FREQS,
+ // the system.
+ FAPI_ASSERT( i_max_mrw_freqs.size() == NUM_MAX_FREQS,
fapi2::MSS_MAX_FREQ_ATTR_SIZE_CHANGED()
- .set_ACTUAL_SIZE(i_max_freqs.size())
+ .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_freqs.size());
+ 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));
- FAPI_INF("max supported freqs %d %d %d %d %d",
- i_max_freqs[0], i_max_freqs[1], i_max_freqs[2], i_max_freqs[3], i_max_freqs[4]);
+ // This is the list of supported frequencies for VPD and SPD
+ FAPI_ASSERT( !i_hw_freqs.empty(),
+ fapi2::MSS_EMPTY_VECTOR().
+ set_FUNCTION(SUPPORTED_FREQS).
+ set_TARGET(i_target),
+ "Supported system freqs from VPD and SPD are empty for %s",
+ mss::c_str(i_target));
+
+ for( const auto& freq : i_hw_freqs )
+ {
+ FAPI_DBG("VPD supported freqs %d for %s", freq, mss::c_str(i_target) );
+ }
+
+ for( const auto& p : mss::find_targets<fapi2::TARGET_TYPE_MCA>(i_target) )
{
- const auto l_dimms = mss::find_targets<TARGET_TYPE_DIMM>(i_target);
- uint64_t l_dimms_on_port = l_dimms.size();
+ const auto l_dimms = mss::find_targets<TARGET_TYPE_DIMM>(p);
+ const uint64_t l_dimms_on_port = l_dimms.size();
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(i_target),
+ .set_MCA_TARGET(p),
"Seeing %d DIMM on port %s",
l_dimms_on_port,
- mss::c_str(i_target));
+ mss::c_str(p));
for (const auto& d : l_dimms)
{
@@ -447,87 +623,85 @@ fapi2::ReturnCode supported_freqs_helper(const fapi2::Target<TARGET_TYPE_MCA>& i
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_freqs[l_index] );
+ i_max_mrw_freqs[l_index] );
+
+ l_our_max_freq = std::min(l_our_max_freq, i_max_mrw_freqs[l_index]);
+ }// dimm
+ }// mca
- l_our_max_freq = std::min(l_our_max_freq, i_max_freqs[l_index]);
- }
- }
FAPI_INF("after processing DIMM, max freq is %d", l_our_max_freq);
// We need to push things as the memcpy doesn't update the vector's count, etc. and we don't
// create the vector, we get it passed in. It's not a big deal as we want to touch all the elements
// to check for 0's anyway.
- for (size_t i = 0; i < NUM_MRW_FREQS; ++i)
+ for (size_t i = 0; i < i_hw_freqs.size(); ++i)
{
// Funky if-tree makes things clearer than a combinatorialy explosive conditional
- if (i_mrw_freqs[i] == 0)
+ if (i_hw_freqs[i] == 0)
{
// Skip 0's
continue;
}
- if (i_mrw_freqs[i] > l_our_max_freq)
+ if (i_hw_freqs[i] > l_our_max_freq)
{
// Skip freqs larger than our max
continue;
}
// Add this freq if we're not in sync mode, or, if we are, add it if it matches a nest freq
- switch (i_req_sync_mode)
+ FAPI_INF("attribute required sync mode %d for %s", i_req_sync_mode, mss::c_str(i_target));
+
+ if( i_req_sync_mode && !is_nest_freq_valid(i_hw_freqs[i]) )
{
- case true :
- if (is_nest_freq_valid(i_mrw_freqs[i]))
- {
- o_freqs.push_back(i_mrw_freqs[i]);
- }
+ continue;
+ }
- break;
+ o_freqs.push_back(i_hw_freqs[i]);
- case false :
- o_freqs.push_back(i_mrw_freqs[i]);
- break;
- }
+ }//end for
+
+ {
+ // Doing this because the HB compiler freaks out if we have it within the FAPI_ASSERT.
+ // Outputting the value and then incrementing the iterator, that's why it's a post increment
+ // We have at most 4 memory freqs (1866, 2133, 2400, & 2666), if we ever get a list with < 4 items
+ // a value of 0 is logged in FFDC once we hit i_hw_freqs.end()...which is better than no logging.
+ auto l_supported = i_hw_freqs.begin();
+
+ const auto l_freq0 = (l_supported != i_hw_freqs.end()) ? *(l_supported++) : 0;
+ const auto l_freq1 = (l_supported != i_hw_freqs.end()) ? *(l_supported++) : 0;
+ const auto l_freq2 = (l_supported != i_hw_freqs.end()) ? *(l_supported++) : 0;
+ const auto l_freq3 = (l_supported != i_hw_freqs.end()) ? *(l_supported++) : 0;
+
+ // If we have an empty set, we have a problem
+ FAPI_ASSERT(o_freqs.size() != 0,
+ fapi2::MSS_MRW_FREQ_MAX_FREQ_EMPTY_SET()
+ .set_MSS_VPD_FREQ_0(l_freq0)
+ .set_MSS_VPD_FREQ_1(l_freq1)
+ .set_MSS_VPD_FREQ_2(l_freq2)
+ .set_MSS_VPD_FREQ_3(l_freq3)
+ .set_MSS_MAX_FREQ_0(i_max_mrw_freqs[0])
+ .set_MSS_MAX_FREQ_1(i_max_mrw_freqs[1])
+ .set_MSS_MAX_FREQ_2(i_max_mrw_freqs[2])
+ .set_MSS_MAX_FREQ_3(i_max_mrw_freqs[3])
+ .set_MSS_MAX_FREQ_4(i_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_MAX_FREQ_FROM_DIMM(l_our_max_freq)
+ .set_MCBIST_TARGET(i_target),
+ "%s didn't find a frequency which was in VPD and was allowable max", mss::c_str(i_target));
}
// We now know o_freqs contains valid frequencies for this DIMM config, system contraints, and sync mode.
// Sort it so we know supported min is o_freq.begin and supported max is o_freq.end - 1
std::sort(o_freqs.begin(), o_freqs.end());
- // If we have an empty set, we have a problem
- FAPI_ASSERT(o_freqs.size() != 0,
- fapi2::MSS_MRW_FREQ_MAX_FREQ_EMPTY_SET()
- .set_MSS_MRW_FREQ_0(i_mrw_freqs[0])
- .set_MSS_MRW_FREQ_1(i_mrw_freqs[1])
- .set_MSS_MRW_FREQ_2(i_mrw_freqs[2])
- .set_MSS_MRW_FREQ_3(i_mrw_freqs[3])
- .set_MSS_MAX_FREQ_0(i_max_freqs[0])
- .set_MSS_MAX_FREQ_1(i_max_freqs[1])
- .set_MSS_MAX_FREQ_2(i_max_freqs[2])
- .set_MSS_MAX_FREQ_3(i_max_freqs[3])
- .set_MSS_MAX_FREQ_4(i_max_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_MAX_FREQ_FROM_DIMM(l_our_max_freq)
- .set_MCA_TARGET(i_target),
- "%s didn't find a frequency which was in VPD and was allowable max", mss::c_str(i_target));
-
fapi_try_exit:
return fapi2::current_err;
}
-///
-/// @brief Return whether a given freq is supported
-/// @param[in] a freq to check for
-/// @param[in] reference to a std::vector<uint32_t> of freqs
-/// @return bool, true iff input freq is supported
-///
-bool is_freq_supported(const uint32_t i_freq, const std::vector<uint32_t>& i_freqs)
-{
- return std::binary_search(i_freqs.begin(), i_freqs.end(), i_freq);
-}
-
}// mss
OpenPOWER on IntegriCloud