diff options
author | Thi Tran <thi@us.ibm.com> | 2014-11-13 13:46:21 -0600 |
---|---|---|
committer | A. Patrick Williams III <iawillia@us.ibm.com> | 2014-12-13 10:47:21 -0600 |
commit | 1d730ba9e2d823e9690e6dcae168b0ccae85a948 (patch) | |
tree | 10e10e15879c6f072d31dfb3ad23fc1c747300f0 /src/usr/hwpf/hwp/mc_config | |
parent | 597e79a3055b155af20d6d64ade2fd2e95699954 (diff) | |
download | talos-hostboot-1d730ba9e2d823e9690e6dcae168b0ccae85a948.tar.gz talos-hostboot-1d730ba9e2d823e9690e6dcae168b0ccae85a948.zip |
SW284608: HWP Memory Throttle Calculation Efficiency and ISDIMM Throttle Support
CQ:SW284608
Change-Id: Ief2d91781ced462009c499564a8ffcbad5da8487
Reviewed-on: http://gfw160.aus.stglabs.ibm.com:8080/gerrit/14446
Reviewed-by: Michael D. Pardeik <pardeik@us.ibm.com>
Reviewed-by: Daniel M. Crowell <dcrowell@us.ibm.com>
Reviewed-by: Thi N. Tran <thi@us.ibm.com>
Tested-by: Thi N. Tran <thi@us.ibm.com>
Reviewed-on: http://gfw160.aus.stglabs.ibm.com:8080/gerrit/14471
Tested-by: Jenkins Server
Reviewed-by: A. Patrick Williams III <iawillia@us.ibm.com>
Diffstat (limited to 'src/usr/hwpf/hwp/mc_config')
-rw-r--r-- | src/usr/hwpf/hwp/mc_config/mss_eff_config/mss_bulk_pwr_throttles.C | 422 | ||||
-rw-r--r-- | src/usr/hwpf/hwp/mc_config/mss_eff_config/mss_eff_config_thermal.C | 1602 |
2 files changed, 325 insertions, 1699 deletions
diff --git a/src/usr/hwpf/hwp/mc_config/mss_eff_config/mss_bulk_pwr_throttles.C b/src/usr/hwpf/hwp/mc_config/mss_eff_config/mss_bulk_pwr_throttles.C index 3cf18b247..21668b90e 100644 --- a/src/usr/hwpf/hwp/mc_config/mss_eff_config/mss_bulk_pwr_throttles.C +++ b/src/usr/hwpf/hwp/mc_config/mss_eff_config/mss_bulk_pwr_throttles.C @@ -22,7 +22,7 @@ /* permissions and limitations under the License. */ /* */ /* IBM_PROLOG_END_TAG */ -// $Id: mss_bulk_pwr_throttles.C,v 1.22 2014/06/02 13:10:53 pardeik Exp $ +// $Id: mss_bulk_pwr_throttles.C,v 1.28 2014/12/01 19:07:07 pardeik Exp $ // $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/ // centaur/working/procedures/ipl/fapi/mss_bulk_pwr_throttles.C,v $ //------------------------------------------------------------------------------ @@ -73,6 +73,24 @@ //------------------------------------------------------------------------------ // Version:| Author: | Date: | Comment: //---------|----------|---------|----------------------------------------------- +// 1.28 | pardeik |01-DEC-14| Gerrit review updates +// | | | changed MAX_UTIL to max_util +// | | | changed MIN_UTIL const to min_util float +// | | | changed IDLE_UTIL const to idle_util float +// 1.27 | pardeik |13-NOV-14| initialize l_channel_power_intercept and +// | | | l_channel_power_slope to zero to prevent +// | | | compile errors +// 1.26 | pardeik |05-NOV-14| removed strings in trace statements +// | | | changed FAPI_IMP to FAPI_INF +// 1.25 | pardeik |31-OCT-14| change ISDIMM_MEMORY_THROTTLE_PERCENT to 65 +// 1.24 | pardeik |31-OCT-14| fixed equation using ISDIMM_MEMORY_THROTTLE_PERCENT +// | | | use power instead of utilization for error check +// | | | RC_MSS_NOT_ENOUGH_AVAILABLE_DIMM_POWER +// 1.23 | pardeik |27-OCT-14| Change to not call mss_power_to_throttle_calc +// | | | Make throttle determination more efficient +// | | | Non Custom DIMMs use hardcoded values and do +// | | | not use power curves for these +// | | | Remove mss_throttle_to_power.H include // 1.22 | pardeik |21-MAY-14| Removed section that adjusts power limit // | | | (was not getting correct throttle values // | | | to have channel pair power be under limit) @@ -138,7 +156,6 @@ // My Includes //------------------------------------------------------------------------------ #include <mss_bulk_pwr_throttles.H> -#include <mss_throttle_to_power.H> //------------------------------------------------------------------------------ // Includes @@ -158,7 +175,6 @@ extern "C" { const fapi::Target & i_target_mba ); - //------------------------------------------------------------------------------ // @brief mss_bulk_pwr_throttles(): This function determines the throttle values // from a MBA channel pair power limit @@ -171,45 +187,78 @@ extern "C" { fapi::ReturnCode mss_bulk_pwr_throttles(const fapi::Target & i_target_mba ) { - fapi::ReturnCode rc; - - const char* procedure_name = "mss_bulk_pwr_throttles"; + fapi::ReturnCode rc = fapi::FAPI_RC_SUCCESS; - FAPI_IMP("*** Running %s on %s ***", procedure_name, - i_target_mba.toEcmdString()); + FAPI_INF("*** Running mss_bulk_pwr_throttles ***"); -// min utilization (percent of max) allowed for floor - const float MIN_UTIL = 1; + const uint8_t MAX_NUM_PORTS = 2; + const uint8_t MAX_NUM_DIMMS = 2; + float idle_util = 0; // in percent + float min_util = 1; // in percent +// These are the constants to use for ISDIMM power/throttle support +// Note that these are hardcoded and ISDIMMs will not use power curves +// No Throttling if available power is >= ISDIMM_MAX_DIMM_POWER +// Throttle when ISDIMM_MIN_DIMM_POWER <= available power <= ATTR_MSS_MEM_WATT_TARGET +// Throttle value will be maximum throttle * ISDIMM_MEMORY_THROTTLE_PERCENT + const uint32_t ISDIMM_MAX_DIMM_POWER = 1200; // cW, max ISDIMM power for no throttling + const uint32_t ISDIMM_MIN_DIMM_POWER = 800; // cW, min ISDIMM power for throttling + const uint8_t ISDIMM_MEMORY_THROTTLE_PERCENT = 65; // percent, throttle impact when limit is between min and max power. A value of 0 would be for no throttle impact. - uint32_t channel_pair_watt_target; - uint32_t throttle_n_per_mba; - uint32_t throttle_n_per_chip; - uint32_t throttle_d; - bool not_enough_available_power; - bool channel_pair_throttle_done; - float channel_pair_power; - uint8_t custom_dimm; + uint32_t l_power_slope_array[MAX_NUM_PORTS][MAX_NUM_DIMMS]; + uint32_t l_power_int_array[MAX_NUM_PORTS][MAX_NUM_DIMMS]; + uint8_t l_dimm_ranks_array[MAX_NUM_PORTS][MAX_NUM_DIMMS]; + uint8_t l_port; + uint8_t l_dimm; + float l_dimm_power_array_idle[MAX_NUM_PORTS][MAX_NUM_DIMMS]; + float l_dimm_power_array_max[MAX_NUM_PORTS][MAX_NUM_DIMMS]; + float l_channel_power_array_idle[MAX_NUM_PORTS]; + float l_channel_power_array_max[MAX_NUM_PORTS]; + uint8_t l_power_curve_percent_uplift; + uint8_t l_power_curve_percent_uplift_idle; + uint32_t l_max_dram_databus_util; + uint8_t l_num_mba_with_dimms; + uint8_t l_custom_dimm; + fapi::Target l_target_chip; + std::vector<fapi::Target> l_target_mba_array; + std::vector<fapi::Target> l_target_dimm_array; + uint8_t l_mba_index; + uint32_t l_throttle_d; + float l_channel_pair_power_idle; + float l_channel_pair_power_max; + uint32_t l_channel_pair_watt_target; + float l_utilization; + uint32_t l_number_of_dimms; + float l_channel_power_slope = 0; + float l_channel_power_intercept = 0; + uint32_t l_throttle_n_per_mba; + uint32_t l_throttle_n_per_chip; + uint32_t channel_pair_power; uint32_t runtime_throttle_n_per_mba; uint32_t runtime_throttle_n_per_chip; - uint32_t runtime_throttle_d; -// Get input attributes - rc = FAPI_ATTR_GET(ATTR_EFF_CUSTOM_DIMM, &i_target_mba, custom_dimm); +// get input attributes + rc = FAPI_ATTR_GET(ATTR_EFF_CUSTOM_DIMM, &i_target_mba, l_custom_dimm); if (rc) { FAPI_ERR("Error getting attribute ATTR_EFF_CUSTOM_DIMM"); return rc; } - rc = FAPI_ATTR_GET(ATTR_MSS_MEM_WATT_TARGET, - &i_target_mba, channel_pair_watt_target); + rc = FAPI_ATTR_GET(ATTR_MRW_MAX_DRAM_DATABUS_UTIL, + NULL, l_max_dram_databus_util); if (rc) { - FAPI_ERR("Error getting attribute ATTR_MSS_MEM_WATT_TARGET"); + FAPI_ERR("Error getting attribute ATTR_MRW_MAX_DRAM_DATABUS_UTIL"); return rc; } - rc = FAPI_ATTR_GET(ATTR_MRW_MEM_THROTTLE_DENOMINATOR, NULL, throttle_d); + rc = FAPI_ATTR_GET(ATTR_MRW_MEM_THROTTLE_DENOMINATOR, NULL, l_throttle_d); if (rc) { FAPI_ERR("Error getting attribute ATTR_MRW_MEM_THROTTLE_DENOMINATOR"); return rc; } + rc = FAPI_ATTR_GET(ATTR_MSS_MEM_WATT_TARGET, + &i_target_mba, l_channel_pair_watt_target); + if (rc) { + FAPI_ERR("Error getting attribute ATTR_MSS_MEM_WATT_TARGET"); + return rc; + } rc = FAPI_ATTR_GET(ATTR_MSS_RUNTIME_MEM_THROTTLE_NUMERATOR_PER_MBA, &i_target_mba, runtime_throttle_n_per_mba); if (rc) { @@ -222,148 +271,287 @@ extern "C" { FAPI_ERR("Error getting attribute ATTR_MSS_RUNTIME_MEM_THROTTLE_NUMERATOR_PER_CHIP"); return rc; } - rc = FAPI_ATTR_GET(ATTR_MSS_RUNTIME_MEM_THROTTLE_DENOMINATOR, - &i_target_mba, runtime_throttle_d); - if (rc) { - FAPI_ERR("Error getting attribute ATTR_MSS_RUNTIME_MEM_THROTTLE_DENOMINATOR"); - return rc; - } +// other attributes for custom dimms to get + if (l_custom_dimm == fapi::ENUM_ATTR_EFF_CUSTOM_DIMM_YES) + { + rc = FAPI_ATTR_GET(ATTR_MRW_DIMM_POWER_CURVE_PERCENT_UPLIFT, + NULL, l_power_curve_percent_uplift); + if (rc) { + FAPI_ERR("Error getting attribute ATTR_MRW_DIMM_POWER_CURVE_PERCENT_UPLIFT"); + return rc; + } + rc = FAPI_ATTR_GET(ATTR_MRW_DIMM_POWER_CURVE_PERCENT_UPLIFT_IDLE, + NULL, l_power_curve_percent_uplift_idle); + if (rc) { + FAPI_ERR("Error getting attribute ATTR_MRW_DIMM_POWER_CURVE_PERCENT_UPLIFT_IDLE"); + return rc; + } + rc = FAPI_ATTR_GET(ATTR_MSS_POWER_SLOPE, + &i_target_mba, l_power_slope_array); + if (rc) { + FAPI_ERR("Error getting attribute ATTR_MSS_POWER_SLOPE"); + return rc; + } + rc = FAPI_ATTR_GET(ATTR_MSS_POWER_INT, + &i_target_mba, l_power_int_array); + if (rc) { + FAPI_ERR("Error getting attribute ATTR_MSS_POWER_INT"); + return rc; + } + rc = FAPI_ATTR_GET(ATTR_EFF_NUM_RANKS_PER_DIMM, + &i_target_mba, l_dimm_ranks_array); + if (rc) { + FAPI_ERR("Error getting attribute ATTR_EFF_NUM_RANKS_PER_DIMM"); + return rc; + } + } -//------------------------------------------------------------------------------ -// THROTTLE SECTION -//------------------------------------------------------------------------------ +// Maximum theoretical data bus utilization (percent of max) (for ceiling) +// Comes from MRW value in c% - convert to % + float max_util = (float) l_max_dram_databus_util / 100; -// Determine if the channel pair power for this MBA is over the limit when the -// runtime memory throttle settings are used -// If not over the limit, then use the runtime throttle settings (defined in -// mss_eff_config_thermal) -// If over limit, then increase throttle value until it is at or below limit -// If unable to get power below limit, then call out an error - -// Start with the runtime throttle settings since we may have a thermal/power limit - throttle_n_per_mba = runtime_throttle_n_per_mba; - throttle_n_per_chip = runtime_throttle_n_per_chip; - -// calculate power and change throttle values in this while loop until limit has -// been satisfied or throttles have reached the minimum limit - not_enough_available_power = false; - channel_pair_throttle_done = false; - while (channel_pair_throttle_done == false) +// determine the dimm power +// For custom dimms, use the VPD power curve data + if (l_custom_dimm == fapi::ENUM_ATTR_EFF_CUSTOM_DIMM_YES) { - rc = mss_throttle_to_power_calc( - i_target_mba, - throttle_n_per_mba, - throttle_n_per_chip, - throttle_d, - channel_pair_power - ); - if (rc) - { - FAPI_ERR("Error (0x%x) calling mss_throttle_to_power_calc", static_cast<uint32_t>(rc)); +// get number of mba's with dimms +// Get Centaur target for the given MBA + rc = fapiGetParentChip(i_target_mba, l_target_chip); + if (rc) { + FAPI_ERR("Error calling fapiGetParentChip"); return rc; } +// Get MBA targets from the parent chip centaur + rc = fapiGetChildChiplets(l_target_chip, + fapi::TARGET_TYPE_MBA_CHIPLET, + l_target_mba_array, + fapi::TARGET_STATE_PRESENT); + if (rc) { + FAPI_ERR("Error calling fapiGetChildChiplets"); + return rc; + } + l_num_mba_with_dimms = 0; + for (l_mba_index=0; l_mba_index < l_target_mba_array.size(); l_mba_index++) + { + rc = fapiGetAssociatedDimms(l_target_mba_array[l_mba_index], + l_target_dimm_array, + fapi::TARGET_STATE_PRESENT); + if (rc) { + FAPI_ERR("Error calling fapiGetAssociatedDimms"); + return rc; + } + if (l_target_dimm_array.size() > 0) + { + l_num_mba_with_dimms++; + } + } -// compare channel pair power to mss_watt_target for channel and decrease -// throttles if it is above this limit -// throttle decrease will decrement throttle numerator by one -// and recalculate power until utilization (N/M) reaches a lower limit - - if (channel_pair_power > channel_pair_watt_target) +// add up the power from all dimms for this MBA (across both channels) +// for IDLE (utilization=0) and maximum utilization + l_channel_pair_power_idle = 0; + l_channel_pair_power_max = 0; + for (l_port = 0; l_port < MAX_NUM_PORTS; l_port++) { -// check to see if dimm utilization is greater than the min utilization limit, -// continue if it is, error if it is not - if ((((float)throttle_n_per_chip * 100 * 4) / throttle_d) > - MIN_UTIL) + l_channel_power_array_idle[l_port] = 0; + l_channel_power_array_max[l_port] = 0; + for (l_dimm=0; l_dimm < MAX_NUM_DIMMS; l_dimm++) { - if (throttle_n_per_chip > 1) +// default dimm power is zero (used for dimms that are not physically present) + l_dimm_power_array_idle[l_port][l_dimm] = 0; + l_dimm_power_array_max[l_port][l_dimm] = 0; +// See if there are any ranks present on the dimm (configured or deconfigured) + if (l_dimm_ranks_array[l_port][l_dimm] > 0) + { + l_dimm_power_array_idle[l_port][l_dimm] = l_dimm_power_array_idle[l_port][l_dimm] + (idle_util / 100 * l_power_slope_array[l_port][l_dimm]) + l_power_int_array[l_port][l_dimm]; + l_dimm_power_array_max[l_port][l_dimm] = l_dimm_power_array_max[l_port][l_dimm] + (max_util / 100 * l_power_slope_array[l_port][l_dimm]) + l_power_int_array[l_port][l_dimm]; + } +// Include any system uplift here too + if (l_dimm_power_array_idle[l_port][l_dimm] > 0) { - if (custom_dimm == fapi::ENUM_ATTR_EFF_CUSTOM_DIMM_YES) - { -// CDIMMs, use per chip throttling for any thermal or available power limits - throttle_n_per_chip--; - } - else - { -// ISDIMMs, use per mba throttling for available power limit -// per_mba throttling (ie. per dimm for ISDIMMs) will limit performance if all -// traffic is sent to one dimm, so use the per_chip - throttle_n_per_chip--; - } + l_dimm_power_array_idle[l_port][l_dimm] = + l_dimm_power_array_idle[l_port][l_dimm] * + (1 + (float)l_power_curve_percent_uplift_idle / 100); } -// This was increment throttle_d++, but don't want to change the denominator since OCC does not set it. -// Done if we reach this point (ie. not enough power) - else + if (l_dimm_power_array_max[l_port][l_dimm] > 0) { - channel_pair_throttle_done = true; - not_enough_available_power = true; + l_dimm_power_array_max[l_port][l_dimm] = + l_dimm_power_array_max[l_port][l_dimm] * + (1 + (float)l_power_curve_percent_uplift / 100); } - FAPI_DBG("Throttle update [N_per_mba/N_per_chip/M %d/%d/%d]", throttle_n_per_mba, throttle_n_per_chip, throttle_d); +// calculate channel power by adding up the power of each dimm + l_channel_power_array_idle[l_port] = l_channel_power_array_idle[l_port] + l_dimm_power_array_idle[l_port][l_dimm]; + l_channel_power_array_max[l_port] = l_channel_power_array_max[l_port] + l_dimm_power_array_max[l_port][l_dimm]; + FAPI_DBG("[P%d:D%d][CH Util %4.2f/%4.2f][Slope:Int %d:%d][UpliftPercent idle/max %d/%d)][Power min/max %4.2f/%4.2f cW]", l_port, l_dimm, idle_util, max_util, l_power_slope_array[l_port][l_dimm], l_power_int_array[l_port][l_dimm], l_power_curve_percent_uplift_idle, l_power_curve_percent_uplift, l_dimm_power_array_idle[l_port][l_dimm], l_dimm_power_array_max[l_port][l_dimm]); + } + FAPI_DBG("[P%d][CH Util %4.2f/%4.2f][Power %4.2f/%4.2f cW]", l_port, min_util, max_util, l_channel_power_array_idle[l_port], l_channel_power_array_max[l_port]); + l_channel_pair_power_idle = l_channel_pair_power_idle + l_channel_power_array_idle[l_port]; + l_channel_pair_power_max = l_channel_pair_power_max + l_channel_power_array_max[l_port]; + } + +// calculate the slope/intercept values from power values just calculated above + l_channel_power_slope = (l_channel_pair_power_max - l_channel_pair_power_idle) / ( (max_util / 100) - (idle_util / 100) ); + l_channel_power_intercept = l_channel_pair_power_idle; + +// calculate the utilization needed to be under power limit + l_utilization = 0; + if (l_channel_pair_watt_target > l_channel_power_intercept) + { + l_utilization = (l_channel_pair_watt_target - l_channel_power_intercept) / l_channel_power_slope * 100; + if (l_utilization > max_util) + { + l_utilization = max_util; + } + } + +// Calculate the NperChip and NperMBA Throttles + l_throttle_n_per_chip = int((l_utilization / 100 * l_throttle_d / 4) * l_num_mba_with_dimms); + if (l_throttle_n_per_chip > (max_util / 100 * l_throttle_d / 4) ) + { + l_throttle_n_per_mba = int((max_util / 100 * l_throttle_d / 4)); + } + else + { + l_throttle_n_per_mba = l_throttle_n_per_chip; + } + +// Calculate the channel power at the utilization determined + channel_pair_power = int(l_utilization / 100 * l_channel_power_slope + l_channel_power_intercept); + + FAPI_DBG("[Channel Pair Power min/max %4.2f/%4.2f cW][Slope/Intercept %4.2f/%4.2f cW][Utilization Percent %4.2f, Power %d cW]", l_channel_pair_power_idle, l_channel_pair_power_max, l_channel_power_slope, l_channel_power_intercept, l_utilization, channel_pair_power); + } + +// for non custom dimms, use hardcoded values +// If power limit is at or above max power, use unthrottled settings +// If between min and max power, use a static throttle point +// If below min power, return an error + else + { +// get number of dimms attached to this mba + rc = fapiGetAssociatedDimms(i_target_mba, + l_target_dimm_array, + fapi::TARGET_STATE_PRESENT); + if (rc) { + FAPI_ERR("Error calling fapiGetAssociatedDimms"); + return rc; + } + l_number_of_dimms = l_target_dimm_array.size(); + +// ISDIMMs, set to a value of one since throttles are handled on a per MBA basis + l_num_mba_with_dimms = 1; + +// MBA Power Limit is higher than dimm power, run unthrottled + if (l_channel_pair_watt_target >= (ISDIMM_MAX_DIMM_POWER * l_number_of_dimms)) + { + l_utilization = max_util; + channel_pair_power = ISDIMM_MAX_DIMM_POWER * l_number_of_dimms; + } + else if (l_channel_pair_watt_target >= (ISDIMM_MIN_DIMM_POWER * l_number_of_dimms)) + { + if (ISDIMM_MEMORY_THROTTLE_PERCENT > 99) + { + l_utilization = min_util; } -// minimum utilization limit was reached for this throttle N/M value else { -// Throttles can't be changed anymore (already at or below MIN_UTIL) - channel_pair_throttle_done = true; - not_enough_available_power = true; + l_utilization = max_util * (1 - (float)ISDIMM_MEMORY_THROTTLE_PERCENT / 100); } + channel_pair_power = ISDIMM_MIN_DIMM_POWER * l_number_of_dimms; } -// channel pair power is less than limit, so keep existing throttles else { - FAPI_INF("There is enough available memory power [Channel Pair Power %4.2f/%d cW]", channel_pair_power, channel_pair_watt_target); - channel_pair_throttle_done = true; + // error case, available power less than allocated minimum dimm power + l_utilization = 0; + channel_pair_power = ISDIMM_MIN_DIMM_POWER * l_number_of_dimms; } + l_throttle_n_per_mba = int(l_utilization / 100 * l_throttle_d / 4); + l_throttle_n_per_chip = l_throttle_n_per_mba; + + FAPI_DBG("[Power/DIMM min/max %d/%d cW][Utilization Percent %4.2f][Number of DIMMs %d]", ISDIMM_MIN_DIMM_POWER, ISDIMM_MAX_DIMM_POWER, l_utilization, l_number_of_dimms); + } -// Set per_mba throttle to per_chip throttle if it is greater -// This way, when OCC throttles using per_mba due to thermal reasons, -// it has a higher chance of making an immediate impact -// NOTE: If above throttle determination uses throttle_n_per_mba, then -// we need to change this around - if (throttle_n_per_mba > throttle_n_per_chip) +// adjust the throttles to minimum utilization if needed + if (l_utilization < min_util) { - throttle_n_per_mba = throttle_n_per_chip; + l_throttle_n_per_mba = int(min_util / 100 * l_throttle_d / 4); + l_throttle_n_per_chip = l_throttle_n_per_mba * l_num_mba_with_dimms; } - FAPI_INF("Final Throttle Settings [N_per_mba/N_per_chip/M %d/%d/%d]", throttle_n_per_mba, throttle_n_per_chip, throttle_d); +// ensure that N throttle values are not zero, if so set to lowest values possible + if ( (l_throttle_n_per_mba == 0) || (l_throttle_n_per_mba == 0)) + { + l_throttle_n_per_mba = 1; + l_throttle_n_per_chip = l_throttle_n_per_mba * l_num_mba_with_dimms; + } -//------------------------------------------------------------------------------ -// update output attributes +// adjust the throttles to the MRW thermal limit throttles (ie. thermal/power limit less than available power) + if ( (l_throttle_n_per_mba > runtime_throttle_n_per_mba) || + (l_throttle_n_per_chip > runtime_throttle_n_per_chip) ) + { + FAPI_DBG("Throttles [%d/%d/%d] will be limited by power/thermal limit [%d/%d/%d].", l_throttle_n_per_mba, l_throttle_n_per_chip, l_throttle_d, runtime_throttle_n_per_mba, runtime_throttle_n_per_chip, l_throttle_d); + if (l_throttle_n_per_mba > runtime_throttle_n_per_mba) { + l_throttle_n_per_mba = runtime_throttle_n_per_mba; + } + if (l_throttle_n_per_chip > runtime_throttle_n_per_chip) { + l_throttle_n_per_chip = runtime_throttle_n_per_chip; + } + + } + +// Calculate out the utilization at the final throttle settings + l_utilization = (float)l_throttle_n_per_chip * 4 / l_throttle_d / l_num_mba_with_dimms * 100; + +// Calculate out the utilization at this new utilization setting for custom dimms +// does not matter for non custom dimms since those do not use power curves + if (l_custom_dimm == fapi::ENUM_ATTR_EFF_CUSTOM_DIMM_YES) + { + channel_pair_power = int(l_utilization / 100 * l_channel_power_slope + l_channel_power_intercept); + } + + FAPI_INF("[Available Channel Pair Power %d cW][UTIL %4.2f][Channel Pair Power %d cW][Throttles %d/%d/%d]", l_channel_pair_watt_target, l_utilization, channel_pair_power, l_throttle_n_per_mba, l_throttle_n_per_chip, l_throttle_d); + +// Update output attributes rc = FAPI_ATTR_SET(ATTR_MSS_MEM_THROTTLE_NUMERATOR_PER_MBA, - &i_target_mba, throttle_n_per_mba); + &i_target_mba, l_throttle_n_per_mba); if (rc) { FAPI_ERR("Error writing attribute ATTR_MSS_MEM_THROTTLE_NUMERATOR_PER_MBA"); return rc; } rc = FAPI_ATTR_SET(ATTR_MSS_MEM_THROTTLE_NUMERATOR_PER_CHIP, - &i_target_mba, throttle_n_per_chip); + &i_target_mba, l_throttle_n_per_chip); if (rc) { FAPI_ERR("Error writing attribute ATTR_MSS_MEM_THROTTLE_NUMERATOR_PER_CHIP"); return rc; } rc = FAPI_ATTR_SET(ATTR_MSS_MEM_THROTTLE_DENOMINATOR, - &i_target_mba, throttle_d); + &i_target_mba, l_throttle_d); if (rc) { FAPI_ERR("Error writing attribute ATTR_MSS_MEM_THROTTLE_DENOMINATOR"); return rc; } + rc = FAPI_ATTR_SET(ATTR_MSS_CHANNEL_PAIR_MAXPOWER, + &i_target_mba, channel_pair_power); + if (rc) { + FAPI_ERR("Error writing attribute ATTR_MSS_CHANNEL_PAIR_MAXPOWER"); + return rc; + } - if (not_enough_available_power == true) +// Check to see if there is not enough available power at min_util or higher + if (channel_pair_power > l_channel_pair_watt_target) { -// return error for TMGT to handle if there is not enough available memory power -// at the minimum utilization throttle setting - FAPI_ERR("Not enough available memory power [Channel Pair Power %4.2f/%d cW]", channel_pair_power, channel_pair_watt_target); - const float & PAIR_POWER = channel_pair_power; - const uint32_t & PAIR_WATT_TARGET = channel_pair_watt_target; + FAPI_ERR("Not enough available memory power [Channel Pair Power %d/%d cW]", channel_pair_power, l_channel_pair_watt_target); + const uint32_t & PAIR_POWER = channel_pair_power; + const uint32_t & PAIR_WATT_TARGET = l_channel_pair_watt_target; const fapi::Target & MEM_MBA = i_target_mba; FAPI_SET_HWP_ERROR(rc, RC_MSS_NOT_ENOUGH_AVAILABLE_DIMM_POWER); return rc; + } - FAPI_IMP("*** %s COMPLETE on %s ***", procedure_name, - i_target_mba.toEcmdString()); + FAPI_INF("*** mss_bulk_pwr_throttles COMPLETE ***"); return rc; + } } //end extern C diff --git a/src/usr/hwpf/hwp/mc_config/mss_eff_config/mss_eff_config_thermal.C b/src/usr/hwpf/hwp/mc_config/mss_eff_config/mss_eff_config_thermal.C index 5a2fb48f7..a86cf1d0e 100644 --- a/src/usr/hwpf/hwp/mc_config/mss_eff_config/mss_eff_config_thermal.C +++ b/src/usr/hwpf/hwp/mc_config/mss_eff_config/mss_eff_config_thermal.C @@ -22,7 +22,7 @@ /* permissions and limitations under the License. */ /* */ /* IBM_PROLOG_END_TAG */ -// $Id: mss_eff_config_thermal.C,v 1.27 2014/06/02 13:11:01 pardeik Exp $ +// $Id: mss_eff_config_thermal.C,v 1.29 2014/11/06 21:05:54 pardeik Exp $ // $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/ // centaur/working/procedures/ipl/fapi/mss_eff_config_thermal.C,v $ //------------------------------------------------------------------------------ @@ -55,6 +55,14 @@ //------------------------------------------------------------------------------ // Version:| Author: | Date: | Comment: //---------|----------|---------|----------------------------------------------- +// 1.29 | pardeik |06-NOV-14| removed strings in trace statements +// | | | changed FAPI_IMP to FAPI_INF +// | | | removed unused constants +// 1.28 | pardeik |28-OCT-14| Updates for non custom dimm power procedure +// | | | Removed mss_eff_config_thermal_term +// | | | Removed mss_eff_config_thermal_get_wc_term +// | | | Removed mss_eff_config_thermal_get_cen_drv_value +// | | | Updates to mss_eff_config_thermal_powercurve // 1.27 | pardeik |22-MAY-14| Removed attribute update section not needed // | | | Initialize runtime throttle attributes before // | | | calling bulk_pwr_throttles @@ -142,18 +150,9 @@ TODO ITEMS: const uint8_t NUM_PORTS = 2; const uint8_t NUM_DIMMS = 2; const uint8_t NUM_RANKS = 4; -const uint32_t ISDIMM_POWER_SLOPE_DEFAULT = 940; -const uint32_t ISDIMM_POWER_INT_DEFAULT = 900; // Only use values here (not any valid bits or flag bits) const uint32_t CDIMM_POWER_SLOPE_DEFAULT = 0x0240; const uint32_t CDIMM_POWER_INT_DEFAULT = 0x00CE; -// These are based on what was used when ISDIMM power values were taken from the -// power calculator -const uint8_t IDLE_DIMM_UTILIZATION = 0; -const uint8_t ACTIVE_DIMM_UTILIZATION = 70; -const uint8_t DATA_BUS_READ_PERCENT = 66; -const uint8_t DATA_BUS_WRITE_PERCENT = 34; - extern "C" { @@ -174,43 +173,6 @@ extern "C" { const fapi::Target & i_target_mba ); - fapi::ReturnCode mss_eff_config_thermal_term - ( - const char nom_or_wc_term[4], - uint8_t i_port, - uint8_t i_dimm, - uint8_t i_rank, - uint32_t i_dimm_voltage, - uint8_t i_dram_width, - uint8_t i_dram_tdqs, - uint8_t i_dimm_type, - uint8_t i_stack_type, - uint8_t i_dimm_master_ranks_array[NUM_PORTS][NUM_DIMMS], - uint8_t i_dimm_ranks_configed_array[NUM_PORTS][NUM_DIMMS], - uint8_t i_dimm_dram_ron[NUM_PORTS][NUM_DIMMS], - uint8_t i_dimm_rank_odt_rd[NUM_PORTS][NUM_DIMMS][NUM_RANKS], - uint8_t i_dimm_rank_odt_wr[NUM_PORTS][NUM_DIMMS][NUM_RANKS], - uint8_t i_dram_rtt_nom[NUM_PORTS][NUM_DIMMS][NUM_RANKS], - uint8_t i_dram_rtt_wr[NUM_PORTS][NUM_DIMMS][NUM_RANKS], - uint8_t i_cen_dq_dqs_rcv_imp[NUM_PORTS], - uint8_t i_cen_dq_dqs_drv_imp[NUM_PORTS], - float &o_dimm_power_adder_termination - ); - - fapi::ReturnCode mss_eff_config_thermal_get_wc_term - ( - const fapi::Target &i_target_mba, - uint8_t i_port, - uint8_t &o_cen_dq_dqs_rcv_imp_wc, - uint8_t &o_cen_dq_dqs_drv_imp_wc - ); - - fapi::ReturnCode mss_eff_config_thermal_get_cen_drv_value - ( - uint8_t i_cen_dq_dqs_drv_imp, - uint8_t &o_cen_dq_dqs_drv_imp - ); - //------------------------------------------------------------------------------ // @brief mss_eff_config_thermal(): This function determines the @@ -225,9 +187,7 @@ extern "C" { { fapi::ReturnCode rc = fapi::FAPI_RC_SUCCESS; - const char* procedure_name = "mss_eff_config_thermal"; - - FAPI_IMP("*** Running %s on %s ***", procedure_name, + FAPI_INF("*** Running mss_eff_config_thermal on %s ***", i_target_mba.toEcmdString()); rc = mss_eff_config_thermal_powercurve(i_target_mba); @@ -244,7 +204,7 @@ extern "C" { } - FAPI_IMP("*** %s COMPLETE on %s ***", procedure_name, + FAPI_INF("*** mss_eff_config_thermal COMPLETE on %s ***", i_target_mba.toEcmdString()); return rc; } @@ -262,126 +222,24 @@ extern "C" { { fapi::ReturnCode rc = fapi::FAPI_RC_SUCCESS; - const char* procedure_name = "mss_eff_config_thermal_powercurve"; - - FAPI_IMP("*** Running %s on %s ***", procedure_name, + FAPI_INF("*** Running mss_eff_config_thermal_powercurve on %s ***", i_target_mba.toEcmdString()); - enum - { - DDR3 = fapi::ENUM_ATTR_EFF_DRAM_GEN_DDR3, - DDR4 = fapi::ENUM_ATTR_EFF_DRAM_GEN_DDR4, - X4 = fapi::ENUM_ATTR_EFF_DRAM_WIDTH_X4, - X8 = fapi::ENUM_ATTR_EFF_DRAM_WIDTH_X8, - }; - -// Structure types for the table that holds dimm power and adjustment values -// that will be used - - struct dimm_power_t - { - uint32_t idle; - uint32_t active; - }; - struct dimm_type_t - { - int32_t udimm; - int32_t lrdimm; - int32_t rdimm; - }; - struct power_data_t - { - uint8_t dram_generation; - uint8_t dram_width; - uint8_t dimm_ranks; - dimm_power_t rank_power; - dimm_type_t dimm_type_adder; - int32_t dimm_voltage_base; - int32_t dimm_frequency_base; - }; - -//------------------------------------------------------------------------------ -// Master Ranks column uses the values in the same table entry for the number of -// master ranks specified. Default is to have it use same power for each master -// rank, so that is why master ranks = 1. If we need to separate power based on -// number of master ranks, then have the table setup for descending master rank -// values. We always need an entry for master ranks of 1. Table lookup will -// stop after first matching entry is found (DRAM Generation, DRAM Width, and -// Master Ranks = dimm_master_ranks_array OR 1) -// -// These values need to cover the power of all IBM dimms. Values will come from -// the power calculator and be verified by hardware measurements. -// -// Base Voltage and Base Frequency values need to match what mss_volt/mss_freq -// uses. -// -// DRAM DRAM Master RankPower DIMMType Base Base -// Gen Width Ranks idle,full Adder Volt Freq -// cW U,LR,RDIMM mV MHz -//------------------------------------------------------------------------------ -// TODO: Update ISDIMM power table values after measurements have been taken - power_data_t power_table[] = - { - { DDR3, X4, 1, { 70,373}, {0,93,104}, 1350, 1066 }, - { DDR3, X8, 1, { 52,300}, {0,93,104}, 1350, 1066 }, - { DDR4, X4, 1, { 70,373}, {0,93,104}, 1350, 1066 }, - { DDR4, X8, 1, { 52,300}, {0,93,104}, 1350, 1066 }, - }; - // other variables used in this function fapi::Target target_chip; - std::vector<fapi::Target> target_dimm_array; uint8_t port; uint8_t dimm; - uint8_t mba_port; - uint8_t mba_dimm; - uint8_t rank; - uint8_t entry; - uint8_t dimm_type; - uint8_t stack_type[NUM_PORTS][NUM_DIMMS]; uint8_t custom_dimm; uint8_t dimm_ranks_array[NUM_PORTS][NUM_DIMMS]; - uint32_t power_table_size; uint32_t power_slope_array[NUM_PORTS][NUM_DIMMS]; uint32_t power_int_array[NUM_PORTS][NUM_DIMMS]; uint32_t power_slope2_array[NUM_PORTS][NUM_DIMMS]; uint32_t power_int2_array[NUM_PORTS][NUM_DIMMS]; - uint8_t found_entry_in_table; - uint8_t dram_width; - uint8_t dram_tdqs; - uint8_t dram_gen; - uint32_t dimm_voltage; - uint32_t dimm_frequency; - uint8_t dimm_ranks_configed_array[NUM_PORTS][NUM_DIMMS]; - uint8_t dimm_master_ranks_array[NUM_PORTS][NUM_DIMMS]; - int32_t dimm_power_adder_type; - float dimm_power_multiplier_volt; - float dimm_power_mulitiplier_freq; - float dimm_idle_power; - float dimm_active_power; - float dimm_power_adder_termination = 0; - float dimm_power_adder_termination_largest = 0; - uint8_t dimm_rank_odt_rd[NUM_PORTS][NUM_DIMMS][NUM_RANKS]; - uint8_t dimm_rank_odt_wr[NUM_PORTS][NUM_DIMMS][NUM_RANKS]; - uint8_t dimm_dram_ron[NUM_PORTS][NUM_DIMMS]; - uint8_t cen_dq_dqs_rcv_imp[NUM_PORTS]; - uint8_t cen_dq_dqs_drv_imp[NUM_PORTS]; - float dimm_power_adder_termination_wc = 0; - float dimm_power_adder_termination_largest_wc = 0; - uint8_t cen_dq_dqs_rcv_imp_wc[NUM_PORTS]; - uint8_t cen_dq_dqs_drv_imp_wc[NUM_PORTS]; - uint8_t num_dimms_on_port; - uint8_t dram_rtt_nom[NUM_PORTS][NUM_DIMMS][NUM_RANKS]; - uint8_t dram_rtt_wr[NUM_PORTS][NUM_DIMMS][NUM_RANKS]; - char dram_gen_str[4]; - uint8_t dimm_number_registers[NUM_PORTS][NUM_DIMMS]; - uint8_t dimm_index; uint32_t cdimm_master_power_slope; uint32_t cdimm_master_power_intercept; uint32_t cdimm_supplier_power_slope; uint32_t cdimm_supplier_power_intercept; - power_table_size = (sizeof(power_table))/(sizeof(power_data_t)); //------------------------------------------------------------------------------ // Get input attributes @@ -394,97 +252,17 @@ extern "C" { return rc; } - rc = FAPI_ATTR_GET(ATTR_EFF_DRAM_GEN, &i_target_mba, dram_gen); - if (rc) { - FAPI_ERR("Error getting attribute ATTR_EFF_DRAM_GEN"); - return rc; - } - rc = FAPI_ATTR_GET(ATTR_EFF_DIMM_TYPE, &i_target_mba, dimm_type); - if (rc) { - FAPI_ERR("Error getting attribute ATTR_EFF_DIMM_TYPE"); - return rc; - } - rc = FAPI_ATTR_GET(ATTR_EFF_STACK_TYPE, &i_target_mba, stack_type); - if (rc) { - FAPI_ERR("Error getting attribute ATTR_EFF_STACK_TYPE"); - return rc; - } rc = FAPI_ATTR_GET(ATTR_EFF_CUSTOM_DIMM, &i_target_mba, custom_dimm); if (rc) { FAPI_ERR("Error getting attribute ATTR_EFF_CUSTOM_DIMM"); return rc; } - rc = FAPI_ATTR_GET(ATTR_EFF_DRAM_WIDTH, &i_target_mba, dram_width); - if (rc) { - FAPI_ERR("Error getting attribute ATTR_EFF_DRAM_WIDTH"); - return rc; - } - rc = FAPI_ATTR_GET(ATTR_EFF_DRAM_TDQS, &i_target_mba, dram_tdqs); - if (rc) { - FAPI_ERR("Error getting attribute ATTR_EFF_DRAM_TDQS"); - return rc; - } rc = FAPI_ATTR_GET(ATTR_EFF_NUM_RANKS_PER_DIMM, &i_target_mba, dimm_ranks_array); if (rc) { FAPI_ERR("Error getting attribute ATTR_EFF_NUM_RANKS_PER_DIMM"); return rc; } - rc = FAPI_ATTR_GET(ATTR_EFF_NUM_MASTER_RANKS_PER_DIMM, - &i_target_mba, dimm_master_ranks_array); - if (rc) { - FAPI_ERR("Error getting attribute ATTR_EFF_NUM_MASTER_RANKS_PER_DIMM"); - return rc; - } - rc = FAPI_ATTR_GET(ATTR_EFF_DIMM_RANKS_CONFIGED, - &i_target_mba, dimm_ranks_configed_array); - if (rc) { - FAPI_ERR("Error getting attribute ATTR_EFF_DIMM_RANKS_CONFIGED"); - return rc; - } - rc = FAPI_ATTR_GET(ATTR_VPD_DRAM_RON, &i_target_mba, dimm_dram_ron); - if (rc) { - FAPI_ERR("Error getting attribute ATTR_VPD_DRAM_RON"); - return rc; - } - rc = FAPI_ATTR_GET(ATTR_VPD_ODT_RD, &i_target_mba, dimm_rank_odt_rd); - if (rc) { - FAPI_ERR("Error getting attribute ATTR_VPD_ODT_RD"); - return rc; - } - rc = FAPI_ATTR_GET(ATTR_VPD_ODT_WR, &i_target_mba, dimm_rank_odt_wr); - if (rc) { - FAPI_ERR("Error getting attribute ATTR_VPD_ODT_WR"); - return rc; - } - rc = FAPI_ATTR_GET(ATTR_EFF_CEN_RCV_IMP_DQ_DQS, - &i_target_mba, cen_dq_dqs_rcv_imp); - if (rc) { - FAPI_ERR("Error getting attribute ATTR_EFF_CEN_RCV_IMP_DQ_DQS"); - return rc; - } - rc = FAPI_ATTR_GET(ATTR_EFF_CEN_DRV_IMP_DQ_DQS, - &i_target_mba, cen_dq_dqs_drv_imp); - if (rc) { - FAPI_ERR("Error getting attribute ATTR_EFF_CEN_DRV_IMP_DQ_DQS"); - return rc; - } - rc = FAPI_ATTR_GET(ATTR_VPD_DRAM_RTT_NOM, &i_target_mba, dram_rtt_nom); - if (rc) { - FAPI_ERR("Error getting attribute ATTR_VPD_DRAM_RTT_NOM"); - return rc; - } - rc = FAPI_ATTR_GET(ATTR_VPD_DRAM_RTT_WR, &i_target_mba, dram_rtt_wr); - if (rc) { - FAPI_ERR("Error getting attribute ATTR_VPD_DRAM_RTT_WR"); - return rc; - } - rc = FAPI_ATTR_GET(ATTR_EFF_NUM_DROPS_PER_PORT, - &i_target_mba, num_dimms_on_port); - if (rc) { - FAPI_ERR("Error getting attribute ATTR_EFF_NUM_DROPS_PER_PORT"); - return rc; - } // Only get power curve values for custom dimms to prevent errors if (custom_dimm == fapi::ENUM_ATTR_EFF_CUSTOM_DIMM_YES) { @@ -515,172 +293,12 @@ extern "C" { } } -// Get voltage and frequency attributes - rc = FAPI_ATTR_GET(ATTR_MSS_VOLT, &target_chip, dimm_voltage); - if (rc) { - FAPI_ERR("Error getting attribute ATTR_MSS_VOLT"); - return rc; - } - rc = FAPI_ATTR_GET(ATTR_MSS_FREQ, &target_chip, dimm_frequency); - if (rc) { - FAPI_ERR("Error getting attribute ATTR_MSS_FREQ"); - return rc; - } - -// get any attributes from DIMM SPD - if ( - (custom_dimm == fapi::ENUM_ATTR_EFF_CUSTOM_DIMM_NO) - && (dimm_type == fapi::ENUM_ATTR_EFF_DIMM_TYPE_RDIMM) - ) - { - rc = fapiGetAssociatedDimms(i_target_mba, target_dimm_array, - fapi::TARGET_STATE_PRESENT); - if (rc) { - FAPI_ERR("Error from fapiGetAssociatedDimms"); - return rc; - } - for (dimm_index=0; - dimm_index < target_dimm_array.size(); - dimm_index++) - { - rc = FAPI_ATTR_GET(ATTR_MBA_PORT, - &target_dimm_array[dimm_index], port); - if (rc) { - FAPI_ERR("Error getting attribute ATTR_MBA_PORT"); - return rc; - } - rc = FAPI_ATTR_GET(ATTR_MBA_DIMM, - &target_dimm_array[dimm_index], dimm); - if (rc) { - FAPI_ERR("Error getting attribute ATTR_MBA_DIMM"); - return rc; - } - rc = FAPI_ATTR_GET(ATTR_SPD_NUM_OF_REGISTERS_USED_ON_RDIMM, - &target_dimm_array[dimm_index], - dimm_number_registers[port][dimm]); - if (rc) { - FAPI_ERR("Error getting attribute ATTR_SPD_NUM_OF_REGISTERS_USED_ON_RDIMM"); - return rc; - } - } - } - - -// determine worst case termination settings here for ISDIMMs (to be used later) - if (custom_dimm == fapi::ENUM_ATTR_EFF_CUSTOM_DIMM_NO) - { -// get worst case termination values that will be used -// Only look at Centaur DQ/DQS Driver and Receiver termination settings -// Note that the DRAM rtt_nom, rtt_wr, and ron will not be allowed to change, -// all these will stay at the nominal settings - for (port=0; port < NUM_PORTS; port++) - { - rc = mss_eff_config_thermal_get_wc_term - ( - i_target_mba, - port, - cen_dq_dqs_rcv_imp_wc[port], - cen_dq_dqs_drv_imp_wc[port] - ); - if (rc) - { - FAPI_ERR("Error (0x%x) calling mss_eff_config_thermal_get_wc_term", static_cast<uint32_t>(rc)); - return rc; - } - } - } - //------------------------------------------------------------------------------ // Power Curve Determination //------------------------------------------------------------------------------ // Iterate through the MBA ports to get power slope/intercept values for (port=0; port < NUM_PORTS; port++) { -// Get termination power for ISDIMM - if (custom_dimm == fapi::ENUM_ATTR_EFF_CUSTOM_DIMM_NO) - { - dimm_power_adder_termination_largest=0; - dimm_power_adder_termination_largest_wc=0; - -// iterate through the dimms on each port to determine termination power to use - for (dimm=0; dimm < NUM_DIMMS; dimm++) - { -// calculate the effective net termination for each rank - for (rank=0; rank < NUM_RANKS; rank++) - { -// nominal termination - rc = mss_eff_config_thermal_term - ( - "NOM", - port, - dimm, - rank, - dimm_voltage, - dram_width, - dram_tdqs, - dimm_type, - stack_type[port][dimm], - dimm_master_ranks_array, - dimm_ranks_configed_array, - dimm_dram_ron, - dimm_rank_odt_rd, - dimm_rank_odt_wr, - dram_rtt_nom, - dram_rtt_wr, - cen_dq_dqs_rcv_imp, - cen_dq_dqs_drv_imp, - dimm_power_adder_termination - ); - if (rc) - { - FAPI_ERR("Error (0x%x) calling mss_eff_config_thermal_term", static_cast<uint32_t>(rc)); - return rc; - } - if (dimm_power_adder_termination > - dimm_power_adder_termination_largest) - { - dimm_power_adder_termination_largest = - dimm_power_adder_termination; - } - -// worst case termination - rc = mss_eff_config_thermal_term - ( - "WC", - port, - dimm, - rank, - dimm_voltage, - dram_width, - dram_tdqs, - dimm_type, - stack_type[port][dimm], - dimm_master_ranks_array, - dimm_ranks_configed_array, - dimm_dram_ron, - dimm_rank_odt_rd, - dimm_rank_odt_wr, - dram_rtt_nom, - dram_rtt_wr, - cen_dq_dqs_rcv_imp_wc, - cen_dq_dqs_drv_imp_wc, - dimm_power_adder_termination_wc - ); - if (rc) - { - FAPI_ERR("Error (0x%x) calling mss_eff_config_thermal_term", static_cast<uint32_t>(rc)); - return rc; - } - if (dimm_power_adder_termination_wc > - dimm_power_adder_termination_largest_wc) - { - dimm_power_adder_termination_largest_wc = - dimm_power_adder_termination_wc; - } - } - } - } - // iterate through the dimms on each port again to determine power slope and // intercept for (dimm=0; dimm < NUM_DIMMS; dimm++) @@ -760,213 +378,9 @@ extern "C" { } FAPI_DBG("CDIMM Power [P%d:D%d][SLOPE=%d:INT=%d cW][SLOPE2=%d:INT2=%d cW]", port, dimm, power_slope_array[port][dimm], power_int_array[port][dimm], power_slope2_array[port][dimm], power_int2_array[port][dimm]); } -// ISDIMM power slope/intercept will come from equation - else - { -// Get the dimm power from table and add on any adjustments (if not found in -// table - should never happen - then default values will be used) - power_slope_array[port][dimm] = - ISDIMM_POWER_SLOPE_DEFAULT; - power_int_array[port][dimm] = ISDIMM_POWER_INT_DEFAULT; - - found_entry_in_table = 0; - for (entry = 0; entry < power_table_size; entry++) - { - if ( - (power_table[entry].dram_generation == dram_gen) - && - (power_table[entry].dram_width == dram_width) - && - ((power_table[entry].dimm_ranks == - dimm_master_ranks_array[port][dimm]) || - (power_table[entry].dimm_ranks == 1)) - ) - { -// get adder for dimm type - if (dimm_type == fapi::ENUM_ATTR_EFF_DIMM_TYPE_UDIMM) - { - dimm_power_adder_type = - power_table[entry].dimm_type_adder.udimm; - } - else if (dimm_type == fapi::ENUM_ATTR_EFF_DIMM_TYPE_LRDIMM) - { - dimm_power_adder_type = - power_table[entry].dimm_type_adder.lrdimm; - } - else // RDIMM - { - dimm_power_adder_type = - power_table[entry].dimm_type_adder.rdimm; - } - - - if (dimm_type == fapi::ENUM_ATTR_EFF_DIMM_TYPE_RDIMM) { - dimm_power_adder_type = - dimm_power_adder_type * - dimm_number_registers[port][dimm]; - } - -// get adder for dimm voltage - dimm_power_multiplier_volt = - ( - (float(dimm_voltage) / - power_table[entry].dimm_voltage_base) - * - (float(dimm_voltage) / - power_table[entry].dimm_voltage_base) - ); -// get adder for dimm frequency - dimm_power_mulitiplier_freq = - (float(dimm_frequency) / - power_table[entry].dimm_frequency_base); -// get adder for termination using equation (in cW) - dimm_power_adder_termination = - dimm_power_adder_termination_largest * 100; - dimm_power_adder_termination_wc = - dimm_power_adder_termination_largest_wc * 100; -// add up power for each dimm on channel and divide by number of dimms to get an -// average power for each dimm -// calculate idle and active dimm power (active power includes worst case -// termination power) - dimm_idle_power = - ( - (float( - ( - ( - power_table[entry].rank_power.idle - * - ( - dimm_master_ranks_array[port][dimm] - + (dimm_ranks_array[port][dimm] - - dimm_master_ranks_array - [port][dimm]) - ) + dimm_power_adder_type - ) - * (dimm_power_multiplier_volt) - * (dimm_power_mulitiplier_freq) - ) - * - num_dimms_on_port - ) - / (num_dimms_on_port) - ) - ); -//------------------------------------------------------------------------------ - dimm_active_power = - ( - (float( - ( - ( - (power_table[entry].rank_power.idle - * - ( - dimm_master_ranks_array[port][dimm] - + - ( - dimm_ranks_array[port][dimm] - - dimm_master_ranks_array - [port][dimm] - ) - ) - + - ( - power_table[entry].rank_power.active - - - power_table[entry].rank_power.idle - ) - ) - + - dimm_power_adder_type - ) - * (dimm_power_multiplier_volt) - * (dimm_power_mulitiplier_freq) - ) - * num_dimms_on_port - - (power_table[entry].rank_power.active - - power_table[entry].rank_power.idle) - * (num_dimms_on_port - 1) - + dimm_power_adder_termination - + (dimm_power_adder_termination_wc - - dimm_power_adder_termination) - ) - / - (num_dimms_on_port) - ) - ); -//------------------------------------------------------------------------------ -// calculate dimm power slope and intercept (add on 0.5 so value is effectively -// rounded to nearest integer) - power_slope_array[port][dimm] = - int( - (dimm_active_power - dimm_idle_power) / - (float(ACTIVE_DIMM_UTILIZATION - - IDLE_DIMM_UTILIZATION) / 100) - + 0.5 - ); - power_int_array[port][dimm] = - int(dimm_idle_power + 0.5); - power_slope2_array[port][dimm] = - power_slope_array[port][dimm]; - power_int2_array[port][dimm] = - power_int_array[port][dimm]; - if (power_table[entry].dram_generation == DDR3) - { - sprintf(dram_gen_str, "DDR3"); - } - if (power_table[entry].dram_generation == DDR4) - { - sprintf(dram_gen_str, "DDR4"); - } - - found_entry_in_table = 1; - FAPI_DBG("FOUND ENTRY: GEN=%s WIDTH=X%d RANK=%d IDLE(%d%%)=%d ACTIVE(%d%%)=%d ADDER[TYPE=%d WCTERM=%4.2f] Multiplier[VOLT=%4.2f FREQ=%4.2f]", dram_gen_str, power_table[entry].dram_width, power_table[entry].dimm_ranks, IDLE_DIMM_UTILIZATION, power_table[entry].rank_power.idle, ACTIVE_DIMM_UTILIZATION, power_table[entry].rank_power.active, dimm_power_adder_type, dimm_power_adder_termination_wc, dimm_power_multiplier_volt, dimm_power_mulitiplier_freq); - FAPI_DBG("ISDIMM Power [P%d:D%d][%s:X%d:R%d/%d:%d:%d][IDLE(%d%%)=%4.2f:ACTIVE(%d%%)=%4.2f cW][SLOPE=%d:INT=%d cW]", port, dimm, dram_gen_str, power_table[entry].dram_width, dimm_master_ranks_array[port][dimm], (dimm_ranks_array[port][dimm] - dimm_master_ranks_array[port][dimm]), dimm_voltage, dimm_frequency, IDLE_DIMM_UTILIZATION, dimm_idle_power, ACTIVE_DIMM_UTILIZATION, dimm_active_power, power_slope_array[port][dimm], power_int_array[port][dimm]); - FAPI_DBG("ISDIMM Power [P%d:D%d][SLOPE=%d:INT=%d cW][SLOPE2=%d:INT2=%d cW]", port, dimm, power_slope_array[port][dimm], power_int_array[port][dimm], power_slope2_array[port][dimm], power_int2_array[port][dimm]); - break; - } - - } -//------------------------------------------------------------------------------ - if (found_entry_in_table == 0) - { - - FAPI_ERR("Failed to Find DIMM Power Values on %s. Default values will be used [P%d:D%d][Slope=%d:INT=%d cW]", i_target_mba.toEcmdString(), port, dimm, power_slope_array[port][dimm], power_int_array[port][dimm]); - -// get dimm target, we should always find a valid dimm target from this -// since we have ranks present on this dimm if we are here in the code - for (dimm_index=0; - dimm_index < target_dimm_array.size(); - dimm_index++) - { - rc = FAPI_ATTR_GET - (ATTR_MBA_PORT, - &target_dimm_array[dimm_index], mba_port); - if (rc) { - FAPI_ERR("Error getting attribute ATTR_MBA_PORT"); - return rc; - } - rc = FAPI_ATTR_GET - (ATTR_MBA_DIMM, - &target_dimm_array[dimm_index], mba_dimm); - if (rc) { - FAPI_ERR("Error getting attribute ATTR_MBA_DIMM"); - return rc; - } - if ( (mba_port == port) && (mba_dimm == dimm)) { - break; - } - } - const fapi::Target & MEM_DIMM = - target_dimm_array[dimm_index]; - uint32_t FFDC_DATA_1 = dram_gen; - uint32_t FFDC_DATA_2 = dram_width; - uint8_t FFDC_DATA_3 = - dimm_master_ranks_array[port][dimm]; - FAPI_SET_HWP_ERROR - (rc, RC_MSS_DIMM_NOT_FOUND_IN_POWER_TABLE); - if (rc) fapiLogError(rc); - } - } +// non custom dimms will no longer use power curves +// These will use a simplified approach of using throttle values for certain ranges of power +// in mss_bulk_pwr_throttles. } } } @@ -997,7 +411,7 @@ extern "C" { return rc; } - FAPI_IMP("*** %s COMPLETE on %s ***", procedure_name, + FAPI_INF("*** mss_eff_config_thermal_powercurve COMPLETE on %s ***", i_target_mba.toEcmdString()); return rc; } @@ -1015,9 +429,7 @@ extern "C" { { fapi::ReturnCode rc = fapi::FAPI_RC_SUCCESS; - const char* procedure_name = "mss_eff_config_thermal_throttles"; - - FAPI_IMP("*** Running %s on %s ***", procedure_name, + FAPI_INF("*** Running mss_eff_config_thermal_throttles on %s ***", i_target_mba.toEcmdString()); // variables used in this function @@ -1078,8 +490,6 @@ extern "C" { return rc; } - - // Get number of Centaur MBAs that have dimms present // Custom dimms (CDIMMs) use mba/chip throttling, so count number of mbas that have dimms if (custom_dimm == fapi::ENUM_ATTR_EFF_CUSTOM_DIMM_YES) @@ -1180,7 +590,6 @@ extern "C" { return rc; } - // Call the procedure function that takes a channel pair power limit and // converts it to throttle values @@ -1191,6 +600,8 @@ extern "C" { return rc; } + FAPI_INF("MRW Power/Thermal Limit %d. Throttles [%d/%d/%d].", channel_pair_thermal_power_limit, runtime_throttle_n_per_mba, runtime_throttle_n_per_chip, runtime_throttle_d); + // Read back in the updated throttle attribute values (these are now set to // values that will give dimm/channel power underneath the thermal power limit) rc = FAPI_ATTR_GET(ATTR_MSS_MEM_THROTTLE_NUMERATOR_PER_MBA, @@ -1248,982 +659,9 @@ extern "C" { return rc; } - FAPI_IMP("*** %s COMPLETE on %s ***", procedure_name, + FAPI_INF("*** mss_eff_config_thermal_throttles COMPLETE on %s ***", i_target_mba.toEcmdString()); return rc; } -//------------------------------------------------------------------------------ -// @brief mss_eff_config_thermal_term(): This function calculates the data bus -// termination power -// -// @param[in] const char i_nom_or_wc_term[4]: description of what is being -// calculated (ie. NOM or WC) -// @param[in] uint8_t i_port: MBA port being worked on -// @param[in] uint8_t i_dimm: DIMM being worked on -// @param[in] uint8_t i_rank: Rank being worked on -// @param[in] uint32_t i_dimm_voltage: DIMM Voltage -// @param[in] uint8_t i_dram_width: DRAM Width -// @param[in] uint8_t i_dram_tdqs: DRAM TDQS enable/disable -// @param[in] uint8_t i_dimm_type: DIMM Type -// @param[in] uint8_t i_stack_type: DRAM Stack Type -// @param[in] uint8_t i_dimm_master_ranks_array: Number of Master Ranks -// @param[in] uint8_t i_dimm_ranks_configed_array[NUM_PORTS][NUM_DIMMS]: -// Master Ranks configured -// @param[in] uint8_t i_dimm_dram_ron[NUM_PORTS][NUM_DIMMS]: DRAM RON driver -// impedance -// @param[in] uint8_t i_dimm_rank_odt_rd[NUM_PORTS][NUM_DIMMS][NUM_RANKS]: -// Read ODT -// @param[in] uint8_t i_dimm_rank_odt_wr[NUM_PORTS][NUM_DIMMS][NUM_RANKS]: -// Write ODT -// @param[in] uint8_t i_dram_rtt_nom[NUM_PORTS][NUM_DIMMS][NUM_RANKS]: DRAM -// RTT NOM -// @param[in] uint8_t i_dram_rtt_wr[NUM_PORTS][NUM_DIMMS][NUM_RANKS]: DRAM -// RTT WR -// @param[in] uint8_t i_cen_dq_dqs_rcv_imp[NUM_PORTS]: Centaur DQ/DQS -// receiver impedance -// @param[in] uint8_t i_cen_dq_dqs_drv_imp[NUM_PORTS]: Centaur DQ/DQS driver -// impedance -// @param[out] float &o_dimm_power_adder_termination: Termination Power -// Calculated in Watts -// -// @return fapi::ReturnCode -//------------------------------------------------------------------------------ - - fapi::ReturnCode mss_eff_config_thermal_term - ( - const char i_nom_or_wc_term[4], - uint8_t i_port, - uint8_t i_dimm, - uint8_t i_rank, - uint32_t i_dimm_voltage, - uint8_t i_dram_width, - uint8_t i_dram_tdqs, - uint8_t i_dimm_type, - uint8_t i_stack_type, - uint8_t i_dimm_master_ranks_array[NUM_PORTS][NUM_DIMMS], - uint8_t i_dimm_ranks_configed_array[NUM_PORTS][NUM_DIMMS], - uint8_t i_dimm_dram_ron[NUM_PORTS][NUM_DIMMS], - uint8_t i_dimm_rank_odt_rd[NUM_PORTS][NUM_DIMMS][NUM_RANKS], - uint8_t i_dimm_rank_odt_wr[NUM_PORTS][NUM_DIMMS][NUM_RANKS], - uint8_t i_dram_rtt_nom[NUM_PORTS][NUM_DIMMS][NUM_RANKS], - uint8_t i_dram_rtt_wr[NUM_PORTS][NUM_DIMMS][NUM_RANKS], - uint8_t i_cen_dq_dqs_rcv_imp[NUM_PORTS], - uint8_t i_cen_dq_dqs_drv_imp[NUM_PORTS], - float &o_dimm_power_adder_termination - ) - { - fapi::ReturnCode rc = fapi::FAPI_RC_SUCCESS; - - const char* procedure_name = "mss_eff_config_thermal_term"; - - FAPI_IMP("*** Running %s ***", procedure_name); - - uint8_t number_nets_term_rd; - uint8_t number_nets_term_wr; - uint8_t ma0odt01_dimm; - uint8_t ma1odt01_dimm; - uint8_t ma0odt0_rank; - uint8_t ma0odt1_rank; - uint8_t ma1odt0_rank; - uint8_t ma1odt1_rank; - uint8_t rank_mask; - float eff_term_rd; - float eff_net_term_rd; - float term_odt_mult_rd; - float eff_term_wr; - float eff_net_term_wr; - float term_odt_mult_wr; - uint8_t cen_dq_dqs_drv_imp_value; - -// Get number of nets that will have termination applied from ODT (DQ,DQS,DM, -// TDQS) -// number of nets for DQ (9 DRAMs x 8 bits each, or 18 DRAMs x 4 bits each = 72) - number_nets_term_rd = 72; - number_nets_term_wr = 72; -// add in number of nets for DQS + DM + TDQS (TDQS only supported for X8, DM -// only used for writes) - if (i_dram_width == fapi::ENUM_ATTR_EFF_DRAM_WIDTH_X4) - { - number_nets_term_rd = number_nets_term_rd + 36 + 0 + 0; - number_nets_term_wr = number_nets_term_wr + 36 + 0 + 0; - } - else if ((i_dram_width == fapi::ENUM_ATTR_EFF_DRAM_WIDTH_X8) && - (i_dram_tdqs == fapi::ENUM_ATTR_EFF_DRAM_TDQS_DISABLE)) - { - number_nets_term_rd = number_nets_term_rd + 18 + 0 + 0; - number_nets_term_wr = number_nets_term_wr + 18 + 9 + 0; - } - else if ((i_dram_width == fapi::ENUM_ATTR_EFF_DRAM_WIDTH_X8) && - (i_dram_tdqs == fapi::ENUM_ATTR_EFF_DRAM_TDQS_ENABLE)) - { - number_nets_term_rd = number_nets_term_rd + 18 + 0 + 18; - number_nets_term_wr = number_nets_term_wr + 18 + 0 + 18; - } - -// which rank is mapped to the [01]ODT[01] nets, from centaur spec, every type -// uses Ranks 0,1,4,5, with the following exceptions -// Type 1D used Ranks 0,2,4,6 in that order (0_ODT0,0_ODT1,1_ODT0,1_ODT1) -// expect that EFF_ODT_RD and EFF_ODT_WR will be setup correctly so we just need -// to add up any termination in parallel for the bits set in these attributes -// Also need to consider if ODT is tied high for writes (if rtt_wr is set for -// the rank being written to, then it will be assumed that ODT is tied high) - -// Type_1D is also the following (use these instead of attribute) -// 1. RDIMM or UDIMM -// 2. 4 Master Ranks -// 3. Planar or DDP/QDP - if ( - ((i_dimm_type == fapi::ENUM_ATTR_EFF_DIMM_TYPE_RDIMM) - || (i_dimm_type == fapi::ENUM_ATTR_EFF_DIMM_TYPE_UDIMM)) - && - (i_dimm_master_ranks_array[i_port][i_dimm] == 4) - && - ((i_stack_type == fapi::ENUM_ATTR_EFF_STACK_TYPE_NONE) - || (i_stack_type == fapi::ENUM_ATTR_EFF_STACK_TYPE_DDP_QDP)) - ) - { - ma0odt01_dimm = 0; - ma1odt01_dimm = 1; - ma0odt0_rank = 0; - ma0odt1_rank = 2; - ma1odt0_rank = 0; - ma1odt1_rank = 2; - } - else - { - ma0odt01_dimm = 0; - ma1odt01_dimm = 1; - ma0odt0_rank = 0; - ma0odt1_rank = 1; - ma1odt0_rank = 0; - ma1odt1_rank = 1; - } - -// check to see if rank is configured, only get termination power for these -// ranks - rank_mask = 0x00; - if (i_rank == 0) - { - rank_mask = 0x80; - } - else if (i_rank == 1) - { - rank_mask = 0x40; - } - else if (i_rank == 2) - { - rank_mask = 0x20; - } - else if (i_rank == 3) - { - rank_mask = 0x10; - } - if ((i_dimm_ranks_configed_array[i_port][i_dimm] & rank_mask) != 0) - { -// effective net termination = [(active termination in parallel || driver -// impedance) + active termination in parallel] - - - -//------------------------------------------------------------------------------ -// calculate out effective termination for reads -//------------------------------------------------------------------------------ - eff_term_rd = 0; - -//------------------------------------------------------------------------------ -// 0ODT0 - if ( - ((i_dimm_rank_odt_rd[i_port][i_dimm][i_rank] & 0x80) != 0) - && - (i_dram_rtt_nom[i_port][ma0odt01_dimm][ma0odt0_rank] != - fapi::ENUM_ATTR_VPD_DRAM_RTT_NOM_DISABLE) - ) - { - if (eff_term_rd == 0) - { - eff_term_rd = - i_dram_rtt_nom[i_port][ma0odt01_dimm][ma0odt0_rank]; - } - else - { - eff_term_rd = - (eff_term_rd * - i_dram_rtt_nom[i_port][ma0odt01_dimm][ma0odt0_rank]) - / - (eff_term_rd + - i_dram_rtt_nom[i_port][ma0odt01_dimm][ma0odt0_rank]); - } - FAPI_DBG("[P%d:D%d:R%d] 0ODT0 RD TERMINATION = %4.2f (%d)", i_port, i_dimm, i_rank, eff_term_rd, i_dram_rtt_nom[i_port][ma0odt01_dimm][ma0odt0_rank]); - - } -//------------------------------------------------------------------------------ -// 0ODT1 - if ( - ((i_dimm_rank_odt_rd[i_port][i_dimm][i_rank] & 0x40) != 0) - && - (i_dram_rtt_nom[i_port][ma0odt01_dimm][ma0odt1_rank] != - fapi::ENUM_ATTR_VPD_DRAM_RTT_NOM_DISABLE) - ) - { - if (eff_term_rd == 0) - { - eff_term_rd = - i_dram_rtt_nom[i_port][ma0odt01_dimm][ma0odt1_rank]; - } - else - { - eff_term_rd = - (eff_term_rd * - i_dram_rtt_nom[i_port][ma0odt01_dimm][ma0odt1_rank]) - / - (eff_term_rd + - i_dram_rtt_nom[i_port][ma0odt01_dimm][ma0odt1_rank]); - } - FAPI_DBG("[P%d:D%d:R%d] 0ODT1 RD TERMINATION = %4.2f (%d)", i_port, i_dimm, i_rank, eff_term_rd, i_dram_rtt_nom[i_port][ma0odt01_dimm][ma0odt1_rank]); - } -//------------------------------------------------------------------------------ -// 1ODT0 - if ( - ((i_dimm_rank_odt_rd[i_port][i_dimm][i_rank] & 0x20) != 0) - && - (i_dram_rtt_nom[i_port][ma1odt01_dimm][ma1odt0_rank] != - fapi::ENUM_ATTR_VPD_DRAM_RTT_NOM_DISABLE) - ) - { - if (eff_term_rd == 0) - { - eff_term_rd = - i_dram_rtt_nom[i_port][ma1odt01_dimm][ma1odt0_rank]; - } - else - { - eff_term_rd = - (eff_term_rd * - i_dram_rtt_nom[i_port][ma1odt01_dimm][ma1odt0_rank]) - / - (eff_term_rd + - i_dram_rtt_nom[i_port][ma1odt01_dimm][ma1odt0_rank]); - } - FAPI_DBG("[P%d:D%d:R%d] 1ODT0 RD TERMINATION = %4.2f (%d)", i_port, i_dimm, i_rank, eff_term_rd, i_dram_rtt_nom[i_port][ma1odt01_dimm][ma1odt0_rank]); - } -//------------------------------------------------------------------------------ -// 1ODT1 - if ( - ((i_dimm_rank_odt_rd[i_port][i_dimm][i_rank] & 0x10) != 0) - && - (i_dram_rtt_nom[i_port][ma1odt01_dimm][ma1odt1_rank] != - fapi::ENUM_ATTR_VPD_DRAM_RTT_NOM_DISABLE) - ) - { - if (eff_term_rd == 0) - { - eff_term_rd = - i_dram_rtt_nom[i_port][ma1odt01_dimm][ma1odt1_rank]; - } - else - { - eff_term_rd = - (eff_term_rd * - i_dram_rtt_nom[i_port][ma1odt01_dimm][ma1odt1_rank]) - / - (eff_term_rd + - i_dram_rtt_nom[i_port][ma1odt01_dimm][ma1odt1_rank]); - } - FAPI_DBG("[P%d:D%d:R%d] 1ODT1 RD TERMINATION = %4.2f (%d)", i_port, i_dimm, i_rank, eff_term_rd, i_dram_rtt_nom[i_port][ma1odt01_dimm][ma1odt1_rank]); - } - -// calculate out effective read termination - if (eff_term_rd != 0) - { - eff_net_term_rd = - (float( - (float(eff_term_rd * i_cen_dq_dqs_rcv_imp[i_port]) / - (eff_term_rd + i_cen_dq_dqs_rcv_imp[i_port])) - * i_dimm_dram_ron[i_port][i_dimm] - ) - / - ( - (float(eff_term_rd * i_cen_dq_dqs_rcv_imp[i_port]) / - (eff_term_rd + i_cen_dq_dqs_rcv_imp[i_port]) - ) - + i_dimm_dram_ron[i_port][i_dimm] - ) - ) - + - (float(eff_term_rd * i_cen_dq_dqs_rcv_imp[i_port]) / - (eff_term_rd + i_cen_dq_dqs_rcv_imp[i_port])); - term_odt_mult_rd = 1.25; - } - else - { - eff_net_term_rd = - (float((i_cen_dq_dqs_rcv_imp[i_port]) * - i_dimm_dram_ron[i_port][i_dimm]) - / ((i_cen_dq_dqs_rcv_imp[i_port]) + - i_dimm_dram_ron[i_port][i_dimm]) - ) - + - (i_cen_dq_dqs_rcv_imp[i_port]); - term_odt_mult_rd = 1; - } -// writes -//------------------------------------------------------------------------------ -// calculate out effective termination for writes -//------------------------------------------------------------------------------ - eff_term_wr = 0; - -// check to see if ODT is tied high (rank is not one of the ranks that get ODT -// driven to it, and rtt_wr or rtt_nom are enabled) - if ( - ( - (((i_rank != ma0odt0_rank) && (i_rank != ma0odt1_rank)) && - (i_dimm == 0)) - || - (((i_rank != ma1odt0_rank) && (i_rank != ma1odt1_rank)) && - (i_dimm == 1)) - ) - && - ((i_dram_rtt_wr[i_port][i_dimm][i_rank] != - fapi::ENUM_ATTR_VPD_DRAM_RTT_WR_DISABLE) || - (i_dram_rtt_nom[i_port][i_dimm][i_rank] != - fapi::ENUM_ATTR_VPD_DRAM_RTT_NOM_DISABLE)) - ) - { -// dynamic ODT enabled, so use rtt_wr (only if the rank being written to has -// it enabled) - if (i_dram_rtt_wr[i_port][i_dimm][i_rank] != - fapi::ENUM_ATTR_VPD_DRAM_RTT_WR_DISABLE) - { - if (eff_term_wr == 0) - { - eff_term_wr = i_dram_rtt_wr[i_port][i_dimm][i_rank]; - } - else - { - eff_term_wr = - (eff_term_wr * i_dram_rtt_wr[i_port][i_dimm][i_rank]) - / - (eff_term_wr + i_dram_rtt_wr[i_port][i_dimm][i_rank]); - } - } - - // dynamic ODT disabled, so use rtt_nom - else if (i_dram_rtt_nom[i_port][i_dimm][i_rank] != - fapi::ENUM_ATTR_VPD_DRAM_RTT_NOM_DISABLE) - { - if (eff_term_wr == 0) - { - eff_term_wr = i_dram_rtt_nom[i_port][i_dimm][i_rank]; - } - else - { - eff_term_wr = - (eff_term_wr * i_dram_rtt_nom[i_port][i_dimm][i_rank]) - / - (eff_term_wr + - i_dram_rtt_nom[i_port][i_dimm][i_rank]); - } - - } - FAPI_DBG("[P%d:D%d:R%d] WR TERMINATION = %4.2f (%d/%d)", i_port, i_dimm, i_rank, eff_term_wr, i_dram_rtt_wr[i_port][i_dimm][i_rank], i_dram_rtt_nom[i_port][i_dimm][i_rank]); - } -//------------------------------------------------------------------------------ -// 0ODT0 - if ( - ((i_dimm_rank_odt_wr[i_port][i_dimm][i_rank] & 0x80) != 0) - && - ((i_dram_rtt_wr[i_port][ma0odt01_dimm][ma0odt0_rank] != - fapi::ENUM_ATTR_VPD_DRAM_RTT_WR_DISABLE) || - (i_dram_rtt_nom[i_port][ma0odt01_dimm][ma0odt0_rank] != - fapi::ENUM_ATTR_VPD_DRAM_RTT_NOM_DISABLE)) - ) - { -// dynamic ODT enabled, so use rtt_wr (only if the rank being written to has -// it enabled) - if ( - (i_dram_rtt_wr[i_port][ma0odt01_dimm][ma0odt0_rank] != - fapi::ENUM_ATTR_VPD_DRAM_RTT_WR_DISABLE) - && (i_dimm == 0) - && (i_rank == ma0odt0_rank) - ) - { - if (eff_term_wr == 0) - { - eff_term_wr = - i_dram_rtt_wr[i_port][ma0odt01_dimm][ma0odt0_rank]; - } - else - { - eff_term_wr = - (eff_term_wr * - i_dram_rtt_wr[i_port][ma0odt01_dimm][ma0odt0_rank]) - / - (eff_term_wr + - i_dram_rtt_wr[i_port][ma0odt01_dimm][ma0odt0_rank]); - } - } - // dynamic ODT disabled, so use rtt_nom - else if (i_dram_rtt_nom[i_port][ma0odt01_dimm][ma0odt0_rank] != - fapi::ENUM_ATTR_VPD_DRAM_RTT_NOM_DISABLE) - { - if (eff_term_wr == 0) - { - eff_term_wr = - i_dram_rtt_nom[i_port][ma0odt01_dimm][ma0odt0_rank]; - } - else - { - eff_term_wr = - (eff_term_wr * - i_dram_rtt_nom[i_port][ma0odt01_dimm][ma0odt0_rank]) - / - (eff_term_wr + - i_dram_rtt_nom[i_port][ma0odt01_dimm][ma0odt0_rank]); - } - - } - FAPI_DBG("[P%d:D%d:R%d] 0ODT0 WR TERMINATION = %4.2f (%d/%d)", i_port, i_dimm, i_rank, eff_term_wr, i_dram_rtt_nom[i_port][ma0odt01_dimm][ma0odt0_rank], i_dram_rtt_wr[i_port][ma0odt01_dimm][ma0odt0_rank]); - } -//------------------------------------------------------------------------------ -// 0ODT1 - if ( - ((i_dimm_rank_odt_wr[i_port][i_dimm][i_rank] & 0x40) != 0) - && - ((i_dram_rtt_wr[i_port][ma0odt01_dimm][ma0odt1_rank] != - fapi::ENUM_ATTR_VPD_DRAM_RTT_WR_DISABLE) || - (i_dram_rtt_nom[i_port][ma0odt01_dimm][ma0odt1_rank] != - fapi::ENUM_ATTR_VPD_DRAM_RTT_NOM_DISABLE)) - ) - { -// dynamic ODT enabled, so use rtt_wr (only if the rank being written to has -// it enabled) - if ( - (i_dram_rtt_wr[i_port][ma0odt01_dimm][ma0odt1_rank] != - fapi::ENUM_ATTR_VPD_DRAM_RTT_WR_DISABLE) - && (i_dimm == 0) - && (i_rank == ma0odt1_rank) - ) - { - if (eff_term_wr == 0) - { - eff_term_wr = - i_dram_rtt_wr[i_port][ma0odt01_dimm][ma0odt1_rank]; - } - else - { - eff_term_wr = - (eff_term_wr * - i_dram_rtt_wr[i_port][ma0odt01_dimm][ma0odt1_rank]) - / - (eff_term_wr + - i_dram_rtt_wr[i_port][ma0odt01_dimm][ma0odt1_rank]); - } - } -// dynamic ODT disabled, so use rtt_nom - else if (i_dram_rtt_nom[i_port][ma0odt01_dimm][ma0odt1_rank] != - fapi::ENUM_ATTR_VPD_DRAM_RTT_NOM_DISABLE) - { - if (eff_term_wr == 0) - { - eff_term_wr = - i_dram_rtt_nom[i_port][ma0odt01_dimm][ma0odt1_rank]; - } - else - { - eff_term_wr = - (eff_term_wr * - i_dram_rtt_nom[i_port][ma0odt01_dimm][ma0odt1_rank]) - / - (eff_term_wr + - i_dram_rtt_nom[i_port][ma0odt01_dimm][ma0odt1_rank]); - } - - } - FAPI_DBG("[P%d:D%d:R%d] 0ODT1 WR TERMINATION = %4.2f (%d/%d)", i_port, i_dimm, i_rank, eff_term_wr, i_dram_rtt_nom[i_port][ma0odt01_dimm][ma0odt1_rank], i_dram_rtt_wr[i_port][ma0odt01_dimm][ma0odt1_rank]); - } -//------------------------------------------------------------------------------ -// 1ODT0 - if ( - ((i_dimm_rank_odt_wr[i_port][i_dimm][i_rank] & 0x20) != 0) - && - ((i_dram_rtt_wr[i_port][ma1odt01_dimm][ma1odt0_rank] != - fapi::ENUM_ATTR_VPD_DRAM_RTT_WR_DISABLE) || - (i_dram_rtt_nom[i_port][ma1odt01_dimm][ma1odt0_rank] != - fapi::ENUM_ATTR_VPD_DRAM_RTT_NOM_DISABLE)) - ) - { -// dynamic ODT enabled, so use rtt_wr (only if the rank being written to has -// it enabled) - if ( - (i_dram_rtt_wr[i_port][ma1odt01_dimm][ma1odt0_rank] != - fapi::ENUM_ATTR_VPD_DRAM_RTT_WR_DISABLE) - && (i_dimm == 1) - && (i_rank == ma1odt0_rank) - ) - { - if (eff_term_wr == 0) - { - eff_term_wr = - i_dram_rtt_wr[i_port][ma1odt01_dimm][ma1odt0_rank]; - } - else - { - eff_term_wr = - (eff_term_wr * - i_dram_rtt_wr[i_port][ma1odt01_dimm][ma1odt0_rank]) - / - (eff_term_wr + - i_dram_rtt_wr[i_port][ma1odt01_dimm][ma1odt0_rank]); - } - } - // dynamic ODT disabled, so use rtt_nom - else if (i_dram_rtt_nom[i_port][ma1odt01_dimm][ma1odt0_rank] != - fapi::ENUM_ATTR_VPD_DRAM_RTT_NOM_DISABLE) - { - if (eff_term_wr == 0) - { - eff_term_wr = - i_dram_rtt_nom[i_port][ma1odt01_dimm][ma1odt0_rank]; - } - else - { - eff_term_wr = - (eff_term_wr * - i_dram_rtt_nom[i_port][ma1odt01_dimm][ma1odt0_rank]) - / - (eff_term_wr + - i_dram_rtt_nom[i_port][ma1odt01_dimm][ma1odt0_rank]); - } - - } - FAPI_DBG("[P%d:D%d:R%d] 1ODT0 WR TERMINATION = %4.2f (%d/%d)", i_port, i_dimm, i_rank, eff_term_wr, i_dram_rtt_nom[i_port][ma1odt01_dimm][ma1odt0_rank], i_dram_rtt_wr[i_port][ma1odt01_dimm][ma1odt0_rank]); - } -//------------------------------------------------------------------------------ -// 1ODT1 - if ( - ((i_dimm_rank_odt_wr[i_port][i_dimm][i_rank] & 0x10) != 0) - && - ((i_dram_rtt_wr[i_port][ma1odt01_dimm][ma1odt1_rank] != - fapi::ENUM_ATTR_VPD_DRAM_RTT_WR_DISABLE) || - (i_dram_rtt_nom[i_port][ma1odt01_dimm][ma1odt1_rank] != - fapi::ENUM_ATTR_VPD_DRAM_RTT_NOM_DISABLE)) - ) - { -// dynamic ODT enabled, so use rtt_wr (only if the rank being written to has -// it enabled) - if ( - (i_dram_rtt_wr[i_port][ma1odt01_dimm][ma1odt1_rank] != - fapi::ENUM_ATTR_VPD_DRAM_RTT_WR_DISABLE) - && (i_dimm == 1) - && (i_rank == ma1odt1_rank) - ) - { - if (eff_term_wr == 0) - { - eff_term_wr = - i_dram_rtt_wr[i_port][ma1odt01_dimm][ma1odt1_rank]; - } - else - { - eff_term_wr = - (eff_term_wr * - i_dram_rtt_wr[i_port][ma1odt01_dimm][ma1odt1_rank]) - / - (eff_term_wr + - i_dram_rtt_wr[i_port][ma1odt01_dimm][ma1odt1_rank]); - } - } - // dynamic ODT disabled, so use rtt_nom - else if (i_dram_rtt_nom[i_port][ma1odt01_dimm][ma1odt1_rank] != - fapi::ENUM_ATTR_VPD_DRAM_RTT_NOM_DISABLE) - { - if (eff_term_wr == 0) - { - eff_term_wr = - i_dram_rtt_nom[i_port][ma1odt01_dimm][ma1odt1_rank]; - } - else - { - eff_term_wr = - (eff_term_wr * - i_dram_rtt_nom[i_port][ma1odt01_dimm][ma1odt1_rank]) - / - (eff_term_wr + - i_dram_rtt_nom[i_port][ma1odt01_dimm][ma1odt1_rank]); - } - - } - FAPI_DBG("[P%d:D%d:R%d] 1ODT1 WR TERMINATION = %4.2f (%d/%d)", i_port, i_dimm, i_rank, eff_term_wr, i_dram_rtt_nom[i_port][ma1odt01_dimm][ma1odt1_rank], i_dram_rtt_wr[i_port][ma1odt01_dimm][ma1odt1_rank]); - } - - -// Translate enum value to a resistance value for i_cen_dq_dqs_drv_imp[i_port] - rc = mss_eff_config_thermal_get_cen_drv_value - ( - i_cen_dq_dqs_drv_imp[i_port], - cen_dq_dqs_drv_imp_value - ); - if (rc) - { - FAPI_ERR("Error (0x%x) calling mss_eff_config_thermal_get_cen_drv_value", static_cast<uint32_t>(rc)); - return rc; - } - - if (eff_term_wr != 0) - { - eff_net_term_wr = - (float(eff_term_wr * cen_dq_dqs_drv_imp_value) / - (eff_term_wr + cen_dq_dqs_drv_imp_value)) + eff_term_wr; - term_odt_mult_wr = 1.25; - } - else - { - eff_net_term_wr = cen_dq_dqs_drv_imp_value; - term_odt_mult_wr = 1; - } - -//------------------------------------------------------------------------------ -// From Warren: -// Termination power = (voltage/net termination) * number of nets * -// (% of traffic on bus*1.25) -// The net termination is the effective termination that exists between the -// power rail and ground. So in my calculations this is all the active -// termination in parallel with the driver impedance + all the active -// termination in parallel. The value is different for reads and writes. -// Number of nets includes the strobe nets (2 nets per strobe) -// % of traffic on bus is the % of the bus used for data traffic split out from -// reads and writes. The 1.25 factor is due to the odt_en signals being active -// longer then the data windows. -// Value here is in Watts (W) - o_dimm_power_adder_termination = - float(i_dimm_voltage) / 1000 - * - ( - ((float(i_dimm_voltage) / 1000 / eff_net_term_rd) * - (number_nets_term_rd) * - (float(ACTIVE_DIMM_UTILIZATION) / 100) * - (float(DATA_BUS_READ_PERCENT) / 100) * (term_odt_mult_rd)) - + - ((float(i_dimm_voltage) / 1000 / eff_net_term_wr) * - (number_nets_term_wr) * - (float(ACTIVE_DIMM_UTILIZATION) / 100) * - (float(DATA_BUS_WRITE_PERCENT) / 100) * (term_odt_mult_wr)) - ); - FAPI_DBG("%s TERM:[P%d:D%d:R%d] CEN[DRV=%d RCV=%d] DRAM[DRV=%d ODT_RD=%4.2f ODT_WR=%4.2f]", i_nom_or_wc_term, i_port, i_dimm, i_rank, cen_dq_dqs_drv_imp_value, i_cen_dq_dqs_rcv_imp[i_port], i_dimm_dram_ron[i_port][i_dimm], eff_term_rd, eff_term_wr); - FAPI_DBG("%s TERM POWER:[P%d:D%d:R%d] RD[Nets=%d EffTerm=%3.2f ODTMult=%1.2f] WR[Nets=%d EffTerm=%3.2f ODTMult=%1.2f] TermPower(%d%%)=%2.2f W", i_nom_or_wc_term, i_port, i_dimm, i_rank, number_nets_term_rd, eff_net_term_rd, term_odt_mult_rd, number_nets_term_wr, eff_net_term_wr, term_odt_mult_wr, ACTIVE_DIMM_UTILIZATION, o_dimm_power_adder_termination); - } - else - { -// rank not configured, so it has no termination power associated with it - o_dimm_power_adder_termination = 0; - } - - FAPI_IMP("*** %s COMPLETE ***", procedure_name); - return rc; - } - -//------------------------------------------------------------------------------ -// @brief mss_eff_config_thermal_get_wc_term(): This function finds the worst -// case termination settings possible for a given set of termination settings -// -// @param[in] const fapi::Target &i_target_mba: MBA Target -// @param[in] uint8_t i_port: MBA port being worked on -// @param[out] uint8_t &o_cen_dq_dqs_rcv_imp_wc: Worst Case Centaur DQ/DQS -// receiver impedance (output) -// @param[out] uint8_t &o_cen_dq_dqs_drv_imp_wc: Worst Case Centaur DQ/DQS -// driver impedance (output) -// -// @return fapi::ReturnCode -//------------------------------------------------------------------------------ - - fapi::ReturnCode mss_eff_config_thermal_get_wc_term - ( - const fapi::Target &i_target_mba, - uint8_t i_port, - uint8_t &o_cen_dq_dqs_rcv_imp_wc, - uint8_t &o_cen_dq_dqs_drv_imp_wc - ) - { - fapi::ReturnCode rc = fapi::FAPI_RC_SUCCESS; - - const char * procedure_name = "mss_eff_config_thermal_get_wc_term"; - - FAPI_IMP("*** Running %s ***", procedure_name); - - uint8_t l_cen_dq_dqs_rcv_imp[NUM_PORTS]; - uint8_t l_cen_dq_dqs_drv_imp[NUM_PORTS]; - uint32_t l_cen_dq_dqs_rcv_imp_schmoo[NUM_PORTS]; - uint32_t l_cen_dq_dqs_drv_imp_schmoo[NUM_PORTS]; - uint32_t l_loop; - uint32_t l_schmoo_mask; - -// This lists out the number and enum values for the centaur dq/dqs receiver and -// driver impedance. Have the list go from strongest to weakest termination. -// If the size changes at all, then updates are needed below to get the correct -// mask - - const uint8_t MAX_CEN_RCV_IMP = 10; - uint8_t cen_rcv_imp_array[] = { - fapi::ENUM_ATTR_EFF_CEN_RCV_IMP_DQ_DQS_OHM15, - fapi::ENUM_ATTR_EFF_CEN_RCV_IMP_DQ_DQS_OHM20, - fapi::ENUM_ATTR_EFF_CEN_RCV_IMP_DQ_DQS_OHM30, - fapi::ENUM_ATTR_EFF_CEN_RCV_IMP_DQ_DQS_OHM40, - fapi::ENUM_ATTR_EFF_CEN_RCV_IMP_DQ_DQS_OHM48, - fapi::ENUM_ATTR_EFF_CEN_RCV_IMP_DQ_DQS_OHM60, - fapi::ENUM_ATTR_EFF_CEN_RCV_IMP_DQ_DQS_OHM80, - fapi::ENUM_ATTR_EFF_CEN_RCV_IMP_DQ_DQS_OHM120, - fapi::ENUM_ATTR_EFF_CEN_RCV_IMP_DQ_DQS_OHM160, - fapi::ENUM_ATTR_EFF_CEN_RCV_IMP_DQ_DQS_OHM240 - }; - - const uint8_t MAX_CEN_DRV_IMP = 16; - uint8_t cen_drv_imp_array[] = { - fapi::ENUM_ATTR_EFF_CEN_DRV_IMP_DQ_DQS_OHM24_FFE0, - fapi::ENUM_ATTR_EFF_CEN_DRV_IMP_DQ_DQS_OHM30_FFE0, - fapi::ENUM_ATTR_EFF_CEN_DRV_IMP_DQ_DQS_OHM30_FFE480, - fapi::ENUM_ATTR_EFF_CEN_DRV_IMP_DQ_DQS_OHM30_FFE240, - fapi::ENUM_ATTR_EFF_CEN_DRV_IMP_DQ_DQS_OHM30_FFE160, - fapi::ENUM_ATTR_EFF_CEN_DRV_IMP_DQ_DQS_OHM30_FFE120, - fapi::ENUM_ATTR_EFF_CEN_DRV_IMP_DQ_DQS_OHM34_FFE0, - fapi::ENUM_ATTR_EFF_CEN_DRV_IMP_DQ_DQS_OHM34_FFE480, - fapi::ENUM_ATTR_EFF_CEN_DRV_IMP_DQ_DQS_OHM34_FFE240, - fapi::ENUM_ATTR_EFF_CEN_DRV_IMP_DQ_DQS_OHM34_FFE160, - fapi::ENUM_ATTR_EFF_CEN_DRV_IMP_DQ_DQS_OHM34_FFE120, - fapi::ENUM_ATTR_EFF_CEN_DRV_IMP_DQ_DQS_OHM40_FFE0, - fapi::ENUM_ATTR_EFF_CEN_DRV_IMP_DQ_DQS_OHM40_FFE480, - fapi::ENUM_ATTR_EFF_CEN_DRV_IMP_DQ_DQS_OHM40_FFE240, - fapi::ENUM_ATTR_EFF_CEN_DRV_IMP_DQ_DQS_OHM40_FFE160, - fapi::ENUM_ATTR_EFF_CEN_DRV_IMP_DQ_DQS_OHM40_FFE120 - }; - - -// Get attributes for nominal settings and possible settings to choose from - rc = FAPI_ATTR_GET(ATTR_EFF_CEN_RCV_IMP_DQ_DQS, - &i_target_mba, l_cen_dq_dqs_rcv_imp); - if (rc) { - FAPI_ERR("Error getting attribute ATTR_EFF_CEN_RCV_IMP_DQ_DQS"); - return rc; - } - rc = FAPI_ATTR_GET(ATTR_EFF_CEN_DRV_IMP_DQ_DQS, - &i_target_mba, l_cen_dq_dqs_drv_imp); - if (rc) { - FAPI_ERR("Error getting attribute ATTR_EFF_CEN_DRV_IMP_DQ_DQS"); - return rc; - } - rc = FAPI_ATTR_GET(ATTR_EFF_CEN_RCV_IMP_DQ_DQS_SCHMOO, - &i_target_mba, l_cen_dq_dqs_rcv_imp_schmoo); - if (rc) { - FAPI_ERR("Error getting attribute ATTR_EFF_CEN_RCV_IMP_DQ_DQS_SCHMOO"); - return rc; - } - rc = FAPI_ATTR_GET(ATTR_EFF_CEN_DRV_IMP_DQ_DQS_SCHMOO, - &i_target_mba, l_cen_dq_dqs_drv_imp_schmoo); - if (rc) { - FAPI_ERR("Error getting attribute ATTR_EFF_CEN_DRV_IMP_DQ_DQS_SCHMOO"); - return rc; - } - -// initialize to default values in case below does not find a match - o_cen_dq_dqs_rcv_imp_wc = l_cen_dq_dqs_rcv_imp[i_port]; - o_cen_dq_dqs_drv_imp_wc = l_cen_dq_dqs_drv_imp[i_port]; - -// find strongest termination setting that could be used, if none found, then -// use nominal - l_schmoo_mask = 0x00000000; - for (l_loop=0; l_loop < MAX_CEN_RCV_IMP; l_loop++) - { - switch (l_loop) - { - case 0: - l_schmoo_mask = 0x80000000; - break; - case 1: - l_schmoo_mask = 0x40000000; - break; - case 2: - l_schmoo_mask = 0x20000000; - break; - case 3: - l_schmoo_mask = 0x10000000; - break; - case 4: - l_schmoo_mask = 0x08000000; - break; - case 5: - l_schmoo_mask = 0x04000000; - break; - case 6: - l_schmoo_mask = 0x02000000; - break; - case 7: - l_schmoo_mask = 0x01000000; - break; - case 8: - l_schmoo_mask = 0x00800000; - break; - case 9: - l_schmoo_mask = 0x00400000; - break; - default: - o_cen_dq_dqs_rcv_imp_wc = l_cen_dq_dqs_rcv_imp[i_port]; - } - if ((l_cen_dq_dqs_rcv_imp_schmoo[i_port] & l_schmoo_mask) != 0) - { - o_cen_dq_dqs_rcv_imp_wc = cen_rcv_imp_array[l_loop]; - break; - } - } - - l_schmoo_mask = 0x00000000; - for (l_loop=0; l_loop < MAX_CEN_DRV_IMP; l_loop++) - { - switch (l_loop) - { - case 0: - l_schmoo_mask = 0x80000000; - break; - case 1: - l_schmoo_mask = 0x40000000; - break; - case 2: - l_schmoo_mask = 0x20000000; - break; - case 3: - l_schmoo_mask = 0x10000000; - break; - case 4: - l_schmoo_mask = 0x08000000; - break; - case 5: - l_schmoo_mask = 0x04000000; - break; - case 6: - l_schmoo_mask = 0x02000000; - break; - case 7: - l_schmoo_mask = 0x01000000; - break; - case 8: - l_schmoo_mask = 0x00800000; - break; - case 9: - l_schmoo_mask = 0x00400000; - break; - case 10: - l_schmoo_mask = 0x00200000; - break; - case 11: - l_schmoo_mask = 0x00100000; - break; - case 12: - l_schmoo_mask = 0x00080000; - break; - case 13: - l_schmoo_mask = 0x00040000; - break; - case 14: - l_schmoo_mask = 0x00020000; - break; - case 15: - l_schmoo_mask = 0x00010000; - break; - default: - o_cen_dq_dqs_drv_imp_wc = l_cen_dq_dqs_drv_imp[i_port]; - } - if ((l_cen_dq_dqs_drv_imp_schmoo[i_port] & l_schmoo_mask) != 0) - { - o_cen_dq_dqs_drv_imp_wc = cen_drv_imp_array[l_loop]; - break; - } - } - - FAPI_IMP("*** %s COMPLETE ***", procedure_name); - return rc; - } - - -//------------------------------------------------------------------------------ -// @brief mss_eff_config_thermal_get_cen_drv_value(): This function will -// translate the centaur driver impedance enum value to a termination resistance -// -// @param[in] uint8_t &i_cen_dq_dqs_drv_imp: Centaur DQ/DQS driver impedance -// enum setting (input) -// @param[out] uint8_t &o_cen_dq_dqs_drv_imp: Centaur DQ/DQS driver impedance -// value (output) -// -// @return fapi::ReturnCode -//------------------------------------------------------------------------------ - - fapi::ReturnCode mss_eff_config_thermal_get_cen_drv_value - ( - uint8_t i_cen_dq_dqs_drv_imp, - uint8_t &o_cen_dq_dqs_drv_imp - ) - { - fapi::ReturnCode rc = fapi::FAPI_RC_SUCCESS; - - const char* procedure_name = "mss_eff_config_thermal_get_cen_drv_value"; - - FAPI_IMP("*** Running %s ***", procedure_name); - - switch (i_cen_dq_dqs_drv_imp) - { - case fapi::ENUM_ATTR_EFF_CEN_DRV_IMP_DQ_DQS_OHM24_FFE0: - o_cen_dq_dqs_drv_imp = 24; - break; - case fapi::ENUM_ATTR_EFF_CEN_DRV_IMP_DQ_DQS_OHM30_FFE0: - o_cen_dq_dqs_drv_imp = 30; - break; - case fapi::ENUM_ATTR_EFF_CEN_DRV_IMP_DQ_DQS_OHM30_FFE480: - o_cen_dq_dqs_drv_imp = 30; - break; - case fapi::ENUM_ATTR_EFF_CEN_DRV_IMP_DQ_DQS_OHM30_FFE240: - o_cen_dq_dqs_drv_imp = 30; - break; - case fapi::ENUM_ATTR_EFF_CEN_DRV_IMP_DQ_DQS_OHM30_FFE160: - o_cen_dq_dqs_drv_imp = 30; - break; - case fapi::ENUM_ATTR_EFF_CEN_DRV_IMP_DQ_DQS_OHM30_FFE120: - o_cen_dq_dqs_drv_imp = 30; - break; - case fapi::ENUM_ATTR_EFF_CEN_DRV_IMP_DQ_DQS_OHM34_FFE0: - o_cen_dq_dqs_drv_imp = 34; - break; - case fapi::ENUM_ATTR_EFF_CEN_DRV_IMP_DQ_DQS_OHM34_FFE480: - o_cen_dq_dqs_drv_imp = 34; - break; - case fapi::ENUM_ATTR_EFF_CEN_DRV_IMP_DQ_DQS_OHM34_FFE240: - o_cen_dq_dqs_drv_imp = 34; - break; - case fapi::ENUM_ATTR_EFF_CEN_DRV_IMP_DQ_DQS_OHM34_FFE160: - o_cen_dq_dqs_drv_imp = 34; - break; - case fapi::ENUM_ATTR_EFF_CEN_DRV_IMP_DQ_DQS_OHM34_FFE120: - o_cen_dq_dqs_drv_imp = 34; - break; - case fapi::ENUM_ATTR_EFF_CEN_DRV_IMP_DQ_DQS_OHM40_FFE0: - o_cen_dq_dqs_drv_imp = 40; - break; - case fapi::ENUM_ATTR_EFF_CEN_DRV_IMP_DQ_DQS_OHM40_FFE480: - o_cen_dq_dqs_drv_imp = 40; - break; - case fapi::ENUM_ATTR_EFF_CEN_DRV_IMP_DQ_DQS_OHM40_FFE240: - o_cen_dq_dqs_drv_imp = 40; - break; - case fapi::ENUM_ATTR_EFF_CEN_DRV_IMP_DQ_DQS_OHM40_FFE160: - o_cen_dq_dqs_drv_imp = 40; - break; - case fapi::ENUM_ATTR_EFF_CEN_DRV_IMP_DQ_DQS_OHM40_FFE120: - o_cen_dq_dqs_drv_imp = 40; - break; - default: - o_cen_dq_dqs_drv_imp = 24; - } - - FAPI_IMP("*** %s COMPLETE ***", procedure_name); - return rc; - } - - } //end extern C |