summaryrefslogtreecommitdiffstats
path: root/src/import/chips/ocmb/explorer/procedures/hwp
diff options
context:
space:
mode:
authorAlvin Wang <wangat@tw.ibm.com>2019-04-16 10:57:56 -0500
committerChristian R. Geddes <crgeddes@us.ibm.com>2019-04-30 11:53:20 -0500
commit4ce53f71e9fcf0c22fdb83af31b450db975df233 (patch)
tree0c85bb228692dd78965a54f78795af407ff7209d /src/import/chips/ocmb/explorer/procedures/hwp
parent902e166a98fe9cce8dbf6dc69534f45499c0ab1d (diff)
downloadtalos-hostboot-4ce53f71e9fcf0c22fdb83af31b450db975df233.tar.gz
talos-hostboot-4ce53f71e9fcf0c22fdb83af31b450db975df233.zip
Move power_thermal lib to generic
Change-Id: I2851b7fa990d7e8c5a2d726b650b4e2fc11f3fe7 Reviewed-on: http://rchgit01.rchland.ibm.com/gerrit1/72525 Tested-by: FSP CI Jenkins <fsp-CI-jenkins+hostboot@us.ibm.com> Tested-by: Jenkins Server <pfd-jenkins+hostboot@us.ibm.com> Dev-Ready: STEPHEN GLANCY <sglancy@us.ibm.com> Tested-by: Hostboot CI <hostboot-ci+hostboot@us.ibm.com> Tested-by: HWSV CI <hwsv-ci+hostboot@us.ibm.com> Reviewed-by: Louis Stermole <stermole@us.ibm.com> Reviewed-by: STEPHEN GLANCY <sglancy@us.ibm.com> Reviewed-by: Jennifer A. Stofer <stofer@us.ibm.com> Reviewed-on: http://rchgit01.rchland.ibm.com/gerrit1/72845 Tested-by: Jenkins OP Build CI <op-jenkins+hostboot@us.ibm.com> Tested-by: Jenkins OP HW <op-hw-jenkins+hostboot@us.ibm.com> Reviewed-by: Christian R. Geddes <crgeddes@us.ibm.com>
Diffstat (limited to 'src/import/chips/ocmb/explorer/procedures/hwp')
-rw-r--r--src/import/chips/ocmb/explorer/procedures/hwp/memory/exp_bulk_pwr_throttles.C59
-rw-r--r--src/import/chips/ocmb/explorer/procedures/hwp/memory/exp_bulk_pwr_throttles.H39
-rw-r--r--src/import/chips/ocmb/explorer/procedures/hwp/memory/exp_bulk_pwr_throttles.mk6
-rw-r--r--src/import/chips/ocmb/explorer/procedures/hwp/memory/exp_config_thermal.C152
-rw-r--r--src/import/chips/ocmb/explorer/procedures/hwp/memory/exp_config_thermal.H31
-rw-r--r--src/import/chips/ocmb/explorer/procedures/hwp/memory/exp_config_thermal.mk7
-rw-r--r--src/import/chips/ocmb/explorer/procedures/hwp/memory/lib/power_thermal/exp_decoder.C261
-rw-r--r--src/import/chips/ocmb/explorer/procedures/hwp/memory/lib/power_thermal/exp_decoder.H58
-rw-r--r--src/import/chips/ocmb/explorer/procedures/hwp/memory/lib/power_thermal/exp_throttle.C134
-rw-r--r--src/import/chips/ocmb/explorer/procedures/hwp/memory/lib/power_thermal/exp_throttle.H57
-rw-r--r--src/import/chips/ocmb/explorer/procedures/hwp/memory/lib/power_thermal/exp_throttle_traits.H144
11 files changed, 948 insertions, 0 deletions
diff --git a/src/import/chips/ocmb/explorer/procedures/hwp/memory/exp_bulk_pwr_throttles.C b/src/import/chips/ocmb/explorer/procedures/hwp/memory/exp_bulk_pwr_throttles.C
index 28aad7416..880004e23 100644
--- a/src/import/chips/ocmb/explorer/procedures/hwp/memory/exp_bulk_pwr_throttles.C
+++ b/src/import/chips/ocmb/explorer/procedures/hwp/memory/exp_bulk_pwr_throttles.C
@@ -22,3 +22,62 @@
/* permissions and limitations under the License. */
/* */
/* IBM_PROLOG_END_TAG */
+
+///
+/// @file exp_bulk_pwr_throttles.C
+/// @brief The explorer thermal/power config
+///
+// *HWP HWP Owner: Andre Marin <aamarin@us.ibm.com>
+// *HWP HWP Backup: Stephen Glancy <sglancy@us.ibm.com>
+// *HWP Team: Memory
+// *HWP Level: 3
+// *HWP Consumed by: Memory
+
+#include <lib/shared/exp_defaults.H>
+#include <vector>
+
+#include <fapi2.H>
+#include <exp_bulk_pwr_throttles.H>
+#include <lib/shared/exp_consts.H>
+#include <lib/power_thermal/exp_throttle.H>
+#include <mss_explorer_attribute_getters.H>
+#include <mss_explorer_attribute_setters.H>
+#include <generic/memory/lib/utils/find.H>
+#include <generic/memory/lib/utils/count_dimm.H>
+
+extern "C"
+{
+ ///
+ /// @brief Set ATTR_EXP_PORT_MAXPOWER, ATTR_EXP_MEM_THROTTLED_N_COMMANDS_PER_SLOT, ATTR_EXP_MEM_THROTTLED_N_COMMANDS_PER_PORT
+ /// @param[in] i_targets vector of OCMB chips
+ /// @param[in] i_throttle_type thermal boolean to determine whether to calculate throttles based on the power regulator or thermal limits
+ /// @return fapi2::ReturnCode - FAPI2_RC_SUCCESS iff get is OK
+ /// @note determines the throttle levels based off of the port's power curve,
+ /// sets the slot throttles to the same
+ /// @note Enums are POWER for power egulator throttles and THERMAL for thermal throttles
+ /// @note equalizes the throttles to the lowest of runtime and the lowest slot-throttle value
+ ///
+ fapi2::ReturnCode exp_bulk_pwr_throttles( const std::vector< fapi2::Target<fapi2::TARGET_TYPE_OCMB_CHIP> >& i_targets,
+ const mss::throttle_type i_throttle_type)
+ {
+ FAPI_INF("Start exp_bulk_pwr_throttles for %s type throttling",
+ (( i_throttle_type == mss::throttle_type::THERMAL) ? "THERMAL" : "POWER"));
+
+ for ( const auto& l_ocmb : i_targets)
+ {
+ FAPI_TRY(mss::power_thermal::pwr_throttles(l_ocmb, i_throttle_type));
+ }
+
+ // Equalizes the throttles to the lowest of runtime and the lowest slot-throttle value
+ FAPI_TRY(mss::power_thermal::equalize_throttles(i_targets, i_throttle_type));
+
+ FAPI_INF("End exp_bulk_pwr_throttles");
+ return fapi2::current_err;
+
+ fapi_try_exit:
+ FAPI_ERR("Error calculating exp_bulk_pwr_throttles using %s throttling",
+ ((i_throttle_type == mss::throttle_type::POWER) ? "power" : "thermal"));
+ return fapi2::current_err;
+ }
+
+} //extern C
diff --git a/src/import/chips/ocmb/explorer/procedures/hwp/memory/exp_bulk_pwr_throttles.H b/src/import/chips/ocmb/explorer/procedures/hwp/memory/exp_bulk_pwr_throttles.H
index 1112aefb8..79472932b 100644
--- a/src/import/chips/ocmb/explorer/procedures/hwp/memory/exp_bulk_pwr_throttles.H
+++ b/src/import/chips/ocmb/explorer/procedures/hwp/memory/exp_bulk_pwr_throttles.H
@@ -22,3 +22,42 @@
/* permissions and limitations under the License. */
/* */
/* IBM_PROLOG_END_TAG */
+
+///
+/// @file exp_bulk_pwr_throttles.H
+/// @brief The explorer thermal/power config
+///
+// *HWP HWP Owner: Andre Marin <aamarin@us.ibm.com>
+// *HWP HWP Backup: Stephen Glancy <sglancy@us.ibm.com>
+// *HWP Team: Memory
+// *HWP Level: 3
+// *HWP Consumed by: Memory
+#ifndef EXP_BULK_PWR_THROTTLES_H_
+#define EXP_BULK_PWR_THROTTLES_H_
+
+#include <fapi2.H>
+#include <generic/memory/lib/utils/shared/mss_generic_consts.H>
+
+typedef fapi2::ReturnCode (*exp_bulk_pwr_throttles_FP_t) ( const
+ std::vector< fapi2::Target<fapi2::TARGET_TYPE_OCMB_CHIP> >&,
+ const mss::throttle_type i_throttle_type);
+
+extern "C"
+{
+
+ ///
+ /// @brief Set ATTR_MSS_PORT_MAXPOWER, ATTR_MSS_MEM_THROTTLED_N_COMMANDS_PER_SLOT, ATTR_MSS_MEM_THROTTLED_N_COMMANDS_PER_PORT
+ /// @param[in] i_targets vector of OCMB chip
+ /// @param[in] i_throttle_type thermal boolean to determine whether to calculate throttles based on the power regulator or thermal limits
+ /// @return fapi2::ReturnCode - FAPI2_RC_SUCCESS iff get is OK
+ /// @note Called in p9_mss_bulk_pwr_throttles
+ /// @note determines the throttle levels based off of the port's power curve,
+ /// sets the slot throttles to the same
+ /// @note Enums are POWER for power egulator throttles and THERMAL for thermal throttles
+ /// @note equalizes the throttles to the lowest of runtime and the lowest slot-throttle value
+ ///
+ fapi2::ReturnCode exp_bulk_pwr_throttles( const std::vector< fapi2::Target<fapi2::TARGET_TYPE_OCMB_CHIP> >& i_targets,
+ const mss::throttle_type i_throttle_type);
+}
+
+#endif
diff --git a/src/import/chips/ocmb/explorer/procedures/hwp/memory/exp_bulk_pwr_throttles.mk b/src/import/chips/ocmb/explorer/procedures/hwp/memory/exp_bulk_pwr_throttles.mk
index 6dfbc4fe6..c0ef17e69 100644
--- a/src/import/chips/ocmb/explorer/procedures/hwp/memory/exp_bulk_pwr_throttles.mk
+++ b/src/import/chips/ocmb/explorer/procedures/hwp/memory/exp_bulk_pwr_throttles.mk
@@ -22,3 +22,9 @@
# permissions and limitations under the License.
#
# IBM_PROLOG_END_TAG
+
+-include 00exp_common.mk
+
+PROCEDURE=exp_bulk_pwr_throttles
+$(eval $(call ADD_EXP_MEMORY_INCDIRS,$(PROCEDURE)))
+$(call BUILD_PROCEDURE)
diff --git a/src/import/chips/ocmb/explorer/procedures/hwp/memory/exp_config_thermal.C b/src/import/chips/ocmb/explorer/procedures/hwp/memory/exp_config_thermal.C
index c552c0454..215cc7829 100644
--- a/src/import/chips/ocmb/explorer/procedures/hwp/memory/exp_config_thermal.C
+++ b/src/import/chips/ocmb/explorer/procedures/hwp/memory/exp_config_thermal.C
@@ -22,3 +22,155 @@
/* permissions and limitations under the License. */
/* */
/* IBM_PROLOG_END_TAG */
+
+///
+/// @file exp_config_thermal.C
+/// @brief The explorer thermal/power config
+///
+// *HWP HWP Owner: Andre Marin <aamarin@us.ibm.com>
+// *HWP HWP Backup: Stephen Glancy <sglancy@us.ibm.com>
+// *HWP Team: Memory
+// *HWP Level: 3
+// *HWP Consumed by: Memory
+
+#include <lib/shared/exp_defaults.H>
+#include <fapi2.H>
+#include <vector>
+#include <exp_bulk_pwr_throttles.H>
+#include <exp_config_thermal.H>
+#include <lib/power_thermal/exp_decoder.H>
+#include <lib/power_thermal/exp_throttle.H>
+#include <lib/shared/exp_consts.H>
+#include <mss_explorer_attribute_getters.H>
+#include <mss_explorer_attribute_setters.H>
+#include <generic/memory/lib/utils/shared/mss_generic_consts.H>
+#include <generic/memory/lib/utils/dimm/kind.H>
+#include <generic/memory/lib/utils/count_dimm.H>
+#include <generic/memory/lib/mss_generic_attribute_getters.H>
+#include <generic/memory/lib/mss_generic_system_attribute_getters.H>
+
+extern "C"
+{
+ ///
+ /// @brief Perform thermal calculations
+ /// @param[in] i_targets vector of OCMB chip
+ /// @return FAPI2_RC_SUCCESS iff ok
+ fapi2::ReturnCode exp_mss_eff_config_thermal( const std::vector< fapi2::Target<fapi2::TARGET_TYPE_OCMB_CHIP> >&
+ i_targets )
+ {
+ using TT = mss::power_thermal::throttle_traits<>;
+ fapi2::ReturnCode l_rc = fapi2::FAPI2_RC_SUCCESS;
+ FAPI_INF("Start exp_mss_eff_config_thermal");
+
+ // Return error if safemode throttle utilization is less than MIN_UTIL
+ // This section needs to be in braces otherwise the compile will fail
+ const uint64_t l_min_util = TT::MIN_UTIL;
+ uint32_t l_safemode_util = 0;
+ FAPI_TRY( mss::attr::get_mrw_safemode_dram_databus_util(l_safemode_util), "Error in exp_mss_eff_config_thermal" );
+ FAPI_ASSERT( l_safemode_util >= TT::MIN_UTIL,
+ fapi2::MSS_MRW_SAFEMODE_UTIL_THROTTLE_NOT_SUPPORTED()
+ .set_MRW_SAFEMODE_UTIL(l_safemode_util)
+ .set_MIN_UTIL_VALUE(l_min_util),
+ "MRW safemode util (%d centi percent) has less util than the min util allowed (%d centi percent)",
+ l_safemode_util, l_min_util );
+
+ for ( const auto& l_ocmb : i_targets)
+ {
+ //Restore runtime_throttles from safemode setting
+ //Sets throttles to max_databus_util value
+ FAPI_INF("Restoring throttles for %s", mss::c_str(l_ocmb));
+ FAPI_TRY( mss::power_thermal::restore_runtime_throttles<>(l_ocmb), "Error in exp_mss_eff_config_thermal");
+
+ //Not doing any work if there are no dimms installed
+ if (mss::count_dimm(l_ocmb) == 0)
+ {
+ FAPI_INF("Skipping eff_config thermal because no dimms for %s", mss::c_str(l_ocmb));
+ continue;
+ }
+
+ // Thermal power (OCMB+DRAM)
+ uint64_t l_thermal_power_limit[TT::SIZE_OF_THERMAL_LIMIT_ATTR] = {0};
+ uint64_t l_thermal_power_slope[TT::SIZE_OF_THERMAL_SLOPE_ATTR] = {0};
+ uint64_t l_thermal_power_intecept[TT::SIZE_OF_THERMAL_INTERCEPT_ATTR] = {0};
+ // Power (PMIC)
+ uint64_t l_current_curve_with_limit[TT::SIZE_OF_CURRENT_CURVE_WITH_LIMIT_ATTR] = {0};
+
+ // Get the data from MRW
+ FAPI_TRY( mss::attr::get_mrw_ocmb_thermal_memory_power_limit (l_thermal_power_limit),
+ "Error in exp_mss_eff_config_thermal");
+ FAPI_TRY( mss::attr::get_mrw_ocmb_pwr_slope (l_thermal_power_slope), "Error in exp_mss_eff_config_thermal");
+ FAPI_TRY( mss::attr::get_mrw_ocmb_pwr_intercept (l_thermal_power_intecept), "Error in exp_mss_eff_config_thermal");
+ FAPI_TRY( mss::attr::get_mrw_ocmb_current_curve_with_limit (l_current_curve_with_limit),
+ "Error in exp_mss_eff_config_thermal");
+
+ // Convert array to vector
+ using namespace std;
+ vector<uint64_t> l_thermal_power_limit_v ( begin(l_thermal_power_limit), end(l_thermal_power_limit) );
+ vector<uint64_t> l_thermal_power_slope_v ( begin(l_thermal_power_slope), end(l_thermal_power_slope) );
+ vector<uint64_t> l_thermal_power_intecept_v ( begin(l_thermal_power_intecept), end(l_thermal_power_intecept) );
+ vector<uint64_t> l_current_curve_with_limit_v( begin(l_current_curve_with_limit), end(l_current_curve_with_limit) );
+
+
+ uint16_t l_slope [TT::DIMMS_PER_PORT] = {0};
+ uint16_t l_intercept[TT::DIMMS_PER_PORT] = {0};
+ uint32_t l_limit [TT::DIMMS_PER_PORT] = {0};
+
+ const std::vector<mss::throttle_type> throttle_types{ mss::throttle_type::POWER, mss::throttle_type::THERMAL};
+
+ for (const auto& l_throttle_type : throttle_types )
+ {
+ for (const auto& l_port : mss::find_targets<fapi2::TARGET_TYPE_MEM_PORT>(l_ocmb))
+ {
+ //Don't run if there are no dimms on the port
+ if (mss::count_dimm(l_port) == 0)
+ {
+ continue;
+ }
+
+ // Set the thermal power throttle
+ //Set the PMIC current slope, intercept and limit
+ mss::power_thermal::get_power_attrs (l_throttle_type,
+ l_port,
+ l_thermal_power_slope_v,
+ l_thermal_power_intecept_v,
+ l_thermal_power_limit_v,
+ l_current_curve_with_limit_v,
+ l_slope,
+ l_intercept,
+ l_limit);
+
+ FAPI_TRY(mss::attr::set_total_pwr_slope(l_port, l_slope));
+ FAPI_TRY(mss::attr::set_total_pwr_intercept(l_port, l_intercept));
+ FAPI_TRY(mss::attr::set_dimm_thermal_limit(l_port, l_limit));
+
+ FAPI_INF( "PMIC current curve slope is %d, intercept is %d, limit is %d for %s", l_slope[0], l_intercept[0],
+ l_limit[0], mss::c_str(l_port));
+
+ FAPI_INF("Starting pwr_throttles(%s)", mss::throttle_type::POWER == l_throttle_type ? "POWER" : "THERMAL");
+ //get the power limits, done per dimm and set to worst case for the slot and port throttles
+ FAPI_TRY(mss::power_thermal::pwr_throttles(l_ocmb, mss::throttle_type::POWER));
+ FAPI_TRY(l_rc, "Failed running exp_mss_eff_config_thermal with %s throttling",
+ mss::throttle_type::POWER == l_throttle_type ? "POWER" : "THERMAL");
+
+ //Set runtime throttles to worst case between ATTR_EXP_MEM_THROTTLED_N_COMMANDS_PER_SLOT
+ //and ATTR_EXP_MEM_RUNTIME_THROTTLED_N_COMMANDS_PER_SLOT and the _PORT equivalents also
+ FAPI_INF("Starting update");
+ FAPI_TRY( mss::power_thermal::update_runtime_throttle(l_ocmb), "Error in exp_mss_eff_config_thermal for %d",
+ mss::c_str(l_port));
+ FAPI_INF("finished update");
+ }
+ }
+ }
+
+ // Equalizes the throttles to the lowest of runtime and the lowest slot-throttle value
+ FAPI_TRY(mss::power_thermal::equalize_throttles(i_targets, mss::throttle_type::POWER));
+ FAPI_TRY(mss::power_thermal::equalize_throttles(i_targets, mss::throttle_type::THERMAL));
+
+ //Done
+ FAPI_INF( "End exp_mss_eff_config_thermal");
+
+ fapi_try_exit:
+ return fapi2::current_err;
+ }
+
+} //extern C
diff --git a/src/import/chips/ocmb/explorer/procedures/hwp/memory/exp_config_thermal.H b/src/import/chips/ocmb/explorer/procedures/hwp/memory/exp_config_thermal.H
index 76f5cd416..dd03ba8c0 100644
--- a/src/import/chips/ocmb/explorer/procedures/hwp/memory/exp_config_thermal.H
+++ b/src/import/chips/ocmb/explorer/procedures/hwp/memory/exp_config_thermal.H
@@ -22,3 +22,34 @@
/* permissions and limitations under the License. */
/* */
/* IBM_PROLOG_END_TAG */
+
+///
+/// @file exp_config_thermal.H
+/// @brief The explorer thermal/power config
+///
+// *HWP HWP Owner: Andre Marin <aamarin@us.ibm.com>
+// *HWP HWP Backup: Stephen Glancy <sglancy@us.ibm.com>
+// *HWP Team: Memory
+// *HWP Level: 3
+// *HWP Consumed by: Memory
+#ifndef EXP_CONFIG_THERMAL_H_
+#define EXP_CONFIG_THERMAL_H_
+
+#include <fapi2.H>
+
+typedef fapi2::ReturnCode (*exp_mss_eff_config_thermal_FP_t) (const
+ std::vector< fapi2::Target<fapi2::TARGET_TYPE_OCMB_CHIP> >&);
+
+extern "C"
+{
+
+ ///
+ /// @brief Config the thermal/power throttle setting
+ /// @param[in] i_target vector of OCMB chip
+ /// @return FAPI2_RC_SUCCESS iff ok
+ ///
+ fapi2::ReturnCode exp_mss_eff_config_thermal( const std::vector< fapi2::Target<fapi2::TARGET_TYPE_OCMB_CHIP> >&
+ i_targets);
+}
+
+#endif
diff --git a/src/import/chips/ocmb/explorer/procedures/hwp/memory/exp_config_thermal.mk b/src/import/chips/ocmb/explorer/procedures/hwp/memory/exp_config_thermal.mk
index 22abeb618..dfba66804 100644
--- a/src/import/chips/ocmb/explorer/procedures/hwp/memory/exp_config_thermal.mk
+++ b/src/import/chips/ocmb/explorer/procedures/hwp/memory/exp_config_thermal.mk
@@ -22,3 +22,10 @@
# permissions and limitations under the License.
#
# IBM_PROLOG_END_TAG
+
+-include 00exp_common.mk
+
+PROCEDURE=exp_config_thermal
+$(eval $(call ADD_EXP_MEMORY_INCDIRS,$(PROCEDURE)))
+lib$(PROCEDURE)_DEPLIBS+=exp_bulk_pwr_throttles
+$(call BUILD_PROCEDURE)
diff --git a/src/import/chips/ocmb/explorer/procedures/hwp/memory/lib/power_thermal/exp_decoder.C b/src/import/chips/ocmb/explorer/procedures/hwp/memory/lib/power_thermal/exp_decoder.C
index eedfafe84..d08f0a4bb 100644
--- a/src/import/chips/ocmb/explorer/procedures/hwp/memory/lib/power_thermal/exp_decoder.C
+++ b/src/import/chips/ocmb/explorer/procedures/hwp/memory/lib/power_thermal/exp_decoder.C
@@ -22,3 +22,264 @@
/* permissions and limitations under the License. */
/* */
/* IBM_PROLOG_END_TAG */
+
+///
+/// @file exp_decoder.C
+/// @brief Decode MSS_MRW_PWR_CURVE_SLOPE, PWR_CURVE_INTERCEPT, and THERMAL_POWER_LIMIT
+///
+// *HWP HWP Owner: Louis Stermole <stermole@us.ibm.com>
+// *HWP HWP Backup: Andre Marin <aamarin@us.ibm.com>
+// *HWP Team: Memory
+// *HWP Level: 3
+// *HWP Consumed by: FSP:HB
+
+#include <lib/shared/exp_defaults.H>
+// fapi2
+#include <fapi2.H>
+#include <vector>
+#include <utility>
+
+#include <lib/shared/exp_consts.H>
+#include <lib/power_thermal/exp_decoder.H>
+#include <generic/memory/lib/utils/find.H>
+#include <generic/memory/lib/utils/c_str.H>
+#include <generic/memory/lib/utils/dimm/kind.H>
+#include <generic/memory/lib/utils/count_dimm.H>
+#include <generic/memory/lib/utils/power_thermal/gen_decoder.H>
+
+namespace mss
+{
+namespace power_thermal
+{
+
+const std::vector< std::pair<uint8_t , uint8_t> > throttle_traits<mss::mc_type::EXPLORER>::DIMM_TYPE_MAP =
+{
+ {fapi2::ENUM_ATTR_MEM_EFF_DIMM_TYPE_RDIMM, 0b00},
+ {fapi2::ENUM_ATTR_MEM_EFF_DIMM_TYPE_UDIMM, 0b01},
+ {fapi2::ENUM_ATTR_MEM_EFF_DIMM_TYPE_LRDIMM, 0b10},
+ {fapi2::ENUM_ATTR_MEM_EFF_DIMM_TYPE_DDIMM, 0b11},
+ {ANY_TYPE, 0b111}
+};
+
+///
+/// @brief Finds a value for the power curve slope attributes by matching the generated hashes
+/// @param[in] i_slope vector of generated key-values from POWER_CURVE_SLOPE
+/// @return fapi2::ReturnCode FAPI2_RC_SUCCESS iff the encoding was successful
+/// @note populates iv_vddr_slope, iv_total_slop
+///
+template<>
+fapi2::ReturnCode decoder<mss::mc_type::EXPLORER>::find_slope (
+ const std::vector< const std::vector<uint64_t>* >& i_slope)
+{
+ using TT = throttle_traits<mss::mc_type::EXPLORER>;
+
+ // For explorer, two attribute are used to get slope (i_slope[0], i_slope[1])
+ // ATTR_MSS_MRW_OCMB_THERMAL_MEMORY_PWR_SLOPE is for thermal power slope
+ // ATTR_MSS_MRW_OCMB_CURRENT_CURVE_WITH_LIMIT is for power slope
+ FAPI_ASSERT(i_slope.size() == 2,
+ fapi2::MSS_POWER_THERMAL_ATTR_VECTORS_INCORRECT()
+ .set_FUNCTION(SLOPE)
+ .set_INPUT_SIZE(i_slope.size())
+ .set_EXPECTED_SIZE(2),
+ "The attributes vectors size is incorrect for find_slope input:%d, expected:%d",
+ i_slope.size(),
+ 2);
+
+ // To get thermal power slope
+ get_power_thermal_value<TT::THERMAL_START, TT::THERMAL_LENGTH, SLOPE>(
+ *i_slope[0],
+ "ATTR_MSS_MRW_OCMB_THERMAL_MEMORY_PWR_SLOPE",
+ iv_total_slope);
+
+ // To get power slope
+ get_power_thermal_value<TT::POWER_SLOPE_START, TT::POWER_SLOPE_LENGTH, SLOPE>(
+ *i_slope[1],
+ "ATTR_MSS_MRW_OCMB_CURRENT_CURVE_WITH_LIMIT",
+ iv_vddr_slope);
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+///
+/// @brief Finds a value for power curve intercept attributes by matching the generated hashes
+/// @param[in] i_intercept vector of generated key-values for ATTR_MSS_MRW_POWER_CURVE_INTERCEPT
+/// @return fapi2::ReturnCode FAPI2_RC_SUCCESS iff the encoding was successful
+/// @note populates iv_vddr_intercept, iv_total_intercept
+///
+template<>
+fapi2::ReturnCode decoder<mss::mc_type::EXPLORER>::find_intercept (
+ const std::vector< const std::vector<uint64_t>* >& i_intercept)
+{
+ using TT = throttle_traits<mss::mc_type::EXPLORER>;
+
+ // For explorer, two attribute are used to get slope (i_slope[0], i_slope[1])
+ // ATTR_MSS_MRW_OCMB_POWER_INTERCEPT is for thermal power intercept
+ // ATTR_MSS_MRW_OCMB_CURRENT_CURVE_WITH_LIMIT is for power intercept
+ FAPI_ASSERT(i_intercept.size() == 2,
+ fapi2::MSS_POWER_THERMAL_ATTR_VECTORS_INCORRECT()
+ .set_FUNCTION(INTERCEPT)
+ .set_INPUT_SIZE(i_intercept.size())
+ .set_EXPECTED_SIZE(2),
+ "The attributes vectors size is incorrect for find_intercept input:%d, expected:%d",
+ i_intercept.size(),
+ 2);
+
+ // To get thermal power intercept
+ get_power_thermal_value<TT::THERMAL_START, TT::THERMAL_LENGTH, INTERCEPT>(
+ *i_intercept[0],
+ "ATTR_MSS_MRW_OCMB_POWER_INTERCEPT",
+ iv_total_intercept);
+
+ // To get power intercept
+ get_power_thermal_value<TT::POWER_INTERCEPT_START, TT::POWER_INTERCEPT_LENGTH, INTERCEPT>(
+ *i_intercept[1],
+ "ATTR_MSS_MRW_OCMB_CURRENT_CURVE_WITH_LIMIT",
+ iv_vddr_intercept);
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+
+///
+/// @brief Finds a value from ATTR_MSS_MRW_THERMAL_MEMORY_POWER_LIMIT and stores in iv variable
+/// @param[in] i_thermal_limits is a vector of the generated values from ATTR_MSS_MRW_THERMAL_POWER_LIMIT
+/// @return fapi2::ReturnCode FAPI2_RC_SUCCESS iff the encoding was successful
+/// @note populates thermal_power_limit.
+///
+template<>
+fapi2::ReturnCode decoder<mss::mc_type::EXPLORER>::find_thermal_power_limit (
+ const std::vector< const std::vector<uint64_t>* >& i_thermal_limits)
+{
+ using TT = throttle_traits<mss::mc_type::EXPLORER>;
+
+ // For explorer, two attribute are used to get slope (i_slope[0], i_slope[1])
+ // ATTR_MSS_MRW_OCMB_THERMAL_MEMORY_POWER_LIMIT is for thermal power limit
+ // ATTR_MSS_MRW_OCMB_CURRENT_CURVE_WITH_LIMIT is for power limit
+ FAPI_ASSERT(i_thermal_limits.size() == 2,
+ fapi2::MSS_POWER_THERMAL_ATTR_VECTORS_INCORRECT()
+ .set_FUNCTION(INTERCEPT)
+ .set_INPUT_SIZE(i_thermal_limits.size())
+ .set_EXPECTED_SIZE(2),
+ "The attributes vectors size is incorrect for find_thermal_power_limit input:%d, expected:%d",
+ i_thermal_limits.size(),
+ 2);
+
+ // To get thermal power limit
+ get_power_thermal_value<TT::THERMAL_START, TT::THERMAL_LENGTH, POWER_LIMIT>(
+ *i_thermal_limits[0],
+ "ATTR_MSS_MRW_OCMB_THERMAL_MEMORY_POWER_LIMIT",
+ iv_thermal_power_limit);
+
+ // To get power intercept
+ get_power_thermal_value<TT::POWER_LIMIT_START, TT::POWER_LIMIT_LENGTH, POWER_LIMIT>(
+ *i_thermal_limits[1],
+ "ATTR_MSS_MRW_OCMB_CURRENT_CURVE_WITH_LIMIT",
+ iv_power_limit);
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+
+///
+/// @brief find the power curve attributes for each dimm on an MCS target
+/// @param[in] i_targets vector of MCS targets on which dimm attrs will be set
+/// @param[in] i_slope vector of generated hashes for encoding and values for MSS_MRW_POWER_SLOPE
+/// @param[in] i_intercept vector of generated hashes for encoding and values for MSS_MRW_POWER_INTERCEPT
+/// @param[in] i_thermal_power_limit vector of generated hashes for encoding and values for MSS_MRW_THERMAL_MEMORY_POWER_LIMIT
+/// @param[out] o_vddr_slope the VDDR power curve slope for each dimm
+/// @param[out] o_vddr_int the VDDR power curve intercept for each dimm
+/// @param[out] o_total_slope the VDDR+VPP power curve slope for each dimm
+/// @param[out] o_total_int the VDDR+VPP power curve intercept for each dimm
+/// @param[out] o_thermal_power the thermal power limit for the dimm
+/// @return FAPI2_RC_SUCCESS iff ok
+/// @note used to set power curve attributes in calling function
+/// @note decodes the attribute "encoding" to get the vddr and vddr/vpp power curves for a dimm
+///
+fapi2::ReturnCode get_power_attrs (const mss::throttle_type i_throttle_type,
+ const fapi2::Target<fapi2::TARGET_TYPE_MEM_PORT>& i_port,
+ const std::vector< uint64_t >& i_slope,
+ const std::vector< uint64_t >& i_intercept,
+ const std::vector< uint64_t >& i_thermal_power_limit,
+ const std::vector< uint64_t >& i_current_curve_with_limit,
+ uint16_t o_slope [throttle_traits<>::DIMMS_PER_PORT],
+ uint16_t o_intercept [throttle_traits<>::DIMMS_PER_PORT],
+ uint32_t o_limit [throttle_traits<>::DIMMS_PER_PORT])
+{
+ using TT = throttle_traits<mss::mc_type::EXPLORER>;
+
+ for (const auto& l_dimm : find_targets <fapi2::TARGET_TYPE_DIMM> (i_port))
+ {
+ const auto l_dimm_pos = mss::index (l_dimm);
+ mss::dimm::kind l_kind (l_dimm);
+ mss::power_thermal::decoder<> l_decoder(l_kind);
+
+ FAPI_TRY( l_decoder.generate_encoding(), "%s Error in get_power_attrs", mss::c_str(l_dimm) );
+
+ // The first entry into these arrays must be valid
+ // If we don't find any values, the attributes aren't found so go with some defaults
+ if (i_slope.empty() || i_slope[0] == 0)
+ {
+ FAPI_INF("%s ATTR_MSS_MRW_OCMB_PWR_SLOPE not found!!", mss::c_str(l_dimm));
+
+ o_slope[l_dimm_pos] =
+ (i_throttle_type == mss::throttle_type::POWER) ? TT::POWER_SLOPE : TT::TOTAL_SLOPE;
+ }
+ else
+ {
+ const std::vector< const std::vector<uint64_t>* > l_slope {&i_slope, &i_current_curve_with_limit};
+
+ FAPI_TRY( l_decoder.find_slope(l_slope), "%s Error in get_power_attrs", mss::c_str(l_dimm) );
+
+ o_slope[l_dimm_pos] =
+ (i_throttle_type == mss::throttle_type::POWER) ? l_decoder.iv_vddr_slope : l_decoder.iv_total_slope;
+ }
+
+ if (i_intercept.empty() || i_intercept[0] == 0)
+ {
+ FAPI_INF("%s ATTR_MSS_MRW_OCMB_PWR_INTERCEPT not found!!", mss::c_str(l_dimm));
+
+ o_intercept[l_dimm_pos] =
+ (i_throttle_type == mss::throttle_type::POWER) ? TT::POWER_INT : TT::TOTAL_INT;
+ }
+ else
+ {
+ const std::vector< const std::vector<uint64_t>* > l_intercept {&i_intercept, &i_current_curve_with_limit};
+
+ FAPI_TRY( l_decoder.find_intercept(l_intercept), "%s Error in get_power_attrs", mss::c_str(l_dimm) );
+
+ o_intercept[l_dimm_pos] =
+ (i_throttle_type == mss::throttle_type::POWER) ? l_decoder.iv_vddr_intercept : l_decoder.iv_total_intercept;
+ }
+
+ if (i_thermal_power_limit.empty() || i_thermal_power_limit[0] == 0)
+ {
+ FAPI_INF("%s ATTR_MSS_MRW_OCMB_THERMAL_MEMORY_POWER_LIMIT not found!!", mss::c_str(l_dimm));
+
+ // The unit of limit and intercept is cA but limit is dA in mss::throttle_type::POWER
+ // So we need to transfer them to the same unit
+ o_limit[l_dimm_pos] =
+ (i_throttle_type == mss::throttle_type::POWER) ? TT::POWER_LIMIT * DECI_TO_CENTI : TT::THERMAL_LIMIT;
+ }
+ else
+ {
+ std::vector< const std::vector<uint64_t>* > l_thermal_power_limit {&i_thermal_power_limit, &i_current_curve_with_limit};
+
+ FAPI_TRY( l_decoder.find_thermal_power_limit(l_thermal_power_limit),
+ "%s Error in get_power_attrs", mss::c_str(l_dimm) );
+ // The unit of limit and intercept is cA but limit is dA in mss::throttle_type::POWER
+ // So we need to transfer them to the same unit
+ o_limit[l_dimm_pos] =
+ (i_throttle_type == mss::throttle_type::POWER) ? l_decoder.iv_power_limit * DECI_TO_CENTI :
+ l_decoder.iv_thermal_power_limit;
+ }
+ }
+
+fapi_try_exit:
+ return fapi2::current_err;
+}
+
+} //ns power_thermal
+} // ns mss
diff --git a/src/import/chips/ocmb/explorer/procedures/hwp/memory/lib/power_thermal/exp_decoder.H b/src/import/chips/ocmb/explorer/procedures/hwp/memory/lib/power_thermal/exp_decoder.H
index 3ce2f3ed3..9f49ee70f 100644
--- a/src/import/chips/ocmb/explorer/procedures/hwp/memory/lib/power_thermal/exp_decoder.H
+++ b/src/import/chips/ocmb/explorer/procedures/hwp/memory/lib/power_thermal/exp_decoder.H
@@ -22,3 +22,61 @@
/* permissions and limitations under the License. */
/* */
/* IBM_PROLOG_END_TAG */
+
+///
+/// @file exp_decoder.H
+/// @brief Decoder for ATTR_MSS_MRW_PWR_CURVE_SLOPE and _INTERCEPT and THERMAL_POWER_LIMIT
+///
+// *HWP HWP Owner: Louis Stermole <stermole@us.ibm.com>
+// *HWP HWP Backup: Stephen Glancy <sglancy@us.ibm.com>
+// *HWP Team: Memory
+// *HWP Level: 3
+// *HWP Consumed by: FSP:HB
+
+#ifndef _MSS_POWER_EXP_DECODER__
+#define _MSS_POWER_EXP_DECODER__
+
+#include <fapi2.H>
+
+#include <lib/shared/exp_consts.H>
+#include <generic/memory/lib/utils/dimm/kind.H>
+#include <lib/power_thermal/exp_throttle.H>
+#include <generic/memory/lib/utils/power_thermal/gen_decoder.H>
+
+
+namespace mss
+{
+
+namespace power_thermal
+{
+
+
+///
+/// @brief find the power curve attributes for each dimm on an MCS target
+/// @param[in] i_targets vector of MCS targets on which dimm attrs will be set
+/// @param[in] i_slope vector of generated hashes for encoding and values for MSS_MRW_POWER_SLOPE
+/// @param[in] i_intercept vector of generated hashes for encoding and values for MSS_MRW_POWER_INTERCEPT
+/// @param[in] i_thermal_power_limit vector of generated hashes for encoding and values for MSS_MRW_THERMAL_MEMORY_POWER_LIMIT
+/// @param[out] o_vddr_slope the VDDR power curve slope for each dimm
+/// @param[out] o_vddr_int the VDDR power curve intercept for each dimm
+/// @param[out] o_total_slope the VDDR+VPP power curve slope for each dimm
+/// @param[out] o_total_int the VDDR+VPP power curve intercept for each dimm
+/// @param[out] o_thermal_power the thermal power limit for the dimm
+/// @return FAPI2_RC_SUCCESS iff ok
+/// @note used to set power curve attributes in calling function
+/// @note decodes the attribute "encoding" to get the vddr and vddr/vpp power curves for a dimm
+///
+fapi2::ReturnCode get_power_attrs (const mss::throttle_type i_throttle_type,
+ const fapi2::Target<fapi2::TARGET_TYPE_MEM_PORT>& i_port,
+ const std::vector< uint64_t >& i_slope,
+ const std::vector< uint64_t >& i_intercept,
+ const std::vector< uint64_t >& i_thermal_power_limit,
+ const std::vector< uint64_t >& i_current_curve_with_limit,
+ uint16_t o_slope [throttle_traits<>::DIMMS_PER_PORT],
+ uint16_t o_intercept [throttle_traits<>::DIMMS_PER_PORT],
+ uint32_t o_limit [throttle_traits<>::DIMMS_PER_PORT]);
+
+
+} // power_thermal
+} // mss
+#endif
diff --git a/src/import/chips/ocmb/explorer/procedures/hwp/memory/lib/power_thermal/exp_throttle.C b/src/import/chips/ocmb/explorer/procedures/hwp/memory/lib/power_thermal/exp_throttle.C
index b3114480e..0e95aebb7 100644
--- a/src/import/chips/ocmb/explorer/procedures/hwp/memory/lib/power_thermal/exp_throttle.C
+++ b/src/import/chips/ocmb/explorer/procedures/hwp/memory/lib/power_thermal/exp_throttle.C
@@ -22,3 +22,137 @@
/* permissions and limitations under the License. */
/* */
/* IBM_PROLOG_END_TAG */
+
+///
+/// @file exp_throttle.C
+/// @brief Determine throttle settings for memory
+///
+// *HWP HWP Owner: Andre A. Marin <aamarin@us.ibm.com>
+// *HWP HWP Backup: Louis Stermole <stermole@us.ibm.com>
+// *HWP Team: Memory
+// *HWP Level: 3
+// *HWP Consumed by: FSP:HB
+
+#include <lib/shared/exp_defaults.H>
+// fapi2
+#include <fapi2.H>
+
+#include <lib/shared/exp_consts.H>
+#include <lib/power_thermal/exp_throttle.H>
+#include <mss_explorer_attribute_getters.H>
+#include <mss_explorer_attribute_setters.H>
+#include <generic/memory/lib/utils/count_dimm.H>
+
+namespace mss
+{
+namespace power_thermal
+{
+///
+/// @brief Calcuate the throttle values based on throttle type
+/// @param[in] i_target
+/// @param[in] i_throttle_type thermal boolean to determine whether to calculate throttles based on the power regulator or thermal limits
+/// @return fapi2::ReturnCode - FAPI2_RC_SUCCESS iff get is OK
+/// @note Called in p9_mss_bulk_pwr_throttles
+/// @note determines the throttle levels based off of the port's power curve,
+/// sets the slot throttles to the same
+/// @note Enums are POWER for power egulator throttles and THERMAL for thermal throttles
+/// @note equalizes the throttles to the lowest of runtime and the lowest slot-throttle value
+///
+fapi2::ReturnCode pwr_throttles( const fapi2::Target<fapi2::TARGET_TYPE_OCMB_CHIP>& i_target,
+ const mss::throttle_type i_throttle_type)
+{
+ FAPI_INF("Start exp_bulk_pwr_throttle for %s type throttling for %s",
+ (( i_throttle_type == mss::throttle_type::THERMAL) ? "THERMAL" : "POWER"), mss::c_str(i_target));
+
+ if (mss::count_dimm (i_target) == 0)
+ {
+ return fapi2::FAPI2_RC_SUCCESS;
+ }
+
+ uint16_t l_slot = 0;
+ uint16_t l_port = 0;
+ uint32_t l_power = 0;
+
+ for (const auto& l_port_target : mss::find_targets<fapi2::TARGET_TYPE_MEM_PORT>(i_target))
+ {
+ fapi2::ReturnCode l_rc = fapi2::FAPI2_RC_SUCCESS;
+
+ //Don't run if there are no dimms on the port
+ if (mss::count_dimm(l_port_target) == 0)
+ {
+ continue;
+ }
+
+ mss::power_thermal::throttle<> l_pwr_struct(l_port_target, l_rc);
+ FAPI_TRY(l_rc, "Error constructing mss:power_thermal::throttle object for target %s",
+ mss::c_str(l_port_target));
+
+ //Let's do the actual work now
+ if ( i_throttle_type == mss::throttle_type::THERMAL)
+ {
+ FAPI_TRY (l_pwr_struct.thermal_throttles());
+ }
+ else
+ {
+ FAPI_TRY (l_pwr_struct.power_regulator_throttles());
+ }
+
+ l_slot = l_pwr_struct.iv_n_slot;
+ l_port = l_pwr_struct.iv_n_port;
+ l_power = l_pwr_struct.iv_calc_port_maxpower;
+
+ FAPI_INF("For target %s Calculated power is %d, throttle per slot is %d, throttle per port is %d",
+ mss::c_str(l_port_target), l_power, l_slot, l_port);
+
+ FAPI_TRY(mss::attr::set_port_maxpower( l_port_target, l_power));
+ FAPI_TRY(mss::attr::set_mem_throttled_n_commands_per_slot( l_port_target, l_slot));
+ FAPI_TRY(mss::attr::set_mem_throttled_n_commands_per_port( l_port_target, l_port));
+ }
+
+ FAPI_INF("End bulk_pwr_throttles for %s", mss::c_str(i_target));
+ return fapi2::current_err;
+
+fapi_try_exit:
+ FAPI_ERR("Error calculating bulk_pwr_throttles using %s throttling",
+ ((i_throttle_type == mss::throttle_type::POWER) ? "power" : "thermal"));
+ return fapi2::current_err;
+}
+
+///
+/// @brief Equalize the throttles among OCMB chips
+/// @param[in] i_targets vector of OCMB chips
+/// @param[in] i_throttle_type thermal boolean to determine whether to calculate throttles based on the power regulator or thermal limits
+/// @return fapi2::ReturnCode - FAPI2_RC_SUCCESS iff get is OK
+/// @note equalizes the throttles to the lowest of runtime and the lowest slot-throttle value
+///
+fapi2::ReturnCode equalize_throttles( const std::vector< fapi2::Target<fapi2::TARGET_TYPE_OCMB_CHIP> >& i_targets,
+ const mss::throttle_type i_throttle_type)
+{
+ FAPI_INF("Start equalize_throttles for %s type throttling",
+ (( i_throttle_type == mss::throttle_type::THERMAL) ? "THERMAL" : "POWER"));
+
+ std::vector< fapi2::Target<fapi2::TARGET_TYPE_MEM_PORT> > l_exceeded_power;
+
+ // Set all of the throttles to the lowest value per port for performance reasons
+ FAPI_TRY(mss::power_thermal::equalize_throttles(i_targets, i_throttle_type, l_exceeded_power));
+
+ // Report any port that exceeded the max power limit, and return a failing RC if we have any
+ for (const auto& l_port : l_exceeded_power)
+ {
+ FAPI_ERR(" MEM_PORT %s estimated power exceeded the maximum allowed", mss::c_str(l_port) );
+ fapi2::current_err = fapi2::FAPI2_RC_FALSE;
+ }
+
+ FAPI_INF("End equalize_throttles");
+ return fapi2::current_err;
+
+fapi_try_exit:
+ FAPI_ERR("Error calculating equalize_throttles using %s throttling",
+ ((i_throttle_type == mss::throttle_type::POWER) ? "power" : "thermal"));
+ return fapi2::current_err;
+}
+
+
+
+}//namespace power_thermal
+}//namespace mss
diff --git a/src/import/chips/ocmb/explorer/procedures/hwp/memory/lib/power_thermal/exp_throttle.H b/src/import/chips/ocmb/explorer/procedures/hwp/memory/lib/power_thermal/exp_throttle.H
index 83559db83..683e484e0 100644
--- a/src/import/chips/ocmb/explorer/procedures/hwp/memory/lib/power_thermal/exp_throttle.H
+++ b/src/import/chips/ocmb/explorer/procedures/hwp/memory/lib/power_thermal/exp_throttle.H
@@ -22,3 +22,60 @@
/* permissions and limitations under the License. */
/* */
/* IBM_PROLOG_END_TAG */
+
+///
+/// @file exp_throttle.H
+/// @brief throttle API
+///
+
+// *HWP HWP Owner: Andre Marin <aamarin@us.ibm.com>
+// *HWP HWP Backup: Louis Stermole <stermole@us.ibm.com>
+// *HWP Team: Memory
+// *HWP Level: 3
+// *HWP Consumed by: FSP:HB
+
+#ifndef _MSS_EXP_THROTTLE_
+#define _MSS_EXP_THROTTLE_
+
+#include <fapi2.H>
+#include <lib/shared/exp_consts.H>
+#include <lib/power_thermal/exp_throttle.H>
+#include <mss_explorer_attribute_setters.H>
+#include <mss_explorer_attribute_getters.H>
+#include <lib/power_thermal/exp_throttle_traits.H>
+#include <generic/memory/lib/utils/power_thermal/gen_throttle.H>
+
+namespace mss
+{
+namespace power_thermal
+{
+
+///
+/// @brief Set ATTR_EXP_PORT_MAXPOWER, ATTR_OCMB_EXP_MSS_MEM_THROTTLED_N_COMMANDS_PER_SLOT,
+/// ATTR_EXP_MEM_THROTTLED_N_COMMANDS_PER_PORT
+/// @param[in] i_target
+/// @param[in] i_throttle_type thermal boolean to determine whether to calculate throttles based on the power regulator or thermal limits
+/// @return fapi2::ReturnCode - FAPI2_RC_SUCCESS iff get is OK
+/// @note Called in p9_mss_bulk_pwr_throttles
+/// @note determines the throttle levels based off of the port's power curve,
+/// sets the slot throttles to the same
+/// @note Enums are POWER for power egulator throttles and THERMAL for thermal throttles
+/// @note equalizes the throttles to the lowest of runtime and the lowest slot-throttle value
+///
+fapi2::ReturnCode pwr_throttles( const fapi2::Target<fapi2::TARGET_TYPE_OCMB_CHIP>& i_target,
+ const mss::throttle_type i_throttle_type);
+
+///
+/// @brief Equalize the throttles among OCMB chips
+/// @param[in] i_targets vector of OCMB chips
+/// @param[in] i_throttle_type thermal boolean to determine whether to calculate throttles based on the power regulator or thermal limits
+/// @return fapi2::ReturnCode - FAPI2_RC_SUCCESS iff get is OK
+/// @note equalizes the throttles to the lowest of runtime and the lowest slot-throttle value
+///
+fapi2::ReturnCode equalize_throttles( const std::vector< fapi2::Target<fapi2::TARGET_TYPE_OCMB_CHIP> >& i_targets,
+ const mss::throttle_type i_throttle_type);
+
+}//power_thermal
+}// mss
+
+#endif
diff --git a/src/import/chips/ocmb/explorer/procedures/hwp/memory/lib/power_thermal/exp_throttle_traits.H b/src/import/chips/ocmb/explorer/procedures/hwp/memory/lib/power_thermal/exp_throttle_traits.H
index 1c8945f89..d782ce050 100644
--- a/src/import/chips/ocmb/explorer/procedures/hwp/memory/lib/power_thermal/exp_throttle_traits.H
+++ b/src/import/chips/ocmb/explorer/procedures/hwp/memory/lib/power_thermal/exp_throttle_traits.H
@@ -22,3 +22,147 @@
/* permissions and limitations under the License. */
/* */
/* IBM_PROLOG_END_TAG */
+
+///
+/// @file exp_throttle_traits.H
+/// @brief throttle API
+///
+
+// *HWP HWP Owner: Andre Marin <aamarin@us.ibm.com>
+// *HWP HWP Backup: Louis Stermole <stermole@us.ibm.com>
+// *HWP Team: Memory
+// *HWP Level: 3
+// *HWP Consumed by: FSP:HB
+
+#ifndef _MSS_EXP_THROTTLE_TRAITS_
+#define _MSS_EXP_THROTTLE_TRAITS_
+
+#include <fapi2.H>
+#include <generic/memory/lib/utils/power_thermal/gen_throttle_traits.H>
+
+namespace mss
+{
+namespace power_thermal
+{
+
+///
+/// @class Traits and policy class for throttle code - specialization for the Explorer mc type
+///
+template<>
+class throttle_traits<mss::mc_type::EXPLORER>
+{
+ public:
+ //////////////////////////////////////////////////////////////
+ // Target types
+ //////////////////////////////////////////////////////////////
+ static constexpr fapi2::TargetType MC_TARGET_TYPE = fapi2::TARGET_TYPE_OCMB_CHIP;
+ static constexpr fapi2::TargetType PORT_TARGET_TYPE = fapi2::TARGET_TYPE_MEM_PORT;
+
+ //////////////////////////////////////////////////////////////
+ // Traits values
+ //////////////////////////////////////////////////////////////
+ // MIN_UTIL is in c%
+ static const uint64_t MIN_UTIL = 2500;
+ // IDLE_UTIL is in c%
+ static const uint64_t IDLE_UTIL = 0;
+ // Minimum throttle allowed for the port and or slot. If we set to 0, we brick the port
+ static const uint64_t MIN_THROTTLE = 1;
+
+ enum size_of_attrs : size_t
+ {
+ // Thermal power (OCMB+DRAM)
+ SIZE_OF_THERMAL_LIMIT_ATTR = 25,
+ SIZE_OF_THERMAL_SLOPE_ATTR = 50,
+ SIZE_OF_THERMAL_INTERCEPT_ATTR = 50,
+
+ // Power (PMIC)
+ SIZE_OF_CURRENT_CURVE_WITH_LIMIT_ATTR = 25,
+ };
+
+ enum default_power
+ {
+ //Values are the worst case defaults for power curves
+ //They are the default/ catch-all values from the power curve attributes
+ //Shouldn't be used if system is set up correctly and attributes are available
+ //This will throttle the DIMMs to ~76% dram data bus utilization
+ //(using the mrw regulator power limit of 1700 cW and thermal power limit here of 1940 cW).
+ // TODO: Need to fill the right value. The current value is from Nimbus
+ // Thermal power (OCMB+DRAM)
+ TOTAL_SLOPE = 0x44C,
+ TOTAL_INT = 0x44C,
+ THERMAL_LIMIT = 0x794,
+
+ // Power (PMIC)
+ POWER_SLOPE = 0x41A,
+ POWER_INT = 0x384,
+ POWER_LIMIT = 0x794,
+
+ };
+
+ enum
+ {
+ PORTS_PER_MC = 1,
+ DIMMS_PER_PORT = 2,
+ };
+
+ //Bit positions for different section of the attribute
+ //first 32 bits are the encoding, second are for values
+ enum DECODE_BUFFER_POS
+ {
+ ENCODING_START = 0,
+ ENCODING_LENGTH = 32,
+
+ // Thermal total power (OCMB+DRAM)
+ THERMAL_START = 32,
+ THERMAL_LENGTH = 16,
+
+ // Current power (PMIC)
+ POWER_LIMIT_START = 32,
+ POWER_LIMIT_LENGTH = 8,
+ POWER_SLOPE_START = 40,
+ POWER_SLOPE_LENGTH = 12,
+ POWER_INTERCEPT_START = 52,
+ POWER_INTERCEPT_LENGTH = 12,
+ };
+
+ //Positions and lengths of the encodings
+ enum ATTR_DECODE_INFO
+ {
+ DIMM_SIZE_START = 0,
+ DIMM_SIZE_LEN = 4,
+
+ DRAM_GEN_START = 4,
+ DRAM_GEN_LEN = 2,
+
+ DIMM_TYPE_START = 6,
+ DIMM_TYPE_LEN = 3,
+
+ DRAM_WIDTH_START = 9,
+ DRAM_WIDTH_LEN = 3,
+
+ DRAM_DENSITY_START = 12,
+ DRAM_DENSITY_LEN = 3,
+
+ DRAM_STACK_TYPE_START = 15,
+ DRAM_STACK_TYPE_LEN = 2,
+
+ DRAM_MFGID_START = 17,
+ DRAM_MFGID_LEN = 3,
+
+ DIMM_MODULE_HEIGHT_START = 20,
+ DIMM_MODULE_HEIGHT_LEN = 2,
+
+ // Invalid for Explorer but compile will fail without them
+ DIMMS_PER_PORT_START = 0,
+ DIMMS_PER_PORT_LEN = 1,
+ };
+
+ // Definition is in chip folder
+ static const std::vector< std::pair<uint8_t , uint8_t> > DIMM_TYPE_MAP;
+
+};
+}//power_thermal
+}// mss
+
+
+#endif
OpenPOWER on IntegriCloud