From 5fddfa6e7b67e3ffe96e5b232646363a99edf1d1 Mon Sep 17 00:00:00 2001 From: Stephen Cprek Date: Thu, 22 Aug 2013 14:49:22 -0500 Subject: Added progress codes messages to be sent to FSP Change-Id: I34b81310b2936481244afb3992f8f2a51aebea29 RTC: 34046 Reviewed-on: http://gfw160.austin.ibm.com:8080/gerrit/5887 Tested-by: Jenkins Server Reviewed-by: Brian H. Horton Reviewed-by: A. Patrick Williams III --- .../initservice/istepdispatcher/istep_mbox_msgs.H | 4 +- .../initservice/istepdispatcher/istepdispatcher.C | 148 ++++++++++++++++++--- .../initservice/istepdispatcher/istepdispatcher.H | 46 ++++++- 3 files changed, 173 insertions(+), 25 deletions(-) diff --git a/src/usr/initservice/istepdispatcher/istep_mbox_msgs.H b/src/usr/initservice/istepdispatcher/istep_mbox_msgs.H index f07545388..00e94faa2 100644 --- a/src/usr/initservice/istepdispatcher/istep_mbox_msgs.H +++ b/src/usr/initservice/istepdispatcher/istep_mbox_msgs.H @@ -54,6 +54,7 @@ enum { HWSVR_BREAKPOINT = 0x00, HWSVR_SYNC_POINT = 0x10, + HWSVR_IPL_PROGRESS_CODE = 0x11, HWSVR_DO_IOVALID_PROCESSING = 0xC1, }; @@ -78,6 +79,8 @@ enum HWSVR_BREAKPOINT, PROCESS_IOVALID_REQUEST = MBOX::FIRST_UNSECURE_MSG | HWSVR_DO_IOVALID_PROCESSING, + IPL_PROGRESS_CODE = MBOX::FIRST_UNSECURE_MSG | + HWSVR_IPL_PROGRESS_CODE, // -------------------------------------------------------------- // Worker Thread Messages @@ -88,7 +91,6 @@ enum 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 5c3cd2d82..959c11ac0 100644 --- a/src/usr/initservice/istepdispatcher/istepdispatcher.C +++ b/src/usr/initservice/istepdispatcher/istepdispatcher.C @@ -36,6 +36,7 @@ #include #include #include +#include //nanosleep #include // printk status @@ -87,6 +88,7 @@ trace_desc_t *g_trac_isteps_trace = NULL; namespace INITSERVICE { + using namespace ERRORLOG; // IStepNameUserDetails using namespace SPLESS; // SingleStepMode @@ -110,12 +112,13 @@ IStepDispatcher::IStepDispatcher () { mutex_init( &iv_bkPtMutex ); mutex_init( &iv_syncMutex ); - mutex_init( &iv_stepMutex ); + mutex_init( &iv_mutex ); sync_cond_init( &iv_syncHit ); - iv_curIStep = 0x0; - iv_curSubStep = 0x0; + setIstepInfo(0); iv_sync = false; + iv_progressThreadStarted = false; + clock_gettime(CLOCK_MONOTONIC, &iv_lastProgressMsgTime); // Save flag indicating whether we're in MPIPL mode iv_mpipl_mode = checkMpiplMode(); @@ -132,6 +135,18 @@ IStepDispatcher::IStepDispatcher () // ---------------------------------------------------------------------------- IStepDispatcher::~IStepDispatcher () { + TRACFCOMP( g_trac_initsvc, ENTER_MRK "IStepDispatcher::~IStepDispatcher " + "destructor" ); + + // Singleton destructor gets run when module gets unloaded. + // The istepdispatcher module never gets unloaded. So rather to send a + // message to error log daemon and tell it to shutdow and delete + // the queue we will assert here because the destructor never gets + // call. + assert(0); + + TRACFCOMP( g_trac_initsvc, EXIT_MRK "IStepDispatcher::~IStepDispatcher " + "destructor." ); } @@ -285,8 +300,7 @@ errlHndl_t IStepDispatcher::executeAllISteps ( void ) errlHndl_t err = NULL; msg_t * theMsg = NULL; - TRACFCOMP( g_trac_initsvc, - ENTER_MRK"IStepDispatcher::executeAllISteps()" ); + TRACFCOMP( g_trac_initsvc, ENTER_MRK"IStepDispatcher::executeAllISteps()"); do { @@ -294,17 +308,15 @@ errlHndl_t IStepDispatcher::executeAllISteps ( void ) // work needed msg from worker thread. uint32_t prevIstep = 0; uint32_t prevSubStep = 0; + for( size_t istep = 0; istep < MaxISteps; istep++ ) { - // Run until num items +1, to be sure we know the last step - // finished for( size_t substep = 0; - substep < (g_isteps[istep].numitems+1) ; - substep++ ) + 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 @@ -319,7 +331,6 @@ errlHndl_t IStepDispatcher::executeAllISteps ( void ) 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 ); @@ -327,6 +338,7 @@ errlHndl_t IStepDispatcher::executeAllISteps ( void ) // 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 ); @@ -361,23 +373,37 @@ errlHndl_t IStepDispatcher::executeAllISteps ( void ) } TRACFCOMP( g_trac_initsvc, - INFO_MRK"executeAllSteps: " + 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 ) + { + 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 @@ -646,6 +672,15 @@ errlHndl_t IStepDispatcher::sendIstepCompleteMsg ( void ) do { + //Send progress code and update clock in thread + /* 15 sec msg constraint not planned for GA1 + err = this->sendProgressCode(); + if( err ) + { + break; + } + */ + // We just need to respond back to the outstanding iv_Msg we should // already have if( iv_Msg ) @@ -736,10 +771,10 @@ errlHndl_t IStepDispatcher::sendMboxMsg ( IStepSync_t i_sendSync, void IStepDispatcher::getIstepInfo ( uint8_t & o_iStep, uint8_t & o_subStep ) { - mutex_lock( &iv_stepMutex ); + mutex_lock( &iv_mutex ); o_iStep = iv_curIStep; o_subStep = iv_curSubStep; - mutex_unlock( &iv_stepMutex ); + mutex_unlock( &iv_mutex ); } @@ -748,10 +783,10 @@ void IStepDispatcher::getIstepInfo ( uint8_t & o_iStep, // ---------------------------------------------------------------------------- void IStepDispatcher::setIstepInfo ( uint16_t i_type ) { - mutex_lock( &iv_stepMutex ); + mutex_lock( &iv_mutex ); iv_curIStep = ((i_type & 0xFF00) >> 8); iv_curSubStep = (i_type & 0xFF); - mutex_unlock( &iv_stepMutex ); + mutex_unlock( &iv_mutex ); } @@ -789,8 +824,7 @@ void IStepDispatcher::handleMoreWorkNeededMsg ( bool i_first ) // Clear out current Istep/substep values. Since worker thread told us // its done, nothing is running right now. - iv_curIStep = 0x0; - iv_curSubStep = 0x0; + setIstepInfo(0); // Only something to do if we've gotten a request from Fsp or SPLESS if( iv_Msg ) @@ -1052,7 +1086,79 @@ void IStepDispatcher::handleProcFabIovalidMsg( ) iv_Msg = NULL; } +// ---------------------------------------------------------------------------- +// This method has a default of true for i_needsLock +// ---------------------------------------------------------------------------- +errlHndl_t IStepDispatcher::sendProgressCode( bool i_needsLock ) +{ + if (i_needsLock) + { + mutex_lock( &iv_mutex ); + } -} // namespace + TRACDCOMP( g_trac_initsvc,ENTER_MRK"IStepDispatcher::sendProgressCode()"); + errlHndl_t err = NULL; + // Put in rolling bit RTC: 84794 + msg_t * myMsg = msg_allocate(); + myMsg->type = IPL_PROGRESS_CODE; + myMsg->data[0] = iv_curIStep; + myMsg->data[1] = iv_curSubStep; + myMsg->extra_data = NULL; + err = sendMboxMsg( ISTEP_ASYNC, myMsg ); + clock_gettime(CLOCK_MONOTONIC, &iv_lastProgressMsgTime); + + TRACDCOMP( g_trac_initsvc,EXIT_MRK"IStepDispatcher::sendProgressCode()" ); + + if (i_needsLock) + { + mutex_unlock( &iv_mutex ); + } + + return err; +} + +void IStepDispatcher::runProgressThread( void ) +{ + TRACDCOMP(g_trac_initsvc, ENTER_MRK"IStepDispatcher::runProgressThread"); + + timespec_t l_CurTime; + timespec_t l_PrevTime; + //errlHndl_t err = NULL; + + mutex_lock( &iv_mutex ); + while(1) + { + l_PrevTime = iv_lastProgressMsgTime; + clock_gettime(CLOCK_MONOTONIC, &l_CurTime); + if( (l_CurTime.tv_sec - l_PrevTime.tv_sec) < MAX_WAIT_TIME_SEC ) + { + mutex_unlock( &iv_mutex ); + nanosleep( MAX_WAIT_TIME_SEC - (l_CurTime.tv_sec - + l_PrevTime.tv_sec), 0 ); + mutex_lock( &iv_mutex ); + } + + /* 15 sec msg constraint not planned for GA1 + if( l_PrevTime.tv_sec == iv_lastProgressMsgTime.tv_sec && + l_PrevTime.tv_nsec == iv_lastProgressMsgTime.tv_nsec) + { + err = this->sendProgressCode(false); + commit error in future + } + */ + } + + TRACDCOMP(g_trac_initsvc, EXIT_MRK"IStepDispatcher::runProgressThread"); +} + +void * IStepDispatcher::startProgressThread ( void * p) +{ + IStepDispatcher * l_pDispatcher = reinterpret_cast(p); + TRACDCOMP(g_trac_initsvc,INFO_MRK"startProgressThread: runProgressThread"); + l_pDispatcher->runProgressThread(); + return NULL; +} + +} // namespace diff --git a/src/usr/initservice/istepdispatcher/istepdispatcher.H b/src/usr/initservice/istepdispatcher/istepdispatcher.H index 2ad5eb8b5..1048b9c75 100644 --- a/src/usr/initservice/istepdispatcher/istepdispatcher.H +++ b/src/usr/initservice/istepdispatcher/istepdispatcher.H @@ -40,6 +40,7 @@ // Includes /******************************************************************************/ #include +#include #include #include #include @@ -58,6 +59,12 @@ namespace INITSERVICE // Globals/Constants /******************************************************************************/ +/** + * @brief the maximum time (seconds) runProgressThread() waits to send the next + * progress code (FSP requires a message every 15 sec). Picking 10 sec + * is a good choice because it is sufficiently less than 15. + */ +const uint64_t MAX_WAIT_TIME_SEC = 10; /******************************************************************************/ // Typedef/Enumerations @@ -83,7 +90,6 @@ enum IStepSync_t ISTEP_ASYNC, }; - /******************************************************************************/ // Class IStepDispatcher /******************************************************************************/ @@ -193,7 +199,15 @@ public: */ bool getIStepMode( ) const; - + /** + * @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 ); protected: @@ -303,12 +317,33 @@ private: */ bool checkMpiplMode ( void ) const; + /** + * @brief This function is used to send a progress message from Hostboot + * to Fsp. + * + * param[in] - flag to acquire mutex or not + * + * @return errlHndl_t - NULL if successful, otherwise a pointer to the + * error log. + */ + errlHndl_t sendProgressCode ( bool i_needsLock = true ); + + /** + * @brief This function spawns a thread for runProgressThread to run on + * + * param[in,out] - pointer to any args + * + * @return NONE + */ + static void * startProgressThread ( void * p); // ----- internal vars ----------------------------- mutex_t iv_bkPtMutex; mutex_t iv_syncMutex; - mutex_t iv_stepMutex; + 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; @@ -317,6 +352,11 @@ private: 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; + + //For progress code messages + timespec_t iv_lastProgressMsgTime; + }; // class IStepDispatcher -- cgit v1.2.1