/** * \fn txDataQ_ClearQueues * \brief Clear all queues * * Dequeue and free all queued packets. * * \note * \param hTxDataQ - The object * \return void * \sa */ void txDataQ_ClearQueues (TI_HANDLE hTxDataQ) { TI_UINT32 uHlid; /* * init all queues in all links */ for (uHlid = 0; uHlid < WLANLINKS_MAX_LINKS; uHlid++) { txDataQ_FlushLinkQueues(hTxDataQ, uHlid); } }
/** * \fn mgmtQueuesSM * \brief The module state-machine (static function) * * The SM follows the system management states (see ETxConnState) and the Mgmt queues * status (empty or not), and contorls the Tx queues flow accordingly (mgmt and data queues). * For detailed explanation, see the Tx-Path LLD document! * * \note To avoid recursion issues, all SM actions are done at the end of the function, * since some of them may invoke the SM again. * \param pTxMgmtQ - The module's object * \param eSmEvent - The event to act upon * \return void * \sa txMgmtQ_SetConnState */ static void mgmtQueuesSM (TTxMgmtQ *pTxMgmtQ, TI_UINT32 uHlid, ESmEvent eSmEvent) { TMgmtLinkQ *pLinkQ = &pTxMgmtQ->aMgmtLinkQ[uHlid]; /* Link queues */ ESmState ePrevState = pLinkQ->eState; ESmAction eSmAction = SM_ACTION_NULL; switch(eSmEvent) { case SM_EVENT_CLOSE: /* * Tx link is closed (expected in any state), so disable both mgmt queues * and if data-queues are active disable them. */ pLinkQ->eState = SM_STATE_CLOSE; pLinkQ->aQenabled[QUEUE_TYPE_MGMT] = TI_FALSE; pLinkQ->aQenabled[QUEUE_TYPE_EAPOL] = TI_FALSE; /* if (ePrevState == SM_STATE_OPEN_DATA) eSmAction = SM_ACTION_ENABLE_MGMT; */ eSmAction = SM_ACTION_STOP_ALL; break; case SM_EVENT_MGMT: /* * Only Mgmt packets are permitted (expected from any state): * - Enable the mgmt queue and disable the Eapol queue. * - If data-queues are active disable them (this will run the scheduler). * - Else run the scheduler (to send mgmt packets if waiting). */ pLinkQ->eState = SM_STATE_MGMT; pLinkQ->aQenabled[QUEUE_TYPE_MGMT] = TI_TRUE; pLinkQ->aQenabled[QUEUE_TYPE_EAPOL] = TI_FALSE; if (ePrevState == SM_STATE_OPEN_DATA) eSmAction = SM_ACTION_ENABLE_MGMT; else eSmAction = SM_ACTION_RUN_SCHEDULER; break; case SM_EVENT_EAPOL: /* * EAPOL packets are also permitted (expected in MGMT or CLOSE state), so enable the * EAPOL queue and run the scheduler (to send packets from EAPOL queue if waiting). */ if ( (ePrevState != SM_STATE_CLOSE) && (ePrevState != SM_STATE_MGMT) ) { TRACE1(pTxMgmtQ->hReport, REPORT_SEVERITY_WARNING, "mgmtQueuesSM: Got SmEvent=EAPOL when eState=%d\n", ePrevState); } pLinkQ->eState = SM_STATE_EAPOL; pLinkQ->aQenabled[QUEUE_TYPE_MGMT] = TI_TRUE; pLinkQ->aQenabled[QUEUE_TYPE_EAPOL] = TI_TRUE; eSmAction = SM_ACTION_RUN_SCHEDULER; break; case SM_EVENT_OPEN: /* * All packets are now permitted (expected in EAPOL state), so if the mgmt-queues * are empty disable them and enable the data queues. */ if (ePrevState != SM_STATE_EAPOL) { TRACE1(pTxMgmtQ->hReport, REPORT_SEVERITY_WARNING, "mgmtQueuesSM: Got SmEvent=OPEN when eState=%d\n", ePrevState); } if ( ARE_LINK_MGMT_QUEUES_EMPTY(pLinkQ->aQueues) ) { pLinkQ->eState = SM_STATE_OPEN_DATA; pLinkQ->aQenabled[QUEUE_TYPE_MGMT] = TI_FALSE; pLinkQ->aQenabled[QUEUE_TYPE_EAPOL] = TI_FALSE; eSmAction = SM_ACTION_ENABLE_DATA; } else { pLinkQ->eState = SM_STATE_OPEN_MGMT; } break; case SM_EVENT_QUEUES_EMPTY: /* * The mgmt-queues are empty, so if in OPEN_MGMT state disable the * mgmt-queues and enable the data-queues. */ if (ePrevState == SM_STATE_OPEN_MGMT) { pLinkQ->eState = SM_STATE_OPEN_DATA; pLinkQ->aQenabled[QUEUE_TYPE_MGMT] = TI_FALSE; pLinkQ->aQenabled[QUEUE_TYPE_EAPOL] = TI_FALSE; eSmAction = SM_ACTION_ENABLE_DATA; } else { /* This may happen so it's just a warning and not an error. */ TRACE1(pTxMgmtQ->hReport, REPORT_SEVERITY_WARNING, "mgmtQueuesSM: Got SmEvent=QUEUES_EMPTY when eState=%d\n", ePrevState); } break; case SM_EVENT_QUEUES_NOT_EMPTY: /* A packet was inserted to the mgmt-queues */ /* * If in OPEN_DATA state, enable mgmt-queues and disable data-queues. * * Note: The scheduler is not run here because it will called by * txMgmtQueue_wakeAll() which will run the scheduler. */ //if (ePrevState == SM_STATE_OPEN_DATA) if ( (ePrevState == SM_STATE_OPEN_DATA) ||( ePrevState == SM_STATE_OPEN_MGMT ) ) { pLinkQ->eState = SM_STATE_OPEN_MGMT; pLinkQ->aQenabled[QUEUE_TYPE_MGMT] = TI_TRUE; pLinkQ->aQenabled[QUEUE_TYPE_EAPOL] = TI_TRUE; eSmAction = SM_ACTION_ENABLE_MGMT; } /* * If in MGMT or EAPOL state, run the scheduler to transmit the packet. */ else if ( (ePrevState == SM_STATE_MGMT) || (ePrevState == SM_STATE_EAPOL) ) { eSmAction = SM_ACTION_RUN_SCHEDULER; } else { /* This may happen so it's just a warning and not an error. */ TRACE1(pTxMgmtQ->hReport, REPORT_SEVERITY_WARNING, "mgmtQueuesSM: Got SmEvent=QUEUES_NOT_EMPTY when eState=%d\n", ePrevState); } break; default: TRACE1(pTxMgmtQ->hReport, REPORT_SEVERITY_ERROR, "mgmtQueuesSM: Unknown SmEvent = %d\n", eSmEvent); break; } TRACE6( pTxMgmtQ->hReport, REPORT_SEVERITY_INFORMATION, "mgmtQueuesSM: <currentState = %d, event = %d> --> nextState = %d, action = %d, MgmtQueEnbl=%d, EapolQueEnbl=%d\n", ePrevState, eSmEvent, pLinkQ->eState, eSmAction, pLinkQ->aQenabled[0], pLinkQ->aQenabled[1]); /* * Execute the required action. * Note: This is done at the end of the SM because it may start a sequence that will call the SM again! */ switch (eSmAction) { case SM_ACTION_NULL: break; case SM_ACTION_ENABLE_DATA: txMgmtQ_DisableLink (pTxMgmtQ, uHlid); txDataQ_EnableLink (pTxMgmtQ->hTxDataQ, uHlid); break; case SM_ACTION_ENABLE_MGMT: txDataQ_DisableLink (pTxMgmtQ->hTxDataQ, uHlid); txMgmtQ_EnableLink (pTxMgmtQ, uHlid); break; case SM_ACTION_RUN_SCHEDULER: runScheduler(pTxMgmtQ); break; case SM_ACTION_STOP_ALL: txDataQ_DisableLink (pTxMgmtQ->hTxDataQ, uHlid); txDataQ_FlushLinkQueues(pTxMgmtQ->hTxDataQ, uHlid); TxMgmtQ_FlushLinkQueues(pTxMgmtQ, uHlid); txMgmtQ_EnableLink (pTxMgmtQ, uHlid); break; default: TRACE1(pTxMgmtQ->hReport, REPORT_SEVERITY_ERROR, ": Unknown SmAction = %d\n", eSmAction); break; } }