summaryrefslogtreecommitdiffstats
path: root/src/occ_405
diff options
context:
space:
mode:
authormbroyles <mbroyles@us.ibm.com>2017-03-09 16:08:57 -0600
committerMartha Broyles <mbroyles@us.ibm.com>2017-03-13 16:23:47 -0400
commitad7e5252c5ef3018832e581d7f363009c3ddab02 (patch)
tree36ebb5c0d3c3b9bc8420c49026787bd6f1667e0b /src/occ_405
parent35eb166d9825cef7e483ac46f954ebc2777c16b3 (diff)
downloadtalos-occ-ad7e5252c5ef3018832e581d7f363009c3ddab02.tar.gz
talos-occ-ad7e5252c5ef3018832e581d7f363009c3ddab02.zip
New mfg test command to set per quad pstate
Change-Id: I3f3b187608b0bfaf83cfa612358b40257db7d5b6 RTC: 170583 Reviewed-on: http://ralgit01.raleigh.ibm.com/gerrit1/37765 Tested-by: FSP CI Jenkins <fsp-CI-jenkins+hostboot@us.ibm.com> Reviewed-by: William A. Bryan <wilbryan@us.ibm.com> Reviewed-by: Christopher J. Cain <cjcain@us.ibm.com> Reviewed-by: Martha Broyles <mbroyles@us.ibm.com>
Diffstat (limited to 'src/occ_405')
-rwxr-xr-xsrc/occ_405/amec/amec_freq.c83
-rwxr-xr-xsrc/occ_405/amec/amec_sys.h4
-rwxr-xr-xsrc/occ_405/cmdh/cmdh_fsp.c2
-rwxr-xr-xsrc/occ_405/cmdh/cmdh_fsp_cmds_datacnfg.c8
-rwxr-xr-xsrc/occ_405/cmdh/cmdh_mnfg_intf.c117
-rwxr-xr-xsrc/occ_405/cmdh/cmdh_mnfg_intf.h32
-rwxr-xr-xsrc/occ_405/occ_sys_config.h1
-rwxr-xr-xsrc/occ_405/state.c5
8 files changed, 212 insertions, 40 deletions
diff --git a/src/occ_405/amec/amec_freq.c b/src/occ_405/amec/amec_freq.c
index 57ac047..6b33d1e 100755
--- a/src/occ_405/amec/amec_freq.c
+++ b/src/occ_405/amec/amec_freq.c
@@ -180,10 +180,12 @@ errlHndl_t amec_set_freq_range(const OCC_MODE i_mode)
g_amec->sys.fmin = l_freq_min;
g_amec->sys.fmax = l_freq_max;
- TRAC_INFO("amec_set_freq_range: Mode[0x%02x] Fmin[%u] Fmax[%u]",
+ TRAC_INFO("amec_set_freq_range: Mode[0x%02x] Fmin[%u] (Pmin 0x%02x) Fmax[%u] (Pmax 0x%02x)",
i_mode,
l_freq_min,
- l_freq_max);
+ proc_freq2pstate(g_amec->sys.fmin),
+ l_freq_max,
+ proc_freq2pstate(g_amec->sys.fmax));
// Now determine the max frequency for the PPM structure
l_ppm_freq[OCC_INTERNAL_MODE_NOM].fmax = G_sysConfigData.sys_mode_freq.table[OCC_MODE_NOMINAL];
@@ -528,51 +530,88 @@ void amec_slv_freq_smh(void)
/*------------------------------------------------------------------------*/
/* Local Variables */
/*------------------------------------------------------------------------*/
- uint8_t quad = 0; // loop through quads
- uint8_t core_num = 0; // core ID
- uint8_t core_idx = 0; // loop through cores within each quad
- Pstate pmax = 0; // select the maximum pstate (minimum frequency)
- // within each quad, initialize to 0 (max frequency)
+ uint8_t quad = 0; // loop through quads
+ uint8_t core_num = 0; // core ID
+ uint8_t core_idx = 0; // loop through cores within each quad
+ Pstate pmax[MAX_QUADS] = {0}; // max pstate (min frequency) within each quad
+ Pstate pmax_chip = 0; // highest Pstate (lowest frequency) across all quads
+ bool l_atLeast1Core[MAX_QUADS] = {FALSE}; // at least 1 core present in quad
+ static bool L_mfg_set_trace[MAX_QUADS] = {FALSE};
+ static bool L_mfg_clear_trace[MAX_QUADS] = {FALSE};
/*------------------------------------------------------------------------*/
/* Code */
/*------------------------------------------------------------------------*/
- // loop through all quads, get f_requests, translate to pstates
+ // loop through all quads, get f_requests, translate to pstates and determine pmax across chip
for (quad = 0; quad < MAX_QUADS; quad++)
{
- for (core_idx=0; core_idx<NUM_CORES_PER_QUAD; core_idx++) // scan quad cores
+ for (core_idx=0; core_idx<NUM_CORES_PER_QUAD; core_idx++) // loop thru all cores in quad
{
- core_num = (quad*NUM_CORES_PER_QUAD) + core_idx; // loop through all cores
+ core_num = (quad*NUM_CORES_PER_QUAD) + core_idx;
- // The higher the pstate number, the lower the frequency
- if(pmax < proc_freq2pstate(g_amec->proc[0].core[core_num].f_request))
+ // ignore core if freq request is 0 (core not present when amec_slv_proc_voting_box ran)
+ if(g_amec->proc[0].core[core_num].f_request != 0)
{
- pmax = proc_freq2pstate(g_amec->proc[0].core[core_num].f_request);
+ l_atLeast1Core[quad] = TRUE;
+ // The higher the pstate number, the lower the frequency
+ if(pmax[quad] < proc_freq2pstate(g_amec->proc[0].core[core_num].f_request))
+ {
+ pmax[quad] = proc_freq2pstate(g_amec->proc[0].core[core_num].f_request);
+ if(pmax_chip < pmax[quad]) // check if this is a new lowest freq for the chip
+ pmax_chip = pmax[quad];
+ }
}
}
+ }
+
+ // check for mfg quad Pstate request and set Pstate for each quad
+ for (quad = 0; quad < MAX_QUADS; quad++)
+ {
+ // set quad with no cores present to lowest frequency for the chip
+ if(l_atLeast1Core[quad] == FALSE)
+ pmax[quad] = pmax_chip;
+
+ // check if there is a mnfg Pstate request for this quad
+ if(g_amec->mnfg_parms.quad_pstate[quad] != 0xFF)
+ {
+ // use mnfg request if it is a lower frequency (higher pState)
+ if(g_amec->mnfg_parms.quad_pstate[quad] > pmax[quad])
+ pmax[quad] = g_amec->mnfg_parms.quad_pstate[quad];
+
+ if(L_mfg_clear_trace[quad] == FALSE)
+ L_mfg_set_trace[quad] = TRUE;
+ }
+ else if(L_mfg_clear_trace[quad] == TRUE)
+ {
+ TRAC_INFO("amec_slv_freq_smh: mfg Quad %d Pstate request cleared. New Pstate = 0x%02x", quad, pmax[quad]);
+ L_mfg_clear_trace[quad] = FALSE;
+ }
// set quad clip bounds/pstates based on system type
if(G_sysConfigData.system_type.kvm)
{
// update quad bounds on OPAL systems
- G_core_data_control_occwrite_ptr->clips.ps_val_clip_min[quad] =
- G_opal_static_table.config.pmin;
- G_core_data_control_occwrite_ptr->clips.ps_val_clip_max[quad] = pmax;
+ G_core_data_control_occwrite_ptr->clips.ps_val_clip_min[quad] = G_opal_static_table.config.pmin;
+ G_core_data_control_occwrite_ptr->clips.ps_val_clip_max[quad] = pmax[quad];
PROC_DBG("Setting Quad %d's min-max clip bounds to %d-%d\n",
- quad, G_opal_static_table.config.pmin, pmax);
+ quad, G_opal_static_table.config.pmin, pmax[quad]);
}
else
{
- // update quad pstate request on non-OPAL systems
- G_core_data_control_occwrite_ptr->pstates.pmcr[quad] =
- ((uint64_t) pmax << 48) +1; // Version 1 (Power9 format)
+ // update quad pstate request on non-OPAL systems. Version 1 (P9 format)
+ G_core_data_control_occwrite_ptr->pstates.pmcr[quad] = ((uint64_t) pmax[quad] << 48) +1;
- PROC_DBG("Setting Quad %d's Pstate to %d\n",quad, pmax);
+ PROC_DBG("Setting Quad %d's Pstate to %d\n",quad, pmax[quad]);
}
- pmax = 0; // initialize for next loop iteration
+ if(L_mfg_set_trace[quad] == TRUE)
+ {
+ TRAC_INFO("amec_slv_freq_smh: mfg Quad %d Pstate request set = 0x%02x", quad, pmax[quad]);
+ L_mfg_set_trace[quad] = FALSE;
+ L_mfg_clear_trace[quad] = TRUE;
+ }
}
}
diff --git a/src/occ_405/amec/amec_sys.h b/src/occ_405/amec/amec_sys.h
index 7fd0f95..0757466 100755
--- a/src/occ_405/amec/amec_sys.h
+++ b/src/occ_405/amec/amec_sys.h
@@ -438,7 +438,7 @@ typedef struct
amec_memctl_t memctl[MAX_NUM_MEM_CONTROLLERS];
amec_vrm_t vrm[NUM_PROC_VRMS];
amec_proc_pwr_votes_t pwr_votes;
- amec_quad_t quad[MAX_NUM_QUADS];
+ amec_quad_t quad[MAX_QUADS];
// Processor Sensors
sensor_t freqa4ms;
@@ -526,6 +526,8 @@ typedef struct amec_mnfg
bool mem_autoslew;
///memory slewing count
uint32_t mem_slew_counter;
+ ///Per Quad Pstate request: 0xFF=no request
+ uint8_t quad_pstate[MAX_QUADS];
} amec_mnfg_t;
//-------------------------------------------------------------
diff --git a/src/occ_405/cmdh/cmdh_fsp.c b/src/occ_405/cmdh/cmdh_fsp.c
index aa5b00d..1247e8a 100755
--- a/src/occ_405/cmdh/cmdh_fsp.c
+++ b/src/occ_405/cmdh/cmdh_fsp.c
@@ -941,7 +941,7 @@ errlHndl_t cmdh_processTmgtRequest (const cmdh_fsp_cmd_t * i_cmd_ptr,
break;
case CMDH_MFG_TEST_CMD:
- cmdh_mnfg_test_parse(i_cmd_ptr,i_rsp_ptr);
+ l_err = cmdh_mnfg_test_parse(i_cmd_ptr,i_rsp_ptr);
break;
case CMDH_GET_FIELD_DEBUG_DATA:
diff --git a/src/occ_405/cmdh/cmdh_fsp_cmds_datacnfg.c b/src/occ_405/cmdh/cmdh_fsp_cmds_datacnfg.c
index 8afaf67..db63d39 100755
--- a/src/occ_405/cmdh/cmdh_fsp_cmds_datacnfg.c
+++ b/src/occ_405/cmdh/cmdh_fsp_cmds_datacnfg.c
@@ -340,6 +340,14 @@ errlHndl_t data_store_freq_data(const cmdh_fsp_cmd_t * i_cmd_ptr,
// Bytes 11-12 Static Power Save Frequency Point
l_freq = (l_buf[8] << 8 | l_buf[9]);
+ // in case min freq was clipped verify power save not below min
+ if(l_freq < l_table[OCC_MODE_MIN_FREQUENCY])
+ {
+ CMDH_TRAC_ERR("Power Save Frequency[%d] is lower than min[%d]",
+ l_freq, l_table[OCC_MODE_MIN_FREQUENCY]);
+ l_freq = l_table[OCC_MODE_MIN_FREQUENCY];
+ }
+
l_table[OCC_MODE_PWRSAVE] = l_freq;
CMDH_TRAC_INFO("Static Power Save frequency = %d MHz", l_freq);
diff --git a/src/occ_405/cmdh/cmdh_mnfg_intf.c b/src/occ_405/cmdh/cmdh_mnfg_intf.c
index 2d78b68..a270b76 100755
--- a/src/occ_405/cmdh/cmdh_mnfg_intf.c
+++ b/src/occ_405/cmdh/cmdh_mnfg_intf.c
@@ -611,13 +611,114 @@ uint8_t cmdh_mnfg_get_sensor(const cmdh_fsp_cmd_t * i_cmd_ptr,
// Function Specification
//
+// Name: cmdh_mnfg_request_quad_pstate
+//
+// Description: This function handles the manufacturing command to request
+// a Pstate per Quad.
+//
+// End Function Specification
+uint8_t cmdh_mnfg_request_quad_pstate(const cmdh_fsp_cmd_t * i_cmd_ptr,
+ cmdh_fsp_rsp_t * o_rsp_ptr)
+{
+ uint8_t l_rc = ERRL_RC_SUCCESS;
+ uint16_t l_datalength = 0;
+ uint16_t l_resp_data_length = 0;
+ uint8_t l_pmin = 0xFF;
+ uint8_t l_pmax = 0xFF;
+ uint8_t l_pstate_request = 0xFF;
+ uint8_t l_quad = 0;
+ mnfg_quad_pstate_cmd_t *l_cmd_ptr = (mnfg_quad_pstate_cmd_t*) i_cmd_ptr;
+ mnfg_quad_pstate_rsp_t *l_rsp_ptr = (mnfg_quad_pstate_rsp_t*) o_rsp_ptr;
+
+ do
+ {
+ if(!IS_OCC_STATE_ACTIVE())
+ {
+ TRAC_ERR("cmdh_mnfg_request_quad_pstate: OCC must be active to request pstate");
+ l_rc = ERRL_RC_INVALID_STATE;
+ break;
+ }
+
+ if(G_sysConfigData.system_type.kvm)
+ {
+ TRAC_ERR("cmdh_mnfg_request_quad_pstate: Must be PowerVM to request pstate");
+ l_rc = ERRL_RC_INVALID_CMD;
+ break;
+ }
+
+ // Check command packet data length
+ l_datalength = CMDH_DATALEN_FIELD_UINT16(i_cmd_ptr);
+ if(l_datalength != (sizeof(mnfg_quad_pstate_cmd_t) -
+ sizeof(cmdh_fsp_cmd_header_t)))
+ {
+ TRAC_ERR("cmdh_mnfg_request_quad_pstate: incorrect data length. exp[%d] act[%d]",
+ (sizeof(mnfg_quad_pstate_cmd_t) -
+ sizeof(cmdh_fsp_cmd_header_t)),
+ l_datalength);
+ l_rc = ERRL_RC_INVALID_CMD_LEN;
+ break;
+ }
+
+ // Check version
+ if(l_cmd_ptr->version != MFG_QUAD_PSTATE_VERSION)
+ {
+ TRAC_ERR("cmdh_mnfg_request_quad_pstate: incorrect version. exp[%d] act[%d]",
+ MFG_QUAD_PSTATE_VERSION,
+ l_cmd_ptr->version);
+ l_rc = ERRL_RC_INVALID_DATA;
+ break;
+ }
+
+ // only allow a Pstate within the current range based on mode
+ l_pmin = proc_freq2pstate(g_amec->sys.fmin);
+ l_pmax = proc_freq2pstate(g_amec->sys.fmax);
+
+ // Process each quad Pstate request, clip any request to min/max
+ // 0xFF has special meaning that OCC is in control
+ for(l_quad = 0; l_quad < MAX_QUADS; l_quad++)
+ {
+ l_pstate_request = l_cmd_ptr->quad_pstate_in[l_quad];
+ if(l_pstate_request != 0xFF)
+ {
+ // pmin is lowest frequency corresponding to highest pState value
+ if(l_pstate_request > l_pmin)
+ l_pstate_request = l_pmin;
+
+ // pmax is highest frequency corresponding to lowest pState value
+ else if(l_pstate_request < l_pmax)
+ l_pstate_request = l_pmax;
+ }
+ // save the quad pState request for amec and return in rsp data
+ g_amec->mnfg_parms.quad_pstate[l_quad] = l_pstate_request;
+ l_rsp_ptr->quad_pstate_out[l_quad] = l_pstate_request;
+ TRAC_INFO("cmdh_mnfg_request_quad_pstate: Quad %d Pstate in = 0x%02x Pstate out = 0x%02x",
+ l_quad,
+ l_cmd_ptr->quad_pstate_in[l_quad],
+ l_rsp_ptr->quad_pstate_out[l_quad]);
+ }
+
+ }while(0);
+
+ // Populate the response data header
+ G_rsp_status = l_rc;
+ l_resp_data_length = sizeof(mnfg_quad_pstate_rsp_t) - sizeof(cmdh_fsp_rsp_header_t);
+ l_rsp_ptr->data_length[0] = ((uint8_t *)&l_resp_data_length)[0];
+ l_rsp_ptr->data_length[1] = ((uint8_t *)&l_resp_data_length)[1];
+
+ return l_rc;
+}
+
+
+
+// Function Specification
+//
// Name: cmdh_mnfg_test_parse
//
// Description: This function parses the manufacturing commands sent via TMGT.
//
// End Function Specification
-void cmdh_mnfg_test_parse (const cmdh_fsp_cmd_t * i_cmd_ptr,
- cmdh_fsp_rsp_t * o_rsp_ptr)
+errlHndl_t cmdh_mnfg_test_parse (const cmdh_fsp_cmd_t * i_cmd_ptr,
+ cmdh_fsp_rsp_t * o_rsp_ptr)
{
uint8_t l_rc = 0;
uint8_t l_sub_cmd = 0;
@@ -650,11 +751,10 @@ void cmdh_mnfg_test_parse (const cmdh_fsp_cmd_t * i_cmd_ptr,
l_rc = cmdh_mnfg_mem_slew(i_cmd_ptr, o_rsp_ptr);
break;
- case MNFG_RETRIEVE_EAR:
- case MNFG_SET_FMINMAX:
- case MNFG_CPM_STRESS_CALI:
- case MNFG_UV_CONTROL:
- case MNFG_FCHECK_CONTROL:
+ case MNFG_QUAD_PSTATE:
+ l_rc = cmdh_mnfg_request_quad_pstate(i_cmd_ptr, o_rsp_ptr);
+ break;
+
default:
// Should never get here...
l_rc = ERRL_RC_INVALID_DATA;
@@ -669,6 +769,7 @@ void cmdh_mnfg_test_parse (const cmdh_fsp_cmd_t * i_cmd_ptr,
cmdh_build_errl_rsp(i_cmd_ptr, o_rsp_ptr, l_rc, &l_errl);
}
- return;
+ return l_errl;
}
+
diff --git a/src/occ_405/cmdh/cmdh_mnfg_intf.h b/src/occ_405/cmdh/cmdh_mnfg_intf.h
index c3a47d5..e96ce0c 100755
--- a/src/occ_405/cmdh/cmdh_mnfg_intf.h
+++ b/src/occ_405/cmdh/cmdh_mnfg_intf.h
@@ -28,18 +28,15 @@
#include "cmdh_fsp.h"
#include "sensor.h"
+#include "p9_pstates_common.h"
typedef enum {
MNFG_RUN_STOP_SLEW = 0x02,
MNFG_LIST_SENSORS = 0x05,
MNFG_GET_SENSOR = 0x06,
MNFG_OVERSUB_EMULATION = 0x07,
- MNFG_RETRIEVE_EAR = 0x08,
MNFG_MEMORY_SLEW = 0x09,
- MNFG_SET_FMINMAX = 0x0A,
- MNFG_CPM_STRESS_CALI = 0x0D,
- MNFG_UV_CONTROL = 0x0E,
- MNFG_FCHECK_CONTROL = 0x0F,
+ MNFG_QUAD_PSTATE = 0x0A,
} MNFG_CMD;
#define MNFG_INTF_SLEW_START 0x00
@@ -172,8 +169,26 @@ typedef struct __attribute__ ((packed))
uint16_t checksum;
}cmdh_mfg_get_sensor_resp_t;
-void cmdh_mnfg_test_parse (const cmdh_fsp_cmd_t * i_cmd_ptr,
- cmdh_fsp_rsp_t * o_rsp_ptr);
+#define MFG_QUAD_PSTATE_VERSION 0
+
+// Used by OCC to get mnfg request quad pstate command
+typedef struct __attribute__ ((packed))
+{
+ struct cmdh_fsp_cmd_header;
+ uint8_t sub_cmd;
+ uint8_t version;
+ uint8_t quad_pstate_in[MAX_QUADS];
+}mnfg_quad_pstate_cmd_t;
+
+// Used by OCC firmware to respond to mnfg request quad pstate command
+typedef struct __attribute__ ((packed))
+{
+ struct cmdh_fsp_rsp_header;
+ uint8_t quad_pstate_out[MAX_QUADS];
+}mnfg_quad_pstate_rsp_t;
+
+errlHndl_t cmdh_mnfg_test_parse (const cmdh_fsp_cmd_t * i_cmd_ptr,
+ cmdh_fsp_rsp_t * o_rsp_ptr);
uint8_t cmdh_mnfg_emulate_oversub(const cmdh_fsp_cmd_t * i_cmd_ptr,
cmdh_fsp_rsp_t * o_rsp_ptr);
@@ -187,4 +202,7 @@ uint8_t cmdh_mnfg_get_sensor(const cmdh_fsp_cmd_t * i_cmd_ptr,
uint8_t cmdh_mnfg_run_stop_slew(const cmdh_fsp_cmd_t * i_cmd_ptr,
cmdh_fsp_rsp_t * o_rsp_ptr);
+uint8_t cmdh_mnfg_request_quad_pstate(const cmdh_fsp_cmd_t * i_cmd_ptr,
+ cmdh_fsp_rsp_t * o_rsp_ptr);
+
#endif
diff --git a/src/occ_405/occ_sys_config.h b/src/occ_405/occ_sys_config.h
index b774b76..25e3bd8 100755
--- a/src/occ_405/occ_sys_config.h
+++ b/src/occ_405/occ_sys_config.h
@@ -39,7 +39,6 @@
#define MAX_NUM_OCC 4
#define MAX_NUM_NODES 4
#define MAX_NUM_CORES 24
-#define MAX_NUM_QUADS 6
#define NUM_CORES_PER_QUAD 4
#define MAX_THREADS_PER_CORE 4
#define MAX_NUM_CHIP_MODULES 4
diff --git a/src/occ_405/state.c b/src/occ_405/state.c
index 1599085..03d1402 100755
--- a/src/occ_405/state.c
+++ b/src/occ_405/state.c
@@ -40,6 +40,7 @@
#include <dimm.h>
#include "pgpe_interface.h"
#include "pstate_pgpe_occ_api.h"
+#include "amec_sys.h"
extern bool G_mem_monitoring_allowed;
extern task_t G_task_table[TASK_END]; // Global task table
@@ -588,6 +589,10 @@ errlHndl_t SMGR_observation_to_active()
static bool l_error_logged = FALSE; // To prevent trace and error log happened over and over
int l_extRc = OCC_NO_EXTENDED_RC;
int l_rc = 0;
+
+ // clear mnfg quad pstate request to default OCC to control all quads
+ memset(&g_amec->mnfg_parms.quad_pstate[0], 0xFF, MAX_QUADS);
+
do
{
// NOTE that this is really unnecessary if you follow the TMGT OCC
OpenPOWER on IntegriCloud