summaryrefslogtreecommitdiffstats
path: root/src/occ/pss/apss.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/occ/pss/apss.c')
-rwxr-xr-xsrc/occ/pss/apss.c911
1 files changed, 911 insertions, 0 deletions
diff --git a/src/occ/pss/apss.c b/src/occ/pss/apss.c
new file mode 100755
index 0000000..5ce452d
--- /dev/null
+++ b/src/occ/pss/apss.c
@@ -0,0 +1,911 @@
+/******************************************************************************
+// @file apss.c
+// @brief OCC APSS component
+*/
+/******************************************************************************
+ *
+ * @page ChangeLogs Change Logs
+ * @section _apss_c apss.c
+ * @verbatim
+ *
+ * Flag Def/Fea Userid Date Description
+ * ------- ---------- -------- ---------- ----------------------------------
+ * @cc000 cjcain 08/04/2011 Created
+ * @pb004 pbavari 09/02/2011 Initialize section support
+ * @01 abagepa 09/14/2011 add global for dcom component
+ * @th002 thallet 11/01/2011 Misc Changes for Nov 1st Milestone
+ * @th006 thallet 11/21/2011 RESET_REQUEST substituted for todo's
+ * @rc001 rickylie 01/10/2012 Change DEBUG_PRINTF to APSS_DBG
+ * @rc003 rickylie 02/03/2012 Verify & Clean Up OCC Headers & Comments
+ * @pb00E pbavari 03/11/2012 Added correct include file
+ * @nh001 neilhsu 05/23/2012 Add missing error log tags
+ * @at009 859308 alvinwan 10/15/2012 Added tracepp support
+ * @ly003 861535 lychen 11/19/2012 Remove APSS configuration/gathering of Altitude & Temperature
+ * @th032 thallet 04/26/2013 Tuleta HW Bringup Changes
+ * @th042 892056 thallet 07/19/2013 Make GPE arg structs non-cacheable
+ * @gm006 SW224414 milesg 09/16/2013 Reset and FFDC improvements
+ * @jh00a 909791 joshych 12/16/2013 Enhance APSS pwr meas trace
+ * @at023 910877 alvinwan 01/09/2014 Excessive fan increase requests error for mfg
+ * @fk005 911760 fmkassem 01/14/2014 APSS data collection retry support.
+ * @gm024 914291 milesg 02/10/2014 APSS data getting out of sync
+ * @gm025 915973 milesg 02/14/2014 Detect power data going to 0
+ * @gm032 918715 milesg 03/19/2014 Improved APSS recovery
+ * @gm035 921471 milesg 03/31/2014 Support retries after GPE times out
+ * @gm037 925908 milesg 05/07/2014 Redundant OCC/APSS support
+ * @gm039 922963 milesg 05/28/2014 Change redundant apss error to predictive
+ *
+ * @endverbatim
+ *
+ *///*************************************************************************/
+
+//*************************************************************************
+// Includes
+//*************************************************************************
+#include "ssx.h"
+
+#include <trac_interface.h>
+#include <apss.h>
+//@pb00Ec - changed from common.h to occ_common.h for ODE support
+#include <occ_common.h>
+#include <comp_ids.h>
+#include <pss_service_codes.h>
+#include <occ_service_codes.h> // @nh001a
+#include <trac.h>
+#include <state.h>
+#include <occ_sys_config.h> // @at023a
+#include <dcom.h> // @at023a
+#include "pss_constants.h" //gm024
+
+//*************************************************************************
+// Externs
+//*************************************************************************
+
+//*************************************************************************
+// Macros
+//*************************************************************************
+
+//*************************************************************************
+// Defines/Enums
+//*************************************************************************
+
+// threshold for calling out the redundant APSS -- gm037
+#define MAX_BACKUP_FAILURES 8
+
+// Configure both GPIOs (directoin/drive/interrupts): All Input, All 1's, No Interrupts
+const apssGpioConfigStruct_t G_gpio_config[2] = { {0x00, 0xFF, 0x00}, {0x00, 0xFF, 0x00} };
+
+// Configure streaming of: 16 ADCs, 2 GPIOs // @ly003c @at023c
+const apssCompositeConfigStruct_t G_apss_composite_config = { 16, 2 };
+
+// Power Measurements (read from APSS every RealTime loop)
+apssPwrMeasStruct_t G_apss_pwr_meas = { {0} };
+
+GPE_BUFFER(initGpioArgs_t G_gpe_apss_initialize_gpio_args);
+GPE_BUFFER(setCompositeModeArgs_t G_gpe_apss_set_composite_mode_args);
+
+uint64_t G_gpe_apss_time_start; // @jh00aa
+uint64_t G_gpe_apss_time_end; // @jh00aa
+
+// Flag for requesting APSS recovery when OCC detects all zeroes or data out of sync
+bool G_apss_recovery_requested = FALSE; //gm024
+
+//*************************************************************************
+// Structures
+//*************************************************************************
+
+
+
+GPE_BUFFER(apss_start_args_t G_gpe_start_pwr_meas_read_args);
+GPE_BUFFER(apss_continue_args_t G_gpe_continue_pwr_meas_read_args);
+GPE_BUFFER(apss_complete_args_t G_gpe_complete_pwr_meas_read_args);
+
+
+//*************************************************************************
+// Globals
+//*************************************************************************
+PoreEntryPoint GPE_apss_start_pwr_meas_read;
+PoreEntryPoint GPE_apss_continue_pwr_meas_read;
+PoreEntryPoint GPE_apss_complete_pwr_meas_read;
+
+// up/down counter for redundant apss failures -- gm037
+uint32_t G_backup_fail_count = 0;
+
+// @01a
+// used to tell slave inbox that pwr meas is complete
+volatile bool G_ApssPwrMeasCompleted = FALSE; // @th002
+
+//*************************************************************************
+// Function Prototypes
+//*************************************************************************
+
+//*************************************************************************
+// Functions
+//*************************************************************************
+
+// Function Specification
+//
+// Name: dumpHexString
+//
+// Description:
+//
+// Flow: FN=None
+//
+// End Function Specification
+#if ( (!defined(NO_TRAC_STRINGS)) && defined(TRAC_TO_SIMICS) )
+// utility function to dump hex data to screen
+void dumpHexString(const void *i_data, const unsigned int len, const char *string)
+{
+ unsigned int i, j;
+ char text[17];
+ uint8_t *data = (uint8_t*)i_data;
+ unsigned int l_len = len;
+
+ text[16] = '\0';
+ if (string != NULL)
+ {
+ printf("%s\n", string);
+ }
+
+ if (len > 0x0800) l_len = 0x800;
+ for(i = 0; i < l_len; i++)
+ {
+ if (i % 16 == 0)
+ {
+ if (i > 0) printf(" \"%s\"\n", text);
+ printf(" %04x:",i);
+ }
+ if (i % 4 == 0) printf(" ");
+
+ printf("%02x",(int)data[i]);
+ if (isprint(data[i])) text[i%16] = data[i];
+ else text[i%16] = '.';
+ }
+ if ((i%16) != 0) {
+ text[i%16] = '\0';
+ for(j = (i % 16); j < 16; ++j) {
+ printf(" ");
+ if (j % 4 == 0) printf(" ");
+ }
+ }
+ printf(" \"%s\"\n", text);
+ return;
+}
+#endif
+
+// Function Specification
+//
+// Name: do_apss_recovery
+//
+// Description: Collect FFDC and attempt recovery for APSS failures
+//
+// Flow: ??? FN= ???
+//
+// End Function Specification
+void do_apss_recovery(void) //gm037
+{
+#define PSS_START_COMMAND 0x8000000000000000ull
+#define PSS_RESET_COMMAND 0x4000000000000000ull
+ int l_scom_rc = 0;
+ uint32_t l_scom_addr;
+ uint64_t l_spi_adc_ctrl0;
+ uint64_t l_spi_adc_ctrl1;
+ uint64_t l_spi_adc_ctrl2;
+ uint64_t l_spi_adc_status;
+ uint64_t l_spi_adc_reset;
+ uint64_t l_spi_adc_wdata;
+
+
+ TRAC_ERR("detected invalid power data[%08x%08x]",
+ (uint32_t)(G_gpe_continue_pwr_meas_read_args.meas_data[0] >> 32),
+ (uint32_t)(G_gpe_continue_pwr_meas_read_args.meas_data[0] & 0x00000000ffffffffull));
+
+ do
+ {
+ //collect SPI ADC FFDC data -- gm032
+ l_scom_addr = SPIPSS_ADC_RESET_REG;
+ l_scom_rc = _getscom(l_scom_addr, &l_spi_adc_reset, SCOM_TIMEOUT);
+ if(l_scom_rc)
+ {
+ break;
+ }
+ l_scom_addr = SPIPSS_ADC_CTRL_REG0;
+ l_scom_rc = _getscom(l_scom_addr, &l_spi_adc_ctrl0, SCOM_TIMEOUT);
+ if(l_scom_rc)
+ {
+ break;
+ }
+ l_scom_addr = SPIPSS_ADC_CTRL_REG1;
+ l_scom_rc = _getscom(l_scom_addr, &l_spi_adc_ctrl1, SCOM_TIMEOUT);
+ if(l_scom_rc)
+ {
+ break;
+ }
+ l_scom_addr = SPIPSS_ADC_CTRL_REG2;
+ l_scom_rc = _getscom(l_scom_addr, &l_spi_adc_ctrl2, SCOM_TIMEOUT);
+ if(l_scom_rc)
+ {
+ break;
+ }
+ l_scom_addr = SPIPSS_ADC_STATUS_REG;
+ l_scom_rc = _getscom(l_scom_addr, &l_spi_adc_status, SCOM_TIMEOUT);
+ if(l_scom_rc)
+ {
+ break;
+ }
+ l_scom_addr = SPIPSS_ADC_WDATA_REG;
+ l_scom_rc = _getscom(l_scom_addr, &l_spi_adc_wdata, SCOM_TIMEOUT);
+ if(l_scom_rc)
+ {
+ break;
+ }
+
+ TRAC_ERR("70000[%08x] 70001[%08x] 70002[%08x] 70003|70005[%08x] 70010[%08x]",
+ (uint32_t)(l_spi_adc_ctrl0 >> 32),
+ (uint32_t)(l_spi_adc_ctrl1 >> 32),
+ (uint32_t)(l_spi_adc_ctrl2 >> 32),
+ (uint32_t)((l_spi_adc_status >> 32) | (l_spi_adc_reset >> 48)), //stuff reset register in lower 16 bits
+ (uint32_t)(l_spi_adc_wdata >> 32));
+
+ //special error handling on OCC backup. Keep an up/down counter of
+ //fail/success and log predictive error when we reach the limit.
+ if(G_occ_role == OCC_SLAVE)
+ {
+ if(G_backup_fail_count < MAX_BACKUP_FAILURES)
+ {
+ //increment the up/down counter
+ G_backup_fail_count++;
+ }
+ else
+ {
+ //We're logging the error so stop running apss tasks
+ rtl_stop_task(TASK_ID_APSS_START);
+ rtl_stop_task(TASK_ID_APSS_CONT);
+ rtl_stop_task(TASK_ID_APSS_DONE);
+
+ TRAC_INFO("Redundant APSS has exceeded failure threshold. Logging Error");
+
+ /*
+ * @errortype
+ * @moduleid PSS_MID_DO_APSS_RECOVERY
+ * @reasoncode REDUNDANT_APSS_GPE_FAILURE
+ * @userdata1 0
+ * @userdata2 0
+ * @userdata4 OCC_NO_EXTENDED_RC
+ * @devdesc Redundant APSS failure. Power Management Redundancy Lost.
+ */
+ errlHndl_t l_err = createErrl(PSS_MID_DO_APSS_RECOVERY,
+ REDUNDANT_APSS_GPE_FAILURE,
+ OCC_NO_EXTENDED_RC,
+ ERRL_SEV_PREDICTIVE, //gm039
+ NULL,
+ DEFAULT_TRACE_SIZE,
+ 0,
+ 0);
+
+ //apss callout
+ addCalloutToErrl(l_err,
+ ERRL_CALLOUT_TYPE_HUID,
+ G_sysConfigData.apss_huid,
+ ERRL_CALLOUT_PRIORITY_HIGH);
+ //processor callout
+ addCalloutToErrl(l_err,
+ ERRL_CALLOUT_TYPE_HUID,
+ G_sysConfigData.proc_huid,
+ ERRL_CALLOUT_PRIORITY_LOW);
+ //backplane callout
+ addCalloutToErrl(l_err,
+ ERRL_CALLOUT_TYPE_HUID,
+ G_sysConfigData.backplane_huid,
+ ERRL_CALLOUT_PRIORITY_LOW);
+ //firmware callout
+ addCalloutToErrl(l_err,
+ ERRL_CALLOUT_TYPE_COMPONENT_ID,
+ ERRL_COMPONENT_ID_FIRMWARE,
+ ERRL_CALLOUT_PRIORITY_MED);
+
+ commitErrl(&l_err);
+
+ break;
+ }
+ }
+
+ TRAC_INFO("Starting APSS recovery. fail_count=%d", G_backup_fail_count);
+
+ //reset the ADC engine -- gm032
+ l_scom_addr = SPIPSS_ADC_RESET_REG;
+ l_scom_rc = _putscom(l_scom_addr, PSS_RESET_COMMAND, SCOM_TIMEOUT);
+ if(l_scom_rc)
+ {
+ break;
+ }
+
+ //zero out the reset register -- gm032
+ l_scom_rc = _putscom(l_scom_addr, 0, SCOM_TIMEOUT);
+ if(l_scom_rc)
+ {
+ break;
+ }
+
+ //attempt recovery by sending the apss
+ //command that was set up earlier by initialization GPE
+ l_scom_addr = SPIPSS_P2S_COMMAND_REG;
+ l_scom_rc = _putscom(l_scom_addr, PSS_START_COMMAND, SCOM_TIMEOUT);
+ if(l_scom_rc)
+ {
+ break;
+ }
+ }while(0);
+
+ //Just trace it if we get a scom failure trying to collect FFDC -- gm032
+ if(l_scom_rc)
+ {
+ TRAC_ERR("apss recovery scom failure. addr=0x%08x, rc=0x%08x", l_scom_addr, l_scom_rc);
+ }
+}
+
+// Note: The complete request must be global, since it must stick around until after the
+// GPE program has completed (in order to do the callback).
+PoreFlex G_meas_start_request;
+// Function Specification
+//
+// Name: task_apss_start_pwr_meas
+//
+// Description: Start the GPE program to request power measurement data from APSS
+// If previous call had failed, commit the error and request reset
+//
+// Task Flags: RTL_FLAG_MSTR, RTL_FLAG_OBS, RTL_FLAG_ACTIVE, RTL_FLAG_APSS_PRES
+//
+// Flow: 07/20/11 FN=task_apss_start_pwr_meas
+//
+// End Function Specification
+void task_apss_start_pwr_meas(struct task *i_self)
+{
+ int l_rc = 0;
+ static bool L_scheduled = FALSE;
+ static bool L_idle_traced = FALSE;
+ static bool L_ffdc_collected = FALSE;
+
+ // Create/schedule GPE_start_pwr_meas_read (non-blocking)
+ APSS_DBG("GPE_start_pwr_meas_read started\n");
+
+ do
+ {
+ if (!async_request_is_idle(&G_meas_start_request.request))
+ {
+ if (!L_idle_traced)
+ {
+ TRAC_ERR("task_apss_start_pwr_meas: request is not idle.");
+ L_idle_traced = TRUE;
+ }
+ break;
+ }
+
+ //check if we need to try recovering the apss -- gm024
+ if(G_apss_recovery_requested)
+ {
+ //do recovery then wait until next tick to do anything more.
+ do_apss_recovery();
+ break;
+ }
+
+ if (L_scheduled)
+ {
+ if ((ASYNC_REQUEST_STATE_COMPLETE != G_meas_start_request.request.completion_state) ||
+ (0 != G_gpe_start_pwr_meas_read_args.error.error))
+ {
+ //error should only be non-zero in the case where the GPE timed out waiting for
+ //the APSS master to complete the last operation. Just keep retrying until
+ //DCOM resets us due to not having valid power data.
+ TRAC_ERR("task_apss_start_pwr_meas: request is not complete or failed with an error(rc:0x%08X, ffdc:0x%08X%08X). " \
+ "CompletionState:0x%X.",
+ G_gpe_start_pwr_meas_read_args.error.rc,
+ G_gpe_start_pwr_meas_read_args.error.ffdc >> 32,
+ G_gpe_start_pwr_meas_read_args.error.ffdc,
+ G_meas_start_request.request.completion_state);
+
+ //collect FFDC and log error once.
+ if (!L_ffdc_collected)
+ {
+ errlHndl_t l_err = NULL;
+
+ /*
+ * @errortype
+ * @moduleid PSS_MID_APSS_START_MEAS
+ * @reasoncode APSS_GPE_FAILURE
+ * @userdata1 GPE returned rc code
+ * @userdata4 ERC_APSS_COMPLETE_FAILURE
+ * @devdesc Failure getting power measurement data from APSS
+ */
+ l_err = createErrl(PSS_MID_APSS_START_MEAS, // i_modId,
+ APSS_GPE_FAILURE, // i_reasonCode,
+ ERC_APSS_COMPLETE_FAILURE,
+ ERRL_SEV_INFORMATIONAL,
+ NULL,
+ DEFAULT_TRACE_SIZE,
+ G_gpe_start_pwr_meas_read_args.error.rc,
+ 0);
+
+ addUsrDtlsToErrl(l_err,
+ (uint8_t*)&G_meas_start_request.ffdc,
+ sizeof(G_meas_start_request.ffdc),
+ ERRL_STRUCT_VERSION_1,
+ ERRL_USR_DTL_BINARY_DATA);
+
+ // Commit Error
+ commitErrl(&l_err);
+
+ //Set to true so that we don't log this error again.
+ L_ffdc_collected = TRUE;
+ }
+ }
+ }
+
+ //clear these out prior to starting the GPE (GPE only sets them)
+ G_gpe_start_pwr_meas_read_args.error.error = 0;
+ G_gpe_start_pwr_meas_read_args.error.ffdc = 0;
+
+ //submit the next request
+ l_rc = pore_flex_schedule(&G_meas_start_request);
+ if (0 != l_rc)
+ {
+ errlHndl_t l_err = NULL;
+
+ TRAC_ERR("task_apss_start_pwr_meas: schedule failed w/rc=0x%08X (%d us)", l_rc,
+ (int) ((ssx_timebase_get())/(SSX_TIMEBASE_FREQUENCY_HZ/1000000)));
+
+ /*
+ * @errortype
+ * @moduleid PSS_MID_APSS_START_MEAS
+ * @reasoncode SSX_GENERIC_FAILURE
+ * @userdata1 GPE shedule returned rc code
+ * @userdata2 0
+ * @userdata4 ERC_APSS_SCHEDULE_FAILURE
+ * @devdesc task_apss_start_pwr_meas schedule failed
+ */
+ l_err = createErrl(PSS_MID_APSS_START_MEAS,
+ SSX_GENERIC_FAILURE,
+ ERC_APSS_SCHEDULE_FAILURE,
+ ERRL_SEV_PREDICTIVE,
+ NULL,
+ DEFAULT_TRACE_SIZE,
+ l_rc,
+ 0);
+
+ //Request reset since this should never happen.
+ REQUEST_RESET(l_err);
+ L_scheduled = FALSE;
+ break;
+ }
+
+ L_scheduled = TRUE;
+
+
+ }while (0);
+
+
+ APSS_DBG("GPE_start_pwr_meas_read finished w/rc=0x%08X\n", G_gpe_start_pwr_meas_read_args.error.rc);
+ APSS_DBG_HEXDUMP(&G_gpe_start_pwr_meas_read_args, sizeof(G_gpe_start_pwr_meas_read_args), "G_gpe_start_pwr_meas_read_args"); // @at009c
+ G_ApssPwrMeasCompleted = FALSE; //Will complete when 3rd task is complete.
+ G_gpe_apss_time_start = ssx_timebase_get(); // @jh00aa
+
+
+} // end task_apss_start_pwr_meas()
+
+
+// Note: The complete request must be global, since it must stick around until after the
+// GPE program has completed (in order to do the callback).
+PoreFlex G_meas_cont_request;
+// Function Specification
+//
+// Name: task_apss_continue_pwr_meas
+//
+// Description: Start GPE to collect 1st block of power measurement data and request
+// the 2nd block
+// If previous call had failed, commit the error and request reset
+//
+// Task Flags: RTL_FLAG_MSTR, RTL_FLAG_OBS, RTL_FLAG_ACTIVE, RTL_FLAG_APSS_PRES
+//
+// Flow: 07/20/11 FN=task_apss_continue_pwr_meas
+//
+// End Function Specification
+void task_apss_continue_pwr_meas(struct task *i_self)
+{
+ int l_rc = 0;
+ static bool L_scheduled = FALSE;
+ static bool L_idle_traced = FALSE;
+ static bool L_ffdc_collected = FALSE;
+
+ // Create/schedule GPE_apss_continue_pwr_meas_read (non-blocking)
+ APSS_DBG("Calling task_apss_continue_pwr_meas.\n");
+
+ do
+ {
+ if (!async_request_is_idle(&G_meas_cont_request.request))
+ {
+ if (!L_idle_traced)
+ {
+ TRAC_ERR("task_apss_continue_pwr_meas: request is not idle.");
+ L_idle_traced = TRUE;
+ }
+ break;
+ }
+
+ //Don't run anything if apss recovery is in progress - gm024
+ if(G_apss_recovery_requested)
+ {
+ break;
+ }
+
+ if (L_scheduled)
+ {
+ if ((ASYNC_REQUEST_STATE_COMPLETE != G_meas_cont_request.request.completion_state) ||
+ (0 != G_gpe_continue_pwr_meas_read_args.error.error))
+ {
+ //error should only be non-zero in the case where the GPE timed out waiting for
+ //the APSS master to complete the last operation. Just keep retrying until
+ //DCOM resets us due to not having valid power data.
+ TRAC_ERR("task_apss_continue_pwr_meas: request is not complete or failed with an error(rc:0x%08X, ffdc:0x%08X%08X). " \
+ "CompletionState:0x%X.",
+ G_gpe_continue_pwr_meas_read_args.error.rc,
+ G_gpe_continue_pwr_meas_read_args.error.ffdc >> 32,
+ G_gpe_continue_pwr_meas_read_args.error.ffdc,
+ G_meas_cont_request.request.completion_state);
+
+
+ //collect FFDC and log error once.
+ if (!L_ffdc_collected)
+ {
+ errlHndl_t l_err = NULL;
+
+ /*
+ * @errortype
+ * @moduleid PSS_MID_APSS_CONT_MEAS
+ * @reasoncode APSS_GPE_FAILURE
+ * @userdata1 GPE returned rc code
+ * @userdata2 0
+ * @userdata4 ERC_APSS_COMPLETE_FAILURE
+ * @devdesc Failure getting power measurement data from APSS
+ */
+ l_err = createErrl(PSS_MID_APSS_CONT_MEAS, // i_modId,
+ APSS_GPE_FAILURE, // i_reasonCode,
+ ERC_APSS_COMPLETE_FAILURE,
+ ERRL_SEV_INFORMATIONAL,
+ NULL,
+ DEFAULT_TRACE_SIZE,
+ G_gpe_continue_pwr_meas_read_args.error.rc,
+ 0);
+
+ addUsrDtlsToErrl(l_err,
+ (uint8_t*)&G_meas_cont_request.ffdc,
+ sizeof(G_meas_cont_request.ffdc),
+ ERRL_STRUCT_VERSION_1,
+ ERRL_USR_DTL_BINARY_DATA);
+
+ // Commit Error
+ commitErrl(&l_err);
+
+ //Set to true so that we don't log this error again.
+ L_ffdc_collected = TRUE;
+ }
+ }
+ }
+
+ //clear these out prior to starting the GPE (GPE only sets them)
+ G_gpe_continue_pwr_meas_read_args.error.error = 0;
+ G_gpe_continue_pwr_meas_read_args.error.ffdc = 0;
+
+ //submit the next request
+ l_rc = pore_flex_schedule(&G_meas_cont_request);
+ if (0 != l_rc)
+ {
+ errlHndl_t l_err = NULL;
+
+ TRAC_ERR("task_apss_cont_pwr_meas: schedule failed w/rc=0x%08X (%d us)", l_rc,
+ (int) ((ssx_timebase_get())/(SSX_TIMEBASE_FREQUENCY_HZ/1000000)));
+
+ /*
+ * @errortype
+ * @moduleid PSS_MID_APSS_CONT_MEAS
+ * @reasoncode SSX_GENERIC_FAILURE
+ * @userdata1 GPE shedule returned rc code
+ * @userdata2 0
+ * @userdata4 ERC_APSS_SCHEDULE_FAILURE
+ * @devdesc task_apss_continue_pwr_meas schedule failed
+ */
+ l_err = createErrl(PSS_MID_APSS_CONT_MEAS,
+ SSX_GENERIC_FAILURE,
+ ERC_APSS_SCHEDULE_FAILURE,
+ ERRL_SEV_PREDICTIVE,
+ NULL,
+ DEFAULT_TRACE_SIZE,
+ l_rc,
+ 0);
+
+ //Request reset since this should never happen.
+ REQUEST_RESET(l_err);
+ L_scheduled = FALSE;
+ break;
+ }
+
+ L_scheduled = TRUE;
+
+
+ }while (0);
+
+ APSS_DBG("task_apss_continue_pwr_meas: finished w/rc=0x%08X\n", G_gpe_continue_pwr_meas_read_args.error.rc);
+ APSS_DBG_HEXDUMP(&G_gpe_continue_pwr_meas_read_args, sizeof(G_gpe_continue_pwr_meas_read_args), "G_gpe_continue_pwr_meas_read_args");
+
+} // end task_apss_continue_pwr_meas
+
+
+// Function Specification
+//
+// Name: reformat_meas_data
+//
+// Description: Extract measurement from GPE programs into G_apss_pwr_meas structure
+// This function is called when the GPE completes the final measurement
+// collection for this loop.
+//
+// Flow: FN=None
+//
+// End Function Specification
+#define APSS_ADC_SEQ_MASK 0xf000f000f000f000ull
+#define APSS_ADC_SEQ_CHECK 0x0000100020003000ull
+void reformat_meas_data()
+{
+ APSS_DBG("GPE_complete_pwr_meas_read finished w/rc=0x%08X\n", G_gpe_complete_pwr_meas_read_args.error.rc);
+ APSS_DBG_HEXDUMP(&G_gpe_complete_pwr_meas_read_args, sizeof(G_gpe_complete_pwr_meas_read_args), "G_gpe_complete_pwr_meas_read_args"); // @at009c
+
+ do
+ {
+ // Make sure complete was successful
+ if (G_gpe_complete_pwr_meas_read_args.error.error)
+ {
+ break;
+ }
+
+ // Check that the first 4 sequence nibbles are 0, 1, 2, 3 in the ADC data
+ if (((G_gpe_continue_pwr_meas_read_args.meas_data[0] & APSS_ADC_SEQ_MASK) != APSS_ADC_SEQ_CHECK) ||
+ !(G_gpe_continue_pwr_meas_read_args.meas_data[0] & ~APSS_ADC_SEQ_MASK)) //gm025
+ {
+ //recovery will begin on the next tick
+ G_apss_recovery_requested = TRUE;
+ break;
+ }
+
+ //decrement up/down fail counter for backup on success.
+ if(G_backup_fail_count)
+ {
+ G_backup_fail_count--;
+ }
+
+ //Don't do the copy unless this is the master OCC -- gm037
+ if(G_occ_role == OCC_MASTER)
+ {
+
+ //fail every 16 seconds
+ //if(!(CURRENT_TICK & 0x0000ffff))
+ //{
+ // G_apss_recovery_requested = TRUE;
+ //}
+
+ APSS_DBG("Populate meas data:\n");
+#if 0
+ APSS_DBG_HEXDUMP(G_gpe_continue_pwr_meas_read_args.meas_data, sizeof(G_gpe_continue_pwr_meas_read_args.meas_data), "G_gpe_continue_pwr_meas_read_args.meas_data"); // @at009c
+ APSS_DBG_HEXDUMP(G_gpe_complete_pwr_meas_read_args.meas_data, sizeof(G_gpe_complete_pwr_meas_read_args.meas_data), "G_gpe_complete_pwr_meas_read_args.meas_data"); // @at009c
+#endif
+
+ // Merge continue/complete data into a single buffer
+ const uint16_t l_continue_meas_length = sizeof(G_gpe_continue_pwr_meas_read_args.meas_data);
+ const uint16_t l_complete_meas_length = sizeof(G_gpe_complete_pwr_meas_read_args.meas_data);
+ uint8_t l_buffer[l_continue_meas_length+l_complete_meas_length];
+ memcpy(&l_buffer[ 0], G_gpe_continue_pwr_meas_read_args.meas_data, l_continue_meas_length);
+ memcpy(&l_buffer[l_continue_meas_length], G_gpe_complete_pwr_meas_read_args.meas_data, l_complete_meas_length);
+ APSS_DBG_HEXDUMP(l_buffer, sizeof(l_buffer), "l_buffer"); // @at009c
+
+ // Copy measurements into correct struction locations (based on composite config)
+ uint16_t l_index = 0;
+ memcpy(G_apss_pwr_meas.adc, &l_buffer[l_index], (G_apss_composite_config.numAdcChannelsToRead * 2));
+ l_index += (G_apss_composite_config.numAdcChannelsToRead * 2);
+ memcpy(G_apss_pwr_meas.gpio, &l_buffer[l_index], (G_apss_composite_config.numGpioPortsToRead * 2));
+ // TOD is always located at same offset
+ memcpy(&G_apss_pwr_meas.tod, &l_buffer[l_continue_meas_length+l_complete_meas_length-8], 8);
+
+ APSS_DBG("...into structure: (%d ADC, %d GPIO)\n", G_apss_composite_config.numAdcChannelsToRead,
+ G_apss_composite_config.numGpioPortsToRead); // @ly003c
+ APSS_DBG_HEXDUMP(&G_apss_pwr_meas, sizeof(G_apss_pwr_meas), "G_apss_pwr_meas"); // @at009c
+ }
+
+ // mark apss pwr meas completed and valid
+ G_ApssPwrMeasCompleted = TRUE; // @th002
+ G_gpe_apss_time_end = ssx_timebase_get(); // @jh00aa
+ APSS_DBG("APSS Completed - %d\n",(int) ssx_timebase_get());
+ }while(0);
+}
+
+
+// Note: The complete request must be global, since it must stick around until after the
+// GPE program has completed (in order to do the callback).
+PoreFlex G_meas_complete_request;
+
+// Function Specification
+//
+// Name: task_apss_complete_pwr_meas
+//
+// Description: Start GPE to collect 2nd block of power measurement data and TOD.
+// If previous call had failed, commit the error and request reset
+//
+// Flow: 07/20/11 FN=task_apss_complete_pwr_meas
+//
+// Task Flags: RTL_FLAG_MSTR, RTL_FLAG_OBS, RTL_FLAG_ACTIVE, RTL_FLAG_APSS_PRES
+//
+// End Function Specification
+void task_apss_complete_pwr_meas(struct task *i_self)
+{
+ int l_rc = 0;
+ static bool L_scheduled = FALSE;
+ static bool L_idle_traced = FALSE;
+ static bool L_ffdc_collected = FALSE;
+
+ // Create/schedule GPE_apss_complete_pwr_meas_read (non-blocking)
+ APSS_DBG("Calling task_apss_complete_pwr_meas.\n");
+
+ do
+ {
+ if (!async_request_is_idle(&G_meas_complete_request.request))
+ {
+ if (!L_idle_traced)
+ {
+ TRAC_ERR("task_apss_complete_pwr_meas: request is not idle.");
+ L_idle_traced = TRUE;
+ }
+ break;
+ }
+
+ if(G_apss_recovery_requested) //gm024
+ {
+ //allow apss measurement to proceed on next tick
+ G_apss_recovery_requested = FALSE;
+ break;
+ }
+
+
+ if (L_scheduled)
+ {
+ if ((ASYNC_REQUEST_STATE_COMPLETE != G_meas_complete_request.request.completion_state) ||
+ (0 != G_gpe_complete_pwr_meas_read_args.error.error))
+ {
+ //error should only be non-zero in the case where the GPE timed out waiting for
+ //the APSS master to complete the last operation. Just keep retrying until
+ //DCOM resets us due to not having valid power data.
+ TRAC_ERR("task_apss_complete_pwr_meas: request is not complete or failed with an error(rc:0x%08X, ffdc:0x%08X%08X). " \
+ "CompletionState:0x%X.",
+ G_gpe_complete_pwr_meas_read_args.error.rc,
+ G_gpe_complete_pwr_meas_read_args.error.ffdc >> 32,
+ G_gpe_complete_pwr_meas_read_args.error.ffdc,
+ G_meas_complete_request.request.completion_state);
+
+ //collect FFDC and log error once.
+ if (!L_ffdc_collected)
+ {
+ errlHndl_t l_err = NULL;
+
+ /*
+ * @errortype
+ * @moduleid PSS_MID_APSS_COMPLETE_MEAS
+ * @reasoncode APSS_GPE_FAILURE
+ * @userdata1 GPE returned rc code
+ * @userdata2 0
+ * @userdata4 ERC_APSS_COMPLETE_FAILURE
+ * @devdesc Failure getting power measurement data from APSS
+ */
+ l_err = createErrl(PSS_MID_APSS_COMPLETE_MEAS, // i_modId,
+ APSS_GPE_FAILURE, // i_reasonCode,
+ ERC_APSS_COMPLETE_FAILURE,
+ ERRL_SEV_INFORMATIONAL,
+ NULL,
+ DEFAULT_TRACE_SIZE,
+ G_gpe_complete_pwr_meas_read_args.error.rc,
+ 0);
+
+ addUsrDtlsToErrl(l_err,
+ (uint8_t*)&G_meas_complete_request.ffdc,
+ sizeof(G_meas_complete_request.ffdc),
+ ERRL_STRUCT_VERSION_1,
+ ERRL_USR_DTL_BINARY_DATA);
+
+ // Commit Error
+ commitErrl(&l_err);
+
+ //Set to true so that we don't log this error again.
+ L_ffdc_collected = TRUE;
+ }
+ }
+ }
+
+ //clear these out prior to starting the GPE (GPE only sets them)
+ G_gpe_complete_pwr_meas_read_args.error.error = 0;
+ G_gpe_complete_pwr_meas_read_args.error.ffdc = 0;
+
+ //submit the next request
+ l_rc = pore_flex_schedule(&G_meas_complete_request);
+ if (0 != l_rc)
+ {
+ errlHndl_t l_err = NULL;
+
+ TRAC_ERR("task_apss_complete_pwr_meas: schedule failed w/rc=0x%08X (%d us)", l_rc,
+ (int) ((ssx_timebase_get())/(SSX_TIMEBASE_FREQUENCY_HZ/1000000)));
+
+ /*
+ * @errortype
+ * @moduleid PSS_MID_APSS_COMPLETE_MEAS
+ * @reasoncode SSX_GENERIC_FAILURE
+ * @userdata1 GPE shedule returned rc code
+ * @userdata2 0
+ * @userdata4 ERC_APSS_SCHEDULE_FAILURE
+ * @devdesc task_apss_complete_pwr_meas schedule failed
+ */
+ l_err = createErrl(PSS_MID_APSS_COMPLETE_MEAS,
+ SSX_GENERIC_FAILURE,
+ ERC_APSS_SCHEDULE_FAILURE,
+ ERRL_SEV_PREDICTIVE,
+ NULL,
+ DEFAULT_TRACE_SIZE,
+ l_rc,
+ 0);
+
+ //Request reset since this should never happen.
+ REQUEST_RESET(l_err);
+ L_scheduled = FALSE;
+ break;
+ }
+
+ L_scheduled = TRUE;
+
+
+ }while (0);
+
+ APSS_DBG("task_apss_complete_pwr_meas: finished w/rc=0x%08X\n", G_gpe_complete_pwr_meas_read_args.error.rc);
+ APSS_DBG_HEXDUMP(&G_gpe_complete_pwr_meas_read_args, sizeof(G_gpe_complete_pwr_meas_read_args), "G_gpe_complete_pwr_meas_read_args");
+
+
+} // end task_apss_complete_pwr_meas
+
+// @at023a - start
+bool apss_gpio_get(uint8_t i_pin_number, uint8_t *o_pin_value)
+{
+ bool l_valid = FALSE;
+
+ if( (i_pin_number != SYSCFG_INVALID_PIN) && (o_pin_value != NULL) )
+ {
+ // Check if G_dcom_slv_inbox_rx is valid.
+ // The default value is all 0, so check if it's no-zero
+ bool l_dcom_data_valid = FALSE;
+ int i=0;
+ for(;i<sizeof(G_dcom_slv_inbox_rx);i++)
+ {
+ if( ((char*)&G_dcom_slv_inbox_rx)[i] != 0 )
+ {
+ l_dcom_data_valid = TRUE;
+ break;
+ }
+ }
+
+ if( l_dcom_data_valid == TRUE)
+ {
+ uint8_t l_gpio_port = i_pin_number/NUM_OF_APSS_PINS_PER_GPIO_PORT;
+ uint8_t l_gpio_mask = 0x1 << i_pin_number % NUM_OF_APSS_PINS_PER_GPIO_PORT;
+ l_valid = TRUE;
+ if( G_dcom_slv_inbox_rx.gpio[l_gpio_port] & l_gpio_mask )
+ {
+ *o_pin_value = 1;
+ }
+ else
+ {
+ *o_pin_value = 0;
+ }
+ }
+ }
+ return l_valid;
+}
+// @at023a - end
OpenPOWER on IntegriCloud