Skip to content

Commit ad7e525

Browse files
committed
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>
1 parent 35eb166 commit ad7e525

File tree

8 files changed

+212
-40
lines changed

8 files changed

+212
-40
lines changed

src/occ_405/amec/amec_freq.c

Lines changed: 61 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -180,10 +180,12 @@ errlHndl_t amec_set_freq_range(const OCC_MODE i_mode)
180180
g_amec->sys.fmin = l_freq_min;
181181
g_amec->sys.fmax = l_freq_max;
182182

183-
TRAC_INFO("amec_set_freq_range: Mode[0x%02x] Fmin[%u] Fmax[%u]",
183+
TRAC_INFO("amec_set_freq_range: Mode[0x%02x] Fmin[%u] (Pmin 0x%02x) Fmax[%u] (Pmax 0x%02x)",
184184
i_mode,
185185
l_freq_min,
186-
l_freq_max);
186+
proc_freq2pstate(g_amec->sys.fmin),
187+
l_freq_max,
188+
proc_freq2pstate(g_amec->sys.fmax));
187189

188190
// Now determine the max frequency for the PPM structure
189191
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)
528530
/*------------------------------------------------------------------------*/
529531
/* Local Variables */
530532
/*------------------------------------------------------------------------*/
531-
uint8_t quad = 0; // loop through quads
532-
uint8_t core_num = 0; // core ID
533-
uint8_t core_idx = 0; // loop through cores within each quad
534-
Pstate pmax = 0; // select the maximum pstate (minimum frequency)
535-
// within each quad, initialize to 0 (max frequency)
533+
uint8_t quad = 0; // loop through quads
534+
uint8_t core_num = 0; // core ID
535+
uint8_t core_idx = 0; // loop through cores within each quad
536+
Pstate pmax[MAX_QUADS] = {0}; // max pstate (min frequency) within each quad
537+
Pstate pmax_chip = 0; // highest Pstate (lowest frequency) across all quads
538+
bool l_atLeast1Core[MAX_QUADS] = {FALSE}; // at least 1 core present in quad
539+
static bool L_mfg_set_trace[MAX_QUADS] = {FALSE};
540+
static bool L_mfg_clear_trace[MAX_QUADS] = {FALSE};
536541

537542
/*------------------------------------------------------------------------*/
538543
/* Code */
539544
/*------------------------------------------------------------------------*/
540545

541-
// loop through all quads, get f_requests, translate to pstates
546+
// loop through all quads, get f_requests, translate to pstates and determine pmax across chip
542547
for (quad = 0; quad < MAX_QUADS; quad++)
543548
{
544-
for (core_idx=0; core_idx<NUM_CORES_PER_QUAD; core_idx++) // scan quad cores
549+
for (core_idx=0; core_idx<NUM_CORES_PER_QUAD; core_idx++) // loop thru all cores in quad
545550
{
546-
core_num = (quad*NUM_CORES_PER_QUAD) + core_idx; // loop through all cores
551+
core_num = (quad*NUM_CORES_PER_QUAD) + core_idx;
547552

548-
// The higher the pstate number, the lower the frequency
549-
if(pmax < proc_freq2pstate(g_amec->proc[0].core[core_num].f_request))
553+
// ignore core if freq request is 0 (core not present when amec_slv_proc_voting_box ran)
554+
if(g_amec->proc[0].core[core_num].f_request != 0)
550555
{
551-
pmax = proc_freq2pstate(g_amec->proc[0].core[core_num].f_request);
556+
l_atLeast1Core[quad] = TRUE;
557+
// The higher the pstate number, the lower the frequency
558+
if(pmax[quad] < proc_freq2pstate(g_amec->proc[0].core[core_num].f_request))
559+
{
560+
pmax[quad] = proc_freq2pstate(g_amec->proc[0].core[core_num].f_request);
561+
if(pmax_chip < pmax[quad]) // check if this is a new lowest freq for the chip
562+
pmax_chip = pmax[quad];
563+
}
552564
}
553565
}
566+
}
567+
568+
// check for mfg quad Pstate request and set Pstate for each quad
569+
for (quad = 0; quad < MAX_QUADS; quad++)
570+
{
571+
// set quad with no cores present to lowest frequency for the chip
572+
if(l_atLeast1Core[quad] == FALSE)
573+
pmax[quad] = pmax_chip;
574+
575+
// check if there is a mnfg Pstate request for this quad
576+
if(g_amec->mnfg_parms.quad_pstate[quad] != 0xFF)
577+
{
578+
// use mnfg request if it is a lower frequency (higher pState)
579+
if(g_amec->mnfg_parms.quad_pstate[quad] > pmax[quad])
580+
pmax[quad] = g_amec->mnfg_parms.quad_pstate[quad];
581+
582+
if(L_mfg_clear_trace[quad] == FALSE)
583+
L_mfg_set_trace[quad] = TRUE;
584+
}
585+
else if(L_mfg_clear_trace[quad] == TRUE)
586+
{
587+
TRAC_INFO("amec_slv_freq_smh: mfg Quad %d Pstate request cleared. New Pstate = 0x%02x", quad, pmax[quad]);
588+
L_mfg_clear_trace[quad] = FALSE;
589+
}
554590

555591
// set quad clip bounds/pstates based on system type
556592
if(G_sysConfigData.system_type.kvm)
557593
{
558594
// update quad bounds on OPAL systems
559-
G_core_data_control_occwrite_ptr->clips.ps_val_clip_min[quad] =
560-
G_opal_static_table.config.pmin;
561-
G_core_data_control_occwrite_ptr->clips.ps_val_clip_max[quad] = pmax;
595+
G_core_data_control_occwrite_ptr->clips.ps_val_clip_min[quad] = G_opal_static_table.config.pmin;
596+
G_core_data_control_occwrite_ptr->clips.ps_val_clip_max[quad] = pmax[quad];
562597

563598
PROC_DBG("Setting Quad %d's min-max clip bounds to %d-%d\n",
564-
quad, G_opal_static_table.config.pmin, pmax);
599+
quad, G_opal_static_table.config.pmin, pmax[quad]);
565600
}
566601
else
567602
{
568-
// update quad pstate request on non-OPAL systems
569-
G_core_data_control_occwrite_ptr->pstates.pmcr[quad] =
570-
((uint64_t) pmax << 48) +1; // Version 1 (Power9 format)
603+
// update quad pstate request on non-OPAL systems. Version 1 (P9 format)
604+
G_core_data_control_occwrite_ptr->pstates.pmcr[quad] = ((uint64_t) pmax[quad] << 48) +1;
571605

572-
PROC_DBG("Setting Quad %d's Pstate to %d\n",quad, pmax);
606+
PROC_DBG("Setting Quad %d's Pstate to %d\n",quad, pmax[quad]);
573607
}
574608

575-
pmax = 0; // initialize for next loop iteration
609+
if(L_mfg_set_trace[quad] == TRUE)
610+
{
611+
TRAC_INFO("amec_slv_freq_smh: mfg Quad %d Pstate request set = 0x%02x", quad, pmax[quad]);
612+
L_mfg_set_trace[quad] = FALSE;
613+
L_mfg_clear_trace[quad] = TRUE;
614+
}
576615
}
577616
}
578617

src/occ_405/amec/amec_sys.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -438,7 +438,7 @@ typedef struct
438438
amec_memctl_t memctl[MAX_NUM_MEM_CONTROLLERS];
439439
amec_vrm_t vrm[NUM_PROC_VRMS];
440440
amec_proc_pwr_votes_t pwr_votes;
441-
amec_quad_t quad[MAX_NUM_QUADS];
441+
amec_quad_t quad[MAX_QUADS];
442442

443443
// Processor Sensors
444444
sensor_t freqa4ms;
@@ -526,6 +526,8 @@ typedef struct amec_mnfg
526526
bool mem_autoslew;
527527
///memory slewing count
528528
uint32_t mem_slew_counter;
529+
///Per Quad Pstate request: 0xFF=no request
530+
uint8_t quad_pstate[MAX_QUADS];
529531
} amec_mnfg_t;
530532

531533
//-------------------------------------------------------------

src/occ_405/cmdh/cmdh_fsp.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -941,7 +941,7 @@ errlHndl_t cmdh_processTmgtRequest (const cmdh_fsp_cmd_t * i_cmd_ptr,
941941
break;
942942

943943
case CMDH_MFG_TEST_CMD:
944-
cmdh_mnfg_test_parse(i_cmd_ptr,i_rsp_ptr);
944+
l_err = cmdh_mnfg_test_parse(i_cmd_ptr,i_rsp_ptr);
945945
break;
946946

947947
case CMDH_GET_FIELD_DEBUG_DATA:

src/occ_405/cmdh/cmdh_fsp_cmds_datacnfg.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -340,6 +340,14 @@ errlHndl_t data_store_freq_data(const cmdh_fsp_cmd_t * i_cmd_ptr,
340340

341341
// Bytes 11-12 Static Power Save Frequency Point
342342
l_freq = (l_buf[8] << 8 | l_buf[9]);
343+
// in case min freq was clipped verify power save not below min
344+
if(l_freq < l_table[OCC_MODE_MIN_FREQUENCY])
345+
{
346+
CMDH_TRAC_ERR("Power Save Frequency[%d] is lower than min[%d]",
347+
l_freq, l_table[OCC_MODE_MIN_FREQUENCY]);
348+
l_freq = l_table[OCC_MODE_MIN_FREQUENCY];
349+
}
350+
343351
l_table[OCC_MODE_PWRSAVE] = l_freq;
344352
CMDH_TRAC_INFO("Static Power Save frequency = %d MHz", l_freq);
345353

src/occ_405/cmdh/cmdh_mnfg_intf.c

Lines changed: 109 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -609,15 +609,116 @@ uint8_t cmdh_mnfg_get_sensor(const cmdh_fsp_cmd_t * i_cmd_ptr,
609609
return l_rc;
610610
}
611611

612+
// Function Specification
613+
//
614+
// Name: cmdh_mnfg_request_quad_pstate
615+
//
616+
// Description: This function handles the manufacturing command to request
617+
// a Pstate per Quad.
618+
//
619+
// End Function Specification
620+
uint8_t cmdh_mnfg_request_quad_pstate(const cmdh_fsp_cmd_t * i_cmd_ptr,
621+
cmdh_fsp_rsp_t * o_rsp_ptr)
622+
{
623+
uint8_t l_rc = ERRL_RC_SUCCESS;
624+
uint16_t l_datalength = 0;
625+
uint16_t l_resp_data_length = 0;
626+
uint8_t l_pmin = 0xFF;
627+
uint8_t l_pmax = 0xFF;
628+
uint8_t l_pstate_request = 0xFF;
629+
uint8_t l_quad = 0;
630+
mnfg_quad_pstate_cmd_t *l_cmd_ptr = (mnfg_quad_pstate_cmd_t*) i_cmd_ptr;
631+
mnfg_quad_pstate_rsp_t *l_rsp_ptr = (mnfg_quad_pstate_rsp_t*) o_rsp_ptr;
632+
633+
do
634+
{
635+
if(!IS_OCC_STATE_ACTIVE())
636+
{
637+
TRAC_ERR("cmdh_mnfg_request_quad_pstate: OCC must be active to request pstate");
638+
l_rc = ERRL_RC_INVALID_STATE;
639+
break;
640+
}
641+
642+
if(G_sysConfigData.system_type.kvm)
643+
{
644+
TRAC_ERR("cmdh_mnfg_request_quad_pstate: Must be PowerVM to request pstate");
645+
l_rc = ERRL_RC_INVALID_CMD;
646+
break;
647+
}
648+
649+
// Check command packet data length
650+
l_datalength = CMDH_DATALEN_FIELD_UINT16(i_cmd_ptr);
651+
if(l_datalength != (sizeof(mnfg_quad_pstate_cmd_t) -
652+
sizeof(cmdh_fsp_cmd_header_t)))
653+
{
654+
TRAC_ERR("cmdh_mnfg_request_quad_pstate: incorrect data length. exp[%d] act[%d]",
655+
(sizeof(mnfg_quad_pstate_cmd_t) -
656+
sizeof(cmdh_fsp_cmd_header_t)),
657+
l_datalength);
658+
l_rc = ERRL_RC_INVALID_CMD_LEN;
659+
break;
660+
}
661+
662+
// Check version
663+
if(l_cmd_ptr->version != MFG_QUAD_PSTATE_VERSION)
664+
{
665+
TRAC_ERR("cmdh_mnfg_request_quad_pstate: incorrect version. exp[%d] act[%d]",
666+
MFG_QUAD_PSTATE_VERSION,
667+
l_cmd_ptr->version);
668+
l_rc = ERRL_RC_INVALID_DATA;
669+
break;
670+
}
671+
672+
// only allow a Pstate within the current range based on mode
673+
l_pmin = proc_freq2pstate(g_amec->sys.fmin);
674+
l_pmax = proc_freq2pstate(g_amec->sys.fmax);
675+
676+
// Process each quad Pstate request, clip any request to min/max
677+
// 0xFF has special meaning that OCC is in control
678+
for(l_quad = 0; l_quad < MAX_QUADS; l_quad++)
679+
{
680+
l_pstate_request = l_cmd_ptr->quad_pstate_in[l_quad];
681+
if(l_pstate_request != 0xFF)
682+
{
683+
// pmin is lowest frequency corresponding to highest pState value
684+
if(l_pstate_request > l_pmin)
685+
l_pstate_request = l_pmin;
686+
687+
// pmax is highest frequency corresponding to lowest pState value
688+
else if(l_pstate_request < l_pmax)
689+
l_pstate_request = l_pmax;
690+
}
691+
// save the quad pState request for amec and return in rsp data
692+
g_amec->mnfg_parms.quad_pstate[l_quad] = l_pstate_request;
693+
l_rsp_ptr->quad_pstate_out[l_quad] = l_pstate_request;
694+
TRAC_INFO("cmdh_mnfg_request_quad_pstate: Quad %d Pstate in = 0x%02x Pstate out = 0x%02x",
695+
l_quad,
696+
l_cmd_ptr->quad_pstate_in[l_quad],
697+
l_rsp_ptr->quad_pstate_out[l_quad]);
698+
}
699+
700+
}while(0);
701+
702+
// Populate the response data header
703+
G_rsp_status = l_rc;
704+
l_resp_data_length = sizeof(mnfg_quad_pstate_rsp_t) - sizeof(cmdh_fsp_rsp_header_t);
705+
l_rsp_ptr->data_length[0] = ((uint8_t *)&l_resp_data_length)[0];
706+
l_rsp_ptr->data_length[1] = ((uint8_t *)&l_resp_data_length)[1];
707+
708+
return l_rc;
709+
}
710+
711+
712+
612713
// Function Specification
613714
//
614715
// Name: cmdh_mnfg_test_parse
615716
//
616717
// Description: This function parses the manufacturing commands sent via TMGT.
617718
//
618719
// End Function Specification
619-
void cmdh_mnfg_test_parse (const cmdh_fsp_cmd_t * i_cmd_ptr,
620-
cmdh_fsp_rsp_t * o_rsp_ptr)
720+
errlHndl_t cmdh_mnfg_test_parse (const cmdh_fsp_cmd_t * i_cmd_ptr,
721+
cmdh_fsp_rsp_t * o_rsp_ptr)
621722
{
622723
uint8_t l_rc = 0;
623724
uint8_t l_sub_cmd = 0;
@@ -650,11 +751,10 @@ void cmdh_mnfg_test_parse (const cmdh_fsp_cmd_t * i_cmd_ptr,
650751
l_rc = cmdh_mnfg_mem_slew(i_cmd_ptr, o_rsp_ptr);
651752
break;
652753

653-
case MNFG_RETRIEVE_EAR:
654-
case MNFG_SET_FMINMAX:
655-
case MNFG_CPM_STRESS_CALI:
656-
case MNFG_UV_CONTROL:
657-
case MNFG_FCHECK_CONTROL:
754+
case MNFG_QUAD_PSTATE:
755+
l_rc = cmdh_mnfg_request_quad_pstate(i_cmd_ptr, o_rsp_ptr);
756+
break;
757+
658758
default:
659759
// Should never get here...
660760
l_rc = ERRL_RC_INVALID_DATA;
@@ -669,6 +769,7 @@ void cmdh_mnfg_test_parse (const cmdh_fsp_cmd_t * i_cmd_ptr,
669769
cmdh_build_errl_rsp(i_cmd_ptr, o_rsp_ptr, l_rc, &l_errl);
670770
}
671771

672-
return;
772+
return l_errl;
673773
}
674774

775+

src/occ_405/cmdh/cmdh_mnfg_intf.h

Lines changed: 25 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -28,18 +28,15 @@
2828

2929
#include "cmdh_fsp.h"
3030
#include "sensor.h"
31+
#include "p9_pstates_common.h"
3132

3233
typedef enum {
3334
MNFG_RUN_STOP_SLEW = 0x02,
3435
MNFG_LIST_SENSORS = 0x05,
3536
MNFG_GET_SENSOR = 0x06,
3637
MNFG_OVERSUB_EMULATION = 0x07,
37-
MNFG_RETRIEVE_EAR = 0x08,
3838
MNFG_MEMORY_SLEW = 0x09,
39-
MNFG_SET_FMINMAX = 0x0A,
40-
MNFG_CPM_STRESS_CALI = 0x0D,
41-
MNFG_UV_CONTROL = 0x0E,
42-
MNFG_FCHECK_CONTROL = 0x0F,
39+
MNFG_QUAD_PSTATE = 0x0A,
4340
} MNFG_CMD;
4441

4542
#define MNFG_INTF_SLEW_START 0x00
@@ -172,8 +169,26 @@ typedef struct __attribute__ ((packed))
172169
uint16_t checksum;
173170
}cmdh_mfg_get_sensor_resp_t;
174171

175-
void cmdh_mnfg_test_parse (const cmdh_fsp_cmd_t * i_cmd_ptr,
176-
cmdh_fsp_rsp_t * o_rsp_ptr);
172+
#define MFG_QUAD_PSTATE_VERSION 0
173+
174+
// Used by OCC to get mnfg request quad pstate command
175+
typedef struct __attribute__ ((packed))
176+
{
177+
struct cmdh_fsp_cmd_header;
178+
uint8_t sub_cmd;
179+
uint8_t version;
180+
uint8_t quad_pstate_in[MAX_QUADS];
181+
}mnfg_quad_pstate_cmd_t;
182+
183+
// Used by OCC firmware to respond to mnfg request quad pstate command
184+
typedef struct __attribute__ ((packed))
185+
{
186+
struct cmdh_fsp_rsp_header;
187+
uint8_t quad_pstate_out[MAX_QUADS];
188+
}mnfg_quad_pstate_rsp_t;
189+
190+
errlHndl_t cmdh_mnfg_test_parse (const cmdh_fsp_cmd_t * i_cmd_ptr,
191+
cmdh_fsp_rsp_t * o_rsp_ptr);
177192

178193
uint8_t cmdh_mnfg_emulate_oversub(const cmdh_fsp_cmd_t * i_cmd_ptr,
179194
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,
187202
uint8_t cmdh_mnfg_run_stop_slew(const cmdh_fsp_cmd_t * i_cmd_ptr,
188203
cmdh_fsp_rsp_t * o_rsp_ptr);
189204

205+
uint8_t cmdh_mnfg_request_quad_pstate(const cmdh_fsp_cmd_t * i_cmd_ptr,
206+
cmdh_fsp_rsp_t * o_rsp_ptr);
207+
190208
#endif

src/occ_405/occ_sys_config.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,6 @@
3939
#define MAX_NUM_OCC 4
4040
#define MAX_NUM_NODES 4
4141
#define MAX_NUM_CORES 24
42-
#define MAX_NUM_QUADS 6
4342
#define NUM_CORES_PER_QUAD 4
4443
#define MAX_THREADS_PER_CORE 4
4544
#define MAX_NUM_CHIP_MODULES 4

src/occ_405/state.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040
#include <dimm.h>
4141
#include "pgpe_interface.h"
4242
#include "pstate_pgpe_occ_api.h"
43+
#include "amec_sys.h"
4344

4445
extern bool G_mem_monitoring_allowed;
4546
extern task_t G_task_table[TASK_END]; // Global task table
@@ -588,6 +589,10 @@ errlHndl_t SMGR_observation_to_active()
588589
static bool l_error_logged = FALSE; // To prevent trace and error log happened over and over
589590
int l_extRc = OCC_NO_EXTENDED_RC;
590591
int l_rc = 0;
592+
593+
// clear mnfg quad pstate request to default OCC to control all quads
594+
memset(&g_amec->mnfg_parms.quad_pstate[0], 0xFF, MAX_QUADS);
595+
591596
do
592597
{
593598
// NOTE that this is really unnecessary if you follow the TMGT OCC

0 commit comments

Comments
 (0)