summaryrefslogtreecommitdiffstats
path: root/src/occ_405/state.c
blob: 5cc0b406f6d36228fb3122642101b08e21077165 (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
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
/* IBM_PROLOG_BEGIN_TAG                                                   */
/* This is an automatically generated prolog.                             */
/*                                                                        */
/* $Source: src/occ_405/state.c $                                         */
/*                                                                        */
/* OpenPOWER OnChipController Project                                     */
/*                                                                        */
/* Contributors Listed Below - COPYRIGHT 2011,2016                        */
/* [+] 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                                                     */

#include <occ_common.h>
#include <common_types.h>
#include <centaur_data.h>
#include "ssx_io.h"
#include "trac.h"
#include "rtls.h"
#include "state.h"
#include "dcom.h"
#include "occ_service_codes.h"
#include "proc_pstate.h"
#include "cmdh_fsp_cmds_datacnfg.h"
#include "cmdh_fsp.h"
#include "proc_data.h"
// TEMP -- Doesn't exist anymore
//#include "heartbeat.h"
#include "scom.h"
#include <fir_data_collect.h>
#include <dimm.h>

extern proc_gpsm_dcm_sync_occfw_t G_proc_dcm_sync_state;
extern bool G_mem_monitoring_allowed;
extern task_t G_task_table[TASK_END];  // Global task table

// 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();

// State that OCC is currently in
OCC_STATE          G_occ_internal_state     = OCC_STATE_STANDBY;

// State that OCC is requesting that TMGT put OCC into
OCC_STATE          G_occ_internal_req_state = OCC_STATE_NOCHANGE;

// State that TMGT wants to put OCC into
OCC_STATE          G_occ_external_req_state = OCC_STATE_NOCHANGE;

// Indicates if we are currently in a state transition
bool               G_state_transition_occuring = FALSE;

// State that OCC Master is requesting
OCC_STATE          G_occ_master_state       = OCC_STATE_NOCHANGE;

// Semaphore to allow state change to be called from multiple threads
SsxSemaphore G_smgrStateChangeSem;

// Table that indicates which functions should be run for a given mode
// transition.
const smgr_state_trans_t G_smgr_state_trans[] =
{
    /* ----- SPECIFIC CASE STATE TRANSITIONS ----- */
    /* These are specific state transitions for when it matters what
     * state we were in before the transition.  These must come before
     * the agnostic state transitions below, and will be run instead of
     * 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},

    /* ----- 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_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;

// Function Specification
//
// Name: SMGR_is_mode_transitioning
//
// Description:
//
// End Function Specification
inline bool SMGR_is_state_transitioning(void)
{
   return G_state_transition_occuring;
}


// Function Specification
//
// Name:
//
// Description:
//
// End Function Specification
errlHndl_t SMGR_standby_to_observation()
{
    errlHndl_t              l_errlHndl = NULL;
    static bool l_error_logged = FALSE;  // To prevent trace and error log happened over and over

    if( SMGR_MASK_OBSERVATION_READY ==
        (SMGR_validate_get_valid_states() & SMGR_MASK_OBSERVATION_READY))
    {
        l_error_logged = FALSE;
        TRAC_IMP("SMGR: Standby to Observation Transition Started");

        memory_init();

        // Set the RTL Flags to indicate which tasks can run
        //   - Set OBSERVATION b/c we're in OBSERVATION 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_OBSERVATION;

        TRAC_IMP("SMGR: Standby to Observation Transition Completed");
    }
    else if(FALSE == l_error_logged)
    {
        l_error_logged = TRUE;
        TRAC_ERR("SMGR: Standby to Observation Transition Failed");
        /* @
         * @errortype
         * @moduleid    MAIN_STATE_TRANSITION_MID
         * @reasoncode  INTERNAL_FAILURE
         * @userdata1   none
         * @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

        // Callout firmware
        addCalloutToErrl(l_errlHndl,
                     ERRL_CALLOUT_TYPE_COMPONENT_ID,
                     ERRL_COMPONENT_ID_FIRMWARE,
                     ERRL_CALLOUT_PRIORITY_HIGH);
    }
    return l_errlHndl;
}


// Function Specification
//
// Name:
//
// Description:
//
// End Function Specification
errlHndl_t SMGR_observation_to_standby()
{
    errlHndl_t              l_errlHndl = NULL;

    TRAC_IMP("SMGR: Observation to Standby Transition Started");

    // 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);

    // Set the actual STATE now that we have finished everything else
    CURRENT_STATE() = OCC_STATE_STANDBY;

    TRAC_IMP("SMGR: Observation to Standby Transition Completed");

    return l_errlHndl;
}


// Function Specification
//
// Name:
//
// Description:
//
// End Function Specification
errlHndl_t SMGR_observation_to_active()
{
    errlHndl_t      l_errlHndl = NULL;
/* TEMP -- UNNECCESSARY IN PHASE1 */
#if 0
    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;

    // First check to make sure Pstates are enabled. If they aren't, then
    // wait TBD seconds in case we are going directly from Standby to Active
    // (pstate init only happens in observation state, so it might not be
    // done yet...must call it in this while loop since it is done in this
    // same thread...)
    //
    // 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(((DATA_get_present_cnfgdata() & SMGR_VALIDATE_DATA_ACTIVE_MASK) ==
            SMGR_VALIDATE_DATA_ACTIVE_MASK)
        && !proc_is_hwpstate_enabled() )
    {
        SsxTimebase start = ssx_timebase_get();
        while( ! proc_is_hwpstate_enabled() )
        {
            SsxInterval timeout =  SSX_SECONDS(5);
            if ((ssx_timebase_get() - start) > timeout)
            {
                if(FALSE == l_error_logged)
                {
                    TRAC_ERR("SMGR: Timeout waiting for Pstates to be enabled, master state=%d, slave state=%d, pmc_mode[%08x], chips_present[%02x], pmc_deconfig[%08x]",
                            G_proc_dcm_sync_state.sync_state_master,
                            G_proc_dcm_sync_state.sync_state_slave,
                            in32(PMC_MODE_REG),
                            G_sysConfigData.is_occ_present,
                            in32(PMC_CORE_DECONFIGURATION_REG));
                }
                l_extRc = ERC_GENERIC_TIMEOUT;
                break;
            }
            proc_gpsm_dcm_sync_enable_pstates_smh();
            ssx_sleep(SSX_MICROSECONDS(500));
        }
        if(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: 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);

        // Ensure that the dpll override (enabled when mfg biases freq) has been disabled.
        int l_core;
        uint32_t l_configured_cores;
        pcbs_pmgp1_reg_t l_pmgp1;
        l_configured_cores = ~in32(PMC_CORE_DECONFIGURATION_REG);
        for(l_core = 0; l_core < PGP_NCORES; l_core++, l_configured_cores <<= 1)
        {
            if(!(l_configured_cores & 0x80000000)) continue;
            l_pmgp1.value = 0;
            l_pmgp1.fields.dpll_freq_override_enable = 1;
            l_rc = putscom_ffdc(CORE_CHIPLET_ADDRESS(PCBS_PMGP1_REG_AND, l_core),
                           ~l_pmgp1.value, NULL); //commit errors internally
            if(l_rc)
            {
                TRAC_ERR("Failed disabling dpll frequency override.  rc=0x%08x, core=%d", l_rc, l_core);
                break;
            }
        }
        if(!l_rc)
        {

            // Set the actual STATE now that we have finished everything else
            CURRENT_STATE() = OCC_STATE_ACTIVE;
            TRAC_IMP("SMGR: Observation to Active Transition Completed");

            // Configure and enable the PCB slave heartbeat timer
            //
            // task_core_data is running in every RTL tick and scheduling a run
            // of gpe_get_per_core_data which will do a getscom on
            // PCBS_PMSTATEHISTOCC_REG.  We will use PCBS_PMSTATEHISTOCC_REG as
            // the PCBS heartbeat trigger register.
            unsigned int l_actual_pcbs_hb_time = 0;
            ChipConfigCores l_cfgd_cores =
                    (ChipConfigCores)((uint64_t)core_configuration() >> 16);
            TRAC_IMP("Configuring PCBS heartbeat for configured cores=0x%8.8x", l_cfgd_cores);
            TRAC_IMP("OCC configuration view: G_present_hw_cores=0x%8.8x, G_present_cores=0x%8.8x",
                    G_present_hw_cores, G_present_cores);

            // Setup the pcbs heartbeat timer
            l_rc = pcbs_hb_config(1, // enable = yes
                                  l_cfgd_cores,
                                  PCBS_PMSTATEHISTOCC_REG,
                                  PCBS_HEARBEAT_TIME_US,
                                  0, // force = no
                                  &l_actual_pcbs_hb_time);

            if (l_rc)
            {
                TRAC_ERR("Failure configuring the PCBS heartbeat timer, rc=%d",
                         l_rc);
                // FIXME #state_c_002 Add appropriate callouts for
                // serviceability review
                l_extRc = ERC_STATE_HEARTBEAT_CFG_FAILURE;
            }
            else
            {
                TRAC_IMP("PCBS heartbeat enabled, requested time(us)=%d, actual time(us)=%d",
                         PCBS_HEARBEAT_TIME_US,
                         l_actual_pcbs_hb_time);
            }

            // TODO: #state_c_001 Manually configuring the PMC
            // heartbeat until pmc_hb_config is shown to be working
            // Reference SW238882 for more information on updates needed in
            // pmc_hb_config.  Note that if PMC parameter hangpulse pre-divider
            // is 0 then the PMC heartbeat counter uses nest_nclck/4 instead of
            // the hangpulse to count the heartbeat timeout.
            pmc_parameter_reg0_t ppr0;
            pmc_occ_heartbeat_reg_t pohr;
            pohr.value = in32(PMC_OCC_HEARTBEAT_REG);
            ppr0.value = in32(PMC_PARAMETER_REG0);
            pohr.fields.pmc_occ_heartbeat_en = 0;
            // This combined with the hang pulse count and pre-divider yields
            // about a 2 second timeout
            pohr.fields.pmc_occ_heartbeat_time = 0xffff;
            TRAC_IMP("Configure PMC heartbeat, heartbeat_time=0x%x",
                    pohr.fields.pmc_occ_heartbeat_time);
            ppr0.fields.hangpulse_predivider = 1;
            TRAC_IMP("Configure PMC parm reg predivider=%d",
                    ppr0.fields.hangpulse_predivider);

            // Write registers twice, known issue with heartbeat reg
            out32(PMC_OCC_HEARTBEAT_REG, pohr.value);
            out32(PMC_OCC_HEARTBEAT_REG, pohr.value);
            out32(PMC_PARAMETER_REG0, ppr0.value);
            out32(PMC_PARAMETER_REG0, ppr0.value);
            TRAC_IMP("Enable PMC heartbeat timer");
            pohr.value = in32(PMC_OCC_HEARTBEAT_REG);
            pohr.fields.pmc_occ_heartbeat_en = 1;
            out32(PMC_OCC_HEARTBEAT_REG, pohr.value);
            out32(PMC_OCC_HEARTBEAT_REG, pohr.value);
        }
    }
    else
    {
        //trace and log an error.
        l_rc = -1;
    }

    if(l_rc)
    {
        TRAC_ERR("SMGR: Observation to Active Transition Failed, cnfgdata=0x%08x, reqd=0x%08x",
                DATA_get_present_cnfgdata(),
                SMGR_VALIDATE_DATA_ACTIVE_MASK);
    }


    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);
    }
#endif
    return l_errlHndl;
}


// Function Specification
//
// Name:  SMGR_active_to_observation
//
// Description:
//
// End Function Specification
errlHndl_t SMGR_active_to_observation()
{
    errlHndl_t              l_errlHndl = NULL;

    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);

    // Set the actual STATE now that we have finished everything else
    CURRENT_STATE() = OCC_STATE_OBSERVATION;

    TRAC_IMP("SMGR: Active to Observation Transition Completed");

    return l_errlHndl;
}


// Function Specification
//
// Name:  SMGR_active_to_standby
//
// Description:
//
// End Function Specification
errlHndl_t SMGR_active_to_standby()
{
    errlHndl_t              l_errlHndl = NULL;

    TRAC_IMP("SMGR: Active to Standby Transition Started");

    // Transtion through both functions on this multi-state transtion
    l_errlHndl = SMGR_active_to_observation();
    if(NULL == l_errlHndl)
    {
       l_errlHndl = SMGR_observation_to_standby();
    }

    if(l_errlHndl)
    {
        TRAC_ERR("SMGR: Active to Standby Transition Failed");
    }
    else
    {
        TRAC_IMP("SMGR: Active to Standby Transition Completed");
    }

    return l_errlHndl;
}


// Function Specification
//
// Name:  SMGR_standby_to_active
//
// Description: Makes the appropriate calls when transitioning from
//              standby to active.
//
// End Function Specification
errlHndl_t SMGR_standby_to_active()
{
    errlHndl_t              l_errlHndl = NULL;

    TRAC_IMP("SMGR: Standby to Active Transition Started");

    // Transtion through both functions on this multi-state transtion
    l_errlHndl = SMGR_standby_to_observation();
    if(NULL == l_errlHndl)
    {
       l_errlHndl = SMGR_observation_to_active();
    }

    if(l_errlHndl)
    {
        TRAC_ERR("SMGR: Standby to Active Transition Failed");
    }
    else
    {
        TRAC_IMP("SMGR: Standby to Active Transition Completed");
    }

    return l_errlHndl;
}


// Function Specification
//
// Name:  SMGR_all_to_safe
//
// Description:
//
// End Function Specification
errlHndl_t SMGR_all_to_safe()
{
    errlHndl_t              l_errlHndl = NULL;

    TRAC_IMP("SMGR: All States to Safe Transition Started");

    // If we are master, make sure we are broadcasting that the requested
    // state is "safe state"
    if (OCC_MASTER == G_occ_role)
    {
       G_occ_external_req_state = OCC_STATE_SAFE;
    }

    // If we are master, we will wait 15ms to go to full on safe mode
    // This is to give the slaves time to see that we are broadcasting
    // Safe State, and react to it.  This must be > 10ms.  It doesn't hurt
    // to do this on the slaves also.
    ssx_sleep(SSX_MILLISECONDS(15));

    // 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
    //   - Clear STANDBY b/c not in STANDBY State
    rtl_clr_run_mask_deferred(RTL_FLAG_ACTIVE | RTL_FLAG_OBS | RTL_FLAG_STANDBY);

    // Only reset task & wdt task will run from now on
    // !!! There is no recovery to this except a reset !!!
    rtl_set_run_mask_deferred(RTL_FLAG_RST_REQ);

    // Notes:
    //  - We can still talk to FSP
    //  - We will still be able to go out on PIB
    //  - We will still attempt to load an applet if told to do so
    //  - The master will no longer broadcast to slaves, and vice versa

    // Set the actual STATE now that we have finished everything else
    CURRENT_STATE() = OCC_STATE_SAFE;

    TRAC_IMP("SMGR: All States to Safe Transition Completed");

    return l_errlHndl;
}


// Function Specification
//
// Name:  SMGR_set_state
//
// Description:
//
// End Function Specification
errlHndl_t SMGR_set_state(OCC_STATE i_new_state)
{
    errlHndl_t l_transResult = NULL; //Was the transition successful?
    int jj=0;

    do
    {
        // Get lock for critical section
        if(ssx_semaphore_pend(&G_smgrStateChangeSem,SSX_WAIT_FOREVER))
        {
            /* @
             * @errortype
             * @moduleid    MAIN_STATE_TRANSITION_MID
             * @reasoncode  SSX_GENERIC_FAILURE
             * @userdata1   none
             * @userdata4   ERC_RUNNING_SEM_PENDING_FAILURE
             * @devdesc     SSX semaphore related failure
             */
            l_transResult = createErrl(MAIN_STATE_TRANSITION_MID,        //modId
                                       SSX_GENERIC_FAILURE,              //reasoncode
                                       ERC_RUNNING_SEM_PENDING_FAILURE,  //Extended reason code
                                       ERRL_SEV_UNRECOVERABLE,           //Severity
                                       NULL,                             //Trace Buf
                                       DEFAULT_TRACE_SIZE,               //Trace Size
                                       0,                                //userdata1
                                       0);                               //userdata2

            addCalloutToErrl(l_transResult,
                             ERRL_CALLOUT_TYPE_COMPONENT_ID,
                             ERRL_COMPONENT_ID_FIRMWARE,
                             ERRL_CALLOUT_PRIORITY_HIGH);

            break;
        }

        //If there is no change to the state, just exit
        if(i_new_state == OCC_STATE_NOCHANGE)
        {
            break;
        }

        // Loop through state transition table, and find the state
        // transition function that matches the transition we need to do.
        for(jj=0; jj<G_smgr_state_trans_count; jj++)
        {
            if(((G_smgr_state_trans[jj].old_state == G_occ_internal_state)
                ||
                (G_smgr_state_trans[jj].old_state == OCC_STATE_ALL))
               &&
               (G_smgr_state_trans[jj].new_state == i_new_state))
            {
                // We found the transtion that matches, now run the function
                // that is associated with that state transition.
                if(NULL != G_smgr_state_trans[jj].trans_func_ptr)
                {
                    // Signal that we are now in a state transition
                    G_state_transition_occuring = TRUE;
                    // Run transition function
                    l_transResult = (G_smgr_state_trans[jj].trans_func_ptr)();
                    // Signal that we are done with the transition
                    G_state_transition_occuring = FALSE;
                    break;
                }
            }
        }

        // Check if we hit the end of the table without finding a valid
        // state transition.  If we did, log an internal error.
        if(G_smgr_state_trans_count == jj)
        {
            TRAC_ERR("No transition (or NULL) found for the state change");
            l_transResult = NULL;
            break;
        }

        // If the state OCC requested from TMGT is the state we are now in,
        // then change the requested state to NO CHANGE.
        if(CURRENT_STATE() == REQUESTED_STATE())
        {
            REQUESTED_STATE() = OCC_STATE_NOCHANGE;
        }
    } while ( 0 );

    // Get lock for critical section
    ssx_semaphore_post(&G_smgrStateChangeSem);

    return l_transResult;
}


// Function Specification
//
// Name:  SMGR_validate_get_valid_states
//
// Description: Return a byte of status masks that correspond to the v10 poll
//              response definition status byte.
//
// End Function Specification
uint8_t SMGR_validate_get_valid_states(void)
{
    uint8_t         l_valid_states = 0;
    uint32_t        l_datamask = DATA_get_present_cnfgdata();
    static BOOLEAN  l_throttle_traced = FALSE;

    // If we have everything we need to go to observation state
    if((l_datamask & SMGR_VALIDATE_DATA_OBSERVATION_MASK) ==
            SMGR_VALIDATE_DATA_OBSERVATION_MASK)
    {
        l_valid_states |= SMGR_MASK_OBSERVATION_READY;
    }

    // If we have everything we need to go to active state
    if(((l_datamask & SMGR_VALIDATE_DATA_ACTIVE_MASK) ==
            SMGR_VALIDATE_DATA_ACTIVE_MASK) )
    {
        l_valid_states |= SMGR_MASK_ACTIVE_READY;

        if(!l_throttle_traced)
        {
            TRAC_IMP("Setting Active Bit for this OCC");
            l_throttle_traced = TRUE;
        }
    }

    // If we are master OCC, set this bit
    if(OCC_MASTER == G_occ_role)
    {
       l_valid_states |= SMGR_MASK_MASTER_OCC;
    }

    // Indicate if this OCC is the FIR master.
    if (OCC_IS_FIR_MASTER())
    {
        l_valid_states |= OCC_ROLE_FIR_MASTER_MASK;
    }

    return l_valid_states;
}

OpenPOWER on IntegriCloud