diff options
author | Matt Ploetz <maploetz@us.ibm.com> | 2013-09-24 11:03:02 -0500 |
---|---|---|
committer | A. Patrick Williams III <iawillia@us.ibm.com> | 2013-10-12 14:51:14 -0500 |
commit | 4e536844c21b0ab7c256e49c63e8e9520c9e1d19 (patch) | |
tree | 03fa743c3e3f5c00cf1d44a936a3c92c7673b48c /src/usr/initservice | |
parent | effbdc22da60af7ae67f69005f63a6a6e4db773d (diff) | |
download | talos-hostboot-4e536844c21b0ab7c256e49c63e8e9520c9e1d19.tar.gz talos-hostboot-4e536844c21b0ab7c256e49c63e8e9520c9e1d19.zip |
Hardware Reconfigure loop and Istepdispatcher redesign
Change-Id: Icc037be6b0eac67d1b5196180f8a53f083afa085
RTC: 34055
Reviewed-on: http://gfw160.austin.ibm.com:8080/gerrit/6324
Tested-by: Jenkins Server
Reviewed-by: A. Patrick Williams III <iawillia@us.ibm.com>
Diffstat (limited to 'src/usr/initservice')
-rw-r--r-- | src/usr/initservice/istepdispatcher/istepWorker.C | 572 | ||||
-rw-r--r-- | src/usr/initservice/istepdispatcher/istepWorker.H | 81 | ||||
-rw-r--r-- | src/usr/initservice/istepdispatcher/istep_mbox_msgs.H | 24 | ||||
-rw-r--r-- | src/usr/initservice/istepdispatcher/istepdispatcher.C | 1548 | ||||
-rw-r--r-- | src/usr/initservice/istepdispatcher/istepdispatcher.H | 325 | ||||
-rw-r--r-- | src/usr/initservice/istepdispatcher/makefile | 2 |
6 files changed, 948 insertions, 1604 deletions
diff --git a/src/usr/initservice/istepdispatcher/istepWorker.C b/src/usr/initservice/istepdispatcher/istepWorker.C deleted file mode 100644 index f14651e41..000000000 --- a/src/usr/initservice/istepdispatcher/istepWorker.C +++ /dev/null @@ -1,572 +0,0 @@ -/* IBM_PROLOG_BEGIN_TAG */ -/* This is an automatically generated prolog. */ -/* */ -/* $Source: src/usr/initservice/istepdispatcher/istepWorker.C $ */ -/* */ -/* IBM CONFIDENTIAL */ -/* */ -/* COPYRIGHT International Business Machines Corp. 2012,2013 */ -/* */ -/* p1 */ -/* */ -/* Object Code Only (OCO) source materials */ -/* Licensed Internal Code Source Materials */ -/* IBM HostBoot Licensed Internal Code */ -/* */ -/* The source code for this program is not published or otherwise */ -/* divested of its trade secrets, irrespective of what has been */ -/* deposited with the U.S. Copyright Office. */ -/* */ -/* Origin: 30 */ -/* */ -/* IBM_PROLOG_END_TAG */ -/** - * @file istepWorker.C - * - * IStep Dispatcher worker thread. - * - */ - -/******************************************************************************/ -// Includes -/******************************************************************************/ -#include <stdint.h> -#include <stdio.h> -#include <string.h> - -#include <sys/msg.h> -#include <vfs/vfs.H> - -#include <errl/errlentry.H> - -#include <isteps/istepmasterlist.H> -#include <hwpf/istepreasoncodes.H> -#include <hwas/common/deconfigGard.H> -#include <hwas/hwasPlat.H> - -#include "../baseinitsvc/initservice.H" - -#include <diag/attn/attn.H> - -//#include <initservice/initsvcudistep.H> // InitSvcUserDetailsIstep - -#include <targeting/attrsync.H> - -#include <targeting/common/attributes.H> - -#include <fapiAttributeService.H> - -#include "istep_mbox_msgs.H" -#include "istepWorker.H" -#include "istepdispatcher.H" - -// ----- namespace INITSERVICE ------------------------------------------- -namespace INITSERVICE -{ -/******************************************************************************/ -// Globals/Constants -/******************************************************************************/ -extern trace_desc_t *g_trac_initsvc; - -bool getSyncEnabledAttribute(); -void loadModules( uint32_t istep ); -void unLoadModules( uint32_t istep ); - -// ---------------------------------------------------------------------------- -// startIStepWorkerThread -// ---------------------------------------------------------------------------- -void* startIStepWorkerThread ( void * io_args ) -{ - TRACFCOMP( g_trac_initsvc, - ENTER_MRK"startIStepWorkerThread()" ); - - // detach from main istep dispatcher thread - task_detach(); - - // Worker thread entry - iStepWorkerThread( io_args ); - - TRACDCOMP( g_trac_initsvc, - EXIT_MRK"startIStepWorkerThread()" ); - - // Shutdown. - return NULL; -} - - -// ---------------------------------------------------------------------------- -// iStepWorkerThread() -// ---------------------------------------------------------------------------- -void iStepWorkerThread ( void * i_msgQ ) -{ - errlHndl_t err = NULL; - msg_q_t theQ = static_cast<msg_q_t>( i_msgQ ); - msg_t * theMsg = NULL; - uint32_t istep = 0x0; - uint32_t substep = 0x0; - uint32_t prevStep = 0x0; - uint64_t progressCode = 0x0; - bool first = true; - - TRACDCOMP( g_trac_initsvc, - ENTER_MRK"iStepWorkerThread()" ); - - // cache the value, it wont change during ipl. - bool step_mode = IStepDispatcher::getTheInstance().getIStepMode(); - - while( 1 ) - { - // Send More Work Needed msg to the main thread. - theMsg = msg_allocate(); - theMsg->type = MORE_WORK_NEEDED; - theMsg->data[0] = first ? 1 : 0x0; - if ( err ) - { - // The size of the errorlog (data[1]) is intentionally left at 0; - // the main thread will commit this errorlog. We do not really - // need to send the size of the errorlog. - theMsg->data[1] = 0; - TRACFCOMP( g_trac_initsvc, - "istepWorker: send errlog back to main, PLID = 0x%x", - err->plid() ); - } - - theMsg->extra_data = err; - err = NULL; - TRACDCOMP( g_trac_initsvc, - INFO_MRK"istepWorker: sendmsg t=0x%08x, d0=0x%016x, d1=0x%016x, x=%p", - theMsg->type, - theMsg->data[0], - theMsg->data[1], - theMsg->extra_data ); - - // Wait here until the main thread has work for us. - msg_sendrecv( theQ, - theMsg ); - - TRACDCOMP( g_trac_initsvc, - INFO_MRK"istepWorker: rcvmsg t=0x%08x, d0=0x%016x, d1=0x%016x, x=%p", - theMsg->type, - theMsg->data[0], - theMsg->data[1], - theMsg->extra_data ); - - first = false; - - // Got a response... The step/substep to execute are in data[0] - istep = ((theMsg->data[0] & 0xFF00) >> 8); - substep = (theMsg->data[0] & 0xFF); - - - // Get the Task Info for this step - const TaskInfo * theStep = findTaskInfo( istep, - substep ); - - if( NULL != theStep ) - { - TRACFCOMP( g_trac_initsvc, - "IStepDispatcher (worker): " - "Run Istep (%d), substep(%d), - %s", - istep, substep, theStep->taskname ); - - // Post the Progress Code - InitService::getTheInstance().setProgressCode( progressCode ); - - if( prevStep != istep ) - { - // unload the modules from the previous step - unLoadModules( prevStep ); - // load modules for this step - loadModules( istep ); - prevStep = istep; - } - - err = InitService::getTheInstance().executeFn( theStep, - NULL ); - - // flush contTrace immediately after each istep/substep returns - TRAC_FLUSH_BUFFERS(); - - // sync the attributes to fsp in single step mode but only - // after step 6 is complete to allow discoverTargets() to - // run before the sync is done. - if( step_mode && istep > 6 ) - { - // this value can change between steps, so read now - if( getSyncEnabledAttribute() ) - { - TRACFCOMP( g_trac_initsvc, "sync attributes to FSP"); - - errlHndl_t l_errl = TARGETING::syncAllAttributesToFsp(); - - if(l_errl) - { - TRACFCOMP(g_trac_initsvc, - "Attribute sync between steps failed" - "see %x for details", - l_errl->eid()); - - errlCommit(l_errl, INITSVC_COMP_ID); - } - } - } - - bool callouts = false; - // check to see if there were any deferred deconfigure callouts - // IF there wasn't a PLD detected. - if (HWAS::hwasPLDDetection()) - { - TRACFCOMP(g_trac_initsvc, - "hwasPLDDetection return true - clear deconfig records"); - HWAS::theDeconfigGard().clearDeconfigureRecords(NULL); - } - else - { - // call HWAS to have this processed - callouts = HWAS::processDeferredDeconfig(); - } - - // force a TI if there were callouts - if (callouts) - { - TRACFCOMP(g_trac_initsvc, - INFO_MRK"HWAS has deferred deconfigs!"); - - // we are going to return an errl so that we TI - // but if there is an error already (and it's very likely, - // since that's how deconfigure callouts happen) we want - // go send that one along - if (err) - { - TRACFCOMP( g_trac_initsvc, - "istepDispatcher, committing errorlog, PLID = 0x%x", - err->plid() ); - errlCommit( err, INITSVC_COMP_ID ); - // err is now NULL - } - - /*@ - * @errortype - * @reasoncode ISTEP_DELAYED_DECONFIG - * @severity ERRORLOG::ERRL_SEV_UNRECOVERABLE - * @moduleid ISTEP_INITSVC_MOD_ID - * @userdata1 Current Istep - * @userdata2 Current SubStep - * @devdesc a deferred deconfigure callup was - * encountered; - */ - err = new ERRORLOG::ErrlEntry( - ERRORLOG::ERRL_SEV_UNRECOVERABLE, - ISTEP_INITSVC_MOD_ID, - ISTEP_DELAYED_DECONFIG, - istep , - substep ); - - // add procedure callout - err->addProcedureCallout(HWAS::EPUB_PRC_FIND_DECONFIGURED_PART, - HWAS::SRCI_PRIORITY_HIGH); - } - - if( err ) - { - TRACFCOMP( g_trac_initsvc, - "IStepDipspatcher (worker): " - "Istep %s return PLID=0x%x", - theStep->taskname, - err->plid() ); - } - // Check for any attentions and invoke PRD for analysis - else if ( true == theStep->taskflags.check_attn ) - { - TRACDCOMP( g_trac_initsvc, - INFO_MRK"Check for attentions and invoke PRD" ); - - err = ATTN::checkForIplAttentions(); - - if ( err ) - { - TRACFCOMP( g_trac_initsvc, - "IStepDipspatcher (worker): " - "ERROR return from PRD analysis after Istep %s", - theStep->taskname); - } - } - - } - else - { -#if 1 - TRACFCOMP( g_trac_initsvc, - "istepWorker: Empty Istep, nothing to do!" ); -#else - // @TODO reopen issue 70657 - // Invalid istep sent from FSP or spless, return error. - TRACFCOMP( g_trac_initsvc, - "istepWorker: ERROR: " - "Invalid Istep %d, substep %d ", - istep, - substep ); - // This istep should have not been sent here to run, make up - // an errorlog and return it. - /*@ - * @errortype - * @reasoncode ISTEP_INVALID_ISTEP - * @severity ERRORLOG::ERRL_SEV_UNRECOVERABLE - * @moduleid ISTEP_INITSVC_MOD_ID - * @userdata1 Current Istep - * @userdata2 Current SubStep - * @devdesc An invalid istep or substep was passed. - */ - err = new ERRORLOG::ErrlEntry( ERRORLOG::ERRL_SEV_UNRECOVERABLE, - ISTEP_INITSVC_MOD_ID, - ISTEP_INVALID_ISTEP, - istep, - substep ); - - TRACFCOMP( g_trac_initsvc, - ERR_MRK"istepWorker ERROR:" - "Invalid Istep %d.%d, returned errlog PLID=0x%x", - istep, - substep, - err->plid() ); -#endif - - } - - - msg_free( theMsg ); - theMsg = NULL; - } // end while(1) - - // Something bad happened... this thread should never exit once started - assert( false, "istepWorker: should never get here." ); -} - - -// load module routine used in simple temp solution -// for module management -void loadModules( uint32_t istepNumber ) -{ - errlHndl_t l_errl = NULL; - do - { - // if no dep modules then just exit out, let the call to - // executeFN load the module based on the function being - // called. - if( g_isteps[istepNumber].depModules == NULL) - { - TRACDCOMP( g_trac_initsvc, - "g_isteps[%d].depModules == NULL", - istepNumber ); - break; - } - uint32_t i = 0; - - while( ( l_errl == NULL ) && - ( g_isteps[istepNumber].depModules->modulename[i][0] != 0) ) - { - TRACFCOMP( g_trac_initsvc, - "loading [%s]", - g_isteps[istepNumber].depModules->modulename[i]); - - l_errl = VFS::module_load( - g_isteps[istepNumber].depModules->modulename[i] ); - i++; - } - - if( l_errl ) - { - errlCommit( l_errl, ISTEP_COMP_ID ); - assert(0); - } - - }while(0); -} - - -// unload module routine used in simple temp solution -// for module management -void unLoadModules( uint32_t istepNumber ) -{ - errlHndl_t l_errl = NULL; - - do - { - // if no dep modules then just exit out - if( g_isteps[istepNumber].depModules == NULL) - { - TRACDCOMP( g_trac_initsvc, - "g_isteps[%d].depModules == NULL", - istepNumber ); - break; - } - uint32_t i = 0; - - while( ( l_errl == NULL ) && - ( g_isteps[istepNumber].depModules->modulename[i][0] != 0) ) - { - TRACFCOMP( g_trac_initsvc, - "unloading [%s]", - g_isteps[istepNumber].depModules->modulename[i]); - - l_errl = VFS::module_unload( - g_isteps[istepNumber].depModules->modulename[i] ); - - i++; - } - - if( l_errl ) - { - TRACFCOMP( g_trac_initsvc, - " failed to unload module, commit error and move on"); - errlCommit(l_errl, INITSVC_COMP_ID ); - l_errl = NULL; - } - - }while(0); -} - -// ---------------------------------------------------------------------------- -// findTaskInfo() -// ---------------------------------------------------------------------------- -const TaskInfo * findTaskInfo( const uint32_t i_IStep, - const uint32_t i_SubStep ) -{ - // default return is NULL - const TaskInfo *l_pistep = NULL; - - // Cache the ipl mode since it doesn't change during an IPL - static bool l_mpipl_mode = IStepDispatcher::getTheInstance().isMpiplMode(); - - // apply filters - do - { - // Sanity check / dummy IStep - if( g_isteps[i_IStep].pti == NULL) - { - TRACDCOMP( g_trac_initsvc, - "g_isteps[%d].pti == NULL (substep=%d)", - i_IStep, - i_SubStep ); - break; - } - - // check input range - IStep - if( i_IStep >= INITSERVICE::MaxISteps ) - { - TRACDCOMP( g_trac_initsvc, - "IStep %d out of range. (substep=%d) ", - i_IStep, - i_SubStep ); - break; // break out with l_pistep set to NULL - } - - // check input range - ISubStep - if( i_SubStep >= g_isteps[i_IStep].numitems ) - { - TRACDCOMP( g_trac_initsvc, - "IStep %d Substep %d out of range.", - i_IStep, - i_SubStep ); - break; // break out with l_pistep set to NULL - } - - // check for end of list. - if( g_isteps[i_IStep].pti[i_SubStep].taskflags.task_type - == END_TASK_LIST ) - { - TRACDCOMP( g_trac_initsvc, - "IStep %d SubStep %d task_type==END_TASK_LIST.", - i_IStep, - i_SubStep ); - break; - } - - // check to see if the pointer to the function is NULL. - // This is possible if some of the substeps aren't working yet - // and are just placeholders. - if( g_isteps[i_IStep].pti[i_SubStep].taskfn == NULL ) - { - TRACDCOMP( g_trac_initsvc, - "IStep %d SubStep %d fn ptr is NULL.", - i_IStep, - i_SubStep ); - break; - } - - // check to see if we should skip this istep - // This is possible depending on which IPL mode we're in - uint8_t l_ipl_op = g_isteps[i_IStep].pti[i_SubStep].taskflags.ipl_op; - if (true == l_mpipl_mode) - { - if (!(l_ipl_op & MPIPL_OP)) - { - TRACDCOMP( g_trac_initsvc, - "Skipping IStep %d SubStep %d for MPIPL mode", - i_IStep, - i_SubStep ); - break; - } - } - else - { - if (!(l_ipl_op & NORMAL_IPL_OP)) - { - TRACDCOMP( g_trac_initsvc, - "Skipping IStep %d SubStep %d for non MPIPL mode", - i_IStep, - i_SubStep ); - break; - } - } - - // we're good, set the istep & return it to caller - l_pistep = &( g_isteps[i_IStep].pti[i_SubStep] ); - } while( 0 ); - - return l_pistep; -} - -bool getSyncEnabledAttribute() -{ - using namespace TARGETING; - - Target* l_pTopLevel = NULL; - - uint8_t l_syncEnabled = 0; - - TargetService& l_targetService = targetService(); - - l_targetService.getTopLevelTarget( l_pTopLevel ); - - if( l_pTopLevel == NULL ) - { - TRACFCOMP( g_trac_initsvc, - "Top level handle was NULL, default sync not enabled" ); - /*@ - * @errortype - * @reasoncode ISTEP::ISTEP_TOP_LEVEL_TARGET_NULL - * @severity ERRORLOG::ERRL_SEV_UNRECOVERABLE - * @moduleid ISTEP_INITSVC_MOD_ID - * @userdata1 N/A - * @userdata2 N/A - * @devdesc call to get top level targeting handle - * returned null. - */ - - errlHndl_t err = new ERRORLOG::ErrlEntry( - ERRORLOG::ERRL_SEV_UNRECOVERABLE, - ISTEP::ISTEP_INITSVC_MOD_ID, - ISTEP::ISTEP_TOP_LEVEL_TARGET_NULL ); - - errlCommit( err, ISTEP_COMP_ID ); - } - else - { - l_syncEnabled = l_pTopLevel->getAttr<ATTR_SYNC_BETWEEN_STEPS> (); - } - - return ( (l_syncEnabled) ? true : false ); - -} -} // namespace diff --git a/src/usr/initservice/istepdispatcher/istepWorker.H b/src/usr/initservice/istepdispatcher/istepWorker.H deleted file mode 100644 index 87f8c8468..000000000 --- a/src/usr/initservice/istepdispatcher/istepWorker.H +++ /dev/null @@ -1,81 +0,0 @@ -/* IBM_PROLOG_BEGIN_TAG - * This is an automatically generated prolog. - * - * $Source: src/usr/initservice/istepdispatcher/istepWorker.H $ - * - * IBM CONFIDENTIAL - * - * COPYRIGHT International Business Machines Corp. 2012 - * - * p1 - * - * Object Code Only (OCO) source materials - * Licensed Internal Code Source Materials - * IBM HostBoot Licensed Internal Code - * - * The source code for this program is not published or other- - * wise divested of its trade secrets, irrespective of what has - * been deposited with the U.S. Copyright Office. - * - * Origin: 30 - * - * IBM_PROLOG_END_TAG - */ -#ifndef __ISTEPWORKER_H -#define __ISTEPWORKER_H -/** - * @file istepWorker.H - * - * IStep Dispatcher Worker thread - */ - -/******************************************************************************/ -// Includes -/******************************************************************************/ -#include <stdint.h> - -#include <initservice/initsvcstructs.H> - - -namespace INITSERVICE -{ - -/** -* @brief This function is called to start the task. -* -* @param[in/out] io_args - This is a void pointer, but the code expects that -* this will be the msg queue to communicate with the main thread. -* -* @return NULL -*/ -void* startIStepWorkerThread ( void * io_args ); - -/** -* @brief This function is the main loop for the Istep dispatcher worker -* thread. -* -* @param[in] i_msgQ - The message queue to talk to the main thread. -* -* @return any errlogs - */ -void iStepWorkerThread ( void * i_msgQ ); - -/** - * @brief This function will be used to query the istep master list and the - * other istep headers to know what functions/tasks need to be started - * for the Istep/Substep that we are in. - * - * @param[in] i_IStep - The Istep to run. - * - * @param[in] i_SubStep - The SubStep to run. - * - * @return TaskInfo - The task info for the task to start as a result of the - * requested Istep/Substep. - */ -const TaskInfo * findTaskInfo ( const uint32_t i_IStep, - const uint32_t i_SubStep ); - - -} // namespace - -#endif diff --git a/src/usr/initservice/istepdispatcher/istep_mbox_msgs.H b/src/usr/initservice/istepdispatcher/istep_mbox_msgs.H index 00e94faa2..57bdb9486 100644 --- a/src/usr/initservice/istepdispatcher/istep_mbox_msgs.H +++ b/src/usr/initservice/istepdispatcher/istep_mbox_msgs.H @@ -35,8 +35,6 @@ namespace INITSERVICE { const uint32_t SPLESS_MSG = 0x000F0000; -const uint32_t ISTEP_WORKER_MSG = 0x00F00000; - const uint32_t ISTEP_MSG_SUCCESS = 0x00F00000; const uint32_t ISTEP_INVALID_MESSAGE = 0x00F00000; @@ -52,6 +50,9 @@ enum // HwSvr Msg Type Enums enum { + // Secure + HWSVR_ISTEP_MSG_TYPE = 0x00, + // Unsecure HWSVR_BREAKPOINT = 0x00, HWSVR_SYNC_POINT = 0x10, HWSVR_IPL_PROGRESS_CODE = 0x11, @@ -59,20 +60,14 @@ enum }; // ------------------------------------------------------------------ -// Worker Thread Msg Type Enums -enum -{ - WORKER_MORE_WORK_NEEDED = 0x00, - WORKER_BREAKPOINT = 0x01, -}; - -// ------------------------------------------------------------------ // Msgs that IstepDispatcher can accept enum { // -------------------------------------------------------------- // General Messages from all sources // -------------------------------------------------------------- + ISTEP_MSG_TYPE = MBOX::FIRST_SECURE_MSG | + HWSVR_ISTEP_MSG_TYPE, SYNC_POINT_REACHED = MBOX::FIRST_UNSECURE_MSG | HWSVR_SYNC_POINT, BREAKPOINT = MBOX::FIRST_UNSECURE_MSG | @@ -82,15 +77,6 @@ enum IPL_PROGRESS_CODE = MBOX::FIRST_UNSECURE_MSG | HWSVR_IPL_PROGRESS_CODE, - // -------------------------------------------------------------- - // Worker Thread Messages - // -------------------------------------------------------------- - MORE_WORK_NEEDED = MBOX::FIRST_SECURE_MSG | - ISTEP_WORKER_MSG | - WORKER_MORE_WORK_NEEDED, - BREAKPOINT_WORKER = MBOX::FIRST_SECURE_MSG | - ISTEP_WORKER_MSG | - WORKER_BREAKPOINT, }; } // namespace diff --git a/src/usr/initservice/istepdispatcher/istepdispatcher.C b/src/usr/initservice/istepdispatcher/istepdispatcher.C index 7197dc8d2..d8c14375e 100644 --- a/src/usr/initservice/istepdispatcher/istepdispatcher.C +++ b/src/usr/initservice/istepdispatcher/istepdispatcher.C @@ -33,71 +33,53 @@ /******************************************************************************/ // Includes /******************************************************************************/ -#include <stdint.h> -#include <stdio.h> -#include <string.h> -#include <sys/time.h> //nanosleep +#include <stdint.h> +#include <sys/time.h> //nanosleep +#include <kernel/console.H> // printk status +#include <vfs/vfs.H> // for VFS::module_load +#include <sys/task.h> // tid_t, task_create, etc +#include <errl/errlentry.H> // errlHndl_t +#include <initservice/isteps_trace.H> // ISTEPS_TRACE buffer +#include <initservice/initsvcudistep.H> // InitSvcUserDetailsIstep +#include <initservice/taskargs.H> // TASK_ENTRY_MACRO +#include <targeting/common/targetservice.H> +#include <targeting/attrsync.H> +#include <establish_system_smp.H> +#include <hwpf/plat/fapiPlatAttributeService.H> +#include <mbox/mbox_queues.H> // HB_ISTEP_MSGQ +#include <mbox/mboxif.H> // register mailbox +#include <isteps/istepmasterlist.H> +#include "istepdispatcher.H" +#include "istep_mbox_msgs.H" +#include "splesscommon.H" +#include <diag/attn/attn.H> +#include <hwpf/istepreasoncodes.H> +#include <hwas/common/deconfigGard.H> +#include <hwas/hwasPlat.H> -#include <kernel/console.H> // printk status - -// for VFS::module_load -#include <vfs/vfs.H> - -#include <sys/task.h> // tid_t, task_create, etc - -#include <errl/errlentry.H> // errlHndl_t - -#include <devicefw/userif.H> // targeting - -#include <initservice/isteps_trace.H> // ISTEPS_TRACE buffer -#include <initservice/initsvcudistep.H> // InitSvcUserDetailsIstep -#include <initservice/taskargs.H> // TASK_ENTRY_MACRO - -#include <targeting/common/attributes.H> // ISTEP_MODE attribute -#include <targeting/common/targetservice.H> -#include <targeting/attrsync.H> - - -#include <establish_system_smp.H> - -#include <hwpf/plat/fapiPlatAttributeService.H> - -#include <mbox/mbox_queues.H> // HB_ISTEP_MSGQ -#include <mbox/mboxif.H> // register mailbox - -#include <isteps/istepmasterlist.H> - -#include "istepdispatcher.H" -#include "istepWorker.H" -#include "istep_mbox_msgs.H" - -#include "splesscommon.H" - -// ----- namespace ISTEPS_TRACE --------------------------------------- namespace ISTEPS_TRACE { + // declare storage for isteps_trace! + trace_desc_t * g_trac_isteps_trace = NULL; + TRAC_INIT(&ISTEPS_TRACE::g_trac_isteps_trace, "ISTEPS_TRACE", 2*KILOBYTE); +} -// declare storage for isteps_trace! -trace_desc_t *g_trac_isteps_trace = NULL; - -} // end namespace -// ----- end namespace ISTEPS_TRACE ----------------------------------- - - -// ----- namespace INITSERVICE ------------------------------------------- namespace INITSERVICE { - - -using namespace ERRORLOG; // IStepNameUserDetails -using namespace SPLESS; // SingleStepMode - /******************************************************************************/ // Globals/Constants /******************************************************************************/ extern trace_desc_t *g_trac_initsvc; - const MBOX::queue_id_t HWSVRQ = MBOX::IPL_SERVICE_QUEUE; +const uint8_t INNER_START_STEP = 12; +const uint8_t INNER_START_SUBSTEP = 1; +const uint8_t INNER_STOP_STEP = 12; +const uint8_t INNER_STOP_SUBSTEP = 5; +const uint8_t OUTER_START_STEP = 13; +const uint8_t OUTER_START_SUBSTEP = 1; +const uint8_t OUTER_STOP_STEP = 14; +const uint8_t OUTER_STOP_SUBSTEP = 7; +const uint8_t HB_START_ISTEP = 6; /** * _start() task entry procedure using the macro in taskargs.H @@ -107,29 +89,46 @@ TASK_ENTRY_MACRO( IStepDispatcher::getTheInstance().init ); // ---------------------------------------------------------------------------- // IstepDispatcher() // ---------------------------------------------------------------------------- -IStepDispatcher::IStepDispatcher () - : iv_workerMsg( NULL ) +IStepDispatcher::IStepDispatcher() : + iv_syncPointReached(false), + iv_istepModulesLoaded(0), + iv_progressThreadStarted(false), + iv_curIStep(0), + iv_curSubStep(0), + iv_pIstepMsg(NULL) { - mutex_init( &iv_bkPtMutex ); - mutex_init( &iv_syncMutex ); - mutex_init( &iv_mutex ); - sync_cond_init( &iv_syncHit ); - - setIstepInfo(0); - iv_sync = false; - iv_progressThreadStarted = false; - clock_gettime(CLOCK_MONOTONIC, &iv_lastProgressMsgTime); + mutex_init(&iv_bkPtMutex); + mutex_init(&iv_mutex); + mutex_init(&iv_syncMutex); + sync_cond_init(&iv_syncHit); + + TARGETING::Target* l_pSys = NULL; + TARGETING::targetService().getTopLevelTarget(l_pSys); + iv_mpiplMode = l_pSys->getAttr<TARGETING::ATTR_IS_MPIPL_HB>(); + TRACFCOMP(g_trac_initsvc, "IStepDispatcher: MPIPL Mode: %d", iv_mpiplMode); + iv_istepMode = l_pSys->getAttr<TARGETING::ATTR_ISTEP_MODE>(); + TRACFCOMP(g_trac_initsvc, "IStepDispatcher: IStep Mode: %d", iv_istepMode); + iv_spBaseServicesEnabled = spBaseServicesEnabled(); + TRACFCOMP(g_trac_initsvc, "IStepDispatcher: SP base Services Enabled: %d", + iv_spBaseServicesEnabled); + iv_mailboxEnabled = MBOX::mailbox_enabled(); + TRACFCOMP(g_trac_initsvc, "IStepDispatcher: Mailbox Enabled: %d", + iv_mailboxEnabled); + + if (iv_spBaseServicesEnabled) + { + // SP Base Services Enabled implies that HWSV is running. If this is + // true then the mailbox must be enabled + assert(iv_mailboxEnabled); + } - // Save flag indicating whether we're in MPIPL mode - iv_mpipl_mode = checkMpiplMode(); - TRACFCOMP( g_trac_initsvc, "MPIPL mode = %u", - iv_mpipl_mode ); + // Note that if SP Base Services are not enabled and the Mailbox is enabled + // then Cronus is sending messages to Hostboot. - // init mailbox / message Q. + clock_gettime(CLOCK_MONOTONIC, &iv_lastProgressMsgTime); iv_msgQ = msg_q_create(); } - // ---------------------------------------------------------------------------- // ~IstepDispatcher() // ---------------------------------------------------------------------------- @@ -144,106 +143,64 @@ IStepDispatcher::~IStepDispatcher () // the queue we will assert here because the destructor never gets // call. assert(0); - - TRACFCOMP( g_trac_initsvc, EXIT_MRK "IStepDispatcher::~IStepDispatcher " - "destructor." ); } - // ---------------------------------------------------------------------------- // IstepDispatcher::getTheInstance() // ---------------------------------------------------------------------------- -IStepDispatcher& IStepDispatcher::getTheInstance () +IStepDispatcher& IStepDispatcher::getTheInstance() { return Singleton<IStepDispatcher>::instance(); } - // ---------------------------------------------------------------------------- // IStepDispatcher::init() // ---------------------------------------------------------------------------- -void IStepDispatcher::init ( errlHndl_t &io_rtaskRetErrl ) +void IStepDispatcher::init(errlHndl_t &io_rtaskRetErrl) { errlHndl_t err = NULL; - // initialize (and declare) ISTEPS_TRACE here, the rest of the isteps will - // use it. - ISTEPS_TRACE::g_trac_isteps_trace = NULL; - TRAC_INIT(&ISTEPS_TRACE::g_trac_isteps_trace, "ISTEPS_TRACE", 2*KILOBYTE ); - - printk( "IstepDispatcher entry.\n" ); - TRACFCOMP( g_trac_initsvc, - "IStep Dispatcher entry." ); + printk( "IStepDispatcher entry.\n" ); + TRACFCOMP( g_trac_initsvc, "IStepDispatcher entry." ); do { - if( MBOX::mailbox_enabled() ) + if(iv_mailboxEnabled) { - // register message Q with FSP Mailbox - only if mailbox - // enabled - err = MBOX::msgq_register( MBOX::HB_ISTEP_MSGQ, - iv_msgQ ); + // Register message Q with FSP Mailbox + err = MBOX::msgq_register( MBOX::HB_ISTEP_MSGQ, iv_msgQ ); - if( err ) + if(err) { + TRACFCOMP(g_trac_initsvc, + "ERROR: Failed to register mailbox, terminating"); break; } } - else - { - assert(spLess()); // If the mailbox is disabled, we better be in - // spLess mode. Otherwise, attributes are set - // incorrectly. - } - - // Spawn off the Worker thread - tid_t l_workerTid = task_create( startIStepWorkerThread, - iv_msgQ ); - assert( l_workerTid > 0 ); - - // Check for SPLess operation in istep mode - if( spLess() && getIStepMode()) - { - // SPless user console is attached, - // launch SPTask. - TRACFCOMP( g_trac_initsvc, - "IStep single-step enable (SPLESS)" ); - - tid_t l_spTaskTid = task_create( spTask, - iv_msgQ ); - assert( l_spTaskTid > 0 ); - } - - if( err ) - { - TRACFCOMP( g_trac_initsvc, - "ERROR: Failed to register mailbox, terminating" ); - - break; - } - if( getIStepMode() ) + if(iv_istepMode) { - printk( "IStep single-step\n" ); - TRACFCOMP( g_trac_initsvc, - "IStep single-step" ); - - err = msgHndlr(); - if( err ) + // IStep mode (receive messages to run individual steps) + if (!iv_mailboxEnabled) { - break; + // Cannot get messages from either HWSV or Cronus. Launch SPTask + // to accept messages from the SPless user console + TRACFCOMP(g_trac_initsvc, "IStep mode and SPLESS"); + tid_t spTaskTid = task_create(spTask, iv_msgQ); + assert(spTaskTid > 0); } + + // Call the message handler to handle messages from FSP or SPless + // user console, these messages include the IStep messages. This + // function never returns. + msgHndlr(); } else { - printk( "IStep run-all\n" ); - TRACFCOMP( g_trac_initsvc, - "IStep run all" ); - - if(MBOX::mailbox_enabled()) + // Non-IStep mode (run all isteps automatically) + if(iv_spBaseServicesEnabled) { - // Read the attribute indicating if the FSP has overrides - // and get the overrides if it does + // Base Services available. Figure out if HWSV has overrides uint8_t l_attrOverridesExist = 0; TARGETING::Target* l_pTopLevelTarget = NULL; TARGETING::targetService().getTopLevelTarget(l_pTopLevelTarget); @@ -256,22 +213,25 @@ void IStepDispatcher::init ( errlHndl_t &io_rtaskRetErrl ) else { l_attrOverridesExist = l_pTopLevelTarget-> - getAttr<TARGETING::ATTR_PLCK_IPL_ATTR_OVERRIDES_EXIST>(); + getAttr<TARGETING::ATTR_PLCK_IPL_ATTR_OVERRIDES_EXIST>(); } if (l_attrOverridesExist) { fapi::theAttrOverrideSync().getAttrOverridesFromFsp(); } + + // Start a new thread to handle non-IStep messages from the FSP + // (e.g. sync point reached) + tid_t msgHndlrTaskTid = task_create(startMsgHndlrThread, this); + assert(msgHndlrTaskTid > 0); } - // Execute all Isteps sequentially in 'normal' mode err = executeAllISteps(); - if( err ) + if(err) { - // per interlock meeting, adding sync after ipl failure in - // normal IPL mode + // Sync all attributes to FSP TRACFCOMP( g_trac_initsvc, "sync attributes to FSP"); errlHndl_t l_syncAttrErrl = TARGETING::syncAllAttributesToFsp(); @@ -282,7 +242,6 @@ void IStepDispatcher::init ( errlHndl_t &io_rtaskRetErrl ) "%x for details", l_syncAttrErrl->eid()); errlCommit(l_syncAttrErrl, INITSVC_COMP_ID); } - break; } @@ -290,813 +249,818 @@ void IStepDispatcher::init ( errlHndl_t &io_rtaskRetErrl ) // Attributes to sync to the FSP fapi::theAttrOverrideSync().sendAttrOverridesAndSyncsToFsp(); } - } while( 0 ); + } while(0); - TRACFCOMP( g_trac_initsvc, - "IStepDispatcher finished."); + TRACFCOMP( g_trac_initsvc, "IStepDispatcher finished."); printk( "IStepDispatcher exit.\n" ); - io_rtaskRetErrl= err; + io_rtaskRetErrl = err; } - // ---------------------------------------------------------------------------- // IStepDispatcher::executeAllISteps() // ---------------------------------------------------------------------------- -errlHndl_t IStepDispatcher::executeAllISteps ( void ) +errlHndl_t IStepDispatcher::executeAllISteps() { errlHndl_t err = NULL; - msg_t * theMsg = NULL; + uint32_t istep = 0; + uint32_t substep = 0; + bool l_deconfigs = false; + uint32_t numReconfigs = 0; + const uint32_t MAX_NUM_RECONFIG_ATTEMPTS = 30; - TRACFCOMP( g_trac_initsvc, ENTER_MRK"IStepDispatcher::executeAllISteps()"); + TRACFCOMP(g_trac_initsvc, ENTER_MRK"IStepDispatcher::executeAllISteps()"); - do + while (istep < MaxISteps) { - // Sequentially loop through all isteps, executing each by replying to - // work needed msg from worker thread. - uint32_t prevIstep = 0; - uint32_t prevSubStep = 0; - - for( size_t istep = 0; - istep < MaxISteps; - istep++ ) + substep = 0; + while (substep < g_isteps[istep].numitems) { - for( size_t substep = 0; - substep < (g_isteps[istep].numitems+1); - substep++ ) - { -#if 0 - // @TODO reopen issue 70657 - // Check to see if this is a valid istep, if not, don't - // send it to istepWorker. IstepWorker treats invalid - // isteps as an error. - if ( NULL == findTaskInfo( istep, substep )) - { - TRACFCOMP( g_trac_initsvc, - "executeAllSteps: " - "skipping empty istep %d, substep: %d", - istep, substep ); - continue; - } -#endif - // Before we can do anything, we need to be sure that - // the worker thread is ready to start - theMsg = msg_wait( iv_msgQ ); - - // check for sync msgs - if( theMsg->type == SYNC_POINT_REACHED ) - { - // Pause Progress Thread RTC: 84794 - TRACFCOMP( g_trac_initsvc, - INFO_MRK"Got sync msg (0x%08x)", - theMsg->type ); - handleSyncPointReachedMsg(); - - // We didn't really do anything for this substep - substep--; - continue; - } + err = doIstep(istep, substep, l_deconfigs); - // If we just got the msg that the last step finished, break - // out - if( substep == (g_isteps[istep].numitems + 1) ) - { - TRACFCOMP( g_trac_initsvc, - INFO_MRK"Last Step, exit" ); - break; - } - - // Look for an errlog in extra_data - if( NULL != theMsg->extra_data ) + if (err) + { + // IStep error, check if a reconfig loop should be attempted + TRACFCOMP(g_trac_initsvc, ERR_MRK"executeAllISteps: IStep Error on %d:%d", + istep, substep); + + uint8_t newIstep = 0; + uint8_t newSubstep = 0; + + // Check for reconfigure. If istep returns an error, and there + // was a deconfigure, and checkReconfig is true (meaning the + // error is within the loops) then reconfigure. Else, break out + // with istep error. + if ( l_deconfigs && + (checkReconfig(istep, substep, newIstep, newSubstep) == + true)) { - TRACFCOMP( g_trac_initsvc, - ERR_MRK"executeAllISteps: " - "Error returned from istep(%d), substep(%d)", - prevIstep, - prevSubStep ); - - err = ((errlHndl_t)theMsg->extra_data); - - break; + if (numReconfigs >= MAX_NUM_RECONFIG_ATTEMPTS) + { + // Reconfigure loop has already been attempted too + // often, break out with the istep error + TRACFCOMP(g_trac_initsvc, ERR_MRK"executeAllISteps: No Reconfig Loop, Max count exceeded"); + break; + } + + // Delete the Istep error and create a new info error with + // the same plid stating that a reconfig loop was performed + uint32_t l_plid = err->plid(); + delete err; + err = NULL; + numReconfigs++; + + uint64_t errWord = FOUR_UINT16_TO_UINT64( + istep, substep, newIstep, newSubstep); + /*@ + * @errortype + * @reasoncode ISTEP_RECONFIG_LOOP_ENTERED + * @severity ERRORLOG::ERRL_SEV_INFORMATIONAL + * @moduleid ISTEP_INITSVC_MOD_ID + * @userdata1[0:15] Istep that failed + * @userdata1[16:31] Substep that failed + * @userdata1[32:47] Istep that reconfig looped back to + * @userdata1[48:63] Substep that reconfig looped back to + * @userdata2 The number of reconfigs loops tried + * @devdesc IStep failed and HW deconfigured. + * Looped back to an earlier istep + * (Reconfigure loop). + */ + err = new ERRORLOG::ErrlEntry( + ERRORLOG::ERRL_SEV_INFORMATIONAL, + ISTEP_INITSVC_MOD_ID, + ISTEP_RECONFIG_LOOP_ENTERED, + errWord, + numReconfigs); + err->plid(l_plid); + errlCommit(err, INITSVC_COMP_ID); + + istep = newIstep; + substep = newSubstep; + TRACFCOMP(g_trac_initsvc, ERR_MRK"executeAllISteps: Reconfig Loop: Back to %d:%d", + istep, substep); } - - TRACFCOMP( g_trac_initsvc, - INFO_MRK"executeAllISteps: " - "type: 0x%08x, istep: %d, substep: %d", - theMsg->type, istep, substep ); - - // Set the Istep info - prevIstep = istep; - prevSubStep = substep; - uint16_t istepInfo = ((istep << 8 ) | substep); - setIstepInfo( istepInfo ); - - // Send Progress Code - err = this->sendProgressCode(); - if( err ) + else { + // Break out with the istep error + TRACFCOMP(g_trac_initsvc, ERR_MRK"executeAllISteps: No Reconfig Loop"); break; } - - // Put the step/substep into data[0] for the worker thread - theMsg->data[0] = istepInfo; - msg_respond( iv_msgQ, - theMsg ); - - // StartProgeressThread - // Done here to make sure istep and substep are valid - if ( !iv_progressThreadStarted ) - { - tid_t l_progTid = task_create(startProgressThread,this); - assert( l_progTid > 0 ); - iv_progressThreadStarted = true; - } - - theMsg = NULL; - } // for substep - - if( err ) + } + else { - break; + substep++; } - } // for istep < MaxISteps; + } - if( err ) + if (err) { break; } - } while ( 0 ); + istep++; + } - TRACFCOMP( g_trac_initsvc, - EXIT_MRK"IStepDispatcher::executeAllISteps()" ); + TRACFCOMP(g_trac_initsvc, EXIT_MRK"IStepDispatcher::executeAllISteps()"); return err; } - // ---------------------------------------------------------------------------- -// IStepDispatcher::msgHndlr() +// IStepDispatcher::doIstep() // ---------------------------------------------------------------------------- -errlHndl_t IStepDispatcher::msgHndlr ( void ) +errlHndl_t IStepDispatcher::doIstep(uint32_t i_istep, + uint32_t i_substep, + bool & o_deconfigs) { errlHndl_t err = NULL; - msg_t * theMsg = NULL; - - // TODO - Issue 45012 - // There is enough common code between this path and executeAllISteps() - // that the issue above will be used to combine the 2 paths into one - // commone code path. + o_deconfigs = false; - TRACFCOMP( g_trac_initsvc, - ENTER_MRK"IStepDispatcher::msgHndlr()" ); + // Get the Task Info for this step + const TaskInfo * theStep = findTaskInfo(i_istep, i_substep); - // We will stay in this loop unless there is a failure or other reason to - // exit out and terminate. This loop is the main handler for the Istep - // Dispatcher. It receives all messages from the Fsp, Child worker - // thread, and the SPLess task. - while( 1 ) + // If the step has valid work to be done, then execute it. + if(NULL != theStep) { - theMsg = msg_wait( iv_msgQ ); - - TRACDCOMP( g_trac_initsvc, - "msgHndlr: rcvmsg t=0x%08x, d0=0x%016x, d1=0x%016x, x=%p", - theMsg->type, - theMsg->data[0], - theMsg->data[1], - theMsg->extra_data ); + TRACFCOMP(g_trac_initsvc,ENTER_MRK"doIstep: step %d, substep %d, task %s", + i_istep, i_substep, theStep->taskname); - switch( theMsg->type ) + // Send progress codes if in run-all mode + if (!iv_istepMode) { - case SYNC_POINT_REACHED: - TRACDCOMP( g_trac_initsvc, - "msgHndlr : SYNC_POINT_REACHED" ); - // Sync point reached from Fsp - iv_Msg = theMsg; - handleSyncPointReachedMsg(); - break; + mutex_lock(&iv_mutex); + iv_curIStep = i_istep; + iv_curSubStep = i_substep; - case MORE_WORK_NEEDED: - TRACDCOMP( g_trac_initsvc, - "msgHndlr : MORE_WORK_NEEDED" ); - // Worker thread is ready for more work. - iv_workerMsg = theMsg; - // The very first MORE_WORK_NEEDED message will - // have theMsg->data[0] set to 1. It is set to 0 - // for subsequent messages. handleMoreWorkNeededMsg - // needs to know the very first MORE_WORK_NEEDED msg - // to handle the case that a msg is queued in the - // mbox msg queue before this first MORE_WORK_NEEDED - // is received. - handleMoreWorkNeededMsg( (theMsg->data[0] == 1) ); - break; + // Send Progress Code + err = this->sendProgressCode(false); + mutex_unlock(&iv_mutex); - case PROCESS_IOVALID_REQUEST: - TRACFCOMP( g_trac_initsvc, - "msgHndlr : PROCESS_IOVALID_REQUEST" ); + if(err) + { + // Commit the error and continue + errlCommit(err, INITSVC_COMP_ID); + } - // make sure the needed libraries are loaded - err = VFS::module_load("libestablish_system_smp.so"); + // Start progress thread, if not yet started + if (!iv_progressThreadStarted) + { + tid_t l_progTid = task_create(startProgressThread,this); + assert( l_progTid > 0 ); + iv_progressThreadStarted = true; + } + } - // if the module loaded ok, do the processing - if( err == NULL ) - { - iv_Msg = theMsg; - handleProcFabIovalidMsg(); - } - break; + if(iv_istepModulesLoaded != i_istep) + { + // unload the modules from the previous step + unLoadModules(iv_istepModulesLoaded); + // load modules for this step + loadModules(i_istep); + iv_istepModulesLoaded = i_istep; + } - default: - // Default Message - // This SHOULD be a message from the Fsp with the Step/substep - // to be executed. - // Gotta check to make sure Fsp hadn't sent us a 2nd Istep - // request for some reason, if so, its an error. - if( iv_Msg ) - { - TRACFCOMP( g_trac_initsvc, - ERR_MRK"msgHndlr: ERROR: " - "IStep Dispatcher has another Istep request" - "for step: %d, substep: %d", - ((theMsg->type & 0xFF00) >> 8), - (theMsg->type & 0xFF) ); + uint32_t preDeconfigs = HWAS::theDeconfigGard().getDeconfigureStatus(); - /*@ - * @errortype - * @reasoncode ISTEP_MULTIPLE_ISTEP_REQ - * @severity ERRORLOG::ERRL_SEV_UNRECOVERABLE - * @moduleid ISTEP_INITSVC_MOD_ID - * @userdata1 Current Istep - * @userdata2 Current SubStep - * @devdesc A Second Istep request has been made - * and we are still working on a - * previous Istep. - */ - err = new ERRORLOG::ErrlEntry( - ERRORLOG::ERRL_SEV_UNRECOVERABLE, - ISTEP_INITSVC_MOD_ID, - ISTEP_MULTIPLE_ISTEP_REQ, - ((theMsg->type & 0xFF00) >> 8), - (theMsg->type & 0xFF) ); + err = InitService::getTheInstance().executeFn(theStep, NULL); - break; - } + // flush contTrace immediately after each i_istep/substep returns + TRAC_FLUSH_BUFFERS(); - TRACDCOMP( g_trac_initsvc, - "msgHndlr : default" ); - iv_Msg = theMsg; - handleIStepRequestMsg(); - break; - }; // end switch + // sync the attributes to fsp in single step mode but only after step 6 + // is complete to allow discoverTargets() to run before the sync is done + if(iv_istepMode && (i_istep > HB_START_ISTEP)) + { + if(isAttrSyncEnabled()) + { + TRACFCOMP(g_trac_initsvc, INFO_MRK"doIstep: sync attributes to FSP"); + + errlHndl_t l_errl = TARGETING::syncAllAttributesToFsp(); - if( err ) + if(l_errl) + { + TRACFCOMP(g_trac_initsvc, ERR_MRK"doIstep: syncattributes failed see %x for details", + l_errl->eid()); + errlCommit(l_errl, INITSVC_COMP_ID); + } + } + } + + // Check for Power Line Disturbance (PLD) + if (HWAS::hwasPLDDetection()) { - TRACFCOMP( g_trac_initsvc, - "istepDispatcher, recieved errorlog, PLID = 0x%x", - err->plid() ); - // Breaking here will be a BAD thing... It means that we are - // exiting not just Istep Dispatcher, but all of Hostboot. - // This should only happen if there is an error during an Istep. - errlCommit( err, - INITSVC_COMP_ID ); + // There was a PLD, clear any deferred deconfig records + TRACFCOMP(g_trac_initsvc, ERR_MRK"doIstep: PLD, clearing deferred deconfig records"); + HWAS::theDeconfigGard().clearDeconfigureRecords(NULL); } - } // end while(1) + else + { + // There was no PLD, process any deferred deconfig records (i.e. + // actually do the deconfigures) + bool deferredDeconfigs = HWAS::processDeferredDeconfig(); - TRACFCOMP( g_trac_initsvc, - EXIT_MRK"IStepDispatcher::msgHndlr()" ); + if (deferredDeconfigs) + { + TRACFCOMP(g_trac_initsvc, ERR_MRK"doIstep: Processed deferred deconfig records"); + } + } - return err; -} + uint32_t postDeconfigs = HWAS::theDeconfigGard().getDeconfigureStatus(); + if (postDeconfigs != preDeconfigs) + { + o_deconfigs = true; -// ---------------------------------------------------------------------------- -// waitForSyncPoint() -// IStepDispatcher::waitForSyncPoint() -// ---------------------------------------------------------------------------- -void waitForSyncPoint ( void ) -{ - TRACDCOMP( g_trac_initsvc, - ENTER_MRK"waitForSyncPoint()" ); + if (err == NULL) + { + // IStep returned success, but HW was deconfigured! IStep + // success is a contract that the IStep worked and the system + // config did not change. Therefore create an error. + TRACFCOMP(g_trac_initsvc, ERR_MRK"doIstep: Creating deconfig error"); + + /*@ + * @errortype + * @reasoncode ISTEP_FAILED_DUE_TO_DECONFIG + * @severity ERRORLOG::ERRL_SEV_UNRECOVERABLE + * @moduleid ISTEP_INITSVC_MOD_ID + * @userdata1 Istep that failed + * @userdata2 SubStep that failed + * @devdesc IStep reported success but HW deconfigured + */ + err = new ERRORLOG::ErrlEntry( + ERRORLOG::ERRL_SEV_UNRECOVERABLE, + ISTEP_INITSVC_MOD_ID, + ISTEP_FAILED_DUE_TO_DECONFIG, + i_istep, i_substep); + } + } - IStepDispatcher::getTheInstance().waitForSyncPoint(); + if(err) + { + TRACFCOMP(g_trac_initsvc, ERR_MRK"doIstep: Istep failed, plid 0x%x", + err->plid()); + } + // Check for any attentions and invoke PRD for analysis + else if (true == theStep->taskflags.check_attn) + { + TRACDCOMP(g_trac_initsvc, + INFO_MRK"Check for attentions and invoke PRD" ); - TRACDCOMP( g_trac_initsvc, - EXIT_MRK"waitForSyncPoint()" ); -} + err = ATTN::checkForIplAttentions(); -void IStepDispatcher::waitForSyncPoint ( void ) -{ - TRACDCOMP( g_trac_initsvc, - ENTER_MRK"IStepDispatcher::waitForSyncPoint()" ); + if ( err ) + { + TRACFCOMP( g_trac_initsvc, ERR_MRK"doIstep: error from checkForIplAttentions"); + } + } - if( getIStepMode() || - spLess() ) - { - TRACFCOMP( g_trac_initsvc, - INFO_MRK"Istep mode or SPless, " - "no wait for sync point allowed" ); - return; + TRACFCOMP(g_trac_initsvc, EXIT_MRK"doIstep: step %d, substep %d", + i_istep, i_substep); } - - // Lock here to hold off all additional callers - TRACFCOMP( g_trac_initsvc, - INFO_MRK"Wait for sync point" ); - mutex_lock( &iv_syncMutex ); - while( !iv_sync ) + else { - sync_cond_wait( &iv_syncHit, - &iv_syncMutex ); + TRACDCOMP( g_trac_initsvc, INFO_MRK"doIstep: Empty Istep, nothing to do!" ); } - iv_sync = false; - mutex_unlock( &iv_syncMutex ); - TRACDCOMP( g_trac_initsvc, - INFO_MRK"Sync point hit." ); - TRACDCOMP( g_trac_initsvc, - EXIT_MRK"IStepDispatcher::waitForSyncPoint()" ); + return err; } // ---------------------------------------------------------------------------- -// sendSyncPoint() -// IStepDispatcher::sendSyncPoint() +// findTaskInfo() // ---------------------------------------------------------------------------- -errlHndl_t sendSyncPoint ( void ) +const TaskInfo * IStepDispatcher::findTaskInfo(const uint32_t i_IStep, + const uint32_t i_SubStep) { - TRACFCOMP( g_trac_initsvc, - ENTER_MRK"sendSyncPoint()" ); + // default return is NULL + const TaskInfo *l_pistep = NULL; - return IStepDispatcher::getTheInstance().sendSyncPoint(); -} + // apply filters + do + { + // Sanity check / dummy IStep + if(g_isteps[i_IStep].pti == NULL) + { + TRACDCOMP( g_trac_initsvc, + "g_isteps[%d].pti == NULL (substep=%d)", + i_IStep, + i_SubStep ); + break; + } -errlHndl_t IStepDispatcher::sendSyncPoint ( void ) -{ - errlHndl_t err = NULL; + // check input range - IStep + if( i_IStep >= MaxISteps ) + { + TRACDCOMP( g_trac_initsvc, + "IStep %d out of range. (substep=%d) ", + i_IStep, + i_SubStep ); + break; // break out with l_pistep set to NULL + } - TRACDCOMP( g_trac_initsvc, - ENTER_MRK"IStepDispatcher::sendSyncPoint()" ); + // check input range - ISubStep + if( i_SubStep >= g_isteps[i_IStep].numitems ) + { + TRACDCOMP( g_trac_initsvc, + "IStep %d Substep %d out of range.", + i_IStep, + i_SubStep ); + break; // break out with l_pistep set to NULL + } - if( getIStepMode() ) - { - TRACFCOMP( g_trac_initsvc, - INFO_MRK"Istep mode, no sending sync point allowed" ); - return err; - } + // check for end of list. + if( g_isteps[i_IStep].pti[i_SubStep].taskflags.task_type + == END_TASK_LIST ) + { + TRACDCOMP( g_trac_initsvc, + "IStep %d SubStep %d task_type==END_TASK_LIST.", + i_IStep, + i_SubStep ); + break; + } - msg_t * myMsg = msg_allocate(); - myMsg->type = SYNC_POINT_REACHED; - uint64_t tmpVal = iv_curIStep; - tmpVal = tmpVal << 32; - tmpVal |= iv_curSubStep; - myMsg->data[0] = tmpVal; - myMsg->data[1] = 0x0; - myMsg->extra_data = NULL; - err = sendMboxMsg( ISTEP_ASYNC, - myMsg ); + // check to see if the pointer to the function is NULL. + // This is possible if some of the substeps aren't working yet + // and are just placeholders. + if( g_isteps[i_IStep].pti[i_SubStep].taskfn == NULL ) + { + TRACDCOMP( g_trac_initsvc, + "IStep %d SubStep %d fn ptr is NULL.", + i_IStep, + i_SubStep ); + break; + } + + // check to see if we should skip this istep + // This is possible depending on which IPL mode we're in + uint8_t l_ipl_op = g_isteps[i_IStep].pti[i_SubStep].taskflags.ipl_op; + if (true == iv_mpiplMode) + { + if (!(l_ipl_op & MPIPL_OP)) + { + TRACDCOMP( g_trac_initsvc, + "Skipping IStep %d SubStep %d for MPIPL mode", + i_IStep, + i_SubStep ); + break; + } + } + else + { + if (!(l_ipl_op & NORMAL_IPL_OP)) + { + TRACDCOMP( g_trac_initsvc, + "Skipping IStep %d SubStep %d for non MPIPL mode", + i_IStep, + i_SubStep ); + break; + } + } - TRACDCOMP( g_trac_initsvc, - EXIT_MRK"IStepDispatcher::sendSyncPoint()" ); + // we're good, set the istep & return it to caller + l_pistep = &( g_isteps[i_IStep].pti[i_SubStep] ); + } while( 0 ); - return err; + return l_pistep; } // ---------------------------------------------------------------------------- -// sendIstepCompleteMsg() -// IStepDispatcher::sendIstepCompleteMsg() +// loadModules() // ---------------------------------------------------------------------------- -errlHndl_t sendIstepCompleteMsg ( void ) +void IStepDispatcher::loadModules(uint32_t istepNumber) const { - TRACFCOMP( g_trac_initsvc, - ENTER_MRK"sendIstepCompleteMsg()" ); - - return IStepDispatcher::getTheInstance().sendIstepCompleteMsg(); -} - -errlHndl_t IStepDispatcher::sendIstepCompleteMsg ( void ) -{ - errlHndl_t err = NULL; - - TRACDCOMP( g_trac_initsvc, - ENTER_MRK"IStepDispatcher::sendIstepCompleteMsg()" ); - + errlHndl_t l_errl = NULL; do { - //Send progress code and update clock in thread - /* 15 sec msg constraint not planned for GA1 - err = this->sendProgressCode(); - if( err ) + // if no dep modules then just exit out, let the call to + // executeFN load the module based on the function being + // called. + if( g_isteps[istepNumber].depModules == NULL) { + TRACDCOMP( g_trac_initsvc, + "g_isteps[%d].depModules == NULL", + istepNumber ); break; } - */ + uint32_t i = 0; - // We just need to respond back to the outstanding iv_Msg we should - // already have - if( iv_Msg ) - { - iv_Msg->data[0] = 0x0; - msg_respond( iv_msgQ, - iv_Msg ); - iv_Msg = NULL; - } - else + while( ( l_errl == NULL ) && + ( g_isteps[istepNumber].depModules->modulename[i][0] != 0) ) { TRACFCOMP( g_trac_initsvc, - ERR_MRK"Request to send Istep complete, " - "but no outstanding message from Fsp found!!" ); - - /*@ - * @errortype - * @reasoncode NO_MSG_PRESENT - * @severity ERRORLOG::ERRL_SEV_UNRECOVERABLE - * @moduleid ISTEP_INITSVC_MOD_ID - * @userdata1 Current Istep - * @userdata2 Current SubStep - * @devdesc Request to send Istep Complete msg to Fsp, but - * no outstanding message from Fsp found. - */ - err = new ERRORLOG::ErrlEntry( ERRORLOG::ERRL_SEV_UNRECOVERABLE, - ISTEP_INITSVC_MOD_ID, - NO_MSG_PRESENT, - iv_curIStep, - iv_curSubStep ); + "loading [%s]", + g_isteps[istepNumber].depModules->modulename[i]); - break; + l_errl = VFS::module_load( + g_isteps[istepNumber].depModules->modulename[i] ); + i++; } - } while( 0 ); - - TRACDCOMP( g_trac_initsvc, - EXIT_MRK"IStepDispatcher::sendIstepCompleteMsg()" ); + if( l_errl ) + { + errlCommit( l_errl, ISTEP_COMP_ID ); + assert(0); + } - return err; + }while(0); } - // ---------------------------------------------------------------------------- -// IStepDispatcher::sendMboxMsg() +// unloadModules() // ---------------------------------------------------------------------------- -errlHndl_t IStepDispatcher::sendMboxMsg ( IStepSync_t i_sendSync, - msg_t * i_msg ) +void IStepDispatcher::unLoadModules(uint32_t istepNumber) const { - errlHndl_t err = NULL; - - TRACDCOMP( g_trac_initsvc, - ENTER_MRK"IStepDispatcher::sendMboxMsg()" ); + errlHndl_t l_errl = NULL; do { - if( ISTEP_SYNC == i_sendSync ) - { - err = MBOX::sendrecv( HWSVRQ, - i_msg ); - } - else if( ISTEP_ASYNC == i_sendSync ) + // if no dep modules then just exit out + if( g_isteps[istepNumber].depModules == NULL) { - err = MBOX::send( HWSVRQ, - i_msg ); + TRACDCOMP( g_trac_initsvc, + "g_isteps[%d].depModules == NULL", + istepNumber ); + break; } - else + uint32_t i = 0; + + while( ( l_errl == NULL ) && + ( g_isteps[istepNumber].depModules->modulename[i][0] != 0) ) { - // should never get here, but if we do, just return back... - // Nothing to send. + TRACFCOMP( g_trac_initsvc, + "unloading [%s]", + g_isteps[istepNumber].depModules->modulename[i]); + + l_errl = VFS::module_unload( + g_isteps[istepNumber].depModules->modulename[i] ); + + i++; } - if( err ) + if( l_errl ) { - break; + TRACFCOMP( g_trac_initsvc, + " failed to unload module, commit error and move on"); + errlCommit(l_errl, INITSVC_COMP_ID ); + l_errl = NULL; } - } while( 0 ); - TRACDCOMP( g_trac_initsvc, - EXIT_MRK"IStepDispatcher::sendMboxMsg()" ); - - return err; + }while(0); } - // ---------------------------------------------------------------------------- -// IStepDispatcher::getIstepInfo() +// IStepDispatcher::isAttrSyncEnabled() // ---------------------------------------------------------------------------- -void IStepDispatcher::getIstepInfo ( uint8_t & o_iStep, - uint8_t & o_subStep ) +bool IStepDispatcher::isAttrSyncEnabled() const { - mutex_lock( &iv_mutex ); - o_iStep = iv_curIStep; - o_subStep = iv_curSubStep; - mutex_unlock( &iv_mutex ); + TARGETING::Target* l_pTopLevel = NULL; + TARGETING::targetService().getTopLevelTarget(l_pTopLevel); + uint8_t l_syncEnabled = + l_pTopLevel->getAttr<TARGETING::ATTR_SYNC_BETWEEN_STEPS>(); + return l_syncEnabled; } - // ---------------------------------------------------------------------------- -// IStepDispatcher::setIstepInfo() +// IStepDispatcher::msgHndlr() // ---------------------------------------------------------------------------- -void IStepDispatcher::setIstepInfo ( uint16_t i_type ) +void IStepDispatcher::msgHndlr() { - mutex_lock( &iv_mutex ); - iv_curIStep = ((i_type & 0xFF00) >> 8); - iv_curSubStep = (i_type & 0xFF); - mutex_unlock( &iv_mutex ); -} + TRACFCOMP( g_trac_initsvc, ENTER_MRK"IStepDispatcher::msgHndlr"); + // Loop forever + while(1) + { + msg_t * pMsg = NULL; + pMsg = msg_wait(iv_msgQ); + + switch(pMsg->type) + { + case SYNC_POINT_REACHED: + // Sync point reached from Fsp + TRACFCOMP(g_trac_initsvc, INFO_MRK"msgHndlr: SYNC_POINT_REACHED"); + handleSyncPointReachedMsg(pMsg); + break; + case PROCESS_IOVALID_REQUEST: + TRACFCOMP(g_trac_initsvc, INFO_MRK"msgHndlr: PROCESS_IOVALID_REQUEST"); + handleProcFabIovalidMsg(pMsg); + break; + case ISTEP_MSG_TYPE: + TRACFCOMP(g_trac_initsvc, INFO_MRK"msgHndlr: ISTEP_MSG_TYPE"); + if (iv_istepMode) + { + handleIStepRequestMsg(pMsg); + } + else + { + TRACFCOMP(g_trac_initsvc, ERR_MRK"msgHndlr: Ignoring IStep msg in non-IStep mode!"); + } + break; + default: + TRACFCOMP(g_trac_initsvc, ERR_MRK"msgHndlr: Ignoring unknown message 0x%08x", + pMsg->type); + break; + }; + } + + TRACFCOMP( g_trac_initsvc, EXIT_MRK"IStepDispatcher::msgHndlr"); +} // ---------------------------------------------------------------------------- -// IStepDispatcher::handleSyncPointReachedMsg() +// IStepDispatcher::waitForSyncPoint() // ---------------------------------------------------------------------------- -void IStepDispatcher::handleSyncPointReachedMsg ( void ) +void IStepDispatcher::waitForSyncPoint() { - TRACDCOMP( g_trac_initsvc, - ENTER_MRK"IStepDispatcher::handleSyncPointReachedMsg()" ); + TRACFCOMP(g_trac_initsvc, ENTER_MRK"IStepDispatcher::waitForSyncPoint"); - do + if(iv_istepMode || (!iv_spBaseServicesEnabled)) { - // Indicate we hit a sync point, and get anyone waiting moving. - mutex_lock( &iv_syncMutex ); - iv_sync = true; - sync_cond_signal( &iv_syncHit ); - mutex_unlock( &iv_syncMutex ); - } while( 0 ); + TRACFCOMP(g_trac_initsvc, INFO_MRK"waitForSyncPoint: Istep mode or no base services, returning"); + } + else + { + // Wait for the condition variable to be signalled + mutex_lock(&iv_syncMutex); + while(!iv_syncPointReached) + { + sync_cond_wait(&iv_syncHit, &iv_syncMutex); + } + iv_syncPointReached = false; + mutex_unlock(&iv_syncMutex); + } - TRACDCOMP( g_trac_initsvc, - EXIT_MRK"IStepDispatcher::handleSyncPointReachedMsg()" ); + TRACFCOMP(g_trac_initsvc, EXIT_MRK"IStepDispatcher::waitForSyncPoint"); } - // ---------------------------------------------------------------------------- -// IStepDispatcher::handleMoreWorkNeededMsg() +// IStepDispatcher::sendSyncPoint() // ---------------------------------------------------------------------------- -void IStepDispatcher::handleMoreWorkNeededMsg ( bool i_first ) +errlHndl_t IStepDispatcher::sendSyncPoint() { - uint32_t l_plid = 0; - - TRACDCOMP( g_trac_initsvc, - ENTER_MRK"IStepDispatcher::handleMoreWorkNeededMsg()" ); + errlHndl_t err = NULL; - // Clear out current Istep/substep values. Since worker thread told us - // its done, nothing is running right now. - setIstepInfo(0); + TRACFCOMP(g_trac_initsvc, ENTER_MRK"IStepDispatcher::sendSyncPoint"); - // Only something to do if we've gotten a request from Fsp or SPLESS - if( iv_Msg ) + if(iv_istepMode || (!iv_spBaseServicesEnabled)) { - if (i_first) + TRACFCOMP( g_trac_initsvc, INFO_MRK"sendSyncPoint: Istep mode or no base services, returning"); + } + else + { + msg_t * myMsg = msg_allocate(); + myMsg->type = SYNC_POINT_REACHED; + mutex_lock(&iv_mutex); + uint64_t tmpVal = iv_curIStep; + tmpVal = tmpVal << 32; + tmpVal |= iv_curSubStep; + mutex_unlock(&iv_mutex); + myMsg->data[0] = tmpVal; + myMsg->data[1] = 0x0; + myMsg->extra_data = NULL; + + err = MBOX::send(HWSVRQ, myMsg); + + if (err) { - handleIStepRequestMsg(); + TRACFCOMP( g_trac_initsvc, ERR_MRK"sendSyncPoint: Error sending message"); } - // Send response back to caller? - else if( !msg_is_async( iv_Msg ) ) - { - // if the istep failed, istepWorker will return the errorlog - // in iv_WorkerMsg->extra_data. Commit the error here and then - // return the plid as status to the FSP/spless in iv_Msg. - // Note that there are 2 messages in transit here, iv_WorkerMsg - // and iv_Msg . - if ( iv_workerMsg->extra_data != NULL ) - { - errlHndl_t tmpErr = static_cast<errlHndl_t>(iv_workerMsg->extra_data); - l_plid = tmpErr->plid(); - errlCommit( tmpErr, - INITSVC_COMP_ID ); + } - // pass the plid back to FSP/spless as status. - } - // status is returned in the high 32 bits of data[0] . - // I'm not sure what the lower 32 bits are. - iv_Msg->data[0] = ( static_cast<uint64_t>(l_plid) << 32 ); - iv_Msg->data[1] = 0x0; - iv_Msg->extra_data = NULL; + TRACFCOMP( g_trac_initsvc, EXIT_MRK"IStepDispatcher::sendSyncPoint"); + return err; +} +// ---------------------------------------------------------------------------- +// IStepDispatcher::sendIstepCompleteMsg() +// ---------------------------------------------------------------------------- +errlHndl_t IStepDispatcher::sendIstepCompleteMsg() +{ + errlHndl_t err = NULL; - TRACDCOMP( g_trac_initsvc, - "MoreWorkNeeded: sendmsg t=0x%08x, d0=0x%016x, d1=0x%016x, x=%p", - iv_Msg->type, - iv_Msg->data[0], - iv_Msg->data[1], - iv_Msg->extra_data ); + TRACFCOMP( g_trac_initsvc, ENTER_MRK"IStepDispatcher::sendIstepCompleteMsg"); - // Send the potentially modified set of Attribute overrides and any - // Attributes to sync to the FSP - fapi::theAttrOverrideSync().sendAttrOverridesAndSyncsToFsp(); + //Send progress code and update clock in thread + /* 15 sec msg constraint not planned for GA1 + err = this->sendProgressCode(); + if( err ) + { + break; + } + */ - msg_respond( iv_msgQ, - iv_Msg ); - iv_Msg = NULL; - } + // Respond to the IStep message stashed in iv_pIstepMsg + mutex_lock(&iv_mutex); + uint8_t curIStep = iv_curIStep; + uint8_t curSubStep = iv_curSubStep; + msg_t * pMsg = iv_pIstepMsg; + iv_pIstepMsg = NULL; + mutex_unlock(&iv_mutex); + + if(pMsg) + { + pMsg->data[0] = 0; + msg_respond(iv_msgQ, pMsg ); + pMsg = NULL; } else { - // We should never be here... Worker message should only be doing - // something if it got a request from outside. + TRACFCOMP(g_trac_initsvc, ERR_MRK"sendIstepCompleteMsg: No message to respond to!"); + + /*@ + * @errortype + * @reasoncode NO_MSG_PRESENT + * @severity ERRORLOG::ERRL_SEV_UNRECOVERABLE + * @moduleid ISTEP_INITSVC_MOD_ID + * @userdata1 Current Istep + * @userdata2 Current SubStep + * @devdesc Request to send Istep Complete msg to Fsp, but + * no outstanding message from Fsp found. + */ + err = new ERRORLOG::ErrlEntry( ERRORLOG::ERRL_SEV_UNRECOVERABLE, + ISTEP_INITSVC_MOD_ID, + NO_MSG_PRESENT, + curIStep, + curSubStep ); } - TRACDCOMP( g_trac_initsvc, - EXIT_MRK"IStepDispatcher::handleMoreWorkNeededMsg()" ); + TRACFCOMP( g_trac_initsvc, EXIT_MRK"IStepDispatcher::sendIstepCompleteMsg"); + return err; } - // ---------------------------------------------------------------------------- -// iStepBreakPoint() +// IStepDispatcher::handleSyncPointReachedMsg() // ---------------------------------------------------------------------------- -void iStepBreakPoint ( uint32_t i_info ) +void IStepDispatcher::handleSyncPointReachedMsg(msg_t * & io_pMsg) { - TRACFCOMP( g_trac_initsvc, - ENTER_MRK"handleBreakpointMsg()" ); - IStepDispatcher::getTheInstance().handleBreakpoint( i_info ); -} + TRACFCOMP(g_trac_initsvc, ENTER_MRK"IStepDispatcher::handleSyncPointReachedMsg"); + + // Signal any IStep waiting for a sync point + mutex_lock(&iv_syncMutex); + iv_syncPointReached = true; + sync_cond_signal(&iv_syncHit); + mutex_unlock(&iv_syncMutex); + + if (msg_is_async(io_pMsg)) + { + // It is expected that Sync Point Reached messages are async + msg_free(io_pMsg); + io_pMsg = NULL; + } + else + { + // Send the message back as a response + msg_respond(iv_msgQ, io_pMsg); + io_pMsg = NULL; + } + TRACFCOMP(g_trac_initsvc, EXIT_MRK"IStepDispatcher::handleSyncPointReachedMsg"); +} // ---------------------------------------------------------------------------- -// IStepDispatcher::handleBreakpoint() +// IStepDispatcher::iStepBreakPoint() // ---------------------------------------------------------------------------- -void IStepDispatcher::handleBreakpoint ( uint32_t i_info ) +void IStepDispatcher::iStepBreakPoint(uint32_t i_info) { // Throttle the breakpoints by locking here. - mutex_lock( &iv_bkPtMutex ); + mutex_lock(&iv_bkPtMutex); errlHndl_t err = NULL; - TRACDCOMP( g_trac_initsvc, - ENTER_MRK"IStepDispatcher::handleBreakpointMsg()" ); + TRACFCOMP(g_trac_initsvc, ENTER_MRK"IStepDispatcher::handleBreakpointMsg"); - // Send Breakpoint msg to Fsp. - msg_t * myMsg = msg_allocate(); - myMsg->type = BREAKPOINT; - uint64_t tmpVal = 0x0; - tmpVal = tmpVal & i_info; - myMsg->data[0] = (tmpVal << 32); // TODO - Is this really a Fsp requirement? - myMsg->data[1] = 0x0; - myMsg->extra_data = NULL; + // Breakpoints are only supported when FSP is attached - if( MBOX::mailbox_enabled() ) + if(iv_mailboxEnabled) { - // FSP Attached - // Wait for Fsp to respond. - err = sendMboxMsg( ISTEP_SYNC, - myMsg ); - // TODO - Do we care what they sent back? Not sure... HwSvr - // has no documentation on this... - if( err ) + // Send a breakpoint message to the FSP and wait for response + msg_t * pMsg = msg_allocate(); + pMsg->type = BREAKPOINT; + pMsg->data[0] = i_info; + pMsg->data[1] = 0x0; + pMsg->extra_data = NULL; + + err = MBOX::sendrecv(HWSVRQ, pMsg); + + if(err) { - errlCommit( err, - INITSVC_COMP_ID ); + TRACFCOMP(g_trac_initsvc, ERR_MRK"handleBreakpointMsg: Error sending message"); + errlCommit(err, INITSVC_COMP_ID); + msg_free(pMsg); + pMsg = NULL; } } - else - { - // SPLESS - msg_respond( iv_msgQ, - myMsg ); - - // Now wait for spless code to respond that we're done with the - // breakpoint - msg_t * rspMsg; - rspMsg = msg_wait( iv_msgQ ); - msg_free(rspMsg); - } - msg_free( myMsg ); - TRACDCOMP( g_trac_initsvc, - EXIT_MRK"IStepDispatcher::handleBreakpointMsg()" ); - mutex_unlock( &iv_bkPtMutex ); + TRACFCOMP(g_trac_initsvc, EXIT_MRK"IStepDispatcher::handleBreakpointMsg"); + mutex_unlock(&iv_bkPtMutex); } - // ---------------------------------------------------------------------------- // IStepDispatcher::handleIStepRequestMsg() // ---------------------------------------------------------------------------- -void IStepDispatcher::handleIStepRequestMsg ( void ) +void IStepDispatcher::handleIStepRequestMsg(msg_t * & io_pMsg) { - TRACDCOMP( g_trac_initsvc, - ENTER_MRK"IStepDispatcher::handleIStepRequestMsg()" ); + errlHndl_t err = NULL; + bool l_deconfigs = false; - // Only something to do, if the worker thread is ready for work - if( iv_workerMsg ) - { - // debug - TRACDCOMP( g_trac_initsvc, - "handleIstepRequestMsg: iv_Msg: t=0x%08x, d0=0x%016x, d1=0x%016x, x=%p", - iv_Msg->type, - iv_Msg->data[0], - iv_Msg->data[1], - iv_Msg->extra_data ); - - // Set new istep/substep info - uint16_t stepInfo = ((iv_Msg->data[0] & 0x000000FF00000000) >> 24); - stepInfo = (stepInfo | (iv_Msg->data[0] & 0xFF) ); - setIstepInfo( stepInfo ); - - TRACDCOMP( g_trac_initsvc, - INFO_MRK"handleIstepRequestMsg: Istep req: 0x%04x", - stepInfo ); - - // Set step/substep in data[0]; - iv_workerMsg->data[0] = stepInfo; - msg_respond( iv_msgQ, - iv_workerMsg ); - - iv_workerMsg = NULL; - } + // find the step/substep. The step is in the top 32bits, the substep is in + // the bottom 32bits and is a byte + uint8_t istep = ((io_pMsg->data[0] & 0x000000FF00000000) >> 32); + uint8_t substep = (io_pMsg->data[0] & 0x00000000000000FF); - TRACDCOMP( g_trac_initsvc, - EXIT_MRK"IStepDispatcher::handleIStepRequestMsg()" ); -} + TRACFCOMP(g_trac_initsvc, ENTER_MRK"handleIstepRequestMsg: 0x%016x, istep: %d, substep: %d", + io_pMsg->data[0], istep, substep); + // Transfer ownership of the message pointer to iv_pIstepMsg because if the + // IStep doesn't return (start_payload), it will call sendIstepCompleteMsg + // which will respond to iv_pIstepMsg + mutex_lock(&iv_mutex); + iv_curIStep = istep; + iv_curSubStep = substep; + iv_pIstepMsg = io_pMsg; + io_pMsg = NULL; + mutex_unlock(&iv_mutex); -// ---------------------------------------------------------------------------- -// IStepDispatcher::getIStepMode() -// ---------------------------------------------------------------------------- -bool IStepDispatcher::getIStepMode( ) const -{ - using namespace TARGETING; - Target* l_pTopLevel = NULL; - bool l_istepmodeflag = false; - TargetService& l_targetService = targetService(); + err = doIstep (istep, substep, l_deconfigs); + + uint64_t status = 0; - (void)l_targetService.getTopLevelTarget( l_pTopLevel ); - if( l_pTopLevel == NULL ) + if (err) { - TRACFCOMP( g_trac_initsvc, - "Top level handle was NULL" ); - l_istepmodeflag = false; + // Commit the error and record the plid as status in the top 32bits + status = err->plid(); + status <<= 32; + errlCommit(err, INITSVC_COMP_ID); + } + + // Transfer ownership of the message pointer back from iv_pIstepMsg + mutex_lock(&iv_mutex); + io_pMsg = iv_pIstepMsg; + iv_pIstepMsg = NULL; + mutex_unlock(&iv_mutex); + + if (io_pMsg == NULL) + { + // An IStep already responded to the message!! + TRACFCOMP(g_trac_initsvc, ERR_MRK"handleIstepRequestMsg: message response already sent!"); } else { - l_istepmodeflag = l_pTopLevel->getAttr<ATTR_ISTEP_MODE> (); + if (msg_is_async(io_pMsg)) + { + // Unexpected + TRACFCOMP(g_trac_initsvc, ERR_MRK"handleIstepRequestMsg: async istep message!"); + } + else + { + io_pMsg->data[0] = status; + io_pMsg->data[1] = 0x0; + io_pMsg->extra_data = NULL; + msg_respond(iv_msgQ, io_pMsg); + io_pMsg = NULL; + } } - return l_istepmodeflag; + TRACFCOMP( g_trac_initsvc, EXIT_MRK"IStepDispatcher::handleIStepRequestMsg"); } - // ---------------------------------------------------------------------------- -// IStepDispatcher::checkMpiplMode() +// IStepDispatcher::handleProcFabIovalidMsg() // ---------------------------------------------------------------------------- -bool IStepDispatcher::checkMpiplMode( ) const +void IStepDispatcher::handleProcFabIovalidMsg(msg_t * & io_pMsg) { - using namespace TARGETING; - - Target* l_pTopLevel = NULL; - bool l_isMpiplMode = false; + TRACFCOMP(g_trac_initsvc, ENTER_MRK"IStepDispatcher::handleProcFabIovalidMsg"); - TargetService& l_targetService = targetService(); - (void)l_targetService.getTopLevelTarget( l_pTopLevel ); + // Ensure the library is loaded + errlHndl_t err = VFS::module_load("libestablish_system_smp.so"); - uint8_t is_mpipl = 0; - if(l_pTopLevel && - l_pTopLevel->tryGetAttr<ATTR_IS_MPIPL_HB>(is_mpipl) && - is_mpipl) + if (err) { - l_isMpiplMode = true; + TRACFCOMP(g_trac_initsvc, "handleProcFabIovalidMsg: Error loading module, PLID = 0x%x", + err->plid()); + errlCommit(err, INITSVC_COMP_ID); + msg_free(io_pMsg); + io_pMsg = NULL; } - - return l_isMpiplMode; -} - -void IStepDispatcher::handleProcFabIovalidMsg( ) -{ - TRACDCOMP( g_trac_initsvc, - ENTER_MRK"IStepDispatcher::handleProcFabIovalidMsg()" ); - - // make sure the needed libraries are loaded, we are in step 18 - // but hostboot does not actually load any libs until step 18.12 - // since all previous sub steps are run by the fsp. - errlHndl_t err = VFS::module_load("libedi_ei_initialization.so"); - - // if the module loaded ok, do the processing - if( err == NULL ) + else { - // do hostboot processing for istep - // sys_proc_fab_ipvalid - ESTABLISH_SYSTEM_SMP::host_sys_fab_iovalid_processing( iv_Msg ); - - // Send the message back as a response - msg_respond(iv_msgQ, iv_Msg); + // $TODO RTC:88284 - Create Child Thread + ESTABLISH_SYSTEM_SMP::host_sys_fab_iovalid_processing(io_pMsg); - // if there was an error don't winkle - if( iv_Msg->data[0] == HWSVR_MSG_SUCCESS ) + // if there was an error don't winkle ? + if(io_pMsg->data[0] == HWSVR_MSG_SUCCESS) { TRACFCOMP( g_trac_initsvc, - "$TODO RTC:71447 - winkle all cores"); + "$TODO RTC:71447 - winkle all cores"); } - } - else - { - // Send the elog id back in the message - iv_Msg->data[0] = err->eid(); - - // commmit the log so it gets to the FSP - errlCommit(err, INITSVC_COMP_ID); - - msg_respond(iv_msgQ, iv_Msg); + // Send the message back as a response + msg_respond(iv_msgQ, io_pMsg); + io_pMsg = NULL; } - TRACDCOMP( g_trac_initsvc, - EXIT_MRK"IStepDispatcher::handleProcFabIovalidMsg()" ); - - iv_Msg = NULL; + TRACFCOMP( g_trac_initsvc, EXIT_MRK"IStepDispatcher::handleProcFabIovalidMsg"); } // ---------------------------------------------------------------------------- +// IStepDispatcher::handleProcFabIovalidMsg() // This method has a default of true for i_needsLock // ---------------------------------------------------------------------------- -errlHndl_t IStepDispatcher::sendProgressCode( bool i_needsLock ) +errlHndl_t IStepDispatcher::sendProgressCode(bool i_needsLock) { if (i_needsLock) { @@ -1113,9 +1077,10 @@ errlHndl_t IStepDispatcher::sendProgressCode( bool i_needsLock ) myMsg->data[0] = iv_curIStep; myMsg->data[1] = iv_curSubStep; myMsg->extra_data = NULL; - err = sendMboxMsg( ISTEP_ASYNC, myMsg ); + err = MBOX::send(HWSVRQ, myMsg); clock_gettime(CLOCK_MONOTONIC, &iv_lastProgressMsgTime); - + TRACFCOMP( g_trac_initsvc,INFO_MRK"Progress Code %d.%d Sent", + myMsg->data[0],myMsg->data[1]); TRACDCOMP( g_trac_initsvc,EXIT_MRK"IStepDispatcher::sendProgressCode()" ); if (i_needsLock) @@ -1126,7 +1091,10 @@ errlHndl_t IStepDispatcher::sendProgressCode( bool i_needsLock ) return err; } -void IStepDispatcher::runProgressThread( void ) +// ---------------------------------------------------------------------------- +// IStepDispatcher::runProgressThread() +// ---------------------------------------------------------------------------- +void IStepDispatcher::runProgressThread() { TRACDCOMP(g_trac_initsvc, ENTER_MRK"IStepDispatcher::runProgressThread"); @@ -1166,7 +1134,10 @@ void IStepDispatcher::runProgressThread( void ) TRACDCOMP(g_trac_initsvc, EXIT_MRK"IStepDispatcher::runProgressThread"); } -void * IStepDispatcher::startProgressThread ( void * p) +// ---------------------------------------------------------------------------- +// IStepDispatcher::startProgressThread() +// ---------------------------------------------------------------------------- +void * IStepDispatcher::startProgressThread(void * p) { IStepDispatcher * l_pDispatcher = reinterpret_cast<IStepDispatcher *>(p); TRACDCOMP(g_trac_initsvc,INFO_MRK"startProgressThread: runProgressThread"); @@ -1174,4 +1145,77 @@ void * IStepDispatcher::startProgressThread ( void * p) return NULL; } +// ---------------------------------------------------------------------------- +// IStepDispatcher::startMsgHndlrThread() +// ---------------------------------------------------------------------------- +void * IStepDispatcher::startMsgHndlrThread(void * p) +{ + IStepDispatcher * l_pDispatcher = reinterpret_cast<IStepDispatcher *>(p); + TRACDCOMP(g_trac_initsvc,INFO_MRK"msgHndlrThread"); + l_pDispatcher->msgHndlr(); + return NULL; +} + +// ---------------------------------------------------------------------------- +// IStepDispatcher::checkReconfig() +// ---------------------------------------------------------------------------- +bool IStepDispatcher::checkReconfig(const uint8_t i_curIstep, + const uint8_t i_curSubstep, + uint8_t & o_newIstep, + uint8_t & o_newSubstep) +{ + bool doReconfigure = false; + TRACDCOMP(g_trac_initsvc, ENTER_MRK"IStepDispatcher::checkReconfig(): istep %d.%d", + i_curIstep, i_curSubstep); + + uint16_t current = (i_curIstep << 8) | i_curSubstep; + const uint16_t INNER_START = (INNER_START_STEP << 8) | INNER_START_SUBSTEP; + const uint16_t INNER_STOP = (INNER_STOP_STEP << 8) | INNER_STOP_SUBSTEP; + const uint16_t OUTER_START = (OUTER_START_STEP << 8) | OUTER_START_SUBSTEP; + const uint16_t OUTER_STOP = (OUTER_STOP_STEP << 8) | OUTER_STOP_SUBSTEP; + + if ((current >= INNER_START) && (current <= INNER_STOP)) + { + doReconfigure = true; + o_newIstep = INNER_START_STEP; + o_newSubstep = INNER_START_SUBSTEP; + } + else if ((current >= OUTER_START) && (current <= OUTER_STOP)) + { + doReconfigure = true; + o_newIstep = OUTER_START_STEP; + o_newSubstep = OUTER_START_SUBSTEP; + } + + TRACDCOMP(g_trac_initsvc, EXIT_MRK"IStepDispatcher::checkReconfig: reconfig new istep/substep: %d %d.%d", + doReconfigure, o_newIstep, o_newSubstep); + + return doReconfigure; +} + +// ---------------------------------------------------------------------------- +// Extarnal functions defined that map directly to IStepDispatcher public member +// functions. +// Defined in istepdispatcherif.H, initsvcbreakpoint.H +// ---------------------------------------------------------------------------- +void waitForSyncPoint() +{ + IStepDispatcher::getTheInstance().waitForSyncPoint(); +} + +errlHndl_t sendSyncPoint() +{ + return IStepDispatcher::getTheInstance().sendSyncPoint(); +} + +errlHndl_t sendIstepCompleteMsg() +{ + return IStepDispatcher::getTheInstance().sendIstepCompleteMsg(); +} + +void iStepBreakPoint(uint32_t i_info) +{ + IStepDispatcher::getTheInstance().iStepBreakPoint( i_info ); +} + } // namespace diff --git a/src/usr/initservice/istepdispatcher/istepdispatcher.H b/src/usr/initservice/istepdispatcher/istepdispatcher.H index 1048b9c75..077a8d869 100644 --- a/src/usr/initservice/istepdispatcher/istepdispatcher.H +++ b/src/usr/initservice/istepdispatcher/istepdispatcher.H @@ -29,28 +29,21 @@ * */ -/** - * @page IStepDispatcher IStep Dispatcher - * - * - */ - - /******************************************************************************/ // Includes /******************************************************************************/ -#include <stdint.h> -#include <time.h> -#include <util/singleton.H> -#include <sys/msg.h> -#include <sys/sync.h> -#include <errl/errlentry.H> -#include <initservice/taskargs.H> -#include <initservice/initsvcreasoncodes.H> -#include <initservice/initsvcstructs.H> -#include "../baseinitsvc/initservice.H" -#include "splesscommon.H" -#include "istep_mbox_msgs.H" +#include <stdint.h> +#include <time.h> +#include <util/singleton.H> +#include <sys/msg.h> +#include <sys/sync.h> +#include <errl/errlentry.H> +#include <initservice/taskargs.H> +#include <initservice/initsvcreasoncodes.H> +#include <initservice/initsvcstructs.H> +#include "../baseinitsvc/initservice.H" +#include "splesscommon.H" +#include "istep_mbox_msgs.H" namespace INITSERVICE { @@ -81,20 +74,6 @@ const uint64_t MAX_WAIT_TIME_SEC = 10; void* spTask ( void *io_pArgs ); /** - * @brief enums for whether the messages IStepdispatcher sends are synchronus - * or asynchronous. - */ -enum IStepSync_t -{ - ISTEP_SYNC, - ISTEP_ASYNC, -}; - -/******************************************************************************/ -// Class IStepDispatcher -/******************************************************************************/ - -/** * @class IStepDispatcher * * Dispatch ISteps and handle return codes, errorlogs, etc. @@ -108,106 +87,70 @@ public: /** * @brief Get singleton instance of this class. * - * @return the (one and only) instance of IStepDispatcher + * @return the (one and only) instance of IStepDispatcher */ static IStepDispatcher& getTheInstance(); /** - * @brief This function is what is called to startup the main istep - * dispatcher thread. + * @brief Initialize + * + * IStep Mode: Waits for messages + * Non-IStep Mode: Executes all ISteps * * @param[in/out] io_rtaskRetErrl - Errorlog pointer to be returned for * any errors that might have been encountered. - * - * @return NONE. */ - void init ( errlHndl_t &io_rtaskRetErrl ); + void init (errlHndl_t &io_rtaskRetErrl); /** - * @brief This function is used to send a sync point message from Hostboot - * to the Fsp. + * @brief Send a SyncPoint * - * @return errlHndl_t - NULL if successful, otherwise a pointer to the - * error log. + * Called by an IStep to send a sync point message to the FSP. A message + * is not sent in IStep mode or SPLess mode. + * + * @return errlHndl_t */ - errlHndl_t sendSyncPoint ( void ); + errlHndl_t sendSyncPoint(); /** - * @brief This function is used for calling code to be held off waiting - * for a syncpoint message from an external source. Anyone calling - * this will be blocked on this call until ANY sync point message is - * received. Once received, each caller in succession will be - * released. + * @brief Wait for a SyncPoint * - * @return NONE. + * Called by an IStep to wait for a sync point message from the FSP. This + * returns immediately in IStep mode or SPLess mode because no sync points + * will be sent */ - void waitForSyncPoint ( void ); + void waitForSyncPoint(); /** - * @brief This function when called will send a Istep complete mailbox - * message to the Fsp to indicate that the current Istep is complete. + * @brief Sends an IStepComplete message + * + * Only called by ISteps that do not return and need to repsond to the + * IStep request message (i.e. start_payload), this should only be called + * in IStep mode. * * @return errlHndl_t - NULL if successful, otherwise a pointer to the * error log. */ - errlHndl_t sendIstepCompleteMsg ( void ); + errlHndl_t sendIstepCompleteMsg(); /** - * @brief This function will handle all breakpoint requests from the - * running istep code. The running istep code would be initiated via - * the istep dispatcher worker thread. Thus, holding off the worker - * thread. + * @brief Handles a breakpoint request from an IStep + * + * Sends a BREAKPOINT message to the FSP and waits for a response * * @param[in] i_info - TODO - this needs to be decided yet. But it seems * at least preliminarily that this will contain a unique breakpoint * numbering value. - * - * @return NONE. - */ - void handleBreakpoint ( uint32_t i_info ); - - /** - * @brief This function will return the current istep and substep. - * - * @param[out] o_iStep - The current Istep value. - * - * @param[out] o_subStep - The current SubStep value. - * - * @return NONE. - */ - void getIstepInfo ( uint8_t & o_iStep, - uint8_t & o_subStep ); - - /** - * @brief This function will return whether or not we are in MPIPL mode - * - * @return bool - flag indicating whether we're in MPIPL mode - * @retval false if not in MPIPL mode - * true if in MPIPL mode - */ - bool isMpiplMode( void ) const - { - return iv_mpipl_mode; - } - - /** - * @brief getIStepMode - return value of IStep Mode - * - * @return bool - value of iv_istepmodeflag - * @retval false if IStep Mode is "OFF" - * true if IStep Mode is "ON" */ - bool getIStepMode( ) const; + void iStepBreakPoint(uint32_t i_info); /** * @brief This function sends a progress message if an istep/substep takes * longer than MAX_WAIT_TIME_SEC. This function never returns and * should only be called on a new thread by the startProgressThread * function - * - * @return NONE. */ - void runProgressThread ( void ); + void runProgressThread(); protected: @@ -216,7 +159,6 @@ protected: */ IStepDispatcher(); - /** * @brief Destructor for the IStepDispatcher object. */ @@ -225,140 +167,165 @@ protected: private: /** - * @note Disable copy constructor and assignment operator + * @note Disable copy constructor and assignment operator */ IStepDispatcher(const IStepDispatcher& i_right); IStepDispatcher& operator=(const IStepDispatcher& i_right); - /** - * @brief This function will start at istep 0, substep 0, and cycle - * through all possible isteps, returning when complete, or an error - * is hit. + * @brief Executes all ISteps * - * @return errlHndl_t - NULL if successful, otherwise a pointer to an - * error log. + * @return errlHndl_t */ - errlHndl_t executeAllISteps ( void ); + errlHndl_t executeAllISteps(); /** - * @brief This function is the main handler loop for the Istep Dispatcher. - * it receives all messages from outside sources and initiates the - * proper action and response (if required). + * @brief Executes the given istep * - * @return errlHndl_t - NULL if successful, otherwise a pointer to an - * error log. + * @param[in] i_istep The istep to be executed. + * @param[in] i_substep The substep to be executed. + * @param[out] o_deconfigs If error returned then true if HW was + * deconfigured during the istep + * @return errlHndl_t */ - errlHndl_t msgHndlr ( void ); + errlHndl_t doIstep(uint32_t i_istep, + uint32_t i_substep, + bool & o_deconfigs); /** - * @brief This function is used to send mailbox messages to the Fsp. - * - * @param[in] i_sendSync - The sync type of message to send. Whether - * synchronous or asynchronous. - * - * @param[in] i_msg - The message to send to the Fsp. - * - * @return errlHndl_t - NULL if successful, otherwise a pointer to an - * error log. + * @brief Handles all messages from the FSP or SPless user console */ - errlHndl_t sendMboxMsg ( IStepSync_t i_sendSync, - msg_t * i_msg ); + void msgHndlr(); /** - * @brief This function is used for all of the Syncpoint message handling. + * @brief Handles a SyncPointReached message. + * + * Signals any IStep thread waiting for a SyncPoint * - * @return NONE. + * @param[io] io_pMsg Reference to pointer to message (cleaned up) */ - void handleSyncPointReachedMsg ( void ); + void handleSyncPointReachedMsg(msg_t * & io_pMsg); /** - * @brief This function is used to handle the message from the worker - * thread requesting more work. + * @brief Handles a ProcFabIovalid message. * - * @param[in] i_first - TRUE for the very first call. FALSE afterward + * Executes the processing required for the sys_proc_fab_iovalid istep * - * @return NONE. + * @param[io] io_pMsg Reference to pointer to message (cleaned up) */ - void handleMoreWorkNeededMsg ( bool i_first ); + void handleProcFabIovalidMsg(msg_t * & io_pMsg); /** - * @brief This function is used to handle the message from the FSP - * telling hostboot to execute the processing required for - * the sys_proc_fab_iovalid istep + * @brief Handles an IStepRequest message + * + * Executes the requested IStep and returns result in response message * - * @return NONE. + * @param[io] io_pMsg Reference to pointer to message (cleaned up) */ - void handleProcFabIovalidMsg( void ); + void handleIStepRequestMsg(msg_t * & io_pMsg); - /** - * @brief This function is used to handle the single Istep requests from - * outside sources. + /** + * @brief This function will be used to query the istep master list and the + * other istep headers to know what functions/tasks need to be started + * for the Istep/Substep that we are in. + * + * @param[in] i_IStep - The Istep to run. + * @param[in] i_SubStep - The SubStep to run. * - * @return NONE. + * @return TaskInfo - The task info for the task to start as a result of the + * requested Istep/Substep. */ - void handleIStepRequestMsg ( void ); + const TaskInfo * findTaskInfo(const uint32_t i_IStep, + const uint32_t i_SubStep); /** - * @brief This function is used to set the current Istep and Substep - * values for what is currently running. - * - * @return NONE. + * @brief This function loads the modules for each new Istep */ - void setIstepInfo ( uint16_t i_type ); + void loadModules(uint32_t istepNumber) const; + /** + * @brief This function unloads the modules for each new Istep + */ + void unLoadModules(uint32_t istepNumber) const; /** - * @brief This function will check whether or not we are in MPIPL mode + * @brief This function will check if FSP attribute sync is enabled * - * @return bool - flag indicating whether we're in MPIPL mode - * @retval false if not in MPIPL mode - * true if in MPIPL mode + * @return bool - True if sync is enabled, false otherwise. */ - bool checkMpiplMode ( void ) const; + bool isAttrSyncEnabled() const; /** - * @brief This function is used to send a progress message from Hostboot - * to Fsp. + * @brief Checks if a deconfigure happened inside a set of isteps and can be + * reconfigured to try again. * - * param[in] - flag to acquire mutex or not + * @param[in] i_curIstep current istep + * @param[in] i_curSubstep current substep + * @param[out] o_newIstep new Istep to run, if necessary + * @param[out] o_newSubstep new Substep to run, if necessary * - * @return errlHndl_t - NULL if successful, otherwise a pointer to the - * error log. + * @return bool - True if the reconfigure happened inside the set of + * neccessary isteps and needs to be retried, false otherwise */ - errlHndl_t sendProgressCode ( bool i_needsLock = true ); + static bool checkReconfig(const uint8_t i_curIstep, + const uint8_t i_curSubstep, + uint8_t & o_newIstep, + uint8_t & o_newSubstep); /** - * @brief This function spawns a thread for runProgressThread to run on + * @brief Sends a progress message from Hostboot to Fsp. + * + * param[in] i_needsLock flag to acquire mutex or not * - * param[in,out] - pointer to any args + * @return errlHndl_t + */ + errlHndl_t sendProgressCode(bool i_needsLock = true); + + /** + * @brief This function is called on a dedicated task to post progress codes * - * @return NONE + * param[in] p Pointer to any args */ static void * startProgressThread ( void * p); - // ----- internal vars ----------------------------- - - mutex_t iv_bkPtMutex; - mutex_t iv_syncMutex; - mutex_t iv_mutex; //used to synchronize access to all instance - //variables except iv_sync which is handled by - //iv_syncMutex/iv_syncHit - sync_cond_t iv_syncHit; - uint8_t iv_curIStep; - uint8_t iv_curSubStep; - bool iv_sync; - bool iv_mpipl_mode; //flag indicating whether we're in MPIPL mode - msg_q_t iv_msgQ; - msg_t* iv_workerMsg; // More work Needed Msg from Worker - msg_t* iv_Msg; // All other Msgs that need to be saved - bool iv_progressThreadStarted; + /** + * @brief This function is called on a dedicated task to run the MsgHndlr + * + * param[in] p Pointer to any args + */ + static void * startMsgHndlrThread ( void * p); + + // Instance variables + + // Mutexes + mutable mutex_t iv_bkPtMutex; // Used to throttle breakpoints + mutable mutex_t iv_mutex; //used to synchronize access to all instance + //variables except iv_syncPointReached + + // Used for waiting for and signalling Sync Points + mutable mutex_t iv_syncMutex; + mutable sync_cond_t iv_syncHit; + bool iv_syncPointReached; - //For progress code messages - timespec_t iv_lastProgressMsgTime; + // Set once in the constructor, mutex protection not needed + bool iv_mpiplMode; + bool iv_istepMode; + bool iv_spBaseServicesEnabled; + bool iv_mailboxEnabled; -}; // class IStepDispatcher + // Used in only one thread, mutex protection not needed + uint32_t iv_istepModulesLoaded; + bool iv_progressThreadStarted; + + // Used in multiple threads, mutex protection needed + uint8_t iv_curIStep; // Current Step + uint8_t iv_curSubStep; // Current SubStep + msg_t* iv_pIstepMsg; // External Istep request message + timespec_t iv_lastProgressMsgTime; // Last time progress message sent + // Message Queue for receiving message from SP or SPless user console + msg_q_t iv_msgQ; +}; } // namespace diff --git a/src/usr/initservice/istepdispatcher/makefile b/src/usr/initservice/istepdispatcher/makefile index fbcf0ea18..550a4644d 100644 --- a/src/usr/initservice/istepdispatcher/makefile +++ b/src/usr/initservice/istepdispatcher/makefile @@ -30,7 +30,7 @@ EXTRAINCDIR += ${ROOTPATH}/src/include/usr/hwpf/plat EXTRAINCDIR += ${ROOTPATH}/src/include/usr/hwpf/hwp OBJS = istepdispatcher.o initsvcudistep.o \ - sptask.o splesscommon.o istepWorker.o + sptask.o splesscommon.o ## SUBDIRS = test.d |