summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorWael El-Essawy <welessa@us.ibm.com>2017-01-27 11:01:21 -0600
committerWael El-Essawy <welessa@us.ibm.com>2017-02-22 12:01:54 -0500
commitcfdf01a5cd0d5651a5930cc6ff014fade184c90f (patch)
tree49ae2529e1584732e5a9c616e11107bd39e275d4 /src
parent3b610c244fb402e50768b8d67b55a91f665a53d3 (diff)
downloadtalos-occ-cfdf01a5cd0d5651a5930cc6ff014fade184c90f.tar.gz
talos-occ-cfdf01a5cd0d5651a5930cc6ff014fade184c90f.zip
Characterization state, new state transitions and Active to Observation state
Support for new characterization state changes used by manufacturing. Observation state and new characterization state. Details in version 0.10 OCC Interface Specifications. Change-Id: I2ff0fc9327ad75e54c0a47cf42946e58f387522b RTC: 163268 Reviewed-on: http://ralgit01.raleigh.ibm.com/gerrit1/35517 Tested-by: FSP CI Jenkins <fsp-CI-jenkins+hostboot@us.ibm.com> Reviewed-by: Andres A. Lugo-Reyes <aalugore@us.ibm.com> Reviewed-by: Martha Broyles <mbroyles@us.ibm.com> Reviewed-by: Wael El-Essawy <welessa@us.ibm.com>
Diffstat (limited to 'src')
-rw-r--r--src/include/pstate_pgpe_occ_api.h53
-rwxr-xr-xsrc/occ_405/amec/amec_data.c8
-rwxr-xr-xsrc/occ_405/amec/amec_freq.c3
-rwxr-xr-xsrc/occ_405/amec/amec_slave_smh.c10
-rwxr-xr-xsrc/occ_405/main.c12
-rw-r--r--src/occ_405/occ_service_codes.h17
-rw-r--r--src/occ_405/pgpe/pgpe_interface.c325
-rw-r--r--src/occ_405/pgpe/pgpe_interface.h15
-rw-r--r--src/occ_405/pgpe/pgpe_service_codes.h3
-rwxr-xr-xsrc/occ_405/proc/proc_data_control.c243
-rwxr-xr-xsrc/occ_405/state.c971
-rwxr-xr-xsrc/occ_405/state.h32
-rwxr-xr-xsrc/occ_405/thread/chom.c6
13 files changed, 1287 insertions, 411 deletions
diff --git a/src/include/pstate_pgpe_occ_api.h b/src/include/pstate_pgpe_occ_api.h
index 0b0415e..e1c18f9 100644
--- a/src/include/pstate_pgpe_occ_api.h
+++ b/src/include/pstate_pgpe_occ_api.h
@@ -1,25 +1,19 @@
/* IBM_PROLOG_BEGIN_TAG */
/* This is an automatically generated prolog. */
/* */
-/* $Source: src/include/pstate_pgpe_occ_api.h $ */
+/* $Source: chips/p9/common/pmlib/include/pstate_pgpe_occ_api.h $ */
/* */
-/* OpenPOWER OnChipController Project */
-/* */
-/* Contributors Listed Below - COPYRIGHT 2016 */
-/* [+] International Business Machines Corp. */
+/* IBM CONFIDENTIAL */
/* */
+/* EKB Project */
/* */
-/* Licensed under the Apache License, Version 2.0 (the "License"); */
-/* you may not use this file except in compliance with the License. */
-/* You may obtain a copy of the License at */
+/* COPYRIGHT 2015,2017 */
+/* [+] International Business Machines Corp. */
/* */
-/* http://www.apache.org/licenses/LICENSE-2.0 */
/* */
-/* Unless required by applicable law or agreed to in writing, software */
-/* distributed under the License is distributed on an "AS IS" BASIS, */
-/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */
-/* implied. See the License for the specific language governing */
-/* permissions and limitations under the License. */
+/* The source code for this program is not published or otherwise */
+/* divested of its trade secrets, irrespective of what has been */
+/* deposited with the U.S. Copyright Office. */
/* */
/* IBM_PROLOG_END_TAG */
/// @file p9_pstates_pgpe_occ_api.h
@@ -41,9 +35,6 @@
extern "C" {
#endif
-// Maximum Number of Quads supported
-#define MAX_QUADS 6
-
//---------------
// IPC from 405
@@ -62,11 +53,19 @@ enum MESSAGE_ID_IPI2HI
//
// Return Codes
//
-#define PGPE_RC_SUCCESS 0x01
-#define PGPE_WOF_RC_NOT_ENABLED 0x10
+//\todo
+//Get feedback from Martha and Greg on these return codes
+//
+#define PGPE_RC_SUCCESS 0x01
+#define PGPE_WOF_RC_NOT_ENABLED 0x10
+#define PGPE_RC_PSTATES_DISABLED 0x11
+#define PGPE_RC_REQ_PSTATE_ALREADY_STARTED 0x12
+#define PGPE_RC_REQ_PSTATE_ALREADY_SUSPENDED 0x13
+#define PGPE_RC_OCC_NOT_PMCR_OWNER 0x14
// Active quad mismatch with requested active quads. PGPE did not switch
// to using the new VFRT. The original VFRT is still being used.
#define PGPE_WOF_RC_VFRT_QUAD_MISMATCH 0x20
+#define PGPE_RC_REQ_WHILE_PENDING_ACK 0x21
//
// PMCR Owner
@@ -74,7 +73,8 @@ enum MESSAGE_ID_IPI2HI
typedef enum
{
PMCR_OWNER_HOST = 0,
- PMCR_OWNER_OCC = 1
+ PMCR_OWNER_OCC = 1,
+ PMCR_OWNER_CHAR = 2
} PMCR_OWNER;
@@ -88,14 +88,14 @@ typedef struct ipcmsg_base
// Start Suspend Actions
//
#define PGPE_ACTION_PSTATE_START 0
-#define PGPE_ACTION_PSTATE_SUSPEND 1
+#define PGPE_ACTION_PSTATE_STOP 1
-typedef struct ipcmsg_start_suspend
+typedef struct ipcmsg_start_stop
{
ipcmsg_base_t msg_cb;
uint8_t action;
PMCR_OWNER pmcr_owner;
-} ipcmsg_start_suspend_t;
+} ipcmsg_start_stop_t;
typedef struct ipcmsg_clip_update
@@ -269,9 +269,9 @@ typedef union quad_state0
uint64_t quad1_pstate : 8; // Pstate of Quad 1; 0xFF indicates EQ is off
uint64_t quad2_pstate : 8; // Pstate of Quad 2; 0xFF indicates EQ is off
uint64_t quad3_pstate : 8; // Pstate of Quad 3; 0xFF indicates EQ is off
+ uint64_t core_poweron_state : 16; // bit vector: 0:core0, 1:core1, ..., 15:core15
uint64_t ivrm_state : 4; // ivrm state: bit vector 0:quad0, 1:quad1, 2:quad2, 3;quad3
uint64_t ivrm_state_rsvd : 4;
- uint64_t core_poweron_state : 16; // bit vector: 0:core0, 1:core1, ..., 15:core15
uint64_t external_vrm_setpoint : 8; // set point in mV
} fields;
} quad_state0_t;
@@ -288,12 +288,11 @@ typedef union quad_state1
{
uint64_t quad4_pstate : 8; // Pstate of Quad 4; 0xFF indicates EQ is off
uint64_t quad5_pstate : 8; // Pstate of Quad 5; 0xFF indicates EQ is off
- uint64_t requested_active_quad : 6; // Pstate of Quad 5; 0xFF indicates EQ is off
- uint64_t quad_pstate_rsvd : 10;
+ uint64_t reserved : 16;
uint64_t ivrm_state : 2; // ivrm state: bit vector 0:quad4, 1:quad5
uint64_t ivrm_state_rsvd : 6;
uint64_t core_poweron_state : 8; // bit vector: 0:core16, 1:core17, ..., 7:core23
- uint64_t core_poweron_state_rsvd : 8;
+ uint64_t requested_active_quad : 8;
uint64_t external_vrm_setpoint : 8; // set point in mV
} fields;
} quad_state1_t;
diff --git a/src/occ_405/amec/amec_data.c b/src/occ_405/amec/amec_data.c
index 05d60b9..816c59e 100755
--- a/src/occ_405/amec/amec_data.c
+++ b/src/occ_405/amec/amec_data.c
@@ -95,7 +95,7 @@ errlHndl_t AMEC_data_write_fcurr(const OCC_MODE i_mode)
/*------------------------------------------------------------------------*/
/* Local Variables */
/*------------------------------------------------------------------------*/
- errlHndl_t l_err = NULL;
+ errlHndl_t l_err = NULL;
/*------------------------------------------------------------------------*/
/* Code */
@@ -125,12 +125,10 @@ errlHndl_t AMEC_data_write_fcurr(const OCC_MODE i_mode)
if(!l_err)
{
- // set the clip bounds wide open (if not in active state)
- // if not already in active mode, send IPC command to PGPE to set
- // pStates clips wide open (pmin - pmax)
+ // set the clip bounds open (if not in active state)
if(!IS_OCC_STATE_ACTIVE())
{
- l_err = pgpe_widen_clip_ranges();
+ pgpe_widen_clip_ranges(CURRENT_STATE());
}
}
diff --git a/src/occ_405/amec/amec_freq.c b/src/occ_405/amec/amec_freq.c
index 5dadfa7..916b319 100755
--- a/src/occ_405/amec/amec_freq.c
+++ b/src/occ_405/amec/amec_freq.c
@@ -593,7 +593,7 @@ void amec_slv_freq_smh(void)
uint8_t core_num = 0; // core ID
uint8_t core_idx = 0; // loop through cores within each quad
Pstate pmax = 0; // select the maximum pstate (minimum frequency)
- // within each quad, initialize to 0
+ // within each quad, initialize to 0 (max frequency)
/*------------------------------------------------------------------------*/
/* Code */
@@ -606,6 +606,7 @@ void amec_slv_freq_smh(void)
{
core_num = (quad*NUM_CORES_PER_QUAD) + core_idx; // loop through all cores
+ // The higher the pstate number, the lower the frequency
if(pmax < proc_freq2pstate(g_amec->proc[0].core[core_num].f_request))
{
pmax = proc_freq2pstate(g_amec->proc[0].core[core_num].f_request);
diff --git a/src/occ_405/amec/amec_slave_smh.c b/src/occ_405/amec/amec_slave_smh.c
index bf33cc4..2f28289 100755
--- a/src/occ_405/amec/amec_slave_smh.c
+++ b/src/occ_405/amec/amec_slave_smh.c
@@ -62,6 +62,8 @@
// Externs
//*************************************************************************
extern dcom_slv_inbox_t G_dcom_slv_inbox_rx;
+extern opal_proc_voting_reason_t G_amec_opal_proc_throt_reason;
+
//*************************************************************************
// Macros
//*************************************************************************
@@ -345,6 +347,14 @@ void amec_slv_common_tasks_post(void)
// If not configured, this call will return immediately.
amec_tb_record(AMEC_TB_250US);
}
+ // 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()) &&
+ (MANUFACTURING_OVERRIDE != G_amec_opal_proc_throt_reason) &&
+ (G_sysConfigData.system_type.kvm == true) )
+ {
+ G_amec_opal_proc_throt_reason = MANUFACTURING_OVERRIDE;
+ ssx_semaphore_post(&G_dcomThreadWakeupSem);
+ }
}
// Function Specification
diff --git a/src/occ_405/main.c b/src/occ_405/main.c
index f34bba6..3012a01 100755
--- a/src/occ_405/main.c
+++ b/src/occ_405/main.c
@@ -1157,16 +1157,16 @@ void hmon_routine()
commitErrl(&l_err);
}
- //if we are in observation or active state, then monitor the processor temperature
- //for timeout conditions
- if (IS_OCC_STATE_OBSERVATION() || IS_OCC_STATE_ACTIVE())
+ //if we are in observation, characterization, or activate state, then monitor the processor
+ //temperature for timeout conditions and the processor VRHOT signal.
+ if (IS_OCC_STATE_OBSERVATION() || IS_OCC_STATE_ACTIVE() || IS_OCC_STATE_CHARACTERIZATION())
{
amec_health_check_proc_timeout();
}
- //if we are in observation or active state with memory temperature data being collected
- //then monitor the temperature collections for overtemp and timeout conditions
- if((IS_OCC_STATE_OBSERVATION() || IS_OCC_STATE_ACTIVE()) &&
+ //if we are in observation, characterization, or active state with memory temperature data
+ // being collected then monitor the temperature collections for overtemp and timeout conditions
+ if((IS_OCC_STATE_OBSERVATION() || IS_OCC_STATE_ACTIVE() || IS_OCC_STATE_CHARACTERIZATION()) &&
rtl_task_is_runnable(TASK_ID_DIMM_SM))
{
// For Cumulus systems only, check for centaur timeout and overtemp errors
diff --git a/src/occ_405/occ_service_codes.h b/src/occ_405/occ_service_codes.h
index a98ae03..c55194f 100644
--- a/src/occ_405/occ_service_codes.h
+++ b/src/occ_405/occ_service_codes.h
@@ -172,10 +172,6 @@ enum occExtReasonCode
ERC_APSS_ADC_OUT_OF_RANGE_FAILURE = 0x0026,
ERC_APSS_ADC_DUPLICATED_FAILURE = 0x0027,
- ERC_STATE_FROM_OBS_TO_STB_FAILURE = 0x0028,
- ERC_STATE_FROM_STB_TO_OBS_FAILURE = 0x0029,
- ERC_STATE_HEARTBEAT_CFG_FAILURE = 0x0080,
-
ERC_AMEC_PCAPS_MISMATCH_FAILURE = 0x002A,
ERC_AMEC_UNDER_PCAP_FAILURE = 0x002B,
@@ -236,12 +232,15 @@ enum occExtReasonCode
ERC_PGPE_BEACON_TIMEOUT = 0x00B0,
ERC_PGPE_NOT_IDLE = 0x00B1,
ERC_PGPE_UNSUCCESSFULL = 0x00B2,
+
ERC_PGPE_CLIP_UNSUCCESSFULL = 0x00B3,
ERC_PGPE_PMCR_UNSUCCESSFULL = 0x00B4,
ERC_PGPE_START_FAILURE = 0x00B5,
ERC_PGPE_SUSPEND_FAILURE = 0x00B6,
ERC_PGPE_CLIP_FAILURE = 0x00B7,
ERC_PGPE_PPMR_OPPB_SIZE_MISMATCH = 0x00B8,
+ ERC_PGPE_ACTIVE_TO_OBSERVATION_TIMEOUT = 0x00B9,
+ ERC_PGPE_TASK_TIMEOUT = 0x00BA,
ERC_WOF_QUAD_COUNT_FAILURE = 0x00C0,
@@ -250,6 +249,16 @@ enum occExtReasonCode
ERC_SMGR_NO_VALID_MODE_TRANSITION_CALL = 0x00E0,
ERC_SMGR_NO_VALID_STATE_TRANSITION_CALL = 0x00E1,
+
+ ERC_STATE_FROM_ALL_TO_STB_FAILURE = 0x0123,
+ ERC_STATE_FROM_ACT_TO_CHR_FAILURE = 0x0124,
+ ERC_STATE_FROM_CHR_TO_ACT_FAILURE = 0x0125,
+ ERC_STATE_FROM_CHR_TO_OBS_FAILURE = 0x0126,
+ ERC_STATE_FROM_OBS_TO_CHR_FAILURE = 0x0127,
+ ERC_STATE_FROM_STB_TO_CHR_FAILURE = 0x0128,
+ ERC_STATE_FROM_STB_TO_OBS_FAILURE = 0x0129,
+
+ ERC_STATE_HEARTBEAT_CFG_FAILURE = 0x0180,
};
// Error log Module Ids
diff --git a/src/occ_405/pgpe/pgpe_interface.c b/src/occ_405/pgpe/pgpe_interface.c
index bbdf801..b459b44 100644
--- a/src/occ_405/pgpe/pgpe_interface.c
+++ b/src/occ_405/pgpe/pgpe_interface.c
@@ -35,6 +35,7 @@
#include "proc_pstate.h"
#include "proc_data_control.h"
#include "occ_sys_config.h"
+#include "ssx.h"
extern opal_static_table_t G_opal_static_table;
@@ -56,7 +57,7 @@ GpeRequest G_wof_vfrt_req;
// The the GPE parameter fields for PGPE IPC calls.
GPE_BUFFER(ipcmsg_clip_update_t* G_clip_update_parms_ptr);
GPE_BUFFER(ipcmsg_set_pmcr_t* G_pmcr_set_parms_ptr);
-GPE_BUFFER(ipcmsg_start_suspend_t G_start_suspend_parms);
+GPE_BUFFER(ipcmsg_start_stop_t G_start_suspend_parms);
GPE_BUFFER(ipcmsg_wof_control_t G_wof_control_parms);
GPE_BUFFER(ipcmsg_wof_vfrt_t G_wof_vfrt_parms);
@@ -69,7 +70,7 @@ GPE_BUFFER(ipcmsg_wof_vfrt_t G_wof_vfrt_parms);
//
// End Function Specification
-errlHndl_t init_pgpe_ipcs(void)
+void init_pgpe_ipcs(void)
{
errlHndl_t err = NULL; // Error handler
@@ -108,18 +109,19 @@ errlHndl_t init_pgpe_ipcs(void)
{
REQUEST_RESET(err);
}
+ else
+ {
+ // Initialization used in the task_core_data_control for PGPE success
+ // checks made before the first clip/pstate IPC message to be ever sent
+ // from either of the two double buffers.
+ G_core_data_control_occwrite_ptr->clips.msg_cb.rc = PGPE_RC_SUCCESS;
+ G_core_data_control_occwrite_ptr->pstates.msg_cb.rc = PGPE_RC_SUCCESS;
+
+ G_core_data_control_gpewrite_ptr->clips.msg_cb.rc = PGPE_RC_SUCCESS;
+ G_core_data_control_gpewrite_ptr->pstates.msg_cb.rc = PGPE_RC_SUCCESS;
+ }
- // Initialization used in the task_core_data_control for PGPE success
- // checks made before the first clip/pstate IPC message to be ever sent
- // from either of the two double buffers.
- G_core_data_control_occwrite_ptr->clips.msg_cb.rc = PGPE_RC_SUCCESS;
- G_core_data_control_occwrite_ptr->pstates.msg_cb.rc = PGPE_RC_SUCCESS;
-
- G_core_data_control_gpewrite_ptr->clips.msg_cb.rc = PGPE_RC_SUCCESS;
- G_core_data_control_gpewrite_ptr->pstates.msg_cb.rc = PGPE_RC_SUCCESS;
-
-
- return(err);
+ return;
}
@@ -411,65 +413,227 @@ errlHndl_t pgpe_init_wof_vfrt(void)
// Function Specification
//
-// Name: pgpe_widen_clip_ranges
+// Name: pgpe_widen_clip_blocking
//
-// Description: Wide open PGPE clip ranges. Since this IPC call
-// is non-blocking, this routine has to assure call
-// completion before checking the pgpe return value.
+// Description: a blocking version of pgpe_widen_clip_ranges
+// this call waits until the clip IPC task completes,
+// and verifies this was a successful completion.
//
// End Function Specification
-errlHndl_t pgpe_widen_clip_ranges(void)
+#define CLIP_UPDATE_TIMEOUT 5 //maximum waiting time (usec) for clip update IPC task
+int pgpe_widen_clip_blocking(OCC_STATE state)
{
+ errlHndl_t err;
+ uint8_t wait_time = 0;
+ int rc = 0; // Return code: 0 means success, otherwise an error.
- errlHndl_t err = NULL; // Error handler
- uint8_t i; // Loop variable
+ do
+ {
+ // verify that the clip update IPC task is not currently running
+ if( !async_request_is_idle(&G_clip_update_req.request) )
+ {
+ // an earlier clip update IPC call has not completed, trace and log an error
+ TRAC_ERR("pgpe_blocking_widen_clip: clip update IPC task is not Idle");
+
+ /*
+ * @errortype
+ * @moduleid PGPE_WIDEN_CLIP_BLOCKING_MOD
+ * @reasoncode PGPE_FAILURE
+ * @userdata4 ERC_PGPE_NOT_IDLE
+ * @devdesc pgpe clip update not idle
+ */
+ err = createErrl(
+ PGPE_WIDEN_CLIP_BLOCKING_MOD, //ModId
+ PGPE_FAILURE, //Reasoncode
+ ERC_PGPE_NOT_IDLE, //Extended reason code
+ ERRL_SEV_PREDICTIVE, //Severity
+ NULL, //Trace Buf
+ DEFAULT_TRACE_SIZE, //Trace Size
+ 0, //Userdata1
+ 0 //Userdata2
+ );
+
+ rc = PGPE_FAILURE;
+ break;
+ }
+ else
+ {
+ // the function call to widen the clips
+ rc = pgpe_widen_clip_ranges(state);
+
+ // clip update task failed
+ if(rc)
+ {
+ break;
+ }
+ }
+
+
+ // Wait until the clip_update IPC task completes
+ while( !async_request_is_idle(&G_clip_update_req.request) )
+ {
+ if(wait_time > CLIP_UPDATE_TIMEOUT)
+ {
+ TRAC_ERR("pgpe_blocking_widen_clip: clip update IPC task timeout!");
+
+ /*
+ * @errortype
+ * @moduleid PGPE_WIDEN_CLIP_BLOCKING_MOD
+ * @reasoncode GPE_REQUEST_TASK_TIMEOUT
+ * @userdata4 OCC_NO_EXTENDED_RC
+ * @devdesc pgpe clip update timeout
+ */
+ err = createErrl(
+ PGPE_WIDEN_CLIP_BLOCKING_MOD, //ModId
+ GPE_REQUEST_TASK_TIMEOUT, //Reasoncode
+ OCC_NO_EXTENDED_RC, //Extended reason code
+ ERRL_SEV_PREDICTIVE, //Severity
+ NULL, //Trace Buf
+ DEFAULT_TRACE_SIZE, //Trace Size
+ 0, //Userdata1
+ 0 //Userdata2
+ );
+
+ rc = GPE_REQUEST_TASK_TIMEOUT;
+ break;
+ }
+
+ // sleep for 1 microsecond (allows context switching)
+ ssx_sleep(SSX_MICROSECONDS(1));
+
+ wait_time++;
+ }
+
+ // clip update timed out
+ if(err)
+ {
+ break;
+ }
+
+ // IPC task completed. check for errors
+ if ( G_clip_update_parms_ptr->msg_cb.rc != PGPE_RC_SUCCESS )
+ {
+ // clip update IPC call has not completed, trace and log an error
+ TRAC_ERR("pgpe_blocking_widen_clip: clip update IPC task "
+ "returned an error [0x%08X]",
+ G_clip_update_parms_ptr->msg_cb.rc);
+
+ /*
+ * @errortype
+ * @moduleid PGPE_WIDEN_CLIP_BLOCKING_MOD
+ * @reasoncode GPE_REQUEST_RC_FAILURE
+ * @userdata1 PGPE clip update's rc
+ * @userdata4 OCC_NO_EXTENDED_RC
+ * @devdesc pgpe clip update returned a failure code
+ */
+ err = createErrl(
+ PGPE_WIDEN_CLIP_BLOCKING_MOD, //ModId
+ GPE_REQUEST_RC_FAILURE, //Reasoncode
+ OCC_NO_EXTENDED_RC, //Extended reason code
+ ERRL_SEV_PREDICTIVE, //Severity
+ NULL, //Trace Buf
+ DEFAULT_TRACE_SIZE, //Trace Size
+ G_clip_update_parms_ptr->msg_cb.rc, //Userdata1
+ 0 //Userdata2
+ );
+
+ rc = GPE_REQUEST_RC_FAILURE;
+ }
+ } while (0);
- // Set clip bounds wide open
- for(i=0; i<MAX_QUADS; i++)
+ if(err)
{
- // minimum pstate
- G_clip_update_parms_ptr->ps_val_clip_min[i] = pmin_rail();
+ REQUEST_RESET(err);
+ }
+
+ return(rc);
+}
+
- // maximum pstate:
- G_clip_update_parms_ptr->ps_val_clip_max[i] = proc_freq2pstate(G_proc_fmax_mhz);
+// Function Specification
+//
+// Name: pgpe_widen_clip_ranges
+//
+// Description: Widens PGPE clip ranges between minimum pstate,
+// and maximum pstate allowed in the specified
+// "state" parameter. Since this IPC call is
+// non-blocking, the caller has to assure that
+// IPC clip update task is idle, wait for IPC task
+// completion, then check the pgpe return value.
+//
+// End Function Specification
+
+int pgpe_widen_clip_ranges(OCC_STATE state)
+{
+
+ errlHndl_t err = NULL; // Error handler
+ int rc = 0; // return code
+ uint8_t quad; // Loop variable
+
+ Pstate pmin = pmin_rail();
+ Pstate pmax;
+
+ bool valid_state = false;
+
+ // when transitioning to observation state,
+ // set max clip to legacy turbo pstate clip
+ if(state == OCC_STATE_OBSERVATION)
+ {
+ pmax = proc_freq2pstate(G_sysConfigData.sys_mode_freq.table[OCC_MODE_TURBO]);
+ valid_state = true;
+ }
+ // when transitioning to active or characterization state,
+ // wide open the clips. If WOF is enabled set it to ultra
+ // -turbo pstate, else, set it to turbo pstate.
+ else if (state == OCC_STATE_ACTIVE || state == OCC_STATE_CHARACTERIZATION)
+ {
+ pmax = proc_freq2pstate(G_proc_fmax_mhz);
+ valid_state = true;
}
- // Check that no previous clip update calls are still in progress
- if(async_request_is_idle(&G_clip_update_req.request))
+ if(valid_state)
{
+ // Set clip bounds
+ for(quad=0; quad<MAX_QUADS; quad++)
+ {
+ // minimum pstate, independent of state
+ G_clip_update_parms_ptr->ps_val_clip_min[quad] = pmin;
+
+ // max pstate (legacy turbo / ultra-turbo)
+ G_clip_update_parms_ptr->ps_val_clip_max[quad] = pmax;
+ }
+
// will check for this IPC completion at transition to active state
- err = pgpe_clip_update();
+ rc = pgpe_clip_update();
}
else
{
- // an earlier clip update IPC call has not completed, trace and log an error
- TRAC_ERR("pgpe_widen_clip_ranges: clip update IPC task is not Idle");
-
- // log an error
- MAIN_TRAC_ERR("pgpe_widen_clip_ranges: clip update IPC is not Idle");
-
+ TRAC_ERR("pgpe_widen_clip_ranges: should never be called in state %d", state);
/*
* @errortype
* @moduleid PGPE_WIDEN_CLIP_RANGES_MOD
* @reasoncode PGPE_FAILURE
- * @userdata1 0
- * @userdata4 ERC_PGPE_NOT_IDLE
- * @devdesc pgpe clip update not idle
+ * @userdata1 state
+ * @userdata4 ERC_PGPE_CLIP_FAILURE
+ * @devdesc pgpe clip update requested in an invalid state
*/
err = createErrl(
- PGPE_WIDEN_CLIP_RANGES_MOD, //ModId
- PGPE_FAILURE, //Reasoncode
- OCC_NO_EXTENDED_RC, //Extended reason code
- ERRL_SEV_PREDICTIVE, //Severity
- NULL, //Trace Buf
- DEFAULT_TRACE_SIZE, //Trace Size
- 0, //Userdata1
- 0 //Userdata2
+ PGPE_WIDEN_CLIP_RANGES_MOD, //ModId
+ PGPE_FAILURE, //Reasoncode
+ ERC_PGPE_CLIP_FAILURE, //Extended reason code
+ ERRL_SEV_PREDICTIVE, //Severity
+ NULL, //Trace Buf
+ DEFAULT_TRACE_SIZE, //Trace Size
+ state, //Userdata1
+ 0 //Userdata2
);
+
+ rc = PGPE_FAILURE;
+ REQUEST_RESET(err);
}
- return(err);
+ return(rc);
}
// Function Specification
@@ -482,10 +646,10 @@ errlHndl_t pgpe_widen_clip_ranges(void)
//
// End Function Specification
-errlHndl_t pgpe_clip_update(void)
+int pgpe_clip_update(void)
{
- int rc; // gpe schedule return code
- errlHndl_t err = NULL; // Error handler
+ int rc = 0; // return code
+ errlHndl_t err = NULL; // Error handler
do
{
@@ -515,6 +679,15 @@ errlHndl_t pgpe_clip_update(void)
0 //Userdata2
);
+ // Callout firmware
+ addCalloutToErrl(err,
+ ERRL_CALLOUT_TYPE_COMPONENT_ID,
+ ERRL_COMPONENT_ID_FIRMWARE,
+ ERRL_CALLOUT_PRIORITY_HIGH);
+
+ commitErrl(&err);
+
+ rc = PGPE_FAILURE;
break;
}
@@ -554,11 +727,12 @@ errlHndl_t pgpe_clip_update(void)
0 // userdata2
);
+ rc = GPE_REQUEST_SCHEDULE_FAILURE;
REQUEST_RESET(err); //This will add a firmware callout for us
}
}while(0);
- return err;
+ return rc;
}
@@ -617,15 +791,16 @@ void pgpe_start_suspend_callback(void)
{
// Pstates are now enabled (enable Active State transition).
G_proc_pstate_status = PSTATES_ENABLED;
+
+ // upon successful pstates START, assign G_proc_pmcr_owner (OCC/CHAR/HOST)
+ G_proc_pmcr_owner = G_start_suspend_parms.pmcr_owner;
}
// this was a command to disable pstates
- else if(G_start_suspend_parms.action == PGPE_ACTION_PSTATE_SUSPEND)
+ else if(G_start_suspend_parms.action == PGPE_ACTION_PSTATE_STOP)
{
// Pstates are now disabled (disaable Active State transition).
G_proc_pstate_status = PSTATES_DISABLED;
}
-
- G_proc_pmcr_owner = G_start_suspend_parms.pmcr_owner;
}
} while(0);
@@ -645,25 +820,13 @@ void pgpe_start_suspend_callback(void)
//
// End Function Specification
-errlHndl_t pgpe_start_suspend(uint8_t action)
+int pgpe_start_suspend(uint8_t action, PMCR_OWNER owner)
{
- PMCR_OWNER owner; // PMCR owner
- int rc; // gpe schedule return codes
+ int rc; // return code
errlHndl_t err = NULL; // Error handler
- // For now, we set PMCR ownership based on whether the system
- // is OPAL system or not.
- if(G_sysConfigData.system_type.kvm)
- {
- owner = PMCR_OWNER_HOST;
- }
- else
- {
- owner = PMCR_OWNER_OCC;
- }
-
// set the IPC parameters
- G_start_suspend_parms.action = action;
+ G_start_suspend_parms.action = action;
G_start_suspend_parms.pmcr_owner = owner;
// @TODO: remove this precompile directive check when PGPE code is integrated.
@@ -700,6 +863,7 @@ errlHndl_t pgpe_start_suspend(uint8_t action)
0 // userdata2
);
+ rc = GPE_REQUEST_SCHEDULE_FAILURE;
REQUEST_RESET(err); //This will add a firmware callout for us
}
// successfully scheduled, set the G_proc_pstate_status to indicate transition
@@ -712,7 +876,7 @@ errlHndl_t pgpe_start_suspend(uint8_t action)
pgpe_start_suspend_callback();
#endif
- return err;
+ return rc;
}
@@ -727,9 +891,9 @@ errlHndl_t pgpe_start_suspend(uint8_t action)
//
// End Function Specification
-errlHndl_t pgpe_pmcr_set(void)
+int pgpe_pmcr_set(void)
{
- int rc; // gpe schedule return codes
+ int rc; // return code
errlHndl_t err = NULL; // Error handler
do
@@ -760,6 +924,15 @@ errlHndl_t pgpe_pmcr_set(void)
0 //Userdata2
);
+ // Callout firmware
+ addCalloutToErrl(err,
+ ERRL_CALLOUT_TYPE_COMPONENT_ID,
+ ERRL_COMPONENT_ID_FIRMWARE,
+ ERRL_CALLOUT_PRIORITY_HIGH);
+
+ commitErrl(&err);
+
+ rc = PGPE_FAILURE;
break;
}
@@ -778,10 +951,7 @@ errlHndl_t pgpe_pmcr_set(void)
//Error in scheduling pgpe clip update task
TRAC_ERR("pgpe_pmcr_set: Failed to schedule PMCR setup pgpe task rc=%x",
rc);
- }
- if(rc != 0)
- {
/* @
* @errortype
* @moduleid PGPE_PMCR_SET_MOD
@@ -790,7 +960,7 @@ errlHndl_t pgpe_pmcr_set(void)
* @userdata2 0
* @userdata4 OCC_NO_EXTENDED_RC
* @devdesc OCC Failed to schedule a GPE job for clip update
- */
+ */
err = createErrl(
PGPE_PMCR_SET_MOD, // modId
GPE_REQUEST_SCHEDULE_FAILURE, // reasoncode
@@ -802,11 +972,12 @@ errlHndl_t pgpe_pmcr_set(void)
0 // userdata2
);
+ rc = GPE_REQUEST_SCHEDULE_FAILURE;
REQUEST_RESET(err); //This will add a firmware callout for us
}
}
while(0);
- return err;
+ return rc;
}
diff --git a/src/occ_405/pgpe/pgpe_interface.h b/src/occ_405/pgpe/pgpe_interface.h
index a777f28..539c422 100644
--- a/src/occ_405/pgpe/pgpe_interface.h
+++ b/src/occ_405/pgpe/pgpe_interface.h
@@ -27,8 +27,10 @@
#define _PGPE_INTERFACE_H_
#include "errl.h"
+#include "state.h"
+#include "pstate_pgpe_occ_api.h"
-errlHndl_t init_pgpe_ipcs(void);
+void init_pgpe_ipcs(void);
errlHndl_t pgpe_init_clips(void);
errlHndl_t pgpe_init_pmcr(void);
@@ -36,10 +38,13 @@ errlHndl_t pgpe_init_start_suspend(void);
errlHndl_t pgpe_init_wof_control(void);
errlHndl_t pgpe_init_wof_vfrt(void);
-errlHndl_t pgpe_widen_clip_ranges(void);
-errlHndl_t pgpe_clip_update(void);
-errlHndl_t pgpe_pmcr_set(void);
-errlHndl_t pgpe_start_suspend(uint8_t action);
+int pgpe_widen_clip_ranges(OCC_STATE state);
+int pgpe_widen_clip_blocking(OCC_STATE state);
+int pgpe_clip_update(void);
+
+int pgpe_pmcr_set(void);
+
+int pgpe_start_suspend(uint8_t action, PMCR_OWNER owner);
void pgpe_start_suspend_callback(void);
#endif /* #ifndef _PGPE_INTERFACE_H_ */
diff --git a/src/occ_405/pgpe/pgpe_service_codes.h b/src/occ_405/pgpe/pgpe_service_codes.h
index 2e66952..30d6f1d 100644
--- a/src/occ_405/pgpe/pgpe_service_codes.h
+++ b/src/occ_405/pgpe/pgpe_service_codes.h
@@ -39,7 +39,8 @@ enum pgpeModuleId
PGPE_START_SUSPEND_MOD = PGPE_COMP_ID | 0x06,
PGPE_PMCR_SET_MOD = PGPE_COMP_ID | 0x07,
PGPE_WIDEN_CLIP_RANGES_MOD = PGPE_COMP_ID | 0x08,
- PGPE_START_SUSPEND_CALLBACK_MOD = PGPE_COMP_ID | 0x09,
+ PGPE_WIDEN_CLIP_BLOCKING_MOD = PGPE_COMP_ID | 0x09,
+ PGPE_START_SUSPEND_CALLBACK_MOD = PGPE_COMP_ID | 0x0A,
};
diff --git a/src/occ_405/proc/proc_data_control.c b/src/occ_405/proc/proc_data_control.c
index f10ce43..0e902a8 100755
--- a/src/occ_405/proc/proc_data_control.c
+++ b/src/occ_405/proc/proc_data_control.c
@@ -39,6 +39,7 @@
#include "p9_pstates_common.h"
#include "pgpe_interface.h"
#include "rtls_service_codes.h"
+#include "proc_pstate.h"
// The the GPE parameter fields for PGPE IPC calls.
extern GPE_BUFFER(ipcmsg_clip_update_t* G_clip_update_parms_ptr);
@@ -47,6 +48,13 @@ extern GPE_BUFFER(ipcmsg_set_pmcr_t* G_pmcr_set_parms_ptr);
extern GpeRequest G_clip_update_req;
extern GpeRequest G_pmcr_set_req;
+extern bool G_state_transition_occuring; // A state transition is currently going on?
+
+// a global flag used by task_core_data_control() to indicate
+// that the OCC is ready to transition to observation state
+// (after initiatibg a clip update IPC task if needed)
+bool G_active_to_observation_ready = false;
+
// create gpe request for GPE job. The initialization will be done one time
// during gpe request create.
GpeRequest G_core_data_control_req;
@@ -70,112 +78,165 @@ GPE_BUFFER(PstatesClips* G_core_data_control_gpewrite_ptr) = { &G_quads_data_con
// End Function Specification
void task_core_data_control( task_t * i_task )
{
- errlHndl_t err = NULL; //Error handler
- PstatesClips* l_temp = NULL;
+ errlHndl_t err = NULL; //Error handler
+ PstatesClips* l_temp = NULL;
+ static bool L_trace_logged = false; // trace logging to avoid unnecessarily repeatig logs
+
/////////////////////////////////////////////////////////////////
- // perform Pstate/clip control if previous IPC call completed successfully
- // if not idle, ignore cycle
- // if an error was returned, log an error, and request reset
- if(G_sysConfigData.system_type.kvm) // OPAL system
+ // Once a state transition process starts, task data control
+ // stops updating the PMCR/CLIPS updates, this way, the state
+ // transition protocol can set the clips without colliding
+ // with the task_core_data_control IPC tasks.
+ if(G_state_transition_occuring)
{
- // confirm that the clip update IPC from last cycle
- // has successfully completed on PGPE (with no errors)
- if( async_request_is_idle(&G_clip_update_req.request) && //clip_update/widen_clip_ranges completed
- (G_clip_update_parms_ptr->msg_cb.rc == PGPE_RC_SUCCESS) ) // with no errors
+ if(L_trace_logged == false)
{
-
- //The previous OPAL PGPE request succeeded:
-
- //1) swap gpewrite ptr with the occwrite ptr (double buffering).
- l_temp = G_core_data_control_occwrite_ptr;
- G_core_data_control_occwrite_ptr = G_core_data_control_gpewrite_ptr;
- G_core_data_control_gpewrite_ptr = l_temp;
-
- //2) Set clip values from gpewrite's quad clips data-structure
- G_clip_update_parms_ptr = &G_core_data_control_gpewrite_ptr->clips;
-
- //call PGPE IPC function to update the clips
- pgpe_clip_update();
+ TRAC_INFO("task_core_data_control: Pstate Control stopped because a state transition started.");
+ L_trace_logged = true;
}
- else if(G_clip_update_parms_ptr->msg_cb.rc != PGPE_RC_SUCCESS)
+
+ // Only Transitioning to Observation state necessitates clip update
+ // (if the last clip update was higher than legacy turbo).
+ if ((G_occ_master_state == OCC_STATE_OBSERVATION) &&
+ !G_active_to_observation_ready)
{
- // an earlier clip update IPC call has not completed, trace and log an error
- TRAC_ERR("task_core_data_control: clip update IPC task returned an error, %d",
- G_clip_update_parms_ptr->msg_cb.rc);
-
- /*
- * @errortype
- * @moduleid RTLS_TASK_CORE_DATA_CONTROL_MOD
- * @reasoncode PGPE_FAILURE
- * @userdata1 rc
- * @userdata2 clip update task idle?
- * @userdata4 ERC_PGPE_CLIP_UNSUCCESSFULL
- * @devdesc pgpe clip update returned an error
- */
- err = createErrl(
- RTLS_TASK_CORE_DATA_CONTROL_MOD, //ModId
- PGPE_FAILURE, //Reasoncode
- ERC_PGPE_CLIP_UNSUCCESSFULL, //Extended reason code
- ERRL_SEV_PREDICTIVE, //Severity
- NULL, //Trace Buf
- DEFAULT_TRACE_SIZE, //Trace Size
- G_clip_update_parms_ptr->msg_cb.rc, //Userdata1
- async_request_is_idle(&G_clip_update_req.request) //Userdata2
- );
+ // confirm that the last clip update IPC successfully completed on PGPE (with no errors)
+ if( async_request_is_idle(&G_clip_update_req.request) && //clip_update/widen_clip_ranges completed
+ (G_clip_update_parms_ptr->msg_cb.rc == PGPE_RC_SUCCESS) ) // with no errors
+ {
+ uint8_t quad = 0;
+ Pstate pclip = 0xff; // Initialize pclip to 0xff (lowest possible frequency)
+
+ // Only if last clip update sent to PGPE is larger than legacy turbo,
+ // send new clips with legacy turbo values, otherwise, no action needed.
+ for (quad = 0; quad < MAX_QUADS; quad++)
+ {
+ if(G_clip_update_parms_ptr->ps_val_clip_max[quad] < pclip)
+ {
+ // minimum pclip value corresponds to pstate of maximum frequency
+ pclip = G_clip_update_parms_ptr->ps_val_clip_max[quad];
+ }
+ }
+ // pclip of highest quad frequency corresponds to a frequency higher than legacy turbo
+ if(pclip < proc_freq2pstate(G_sysConfigData.sys_mode_freq.table[OCC_MODE_TURBO]))
+ {
+ pgpe_widen_clip_ranges(OCC_STATE_OBSERVATION);
+ }
+
+ //Whether clips have been lowered from frequencies higher than legacy turbo
+ //frequency, or already lower than turbo frequency, OCC is now ready to
+ //transition to Observation state.
+ G_active_to_observation_ready = true;
+ }
}
}
else
{
- // NON OPAL System, OCC owns PMCR:
- if( async_request_is_idle(&G_pmcr_set_req.request) && // PMCR IPC from last TICK completed
- (G_pmcr_set_parms_ptr->msg_cb.rc == PGPE_RC_SUCCESS) ) // with no errors
- {
- //The previous Non-OPAL PGPE request succeeded:
-
- //1) swap gpewrite ptr with the occwrite ptr (double buffering).
- l_temp = G_core_data_control_occwrite_ptr;
- G_core_data_control_occwrite_ptr = G_core_data_control_gpewrite_ptr;
- G_core_data_control_gpewrite_ptr = l_temp;
+ L_trace_logged = false;
- //2) Set Pstate values from gpewrite's quad pstates data-structure
- G_pmcr_set_parms_ptr = &G_core_data_control_gpewrite_ptr->pstates;
-
- //call PGPE IPC function to update Pstates
- pgpe_pmcr_set();
+ // perform Pstate/clip control if previous IPC call completed successfully
+ // if not idle, ignore cycle
+ // if an error was returned, log an error, and request reset
+ if(G_sysConfigData.system_type.kvm) // OPAL system
+ {
+ // confirm that the clip update IPC from last cycle
+ // has successfully completed on PGPE (with no errors)
+ if( async_request_is_idle(&G_clip_update_req.request) && //clip_update/widen_clip_ranges completed
+ (G_clip_update_parms_ptr->msg_cb.rc == PGPE_RC_SUCCESS) ) // with no errors
+ {
+ //The previous OPAL PGPE request succeeded:
+
+ //1) swap gpewrite ptr with the occwrite ptr (double buffering).
+ l_temp = G_core_data_control_occwrite_ptr;
+ G_core_data_control_occwrite_ptr = G_core_data_control_gpewrite_ptr;
+ G_core_data_control_gpewrite_ptr = l_temp;
+
+ //2) Set clip values from gpewrite's quad clips data-structure
+ G_clip_update_parms_ptr = &G_core_data_control_gpewrite_ptr->clips;
+
+ //call PGPE IPC function to update the clips
+ pgpe_clip_update();
+ }
+ else if(G_clip_update_parms_ptr->msg_cb.rc != PGPE_RC_SUCCESS)
+ {
+ // an earlier clip update IPC call has not completed, trace and log an error
+ TRAC_ERR("task_core_data_control: clip update IPC task returned an error, %d",
+ G_clip_update_parms_ptr->msg_cb.rc);
+
+ /*
+ * @errortype
+ * @moduleid RTLS_TASK_CORE_DATA_CONTROL_MOD
+ * @reasoncode PGPE_FAILURE
+ * @userdata1 rc
+ * @userdata2 clip update task idle?
+ * @userdata4 ERC_PGPE_CLIP_UNSUCCESSFULL
+ * @devdesc pgpe clip update returned an error
+ */
+ err = createErrl(
+ RTLS_TASK_CORE_DATA_CONTROL_MOD, //ModId
+ PGPE_FAILURE, //Reasoncode
+ ERC_PGPE_CLIP_UNSUCCESSFULL, //Extended reason code
+ ERRL_SEV_PREDICTIVE, //Severity
+ NULL, //Trace Buf
+ DEFAULT_TRACE_SIZE, //Trace Size
+ G_clip_update_parms_ptr->msg_cb.rc, //Userdata1
+ async_request_is_idle(&G_clip_update_req.request) //Userdata2
+ );
+ }
}
- else if(G_pmcr_set_parms_ptr->msg_cb.rc != PGPE_RC_SUCCESS)
+ else
{
- // an earlier clip update IPC call has not completed, trace and log an error
- TRAC_ERR("task_core_data_control: pstate update IPC task returned an error, %d",
- G_pmcr_set_parms_ptr->msg_cb.rc);
-
- /*
- * @errortype
- * @moduleid RTLS_TASK_CORE_DATA_CONTROL_MOD
- * @reasoncode PGPE_FAILURE
- * @userdata1 rc
- * @userdata2 pmcr set task idle?
- * @userdata4 ERC_PGPE_PMCR_UNSUCCESSFULL
- * @devdesc pgpe PMCR set returned an error
- */
- err = createErrl(
- RTLS_TASK_CORE_DATA_CONTROL_MOD, //ModId
- PGPE_FAILURE, //Reasoncode
- ERC_PGPE_PMCR_UNSUCCESSFULL, //Extended reason code
- ERRL_SEV_PREDICTIVE, //Severity
- NULL, //Trace Buf
- DEFAULT_TRACE_SIZE, //Trace Size
- G_pmcr_set_parms_ptr->msg_cb.rc, //Userdata1
- async_request_is_idle(&G_pmcr_set_req.request) //Userdata2
- );
+ // NON OPAL System, OCC owns PMCR:
+ if( async_request_is_idle(&G_pmcr_set_req.request) && // PMCR IPC from last TICK completed
+ (G_pmcr_set_parms_ptr->msg_cb.rc == PGPE_RC_SUCCESS) ) // with no errors
+ {
+ //The previous Non-OPAL PGPE request succeeded:
+
+ //1) swap gpewrite ptr with the occwrite ptr (double buffering).
+ l_temp = G_core_data_control_occwrite_ptr;
+ G_core_data_control_occwrite_ptr = G_core_data_control_gpewrite_ptr;
+ G_core_data_control_gpewrite_ptr = l_temp;
+
+ //2) Set Pstate values from gpewrite's quad pstates data-structure
+ G_pmcr_set_parms_ptr = &G_core_data_control_gpewrite_ptr->pstates;
+
+ //call PGPE IPC function to update Pstates
+ pgpe_pmcr_set();
+ }
+ else if(G_pmcr_set_parms_ptr->msg_cb.rc != PGPE_RC_SUCCESS)
+ {
+ // an earlier clip update IPC call has not completed, trace and log an error
+ TRAC_ERR("task_core_data_control: pstate update IPC task returned an error, %d",
+ G_pmcr_set_parms_ptr->msg_cb.rc);
+
+ /*
+ * @errortype
+ * @moduleid RTLS_TASK_CORE_DATA_CONTROL_MOD
+ * @reasoncode PGPE_FAILURE
+ * @userdata1 rc
+ * @userdata2 pmcr set task idle?
+ * @userdata4 ERC_PGPE_PMCR_UNSUCCESSFULL
+ * @devdesc pgpe PMCR set returned an error
+ */
+ err = createErrl(
+ RTLS_TASK_CORE_DATA_CONTROL_MOD, //ModId
+ PGPE_FAILURE, //Reasoncode
+ ERC_PGPE_PMCR_UNSUCCESSFULL, //Extended reason code
+ ERRL_SEV_PREDICTIVE, //Severity
+ NULL, //Trace Buf
+ DEFAULT_TRACE_SIZE, //Trace Size
+ G_pmcr_set_parms_ptr->msg_cb.rc, //Userdata1
+ async_request_is_idle(&G_pmcr_set_req.request) //Userdata2
+ );
+ }
}
- }
- if(err)
- {
- // commit error log
- REQUEST_RESET(err);
+ if(err)
+ {
+ // commit error log
+ REQUEST_RESET(err);
+ }
}
return;
diff --git a/src/occ_405/state.c b/src/occ_405/state.c
index 81b5f9c..341dba7 100755
--- a/src/occ_405/state.c
+++ b/src/occ_405/state.c
@@ -45,20 +45,15 @@ extern bool G_mem_monitoring_allowed;
extern task_t G_task_table[TASK_END]; // Global task table
extern bool G_simics_environment;
+extern pstateStatus G_proc_pstate_status;
+
extern GpeRequest G_clip_update_req;
extern GPE_BUFFER(ipcmsg_clip_update_t* G_clip_update_parms_ptr);
+// OCC is ready to transition to observation state?
+extern bool G_active_to_observation_ready;
-// Maximum allowed value approx. 16.3 ms
-#define PCBS_HEARBEAT_TIME_US 16320
-
-errlHndl_t SMGR_standby_to_observation();
-errlHndl_t SMGR_standby_to_active();
-errlHndl_t SMGR_observation_to_standby();
-errlHndl_t SMGR_observation_to_active();
-errlHndl_t SMGR_active_to_observation();
-errlHndl_t SMGR_active_to_standby();
-errlHndl_t SMGR_all_to_safe();
+extern PMCR_OWNER G_proc_pmcr_owner;
// State that OCC is currently in
OCC_STATE G_occ_internal_state = OCC_STATE_STANDBY;
@@ -89,22 +84,28 @@ const smgr_state_trans_t G_smgr_state_trans[] =
* those catch-all transition functions. */
/* Current State New State Transition Function */
- {OCC_STATE_STANDBY, OCC_STATE_OBSERVATION, &SMGR_standby_to_observation},
- {OCC_STATE_STANDBY, OCC_STATE_ACTIVE, &SMGR_standby_to_active},
- {OCC_STATE_OBSERVATION, OCC_STATE_STANDBY, &SMGR_observation_to_standby},
- {OCC_STATE_OBSERVATION, OCC_STATE_ACTIVE, &SMGR_observation_to_active},
- {OCC_STATE_ACTIVE, OCC_STATE_OBSERVATION, &SMGR_active_to_observation},
- {OCC_STATE_ACTIVE, OCC_STATE_STANDBY, &SMGR_active_to_standby},
+ {OCC_STATE_STANDBY, OCC_STATE_OBSERVATION, &SMGR_standby_to_observation},
+ {OCC_STATE_STANDBY, OCC_STATE_CHARACTERIZATION, &SMGR_standby_to_characterization},
+ {OCC_STATE_STANDBY, OCC_STATE_ACTIVE, &SMGR_standby_to_active},
+ {OCC_STATE_OBSERVATION, OCC_STATE_CHARACTERIZATION, &SMGR_observation_to_characterization},
+ {OCC_STATE_OBSERVATION, OCC_STATE_ACTIVE, &SMGR_observation_to_active},
+ {OCC_STATE_CHARACTERIZATION, OCC_STATE_OBSERVATION, &SMGR_characterization_to_observation},
+ {OCC_STATE_CHARACTERIZATION, OCC_STATE_ACTIVE, &SMGR_characterization_to_active},
+ {OCC_STATE_ACTIVE, OCC_STATE_OBSERVATION, &SMGR_active_to_observation},
+ {OCC_STATE_ACTIVE, OCC_STATE_CHARACTERIZATION, &SMGR_active_to_characterization},
/* ----- DEFAULT STATE TRANSITIONS ----- */
/* These are default state transitions for when it doesn't matter what
* state we were in before the transition. */
/* Current State New State Transition Function */
+ {OCC_STATE_ALL, OCC_STATE_STANDBY, &SMGR_all_to_standby},
{OCC_STATE_ALL, OCC_STATE_SAFE, &SMGR_all_to_safe},
};
+
const uint8_t G_smgr_state_trans_count = sizeof(G_smgr_state_trans)/sizeof(smgr_state_trans_t);
+
uint32_t G_smgr_validate_data_active_mask = SMGR_VALIDATE_DATA_ACTIVE_MASK_HARDCODES;
uint32_t G_smgr_validate_data_observation_mask = SMGR_VALIDATE_DATA_OBSERVATION_MASK_HARDCODES;
@@ -164,21 +165,20 @@ errlHndl_t SMGR_standby_to_observation()
* @userdata4 ERC_STATE_FROM_STB_TO_OBS_FAILURE
* @devdesc Failed changing from standby to observation
*/
- l_errlHndl = createErrl(MAIN_STATE_TRANSITION_MID, //modId
- INTERNAL_FAILURE, //reasoncode
- ERC_STATE_FROM_STB_TO_OBS_FAILURE,//Extended reason code
- ERRL_SEV_UNRECOVERABLE, //Severity
- NULL, //Trace Buf
- DEFAULT_TRACE_SIZE, //Trace Size
- 0, //userdata1
- 0); //userdata2
+ l_errlHndl = createErrl(MAIN_STATE_TRANSITION_MID, //modId
+ INTERNAL_FAILURE, //reasoncode
+ ERC_STATE_FROM_STB_TO_OBS_FAILURE,//Extended reason code
+ ERRL_SEV_UNRECOVERABLE, //Severity
+ NULL, //Trace Buf
+ DEFAULT_TRACE_SIZE, //Trace Size
+ 0, //userdata1
+ 0); //userdata2
// Callout firmware
addCalloutToErrl(l_errlHndl,
ERRL_CALLOUT_TYPE_COMPONENT_ID,
ERRL_COMPONENT_ID_FIRMWARE,
ERRL_CALLOUT_PRIORITY_HIGH);
-
}
return l_errlHndl;
}
@@ -186,27 +186,98 @@ errlHndl_t SMGR_standby_to_observation()
// Function Specification
//
-// Name:
+// Name: SMGR_standby_to_characterization
//
-// Description:
+// Description: switch from standby state to characterization state
//
// End Function Specification
-errlHndl_t SMGR_observation_to_standby()
+errlHndl_t SMGR_standby_to_characterization()
{
- errlHndl_t l_errlHndl = NULL;
+ errlHndl_t l_errlHndl = NULL;
+ int rc = 0;
+ static bool l_error_logged = FALSE; // To prevent trace and error log happened over and over
- TRAC_IMP("SMGR: Observation to Standby Transition Started");
+ do
+ {
- // Set the RTL Flags to indicate which tasks can run
- // - Clear ACTIVE b/c not in ACTIVE State
- // - Clear OBSERVATION b/c not in OBSERVATION State
- rtl_clr_run_mask_deferred(RTL_FLAG_ACTIVE | RTL_FLAG_OBS );
- rtl_set_run_mask_deferred(RTL_FLAG_STANDBY);
+ if( SMGR_MASK_ACTIVE_READY ==
+ (SMGR_validate_get_valid_states() & SMGR_MASK_ACTIVE_READY))
+ {
+ l_error_logged = FALSE;
+ TRAC_IMP("SMGR: Standby to Characterization State Transition Started");
- // Set the actual STATE now that we have finished everything else
- CURRENT_STATE() = OCC_STATE_STANDBY;
+ // wide open pstate clips
+ rc = pgpe_widen_clip_blocking(OCC_STATE_CHARACTERIZATION);
- TRAC_IMP("SMGR: Observation to Standby Transition Completed");
+ if(rc)
+ {
+ TRAC_ERR("SMGR: failed to widen pstate clips.");
+ break;
+ }
+ else // successfully wide opened clips; enable pstates, then start transition
+ {
+
+ // update OPAL static table in main memory
+ if(G_sysConfigData.system_type.kvm)
+ {
+ // upon succesful enablement of Pstate protocol on
+ // PGPE update OPAL table with pstate information.
+ proc_pstate_kvm_setup();
+ }
+
+ // Start pstates on PGPE and set Characterization as owner
+ rc = pgpe_start_suspend(PGPE_ACTION_PSTATE_START, PMCR_OWNER_CHAR);
+
+ if(rc)
+ {
+ TRAC_ERR("SMGR: failed to start the pstate protocol on PGPE.");
+ break;
+ }
+ else // Clips wide opened and pstates started successfully, start transition
+ {
+ memory_init();
+
+ // Set the RTL Flags to indicate which tasks can run
+ // - Set OBSERVATION flags in Characterization State
+ rtl_clr_run_mask_deferred(RTL_FLAG_STANDBY);
+ rtl_set_run_mask_deferred(RTL_FLAG_OBS);
+
+ // Set the actual STATE now that we have finished everything else
+ CURRENT_STATE() = OCC_STATE_CHARACTERIZATION;
+
+ TRAC_IMP("SMGR: Standby to Characterization Transition Completed");
+ }
+ }
+ }
+ } while (0);
+
+ if(l_errlHndl && (false == l_error_logged))
+ {
+ l_error_logged = TRUE;
+ TRAC_ERR("SMGR: Standby to Characterization Transition Failed");
+ /* @
+ * @errortype
+ * @moduleid MAIN_STATE_TRANSITION_MID
+ * @reasoncode INTERNAL_FAILURE
+ * @userdata1 none
+ * @userdata4 ERC_STATE_FROM_STB_TO_CHR_FAILURE
+ * @devdesc Failed changing from standby to characterization
+ */
+ l_errlHndl = createErrl(MAIN_STATE_TRANSITION_MID, //modId
+ INTERNAL_FAILURE, //reasoncode
+ ERC_STATE_FROM_STB_TO_CHR_FAILURE, //Extended reason code
+ ERRL_SEV_UNRECOVERABLE, //Severity
+ NULL, //Trace Buf
+ DEFAULT_TRACE_SIZE, //Trace Size
+ 0, //userdata1
+ 0); //userdata2
+
+ // Callout firmware
+ addCalloutToErrl(l_errlHndl,
+ ERRL_CALLOUT_TYPE_COMPONENT_ID,
+ ERRL_COMPONENT_ID_FIRMWARE,
+ ERRL_CALLOUT_PRIORITY_HIGH);
+ }
return l_errlHndl;
}
@@ -214,170 +285,507 @@ errlHndl_t SMGR_observation_to_standby()
// Function Specification
//
-// Name: SMGR_observation_to_active
+// Name: SMGR_all_to_standby
//
-// Description: Transition from Observation state to Active state
+// Description: Switch from any state to standby state
//
// End Function Specification
-errlHndl_t SMGR_observation_to_active()
+
+#define WAIT_PGPE_TASK_TIMEOUT 200 // maximum time to wait for a PGPE task before timeout
+errlHndl_t SMGR_all_to_standby()
{
- errlHndl_t l_errlHndl = NULL;
- static bool l_error_logged = FALSE; // To prevent trace and error log happened over and over
- int l_extRc = OCC_NO_EXTENDED_RC;
- int l_rc = 0;
+ errlHndl_t l_errlHndl = NULL;
+ static bool l_error_logged = FALSE; // To prevent trace and error logging over and over
+ uint8_t wait_time = 0;
+ int rc;
- // confirm that the clip update IPC call to widen clip ranges
- // has successfully completed on PGPE (with no errors)
- if( !async_request_is_idle(&G_clip_update_req.request) ) //widen_clip_ranges didn't complete
+ TRAC_IMP("SMGR: Transition from State (%d) to Standby Started",
+ CURRENT_STATE());
+
+ do
{
- // an earlier clip update IPC call has not completed, trace and log an error
- TRAC_ERR("SMGR: clip update IPC task is not Idle");
- /*
+ // if Psates in transition (a pgpe_start_suspend IPC call still running),
+ // wait until it is settled up to WAIT_PGPE_TASK_TIMEOUT usec
+ while(G_proc_pstate_status == PSTATES_IN_TRANSITION &&
+ wait_time < WAIT_PGPE_TASK_TIMEOUT)
+ {
+ // wait until pgpe_start_suspend call is completed. Sleep enables context switching.
+ ssx_sleep(SSX_MICROSECONDS(10));
+ wait_time += 10;
+ }
+
+ // check for timeout while waiting for pgpe_start_suspend() IPC completion
+ if(wait_time >= WAIT_PGPE_TASK_TIMEOUT)
+ {
+ TRAC_ERR("SMGR: Timeout waiting for Pstates start/suspend IPC task");
+
+ /* @
* @errortype
- * @moduleid MAIN_SMGR_MID
- * @reasoncode PGPE_FAILURE
- * @userdata4 ERC_PGPE_NOT_IDLE
- * @devdesc pgpe clip update not idle
+ * @moduleid MAIN_STATE_TRANSITION_MID
+ * @reasoncode GPE_REQUEST_TASK_TIMEOUT
+ * @userdata1 wait_time
+ * @userdata4 OCC_NO_EXTENDED_RC
+ * @devdesc timeout waiting for pstates start/suspend task
*/
- l_errlHndl = createErrl(
- MAIN_SMGR_MID, //ModId
- PGPE_FAILURE, //Reasoncode
- ERC_PGPE_NOT_IDLE, //Extended reason code
- ERRL_SEV_PREDICTIVE, //Severity
- NULL, //Trace Buf
- DEFAULT_TRACE_SIZE, //Trace Size
- 0, //Userdata1
- 0 //Userdata2
- );
+ l_errlHndl = createErrl(MAIN_STATE_TRANSITION_MID, //modId
+ GPE_REQUEST_TASK_TIMEOUT, //reasoncode
+ OCC_NO_EXTENDED_RC, //Extended reason code
+ ERRL_SEV_UNRECOVERABLE, //Severity
+ NULL, //Trace Buf
+ DEFAULT_TRACE_SIZE, //Trace Size
+ wait_time, //userdata1
+ 0); //userdata2
+
+ // Callout firmware
+ addCalloutToErrl(l_errlHndl,
+ ERRL_CALLOUT_TYPE_COMPONENT_ID,
+ ERRL_COMPONENT_ID_FIRMWARE,
+ ERRL_CALLOUT_PRIORITY_HIGH);
+ break;
+ }
+
+ // Stop Pstates if enabled
+ if(G_proc_pstate_status == PSTATES_ENABLED)
+ {
+ rc = pgpe_start_suspend(PGPE_ACTION_PSTATE_STOP, G_proc_pmcr_owner);
+ if(rc)
+ {
+ TRAC_ERR("SMGR: Failed to stop the pstate protocol on PGPE.");
+ break;
+ }
+ }
+
+ // Pstates Disabled, ready to safely transition to standby
+
+ // Set the RTL Flags to indicate which tasks can run
+ // - Clear ACTIVE b/c not in ACTIVE State
+ // - Clear OBSERVATION b/c not in CHARACTERIZATION State
+ rtl_clr_run_mask_deferred(RTL_FLAG_ACTIVE | RTL_FLAG_OBS );
+ rtl_set_run_mask_deferred(RTL_FLAG_STANDBY);
+
+ // Set the actual STATE now that we have finished everything else
+ CURRENT_STATE() = OCC_STATE_STANDBY;
+
+ TRAC_IMP("SMGR: Transition to Standby Completed");
+
+ } while (0);
+
+ if(l_errlHndl)
+ {
+ l_error_logged = TRUE;
+ TRAC_ERR("SMGR: Transition to Standby Failed");
+
+ /* @
+ * @errortype
+ * @moduleid MAIN_STATE_TRANSITION_MID
+ * @reasoncode INTERNAL_FAILURE
+ * @userdata1 starting state
+ * @userdata4 ERC_STATE_FROM_ALL_TO_STB_FAILURE
+ * @devdesc Failed changing from observation to characterization
+ */
+ l_errlHndl = createErrl(MAIN_STATE_TRANSITION_MID, //modId
+ INTERNAL_FAILURE, //reasoncode
+ ERC_STATE_FROM_ALL_TO_STB_FAILURE, //Extended reason code
+ ERRL_SEV_UNRECOVERABLE, //Severity
+ NULL, //Trace Buf
+ DEFAULT_TRACE_SIZE, //Trace Size
+ CURRENT_STATE(), //userdata1
+ 0); //userdata2
// Callout firmware
addCalloutToErrl(l_errlHndl,
- ERRL_CALLOUT_TYPE_COMPONENT_ID,
- ERRL_COMPONENT_ID_FIRMWARE,
- ERRL_CALLOUT_PRIORITY_HIGH);
+ ERRL_CALLOUT_TYPE_COMPONENT_ID,
+ ERRL_COMPONENT_ID_FIRMWARE,
+ ERRL_CALLOUT_PRIORITY_HIGH);
}
- else if ( G_clip_update_parms_ptr->msg_cb.rc != PGPE_RC_SUCCESS ) // IPC task completed with errors
+
+ return l_errlHndl;
+}
+
+// Function Specification
+//
+// Name: SMGR_characterization_to_observation
+//
+// Description: Switch from characterization to observation state
+//
+// End Function Specification
+errlHndl_t SMGR_characterization_to_observation()
+{
+ errlHndl_t l_errlHndl = NULL;
+ int rc = 0;
+ static bool l_error_logged = FALSE; // To prevent trace and error logging over and over
+
+ TRAC_IMP("SMGR: Characterization to Observation Transition Started");
+
+ do
{
- // an earlier clip update IPC call has not completed, trace and log an error
- TRAC_ERR("SMGR: clip update IPC task returned an error [0x%08X]",
- G_clip_update_parms_ptr->msg_cb.rc);
+ // widen clips to legacy turbo
+ rc = pgpe_widen_clip_blocking(OCC_STATE_OBSERVATION);
- /*
- * @errortype
- * @moduleid MAIN_SMGR_MID
- * @reasoncode PGPE_FAILURE
- * @userdata1 PGPE clip update's rc
- * @userdata4 ERC_PGPE_CLIP_FAILURE
- * @devdesc pgpe clip update not idle
- */
- l_errlHndl = createErrl(
- MAIN_SMGR_MID, //ModId
- PGPE_FAILURE, //Reasoncode
- ERC_PGPE_CLIP_FAILURE, //Extended reason code
- ERRL_SEV_PREDICTIVE, //Severity
- NULL, //Trace Buf
- DEFAULT_TRACE_SIZE, //Trace Size
- G_clip_update_parms_ptr->msg_cb.rc, //Userdata1
- 0 //Userdata2
- );
+ if(rc)
+ {
+ TRAC_ERR("SMGR: failed to tighten pstate clips.");
+ break;
+ }
+ else // clips set to legacy turbo; stop pstate protocol
+ {
+ rc = pgpe_start_suspend(PGPE_ACTION_PSTATE_STOP, G_proc_pmcr_owner);
+ if(rc)
+ {
+ TRAC_ERR("SMGR: Failed to stop the pstate protocol on PGPE.");
+ break;
+ }
+ else // Clips tightened successfully, and pstates disabled: perform transition
+ {
+ // No RTL Flag changes; only state change
+ CURRENT_STATE() = OCC_STATE_OBSERVATION;
+
+ TRAC_IMP("SMGR: Characterization to Observation Transition Completed");
+ }
+ }
+ } while (0);
+
+ if(rc)
+ {
+ l_error_logged = TRUE;
+ TRAC_ERR("SMGR: Characterization to Observation Transition Failed");
+
+ /* @
+ * @errortype
+ * @moduleid MAIN_STATE_TRANSITION_MID
+ * @reasoncode INTERNAL_FAILURE
+ * @userdata1 none
+ * @userdata4 ERC_STATE_FROM_CHR_TO_OBS_FAILURE
+ * @devdesc Failed changing from observation to characterization
+ */
+ l_errlHndl = createErrl(MAIN_STATE_TRANSITION_MID, //modId
+ INTERNAL_FAILURE, //reasoncode
+ ERC_STATE_FROM_CHR_TO_OBS_FAILURE, //Extended reason code
+ ERRL_SEV_UNRECOVERABLE, //Severity
+ NULL, //Trace Buf
+ DEFAULT_TRACE_SIZE, //Trace Size
+ 0, //userdata1
+ 0); //userdata2
// Callout firmware
addCalloutToErrl(l_errlHndl,
- ERRL_CALLOUT_TYPE_COMPONENT_ID,
- ERRL_COMPONENT_ID_FIRMWARE,
- ERRL_CALLOUT_PRIORITY_HIGH);
+ ERRL_CALLOUT_TYPE_COMPONENT_ID,
+ ERRL_COMPONENT_ID_FIRMWARE,
+ ERRL_CALLOUT_PRIORITY_HIGH);
}
- else // Clips wide opened with no errors, enable Pstates on PGPE
- {
+ return l_errlHndl;
+}
- // Pstates are enabled via an IPC call to PGPE, which will
- // set the G_proc_pstate_status flag
- l_errlHndl = pgpe_start_suspend(PGPE_ACTION_PSTATE_START);
+// Function Specification
+//
+// Name: SMGR_observation_to_characterization
+//
+// Description: Switch from Observation to Characterization state
+//
+// End Function Specification
+errlHndl_t SMGR_observation_to_characterization()
+{
+ int rc = 0;
+ errlHndl_t l_errlHndl = NULL;
+ static bool l_error_logged = FALSE; // To prevent trace and error logging over and over
+
+ TRAC_IMP("SMGR: Observation to Characterization Transition Started");
+
+ // no change in RTL flags, just turn-on pstate protocol, and wide open clips
+
+ do
+ {
+ // Must be active ready if transitioning to characterization state
+ if( (SMGR_MASK_ACTIVE_READY !=
+ (SMGR_validate_get_valid_states() & SMGR_MASK_ACTIVE_READY)) )
+ {
+ TRAC_ERR("SMGR: failed to transition to characterization state "
+ "since OCC is not active ready.");
+ break;
+ }
+ // wide open pstate clips
+ rc = pgpe_widen_clip_blocking(OCC_STATE_CHARACTERIZATION);
- if(l_errlHndl)
+ if(rc)
{
- TRAC_ERR("SMGR: Failed to switch to Active state because of a "
- "failure to start the pstate protocol on PGPE.");
+ TRAC_ERR("SMGR: failed to widen pstate clips.");
+ break;
}
- else
+ else // successfully wide opened clips; enable pstates, then start transition
{
- // Pstates enabled, update OPAL static table in main memory
+ // update OPAL static table in main memory
if(G_sysConfigData.system_type.kvm)
{
// upon succesful enablement of Pstate protocol on
// PGPE update OPAL table with pstate information.
proc_pstate_kvm_setup();
}
+
+ // Start pstates on PGPE and set Characterization as owner
+ rc = pgpe_start_suspend(PGPE_ACTION_PSTATE_START, PMCR_OWNER_CHAR);
+
+ if(rc)
+ {
+ TRAC_ERR("SMGR: failed to start the pstate protocol on PGPE.");
+ break;
+ }
+ else // Clips wide opened successfully and pstates enabled; complete transition
+ {
+ // Set the actual STATE now that we have finished everything else
+ CURRENT_STATE() = OCC_STATE_CHARACTERIZATION;
+
+ TRAC_IMP("SMGR: Observation to Characterization Transition Completed");
+ }
}
+ } while (0);
+
+ if(rc && (false == l_error_logged))
+ {
+ l_error_logged = TRUE;
+ TRAC_ERR("SMGR: Observation to Characterization Transition Failed");
+ /* @
+ * @errortype
+ * @moduleid MAIN_STATE_TRANSITION_MID
+ * @reasoncode INTERNAL_FAILURE
+ * @userdata1 none
+ * @userdata4 ERC_STATE_FROM_OBS_TO_CHR_FAILURE
+ * @devdesc Failed changing from observation to characterization
+ */
+ l_errlHndl = createErrl(MAIN_STATE_TRANSITION_MID, //modId
+ INTERNAL_FAILURE, //reasoncode
+ ERC_STATE_FROM_OBS_TO_CHR_FAILURE, //Extended reason code
+ ERRL_SEV_UNRECOVERABLE, //Severity
+ NULL, //Trace Buf
+ DEFAULT_TRACE_SIZE, //Trace Size
+ 0, //userdata1
+ 0); //userdata2
+
+ // Callout firmware
+ addCalloutToErrl(l_errlHndl,
+ ERRL_CALLOUT_TYPE_COMPONENT_ID,
+ ERRL_COMPONENT_ID_FIRMWARE,
+ ERRL_CALLOUT_PRIORITY_HIGH);
}
- // NOTE that this is really unnecessary if you follow the TMGT OCC
- // Interface Spec, which tells you that you need to check for the "Active
- // Ready" bit in the poll response before you go to active state.
- // But since we have scenerios where TMGT isn't the one putting us in
- // active state (we are going there automatically) we needed to add this.
+ return l_errlHndl;
+}
+
- // If we have all data we need to go to active state, but don't have pstates
- // enabled yet...then we will do the aforementioned wait
- if(((DATA_get_present_cnfgdata() & SMGR_VALIDATE_DATA_ACTIVE_MASK) ==
- SMGR_VALIDATE_DATA_ACTIVE_MASK))
+
+// Function Specification
+//
+// Name: SMGR_observation_to_active
+//
+// Description: Transition from Observation state to Active state
+//
+// End Function Specification
+errlHndl_t SMGR_observation_to_active()
+{
+ errlHndl_t l_errlHndl = NULL;
+ static bool l_error_logged = FALSE; // To prevent trace and error log happened over and over
+ int l_extRc = OCC_NO_EXTENDED_RC;
+ int l_rc = 0;
+ do
{
- SsxTimebase start = ssx_timebase_get();
- while( ! proc_is_hwpstate_enabled() )
+ // NOTE that this is really unnecessary if you follow the TMGT OCC
+ // Interface Spec, which tells you that you need to check for the "Active
+ // Ready" bit in the poll response before you go to active state.
+ // But since we have scenerios where TMGT isn't the one putting us in
+ // active state (we are going there automatically) we needed to add this.
+
+ // If we have all data we need to go to active state, but don't have pstates
+ // enabled yet...then we will do the aforementioned wait
+ if(SMGR_MASK_ACTIVE_READY ==
+ (SMGR_validate_get_valid_states() & SMGR_MASK_ACTIVE_READY))
{
- SsxInterval timeout = SSX_SECONDS(5);
- if ((ssx_timebase_get() - start) > timeout)
+ l_rc = pgpe_widen_clip_blocking(OCC_STATE_ACTIVE);
+
+ if(l_rc)
{
- l_rc = 1;
- if(FALSE == l_error_logged)
+ TRAC_ERR("SMGR: Failed to switch to Active state because of a "
+ "failure to widen clip pstates");
+ break;
+ }
+
+ else // Clips wide opened with no errors, enable Pstates on PGPE
+ {
+
+ // Pstates are enabled via an IPC call to PGPE, which will set the
+ // G_proc_pstate_status flag. PMCR owner is set based on system type.
+ if(G_sysConfigData.system_type.kvm)
{
- TRAC_ERR("SMGR: Timeout waiting for Pstates to be enabled, "
- "pmc_mode[%08x], chips_present[%02x], Cores Present [%08x]",
- in32(PMC_MODE_REG),
- G_sysConfigData.is_occ_present,
- (uint32_t) ((in64(OCB_CCSR)) >> 32));
+ l_rc = pgpe_start_suspend(PGPE_ACTION_PSTATE_START, PMCR_OWNER_HOST);
+ }
+ else
+ {
+ l_rc = pgpe_start_suspend(PGPE_ACTION_PSTATE_START, PMCR_OWNER_OCC);
+ }
+ if(l_rc)
+ {
+ TRAC_ERR("SMGR: Failed to switch to Active state because of a "
+ "failure to start the pstate protocol on PGPE.");
+ break;
}
- l_extRc = ERC_GENERIC_TIMEOUT;
- break;
}
- }
- if(proc_is_hwpstate_enabled() && G_sysConfigData.system_type.kvm)
+
+ // Wait for pstates enablement completition.
+ SsxTimebase start = ssx_timebase_get();
+ while( ! proc_is_hwpstate_enabled() )
+ {
+ SsxInterval timeout = SSX_SECONDS(5);
+ if ((ssx_timebase_get() - start) > timeout)
+ {
+ l_rc = 1;
+ if(FALSE == l_error_logged)
+ {
+ TRAC_ERR("SMGR: Timeout waiting for Pstates to be enabled, "
+ "pmc_mode[%08x], chips_present[%02x], Cores Present [%08x]",
+ in32(PMC_MODE_REG),
+ G_sysConfigData.is_occ_present,
+ (uint32_t) ((in64(OCB_CCSR)) >> 32));
+ }
+ l_extRc = ERC_GENERIC_TIMEOUT;
+ break;
+ }
+ }
+
+ // if pstates are now enabled, all conditions are already met
+ // to transition to active state.
+ if(proc_is_hwpstate_enabled() )
+ {
+ l_error_logged = FALSE;
+ TRAC_IMP("SMGR: Observation to Active Transition Started");
+
+ // Set the RTL Flags to indicate which tasks can run
+ // - Clear OBSERVATION b/c not in OBSERVATION State
+ // - Set ACTIVE b/c we're in ACTIVE State
+ rtl_clr_run_mask_deferred(RTL_FLAG_OBS);
+ rtl_set_run_mask_deferred(RTL_FLAG_ACTIVE);
+
+ // Pstates enabled, update OPAL static table in main memory
+ if(G_sysConfigData.system_type.kvm)
+ {
+ TRAC_IMP("SMGR: Pstates are enabled, continuing with state trans");
+
+ // upon succesful enablement of Pstate protocol on
+ // PGPE update OPAL table with pstate information.
+ proc_pstate_kvm_setup();
+ }
+
+ // Set the actual STATE now that we have finished everything else
+ CURRENT_STATE() = OCC_STATE_ACTIVE;
+ TRAC_IMP("SMGR: Observation to Active Transition Completed");
+ }
+ else
+ {
+ TRAC_ERR("SMGR: Observation to Active Transition Failed, because pstates are not enabled");
+ }
+
+ if(l_rc && FALSE == l_error_logged)
+ {
+ l_error_logged = TRUE;
+ /* @
+ * @errortype
+ * @moduleid MAIN_STATE_TRANSITION_MID
+ * @reasoncode INTERNAL_FAILURE
+ * @userdata1 SMGR_MASK_ACTIVE_READY
+ * @userdata2 valid states
+ * @userdata4 ERC_STATE_FROM_OBS_TO_STB_FAILURE
+ * @devdesc Failed changing from observation to standby
+ */
+ l_errlHndl = createErrl(MAIN_STATE_TRANSITION_MID, //modId
+ INTERNAL_FAILURE, //reasoncode
+ l_extRc, //Extended reason code
+ ERRL_SEV_UNRECOVERABLE, //Severity
+ NULL, //Trace Buf
+ DEFAULT_TRACE_SIZE, //Trace Size
+ SMGR_MASK_ACTIVE_READY, //userdata1
+ SMGR_validate_get_valid_states());//userdata2
+
+ // Callout firmware
+ addCalloutToErrl(l_errlHndl,
+ ERRL_CALLOUT_TYPE_COMPONENT_ID,
+ ERRL_COMPONENT_ID_FIRMWARE,
+ ERRL_CALLOUT_PRIORITY_HIGH);
+ }
+ } // Active Ready
+ else
{
- TRAC_IMP("SMGR: Pstates are enabled, continuing with state trans");
+ TRAC_ERR("SMGR: Observation to Active Transition Failed, "
+ "OCC is not Active Ready cnfgdata=0x%08x, reqd=0x%08x",
+ DATA_get_present_cnfgdata(),
+ SMGR_VALIDATE_DATA_ACTIVE_MASK);
}
- }
+ } while (0);
- // Check if all conditions are met to transition to active state. If
- // they aren't, then log an error and fail to change state.
- if( (SMGR_MASK_ACTIVE_READY ==
- (SMGR_validate_get_valid_states() & SMGR_MASK_ACTIVE_READY))
- && proc_is_hwpstate_enabled() )
- {
- l_error_logged = FALSE;
- TRAC_IMP("SMGR: Observation to Active Transition Started");
+ return l_errlHndl;
+}
- // Set the RTL Flags to indicate which tasks can run
- // - Clear OBSERVATION b/c not in OBSERVATION State
- // - Set ACTIVE b/c we're in ACTIVE State
- rtl_clr_run_mask_deferred(RTL_FLAG_OBS);
- rtl_set_run_mask_deferred(RTL_FLAG_ACTIVE);
+// Function Specification
+//
+// Name: SMGR_characterization_to_active
+//
+// Description: Transition from Characterization state to Active state
+//
+// End Function Specification
+errlHndl_t SMGR_characterization_to_active()
+{
+ int rc = 0;
+ errlHndl_t l_errlHndl = NULL;
+ static bool l_error_logged = FALSE; // To prevent trace and error log happened over and over
- // Set the actual STATE now that we have finished everything else
- CURRENT_STATE() = OCC_STATE_ACTIVE;
- TRAC_IMP("SMGR: Observation to Active Transition Completed");
- }
- else if(l_rc)
+ do
{
- TRAC_ERR("SMGR: Observation to Active Transition Failed, cnfgdata=0x%08x, reqd=0x%08x",
- DATA_get_present_cnfgdata(),
- SMGR_VALIDATE_DATA_ACTIVE_MASK);
- }
+ // change PMCR ownership via an IPC call to PGPE based on system type.
+ if(G_sysConfigData.system_type.kvm)
+ {
+ rc = pgpe_start_suspend(PGPE_ACTION_PSTATE_START, PMCR_OWNER_HOST);
+ }
+ else
+ {
+ rc = pgpe_start_suspend(PGPE_ACTION_PSTATE_START, PMCR_OWNER_OCC);
+ }
+ if(rc)
+ {
+ TRAC_ERR("SMGR: Failed to change PMCR ownership on PGPE.");
+ break;
+ }
+
+ // Have all data we need to go to active state
+ if(((DATA_get_present_cnfgdata() & SMGR_VALIDATE_DATA_ACTIVE_MASK) ==
+ SMGR_VALIDATE_DATA_ACTIVE_MASK) &&
+ // and Psate protocol is enabled
+ proc_is_hwpstate_enabled() && G_sysConfigData.system_type.kvm)
+ {
+ TRAC_IMP("SMGR: Pstates are enabled, continuing with state trans");
+ }
+
+ // Check if all conditions are met to transition to active state. If
+ // they aren't, then log an error and fail to change state.
+ if( (SMGR_MASK_ACTIVE_READY ==
+ (SMGR_validate_get_valid_states() & SMGR_MASK_ACTIVE_READY))
+ && proc_is_hwpstate_enabled() )
+ {
+ l_error_logged = FALSE;
+ TRAC_IMP("SMGR: Characterization to Active Transition Started");
+
+ // Set the RTL Flags to indicate which tasks can run
+ // - Clear OBSERVATION b/c not in CHARACTERIZATION State
+ // - Set ACTIVE b/c we're in ACTIVE State
+ rtl_clr_run_mask_deferred(RTL_FLAG_OBS);
+ rtl_set_run_mask_deferred(RTL_FLAG_ACTIVE);
+
+ // Set the actual STATE now that we have finished everything else
+ CURRENT_STATE() = OCC_STATE_ACTIVE;
+ TRAC_IMP("SMGR: Characterization to Active Transition Completed");
+ }
+ } while (0);
- if(l_rc && FALSE == l_error_logged)
+ if(rc && (false == l_error_logged))
{
l_error_logged = TRUE;
/* @
@@ -386,29 +794,28 @@ errlHndl_t SMGR_observation_to_active()
* @reasoncode INTERNAL_FAILURE
* @userdata1 SMGR_MASK_ACTIVE_READY
* @userdata2 valid states
- * @userdata4 ERC_STATE_FROM_OBS_TO_STB_FAILURE
- * @devdesc Failed changing from observation to standby
+ * @userdata4 ERC_STATE_FROM_CHR_TO_ACT_FAILURE
+ * @devdesc Failed changing from characterization to active
*/
- l_errlHndl = createErrl(MAIN_STATE_TRANSITION_MID, //modId
- INTERNAL_FAILURE, //reasoncode
- l_extRc, //Extended reason code
- ERRL_SEV_UNRECOVERABLE, //Severity
- NULL, //Trace Buf
- DEFAULT_TRACE_SIZE, //Trace Size
- SMGR_MASK_ACTIVE_READY, //userdata1
- SMGR_validate_get_valid_states());//userdata2
+ l_errlHndl = createErrl(MAIN_STATE_TRANSITION_MID, //modId
+ INTERNAL_FAILURE, //reasoncode
+ ERC_STATE_FROM_CHR_TO_ACT_FAILURE, //Extended reason code
+ ERRL_SEV_UNRECOVERABLE, //Severity
+ NULL, //Trace Buf
+ DEFAULT_TRACE_SIZE, //Trace Size
+ SMGR_MASK_ACTIVE_READY, //userdata1
+ SMGR_validate_get_valid_states()); //userdata2
// Callout firmware
addCalloutToErrl(l_errlHndl,
- ERRL_CALLOUT_TYPE_COMPONENT_ID,
- ERRL_COMPONENT_ID_FIRMWARE,
- ERRL_CALLOUT_PRIORITY_HIGH);
-
+ ERRL_CALLOUT_TYPE_COMPONENT_ID,
+ ERRL_COMPONENT_ID_FIRMWARE,
+ ERRL_CALLOUT_PRIORITY_HIGH);
}
+
return l_errlHndl;
}
-
// Function Specification
//
// Name: SMGR_active_to_observation
@@ -416,22 +823,151 @@ errlHndl_t SMGR_observation_to_active()
// Description:
//
// End Function Specification
+
errlHndl_t SMGR_active_to_observation()
{
- errlHndl_t l_errlHndl = NULL;
+ int rc = 0;
+ errlHndl_t l_errlHndl = NULL;
+ uint8_t wait_time = 0;
TRAC_IMP("SMGR: Active to Observation Transition Started");
- // Set the RTL Flags to indicate which tasks can run
- // - Set OBSERVATION b/c in OBSERVATION State
- // - Clear ACTIVE b/c not in ACTIVE State
- rtl_clr_run_mask_deferred(RTL_FLAG_ACTIVE);
- rtl_set_run_mask_deferred(RTL_FLAG_OBS);
+ do
+ {
+ // wait until task_core_data_control() declares that
+ // OCC is ready to transition to Observation state
+ while(!G_active_to_observation_ready)
+ {
+ if(wait_time > WAIT_PGPE_TASK_TIMEOUT)
+ {
+ break;
+ }
- // Set the actual STATE now that we have finished everything else
- CURRENT_STATE() = OCC_STATE_OBSERVATION;
+ // Sleep enables context switching.
+ ssx_sleep(SSX_MICROSECONDS(10));
+ wait_time += 10;
+ }
- TRAC_IMP("SMGR: Active to Observation Transition Completed");
+ // check for timeout while waiting for pgpe_start_suspend() IPC completion
+ if(wait_time > WAIT_PGPE_TASK_TIMEOUT)
+ {
+ TRAC_ERR("SMGR: Timeout waiting for G_active_to_observation_ready flag.");
+
+ /* @
+ * @errortype
+ * @moduleid MAIN_STATE_TRANSITION_MID
+ * @reasoncode PGPE_FAILURE
+ * @userdata1 wait_time
+ * @userdata4 ERC_PGPE_ACTIVE_TO_OBSERVATION_TIMEOUT
+ * @devdesc timeout waiting for pstates start/suspend task
+ */
+ l_errlHndl = createErrl(MAIN_STATE_TRANSITION_MID, //modId
+ PGPE_FAILURE, //reasoncode
+ ERC_PGPE_ACTIVE_TO_OBSERVATION_TIMEOUT, //Extended reason code
+ ERRL_SEV_UNRECOVERABLE, //Severity
+ NULL, //Trace Buf
+ DEFAULT_TRACE_SIZE, //Trace Size
+ wait_time, //userdata1
+ 0); //userdata2
+
+ // Callout firmware
+ addCalloutToErrl(l_errlHndl,
+ ERRL_CALLOUT_TYPE_COMPONENT_ID,
+ ERRL_COMPONENT_ID_FIRMWARE,
+ ERRL_CALLOUT_PRIORITY_HIGH);
+
+ rc = PGPE_FAILURE;
+ break;
+ }
+
+ wait_time = 0;
+
+ // wait until clip update task is done
+ while(!async_request_is_idle(&G_clip_update_req.request))
+ {
+ if(wait_time > WAIT_PGPE_TASK_TIMEOUT)
+ {
+ break;
+ }
+
+ // wait until pgpe_start_suspend call is completed.
+ // Sleep enables context switching.
+ ssx_sleep(SSX_MICROSECONDS(10));
+ wait_time += 10;
+ }
+
+ // check for timeout while waiting for pgpe_start_suspend() IPC completion
+ if(wait_time > WAIT_PGPE_TASK_TIMEOUT)
+ {
+ TRAC_ERR("SMGR: Timeout waiting for clip update IPC task");
+
+ /* @
+ * @errortype
+ * @moduleid MAIN_STATE_TRANSITION_MID
+ * @reasoncode PGPE_FAILURE
+ * @userdata1 wait_time
+ * @userdata4 ERC_PGPE_TASK_TIMEOUT
+ * @devdesc timeout waiting for pstates start/suspend task
+ */
+ l_errlHndl = createErrl(MAIN_STATE_TRANSITION_MID, //modId
+ PGPE_FAILURE, //reasoncode
+ ERC_PGPE_TASK_TIMEOUT, //Extended reason code
+ ERRL_SEV_UNRECOVERABLE, //Severity
+ NULL, //Trace Buf
+ DEFAULT_TRACE_SIZE, //Trace Size
+ wait_time, //userdata1
+ 0); //userdata2
+
+ // Callout firmware
+ addCalloutToErrl(l_errlHndl,
+ ERRL_CALLOUT_TYPE_COMPONENT_ID,
+ ERRL_COMPONENT_ID_FIRMWARE,
+ ERRL_CALLOUT_PRIORITY_HIGH);
+
+ rc = PGPE_FAILURE;
+ break;
+ }
+
+ rc = pgpe_start_suspend(PGPE_ACTION_PSTATE_STOP, G_proc_pmcr_owner);
+ if(rc)
+ {
+ TRAC_ERR("SMGR: failed to stop the pstate protocol on PGPE.");
+ break;
+ }
+ else // Pstates Disabled and clips wide opened successfully, perform state transition
+ {
+ // Set the RTL Flags to indicate which tasks can run
+ // - Set OBSERVATION b/c in OBSERVATION State
+ // - Clear ACTIVE b/c not in ACTIVE State
+ rtl_clr_run_mask_deferred(RTL_FLAG_ACTIVE);
+ rtl_set_run_mask_deferred(RTL_FLAG_OBS);
+
+ // Set the actual STATE now that we have finished everything else
+ CURRENT_STATE() = OCC_STATE_OBSERVATION;
+
+ // clear G_active_to_observation_ready flag again
+ // (for next active_to_observation transition)
+ G_active_to_observation_ready = false;
+ }
+
+ } while (0);
+
+ if(rc)
+ {
+ TRAC_ERR("SMGR: Failed to switch to Observation state");
+ }
+ else
+ {
+ // Pstates disabled, update OPAL static table in main memory
+ if(G_sysConfigData.system_type.kvm)
+ {
+ // upon succesful enablement of Pstate protocol on
+ // PGPE update OPAL table with pstate information.
+ proc_pstate_kvm_setup();
+ }
+
+ TRAC_IMP("SMGR: Active to Observation Transition Completed");
+ }
return l_errlHndl;
}
@@ -439,31 +975,88 @@ errlHndl_t SMGR_active_to_observation()
// Function Specification
//
-// Name: SMGR_active_to_standby
+// Name: SMGR_active_to_characterization
//
-// Description:
+// Description: Switch from Active to characterization state
//
// End Function Specification
-errlHndl_t SMGR_active_to_standby()
+errlHndl_t SMGR_active_to_characterization()
{
- errlHndl_t l_errlHndl = NULL;
+ int rc = 0;
+ errlHndl_t l_errlHndl = NULL;
- TRAC_IMP("SMGR: Active to Standby Transition Started");
+ TRAC_IMP("SMGR: Active to Characterization Transition Started");
- // Transtion through both functions on this multi-state transtion
- l_errlHndl = SMGR_active_to_observation();
- if(NULL == l_errlHndl)
+ do
{
- l_errlHndl = SMGR_observation_to_standby();
- }
+ // open wide pstate clips
+ rc = pgpe_widen_clip_blocking(OCC_STATE_CHARACTERIZATION);
- if(l_errlHndl)
+ if(rc)
+ {
+ TRAC_ERR("SMGR: failed to widen pstate clips.");
+ break;
+ }
+ else // clips widened successfully, keep pstates enabled, but change ownership
+ {
+ rc = pgpe_start_suspend(PGPE_ACTION_PSTATE_START, PMCR_OWNER_CHAR);
+
+ if(rc)
+ {
+ TRAC_ERR("SMGR: failed to change PMCR ownership.");
+ break;
+ }
+ else // Pstates Disabled and clips wide opened successfully, perform state transition
+ {
+ // Set the RTL Flags to indicate which tasks can run
+ // - Set OBSERVATION RTL flags for Characterization State
+ // - Clear ACTIVE b/c not in ACTIVE State
+ rtl_clr_run_mask_deferred(RTL_FLAG_ACTIVE);
+ rtl_set_run_mask_deferred(RTL_FLAG_OBS);
+
+ // Set the actual STATE now that we have finished everything else
+ CURRENT_STATE() = OCC_STATE_CHARACTERIZATION;
+ }
+ }
+ } while (0);
+
+ if(rc)
{
- TRAC_ERR("SMGR: Active to Standby Transition Failed");
+ TRAC_ERR("SMGR: Failed to switch to Characterization state");
+ /* @
+ * @errortype
+ * @moduleid MAIN_STATE_TRANSITION_MID
+ * @reasoncode INTERNAL_FAILURE
+ * @userdata1 rc
+ * @userdata4 ERC_STATE_FROM_ACT_TO_CHR_FAILURE
+ * @devdesc Failed changing from standby to observation
+ */
+ l_errlHndl = createErrl(MAIN_STATE_TRANSITION_MID, //modId
+ INTERNAL_FAILURE, //reasoncode
+ ERC_STATE_FROM_ACT_TO_CHR_FAILURE,//Extended reason code
+ ERRL_SEV_UNRECOVERABLE, //Severity
+ NULL, //Trace Buf
+ DEFAULT_TRACE_SIZE, //Trace Size
+ rc, //userdata1
+ 0); //userdata2
+
+ // Callout firmware
+ addCalloutToErrl(l_errlHndl,
+ ERRL_CALLOUT_TYPE_COMPONENT_ID,
+ ERRL_COMPONENT_ID_FIRMWARE,
+ ERRL_CALLOUT_PRIORITY_HIGH);
}
else
{
- TRAC_IMP("SMGR: Active to Standby Transition Completed");
+ // Pstates disabled, update OPAL static table in main memory
+ if(G_sysConfigData.system_type.kvm)
+ {
+ // upon succesful enablement of Pstate protocol on
+ // PGPE update OPAL table with pstate information.
+ proc_pstate_kvm_setup();
+ }
+
+ TRAC_IMP("SMGR: Active to Characterization Transition Completed");
}
return l_errlHndl;
diff --git a/src/occ_405/state.h b/src/occ_405/state.h
index 9752b9f..17ae7b6 100755
--- a/src/occ_405/state.h
+++ b/src/occ_405/state.h
@@ -31,6 +31,9 @@
#include "errl.h"
#include "mode.h"
+// Maximum allowed value approx. 16.3 ms
+#define PCBS_HEARBEAT_TIME_US 16320
+
extern uint32_t G_smgr_validate_data_active_mask;
extern uint32_t G_smgr_validate_data_observation_mask;
@@ -52,6 +55,7 @@ typedef enum
OCC_STATE_OBSERVATION = 0x02,
OCC_STATE_ACTIVE = 0x03,
OCC_STATE_SAFE = 0x04,
+ OCC_STATE_CHARACTERIZATION = 0x05,
// Make sure this is after the last valid state
OCC_STATE_COUNT,
@@ -63,8 +67,9 @@ typedef enum
} OCC_STATE;
// These are the only states that TMGT/HTMGT can send
-#define OCC_STATE_IS_VALID(state) ((state == OCC_STATE_NOCHANGE) || \
- (state == OCC_STATE_OBSERVATION) || \
+#define OCC_STATE_IS_VALID(state) ((state == OCC_STATE_NOCHANGE) || \
+ (state == OCC_STATE_OBSERVATION) || \
+ (state == OCC_STATE_CHARACTERIZATION) || \
(state == OCC_STATE_ACTIVE))
/**
@@ -144,6 +149,9 @@ typedef enum
// Returns true if OCC State is observation
#define IS_OCC_STATE_OBSERVATION() ( (OCC_STATE_OBSERVATION == G_occ_internal_state)? 1 : 0 )
+// Returns true if OCC State is charaterization
+#define IS_OCC_STATE_CHARACTERIZATION() ( (OCC_STATE_CHARACTERIZATION == G_occ_internal_state)? 1 : 0 )
+
/**
* @struct smgr_state_trans_t
* @brief Used by the "Set State" command to call the correct transition
@@ -162,6 +170,24 @@ extern OCC_STATE G_occ_internal_req_state;
extern OCC_STATE G_occ_master_state;
extern OCC_STATE G_occ_external_req_state;
+// State Transition Function Calls
+errlHndl_t SMGR_standby_to_observation();
+errlHndl_t SMGR_standby_to_characterization();
+errlHndl_t SMGR_standby_to_active();
+
+errlHndl_t SMGR_observation_to_characterization();
+errlHndl_t SMGR_observation_to_active();
+
+errlHndl_t SMGR_characterization_to_observation();
+errlHndl_t SMGR_characterization_to_active();
+
+errlHndl_t SMGR_active_to_observation();
+errlHndl_t SMGR_active_to_characterization();
+
+errlHndl_t SMGR_all_to_standby();
+
+errlHndl_t SMGR_all_to_safe();
+
// Used by macro above to clear flag indicating to not halt OCC when a reset
// is requested.
inline void reset_disable_halt(void);
@@ -182,5 +208,5 @@ errlHndl_t SMGR_set_state(OCC_STATE i_state);
// parms we currently know.
uint8_t SMGR_validate_get_valid_states(void);
-#endif
+#endif // _state_h
diff --git a/src/occ_405/thread/chom.c b/src/occ_405/thread/chom.c
index 979d44d..5e2d6e8 100755
--- a/src/occ_405/thread/chom.c
+++ b/src/occ_405/thread/chom.c
@@ -402,8 +402,10 @@ void chom_main()
chom_data_init();
}
- // only update chom sensors on an active OCC
- if (IS_OCC_STATE_ACTIVE())
+ // only update chom sensors on active, observing, or characterizing OCCs
+ if (IS_OCC_STATE_ACTIVE() ||
+ IS_OCC_STATE_OBSERVATION() ||
+ IS_OCC_STATE_CHARACTERIZATION())
{
chom_update_sensors();
}
OpenPOWER on IntegriCloud