summaryrefslogtreecommitdiffstats
path: root/src/import/generic/memory/lib/utils
diff options
context:
space:
mode:
Diffstat (limited to 'src/import/generic/memory/lib/utils')
-rw-r--r--src/import/generic/memory/lib/utils/assert_noexit.H37
-rw-r--r--src/import/generic/memory/lib/utils/freq/cas_latency.H4
-rw-r--r--src/import/generic/memory/lib/utils/freq/gen_mss_freq.H225
-rw-r--r--src/import/generic/memory/lib/utils/freq/gen_mss_freq_traits.H51
-rw-r--r--src/import/generic/memory/lib/utils/freq/mss_freq_scoreboard.H4
-rw-r--r--src/import/generic/memory/lib/utils/mss_math.H38
-rw-r--r--src/import/generic/memory/lib/utils/shared/mss_generic_consts.H18
7 files changed, 199 insertions, 178 deletions
diff --git a/src/import/generic/memory/lib/utils/assert_noexit.H b/src/import/generic/memory/lib/utils/assert_noexit.H
index 5836511de..e8192e784 100644
--- a/src/import/generic/memory/lib/utils/assert_noexit.H
+++ b/src/import/generic/memory/lib/utils/assert_noexit.H
@@ -22,3 +22,40 @@
/* permissions and limitations under the License. */
/* */
/* IBM_PROLOG_END_TAG */
+
+///
+/// @file assert_noexit.H
+/// @brief MSS specific assert, but don't exit macro
+///
+// *HWP HWP Owner: Stephen Glancy <sglancy@us.ibm.com>
+// *HWP HWP Backup: Andre Marin <aamarin@us.ibm.com>
+// *HWP Team: Memory
+// *HWP Level: 3
+// *HWP Consumed by: HB:FSP
+
+#ifndef _MSS_ASSERT_NOEXIT_H_
+#define _MSS_ASSERT_NOEXIT_H_
+
+#include <fapi2.H>
+
+///
+/// @brief Create an error log based on __conditional__,
+/// the FFDC gathering function is called and the
+/// trace is output as a FAPI error trace. An error log
+/// is created. fapi2::current_err is set to indicate there was
+/// an error so the caller can ripple thru accordingly
+/// The caller is responsible for handling the error object.
+///
+/// @param[in] __conditional__ the condition to assert
+/// @param[in] __ffdc__ the FFDC gathering function
+/// @param[in] ... varargs, as input to FAPI_ERR
+///
+#define MSS_ASSERT_NOEXIT( __conditional__, __ffdc__, ... ) \
+ if (! (__conditional__)) \
+ { \
+ __ffdc__.execute(fapi2::FAPI2_ERRL_SEV_UNDEFINED, true); \
+ FAPI_ERR(__VA_ARGS__); \
+ fapi2::current_err = fapi2::FAPI2_RC_FALSE; \
+ }
+
+#endif
diff --git a/src/import/generic/memory/lib/utils/freq/cas_latency.H b/src/import/generic/memory/lib/utils/freq/cas_latency.H
index 83ae824c9..1b71481e2 100644
--- a/src/import/generic/memory/lib/utils/freq/cas_latency.H
+++ b/src/import/generic/memory/lib/utils/freq/cas_latency.H
@@ -5,7 +5,7 @@
/* */
/* OpenPOWER HostBoot Project */
/* */
-/* Contributors Listed Below - COPYRIGHT 2016,2018 */
+/* Contributors Listed Below - COPYRIGHT 2016,2019 */
/* [+] International Business Machines Corp. */
/* */
/* */
@@ -135,7 +135,7 @@ template <>
class CasLatencyTraits<mc_type::EXPLORER>
{
public:
- static constexpr fapi2::TargetType TARGET_TYPE = fapi2::TARGET_TYPE_OCMB_CHIP;
+ static constexpr fapi2::TargetType TARGET_TYPE = fapi2::TARGET_TYPE_MEM_PORT;
static const std::vector<uint32_t> SUPPORTED_FREQS;
static constexpr const char* MC_STR = "EXPLORER";
};
diff --git a/src/import/generic/memory/lib/utils/freq/gen_mss_freq.H b/src/import/generic/memory/lib/utils/freq/gen_mss_freq.H
index a70dcebb5..4df0eeb06 100644
--- a/src/import/generic/memory/lib/utils/freq/gen_mss_freq.H
+++ b/src/import/generic/memory/lib/utils/freq/gen_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. */
/* */
/* */
@@ -43,7 +43,6 @@
#include <generic/memory/lib/spd/spd_utils.H>
#include <generic/memory/lib/utils/freq/cas_latency.H>
#include <generic/memory/lib/utils/freq/mss_freq_scoreboard.H>
-#include <generic/memory/lib/data_engine/pre_data_init.H>
#include <generic/memory/lib/utils/count_dimm.H>
#include <vpd_access.H>
@@ -81,7 +80,7 @@ fapi2::ReturnCode set_freq(const fapi2::Target<T>& i_target,
/// @param[out] o_master_ranks number of master ranks per DIMM
/// @return FAPI2_RC_SUCCESS iff ok
///
-template<mss::proc_type P, fapi2::TargetType T>
+template<mss::proc_type P, typename TT = mss::frequency_traits<P>, fapi2::TargetType T>
fapi2::ReturnCode get_master_rank_per_dimm(const fapi2::Target<T>& i_target,
uint8_t* o_master_ranks);
@@ -93,56 +92,114 @@ fapi2::ReturnCode get_master_rank_per_dimm(const fapi2::Target<T>& i_target,
/// @param[out] o_dimm_type DIMM types
/// @return FAPI2_RC_SUCCESS iff ok
///
-template<mss::proc_type P, fapi2::TargetType T>
+template<mss::proc_type P, typename TT = mss::frequency_traits<P>, fapi2::TargetType T>
fapi2::ReturnCode get_dimm_type(const fapi2::Target<T>& i_target,
uint8_t* o_dimm_type);
///
-/// @brief Configures the number of ranks in the VPD accessor dependent upon DIMM type
+/// @brief Calls out the code if we calculated a bad frequency for the domain
/// @tparam P mss::proc_type on which to operate
/// @tparam TT Traits associated with the processor type
-/// @param[in] i_target the target on which to set the frequency values
-/// @param[in,out] io_vpd_info VPD information that needs to be configured
-/// @return FAPI2_RC_SUCCESS iff ok
+/// @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<mss::proc_type P, typename TT = mss::frequency_traits<P>>
+fapi2::ReturnCode callout_bad_freq_calculated(const fapi2::Target<TT::FREQ_TARGET_TYPE>& i_target,
+ const uint64_t i_final_freq);
+
+///
+/// @brief Configures the number of ranks in the VPD accessor dependent upon DIMM type
+/// @tparam P mss::proc_type on which to operate
+/// @tparam TT Traits associated with the processor type
+/// @param[in] i_target the target on which to set the frequency values
+/// @param[in,out] io_vpd_info VPD information that needs to be configured
+/// @return FAPI2_RC_SUCCESS iff ok
///
template<mss::proc_type P, typename TT = mss::frequency_traits<P>>
fapi2::ReturnCode configure_vpd_ranks(const fapi2::Target<TT::PORT_TARGET_TYPE>& i_target,
- fapi2::VPDInfo<TT::VPD_TARGET_TYPE>& io_vpd_info)
+ fapi2::VPDInfo<TT::VPD_TARGET_TYPE>& io_vpd_info);
+
+///
+/// @brief Checks to see if a specific VPD configuration is valid
+/// @tparam P mss::proc_type on which to operate
+/// @tparam TT Traits associated with the processor type
+/// @param[in] i_target the target on which to operate
+/// @param[in] i_proposed_freq frequency to check for support
+/// @param[in,out] io_vpd_info VPDInfo instance to use
+/// @param[out] o_supported true if VPD supports the proposed frequency
+///
+template<mss::proc_type P, typename TT = mss::frequency_traits<P>>
+fapi2::ReturnCode is_vpd_config_supported( const fapi2::Target<TT::VPD_TARGET_TYPE>& i_target,
+ const uint64_t i_proposed_freq,
+ fapi2::VPDInfo<TT::VPD_TARGET_TYPE>& io_vpd_info,
+ bool& o_supported)
{
- uint8_t l_rank_count_dimm[TT::MAX_DIMM_PER_PORT] = {};
- uint8_t l_dimm_type[TT::MAX_DIMM_PER_PORT] = {};
-
- // ATTR to update
- // Note: this flat out assumes that we have two DIMM per port max. This goes against the directive to have arrays be dynamic in length and derived from ATTR's
- FAPI_TRY( get_master_rank_per_dimm<P>(i_target, &(l_rank_count_dimm[0])) );
- FAPI_TRY( get_dimm_type<P>(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");
-
- io_vpd_info.iv_rank_count_dimm_0 = l_rank_count_dimm[0];
- io_vpd_info.iv_rank_count_dimm_1 = l_rank_count_dimm[1];
+ uint8_t l_vpd_blob[TT::VPD_KEYWORD_MAX] = {};
+
+ // We are unsupported by default
+ o_supported = false;
+
+ // 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.
+
+ // So, we'll use VPD access for the IBM specific product data (assuming the vendor of the OCMB's side as well)
+ if( fapi2::getVPD(i_target, io_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(i_target), i_proposed_freq );
+
+ return fapi2::FAPI2_RC_SUCCESS;
+ }
+
+ // Need temporary variables to avoid issues with FAPI_ASSERT and templated variables
+ {
+ fapi2::current_err = fapi2::FAPI2_RC_SUCCESS;
+ const auto VPD_KW_MAX = TT::VPD_KEYWORD_MAX;
+ const auto VPD_BLOB = TT::VPD_BLOB;
+ FAPI_ASSERT( io_vpd_info.iv_size <= TT::VPD_KEYWORD_MAX,
+ fapi2::MSS_INVALID_VPD_KEYWORD_MAX().
+ set_MAX(VPD_KW_MAX).
+ set_ACTUAL(io_vpd_info.iv_size).
+ set_KEYWORD(VPD_BLOB).
+ set_MCS_TARGET(i_target),
+ "VPD MR keyword size retrieved: %d, is larger than max: %d for %s",
+ io_vpd_info.iv_size, TT::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(i_target, io_vpd_info, &(l_vpd_blob[0])) != fapi2::FAPI2_RC_SUCCESS )
+ {
+ FAPI_INF("Couldn't retrieve %s data from VPD for this config %s -- skipping freq %d MT/s", TT::VPD_BLOB_NAME,
+ mss::c_str(i_target), i_proposed_freq );
+
+ return fapi2::FAPI2_RC_SUCCESS;
+ }
+
+ // If we made it here, it means the frequency was supported for this config
+ o_supported = true;
fapi_try_exit:
return fapi2::current_err;
}
///
+/// @brief Check VPD config for support of a given freq
+/// @tparam P mss::proc_type on which to operate
+/// @tparam TT Traits associated with the processor type
+/// @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<mss::proc_type P, typename TT = mss::frequency_traits<P>>
+fapi2::ReturnCode check_freq_support_vpd( const fapi2::Target<TT::PORT_TARGET_TYPE>& i_target,
+ const uint64_t i_proposed_freq,
+ bool& o_supported);
+
+///
/// @brief Sets frequency attributes
/// @tparam P mss::proc_type on which to operate
/// @tparam TT Traits associated with the processor type
@@ -169,28 +226,7 @@ inline fapi2::ReturnCode set_freq_attrs(const fapi2::Target<TT::FREQ_TARGET_TYPE
// If we saw all 0's, write a 0.
l_final_freq = (l_final_freq == UINT64_MAX) ? 0 : l_final_freq;
- {
- // 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;
- const auto FREQ3 = TT::SUPPORTED_FREQ3;
-
- // 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(), l_final_freq) ||
- l_final_freq == 0,
- fapi2::MSS_BAD_FREQ_CALCULATED()
- .set_MSS_FREQ(l_final_freq)
- .set_TARGET(i_target)
- .set_PROC_TYPE(P)
- .set_SUPPORTED_FREQ_0(FREQ0)
- .set_SUPPORTED_FREQ_1(FREQ1)
- .set_SUPPORTED_FREQ_2(FREQ2)
- .set_SUPPORTED_FREQ_3(FREQ3),
- "%s: Calculated FREQ (%d) isn't supported",
- mss::c_str(i_target),
- l_final_freq);
- }
+ FAPI_TRY(callout_bad_freq_calculated<P>(i_target, l_final_freq));
FAPI_INF( "Final Chosen Frequency: %d (%s)", l_final_freq, mss::c_str(i_target) );
@@ -258,7 +294,6 @@ fapi_try_exit:
/// @tparam P mss::proc_type on which to operate
/// @tparam TT Traits associated with the processor type
/// @param[in] i_target the target on which to operate
-/// @param[in] i_target target on which to operate 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
///
@@ -267,8 +302,6 @@ template<mss::proc_type P, typename TT = mss::frequency_traits<P>>
fapi2::ReturnCode vpd_supported_freqs( const fapi2::Target<TT::FREQ_TARGET_TYPE>& i_target,
std::vector<std::vector<uint32_t>>& o_vpd_supported_freqs)
{
- uint8_t l_vpd_blob[TT::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;
@@ -281,12 +314,9 @@ fapi2::ReturnCode vpd_supported_freqs( const fapi2::Target<TT::FREQ_TARGET_TYPE>
o_vpd_supported_freqs.push_back(std::vector<uint32_t>());
}
- fapi2::VPDInfo<TT::VPD_TARGET_TYPE> l_vpd_info(TT::VPD_BLOB);
-
// Just go to find target for the port level
for( const auto& p : mss::find_targets<TT::PORT_TARGET_TYPE>(i_target) )
{
- const auto& l_vpd_target = mss::find_target<TT::VPD_TARGET_TYPE>(p);
const auto l_port_pos = mss::relative_pos<TT::FREQ_TARGET_TYPE>(p);
FAPI_TRY( configured_ports.setBit(l_port_pos) );
@@ -302,61 +332,21 @@ fapi2::ReturnCode vpd_supported_freqs( const fapi2::Target<TT::FREQ_TARGET_TYPE>
continue;
}
- // Configures the number of ranks for the VPD configuration
- FAPI_TRY( configure_vpd_ranks<P>(p, l_vpd_info), "%s failed to configure VPD ranks", mss::c_str(p));
- l_vpd_info.iv_is_config_ffdc_enabled = false;
-
// Iterate through all supported memory freqs
for( const auto& freq : TT::SUPPORTED_FREQS )
{
- l_vpd_info.iv_freq_mhz = freq;
+ bool l_supported = false;
- 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);
+ FAPI_TRY(check_freq_support_vpd<P>(p, freq, l_supported));
- // 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.
-
- // So, we'll use VPD access for the IBM specific product data (assuming the vendor of the OCMB's side as well)
- if( fapi2::getVPD(l_vpd_target, 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;
- }
-
- // Need temporary variables to avoid issues with FAPI_ASSERT and templated variables
- {
- const auto VPD_KW_MAX = TT::VPD_KEYWORD_MAX;
- const auto VPD_BLOB = TT::VPD_BLOB;
- FAPI_ASSERT( l_vpd_info.iv_size <= TT::VPD_KEYWORD_MAX,
- fapi2::MSS_INVALID_VPD_KEYWORD_MAX().
- set_MAX(VPD_KW_MAX).
- set_ACTUAL(l_vpd_info.iv_size).
- set_KEYWORD(VPD_BLOB).
- set_MCS_TARGET(i_target),
- "VPD MR keyword size retrieved: %d, is larger than max: %d for %s",
- l_vpd_info.iv_size, TT::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(l_vpd_target, l_vpd_info, &(l_vpd_blob[0])) != fapi2::FAPI2_RC_SUCCESS )
+ // Add supported freqs to our output
+ if (l_supported)
{
- FAPI_INF("Couldn't retrieve %s data from VPD for this config %s -- skipping freq %d MT/s", TT::VPD_BLOB_NAME,
- mss::c_str(p), freq );
-
- fapi2::current_err = fapi2::FAPI2_RC_SUCCESS;
- continue;
+ FAPI_INF("VPD supported freq added: %d for %s", freq, mss::c_str(p) );
+ o_vpd_supported_freqs[l_port_pos].push_back(freq);
}
-
- // 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
+ }
+ }
// Mark any ports we didn't visit as supporting all frequencies
for ( uint64_t l_port_pos = 0; l_port_pos < TT::PORTS_PER_FREQ_DOMAIN; ++l_port_pos )
@@ -468,13 +458,13 @@ inline fapi2::ReturnCode supported_freqs(const fapi2::Target<TT::FREQ_TARGET_TYP
o_freqs.clear();
freq_scoreboard l_scoreboard(TT::PORTS_PER_FREQ_DOMAIN, TT::SUPPORTED_FREQS);
- std::vector<uint32_t> l_max_freqs(NUM_MAX_FREQS, 0);
+ std::vector<uint32_t> l_max_mrw_freqs(NUM_MAX_FREQS, 0);
std::vector<std::vector<uint32_t>> l_vpd_supported_freqs;
std::vector<uint32_t> l_spd_supported_freq;
std::vector<uint8_t> l_deconfigured = {0};
// Retrieve system MRW, SPD, and VPD constraints
- FAPI_TRY( max_allowed_dimm_freq<P>(l_max_freqs.data()), "%s max_allowed_dimm_freq", mss::c_str(i_target) );
+ FAPI_TRY( max_allowed_dimm_freq<P>(l_max_mrw_freqs.data()), "%s max_allowed_dimm_freq", mss::c_str(i_target) );
FAPI_TRY( spd_supported_freq<P>(i_target, l_spd_supported_freq),
"%s spd supported freqs", mss::c_str(i_target) );
FAPI_TRY( vpd_supported_freqs<P>(i_target, l_vpd_supported_freqs),
@@ -484,7 +474,7 @@ inline fapi2::ReturnCode supported_freqs(const fapi2::Target<TT::FREQ_TARGET_TYP
FAPI_TRY( limit_freq_by_processor<P>(i_target, l_scoreboard) );
// Limit frequency scoreboard according to MRW constraints
- FAPI_TRY( limit_freq_by_mrw<P>(i_target, l_max_freqs, l_scoreboard) );
+ FAPI_TRY( limit_freq_by_mrw<P>(i_target, l_max_mrw_freqs, l_scoreboard) );
// Limit frequency scoreboard according to VPD constraints
FAPI_TRY( limit_freq_by_vpd<P>(i_target, l_vpd_supported_freqs, l_scoreboard) );
@@ -537,9 +527,6 @@ fapi2::ReturnCode generate_freq(const fapi2::Target<TT::FREQ_TARGET_TYPE>& i_tar
std::vector<uint64_t> l_min_dimm_freq;
std::vector<uint32_t> l_supported_freqs;
- // We will first set pre-eff_config attributes
- FAPI_TRY( mss::set_pre_init_attrs<P>(i_target));
-
// Get supported freqs for this MCBIST
FAPI_TRY( mss::supported_freqs<P>(i_target, l_supported_freqs), "%s failed to get supported frequencies",
mss::c_str(i_target) );
diff --git a/src/import/generic/memory/lib/utils/freq/gen_mss_freq_traits.H b/src/import/generic/memory/lib/utils/freq/gen_mss_freq_traits.H
index 791fa5b97..5c6e31ab3 100644
--- a/src/import/generic/memory/lib/utils/freq/gen_mss_freq_traits.H
+++ b/src/import/generic/memory/lib/utils/freq/gen_mss_freq_traits.H
@@ -5,7 +5,7 @@
/* */
/* OpenPOWER HostBoot Project */
/* */
-/* Contributors Listed Below - COPYRIGHT 2018 */
+/* Contributors Listed Below - COPYRIGHT 2018,2019 */
/* [+] International Business Machines Corp. */
/* */
/* */
@@ -36,9 +36,7 @@
#ifndef _GEN_MSS_FREQ_TRAITS_H_
#define _GEN_MSS_FREQ_TRAITS_H_
-#include <fapi2.H>
#include <generic/memory/lib/utils/shared/mss_generic_consts.H>
-#include <vpd_access.H>
namespace mss
{
@@ -50,52 +48,5 @@ namespace mss
template< mss::proc_type P >
class frequency_traits;
-///
-/// @class Traits and policy class for frequency and synchronous code - specialization for the NIMBUS processor type
-///
-template<>
-class frequency_traits<mss::proc_type::NIMBUS>
-{
- public:
- //////////////////////////////////////////////////////////////
- // Target types
- //////////////////////////////////////////////////////////////
- static constexpr fapi2::TargetType PORT_TARGET_TYPE = fapi2::TARGET_TYPE_MCA;
- static constexpr fapi2::TargetType FREQ_TARGET_TYPE = fapi2::TARGET_TYPE_MCBIST;
- static constexpr fapi2::TargetType VPD_TARGET_TYPE = fapi2::TARGET_TYPE_MCS;
-
- //////////////////////////////////////////////////////////////
- // Traits values
- //////////////////////////////////////////////////////////////
- static const std::vector<uint64_t> SUPPORTED_FREQS;
- // MCBIST is our frequency domain. So 4 ports per MCBIST
- static constexpr uint64_t PORTS_PER_FREQ_DOMAIN = 4;
- // 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 Nimbus is constant - NIMBUS
- static constexpr mss::mc_type MC = mss::mc_type::NIMBUS;
- static constexpr const char* PROC_STR = "NIMBUS";
-
- // VPD traits values
- // VPD keyword max is slightly repeated (it's in NIMBUS consts too)
- static constexpr uint64_t VPD_KEYWORD_MAX = 255;
- static constexpr const char* VPD_BLOB_NAME = "MR";
- static constexpr auto VPD_BLOB = fapi2::MemVpdData::MR;
- 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_1866;
- static constexpr uint64_t SUPPORTED_FREQ1 = DIMM_SPEED_2133;
- static constexpr uint64_t SUPPORTED_FREQ2 = DIMM_SPEED_2400;
- static constexpr uint64_t SUPPORTED_FREQ3 = DIMM_SPEED_2666;
-};
-
-
} // ns mss
#endif
diff --git a/src/import/generic/memory/lib/utils/freq/mss_freq_scoreboard.H b/src/import/generic/memory/lib/utils/freq/mss_freq_scoreboard.H
index 104bf38ca..cf96a1f5d 100644
--- a/src/import/generic/memory/lib/utils/freq/mss_freq_scoreboard.H
+++ b/src/import/generic/memory/lib/utils/freq/mss_freq_scoreboard.H
@@ -5,7 +5,7 @@
/* */
/* OpenPOWER HostBoot Project */
/* */
-/* Contributors Listed Below - COPYRIGHT 2018 */
+/* Contributors Listed Below - COPYRIGHT 2018,2019 */
/* [+] International Business Machines Corp. */
/* */
/* */
@@ -574,7 +574,7 @@ inline fapi2::ReturnCode limit_freq_by_mrw(const fapi2::Target<TT::FREQ_TARGET_T
FAPI_ASSERT( (l_dimms_on_port <= TT::MAX_DIMM_PER_PORT),
fapi2::MSS_TOO_MANY_DIMMS_ON_PORT()
.set_DIMM_COUNT(l_dimms_on_port)
- .set_MCA_TARGET(p),
+ .set_PORT_TARGET(p),
"Seeing %d DIMM on port %s",
l_dimms_on_port,
mss::c_str(p));
diff --git a/src/import/generic/memory/lib/utils/mss_math.H b/src/import/generic/memory/lib/utils/mss_math.H
index b60cbc2ae..ebb3da8e3 100644
--- a/src/import/generic/memory/lib/utils/mss_math.H
+++ b/src/import/generic/memory/lib/utils/mss_math.H
@@ -5,7 +5,7 @@
/* */
/* OpenPOWER HostBoot Project */
/* */
-/* Contributors Listed Below - COPYRIGHT 2017 */
+/* Contributors Listed Below - COPYRIGHT 2017,2019 */
/* [+] International Business Machines Corp. */
/* */
/* */
@@ -71,6 +71,42 @@ inline int64_t round_half_away_from_zero( const double i_input )
return ( i_input < 0.0 ? static_cast<int64_t>(i_input - 0.5) : static_cast<int64_t>(i_input + 0.5) );
}
+///
+/// @brief Divide and round unsigned values
+/// @tparam T input and output types
+/// @param[in] i_divisor the divisor (number to be divided)
+/// @param[in] i_dividend the dividend (number to divide by)
+/// @param[out] o_quotient the quotient
+/// @return FAPI2_RC_SUCCESS iff successful
+///
+template<typename T>
+inline fapi2::ReturnCode divide_and_round( const T i_divisor,
+ const T i_dividend,
+ T& o_quotient )
+{
+ o_quotient = 0;
+
+ // Zero dividend would cause a divide-by-zero, so prevent that
+ FAPI_ASSERT( (i_dividend != 0),
+ fapi2::MSS_DIVIDE_BY_ZERO()
+ .set_DIVISOR(i_divisor)
+ .set_DIVIDEND(i_dividend),
+ "Caught an attempt to divide by zero (%d / %d)",
+ i_divisor, i_dividend );
+
+ {
+ const auto l_quotient_unrounded = i_divisor / i_dividend;
+ const auto l_remainder = i_divisor % i_dividend;
+
+ // Round the quotient up or down depending on the remainder
+ o_quotient = l_quotient_unrounded + ((l_remainder >= i_dividend / 2) ? 1 : 0);
+ }
+ return fapi2::FAPI2_RC_SUCCESS;
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
}// mss
diff --git a/src/import/generic/memory/lib/utils/shared/mss_generic_consts.H b/src/import/generic/memory/lib/utils/shared/mss_generic_consts.H
index f7f2338fb..7a15bdfe0 100644
--- a/src/import/generic/memory/lib/utils/shared/mss_generic_consts.H
+++ b/src/import/generic/memory/lib/utils/shared/mss_generic_consts.H
@@ -5,7 +5,7 @@
/* */
/* OpenPOWER HostBoot Project */
/* */
-/* Contributors Listed Below - COPYRIGHT 2018 */
+/* Contributors Listed Below - COPYRIGHT 2018,2019 */
/* [+] Evan Lojewski */
/* [+] International Business Machines Corp. */
/* */
@@ -136,9 +136,11 @@ enum generic_ffdc_codes
LIMIT_FREQ_BY_VPD = 0x1025,
SET_DIMM_TYPE = 0x1026,
SET_DRAM_GEN = 0x1027,
- SET_HYBRID = 0x1027,
- SET_HYBRID_MEDIA = 0x1028,
- SET_MRANKS = 0x1029,
+ SET_HYBRID = 0x1028,
+ SET_HYBRID_MEDIA = 0x1029,
+ SET_MRANKS = 0x102A,
+ SET_HOST_TO_DDR_SPEED_RATIO = 0x102B,
+ SET_ATTR_HOST_TO_DDR_SPEED_RATIO = 0x102C,
SET_DIMM_RANKS_CNFG = 0x1039,
DDIMM_RAWCARD_DECODE = 0x103a,
SET_DRAM_WIDTH = 0x1040,
@@ -240,6 +242,14 @@ enum states
NO_CHIP_SELECT_ACTIVE = 0xFF,
};
+///
+/// @brief Supported DIMM speed equality deliberations
+///
+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
+};
namespace spd
{
OpenPOWER on IntegriCloud