summaryrefslogtreecommitdiffstats
path: root/src/usr/hwpf/hwp/mc_config
diff options
context:
space:
mode:
authorVan Lee <vanlee@us.ibm.com>2012-09-11 13:06:45 -0500
committerA. Patrick Williams III <iawillia@us.ibm.com>2012-09-24 12:06:11 -0500
commit79bfb2c828042294a30fe8f37aa090333df82736 (patch)
treeef3f052835ca9278f30d008a39563c40d53e7346 /src/usr/hwpf/hwp/mc_config
parent587478c754f06fa5e23893eabd62afd41f1fd12f (diff)
downloadtalos-hostboot-79bfb2c828042294a30fe8f37aa090333df82736.tar.gz
talos-hostboot-79bfb2c828042294a30fe8f37aa090333df82736.zip
integrate new version of existing HWPs into hostboot
- added mss_eff_config_rank_group.C Change-Id: Ie6b2b2b81137892d6753e1497cfe877852ff30a5 Reviewed-on: http://gfw160.austin.ibm.com:8080/gerrit/1720 Tested-by: Jenkins Server Reviewed-by: Van H. Lee <vanlee@us.ibm.com> Reviewed-by: Brian H. Horton <brianh@linux.ibm.com> Reviewed-by: Thi N. Tran <thi@us.ibm.com> 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_eff_config.C60
-rw-r--r--src/usr/hwpf/hwp/mc_config/mss_eff_config/mss_eff_config_rank_group.C61
-rw-r--r--src/usr/hwpf/hwp/mc_config/mss_eff_config/mss_eff_config_thermal.C374
3 files changed, 288 insertions, 207 deletions
diff --git a/src/usr/hwpf/hwp/mc_config/mss_eff_config/mss_eff_config.C b/src/usr/hwpf/hwp/mc_config/mss_eff_config/mss_eff_config.C
index 53f5723ce..0cc83b26e 100644
--- a/src/usr/hwpf/hwp/mc_config/mss_eff_config/mss_eff_config.C
+++ b/src/usr/hwpf/hwp/mc_config/mss_eff_config/mss_eff_config.C
@@ -1,27 +1,26 @@
-/* IBM_PROLOG_BEGIN_TAG
- * This is an automatically generated prolog.
- *
- * $Source: src/usr/hwpf/hwp/mc_init/mss_eff_config/mss_eff_config.C $
- *
- * IBM CONFIDENTIAL
- *
- * COPYRIGHT International Business Machines Corp. 2012
- *
- * p1
- *
- * Object Code Only (OCO) source materials
- * Licensed Internal Code Source Materials
- * IBM HostBoot Licensed Internal Code
- *
- * The source code for this program is not published or other-
- * wise divested of its trade secrets, irrespective of what has
- * been deposited with the U.S. Copyright Office.
- *
- * Origin: 30
- *
- * IBM_PROLOG_END_TAG
- */
-// $Id: mss_eff_config.C,v 1.9 2012/06/07 01:16:03 asaetow Exp $
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/usr/hwpf/hwp/mc_config/mss_eff_config/mss_eff_config.C $ */
+/* */
+/* IBM CONFIDENTIAL */
+/* */
+/* COPYRIGHT International Business Machines Corp. 2012 */
+/* */
+/* p1 */
+/* */
+/* Object Code Only (OCO) source materials */
+/* Licensed Internal Code Source Materials */
+/* IBM HostBoot Licensed Internal Code */
+/* */
+/* The source code for this program is not published or otherwise */
+/* divested of its trade secrets, irrespective of what has been */
+/* deposited with the U.S. Copyright Office. */
+/* */
+/* Origin: 30 */
+/* */
+/* IBM_PROLOG_END_TAG */
+// $Id: mss_eff_config.C,v 1.10 2012/08/02 18:31:50 bellows Exp $
// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/centaur/working/procedures/ipl/fapi/mss_eff_config.C,v $
//------------------------------------------------------------------------------
// *! (C) Copyright International Business Machines Corp. 2011
@@ -43,7 +42,7 @@
//------------------------------------------------------------------------------
// Version:| Author: | Date: | Comment:
//---------|----------|---------|-----------------------------------------------
-// 1.10 | | |
+// 1.10 | bellows |02-AUG-12| Added in DIMM functional vector for Daniel
// 1.9 | asaetow |29-MAY-12| Added divide by 0 check for mss_freq.
// | | | Added 9 new attributes from memory_attributes.xml v1.23
// | | | Changed plug_config to my_attr_eff_num_drops_per_port.
@@ -140,6 +139,8 @@ fapi::ReturnCode mss_eff_config(const fapi::Target i_target_mba) {
uint8_t cur_dimm_spd_valid_u8array[PORT_SIZE][DIMM_SIZE] = {{0}};
uint8_t cur_mba_port = 0;
uint8_t cur_mba_dimm = 0;
+ uint8_t dimm_functional_vector = 0x00;
+ uint8_t dimm_functional=0;
uint8_t cur_dram_density = 0;
uint32_t mss_freq = 0;
uint32_t mss_volt = 0;
@@ -297,6 +298,13 @@ fapi::ReturnCode mss_eff_config(const fapi::Target i_target_mba) {
rc = FAPI_ATTR_GET(ATTR_MBA_DIMM, &l_target_dimm_array[dimm_index], cur_mba_dimm); if(rc) return rc;
cur_dimm_spd_valid_u8array[cur_mba_port][cur_mba_dimm] = VALID;
+ rc = FAPI_ATTR_GET(ATTR_FUNCTIONAL, &l_target_dimm_array[dimm_index], dimm_functional); if(rc) return rc;
+ if(dimm_functional == fapi::ENUM_ATTR_FUNCTIONAL_FUNCTIONAL)
+ dimm_functional=1;
+ else
+ dimm_functional=0;
+ dimm_functional_vector |= dimm_functional << ((4*(1-cur_mba_port))+(4-cur_mba_dimm)-1);
+
rc = FAPI_ATTR_GET(ATTR_SPD_DRAM_DEVICE_TYPE, &l_target_dimm_array[dimm_index], spd_dram_device_type_u8array[cur_mba_port][cur_mba_dimm]); if(rc) return rc;
rc = FAPI_ATTR_GET(ATTR_SPD_MODULE_TYPE, &l_target_dimm_array[dimm_index], spd_module_type_u8array[cur_mba_port][cur_mba_dimm]); if(rc) return rc;
rc = FAPI_ATTR_GET(ATTR_SPD_SDRAM_BANKS, &l_target_dimm_array[dimm_index], spd_sdram_banks_u8array[cur_mba_port][cur_mba_dimm]); if(rc) return rc;
@@ -673,7 +681,7 @@ fapi::ReturnCode mss_eff_config(const fapi::Target i_target_mba) {
rc = FAPI_ATTR_SET(ATTR_EFF_SCHMOO_TEST_VALID, &i_target_mba, my_attr_eff_schmoo_test_valid); if(rc) return rc;
rc = FAPI_ATTR_SET(ATTR_EFF_STACK_TYPE, &i_target_mba, my_attr_eff_stack_type); if(rc) return rc;
rc = FAPI_ATTR_SET(ATTR_EFF_ZQCAL_INTERVAL, &i_target_mba, my_attr_eff_zqcal_interval); if(rc) return rc;
-
+ rc = FAPI_ATTR_SET(ATTR_MSS_EFF_DIMM_FUNCTIONAL_VECTOR, &i_target_mba, dimm_functional_vector); if(rc) return rc;
// Calls to sub-procedures
rc = mss_eff_config_rank_group(i_target_mba); if(rc) return rc;
diff --git a/src/usr/hwpf/hwp/mc_config/mss_eff_config/mss_eff_config_rank_group.C b/src/usr/hwpf/hwp/mc_config/mss_eff_config/mss_eff_config_rank_group.C
index 399a91e09..01ab2b3e0 100644
--- a/src/usr/hwpf/hwp/mc_config/mss_eff_config/mss_eff_config_rank_group.C
+++ b/src/usr/hwpf/hwp/mc_config/mss_eff_config/mss_eff_config_rank_group.C
@@ -1,27 +1,26 @@
-/* IBM_PROLOG_BEGIN_TAG
- * This is an automatically generated prolog.
- *
- * $Source: src/usr/hwpf/hwp/mc_config/mss_eff_config/mss_eff_config_rank_group.C $
- *
- * IBM CONFIDENTIAL
- *
- * COPYRIGHT International Business Machines Corp. 2012
- *
- * p1
- *
- * Object Code Only (OCO) source materials
- * Licensed Internal Code Source Materials
- * IBM HostBoot Licensed Internal Code
- *
- * The source code for this program is not published or other-
- * wise divested of its trade secrets, irrespective of what has
- * been deposited with the U.S. Copyright Office.
- *
- * Origin: 30
- *
- * IBM_PROLOG_END_TAG
- */
-// $Id: mss_eff_config_rank_group.C,v 1.6 2012/04/30 15:11:46 asaetow Exp $
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/usr/hwpf/hwp/mc_config/mss_eff_config/mss_eff_config_rank_group.C $ */
+/* */
+/* IBM CONFIDENTIAL */
+/* */
+/* COPYRIGHT International Business Machines Corp. 2012 */
+/* */
+/* p1 */
+/* */
+/* Object Code Only (OCO) source materials */
+/* Licensed Internal Code Source Materials */
+/* IBM HostBoot Licensed Internal Code */
+/* */
+/* The source code for this program is not published or otherwise */
+/* divested of its trade secrets, irrespective of what has been */
+/* deposited with the U.S. Copyright Office. */
+/* */
+/* Origin: 30 */
+/* */
+/* IBM_PROLOG_END_TAG */
+// $Id: mss_eff_config_rank_group.C,v 1.8 2012/08/30 03:07:27 asaetow Exp $
// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/centaur/working/procedures/ipl/fapi/mss_eff_config_rank_group.C,v $
//------------------------------------------------------------------------------
// *! (C) Copyright International Business Machines Corp. 2011
@@ -47,7 +46,9 @@
//------------------------------------------------------------------------------
// Version:| Author: | Date: | Comment:
//---------|----------|---------|-----------------------------------------------
-// 1.7 | | |
+// 1.9 | | |
+// 1.8 | asaetow |29-AUG-12| Fixed variable init for rank_group to INVALID for PORT1.
+// 1.7 | asaetow |24-AUG-12| Fixed variable init for rank_group to INVALID.
// 1.6 | asaetow |30-APR-12| Fixed "fapi::" for hostboot, added "const", renamed "i_target_mba", and changed comments.
// | | | Changed message to standardized format.
// | | | Changed BACKUP to Mark Bellows.
@@ -179,13 +180,15 @@ fapi::ReturnCode mss_eff_config_rank_group(const fapi::Target i_target_mba) {
}
primary_rank_group0_u8array[cur_port] = 0;
primary_rank_group1_u8array[cur_port] = 4;
+ primary_rank_group2_u8array[cur_port] = INVALID;
+ primary_rank_group3_u8array[cur_port] = INVALID;
+ secondary_rank_group0_u8array[cur_port] = INVALID;
+ secondary_rank_group1_u8array[cur_port] = INVALID;
+ secondary_rank_group2_u8array[cur_port] = INVALID;
+ secondary_rank_group3_u8array[cur_port] = INVALID;
if (num_ranks_per_dimm_u8array[cur_port][0] == 2) {
primary_rank_group2_u8array[cur_port] = 1;
primary_rank_group3_u8array[cur_port] = 5;
- secondary_rank_group0_u8array[cur_port] = INVALID;
- secondary_rank_group1_u8array[cur_port] = INVALID;
- secondary_rank_group2_u8array[cur_port] = INVALID;
- secondary_rank_group3_u8array[cur_port] = INVALID;
} else if (num_ranks_per_dimm_u8array[cur_port][0] == 4) {
primary_rank_group2_u8array[cur_port] = 2;
primary_rank_group3_u8array[cur_port] = 6;
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 64809e94a..e8c23eda6 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
@@ -1,27 +1,26 @@
-/* IBM_PROLOG_BEGIN_TAG
- * This is an automatically generated prolog.
- *
- * $Source: src/usr/hwpf/hwp/mc_config/mss_eff_config/mss_eff_config_thermal.C $
- *
- * IBM CONFIDENTIAL
- *
- * COPYRIGHT International Business Machines Corp. 2012
- *
- * p1
- *
- * Object Code Only (OCO) source materials
- * Licensed Internal Code Source Materials
- * IBM HostBoot Licensed Internal Code
- *
- * The source code for this program is not published or other-
- * wise divested of its trade secrets, irrespective of what has
- * been deposited with the U.S. Copyright Office.
- *
- * Origin: 30
- *
- * IBM_PROLOG_END_TAG
- */
-// $Id: mss_eff_config_thermal.C,v 1.7 2012/05/04 15:53:44 pardeik Exp $
+/* IBM_PROLOG_BEGIN_TAG */
+/* This is an automatically generated prolog. */
+/* */
+/* $Source: src/usr/hwpf/hwp/mc_config/mss_eff_config/mss_eff_config_thermal.C $ */
+/* */
+/* IBM CONFIDENTIAL */
+/* */
+/* COPYRIGHT International Business Machines Corp. 2012 */
+/* */
+/* p1 */
+/* */
+/* Object Code Only (OCO) source materials */
+/* Licensed Internal Code Source Materials */
+/* IBM HostBoot Licensed Internal Code */
+/* */
+/* The source code for this program is not published or otherwise */
+/* divested of its trade secrets, irrespective of what has been */
+/* deposited with the U.S. Copyright Office. */
+/* */
+/* Origin: 30 */
+/* */
+/* IBM_PROLOG_END_TAG */
+// $Id: mss_eff_config_thermal.C,v 1.8 2012/06/13 20:53:57 pardeik Exp $
// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/centaur/working/procedures/ipl/fapi/mss_eff_config_thermal.C,v $
//------------------------------------------------------------------------------
// *! (C) Copyright International Business Machines Corp. 2011
@@ -38,14 +37,12 @@
// The purpose of this procedure is to set the default throttle and power attributes for dimms in a given system
// -- The throttles here are intended to be the thermal runtime throttles for dimm/channel N/M
// -- The power attributes are the slope/intercept values. Note that these values are in cW.
-// -- The values are determined by system based on power/thermal characterization
+// -- The power values are determined by DRAM Generation and Width (with various uplifts/adders applied)
+// and will be derived from the model and then verified with hardware measurements
+// -- Power will be per rank for a given dram generation and width
+// -- Uplifts will be applied for dimm type, number of ranks
// -- Thermal values are system dependent and will need to come from the machine readable workbook
-// -- Power values are going to be based on measurements and uplifted as needed based on voltage, frequency, termination, etc.
//
-// TODO:
-// 1. Thermal attributes (IPL and Runtime Throttles) need to come from machine readable workbook
-// 2. Uplifts need to be done based on volt, freq, termination, etc.
-// 3. Power values need to be updated/added for the dimms that will be supported
//
//------------------------------------------------------------------------------
// Don't forget to create CVS comments when you check in your changes!
@@ -54,6 +51,7 @@
//------------------------------------------------------------------------------
// Version:| Author: | Date: | Comment:
//---------|----------|---------|-----------------------------------------------
+// 1.8 | pardeik |13-JUN-12| Major rewrite to have dimm power determined by dram generation and width, with uplifts applied (not based on dimm size lookup table any longer)
// 1.7 | pardeik |04-MAY-12| removed typedef from structures, use fapi to define dimm type enums
// 1.6 | pardeik |10-APR-12| update cdimm power/int default, change power_thermal_values_t to use int32_t instead of uint32_t in order to identify a negative value correctly, added dimm config to the messages printed out
// 1.5 | pardeik |03-APR-12| fix cdimm size/rank addition to cycle through both mba's
@@ -96,204 +94,276 @@ extern "C" {
RDIMM = fapi::ENUM_ATTR_EFF_DIMM_TYPE_RDIMM,
UDIMM = fapi::ENUM_ATTR_EFF_DIMM_TYPE_UDIMM,
LRDIMM = fapi::ENUM_ATTR_EFF_DIMM_TYPE_LRDIMM,
+ 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,
};
-// number of dimms on channel/port
- enum
+// Structure types for the table that holds dimm power and adjustment values that will be used
+
+ struct dimm_power_t
{
- SINGLEDROP = 0,
- DOUBLEDROP = 1,
- DIMM_CONFIG_TYPES = 2, // count of all possible various dimm configurations on port
+ uint32_t idle;
+ uint32_t max;
};
-
-// Structure type for the table that holds dimm power slope and intercept values
-// use int32_t for slope and intercept in case values are entered wrong (ie. negative values will then be flagged)
- struct power_thermal_values_t
+ struct dimm_type_t
+ {
+ int32_t udimm;
+ int32_t lrdimm;
+ int32_t rdimm;
+ int32_t cdimm;
+ };
+ struct dimm_voltage_t
{
- int32_t power_slope;
- int32_t power_int;
+ int8_t volt1500;
+ int8_t volt1350;
+ int8_t volt1200;
};
- struct power_thermal_data_t
+ struct dimm_frequency_t
{
- uint32_t dimm_type;
- uint32_t dimm_size;
- uint8_t dimm_ranks;
- power_thermal_values_t data[DIMM_CONFIG_TYPES];
+ int8_t freq1066;
+ int8_t freq1333;
+ int8_t freq1600;
};
+ struct power_data_t
+ {
+ uint8_t dram_generation;
+ uint8_t dram_width;
+ uint8_t dimm_ranks;
+ dimm_power_t rank_master_power;
+ dimm_type_t dimm_type_adder;
+ dimm_power_t rank_slave_adder;
+ dimm_voltage_t dimm_voltage_adder;
+ dimm_frequency_t dimm_frequency_adder;
+ };
+
+power_data_t l_power_table[] =
+{
+// 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 = l_dimm_master_ranks_array OR 1)
+//
+// Note: Slave rank full bw is set to idle, since the active power for full bw will be acounted for the master rank (ie. only one rank active at a time). Set slave rank full bw to the slave rank idle bw power value.
+//
+// DRAM DRAM Master MasterRankPower DIMMTypeAdder SlaveRankAdder VoltageAdder FrequencyAdder
+// Generation Width Ranks (cW) (cW) (cW) (%) (%)
+// DDR3 X4 1 idle,full UDIMM,LRDIMM, idle,full 1.5,1.35,1.2 1066,1333,1600
+// or or RDIMM,CDIMM
+// DDR4 X8
+//
+
+// TODO: Finalize these values against model. These are just place holders for now and will work for the time being.
+ { DDR3, X4, 1, { 65,650}, {0,50,100,0}, { 65,65}, {10,0,-10}, {0,10,20} },
+ { DDR3, X8, 1, { 50,500}, {0,50,100,0}, { 50,50}, {10,0,-10}, {0,10,20} },
+ { DDR4, X4, 1, { 65,650}, {0,50,100,0}, { 65,65}, {10,0,-10}, {0,10,20} },
+ { DDR4, X8, 1, { 50,500}, {0,50,100,0}, { 50,50}, {10,0,-10}, {0,10,20} },
+};
+
// Default values defined here
const uint8_t l_num_ports = 2; // number of ports per MBA
const uint8_t l_num_dimms = 2; // number of dimms per MBA port
- const uint32_t l_dimm_power_slope_default = 800; // default power slope for rdimm, udimm, lrdimm
- const uint32_t l_dimm_power_int_default = 900; // default power intercept for rdimm, udimm, lrdimm
- const uint32_t l_cdimm_power_slope_default = 2000; // default power slope for cdimm
- const uint32_t l_cdimm_power_int_default = 700; // default power intercept for cdimm
+ const uint32_t l_dimm_power_slope_default = 940; // default power slope (cW/utilization)
+ const uint32_t l_dimm_power_int_default = 900; // default power intercept (cW)
const uint32_t l_dimm_throttle_n_default = 100; // default dimm throttle numerator
const uint32_t l_dimm_throttle_d_default = 100; // default dimm throttle denominator
const uint32_t l_channel_throttle_n_default = 100; // default channel throttle numerator
const uint32_t l_channel_throttle_d_default = 100; // default channel throttle denominator
+ const uint8_t l_idle_dimm_utilization = 0; // DRAM data bus utilization for the idle power defined in table below
+ const uint8_t l_max_dimm_utilization = 100; // DRAM data bus utilization for the active power defined in table below
+
// other variables used in this procedure
+ fapi::Target l_targetCentaur;
+ std::vector<fapi::Target> l_targetDimm;
uint8_t port;
uint8_t dimm;
uint8_t entry;
uint8_t l_dimm_type;
- uint8_t l_dimm_size_array[l_num_ports][l_num_dimms];
uint8_t l_dimm_ranks_array[l_num_ports][l_num_dimms];
- uint32_t l_half_cdimm_size = 0;
- uint8_t l_half_cdimm_ranks = 0;
uint32_t l_list_sz;
uint32_t l_power_slope_array[l_num_ports][l_num_dimms];
uint32_t l_power_int_array[l_num_ports][l_num_dimms];
- uint32_t l_power_int_uplift;
uint32_t l_dimm_throttle_n_array[l_num_ports][l_num_dimms];
uint32_t l_dimm_throttle_d_array[l_num_ports][l_num_dimms];
uint32_t l_channel_throttle_n_array[l_num_ports];
uint32_t l_channel_throttle_d_array[l_num_ports];
uint8_t l_found_entry_in_table;
- uint8_t l_dimm_config[l_num_ports];
+ uint8_t l_dram_width;
+ uint8_t l_dram_gen;
+ uint32_t l_dimm_voltage;
+ uint32_t l_dimm_frequency;
+ uint8_t l_dimm_ranks_configed_array[l_num_ports][l_num_dimms];
+ uint8_t l_dimm_master_ranks_array[l_num_ports][l_num_dimms];
+ int32_t l_dimm_power_adder_type;
+ int8_t l_dimm_power_adder_volt;
+ int8_t l_dimm_power_adder_freq;
+ uint32_t l_dimm_idle_power_adder_slave;
+ uint32_t l_dimm_max_power_adder_slave;
+ int32_t l_dimm_idle_power;
+ int32_t l_dimm_max_power;
+ uint8_t l_dimm_num_slave_ranks;
-// This sets up the power curve values for the DIMMs
-// NOTE: If a value of zero is in the slope or intercept fields, then the default settings will be used
-// NOTE: Power Slope and Intercept values are in cW
-// NOTE: For CDIMM, the power values need to be based on the dimm within the CDIMM (not based on power for whole CDIMM)
-// DIMM, Size, Ranks, Double drop config power slope and intercept, Single drop config power slope and intercept
-
- power_thermal_data_t l_power_thermal_values[]=
- {
-// SINGLE DOUBLE
-// DROP DROP
-// Type, Size, Ranks, slope,int, slope,int
-// RDIMMs - data from P7 based ISDIMMs (1066MHz and 1.35V)
- { RDIMM, 2, 1, {{ 522, 154}, { 526, 153}}}, // example RDIMM 2GB 1Rx8 2Gb
- { RDIMM, 4, 2, {{ 472, 187}, { 512, 182}}}, // example RDIMM 4GB 2Rx8 2Gb
- { RDIMM, 4, 1, {{ 472, 187}, { 512, 182}}}, // example RDIMM 4GB 1Rx8 4Gb
- { RDIMM, 8, 4, {{ 654, 274}, { 657, 262}}}, // example RDIMM 8GB 4Rx8 2Gb
- { RDIMM, 8, 2, {{ 654, 274}, { 657, 262}}}, // example RDIMM 8GB 2Rx4 2Gb OR 8GB 2Rx8 4Gb
- { RDIMM, 16, 4, {{ 770, 458}, { 738, 479}}}, // example RDIMM 16GB 4Rx4 2Gb
- { RDIMM, 16, 2, {{ 770, 458}, { 738, 479}}}, // example RDIMM 16GB 2Rx4 4Gb
- { RDIMM, 32, 4, {{ 770, 458}, { 738, 479}}}, // example RDIMM 32GB 4Rx4 4Gb
-// CDIMMs - projections based on Warren's dimm support table + 3% spread + 10% uplift
-// power values here are HALF of the cdimm power (since we handle one mba at a time) - need to divide this up and give each dimm an equal power amount
-// SingleDrop DoubleDrop
-// TYPE Size/X, Ranks/X, Slope,Int, Slope, Int
-// where X=number of MBA port pairs populated on CDIMM
- { CDIMM, 16/2, 4/2, {{ 957, 153}, { 957, 153}}}, // example short CDIMM 16GB 4Rx8 4Gb OR 8GB 2Rx8 4Gb (Channel A/B populated)
- { CDIMM, 32/2, 8/2, {{1130, 254}, {1130, 254}}}, // example short CDIMM 32GB 4Rx8 4Gb
- { CDIMM, 64/2, 8/2, {{1763, 469}, {1763, 469}}}, // example short CDIMM 64GB 4Rx4 4Gb
- { CDIMM, 128/2, 8/2, {{1763, 599}, {1763, 599}}}, // example tall CDIMM 128GB 4Rx4 4Gb (2H 3DS)
-// UDIMMs
-// LRDIMMs
- };
- l_list_sz = (sizeof(l_power_thermal_values))/(sizeof(power_thermal_data_t));
+ l_list_sz = (sizeof(l_power_table))/(sizeof(power_data_t));
// Get input attributes
+ l_rc = FAPI_ATTR_GET(ATTR_EFF_DRAM_GEN, &i_target, l_dram_gen);
+ if(l_rc) return l_rc;
l_rc = FAPI_ATTR_GET(ATTR_EFF_DIMM_TYPE, &i_target, l_dimm_type);
if(l_rc) return l_rc;
- l_rc = FAPI_ATTR_GET(ATTR_EFF_DIMM_SIZE, &i_target, l_dimm_size_array);
+ l_rc = FAPI_ATTR_GET(ATTR_EFF_DRAM_WIDTH, &i_target, l_dram_width);
if(l_rc) return l_rc;
l_rc = FAPI_ATTR_GET(ATTR_EFF_NUM_RANKS_PER_DIMM, &i_target, l_dimm_ranks_array);
if(l_rc) return l_rc;
+ l_rc = FAPI_ATTR_GET(ATTR_EFF_NUM_MASTER_RANKS_PER_DIMM, &i_target, l_dimm_master_ranks_array);
+ if(l_rc) return l_rc;
+ l_rc = FAPI_ATTR_GET(ATTR_EFF_DIMM_RANKS_CONFIGED, &i_target, l_dimm_ranks_configed_array);
+ if(l_rc) return l_rc;
+// TODO: Get Attributes for number of registers on ISDIMM and Termination settings being used
-// Add up DIMM Size and Ranks if a CDIMM - this will be for half of the cdimm - and dimm config for each mba port (1 or 2 dimms per channel)
- for (port=0; port < l_num_ports; port++)
+// Get Centaur target for the given MBA
+// Get voltage and frequency attributes
+ l_rc = fapiGetParentChip(i_target, l_targetCentaur);
+ if(l_rc)
{
- l_dimm_config[port] = 0;
- for (dimm=0; dimm < l_num_dimms; dimm++)
- {
- if ((l_dimm_type == CDIMM) && (l_dimm_ranks_array[port][dimm] > 0))
- {
- l_half_cdimm_size = l_half_cdimm_size + l_dimm_size_array[port][dimm];
- l_half_cdimm_ranks = l_half_cdimm_ranks + l_dimm_ranks_array[port][dimm];
- }
- if (l_dimm_ranks_array[port][dimm] > 0)
- {
- l_dimm_config[port]++;
- }
- }
- if (l_dimm_config[port] == 1)
- {
- l_dimm_config[port] = SINGLEDROP;
- }
- else if (l_dimm_config[port] == 2)
- {
- l_dimm_config[port] = DOUBLEDROP;
- }
- else
- {
- l_dimm_config[port] = DIMM_CONFIG_TYPES;
- }
+ FAPI_ERR("Error getting Centaur parent target for the given MBA");
+ return l_rc;
}
+ l_rc = FAPI_ATTR_GET(ATTR_MSS_VOLT, &l_targetCentaur, l_dimm_voltage);
+ if(l_rc) return l_rc;
+ l_rc = FAPI_ATTR_GET(ATTR_MSS_FREQ, &l_targetCentaur, l_dimm_frequency);
+ if(l_rc) return l_rc;
// iterate through the MBA ports to define power and thermal attributes
for (port=0; port < l_num_ports; port++)
{
-// initialize entries to zero
+// initialize channel entries to zero
l_channel_throttle_n_array[port] = 0;
l_channel_throttle_d_array[port] = 0;
+// iterate through the dimms on each port
for (dimm=0; dimm < l_num_dimms; dimm++)
{
-// initialize entries to zero
+// initialize dimm entries to zero
l_dimm_throttle_n_array[port][dimm] = 0;
l_dimm_throttle_d_array[port][dimm] = 0;
l_power_slope_array[port][dimm] = 0;
l_power_int_array[port][dimm] = 0;
-// only update values for dimms that are physically present (with default value or table entry value)
+// only update values for dimms that are physically present
if (l_dimm_ranks_array[port][dimm] > 0)
{
-// TODO: Placeholder for thermal attributes from machine readable workbook (runtime throttles) - Hardcode these for now. IPL throttles will need to be added into an initfile once available.
-// Can remove this section once infrastructure is in place to get these from the MRW (probably done in a different firmware procedure)
+// TODO: Placeholder for thermal attributes that will come from machine readable workbook (runtime throttles) - Hardcode these to the default values for now.
+// TODO: IPL throttles will need to be added into an initfile once available.
l_dimm_throttle_n_array[port][dimm] = l_dimm_throttle_n_default;
l_dimm_throttle_d_array[port][dimm] = l_dimm_throttle_d_default;
l_channel_throttle_n_array[port] = l_channel_throttle_n_default;
l_channel_throttle_d_array[port] = l_channel_throttle_d_default;
-// Look up DIMM in Table, get size and ranks first, set slope/int to default values first in case entry is not found in table
-// If table entry is less than zero, then set value to default values
- if (l_dimm_type == CDIMM)
- {
- l_dimm_size_array[port][dimm] = l_half_cdimm_size;
- l_dimm_ranks_array[port][dimm] = l_half_cdimm_ranks;
- l_power_slope_array[port][dimm] = l_cdimm_power_slope_default;
- l_power_int_array[port][dimm] = l_cdimm_power_int_default;
- }
- else
- {
- l_power_slope_array[port][dimm] = l_dimm_power_slope_default;
- l_power_int_array[port][dimm] = l_dimm_power_int_default;
- }
+
+// 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)
+ l_power_slope_array[port][dimm] = l_dimm_power_slope_default;
+ l_power_int_array[port][dimm] = l_dimm_power_int_default;
l_found_entry_in_table = 0;
for (entry = 0; entry < l_list_sz; entry++) {
- if ((l_power_thermal_values[entry].dimm_type == l_dimm_type) && (l_power_thermal_values[entry].dimm_size == l_dimm_size_array[port][dimm]) && (l_power_thermal_values[entry].dimm_ranks == l_dimm_ranks_array[port][dimm]))
+ if ((l_power_table[entry].dram_generation == l_dram_gen) && (l_power_table[entry].dram_width == l_dram_width) && ((l_power_table[entry].dimm_ranks == l_dimm_master_ranks_array[port][dimm]) || (l_power_table[entry].dimm_ranks == 1)))
{
- if ((l_power_thermal_values[entry].data[l_dimm_config[port]].power_slope > 0) && (l_power_thermal_values[entry].data[l_dimm_config[port]].power_int > 0))
+// get adder for dimm type
+ if (l_dimm_type == UDIMM) {
+ l_dimm_power_adder_type = l_power_table[entry].dimm_type_adder.udimm;
+ }
+ else if (l_dimm_type == LRDIMM)
+ {
+ l_dimm_power_adder_type = l_power_table[entry].dimm_type_adder.lrdimm;
+ }
+ else if (l_dimm_type == CDIMM)
+ {
+ l_dimm_power_adder_type = l_power_table[entry].dimm_type_adder.cdimm;
+ }
+ else if ( l_dimm_type == RDIMM )
+ {
+ l_dimm_power_adder_type = l_power_table[entry].dimm_type_adder.rdimm;
+ }
+ else
+ {
+ FAPI_ERR("UNKNOWN DIMM TYPE FOUND: ldimm_type");
+ l_dimm_power_adder_type = 0;
+ }
+// TODO: Use attribute for number of registers for RDIMM when available - via SPD byte 63 bits 1:0
+// TODO: Remove the double uplift below when SPD byte 63 is used
+ // double the uplift for additional register if dimm has more than 2 ranks
+ if ((l_dimm_master_ranks_array[port][dimm] > 2) && (l_dram_width == X4) && ((l_dimm_type == LRDIMM) || (l_dimm_type == RDIMM)))
+ {
+ l_dimm_power_adder_type = l_dimm_power_adder_type * 2;
+ }
+// get adder for dimm voltage
+ if (l_dimm_voltage == 1200)
+ {
+ l_dimm_power_adder_volt = l_power_table[entry].dimm_voltage_adder.volt1200;
+ }
+ else if (l_dimm_voltage == 1350)
+ {
+ l_dimm_power_adder_volt = l_power_table[entry].dimm_voltage_adder.volt1350;
+ }
+ else if (l_dimm_voltage == 1500)
+ {
+ l_dimm_power_adder_volt = l_power_table[entry].dimm_voltage_adder.volt1500;
+ }
+ else
+ {
+ FAPI_ERR("UNKNOWN DIMM VOLTAGE FOUND: l_dimm_voltage");
+ l_dimm_power_adder_volt = 0;
+ }
+// get adder for dimm frequency
+ if (l_dimm_frequency == 1066)
+ {
+ l_dimm_power_adder_freq = l_power_table[entry].dimm_frequency_adder.freq1066;
+ }
+ else if (l_dimm_frequency == 1333)
+ {
+ l_dimm_power_adder_freq = l_power_table[entry].dimm_frequency_adder.freq1333;
+ }
+ else if (l_dimm_frequency == 1600)
{
- l_power_slope_array[port][dimm]=l_power_thermal_values[entry].data[l_dimm_config[port]].power_slope;
- l_power_int_array[port][dimm]=l_power_thermal_values[entry].data[l_dimm_config[port]].power_int;
- FAPI_INF("Found DIMM Entry in Power Table [%d:%d:%d:%d:%d:%d][%d:%d]", port, dimm, l_dimm_type, l_dimm_size_array[port][dimm], l_dimm_ranks_array[port][dimm], l_dimm_config[port], l_power_slope_array[port][dimm], l_power_int_array[port][dimm]);
+ l_dimm_power_adder_freq = l_power_table[entry].dimm_frequency_adder.freq1600;
}
else
{
- FAPI_ERR( "DIMM Entry in Power Table not greater than zero, so default values will be used [%d:%d:%d:%d:%d:%d][%d:%d]", port, dimm, l_dimm_type, l_dimm_size_array[port][dimm], l_dimm_ranks_array[port][dimm], l_dimm_config[port], l_power_slope_array[port][dimm], l_power_int_array[port][dimm]);
+ FAPI_ERR("UNKNOWN DIMM FREQ FOUND: l_dimm_frequency");
+ l_dimm_power_adder_freq = 0;
+ }
+// get adder for slave ranks
+ l_dimm_num_slave_ranks=l_dimm_ranks_array[port][dimm] - l_dimm_master_ranks_array[port][dimm];
+ if (l_dimm_num_slave_ranks > 0)
+ {
+ l_dimm_idle_power_adder_slave = l_power_table[entry].rank_slave_adder.idle * l_dimm_num_slave_ranks;
+ l_dimm_max_power_adder_slave = l_dimm_idle_power_adder_slave + (l_power_table[entry].rank_slave_adder.max - l_power_table[entry].rank_slave_adder.idle);
}
-// break out since first match was found
+ else
+ {
+ l_dimm_idle_power_adder_slave = 0;
+ l_dimm_max_power_adder_slave = 0;
+ }
+// get adder for termination using equation
+// TODO: Need to add this in once equations are available for termination adder
+
+// calculate idle and max dimm power
+ l_dimm_idle_power = int((l_power_table[entry].rank_master_power.idle * l_dimm_master_ranks_array[port][dimm] + l_dimm_power_adder_type + l_dimm_idle_power_adder_slave) * (1 + float(l_dimm_power_adder_volt + l_dimm_power_adder_freq) / 100));
+ l_dimm_max_power = int(((l_power_table[entry].rank_master_power.idle * l_dimm_master_ranks_array[port][dimm] + l_power_table[entry].rank_master_power.max - l_power_table[entry].rank_master_power.idle) + l_dimm_power_adder_type + l_dimm_max_power_adder_slave) * (1 + float(l_dimm_power_adder_volt + l_dimm_power_adder_freq) / 100));
+// caculcate dimm power slope and intercept
+ l_power_slope_array[port][dimm] = int((l_dimm_max_power - l_dimm_idle_power) / (float(l_max_dimm_utilization - l_idle_dimm_utilization) / 100));
+ l_power_int_array[port][dimm] = l_dimm_idle_power;
+
l_found_entry_in_table = 1;
+ FAPI_INF("FOUND ENTRY: GEN=%d WIDTH=%d RANK=%d IDLE=%d MAX=%d ADDER[SLAVE_IDLE=%d SLAVE_MAX=%d TYPE=%d VOLT=%d FREQ=%d]", l_power_table[entry].dram_generation, l_power_table[entry].dram_width, l_power_table[entry].dimm_ranks, l_power_table[entry].rank_master_power.idle, l_power_table[entry].rank_master_power.max, l_power_table[entry].rank_slave_adder.idle, l_power_table[entry].rank_slave_adder.max, l_dimm_power_adder_type, l_dimm_power_adder_volt, l_dimm_power_adder_freq);
+ FAPI_INF("DIMM Power Calculated [P%d:D%d:R%d/%d][IDLE=%d:MAX=%d cW][SLOPE=%d:INT=%d cW]", port, dimm, l_dimm_master_ranks_array[port][dimm], l_dimm_num_slave_ranks, l_dimm_idle_power, l_dimm_max_power, l_power_slope_array[port][dimm], l_power_int_array[port][dimm]);
break;
}
+
}
-// Apply any uplifts to the Slope or intercept values based on various parameters if entry is found in table
-// TODO: What uplifts do we need to do (Frequency, Voltage, Termination, etc) - Use zero uplift for now.
- if (l_found_entry_in_table == 1)
- {
- l_power_int_uplift = 0;
- l_power_int_array[port][dimm] = l_power_int_array[port][dimm] + l_power_int_uplift;
- }
-// post error if entry was not found
- else
+ if (l_found_entry_in_table == 0)
{
- FAPI_ERR( "Failed to Find DIMM Entry in Power Table, so default values will be used [%d:%d:%d:%d:%d:%d][%d:%d]", port, dimm, l_dimm_type, l_dimm_size_array[port][dimm], l_dimm_ranks_array[port][dimm], l_dimm_config[port], l_power_slope_array[port][dimm], l_power_int_array[port][dimm] );
+ FAPI_ERR( "WARNING: Failed to Find DIMM Power Values, so default values will be used [%d:%d][%d:%d]", port, dimm, l_power_slope_array[port][dimm], l_power_int_array[port][dimm] );
}
}
}
}
+
// write output attributes
l_rc = FAPI_ATTR_SET(ATTR_MSS_POWER_SLOPE, &i_target, l_power_slope_array);
if(l_rc) return l_rc;
OpenPOWER on IntegriCloud