From bfd62d9cfdd34d236a84c4cff77c50a4f5af7530 Mon Sep 17 00:00:00 2001 From: Andres Lugo-Reyes Date: Thu, 7 Dec 2017 12:50:43 -0600 Subject: Prevent WOF reset request on ZZ-L systems -ensure VFRT request has all the data it needs before sending Change-Id: I72fa8e2e7ebbb62ee31d0bc594af52f5197fc89e CQ:SW410590 Reviewed-on: http://ralgit01.raleigh.ibm.com/gerrit1/50656 Tested-by: FSP CI Jenkins Reviewed-by: Martha Broyles Reviewed-by: William A. Bryan Reviewed-by: Andres A. Lugo-Reyes --- src/occ_405/amec/amec_parm.h | 1 + src/occ_405/amec/amec_parm_table.c | 1 + src/occ_405/amec/amec_slave_smh.c | 8 +- src/occ_405/wof/wof.c | 216 ++++++++++++++++-------------------- src/occ_405/wof/wof.h | 18 ++- src/occ_405/wof/wof_service_codes.h | 17 +-- 6 files changed, 125 insertions(+), 136 deletions(-) diff --git a/src/occ_405/amec/amec_parm.h b/src/occ_405/amec/amec_parm.h index ddcf0e1..71f1841 100755 --- a/src/occ_405/amec/amec_parm.h +++ b/src/occ_405/amec/amec_parm.h @@ -160,6 +160,7 @@ typedef enum PARM_VDD_RATIO_FREQ, PARM_VDN_RATIO_VOLT, PARM_VDN_RATIO_FREQ, + PARM_VFRT_STATE, PARM_CORES_OFF_B4, PARM_GOOD_QUADS_PER_SORT, PARM_NORMAL_CORES_PER_SORT, diff --git a/src/occ_405/amec/amec_parm_table.c b/src/occ_405/amec/amec_parm_table.c index 9e0b0c6..6e63e6b 100755 --- a/src/occ_405/amec/amec_parm_table.c +++ b/src/occ_405/amec/amec_parm_table.c @@ -234,6 +234,7 @@ amec_parm_t g_amec_parm_list[] = { AMEC_PARM_UINT32(PARM_VDD_RATIO_FREQ, "vddRatioFreq", &g_amec_sys.wof.c_ratio_vdd_freq), AMEC_PARM_UINT32(PARM_VDN_RATIO_VOLT, "vdnRatioVolt", &g_amec_sys.wof.c_ratio_vdn_volt), AMEC_PARM_UINT32(PARM_VDN_RATIO_FREQ, "vdnRatioFreq", &g_amec_sys.wof.c_ratio_vdn_freq), + AMEC_PARM_UINT8(PARM_VFRT_STATE,"vfrtState", &g_amec_sys.wof.vfrt_state), AMEC_PARM_UINT32(PARM_CORES_OFF_B4,"Allcoresoffb4", &g_amec_sys.wof.all_cores_off_before), AMEC_PARM_UINT8(PARM_GOOD_QUADS_PER_SORT, "QuadsPerSort", &g_amec_sys.wof.good_quads_per_sort), AMEC_PARM_UINT8(PARM_NORMAL_CORES_PER_SORT, "CoresPerSort", &g_amec_sys.wof.good_normal_cores_per_sort), diff --git a/src/occ_405/amec/amec_slave_smh.c b/src/occ_405/amec/amec_slave_smh.c index 4750336..0536ee6 100755 --- a/src/occ_405/amec/amec_slave_smh.c +++ b/src/occ_405/amec/amec_slave_smh.c @@ -402,7 +402,7 @@ void amec_slv_common_tasks_pre(void) // Function Specification // -// Name: amec_slv_cmmon_tasks_post +// Name: amec_slv_common_tasks_post // // Description: Runs all the functions that need to run post-AMEC-State-Machine // This function will run every tick. @@ -447,9 +447,15 @@ void amec_slv_common_tasks_post(void) // Call the every tick trace recording if it has been configured via Amester. // If not configured, this call will return immediately. amec_tb_record(AMEC_TB_EVERY_TICK); + + // Check to see if a VFRT IPC request needs to be sent to the PGPE + schedule_vfrt_request(); } else + { L_active_1tick = TRUE; + } + } // if an OPAL system & just transitioned to CHAR or OBS state, set proc mnfg override else if ( (IS_OCC_STATE_CHARACTERIZATION() || IS_OCC_STATE_OBSERVATION()) && diff --git a/src/occ_405/wof/wof.c b/src/occ_405/wof/wof.c index 9e5e990..ff72d5f 100644 --- a/src/occ_405/wof/wof.c +++ b/src/occ_405/wof/wof.c @@ -47,6 +47,7 @@ extern GpeRequest G_wof_vfrt_req; extern GpeRequest G_wof_control_req; extern uint32_t G_nest_frequency_mhz; extern pstateStatus G_proc_pstate_status; +extern uint8_t G_occ_interrupt_type; //****************************************************************************** // Globals //****************************************************************************** @@ -126,7 +127,7 @@ void call_wof_main( void ) { // Variable to ensure we do not keep trying to send vfrt GpeRequest // more than 1 extra time. - static bool L_vfrt_last_chance = false; + static uint8_t L_vfrt_last_chance = MAX_VFRT_CHANCES; // Variable to ensure we do not keep trying to send the wof control static bool L_wof_control_last_chance = false; @@ -218,9 +219,10 @@ void call_wof_main( void ) case INITIAL_VFRT_SENT_WAITING: // Check if request is still processing. // Init state updated in wof_vfrt_callback - if( !async_request_is_idle(&G_wof_vfrt_req.request) ) + if( (!async_request_is_idle(&G_wof_vfrt_req.request)) || + (g_wof->vfrt_state != STANDBY) ) { - if( L_vfrt_last_chance ) + if( L_vfrt_last_chance == 0 ) { INTR_TRAC_ERR("WOF Disabled!" " Init VFRT request timeout"); @@ -228,15 +230,17 @@ void call_wof_main( void ) } else { - INTR_TRAC_INFO("one more chance sending initial VFRT"); - L_vfrt_last_chance = true; + INTR_TRAC_INFO("initial VFRT NOT idle." + " %d more chance(s)", + L_vfrt_last_chance ); + L_vfrt_last_chance--; } } break; case INITIAL_VFRT_SUCCESS: // We made it this far. Reset Last chance - L_vfrt_last_chance = false; + L_vfrt_last_chance = MAX_VFRT_CHANCES; // Send wof control on gpe request // If enable_success returns true, init state was set @@ -294,17 +298,19 @@ void call_wof_main( void ) !g_wof->wof_disabled ) { // Normal execution of wof algorithm - if( !async_request_is_idle(&G_wof_vfrt_req.request) ) + if( (!async_request_is_idle(&G_wof_vfrt_req.request)) || + (g_wof->vfrt_state != STANDBY) ) { - if( L_vfrt_last_chance ) + if( L_vfrt_last_chance == 0 ) { INTR_TRAC_ERR("WOF Disabled! VFRT req timeout"); set_clear_wof_disabled(SET,WOF_RC_VFRT_REQ_TIMEOUT); } else { - INTR_TRAC_INFO("One more chance for vfrt request"); - L_vfrt_last_chance = true; + INTR_TRAC_INFO("VFRT NOT idle. %d more chance(s)", + L_vfrt_last_chance); + L_vfrt_last_chance--; } } else @@ -312,7 +318,7 @@ void call_wof_main( void ) // Request is idle. Run wof algorithm wof_main(); - L_vfrt_last_chance = false; + L_vfrt_last_chance = MAX_VFRT_CHANCES; // Finally make sure we are in the fully enabled state if( g_wof->wof_init_state == PGPE_WOF_ENABLED_NO_PREV_DATA ) { @@ -379,14 +385,6 @@ void wof_main( void ) // Send the new vfrt to the PGPE send_vfrt_to_pgpe( g_wof->next_vfrt_main_mem_addr ); - if(async_request_is_idle(&G_wof_vfrt_req.request)) - { - g_wof->gpe_req_rc = pgpe_request_schedule(&G_wof_vfrt_req); - } - else - { - INTR_TRAC_ERR("VFRT REQUEST at end of wof_main() timed out"); - } } /** @@ -478,16 +476,17 @@ uint32_t calc_vfrt_mainstore_addr( void ) /** - * copy_vfrt_to_sram + * copy_vfrt_to_sram_callback * - * Description: Call back function to copy VFRT into SRAM ping/pong buffer - * This call will also tell the PGPE that a new VFRT is available + * Description: Call back function to BCE request to copy VFRT into SRAM + * ping/pong buffer. This call will also tell the PGPE + * that a new VFRT is available * * Param[in]: i_parms - pointer to a struct that will hold data necessary to * the calculation. * -Pointer to vfrt table temp buffer */ -void copy_vfrt_to_sram( void ) +void copy_vfrt_to_sram_callback( void ) { /* * @@ -520,6 +519,13 @@ void copy_vfrt_to_sram( void ) // Set the parameters for the GpeRequest G_wof_vfrt_parms.homer_vfrt_ptr = (HomerVFRTLayout_t*)l_buffer_address; G_wof_vfrt_parms.active_quads = g_wof->req_active_quad_update; + + if( g_wof->vfrt_state != STANDBY ) + { + // Set vfrt state to let OCC know it needs to schedule the IPC command + g_wof->vfrt_state = NEED_TO_SCHEDULE; + } + } /** @@ -532,6 +538,10 @@ void copy_vfrt_to_sram( void ) */ void wof_vfrt_callback( void ) { + // Update the VFRT state to indicate a new IPC message can be + // scheduled regardless of the RC of the previous one. + g_wof->vfrt_state = STANDBY; + // Confirm the WOF VFRT PGPE request has completed with no errors if( G_wof_vfrt_parms.msg_cb.rc == PGPE_WOF_RC_VFRT_QUAD_MISMATCH ) { @@ -567,7 +577,7 @@ void wof_vfrt_callback( void ) * send_vfrt_to_pgpe * * Description: Function to copy new VFRT from Mainstore to local SRAM buffer - * and calls copy_vfrt_to_sram callback function to send new VFRT + * and calls copy_vfrt_to_sram_callback function to send new VFRT * to the PGPE * Note: If desired VFRT is the same as previous, skip. * @@ -576,8 +586,6 @@ void wof_vfrt_callback( void ) void send_vfrt_to_pgpe( uint32_t i_vfrt_main_mem_addr ) { int l_ssxrc = SSX_OK; - uint32_t l_reasonCode = 0; - uint32_t l_extReasonCode = 0; do { @@ -611,44 +619,30 @@ void send_vfrt_to_pgpe( uint32_t i_vfrt_main_mem_addr ) (uint32_t) &G_vfrt_temp_buff, // SRAM start address MIN_BCE_REQ_SIZE, // size of copy SSX_WAIT_FOREVER, // no timeout - (AsyncRequestCallback)copy_vfrt_to_sram, + (AsyncRequestCallback)copy_vfrt_to_sram_callback, NULL, ASYNC_CALLBACK_IMMEDIATE ); if(l_ssxrc != SSX_OK) { INTR_TRAC_ERR("send_vfrt_to_pgpe: BCDE request create failure rc=[%08X]", -l_ssxrc); - /* - * @errortype - * @moduleid SEND_VFRT_TO_PGPE - * @reasoncode SSX_GENERIC_FAILURE - * @userdata1 RC for BCE block-copy engine - * @userdata2 Internal function checkpoint - * @userdata4 ERC_BCE_REQUEST_CREATE_FAILURE - * @devdesc Failed to create BCDE request - */ - l_reasonCode = SSX_GENERIC_FAILURE; - l_extReasonCode = ERC_BCE_REQUEST_CREATE_FAILURE; break; } - // Do the actual copy - l_ssxrc = bce_request_schedule( &G_vfrt_req ); - - if(l_ssxrc != SSX_OK) + // Make sure we are in correct vfrt state + if( g_wof->vfrt_state == STANDBY ) { - INTR_TRAC_ERR("send_vfrt_to_pgpe: BCE request schedule failure rc=[%08X]", -l_ssxrc); - /* - * @errortype - * @moduleid SEND_VFRT_TO_PGPE - * @reasoncode SSX_GENERIC_FAILURE - * @userdata1 RC for BCE block-copy engine - * @userdata4 ERC_BCE_REQUEST_SCHEDULE_FAILURE - * @devdesc Failed to read PPMR data by using BCDE - */ - l_reasonCode = SSX_GENERIC_FAILURE; - l_extReasonCode = ERC_BCE_REQUEST_SCHEDULE_FAILURE; - break; + // Set the VFRT state to ensure asynchronous order of operations + g_wof->vfrt_state = SEND_INIT; + + // Do the actual copy + l_ssxrc = bce_request_schedule( &G_vfrt_req ); + + if(l_ssxrc != SSX_OK) + { + INTR_TRAC_ERR("send_vfrt_to_pgpe: BCE request schedule failure rc=[%08X]", -l_ssxrc); + break; + } } } }while( 0 ); @@ -656,23 +650,8 @@ void send_vfrt_to_pgpe( uint32_t i_vfrt_main_mem_addr ) // Check for errors and log, if any if( l_ssxrc != SSX_OK ) { - errlHndl_t l_errl = createErrl(SEND_VFRT_TO_PGPE, //modId - l_reasonCode, //reasoncode - l_extReasonCode, //Extended reason code - ERRL_SEV_UNRECOVERABLE, //Severity - NULL, //Trace Buf - 0, //Trace Size - -l_ssxrc, //userdata1 - 0); //userdata2 - - // Callout firmware - addCalloutToErrl(l_errl, - ERRL_CALLOUT_TYPE_COMPONENT_ID, - ERRL_COMPONENT_ID_FIRMWARE, - ERRL_CALLOUT_PRIORITY_HIGH); - - // Commit error log - commitErrl(&l_errl); + // Formally disable WOF + set_clear_wof_disabled( SET, WOF_RC_IPC_FAILURE ); return; } @@ -1284,6 +1263,9 @@ void set_clear_wof_disabled( uint8_t i_action, { if( i_action == SET ) { + // Set the vfrt state back to standby + g_wof->vfrt_state = STANDBY; + // Set the bit g_wof->wof_disabled |= i_bit_mask; @@ -1444,7 +1426,7 @@ void set_clear_wof_disabled( uint8_t i_action, i_bit_mask ); // Reset if on OpenPower - if( (G_sysConfigData.system_type.kvm) ) + if( G_occ_interrupt_type != FSP_SUPPORTED_OCC ) { if(i_bit_mask & ~(IGNORE_WOF_RESET) ) { @@ -1673,6 +1655,49 @@ void wof_control_callback( void ) } } + +/** + * schedule_vfrt_request + * + * Description: Called from amec_slv_common_tasks_post every 500us. Checks + * to see if a new VFRT table is ready to be sent to the PGPE + * and if so, sends it and sets the vfrt state + */ +void schedule_vfrt_request( void ) +{ + if( (g_wof->vfrt_state == NEED_TO_SCHEDULE ) && + (async_request_is_idle(&G_wof_vfrt_req.request)) ) + { + g_wof->gpe_req_rc = pgpe_request_schedule(&G_wof_vfrt_req); + + // Check to make sure IPC request was scheduled correctly + if( g_wof->gpe_req_rc != 0 ) + { + // If we were attempting to send the initial VFRT request, + // reset the state machine so we can start the process + // over + if( g_wof->wof_init_state == INITIAL_VFRT_SENT_WAITING ) + { + g_wof->wof_init_state = WOF_DISABLED; + } + + INTR_TRAC_ERR("schedule_vfrt_request: Error sending VFRT! gperc=%d" + g_wof->gpe_req_rc ); + + // Formally disable wof + set_clear_wof_disabled( SET, WOF_RC_IPC_FAILURE ); + + // Reset the global return code after logging the error + g_wof->gpe_req_rc = 0; + } + + // Update vfrt state + g_wof->vfrt_state = SCHEDULED; + } +} + + + /** * send_initial_vfrt_to_pgpe * @@ -1692,53 +1717,6 @@ void send_initial_vfrt_to_pgpe( void ) // Send the final vfrt to shared OCC-PGPE SRAM. send_vfrt_to_pgpe( g_wof->next_vfrt_main_mem_addr ); - if(async_request_is_idle(&G_wof_vfrt_req.request)) - { - g_wof->gpe_req_rc = pgpe_request_schedule(&G_wof_vfrt_req); - } - else - { - INTR_TRAC_INFO("Intial vfrt request was NOT idle"); - } - - // Check to make sure IPC request was scheduled correctly - if( g_wof->gpe_req_rc != 0 ) - { - INTR_TRAC_ERR("send_initial_vfrt: Error sending initial VFRT! gperc=%d", - g_wof->gpe_req_rc); - //Error in scheduling wof_vfrt task - /* @ - * @errortype - * @moduleid SEND_INIT_VFRT - * @reasoncode GPE_REQUEST_SCHEDULE_FAILURE - * @userdata1 rc - gpe_request_schedule return code - * @userdata2 0 - * @userdata4 OCC_NO_EXTENDED_RC - * @devdesc OCC Failed to schedule a GPE job for wof vfrt - */ - errlHndl_t l_errl = createErrl( - SEND_INIT_VFRT, // modId - GPE_REQUEST_SCHEDULE_FAILURE, // reasoncode - OCC_NO_EXTENDED_RC, // Extended reason code - ERRL_SEV_UNRECOVERABLE, // Severity - NULL, // Trace Buf - DEFAULT_TRACE_SIZE, // Trace Size - g_wof->gpe_req_rc, // userdata1 - 0 // userdata2 - ); - - // Callout firmware - addCalloutToErrl(l_errl, - ERRL_CALLOUT_TYPE_COMPONENT_ID, - ERRL_COMPONENT_ID_FIRMWARE, - ERRL_CALLOUT_PRIORITY_HIGH); - - // Commit error log - commitErrl(&l_errl); - - // Reset the global return code after logging the error - g_wof->gpe_req_rc = 0; - } // Update Init state if(g_wof->wof_init_state < INITIAL_VFRT_SENT_WAITING) diff --git a/src/occ_405/wof/wof.h b/src/occ_405/wof/wof.h index 162c9d7..6d86e44 100644 --- a/src/occ_405/wof/wof.h +++ b/src/occ_405/wof/wof.h @@ -37,6 +37,7 @@ #define PGPE_WOF_OFF 0 #define PGPE_WOF_ON 1 #define NUM_CORES_PER_QUAD 4 +#define MAX_VFRT_CHANCES 2 #define WOF_TABLES_OFFSET 0xC0000 // Relative to PPMR_ADDRESS_HOMER #define MAX_CEFF_RATIO 10000 // 1.0 ratio = 10000 // (scaled to avoid floating point) @@ -71,6 +72,7 @@ #define WOF_RC_RESET_LIMIT_REACHED 0x00100000 #define WOF_RC_UNSUPPORTED_FREQUENCIES 0x00200000 #define WOF_RC_NO_CONFIGURED_CORES 0x00400000 +#define WOF_RC_IPC_FAILURE 0x00800000 //*************************************************************************** // Temp space used to save hard coded addresses @@ -100,6 +102,15 @@ enum wof_init_states WOF_ENABLED, //5 }; +// Enumeration to define VFRT send state +enum vfrt_send_states +{ + STANDBY, + SEND_INIT, + NEED_TO_SCHEDULE, + SCHEDULED, +}; + // Enumeration to define reasons (H)TMGT is disabling WOF enum wof_disabled_htmgt_rc { @@ -323,7 +334,8 @@ typedef struct uint32_t c_ratio_vdn_volt; // Frequency used in ceff_ratio_vdn calc uint32_t c_ratio_vdn_freq; - + // Holds the state of various async operations relating to sending a VFRT + uint8_t vfrt_state; uint32_t all_cores_off_before; //OPPB variables uint8_t good_quads_per_sort; @@ -377,7 +389,7 @@ uint8_t calc_quad_step_from_start( void ); uint32_t calc_vfrt_mainstore_addr( void ); -void copy_vfrt_to_sram( void ); +void copy_vfrt_to_sram_callback( void ); void wof_vfrt_callback( void ); @@ -444,4 +456,6 @@ void print_data( void ); void print_oppb( void ); uint32_t prevent_over_current( uint32_t i_ceff_ratio ); + +void schedule_vfrt_request( void ); #endif diff --git a/src/occ_405/wof/wof_service_codes.h b/src/occ_405/wof/wof_service_codes.h index 9e577aa..f641130 100644 --- a/src/occ_405/wof/wof_service_codes.h +++ b/src/occ_405/wof/wof_service_codes.h @@ -29,20 +29,9 @@ enum wofModuleId { - WOF_MAIN = WOF_COMP_ID | 0x01, - SEND_VFRT_TO_PGPE = WOF_COMP_ID | 0x02, - COPY_VFRT_TO_SRAM = WOF_COMP_ID | 0x03, - WOF_CONTROL_CALLBACK = WOF_COMP_ID | 0x04, - WOF_VFRT_CALLBACK = WOF_COMP_ID | 0x05, - CALC_EFF_CAP_VOLT = WOF_COMP_ID | 0x06, - CALC_EFF_CAP_FREQ = WOF_COMP_ID | 0x07, - CALC_CEFF_RATIO_VDD = WOF_COMP_ID | 0x08, - CALC_CEFF_RATIO_VDN = WOF_COMP_ID | 0x09, - DISABLE_WOF = WOF_COMP_ID | 0x0A, - ENABLE_WOF = WOF_COMP_ID | 0x0B, - SEND_INIT_VFRT = WOF_COMP_ID | 0x0C, - SET_CLEAR_WOF_DISABLED = WOF_COMP_ID | 0x0D, - CALL_WOF_MAIN = WOF_COMP_ID | 0x0E, + DISABLE_WOF = WOF_COMP_ID | 0x01, + ENABLE_WOF = WOF_COMP_ID | 0x02, + SET_CLEAR_WOF_DISABLED = WOF_COMP_ID | 0x03, }; -- cgit v1.2.1