summaryrefslogtreecommitdiffstats
path: root/src/usr/htmgt
diff options
context:
space:
mode:
authorChris Cain <cjcain@us.ibm.com>2017-06-05 11:48:32 -0500
committerDaniel M. Crowell <dcrowell@us.ibm.com>2017-06-22 09:30:04 -0400
commit7d4cab0615138ae20cc02013b595f36f02e21a63 (patch)
treea23cd06845aba746e8194fadc0f7cc4652cad51b /src/usr/htmgt
parentccb74685e3205a1f74e4a2264f27775144600d2c (diff)
downloadtalos-hostboot-7d4cab0615138ae20cc02013b595f36f02e21a63.tar.gz
talos-hostboot-7d4cab0615138ae20cc02013b595f36f02e21a63.zip
HTMGT: Memory Throttling and Power Capping support
- Enable DIMM thermal monitoring - Implement VRM thermal monitoring support - Implement memory throttle calculations - Move HTMGT only attributes to _openpower xml files System owner will need to update the following for full support: OPEN_POWER_MIN_MEM_UTILIZATION_POWER_CAP OPEN_POWER_VRM_READ_TIMEOUT_SEC Change-Id: Ib7f31e58c62af4b66edc3989156ebc6e636cc741 RTC: 153942 Reviewed-on: http://ralgit01.raleigh.ibm.com/gerrit1/41982 Tested-by: Jenkins Server <pfd-jenkins+hostboot@us.ibm.com> Reviewed-by: Martha Broyles <mbroyles@us.ibm.com> Tested-by: Jenkins OP Build CI <op-jenkins+hostboot@us.ibm.com> Tested-by: FSP CI Jenkins <fsp-CI-jenkins+hostboot@us.ibm.com> Reviewed-by: Daniel M. Crowell <dcrowell@us.ibm.com>
Diffstat (limited to 'src/usr/htmgt')
-rw-r--r--src/usr/htmgt/htmgt.C6
-rw-r--r--src/usr/htmgt/htmgt_cfgdata.C180
-rw-r--r--src/usr/htmgt/htmgt_cfgdata.H3
-rw-r--r--src/usr/htmgt/htmgt_memthrottles.C767
-rw-r--r--src/usr/htmgt/htmgt_memthrottles.H13
-rw-r--r--src/usr/htmgt/htmgt_utility.H2
-rw-r--r--src/usr/htmgt/makefile11
-rw-r--r--src/usr/htmgt/test/htmgtcfgtest.H18
8 files changed, 602 insertions, 398 deletions
diff --git a/src/usr/htmgt/htmgt.C b/src/usr/htmgt/htmgt.C
index 56759c39f..7107d3e44 100644
--- a/src/usr/htmgt/htmgt.C
+++ b/src/usr/htmgt/htmgt.C
@@ -77,7 +77,11 @@ namespace HTMGT
{
#ifndef __HOSTBOOT_RUNTIME
// Calc memory throttles (once per IPL)
- calcMemThrottles();
+ l_err = calcMemThrottles();
+ if( l_err )
+ {
+ break;
+ }
#endif
// Make sure OCCs are ready for communication
diff --git a/src/usr/htmgt/htmgt_cfgdata.C b/src/usr/htmgt/htmgt_cfgdata.C
index 144eacb56..eb4136d19 100644
--- a/src/usr/htmgt/htmgt_cfgdata.C
+++ b/src/usr/htmgt/htmgt_cfgdata.C
@@ -31,6 +31,7 @@
#include "ipmi/ipmisensor.H"
#include <htmgt/htmgt_reasoncodes.H>
#include <fapi2_attribute_service.H>
+#include "htmgt_memthrottles.H"
using namespace TARGETING;
@@ -159,10 +160,10 @@ namespace HTMGT
break;
case OCC_CFGDATA_MEM_THROTTLE:
- if (int_flags_set(FLAG_SEND_MEM_CONFIG))
+ if (!int_flags_set(FLAG_DISABLE_MEM_CONFIG))
{
getMemThrottleMessageData(occ->getTarget(),
- cmdData, cmdDataLen);
+ occInstance, cmdData, cmdDataLen);
}
break;
@@ -238,10 +239,8 @@ enum occCfgDataVersion
{
OCC_CFGDATA_FREQ_POINT_VERSION = 0x20,
OCC_CFGDATA_APSS_VERSION = 0x20,
- OCC_CFGDATA_MEM_CONFIG_VERSION = 0x21,
OCC_CFGDATA_PCAP_CONFIG_VERSION = 0x20,
OCC_CFGDATA_SYS_CONFIG_VERSION = 0x20,
- OCC_CFGDATA_MEM_THROTTLE_VERSION = 0x20,
OCC_CFGDATA_TCT_CONFIG_VERSION = 0x20,
OCC_CFGDATA_AVSBUS_CONFIG_VERSION = 0X01,
};
@@ -289,7 +288,6 @@ void writeMemConfigData( uint8_t *& o_data,
//Byte 11 Nimbus DIMM Temp i2c address
// Cumulus Reserved for Cumulus
o_data[io_index++] = i_i2cDevAddr;
-
}
@@ -301,7 +299,7 @@ void getMemConfigMessageData(const TargetHandle_t i_occ,
assert(o_data != nullptr);
o_data[index++] = OCC_CFGDATA_MEM_CONFIG;
- o_data[index++] = OCC_CFGDATA_MEM_CONFIG_VERSION;
+ o_data[index++] = 0x21; // version
//System reference needed for these ATTR.
Target* sys = nullptr;
@@ -328,7 +326,7 @@ void getMemConfigMessageData(const TargetHandle_t i_occ,
//Byte 5: Number of data sets.
size_t numSetsOffset = index++; //Will fill in numSets at the end
- if (int_flags_set(FLAG_SEND_MEM_CONFIG))
+ if (!int_flags_set(FLAG_DISABLE_MEM_CONFIG))
{
TargetHandleList centaurs;
TargetHandleList mbas;
@@ -458,6 +456,7 @@ void getMemConfigMessageData(const TargetHandle_t i_occ,
void getMemThrottleMessageData(const TargetHandle_t i_occ,
+ const uint8_t i_occ_instance,
uint8_t* o_data, uint64_t & o_size)
{
uint8_t numSets = 0;
@@ -467,17 +466,17 @@ void getMemThrottleMessageData(const TargetHandle_t i_occ,
assert(proc != nullptr);
assert(o_data != nullptr);
- TargetHandleList centaurs;
+ //Get all functional MCSs
+ TargetHandleList mcs_list;
+ getAllChiplets(mcs_list, TYPE_MCS, true);
+ TMGT_INF("calcMemThrottles: found %d MCSs", mcs_list.size());
o_data[index++] = OCC_CFGDATA_MEM_THROTTLE;
- o_data[index++] = OCC_CFGDATA_MEM_THROTTLE_VERSION;
+ o_data[index++] = 0x20; // version;
//Byte 3: Number of memory throttling data sets.
size_t numSetsOffset = index++; //Will fill in numSets at the end
-
- getChildAffinityTargets(centaurs, proc, CLASS_CHIP, TYPE_MEMBUF);
-
//Next, the following format repeats per set/MBA:
//Byte 0: Cumulus: Centaur position 0-7
// Nimbus : Memory Controller
@@ -489,49 +488,112 @@ void getMemThrottleMessageData(const TargetHandle_t i_occ,
//Bytes 8-9: Turbo N_PER_CHIP
//Bytes 10-11: Max mem power with throttle @Turbo
//Bytes 12-13: Power Capping N_PER_MBA
- //Bytes 14-15: Power Capping N_PER_MBA
+ //Bytes 14-15: Power Capping N_PER_CHIP
//Bytes 16-17: Max mem power with throttle @PowerCapping
//Bytes 18-19: Nominal Power N_PER_MBA
//Bytes 20-21: Nominal Power N_PER_CHIP
//Bytes 22-23: Max mem power with throttle @Nominal
//Bytes 24-29: Reserved
- // Hard coding until we can get mem throttle cfg data
- for (uint8_t entry = 0; entry < 2; ++entry)
+ for(const auto & mcs_target : mcs_list)
{
- o_data[index++] = 0x00; //MC01
- o_data[index++] = entry; // Port
- o_data[index++] = 0x44; // Min N Per MBA
- o_data[index++] = 0x44;
- o_data[index++] = 0x01; // Max mem pwr at min throttle
- o_data[index++] = 0x00;
- o_data[index++] = 0x45; // Turbo N per MBA
- o_data[index++] = 0x56;
- o_data[index++] = 0x55; // Turbo N per chip
- o_data[index++] = 0x5F;
- o_data[index++] = 0x01; // Max mem pwr at turbo
- o_data[index++] = 0x10;
- o_data[index++] = 0x45; // Power capping N per MBA
- o_data[index++] = 0x56;
- o_data[index++] = 0x55; // Power capping N per chip
- o_data[index++] = 0x5F;
- o_data[index++] = 0x01; // Max mem pwr at power capping
- o_data[index++] = 0x20;
- o_data[index++] = 0x45; // Nominal N per MBA
- o_data[index++] = 0x56;
- o_data[index++] = 0x55; // Nominal N per chip
- o_data[index++] = 0x5F;
- o_data[index++] = 0x01; // Max mem pwr at Nominal
- o_data[index++] = 0x30;
- o_data[index++] = 0x00; // reserved
- o_data[index++] = 0x00;
- o_data[index++] = 0x00;
- o_data[index++] = 0x00;
- o_data[index++] = 0x00;
- o_data[index++] = 0x00;
- ++numSets ;
- }
+ uint8_t mcs_unit = 0xFF;
+ if (!mcs_target->tryGetAttr<TARGETING::ATTR_CHIP_UNIT>(mcs_unit))
+ {
+ uint32_t mcs_huid = 0xFFFFFFFF;
+ mcs_target->tryGetAttr<TARGETING::ATTR_HUID>(mcs_huid);
+ TMGT_ERR("calcMemThrottles: Unable to determine MCS unit for HUID"
+ " 0x%04X", mcs_huid);
+ continue;
+ }
+ ConstTargetHandle_t proc_target = getParentChip(mcs_target);
+ assert(proc_target != nullptr);
+ // Make sure this MCS is for the current OCC/Proc
+ if (i_occ_instance == proc_target->getAttr<TARGETING::ATTR_POSITION>())
+ {
+ // Read the throttle and power values for this MCS
+ ATTR_OT_MIN_N_PER_MBA_type npm_min;
+ ATTR_OT_MEM_POWER_type power_min;
+ mcs_target->tryGetAttr<ATTR_OT_MIN_N_PER_MBA>(npm_min);
+ mcs_target->tryGetAttr<ATTR_OT_MEM_POWER>(power_min);
+ ATTR_N_PLUS_ONE_N_PER_MBA_type npm_redun;
+ ATTR_N_PLUS_ONE_N_PER_CHIP_type npc_redun;
+ ATTR_N_PLUS_ONE_MEM_POWER_type power_redun;
+ mcs_target->tryGetAttr<ATTR_N_PLUS_ONE_N_PER_MBA>(npm_redun);
+ mcs_target->tryGetAttr<ATTR_N_PLUS_ONE_N_PER_CHIP>(npc_redun);
+ mcs_target->tryGetAttr<ATTR_N_PLUS_ONE_MEM_POWER>(power_redun);
+ ATTR_POWERCAP_N_PER_MBA_type npm_pcap;
+ ATTR_POWERCAP_N_PER_CHIP_type npc_pcap;
+ ATTR_POWERCAP_MEM_POWER_type power_pcap;
+ mcs_target->tryGetAttr<ATTR_POWERCAP_N_PER_MBA>(npm_pcap);
+ mcs_target->tryGetAttr<ATTR_POWERCAP_N_PER_CHIP>(npc_pcap);
+ mcs_target->tryGetAttr<ATTR_POWERCAP_MEM_POWER>(power_pcap);
+
+ // Query the functional MCAs for this MCS
+ TARGETING::TargetHandleList mca_list;
+ getChildAffinityTargetsByState(mca_list, mcs_target, CLASS_UNIT,
+ TYPE_MCA, UTIL_FILTER_FUNCTIONAL);
+ for(const auto & mca_target : mca_list)
+ {
+ // unit identifies unique MCA under a processor
+ uint8_t mca_unit = 0xFF;
+ mca_target->tryGetAttr<TARGETING::ATTR_CHIP_UNIT>(mca_unit);
+ const uint8_t mca_rel_pos = mca_unit % 2;
+ if ((npm_min[mca_rel_pos] == 0) ||
+ (npm_redun[mca_rel_pos] == 0) ||
+ (npm_pcap[mca_rel_pos] == 0))
+ {
+ TMGT_ERR("calcMemThrottles: MCS%d/MCA%d [%d]"
+ " - Ignored due to null throttle",
+ mcs_unit, mca_unit, mca_rel_pos);
+ TMGT_ERR("N/slot: Min=%d, Turbo=%d, Pcap=%d",
+ npm_min[mca_rel_pos], npm_redun[mca_rel_pos],
+ npm_pcap[mca_rel_pos]);
+ continue;
+ }
+ if (mca_rel_pos >= TMGT_MAX_MCA_PER_MCS)
+ {
+ TMGT_ERR("calcMemThrottles: OCC%d / MCS%d / MCA%d"
+ " - Ignored due invalid MCA position: %d",
+ i_occ_instance, mcs_unit, mca_unit, mca_rel_pos);
+ continue;
+ }
+ TMGT_INF("calcMemThrottles: OCC%d / MCS%d / MCA%d [%d]",
+ i_occ_instance, mcs_unit, mca_unit, mca_rel_pos);
+ // OCC expects phyMC=0 for (MCS0-1) and 1 for (MCS2-3)
+ // MCS MCA MCA OCC OCC
+ // unit unit relPos phyMC phyPort
+ // 0 0 0 0 0
+ // 0 1 1 0 1
+ // 1 2 0 0 2
+ // 1 3 1 0 3
+ // 2 4 0 1 0
+ // 2 5 1 1 1
+ // 3 6 0 1 2
+ // 3 7 1 1 3
+ o_data[index] = mcs_unit >> 1; // MC (0-1)
+ o_data[index+1] = mca_unit % 4; // Phy Port (0-3)
+ // Minimum
+ UINT16_PUT(&o_data[index+ 2], npm_min[mca_rel_pos]);
+ UINT16_PUT(&o_data[index+ 4], power_min[mca_rel_pos]);
+ // Turbo
+ UINT16_PUT(&o_data[index+ 6], npm_redun[mca_rel_pos]);
+ UINT16_PUT(&o_data[index+ 8], npc_redun[mca_rel_pos]);
+ UINT16_PUT(&o_data[index+10], power_redun[mca_rel_pos]);
+ // Power Capping
+ UINT16_PUT(&o_data[index+12], npm_pcap[mca_rel_pos]);
+ UINT16_PUT(&o_data[index+14], npc_pcap[mca_rel_pos]);
+ UINT16_PUT(&o_data[index+16], power_pcap[mca_rel_pos]);
+ // Nominal (same as Turbo)
+ UINT16_PUT(&o_data[index+18], npm_redun[mca_rel_pos]);
+ UINT16_PUT(&o_data[index+20], npc_redun[mca_rel_pos]);
+ UINT16_PUT(&o_data[index+22], power_redun[mca_rel_pos]);
+ index += 30;
+ ++numSets ;
+ }
+ }
+ }
TMGT_INF("getMemThrottleMessageData: returning %d"
" sets of data for OCC 0x%X",
@@ -669,8 +731,13 @@ void getPowerCapMessageData(uint8_t* o_data, uint64_t & o_size)
index += 2;
// Quick Power Drop Power Cap
- ATTR_OPEN_POWER_N_BULK_POWER_LIMIT_WATTS_type qpd_pcap =
- sys->getAttr<ATTR_OPEN_POWER_N_BULK_POWER_LIMIT_WATTS>();
+ ATTR_OPEN_POWER_N_BULK_POWER_LIMIT_WATTS_type qpd_pcap;
+ if ( ! sys->tryGetAttr
+ <ATTR_OPEN_POWER_N_BULK_POWER_LIMIT_WATTS>(qpd_pcap))
+ {
+ // attr does not exist, so disable by sending 0
+ qpd_pcap = 0;
+ }
UINT16_PUT(&o_data[index], qpd_pcap);
index += 2;
@@ -846,7 +913,7 @@ void getThermalControlMessageData(uint8_t* o_data,
l_numSets++;
}
- // Dimm
+ // DIMM
o_data[index++] = CFGDATA_FRU_TYPE_DIMM;
l_DVFS_temp =l_sys->getAttr<ATTR_OPEN_POWER_DIMM_THROTTLE_TEMP_DEG_C>();
l_ERR_temp =l_sys->getAttr<ATTR_OPEN_POWER_DIMM_ERROR_TEMP_DEG_C>();
@@ -864,6 +931,19 @@ void getThermalControlMessageData(uint8_t* o_data,
o_data[index++] = l_timeout;
l_numSets++;
+ // VRM
+ l_timeout = l_sys->getAttr<ATTR_OPEN_POWER_VRM_READ_TIMEOUT_SEC>();
+ if (l_timeout != 0)
+ {
+ o_data[index++] = CFGDATA_FRU_TYPE_VRM;
+ o_data[index++] = 0xFF;
+ o_data[index++] = 0xFF;
+ o_data[index++] = 0xFF;
+ o_data[index++] = 0xFF;
+ o_data[index++] = l_timeout;
+ l_numSets++;
+ }
+
o_data[l_numSetsOffset] = l_numSets;
o_size = index;
diff --git a/src/usr/htmgt/htmgt_cfgdata.H b/src/usr/htmgt/htmgt_cfgdata.H
index 2e0fde5bb..126b5f4c7 100644
--- a/src/usr/htmgt/htmgt_cfgdata.H
+++ b/src/usr/htmgt/htmgt_cfgdata.H
@@ -71,6 +71,7 @@ namespace HTMGT
CFGDATA_FRU_TYPE_PROC = 0x00,
CFGDATA_FRU_TYPE_MEMBUF = 0x01,
CFGDATA_FRU_TYPE_DIMM = 0x02,
+ CFGDATA_FRU_TYPE_VRM = 0x03,
CFDATA_DVFS_NOT_DEFINED = 0xFF,
};
@@ -146,11 +147,13 @@ namespace HTMGT
* including the format and version numbers.
*
* @param[in] i_occ - the OCC to gather data for
+ * @param[in] i_occ_instance - OCC instance number
* @param[in] o_data - preallocated buffer to fill in
* @param[out] o_size - set to the message size
* @pre o_data is large enough.
*/
void getMemThrottleMessageData(const TARGETING::TargetHandle_t i_occ,
+ const uint8_t i_occ_instance,
uint8_t* o_data, uint64_t & o_size);
diff --git a/src/usr/htmgt/htmgt_memthrottles.C b/src/usr/htmgt/htmgt_memthrottles.C
index b87addd14..a919d3928 100644
--- a/src/usr/htmgt/htmgt_memthrottles.C
+++ b/src/usr/htmgt/htmgt_memthrottles.C
@@ -5,7 +5,7 @@
/* */
/* OpenPOWER HostBoot Project */
/* */
-/* Contributors Listed Below - COPYRIGHT 2014,2016 */
+/* Contributors Listed Below - COPYRIGHT 2014,2017 */
/* [+] International Business Machines Corp. */
/* */
/* */
@@ -31,8 +31,13 @@
#include <targeting/common/attributes.H>
#include <targeting/common/targetservice.H>
#include <fapi2.H>
+#include <plat_hwp_invoker.H>
+// Hardware Procedures:
+#include <p9_mss_utils_to_throttle.H>
+#include <p9_mss_bulk_pwr_throttles.H>
+// See src/include/usr/targeting/common/utilFilter.H for handy target utilities
using namespace TARGETING;
@@ -46,297 +51,184 @@ namespace HTMGT
{
/**
- * Helper function to run the hardware procedure to calculate the
- * throttle attributes for the Over Temp condition.
- * flow = htmgtCalcMemThrottle_OT
+ * Run hardware procedure to determine throttle/numerator/number of commands
+ * based on the specified utilization
*
- * @param[in] i_mbas - list of functional MBAs
* @param[in] i_utilization - Minimum utilization value required
- * @param[in] i_nSafeModeMBA - the safe mode MBA throttle numerator
+ * @param[in] i_watt_target - power target required for bulk_pwr_throttles
*/
-void memPowerThrottleOT(TargetHandleList & i_mbas,
- const uint32_t i_nSafeModeMBA,
- const uint8_t i_utilization)
+errlHndl_t call_utils_to_throttle(
+ std::vector <fapi2::Target<fapi2::TARGET_TYPE_MCS>> i_fapi_target_list,
+ const uint32_t i_util,
+ const uint32_t i_watt_target = 0)
{
- bool useSafeMode = false;
- bool throttleError = false;
- uint32_t nUtilBased = 0;
- uint32_t mbaHuid = 0;
- Target* sys = NULL;
-
- TMGT_INF(ENTER_MRK" memPowerThrottleOT");
+ errlHndl_t err = NULL;
+ uint32_t utilization[TMGT_MAX_MCA_PER_MCS] = { i_util, i_util };
+ uint32_t l_watt_targets[TMGT_MAX_MCA_PER_MCS][TMGT_MAX_DIMM_PER_MCA] =
+ {i_watt_target, i_watt_target, i_watt_target, i_watt_target};
+ TMGT_INF("call_utils_to_throttle: utilization: 0x%04X, watt_target: "
+ "0x%04X", i_util, i_watt_target);
+
+ // Update input attributes for specified targets
+ for(const auto & l_fapi_target : i_fapi_target_list)
+ {
+ FAPI_ATTR_SET(fapi2::ATTR_MSS_DATABUS_UTIL, l_fapi_target, utilization);
+ if (i_watt_target)
+ {
+ FAPI_ATTR_SET(fapi2::ATTR_MSS_MEM_WATT_TARGET,
+ l_fapi_target, l_watt_targets);
+ }
+ }
- targetService().getTopLevelTarget(sys);
- assert(sys != NULL);
+ // p9_mss_utils_to_throttle() - Sets number commands allowed within a
+ // given port databus utilization
+ // inputs: ATTR_MSS_DATABUS_UTIL
+ // outputs: ATTR_MSS_MEM_THROTTLED_N_COMMANDS_PER_SLOT,
+ // ATTR_MSS_MEM_THROTTLED_N_COMMANDS_PER_PORT, and
+ // ATTR_MSS_PORT_MAXPOWER
+ TMGT_INF("call_utils_to_throttle: Calling HWP:p9_mss_utils_to_throttle"
+ "(POWER) for %d MCS Targets", i_fapi_target_list.size());
+ {
+ FAPI_INVOKE_HWP(err, p9_mss_utils_to_throttle, i_fapi_target_list);
+ }
- for( const auto & mba : i_mbas )
+ if (NULL != err)
{
- mbaHuid = mba->getAttr<ATTR_HUID>();
- useSafeMode = true;
- nUtilBased = 0;
+ TMGT_ERR("call_utils_to_throttle: HWP:p9_mss_utils_to_throttle failed"
+ " with rc=0x%04X", err->reasonCode());
+ }
- if (i_utilization != 0)
- {
- //Run a hardware procedure to calculate the lowest
- //possible throttle setting based on the minimum
- //utilization percentage.
- errlHndl_t err = NULL;
- const fapi2::Target<fapi2::TARGET_TYPE_MBA> fapiTarget(mba);
-
- //Set this so the procedure can use it
- mba->setAttr<ATTR_MSS_DATABUS_UTIL_PER_MBA>(i_utilization);
-
-/* TODO: RTC 155033 - Memory Throttle Settings
- FAPI_INVOKE_HWP(err, mss_util_to_throttle, fapiTarget);
-*/
- if (err)
- {
- //Ignore the error and just use safe
- //mode as the lowest throttle
- TMGT_ERR("memPowerThrottleOT: Failed call to "
- "mss_util_to_throttle on MBA 0x%X",
- mbaHuid);
-
- delete err;
- err = NULL;
- }
- else
- {
- //get the procedure output
- nUtilBased = mba->getAttr<ATTR_MSS_UTIL_N_PER_MBA>();
+ return err;
- if (0 != nUtilBased)
- {
- useSafeMode = false;
- }
- else
- {
- TMGT_ERR("memPowerThrottleOT: mss_util_to_throttle"
- " calculated a numerator of 0, MBA 0x%X",
- mbaHuid);
-
- if (!throttleError)
- {
- throttleError = true;
-
- /*@
- * @errortype
- * @reasoncode HTMGT_RC_OT_THROTTLE_INVALID_N
- * @severity ERRL_SEV_UNRECOVERABLE
- * @moduleid HTMGT_MOD_MEMTHROTTLE
- * @userdata1 MBA HUID
- * @devdesc Overtemp Throttle HW procedure
- * calculated an invalid numerator
- * value.
- */
- err = new ERRORLOG::ErrlEntry(
- ERRORLOG::ERRL_SEV_UNRECOVERABLE,
- HTMGT_MOD_MEMTHROTTLE,
- HTMGT_RC_OT_THROTTLE_INVALID_N,
- mbaHuid, 0, true);
- err->collectTrace(HTMGT_COMP_NAME);
- errlCommit(err, HTMGT_COMP_ID);
- }
- }
- }
- }
+} // end call_utils_to_throttle()
- if (useSafeMode)
- {
- nUtilBased = i_nSafeModeMBA;
- TMGT_INF("memPowerThrottleOT: MBA 0x%X must use safemode"
- " numerator", mbaHuid);
- }
+/**
+ * Calculate throttles for over-temperture
+ *
+ * @param[in] i_fapi_target_list - list of FAPI MCS targets
+ * @param[in] i_utilization - Minimum utilization value required
+ */
+errlHndl_t memPowerThrottleOT(
+ std::vector < fapi2::Target< fapi2::TARGET_TYPE_MCS>> i_fapi_target_list,
+ const uint8_t i_utilization)
+{
+ errlHndl_t err = NULL;
- TMGT_INF("memPowerThrottleOT: MBA 0x%X: N Util OT = 0x%X",
- mbaHuid, nUtilBased);
+ TMGT_INF("memPowerThrottleOT: Calculating throttles for util: %d",
+ i_utilization);
- mba->setAttr<ATTR_OT_MIN_N_PER_MBA>(nUtilBased);
+ err = call_utils_to_throttle(i_fapi_target_list, i_utilization);
+ if (NULL == err)
+ {
+ uint32_t ot_mem_power = 0;
+ for(const auto & mcs_fapi_target : i_fapi_target_list)
+ {
+ // Read HWP outputs:
+ ATTR_OT_MIN_N_PER_MBA_type l_slot = {0};
+ ATTR_OT_MEM_POWER_type l_power = {0};
+ FAPI_ATTR_GET(fapi2::ATTR_MSS_MEM_THROTTLED_N_COMMANDS_PER_SLOT,
+ mcs_fapi_target, l_slot);
+ FAPI_ATTR_GET(fapi2::ATTR_MSS_PORT_MAXPOWER,
+ mcs_fapi_target, l_power);
+ ot_mem_power += l_power[0] + l_power[1];
+
+ // Update MCS data (to be sent to OCC)
+ TARGETING::Target * mcs_target =
+ reinterpret_cast<TARGETING::Target *>(mcs_fapi_target.get());
+ ConstTargetHandle_t proc_target = getParentChip(mcs_target);
+ assert(proc_target != nullptr);
+ const uint8_t occ_instance =
+ proc_target->getAttr<TARGETING::ATTR_POSITION>();
+ uint8_t mcs_unit = 0xFF;
+ mcs_target->tryGetAttr<TARGETING::ATTR_CHIP_UNIT>(mcs_unit);
+ mcs_target->setAttr<ATTR_OT_MIN_N_PER_MBA>(l_slot);
+ mcs_target->setAttr<ATTR_OT_MEM_POWER>(l_power);
+ TMGT_INF("memPowerThrottleOT: MIN: OCC%d/MCS%d - "
+ "N/slot: %d/%d, Power: %d/%dcW",
+ occ_instance, mcs_unit, l_slot[0], l_slot[1],
+ l_power[0], l_power[1]);
+ }
+ TMGT_INF("memPowerThrottleOT: Total Minimum Memory"
+ " Power: %dW", ot_mem_power/100);
+ }
+ else
+ {
+ TMGT_ERR("memPowerThrottleOT: Failed to calculate over-temp"
+ " memory throttles, rc=0x%04X",
+ err->reasonCode());
}
+ return err;
-}
-
-
+} // end memPowerThrottleOT()
/**
- * Helper function to run the mss_bulk_pwr_throttles and
- * mss_util_to_throttle to calculate memory throttling
- * numerator values.
+ * Run the p9_mss_bulk_pwr_throttles hardware procedure
+ * to calculate memory throttling numerator values.
*
- * @param[in] i_mba - the MBA
- * @param[in] i_wattTarget - the power target for the MBA
+ * @param[in] i_fapi_target_list - list of FAPI MCS targets
+ * @param[in] i_wattTarget - the power target for the MCS
* @param[in] i_utilization - the utilization desired
- * @param[out] o_useSafeMode - will be set to true if safe mode
- * values should be used
- * @param[out] o_nMBA - set to the N_PER_MBA numerator value
- * (don't use if safemode=true)
- * @param[out] o_nChip - set to the N_PER_CHIP numerator value
- * (don't use if safemode=true)
*/
-void doMBAThrottleCalc(TARGETING::Target * i_mba,
+errlHndl_t call_bulk_pwr_throttles(
+ std::vector < fapi2::Target< fapi2::TARGET_TYPE_MCS>> i_fapi_target_list,
const uint32_t i_wattTarget,
- const uint8_t i_utilization,
- bool & o_useSafeMode,
- uint32_t & o_nMBA,
- uint32_t & o_nChip)
+ const uint8_t i_utilization)
{
errlHndl_t err = NULL;
- o_useSafeMode = false;
- o_nMBA = 0;
- o_nChip = 0;
-
- TARGETING::ATTR_MSS_MEM_WATT_TARGET_type l_wattArray = {{i_wattTarget,
- i_wattTarget},
- {i_wattTarget,
- i_wattTarget}};
//Set the values the procedures need
- i_mba->setAttr<ATTR_MSS_MEM_WATT_TARGET>(l_wattArray);
- i_mba->setAttr<ATTR_MSS_DATABUS_UTIL_PER_MBA>(i_utilization);
-
- const fapi2::Target<fapi2::TARGET_TYPE_MBA> fapiTarget(i_mba);
-
-/* TODO This hwp is changing for p9
- FAPI_INVOKE_HWP(err, mss_bulk_pwr_throttles, fapiTarget);
-*/
- if (err)
- {
- TMGT_ERR("doMBAThrottleCalc: Failed call to mss_bulk_pwr_throttles"
- " on MBA 0x%X",
- i_mba->getAttr<ATTR_HUID>());
- }
- else
+ err = call_utils_to_throttle(i_fapi_target_list,
+ i_utilization, i_wattTarget);
+ if (NULL == err)
{
- //Get the procedure outputs
- o_nMBA = i_mba->getAttr<ATTR_MSS_MEM_THROTTLE_NUMERATOR_PER_MBA>();
- o_nChip = i_mba->getAttr<ATTR_MSS_MEM_THROTTLE_NUMERATOR_PER_CHIP>();
-
- //Make sure neither are 0
- if ((0 == o_nMBA) || (0 == o_nChip))
+ TMGT_INF("call_bulk_pwr_throttles: Calling HWP:p9_mss_bulk_pwr_"
+ "throttles(POWER) for MCS Targets");
+ FAPI_INVOKE_HWP(err, p9_mss_bulk_pwr_throttles, i_fapi_target_list,
+ mss::throttle_type::POWER);
+ if (NULL != err)
{
- TMGT_ERR("doMBAThrottleCalc: mss_bulk_pwr_throttles calculated a"
- " numerator value of 0: nMBA = %d, nChip = %d, MBA 0x%X",
- o_nMBA, o_nChip, i_mba->getAttr<ATTR_HUID>());
-
- /*@
- * @errortype
- * @reasoncode HTMGT_RC_THROTTLE_INVALID_N
- * @severity ERRL_SEV_UNRECOVERABLE
- * @moduleid HTMGT_MOD_MEMTHROTTLE
- * @userdata1 MBA HUID
- * @userdata2[0:31] MBA numerator
- * @userdata2[32:63] Chip numerator
- * @devdesc Throttle HW procedure calculated
- * an invalid numerator value.
- */
- uint64_t data = ((uint64_t)o_nMBA << 32) | o_nChip;
- err = new ERRORLOG::ErrlEntry(ERRORLOG::ERRL_SEV_UNRECOVERABLE,
- HTMGT_MOD_MEMTHROTTLE,
- HTMGT_RC_THROTTLE_INVALID_N,
- i_mba->getAttr<ATTR_HUID>(),
- data, true);
- }
- else if (i_utilization != 0)
- {
- //Make sure the calculated throttles meet the min
- //utilization, if provided.
-
-/* TODO this hwp is changing for p9
- FAPI_INVOKE_HWP(err, mss_util_to_throttle, fapiTarget);
-*/
- if (err)
- {
- TMGT_ERR("doMBAThrottleCalc: Failed call to "
- "mss_util_to_throttle on MBA 0x%X",
- i_mba->getAttr<ATTR_HUID>());
- }
- else
- {
- //Get the value the procedure wrote
- uint32_t nUtilMBA = i_mba->getAttr<ATTR_MSS_UTIL_N_PER_MBA>();
-
- TRACUCOMP("doMBAThrottleCalc: mss_util_to_throttle"
- " calculated N = %d",
- nUtilMBA);
-
- //If mss_bulk_pwr_throttles calculated a value
- //that doesn't meet the minimum requested utilization,
- //then we have a problem.
- if (nUtilMBA > o_nMBA)
- {
- TMGT_ERR("doMBAThrottleCalc: MSS_UTIL_N_PER_MBA 0x%X "
- "> MSS_MEM_THROTTLE_N_PER_MBA 0x%X on MBA 0x%X",
- nUtilMBA, o_nMBA,
- i_mba->getAttr<ATTR_HUID>());
-
- /*@
- * @errortype
- * @reasoncode HTMGT_RC_THROTTLE_UTIL_ERROR
- * @severity ERRL_SEV_UNRECOVERABLE
- * @moduleid HTMGT_MOD_MEMTHROTTLE
- * @userdata1 MBA HUID
- * @userdata2[0:31] util based N
- * @userdata2[32:63] calculated N
- * @devdesc Throttle numerator calculated
- * doesn't meet min utilization
- */
- uint64_t data = ((uint64_t)nUtilMBA << 32) | o_nMBA;
- err = new ERRORLOG::ErrlEntry(
- ERRORLOG::ERRL_SEV_UNRECOVERABLE,
- HTMGT_MOD_MEMTHROTTLE,
- HTMGT_RC_THROTTLE_UTIL_ERROR,
- i_mba->getAttr<ATTR_HUID>(),
- data, true);
- }
- }
+ TMGT_ERR("call_bulk_pwr_throttles: p9_mss_bulk_pwr_throttles "
+ "failed with rc=0x%04X", err->reasonCode());
}
}
-
- if (err)
+ else
{
- err->collectTrace(HTMGT_COMP_NAME);
- errlCommit(err, HTMGT_COMP_ID);
- o_useSafeMode = true;
+ TMGT_ERR("call_bulk_pwr_throttles: call_utils_to_throttle failed with"
+ " rc=0x%04X", err->reasonCode());
}
-}
+ return err;
+
+} // end call_bulk_pwr_throttles()
/**
- * Helper function to run the hardware procedures to calculate the
- * throttle attributes used for redundant power.
- * flow = htmgtCalcMemThrottle_redundantPwr
+ * Calculate throttles for when system has redundant power (N+1 mode)
*
- * @param[in] i_mbas - the list of functional MBAs
- * @param[in] i_nSafeModeMBA - the safe mode MBA throttle numerator
- * @param[in] i_nSafeModeChip - the safe mode MBA throttle numerator
+ * @param[in] i_fapi_target_list - list of FAPI MCS targets
* @param[in] i_utilization - Minimum utilization value required
* @param[in] i_efficiency - the regulator efficiency
*/
-void memPowerThrottleRedPower(TargetHandleList & i_mbas,
- const uint32_t i_nSafeModeMBA,
- const uint32_t i_nSafeModeChip,
+errlHndl_t memPowerThrottleRedPower(
+ std::vector <fapi2::Target<fapi2::TARGET_TYPE_MCS>> i_fapi_target_list,
const uint8_t i_utilization,
const uint8_t i_efficiency)
{
+ errlHndl_t err = NULL;
Target* sys = NULL;
uint32_t power = 0;
uint32_t wattTarget = 0;
- uint32_t nChip = 0;
- uint32_t nMBA = 0;
- bool useSafeMode = false;
-
targetService().getTopLevelTarget(sys);
assert(sys != NULL);
- //Get the max N+1 power allocated to memory
+ //Get the max redundant (N+1) power allocated to memory
power = sys->getAttr<ATTR_OPEN_POWER_N_PLUS_ONE_MAX_MEM_POWER_WATTS>();
- power *= 100; //centiWatts
+ power *= 100; // convert to centiWatts
//Account for the regulator efficiency (percentage), if supplied
if (i_efficiency != 0)
@@ -344,72 +236,86 @@ void memPowerThrottleRedPower(TargetHandleList & i_mbas,
power = (power * i_efficiency) / 100;
}
- //Find the Watt target for each MBA
- if (i_mbas.size())
+ //Find the Watt target for each MCS
+ if (i_fapi_target_list.size())
{
- wattTarget = power / i_mbas.size();
+ wattTarget = power / i_fapi_target_list.size();
}
- TMGT_INF("memPowerThrottleRedPower: power = %d, wattTarget = %d",
- power, wattTarget);
+ TMGT_INF("memPowerThrottleRedPower: N+1 power: %dW / %dcW per MCS",
+ power/100, wattTarget);
- for( const auto & mba : i_mbas )
+ //Calculate the throttles
+ err = call_bulk_pwr_throttles(i_fapi_target_list,
+ wattTarget,
+ i_utilization);
+ if (NULL == err)
{
- useSafeMode = false;
- nMBA = nChip = 0;
-
- //Run the calculations
- doMBAThrottleCalc(mba, wattTarget, i_utilization,
- useSafeMode, nMBA, nChip);
-
- if (useSafeMode)
+ uint32_t nominal_mem_power = 0;
+ for(auto & mcs_fapi_target : i_fapi_target_list)
{
- nMBA = i_nSafeModeMBA;
- nChip = i_nSafeModeChip;
- TMGT_INF("memPowerThrottleRedPower: MBA 0x%X using safemode "
- "numerator",
- mba->getAttr<ATTR_HUID>());
+ // Read HWP output parms:
+ ATTR_N_PLUS_ONE_N_PER_MBA_type l_slot = {0};
+ ATTR_N_PLUS_ONE_N_PER_CHIP_type l_port = {0};
+ ATTR_N_PLUS_ONE_MEM_POWER_type l_power = {0};
+ FAPI_ATTR_GET(fapi2::ATTR_MSS_MEM_THROTTLED_N_COMMANDS_PER_SLOT,
+ mcs_fapi_target, l_slot);
+ FAPI_ATTR_GET(fapi2::ATTR_MSS_MEM_THROTTLED_N_COMMANDS_PER_PORT,
+ mcs_fapi_target, l_port);
+ FAPI_ATTR_GET(fapi2::ATTR_MSS_PORT_MAXPOWER,
+ mcs_fapi_target, l_power);
+ nominal_mem_power += l_power[0] + l_power[1];
+
+ // Update MCS data (to be sent to OCC)
+ TARGETING::Target * mcs_target =
+ reinterpret_cast<TARGETING::Target *>(mcs_fapi_target.get());
+ ConstTargetHandle_t proc_target = getParentChip(mcs_target);
+ assert(proc_target != nullptr);
+ const uint8_t occ_instance =
+ proc_target->getAttr<TARGETING::ATTR_POSITION>();
+ uint8_t mcs_unit = 0xFF;
+ mcs_target->tryGetAttr<TARGETING::ATTR_CHIP_UNIT>(mcs_unit);
+ mcs_target->setAttr<ATTR_N_PLUS_ONE_N_PER_MBA>(l_slot);
+ mcs_target->setAttr<ATTR_N_PLUS_ONE_N_PER_CHIP>(l_port);
+ mcs_target->setAttr<ATTR_N_PLUS_ONE_MEM_POWER>(l_power);
+
+ TMGT_INF("memPowerThrottleRedPower: NOMINAL: OCC%d/MCS%d - "
+ "N/slot: %d/%d, N/port: %d/%d, Power: %d/%dcW",
+ occ_instance, mcs_unit, l_slot[0], l_slot[1],
+ l_port[0], l_port[1], l_power[0], l_power[1]);
}
-
- //Set the attributes we'll send to OCC later
- TMGT_INF("memPowerThrottleRedPower: MBA 0x%X: N_PER_MBA = 0x%X, "
- "N_PER_CHIP = 0x%X",
- mba->getAttr<ATTR_HUID>(), nMBA, nChip);
-
- mba->setAttr<ATTR_N_PLUS_ONE_N_PER_MBA>(nMBA);
- mba->setAttr<ATTR_N_PLUS_ONE_N_PER_CHIP>(nChip);
-
+ TMGT_INF("memPowerThrottleRedPower: Total Redundant Memory Power: %dW",
+ nominal_mem_power/100);
+ }
+ else
+ {
+ TMGT_ERR("memPowerThrottleRedPower: Failed to calculate redundant "
+ "power memory throttles, rc=0x%04X",
+ err->reasonCode());
}
+ return err;
-}
+} // end memPowerThrottleRedPower()
/**
- * Helper function to run the hardware procedures to calculate the
- * throttle attributes used for oversubscription.
- * flow = htmgtCalcMemThrottle_oversub
+ * Calculate throttles for when system is oversubscribed (N mode)
*
- * @param[in] i_mbas - the list of functional MBAs
- * @param[in] i_nSafeModeMBA - the safe mode MBA throttle numerator
- * @param[in] i_nSafeModeChip - the safe mode MBA throttle numerator
+ * @param[in] i_fapi_target_list - list of FAPI MCS targets
* @param[in] i_utilization - Minimum utilization value required
* @param[in] i_efficiency - the regulator efficiency
*/
-void memPowerThrottleOverSub(TargetHandleList & i_mbas,
- const uint32_t i_nSafeModeMBA,
- const uint32_t i_nSafeModeChip,
- const uint8_t i_utilization,
- const uint8_t i_efficiency)
+errlHndl_t memPowerThrottleOverSub(
+ std::vector <fapi2::Target<fapi2::TARGET_TYPE_MCS>> i_fapi_target_list,
+ const uint8_t i_utilization,
+ const uint8_t i_efficiency)
{
+ errlHndl_t err = NULL;
Target* sys = NULL;
uint32_t power = 0;
uint32_t wattTarget = 0;
- uint32_t nChip = 0;
- uint32_t nMBA = 0;
- bool useSafeMode = false;
-
targetService().getTopLevelTarget(sys);
assert(sys != NULL);
@@ -423,87 +329,278 @@ void memPowerThrottleOverSub(TargetHandleList & i_mbas,
power = (power * i_efficiency) / 100;
}
- //Find the Watt target for each MBA
- if (i_mbas.size())
+ //Find the Watt target for each MCS
+ if (i_fapi_target_list.size())
{
- wattTarget = power / i_mbas.size();
+ wattTarget = power / i_fapi_target_list.size();
}
- TMGT_INF("memPowerThrottleOverSub: power = %d, wattTarget = %d",
- power, wattTarget);
+ TMGT_INF("memPowerThrottleOverSub: N power: %dW / %dcW per MCS",
+ power/100, wattTarget);
- for ( const auto & mba : i_mbas )
+ //Calculate the throttles
+ err = call_bulk_pwr_throttles(i_fapi_target_list,
+ wattTarget,
+ i_utilization);
+ if (NULL == err)
{
- useSafeMode = false;
- nMBA = nChip = 0;
-
- //Run the calculations
- doMBAThrottleCalc(mba, wattTarget, i_utilization,
- useSafeMode, nMBA, nChip);
-
- if (useSafeMode)
+ uint32_t oversub_mem_power = 0;
+ for(auto & mcs_fapi_target : i_fapi_target_list)
{
- nMBA = i_nSafeModeMBA;
- nChip = i_nSafeModeChip;
- TMGT_INF("memPowerThrottleOverSub: MBA 0x%X using safemode "
- "numerator",
- mba->getAttr<ATTR_HUID>());
+ // Read HWP output parms:
+ ATTR_OVERSUB_N_PER_MBA_type l_slot = {0};
+ ATTR_OVERSUB_N_PER_CHIP_type l_port = {0};
+ ATTR_OVERSUB_MEM_POWER_type l_power = {0};
+ FAPI_ATTR_GET(fapi2::ATTR_MSS_MEM_THROTTLED_N_COMMANDS_PER_SLOT,
+ mcs_fapi_target, l_slot);
+ FAPI_ATTR_GET(fapi2::ATTR_MSS_MEM_THROTTLED_N_COMMANDS_PER_PORT,
+ mcs_fapi_target, l_port);
+ FAPI_ATTR_GET(fapi2::ATTR_MSS_PORT_MAXPOWER,
+ mcs_fapi_target, l_power);
+ oversub_mem_power += l_power[0] + l_power[1];
+
+ // Update MCS data (to be sent to OCC)
+ TARGETING::Target * mcs_target =
+ reinterpret_cast<TARGETING::Target *>(mcs_fapi_target.get());
+ ConstTargetHandle_t proc_target = getParentChip(mcs_target);
+ assert(proc_target != nullptr);
+ const uint8_t occ_instance =
+ proc_target->getAttr<TARGETING::ATTR_POSITION>();
+ uint8_t mcs_unit = 0xFF;
+ mcs_target->tryGetAttr<TARGETING::ATTR_CHIP_UNIT>(mcs_unit);
+ mcs_target->setAttr<ATTR_OVERSUB_N_PER_MBA>(l_slot);
+ mcs_target->setAttr<ATTR_OVERSUB_N_PER_CHIP>(l_port);
+ mcs_target->setAttr<ATTR_OVERSUB_MEM_POWER>(l_power);
+
+ TMGT_INF("memPowerThrottleOverSub: OVERSUB: OCC%d/MCS%d - "
+ "N/slot: %d/%d, N/port: %d/%d, Power: %d/%dcW",
+ occ_instance, mcs_unit, l_slot[0], l_slot[1],
+ l_port[0], l_port[1], l_power[0], l_power[1]);
}
+ TMGT_INF("memPowerThrottleOverSub: Total Oversubscription Memory"
+ " Power: %dW", oversub_mem_power/100);
+ }
+ else
+ {
+ TMGT_ERR("memPowerThrottleOverSub: Failed to calculate redundant "
+ "power memory throttles, rc=0x%04X",
+ err->reasonCode());
+ }
+
+ return err;
+
+} // end memPowerThrottleOverSub()
+
- //Set the attributes we'll send to OCC later
- TMGT_INF("memPowerThrottleOverSub: MBA 0x%X: N_PER_MBA = 0x%X, "
- "N_PER_CHIP = 0x%X",
- mba->getAttr<ATTR_HUID>(), nMBA, nChip);
- mba->setAttr<ATTR_OVERSUB_N_PER_MBA>(nMBA);
- mba->setAttr<ATTR_OVERSUB_N_PER_CHIP>(nChip);
+/**
+ * Run hardware procedures to calculate the throttles for power capping
+ *
+ * @param[in] i_fapi_target_list - list of FAPI MCS targets
+ * @param[in] i_utilization - Minimum utilization value required
+ */
+errlHndl_t memPowerThrottlePowercap(
+ std::vector < fapi2::Target< fapi2::TARGET_TYPE_MCS>> i_fapi_target_list,
+ const uint8_t i_utilization)
+{
+ errlHndl_t err = NULL;
+
+ TMGT_INF("memPowerThrottlePowercap: Calculating throttles for util: %d",
+ i_utilization);
+ if (i_utilization != 0)
+ {
+ //Calculate the throttles
+ err = call_utils_to_throttle(i_fapi_target_list, i_utilization);
}
+ if (NULL == err)
+ {
+ uint32_t pcap_mem_power = 0;
+ for(auto & mcs_fapi_target : i_fapi_target_list)
+ {
+ TARGETING::Target * mcs_target =
+ reinterpret_cast<TARGETING::Target *>(mcs_fapi_target.get());
+ ConstTargetHandle_t proc_target = getParentChip(mcs_target);
+ assert(proc_target != nullptr);
+ const uint8_t occ_instance =
+ proc_target->getAttr<TARGETING::ATTR_POSITION>();
+ uint8_t mcs_unit = 0xFF;
+ mcs_target->tryGetAttr<TARGETING::ATTR_CHIP_UNIT>(mcs_unit);
+
+ // Read HWP output parms (if the procedure was run):
+ ATTR_POWERCAP_N_PER_MBA_type l_slot = {0xFF, 0xFF};
+ ATTR_POWERCAP_N_PER_CHIP_type l_port = {0xFF, 0xFF};
+ ATTR_POWERCAP_MEM_POWER_type l_power = {0};
+ if (i_utilization != 0)
+ {
+ FAPI_ATTR_GET(fapi2::ATTR_MSS_MEM_THROTTLED_N_COMMANDS_PER_SLOT,
+ mcs_fapi_target, l_slot);
+ FAPI_ATTR_GET(fapi2::ATTR_MSS_MEM_THROTTLED_N_COMMANDS_PER_PORT,
+ mcs_fapi_target, l_port);
+ FAPI_ATTR_GET(fapi2::ATTR_MSS_PORT_MAXPOWER,
+ mcs_fapi_target, l_power);
+ }
+ // else N values will be 0xFF and will be overwritten below
+
+ // Validate pcap throttles are the lowest throttles
+ ATTR_N_PLUS_ONE_N_PER_MBA_type l_slot_redun = {0};
+ ATTR_N_PLUS_ONE_N_PER_CHIP_type l_port_redun = {0};
+ ATTR_N_PLUS_ONE_MEM_POWER_type l_power_redun = {0};
+ mcs_target->tryGetAttr<ATTR_N_PLUS_ONE_N_PER_MBA>(l_slot_redun);
+ mcs_target->tryGetAttr<ATTR_N_PLUS_ONE_N_PER_CHIP>(l_port_redun);
+ mcs_target->tryGetAttr<ATTR_N_PLUS_ONE_MEM_POWER>(l_power_redun);
+ ATTR_OVERSUB_N_PER_MBA_type l_slot_oversub = {0};
+ ATTR_OVERSUB_N_PER_CHIP_type l_port_oversub = {0};
+ ATTR_OVERSUB_MEM_POWER_type l_power_oversub = {0};
+ mcs_target->tryGetAttr<ATTR_OVERSUB_N_PER_MBA>(l_slot_oversub);
+ mcs_target->tryGetAttr<ATTR_OVERSUB_N_PER_CHIP>(l_port_oversub);
+ mcs_target->tryGetAttr<ATTR_OVERSUB_MEM_POWER>(l_power_oversub);
+ unsigned int mca_index;
+ for (mca_index = 0; mca_index < TMGT_MAX_MCA_PER_MCS; ++mca_index)
+ {
+ if (l_slot[mca_index] > l_slot_oversub[mca_index])
+ {
+ TMGT_INF("memPowerThrottlePowercap: MCS%d/MCA%d"
+ " oversub throttle (%d) < pcap throttle (%d)",
+ mcs_unit, mca_index,
+ l_slot_oversub[mca_index], l_slot[mca_index]);
+ l_slot[mca_index] = l_slot_oversub[mca_index];
+ l_port[mca_index] = l_port_oversub[mca_index];
+ l_power[mca_index] = l_power_oversub[mca_index];
+ }
+ if (l_slot[mca_index] > l_slot_redun[mca_index])
+ {
+ TMGT_INF("memPowerThrottlePowercap: MCS%d/MCA%d - "
+ " redun throttle (%d) < pcap throttle (%d)",
+ mcs_unit, mca_index,
+ l_slot_redun[mca_index], l_slot[mca_index]);
+ l_slot[mca_index] = l_slot_redun[mca_index];
+ l_port[mca_index] = l_port_redun[mca_index];
+ l_power[mca_index] = l_power_redun[mca_index];
+ }
+ }
-}
+ // Update MCS data (to be sent to OCC)
+ mcs_target->setAttr<ATTR_POWERCAP_N_PER_MBA>(l_slot);
+ mcs_target->setAttr<ATTR_POWERCAP_N_PER_CHIP>(l_port);
+ mcs_target->setAttr<ATTR_POWERCAP_MEM_POWER>(l_power);
+ pcap_mem_power += l_power[0] + l_power[1];
+
+ // Trace Results
+ TMGT_INF("memPowerThrottlePowercap: PCAP: OCC%d/MCS%d - "
+ "N/slot: %d/%d, N/port: %d/%d, Power: %d/%dcW",
+ occ_instance, mcs_unit, l_slot[0], l_slot[1],
+ l_port[0], l_port[1], l_power[0], l_power[1]);
+ }
+ TMGT_INF("memPowerThrottlePowercap: Total PowerCap Memory"
+ " Power: %dW", pcap_mem_power/100);
+ }
+ else
+ {
+ TMGT_ERR("memPowerThrottlePowercap: Failed to calculate powercap "
+ "memory throttles, rc=0x%04X",
+ err->reasonCode());
+ }
+ return err;
+} // end memPowerThrottlePowercap()
-void calcMemThrottles()
+
+
+errlHndl_t calcMemThrottles()
{
Target* sys = NULL;
- TargetHandleList mbas;
targetService().getTopLevelTarget(sys);
assert(sys != NULL);
- uint32_t nSafeModeMBA =
- sys->getAttr<ATTR_MRW_SAFEMODE_MEM_THROTTLE_NUMERATOR_PER_MBA>();
-
- uint32_t nSafeModeChip =
- sys->getAttr<ATTR_MRW_SAFEMODE_MEM_THROTTLE_NUMERATOR_PER_CHIP>();
-
- uint8_t utilization =
+ uint8_t min_utilization =
sys->getAttr<ATTR_OPEN_POWER_MIN_MEM_UTILIZATION_THROTTLING>();
-
- uint8_t efficiency =
+ if (min_utilization == 0)
+ {
+ uint32_t l_safe_n_per_mba =
+ sys->getAttr<ATTR_MSS_MRW_SAFEMODE_MEM_THROTTLED_N_COMMANDS_PER_PORT>();
+ TMGT_INF("MIN_MEM_UTILIZATION_THROTTLING is 0, so reading "
+ "ATTR_MSS_MRW_SAFEMODE_MEM_THROTTLED_N_COMMANDS_PER_PORT:"
+ " %d", l_safe_n_per_mba);
+ if (l_safe_n_per_mba == 0)
+ {
+ l_safe_n_per_mba = 10;
+ TMGT_ERR("ATTR_MSS_MRW_SAFEMODE_MEM_THROTTLED_N_COMMANDS_PER_PORT"
+ " is 0! Using %d", l_safe_n_per_mba);
+ }
+ }
+ const uint8_t efficiency =
sys->getAttr<ATTR_OPEN_POWER_REGULATOR_EFFICIENCY_FACTOR>();
+ TMGT_INF("calcMemThrottles: Using min utilization=%d, efficiency=%d"
+ " percent", min_utilization, efficiency);
- TMGT_INF("calcMemThrottles: Using nSafeModeMBA=0x%X, nSafeModeChip=0x%X",
- nSafeModeMBA, nSafeModeChip);
-
- TMGT_INF("calcMemThrottles: Using utilization=%d, efficiency=%d percent",
- utilization, efficiency);
+ //Get all functional MCSs
+ TargetHandleList mcs_list;
+ getAllChiplets(mcs_list, TYPE_MCS, true);
+ TMGT_INF("calcMemThrottles: found %d MCSs", mcs_list.size());
+ // Create a FAPI Target list for HWP
+ std::vector < fapi2::Target< fapi2::TARGET_TYPE_MCS>> l_fapi_target_list;
+ for(const auto & mcs_target : mcs_list)
+ {
+ uint32_t mcs_huid = 0xFFFFFFFF;
+ uint8_t mcs_unit = 0xFF;
+ mcs_target->tryGetAttr<TARGETING::ATTR_HUID>(mcs_huid);
+ mcs_target->tryGetAttr<TARGETING::ATTR_CHIP_UNIT>(mcs_unit);
+
+ // Query the functional MCAs for this MCS
+ TARGETING::TargetHandleList mca_list;
+ getChildAffinityTargetsByState(mca_list, mcs_target, CLASS_UNIT,
+ TYPE_MCA, UTIL_FILTER_FUNCTIONAL);
+ uint8_t occ_instance = 0xFF;
+ ConstTargetHandle_t proc_target = getParentChip(mcs_target);
+ assert(proc_target != nullptr);
+ occ_instance = proc_target->getAttr<TARGETING::ATTR_POSITION>();
+ TMGT_INF("calcMemThrottles: OCC%d, MCS%d HUID:0x%08X has %d"
+ " functional MCSs",
+ occ_instance, mcs_unit, mcs_huid, mca_list.size());
+
+ // Convert to FAPI target and add to list
+ fapi2::Target<fapi2::TARGET_TYPE_MCS> l_fapiTarget(mcs_target);
+ l_fapi_target_list.push_back(l_fapiTarget);
+ }
- //Get all functional MBAs
- getAllChiplets(mbas, TYPE_MBA, true);
+ errlHndl_t err = NULL;
+ do
+ {
+ //Calculate Throttle settings for Over Temperature
+ err = memPowerThrottleOT(l_fapi_target_list, min_utilization);
+ if (NULL != err) break;
+
+ //Calculate Throttle settings for Nominal/Turbo
+ err = memPowerThrottleRedPower(l_fapi_target_list,
+ min_utilization, efficiency);
+ if (NULL != err) break;
+
+ //Calculate Throttle settings for Oversubscription
+ err = memPowerThrottleOverSub(l_fapi_target_list,
+ min_utilization, efficiency);
+ if (NULL != err) break;
+
+ //Calculate Throttle settings for Power Capping
+ uint8_t pcap_min_utilization;
+ if (!sys->tryGetAttr<ATTR_OPEN_POWER_MIN_MEM_UTILIZATION_POWER_CAP>
+ (pcap_min_utilization))
+ {
+ pcap_min_utilization = 0;
+ }
+ err = memPowerThrottlePowercap(l_fapi_target_list,pcap_min_utilization);
- //Calculate Throttle settings for Over Temperature
- memPowerThrottleOT(mbas, nSafeModeMBA, utilization);
+ } while(0);
- //Calculate Throttle settings for Redundant Power
- memPowerThrottleRedPower(mbas, nSafeModeMBA, nSafeModeChip,
- utilization, efficiency);
+ if (err)
+ {
+ err->collectTrace(HTMGT_COMP_NAME);
+ }
- //Calculate Throttle settings for Oversubscription
- memPowerThrottleOverSub(mbas, nSafeModeMBA, nSafeModeChip,
- utilization, efficiency);
+ return err;
}
} // End namespace
diff --git a/src/usr/htmgt/htmgt_memthrottles.H b/src/usr/htmgt/htmgt_memthrottles.H
index 7816da98f..37b79bf54 100644
--- a/src/usr/htmgt/htmgt_memthrottles.H
+++ b/src/usr/htmgt/htmgt_memthrottles.H
@@ -5,7 +5,7 @@
/* */
/* OpenPOWER HostBoot Project */
/* */
-/* Contributors Listed Below - COPYRIGHT 2014 */
+/* Contributors Listed Below - COPYRIGHT 2014,2017 */
/* [+] International Business Machines Corp. */
/* */
/* */
@@ -25,18 +25,23 @@
#ifndef HTMGT_MEMTHROTTLES_H
#define HTMGT_MEMTHROTTLES_H
+#include <errl/errlmanager.H>
namespace HTMGT
{
+ // NIMBUS:
+ const uint8_t TMGT_MAX_MCS_PER_MCBIST = 2;
+ const uint8_t TMGT_MAX_MCA_PER_MCS = 2;
+ const uint8_t TMGT_MAX_DIMM_PER_MCA = 2;
+ const uint8_t TMGT_MAX_DIMM_PER_MCS =
+ TMGT_MAX_DIMM_PER_MCA * TMGT_MAX_MCA_PER_MCS;
/**
* Calculates the memory throttling numerator values for the OT,
* oversubscription, and redundant power cases. The results are
* stored in attributes under the corresponding MBAs.
*/
- void calcMemThrottles();
-
-
+ errlHndl_t calcMemThrottles();
};
#endif
diff --git a/src/usr/htmgt/htmgt_utility.H b/src/usr/htmgt/htmgt_utility.H
index 7872a1f78..5ef5d7457 100644
--- a/src/usr/htmgt/htmgt_utility.H
+++ b/src/usr/htmgt/htmgt_utility.H
@@ -117,7 +117,7 @@ namespace HTMGT
enum internalFlagTypes
{
FLAG_HALT_ON_OCC_SRC = 0x00800000, // Prevent resets after SRC
- FLAG_SEND_MEM_CONFIG = 0x00000800, // Enables sending mem config
+ FLAG_DISABLE_MEM_CONFIG = 0x00000800, // Disable sending mem config
FLAG_HALT_ON_RESET_FAIL = 0x00000100, // Stop additional resets
FLAG_EXT_RESET_DISABLED = 0x00000080, // Ignore opal-prd/BMC resets
FLAG_DISABLE_MEM_THROTTLE = 0x00000040,
diff --git a/src/usr/htmgt/makefile b/src/usr/htmgt/makefile
index e73d02705..8ddea9b09 100644
--- a/src/usr/htmgt/makefile
+++ b/src/usr/htmgt/makefile
@@ -5,7 +5,7 @@
#
# OpenPOWER HostBoot Project
#
-# Contributors Listed Below - COPYRIGHT 2014,2016
+# Contributors Listed Below - COPYRIGHT 2014,2017
# [+] International Business Machines Corp.
#
#
@@ -28,6 +28,15 @@ MODULE = htmgt
# objects common to hostboot and hbrt
include htmgt_common.mk
+EXTRAINCDIR += ${ROOTPATH}/src/import/chips/p9/procedures/hwp/memory
+EXTRAINCDIR += ${ROOTPATH}/src/import
+
+PROCEDURES_PATH = ${ROOTPATH}/src/import/chips/p9/procedures
+EXTRAINCDIR += $(PROCEDURES_PATH)/hwp/memory
+include ${ROOTPATH}/procedure.rules.mk
+OBJS += $(PROCEDURES_PATH)/hwp/memory/p9_mss_utils_to_throttle.o
+OBJS += $(PROCEDURES_PATH)/hwp/memory/p9_mss_bulk_pwr_throttles.o
+
# objects unique to hostboot
OBJS += htmgt_memthrottles.o
diff --git a/src/usr/htmgt/test/htmgtcfgtest.H b/src/usr/htmgt/test/htmgtcfgtest.H
index 776d24e2a..ab71ec034 100644
--- a/src/usr/htmgt/test/htmgtcfgtest.H
+++ b/src/usr/htmgt/test/htmgtcfgtest.H
@@ -127,31 +127,37 @@ public:
//Make sure all of the numerators are set
for (mba=mbas.begin();mba!=mbas.end();++mba)
{
- if (0 == (*mba)->getAttr<ATTR_OT_MIN_N_PER_MBA>())
+ ATTR_OT_MIN_N_PER_MBA_type n;
+ (*mba)->tryGetAttr<ATTR_OT_MIN_N_PER_MBA>(n);
+ if ((0 == n[0]) && (0 == n[1]))
{
TS_FAIL("MBA 0x%X has value of zero for OT_MIN_N_PER_MBA",
(*mba)->getAttr<ATTR_HUID>());
}
- if (0 == (*mba)->getAttr<ATTR_N_PLUS_ONE_N_PER_MBA>())
+ (*mba)->tryGetAttr<ATTR_N_PLUS_ONE_N_PER_MBA>(n);
+ if ((0 == n[0]) && (0 == n[1]))
{
TS_FAIL("MBA 0x%X has value of zero for N_PLUS_ONE_N_PER_MBA",
(*mba)->getAttr<ATTR_HUID>());
}
- if (0 == (*mba)->getAttr<ATTR_N_PLUS_ONE_N_PER_CHIP>())
+ (*mba)->tryGetAttr<ATTR_N_PLUS_ONE_N_PER_CHIP>(n);
+ if ((0 == n[0]) && (0 == n[1]))
{
TS_FAIL("MBA 0x%X has value of zero for N_PLUS_ONE_N_PER_CHIP",
(*mba)->getAttr<ATTR_HUID>());
}
- if (0 == (*mba)->getAttr<ATTR_OVERSUB_N_PER_MBA>())
+ (*mba)->tryGetAttr<ATTR_OVERSUB_N_PER_MBA>(n);
+ if ((0 == n[0]) && (0 == n[1]))
{
TS_FAIL("MBA 0x%X has value of zero for OVERSUB_N_PER_MBA",
(*mba)->getAttr<ATTR_HUID>());
}
- if (0 == (*mba)->getAttr<ATTR_OVERSUB_N_PER_CHIP>())
+ (*mba)->tryGetAttr<ATTR_OVERSUB_N_PER_CHIP>(n);
+ if ((0 == n[0]) && (0 == n[1]))
{
TS_FAIL("MBA 0x%X has value of zero for OVERSUB_N_PER_CHIP",
(*mba)->getAttr<ATTR_HUID>());
@@ -179,7 +185,7 @@ public:
{
memset(data, 0, 4*KILOBYTE);
- getMemThrottleMessageData(*occ, data, size);
+ getMemThrottleMessageData(*occ, 0, data, size);
if (data[0] != OCC_CFGDATA_MEM_THROTTLE)
{
OpenPOWER on IntegriCloud