summaryrefslogtreecommitdiffstats
path: root/src/import/chips
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
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')
-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
-rw-r--r--src/import/chips/ocmb/explorer/procedures/xml/attribute_info/exp_power_thermal.xml164
-rw-r--r--src/import/chips/p9/procedures/hwp/memory/lib/dimm/kind.H4
-rw-r--r--src/import/chips/p9/procedures/hwp/memory/lib/mss_attribute_accessors.H135
-rw-r--r--src/import/chips/p9/procedures/hwp/memory/lib/power_thermal/accessor_wrapper.H257
-rw-r--r--src/import/chips/p9/procedures/hwp/memory/lib/power_thermal/decoder.C177
-rw-r--r--src/import/chips/p9/procedures/hwp/memory/lib/power_thermal/decoder.H275
-rw-r--r--src/import/chips/p9/procedures/hwp/memory/lib/power_thermal/throttle.C821
-rw-r--r--src/import/chips/p9/procedures/hwp/memory/lib/power_thermal/throttle.H319
-rw-r--r--src/import/chips/p9/procedures/hwp/memory/lib/power_thermal/throttle_traits.H122
-rw-r--r--src/import/chips/p9/procedures/hwp/memory/lib/shared/mss_const.H5
-rw-r--r--src/import/chips/p9/procedures/hwp/memory/p9_mss_bulk_pwr_throttles.C6
-rw-r--r--src/import/chips/p9/procedures/hwp/memory/p9_mss_eff_config_thermal.C19
-rw-r--r--src/import/chips/p9/procedures/hwp/memory/p9_mss_utils_to_throttle.C17
-rw-r--r--src/import/chips/p9/procedures/xml/error_info/p9_memory_mss_eff_config_thermal.xml189
25 files changed, 1726 insertions, 1732 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
diff --git a/src/import/chips/ocmb/explorer/procedures/xml/attribute_info/exp_power_thermal.xml b/src/import/chips/ocmb/explorer/procedures/xml/attribute_info/exp_power_thermal.xml
index eaa83be48..8b50d2594 100644
--- a/src/import/chips/ocmb/explorer/procedures/xml/attribute_info/exp_power_thermal.xml
+++ b/src/import/chips/ocmb/explorer/procedures/xml/attribute_info/exp_power_thermal.xml
@@ -23,4 +23,168 @@
<!-- -->
<!-- IBM_PROLOG_END_TAG -->
<attributes>
+ <attribute>
+ <id>ATTR_EXP_MEM_THROTTLED_N_COMMANDS_PER_PORT</id>
+ <targetType>TARGET_TYPE_MEM_PORT</targetType>
+ <description>
+ This is the throttled N commands per window
+ of M DRAM clocks setting for cfg_nm_n_per_port.
+ </description>
+ <initToZero></initToZero>
+ <valueType>uint16</valueType>
+ <writeable/>
+ <mssAccessorName>mem_throttled_n_commands_per_port</mssAccessorName>
+ </attribute>
+
+ <attribute>
+ <id>ATTR_EXP_MEM_THROTTLED_N_COMMANDS_PER_SLOT</id>
+ <targetType>TARGET_TYPE_MEM_PORT</targetType>
+ <description>This is the throttle numerator setting for cfg_nm_n_per_slot</description>
+ <initToZero></initToZero>
+ <valueType>uint16</valueType>
+ <writeable/>
+ <mssAccessorName>mem_throttled_n_commands_per_slot</mssAccessorName>
+ </attribute>
+
+ <attribute>
+ <id>ATTR_EXP_RUNTIME_MEM_THROTTLED_N_COMMANDS_PER_PORT</id>
+ <targetType>TARGET_TYPE_MEM_PORT</targetType>
+ <description>
+ Runtime throttled N commands per
+ M DRAM clocks setting for cfg_nm_n_per_port.
+ </description>
+ <initToZero></initToZero>
+ <valueType>uint16</valueType>
+ <writeable/>
+ <mssAccessorName>runtime_mem_throttled_n_commands_per_port</mssAccessorName>
+ </attribute>
+
+ <attribute>
+ <id>ATTR_EXP_RUNTIME_MEM_THROTTLED_N_COMMANDS_PER_SLOT</id>
+ <targetType>TARGET_TYPE_MEM_PORT</targetType>
+ <description>Runtime throttle numerator setting for cfg_nm_n_per_slot</description>
+ <initToZero></initToZero>
+ <valueType>uint16</valueType>
+ <writeable/>
+ <mssAccessorName>runtime_mem_throttled_n_commands_per_slot</mssAccessorName>
+ </attribute>
+
+ <attribute>
+ <id>ATTR_EXP_SAFEMODE_MEM_THROTTLED_N_COMMANDS_PER_PORT</id>
+ <targetType>TARGET_TYPE_MEM_PORT</targetType>
+ <description>
+ Safe mode throttle value for numerator cfg_nm_n_per_port
+ Set to below optimum value/ rate.
+ On a per port basis
+ Also used for emergency mode throttle MBA_FARB4Q_EMERGENCY_N
+ Used to thermally protect the system in all supported environmental conditions when OCC is not functional
+ </description>
+ <valueType>uint16</valueType>
+ <default>32</default>
+ <platInit/>
+ <initToZero/>
+ <mssAccessorName>safemode_mem_throttled_n_commands_per_port</mssAccessorName>
+ </attribute>
+
+ <attribute>
+ <id>ATTR_EXP_RUNTIME_MEM_M_DRAM_CLOCKS</id>
+ <targetType>TARGET_TYPE_MEM_PORT</targetType>
+ <description>Runtime for M DRAM clocks setting for cfg_nm_m</description>
+ <initToZero></initToZero>
+ <valueType>uint32</valueType>
+ <writeable/>
+ </attribute>
+
+ <attribute>
+ <id>ATTR_EXP_MEM_PORT_POS_OF_FAIL_THROTTLE</id>
+ <targetType>TARGET_TYPE_SYSTEM</targetType>
+ <description>
+ This is the fapi position of the port that failed to calculate
+ memory throttles given the passed in watt target and or utilization
+ </description>
+ <initToZero></initToZero>
+ <valueType>uint64</valueType>
+ <writeable/>
+ </attribute>
+
+ <attribute>
+ <id>ATTR_EXP_MEM_WATT_TARGET</id>
+ <targetType>TARGET_TYPE_MEM_PORT</targetType>
+ <description>
+ Total memory power used to throttle for each dimm
+ Used to compute the throttles on the channel and/or dimms for OCC
+ OCC sets after IPL
+ </description>
+ <initToZero></initToZero>
+ <mssUnit>cW</mssUnit>
+ <valueType>uint32</valueType>
+ <writeable/>
+ <array>2</array>
+ <mssAccessorName>mem_watt_target</mssAccessorName>
+ </attribute>
+
+ <attribute>
+ <id>ATTR_EXP_TOTAL_PWR_SLOPE</id>
+ <targetType>TARGET_TYPE_MEM_PORT</targetType>
+ <description>
+ VDDR+VPP Power slope value for dimm
+ creator: mss_eff_config
+ consumer: mss_bulk_pwr_throttles
+ </description>
+ <initToZero></initToZero>
+ <valueType>uint16</valueType>
+ <writeable/>
+ <array>2</array>
+ <mssAccessorName>total_pwr_slope</mssAccessorName>
+ </attribute>
+
+ <attribute>
+ <id>ATTR_EXP_TOTAL_PWR_INTERCEPT</id>
+ <targetType>TARGET_TYPE_MEM_PORT</targetType>
+ <description>
+ VDDR+VPP Power intercept value for dimm
+ </description>
+ <initToZero></initToZero>
+ <valueType>uint16</valueType>
+ <writeable/>
+ <array>2</array>
+ <mssAccessorName>total_pwr_intercept</mssAccessorName>
+ </attribute>
+
+ <attribute>
+ <id>ATTR_EXP_DATABUS_UTIL</id>
+ <targetType>TARGET_TYPE_MEM_PORT</targetType>
+ <description>
+ Databus utilization per port limit used to calculate memory throttles and power limit
+ </description>
+ <initToZero></initToZero>
+ <valueType>uint32</valueType>
+ <writeable/>
+ <mssAccessorName>databus_util</mssAccessorName>
+ </attribute>
+
+ <attribute>
+ <id>ATTR_EXP_PORT_MAXPOWER</id>
+ <targetType>TARGET_TYPE_MEM_PORT</targetType>
+ <description>Channel Pair Max Power output from thermal procedures</description>
+ <initToZero></initToZero>
+ <valueType>uint32</valueType>
+ <writeable/>
+ <mssAccessorName>port_maxpower</mssAccessorName>
+ </attribute>
+
+ <attribute>
+ <id>ATTR_EXP_DIMM_THERMAL_LIMIT</id>
+ <targetType>TARGET_TYPE_MEM_PORT</targetType>
+ <description>
+ DIMM Max Power based on a thermal limit
+ Decoded from ATTR_MSS_MRW_THERMAL_POWER_LIMIT
+ </description>
+ <initToZero></initToZero>
+ <valueType>uint32</valueType>
+ <writeable/>
+ <mssUnit>cW</mssUnit>
+ <array>2</array>
+ <mssAccessorName>dimm_thermal_limit</mssAccessorName>
+ </attribute>
</attributes>
diff --git a/src/import/chips/p9/procedures/hwp/memory/lib/dimm/kind.H b/src/import/chips/p9/procedures/hwp/memory/lib/dimm/kind.H
index ee707c821..eb7873253 100644
--- a/src/import/chips/p9/procedures/hwp/memory/lib/dimm/kind.H
+++ b/src/import/chips/p9/procedures/hwp/memory/lib/dimm/kind.H
@@ -5,7 +5,7 @@
/* */
/* OpenPOWER HostBoot Project */
/* */
-/* Contributors Listed Below - COPYRIGHT 2016,2018 */
+/* Contributors Listed Below - COPYRIGHT 2016,2019 */
/* [+] International Business Machines Corp. */
/* */
/* */
@@ -237,6 +237,8 @@ class kind
uint8_t iv_hybrid;
uint8_t iv_hybrid_memory_type;
uint16_t iv_rcd_mfgid;
+ // This is just a workaround. There is another task that will port kind library to generic folder
+ uint8_t iv_module_height;
///
/// @brief equal_config
diff --git a/src/import/chips/p9/procedures/hwp/memory/lib/mss_attribute_accessors.H b/src/import/chips/p9/procedures/hwp/memory/lib/mss_attribute_accessors.H
index c482989dd..8d6458ed3 100644
--- a/src/import/chips/p9/procedures/hwp/memory/lib/mss_attribute_accessors.H
+++ b/src/import/chips/p9/procedures/hwp/memory/lib/mss_attribute_accessors.H
@@ -21501,6 +21501,141 @@ fapi_try_exit:
return fapi2::current_err;
}
+///
+/// @brief ATTR_MSS_MRW_OCMB_THERMAL_MEMORY_POWER_LIMIT getter
+/// @param[out] uint64_t* memory to store the value
+/// @note Generated by gen_accessors.pl generateParameters (SYSTEM A)
+/// @return fapi2::ReturnCode - FAPI2_RC_SUCCESS iff get is OK
+/// @note Machine Readable Workbook Thermal Memory Power Limit Used to calculate throttles
+/// to be at or under the power limit Per DIMM basis KEY (0-21): In order DIMM_SIZE
+/// = bits 0-3, DIMM_GEN = 4-5, DIMM_TYPE = 6-8, DIMM_WIDTH = 9-11, DIMM_DENSITY =
+/// 12-14, DIMM_STACK_TYPE = 15-16, DRAM_MFGID = 17-19, DIMM_HEIGHT = 20-21, Bits
+/// 22-32: Not used VALUE (bits 32-47) in cW: OCMB+DRAM thermal power limit per DIMM
+/// =
+/// 32-47
+///
+inline fapi2::ReturnCode mrw_ocmb_thermal_memory_power_limit(uint64_t* o_array)
+{
+ uint64_t l_value[25];
+
+ FAPI_TRY( FAPI_ATTR_GET(fapi2::ATTR_MSS_MRW_OCMB_THERMAL_MEMORY_POWER_LIMIT, fapi2::Target<fapi2::TARGET_TYPE_SYSTEM>(),
+ l_value) );
+ memcpy(o_array, &l_value, 200);
+ return fapi2::current_err;
+
+fapi_try_exit:
+ FAPI_ERR("failed accessing ATTR_MSS_MRW_OCMB_THERMAL_MEMORY_POWER_LIMIT: 0x%lx (system target)",
+ uint64_t(fapi2::current_err));
+ return fapi2::current_err;
+}
+
+///
+/// @brief ATTR_MSS_MRW_OCMB_PWR_SLOPE getter
+/// @param[out] uint64_t* memory to store the value
+/// @note Generated by gen_accessors.pl generateParameters (SYSTEM A)
+/// @return fapi2::ReturnCode - FAPI2_RC_SUCCESS iff get is OK
+/// @note Machine Readable Workbook Power Curve Slope for DIMM Used to get the OCMB+DRAM
+/// power curve for each DIMM Per DIMM basis KEY (0-21): In order DIMM_SIZE = bits
+/// 0-3, DIMM_GEN = 4-5, DIMM_TYPE = 6-8, DIMM_WIDTH = 9-11, DIMM_DENSITY = 12-14,
+/// DIMM_STACK_TYPE = 15-16, DRAM_MFGID = 17-19, DIMM_HEIGHT = 20-21, Bits 22-32:
+/// Not used VALUE (bits 32-47) in cW/utilization: OCMB+DRAM thermal power limit per
+/// DIMM =
+/// 32-47
+///
+inline fapi2::ReturnCode mrw_ocmb_pwr_slope(uint64_t* o_array)
+{
+ uint64_t l_value[50];
+
+ FAPI_TRY( FAPI_ATTR_GET(fapi2::ATTR_MSS_MRW_OCMB_PWR_SLOPE, fapi2::Target<fapi2::TARGET_TYPE_SYSTEM>(), l_value) );
+ memcpy(o_array, &l_value, 400);
+ return fapi2::current_err;
+
+fapi_try_exit:
+ FAPI_ERR("failed accessing ATTR_MSS_MRW_OCMB_PWR_SLOPE: 0x%lx (system target)",
+ uint64_t(fapi2::current_err));
+ return fapi2::current_err;
+}
+
+///
+/// @brief ATTR_MSS_MRW_OCMB_PWR_INTERCEPT getter
+/// @param[out] uint64_t* memory to store the value
+/// @note Generated by gen_accessors.pl generateParameters (SYSTEM A)
+/// @return fapi2::ReturnCode - FAPI2_RC_SUCCESS iff get is OK
+/// @note Machine Readable Workbook Power Curve Intercept for DIMM Used to get the
+/// OCMB+DRAM power curve for each DIMM Per DIMM basis KEY (0-21): In order
+/// DIMM_SIZE = bits 0-3, DIMM_GEN = 4-5, DIMM_TYPE = 6-8, DIMM_WIDTH = 9-11,
+/// DIMM_DENSITY = 12-14, DIMM_STACK_TYPE = 15-16, DRAM_MFGID = 17-19, DIMM_HEIGHT =
+/// 20-21, Bits 22-32: Not used VALUE (bits 32-47) in cW/utilization: OCMB+DRAM
+/// thermal power limit per DIMM =
+/// 32-47
+///
+inline fapi2::ReturnCode mrw_ocmb_pwr_intercept(uint64_t* o_array)
+{
+ uint64_t l_value[50];
+
+ FAPI_TRY( FAPI_ATTR_GET(fapi2::ATTR_MSS_MRW_OCMB_PWR_INTERCEPT, fapi2::Target<fapi2::TARGET_TYPE_SYSTEM>(), l_value) );
+ memcpy(o_array, &l_value, 400);
+ return fapi2::current_err;
+
+fapi_try_exit:
+ FAPI_ERR("failed accessing ATTR_MSS_MRW_OCMB_PWR_INTERCEPT: 0x%lx (system target)",
+ uint64_t(fapi2::current_err));
+ return fapi2::current_err;
+}
+
+///
+/// @brief ATTR_MSS_MRW_OCMB_CURRENT_CURVE_WITH_LIMIT getter
+/// @param[out] uint64_t* memory to store the value
+/// @note Generated by gen_accessors.pl generateParameters (SYSTEM A)
+/// @return fapi2::ReturnCode - FAPI2_RC_SUCCESS iff get is OK
+/// @note Machine Readable Workbook Power Curve Intercept and limit for DIMM Used to get
+/// the PMIC power curve and limit for each DIMM Per DIMM basis KEY (0-21): In order
+/// DIMM_SIZE = bits 0-3, DIMM_GEN = 4-5, DIMM_TYPE = 6-8, DIMM_WIDTH = 9-11,
+/// DIMM_DENSITY = 12-14, DIMM_STACK_TYPE = 15-16, DRAM_MFGID = 17-19, DIMM_HEIGHT =
+/// 20-21, Bits 22-32: Not used VALUE (bits 32-39): Current limit (dA) VALUE (bits
+/// 40-51): Current slope (cA/utilization) VALUE (bits 52-63): Current intercept
+/// (cA)
+///
+inline fapi2::ReturnCode mrw_ocmb_current_curve_with_limit(uint64_t* o_array)
+{
+ uint64_t l_value[25];
+
+ FAPI_TRY( FAPI_ATTR_GET(fapi2::ATTR_MSS_MRW_OCMB_CURRENT_CURVE_WITH_LIMIT, fapi2::Target<fapi2::TARGET_TYPE_SYSTEM>(),
+ l_value) );
+ memcpy(o_array, &l_value, 200);
+ return fapi2::current_err;
+
+fapi_try_exit:
+ FAPI_ERR("failed accessing ATTR_MSS_MRW_OCMB_CURRENT_CURVE_WITH_LIMIT: 0x%lx (system target)",
+ uint64_t(fapi2::current_err));
+ return fapi2::current_err;
+}
+
+///
+/// @brief ATTR_MSS_MRW_SAFEMODE_DRAM_DATABUS_UTIL getter
+/// @param[out] uint32_t& reference to store the value
+/// @note Generated by gen_accessors.pl generateParameters (SYSTEM)
+/// @return fapi2::ReturnCode - FAPI2_RC_SUCCESS iff get is OK
+/// @note Machine Readable Workbook value for safe mode dram data bus utilization in centi
+/// percent (c%). Set to below optimum value/ rate. On a per port basis Also used
+/// for emergency mode throttle Used to thermally protect the system in all
+/// supported environmental conditions when OCC is not functional Consumer:
+/// thermal_init, initfile Default to 2500
+/// c%%
+///
+inline fapi2::ReturnCode mrw_safemode_dram_databus_util(uint32_t& o_value)
+{
+
+ FAPI_TRY( FAPI_ATTR_GET(fapi2::ATTR_MSS_MRW_SAFEMODE_DRAM_DATABUS_UTIL, fapi2::Target<fapi2::TARGET_TYPE_SYSTEM>(),
+ o_value) );
+ return fapi2::current_err;
+
+fapi_try_exit:
+ FAPI_ERR("failed accessing ATTR_MSS_MRW_SAFEMODE_DRAM_DATABUS_UTIL: 0x%lx (system target)",
+ uint64_t(fapi2::current_err));
+ return fapi2::current_err;
+}
+
}
diff --git a/src/import/chips/p9/procedures/hwp/memory/lib/power_thermal/accessor_wrapper.H b/src/import/chips/p9/procedures/hwp/memory/lib/power_thermal/accessor_wrapper.H
index a9cebab3a..fd0991a7a 100644
--- a/src/import/chips/p9/procedures/hwp/memory/lib/power_thermal/accessor_wrapper.H
+++ b/src/import/chips/p9/procedures/hwp/memory/lib/power_thermal/accessor_wrapper.H
@@ -22,3 +22,260 @@
/* permissions and limitations under the License. */
/* */
/* IBM_PROLOG_END_TAG */
+///
+/// @file accessor_wrapper.H
+/// @brief The wrapper of new accessor API(get_/set_) to old accessor 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_ACCESSOR_WRAPPER_
+#define _MSS_ACCESSOR_WRAPPER_
+
+#include <fapi2.H>
+#include <lib/shared/mss_const.H>
+#include <lib/mss_attribute_accessors.H>
+
+
+namespace mss
+{
+namespace attr
+{
+///
+/// @brief ATTR_MSS_RUNTIME_MEM_THROTTLED_N_COMMANDS_PER_SLOT getter
+/// @param[in] const ref to the TARGET_TYPE_MCA
+/// @param[out] uint16_t& reference to store the value
+/// @return fapi2::ReturnCode - FAPI2_RC_SUCCESS iff get is OK
+/// @note Runtime throttle numerator setting for cfg_nm_n_per_slot
+///
+inline fapi2::ReturnCode get_runtime_mem_throttled_n_commands_per_slot(const fapi2::Target<fapi2::TARGET_TYPE_MCA>&
+ i_target, uint16_t& o_value)
+{
+ return mss::runtime_mem_throttled_n_commands_per_slot(i_target, o_value);
+}
+
+///
+/// @brief ATTR_MSS_RUNTIME_MEM_THROTTLED_N_COMMANDS_PER_SLOT setter
+/// @param[in] const ref to the TARGET_TYPE_MCA
+/// @param[in] uint16_t the value to set
+/// @return fapi2::ReturnCode - FAPI2_RC_SUCCESS iff set is OK
+/// @note Runtime throttle numerator setting for cfg_nm_n_per_slot
+///
+inline fapi2::ReturnCode set_runtime_mem_throttled_n_commands_per_slot(const fapi2::Target<fapi2::TARGET_TYPE_MCA>&
+ i_target, uint16_t i_value)
+{
+ uint16_t l_value[2] = {};
+
+ FAPI_TRY( FAPI_ATTR_GET(fapi2::ATTR_MSS_RUNTIME_MEM_THROTTLED_N_COMMANDS_PER_SLOT,
+ i_target.getParent<fapi2::TARGET_TYPE_MCS>(), l_value) );
+ l_value[mss::index(i_target)] = i_value;
+ FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_MSS_RUNTIME_MEM_THROTTLED_N_COMMANDS_PER_SLOT,
+ i_target.getParent<fapi2::TARGET_TYPE_MCS>(), l_value) );
+ return fapi2::current_err;
+
+fapi_try_exit:
+ FAPI_ERR("failed setting ATTR_MSS_RUNTIME_MEM_THROTTLED_N_COMMANDS_PER_SLOT: 0x%lx (target: %s)",
+ uint64_t(fapi2::current_err), mss::c_str(i_target));
+ return fapi2::current_err;
+}
+
+
+///
+/// @brief ATTR_MSS_RUNTIME_MEM_THROTTLED_N_COMMANDS_PER_PORT getter
+/// @param[in] const ref to the TARGET_TYPE_MCA
+/// @param[out] uint16_t& reference to store the value
+/// @return fapi2::ReturnCode - FAPI2_RC_SUCCESS iff get is OK
+/// @note Runtime throttled N commands per M DRAM clocks setting for cfg_nm_n_per_port.
+///
+inline fapi2::ReturnCode get_runtime_mem_throttled_n_commands_per_port(const fapi2::Target<fapi2::TARGET_TYPE_MCA>&
+ i_target, uint16_t& o_value)
+{
+ return mss::runtime_mem_throttled_n_commands_per_port(i_target, o_value);
+}
+
+///
+/// @brief ATTR_MSS_RUNTIME_MEM_THROTTLED_N_COMMANDS_PER_PORT setter
+/// @param[in] const ref to the TARGET_TYPE_MCA
+/// @param[in] uint16_t the value to set
+/// @return fapi2::ReturnCode - FAPI2_RC_SUCCESS iff set is OK
+/// @note Runtime throttled N commands per M DRAM clocks setting for cfg_nm_n_per_port.
+///
+inline fapi2::ReturnCode set_runtime_mem_throttled_n_commands_per_port(const fapi2::Target<fapi2::TARGET_TYPE_MCA>&
+ i_target, uint16_t i_value)
+{
+ uint16_t l_value[2] = {};
+
+ FAPI_TRY( FAPI_ATTR_GET(fapi2::ATTR_MSS_RUNTIME_MEM_THROTTLED_N_COMMANDS_PER_PORT,
+ i_target.getParent<fapi2::TARGET_TYPE_MCS>(), l_value) );
+ l_value[mss::index(i_target)] = i_value;
+ FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_MSS_RUNTIME_MEM_THROTTLED_N_COMMANDS_PER_PORT,
+ i_target.getParent<fapi2::TARGET_TYPE_MCS>(), l_value) );
+ return fapi2::current_err;
+
+fapi_try_exit:
+ FAPI_ERR("failed setting ATTR_MSS_RUNTIME_MEM_THROTTLED_N_COMMANDS_PER_PORT: 0x%lx (target: %s)",
+ uint64_t(fapi2::current_err), mss::c_str(i_target));
+ return fapi2::current_err;
+}
+
+///
+/// @brief ATTR_MSS_MEM_THROTTLED_N_COMMANDS_PER_SLOT getter
+/// @param[in] const ref to the TARGET_TYPE_MCA
+/// @param[out] uint16_t& reference to store the value
+/// @return fapi2::ReturnCode - FAPI2_RC_SUCCESS iff get is OK
+/// @note This is the throttle numerator setting for cfg_nm_n_per_slot
+///
+inline fapi2::ReturnCode get_mem_throttled_n_commands_per_slot(const fapi2::Target<fapi2::TARGET_TYPE_MCA>& i_target,
+ uint16_t& o_value)
+{
+ return mss::mem_throttled_n_commands_per_slot(i_target, o_value);
+}
+
+///
+/// @brief ATTR_MSS_MEM_THROTTLED_N_COMMANDS_PER_PORT setter
+/// @param[in] const ref to the TARGET_TYPE_MCA
+/// @param[in] uint16_t the value to set
+/// @return fapi2::ReturnCode - FAPI2_RC_SUCCESS iff set is OK
+/// @note This is the throttled N commands per window of M DRAM clocks setting for cfg_nm_n_per_port.
+///
+inline fapi2::ReturnCode set_mem_throttled_n_commands_per_port(const fapi2::Target<fapi2::TARGET_TYPE_MCA>& i_target,
+ uint16_t i_value)
+{
+ uint16_t l_value[2] = {};
+
+ FAPI_TRY( FAPI_ATTR_GET(fapi2::ATTR_MSS_MEM_THROTTLED_N_COMMANDS_PER_PORT, i_target.getParent<fapi2::TARGET_TYPE_MCS>(),
+ l_value) );
+ l_value[mss::index(i_target)] = i_value;
+ FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_MSS_MEM_THROTTLED_N_COMMANDS_PER_PORT, i_target.getParent<fapi2::TARGET_TYPE_MCS>(),
+ l_value) );
+ return fapi2::current_err;
+
+fapi_try_exit:
+ FAPI_ERR("failed setting ATTR_MSS_MEM_THROTTLED_N_COMMANDS_PER_PORT: 0x%lx (target: %s)",
+ uint64_t(fapi2::current_err), mss::c_str(i_target));
+ return fapi2::current_err;
+}
+
+///
+/// @brief ATTR_MSS_MEM_THROTTLED_N_COMMANDS_PER_PORT getter
+/// @param[in] const ref to the TARGET_TYPE_MCA
+/// @param[out] uint16_t& reference to store the value
+/// @return fapi2::ReturnCode - FAPI2_RC_SUCCESS iff get is OK
+/// @note This is the throttled N commands per window of M DRAM clocks setting for cfg_nm_n_per_port.
+///
+inline fapi2::ReturnCode get_mem_throttled_n_commands_per_port(const fapi2::Target<fapi2::TARGET_TYPE_MCA>& i_target,
+ uint16_t& o_value)
+{
+ return mss::mem_throttled_n_commands_per_port(i_target, o_value);
+}
+
+///
+/// @brief ATTR_MSS_MEM_THROTTLED_N_COMMANDS_PER_SLOT setter
+/// @param[in] const ref to the TARGET_TYPE_MCA
+/// @param[in] uint16_t the value to set
+/// @return fapi2::ReturnCode - FAPI2_RC_SUCCESS iff set is OK
+/// @note This is the throttle numerator setting for cfg_nm_n_per_slot
+///
+inline fapi2::ReturnCode set_mem_throttled_n_commands_per_slot(const fapi2::Target<fapi2::TARGET_TYPE_MCA>& i_target,
+ uint16_t i_value)
+{
+ uint16_t l_value[2] = {};
+
+ FAPI_TRY( FAPI_ATTR_GET(fapi2::ATTR_MSS_MEM_THROTTLED_N_COMMANDS_PER_SLOT, i_target.getParent<fapi2::TARGET_TYPE_MCS>(),
+ l_value) );
+ l_value[mss::index(i_target)] = i_value;
+ FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_MSS_MEM_THROTTLED_N_COMMANDS_PER_SLOT, i_target.getParent<fapi2::TARGET_TYPE_MCS>(),
+ l_value) );
+ return fapi2::current_err;
+
+fapi_try_exit:
+ FAPI_ERR("failed setting ATTR_MSS_MEM_THROTTLED_N_COMMANDS_PER_SLOT: 0x%lx (target: %s)",
+ uint64_t(fapi2::current_err), mss::c_str(i_target));
+ return fapi2::current_err;
+}
+
+///
+/// @brief ATTR_MSS_PORT_MAXPOWER setter
+/// @param[in] const ref to the TARGET_TYPE_MCA
+/// @param[in] uint32_t the value to set
+/// @return fapi2::ReturnCode - FAPI2_RC_SUCCESS iff set is OK
+/// @note Channel Pair Max Power output from thermal procedures
+///
+inline fapi2::ReturnCode set_port_maxpower(const fapi2::Target<fapi2::TARGET_TYPE_MCA>& i_target, uint32_t i_value)
+{
+ uint32_t l_value[2] = {};
+
+ FAPI_TRY( FAPI_ATTR_GET(fapi2::ATTR_MSS_PORT_MAXPOWER, i_target.getParent<fapi2::TARGET_TYPE_MCS>(), l_value) );
+ l_value[mss::index(i_target)] = i_value;
+ FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_MSS_PORT_MAXPOWER, i_target.getParent<fapi2::TARGET_TYPE_MCS>(), l_value) );
+ return fapi2::current_err;
+
+fapi_try_exit:
+ FAPI_ERR("failed setting ATTR_MSS_PORT_MAXPOWER: 0x%lx (target: %s)",
+ uint64_t(fapi2::current_err), mss::c_str(i_target));
+ return fapi2::current_err;
+}
+
+
+///
+/// @brief ATTR_MSS_DIMM_THERMAL_LIMIT getter
+/// @param[in] const ref to the TARGET_TYPE_MCA
+/// @param[out] uint32_t&[] array reference to store the value
+/// @return fapi2::ReturnCode - FAPI2_RC_SUCCESS iff get is OK
+/// @note DIMM Max Power based on a thermal limit Decoded from ATTR_MSS_MRW_THERMAL_POWER_LIMIT
+///
+inline fapi2::ReturnCode get_dimm_thermal_limit(const fapi2::Target<fapi2::TARGET_TYPE_MCA>& i_target,
+ uint32_t (&o_array)[2])
+{
+ return mss::dimm_thermal_limit(i_target, o_array);
+}
+
+///
+/// @brief ATTR_MSS_TOTAL_PWR_INTERCEPT getter
+/// @param[in] const ref to the TARGET_TYPE_MCA
+/// @param[out] uint16_t&[] array reference to store the value
+/// @return fapi2::ReturnCode - FAPI2_RC_SUCCESS iff get is OK
+/// @note VDDR+VPP Power intercept value for dimm creator: mss_eff_config consumer: mss_bulk_pwr_throttles
+///
+inline fapi2::ReturnCode get_total_pwr_intercept(const fapi2::Target<fapi2::TARGET_TYPE_MCA>& i_target,
+ uint16_t (&o_array)[2])
+{
+ return total_pwr_intercept(i_target, o_array);
+}
+
+///
+/// @brief ATTR_MSS_TOTAL_PWR_SLOPE getter
+/// @param[in] const ref to the TARGET_TYPE_MCA
+/// @param[out] uint16_t&[] array reference to store the value
+/// @return fapi2::ReturnCode - FAPI2_RC_SUCCESS iff get is OK
+/// @note VDDR+VPP Power slope value for dimm creator: mss_eff_config consumer: mss_bulk_pwr_throttles
+///
+inline fapi2::ReturnCode get_total_pwr_slope(const fapi2::Target<fapi2::TARGET_TYPE_MCA>& i_target,
+ uint16_t (&o_array)[2])
+{
+ return mss::total_pwr_slope(i_target, o_array);
+}
+
+///
+/// @brief ATTR_MSS_MEM_WATT_TARGET getter
+/// @param[in] const ref to the TARGET_TYPE_MCA
+/// @param[out] uint32_t&[] array reference to store the value
+/// @return fapi2::ReturnCode - FAPI2_RC_SUCCESS iff get is OK
+/// @note Total memory power used to throttle for each dimm Used to compute the throttles
+/// on the channel and/or dimms for OCC OCC sets after IPL creator: mss_eff_config consumer:
+/// mss_bulk_pwr_throttle, mss_utils_to_throttle firmware notes: none.
+///
+inline fapi2::ReturnCode get_mem_watt_target(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target,
+ uint32_t& o_value)
+{
+ return mss::mem_watt_target(i_target, o_value);
+}
+
+}// namespace attr
+}// namespace mss
+
+#endif
diff --git a/src/import/chips/p9/procedures/hwp/memory/lib/power_thermal/decoder.C b/src/import/chips/p9/procedures/hwp/memory/lib/power_thermal/decoder.C
index b381042a2..13e2cafe3 100644
--- a/src/import/chips/p9/procedures/hwp/memory/lib/power_thermal/decoder.C
+++ b/src/import/chips/p9/procedures/hwp/memory/lib/power_thermal/decoder.C
@@ -5,7 +5,7 @@
/* */
/* OpenPOWER HostBoot Project */
/* */
-/* Contributors Listed Below - COPYRIGHT 2016,2018 */
+/* Contributors Listed Below - COPYRIGHT 2016,2019 */
/* [+] International Business Machines Corp. */
/* */
/* */
@@ -32,6 +32,7 @@
// *HWP Level: 3
// *HWP Consumed by: FSP:HB
+#include <lib/shared/nimbus_defaults.H>
// fapi2
#include <fapi2.H>
#include <vector>
@@ -44,100 +45,21 @@
#include <generic/memory/lib/utils/find.H>
#include <generic/memory/lib/utils/c_str.H>
#include <generic/memory/lib/utils/count_dimm.H>
+#include <generic/memory/lib/utils/power_thermal/gen_decoder.H>
#include <lib/dimm/kind.H>
#include <lib/shared/mss_const.H>
-using fapi2::TARGET_TYPE_MCA;
-using fapi2::TARGET_TYPE_MCS;
-using fapi2::TARGET_TYPE_DIMM;
-using fapi2::TARGET_TYPE_MCBIST;
-
namespace mss
{
namespace power_thermal
{
-///
-/// @brief generates the 32 bit encoding for the power curve attributes
-/// @return fapi2::ReturnCode FAPI2_RC_SUCCESS iff the encoding was successful
-/// @note populates iv_gen_keys
-///
-fapi2::ReturnCode decoder::generate_encoding()
-{
- //DIMM_SIZE
- FAPI_TRY(( encode<DIMM_SIZE_START, DIMM_SIZE_LEN>
- (iv_kind.iv_target, iv_kind.iv_size, DIMM_SIZE_MAP, iv_gen_key)),
- "Failed to generate power thermal encoding for %s val %d on target: %s",
- "DIMM_SIZE", iv_kind.iv_size, c_str(iv_kind.iv_target) );
-
- //DRAM_GEN
- FAPI_TRY(( encode<DRAM_GEN_START, DRAM_GEN_LEN>
- (iv_kind.iv_target, iv_kind.iv_dram_generation, DRAM_GEN_MAP, iv_gen_key)),
- "Failed to generate power thermal encoding for %s val %d on target: %s",
- "DRAM_GEN", iv_kind.iv_dram_generation, c_str(iv_kind.iv_target) );
-
- //DIMM_TYPE
- FAPI_TRY(( encode<DIMM_TYPE_START, DIMM_TYPE_LEN>
- (iv_kind.iv_target, iv_kind.iv_dimm_type, DIMM_TYPE_MAP, iv_gen_key)),
- "Failed to generate power thermal encoding for %s val %d on target: %s",
- "DIMM_TYPE", iv_kind.iv_dimm_type, c_str(iv_kind.iv_target) );
-
- //DRAM WIDTH
- FAPI_TRY(( encode<DRAM_WIDTH_START, DRAM_WIDTH_LEN>
- (iv_kind.iv_target, iv_kind.iv_dram_width, DRAM_WIDTH_MAP, iv_gen_key)),
- "Failed to generate power thermal encoding for %s val %d on target: %s",
- "DRAM_WIDTH", iv_kind.iv_dram_width, c_str(iv_kind.iv_target) );
-
- //DRAM DENSITY
- FAPI_TRY(( encode<DRAM_DENSITY_START, DRAM_DENSITY_LEN>
- (iv_kind.iv_target, iv_kind.iv_dram_density, DRAM_DENSITY_MAP, iv_gen_key)),
- "Failed to generate power thermal encoding for %s val %d on target: %s",
- "DRAM_DENSITY", iv_kind.iv_dram_density, c_str(iv_kind.iv_target) );
-
- //DRAM STACK TYPE
- FAPI_TRY(( encode<DRAM_STACK_TYPE_START, DRAM_STACK_TYPE_LEN>
- (iv_kind.iv_target, iv_kind.iv_stack_type, DRAM_STACK_TYPE_MAP, iv_gen_key)),
- "Failed to generate power thermal encoding for %s val %d on target: %s",
- "DRAM_STACK_TYPE", iv_kind.iv_stack_type, c_str(iv_kind.iv_target) );
-
- //DRAM MFG ID
- FAPI_TRY(( encode<DRAM_MFGID_START, DRAM_MFGID_LEN>
- (iv_kind.iv_target, iv_kind.iv_mfgid, DRAM_MFGID_MAP, iv_gen_key)),
- "Failed to generate power thermal encoding for %s val %d on target: %s",
- "DRAM_MFG_ID", iv_kind.iv_mfgid, c_str(iv_kind.iv_target) );
-
- //NUM DROPS PER PORT
- FAPI_TRY(( encode<DIMMS_PER_PORT_START, DIMMS_PER_PORT_LEN>
- (iv_kind.iv_target, iv_dimms_per_port, DIMMS_PORT_MAP, iv_gen_key)),
- "Failed to generate power thermal encoding for %s val %d on target: %s",
- "DIMMS_PER_PORT", iv_dimms_per_port, c_str(iv_kind.iv_target) );
-
-fapi_try_exit:
- return fapi2::current_err;
-}
-///
-///@brief a compare functor for the decoder::find_attr functions below
-///@note AND's the input hash with the generated hash from the DIMM to see if they match
-///@note Using an AND instead of == because not all DIMM configs have power slopes, so defaults are needed
-///
-struct is_match
+const std::vector< std::pair<uint8_t , uint8_t> > throttle_traits<mss::mc_type::NIMBUS>::DIMM_TYPE_MAP =
{
- ///
- ///@brief functor constructor
- ///@param[in] i_gen_key the class object's constructed hash for the installed dimm, to be compared with the attr array
- ///
- is_match(const uint32_t i_gen_key) : iv_gen_key(i_gen_key) {}
- const fapi2::buffer<uint32_t> iv_gen_key;
-
- ///
- ///@brief Boolean compare used for find_if function
- ///
- bool operator()(const uint64_t i_hash)
- {
- // l_this_hash is the first half of the i_hash's bits
- uint32_t l_this_hash = i_hash >> 32;
- return ((l_this_hash & iv_gen_key) == iv_gen_key);
- }
+ {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},
+ {ANY_TYPE, 0b11}
};
///
@@ -146,16 +68,21 @@ struct is_match
/// @return fapi2::ReturnCode FAPI2_RC_SUCCESS iff the encoding was successful
/// @note populates iv_vddr_slope, iv_total_slop
///
-fapi2::ReturnCode decoder::find_slope (const std::vector<uint64_t>& i_slope)
+template<>
+fapi2::ReturnCode decoder<mss::mc_type::NIMBUS>::find_slope (
+ const std::vector< const std::vector<uint64_t>* >& i_slope)
{
+ using TT = throttle_traits<mss::mc_type::NIMBUS>;
+
+ // For nimbus only one attribute is used to get slope (i_slope[0])
// Find iterator to matching key (if it exists)
- const auto l_value_iterator = std::find_if(i_slope.begin(),
- i_slope.end(),
- is_match(iv_gen_key));
+ const auto l_value_iterator = std::find_if((*i_slope[0]).begin(),
+ (*i_slope[0]).end(),
+ is_match<>(iv_gen_key));
//Should have matched with the default ATTR value at least
//The last value should always be the default value
- FAPI_ASSERT(l_value_iterator != i_slope.end(),
+ FAPI_ASSERT(l_value_iterator != (*i_slope[0]).end(),
fapi2::MSS_NO_POWER_THERMAL_ATTR_FOUND()
.set_GENERATED_KEY(iv_gen_key)
.set_FUNCTION(SLOPE)
@@ -184,8 +111,8 @@ fapi2::ReturnCode decoder::find_slope (const std::vector<uint64_t>& i_slope)
{
const fapi2::buffer<uint64_t> l_temp(*l_value_iterator);
- l_temp.extractToRight<VDDR_START, VDDR_LENGTH>( iv_vddr_slope);
- l_temp.extractToRight<TOTAL_START, TOTAL_LENGTH>(iv_total_slope);
+ l_temp.extractToRight<TT::VDDR_START, TT::VDDR_LENGTH>( iv_vddr_slope);
+ l_temp.extractToRight<TT::TOTAL_START, TT::TOTAL_LENGTH>(iv_total_slope);
}
fapi_try_exit:
return fapi2::current_err;
@@ -197,15 +124,19 @@ fapi_try_exit:
/// @return fapi2::ReturnCode FAPI2_RC_SUCCESS iff the encoding was successful
/// @note populates iv_vddr_intercept, iv_total_intercept
///
-fapi2::ReturnCode decoder::find_intercept (const std::vector<uint64_t>& i_intercept)
+template<>
+fapi2::ReturnCode decoder<mss::mc_type::NIMBUS>::find_intercept (
+ const std::vector< const std::vector<uint64_t>* >& i_intercept)
{
+ using TT = throttle_traits<mss::mc_type::NIMBUS>;
+
// Find iterator to matching key (if it exists)
- const auto l_value_iterator = std::find_if(i_intercept.begin(),
- i_intercept.end(),
- is_match(iv_gen_key));
+ const auto l_value_iterator = std::find_if((*i_intercept[0]).begin(),
+ (*i_intercept[0]).end(),
+ is_match<>(iv_gen_key));
//Should have matched with the all default ATTR at least
//The last value should always be the default value
- FAPI_ASSERT(l_value_iterator != i_intercept.end(),
+ FAPI_ASSERT(l_value_iterator != (*i_intercept[0]).end(),
fapi2::MSS_NO_POWER_THERMAL_ATTR_FOUND()
.set_GENERATED_KEY(iv_gen_key)
.set_FUNCTION(INTERCEPT)
@@ -234,31 +165,36 @@ fapi2::ReturnCode decoder::find_intercept (const std::vector<uint64_t>& i_interc
{
const fapi2::buffer<uint64_t> l_temp(*l_value_iterator);
- l_temp.extractToRight<VDDR_START, VDDR_LENGTH>( iv_vddr_intercept);
- l_temp.extractToRight<TOTAL_START, TOTAL_LENGTH>(iv_total_intercept);
+ l_temp.extractToRight<TT::VDDR_START, TT::VDDR_LENGTH>( iv_vddr_intercept);
+ l_temp.extractToRight<TT::TOTAL_START, TT::TOTAL_LENGTH>(iv_total_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
+/// @note populates thermal_power_limit.
///
-fapi2::ReturnCode decoder::find_thermal_power_limit (const std::vector<uint64_t>& i_thermal_limits)
+template<>
+fapi2::ReturnCode decoder<mss::mc_type::NIMBUS>::find_thermal_power_limit (
+ const std::vector< const std::vector<uint64_t>* >& i_thermal_limits)
{
+ using TT = throttle_traits<mss::mc_type::NIMBUS>;
+
// Find iterator to matching key (if it exists)
- const auto l_value_iterator = std::find_if(i_thermal_limits.begin(),
- i_thermal_limits.end(),
- is_match(iv_gen_key));
+ const auto l_value_iterator = std::find_if((*i_thermal_limits[0]).begin(),
+ (*i_thermal_limits[0]).end(),
+ is_match<>(iv_gen_key));
fapi2::buffer<uint64_t> l_temp;
//Should have matched with the all default ATTR at least
//The last value should always be the default value
- FAPI_ASSERT(l_value_iterator != i_thermal_limits.end(),
+ FAPI_ASSERT(l_value_iterator != (*i_thermal_limits[0]).end(),
fapi2::MSS_NO_POWER_THERMAL_ATTR_FOUND()
.set_GENERATED_KEY(iv_gen_key)
.set_FUNCTION(POWER_LIMIT)
@@ -287,11 +223,13 @@ fapi2::ReturnCode decoder::find_thermal_power_limit (const std::vector<uint64_t>
{
const fapi2::buffer<uint64_t> l_temp(*l_value_iterator);
- l_temp.extractToRight<THERMAL_POWER_START, THERMAL_POWER_LENGTH>( iv_thermal_power_limit);
+ l_temp.extractToRight<TT::THERMAL_POWER_START, TT::THERMAL_POWER_LENGTH>( iv_thermal_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
@@ -317,13 +255,15 @@ fapi2::ReturnCode get_power_attrs (const fapi2::Target<fapi2::TARGET_TYPE_MCS>&
uint16_t o_total_int [PORTS_PER_MCS][MAX_DIMM_PER_PORT],
uint32_t o_thermal_power [PORTS_PER_MCS][MAX_DIMM_PER_PORT])
{
+ using TT = throttle_traits<mss::mc_type::NIMBUS>;
+
for (const auto& l_dimm : find_targets <fapi2::TARGET_TYPE_DIMM> (i_mcs))
{
- const auto l_mca_pos = mss::index (find_target<TARGET_TYPE_MCA>(l_dimm));
+ const auto l_mca_pos = mss::index (find_target<fapi2::TARGET_TYPE_MCA>(l_dimm));
const auto l_dimm_pos = mss::index (l_dimm);
mss::dimm::kind l_kind (l_dimm);
- mss::power_thermal::decoder l_decoder(l_kind);
+ mss::power_thermal::decoder<> l_decoder(l_kind);
FAPI_TRY( l_decoder.generate_encoding(), "%s Error in get_power_attrs", mss::c_str(i_mcs) );
// The first entry into these arrays must be valid
@@ -331,12 +271,13 @@ fapi2::ReturnCode get_power_attrs (const fapi2::Target<fapi2::TARGET_TYPE_MCS>&
if (i_slope.empty() || i_slope[0] == 0)
{
FAPI_INF("%s ATTR_MSS_MRW_PWR_SLOPE not found!!", mss::c_str(i_mcs));
- o_vddr_slope [l_mca_pos][l_dimm_pos] = default_power::VDDR_SLOPE;
- o_total_slope [l_mca_pos][l_dimm_pos] = default_power::TOTAL_SLOPE;
+ o_vddr_slope [l_mca_pos][l_dimm_pos] = TT::VDDR_SLOPE;
+ o_total_slope [l_mca_pos][l_dimm_pos] = TT::TOTAL_SLOPE;
}
else
{
- FAPI_TRY( l_decoder.find_slope(i_slope), "%s Error in get_power_attrs", mss::c_str(i_mcs) );
+ const std::vector< const std::vector<uint64_t>* > l_slope {&i_slope};
+ FAPI_TRY( l_decoder.find_slope(l_slope), "%s Error in get_power_attrs", mss::c_str(i_mcs) );
o_vddr_slope [l_mca_pos][l_dimm_pos] = l_decoder.iv_vddr_slope;
o_total_slope [l_mca_pos][l_dimm_pos] = l_decoder.iv_total_slope;
}
@@ -344,12 +285,13 @@ fapi2::ReturnCode get_power_attrs (const fapi2::Target<fapi2::TARGET_TYPE_MCS>&
if (i_intercept.empty() || i_intercept[0] == 0)
{
FAPI_INF("%s ATTR_MSS_MRW_PWR_INTERCEPT not found!!", mss::c_str(i_mcs));
- o_total_int [l_mca_pos][l_dimm_pos] = default_power::TOTAL_INT;
- o_vddr_int [l_mca_pos][l_dimm_pos] = default_power::VDDR_INT;
+ o_total_int [l_mca_pos][l_dimm_pos] = TT::TOTAL_INT;
+ o_vddr_int [l_mca_pos][l_dimm_pos] = TT::VDDR_INT;
}
else
{
- FAPI_TRY( l_decoder.find_intercept(i_intercept), "%s Error in get_power_attrs", mss::c_str(i_mcs) );
+ std::vector< const std::vector<uint64_t>* > l_intercept {&i_intercept};
+ FAPI_TRY( l_decoder.find_intercept(l_intercept), "%s Error in get_power_attrs", mss::c_str(i_mcs) );
o_vddr_int [l_mca_pos][l_dimm_pos] = l_decoder.iv_vddr_intercept;
o_total_int [l_mca_pos][l_dimm_pos] = l_decoder.iv_total_intercept;
}
@@ -357,11 +299,12 @@ fapi2::ReturnCode get_power_attrs (const fapi2::Target<fapi2::TARGET_TYPE_MCS>&
if (i_thermal_power_limit.empty() || i_thermal_power_limit[0] == 0)
{
FAPI_INF("%s ATTR_MSS_MRW_THERMAL_MEMORY_POWER_LIMIT not found!!", mss::c_str(i_mcs));
- o_thermal_power [l_mca_pos][l_dimm_pos] = default_power::THERMAL_LIMIT;
+ o_thermal_power [l_mca_pos][l_dimm_pos] = TT::THERMAL_LIMIT;
}
else
{
- FAPI_TRY( l_decoder.find_thermal_power_limit(i_thermal_power_limit),
+ std::vector< const std::vector<uint64_t>* > l_thermal_power_limit {&i_thermal_power_limit};
+ FAPI_TRY( l_decoder.find_thermal_power_limit(l_thermal_power_limit),
"%s Error in get_power_attrs", mss::c_str(i_mcs) );
o_thermal_power [l_mca_pos][l_dimm_pos] = l_decoder.iv_thermal_power_limit;
}
diff --git a/src/import/chips/p9/procedures/hwp/memory/lib/power_thermal/decoder.H b/src/import/chips/p9/procedures/hwp/memory/lib/power_thermal/decoder.H
index ac1efcdbe..f26421ea4 100644
--- a/src/import/chips/p9/procedures/hwp/memory/lib/power_thermal/decoder.H
+++ b/src/import/chips/p9/procedures/hwp/memory/lib/power_thermal/decoder.H
@@ -36,222 +36,17 @@
#define _MSS_POWER_DECODER__
#include <fapi2.H>
+#include <lib/shared/mss_const.H>
#include <lib/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
{
-enum size_of_attrs : size_t
-{
- SIZE_OF_POWER_CURVES_ATTRS = 100,
- SIZE_OF_THERMAL_ATTR = 10,
-};
-
-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).
- VDDR_SLOPE = 0x41A,
- VDDR_INT = 0x384,
- TOTAL_SLOPE = 0x44C,
- TOTAL_INT = 0x44C,
- THERMAL_LIMIT = 0x794,
-};
-
-//Currently needs to be in sorted order for lookup to work
-static const std::vector< std::pair<uint32_t , uint8_t> > DIMM_SIZE_MAP =
-{
- {4, 0b0000},
- {8, 0b0001},
- {16, 0b0010},
- {32, 0b0011},
- {64, 0b0100},
- {128, 0b0101},
- {256, 0b0110},
- {512, 0b0111},
-};
-
-static const std::vector< std::pair<uint8_t , uint8_t> > DIMM_TYPE_MAP =
-{
- {fapi2::ENUM_ATTR_EFF_DIMM_TYPE_RDIMM, 0b00},
- {fapi2::ENUM_ATTR_EFF_DIMM_TYPE_UDIMM, 0b01},
- {fapi2::ENUM_ATTR_EFF_DIMM_TYPE_LRDIMM, 0b10},
-};
-
-static const std::vector< std::pair<uint8_t , uint8_t> > DRAM_GEN_MAP =
-{
- {fapi2::ENUM_ATTR_EFF_DRAM_GEN_EMPTY, 0b00},
- {fapi2::ENUM_ATTR_EFF_DRAM_GEN_DDR3, 0b01},
- {fapi2::ENUM_ATTR_EFF_DRAM_GEN_DDR4, 0b10}
-};
-
-static const std::vector <std::pair<uint8_t, uint8_t> > DRAM_WIDTH_MAP =
-{
- {fapi2::ENUM_ATTR_EFF_DRAM_WIDTH_X4, 0b000},
- {fapi2::ENUM_ATTR_EFF_DRAM_WIDTH_X8, 0b001},
- {fapi2::ENUM_ATTR_EFF_DRAM_WIDTH_X16, 0b010},
- {fapi2::ENUM_ATTR_EFF_DRAM_WIDTH_X32, 0b011}
-};
-
-static const std::vector< std::pair<uint8_t , uint8_t> > DRAM_DENSITY_MAP =
-{
- {4, 0b000},
- {8, 0b001},
- {16, 0b010},
- {32, 0b011},
- {64, 0b100},
-};
-
-static const std::vector <std::pair<uint8_t, uint8_t> > DRAM_STACK_TYPE_MAP =
-{
- {fapi2::ENUM_ATTR_EFF_PRIM_STACK_TYPE_SDP, 0b00},
- {fapi2::ENUM_ATTR_EFF_PRIM_STACK_TYPE_DDP_QDP, 0b01},
- {fapi2::ENUM_ATTR_EFF_PRIM_STACK_TYPE_3DS, 0b10}
-};
-
-//Note, the first entries of the pairs need to be in sorted order!!
-static const std::vector <std::pair<uint16_t, uint8_t> > DRAM_MFGID_MAP =
-{
- //Kingston
- {0x0198, 0b011},
- //A-data
- {0x04CB, 0b101},
- //Micron
- {0x802C, 0b000},
- //HYNIX
- {0x80AD, 0b001},
- //SAMSUNG
- {0x80CE, 0b010},
- //Innodisk
- {0x86F1, 0b100},
-};
-
-static const std::vector < std::pair< uint8_t, uint8_t> > DIMMS_PORT_MAP =
-{
- //Num dimms per MCA, only 1 or 2 possible options. 0 is no-op
- {1, 0b00},
- {2, 0b01}
-};
-
-//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,
- VDDR_START = 32,
- VDDR_LENGTH = 16,
- TOTAL_START = 48,
- TOTAL_LENGTH = 16,
- THERMAL_POWER_START = 32,
- THERMAL_POWER_LENGTH = 32,
-};
-
-//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 = 2,
-
- DRAM_WIDTH_START = 8,
- DRAM_WIDTH_LEN = 3,
-
- DRAM_DENSITY_START = 11,
- DRAM_DENSITY_LEN = 3,
-
- DRAM_STACK_TYPE_START = 14,
- DRAM_STACK_TYPE_LEN = 2,
-
- DRAM_MFGID_START = 16,
- DRAM_MFGID_LEN = 3,
-
- DIMMS_PER_PORT_START = 19,
- DIMMS_PER_PORT_LEN = 2,
-};
-
-///
-/// @class decoder
-/// @brief Decodes the power curve and thermal power limit attributes for eff_config_thermal
-///
-class decoder
-{
- public:
-
- //IVs for all of the attributes per MCS
- const mss::dimm::kind iv_kind;
-
- //Left in here rather than calculating during encode for testing
- uint8_t iv_dimms_per_port;
-
- //Power thermal attributes, both total and vddr versions will be used in eff_config_thermal
- uint16_t iv_vddr_slope;
- uint16_t iv_vddr_intercept;
- uint16_t iv_total_slope;
- uint16_t iv_total_intercept;
-
- uint32_t iv_thermal_power_limit;
- //Generated key, used to decode all three power curve attributes
- fapi2::buffer<uint32_t> iv_gen_key;
-
- ///
- /// @brief Constructor
- /// @param[in] dimm::kind to call power thermal stuff on
- ///
- decoder( mss::dimm::kind& i_kind):
- iv_kind(i_kind)
- {
- iv_dimms_per_port = mss::count_dimm (find_target<fapi2::TARGET_TYPE_MCA>(iv_kind.iv_target));
- };
-
- //
- // @brief Default destructor
- //
- ~decoder() = default;
-
- ///
- /// @brief generates the 32 bit encoding for the power curve attributes
- /// @return fapi2::ReturnCode FAPI2_RC_SUCCESS iff the encoding was successful
- /// @note populates iv_gen_key
- ///
- fapi2::ReturnCode generate_encoding ();
-
- ///
- /// @brief Finds a value for the power curve slope attributes by matching the generated hashes
- /// @param[in] i_array is a vector of the attribute values
- /// @return fapi2::ReturnCode FAPI2_RC_SUCCESS iff the encoding was successful
- /// @note populates iv_vddr_slope, iv_total_slope
- ///
- fapi2::ReturnCode find_slope (const std::vector<uint64_t>& i_slope);
-
- ///
- /// @brief Finds a value for power curve intercept attributes by matching the generated hashes
- /// @param[in] i_array is a vector of the attribute values
- /// @return fapi2::ReturnCode FAPI2_RC_SUCCESS iff the encoding was successful
- /// @note populates iv_vddr_intercept, iv_total_intercept
- ///
- fapi2::ReturnCode find_intercept (const std::vector<uint64_t>& i_intercept);
-
- ///
- /// @brief Finds a value from ATTR_MSS_MRW_THERMAL_MEMORY_POWER_LIMIT and stores in iv variable
- /// @param[in] i_array is a vector of the attribute values
- /// @return fapi2::ReturnCode FAPI2_RC_SUCCESS iff the encoding was successful
- /// @note populates iv_thermal_power_limit
- ///
- fapi2::ReturnCode find_thermal_power_limit (const std::vector<uint64_t>& i_thermal_limits);
-
-};
///
/// @brief find the power curve attributes for each dimm on an MCS target
@@ -277,70 +72,6 @@ fapi2::ReturnCode get_power_attrs (const fapi2::Target<fapi2::TARGET_TYPE_MCS>&
uint16_t o_total_slope [PORTS_PER_MCS][MAX_DIMM_PER_PORT],
uint16_t o_total_int [PORTS_PER_MCS][MAX_DIMM_PER_PORT],
uint32_t o_thermal_power [PORTS_PER_MCS][MAX_DIMM_PER_PORT]);
-///
-/// @brief Encode the attribute into a bit encoding
-/// @tparam[in] S *ATTR*_SIZE enum used for fapi2::buffer position
-/// @tparam[in] L *ATTR*_LEN enum used for fapi2::buffer position
-/// @tparam[in] OT fapi2::buffer of some integral type
-/// @tparam[in] T integral type of key
-/// @param[in] i_target the DIMM the encoding is for
-/// @param[in] i_attr the attribute key being used for the encoding
-/// @param[in] i_map a vector of pairs of the ATTR values and encodings for each value, sorted
-/// @param[out] o_buf the fapi2::buffer where the encoding is going into
-/// @return fapi2::ReturnCode FAPI2_RC_SUCCESS iff attribute is found in map lookup
-///
-template<size_t S, size_t L, typename T, typename OT>
-inline fapi2::ReturnCode encode ( const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target,
- const T& i_attr,
- const std::vector<std::pair<T, OT> >& i_map,
- fapi2::buffer<uint32_t>& o_buf)
-{
- //used to hold result from vector pair lookup
- OT l_encoding = 0;
-
- //Failing out if we don't find an encoding. All suported types should be encoded above
- FAPI_ASSERT( mss::find_value_from_key (i_map, i_attr, l_encoding),
- fapi2::MSS_POWER_THERMAL_ENCODE_ERROR()
- .set_ATTR(i_attr)
- .set_DIMM_TARGET(i_target),
- "Couldn't find encoding for power thermal encode for value: %x target: %s", i_attr, mss::c_str(i_target));
- o_buf.insertFromRight<S, L>(l_encoding);
-
-fapi_try_exit:
- return fapi2::current_err;
-}
-
-///
-/// @brief Decode the attribute into a bit encoding
-/// @tparam[in] S DRAM_GEN_SIZE enum used for fapi2::buffer position
-/// @tparam[in] L DRAM_GEN_LEN enum used for fapi2::buffer position
-/// @tparam[in] OT fapi2::buffer of some integral type
-/// @tparam[in] T integral type of key
-/// @param[in] i_target the DIMM the encoding is for
-/// @param[in] i_map a vector of pairs of the ATTR values and encodings for each value
-/// @param[in] i_buf the fapi2::buffer that has the encoding to parse
-/// @param[out] o_attr the attribute value from the encoding is going
-/// @return fapi2::ReturnCode FAPI2_RC_SUCCESS iff attribute is found in map lookup
-///
-template<size_t S, size_t L, typename T, typename OT>
-inline fapi2::ReturnCode decode ( const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target,
- const std::vector<std::pair<T, OT> >& i_map,
- fapi2::buffer<uint32_t>& i_buf,
- T& o_attr )
-{
- //used to hold result from vector pair lookup
- OT l_encoding = 0;
- i_buf.extractToRight<S, L>(l_encoding);
-
- //Failing out if we don't find an decoding. All suported types should be encoded above
- FAPI_ASSERT( mss::find_key_from_value (i_map, l_encoding, o_attr),
- fapi2::MSS_POWER_THERMAL_DECODE_ERROR()
- .set_ATTR(l_encoding)
- .set_DIMM_TARGET(i_target),
- "Couldn't find encoding for power thermal decode for target: %s", mss::c_str(i_target));
-fapi_try_exit:
- return fapi2::current_err;
-}
} // power_thermal
} // mss
diff --git a/src/import/chips/p9/procedures/hwp/memory/lib/power_thermal/throttle.C b/src/import/chips/p9/procedures/hwp/memory/lib/power_thermal/throttle.C
index 82a5e2c6e..0ef22bddd 100644
--- a/src/import/chips/p9/procedures/hwp/memory/lib/power_thermal/throttle.C
+++ b/src/import/chips/p9/procedures/hwp/memory/lib/power_thermal/throttle.C
@@ -31,6 +31,8 @@
// *HWP Team: Memory
// *HWP Level: 3
// *HWP Consumed by: FSP:HB
+
+#include <lib/shared/nimbus_defaults.H>
//std lib
#include<algorithm>
// fapi2
@@ -41,687 +43,12 @@
#include <generic/memory/lib/utils/count_dimm.H>
#include <generic/memory/lib/utils/pos.H>
-using fapi2::TARGET_TYPE_MCA;
-using fapi2::TARGET_TYPE_MCS;
-using fapi2::TARGET_TYPE_DIMM;
-using fapi2::TARGET_TYPE_MCBIST;
-
namespace mss
{
namespace power_thermal
{
///
-/// @brief Constructor
-/// @param[in] i_target MCS target to call power thermal stuff on
-/// @param[out] o_rc, a return code which determines the success of the constructor
-///
-throttle::throttle( const fapi2::Target<fapi2::TARGET_TYPE_MCA>& i_mca, fapi2::ReturnCode& o_rc) :
- iv_target(i_mca),
- iv_databus_port_max(0),
- iv_runtime_n_slot(0),
- iv_runtime_n_port(0),
- iv_n_slot(0),
- iv_n_port(0),
- iv_port_power_limit(0),
- iv_calc_port_maxpower(0)
-{
- //holder for watt_target to add up for port
- uint32_t l_dimm_power_limits [MAX_DIMM_PER_PORT] = {};
-
- FAPI_TRY( mrw_max_dram_databus_util(iv_databus_port_max), "%s Error in throttle ctor", mss::c_str(i_mca) );
- FAPI_TRY( mrw_dimm_power_curve_percent_uplift(iv_power_uplift), "%s Error in throttle ctor", mss::c_str(i_mca) );
- FAPI_TRY( mrw_dimm_power_curve_percent_uplift_idle(iv_power_uplift_idle), "%s Error in throttle ctor",
- mss::c_str(i_mca) );
- FAPI_TRY( dimm_thermal_limit( iv_target, iv_dimm_thermal_limit), "%s Error in throttle ctor", mss::c_str(i_mca) );
- FAPI_TRY( total_pwr_intercept( iv_target, iv_pwr_int), "%s Error in throttle ctor", mss::c_str(i_mca) );
- FAPI_TRY( total_pwr_slope( iv_target, iv_pwr_slope), "%s Error in throttle ctor", mss::c_str(i_mca) );
- FAPI_TRY( runtime_mem_throttled_n_commands_per_slot(iv_target, iv_runtime_n_slot ), "%s Error in throttle ctor",
- mss::c_str(i_mca) );
- FAPI_TRY( runtime_mem_throttled_n_commands_per_port(iv_target, iv_runtime_n_port ), "%s Error in throttle ctor",
- mss::c_str(i_mca) );
- FAPI_TRY( mem_watt_target( iv_target, l_dimm_power_limits), "%s Error in throttle ctor", mss::c_str(i_mca) );
- FAPI_TRY( mrw_mem_m_dram_clocks(iv_m_clocks), "%s Error in throttle ctor", mss::c_str(i_mca) );
-
- //Port power limit = sum of dimm power limits
- for ( const auto& l_dimm : mss::find_targets<TARGET_TYPE_DIMM>(iv_target) )
- {
- iv_port_power_limit += l_dimm_power_limits[mss::index(l_dimm)];
- }
-
- FAPI_INF("Setting up throttle for target %s, Values are: max databus is %d, uplifts are %d %d, runtime throttles are %d %d",
- mss::c_str(iv_target),
- iv_databus_port_max,
- iv_power_uplift,
- iv_power_uplift_idle,
- iv_runtime_n_slot,
- iv_runtime_n_port);
-
- FAPI_INF("The dimm power limit for dimm0 is %d, dimm1 is %d, port power limit is %d, dram clocks are %d, dimm power curve slopes are %d %d,",
- l_dimm_power_limits[0],
- l_dimm_power_limits[1],
- iv_port_power_limit,
- iv_m_clocks,
- iv_pwr_slope[0],
- iv_pwr_slope[1]);
-
- FAPI_INF("DIMM power curve intercepts are %d %d, DIMM power thermal limits are %d %d",
- iv_pwr_int[0],
- iv_pwr_int[1],
- iv_dimm_thermal_limit[0],
- iv_dimm_thermal_limit[1]);
-
- FAPI_ASSERT( (iv_databus_port_max != 0),
- fapi2::MSS_NO_DATABUS_UTILIZATION()
- .set_PORT_DATABUS_UTIL(iv_databus_port_max)
- .set_DIMM_COUNT(mss::count_dimm(iv_target)),
- "Failed to get max databus utilization for target %s",
- mss::c_str(iv_target));
-
- FAPI_ASSERT( (iv_port_power_limit != 0),
- fapi2::MSS_NO_PORT_POWER_LIMIT()
- .set_COUNT_DIMMS( mss::count_dimm(iv_target))
- .set_PORT_POWER_LIMIT( iv_port_power_limit),
- "Error calculating port_power_limit on target %s with %d DIMMs installed",
- mss::c_str(iv_target),
- iv_port_power_limit);
-
- //Checking to make sure all of the attributes are valid
- for ( const auto& l_dimm : mss::find_targets<TARGET_TYPE_DIMM>(iv_target) )
- {
- const auto l_pos = mss::index(l_dimm);
- FAPI_ASSERT( (iv_pwr_int[l_pos] != 0),
- fapi2::MSS_POWER_INTERCEPT_NOT_SET(),
- "The attribute ATTR_MSS_TOTAL_PWR_INTERCEPT equals 0 for %s",
- mss::c_str(l_dimm));
-
- FAPI_ASSERT( (iv_pwr_slope[l_pos] != 0),
- fapi2::MSS_POWER_SLOPE_NOT_SET(),
- "The attribute ATTR_MSS_TOTAL_PWR_SLOPE equals 0 for %s",
- mss::c_str(l_dimm));
- }
-
-fapi_try_exit:
- o_rc = fapi2::current_err;
- return;
-}
-
-///
-/// @brief Set ATTR_MSS_CHANNEL_PAIR_MAXPOWER, ATTR_MSS_MEM_THROTTLED_N_COMMANDS_PER_SLOT and _PER_PORT
-/// @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,
-/// @note the _per_slot throttles are set to the _per_port values
-/// @note throttles are all equalized and set to the worst case value
-///
-fapi2::ReturnCode throttle::power_regulator_throttles ()
-{
- double l_port_power_calc_idle = 0;
- double l_port_power_calc_max = 0;
- uint32_t l_port_power_slope = 0;
- uint32_t l_port_power_int = 0;
- double l_calc_util_port = 0;
- double l_databus_dimm_max[MAX_DIMM_PER_PORT] = {};
- double l_calc_databus_port_idle[MAX_DIMM_PER_PORT] = {IDLE_UTIL, IDLE_UTIL};
-
- FAPI_INF("Starting power regulator throttles");
-
- //Decide utilization for each dimm based off of dimm count and power slopes
- FAPI_TRY( calc_databus(iv_databus_port_max, l_databus_dimm_max),
- "Failed to calculate each DIMMs' percentage of dram databus utilization for target %s, max port databus is %d",
- mss::c_str(iv_target),
- iv_databus_port_max);
-
- //Use the dimm utilizations and dimm power slopes to calculate port min and max power
- FAPI_TRY( calc_port_power(l_calc_databus_port_idle,
- l_databus_dimm_max,
- l_port_power_calc_idle,
- l_port_power_calc_max),
- "Failed to calculate the max and idle power for port %s",
- mss::c_str(iv_target));
-
- FAPI_INF("POWER throttles: %s max port power is %f", mss::c_str(iv_target), l_port_power_calc_max);
-
- //Calculate the power curve slope and intercept using the port's min and max power values
- FAPI_TRY(calc_power_curve(l_port_power_calc_idle,
- l_port_power_calc_max,
- l_port_power_slope,
- l_port_power_int),
- "Failed to calculate the power curve for port %s, calculated port power max is %d, idle is %d",
- mss::c_str(iv_target),
- l_port_power_calc_max,
- l_port_power_calc_idle);
-
- FAPI_INF("%s POWER Port power limit is %d", mss::c_str(iv_target), iv_port_power_limit);
- //Calculate the port's utilization to get under watt target using the port's calculated slopes
- calc_util_usage(l_port_power_slope,
- l_port_power_int,
- iv_port_power_limit,
- l_calc_util_port);
-
- FAPI_INF("%s POWER calc util port is %f", mss::c_str(iv_target), l_calc_util_port);
-
- //Calculate the new slot values and the max power value for the port
- FAPI_TRY( calc_slots_and_power( l_calc_util_port),
- "%s Error calculating the final throttles and power values for target with passed in port utilization %d",
- mss::c_str(iv_target),
- l_calc_util_port);
-
-fapi_try_exit:
- return fapi2::current_err;
-}
-
-///
-/// @brief set iv_n_port, iv_n_slot, iv_calc_port_maxpower
-/// @param[in] i_util_port pass in the calculated port databus utilization
-/// @return fapi2::ReturnCode - FAPI2_RC_SUCCESS iff get is OK
-///
-fapi2::ReturnCode throttle::calc_slots_and_power (const double i_util_port)
-{
- //Calculate the Port N throttles
- iv_n_port = power_thermal::throttled_cmds(i_util_port, iv_m_clocks);
-
- //Set iv_n_slot to the lower value between the slot runtime and iv_n_port
- iv_n_slot = (iv_runtime_n_slot != 0) ? std::min (iv_n_port, iv_runtime_n_slot) : iv_n_port;
-
- //Choose the lowest value of the runtime and the calculated
- iv_n_port = (iv_runtime_n_port != 0) ? std::min (iv_n_port, iv_runtime_n_port) : iv_n_port;
-
- //Use the throttle value to calculate the power that gets to exactly that value
- FAPI_TRY( calc_power_from_n(iv_n_slot, iv_n_port, iv_calc_port_maxpower));
-
-fapi_try_exit:
- return fapi2::current_err;
-}
-
-///
-/// @brief Set ATTR_MSS_MEM_THROTTLED_N_COMMANDS_PER_SLOT and PER_PORT
-/// @return fapi2::ReturnCode - FAPI2_RC_SUCCESS iff get is OK
-/// @note Called in p9_mss_bulk_pwr_throttles
-/// @note Sets the throttle levels based off of the dimm's thermal limits
-/// @note both DIMM's on a port are set to the same throttle level
-///
-fapi2::ReturnCode throttle::thermal_throttles ()
-{
- double l_dimm_power_idle [MAX_DIMM_PER_PORT] = {};
- double l_dimm_power_max [MAX_DIMM_PER_PORT] = {};
- uint32_t l_dimm_power_slope [MAX_DIMM_PER_PORT] = {};
- uint32_t l_dimm_power_int [MAX_DIMM_PER_PORT] = {};
- double l_calc_util [MAX_DIMM_PER_PORT] = {};
- const auto l_count = count_dimm (iv_target);
-
- //Calculate the dimm power range for each dimm at max utilization for each
- calc_dimm_power(power_thermal::IDLE_UTIL,
- iv_databus_port_max,
- l_dimm_power_idle,
- l_dimm_power_max);
-
- //Let's calculate the N throttle for each DIMM
- for ( const auto& l_dimm : mss::find_targets<TARGET_TYPE_DIMM>(iv_target) )
- {
- uint16_t l_temp_n_slot = 0;
- uint8_t l_pos = mss::index(l_dimm);
- //Calculate the power curve taking the thermal limit into account
- FAPI_TRY( calc_power_curve(l_dimm_power_idle[l_pos],
- l_dimm_power_max[l_pos],
- l_dimm_power_slope[l_pos],
- l_dimm_power_int[l_pos]),
- "Failed to calculate the power curve for dimm %s, calculated dimm power curve slope is %d, intercept %d",
- mss::c_str(l_dimm),
- l_dimm_power_slope[l_pos],
- l_dimm_power_int[l_pos]);
-
- //Calculate the databus utilization at the calculated power curve
- calc_util_usage(l_dimm_power_slope[l_pos],
- l_dimm_power_int[l_pos],
- iv_dimm_thermal_limit[l_pos],
- l_calc_util[l_pos]);
-
- FAPI_INF("THERMAL throttles: %s dram databus utilization is %f", mss::c_str(l_dimm), l_calc_util[l_pos]);
-
- l_temp_n_slot = power_thermal::throttled_cmds (l_calc_util[l_pos], iv_m_clocks);
-
- //Set to the min between the two value
- //If iv_n_slot == 0 (so uninitialized), set it to the calculated slot value
- //The l_n_slot value can't be equal to 0 because there's a dimm installed
- if ((l_temp_n_slot < iv_n_slot) || (iv_n_slot == 0))
- {
- iv_n_slot = l_temp_n_slot;
- }
- }
-
- //Set to lowest value between calculated and runtime
- FAPI_INF("THERMAL throttles: runtime slot is %d, calc n slot is %d", iv_runtime_n_slot, iv_n_slot);
- //Taking the min of the SLOT * (# of dimms on the port) and the iv_runtime_port throttle value
- //Thermal throttling happens after the POWER calculations. the iv_runtime_n_port value shouldn't be set to 0
- iv_n_port = std::min(iv_runtime_n_port, static_cast<uint16_t>(iv_n_slot * l_count));
- iv_n_port = (iv_n_port == 0) ? MIN_THROTTLE : iv_n_port;
-
- iv_n_slot = std::min(iv_n_slot, iv_runtime_n_slot);
- iv_n_slot = (iv_n_slot == 0) ? MIN_THROTTLE : iv_n_slot;
-
- //Now time to get and set iv_calc_port_max from the calculated N throttle
- FAPI_TRY( calc_power_from_n(iv_n_slot, iv_n_port, iv_calc_port_maxpower),
- "Failed to calculate the final max port maxpower. Slot throttle value is %d, port value is %d",
- iv_n_slot,
- iv_n_port);
-
- return fapi2::FAPI2_RC_SUCCESS;
-fapi_try_exit:
- FAPI_ERR("Error calculating mss::power_thermal::thermal_throttles()");
- return fapi2::current_err;
-}
-
-///
-/// @brief Calculates the min and max power usage for a port based off of power curves and utilizations
-/// @param[in] i_idle_util the utilization of the databus in idle mode (0% most likely)
-/// @param[in] i_max_util the utilization of the dimm at maximum possible percentage (mrw or calculated)
-/// @param[out] o_port_power_idle max value of port power in cW
-/// @param[out] o_port_power_max max value of port power in cW
-/// @return fapi2::FAPI2_RC_SUCCESS iff the method was a success
-/// @note Called twice in p9_mss_bulk_pwr_throttles
-/// @note uses dimm power curves from class variables
-///
-fapi2::ReturnCode throttle::calc_port_power(const double i_idle_util [MAX_DIMM_PER_PORT],
- const double i_max_util [MAX_DIMM_PER_PORT],
- double& o_port_power_idle,
- double& o_port_power_max) const
-{
- //Playing it safe
- o_port_power_idle = 0;
- o_port_power_max = 0;
-
- //Calculate the port power curve info by summing the dimms on the port
- for ( const auto& l_dimm : mss::find_targets<TARGET_TYPE_DIMM>(iv_target) )
- {
- const auto l_pos = mss::index(l_dimm);
- //Printing as decimals because HB messes up floats
- FAPI_INF("%s max dram databus for DIMM in pos %d is %d, databus for idle is %d",
- mss::c_str(iv_target),
- l_pos,
- static_cast<uint64_t>( i_max_util[l_pos]),
- static_cast<uint64_t>( i_idle_util[l_pos]) );
- //Sum up the dim's power to calculate the port power curve
- o_port_power_idle += calc_power(i_idle_util[l_pos], l_pos);
- o_port_power_max += calc_power(i_max_util[l_pos], l_pos);
- }
-
- //Raise the powers by the uplift percent
- calc_power_uplift(iv_power_uplift_idle, o_port_power_idle);
- calc_power_uplift(iv_power_uplift, o_port_power_max);
-
- FAPI_ASSERT( (o_port_power_max > 0),
- fapi2::MSS_NO_PORT_POWER()
- .set_COUNT_DIMMS(mss::count_dimm(iv_target))
- .set_MAX_UTILIZATION_DIMM_0(i_max_util[0])
- .set_MAX_UTILIZATION_DIMM_1(i_max_util[1]),
- "No Port Power limit was calculated for %s, %d DIMMs installed, utilizations: DIMM 0 %d, DIMM 1 %d",
- mss::c_str(iv_target),
- mss::count_dimm(iv_target),
- i_max_util[0],
- i_max_util[1]);
-
- //FAPI_ASSERTs don't set the current err to good
- return fapi2::FAPI2_RC_SUCCESS;
-fapi_try_exit:
- return fapi2::current_err;
-}
-
-///
-/// @brief Calculates max and min power usages based off of DIMM power curves
-/// @param[in] i_databus_idle idle databus utilization (either calculated or mrw)
-/// @param[in] i_databus_max max databus utilization (either calculated or mrw)
-/// @param[out] o_dimm_power_idle array of dimm power in cW
-/// @param[out] o_dimm_power_max array of dimm power in cW
-/// @return fapi2::ReturnCode - FAPI2_RC_SUCCESS iff the split is OK
-/// @note Called in p9_mss_bulk_pwr_throttles
-/// @note used for the thermal throttles
-///
-void throttle::calc_dimm_power(const double i_databus_idle,
- const double i_databus_max,
- double o_dimm_power_idle [MAX_DIMM_PER_PORT],
- double o_dimm_power_max [MAX_DIMM_PER_PORT]) const
-{
- for ( const auto& l_dimm : mss::find_targets<TARGET_TYPE_DIMM>(iv_target) )
- {
- const uint8_t l_pos = mss::index(l_dimm);
- o_dimm_power_idle[l_pos] = calc_power(i_databus_idle, l_pos);
- o_dimm_power_max[l_pos] = calc_power(i_databus_max, l_pos);
-
- //Raise the powers by the uplift percent
-
- calc_power_uplift(iv_power_uplift_idle, o_dimm_power_idle[l_pos]);
- calc_power_uplift(iv_power_uplift, o_dimm_power_max[l_pos]);
-
- FAPI_INF("Calc_dimm_power: dimm (%d) power max is %f, %f for dimm slope of %d, intercept of %d",
- l_pos,
- o_dimm_power_max[l_pos],
- o_dimm_power_max[l_pos],
- iv_pwr_slope[l_pos],
- iv_pwr_int[l_pos]);
- }
-}
-
-///
-/// @brief Calculate the port power curve in order to calculate the port utilization
-/// @param[in] i_power_idle double of the port's power consumption at idle
-/// @param[in] i_power_max double of the port's power consumption at max utilization
-/// @param[out] o_slope
-/// @param[out] o_int
-/// @note Called in p9_mss_bulk_pwr_throttles
-/// @note Port power curve needed to calculate the port utilization
-///
-fapi2::ReturnCode throttle::calc_power_curve(const double i_power_idle,
- const double i_power_max,
- uint32_t& o_slope,
- uint32_t& o_int) const
-{
- const double l_divisor = ((static_cast<double>(iv_databus_port_max) / UTIL_CONVERSION) - IDLE_UTIL);
- FAPI_ASSERT ((l_divisor > 0),
- fapi2::MSS_CALC_POWER_CURVE_DIVIDE_BY_ZERO()
- .set_PORT_DATABUS_UTIL(iv_databus_port_max)
- .set_UTIL_CONVERSION(UTIL_CONVERSION)
- .set_IDLE_UTIL(IDLE_UTIL)
- .set_RESULT(l_divisor),
- "Calculated zero for the divisor in calc_power_curve on target %s",
- mss::c_str(iv_target) );
-
- o_slope = (i_power_max - i_power_idle) / l_divisor;
- o_int = i_power_idle - (o_slope * IDLE_UTIL);
- FAPI_INF("Calc_power_curve: power idle is %f, max is %f, slope is %d, int is %d",
- i_power_idle,
- i_power_max,
- o_slope,
- o_int);
- return fapi2::FAPI2_RC_SUCCESS;
-
-fapi_try_exit:
- FAPI_INF("Error calculating mss::power_thermal::calc_power_curve");
- return fapi2::current_err;
-
-}
-
-///
-/// @brief Calculate the databus utilization given the power curve
-/// @param[in] i_slope
-/// @param[in] i_int
-/// @param[in] i_power_limit either the port_power_limit or the dimm thermal power limit
-/// @param[out] o_port_util the port's databus utilization
-/// @note Called in p9_mss_bulk_pwr_throttles
-/// @note Chooses worst case between the maximum allowed databus utilization and the calculated value
-///
-void throttle::calc_util_usage(const uint32_t i_slope,
- const uint32_t i_int,
- const uint32_t i_power_limit,
- double& o_util) const
-{
- o_util = ((static_cast<double>(i_power_limit) - i_int) / i_slope ) * UTIL_CONVERSION;
-
- //Cast to uint32 for edge case where it has decimals
- o_util = (static_cast<uint32_t>(o_util) < iv_databus_port_max) ? static_cast<uint32_t>(o_util) : iv_databus_port_max;
-
- // Check for the minimum threshnold and update if need be
- if(o_util < MIN_UTIL)
- {
- FAPI_INF("Calculated utilization (%lu) is less than the minimum utilization: %lu. Setting to minimum value", o_util,
- MIN_UTIL);
- o_util = MIN_UTIL;
- }
-}
-
-///
-/// @brief calculated the output power estimate from the calculated N throttle
-/// @param[in] i_n_slot the throttle per slot in terms of N commands
-/// @param[in] i_n_port the throttle per port in terms of N commands
-/// @param[out] o_power the calculated power
-/// @return fapi2::ReturnCode iff it was a success
-///
-fapi2::ReturnCode throttle::calc_power_from_n (const uint16_t i_n_slot,
- const uint16_t i_n_port,
- uint32_t& o_power) const
-{
- double l_calc_util_port = 0;
- double l_calc_util_slot = 0;
- double l_calc_databus_port_max[MAX_DIMM_PER_PORT] = {};
- double l_calc_databus_port_idle[MAX_DIMM_PER_PORT] = {};
- double l_port_power_max = 0;
- double l_port_power_idle = 0;
-
- FAPI_TRY( calc_util_from_throttles(i_n_slot, iv_m_clocks, l_calc_util_slot),
- "%s Error calculating utilization from slot throttle %d and mem clocks %d",
- mss::c_str(iv_target),
- i_n_slot,
- iv_m_clocks);
- FAPI_TRY( calc_util_from_throttles(i_n_port, iv_m_clocks, l_calc_util_port),
- "%s Error calculating utilization from port throttle %d and mem clocks %d",
- mss::c_str(iv_target),
- i_n_port,
- iv_m_clocks);
-
- //Determine the utilization for each DIMM that will maximize the port power
- FAPI_TRY( calc_split_util(l_calc_util_slot, l_calc_util_port, l_calc_databus_port_max),
- "Error splitting the utilization for target %s with slot utilizatio %d and port util %d",
- mss::c_str(iv_target),
- l_calc_util_slot,
- l_calc_util_port);
-
- FAPI_TRY( calc_port_power(l_calc_databus_port_idle,
- l_calc_databus_port_max,
- l_port_power_idle,
- l_port_power_max),
- "Error calculating the port power value for %s. Slot value is %d, port value is %d",
- mss::c_str(iv_target),
- i_n_slot,
- i_n_port);
-
- o_power = power_thermal::round_up (l_port_power_max);
-
-fapi_try_exit:
- return fapi2::current_err;
-}
-
-///
-/// @brief Converts the port maximum databus to a dimm level based on powerslopes and dimms installed
-/// @param[in] i_databus_port_max max databus utilization for the port (either calculated or mrw)
-/// @param[out] o_databus_dimm_max array of dimm utilization values
-/// @return fapi2::ReturnCode - FAPI2_RC_SUCCESS iff the split is OK
-/// @note Called in p9_mss_bulk_pwr_throttles
-/// @used to calculate the port power based off of DIMM power curves
-///
-fapi2::ReturnCode throttle::calc_databus (const double i_databus_port_max,
- double o_databus_dimm_max [MAX_DIMM_PER_PORT])
-{
- uint8_t l_count_dimms = count_dimm(iv_target);
-
- //No work for no dimms
- if (l_count_dimms == 0)
- {
- return fapi2::FAPI2_RC_SUCCESS;
- }
-
- for (const auto& l_dimm : mss::find_targets<fapi2::TARGET_TYPE_DIMM>(iv_target))
- {
- //Left early if count_dimms == 0
- o_databus_dimm_max[mss::index(l_dimm)] = i_databus_port_max / l_count_dimms;
- }
-
- //If the power slopes aren't equal, set the dimm with the highest power slope
- //Should be correct even if only one DIMM is installed
- if (iv_pwr_slope[0] != iv_pwr_slope[1])
- {
- o_databus_dimm_max[0] = (iv_pwr_slope[0] > iv_pwr_slope[1]) ? i_databus_port_max : 0;
- o_databus_dimm_max[1] = (iv_pwr_slope[1] > iv_pwr_slope[0]) ? i_databus_port_max : 0;
- }
-
- //Make sure both are not 0
- FAPI_ASSERT ( (o_databus_dimm_max[0] != 0) || (o_databus_dimm_max[1] != 0),
- fapi2::MSS_NO_DATABUS_UTILIZATION()
- .set_PORT_DATABUS_UTIL(i_databus_port_max)
- .set_DIMM_COUNT(l_count_dimms),
- "Failed to calculated databus utilization for target %s",
- mss::c_str(iv_target));
-
- return fapi2::FAPI2_RC_SUCCESS;
-fapi_try_exit:
- return fapi2::current_err;
-}
-
-///
-/// @brief Converts the port and slot util to a dimm level based on powerslopes and number of dimms installed
-/// @param[in] i_util_slot databus utilization for the slot
-/// @param[in] i_util_port databus utilization for the port
-/// @param[out] o_util_dimm_max array of dimm utilization values
-/// @return fapi2::ReturnCode - FAPI2_RC_SUCCESS iff the split is OK
-/// @note determines worst case utilization per dimms, takes into account port and combine slot throttles
-/// @note used in calculating the port power, not for calculating the slot and port utilization
-///
-fapi2::ReturnCode throttle::calc_split_util(
- const double i_util_slot,
- const double i_util_port,
- double o_util_dimm_max [MAX_DIMM_PER_PORT]) const
-{
- uint8_t l_count_dimms = count_dimm (iv_target);
- //The total utilization to be used is limited by either what the port can allow or what the dimms can use
- FAPI_ASSERT( (i_util_slot <= i_util_port),
- fapi2::MSS_SLOT_UTIL_EXCEEDS_PORT()
- .set_SLOT_UTIL(i_util_slot)
- .set_PORT_UTIL(i_util_port),
- "The slot utilization (%f) exceeds the port's utilization (%f)",
- i_util_slot,
- i_util_port);
-
- if (l_count_dimms == 0)
- {
- return fapi2::FAPI2_RC_SUCCESS;
- }
-
- //assumptions slot <= port, l_count_dimms <=2
- else if (i_util_slot * l_count_dimms > i_util_port)
- {
- FAPI_INF("In mss::power_thermal::calc_split i_util_slot is %f, i_util_port is %f, l_count_dimms is %d",
- i_util_slot,
- i_util_port,
- l_count_dimms);
- const uint8_t l_high_pos = (iv_pwr_slope[0] >= iv_pwr_slope[1]) ? 0 : 1;
-
- //Highest power_slope gets the higher utilization
- o_util_dimm_max[l_high_pos] = std::min(i_util_slot, i_util_port);
- //Set the other dimm to the left over utilization (i_util_port - i_util_slot)
- o_util_dimm_max[(!l_high_pos)] = (l_count_dimms == 2) ? (i_util_port - o_util_dimm_max[l_high_pos]) : 0;
-
- FAPI_INF("Split utilization for target %s, DIMM in %d gets %f, DIMM in %d gets %f",
- mss::c_str(iv_target),
- l_high_pos,
- o_util_dimm_max[l_high_pos],
- !l_high_pos,
- o_util_dimm_max[!l_high_pos]);
- }
-
- else
- {
- //If only 1 dimm, i_util_port == i_util_slot
- //If 2 dimms, 2*i_util_slot <= i_util_pot
- //Either way, limit utilization by the slot value
- for (const auto& l_dimm : mss::find_targets<TARGET_TYPE_DIMM>(iv_target))
- {
- const size_t l_pos = mss::index(l_dimm);
- o_util_dimm_max[l_pos] = i_util_slot;
- }
- }
-
- //make sure both are not 0
- FAPI_ASSERT ( (o_util_dimm_max[0] != 0) || (o_util_dimm_max[1] != 0),
- fapi2::MSS_NO_DATABUS_UTILIZATION()
- .set_PORT_DATABUS_UTIL(i_util_port)
- .set_DIMM_COUNT(mss::count_dimm(iv_target)),
- "Failed to calculated util utilization for target %s",
- mss::c_str(iv_target));
-fapi_try_exit:
- return fapi2::current_err;
-}
-
-///
-/// @brief Perform thermal calculations as part of the effective configuration
-/// @param[in] i_target the MCS target in which the runtime throttles will be reset
-/// @return FAPI2_RC_SUCCESS iff ok
-///
-fapi2::ReturnCode restore_runtime_throttles( const fapi2::Target<fapi2::TARGET_TYPE_MCS>& i_target )
-{
- uint16_t l_run_throttles [MAX_DIMM_PER_PORT] = {};
- uint32_t l_max_databus = 0;
- uint32_t l_throttle_m_clocks = {};
-
- FAPI_TRY( mrw_mem_m_dram_clocks(l_throttle_m_clocks) );
- FAPI_TRY( mrw_max_dram_databus_util(l_max_databus) );
-
- //Set runtime throttles to unthrottled value, using max dram utilization and M throttle
- //Do I need to check to see if any DIMMS configured on the port?
- for (const auto& l_mca : mss::find_targets<TARGET_TYPE_MCA>(i_target))
- {
- const auto l_pos = mss::index(l_mca);
-
- if (mss::count_dimm (l_mca) != 0)
- {
- l_run_throttles[l_pos] = mss::power_thermal::throttled_cmds (l_max_databus, l_throttle_m_clocks);
- }
- }
-
- FAPI_TRY( FAPI_ATTR_SET( fapi2::ATTR_MSS_RUNTIME_MEM_THROTTLED_N_COMMANDS_PER_PORT, i_target, l_run_throttles) );
- FAPI_TRY( FAPI_ATTR_SET( fapi2::ATTR_MSS_RUNTIME_MEM_THROTTLED_N_COMMANDS_PER_SLOT, i_target, l_run_throttles) );
-
-fapi_try_exit:
- return fapi2::current_err;
-}
-
-///
-/// @brief Update the runtime throttles to the worst case of the general throttle values and the runtime values
-/// @param[in] i_target the MCS target in which the runtime throttles will be set
-/// @return FAPI2_RC_SUCCESS iff ok
-///
-fapi2::ReturnCode update_runtime_throttles( const std::vector< fapi2::Target<fapi2::TARGET_TYPE_MCS> >& i_targets )
-{
- for (const auto& l_mcs : i_targets)
- {
- if (mss::count_dimm(l_mcs) == 0)
- {
- continue;
- }
-
- uint16_t l_run_slot [PORTS_PER_MCS] = {};
- uint16_t l_run_port [PORTS_PER_MCS] = {};
- uint16_t l_calc_slot [PORTS_PER_MCS] = {};
- uint16_t l_calc_port [PORTS_PER_MCS] = {};
-
- FAPI_TRY(runtime_mem_throttled_n_commands_per_slot(l_mcs, l_run_slot));
- FAPI_TRY(runtime_mem_throttled_n_commands_per_port(l_mcs, l_run_port));
- FAPI_TRY(mem_throttled_n_commands_per_slot(l_mcs, l_calc_slot));
- FAPI_TRY(mem_throttled_n_commands_per_port(l_mcs, l_calc_port));
-
- for (const auto& l_mca : mss::find_targets<TARGET_TYPE_MCA>(l_mcs))
- {
- const auto l_pos = mss::index(l_mca);
- //Choose the worst case between runtime and calculated throttles
- //Have to make sure the calc_slot isn't equal to 0 though
- l_run_slot[l_pos] = (l_calc_slot[l_pos] != 0) ?
- std::min(l_run_slot[l_pos], l_calc_slot[l_pos]) : l_run_slot[l_pos];
- l_run_port[l_pos] = (l_calc_port[l_pos] != 0) ?
- std::min(l_run_port[l_pos], l_calc_port[l_pos]) : l_run_port[l_pos];
-
- FAPI_INF("New runtime throttles for %s for slot are %d, port are %d",
- mss::c_str(l_mca),
- l_run_slot[l_pos],
- l_run_port[l_pos]);
- }
-
- FAPI_TRY( FAPI_ATTR_SET( fapi2::ATTR_MSS_RUNTIME_MEM_THROTTLED_N_COMMANDS_PER_PORT, l_mcs, l_run_port) );
- FAPI_TRY( FAPI_ATTR_SET( fapi2::ATTR_MSS_RUNTIME_MEM_THROTTLED_N_COMMANDS_PER_SLOT, l_mcs, l_run_slot) );
- }
-
-fapi_try_exit:
- return fapi2::current_err;
-}
-
-///
/// @brief set ATTR_MSS_RUNTIME_MEM_M_DRAM_CLOCKS and ATTR_MSS_MEM_WATT_TARGET
/// @param[in] i_targets vector of mcs targets all on the same vddr domain
/// @return FAPI2_RC_SUCCESS iff it was a success
@@ -785,149 +112,5 @@ fapi_try_exit:
return fapi2::current_err;
}
-///
-/// @brief Equalize the throttles and estimated power at those throttle levels
-/// @param[in] i_targets vector of MCS targets all on the same VDDR domain
-/// @param[in] i_throttle_type denotes if this was done for POWER (VMEM) or THERMAL (VMEM+VPP) throttles
-/// @param[out] o_exceeded_power vector of MCA targets where the estimated power exceeded the maximum allowed
-/// @return FAPI2_RC_SUCCESS iff ok
-/// @note sets the throttles and power to the worst case
-/// Called by p9_mss_bulk_pwr_throttles and by p9_mss_utils_to_throttle (so by IPL or by OCC)
-///
-fapi2::ReturnCode equalize_throttles (const std::vector< fapi2::Target<fapi2::TARGET_TYPE_MCS> >& i_targets,
- const throttle_type i_throttle_type,
- std::vector< fapi2::Target<fapi2::TARGET_TYPE_MCA> >& o_exceeded_power)
-{
- o_exceeded_power.clear();
-
- //Set to max values so every compare will change to min value
- uint16_t l_min_slot = ~(0);
- uint16_t l_min_port = ~(0);
-
- //Loop through all of the MCS targets to find the worst case throttle value (lowest) for the slot and port
- for (const auto& l_mcs : i_targets)
- {
- uint16_t l_calc_slot [mss::PORTS_PER_MCS] = {};
- uint16_t l_calc_port [mss::PORTS_PER_MCS] = {};
- uint16_t l_run_slot [mss::PORTS_PER_MCS] = {};
- uint16_t l_run_port [mss::PORTS_PER_MCS] = {};
-
- FAPI_TRY(mem_throttled_n_commands_per_slot(l_mcs, l_calc_slot));
- FAPI_TRY(mem_throttled_n_commands_per_port(l_mcs, l_calc_port));
- FAPI_TRY(runtime_mem_throttled_n_commands_per_slot(l_mcs, l_run_slot));
- FAPI_TRY(runtime_mem_throttled_n_commands_per_port(l_mcs, l_run_port));
-
- for (const auto& l_mca : mss::find_targets<TARGET_TYPE_MCA>(l_mcs))
- {
- if (mss::count_dimm(l_mca) == 0)
- {
- continue;
- }
-
- const auto l_pos = mss::index(l_mca);
- //Find the smaller of the three values (calculated slot, runtime slot, and min slot)
- l_min_slot = (l_calc_slot[l_pos] != 0) ? std::min( std::min (l_calc_slot[l_pos], l_run_slot[l_pos]),
- l_min_slot) : l_min_slot;
- l_min_port = (l_calc_port[l_pos] != 0) ? std::min( std::min( l_calc_port[l_pos], l_run_port[l_pos]),
- l_min_port) : l_min_port;
- }
- }
-
- FAPI_INF("Calculated min slot is %d, min port is %d for the system", l_min_slot, l_min_port);
-
- //Now set every port to have those values
- {
- for (const auto& l_mcs : i_targets)
- {
- uint16_t l_fin_slot [mss::PORTS_PER_MCS] = {};
- uint16_t l_fin_port [mss::PORTS_PER_MCS] = {};
- uint32_t l_fin_power [mss::PORTS_PER_MCS] = {};
-
- for (const auto& l_mca : mss::find_targets<TARGET_TYPE_MCA>(l_mcs))
- {
- if (mss::count_dimm(l_mca) == 0)
- {
- continue;
- }
-
- const auto l_pos = mss::index(l_mca);
- // Declaring above to avoid fapi2 jump
- uint64_t l_power_limit = 0;
-
- l_fin_slot[l_pos] = (mss::count_dimm(l_mca)) ? l_min_slot : 0;
- l_fin_port[l_pos] = (mss::count_dimm(l_mca)) ? l_min_port : 0;
-
- //Need to create throttle object for each mca in order to get dimm configuration and power curves
- //To calculate the slot/port utilization and total port power consumption
- fapi2::ReturnCode l_rc;
-
- const auto l_dummy = mss::power_thermal::throttle(l_mca, l_rc);
- FAPI_TRY(l_rc, "Failed creating a throttle object in equalize_throttles");
-
- FAPI_TRY( l_dummy.calc_power_from_n(l_fin_slot[l_pos], l_fin_port[l_pos], l_fin_power[l_pos]),
- "Failed calculating the power value for throttles: slot %d, port %d for target %s",
- l_fin_slot[l_pos],
- l_fin_port[l_pos],
- mss::c_str(l_mca));
-
- //Only calculate the power for ports that have dimms
- l_fin_power[l_pos] = (mss::count_dimm(l_mca) != 0 ) ? l_fin_power[l_pos] : 0;
-
- // You may ask why this is not a variable within the throttle struct
- // It's because POWER throttling is on a per port basis while the THERMAL throttle is per dimm
- // Didn't feel like adding a variable just for this check
- l_power_limit = (i_throttle_type == throttle_type::POWER) ?
- l_dummy.iv_port_power_limit : (l_dummy.iv_dimm_thermal_limit[0] + l_dummy.iv_dimm_thermal_limit[1]);
-
- FAPI_INF("Calculated power is %d, limit is %d", l_fin_power[l_pos], l_power_limit);
-
- //If there's an error with calculating port power, the wrong watt target was passed in
- //Returns an error but doesn't deconfigure anything. Calling function can log if it wants to
- //Called by OCC and by p9_mss_eff_config_thermal, thus different ways for error handling
- //Continue setting throttles to prevent a possible throttle == 0
- //The error will be the last bad port found
- if (l_fin_power[l_pos] > l_power_limit)
- {
- //Need this because of pos traits and templating stuff
- uint64_t l_fail = mss::fapi_pos(l_mca);
- //Set the failing port. OCC just needs one failing port, doesn't need all of them
- FAPI_TRY( FAPI_ATTR_SET( fapi2::ATTR_MSS_MEM_PORT_POS_OF_FAIL_THROTTLE,
- fapi2::Target<fapi2::TARGET_TYPE_SYSTEM>(),
- l_fail) );
-
- FAPI_ASSERT_NOEXIT( false,
- fapi2::MSS_CALC_PORT_POWER_EXCEEDS_MAX()
- .set_CALCULATED_PORT_POWER(l_fin_power[l_pos])
- .set_MAX_POWER_ALLOWED(l_power_limit)
- .set_PORT_POS(mss::pos(l_mca))
- .set_MCA_TARGET(l_mca),
- "Error calculating the final port power value for target %s, calculated power is %d, max value can be %d",
- mss::c_str(l_mca),
- l_fin_power[l_pos],
- l_power_limit);
-
- o_exceeded_power.push_back(l_mca);
- }
-
- FAPI_INF("%s Final throttles values for slot %d, for port %d, power value %d",
- mss::c_str(l_mca),
- l_fin_port[l_pos],
- l_fin_slot[l_pos],
- l_fin_power[l_pos]);
- }
-
- //Even if there's an error, still calculate and set the throttles.
- //OCC will set to safemode if there's an error
- //Better to set the throttles than leave them 0, and potentially brick the memory
- FAPI_TRY( FAPI_ATTR_SET( fapi2::ATTR_MSS_MEM_THROTTLED_N_COMMANDS_PER_PORT, l_mcs, l_fin_port) );
- FAPI_TRY( FAPI_ATTR_SET( fapi2::ATTR_MSS_MEM_THROTTLED_N_COMMANDS_PER_SLOT, l_mcs, l_fin_slot) );
- FAPI_TRY( FAPI_ATTR_SET( fapi2::ATTR_MSS_PORT_MAXPOWER, l_mcs, l_fin_power) );
- }
- }
- return fapi2::FAPI2_RC_SUCCESS;
-fapi_try_exit:
- FAPI_ERR("Error equalizing memory throttles");
- return fapi2::current_err;
-}
}//namespace power_thermal
}//namespace mss
diff --git a/src/import/chips/p9/procedures/hwp/memory/lib/power_thermal/throttle.H b/src/import/chips/p9/procedures/hwp/memory/lib/power_thermal/throttle.H
index 189583cfa..20152398e 100644
--- a/src/import/chips/p9/procedures/hwp/memory/lib/power_thermal/throttle.H
+++ b/src/import/chips/p9/procedures/hwp/memory/lib/power_thermal/throttle.H
@@ -5,7 +5,7 @@
/* */
/* OpenPOWER HostBoot Project */
/* */
-/* Contributors Listed Below - COPYRIGHT 2016,2018 */
+/* Contributors Listed Below - COPYRIGHT 2016,2019 */
/* [+] International Business Machines Corp. */
/* */
/* */
@@ -39,332 +39,23 @@
#include <fapi2.H>
#include <lib/shared/mss_const.H>
#include <lib/mss_attribute_accessors.H>
+#include <lib/power_thermal/accessor_wrapper.H>
+#include <lib/power_thermal/throttle_traits.H>
+#include <generic/memory/lib/utils/power_thermal/gen_throttle.H>
namespace mss
{
namespace power_thermal
{
///
-/// @brief throttle constants used in the power_thermal functions
-///
-enum throttle_const : size_t
-{
- /// Dram data bus utilization is bus utilization / 4
- DRAM_BUS_UTILS = 4,
-
- /// 10000 to convert to and from c%
- UTIL_CONVERSION = 10000,
-
- /// Conversion to percentage
- PERCENT_CONVERSION = 100,
-
- /// MIN_UTIL is in c%
- MIN_UTIL = 2500,
-
- /// IDLE_UTIL is in c%
- IDLE_UTIL = 0,
-
- /// Minimum throttle allowed for the port and or slot. If we set to 0, we brick the port
- MIN_THROTTLE = 1,
-};
-
-///
-/// @class throttle
-/// @brief Determine power_thermal throttles for memory
-///
-class throttle
-{
- private:
- ///
- /// @brief Calculate the power (cW) of inputs and the power curve
- /// @tparam T
- /// @param[in] i_util the databus utilization that the power will be based on
- /// @param[in] l_pos the dimm position for the power value being calculated.
- /// @return Integral type T
- ///
- template<typename T>
- inline T calc_power (const T i_util, const size_t i_pos) const
- {
- return ((i_util / UTIL_CONVERSION) * iv_pwr_slope[i_pos]) + iv_pwr_int[i_pos];
- }
-
- ///
- /// @brief Raise the o_value by the percent passed in
- /// @param[in] i_uplift the percent the o_Value should be raised by
- /// @param[out] o_value the value that will be modified
- ///
- inline void calc_power_uplift (const uint8_t i_uplift, double& o_value) const
- {
- o_value *= (1 + (static_cast<double>(i_uplift) / PERCENT_CONVERSION));
- }
-
- public:
- const fapi2::Target<fapi2::TARGET_TYPE_MCA>& iv_target;
-
- uint32_t iv_databus_port_max;
-
- uint8_t iv_power_uplift_idle;
- uint8_t iv_power_uplift;
-
- uint16_t iv_runtime_n_slot;
- uint16_t iv_runtime_n_port;
- uint32_t iv_m_clocks;
- uint32_t iv_dimm_thermal_limit[MAX_DIMM_PER_PORT] = {};
- uint16_t iv_pwr_slope[MAX_DIMM_PER_PORT] = {};
- uint16_t iv_pwr_int[MAX_DIMM_PER_PORT] = {};
- uint16_t iv_n_slot;
- uint16_t iv_n_port;
- uint32_t iv_port_power_limit;
- uint32_t iv_calc_port_maxpower;
-
- //default ctor deleted
- throttle() = delete;
-
- ///
- /// @brief Constructor
- /// @param[in] i_target MCA target to call power thermal stuff on
- /// @param[out] o_rc fapi2::ReturnCode fapi2::FAPI2_RC_SUCCESS iff ctor was successful
- ///
- throttle( const fapi2::Target<fapi2::TARGET_TYPE_MCA>& i_mca, fapi2::ReturnCode& o_rc);
-
- //
- // @brief Destructor
- //
- ~throttle() = default;
-
- ///
- /// @brief Calculates the min and max power usage for a port
- /// @param[in] i_idle_util the utilization of the databus in idle mode
- /// @param[in] i_max_util the utilization of the port at maximum possible (mrw or calculated)
- /// @param[out] o_port_power_idle max value of port power in cW
- /// @param[out] o_port_power_max max value of port power in cW
- /// @return fapi2::ReturnCode - FAPI2_RC_SUCCESS iff the split is OK
- /// @note Called twice in p9_mss_bulk_pwr_throttles
- ///
- fapi2::ReturnCode calc_port_power( const double i_idle_util [MAX_DIMM_PER_PORT],
- const double i_max_util [MAX_DIMM_PER_PORT],
- double& o_port_power_idle,
- double& o_port_power_max) const;
- ///
- /// @brief Calculates max and min power usages based off of DIMM power curves
- /// @param[in] i_databus_port_max max databus utilization for the port (either calculated or mrw)
- /// @param[in] i_port_power_calc_idle double of the port's power consumption at idle
- /// @param[out] o_dimm_power_idle array of dimm power in cW
- /// @param[out] o_dimm_power_max array of dimm power in cW
- /// @note Called in p9_mss_bulk_pwr_throttles
- /// @note used for the thermal throttles
- ///
- void calc_dimm_power(const double i_databus_idle,
- const double i_databus_max,
- double o_dimm_power_idle [MAX_DIMM_PER_PORT],
- double o_dimm_power_max [MAX_DIMM_PER_PORT]) const;
-
- ///
- /// @brief Calculate the power curve in order to calculate databus utilization
- /// @param[in] i_power_idle double of the port's power consumption at idle
- /// @param[in] i_power_max double of the port's power consumption at max utilization
- /// @param[out] o_power_slope
- /// @param[out] o_power_int
- /// @return fapi2::ReturnCode - FAPI2_RC_SUCCESS iff the split is OK
- /// @note Called in p9_mss_bulk_pwr_throttles
- /// @note Power curve needed to calculate the utilization
- ///
- fapi2::ReturnCode calc_power_curve(const double i_power_idle,
- const double i_power_max,
- uint32_t& o_power_slope,
- uint32_t& o_power_int) const;
- ///
- /// @brief Calculate the databus utilization given the power curve
- /// @param[in] i_slope
- /// @param[in] i_int
- /// @param[in] i_power_limit either iv_port_power_limit or thermal_power_limit depending on throttle type
- /// @param[out] o_port_util the port's databus utilization
- /// @note Called in p9_mss_bulk_pwr_throttles
- /// @note Chooses worst case between the maximum allowed databus utilization and the calculated value
- ///
- void calc_util_usage(const uint32_t i_slope,
- const uint32_t i_int,
- const uint32_t i_power_limit,
- double& o_util) const;
- ///
- /// @brief set iv_n_port, iv_n_slot, iv_calc_port_maxpower
- /// @param[in] i_util_port pass in the calculated port databus utilization
- /// @return fapi2::ReturnCode - FAPI2_RC_SUCCESS iff get is OK
- ///
- fapi2::ReturnCode calc_slots_and_power (const double i_util_port);
-
- ///
- /// @brief calculated the output power estimate from the calculated N throttle
- /// @param[in] i_n_slot the N throttle per slot
- /// @param[in] i_n_port the N throttle per port
- /// @param[out] o_power the calculated power
- /// @return fapi2::ReturnCode - FAPI2_RC_SUCCESS iff the split is OK
- ///
- fapi2::ReturnCode calc_power_from_n (const uint16_t i_n_slot, const uint16_t i_n_port, uint32_t& o_power) const;
-
- ///
- /// @brief Converts the port maximum databus util to a dimm level based on powerslopes and dimms installed
- /// @param[in] i_databus_port_max max databus utilization for the port (either calculated or mrw)
- /// @param[out] o_databus_dimm_max array of dimm utilization values
- /// @return fapi2::ReturnCode - FAPI2_RC_SUCCESS iff the split is OK
- /// @note Called in p9_mss_bulk_pwr_throttles
- /// @used to calculate the port power based off of DIMM power curves
- ///
- fapi2::ReturnCode calc_databus( const double i_databus_port_max,
- double o_databus_dimm_max [MAX_DIMM_PER_PORT]);
- ///
- /// @brief Converts the port and slot util to a dimm level based on powerslopes and number of dimms installed
- /// @param[in] i_util_slot databus utilization for the slot
- /// @param[in] i_util_port databus utilization for the port
- /// @param[out] o_util_dimm_max array of dimm utilization values
- /// @return fapi2::ReturnCode - FAPI2_RC_SUCCESS iff the split is OK
- /// @note determines worst case utilization per dimms, takes into account port and combine slot throttles
- ///
- fapi2::ReturnCode calc_split_util(
- const double i_util_slot,
- const double i_util_port,
- double o_util_dimm_max [MAX_DIMM_PER_PORT]) const;
-
-
- ///
- /// @brief Calculate ATTR_MSS_CHANNEL_PAIR_MAXPOWER and ATTR_MSS_MEM_THROTTLED_N_COMMANDS_PER_SLOT,
- /// @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, max databus utilization,
- /// and memwat target.
- /// @note currently sets the slot and port throttles to the same value
- ///
- fapi2::ReturnCode power_regulator_throttles ();
-
- ///
- /// @brief Set ATTR_MSS_MEM_THROTTLED_N_COMMANDS_PER_SLOT,
- /// @return fapi2::ReturnCode - FAPI2_RC_SUCCESS iff get is OK
- /// @note Called in p9_mss_bulk_pwr_throttles
- /// @note Sets the throttle levels based off of the dimm's thermal limits
- /// @note both DIMM's on a port are set to the same throttle level
- ///
- fapi2::ReturnCode thermal_throttles ();
-};
-
-///
-/// @brief Calculate N (address operations) allowed within a window of M DRAM clocks
-/// @param[in] i_databus_util databus utilization percentage (e.g. 5% = 5)
-/// @param[in] i_num_dram_clocks window of M DRAM clocks
-/// @return number of throttled commands allowed
-/// @note Uses N/M Throttling.
-/// Equation: N = (DRAM data bus utilization * M) / (4 * 10000)
-///
-inline uint32_t throttled_cmds(const uint32_t i_databus_util, const uint32_t i_num_dram_clocks)
-{
- constexpr uint64_t l_divisor = DRAM_BUS_UTILS * UTIL_CONVERSION;
- const uint64_t l_dividend = i_databus_util * i_num_dram_clocks;
- const uint64_t l_result = l_dividend / l_divisor;
-
- //Make sure N is not equal to 0, or we brick the dram until reboot
- return ((l_result == 0) ? 1 : l_result);
-}
-
-///
-/// @brief Calculate the port databus utilization based off of N throttles and M dram clocks
-/// @tparam T output type
-/// @param[in] i_n_throttles N (address operations) allowed within a window of M DRAM clocks
-/// @param[in] i_num_dram_clocks window of M DRAM clocks
-/// @param[out] o_calc_util
-/// @return FAPI2_RC_SUCCESS iff method was a success
-/// @note Uses N/M Throttling.
-/// @note DRAM databus utilization = N * 4 * 10000 / M
-///
-template<typename T>
-fapi2::ReturnCode calc_util_from_throttles(const uint16_t i_n_throttles,
- const uint32_t i_num_dram_clocks,
- T& o_calc_util)
-{
- constexpr uint32_t l_multiplier = DRAM_BUS_UTILS * UTIL_CONVERSION;
- FAPI_ASSERT( (i_num_dram_clocks != 0),
- fapi2::MSS_M_DRAM_CLOCKS_EQUALS_ZERO(),
- "ATTR_MSS_MRW_MEM_M_DRAM_CLOCKS was not set and equals zero");
-
- o_calc_util = (static_cast<double>(i_n_throttles) * l_multiplier) / i_num_dram_clocks;
-
- // Best way to check for overflow if o_calc_util can be a double?
- // If o_calc_util overflows, the value inside will be below the expected outcome
- // So compare o_calc_util with the calculated value, but store calculated value in largest storage
- // Compare ">=" because o_calc_util can be a double, and so we can't compare just equality due to truncation
- FAPI_ASSERT( o_calc_util >= static_cast<uint64_t>((static_cast<double>(i_n_throttles) * l_multiplier) /
- i_num_dram_clocks),
- fapi2::MSS_OUTPUT_OVERFLOW_CALC_UTIL()
- .set_RESULT((static_cast<double>(i_n_throttles) * l_multiplier) / i_num_dram_clocks),
- "Overflow of output variable in calc_util_from_throttles throttles: %d, multiplier %d, dram_clocks %d",
- i_n_throttles,
- l_multiplier,
- i_num_dram_clocks);
-
- // Check for the minimum
- if(o_calc_util < MIN_UTIL)
- {
- FAPI_INF("Calculated utilization (%f) is less than the minimum utilization: %lu. Setting to minimum value",
- o_calc_util, MIN_UTIL);
- o_calc_util = MIN_UTIL;
- }
-
- FAPI_INF("In calc_util_from_throttles, calculated %f for output utilization", o_calc_util);
- return fapi2::FAPI2_RC_SUCCESS;
-fapi_try_exit:
- return fapi2::current_err;
-}
-
-///
-/// @brief Determines if the double has decimal digits and adds 1 and rounds if true
-/// @param[in] i_val the double to be rounded up if trialing digits
-/// @return the input value rounded up to the next whole digit
-/// @note Called in p9_mss_bulk_pwr_throttles
-///
-inline uint32_t round_up(double i_val)
-{
- //convert to uint to truncate decimals and convert back to double for comparison
- uint32_t temp = uint32_t (i_val);
-
- //if not equal, lost something from truncating, so add 1
- temp += (temp == i_val) ? 0 : 1;
-
- //Truncate final value
- return temp;
-}
-
-///
-/// @brief Perform thermal calculations as part of the effective configuration
-/// @param[in] i_target the MCS target in which the runtime throttles will be reset
-/// @return FAPI2_RC_SUCCESS iff ok
-///
-fapi2::ReturnCode restore_runtime_throttles( const fapi2::Target<fapi2::TARGET_TYPE_MCS>& i_target );
-
-///
-/// @brief Update the runtime throttles to the worst case of the general throttle values and the runtime values
-/// @param[in] i_target the MCS target in which the runtime throttles will be set
-/// @return FAPI2_RC_SUCCESS iff ok
-///
-fapi2::ReturnCode update_runtime_throttles(const std::vector< fapi2::Target<fapi2::TARGET_TYPE_MCS> >& i_targets);
-
-///
/// @brief set ATTR_MSS_RUNTIME_MEM_M_DRAM_CLOCKS and ATTR_MSS_MEM_WATT_TARGET
/// @param[in] i_targets vector of mcs targets all on the same vddr domain
/// @return FAPI2_RC_SUCCESS iff it was a success
///
fapi2::ReturnCode set_runtime_m_and_watt_limit( const std::vector< fapi2::Target<fapi2::TARGET_TYPE_MCS> >& i_targets );
-///
-/// @brief Equalize the throttles and estimated power at those throttle levels
-/// @param[in] i_targets vector of MCS targets all on the same VDDR domain
-/// @param[in] i_throttle_type denotes if this was done for POWER (VMEM) or THERMAL (VMEM+VPP) throttles
-/// @param[out] o_exceeded_power vector of MCA targets where the estimated power exceeded the maximum allowed
-/// @return FAPI2_RC_SUCCESS iff ok
-/// @note sets the throttles and power to the worst case
-///
-fapi2::ReturnCode equalize_throttles (const std::vector< fapi2::Target<fapi2::TARGET_TYPE_MCS> >& i_targets,
- const throttle_type i_throttle_type,
- std::vector< fapi2::Target<fapi2::TARGET_TYPE_MCA> >& o_exceeded_power);
-
}//power_thermal
+
}// mss
#endif
diff --git a/src/import/chips/p9/procedures/hwp/memory/lib/power_thermal/throttle_traits.H b/src/import/chips/p9/procedures/hwp/memory/lib/power_thermal/throttle_traits.H
index da277d6fb..15407e3a4 100644
--- a/src/import/chips/p9/procedures/hwp/memory/lib/power_thermal/throttle_traits.H
+++ b/src/import/chips/p9/procedures/hwp/memory/lib/power_thermal/throttle_traits.H
@@ -22,3 +22,125 @@
/* permissions and limitations under the License. */
/* */
/* IBM_PROLOG_END_TAG */
+///
+/// @file p9_mss_utils_to_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_POWER_THROTTLE_TRAITS_
+#define _MSS_POWER_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 NIMBUS mc type
+///
+template<>
+class throttle_traits<mss::mc_type::NIMBUS>
+{
+ public:
+ //////////////////////////////////////////////////////////////
+ // Target types
+ //////////////////////////////////////////////////////////////
+ static constexpr fapi2::TargetType MC_TARGET_TYPE = fapi2::TARGET_TYPE_MCS;
+ static constexpr fapi2::TargetType PORT_TARGET_TYPE = fapi2::TARGET_TYPE_MCA;
+
+ // 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
+ {
+ SIZE_OF_POWER_CURVES_ATTRS = 100,
+ SIZE_OF_THERMAL_ATTR = 10,
+ };
+
+ 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).
+ VDDR_SLOPE = 0x41A,
+ VDDR_INT = 0x384,
+ TOTAL_SLOPE = 0x44C,
+ TOTAL_INT = 0x44C,
+ THERMAL_LIMIT = 0x794,
+ };
+
+ enum
+ {
+ PORTS_PER_MC = 2,
+ 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,
+ VDDR_START = 32,
+ VDDR_LENGTH = 16,
+ TOTAL_START = 48,
+ TOTAL_LENGTH = 16,
+ THERMAL_POWER_START = 32,
+ THERMAL_POWER_LENGTH = 32,
+ };
+
+ //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 = 2,
+
+ DRAM_WIDTH_START = 8,
+ DRAM_WIDTH_LEN = 3,
+
+ DRAM_DENSITY_START = 11,
+ DRAM_DENSITY_LEN = 3,
+
+ DRAM_STACK_TYPE_START = 14,
+ DRAM_STACK_TYPE_LEN = 2,
+
+ DRAM_MFGID_START = 16,
+ DRAM_MFGID_LEN = 3,
+
+ DIMMS_PER_PORT_START = 19,
+ DIMMS_PER_PORT_LEN = 2,
+
+ // Invalid for Nimbus but compile will fail without them
+ DIMM_MODULE_HEIGHT_START = 0,
+ DIMM_MODULE_HEIGHT_LEN = 1,
+ };
+
+
+ // Definition is in chip folder
+ static const std::vector< std::pair<uint8_t , uint8_t> > DIMM_TYPE_MAP;
+};
+}//power_thermal
+}// mss
+
+#endif
diff --git a/src/import/chips/p9/procedures/hwp/memory/lib/shared/mss_const.H b/src/import/chips/p9/procedures/hwp/memory/lib/shared/mss_const.H
index 5f175b44c..1564d6f85 100644
--- a/src/import/chips/p9/procedures/hwp/memory/lib/shared/mss_const.H
+++ b/src/import/chips/p9/procedures/hwp/memory/lib/shared/mss_const.H
@@ -156,11 +156,6 @@ enum ffdc_function_codes
// Used in rank.H
MAP_RP_PRIMARY_TO_INIT_CAL = 60,
- // Power thermal functions
- SLOPE = 70,
- INTERCEPT = 71,
- POWER_LIMIT = 72,
-
// PDA function codes
PDA_WR_VREF_LATCH_CONTAINER = 80,
PDA_WR_VREF_LATCH_VECTOR = 81,
diff --git a/src/import/chips/p9/procedures/hwp/memory/p9_mss_bulk_pwr_throttles.C b/src/import/chips/p9/procedures/hwp/memory/p9_mss_bulk_pwr_throttles.C
index 84cc1c73e..a586eda62 100644
--- a/src/import/chips/p9/procedures/hwp/memory/p9_mss_bulk_pwr_throttles.C
+++ b/src/import/chips/p9/procedures/hwp/memory/p9_mss_bulk_pwr_throttles.C
@@ -5,7 +5,7 @@
/* */
/* OpenPOWER HostBoot Project */
/* */
-/* Contributors Listed Below - COPYRIGHT 2015,2018 */
+/* Contributors Listed Below - COPYRIGHT 2015,2019 */
/* [+] International Business Machines Corp. */
/* */
/* */
@@ -32,6 +32,8 @@
// *HWP Team: Memory
// *HWP Level: 3
// *HWP Consumed by: FSP:HB
+
+#include <lib/shared/nimbus_defaults.H>
#include <vector>
#include <fapi2.H>
@@ -88,7 +90,7 @@ extern "C"
const uint8_t l_pos = mss::index(l_mca);
- mss::power_thermal::throttle l_pwr_struct(l_mca, l_rc);
+ mss::power_thermal::throttle<> l_pwr_struct(l_mca, l_rc);
FAPI_TRY(l_rc, "Error constructing mss:power_thermal::throttle object for target %s",
mss::c_str(l_mca));
diff --git a/src/import/chips/p9/procedures/hwp/memory/p9_mss_eff_config_thermal.C b/src/import/chips/p9/procedures/hwp/memory/p9_mss_eff_config_thermal.C
index bd5819fd2..bac3836ff 100644
--- a/src/import/chips/p9/procedures/hwp/memory/p9_mss_eff_config_thermal.C
+++ b/src/import/chips/p9/procedures/hwp/memory/p9_mss_eff_config_thermal.C
@@ -5,7 +5,7 @@
/* */
/* OpenPOWER HostBoot Project */
/* */
-/* Contributors Listed Below - COPYRIGHT 2015,2018 */
+/* Contributors Listed Below - COPYRIGHT 2015,2019 */
/* [+] International Business Machines Corp. */
/* */
/* */
@@ -33,6 +33,7 @@
// *HWP Level: 3
// *HWP Consumed by: FSP:HB
+#include <lib/shared/nimbus_defaults.H>
#include <fapi2.H>
#include <vector>
#include <p9_mss_eff_config_thermal.H>
@@ -52,12 +53,14 @@ extern "C"
/// @note sets ATTR_MSS_MEM_WATT_TARGET, ATTR_MSS_RUNTIME_MEM_THROTTLED_N_COMMANDS_PER_PORT and _PER_SLOT, and ATTR_MSS_PORT_MAXPOWER
fapi2::ReturnCode p9_mss_eff_config_thermal( const std::vector< fapi2::Target<fapi2::TARGET_TYPE_MCS> >& i_targets )
{
+ using TT = mss::power_thermal::throttle_traits<mss::mc_type::NIMBUS>;
+
FAPI_INF("Start effective config thermal");
fapi2::ReturnCode l_rc;
- std::vector< uint64_t > l_slope (mss::power_thermal::SIZE_OF_POWER_CURVES_ATTRS, 0);
- std::vector< uint64_t > l_intercept (mss::power_thermal::SIZE_OF_POWER_CURVES_ATTRS, 0);
- std::vector< uint64_t > l_thermal_power_limit (mss::power_thermal::SIZE_OF_THERMAL_ATTR, 0);
+ std::vector< uint64_t > l_slope (TT::SIZE_OF_POWER_CURVES_ATTRS, 0);
+ std::vector< uint64_t > l_intercept (TT::SIZE_OF_POWER_CURVES_ATTRS, 0);
+ std::vector< uint64_t > l_thermal_power_limit (TT::SIZE_OF_THERMAL_ATTR, 0);
uint16_t l_vddr_slope [mss::PORTS_PER_MCS][mss::MAX_DIMM_PER_PORT] = {};
uint16_t l_vddr_int [mss::PORTS_PER_MCS][mss::MAX_DIMM_PER_PORT] = {};
@@ -75,19 +78,21 @@ extern "C"
// Return error if safemode throttle utilization is less than MIN_UTIL
// This section needs to be in braces otherwise the compile will fail
{
+ using TT = mss::power_thermal::throttle_traits<>;
+ const uint64_t l_min_util = TT::MIN_UTIL;
uint16_t l_throttle_per_port = 0;
uint32_t l_throttle_denominator = 0;
FAPI_TRY(mss::mrw_mem_m_dram_clocks(l_throttle_denominator), "Error in p9_mss_eff_config_thermal" );
FAPI_TRY(mss::mrw_safemode_mem_throttled_n_commands_per_port(l_throttle_per_port),
"Error in p9_mss_eff_config_thermal" );
- FAPI_ASSERT( (l_throttle_per_port >= (mss::power_thermal::MIN_UTIL * l_throttle_denominator /
+ FAPI_ASSERT( (l_throttle_per_port >= (TT::MIN_UTIL * l_throttle_denominator /
mss::power_thermal::DRAM_BUS_UTILS / mss::power_thermal::UTIL_CONVERSION)),
fapi2::MSS_MRW_SAFEMODE_THROTTLE_NOT_SUPPORTED()
.set_MRW_SAFEMODE_N_VALUE(l_throttle_per_port)
.set_MRW_DRAM_CLOCK_THROTTLE_M(l_throttle_denominator)
- .set_MIN_UTIL_VALUE(mss::power_thermal::MIN_UTIL),
+ .set_MIN_UTIL_VALUE(l_min_util),
"MRW safemode attribute (N=%d, M=%d) has less util than the min util allowed (%d centi percent)",
- l_throttle_per_port, l_throttle_denominator, mss::power_thermal::MIN_UTIL);
+ l_throttle_per_port, l_throttle_denominator, l_min_util);
}
//Restore runtime_throttles from safemode setting
diff --git a/src/import/chips/p9/procedures/hwp/memory/p9_mss_utils_to_throttle.C b/src/import/chips/p9/procedures/hwp/memory/p9_mss_utils_to_throttle.C
index 076cd911c..56e2dbc42 100644
--- a/src/import/chips/p9/procedures/hwp/memory/p9_mss_utils_to_throttle.C
+++ b/src/import/chips/p9/procedures/hwp/memory/p9_mss_utils_to_throttle.C
@@ -5,7 +5,7 @@
/* */
/* OpenPOWER HostBoot Project */
/* */
-/* Contributors Listed Below - COPYRIGHT 2015,2018 */
+/* Contributors Listed Below - COPYRIGHT 2015,2019 */
/* [+] International Business Machines Corp. */
/* */
/* */
@@ -37,6 +37,7 @@
// *HWP Level: 3
// *HWP Consumed by: FSP:HB
+#include <lib/shared/nimbus_defaults.H>
#include <p9_mss_utils_to_throttle.H>
// fapi2
@@ -133,28 +134,30 @@ extern "C"
l_input_databus_util[l_port_num] = l_calc_util_safemode;
}
+ using TT = mss::power_thermal::throttle_traits<>;
+ const uint64_t l_min_util = TT::MIN_UTIL;
//Make sure MIN_UTIL <= input_utilization <= max_utilization
- const uint32_t l_databus_util = ( l_input_databus_util[l_port_num] >= mss::power_thermal::MIN_UTIL) ?
+ const uint32_t l_databus_util = ( l_input_databus_util[l_port_num] >= l_min_util) ?
std::min(l_input_databus_util[l_port_num], l_max_databus_util)
- : mss::power_thermal::MIN_UTIL;
+ : l_min_util;
// Error if utilization is less than MIN_UTIL
// Don't exit, let HWP finish and return error at end
- if (l_input_databus_util[l_port_num] < mss::power_thermal::MIN_UTIL)
+ if (l_input_databus_util[l_port_num] < l_min_util)
{
FAPI_ASSERT_NOEXIT( false,
fapi2::MSS_MIN_UTILIZATION_ERROR()
.set_INPUT_UTIL_VALUE(l_input_databus_util[l_port_num])
- .set_MIN_UTIL_VALUE(mss::power_thermal::MIN_UTIL),
+ .set_MIN_UTIL_VALUE(l_min_util),
"%s Input utilization (%d) less than minimum utilization allowed (%d)",
- mss::c_str(l_mca), l_input_databus_util[l_port_num], mss::power_thermal::MIN_UTIL);
+ mss::c_str(l_mca), l_input_databus_util[l_port_num], l_min_util);
l_util_error = true;
}
//Make a throttle object in order to calculate the port power
fapi2::ReturnCode l_rc;
- mss::power_thermal::throttle l_throttle (l_mca, l_rc);
+ mss::power_thermal::throttle<> l_throttle (l_mca, l_rc);
FAPI_TRY(l_rc, "Error calculating mss::power_thermal::throttle constructor in p9_mss_utils_to_throttles");
FAPI_INF( "%s MRW dram clock window: %d, databus utilization: %d",
diff --git a/src/import/chips/p9/procedures/xml/error_info/p9_memory_mss_eff_config_thermal.xml b/src/import/chips/p9/procedures/xml/error_info/p9_memory_mss_eff_config_thermal.xml
index 5de51418f..a156088c2 100644
--- a/src/import/chips/p9/procedures/xml/error_info/p9_memory_mss_eff_config_thermal.xml
+++ b/src/import/chips/p9/procedures/xml/error_info/p9_memory_mss_eff_config_thermal.xml
@@ -5,7 +5,7 @@
<!-- -->
<!-- OpenPOWER HostBoot Project -->
<!-- -->
-<!-- Contributors Listed Below - COPYRIGHT 2015,2018 -->
+<!-- Contributors Listed Below - COPYRIGHT 2015,2019 -->
<!-- [+] International Business Machines Corp. -->
<!-- -->
<!-- -->
@@ -34,182 +34,6 @@
<!-- -->
<hwpErrors>
- <hwpError>
- <rc>RC_MSS_NO_POWER_THERMAL_ATTR_FOUND</rc>
- <description>
- There was no match or value found in decoding the power thermal attributes
- </description>
- <ffdc>GENERATED_KEY</ffdc>
- <ffdc>FUNCTION</ffdc>
- <ffdc>DIMM_TARGET</ffdc>
- <ffdc>SIZE</ffdc>
- <ffdc>DRAM_GEN</ffdc>
- <ffdc>DIMM_TYPE</ffdc>
- <ffdc>DRAM_WIDTH</ffdc>
- <ffdc>DRAM_DENSITY</ffdc>
- <ffdc>STACK_TYPE</ffdc>
- <ffdc>MFGID</ffdc>
- <callout>
- <procedure>CODE</procedure>
- <priority>HIGH</priority>
- </callout>
- </hwpError>
-
- <hwpError>
- <rc>RC_MSS_POWER_THERMAL_ENCODE_ERROR</rc>
- <description>
- There was no match or value found in encoding the power thermal attributes
- </description>
- <ffdc>DIMM_TARGET</ffdc>
- <ffdc>ATTR</ffdc>
- <callout>
- <procedure>CODE</procedure>
- <priority>HIGH</priority>
- </callout>
- </hwpError>
-
- <hwpError>
- <rc>RC_MSS_POWER_THERMAL_DECODE_ERROR</rc>
- <description>
- There was no match or value found in decoding the power thermal attributes
- </description>
- <ffdc>DIMM_TARGET</ffdc>
- <ffdc>ATTR</ffdc>
- <callout>
- <procedure>CODE</procedure>
- <priority>HIGH</priority>
- </callout>
- </hwpError>
-
- <hwpError>
- <rc>RC_MSS_POWER_INTERCEPT_NOT_SET</rc>
- <description>
- The attribute ATTR_MSS_TOTAL_POWER_INTERCEPT was not set and equals 0
- </description>
- <callout>
- <procedure>CODE</procedure>
- <priority>HIGH</priority>
- </callout>
- </hwpError>
-
- <hwpError>
- <rc>RC_MSS_POWER_SLOPE_NOT_SET</rc>
- <description>
- The attribute ATTR_MSS_TOTAL_POWER_INTERCEPT was not set and equals 0
- </description>
- <callout>
- <procedure>CODE</procedure>
- <priority>HIGH</priority>
- </callout>
- </hwpError>
-
- <hwpError>
- <rc>RC_MSS_NO_DATABUS_UTILIZATION</rc>
- <description>
- There are 2 DIMMS on the port but both have 0 databus utilization
- </description>
- <ffdc>PORT_DATABUS_UTIL</ffdc>
- <ffdc>DIMM_COUNT</ffdc>
- <callout>
- <procedure>CODE</procedure>
- <priority>HIGH</priority>
- </callout>
- </hwpError>
-
- <hwpError>
- <rc>RC_MSS_CALC_POWER_CURVE_DIVIDE_BY_ZERO</rc>
- <description>
- Denominator equals 0
- </description>
- <ffdc>PORT_DATABUS_UTIL</ffdc>
- <ffdc>UTIL_CONVERSION</ffdc>
- <ffdc>IDLE_UTIL</ffdc>
- <ffdc>RESULT</ffdc>
- <callout>
- <procedure>CODE</procedure>
- <priority>HIGH</priority>
- </callout>
- </hwpError>
-
- <hwpError>
- <rc>RC_MSS_NO_PORT_POWER_LIMIT</rc>
- <description>
- Got 0 when calculating port power limit.
- Either no dimms or attribute MEM_WATT_TARGET wasn't set
- </description>
- <ffdc>COUNT_DIMMS</ffdc>
- <ffdc>PORT_POWER_LIMIT</ffdc>
- <callout>
- <procedure>CODE</procedure>
- <priority>HIGH</priority>
- </callout>
- </hwpError>
-
- <hwpError>
- <rc>RC_MSS_NO_PORT_POWER</rc>
- <description>
- Got 0 when calculating port power limits using the DIMMs databus utilization
- </description>
- <ffdc>COUNT_DIMMS</ffdc>
- <ffdc>MAX_UTILIZATION_DIMM_0</ffdc>
- <ffdc>MAX_UTILIZATION_DIMM_1</ffdc>
- <callout>
- <procedure>CODE</procedure>
- <priority>HIGH</priority>
- </callout>
- </hwpError>
-
- <hwpError>
- <rc>RC_MSS_M_DRAM_CLOCKS_EQUALS_ZERO</rc>
- <description>
- ATTR_MSS_MRW_MEM_M_DRAM_CLOCKS was not set and equals zero
- </description>
- <callout>
- <procedure>CODE</procedure>
- <priority>HIGH</priority>
- </callout>
- </hwpError>
-
- <hwpError>
- <rc>RC_MSS_CALC_PORT_POWER_EXCEEDS_MAX</rc>
- <description>
- The calculated port power from equalizing throttles exceeds the maximum allowed power
- </description>
- <ffdc>CALCULATED_PORT_POWER</ffdc>
- <ffdc>MAX_POWER_ALLOWED</ffdc>
- <ffdc>PORT_POS</ffdc>
- <callout>
- <procedure>CODE</procedure>
- <priority>HIGH</priority>
- </callout>
- <callout>
- <childTargets>
- <parent>MCA_TARGET</parent>
- <childType>TARGET_TYPE_DIMM</childType>
- </childTargets>
- <priority>MEDIUM</priority>
- </callout>
- <deconfigure>
- <childTargets>
- <parent>MCA_TARGET</parent>
- <childType>TARGET_TYPE_DIMM</childType>
- </childTargets>
- </deconfigure>
- </hwpError>
-
- <hwpError>
- <rc>RC_MSS_SLOT_UTIL_EXCEEDS_PORT</rc>
- <description>
- The memory throttle per slot (DIMM) exceeds the allowed throttle for the port
- </description>
- <ffdc>SLOT_UTIL</ffdc>
- <ffdc>PORT_UTIL</ffdc>
- <callout>
- <procedure>CODE</procedure>
- <priority>HIGH</priority>
- </callout>
- </hwpError>
-
<hwpError>
<rc>RC_MSS_SPLIT_UTIL_CALC_ERROR</rc>
<description>
@@ -225,17 +49,6 @@
</callout>
</hwpError>
- <hwpError>
- <rc>RC_MSS_OUTPUT_OVERFLOW_CALC_UTIL</rc>
- <description>
- Type of output variable is not large enough for the calculations
- </description>
- <ffdc>RESULT</ffdc>
- <callout>
- <procedure>CODE</procedure>
- <priority>HIGH</priority>
- </callout>
- </hwpError>
<hwpError>
<rc>RC_MSS_DIMM_COUNT_EXCEEDS_VMEM_REGULATOR_LIMIT</rc>
OpenPOWER on IntegriCloud