summaryrefslogtreecommitdiffstats
path: root/src/occ/amec/amec_sensors_fw.c
blob: 2967b5170c3587898359b86c7a4046b31feec97f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
// @file amec_sensors_fw.c
// @brief AMEC FW Sensor Calculations
/**
 *      @page ChangeLogs Change Logs
 *      @section _amec_sensors_power_c amec_sensors_power.c
 *      @verbatim
 *      
 *   Flag     Def/Fea    Userid    Date      Description
 *   -------- ---------- --------  --------  --------------------------------------
 *   @th00b              thallet   02/24/2012  New file
 *   @pb00E              pbavari   03/11/2012  Added correct include file
 *   @nh001              neilhsu   05/23/2012  Add missing error log tags 
 *   @gm008  SW226989    milesg    09/30/2013  Sapphire initial support
 *   @gm030    917444    milesg    03/06/2014  Add FFDC for GPE jobs timing out
 *
 *  @endverbatim
 */

/******************************************************************************/
/* Includes                                                                   */
/******************************************************************************/
//@pb00Ec - changed from common.h to occ_common.h for ODE support
#include <occ_common.h>
#include <ssx.h>         
#include <errl.h>               // Error logging
#include "sensor.h"
#include "rtls.h"
#include "occ_sys_config.h"
#include "occ_service_codes.h"  // for SSX_GENERIC_FAILURE
#include "dcom.h"
#include "proc_data.h"
#include "amec_smh.h"
#include "amec_slave_smh.h"
#include <trac.h>
#include "amec_sys.h"
#include "sensor_enum.h"
#include "amec_service_codes.h"
#include <amec_sensors_fw.h>


// Function Specification
//
// Name: amec_slv_update_smh_sensors
//
// Description: Update FW Sensors with Amec Slave Timings.
//
// Flow:              FN= None
//
// End Function Specification
void amec_slv_update_smh_sensors(int i_smh_state, uint32_t i_duration)
{
    // Update the duration in the fw timing table
    G_fw_timing.amess_state = i_smh_state;
    G_fw_timing.amess_dur   = i_duration;
}


// Function Specification
//
// Name: amec_slv_update_gpe_sensors
//
// Description: Update FW Sensors with GPE Engine Timings.  Called from
//              callback on GPE routine completion.
//
// Flow:              FN= None
//
// End Function Specification
void amec_slv_update_gpe_sensors(uint8_t i_gpe_engine)
{
    // Update the duration in the fw timing table
    G_fw_timing.gpe_dur[i_gpe_engine] = DURATION_IN_US_UNTIL_NOW_FROM(G_fw_timing.rtl_start_gpe);
}


// Function Specification
//
// Name: amec_update_fw_sensors  
//
// Description: Updates sensors related to the OCC FW Timings
//              
//
// Flow: 02/01/2012   FN= amec_update_fw_sensors
//
// Thread: RealTime Loop
//
// Task Flags: 
//
// End Function Specification
#define MAX_CONSEC_TRACE 4
void amec_update_fw_sensors(void)
{
    errlHndl_t l_err                = NULL;
    int rc                          = 0; 
    int rc2                         = 0;
    static bool l_first_call        = TRUE;
    bool l_gpe0_idle, l_gpe1_idle;       //gm030
    static int L_consec_trace_count = 0; //gm030

    // ------------------------------------------------------
    // Update OCC Firmware Sensors from last tick
    // ------------------------------------------------------
    int l_last_state = G_fw_timing.amess_state;
    // RTLtickdur    = duration of last tick's RTL ISR (max = 250us)
    sensor_update( AMECSENSOR_PTR(RTLtickdur),                     G_fw_timing.rtl_dur);
    // AMEintdur     = duration of last tick's AMEC portion of RTL ISR
    sensor_update( AMECSENSOR_PTR(AMEintdur),                      G_fw_timing.ameint_dur);
    // AMESSdurX     = duration of last tick's AMEC state
    if(l_last_state >= NUM_AMEC_SMH_STATES)
    {
        // Sanity check.  Trace this out, even though it should never happen.
        TRAC_INFO("AMEC State Invalid, Sensor Not Updated");
    }
    else
    {
        // AMESSdurX     = duration of last tick's AMEC state
        sensor_update( AMECSENSOR_ARRAY_PTR(AMESSdur0, l_last_state),  G_fw_timing.amess_dur);
    }

    // ------------------------------------------------------
    // Kick off GPE programs to track WorstCase time in GPE
    // and update the sensors.
    // ------------------------------------------------------
    if( (NULL != G_fw_timing.gpe0_timing_request)
        && (NULL != G_fw_timing.gpe1_timing_request) )
    {
        //Check if both GPE engines were able to complete the last GPE job on the queue
        //within 1 tick.
        l_gpe0_idle = async_request_is_idle(&G_fw_timing.gpe0_timing_request->request); //gm030
        l_gpe1_idle = async_request_is_idle(&G_fw_timing.gpe1_timing_request->request); //gm030
        if(l_gpe0_idle && l_gpe1_idle)
        {
            //reset the consecutive trace count
            L_consec_trace_count = 0;

            //Both GPE engines finished on time.  Now check if they were successful too.
            if( async_request_completed(&(G_fw_timing.gpe0_timing_request->request))
                && async_request_completed(&(G_fw_timing.gpe1_timing_request->request)) )
            {
                // GPEtickdur0     = duration of last tick's PORE-GPE0 duration
                sensor_update( AMECSENSOR_PTR(GPEtickdur0), G_fw_timing.gpe_dur[0]);
                // GPEtickdur1     = duration of last tick's PORE-GPE1 duration
                sensor_update( AMECSENSOR_PTR(GPEtickdur1), G_fw_timing.gpe_dur[1]);
            }
            else
            {
                //This case is expected on the first call of the function.  After that,
                //this should not happen.
                if(!l_first_call) //@gm008
                {
                    //Note: FFDC for this case is gathered by each task responsible for
                    //      a GPE job.
                    TRAC_INFO("GPE task idle but GPE task did not complete");
                }
                l_first_call = FALSE;
            }  
  
            // Update Time used to measure GPE duration.
            G_fw_timing.rtl_start_gpe = G_fw_timing.rtl_start;
      
            // Schedule the GPE Routines that will run and update the worst
            // case timings (via callback) after they complete.  These GPE
            // routines are the last GPE routines added to the queue
            // during the RTL tick.
            rc  = pore_flex_schedule(G_fw_timing.gpe0_timing_request);
            rc2 = pore_flex_schedule(G_fw_timing.gpe1_timing_request);
    
            if(rc || rc2)
            {
                /* @
                 * @errortype
                 * @moduleid    AMEC_UPDATE_FW_SENSORS
                 * @reasoncode  SSX_GENERIC_FAILURE
                 * @userdata1   return code - gpe0
                 * @userdata2   return code - gpe1
                 * @userdata4   OCC_NO_EXTENDED_RC
                 * @devdesc     Failure to schedule PORE-GPE poreFlex object for FW timing
                 *              analysis. 
                 */
                l_err = createErrl(
                    AMEC_UPDATE_FW_SENSORS,             //modId
                    SSX_GENERIC_FAILURE,                //reasoncode
                    OCC_NO_EXTENDED_RC,                 //Extended reason code
                    ERRL_SEV_INFORMATIONAL,             //Severity
                    NULL,                               //Trace Buf
                    DEFAULT_TRACE_SIZE,                 //Trace Size
                    rc,                                 //userdata1
                    rc2);                               //userdata2
  
                // commit error log
                commitErrl( &l_err );
            }
        }
        else if(L_consec_trace_count < MAX_CONSEC_TRACE) //gm030
        {
            uint64_t l_dbg1;

            // gm030
            // Reset will eventually be requested due to not having power measurement
            // data after X ticks, but add some additional FFDC to the trace that
            // will tell us what GPE job is currently executing.
            if(!l_gpe0_idle)
            {
                l_dbg1 = in64(PORE_GPE0_DBG1);
                TRAC_ERR("GPE0 programs did not complete within one tick. DBG1[0x%08x%08x]",
                          l_dbg1 >> 32, 
                          l_dbg1 & 0x00000000ffffffffull);
            }
            if(!l_gpe1_idle)
            {
                l_dbg1 = in64(PORE_GPE1_DBG1);
                TRAC_ERR("GPE1 programs did not complete within one tick. DBG1[0x%08x%08x]",
                          l_dbg1 >> 32, 
                          l_dbg1 & 0x00000000ffffffffull);
            }
            L_consec_trace_count++;
        }
    }
}



OpenPOWER on IntegriCloud