diff options
Diffstat (limited to 'src/import/chips/p9/procedures')
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> |