summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorWael El-Essawy <welessa@us.ibm.com>2016-11-15 15:26:42 -0600
committerWael El-Essawy <welessa@us.ibm.com>2016-11-17 10:09:22 -0500
commit991c4f3f5eb4dc154b50466b5da901deaadc911d (patch)
tree169ba2f1e4bc80198cc95ac1b52d387b09e90344
parent8654bf4844176f1f7f28792362e475617fea1a23 (diff)
downloadtalos-occ-991c4f3f5eb4dc154b50466b5da901deaadc911d.tar.gz
talos-occ-991c4f3f5eb4dc154b50466b5da901deaadc911d.zip
OCC-OPAL Shared Memory Interface: Dynamic data updates
update the following in OPAL shared memory when any of these pieces change: * OCC State * CPU Throttle status * memory throttle status * quick power drop * power shifting ratio * power cap type * Min power cap * Max power cap * current power cap *** When either throttle status bytes change alert OPAL of shared memory interface change via setting SCOM bits 3 in the ext_intr_reason field of OCC Misc register and bit 0 (core_ext_intr) to generate the interrupt. Change-Id: Ic88a38aba4b84fb247389e712da2e326c2cd9c53 RTC: 130202 Reviewed-on: http://ralgit01.raleigh.ibm.com/gerrit1/32688 Tested-by: FSP CI Jenkins <fsp-CI-jenkins+hostboot@us.ibm.com> Reviewed-by: Christopher J. Cain <cjcain@us.ibm.com> Reviewed-by: Martha Broyles <mbroyles@us.ibm.com> Reviewed-by: Wael El-Essawy <welessa@us.ibm.com>
-rwxr-xr-xsrc/occ_405/amec/amec_data.c6
-rwxr-xr-xsrc/occ_405/amec/amec_freq.c114
-rw-r--r--src/occ_405/amec/amec_freq.h37
-rwxr-xr-xsrc/occ_405/amec/amec_slave_smh.c4
-rwxr-xr-xsrc/occ_405/cmdh/cmdh_fsp_cmds_datacnfg.c5
-rwxr-xr-xsrc/occ_405/dcom/dcom_thread.c4
-rwxr-xr-xsrc/occ_405/homer.h8
-rwxr-xr-xsrc/occ_405/proc/proc_pstate.c267
-rwxr-xr-xsrc/occ_405/proc/proc_pstate.h85
-rwxr-xr-xsrc/occ_405/state.c10
10 files changed, 373 insertions, 167 deletions
diff --git a/src/occ_405/amec/amec_data.c b/src/occ_405/amec/amec_data.c
index c5bde89..6663cdc 100755
--- a/src/occ_405/amec/amec_data.c
+++ b/src/occ_405/amec/amec_data.c
@@ -457,6 +457,12 @@ void amec_data_write_pcap(void)
g_amec->pcap.ovs_node_pcap = l_customer;
}
+ //for all new pcap data setting: If KVM, update the OPAL dynamic data
+ if(G_sysConfigData.system_type.kvm)
+ {
+ ssx_semaphore_post(&G_dcomThreadWakeupSem);
+ }
+
// update data mask notifying we got pcap information
extern data_cnfg_t * G_data_cnfg;
G_data_cnfg->data_mask |= DATA_MASK_PCAP_PRESENT;
diff --git a/src/occ_405/amec/amec_freq.c b/src/occ_405/amec/amec_freq.c
index 3f4630e..7115b37 100755
--- a/src/occ_405/amec/amec_freq.c
+++ b/src/occ_405/amec/amec_freq.c
@@ -67,9 +67,12 @@ extern dimm_sensor_flags_t G_dimm_temp_expired_bitmap;
//*************************************************************************
// Globals
//*************************************************************************
-BOOLEAN G_non_dps_power_limited = FALSE;
-uint8_t G_amec_kvm_throt_reason = NO_THROTTLE;
-uint16_t G_time_until_freq_check = FREQ_CHG_CHECK_TIME;
+BOOLEAN G_non_dps_power_limited = FALSE;
+
+opal_proc_voting_reason_t G_amec_opal_proc_throt_reason = NO_THROTTLE;
+opal_mem_voting_reason_t G_amec_opal_mem_throt_reason = NO_MEM_THROTTLE;
+
+uint16_t G_time_until_freq_check = FREQ_CHG_CHECK_TIME;
//FFDC SCOM addresses as requested by Greg Still in defect SW247927
//If new SCOM addresses are added, update the size of the array.
@@ -248,7 +251,7 @@ errlHndl_t amec_set_freq_range(const OCC_MODE i_mode)
// Function Specification
//
-// Name: amec_slv_voting_box
+// Name: amec_slv_proc_voting_box
//
// Description: Slave OCC's voting box that decides the frequency request.
// This function will run every tick.
@@ -258,7 +261,7 @@ errlHndl_t amec_set_freq_range(const OCC_MODE i_mode)
// Task Flags:
//
// End Function Specification
-void amec_slv_voting_box(void)
+void amec_slv_proc_voting_box(void)
{
/*------------------------------------------------------------------------*/
/* Local Variables */
@@ -268,7 +271,7 @@ void amec_slv_voting_box(void)
uint16_t l_core_freq = 0;
uint32_t l_chip_reason = 0;
uint32_t l_core_reason = 0;
- uint8_t l_kvm_throt_reason = NO_THROTTLE;
+ amec_proc_voting_reason_t l_kvm_throt_reason = NO_THROTTLE;
amec_part_t *l_part = NULL;
bool l_freq_req_changed = FALSE;
@@ -288,7 +291,15 @@ void amec_slv_voting_box(void)
{
l_chip_fmax = g_amec->proc[0].pwr_votes.ppb_fmax;
l_chip_reason = AMEC_VOTING_REASON_PPB;
- l_kvm_throt_reason = POWERCAP;
+
+ if( G_sysConfigData.sys_mode_freq.table[OCC_MODE_TURBO] < l_chip_fmax)
+ {
+ l_kvm_throt_reason = PCAP_EXCEED_PTURBO;
+ }
+ else
+ {
+ l_kvm_throt_reason = POWERCAP;
+ }
}
// PMAX_CLIP_FREQ
@@ -313,7 +324,15 @@ void amec_slv_voting_box(void)
{
l_chip_fmax = g_amec->thermalproc.freq_request;
l_chip_reason = AMEC_VOTING_REASON_PROC_THRM;
- l_kvm_throt_reason = CPU_OVERTEMP;
+
+ if( G_sysConfigData.sys_mode_freq.table[OCC_MODE_TURBO] < l_chip_fmax)
+ {
+ l_kvm_throt_reason = PROC_OVERTEMP_EXCEED_PTURBO;
+ }
+ else
+ {
+ l_kvm_throt_reason = CPU_OVERTEMP;
+ }
}
// Controller request based on VRHOT signal from processor regulator
@@ -321,7 +340,15 @@ void amec_slv_voting_box(void)
{
l_chip_fmax = g_amec->vrhotproc.freq_request;
l_chip_reason = AMEC_VOTING_REASON_VRHOT_THRM;
- l_kvm_throt_reason = CPU_OVERTEMP;
+
+ if(G_sysConfigData.sys_mode_freq.table[OCC_MODE_TURBO] < l_chip_fmax)
+ {
+ l_kvm_throt_reason = PROC_OVERTEMP_EXCEED_PTURBO;
+ }
+ else
+ {
+ l_kvm_throt_reason = CPU_OVERTEMP;
+ }
}
for (k=0; k<MAX_NUM_CORES; k++)
@@ -385,7 +412,15 @@ void amec_slv_voting_box(void)
{
l_core_freq = g_amec->proc[0].pwr_votes.proc_pcap_vote;
l_core_reason = AMEC_VOTING_REASON_PWR;
- l_kvm_throt_reason = POWERCAP;
+
+ if(G_sysConfigData.sys_mode_freq.table[OCC_MODE_TURBO] < l_core_freq)
+ {
+ l_kvm_throt_reason = PCAP_EXCEED_PTURBO;
+ }
+ else
+ {
+ l_kvm_throt_reason = POWERCAP;
+ }
}
}
@@ -409,6 +444,8 @@ void amec_slv_voting_box(void)
l_core_freq = g_amec->foverride;
l_core_reason = AMEC_VOTING_REASON_OVERRIDE;
}
+
+ l_kvm_throt_reason = MANUFACTURING_OVERRIDE;
}
if(g_amec->pstate_foverride_enable)
@@ -469,10 +506,9 @@ void amec_slv_voting_box(void)
sensor_update( AMECSENSOR_ARRAY_PTR(FREQ250USP0C0,k),
(uint16_t) g_amec->proc[0].core[k].f_request);
-#if 0
- /// TODO: This can be deleted if deemed useless
+#if DEBUG_PROC_VOTING_BOX
/// This trace that can be used to debug the voting
- /// box an control loops. It will trace the reason why a
+ /// box and control loops. It will trace the reason why a
/// controller is lowering the freq, but will only do it once in a
/// row for the specific freq it wants to control to. It assumes
/// that all cores will be controlled to same freq.
@@ -515,10 +551,10 @@ void amec_slv_voting_box(void)
//check if we need to update the throttle reason in homer
if(G_sysConfigData.system_type.kvm &&
- (l_kvm_throt_reason != G_amec_kvm_throt_reason))
+ (l_kvm_throt_reason != G_amec_opal_proc_throt_reason))
{
//Notify dcom thread to update the table
- G_amec_kvm_throt_reason = l_kvm_throt_reason;
+ G_amec_opal_proc_throt_reason = l_kvm_throt_reason;
ssx_semaphore_post(&G_dcomThreadWakeupSem);
}
}
@@ -537,6 +573,7 @@ void amec_slv_voting_box(void)
// End Function Specification
void amec_slv_freq_smh(void)
{
+// RTC:130201
// TODO/TEMP: Remove '#if 0' when/if needed. Currently does nothing and
// causes warning of set but not used..
#if 0
@@ -557,8 +594,8 @@ void amec_slv_freq_smh(void)
l_pstate[k]= proc_freq2pstate(g_amec->proc[0].core[k].f_request);
}
- // TODO: if this is an OPAL system, send PGPE an IPC to set clipping bounds
- // otherwise, set send PGPE an IPC to set pstates
+ // If this is an OPAL system, send PGPE an IPC to set clipping bounds
+ // otherwise, set send PGPE an IPC to set pstates
if(G_sysConfigData.system_type.kvm)
{
@@ -574,7 +611,7 @@ void amec_slv_freq_smh(void)
// Function Specification
//
-// Name: amec_slv_freq_smh
+// Name: amec_slv_mem_voting_box
//
// Description: Slave OCC's voting box that decides the memory speed request.
// This function will run every tick.
@@ -589,31 +626,42 @@ void amec_slv_mem_voting_box(void)
/*------------------------------------------------------------------------*/
/* Local Variables */
/*------------------------------------------------------------------------*/
- UINT16 l_vote;
- UINT8 l_reason;
- static INT16 l_slew_step = AMEC_MEMORY_STEP_SIZE;
- static bool L_throttle_traced = FALSE;
+ UINT16 l_vote;
+ amec_mem_voting_reason_t l_reason;
+ opal_mem_voting_reason_t kvm_reason;
+ static INT16 l_slew_step = AMEC_MEMORY_STEP_SIZE;
+ static bool L_throttle_traced = FALSE;
/*------------------------------------------------------------------------*/
/* Code */
/*------------------------------------------------------------------------*/
// Start with max allowed speed
- l_vote = AMEC_MEMORY_MAX_STEP;
- l_reason = AMEC_MEM_VOTING_REASON_INIT; // 0
+ l_vote = AMEC_MEMORY_MAX_STEP;
+ l_reason = AMEC_MEM_VOTING_REASON_INIT;
+ kvm_reason = NO_THROTTLE;
+
+ // Memory throttled due to power cap. if also throttled due to
+ // over temp, report over-temp as the reason to OPAL.
+ if (g_amec->pcap.active_mem_level != 0)
+ {
+ kvm_reason = POWER_CAP;
+ }
// Check vote from Centaur thermal control loop
if (l_vote > g_amec->thermalcent.speed_request)
{
l_vote = g_amec->thermalcent.speed_request;
- l_reason = AMEC_MEM_VOTING_REASON_CENT; // 1
+ l_reason = AMEC_MEM_VOTING_REASON_CENT;
+ kvm_reason = MEMORY_OVER_TEMP;
}
// Check vote from DIMM thermal control loop
if (l_vote > g_amec->thermaldimm.speed_request)
{
l_vote = g_amec->thermaldimm.speed_request;
- l_reason = AMEC_MEM_VOTING_REASON_DIMM; // 2
+ l_reason = AMEC_MEM_VOTING_REASON_DIMM;
+ kvm_reason = MEMORY_OVER_TEMP;
}
// Check if memory autoslewing is enabled
@@ -634,7 +682,7 @@ void amec_slv_mem_voting_box(void)
}
l_vote = g_amec->mem_speed_request + l_slew_step;
- l_reason = AMEC_MEM_VOTING_REASON_SLEW; // 3
+ l_reason = AMEC_MEM_VOTING_REASON_SLEW;
}
// Store final vote and vote reason in g_amec
@@ -664,6 +712,16 @@ void amec_slv_mem_voting_box(void)
TRAC_INFO("Memory is no longer being throttled");
}
}
+
+ //check if we need to update the throttle reason in OPAL table
+ if(G_sysConfigData.system_type.kvm &&
+ (kvm_reason != G_amec_opal_mem_throt_reason))
+ {
+ //Notify dcom thread to update the table
+ G_amec_opal_mem_throt_reason = kvm_reason;
+ ssx_semaphore_post(&G_dcomThreadWakeupSem);
+ }
+
return;
}
@@ -893,7 +951,7 @@ void amec_slv_check_perf(void)
// time to stabilize
void amec_verify_pstate()
{
-// @TODO - TEMP Pstate functions not defined yet
+// @TODO - TEMP Pstate functions not defined yet. RTC:164718
#if 0
uint8_t l_core = 0;
int8_t l_pstate_from_fmax = 0;
diff --git a/src/occ_405/amec/amec_freq.h b/src/occ_405/amec/amec_freq.h
index 651a7b1..bffb6aa 100644
--- a/src/occ_405/amec/amec_freq.h
+++ b/src/occ_405/amec/amec_freq.h
@@ -91,15 +91,38 @@ typedef enum
extern BOOLEAN G_non_dps_power_limited;
-// This is reason code used by Voting box amec_slv_mem_voting_box
+// This is memory throttle reason code used by Voting box amec_slv_mem_voting_box
typedef enum
{
- AMEC_MEM_VOTING_REASON_INIT = 0,
- AMEC_MEM_VOTING_REASON_CENT = 1,
- AMEC_MEM_VOTING_REASON_DIMM = 2,
- AMEC_MEM_VOTING_REASON_SLEW = 3,
+ AMEC_MEM_VOTING_REASON_INIT = 0x00,
+ AMEC_MEM_VOTING_REASON_CENT = 0x01,
+ AMEC_MEM_VOTING_REASON_DIMM = 0x02,
+ AMEC_MEM_VOTING_REASON_SLEW = 0x03,
}amec_mem_voting_reason_t;
+// This is memory throttle reason code encoded in OPAL dynamic data
+typedef enum
+{
+ NO_MEM_THROTTLE = 0x00,
+ POWER_CAP = 0x01,
+ MEMORY_OVER_TEMP = 0x02,
+}opal_mem_voting_reason_t;
+
+// This is processor throttle reason code used by Voting box amec_slv_proc_voting_box
+typedef enum {
+ NO_THROTTLE = 0x00,
+ POWERCAP = 0x01,
+ CPU_OVERTEMP = 0x02,
+ POWER_SUPPLY_FAILURE = 0x03,
+ OVERCURRENT = 0x04,
+ OCC_RESET = 0x05,
+ PCAP_EXCEED_PTURBO = 0x06,
+ PROC_OVERTEMP_EXCEED_PTURBO = 0x07,
+ MANUFACTURING_OVERRIDE = 0xAA,
+}amec_proc_voting_reason_t;
+
+typedef amec_proc_voting_reason_t opal_proc_voting_reason_t;
+
//*************************************************************************/
// Structures
//*************************************************************************/
@@ -155,8 +178,8 @@ void fill_pmc_ffdc_buffer(pmc_ffdc_data_t* i_ffdc_ptr);
// Used to set the freq range that amec can control between.
errlHndl_t amec_set_freq_range(const OCC_MODE i_mode);
-// Voting box for handling slave freq votes
-void amec_slv_voting_box(void);
+// Voting box for handling slave processor freq votes
+void amec_slv_proc_voting_box(void);
// Amec Frequency State Machine
void amec_slv_freq_smh(void);
diff --git a/src/occ_405/amec/amec_slave_smh.c b/src/occ_405/amec/amec_slave_smh.c
index fffb5e8..dd35652 100755
--- a/src/occ_405/amec/amec_slave_smh.c
+++ b/src/occ_405/amec/amec_slave_smh.c
@@ -342,8 +342,8 @@ void amec_slv_common_tasks_post(void)
// Call amec_power_control
amec_power_control();
- // Call the OCC slave's voting box
- amec_slv_voting_box();
+ // Call the OCC slave's processor voting box
+ amec_slv_proc_voting_box();
// Call the frequency state machine
amec_slv_freq_smh();
diff --git a/src/occ_405/cmdh/cmdh_fsp_cmds_datacnfg.c b/src/occ_405/cmdh/cmdh_fsp_cmds_datacnfg.c
index c076f1b..3dda966 100755
--- a/src/occ_405/cmdh/cmdh_fsp_cmds_datacnfg.c
+++ b/src/occ_405/cmdh/cmdh_fsp_cmds_datacnfg.c
@@ -287,9 +287,12 @@ errlHndl_t data_store_freq_data(const cmdh_fsp_cmd_t * i_cmd_ptr,
l_table[OCC_MODE_NOMINAL] = l_freq;
CMDH_TRAC_INFO("Nominal frequency = %d", l_freq);
- // Bytes 5-6 Turbo Frequency Point
+ // Bytes 5-6 Turbo Frequency Point:
+ // also store for DPS modes
l_freq = (l_buf[2] << 8 | l_buf[3]);
l_table[OCC_MODE_TURBO] = l_freq;
+ l_table[OCC_MODE_DYN_POWER_SAVE] = l_freq;
+ l_table[OCC_MODE_DYN_POWER_SAVE_FP] = l_freq;
CMDH_TRAC_INFO("Turbo frequency = %d", l_freq);
// Bytes 7-8 Minimum Frequency Point
diff --git a/src/occ_405/dcom/dcom_thread.c b/src/occ_405/dcom/dcom_thread.c
index 80b9a31..0a61a5b 100755
--- a/src/occ_405/dcom/dcom_thread.c
+++ b/src/occ_405/dcom/dcom_thread.c
@@ -36,6 +36,7 @@
#include <trac.h>
#include <state.h>
#include <proc_pstate.h>
+#include <amec_freq.h>
// Debug Counter to make sure dcom thread is running
uint16_t G_dcom_thread_counter = 0;
@@ -100,7 +101,7 @@ void Dcom_thread_routine(void *arg)
// --------------------------------------------------
if(G_sysConfigData.system_type.kvm)
{
- proc_check_for_opal_updates();
+ check_for_opal_updates();
}
// --------------------------------------------------
@@ -160,6 +161,7 @@ void Dcom_thread_routine(void *arg)
}
}
+
// --------------------------------------------------
// SSX Sleep
// --------------------------------------------------
diff --git a/src/occ_405/homer.h b/src/occ_405/homer.h
index e205878..f276c67 100755
--- a/src/occ_405/homer.h
+++ b/src/occ_405/homer.h
@@ -39,8 +39,12 @@
#define HOMER_FIR_PARM_SIZE (3 * 1024)
// OPAL table address in HOMER
-#define OPAL_OFFSET_HOMER 0x000E2000
-#define OPAL_ADDRESS_HOMER (HOMER_BASE_ADDRESS+OPAL_OFFSET_HOMER)
+#define OPAL_OFFSET_HOMER 0x000E2000 // Offset address of OPAL relative to HOMER
+#define OPAL_DYNAMIC_OFFSET 0x0B80 // Offset address of dynamic space (relative to OPAL start address)
+
+#define OPAL_ADDRESS_HOMER (HOMER_BASE_ADDRESS+OPAL_OFFSET_HOMER) // OPAL start address
+#define OPAL_STATIC_ADDRESS_HOMER OPAL_ADDRESS_HOMER // OPAL's Static Address
+#define OPAL_DYNAMIC_ADDRESS_HOMER (OPAL_ADDRESS_HOMER+OPAL_DYNAMIC_OFFSET) // OPAL's Dynamic Address
// OCC/HTMGT command buffer offset in HOMER
#define OCC_HTMGT_CMD_OFFSET_HOMER 0x000E0000
diff --git a/src/occ_405/proc/proc_pstate.c b/src/occ_405/proc/proc_pstate.c
index 23fa2c1..d63c96f 100755
--- a/src/occ_405/proc/proc_pstate.c
+++ b/src/occ_405/proc/proc_pstate.c
@@ -36,6 +36,14 @@
#include "proc_pstate.h"
#include "scom.h"
#include "homer.h"
+#include <amec_freq.h>
+#include <common.h>
+#include <amec_oversub.h>
+#include <amec_sys.h>
+
+//OPAL processor and memory throttle reason coming from the frequency voting boxes.
+extern opal_proc_voting_reason_t G_amec_opal_proc_throt_reason;
+extern opal_mem_voting_reason_t G_amec_opal_mem_throt_reason;
// Holds Fmax for ease of proc_freq2pstate calculation
uint32_t G_proc_fmax = 0;
@@ -57,11 +65,12 @@ uint8_t G_proc_pmin = 0;
// enable pstates completes successfully.
bool G_proc_pstate_enabled = FALSE;
-// Used for OPAL
-DMA_BUFFER( opal_table_t G_opal_table ) = {{0}};
+// OPAL Dynamic data, updated whenever any OCC G_opal_table.dynamic parameter change
+DMA_BUFFER( opal_dynamic_table_t G_opal_dynamic_table ) = {{0}};
+
+// OPAL Static data, updated once at transition to active state
+DMA_BUFFER( opal_static_table_t G_opal_static_table ) = {{0}};
-//KVM throttle reason coming from the frequency voting box.
-extern uint8_t G_amec_kvm_throt_reason;
// Function Specification
//
@@ -175,7 +184,7 @@ void proc_pstate_kvm_setup()
}
// Initialize the opal table in SRAM (sets valid bit)
- populate_pstate_to_opal_tbl();
+ populate_static_opal_data();
// copy sram image into mainstore HOMER
populate_opal_tbl_to_mem();
@@ -186,90 +195,61 @@ void proc_pstate_kvm_setup()
// Function Specification
//
-// Name: populate_pstate_to_opal_tbl
+// Name: populate_dynamic_opal_data
//
-// Description:
+// Description: populate the dynamic data entries in the OPAL table
//
// End Function Specification
-void populate_pstate_to_opal_tbl()
+void populate_dynamic_opal_data()
{
- uint8_t i = 0;
-
- memset(&G_opal_table, 0, sizeof(opal_table_t));
+ memset(&G_opal_dynamic_table, 0, sizeof(G_opal_dynamic_table));
- G_opal_table.config.valid = 1; // default 0x01
- G_opal_table.config.version = 1; // default 0x01
- G_opal_table.config.throttle = NO_THROTTLE; // default 0x00
- G_opal_table.config.pmin = G_proc_pmin - 1;
- G_opal_table.config.pnominal = proc_freq2pstate(G_sysConfigData.sys_mode_freq.table[OCC_MODE_NOMINAL]);
- G_opal_table.config.pmax = G_proc_pmax;
- const uint16_t l_entries = G_opal_table.config.pmin - G_opal_table.config.pmax + 1;
-// const uint8_t l_idx = l_entries-1;
+ // Dynamic OPAL runtime data
+ G_opal_dynamic_table.dynamic.occ_state = CURRENT_STATE();
- for (i = 0; i < l_entries; i++)
+ //If safe state is requested then that overrides anything from amec
+ if(isSafeStateRequested())
{
- G_opal_table.data[i].pstate = (Pstate) G_proc_pmax + i;
- G_opal_table.data[i].flag = 0; // default 0x00
-
-// @TODO: what are parameters used to calculte evids in P9?
-// Use it to calculate evids and complete OPAL Pstate table:
-
-/* if (i < l_gpst_ptr->entries)
- {
- G_opal_table.data[i].evid_vdd = l_gpst_ptr->pstate[i].fields.evid_vdd;
- G_opal_table.data[i].evid_vcs = l_gpst_ptr->pstate[i].fields.evid_vcs;
- }
- else
- {
- // leave the VDD & VCS Vids the same as the "Pstate Table Pmin"
- G_opal_table.data[i].evid_vdd = l_gpst_ptr->pstate[l_idx].fields.evid_vdd;
- G_opal_table.data[i].evid_vcs = l_gpst_ptr->pstate[l_idx].fields.evid_vcs;
- }
-*/
- // calculate frequency for pstate
- G_opal_table.data[i].freq_khz = proc_pstate2freq(G_opal_table.data[i].pstate);
+ G_opal_dynamic_table.dynamic.proc_throt_status = OCC_RESET;
+ }
+ else
+ {
+ G_opal_dynamic_table.dynamic.proc_throt_status = G_amec_opal_proc_throt_reason;
}
-}
-
+ G_opal_dynamic_table.dynamic.mem_throt_status = G_amec_opal_mem_throt_reason;
+ G_opal_dynamic_table.dynamic.quick_power_drop = AMEC_INTF_GET_OVERSUBSCRIPTION();
+ G_opal_dynamic_table.dynamic.power_shift_ratio = 50; // @TODO: Power Shift Ratio is not Implemented yet RTC:133825
+ G_opal_dynamic_table.dynamic.power_cap_type = G_master_pcap_data.source;
+ G_opal_dynamic_table.dynamic.min_power_cap = G_master_pcap_data.soft_min_pcap;
+ G_opal_dynamic_table.dynamic.max_power_cap = G_master_pcap_data.max_pcap;
+ G_opal_dynamic_table.dynamic.current_power_cap = G_master_pcap_data.current_pcap;
+}
// Function Specification
//
-// Name: proc_pstate_initialize
+// Name: populate_static_opal_data
//
-// Description: initialize Global variables required for
-// the proc_freq2pstate function.
+// Description: populate the static configuration entries,
+// the generated pstates table, and maximum pstates
+// for all possible number of active cores.
//
// End Function Specification
-void proc_pstate_initialize(void)
+void populate_static_opal_data()
{
+ memset(&G_opal_dynamic_table, 0, sizeof(G_opal_dynamic_table));
- // @TODO: Schedule a PGPE IPC to enable pstates. This will also tell
- // PGPE how to set PMCR mode register (OCC control pstates or OPAL).
- // the call back IPC function that gets executed after this IPC finishes
- // sets the G_proc_pstate_enabled flag to true, so that the OCC is then
- // able to switch to the active state.
-
- // @TODO: FIXME - TEMP Hack to enable Active State, until PGPE is ready
- G_proc_pstate_enabled = 1;
-
-
- // Set up Key Globals for use by proc_freq2pstate functions
- G_proc_fmax = 4322500;
- G_proc_fmin = 2028250;
- G_khz_per_pstate = 33250;
- G_proc_pmax = 0;
- G_proc_pmin = G_proc_pmax + ((G_proc_fmax - G_proc_fmin)/G_khz_per_pstate);
-
- // Set globals used by amec for pcap calculation
- // could have used G_khz_per_pstate in PCAP calculations
- // instead, but using a separate varaible speeds up PCAP related
- // calculations significantly, by eliminating division operations.
- G_mhz_per_pstate = G_khz_per_pstate/1000;
-
- TRAC_INFO("proc_pstate_initialize: Pstate Key globals initialized to default values");
+ // Static OPAL configuration data
+ G_opal_static_table.config.valid = 1;
+ G_opal_static_table.config.version = 0x90;
+ G_opal_static_table.config.occ_role = G_occ_role;
+ G_opal_static_table.config.pmin = pmin_rail();
+ G_opal_static_table.config.pnominal = proc_freq2pstate(G_sysConfigData.sys_mode_freq.table[OCC_MODE_NOMINAL]);
+ G_opal_static_table.config.pturbo = proc_freq2pstate(G_sysConfigData.sys_mode_freq.table[OCC_MODE_TURBO]);
+ G_opal_static_table.config.puturbo = proc_freq2pstate(G_sysConfigData.sys_mode_freq.table[OCC_MODE_UTURBO]);
+ // TODO - RTC:130201 generate pstates table & Max pstates for var #cores
}
// Function Specification
@@ -289,16 +269,17 @@ void populate_opal_tbl_to_mem()
{
BceRequest pba_copy;
// Set up copy request
- l_ssxrc = bce_request_create(&pba_copy, // block copy object
- &G_pba_bcue_queue, // sram to mainstore copy engine
- OPAL_ADDRESS_HOMER, // mainstore address
- (uint32_t) &G_opal_table, // sram starting address
- (size_t) sizeof(G_opal_table), // size of copy
- SSX_WAIT_FOREVER, // no timeout
- NULL, // call back
- NULL, // call back arguments
- ASYNC_REQUEST_BLOCKING // callback mask
- );
+ l_ssxrc = bce_request_create(
+ &pba_copy, // block copy object
+ &G_pba_bcue_queue, // sram to mainstore copy engine
+ OPAL_DYNAMIC_ADDRESS_HOMER, // mainstore address
+ (uint32_t) &G_opal_dynamic_table, // sram starting address
+ (size_t) sizeof(G_opal_dynamic_table), // size of copy
+ SSX_WAIT_FOREVER, // no timeout
+ NULL, // call back
+ NULL, // call back arguments
+ ASYNC_REQUEST_BLOCKING // callback mask
+ );
if(l_ssxrc != SSX_OK)
{
@@ -309,7 +290,7 @@ void populate_opal_tbl_to_mem()
* @reasoncode SSX_GENERIC_FAILURE
* @userdata1 RC for PBA block-copy engine
* @userdata4 ERC_BCE_REQUEST_CREATE_FAILURE
- * @devdesc SSX BCE related failure
+ * @devdesc Failed to create BCUE request
*/
l_reasonCode = SSX_GENERIC_FAILURE;
l_extReasonCode = ERC_BCE_REQUEST_CREATE_FAILURE;
@@ -328,7 +309,7 @@ void populate_opal_tbl_to_mem()
* @reasoncode SSX_GENERIC_FAILURE
* @userdata1 RC for PBA block-copy engine
* @userdata4 ERC_BCE_REQUEST_SCHEDULE_FAILURE
- * @devdesc Failed to copy data by using DMA
+ * @devdesc Failed to copy OPAL data by using BCUE
*/
l_reasonCode = SSX_GENERIC_FAILURE;
l_extReasonCode = ERC_BCE_REQUEST_SCHEDULE_FAILURE;
@@ -359,33 +340,125 @@ void populate_opal_tbl_to_mem()
// Function Specification
//
-// Name: proc_check_for_opal_updates
+// Name: proc_pstate_initialize
+//
+// Description: initialize Global variables required for
+// the proc_freq2pstate function.
+//
+// End Function Specification
+void proc_pstate_initialize(void)
+{
+ // RTC:130201
+ // @TODO: Schedule a PGPE IPC to enable pstates. This will also tell
+ // PGPE how to set PMCR mode register (OCC control pstates or OPAL).
+
+ // the call back IPC function that gets executed after this IPC finishes
+ // sets the G_proc_pstate_enabled flag to true, so that the OCC is then
+ // able to switch to the active state.
+
+ // @TODO: FIXME - TEMP Hack to enable Active State, until PGPE is ready
+ G_proc_pstate_enabled = 1;
+
+
+ // Set up Key Globals for use by proc_freq2pstate functions
+ // @TODO - FIXME ==> move to initialization code, reading from parameter block
+ G_proc_fmax = 4322500;
+ G_proc_fmin = 2028250;
+ G_khz_per_pstate = 33250;
+ G_proc_pmax = 0;
+ G_proc_pmin = G_proc_pmax + ((G_proc_fmax - G_proc_fmin)/G_khz_per_pstate);
+
+ // Set globals used by amec for pcap calculation
+ // could have used G_khz_per_pstate in PCAP calculations
+ // instead, but using a separate varaible speeds up PCAP related
+ // calculations significantly, by eliminating division operations.
+ G_mhz_per_pstate = G_khz_per_pstate/1000;
+
+ TRAC_INFO("proc_pstate_initialize: Pstate Key globals initialized to default values");
+
+}
+
+// Function Specification
+//
+// Name: check_for_opal_updates
//
// Description: Checks if the opal table needs an update
// and updates if necessary.
//
// End Function Specification
-void proc_check_for_opal_updates()
+void check_for_opal_updates(void)
{
- uint8_t l_latest_throttle_reason;
+ bool throttle_change = false;
- //If safe state is requested then that overrides anything from amec
- if(isSafeStateRequested())
+ // if throttle status change, update OPAL and notify host
+ if( (G_opal_dynamic_table.dynamic.proc_throt_status != G_amec_opal_proc_throt_reason) || // PROC throttle states changed
+ ((G_opal_dynamic_table.dynamic.proc_throt_status != OCC_RESET) && isSafeStateRequested()) || // OCC reset requested & OPAL not updated
+ (G_opal_dynamic_table.dynamic.mem_throt_status != G_amec_opal_mem_throt_reason) ) // Mem throttle status changed
{
- l_latest_throttle_reason = OCC_RESET;
+ throttle_change = true;
+ update_dynamic_opal_data();
}
- else
+
+ // else, if a dynamic OPAL parameter changed, update OPAL dynamic table and OPAL data in memory
+ else if(G_opal_dynamic_table.dynamic.occ_state != CURRENT_STATE() ||
+ G_opal_dynamic_table.dynamic.quick_power_drop != AMEC_INTF_GET_OVERSUBSCRIPTION() ||
+ G_opal_dynamic_table.dynamic.power_shift_ratio != 50 || // @TODO: Power Shift Ratio is not Implemented yet RTC:133825
+ G_opal_dynamic_table.dynamic.power_cap_type != G_master_pcap_data.source ||
+ G_opal_dynamic_table.dynamic.min_power_cap != G_master_pcap_data.soft_min_pcap ||
+ G_opal_dynamic_table.dynamic.max_power_cap != G_master_pcap_data.max_pcap ||
+ G_opal_dynamic_table.dynamic.current_power_cap != G_master_pcap_data.current_pcap )
{
- l_latest_throttle_reason = G_amec_kvm_throt_reason;
+ update_dynamic_opal_data();
}
- //If the throttle reason changed, update it in the HOMER
- if(G_opal_table.config.throttle != l_latest_throttle_reason)
+ // A throttle status change, notify host after copying dynamic OPAL data
+ if(throttle_change)
{
- TRAC_INFO("proc_check_for_opal_updates: throttle reason changed to %d", l_latest_throttle_reason);
- G_opal_table.config.throttle = l_latest_throttle_reason;
- G_opal_table.config.version = 1; // default 0x01
- G_opal_table.config.valid = 1; //default 0x01
- populate_opal_tbl_to_mem();
+ notify_host(INTR_REASON_OPAL_SHARED_MEM_CHANGE);
+ }
+}
+
+
+// Function Specification
+//
+// Name: update_dynamic_opal_data
+//
+// Description: update dynamic opal data in SRAM and
+// copy it over to OPAL space in main memory.
+//
+// End Function Specification
+void update_dynamic_opal_data (void)
+{
+ // Initialize the opal table in SRAM (sets valid bit)
+ populate_dynamic_opal_data();
+
+ // copy sram image into mainstore HOMER
+ populate_opal_tbl_to_mem();
+ TRAC_IMP("update_dynamic_opal_data: update dynamic OPAL data");
+
+
+}
+
+
+// Function Specification
+//
+// Name: pmin_rail
+//
+// Description: returns the smaller pstate (for narrower set of pstates) of:
+// 1) the min pstate from the PGPE pstate table
+// and 2) the TMGT configured min pstate
+//
+// End Function Specification
+uint8_t pmin_rail(void)
+{
+ uint8_t configMinPstate = proc_freq2pstate(G_sysConfigData.sys_mode_freq.table[OCC_MODE_MIN_FREQUENCY]);
+
+ if(configMinPstate < G_proc_pmin)
+ {
+ return configMinPstate;
+ }
+ else
+ {
+ return G_proc_pmin;
}
}
diff --git a/src/occ_405/proc/proc_pstate.h b/src/occ_405/proc/proc_pstate.h
index 7bc545a..962c71a 100755
--- a/src/occ_405/proc/proc_pstate.h
+++ b/src/occ_405/proc/proc_pstate.h
@@ -43,46 +43,63 @@ typedef struct __attribute__ ((packed))
{
uint8_t valid;
uint8_t version;
- // Sapphire_OCC_interface_v3.odp
- // throttle status 0x00 No throttle, 0x01 Powercap, 0x02 CPU overtemp, 0x03 power supply failure, 0x04 overcurrent, 0x05 OCC reset
- uint8_t throttle;
- int8_t pmin;
- int8_t pnominal;
- int8_t pmax;
- uint16_t spare;
+ uint8_t occ_role;
+ uint8_t pmin;
+ uint8_t pnominal;
+ uint8_t pturbo;
+ uint8_t puturbo;
+ uint8_t reserved;
+
} opal_config_t;
+
typedef struct __attribute__ ((packed))
{
int8_t pstate;
uint8_t flag;
- uint8_t evid_vdd;
- uint8_t evid_vcs;
+ uint16_t reserved;
uint32_t freq_khz;
-} opal_data_t;
+} opal_pstate_data_t;
+
+
+typedef struct __attribute__ ((packed))
+{
+ uint8_t occ_state;
+ uint8_t reserved[4];
+ uint8_t proc_throt_status;
+ uint8_t mem_throt_status;
+ uint8_t quick_power_drop;
+ uint8_t power_shift_ratio;
+ uint8_t power_cap_type;
+ uint16_t min_power_cap;
+ uint16_t max_power_cap;
+ uint16_t current_power_cap;
+
+} opal_dynamic_t;
-#define PSTATE_ENTRY_NUMBER 256
// This size must be a multiple of 128
typedef struct __attribute__ ((packed))
{
- opal_config_t config;
- uint64_t reserved;
- opal_data_t data[PSTATE_ENTRY_NUMBER];
- uint8_t pad[112];
-} opal_table_t __attribute__ ((aligned (128)));
-
-enum {
- NO_THROTTLE = 0x00,
- POWERCAP = 0x01,
- CPU_OVERTEMP = 0x02,
- POWER_SUPPLY_FAILURE = 0x03,
- OVERCURRENT = 0x04,
- OCC_RESET = 0x05,
-};
+ opal_dynamic_t dynamic; // Dynamic OPAL parameters: 16B
+ uint8_t pad[112]; // Reserved dynamic space: 112B
+} opal_dynamic_table_t __attribute__ ((aligned (128)));
+
+#define PSTATE_ENTRIES 256 // number of generated PSTATES entries in OPAL table
+
+// This size must be a multiple of 128
+typedef struct __attribute__ ((packed))
+{
+ opal_config_t config; // Static OPAL config parameters: 8B
+ uint8_t reserved[16]; // Reserved static space: 16B
+ opal_pstate_data_t pstates[PSTATE_ENTRIES]; // Generated Pstates Table: 2048B
+ uint8_t max_pstate[24]; // Maximum Pstate with N active cores is max_pstate[N-1]: 24B
+ uint8_t pad[56]; // Padding in reserved static space: 56B
+} opal_static_table_t __attribute__ ((aligned (128)));
+
extern uint32_t G_mhz_per_pstate;
-extern opal_table_t G_opal_table;
+extern opal_dynamic_table_t G_opal_dynamic_table;
// Initialize PState Key parameters
void proc_pstate_initialize(void);
@@ -98,11 +115,21 @@ Pstate proc_freq2pstate(uint32_t i_freq_mhz);
inline bool proc_is_hwpstate_enabled(void);
// Copy pstate data to opal table
-void populate_pstate_to_opal_tbl();
+void populate_dynamic_opal_data(void);
+
+// Copy all opal static data to opal table
+void populate_static_opal_data(void);
// Copy opal table to mainstore memory at OPAL_OFFSET_HOMER
-void populate_opal_tbl_to_mem();
+void populate_opal_tbl_to_mem(void);
// Check if opal table needs update
-void proc_check_for_opal_updates();
+void check_for_opal_updates(void);
+
+// update dynamic opal data in SRAM & main memory
+void update_dynamic_opal_data (void);
+
+void proc_pstate_kvm_setup(void);
+
+uint8_t pmin_rail(void);
#endif
diff --git a/src/occ_405/state.c b/src/occ_405/state.c
index 1314423..956d06e 100755
--- a/src/occ_405/state.c
+++ b/src/occ_405/state.c
@@ -536,9 +536,19 @@ errlHndl_t SMGR_set_state(OCC_STATE i_new_state)
// Signal that we are now in a state transition
G_state_transition_occuring = TRUE;
// Run transition function
+
l_transResult = (G_smgr_state_trans[jj].trans_func_ptr)();
+
+
// Signal that we are done with the transition
G_state_transition_occuring = FALSE;
+
+ //State transition done: If KVM, update the OPAL dynamic data
+ if(G_sysConfigData.system_type.kvm)
+ {
+ ssx_semaphore_post(&G_dcomThreadWakeupSem);
+ }
+
break;
}
}
OpenPOWER on IntegriCloud