diff options
author | Wael El-Essawy <welessa@us.ibm.com> | 2016-11-15 15:26:42 -0600 |
---|---|---|
committer | Wael El-Essawy <welessa@us.ibm.com> | 2016-11-17 10:09:22 -0500 |
commit | 991c4f3f5eb4dc154b50466b5da901deaadc911d (patch) | |
tree | 169ba2f1e4bc80198cc95ac1b52d387b09e90344 /src/occ_405 | |
parent | 8654bf4844176f1f7f28792362e475617fea1a23 (diff) | |
download | talos-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>
Diffstat (limited to 'src/occ_405')
-rwxr-xr-x | src/occ_405/amec/amec_data.c | 6 | ||||
-rwxr-xr-x | src/occ_405/amec/amec_freq.c | 114 | ||||
-rw-r--r-- | src/occ_405/amec/amec_freq.h | 37 | ||||
-rwxr-xr-x | src/occ_405/amec/amec_slave_smh.c | 4 | ||||
-rwxr-xr-x | src/occ_405/cmdh/cmdh_fsp_cmds_datacnfg.c | 5 | ||||
-rwxr-xr-x | src/occ_405/dcom/dcom_thread.c | 4 | ||||
-rwxr-xr-x | src/occ_405/homer.h | 8 | ||||
-rwxr-xr-x | src/occ_405/proc/proc_pstate.c | 267 | ||||
-rwxr-xr-x | src/occ_405/proc/proc_pstate.h | 85 | ||||
-rwxr-xr-x | src/occ_405/state.c | 10 |
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; } } |