summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorJacob Harvey <jlharvey@us.ibm.com>2017-05-02 11:17:07 -0500
committerDaniel M. Crowell <dcrowell@us.ibm.com>2017-05-24 22:40:14 -0400
commite734170c132ccb53b65d24c5f89955b1250cf150 (patch)
tree79a5fc73f559b9296d20dcc2162585bbca1cf9f7 /src
parent53ec24514b4c367250bc73ee2317996992bcf0d1 (diff)
downloadtalos-hostboot-e734170c132ccb53b65d24c5f89955b1250cf150.tar.gz
talos-hostboot-e734170c132ccb53b65d24c5f89955b1250cf150.zip
Change cas latency to be per MCA
Change-Id: I61684fe0b69c72dea4c79ad248f8928a007ffb0f Reviewed-on: http://ralgit01.raleigh.ibm.com/gerrit1/40052 Reviewed-by: STEPHEN GLANCY <sglancy@us.ibm.com> Reviewed-by: Louis Stermole <stermole@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: Thi N. Tran <thi@us.ibm.com> Dev-Ready: JACOB L. HARVEY <jlharvey@us.ibm.com> Reviewed-by: Jennifer A. Stofer <stofer@us.ibm.com> Reviewed-on: http://ralgit01.raleigh.ibm.com/gerrit1/40501 Reviewed-by: Hostboot Team <hostboot@us.ibm.com> Tested-by: Jenkins OP Build CI <op-jenkins+hostboot@us.ibm.com> Reviewed-by: Daniel M. Crowell <dcrowell@us.ibm.com>
Diffstat (limited to 'src')
-rw-r--r--src/import/chips/p9/procedures/hwp/memory/lib/freq/cas_latency.C9
-rw-r--r--src/import/chips/p9/procedures/hwp/memory/lib/freq/cas_latency.H6
-rw-r--r--src/import/chips/p9/procedures/hwp/memory/lib/freq/sync.C98
-rw-r--r--src/import/chips/p9/procedures/hwp/memory/lib/freq/sync.H8
-rw-r--r--src/import/chips/p9/procedures/hwp/memory/lib/spd/spd_factory.C53
-rw-r--r--src/import/chips/p9/procedures/hwp/memory/lib/spd/spd_factory.H55
-rw-r--r--src/import/chips/p9/procedures/hwp/memory/p9_mss_freq.C112
-rw-r--r--src/import/chips/p9/procedures/hwp/memory/p9_mss_freq.H45
-rw-r--r--src/import/chips/p9/procedures/xml/error_info/p9_memory_mss_freq.xml15
-rw-r--r--src/import/generic/memory/lib/utils/find.H28
10 files changed, 247 insertions, 182 deletions
diff --git a/src/import/chips/p9/procedures/hwp/memory/lib/freq/cas_latency.C b/src/import/chips/p9/procedures/hwp/memory/lib/freq/cas_latency.C
index 490b0677b..1a9490a8e 100644
--- a/src/import/chips/p9/procedures/hwp/memory/lib/freq/cas_latency.C
+++ b/src/import/chips/p9/procedures/hwp/memory/lib/freq/cas_latency.C
@@ -77,7 +77,7 @@ enum invalid_timing_function_encoding
/// @param[in] i_caches decoder caches
/// @param[out] o_rc returns FAPI2_RC_SUCCESS if constructor initialzed successfully
///
-cas_latency::cas_latency(const fapi2::Target<fapi2::TARGET_TYPE_MCS>& i_target,
+cas_latency::cas_latency(const fapi2::Target<fapi2::TARGET_TYPE_MCA>& i_target,
const std::vector< std::shared_ptr<spd::decoder> >& i_caches,
fapi2::ReturnCode& o_rc ):
iv_dimm_list_empty(false),
@@ -86,7 +86,6 @@ cas_latency::cas_latency(const fapi2::Target<fapi2::TARGET_TYPE_MCS>& i_target,
iv_proposed_tck(0),
iv_common_cl(UINT64_MAX) // Masks out supported CLs
{
-
if( i_caches.empty() )
{
FAPI_INF("cas latency ctor seeing no SPD caches for %s", mss::c_str(i_target) );
@@ -96,7 +95,7 @@ cas_latency::cas_latency(const fapi2::Target<fapi2::TARGET_TYPE_MCS>& i_target,
for ( const auto& l_cache : i_caches )
{
- // Retrive timing values from the SPD
+ // Retrieve timing values from the SPD
uint64_t l_taa_min_in_ps = 0;
uint64_t l_tckmax_in_ps = 0;
uint64_t l_tck_min_in_ps = 0;
@@ -191,7 +190,7 @@ fapi_try_exit:
/// @param[in] i_common_cl_mask common CAS latency mask we want to force (bitmap)
/// @param[in] i_is_3ds boolean for whether this is a 3DS SDRAM, 3DS is true, false otherwise (default)
///
-cas_latency::cas_latency(const fapi2::Target<fapi2::TARGET_TYPE_MCS>& i_target,
+cas_latency::cas_latency(const fapi2::Target<fapi2::TARGET_TYPE_MCA>& i_target,
const uint64_t i_taa_min,
const uint64_t i_tck_min,
const uint64_t i_common_cl_mask,
@@ -244,7 +243,7 @@ fapi2::ReturnCode cas_latency::find_cl(uint64_t& o_cas_latency,
}
// Update output values after all criteria is met
- // If the MCS has no dimm configured than both
+ // If the MCA has no dimm configured than both
// l_desired_latency & iv_proposed_tck is 0 by initialization
o_cas_latency = l_desired_cas_latency;
o_tck = iv_proposed_tck;
diff --git a/src/import/chips/p9/procedures/hwp/memory/lib/freq/cas_latency.H b/src/import/chips/p9/procedures/hwp/memory/lib/freq/cas_latency.H
index baf44ffae..7a323270b 100644
--- a/src/import/chips/p9/procedures/hwp/memory/lib/freq/cas_latency.H
+++ b/src/import/chips/p9/procedures/hwp/memory/lib/freq/cas_latency.H
@@ -84,7 +84,7 @@ class cas_latency
/// @param[in] i_caches decoder caches
/// @param[out] o_rc returns FAPI2_RC_SUCCESS if constructor initialzed successfully
///
- cas_latency(const fapi2::Target<fapi2::TARGET_TYPE_MCS>& i_target_mcs,
+ cas_latency(const fapi2::Target<fapi2::TARGET_TYPE_MCA>& i_target_mcs,
const std::vector< std::shared_ptr<spd::decoder> >& i_caches,
fapi2::ReturnCode& o_rc);
@@ -96,7 +96,7 @@ class cas_latency
/// @param[in] i_is_3ds loading::IS_3DS if this is for 3DS,
/// loading::NOT_3DS otherwise (default)
///
- cas_latency(const fapi2::Target<fapi2::TARGET_TYPE_MCS>& i_target,
+ cas_latency(const fapi2::Target<fapi2::TARGET_TYPE_MCA>& i_target,
const uint64_t i_taa_min,
const uint64_t i_tck_min,
const uint64_t i_common_cl_mask,
@@ -144,7 +144,7 @@ class cas_latency
/////////////////////////
// Private variables
/////////////////////////
- fapi2::Target<fapi2::TARGET_TYPE_MCS> iv_target;
+ fapi2::Target<fapi2::TARGET_TYPE_MCA> iv_target;
uint64_t iv_largest_taamin;// cas latency time
uint64_t iv_proposed_tck;// cycle time
uint64_t iv_common_cl; // common cas latency
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 73f99cd7a..5513224d8 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
@@ -300,14 +300,14 @@ fapi_try_exit:
///
/// @brief Create and sort a vector of supported MT/s (freq)
-/// @param[in] MCS target for which to get the DIMM configs
+/// @param[in] MCA target for which to get the DIMM configs
/// @param[in,out] reference to a std::vector<uint32_t> space 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
/// 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_MCS>& i_target, std::vector<uint32_t>& io_freqs)
+fapi2::ReturnCode supported_freqs(const fapi2::Target<TARGET_TYPE_MCA>& i_target, std::vector<uint32_t>& io_freqs)
{
std::vector<uint32_t> l_freqs(NUM_VPD_FREQS, 0);
std::vector<uint32_t> l_max_freqs(NUM_MAX_FREQS, 0);
@@ -337,7 +337,7 @@ fapi_try_exit:
///
/// @brief Create and sort a vector of supported MT/s (freq) - helper for testing purposes
-/// @param[in] MCS target for which to get the DIMM configs
+/// @param[in] MCA target for which to get the DIMM configs
/// @param[in] vector of MVPD freqs
/// @param[in] vector of max allowed freqs
/// @param[in] bool whether or not we're forced into sync mode
@@ -347,7 +347,7 @@ fapi_try_exit:
/// 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_MCS>& i_target,
+fapi2::ReturnCode supported_freqs_helper(const fapi2::Target<TARGET_TYPE_MCA>& i_target,
const std::vector<uint32_t>& i_freqs,
const std::vector<uint32_t>& i_max_freqs,
const bool i_req_sync_mode,
@@ -388,55 +388,53 @@ fapi2::ReturnCode supported_freqs_helper(const fapi2::Target<TARGET_TYPE_MCS>& i
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]);
- // Given the max supported freqs, find the config based on our DIMMs. There's no great way to do this ...
- for (const auto& p : mss::find_targets<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();
+
+ 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),
+ "Seeing %d DIMM on port %s",
+ l_dimms_on_port,
+ mss::c_str(i_target));
+
+ for (const auto& d : l_dimms)
{
- const auto l_dimms = mss::find_targets<TARGET_TYPE_DIMM>(p);
- 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(p),
- "Seeing %d DIMM on port %s",
+ 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_RANK_PER_DIMM),
+ 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(p));
+ mss::c_str(d));
+
+ l_index = l_indexes[l_dimms_on_port - 1][l_num_master_ranks - 1];
+
+ 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_index,
+ i_max_freqs[l_index] );
+
+ 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));
- 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_RANK_PER_DIMM),
- fapi2::MSS_TOO_MANY_PRIMARY_RANKS_ON_DIMM()
- .set_RANK_COUNT(l_num_master_ranks)
- .set_DIMM_TARGET(p),
- "seeing %d primary ranks on DIMM %s",
- l_dimms_on_port,
- 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_freqs[l_indexes[l_dimms_on_port - 1][l_num_master_ranks - 1]] );
-
- 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));
-
- l_our_max_freq = std::min(l_our_max_freq, i_max_freqs[l_index]);
- }
+ 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);
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 15f926c1b..a5d8dfaff 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
@@ -90,7 +90,7 @@ fapi2::ReturnCode select_sync_mode(const std::map< fapi2::Target<fapi2::TARGET_T
///
/// @brief Create and sort a vector of supported MT/s (freq) - helper for testing purposes
-/// @param[in] MCS target for which to get the DIMM configs
+/// @param[in] MCA target for which to get the DIMM configs
/// @param[in] vector of MVPD freqs
/// @param[in] vector of max allowed freqs
/// @param[in] bool whether or not we're forced into sync mode
@@ -100,7 +100,7 @@ fapi2::ReturnCode select_sync_mode(const std::map< fapi2::Target<fapi2::TARGET_T
/// 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_helper(const fapi2::Target<fapi2::TARGET_TYPE_MCS>& i_target,
+fapi2::ReturnCode supported_freqs_helper(const fapi2::Target<fapi2::TARGET_TYPE_MCA>& i_target,
const std::vector<uint32_t>& i_freqs,
const std::vector<uint32_t>& i_max_freqs,
const bool i_req_sync_mode,
@@ -108,14 +108,14 @@ fapi2::ReturnCode supported_freqs_helper(const fapi2::Target<fapi2::TARGET_TYPE_
///
/// @brief Create and sort a vector of supported MT/s (freq)
-/// @param[in] MCS target for which to get the DIMM configs
+/// @param[in] MCA target for which to get the DIMM configs
/// @param[in,out] reference to a std::vector<uint32_t> space 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
/// 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_MCS>& i_target,
+fapi2::ReturnCode supported_freqs(const fapi2::Target<fapi2::TARGET_TYPE_MCA>& i_target,
std::vector<uint32_t>& io_freqs);
///
diff --git a/src/import/chips/p9/procedures/hwp/memory/lib/spd/spd_factory.C b/src/import/chips/p9/procedures/hwp/memory/lib/spd/spd_factory.C
index e46b4a8cb..f61ba52b0 100644
--- a/src/import/chips/p9/procedures/hwp/memory/lib/spd/spd_factory.C
+++ b/src/import/chips/p9/procedures/hwp/memory/lib/spd/spd_factory.C
@@ -378,7 +378,7 @@ fapi_try_exit:
/// @note This is done after the SPD cache is configured so that it can reflect the results of the
/// factory and we don't need to worry about SPD versions. This is expressly different than the dram and dimm setters
///
-static fapi2::ReturnCode master_ranks_per_dimm_setter(const fapi2::Target<TARGET_TYPE_DIMM>& i_target,
+fapi2::ReturnCode master_ranks_per_dimm_setter(const fapi2::Target<TARGET_TYPE_DIMM>& i_target,
const std::shared_ptr<decoder>& i_pDecoder)
{
const auto l_mcs = find_target<TARGET_TYPE_MCS>(i_target);
@@ -759,57 +759,6 @@ fapi_try_exit:
///
/// @brief Creates factory object & SPD data caches
-/// @param[in] i_target controller target
-/// @param[out] o_factory_caches vector of factory objects
-/// @param[in] i_pDecoder custom decoder to populate cache (ignored for this specialization)
-/// @return FAPI2_RC_SUCCESS if okay
-/// @note This specialization is suited for creating a cache with platform
-/// SPD data.
-///
-template<>
-fapi2::ReturnCode populate_decoder_caches( const fapi2::Target<TARGET_TYPE_MCS>& i_target,
- std::vector< std::shared_ptr<decoder> >& o_factory_caches,
- const std::shared_ptr<decoder>& i_pDecoder)
-{
- // Input decoder for this version of populating cache would get overriden
- // so I don't bother with it in this specialization
- std::shared_ptr<decoder> l_pDecoder;
-
- for( const auto& l_dimm : find_targets<TARGET_TYPE_DIMM>(i_target) )
- {
- size_t l_size = 0;
- FAPI_TRY( fapi2::getSPD(l_dimm, nullptr, l_size),
- "%s. Failed to retrieve SPD blob size", mss::c_str(i_target) );
-
- {
- // "Container" for SPD data
- std::vector<uint8_t> l_spd(l_size);
-
- // Retrive SPD data
- FAPI_TRY( fapi2::getSPD(l_dimm, l_spd.data(), l_size),
- "%s. Failed to retrieve SPD data", mss::c_str(i_target) );
-
- // Retrieve factory object instance & populate spd data for that instance
- FAPI_TRY( factory(l_dimm, l_spd, l_pDecoder),
- "%s. Failed SPD factory, could not instantiate decoder object", mss::c_str(i_target) );
-
- // Populate spd caches
- o_factory_caches.push_back( l_pDecoder );
- }
-
- // Populate some of the DIMM attributes early. This allows the following code to make
- // decisions based on DIMM information. Expressly done after the factory has decided on the SPD version
- FAPI_TRY( master_ranks_per_dimm_setter(l_dimm, l_pDecoder),
- "%s. Failed master_ranks_per_dimm_setter()", mss::c_str(i_target) );
-
- }// end dimm
-
-fapi_try_exit:
- return fapi2::current_err;
-}
-
-///
-/// @brief Creates factory object & SPD data caches
/// @param[in] i_target the dimm target
/// @param[out] o_factory_caches vector of factory objects
/// @param[in] i_pDecoder custom decoder to populate cache (nullptr default)
diff --git a/src/import/chips/p9/procedures/hwp/memory/lib/spd/spd_factory.H b/src/import/chips/p9/procedures/hwp/memory/lib/spd/spd_factory.H
index 29f6804ba..4087bf464 100644
--- a/src/import/chips/p9/procedures/hwp/memory/lib/spd/spd_factory.H
+++ b/src/import/chips/p9/procedures/hwp/memory/lib/spd/spd_factory.H
@@ -42,9 +42,11 @@
// fapi2
#include <fapi2.H>
+#include <fapi2_spd_access.H>
// mss lib
#include <generic/memory/lib/spd/common/ddr4/spd_decoder_ddr4.H>
+#include <generic/memory/lib/utils/find.H>
namespace mss
{
@@ -147,9 +149,22 @@ fapi2::ReturnCode factory(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target
const std::vector<uint8_t>& i_spd_data,
std::shared_ptr<decoder>& o_fact_obj);
+
+///
+/// @brief Determines & sets effective config for number of master ranks per dimm
+/// @param[in] i_target DIMM fapi2::Target
+/// @param[in] i_pDecoder shared_ptr to SPD decoder
+/// @return fapi2::FAPI2_RC_SUCCESS if okay
+/// @note This is done after the SPD cache is configured so that it can reflect the results of the
+/// factory and we don't need to worry about SPD versions. This is expressly different than the dram and dimm setters
+///
+fapi2::ReturnCode master_ranks_per_dimm_setter(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target,
+ const std::shared_ptr<decoder>& i_pDecoder);
+
///
/// @brief Creates factory object & SPD data caches
-/// @param[in] i_target the fapi2 target
+/// @tparam T fapi2::TargetType, MCA, MCS, MCBIST, PROC_CHIP are possible TargetTypes
+/// @param[in] i_target the fapi2 target to find DIMMs on
/// @param[out] o_factory_caches vector of factory objects
/// @param[in] i_pDecoder optional input decoder to insert custom decoder (nullptr default)
/// @return FAPI2_RC_SUCCESS if okay
@@ -157,8 +172,44 @@ fapi2::ReturnCode factory(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target
template<fapi2::TargetType T>
fapi2::ReturnCode populate_decoder_caches(const fapi2::Target<T>& i_target,
std::vector< std::shared_ptr<decoder> >& o_factory_caches,
- const std::shared_ptr<decoder>& i_pDecoder = nullptr);
+ const std::shared_ptr<decoder>& i_pDecoder = nullptr)
+{
+ // Input decoder for this version of populating cache would get overriden
+ // so I don't bother with it in this specialization
+ std::shared_ptr<decoder> l_pDecoder;
+
+ for( const auto& l_dimm : find_targets<fapi2::TARGET_TYPE_DIMM>(i_target) )
+ {
+ size_t l_size = 0;
+ FAPI_TRY( fapi2::getSPD(l_dimm, nullptr, l_size),
+ "%s. Failed to retrieve SPD blob size", mss::c_str(i_target) );
+
+ {
+ // "Container" for SPD data
+ std::vector<uint8_t> l_spd(l_size);
+
+ // Retrieve SPD data
+ FAPI_TRY( fapi2::getSPD(l_dimm, l_spd.data(), l_size),
+ "%s. Failed to retrieve SPD data", mss::c_str(i_target) );
+
+ // Retrieve factory object instance & populate spd data for that instance
+ FAPI_TRY( factory(l_dimm, l_spd, l_pDecoder),
+ "%s. Failed SPD factory, could not instantiate decoder object", mss::c_str(i_target) );
+
+ // Populate spd caches
+ o_factory_caches.push_back( l_pDecoder );
+ }
+
+ // Populate some of the DIMM attributes early. This allows the following code to make
+ // decisions based on DIMM information. Expressly done after the factory has decided on the SPD version
+ FAPI_TRY( master_ranks_per_dimm_setter(l_dimm, l_pDecoder),
+ "%s. Failed master_ranks_per_dimm_setter()", mss::c_str(i_target) );
+
+ }// end dimm
+fapi_try_exit:
+ return fapi2::current_err;
+}
}// spd
}// mss
diff --git a/src/import/chips/p9/procedures/hwp/memory/p9_mss_freq.C b/src/import/chips/p9/procedures/hwp/memory/p9_mss_freq.C
index 5c3cf9607..5af64ff64 100644
--- a/src/import/chips/p9/procedures/hwp/memory/p9_mss_freq.C
+++ b/src/import/chips/p9/procedures/hwp/memory/p9_mss_freq.C
@@ -28,7 +28,7 @@
/// @brief Calculate and save off DIMM frequencies
///
// *HWP HWP Owner: Andre Marin <aamarin@us.ibm.com>
-// *HWP FW Owner: Brian Silver <bsilver@us.ibm.com>
+// *HWP HWP Backup: Jacob Harvey <jlharvey@us.ibm.com>
// *HWP Team: Memory
// *HWP Level: 1
// *HWP Consumed by: FSP:HB
@@ -63,7 +63,6 @@ using fapi2::FAPI2_RC_SUCCESS;
extern "C"
{
-
///
/// @brief Calculate and save off DIMM frequencies
/// @param[in] i_target, the controller (e.g., MCS)
@@ -80,8 +79,8 @@ extern "C"
// twice for every MC. However, attribute access is cheap so this will suffice for
// the time being.
- std::vector<uint64_t> l_min_dimm_freq(mss::MCS_PER_MC, 0);
- std::vector<uint64_t> l_desired_cas_latency(mss::MCS_PER_MC, 0);
+ std::vector< std::vector<uint64_t> > l_min_dimm_freq(mss::MCS_PER_MC, std::vector<uint64_t> (mss::PORTS_PER_MCS, 0) );
+
const auto& l_mcbist = mss::find_target<TARGET_TYPE_MCBIST>(i_target);
@@ -94,59 +93,69 @@ extern "C"
for (const auto& l_mcs : mss::find_targets<TARGET_TYPE_MCS>(l_mcbist))
{
- const auto l_index = mss::index(l_mcs);
+ const auto l_mcs_index = mss::index(l_mcs);
- // Get cached decoder
- std::vector< std::shared_ptr<mss::spd::decoder> > l_factory_caches;
- FAPI_TRY( mss::spd::populate_decoder_caches(l_mcs, l_factory_caches),
- "%s. Failed to populate decoder cache", mss::c_str(i_target) );
+ std::vector< uint64_t > l_desired_cas_latency(mss::PORTS_PER_MCS, 0 );
+ for (const auto& l_mca : mss::find_targets<TARGET_TYPE_MCA>(l_mcbist))
{
- // instantiation of class that calculates CL algorithm
- fapi2::ReturnCode l_rc;
- mss::cas_latency l_cas_latency( l_mcs, l_factory_caches, l_rc );
- FAPI_TRY( l_rc, "%s. Failed to initialize cas_latency ctor", mss::c_str(i_target) );
-
- if(l_cas_latency.iv_dimm_list_empty)
- {
- // Cannot fail out for an empty DIMM configuration, so default values are set
- FAPI_INF("%s. DIMM list is empty! Setting default values for CAS latency and DIMM speed.",
- mss::c_str(i_target) );
- }
- else
- {
- // We set this to a non-0 so we avoid divide-by-zero errors in the conversions which
- // go from clocks to time (and vice versa.) We have other bugs if there was really
- // no MT/s determined and there really is a DIMM installed, so this is ok.
- // We pick the maximum frequency supported by the system as the default.
- l_min_dimm_freq[l_index] = fapi2::ENUM_ATTR_MSS_FREQ_MT2666;
-
- uint64_t l_tCKmin = 0;
-
- // Find CAS latency using JEDEC algorithm
- FAPI_TRY( l_cas_latency.find_cl(l_desired_cas_latency[l_index],
- l_tCKmin) );
+ const auto l_index = mss::index(l_mca);
- FAPI_INF("%s. Result from CL algorithm, CL (nck): %d, tCK (ps): %d",
- mss::c_str(i_target), l_desired_cas_latency[l_index], l_tCKmin);
+ // Get cached decoder
+ std::vector< std::shared_ptr<mss::spd::decoder> > l_factory_caches;
- // Find dimm transfer speed from selected tCK
- FAPI_TRY( mss::ps_to_freq(l_tCKmin, l_min_dimm_freq[l_index]),
- "%s. Failed ps_to_freq()", mss::c_str(i_target) );
+ FAPI_TRY( mss::spd::populate_decoder_caches(l_mca, l_factory_caches),
+ "%s. Failed to populate decoder cache", mss::c_str(i_target) );
- FAPI_INF("DIMM speed from selected tCK (ps): %d for %s", l_min_dimm_freq[l_index], mss::c_str(l_mcs));
-
- FAPI_TRY(mss::select_supported_freq(l_mcs, l_min_dimm_freq[l_index]),
- "Failed select_supported_freq() for %s", mss::c_str(l_mcs));
-
- FAPI_INF("%s. Selected DIMM speed from supported speeds: %d",
- mss::c_str(i_target), l_min_dimm_freq[l_index]);
-
- }// end else
-
- } // close scope
-
- FAPI_TRY(mss::set_CL_attr(l_mcs, l_desired_cas_latency[l_index] ),
+ {
+ // instantiation of class that calculates CL algorithm
+ fapi2::ReturnCode l_rc;
+ mss::cas_latency l_cas_latency( l_mca, l_factory_caches, l_rc );
+ FAPI_TRY( l_rc, "%s. Failed to initialize cas_latency ctor", mss::c_str(i_target) );
+
+ if(l_cas_latency.iv_dimm_list_empty)
+ {
+ // Cannot fail out for an empty DIMM configuration, so default values are set
+ FAPI_INF("%s. DIMM list is empty! Setting default values for CAS latency and DIMM speed.",
+ mss::c_str(i_target) );
+ }
+ else
+ {
+ // We set this to a non-0 so we avoid divide-by-zero errors in the conversions which
+ // go from clocks to time (and vice versa.) We have other bugs if there was really
+ // no MT/s determined and there really is a DIMM installed, so this is ok.
+ // We pick the maximum frequency supported by the system as the default.
+ l_min_dimm_freq[l_mcs_index][l_index] = fapi2::ENUM_ATTR_MSS_FREQ_MT2666;
+
+ uint64_t l_tCKmin = 0;
+
+ // Find CAS latency using JEDEC algorithm
+ FAPI_TRY( l_cas_latency.find_cl(l_desired_cas_latency[l_index],
+ l_tCKmin) );
+
+ FAPI_INF("%s. Result from CL algorithm, CL (nck): %d, tCK (ps): %d",
+ mss::c_str(i_target), l_desired_cas_latency[l_index], l_tCKmin);
+
+ // Find dimm transfer speed from selected tCK
+ FAPI_TRY( mss::ps_to_freq(l_tCKmin, l_min_dimm_freq[l_mcs_index][l_index]),
+ "%s. Failed ps_to_freq()", mss::c_str(i_target) );
+
+ FAPI_INF("DIMM speed from selected tCK (ps): %d for %s",
+ l_min_dimm_freq[l_mcs_index][l_index],
+ mss::c_str(l_mca));
+
+ FAPI_TRY(mss::select_supported_freq(l_mca, l_min_dimm_freq[l_mcs_index][l_index]),
+ "Failed select_supported_freq() for %s", mss::c_str(l_mca));
+
+ FAPI_INF("%s. Selected DIMM speed from supported speeds: %d",
+ mss::c_str(i_target), l_min_dimm_freq[l_mcs_index][l_index]);
+
+ }// end else
+
+ } // close scope
+ } // End
+
+ FAPI_TRY(mss::set_CL_attr(l_mcs, l_desired_cas_latency),
"%s. Failed set_CL_attr()", mss::c_str(i_target) );
} // close for each mcs
@@ -158,5 +167,4 @@ extern "C"
return fapi2::current_err;
}// p9_mss_freq
-
}// extern C
diff --git a/src/import/chips/p9/procedures/hwp/memory/p9_mss_freq.H b/src/import/chips/p9/procedures/hwp/memory/p9_mss_freq.H
index 3f24856bf..7f1a51771 100644
--- a/src/import/chips/p9/procedures/hwp/memory/p9_mss_freq.H
+++ b/src/import/chips/p9/procedures/hwp/memory/p9_mss_freq.H
@@ -5,7 +5,7 @@
/* */
/* OpenPOWER HostBoot Project */
/* */
-/* Contributors Listed Below - COPYRIGHT 2015,2016 */
+/* Contributors Listed Below - COPYRIGHT 2015,2017 */
/* [+] International Business Machines Corp. */
/* */
/* */
@@ -48,26 +48,44 @@ namespace mss
///
/// @brief Sets DRAM CAS latency attributes
/// @param[in] i_target the controller target
-/// @param[in] i_cas_latency final selected CAS ltency
+/// @param[in] i_cas_latency vector of the two final selected CAS latencies
/// @return FAPI2_RC_SUCCESS iff ok
///
inline fapi2::ReturnCode set_CL_attr(const fapi2::Target<fapi2::TARGET_TYPE_MCS>& i_target,
- uint64_t i_cas_latency)
+ std::vector< uint64_t >& i_cas_latency)
{
- std::vector<uint8_t> l_cls(PORTS_PER_MCS, 0);
+ // 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] = {};
- // Set configured ports
for( const auto& p : find_targets<fapi2::TARGET_TYPE_MCA>(i_target) )
{
- l_cls[mss::index(p)] = i_cas_latency;
- FAPI_INF( "Final Chosen CL: %d for %s", i_cas_latency, mss::c_str(p));
+ // Local variable instead of calling it three times. Hopefully compiler can optimize this better
+ const auto l_index = mss::index(p);
+
+ if ( l_index >= PORTS_PER_MCS)
+ {
+ FAPI_ERR("%s mss::index returned a value greater than PORTS_PER_MCS", mss::c_str(i_target) );
+ fapi2::Assert(false);
+ }
+
+ l_temp[l_index] = i_cas_latency[l_index];
+ FAPI_ASSERT( l_temp[l_index] == i_cas_latency[l_index],
+ fapi2::MSS_BAD_CL_CAST()
+ .set_CL(i_cas_latency[l_index])
+ .set_MCA_TARGET(p),
+ "%s bad cast for cas latency from %d to %d",
+ mss::c_str(i_target),
+ i_cas_latency[l_index],
+ l_temp[l_index]);
+ FAPI_INF( "Final Chosen CL: %d for %s", l_temp[l_index], mss::c_str(p));
}
// set CAS latency attribute
// casts vector into the type FAPI_ATTR_SET is expecting by deduction
FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_EFF_DRAM_CL,
i_target,
- UINT8_VECTOR_TO_1D_ARRAY(l_cls, PORTS_PER_MCS)) ,
+ l_temp) ,
"Failed to set CAS latency attribute");
fapi_try_exit:
@@ -81,17 +99,20 @@ fapi_try_exit:
/// @return FAPI2_RC_SUCCESS iff ok
///
inline fapi2::ReturnCode set_freq_attrs(const fapi2::Target<fapi2::TARGET_TYPE_MCBIST>& i_target,
- const std::vector<uint64_t>& i_dimm_freq)
+ const std::vector< std::vector<uint64_t> >& i_dimm_freq)
{
// Find the minimum (but non-0) freq in the vector. If we see all 0's we'll write a 0. However,
// we shouldn't as the caller should have been dealing with no DIMM before we got here.
uint64_t l_final_freq = UINT64_MAX;
- for (const auto l_freq : i_dimm_freq)
+ for (const auto l_vec : i_dimm_freq)
{
- if (l_freq != 0)
+ for (const auto l_freq : l_vec)
{
- l_final_freq = std::min(l_final_freq, l_freq);
+ if (l_freq != 0)
+ {
+ l_final_freq = std::min(l_final_freq, l_freq);
+ }
}
}
diff --git a/src/import/chips/p9/procedures/xml/error_info/p9_memory_mss_freq.xml b/src/import/chips/p9/procedures/xml/error_info/p9_memory_mss_freq.xml
index 7b4ac84cf..64993ae64 100644
--- a/src/import/chips/p9/procedures/xml/error_info/p9_memory_mss_freq.xml
+++ b/src/import/chips/p9/procedures/xml/error_info/p9_memory_mss_freq.xml
@@ -38,6 +38,21 @@
<hwpErrors>
+ <hwpError>
+ <rc>RC_MSS_BAD_CL_CAST</rc>
+ <description>
+ Calculated Cas Latency exceeds the 8-bit limit. Error calculating
+ </description>
+ <ffdc>CL</ffdc>
+ <callout>
+ <procedure>CODE</procedure>
+ <priority>HIGH</priority>
+ </callout>
+ <callout>
+ <target>MCA_TARGET</target>
+ <priority>MEDIUM</priority>
+ </callout>
+ </hwpError>
<hwpError>
<rc>RC_MSS_INVALID_TIMING_VALUE</rc>
diff --git a/src/import/generic/memory/lib/utils/find.H b/src/import/generic/memory/lib/utils/find.H
index 3641d331f..41d77114b 100644
--- a/src/import/generic/memory/lib/utils/find.H
+++ b/src/import/generic/memory/lib/utils/find.H
@@ -38,7 +38,6 @@
#include <fapi2.H>
#include <vector>
-
#include <generic/memory/lib/utils/pos.H>
#include <generic/memory/lib/utils/c_str.H>
@@ -50,9 +49,17 @@ namespace mss
/// @tparam T the fapi2 target type of the argument
/// @param[in] i_target the fapi2 target T
/// @return a vector of M targets.
+/// @note Only works for valid parent-child relationships
+/// So calling find_targets<TARGET_TYPE_DIMM>(l_mca) will work here
+/// but calling find_targets<TARGET_TYPE_DIMM>(l_mcs) will not work
+/// Compiler will freak out and we'll never get a bad relationship/ error at runtime
+/// If we do, it's on fapi2
///
template< fapi2::TargetType M, fapi2::TargetType T >
-inline std::vector< fapi2::Target<M> > find_targets( const fapi2::Target<T>& i_target);
+inline std::vector< fapi2::Target<M> > find_targets( const fapi2::Target<T>& i_target)
+{
+ return i_target.template getChildren<M>();
+}
///
/// @brief find an element based on a fapi2 target
@@ -60,6 +67,10 @@ inline std::vector< fapi2::Target<M> > find_targets( const fapi2::Target<T>& i_t
/// @tparam T the fapi2 target type of the argument
/// @param[in] i_target the fapi2 target T
/// @return an M target.
+/// @note Only works for valid parent-child relationships
+/// Will work for MCA and DIMM
+/// Will not work for MCS and DIMM
+/// The compiler will let you know if it doesn't work
///
template< fapi2::TargetType M, fapi2::TargetType T >
inline fapi2::Target<M> find_target( const fapi2::Target<T>& i_target )
@@ -223,6 +234,19 @@ inline std::vector< fapi2::Target<fapi2::TARGET_TYPE_MCA> > find_targets
}
///
+/// @brief find all the MCA connected to an MCBIST
+/// @param[in] i_target a fapi2::Target MCBIST
+/// @return a vector of fapi2::TARGET_TYPE_MCA
+///
+template<>
+inline std::vector< fapi2::Target<fapi2::TARGET_TYPE_MCA> > find_targets
+( const fapi2::Target<fapi2::TARGET_TYPE_MCA>& i_target )
+{
+ std::vector< fapi2::Target<fapi2::TARGET_TYPE_MCA> > l_temp = {i_target};
+ return l_temp;
+}
+
+///
/// @brief find the magic MCA connected to an MCBIST
/// @param[in] i_target the fapi2::Target MCBIST
/// @return a vector of fapi2::TARGET_TYPE_MCA
OpenPOWER on IntegriCloud