summaryrefslogtreecommitdiffstats
path: root/src/import/generic/memory/lib/data_engine/data_engine_utils.H
diff options
context:
space:
mode:
Diffstat (limited to 'src/import/generic/memory/lib/data_engine/data_engine_utils.H')
-rw-r--r--src/import/generic/memory/lib/data_engine/data_engine_utils.H334
1 files changed, 329 insertions, 5 deletions
diff --git a/src/import/generic/memory/lib/data_engine/data_engine_utils.H b/src/import/generic/memory/lib/data_engine/data_engine_utils.H
index e2d5652c0..5436fd5a3 100644
--- a/src/import/generic/memory/lib/data_engine/data_engine_utils.H
+++ b/src/import/generic/memory/lib/data_engine/data_engine_utils.H
@@ -39,6 +39,8 @@
#include <fapi2.H>
#include <generic/memory/lib/utils/index.H>
#include <generic/memory/lib/utils/find.H>
+#include <generic/memory/lib/spd/ddimm/efd_decoder.H>
+#include <generic/memory/lib/spd/spd_facade.H>
namespace mss
{
@@ -67,7 +69,7 @@ struct DataSetterTraits2D < proc_type::NIMBUS,
};
///
-/// @brief Helper function for attribute setting
+/// @brief Helper function to update a 2D array output
/// @tparam P proc_type
/// @tparam X size of 1st array index
/// @tparam Y size of 2nd array index
@@ -85,11 +87,13 @@ template < proc_type P,
typename T,
typename TT = DataSetterTraits2D<P, X, Y>
>
-fapi2::ReturnCode data_setter(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target,
+fapi2::ReturnCode update_data(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target,
const T i_setting,
const generic_ffdc_codes i_ffdc_code,
T (&o_data)[X][Y])
{
+ // Currenlty only valid for a DIMM target, for Nimbus, traits enforces this at compile time
+ // Use case is currently for pre_eff_config which is supported in both Axone and Nimbus
const auto l_port_index = mss::index( find_target<TT::TARGET>(i_target) );
const auto l_dimm_index = mss::index(i_target);
@@ -170,8 +174,7 @@ fapi_try_exit:
template< proc_type P,
typename TT,
fapi2::TargetType T,
- typename IT
- >
+ typename IT >
inline fapi2::ReturnCode set_field(const fapi2::Target<T>& i_target,
const IT i_setting)
{
@@ -179,13 +182,334 @@ inline fapi2::ReturnCode set_field(const fapi2::Target<T>& i_target,
typename TT::attr_type l_attr_list = {};
FAPI_TRY( TT::get_attr(l_attr_target, l_attr_list) );
- FAPI_TRY( data_setter<P>(i_target, i_setting, TT::FFDC_CODE, l_attr_list) );
+ FAPI_TRY( update_data<P>(i_target, i_setting, TT::FFDC_CODE, l_attr_list) );
FAPI_TRY( TT::set_attr(l_attr_target, l_attr_list) );
fapi_try_exit:
return fapi2::current_err;
}
+// Controller agnostic functions
+
+namespace gen
+{
+
+///
+/// @brief Get the target associated with the SPD facade
+/// @param[in] i_data the SPD data
+/// return a fapi2 DIMM target
+///
+static inline fapi2::Target<fapi2::TARGET_TYPE_DIMM> get_target(const spd::facade& i_data)
+{
+ return i_data.get_dimm_target();
+}
+
+///
+/// @brief Get the target associated with the EFD decoder
+/// @param[in] i_data the EFD data
+/// return a fapi2 DIMM target
+///
+static inline fapi2::Target<fapi2::TARGET_TYPE_OCMB_CHIP> get_target(const std::shared_ptr<efd::base_decoder>& i_data)
+{
+ return i_data->get_ocmb_target();
+}
+
+///
+/// @brief Helper function to update the structure that holds attr data
+/// @tparam X size of 1st array index
+/// @tparam Y size of 2nd array index
+/// @tparam T Input/output data type
+/// @tparam FFDC the FFDC type
+/// @param[in] i_efd_data the EFD data
+/// @param[in] i_setting array to set
+/// @param[in] i_ffdc_code FFDC function code
+/// @param[out] o_data attribute data structure to set
+/// @return FAPI2_RC_SUCCESS iff okay
+///
+template < size_t X,
+ size_t Y,
+ typename T,
+ typename FFDC >
+inline fapi2::ReturnCode update_data(const std::shared_ptr<efd::base_decoder>& i_efd_data,
+ const T i_setting,
+ const FFDC i_ffdc_code,
+ T (&o_data)[X][Y])
+{
+ const auto l_ocmb = i_efd_data->get_ocmb_target();
+
+ // TK, remove hard-code when VPDinfo struct adds an iv_dimm index
+ // For explorer we can only have 1 DDIMM (index 0), or up to 2 DIMMs
+ constexpr size_t l_dimm_index = 0;
+ const auto l_rank = i_efd_data->get_rank();
+
+ FAPI_ASSERT( l_dimm_index < X,
+ fapi2::MSS_OUT_OF_BOUNDS_INDEXING()
+ .set_INDEX(l_dimm_index)
+ .set_LIST_SIZE(X)
+ .set_FUNCTION(i_ffdc_code)
+ .set_TARGET(l_ocmb),
+ "Dimm index (%d) was larger than max (%d) on %s",
+ l_dimm_index,
+ X,
+ mss::spd::c_str(l_ocmb) );
+
+ FAPI_ASSERT( l_rank < Y,
+ fapi2::MSS_OUT_OF_BOUNDS_INDEXING()
+ .set_INDEX(l_rank)
+ .set_LIST_SIZE(X)
+ .set_FUNCTION(i_ffdc_code)
+ .set_TARGET(l_ocmb),
+ "Rank index (%d) was larger than max (%d) on %s",
+ l_rank,
+ Y,
+ mss::spd::c_str(l_ocmb) );
+
+ FAPI_DBG("Updating data[%d][%d] with %d for %s", l_dimm_index, l_rank, i_setting, spd::c_str(l_ocmb));
+ o_data[l_dimm_index][l_rank] = i_setting;
+
+ return fapi2::FAPI2_RC_SUCCESS;
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief Helper function to update the structure that holds attr data
+/// @tparam X size of 1st array index
+/// @tparam T Input/output data type
+/// @tparam FFDC the FFDC type
+/// @param[in] i_data the SPD data
+/// @param[in] i_target the DIMM target
+/// @param[in] i_setting array to set
+/// @param[in] i_ffdc_code FFDC function code
+/// @param[out] o_data attribute data structure to set
+/// @return FAPI2_RC_SUCCESS iff okay
+///
+template < size_t X,
+ typename T,
+ typename FFDC >
+inline fapi2::ReturnCode update_data( const spd::facade& i_spd_data,
+ const T i_setting,
+ const FFDC i_ffdc_code,
+ T (&o_data)[X])
+{
+ // TK remove hard-code to DIMM0, use REL_POS attr
+ const auto l_dimm = i_spd_data.get_dimm_target();
+ const size_t l_dimm_index = 0;
+
+ FAPI_ASSERT( l_dimm_index < X,
+ fapi2::MSS_OUT_OF_BOUNDS_INDEXING()
+ .set_INDEX(l_dimm_index)
+ .set_LIST_SIZE(X)
+ .set_FUNCTION(i_ffdc_code)
+ .set_TARGET(l_dimm),
+ "Dimm index (%d) was larger than max (%d) on %s",
+ l_dimm_index,
+ X,
+ mss::spd::c_str(l_dimm) );
+
+ FAPI_DBG("Updating data[%d] with %d for %s", l_dimm_index, i_setting, spd::c_str(l_dimm));
+ o_data[l_dimm_index] = i_setting;
+
+ return fapi2::FAPI2_RC_SUCCESS;
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief Helper function to update the structure that holds attr data
+/// @tparam DT the data type
+/// @tparam IT Input data type
+/// @tparam FFDC type
+/// @tparam OT Output data type
+/// @param[in] i_data the data (e.g. EFD, SPD)
+/// @param[in] i_setting array to set
+/// @param[in] i_ffdc_code FFDC function code
+/// @param[out] o_data output to set
+/// @return FAPI2_RC_SUCCESS iff okay
+///
+template < typename DT,
+ typename IT,
+ typename FFDC,
+ typename OT >
+inline fapi2::ReturnCode update_data( const DT& i_data,
+ const IT i_setting,
+ const FFDC i_ffdc_code,
+ OT& o_data )
+{
+ FAPI_DBG("Updating data with %d for %s", i_setting, spd::c_str(get_target(i_data)));
+ o_data = i_setting;
+ return fapi2::FAPI2_RC_SUCCESS;
+}
+
+///
+/// @brief Sets attr data fields
+/// @tparam TT data engine class traits (e.g. preDataInitTraits, etc.)
+/// @tparam T FAPI2 target type
+/// @tparam IT Input data type
+/// @param[in] i_target the FAPI target
+/// @param[in] i_setting value we want to set attr with
+/// @return FAPI2_RC_SUCCESS iff okay
+///
+template< typename TT,
+ fapi2::TargetType T,
+ typename IT >
+inline fapi2::ReturnCode set_field(const fapi2::Target<T>& i_target,
+ const IT i_setting)
+{
+ const auto l_attr_target = mss::find_target<TT::TARGET>(i_target);
+ typename TT::attr_type l_attr_list = {};
+ FAPI_TRY( TT::get_attr(l_attr_target, l_attr_list) );
+
+ FAPI_TRY( update_data(i_target, i_setting, TT::FFDC_CODE, l_attr_list) );
+ FAPI_TRY( TT::set_attr(l_attr_target, l_attr_list) );
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief Helper function to get the target associated with generic attribute setting
+/// @param[in] i_target
+/// return a fapi2 MEM_PORT target
+///
+static inline fapi2::Target<fapi2::TARGET_TYPE_MEM_PORT> get_attr_target(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>&
+ i_target)
+{
+ return mss::find_target<fapi2::TARGET_TYPE_MEM_PORT>(i_target);
+}
+
+///
+/// @brief Helper function to get the target associated with generic attribute setting
+/// @param[in] i_target
+/// return a fapi2 MEM_PORT target
+///
+inline fapi2::Target<fapi2::TARGET_TYPE_MEM_PORT> get_attr_target(const fapi2::Target<fapi2::TARGET_TYPE_OCMB_CHIP>&
+ i_target)
+{
+ // Explorer has only one MEM_PORT per OCMB, so we are looking for the 0th pos relative to the OCMB
+ // Will need to update to take into account a mem_channel index in VPDinfo if we ever support this.
+ // Per FW, for the DDIMM case we can't support unique settings per channel because the SPD
+ // doesn't know about anything outside of the DDIMM itself.
+ return mss::find_targets<fapi2::TARGET_TYPE_MEM_PORT>(i_target)[0];
+}
+
+///
+/// @brief Sets attr data fields
+/// @tparam TT data engine class traits (e.g. preDataInitTraits, etc.)
+/// @tparam DT the data type
+/// @tparam IT Input data type
+/// @param[in] i_target the FAPI target
+/// @param[in] i_setting value we want to set attr with
+/// @return FAPI2_RC_SUCCESS iff okay
+///
+template< typename TT,
+ typename DT,
+ typename IT >
+inline fapi2::ReturnCode set_field(const DT& i_data,
+ const IT i_setting)
+{
+ // Grab the target associated w/the data (e.g. SPD or EFD)
+ const auto l_data_target = get_target(i_data);
+
+ // Grab the target associated w/the attribute to set
+ const auto l_attr_target = get_attr_target(l_data_target);
+
+ // Get the attribute data in its entirety
+ typename TT::attr_type l_attr_list = {};
+ FAPI_TRY( TT::get_attr(l_attr_target, l_attr_list) );
+
+ // Update the portion of interest (can vary per dimm and/or rank)
+ FAPI_TRY( update_data(i_data, i_setting, TT::FFDC_CODE, l_attr_list) );
+
+ // Set the contents back to the attribute
+ FAPI_TRY( TT::set_attr(l_attr_target, l_attr_list) );
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief Template recursive algorithm for setting attrs
+/// @class attr_engine
+/// @tparam ET enum type - conceptually a list of attrs to set
+/// @tparam F enum value - the specific attr value from ET to set
+/// @tparam TT defaulted to attrEngineTraits<ET, F>
+/// @tparam V defaulted to void (dispatch tag)
+///
+template < typename ET,
+ ET F,
+ typename TT = mss::attrEngineTraits<ET, F>,
+ typename V = void >
+struct attr_engine
+{
+ ///
+ /// @brief Sets attributes fields F in ET
+ /// @tparam DT the data type
+ /// @param[in] i_data the data (efd_decoder, spd_facade, etc.)
+ /// @return FAPI2_RC_SUCCESS iff ok
+ ///
+ template < typename DT >
+ static fapi2::ReturnCode single_set(const DT& i_data)
+ {
+ typename TT::attr_integral_type l_value = 0;
+ FAPI_TRY( TT::get_value_to_set(i_data, l_value) );
+
+ FAPI_TRY( set_field<TT>(i_data, l_value) );
+
+ fapi_try_exit:
+ return fapi2::current_err;
+ }
+
+ ///
+ /// @brief Sets attributes fields F in ET
+ /// @tparam DT the data type
+ /// @param[in] i_data the data (efd_decoder, spd_facade, etc.)
+ /// @return FAPI2_RC_SUCCESS iff ok
+ ///
+ template < typename DT >
+ static fapi2::ReturnCode set(const DT& i_data)
+ {
+ FAPI_TRY( (attr_engine<ET, F>::single_set(i_data)) );
+
+ // Compiler isn't smart enough to deduce F - 1u (decrementing the enum values by 1)
+ // Cast needed to help the compiler deduce this value is an ET type
+ // This does the recursive call to unroll a compile-time looping of a enum list of attrs to set
+ FAPI_TRY( (attr_engine < ET, static_cast<ET>(F - 1u) >::set(i_data)) );
+
+ fapi_try_exit:
+ return fapi2::current_err;
+ }
+};
+
+///
+/// @brief Algorithm for setting SI attrs
+/// @class attr_engine
+/// @tparam ET enum type
+/// @tparam F enum value
+/// @note partial specialization when F == 0 (base case). Which is a NOP.
+///
+template < typename ET, ET F>
+struct attr_engine< ET,
+ F,
+ mss::attrEngineTraits<ET, F>,
+ typename std::enable_if<0u == F>::type >
+{
+ ///
+ /// @brief Sets attributes fields F in ET
+ /// @tparam DT the data type
+ /// @param[in] i_data the data (efd_decoder, spd_facade, etc.)
+ /// @return FAPI2_RC_SUCCESS iff ok
+ ///
+ template < typename DT >
+ static fapi2::ReturnCode set(const DT& i_data)
+ {
+ return fapi2::FAPI2_RC_SUCCESS;
+ }
+};
+
+}// gen
}//mss
#endif
OpenPOWER on IntegriCloud