summaryrefslogtreecommitdiffstats
path: root/src/import/chips/p9
diff options
context:
space:
mode:
Diffstat (limited to 'src/import/chips/p9')
-rw-r--r--src/import/chips/p9/procedures/hwp/memory/lib/mss_attribute_accessors.H34
-rw-r--r--src/import/chips/p9/procedures/hwp/memory/lib/power_thermal/decoder.H50
-rw-r--r--src/import/chips/p9/procedures/hwp/memory/lib/power_thermal/throttle.C272
-rw-r--r--src/import/chips/p9/procedures/hwp/memory/lib/power_thermal/throttle.H42
-rw-r--r--src/import/chips/p9/procedures/hwp/memory/lib/utils/find.H11
-rw-r--r--src/import/chips/p9/procedures/hwp/memory/p9_mss_bulk_pwr_throttles.C8
-rw-r--r--src/import/chips/p9/procedures/hwp/memory/p9_mss_bulk_pwr_throttles.H4
-rw-r--r--src/import/chips/p9/procedures/hwp/memory/p9_mss_eff_config.C13
-rw-r--r--src/import/chips/p9/procedures/hwp/memory/p9_mss_eff_config_thermal.C25
-rw-r--r--src/import/chips/p9/procedures/hwp/memory/p9_mss_utils_to_throttle.C48
-rw-r--r--src/import/chips/p9/procedures/xml/attribute_info/memory_mcs_attributes.xml15
-rw-r--r--src/import/chips/p9/procedures/xml/error_info/p9_memory_mss_eff_config.xml63
12 files changed, 488 insertions, 97 deletions
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 fc1a83347..8219c5bed 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
@@ -5644,6 +5644,28 @@ fapi_try_exit:
}
///
+/// @brief ATTR_MSS_MEM_PORT_POS_OF_FAIL_THROTTLE getter
+/// @param[out] uint64_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 This is the fapi position of the port that failed to calculate memory throttles
+/// given the passed in watt target and or
+/// utilization
+///
+inline fapi2::ReturnCode mem_port_fail_throttle(uint64_t& o_value)
+{
+
+ FAPI_TRY( FAPI_ATTR_GET(fapi2::ATTR_MSS_MEM_PORT_POS_OF_FAIL_THROTTLE, fapi2::Target<fapi2::TARGET_TYPE_SYSTEM>(),
+ o_value) );
+ return fapi2::current_err;
+
+fapi_try_exit:
+ FAPI_ERR("failed accessing ATTR_MSS_MEM_PORT_POS_OF_FAIL_THROTTLE: 0x%lx (system target)",
+ uint64_t(fapi2::current_err));
+ return fapi2::current_err;
+}
+
+///
/// @brief ATTR_MSS_MEM_M_DRAM_CLOCKS getter
/// @param[in] const ref to the fapi2::Target<fapi2::TARGET_TYPE_MCA>
/// @param[out] ref to the value uint32_t
@@ -6483,8 +6505,8 @@ fapi_try_exit:
/// @param[out] ref to the value uint32_t
/// @note Generated by gen_accessors.pl generateParameters (D)
/// @return fapi2::ReturnCode - FAPI2_RC_SUCCESS iff get is OK
-/// @note Databus utilization limit used to calculate memory throttles and power limit
-/// creator: OCC consumer:
+/// @note Databus utilization per port limit used to calculate memory throttles and power
+/// limit creator: OCC consumer:
/// mss_utils_to_throttle
///
inline fapi2::ReturnCode databus_util(const fapi2::Target<fapi2::TARGET_TYPE_MCA>& i_target, uint32_t& o_value)
@@ -6507,8 +6529,8 @@ fapi_try_exit:
/// @param[out] ref to the value uint32_t
/// @note Generated by gen_accessors.pl generateParameters (D.1)
/// @return fapi2::ReturnCode - FAPI2_RC_SUCCESS iff get is OK
-/// @note Databus utilization limit used to calculate memory throttles and power limit
-/// creator: OCC consumer:
+/// @note Databus utilization per port limit used to calculate memory throttles and power
+/// limit creator: OCC consumer:
/// mss_utils_to_throttle
///
inline fapi2::ReturnCode databus_util(const fapi2::Target<fapi2::TARGET_TYPE_DIMM>& i_target, uint32_t& o_value)
@@ -6532,8 +6554,8 @@ fapi_try_exit:
/// @param[out] uint32_t* memory to store the value
/// @note Generated by gen_accessors.pl generateParameters (E)
/// @return fapi2::ReturnCode - FAPI2_RC_SUCCESS iff get is OK
-/// @note Databus utilization limit used to calculate memory throttles and power limit
-/// creator: OCC consumer:
+/// @note Databus utilization per port limit used to calculate memory throttles and power
+/// limit creator: OCC consumer:
/// mss_utils_to_throttle
///
inline fapi2::ReturnCode databus_util(const fapi2::Target<fapi2::TARGET_TYPE_MCS>& i_target, uint32_t* o_array)
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 07c293462..613ac3570 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
@@ -68,14 +68,14 @@ enum default_power
//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},
+ {4, 0b0000},
+ {8, 0b0001},
+ {16, 0b0010},
+ {32, 0b0011},
+ {64, 0b0100},
{128, 0b0101},
- {256, 0b0111},
- {512, 0b1000},
+ {256, 0b0110},
+ {512, 0b0111},
};
static const std::vector< std::pair<uint8_t , uint8_t> > DIMM_TYPE_MAP =
@@ -94,9 +94,10 @@ static const std::vector< std::pair<uint8_t , uint8_t> > DRAM_GEN_MAP =
static const std::vector <std::pair<uint8_t, uint8_t> > DRAM_WIDTH_MAP =
{
- {fapi2::ENUM_ATTR_EFF_DRAM_WIDTH_X4, 0b00},
- {fapi2::ENUM_ATTR_EFF_DRAM_WIDTH_X8, 0b01},
- {fapi2::ENUM_ATTR_EFF_DRAM_WIDTH_X16, 0b10}
+ {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 =
@@ -111,14 +112,25 @@ static const std::vector< std::pair<uint8_t , uint8_t> > DRAM_DENSITY_MAP =
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 =
{
- {0x802C, 0b00},
- {0x80AD, 0b01},
- {0x80CE, 0b10}
+ //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 =
@@ -155,18 +167,18 @@ enum ATTR_DECODE_INFO
DIMM_TYPE_LEN = 2,
DRAM_WIDTH_START = 8,
- DRAM_WIDTH_LEN = 2,
+ DRAM_WIDTH_LEN = 3,
- DRAM_DENSITY_START = 10,
+ DRAM_DENSITY_START = 11,
DRAM_DENSITY_LEN = 3,
- DRAM_STACK_TYPE_START = 13,
+ DRAM_STACK_TYPE_START = 14,
DRAM_STACK_TYPE_LEN = 2,
- DRAM_MFGID_START = 15,
- DRAM_MFGID_LEN = 2,
+ DRAM_MFGID_START = 16,
+ DRAM_MFGID_LEN = 3,
- DIMMS_PER_PORT_START = 17,
+ DIMMS_PER_PORT_START = 19,
DIMMS_PER_PORT_LEN = 2,
};
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 031c846b1..d75125d61 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
@@ -67,7 +67,6 @@ throttle::throttle( const fapi2::Target<fapi2::TARGET_TYPE_MCA>& i_mca, fapi2::R
//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) );
-
FAPI_TRY( mrw_dimm_power_curve_percent_uplift(iv_power_uplift) );
FAPI_TRY( mrw_dimm_power_curve_percent_uplift_idle(iv_power_uplift_idle) );
FAPI_TRY( dimm_thermal_limit( iv_target, iv_dimm_thermal_limit) );
@@ -92,8 +91,9 @@ throttle::throttle( const fapi2::Target<fapi2::TARGET_TYPE_MCA>& i_mca, fapi2::R
iv_runtime_n_slot,
iv_runtime_n_port);
- FAPI_INF("The dimm power limit is %d, port power limit is %d, dram clocks are %d, dimm power curve slopes are %d %d,",
+ 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],
@@ -164,8 +164,21 @@ fapi2::ReturnCode throttle::power_regulator_throttles ()
FAPI_INF("POWER calc util port is %f", l_calc_util_port);
- //Calculate the N throttles
- iv_n_port = power_thermal::throttled_cmds(l_calc_util_port, iv_m_clocks);
+ //Calculate the new slot values and the max power value for the port
+ calc_slots_and_power( 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
+///
+void 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;
@@ -174,10 +187,7 @@ fapi2::ReturnCode throttle::power_regulator_throttles ()
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
- iv_calc_port_maxpower = calc_power_from_n(iv_n_port);
-
-fapi_try_exit:
- return fapi2::current_err;
+ iv_calc_port_maxpower = calc_power_from_n(iv_n_slot, iv_n_port);
}
///
@@ -204,7 +214,7 @@ fapi2::ReturnCode throttle::thermal_throttles ()
l_dimm_power_max);
//Let's calculate the N throttle for each DIMM
- for ( const auto& l_dimm : find_targets<TARGET_TYPE_DIMM>(iv_target) )
+ for ( const auto& l_dimm : mss::find_targets<TARGET_TYPE_DIMM>(iv_target) )
{
uint8_t l_pos = mss::index(l_dimm);
//Calculate the power curve taking the thermal limit into account
@@ -237,11 +247,13 @@ fapi2::ReturnCode throttle::thermal_throttles ()
//Taking the min of the SLOT * (# of dimms on the port) and that maximum allowed port throttle (iv_runtime_port)
//So it's the min of either to actually utilized to the maximum allowed utilization
iv_n_port = std::min(iv_runtime_n_port, 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
- iv_calc_port_maxpower = calc_power_from_n(iv_n_port);
+ iv_calc_port_maxpower = calc_power_from_n(iv_n_slot, iv_n_port);
return fapi2::FAPI2_RC_SUCCESS;
fapi_try_exit:
@@ -249,8 +261,6 @@ fapi_try_exit:
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
@@ -379,21 +389,24 @@ void throttle::calc_util_usage(const uint32_t i_slope,
///
///@brief calculated the output power estimate from the calculated N throttle
-///@param[in] i_n_throttle is the throtte N (address operations) that the power (cW) should be calculated fro
+///@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
///@return the power calculated from the uint
///
-uint32_t throttle::calc_power_from_n (const uint16_t i_n_throttle)
+uint32_t throttle::calc_power_from_n (const uint16_t i_n_slot, const uint16_t i_n_port)
{
- double l_calc_util;
+ double l_calc_util_port;
+ double l_calc_util_slot;
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;
- l_calc_util = calc_util_from_throttles(i_n_throttle, iv_m_clocks);
+ l_calc_util_slot = calc_util_from_throttles(i_n_slot, iv_m_clocks);
+ l_calc_util_port = calc_util_from_throttles(i_n_port, iv_m_clocks);
- //Now do everything as port stuff
- calc_databus(l_calc_util, l_calc_databus_port_max);
+ //Determine the utilization for each DIMM that will maximize the port power
+ calc_split_util(l_calc_util_slot, l_calc_util_port, l_calc_databus_port_max);
calc_port_power(l_calc_databus_port_idle,
l_calc_databus_port_max,
@@ -411,7 +424,7 @@ uint32_t throttle::calc_power_from_n (const uint16_t i_n_throttle)
/// @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,
+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);
@@ -448,6 +461,72 @@ fapi_try_exit:
}
///
+/// @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])
+{
+ 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)
+ .set_MCA_TARGET(iv_target),
+ "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 auto 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 & 0x1)] = (l_count_dimms == 2) ? (i_util_port - o_util_dimm_max[l_high_pos]) : 0;
+ }
+
+ else
+ {
+ //If only 1 dimm, i_util_port == i_util_slot
+ //If 2 dimms, 2*i_util_slot <= i_util_pot
+ //Either way, limit util 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_MCA_TARGET(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
@@ -463,7 +542,7 @@ fapi2::ReturnCode restore_runtime_throttles( const fapi2::Target<fapi2::TARGET_T
//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 : find_targets<TARGET_TYPE_MCA>(i_target))
+ for (const auto& l_mca : mss::find_targets<TARGET_TYPE_MCA>(i_target))
{
const auto l_pos = mss::index(l_mca);
@@ -499,7 +578,7 @@ fapi2::ReturnCode update_runtime_throttles( const std::vector< fapi2::Target<fap
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 : find_targets<TARGET_TYPE_MCA>(l_mcs))
+ 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
@@ -517,5 +596,156 @@ 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
+///
+fapi2::ReturnCode set_runtime_m_and_watt_limit( const std::vector< fapi2::Target<fapi2::TARGET_TYPE_MCS> >& i_targets )
+{
+ uint32_t l_m_clocks;
+ uint32_t l_vmem_power_limit_dimm = 0;
+ uint8_t l_max_dimms = 0;
+
+ uint32_t l_count_dimms_vec = 0;
+ uint32_t l_watt_target = 0;
+
+ FAPI_TRY( mrw_vmem_regulator_power_limit_per_dimm_ddr4(l_vmem_power_limit_dimm));
+ FAPI_TRY( mrw_mem_m_dram_clocks(l_m_clocks));
+ FAPI_TRY( mrw_max_number_dimms_possible_per_vmem_regulator(l_max_dimms));
+
+ for (const auto& l_mcs : i_targets)
+ {
+ l_count_dimms_vec += mss::count_dimm(l_mcs);
+ }
+
+ //Now calculate the watt target
+ //Calculate max power available / number of dimms configured on the VDDR rail
+ l_watt_target = (l_vmem_power_limit_dimm * l_max_dimms) / l_count_dimms_vec;
+
+ FAPI_INF("Calculated ATTR_MSS_MEM_WATT_TARGET is %d, power_limit dimm is %d, max_dimms is %d, count dimms on vector is %d",
+ l_watt_target,
+ l_vmem_power_limit_dimm,
+ l_max_dimms,
+ l_count_dimms_vec);
+
+ for (const auto& l_mcs : i_targets)
+ {
+ uint32_t l_watt_temp [PORTS_PER_MCS][MAX_DIMM_PER_PORT] = {{l_watt_target, l_watt_target}, {l_watt_target, l_watt_target}};
+ uint32_t l_temp [PORTS_PER_MCS] = {l_m_clocks, l_m_clocks};
+
+ FAPI_TRY( FAPI_ATTR_SET( fapi2::ATTR_MSS_RUNTIME_MEM_M_DRAM_CLOCKS, l_mcs, l_temp));
+ FAPI_TRY( FAPI_ATTR_SET( fapi2::ATTR_MSS_MEM_WATT_TARGET, l_mcs, l_watt_temp));
+ }
+
+ return fapi2::FAPI2_RC_SUCCESS;
+fapi_try_exit:
+ FAPI_ERR("Error setting power_thermal attributes MSS_WATT_TARGET");
+ 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
+/// @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)
+{
+ //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))
+ {
+ 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", 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))
+ {
+ const auto l_pos = mss::index(l_mca);
+
+ 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;
+ auto l_dummy = mss::power_thermal::throttle(l_mca, l_rc);
+ FAPI_TRY(l_rc, "Failed creating a throttle object in equalize_throttles");
+
+ //Only calculate the power for ports that have dimms installed
+ l_fin_power[l_pos] = (mss::count_dimm(l_mca) != 0 ) ?
+ l_dummy.calc_power_from_n(l_fin_slot[l_pos], l_fin_port[l_pos]) : 0;
+ FAPI_INF("Calculated power is %d, limit is %d", l_fin_power[l_pos], l_dummy.iv_port_power_limit);
+
+ //If error with calculating port power, wrong watt target was passed in
+ //This shouldn't be tripped due to code structure
+ //returns an error but doesn't deconfigure anything. Calling function can log if it wants to
+ //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_dummy.iv_port_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_dummy.iv_port_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 is %d",
+ mss::c_str(l_mca),
+ l_fin_power[l_pos],
+ l_dummy.iv_port_power_limit);
+ }
+ }
+
+ //Even if there's an error, still calculate and set the throttles. OCC will set to safemode if error, and
+ // 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 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 876e277a3..21fa4c232 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
@@ -53,6 +53,7 @@ enum throttle_const : size_t
//MIN_UTIL and IDLE_UTIL are in c%
MIN_UTIL = 100,
IDLE_UTIL = 0,
+ MIN_THROTTLE = 1,
};
///
/// @class throttle
@@ -172,11 +173,18 @@ class throttle
const uint32_t i_power_limit,
double& o_util);
///
+ /// @brief set iv_n_port, iv_n_slot, iv_calc_port_maxpower
+ /// @param[in] i_util_port pass in the calculated port databus utilization
+ ///
+ void calc_slots_and_power (const double i_util_port);
+
+ ///
///@brief calculated the output power estimate from the calculated N throttle
- ///@param[in] i_n_port is the throtte N (address operations) that the power (cW) is be calculated from
+ ///@param[in] i_n_slot the N throttle per slot
+ ///@param[in] i_n_port the N throttle per port
///@return the power calculated from the uint
///
- uint32_t calc_power_from_n (const uint16_t i_n_port);
+ uint32_t calc_power_from_n (const uint16_t i_n_slot, const uint16_t i_n_port);
///
/// @brief Converts the port maximum databus util to a dimm level based on powerslopes and dimms installed
@@ -188,6 +196,19 @@ class throttle
///
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]);
+
///
/// @brief Calculate ATTR_MSS_CHANNEL_PAIR_MAXPOWER and ATTR_MSS_MEM_THROTTLED_N_COMMANDS_PER_SLOT,
@@ -238,7 +259,8 @@ inline uint32_t throttled_cmds(const uint32_t i_databus_util, const uint32_t i_n
inline double calc_util_from_throttles(const uint16_t i_n_throttles, const uint32_t i_num_dram_clocks)
{
constexpr uint32_t l_multiplier = DRAM_BUS_UTILS * UTIL_CONVERSION;
- return ( (double(i_n_throttles) * l_multiplier) / i_num_dram_clocks);
+ const auto l_temp = (double(i_n_throttles) * l_multiplier) / i_num_dram_clocks;
+ return ( (l_temp == 0) ? MIN_THROTTLE : l_temp);
}
@@ -274,6 +296,20 @@ fapi2::ReturnCode restore_runtime_throttles( const fapi2::Target<fapi2::TARGET_T
///
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
+/// @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);
}//power_thermal
}// mss
diff --git a/src/import/chips/p9/procedures/hwp/memory/lib/utils/find.H b/src/import/chips/p9/procedures/hwp/memory/lib/utils/find.H
index 4bdd38101..ca5e3dbb3 100644
--- a/src/import/chips/p9/procedures/hwp/memory/lib/utils/find.H
+++ b/src/import/chips/p9/procedures/hwp/memory/lib/utils/find.H
@@ -161,6 +161,17 @@ find_targets( const fapi2::Target<fapi2::TARGET_TYPE_MCBIST>& i_target )
}
///
+/// @brief find all the MCS connected to a PROC_CHIP
+/// @param[in] i_target a fapi2::Target PROC_CHIP
+/// @return a vector of fapi2::TARGET_TYPE_MCS
+///
+template<>
+inline std::vector< fapi2::Target<fapi2::TARGET_TYPE_MCS> > find_targets
+( const fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP>& i_target )
+{
+ return i_target.getChildren<fapi2::TARGET_TYPE_MCS>();
+}
+///
/// @brief find all the MCS connected to an MCBIST
/// @param[in] i_target a fapi2::Target MCBIST
/// @return a vector of fapi2::TARGET_TYPE_MCS
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 2b7d43395..86f9b0aea 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
@@ -63,6 +63,7 @@ extern "C"
throttle_type t)
{
FAPI_INF("Start bulk_pwr_throttles");
+ fapi2::ReturnCode l_rc = fapi2::FAPI2_RC_SUCCESS;
//Check for THERMAL
if (t == THERMAL)
@@ -100,8 +101,6 @@ extern "C"
FAPI_TRY(FAPI_ATTR_SET( fapi2::ATTR_MSS_MEM_THROTTLED_N_COMMANDS_PER_SLOT, l_mcs, l_slot));
FAPI_TRY(FAPI_ATTR_SET( fapi2::ATTR_MSS_MEM_THROTTLED_N_COMMANDS_PER_PORT, l_mcs, l_port));
}
-
- //Equalize throttles
}
//else do POWER
else
@@ -140,11 +139,12 @@ extern "C"
FAPI_TRY(FAPI_ATTR_SET( fapi2::ATTR_MSS_MEM_THROTTLED_N_COMMANDS_PER_PORT, l_mcs, l_port));
}
- //Equalize throttles
}
+ //Set all of the throttles to the lowest value per port for performance reasons
+ FAPI_TRY(mss::power_thermal::equalize_throttles(i_targets));
FAPI_INF("End bulk_pwr_throttles");
- return fapi2::FAPI2_RC_SUCCESS;
+ return l_rc;
fapi_try_exit:
FAPI_ERR("Error calculating bulk_pwr_throttles");
diff --git a/src/import/chips/p9/procedures/hwp/memory/p9_mss_bulk_pwr_throttles.H b/src/import/chips/p9/procedures/hwp/memory/p9_mss_bulk_pwr_throttles.H
index f0acad89b..d2c4ed35a 100644
--- a/src/import/chips/p9/procedures/hwp/memory/p9_mss_bulk_pwr_throttles.H
+++ b/src/import/chips/p9/procedures/hwp/memory/p9_mss_bulk_pwr_throttles.H
@@ -39,12 +39,12 @@
#include <fapi2.H>
#include <vector>
typedef fapi2::ReturnCode (*p9_mss_bulk_pwr_throttles_FP_t) (const
- std::vector< fapi2::Target< fapi2::TARGET_TYPE_MCS>>&);
+ std::vector< fapi2::Target< fapi2::TARGET_TYPE_MCS>>&, uint8_t l_throttle);
extern "C"
{
- enum throttle_type : size_t
+ enum throttle_type : uint8_t
{
POWER = 0,
THERMAL = 1,
diff --git a/src/import/chips/p9/procedures/hwp/memory/p9_mss_eff_config.C b/src/import/chips/p9/procedures/hwp/memory/p9_mss_eff_config.C
index 2e755c647..57f829f3b 100644
--- a/src/import/chips/p9/procedures/hwp/memory/p9_mss_eff_config.C
+++ b/src/import/chips/p9/procedures/hwp/memory/p9_mss_eff_config.C
@@ -184,19 +184,6 @@ fapi2::ReturnCode p9_mss_eff_config( const fapi2::Target<fapi2::TARGET_TYPE_MCS>
}// dimm
- // Hard-coded RIT protect attribute set (currently not taken account in eff_config)
- {
- uint32_t l_m_dram_clocks[mss::PORTS_PER_MCS] = {0x200, 0x200};
- FAPI_TRY( FAPI_ATTR_SET( fapi2::ATTR_MSS_RUNTIME_MEM_M_DRAM_CLOCKS, i_target, l_m_dram_clocks ) );
- }
- //TODO RTC:160060 verify attributes are needed, best place to put them, and correct values
- // TK hard coded for now, should change at some point. Most of these are set in eff_config_thermal
- {
- uint32_t l_mem_watt_target[mss::PORTS_PER_MCS][mss::MAX_DIMM_PER_PORT] = {{0x640, 0x640}, {0x640, 0x640}};
- FAPI_TRY( FAPI_ATTR_SET( fapi2::ATTR_MSS_MEM_WATT_TARGET, i_target,
- l_mem_watt_target ) );
- }
-
{
uint16_t l_cal_step[mss::PORTS_PER_MCS] = {0xFAC0, 0xFAC0};
FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_MSS_CAL_STEP_ENABLE, i_target, l_cal_step) );
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 11337674a..7c9bcf5ce 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
@@ -59,7 +59,7 @@ extern "C"
uint16_t l_total_slope [mss::PORTS_PER_MCS][mss::MAX_DIMM_PER_PORT] = {};
uint16_t l_total_int [mss::PORTS_PER_MCS][mss::MAX_DIMM_PER_PORT] = {};
uint32_t l_thermal_power [mss::PORTS_PER_MCS][mss::MAX_DIMM_PER_PORT] = {};
-
+ fapi2::ReturnCode l_rc;
//Gotta convert into fapi2::buffers. Not very elegant
//Do it here or in the encode and decode functions
//Not that pretty :(
@@ -74,10 +74,13 @@ extern "C"
FAPI_TRY( mss::mrw_pwr_slope (l_tslope.data() ));
FAPI_TRY( mss::mrw_pwr_intercept (l_tintercept.data()) );
FAPI_TRY( mss::mrw_thermal_memory_power_limit (l_tthermal_power_limit.data()) );
+ FAPI_TRY( mss::power_thermal::set_runtime_m_and_watt_limit(i_targets));
+
+ for (size_t i = 0; i < mss::power_thermal::SIZE_OF_POWER_CURVES_ATTRS; ++i)
{
- for (auto l_tslope_iter = l_tslope.begin(); l_tslope_iter != l_tslope.end(); ++l_tslope_iter)
+ for (const auto l_cur : l_tslope)
{
- auto l_slope_buf = fapi2::buffer<uint64_t> (*l_tslope_iter);
+ fapi2::buffer<uint64_t> l_slope_buf = l_cur;
if (l_slope_buf != 0)
{
@@ -85,9 +88,9 @@ extern "C"
}
}
- for (auto l_tintercept_iter = l_tintercept.begin(); l_tintercept_iter != l_tintercept.end(); ++l_tintercept_iter)
+ for (auto l_cur : l_tintercept)
{
- auto l_intercept_buf = fapi2::buffer<uint64_t> (*l_tintercept_iter);
+ fapi2::buffer<uint64_t> l_intercept_buf = l_cur;
if (l_intercept_buf != 0)
{
@@ -95,11 +98,9 @@ extern "C"
}
}
- for (auto l_tthermal_iter = l_tthermal_power_limit.begin();
- l_tthermal_iter != l_tthermal_power_limit.end();
- ++l_tthermal_iter)
+ for (auto l_cur : l_tthermal_power_limit)
{
- auto l_tthermal_buf = fapi2::buffer<uint64_t> (*l_tthermal_iter);
+ fapi2::buffer<uint64_t> l_tthermal_buf = l_cur;
if (l_tthermal_buf != 0)
{
@@ -148,7 +149,8 @@ extern "C"
FAPI_INF("Starting bulk_pwr");
//get the thermal limits, done per dimm and set to worst case for the slot and port throttles
//Bulk_pwr sets the general, all purpose ATTR_MSS_MEM_THROTTLED_N_COMMANDS_PER_SLOT, _PER_PORT, and MAXPOWER ATTRs
- FAPI_TRY( p9_mss_bulk_pwr_throttles(i_targets, POWER));
+ FAPI_EXEC_HWP(l_rc, p9_mss_bulk_pwr_throttles, i_targets, POWER);
+ FAPI_TRY(l_rc);
//Set runtime throttles to worst case between ATTR_MSS_MEM_THROTTLED_N_COMMANDS_PER_SLOT
//and ATTR_MSS_MEM_RUNTIME_THROTTLED_N_COMMANDS_PER_SLOT and the _PORT equivalents also
@@ -183,7 +185,8 @@ extern "C"
}
//Run thermal throttles with the VDDR+VPP power curves
- FAPI_TRY( p9_mss_bulk_pwr_throttles(i_targets, THERMAL));
+ FAPI_EXEC_HWP(l_rc, p9_mss_bulk_pwr_throttles, i_targets, THERMAL);
+ FAPI_TRY(l_rc);
//Update everything to worst case
FAPI_TRY( mss::power_thermal::update_runtime_throttles (i_targets));
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 cbf1fe988..8ab0ace19 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
@@ -48,6 +48,7 @@
#include <lib/utils/conversions.H>
#include <lib/power_thermal/throttle.H>
#include <lib/mss_attribute_accessors.H>
+#include <lib/utils/count_dimm.H>
using fapi2::TARGET_TYPE_MCS;
using fapi2::TARGET_TYPE_MCA;
@@ -57,8 +58,8 @@ extern "C"
{
///
-/// @brief Sets number commands allowed within a given data bus utilization.
-/// @param[in] i_targets vector of MCS on the same VDDR domain
+/// @brief Sets number commands allowed within a given port databus utilization.
+/// @param[in] i_targets vector of MCS to set throttle attributes on
/// @return FAPI2_RC_SUCCESS iff ok
/// @note throttle_per_slot will be equalized so all throttles coming out will be equal to worst case
///
@@ -66,22 +67,33 @@ extern "C"
{
for( const auto& l_mcs : i_targets )
{
- uint32_t l_databus_util [mss::PORTS_PER_MCS];
+ uint32_t l_input_databus_util [mss::PORTS_PER_MCS] = {};
+ uint32_t l_max_databus_util = {};
uint32_t l_dram_clocks = 0;
- uint16_t l_throttled_cmds_port[mss::PORTS_PER_MCS];
- uint16_t l_throttled_cmds_slot[mss::PORTS_PER_MCS];
- uint32_t l_max_power[mss::PORTS_PER_MCS];
+ uint16_t l_n_port[mss::PORTS_PER_MCS] = {};
+ uint16_t l_n_slot[mss::PORTS_PER_MCS] = {};
+ uint32_t l_max_power[mss::PORTS_PER_MCS] = {};
FAPI_TRY( mss::mrw_mem_m_dram_clocks(l_dram_clocks) );
+
//Util attribute set by OCC
- FAPI_TRY( mss::databus_util(l_mcs, l_databus_util) );
+ FAPI_TRY( mss::databus_util(l_mcs, l_input_databus_util) );
+ FAPI_TRY( mss::mrw_max_dram_databus_util(l_max_databus_util));
+
+ FAPI_INF("Input databus utilization is %d and %d", l_input_databus_util[0], l_input_databus_util[1]);
for( const auto& l_mca : mss::find_targets<TARGET_TYPE_MCA>(l_mcs) )
{
const auto l_port_num = mss::index( l_mca );
+
+ //make sure 0 < input_utilization <= max_utilization
+ uint32_t l_databus_util = ( l_input_databus_util[l_port_num] != 0) ?
+ std::min(l_input_databus_util[l_port_num], l_max_databus_util) : mss::power_thermal::MIN_UTIL;
+
//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);
FAPI_TRY(l_rc, "Error calculating mss::power_thermal::throttle constructor in p9_mss_utils_to_throttles");
@@ -89,17 +101,16 @@ extern "C"
l_dram_clocks,
l_databus_util);
- //Calculate programmable N address operations within M dram clock window
- l_throttled_cmds_port[l_port_num] = mss::power_thermal::throttled_cmds(l_databus_util[l_port_num],
- l_dram_clocks );
- l_throttled_cmds_slot[l_port_num] = l_throttled_cmds_port[l_port_num];
- //Calculate the port power needed to reach the calculated N value
- l_max_power[l_port_num] = l_throttle.calc_power_from_n(l_throttled_cmds_slot[l_port_num]);
+ l_throttle.calc_slots_and_power(l_databus_util);
FAPI_INF( "Calculated N commands per port [%d] = %d commands, maxpower is %d",
l_port_num,
- l_throttled_cmds_port[l_port_num],
- l_max_power[l_port_num]);
+ l_throttle.iv_n_port,
+ l_throttle.iv_calc_port_maxpower);
+
+ l_n_slot[l_port_num] = l_throttle.iv_n_slot;
+ l_n_port[l_port_num] = l_throttle.iv_n_port;
+ l_max_power[l_port_num] = l_throttle.iv_calc_port_maxpower;
}// end for
FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_MSS_PORT_MAXPOWER,
@@ -107,12 +118,15 @@ extern "C"
l_max_power) );
FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_MSS_MEM_THROTTLED_N_COMMANDS_PER_SLOT,
l_mcs,
- l_throttled_cmds_slot) );
+ l_n_slot) );
FAPI_TRY( FAPI_ATTR_SET(fapi2::ATTR_MSS_MEM_THROTTLED_N_COMMANDS_PER_PORT,
l_mcs,
- l_throttled_cmds_port) );
+ l_n_port) );
}
+ //equalize throttles to prevent variable performance
+ FAPI_TRY( mss::power_thermal::equalize_throttles (i_targets));
+
fapi_try_exit:
return fapi2::current_err;
}
diff --git a/src/import/chips/p9/procedures/xml/attribute_info/memory_mcs_attributes.xml b/src/import/chips/p9/procedures/xml/attribute_info/memory_mcs_attributes.xml
index ec12da982..62be56c0e 100644
--- a/src/import/chips/p9/procedures/xml/attribute_info/memory_mcs_attributes.xml
+++ b/src/import/chips/p9/procedures/xml/attribute_info/memory_mcs_attributes.xml
@@ -1198,6 +1198,19 @@
</attribute>
<attribute>
+ <id>ATTR_MSS_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/>
+ <mssAccessorName>mem_port_fail_throttle</mssAccessorName>
+ </attribute>
+
+ <attribute>
<id>ATTR_MSS_MEM_M_DRAM_CLOCKS</id>
<targetType>TARGET_TYPE_MCS</targetType>
<description>
@@ -1332,7 +1345,7 @@
<id>ATTR_MSS_DATABUS_UTIL</id>
<targetType>TARGET_TYPE_MCS</targetType>
<description>
- Databus utilization limit used to calculate memory throttles and power limit
+ Databus utilization per port limit used to calculate memory throttles and power limit
creator: OCC
consumer: mss_utils_to_throttle
</description>
diff --git a/src/import/chips/p9/procedures/xml/error_info/p9_memory_mss_eff_config.xml b/src/import/chips/p9/procedures/xml/error_info/p9_memory_mss_eff_config.xml
index 7007f8c39..07def3931 100644
--- a/src/import/chips/p9/procedures/xml/error_info/p9_memory_mss_eff_config.xml
+++ b/src/import/chips/p9/procedures/xml/error_info/p9_memory_mss_eff_config.xml
@@ -177,4 +177,67 @@
</deconfigure>
</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>
+ <childNumber>EX_NUMBER_IN_ERROR</childNumber>
+ </childTargets>
+ <priority>MEDIUM</priority>
+ </callout>
+ <deconfigure>
+ <childTargets>
+ <parent>MCA_TARGET</parent>
+ <childType>TARGET_TYPE_DIMM</childType>
+ <childNumber>EX_NUMBER_IN_ERROR</childNumber>
+ </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>
+ <deconfigure>
+ <target>MCA_TARGET</target>
+ </deconfigure>
+ </hwpError>
+
+ <hwpError>
+ <rc>RC_MSS_SPLIT_UTIL_CALC_ERROR</rc>
+ <description>
+ Error when splitting up the memory port's utilization
+ </description>
+ <ffdc>MAX_TOTAL_UTIL</ffdc>
+ <ffdc>DIMM_COUNT</ffdc>
+ <ffdc>SLOT_UTIL</ffdc>
+ <ffdc>PORT_UTIL</ffdc>
+ <callout>
+ <procedure>CODE</procedure>
+ <priority>HIGH</priority>
+ </callout>
+ <deconfigure>
+ <target>MCA_TARGET</target>
+ </deconfigure>
+ </hwpError>
+
+
</hwpErrors>
OpenPOWER on IntegriCloud