blob: 172d6acc2bb9a213811050c26b50732002007d6a [file] [log] [blame]
From bdd6ce1bbfe0ee77feefe84662e961fb253c6195 Mon Sep 17 00:00:00 2001
From: Jim Yuan <jim.yuan@supermicro.com>
Date: Fri, 22 Jul 2016 17:50:57 -0700
Subject: [PATCH 10/14] Adjust APSS gain and offset from PWS FRU information.
Signed-off-by: Jim Yuan <jim.yuan@supermicro.com>
---
src/include/usr/ipmi/ipmiif.H | 4 +-
src/usr/htmgt/htmgt_cfgdata.C | 2 +
src/usr/hwpf/hwp/start_payload/start_payload.C | 212 +++++++++++++++++++++
.../common/xmltohb/attribute_types_hb.xml | 2 +
4 files changed, 218 insertions(+), 2 deletions(-)
diff --git a/src/include/usr/ipmi/ipmiif.H b/src/include/usr/ipmi/ipmiif.H
index 9dfd8ee63..5416ddca0 100644
--- a/src/include/usr/ipmi/ipmiif.H
+++ b/src/include/usr/ipmi/ipmiif.H
@@ -251,8 +251,8 @@ namespace IPMI
inline const command_t set_sel_time(void)
{ return std::make_pair(NETFUN_STORAGE, 0x49); }
- inline const command_t read_fru_data(void)
- { return std::make_pair(NETFUN_STORAGE, 0x11); }
+ inline const command_t read_fru_data(void)
+ { return std::make_pair(NETFUN_STORAGE, 0x11); }
inline const command_t write_fru_data(void)
{ return std::make_pair(NETFUN_STORAGE, 0x12); }
diff --git a/src/usr/htmgt/htmgt_cfgdata.C b/src/usr/htmgt/htmgt_cfgdata.C
index 19e7b21bf..7c42abdb6 100644
--- a/src/usr/htmgt/htmgt_cfgdata.C
+++ b/src/usr/htmgt/htmgt_cfgdata.C
@@ -1025,6 +1025,8 @@ void getApssMessageData(uint8_t* o_data,
ATTR_ADC_CHANNEL_OFFSETS_type offset;
sys->tryGetAttr<ATTR_ADC_CHANNEL_OFFSETS>(offset);
+ TMGT_INF("getApssMessageData: gain is %d, offset is %d", gain[15], offset[15]); //jim
+
CPPASSERT(sizeof(function) == sizeof(ground));
CPPASSERT(sizeof(function) == sizeof(gain));
CPPASSERT(sizeof(function) == sizeof(offset));
diff --git a/src/usr/hwpf/hwp/start_payload/start_payload.C b/src/usr/hwpf/hwp/start_payload/start_payload.C
index 5d7865a12..ad155f19e 100644
--- a/src/usr/hwpf/hwp/start_payload/start_payload.C
+++ b/src/usr/hwpf/hwp/start_payload/start_payload.C
@@ -88,6 +88,7 @@
#include <algorithm>
#include <config.h>
#include <ipmi/ipmiwatchdog.H>
+#include <ipmi/ipmiif.H> //jim
#include <vpd/vpd_if.H>
#include <hwpf/hwpf_reasoncodes.H>
@@ -95,6 +96,7 @@
// Uncomment these files as they become available:
// #include "host_start_payload/host_start_payload.H"
+
namespace START_PAYLOAD
{
@@ -277,6 +279,214 @@ errlHndl_t setMaxPstate ( void )
}
#endif
+//jim-start
+enum
+{
+PWS_1600 = 0,
+PWS_1000 = 1,
+PWS_1200 = 2,
+PWS_UNKNOWN = 0xFE,
+};
+
+uint8_t getPSUFRUFromIPMICommands(void)
+{
+ errlHndl_t l_err = NULL;
+ uint8_t* frudata = new uint8_t[120];
+ size_t len = 4;
+ uint8_t fru_header_version = 0;
+ uint8_t j = 0, loop_break = 0, read_offset = 0;
+
+ //create request data buffer
+ uint8_t* data = new uint8_t[len];
+
+ IPMI::completion_code cc = IPMI::CC_UNKBAD;
+
+ data[0] = 60; //try to read from PWS1. 60-PWS1, 61-PWS2
+ data[1] = 0x0;
+ data[2] = 0x0;
+ data[3] = 8;
+ l_err = IPMI::sendrecv(IPMI::read_fru_data(), cc, len, data);
+
+ for (uint8_t i = 0; i <= 8; i++ )
+ fru_header_version = data[1] & 0xF; //normal should be 0x01.
+ TRACFCOMP( ISTEPS_TRACE::g_trac_isteps_trace, "fru header version is %x", fru_header_version);
+ delete[] data;
+
+ if((l_err == NULL) && (cc == IPMI::CC_OK) && (fru_header_version == 1))
+ {
+ TRACFCOMP( ISTEPS_TRACE::g_trac_isteps_trace, "could get FRU from PWS1");
+
+ while ((l_err == NULL) && (loop_break == 0) && (read_offset < 100))
+ {
+ //create request data buffer
+ len = 4; //must set len every time
+ uint8_t* data = new uint8_t[len];
+
+ IPMI::completion_code cc = IPMI::CC_UNKBAD;
+
+ data[0] = 60; //read from PWS1
+ data[1] = read_offset;
+ data[2] = 0x0;
+ data[3] = 8;
+ l_err = IPMI::sendrecv(IPMI::read_fru_data(), cc, len, data);
+
+ if (cc != IPMI::CC_OK) loop_break = 1;
+
+ read_offset += 8;
+ for (uint8_t i = 1; i <= 8; i++ )
+ {
+ frudata[j] = data[i];
+ j++;
+ }
+ delete[] data;
+ }
+
+
+ }
+ else
+ {
+ TRACFCOMP( ISTEPS_TRACE::g_trac_isteps_trace, "could get FRU from PWS2");
+
+ while ((l_err == NULL) && (loop_break == 0) && (read_offset < 100))
+ {
+ //create request data buffer
+ len = 4;//must set len every time
+ uint8_t* data = new uint8_t[len];
+
+ IPMI::completion_code cc = IPMI::CC_UNKBAD;
+
+ data[0] = 61; //read from PWS2
+ data[1] = read_offset;
+ data[2] = 0x0;
+ data[3] = 8;
+ l_err = IPMI::sendrecv(IPMI::read_fru_data(), cc, len, data);
+
+ if (cc != IPMI::CC_OK) loop_break = 1;
+
+ read_offset += 8;
+ for (uint8_t i = 1; i <= 8; i++ )
+ {
+ frudata[j] = data[i];
+ j++;
+ }
+ delete[] data;
+ }
+
+ }
+
+ uint8_t product_info_offset, manufacture_name_offset, manufacture_name_length, product_name_offset, product_name_length;
+ uint8_t product_partnumber_offset, product_partnumber_length;
+ uint8_t fru_offset, powerSupplyFru = PWS_UNKNOWN;
+ uint8_t pws1600[] = {'P','W','S','-','1','K','6','2','A','-','1','R'};
+ uint8_t pws1000[] = {'P','W','S','-','1','K','0','2','A','-','1','R'};
+ uint8_t pws1200[] = {'P','W','S','-','1','K','2','2','A','-','1','R'};
+
+ //code to calculate product part number size and offset. should use structure. refer to FRU spec.
+ product_info_offset = frudata[4] * 8;
+ manufacture_name_offset = product_info_offset + 3;
+ manufacture_name_length = frudata[manufacture_name_offset] & 0x3F;
+ product_name_offset = manufacture_name_offset + manufacture_name_length + 1;
+ product_name_length = frudata[product_name_offset] & 0x3F;
+ product_partnumber_offset = product_name_offset + product_name_length + 1;
+ product_partnumber_length = frudata[product_partnumber_offset] & 0x3F;
+ TRACFCOMP( ISTEPS_TRACE::g_trac_isteps_trace, "product_partnumber_length is %x", product_partnumber_length);
+ fru_offset = product_partnumber_offset + 1;
+
+ if (product_partnumber_length == 12)
+ {
+ for (uint8_t i = 0; pws1600[i] == frudata[fru_offset + i] ; i ++)
+ if (i == 11)
+ powerSupplyFru = PWS_1600;
+
+ for (uint8_t i = 0; pws1000[i] == frudata[fru_offset + i] ; i ++)
+ if (i == 11)
+ powerSupplyFru = PWS_1000;
+
+ for (uint8_t i = 0; pws1200[i] == frudata[fru_offset + i] ; i ++)
+ if (i == 11)
+ powerSupplyFru = PWS_1200;
+ }
+ else
+ powerSupplyFru = PWS_UNKNOWN;
+
+ TRACFCOMP( ISTEPS_TRACE::g_trac_isteps_trace, "powerSupplyFru is %x", powerSupplyFru);
+
+ return powerSupplyFru;
+
+}
+//find apss channel number from XML.
+enum
+{
+V12_SENSE = 0,
+PROC0_POWER = 1,
+PROC1_POWER = 2,
+PCIE_PROC0_POWER = 5,
+PCIE_PROC1_POWER = 6,
+TOTAL_SYSTEM_POWER = 15,
+};
+
+void setAPSSGainOffsetFromPWSInfo(void)
+{
+ TRACFCOMP( ISTEPS_TRACE::g_trac_isteps_trace, "before load OCC");
+
+ //Get Gain/Offset ATTR
+ TARGETING::Target* sys = NULL;
+ targetService().getTopLevelTarget(sys);
+
+ ATTR_ADC_CHANNEL_GAINS_type gain;
+ sys->tryGetAttr<ATTR_ADC_CHANNEL_GAINS>(gain);
+
+ ATTR_ADC_CHANNEL_OFFSETS_type offset;
+ sys->tryGetAttr<ATTR_ADC_CHANNEL_OFFSETS>(offset);
+
+ TRACFCOMP( ISTEPS_TRACE::g_trac_isteps_trace, "gain is %d, offset is %d", gain[15], offset[15]);
+
+ //Note that the function/ APSS channel ids can be indirect. I've hardcoded here, you will need to look at the XML to find the channel/function number that matches
+ //const uint8_t SYS_CHANNEL = 15; //APSS Channel 15 is sys power, ie the gain/offset we need to tweak
+
+ //Get power supply data from BMC
+ uint8_t powerSupplyFru = getPSUFRUFromIPMICommands();
+
+ switch(powerSupplyFru)
+ {
+ case PWS_1600: //PWS-1K62A-1R (1600W):
+ gain[TOTAL_SYSTEM_POWER] = 67800;
+ offset[TOTAL_SYSTEM_POWER] = 0;
+ break;
+
+ case PWS_1000: //PWS-1K02A-1R (1000W):
+ gain[TOTAL_SYSTEM_POWER] = 41500;
+ offset[TOTAL_SYSTEM_POWER] = 0;
+ break;
+
+ case PWS_1200: //PWS-1K22A-1R (1200W):
+ gain[TOTAL_SYSTEM_POWER] = 50000;
+ offset[TOTAL_SYSTEM_POWER] = 0;
+ break;
+
+ default:
+ //Do nothing, leave defaults
+ //Gen error for user attention?
+ break;
+ }
+
+ //Now write the attributes back so they get picked up by OCC code
+ if (!sys->trySetAttr<ATTR_ADC_CHANNEL_GAINS>(gain))
+ {
+ //unlikely, crash
+ //Emit failing trace/console data
+ TRACFCOMP( ISTEPS_TRACE::g_trac_isteps_trace, "set gain failed");
+ assert(0);
+ }
+
+ if (!sys->trySetAttr<ATTR_ADC_CHANNEL_OFFSETS>(offset))
+ {
+ //unlikely, crash
+ //Emit failing trace/console data
+ TRACFCOMP( ISTEPS_TRACE::g_trac_isteps_trace, "set offset failed");
+ assert(0);
+ }
+}
//
// Wrapper function to call host_runtime_setup
//
@@ -318,6 +528,8 @@ void* call_host_runtime_setup( void *io_pArgs )
break;
}
+ setAPSSGainOffsetFromPWSInfo(); //jim add code before activate OCC. START_OCC_DURING_BOOT is defined in config.
+
bool l_activateOCC = is_avp_load();
#ifdef CONFIG_START_OCC_DURING_BOOT
diff --git a/src/usr/targeting/common/xmltohb/attribute_types_hb.xml b/src/usr/targeting/common/xmltohb/attribute_types_hb.xml
index c4eb6603d..64a0c9bae 100644
--- a/src/usr/targeting/common/xmltohb/attribute_types_hb.xml
+++ b/src/usr/targeting/common/xmltohb/attribute_types_hb.xml
@@ -747,6 +747,7 @@
</simpleType>
<persistency>non-volatile</persistency>
<readable/>
+ <writeable/>
</attribute>
<attribute>
@@ -758,6 +759,7 @@
</simpleType>
<persistency>non-volatile</persistency>
<readable/>
+ <writeable/>
</attribute>
<attribute>
--
2.16.2.windows.1