diff options
author | Shawn McCarney <shawnmm@us.ibm.com> | 2017-07-12 16:19:54 -0500 |
---|---|---|
committer | Martha Broyles <mbroyles@us.ibm.com> | 2017-08-02 16:28:58 -0400 |
commit | 9b64b7c93ac21aaac19c98eda502ad00b1454120 (patch) | |
tree | 91302fdf03eb18d6995bbb9776e82c5765064761 /src | |
parent | 2c6661b3dcabd0aa3a69c3aeb34c760638da4064 (diff) | |
download | talos-occ-9b64b7c93ac21aaac19c98eda502ad00b1454120.tar.gz talos-occ-9b64b7c93ac21aaac19c98eda502ad00b1454120.zip |
Timestamp data when collected
This commit contains the following enhancements:
* New IPC function that runs on GPE0 to read the TOD (Time Of Day) registers
* New task on the OCC 405 that gets current TOD every tick via IPC function
* Sensor update function now sets timestamp to current TOD value
Change-Id: I0ea42b01e4df7a93633a68a0f3ed0f839d5e7b3f
RTC: 176504
Reviewed-on: http://ralgit01.raleigh.ibm.com/gerrit1/43891
Tested-by: FSP CI Jenkins <fsp-CI-jenkins+hostboot@us.ibm.com>
Reviewed-by: William A. Bryan <wilbryan@us.ibm.com>
Reviewed-by: Martha Broyles <mbroyles@us.ibm.com>
Diffstat (limited to 'src')
-rw-r--r-- | src/common/get_tod_structs.h | 50 | ||||
-rw-r--r-- | src/common/ipc_func_ids.h | 1 | ||||
-rwxr-xr-x | src/common/pss_constants.h | 7 | ||||
-rw-r--r-- | src/occ_405/occLinkInputFile | 1 | ||||
-rwxr-xr-x | src/occ_405/rtls/rtls.h | 1 | ||||
-rwxr-xr-x | src/occ_405/rtls/rtls_tables.c | 21 | ||||
-rwxr-xr-x | src/occ_405/sensor/sensor.c | 8 | ||||
-rwxr-xr-x | src/occ_405/sensor/sensor.h | 4 | ||||
-rw-r--r-- | src/occ_405/sensor/sensor_get_tod_task.c | 482 | ||||
-rw-r--r-- | src/occ_405/sensor/sensor_get_tod_task.h | 54 | ||||
-rw-r--r-- | src/occ_405/sensor/sensor_main_memory.c | 1 | ||||
-rwxr-xr-x | src/occ_405/sensor/sensor_service_codes.h | 5 | ||||
-rw-r--r-- | src/occ_405/topfiles.mk | 1 | ||||
-rw-r--r-- | src/occ_gpe0/gpe_get_tod.c | 154 | ||||
-rw-r--r-- | src/occ_gpe0/ipc_func_tables.c | 5 | ||||
-rw-r--r-- | src/occ_gpe0/topfiles.mk | 5 |
16 files changed, 789 insertions, 11 deletions
diff --git a/src/common/get_tod_structs.h b/src/common/get_tod_structs.h new file mode 100644 index 0000000..7312a6f --- /dev/null +++ b/src/common/get_tod_structs.h @@ -0,0 +1,50 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/common/get_tod_structs.h $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 2017,2017 */ +/* [+] International Business Machines Corp. */ +/* */ +/* */ +/* 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 */ +/* */ +/* 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. */ +/* */ +/* IBM_PROLOG_END_TAG */ + +/* This header file is used by both occ_405 and occ_gpe0. */ +/* Contains common structures and defines. */ + +#ifndef _GET_TOD_STRUCTS_H +#define _GET_TOD_STRUCTS_H + +#include <stdint.h> // For uint*_t +#include <gpe_export.h> // For GpeErrorStruct + +/** + * Struct containing the error state and arguments for the IPC function + * IPC_ST_GET_TOD_FUNCID. + */ +typedef struct __attribute__ ((packed)) +{ + GpeErrorStruct error; + uint64_t tod; +} gpe_get_tod_args_t; + +/** + * Value used when the actual TOD value is unknown. + */ +#define TOD_VALUE_UNKNOWN 0xFFFFFFFFFFFFFFFFull + +#endif // _GET_TOD_STRUCTS_H diff --git a/src/common/ipc_func_ids.h b/src/common/ipc_func_ids.h index 40842be..3f759a5 100644 --- a/src/common/ipc_func_ids.h +++ b/src/common/ipc_func_ids.h @@ -60,6 +60,7 @@ IPC_FUNCIDS_TABLE_START IPC_FUNC_ID(IPC_ST_GPE0_NOP) IPC_FUNC_ID(IPC_ST_GET_NEST_DTS_FUNCID) IPC_FUNC_ID(IPC_ST_FIR_COLLECTION) + IPC_FUNC_ID(IPC_ST_GET_TOD_FUNCID) IPC_FUNCIDS_ST_END(OCCHW_INST_ID_GPE0) //Functions that are only supported by GPE1 should be defined here diff --git a/src/common/pss_constants.h b/src/common/pss_constants.h index 08a7d90..8ce9bb5 100755 --- a/src/common/pss_constants.h +++ b/src/common/pss_constants.h @@ -1,11 +1,11 @@ /* IBM_PROLOG_BEGIN_TAG */ /* This is an automatically generated prolog. */ /* */ -/* $Source: src/occ_gpe0/pss_constants.h $ */ +/* $Source: src/common/pss_constants.h $ */ /* */ /* OpenPOWER OnChipController Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2011,2016 */ +/* Contributors Listed Below - COPYRIGHT 2011,2017 */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -52,7 +52,8 @@ #define SPIPSS_P2S_WDATA_REG (SPIPSS_REGISTER_BASE + 0x50) #define SPIPSS_P2S_RDATA_REG (SPIPSS_REGISTER_BASE + 0x60) -#define TOD_VALUE_REG 0x00040020 +#define TOD_STATUS_REG 0x00040008 +#define TOD_VALUE_REG 0x00040020 // Constant for use in wait statments: waits (5 * MICROSECONDS) #define MICROSECONDS 600 diff --git a/src/occ_405/occLinkInputFile b/src/occ_405/occLinkInputFile index 9f3725d..123a0dc 100644 --- a/src/occ_405/occLinkInputFile +++ b/src/occ_405/occLinkInputFile @@ -80,6 +80,7 @@ INPUT ( amec_amester.o reset.o rtls_tables.o rtls.o + sensor_get_tod_task.o sensor_inband_cmd.o sensor_info.o sensor_main_memory.o diff --git a/src/occ_405/rtls/rtls.h b/src/occ_405/rtls/rtls.h index 2b8fbae..899d44a 100755 --- a/src/occ_405/rtls/rtls.h +++ b/src/occ_405/rtls/rtls.h @@ -62,6 +62,7 @@ typedef enum { TASK_ID_NEST_DTS, TASK_ID_24X7, // 24x7 data collection task TASK_ID_GPE_TIMINGS, + TASK_ID_GET_TOD, // Get time of day task TASK_END // This must always be the last enum in this list, // so that TASK_END always equals the last task ID + 1. } task_id_t; diff --git a/src/occ_405/rtls/rtls_tables.c b/src/occ_405/rtls/rtls_tables.c index 2f67e5c..eb439cf 100755 --- a/src/occ_405/rtls/rtls_tables.c +++ b/src/occ_405/rtls/rtls_tables.c @@ -37,6 +37,7 @@ #include "amec_sensors_fw.h" #include "dimm.h" #include <common.h> +#include "sensor_get_tod_task.h" // For task_get_tod() //flags for task table #define APSS_TASK_FLAGS RTL_FLAG_MSTR | RTL_FLAG_OBS | RTL_FLAG_ACTIVE | RTL_FLAG_MSTR_READY | RTL_FLAG_RUN @@ -62,8 +63,9 @@ #define FLAGS_AMEC_SLAVE RTL_FLAG_MSTR | RTL_FLAG_NOTMSTR | RTL_FLAG_OBS | RTL_FLAG_ACTIVE | RTL_FLAG_MSTR_READY | RTL_FLAG_NO_APSS | RTL_FLAG_RUN | RTL_FLAG_APSS_NOT_INITD #define FLAGS_AMEC_MASTER RTL_FLAG_MSTR | RTL_FLAG_OBS | RTL_FLAG_ACTIVE | RTL_FLAG_MSTR_READY | RTL_FLAG_NO_APSS | RTL_FLAG_RUN | RTL_FLAG_APSS_NOT_INITD -#define FLAGS_24X7 RTL_FLAG_MSTR | RTL_FLAG_NOTMSTR | RTL_FLAG_OBS | RTL_FLAG_ACTIVE | RTL_FLAG_MSTR_READY | RTL_FLAG_NO_APSS | RTL_FLAG_RUN | RTL_FLAG_APSS_NOT_INITD +#define FLAGS_24X7 RTL_FLAG_MSTR | RTL_FLAG_NOTMSTR | RTL_FLAG_OBS | RTL_FLAG_ACTIVE | RTL_FLAG_MSTR_READY | RTL_FLAG_NO_APSS | RTL_FLAG_RUN | RTL_FLAG_APSS_NOT_INITD +#define FLAGS_GET_TOD RTL_FLAG_MSTR | RTL_FLAG_NOTMSTR | RTL_FLAG_OBS | RTL_FLAG_ACTIVE | RTL_FLAG_MSTR_READY | RTL_FLAG_NO_APSS | RTL_FLAG_RUN | RTL_FLAG_APSS_NOT_INITD #define FLAGS_APSS_START_MEAS APSS_TASK_FLAGS #define FLAGS_APSS_CONT_MEAS APSS_TASK_FLAGS @@ -127,10 +129,12 @@ task_t G_task_table[TASK_END] = { { FLAGS_NEST_DTS, task_nest_dts, NULL }, { FLAGS_24X7, task_24x7, NULL }, // TASK_ID_24X7 { FLAGS_GPE_TIMINGS, task_gpe_timings, NULL }, // TASK_ID_GPE_TIMINGS + { FLAGS_GET_TOD, task_get_tod, NULL }, // TASK_ID_GET_TOD }; const uint8_t G_tick0_seq[] = { TASK_ID_APSS_START, + TASK_ID_GET_TOD, TASK_ID_CORE_DATA_LOW, TASK_ID_DIMM_SM, TASK_ID_APSS_CONT, @@ -153,6 +157,7 @@ const uint8_t G_tick0_seq[] = { const uint8_t G_tick1_seq[] = { TASK_ID_APSS_START, + TASK_ID_GET_TOD, TASK_ID_CORE_DATA_LOW, //TASK_ID_GPU_SM, TASK_ID_APSS_CONT, @@ -175,6 +180,7 @@ const uint8_t G_tick1_seq[] = { const uint8_t G_tick2_seq[] = { TASK_ID_APSS_START, + TASK_ID_GET_TOD, TASK_ID_CORE_DATA_LOW, TASK_ID_DIMM_SM, TASK_ID_APSS_CONT, @@ -197,6 +203,7 @@ const uint8_t G_tick2_seq[] = { const uint8_t G_tick3_seq[] = { TASK_ID_APSS_START, + TASK_ID_GET_TOD, TASK_ID_NEST_DTS, //TASK_ID_GPU_SM, TASK_ID_APSS_CONT, @@ -219,6 +226,7 @@ const uint8_t G_tick3_seq[] = { const uint8_t G_tick4_seq[] = { TASK_ID_APSS_START, + TASK_ID_GET_TOD, TASK_ID_CORE_DATA_LOW, TASK_ID_DIMM_SM, TASK_ID_APSS_CONT, @@ -241,6 +249,7 @@ const uint8_t G_tick4_seq[] = { const uint8_t G_tick5_seq[] = { TASK_ID_APSS_START, + TASK_ID_GET_TOD, TASK_ID_CORE_DATA_LOW, //TASK_ID_GPU_SM, TASK_ID_APSS_CONT, @@ -263,6 +272,7 @@ const uint8_t G_tick5_seq[] = { const uint8_t G_tick6_seq[] = { TASK_ID_APSS_START, + TASK_ID_GET_TOD, TASK_ID_CORE_DATA_LOW, TASK_ID_DIMM_SM, TASK_ID_APSS_CONT, @@ -285,6 +295,7 @@ const uint8_t G_tick6_seq[] = { const uint8_t G_tick7_seq[] = { TASK_ID_APSS_START, + TASK_ID_GET_TOD, //TASK_ID_GPU_SM, TASK_ID_APSS_CONT, TASK_ID_CORE_DATA_HIGH, @@ -306,6 +317,7 @@ const uint8_t G_tick7_seq[] = { const uint8_t G_tick8_seq[] = { TASK_ID_APSS_START, + TASK_ID_GET_TOD, TASK_ID_CORE_DATA_LOW, TASK_ID_DIMM_SM, TASK_ID_APSS_CONT, @@ -328,6 +340,7 @@ const uint8_t G_tick8_seq[] = { const uint8_t G_tick9_seq[] = { TASK_ID_APSS_START, + TASK_ID_GET_TOD, TASK_ID_CORE_DATA_LOW, //TASK_ID_GPU_SM, TASK_ID_APSS_CONT, @@ -350,6 +363,7 @@ const uint8_t G_tick9_seq[] = { const uint8_t G_tick10_seq[] = { TASK_ID_APSS_START, + TASK_ID_GET_TOD, TASK_ID_CORE_DATA_LOW, TASK_ID_DIMM_SM, TASK_ID_APSS_CONT, @@ -372,6 +386,7 @@ const uint8_t G_tick10_seq[] = { const uint8_t G_tick11_seq[] = { TASK_ID_APSS_START, + TASK_ID_GET_TOD, //TASK_ID_GPU_SM, TASK_ID_APSS_CONT, TASK_ID_CORE_DATA_HIGH, @@ -393,6 +408,7 @@ const uint8_t G_tick11_seq[] = { const uint8_t G_tick12_seq[] = { TASK_ID_APSS_START, + TASK_ID_GET_TOD, TASK_ID_CORE_DATA_LOW, TASK_ID_DIMM_SM, TASK_ID_APSS_CONT, @@ -415,6 +431,7 @@ const uint8_t G_tick12_seq[] = { const uint8_t G_tick13_seq[] = { TASK_ID_APSS_START, + TASK_ID_GET_TOD, TASK_ID_CORE_DATA_LOW, //TASK_ID_GPU_SM, TASK_ID_APSS_CONT, @@ -437,6 +454,7 @@ const uint8_t G_tick13_seq[] = { const uint8_t G_tick14_seq[] = { TASK_ID_APSS_START, + TASK_ID_GET_TOD, TASK_ID_CORE_DATA_LOW, TASK_ID_DIMM_SM, TASK_ID_APSS_CONT, @@ -459,6 +477,7 @@ const uint8_t G_tick14_seq[] = { const uint8_t G_tick15_seq[] = { TASK_ID_APSS_START, + TASK_ID_GET_TOD, //TASK_ID_GPU_SM, TASK_ID_APSS_CONT, TASK_ID_CORE_DATA_HIGH, diff --git a/src/occ_405/sensor/sensor.c b/src/occ_405/sensor/sensor.c index 73c2a5e..9863f1e 100755 --- a/src/occ_405/sensor/sensor.c +++ b/src/occ_405/sensor/sensor.c @@ -32,13 +32,15 @@ #include <occ_service_codes.h> // OCC reason codes #include <sensor_service_codes.h> // sensor module ids #include <trac.h> // Trace macros -#include <rtls.h> // For G_current_tick +#include <get_tod_structs.h> // For TOD_VALUE_UNKNOWN #define UINT16_MIN 0 // Global sensor counter uint32_t G_amec_sensor_count = 0; +// See header file for description +volatile uint64_t G_tod = TOD_VALUE_UNKNOWN; void sensor_init(sensor_t * io_sensor_ptr, const uint16_t i_gsid, @@ -268,8 +270,8 @@ void sensor_update( sensor_t * io_sensor_ptr, const uint16_t i_sensor_value) sensor_reset(io_sensor_ptr); } - // update timestamp - io_sensor_ptr->timestamp = G_current_tick; + // set timestamp to current time of day + io_sensor_ptr->timestamp = G_tod; // update sample value io_sensor_ptr->sample = i_sensor_value; diff --git a/src/occ_405/sensor/sensor.h b/src/occ_405/sensor/sensor.h index 3b301d9..33f5e75 100755 --- a/src/occ_405/sensor/sensor.h +++ b/src/occ_405/sensor/sensor.h @@ -239,6 +239,10 @@ extern const sensor_info_t G_sensor_info[]; // Contains array of pointers to mini-sensors, indexed by GSID extern const minisensor_ptr_t G_amec_mini_sensor_list[]; +// Current Time Of Day (TOD). Constantly updated by TASK_ID_GET_TOD. Used by +// sensor_update(). Declared volatile since it is used in multiple threads. +extern volatile uint64_t G_tod; + // sensor_init void sensor_init(sensor_t * io_sensor_ptr, const uint16_t i_gsid, diff --git a/src/occ_405/sensor/sensor_get_tod_task.c b/src/occ_405/sensor/sensor_get_tod_task.c new file mode 100644 index 0000000..eb511dc --- /dev/null +++ b/src/occ_405/sensor/sensor_get_tod_task.c @@ -0,0 +1,482 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/occ_405/sensor/sensor_get_tod_task.c $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 2017,2017 */ +/* [+] International Business Machines Corp. */ +/* */ +/* */ +/* 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 */ +/* */ +/* 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. */ +/* */ +/* IBM_PROLOG_END_TAG */ + +/** + * @file sensor_get_tod_task.c + * + * This file defines the functions and global variables for the task that gets + * the current Time Of Day (TOD). + * + * The register holding the time of day value is read via a SCOM address, and + * the OCC 405 cannot read from this address. To work around this, the IPC + * framework is used to request GPE0 to read the register value. GPE0 returns + * the current time of day value using a GPE_BUFFER. + */ + +//****************************************************************************** +// Includes +//****************************************************************************** +#include <sensor_get_tod_task.h> // Primary header +#include <stdint.h> // For uint*_t +#include <common_types.h> // For bool +#include <sensor.h> // For G_tod +#include <occ_common.h> // For GPE_BUFFER +#include <occ_service_codes.h> // For OCC reason codes +#include <sensor_service_codes.h> // For GET_TOD_*_MOD module ids +#include <trac.h> // For trace macros +#include <errl.h> // For error logging functions and types +#include <occhw_async.h> // For gpe_request_*(), async_request_is_idle() +#include <get_tod_structs.h> // For gpe_get_tod_args_t and TOD_VALUE_UNKNOWN +#include <occ_sys_config.h> // For G_sysConfigData + + +//****************************************************************************** +// Defines +//****************************************************************************** + +/** + * Number of errors before we trace. + */ +#define GET_TOD_ERRORS_BEFORE_TRACE 1 + +/** + * Number of errors before we set G_tod to TOD_VALUE_UNKNOWN. + */ +#define GET_TOD_ERRORS_BEFORE_UNKNOWN 4 + +/** + * Number of errors before we log the error. + */ +#define GET_TOD_ERRORS_BEFORE_LOG 16 + +/** + * Maximum number of errors to count. Must fit in a uint8_t. + */ +#define GET_TOD_MAX_ERRORS GET_TOD_ERRORS_BEFORE_LOG + + +//****************************************************************************** +// Structs and Enums +//****************************************************************************** + +/** + * Type of data to store in the user details section of an error log. + */ +typedef enum +{ + GET_TOD_ERRL_USR_DTLS_NONE, ///< No data to store + GET_TOD_ERRL_USR_DTLS_GPE_FFDC ///< ffdc value from GPE0 in G_get_tod_args +} GET_TOD_ERRL_USR_DTLS_DATA; + + +//****************************************************************************** +// Globals +//****************************************************************************** + +/** + * Buffer holding arguments for the IPC function. Used to pass data to/from GPE0. + */ +GPE_BUFFER(gpe_get_tod_args_t G_get_tod_args); + +/** + * GPE request structure. Used by GPE functions to schedule request. + */ +GpeRequest G_get_tod_request; + +/** + * Specifies whether the GPE request was scheduled. If false, the request + * finished or has never been scheduled/initialized. + */ +bool G_get_tod_req_scheduled = false; + +/** + * Specifies whether the results of the GPE request are available. Must be + * declared volatile since it is used by both regular and callback functions. + */ +volatile bool G_get_tod_results_available = false; + +/** + * Number of consecutive errors that have occurred. Cleared when we + * successfully obtain the current time of day. + */ +uint8_t G_get_tod_error_count = 0; + +/** + * Specifies whether this task is enabled. If the task is disabled it will no + * longer attempt to get the current time of day. + */ +bool G_get_tod_enabled = true; + + +//****************************************************************************** +// Private Functions +//****************************************************************************** + +/** + * Increment the error count. + */ +void get_tod_increment_error_count() +{ + // Increment error count if we are below the maximum + if (G_get_tod_error_count < GET_TOD_MAX_ERRORS) + { + ++G_get_tod_error_count; + } + + // Set time of day to unknown if needed + if (G_get_tod_error_count == GET_TOD_ERRORS_BEFORE_UNKNOWN) + { + G_tod = TOD_VALUE_UNKNOWN; + } +} + + +/** + * Clear the error count. + * + * If there had previously been errors, trace that we have recovered. + */ +void get_tod_clear_error_count() +{ + // If one or more errors had occurred + if (G_get_tod_error_count > 0) + { + // Trace that we recovered + TRAC_INFO("get_tod_clear_error_count: Task recovered after %u errors", + G_get_tod_error_count); + + // Clear error count + G_get_tod_error_count = 0; + } +} + + +/** + * Logs and commits an unrecoverable error. Calls out the processor. Creates a + * user details section if needed containing the specified additional data. + * Does nothing if an error has already been logged. + * + * Disables this task. We will no longer try to read the current time of day. + * + * Note that the required error log comment containing tags like 'userdata4' and + * 'devdesc' must be located by the call to this function. It is not located + * inside this function because the value of those tags varies. + * + * @param i_modId Module ID + * @param i_reasonCode Reason code + * @param i_extReasonCode Extended reason code + * @param i_userData1 Userdata1 value + * @param i_userData2 Userdata2 value + * @param i_usrDtlsData Data to store in a user details section (if any) + */ +void get_tod_log_error(uint16_t i_modId, uint8_t i_reasonCode, + uint16_t i_extReasonCode, uint32_t i_userData1, + uint32_t i_userData2, GET_TOD_ERRL_USR_DTLS_DATA i_usrDtlsData) +{ + // Exit if we have already logged an error + static bool L_error_logged = false; + if (L_error_logged) + { + return; + } + + // Create unrecoverable error + errlHndl_t l_errl = createErrl(i_modId, // Module ID + i_reasonCode, // Reason code + i_extReasonCode, // Extended reason code + ERRL_SEV_UNRECOVERABLE, // Severity + NULL, // Trace Buffers + DEFAULT_TRACE_SIZE, // Trace Size + i_userData1, // Userdata1 + i_userData2); // Userdata2 + + // If specified, add user details section to hold ffdc field from GPE + if (i_usrDtlsData == GET_TOD_ERRL_USR_DTLS_GPE_FFDC) + { + addUsrDtlsToErrl(l_errl, + (uint8_t *) &(G_get_tod_args.error.ffdc), + sizeof(G_get_tod_args.error.ffdc), + ERRL_USR_DTL_STRUCT_VERSION_1, + ERRL_USR_DTL_BINARY_DATA); + } + + // Add processor callout + addCalloutToErrl(l_errl, + ERRL_CALLOUT_TYPE_HUID, + G_sysConfigData.proc_huid, + ERRL_CALLOUT_PRIORITY_MED); + + // Commit error + commitErrl(&l_errl); + L_error_logged = true; + + // Disable this task + TRAC_ERR("get_tod_log_error: Disabled task due to logging an error"); + G_get_tod_enabled = false; +} + + +/** + * Returns whether the global GPE request struct is idle and ready for re-use. + * Returns true immediately if the request was not scheduled. If the request + * was scheduled, checks to see if it has finished. + * + * @return true if GPE request is idle, false otherwise + */ +bool get_tod_is_request_idle(void) +{ + // If the request was not previously scheduled, then it is idle. This also + // handles the case where the request has not been initialized yet. + if (!G_get_tod_req_scheduled) + { + return true; + } + + // Request was scheduled; check if it finished and is now idle + if (async_request_is_idle(&G_get_tod_request.request)) + { + // Request is now idle and ready for re-use + G_get_tod_req_scheduled = false; + return true; + } + + // Request was scheduled but has not finished. Increment error count. + get_tod_increment_error_count(); + + // Trace if necessary + if (G_get_tod_error_count == GET_TOD_ERRORS_BEFORE_TRACE) + { + TRAC_ERR("get_tod_is_request_idle: Waiting for request to finish"); + } + + // Log error if necessary + if (G_get_tod_error_count == GET_TOD_ERRORS_BEFORE_LOG) + { + /* @ + * @errortype + * @moduleid GET_TOD_IS_REQ_IDLE_MOD + * @reasoncode GPE_REQUEST_TASK_NOT_IDLE + * @userdata1 0 + * @userdata2 0 + * @userdata4 ERC_GENERIC_TIMEOUT + * @devdesc GPE request not finished after waiting repeatedly + */ + get_tod_log_error(GET_TOD_IS_REQ_IDLE_MOD, GPE_REQUEST_TASK_NOT_IDLE, + ERC_GENERIC_TIMEOUT, 0, 0, GET_TOD_ERRL_USR_DTLS_NONE); + } + + // Return false since request is not idle + return false; +} + + +/** + * Callback that is invoked when the GPE request completes. + * + * @param i_arg Callback argument specified during gpe_request_create(). Not used. + */ +int get_tod_callback(void * i_arg) +{ + // NOTE: No tracing allowed in callback functions + + // If GPE request was successful copy current time of day into G_tod. We do + // this in a callback so G_tod is updated as soon as possible. + if (G_get_tod_args.error.rc == GPE_RC_SUCCESS) + { + G_tod = G_get_tod_args.tod; + } + + // Set flag indicating results of GPE request are available. Any errors + // will be handled later since callbacks cannot trace. + G_get_tod_results_available = true; + + // Return 0 indicating to async framework that callback ran successfully + return 0; +} + + +/** + * Handles the results of the previous GPE request. + */ +void get_tod_handle_request_results(void) +{ + // Check if results from previous GPE request are available + if (!G_get_tod_results_available) + { + // No results available, so there is nothing to do. There was no + // previous request, or previous request didn't complete due to errors. + return; + } + + // Check whether GPE request successfully read time of day + if (G_get_tod_args.error.rc == GPE_RC_SUCCESS) + { + // Request succeeded. Callback already set G_tod. Clear error counter. + get_tod_clear_error_count(); + } + else + { + // Request failed to read time of day; increment error count + get_tod_increment_error_count(); + + // Trace if needed + if (G_get_tod_error_count == GET_TOD_ERRORS_BEFORE_TRACE) + { + TRAC_ERR("get_tod_handle_request_results: GPE0 error reading TOD register: " + "addr=0x%08X, rc=0x%08X, ffdc=0x%08X%08X", + G_get_tod_args.error.addr, + G_get_tod_args.error.rc, + (uint32_t) (G_get_tod_args.error.ffdc >> 32), + (uint32_t) (G_get_tod_args.error.ffdc & 0x00000000FFFFFFFFull)); + } + + // Log error if needed + if (G_get_tod_error_count == GET_TOD_ERRORS_BEFORE_LOG) + { + /* @ + * @errortype + * @moduleid GET_TOD_HNDL_REQ_RSLT_MOD + * @reasoncode GPE_REQUEST_RC_FAILURE + * @userdata1 SCOM address + * @userdata2 RC from GPE IPC function + * @userdata4 ERC_GETSCOM_FAILURE + * @devdesc GPE request to read SCOM TOD register failed + */ + get_tod_log_error(GET_TOD_HNDL_REQ_RSLT_MOD, GPE_REQUEST_RC_FAILURE, + ERC_GETSCOM_FAILURE, G_get_tod_args.error.addr, + G_get_tod_args.error.rc, GET_TOD_ERRL_USR_DTLS_GPE_FFDC); + } + } + + // Clear flag since we handled the results of the previous GPE request + G_get_tod_results_available = false; +} + + +/** + * Schedules a GPE request to read the TOD register to get current time of day. + */ +void get_tod_schedule_request(void) +{ + // Create (initialize) GPE request if needed + static bool L_request_created = false; + if (!L_request_created) + { + int l_rc = gpe_request_create(&G_get_tod_request, // GpeRequest + &G_async_gpe_queue0, // Queue for GPE0 + IPC_ST_GET_TOD_FUNCID, // IPC Function ID + &G_get_tod_args, // IPC Command Data + SSX_WAIT_FOREVER, // Timeout (none) + get_tod_callback, // Callback + NULL, // Callback argument + ASYNC_CALLBACK_IMMEDIATE); // Options + if (l_rc != 0) + { + // Create failed; trace and log error, then exit. Ignore error + // count because we don't retry creates. + TRAC_ERR("get_tod_schedule_request: Request create failure: rc=0x%08X", l_rc); + /* @ + * @errortype + * @moduleid GET_TOD_SCHED_REQ_MOD + * @reasoncode GPE_REQUEST_CREATE_FAILURE + * @userdata1 Return code from gpe_request_create() + * @userdata2 0 + * @userdata4 OCC_NO_EXTENDED_RC + * @devdesc Failed to create GPE request + */ + get_tod_log_error(GET_TOD_SCHED_REQ_MOD, GPE_REQUEST_CREATE_FAILURE, + OCC_NO_EXTENDED_RC, l_rc, 0, GET_TOD_ERRL_USR_DTLS_NONE); + return; + } + L_request_created = true; + } + + // Schedule GPE request + int l_rc = gpe_request_schedule(&G_get_tod_request); + if (l_rc != 0) + { + // Schedule failed; increment error count + get_tod_increment_error_count(); + + // Trace if needed + if (G_get_tod_error_count == GET_TOD_ERRORS_BEFORE_TRACE) + { + TRAC_ERR("get_tod_schedule_request: Request schedule failure: rc=0x%08X", l_rc); + } + + // Log error if needed + if (G_get_tod_error_count == GET_TOD_ERRORS_BEFORE_LOG) + { + /* @ + * @errortype + * @moduleid GET_TOD_SCHED_REQ_MOD + * @reasoncode GPE_REQUEST_SCHEDULE_FAILURE + * @userdata1 Return code from gpe_request_schedule() + * @userdata2 0 + * @userdata4 OCC_NO_EXTENDED_RC + * @devdesc Failed to schedule GPE request + */ + get_tod_log_error(GET_TOD_SCHED_REQ_MOD, GPE_REQUEST_SCHEDULE_FAILURE, + OCC_NO_EXTENDED_RC, l_rc, 0, GET_TOD_ERRL_USR_DTLS_NONE); + } + return; + } + + // Successfully scheduled request. Request is not blocking, so we will not + // get the results until later. Set flag indicating request is scheduled. + G_get_tod_req_scheduled = true; +} + + +//****************************************************************************** +// Public Functions +//****************************************************************************** + +// See description in header file +void task_get_tod(task_t * i_self) +{ + // Exit if this task is disabled + if (!G_get_tod_enabled) + { + return; + } + + // Exit if the previous GPE request has not finished + if (!get_tod_is_request_idle()) + { + return; + } + + // Handle results of previous GPE request + get_tod_handle_request_results(); + if (!G_get_tod_enabled) + { + // Task disabled due to errors while handling request results + return; + } + + // Schedule new GPE request to get time of day + get_tod_schedule_request(); +} diff --git a/src/occ_405/sensor/sensor_get_tod_task.h b/src/occ_405/sensor/sensor_get_tod_task.h new file mode 100644 index 0000000..d46da75 --- /dev/null +++ b/src/occ_405/sensor/sensor_get_tod_task.h @@ -0,0 +1,54 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/occ_405/sensor/sensor_get_tod_task.h $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 2017,2017 */ +/* [+] International Business Machines Corp. */ +/* */ +/* */ +/* 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 */ +/* */ +/* 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. */ +/* */ +/* IBM_PROLOG_END_TAG */ + +#ifndef _SENSOR_GET_TOD_TASK_H +#define _SENSOR_GET_TOD_TASK_H + +/** + * @file sensor_get_tod_task.h + * + * This file declares the functions for the task that gets the current Time Of + * Day (TOD). + */ + +//****************************************************************************** +// Includes +//****************************************************************************** +#include <rtls.h> // For task_t + + +//****************************************************************************** +// Function Prototypes +//****************************************************************************** + +/** + * Initial function called by the TASK_ID_GET_TOD task. Gets the current Time + * Of Day (TOD) value and stores it in the global variable G_tod. + * + * @param i_self This task + */ +void task_get_tod(task_t * i_self); + +#endif // _SENSOR_GET_TOD_TASK_H diff --git a/src/occ_405/sensor/sensor_main_memory.c b/src/occ_405/sensor/sensor_main_memory.c index 66e4da8..7e4cb51 100644 --- a/src/occ_405/sensor/sensor_main_memory.c +++ b/src/occ_405/sensor/sensor_main_memory.c @@ -43,6 +43,7 @@ #include <occ_service_codes.h> // For OCC reason codes #include <sensor_service_codes.h> // For sensor module ids #include <trac.h> // For trace macros +#include <errl.h> // For error logging functions and types #include <occhw_async.h> // For bce_request_*(), async_request_is_idle() #include <cmdh_fsp_cmds.h> // For G_apss_ch_to_function diff --git a/src/occ_405/sensor/sensor_service_codes.h b/src/occ_405/sensor/sensor_service_codes.h index f511edf..35e2045 100755 --- a/src/occ_405/sensor/sensor_service_codes.h +++ b/src/occ_405/sensor/sensor_service_codes.h @@ -50,6 +50,11 @@ enum occSensorModuleId INBAND_CMD_BCE_COPY_MOD = SNSR_COMP_ID | 0x21, INBAND_CMD_HANDLER_MOD = SNSR_COMP_ID | 0x22, INBAND_CMD_CHECK_MOD = SNSR_COMP_ID | 0x23, + + // Get time of day task + GET_TOD_IS_REQ_IDLE_MOD = SNSR_COMP_ID | 0x30, + GET_TOD_HNDL_REQ_RSLT_MOD = SNSR_COMP_ID | 0x31, + GET_TOD_SCHED_REQ_MOD = SNSR_COMP_ID | 0x32, }; #endif /* #ifndef _SENSOR_SERVICE_CODES_H_ */ diff --git a/src/occ_405/topfiles.mk b/src/occ_405/topfiles.mk index f3b85ad..faae172 100644 --- a/src/occ_405/topfiles.mk +++ b/src/occ_405/topfiles.mk @@ -84,6 +84,7 @@ TOP-C-SOURCES = amec/amec_analytics.c \ rtls/rtls_tables.c \ rtls/rtls.c \ scom.c \ + sensor/sensor_get_tod_task.c \ sensor/sensor_inband_cmd.c \ sensor/sensor_info.c \ sensor/sensor_main_memory.c \ diff --git a/src/occ_gpe0/gpe_get_tod.c b/src/occ_gpe0/gpe_get_tod.c new file mode 100644 index 0000000..187a61b --- /dev/null +++ b/src/occ_gpe0/gpe_get_tod.c @@ -0,0 +1,154 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/occ_gpe0/gpe_get_tod.c $ */ +/* */ +/* OpenPOWER OnChipController Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 2017,2017 */ +/* [+] International Business Machines Corp. */ +/* */ +/* */ +/* 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 */ +/* */ +/* 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. */ +/* */ +/* IBM_PROLOG_END_TAG */ + +/** + * @file gpe_get_tod.c + * + * This file defines the functions for getting the current value of the Time Of + * Day (TOD) register. + */ + +//****************************************************************************** +// Includes +//****************************************************************************** + +#include <stdint.h> // For uint*_t +#include "pk.h" // For PK_TRACE() and pk_halt() +#include "ipc_api.h" // For ipc_msg_t +#include "ipc_async_cmd.h" // For ipc_async_cmd_t +#include "ppe42_scom.h" // For getscom_abs() +#include "gpe_util.h" // For gpe_set_ffdc() +#include "get_tod_structs.h" // For gpe_get_tod_args_t +#include "gpe_err.h" // For GPE_RC_* +#include "pss_constants.h" // For TOD_STATUS_REG and TOD_VALUE_REG + + +//****************************************************************************** +// Defines +//****************************************************************************** + +/** + * Returns the IS_RUNNING bit within the TOD_STATUS_REG register. + * + * IS_RUNNING is bit 20 in the register value. Note that bit 0 is the most + * significant bit. + * + * @param reg_value value of TOD_STATUS_REG register + * @return IS_RUNNING bit. If 1, the TOD is running. + */ +#define TOD_IS_RUNNING(reg_value) \ + (((uint8_t) (((uint64_t) (reg_value)) >> 43)) & 0x01u) + +/** + * Returns the TOD_VALUE field within the TOD_VALUE_REG register. + * + * The TOD_VALUE field is located in bits 0:59 of the register value. Note that + * bit 0 is the most significant bit. In the returned value we must set the low + * order 4 bits (60:63) to 0 rather than right shifting 4 bits. + * + * @param reg_value value of TOD_VALUE_REG register + * @return TOD_VALUE field + */ +#define TOD_VALUE(reg_value) (((uint64_t) (reg_value)) & 0xFFFFFFFFFFFFFFF0ull) + + +//****************************************************************************** +// Functions +//****************************************************************************** + +/** + * Reads the value of the TOD_STATUS_REG and TOD_VALUE_REG registers. If the + * TOD is running, the current Time Of Day value is stored in the tod field of + * the args parameter. + * + * @param args Arguments passed from the OCC 405 via the IPC framework + */ +void gpe_read_tod_registers(gpe_get_tod_args_t * args) +{ + // Initialize output arguments to default values + args->error.rc = GPE_RC_SUCCESS; + args->error.addr = 0; + args->error.ffdc = 0; + args->tod = TOD_VALUE_UNKNOWN; + + // Read value of TOD_STATUS_REG register + uint64_t l_reg_val; + uint32_t rc = getscom_abs(TOD_STATUS_REG, &l_reg_val); + if (rc != 0) + { + gpe_set_ffdc(&(args->error), TOD_STATUS_REG, GPE_RC_SCOM_GET_FAILED, rc); + return; + } + + // Check if TOD is running based on TOD_STATUS_REG value. + if (!TOD_IS_RUNNING(l_reg_val)) + { + // TOD is not running. Operating system is likely fixing it. Not an error. + return; + } + + // Read value of TOD_VALUE_REG register + rc = getscom_abs(TOD_VALUE_REG, &l_reg_val); + if (rc != 0) + { + gpe_set_ffdc(&(args->error), TOD_VALUE_REG, GPE_RC_SCOM_GET_FAILED, rc); + return; + } + + // The TOD_VALUE_REG register contains two fields. Get the TOD_VALUE field + // and store that as the Time Of Day value. + args->tod = TOD_VALUE(l_reg_val); +} + + +/** + * IPC function that gets the current Time Of Day (TOD) value. + * + * First reads the TOD_STATUS_REG register to make sure the TOD is running. + * Then reads the TOD_VALUE_REG register to get the TOD value. + * + * @param cmd A pointer to the IPC command message + * @param arg IPC function argument. Currently not used. + */ +void gpe_get_tod(ipc_msg_t * cmd, void * arg) +{ + // Cast command message pointer to more specific type to access cmd_data field + ipc_async_cmd_t * async_cmd = (ipc_async_cmd_t *) cmd; + + // Cast cmd_data field to specific type of arguments for this IPC function + gpe_get_tod_args_t * args = (gpe_get_tod_args_t *) async_cmd->cmd_data; + + // Read the TOD registers to get the TOD value. Store the result in args. + gpe_read_tod_registers(args); + + // Send back a response with IPC success even if ffdc/rc fields are non-zero + int rc = ipc_send_rsp(cmd, IPC_RC_SUCCESS); + if (rc != 0) + { + PK_TRACE("gpe_get_tod: Failed to send response back. Halting GPE0. rc=0x%08X", rc); + gpe_set_ffdc(&(args->error), 0x00, GPE_RC_IPC_SEND_FAILED, rc); + pk_halt(); + } +} diff --git a/src/occ_gpe0/ipc_func_tables.c b/src/occ_gpe0/ipc_func_tables.c index 91644c5..14166df 100644 --- a/src/occ_gpe0/ipc_func_tables.c +++ b/src/occ_gpe0/ipc_func_tables.c @@ -5,7 +5,7 @@ /* */ /* OpenPOWER OnChipController Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2015,2016 */ +/* Contributors Listed Below - COPYRIGHT 2015,2017 */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -34,6 +34,7 @@ void apss_continue_pwr_meas_read(ipc_msg_t* cmd, void* arg); void apss_complete_pwr_meas_read(ipc_msg_t* cmd, void* arg); void gpe_get_core_data(ipc_msg_t* cmd, void* arg); void gpe_get_nest_dts(ipc_msg_t* cmd, void* arg); +void gpe_get_tod(ipc_msg_t* cmd, void* arg); void ipc_scom_operation(ipc_msg_t* cmd, void* arg); void ipc_fir_collection(ipc_msg_t* cmd, void* arg); @@ -73,7 +74,7 @@ IPC_HANDLER(ipc_scom_operation, 0) // 7 - IPC_ST_SCOM_OPERATION IPC_HANDLER(gpe0_nop, 0) // 8 - IPC_ST_GPE0_NOP IPC_HANDLER(gpe_get_nest_dts, 0) // 9 - IPC_ST_GET_NEST_DTS_FUNCID IPC_HANDLER(ipc_fir_collection, 0) // 10 - IPC_ST_FIR_COLLECTION -IPC_HANDLER_DEFAULT // 11 +IPC_HANDLER(gpe_get_tod, 0) // 11 - IPC_ST_GET_TOD_FUNCID IPC_HANDLER_DEFAULT // 12 IPC_HANDLER_DEFAULT // 13 IPC_HANDLER_DEFAULT // 14 diff --git a/src/occ_gpe0/topfiles.mk b/src/occ_gpe0/topfiles.mk index 682e2d6..332a2c3 100644 --- a/src/occ_gpe0/topfiles.mk +++ b/src/occ_gpe0/topfiles.mk @@ -5,7 +5,7 @@ # # OpenPOWER OnChipController Project # -# Contributors Listed Below - COPYRIGHT 2015,2016 +# Contributors Listed Below - COPYRIGHT 2015,2017 # [+] International Business Machines Corp. # # @@ -24,7 +24,8 @@ # IBM_PROLOG_END_TAG FIRDATA_SOURCES = $(wildcard firdata/*.c) TOP-C-SOURCES = gpe0_main.c pk_app_irq_table.c ipc_func_tables.c apss_read.c \ - apss_init.c gpe_util.c core_data.c gpe_core_data.c nest_dts.c ${FIRDATA_SOURCES} + apss_init.c gpe_util.c core_data.c gpe_core_data.c nest_dts.c ${FIRDATA_SOURCES} \ + gpe_get_tod.c TOP-S-SOURCES = TOP_OBJECTS = $(TOP-C-SOURCES:.c=.o) $(TOP-S-SOURCES:.S=.o) |