TI_STATUS TWD_Stop (TI_HANDLE hTWD) { TTwd *pTWD = (TTwd *)hTWD; ETxnStatus status; fwEvent_Stop (pTWD->hFwEvent); /* close all BA sessions */ TWD_CloseAllBaSessions(hTWD); cmdMbox_Restart (pTWD->hCmdMbox); cmdQueue_Restart (pTWD->hCmdQueue); cmdQueue_DisableMbox (pTWD->hCmdQueue); eventMbox_Stop (pTWD->hEventMbox); MacServices_restart (pTWD->hMacServices); status = twIf_Restart(pTWD->hTwIf); /* Call user stop callback */ if (status != TXN_STATUS_PENDING) { TWD_StopComplete (hTWD); } return TI_OK; }
/* * \brief FW-Event state machine * * \param hFwEvent - FwEvent Driver handle * \return void * * \par Description * * Process the current FW events in a sequence that may progress in the same context, * or exit if pending an Async transaction, which will call back the SM when finished. * * \sa */ static void fwEvent_StateMachine (TfwEvent *pFwEvent) { ETxnStatus eStatus = TXN_STATUS_ERROR; /* Set to error to detect if used uninitialized */ CL_TRACE_START_L3(); /* * Loop through the states sequence as long as the process is synchronous. * Exit when finished or if an Asynchronous process is required. * In this case the SM will be called back upon Async operation completion. */ while (1) { switch (pFwEvent->eSmState) { /* IDLE: Update TwIf and read interrupt info from FW */ case FWEVENT_STATE_IDLE: { CL_TRACE_START_L5(); twIf_Awake(pFwEvent->hTwIf); eStatus = fwEvent_SmReadIntrInfo (pFwEvent); pFwEvent->eSmState = FWEVENT_STATE_WAIT_INTR_INFO; CL_TRACE_END_L5("tiwlan_drv.ko", "CONTEXT", "FwEvent", ".ReadInfo"); break; } /* WAIT_INTR_INFO: We have the interrupt info so call the handlers accordingly */ case FWEVENT_STATE_WAIT_INTR_INFO: { CL_TRACE_START_L5(); eStatus = fwEvent_SmHandleEvents (pFwEvent); /* If state was changed to IDLE by recovery or stop process, exit (process terminated) */ if (pFwEvent->eSmState == FWEVENT_STATE_IDLE) { CL_TRACE_END_L5("tiwlan_drv.ko", "CONTEXT", "FwEvent", ".HndlEvents"); CL_TRACE_END_L3("tiwlan_drv.ko", "CONTEXT", "FwEvent", ""); return; } pFwEvent->eSmState = FWEVENT_STATE_WAIT_HANDLE_COMPLT; CL_TRACE_END_L5("tiwlan_drv.ko", "CONTEXT", "FwEvent", ".HndlEvents"); break; } /* WAIT_HANDLE_COMPLT: Current handling is completed. */ case FWEVENT_STATE_WAIT_HANDLE_COMPLT: { /* If pending interrupt, read interrupt info (back to WAIT_INTR_INFO state) */ if (pFwEvent->bIntrPending) { CL_TRACE_START_L5(); pFwEvent->bIntrPending = TI_FALSE; eStatus = fwEvent_SmReadIntrInfo (pFwEvent); pFwEvent->eSmState = FWEVENT_STATE_WAIT_INTR_INFO; CL_TRACE_END_L5("tiwlan_drv.ko", "CONTEXT", "FwEvent", ".HndlCmplt"); } /* Else - all done so release TwIf to sleep and exit */ else { twIf_Sleep(pFwEvent->hTwIf); pFwEvent->eSmState = FWEVENT_STATE_IDLE; TRACE3(pFwEvent->hReport, REPORT_SEVERITY_INFORMATION, "fwEvent_StateMachine: Completed, NewState=%d, Status=%d, IntrPending=%d\n", pFwEvent->eSmState, eStatus, pFwEvent->bIntrPending); CL_TRACE_END_L3("tiwlan_drv.ko", "CONTEXT", "FwEvent", ""); /**** Finished all current events handling so exit ****/ return; } break; } } /* switch */ TRACE3(pFwEvent->hReport, REPORT_SEVERITY_INFORMATION, "fwEvent_StateMachine: NewState=%d, Status=%d, IntrPending=%d\n", pFwEvent->eSmState, eStatus, pFwEvent->bIntrPending); /* If last status is Pending, exit the SM (to be called back upon Async operation completion) */ if (eStatus == TXN_STATUS_PENDING) { CL_TRACE_END_L3("tiwlan_drv.ko", "CONTEXT", "FwEvent", ""); return; } /* If error occured, stop the process and exit (should be cleaned by recovery process) */ else if (eStatus == TXN_STATUS_ERROR) { TRACE5(pFwEvent->hReport, REPORT_SEVERITY_ERROR, "fwEvent_StateMachine: NewState=%d, Status=%d, IntrPending=%d, EventVector=0x%x, EventMask=0x%x\n", pFwEvent->eSmState, eStatus, pFwEvent->bIntrPending, pFwEvent->uEventVector, pFwEvent->uEventMask); CL_TRACE_END_L3("tiwlan_drv.ko", "CONTEXT", "FwEvent", ""); fwEvent_Stop ((TI_HANDLE)pFwEvent); return; } /* If we got here the status is COMPLETE so continue in the while loop to the next state */ } /* while */ }
/* * \brief FW-Event state machine * * \param hFwEvent - FwEvent Driver handle * \return void * * \par Description * * Process the current FW events in a sequence that may progress in the same context, * or exit if pending an Async transaction, which will call back the SM when finished. * * \sa */ static void fwEvent_StateMachine (TfwEvent *pFwEvent) { ETxnStatus eStatus = TXN_STATUS_ERROR; /* Set to error to detect if used uninitialized */ /* * Loop through the states sequence as long as the process is synchronous. * Exit when finished or if an Asynchronous process is required. * In this case the SM will be called back upon Async operation completion. */ while (1) { switch (pFwEvent->eSmState) { /* IDLE: Update TwIf and read interrupt info from FW */ case FWEVENT_STATE_IDLE: { twIf_Awake(pFwEvent->hTwIf); eStatus = fwEvent_SmReadIntrInfo (pFwEvent); pFwEvent->eSmState = FWEVENT_STATE_WAIT_INTR_INFO; break; } /* WAIT_INTR_INFO: We have the interrupt info so call the handlers accordingly */ case FWEVENT_STATE_WAIT_INTR_INFO: { eStatus = fwEvent_SmHandleEvents (pFwEvent); /* If state was changed to IDLE by recovery or stop process, exit (process terminated) */ if (pFwEvent->eSmState == FWEVENT_STATE_IDLE) { return; } pFwEvent->eSmState = FWEVENT_STATE_WAIT_HANDLE_COMPLT; break; } /* WAIT_HANDLE_COMPLT: Current handling is completed. */ case FWEVENT_STATE_WAIT_HANDLE_COMPLT: { /* If pending interrupt, read interrupt info (back to WAIT_INTR_INFO state) */ if (pFwEvent->bIntrPending) { pFwEvent->bIntrPending = TI_FALSE; eStatus = fwEvent_SmReadIntrInfo (pFwEvent); pFwEvent->eSmState = FWEVENT_STATE_WAIT_INTR_INFO; } /* Else - all done so release TwIf to sleep and exit */ else { twIf_Sleep(pFwEvent->hTwIf); pFwEvent->eSmState = FWEVENT_STATE_IDLE; /**** Finished all current events handling so exit ****/ return; } break; } } /* switch */ /* If last status is Pending, exit the SM (to be called back upon Async operation completion) */ if (eStatus == TXN_STATUS_PENDING) { return; } /* If error occured, stop the process and exit (should be cleaned by recovery process) */ else if (eStatus == TXN_STATUS_ERROR) { fwEvent_Stop ((TI_HANDLE)pFwEvent); return; } /* If we got here the status is COMPLETE so continue in the while loop to the next state */ } /* while */ }