/drivers/net/wireless/tiwlan1251/common/src/core/data_ctrl/Tx/tx.c
C | 1712 lines | 915 code | 274 blank | 523 comment | 165 complexity | 8704803afbf2a443c63ec0d0070266de MD5 | raw file
Possible License(s): AGPL-1.0, GPL-2.0, LGPL-2.0
- /****************************************************************************
- **+-----------------------------------------------------------------------+**
- **| |**
- **| Copyright(c) 1998 - 2008 Texas Instruments. All rights reserved. |**
- **| All rights reserved. |**
- **| |**
- **| Redistribution and use in source and binary forms, with or without |**
- **| modification, are permitted provided that the following conditions |**
- **| are met: |**
- **| |**
- **| * Redistributions of source code must retain the above copyright |**
- **| notice, this list of conditions and the following disclaimer. |**
- **| * Redistributions in binary form must reproduce the above copyright |**
- **| notice, this list of conditions and the following disclaimer in |**
- **| the documentation and/or other materials provided with the |**
- **| distribution. |**
- **| * Neither the name Texas Instruments nor the names of its |**
- **| contributors may be used to endorse or promote products derived |**
- **| from this software without specific prior written permission. |**
- **| |**
- **| THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |**
- **| "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |**
- **| LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |**
- **| A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |**
- **| OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |**
- **| SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |**
- **| LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |**
- **| DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |**
- **| THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |**
- **| (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |**
- **| OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |**
- **| |**
- **+-----------------------------------------------------------------------+**
- ****************************************************************************/
- /***************************************************************************/
- /* */
- /* MODULE: Tx.c */
- /* PURPOSE: Tx module functions */
- /* */
- /***************************************************************************/
- #include "osTIType.h"
- #include "paramIn.h"
- #include "paramOut.h"
- #include "osApi.h"
- #include "tx.h"
- #include "DataCtrl_Api.h"
- #include "siteMgrApi.h"
- #include "802_11Defs.h"
- #include "Ethernet.h"
- /* GWSI_LAYER */
- #include "Core_AdaptTx.h"
- #include "memMngrEx.h"
- #include "report.h"
- #include "utils.h"
- #include "measurementMgrApi.h"
- #include "TI_IPC_Api.h"
- #include "EvHandler.h"
- #include "qosMngr_API.h"
- #include "PowerMgr_API.h"
- #include "bufferPoolApi.h"
- #include "TNETW_Driver_api.h"
- /*
- This is an Ethernet Version 2 frame:
- +--------------+
- | | The destination address is a six byte Media Access
- | Destination | Control (MAC) address, usually burned into the
- | 6 bytes | ROM of the Ethernet card.
- +--------------+
- | | The source address is a six byte MAC address, and
- | Source | can signify a physical station or a broadcast.
- | 6 bytes |
- +--------------+
- | Type | The Type field it must be grater then 1500 dec.
- | 2 bytes |
- +--------------+
- | | Any higher layer information is placed in the
- | Data | data field, which could contain protocol
- | | information or user data.
- ~ ~
- ~ ~
- | 46 to 1500 |
- | bytes |
- | |
- +--------------+
- | FCS |
- | 4 bytes |
- +--------------+
- */
- /*
- 802.2 SNAP DATA Frame
- +----------------+
- | |
- | Destination |
- | 6 bytes |
- +----------------+
- | |
- | Source |
- | 6 bytes |
- +----------------+
- | Frame Length | Must be <= 1500 Dec.
- | 2 bytes |
- +----------------+
- | DSAP - 1 byte | = 0xAA ( SNAP )
- +----------------+
- | SSAP - 1 byte | = 0xAA ( SNAP )
- +----------------+
- |Control - 1 byte| = 0x03
- +----------------+
- | OUI - 3 bytes | = 0x0
- | |
- +----------------+
- | Type - 2 bytes | = Ethernet type (IP=0x0800)
- +----------------+
- | |
- | Data |
- | |
- ~ ~
- ~ ~
- | 46 to 1500 |
- | bytes |
- | |
- +----------------+
- | FCS |
- | 4 bytes |
- +----------------+
- 802.11 DATA Frame
- +----------------+
- | |
- | Frame Control |
- | 2 bytes |
- +----------------+
- | |
- | Duration ID |
- | 2 bytes |
- +----------------+
- | |
- | Address 1 |
- | 6 bytes |
- +----------------+
- | |
- | Address 2 |
- | 6 bytes |
- +----------------+
- | |
- | Address 3 |
- | 6 bytes |
- +----------------+
- | |
- | Sequence Cntrl |
- | 2 bytes |
- +----------------+
- | |
- | Address 4 |
- | 6 bytes |
- +----------------+
- | DSAP - 1 byte | = 0xAA ( SNAP )
- +----------------+
- | SSAP - 1 byte | = 0xAA ( SNAP )
- +----------------+
- |Control - 1 byte| = 0x03
- +----------------+
- | OUI - 3 bytes | = 0x0
- | |
- +----------------+
- | Type - 2 bytes | = Ethernet type (IP=0x0800)
- +----------------+
- | |
- | Data |
- | |
- ~ ~
- ~ ~
- | 46 to 1500 |
- | bytes |
- | |
- +----------------+
- | FCS |
- | 4 bytes |
- +----------------+
- */
- /* Tx queue selection definitions */
- #define Q_LEAST_WEIGHT 0xFFFFFFFF /* Use least possible weight as init value (highest value is lowest priority). */
- #define Q_SELECTION_HISTORY_LEVEL 5 /* Count down from this value if queue is selected to Tx. */
- #define MANAGEMENT_QUEUE_SIZE 16
- #define DEFAULT_QUEUE_TO_HAL 1
- #define EAPOL_PACKET 0x8E88
- /* defined in QosMngr.c - used to update QosControl (userPriority) of a given packet after it has been "downgraded" due to admission control */
- extern UINT8 wmeAcToUpIndex[MAX_NUM_OF_AC];
- /* defined in qosMngr.c - used to identify voice packets in NON QOS APs */
- extern int WMEQosTagToACTable[MAX_NUM_OF_802_1d_TAGS];
- /* this macro accesses the WME Tag-to-AC conversion array in order to enable identifying voice packets even on NON QOS APs */
- #define GET_WME_AC_TYPE_FROM_MSDU(pMsdu) (WMEQosTagToACTable[pMsdu->qosTag])
- #define GET_QUEUE_INDEX(pTxData,acIndex) (pTxData->txDataAcTrfcCtrl[acIndex].QueueIndex)
- #define ABS(a) (((int)(a) >= 0) ? (a) : -((int)(a)))
- static void txData_convertEthToWlanHeader (txData_t *pTxData, mem_MSDU_T *pMsdu);
- static TI_STATUS txData_schedulerSelectQueueToTransmitFrom( TI_HANDLE hTxData, MsduList_t** pMsduListPtr,UINT8 *selectedQueueIndex );
- static void txData_startTxSchedulerFromTimer(TI_HANDLE hTxData);
- static void txData_calcCreditFromTimer(TI_HANDLE hTxData);
- static void txData_UpdateTxCounters( TI_HANDLE hTxData, txCompleteAttr_t *pTxCompleteAttr );
- static void txData_SetTxDelayCounters( TI_HANDLE hTxData, UINT32 txQid, txCompleteAttr_t *pTxCompleteAttr, UINT32 driverDelay );
- static int txData_selectQueueAndUpdateUserPriority (txData_t *pTxData, mem_MSDU_T *pMsdu, int *selectedQueue, acTrfcType_e *selectedAc);
- static int txData_getHighestAdmittedAc(txData_t *pTxData, int startingAcIndex);
- static void txData_startVadTimer(TI_HANDLE hTxData, UINT16 voiceDuration);
- static void txData_stopVadTimer(TI_HANDLE hTxData);
- static void txData_setVadTimer(TI_HANDLE hTxData, BOOL vadEnabled, UINT16 duration);
- static void txData_resetVadTimer(TI_HANDLE hTxData);
- static void txData_vadTimeout(TI_HANDLE hTxData);
- #ifdef TI_DBG
- static void txData_printTxThroughputPerQueue(TI_HANDLE hTxData);
- static void txData_printTxAirThroughputPerQueue(TI_HANDLE hTxData);
- static void txData_printJitter(TI_HANDLE hTxData);
- #endif
- static BOOL txData_acVoPsPollMode(txData_t *pTxData);
- static UINT32 txDataTimeToMsduExpiry( TI_HANDLE htxData, mem_MSDU_T* pMsdu, UINT8 Qid);
- static UINT8 txData_GetAcIdFromQid(TI_HANDLE hTxData,UINT8 Qid);
- TI_STATUS txData_setMediumUsageThresholds(TI_HANDLE hTxData,
- UINT8 acID,
- INT32 highMediumUsageThreshold,
- INT32 lowMediumUsageThreshold);
- static void txData_SetQidToAcTable(TI_HANDLE hTxData,UINT8 QidStart, UINT8 QidEnd,UINT8 AcId);
- /* The TX delay histogram ranges start and end in msec. */
- static UINT32 txDelayRangeStart[TX_DELAY_RANGES_NUM] = { 0, 1, 10, 20, 40, 60, 80, 100, 200 };
- static UINT32 txDelayRangeEnd [TX_DELAY_RANGES_NUM] = { 1, 10, 20, 40, 60, 80, 100, 200, 0xFFFFFFFF };
- /*************************************************************************
- * txData_create *
- **************************************************************************
- * DESCRIPTION: This function initializes the Tx module.
- *
- * INPUT: hOs - handle to Os Abstraction Layer
- * txDataInitParams - Tx Data creation parameters
- * OUTPUT:
- *
- * RETURN: Handle to the allocated Tx data control block
- *************************************************************************/
- TI_HANDLE txData_create(txDataInitParams_t *txDataInitParams,
- TI_HANDLE hOs)
- {
- txData_t *hTxData;
- MsduList_t *mgmtMsduList;
- MsduList_t *dataMsduListArr[MAX_NUM_OF_TX_QUEUES];
- void* pTimer;
- #ifdef TI_DBG
- void* pThroughputTimer;
- void* pAirThroughputTimer;
- void* pJitterTimer;
- #endif
- void* pCreditTimer;
- void* pVadTimer;
- int queueIndex = 0;
- /* check parameters validity */
- if( txDataInitParams->txDataNumOfDataQueues > MAX_NUM_OF_TX_QUEUES ||
- txDataInitParams->txDataNumOfDataQueues <= 0 )
- {
- WLAN_OS_REPORT(("FATAL ERROR - UNABLE TO CREATE TX MODULE. Number of queues error = %d.",txDataInitParams->txDataNumOfDataQueues));
- return NULL;
- }
- /* allocate Tx module control block */
- hTxData = os_memoryAlloc(hOs, (sizeof(txData_t)));
- if(!hTxData)
- return NULL;
- /* reset tx control block */
- os_memoryZero(hOs, hTxData, (sizeof(txData_t)));
- /* allocate the buffer pool */
- hTxData->hBufferPool = bufferPool_create( hOs,
- HAL_CTRL_ACX_TX_DESC_DEF * MAX_NUM_OF_TX_QUEUES,
- sizeof(txPacketIdAttr_t) );
- if ( NULL == hTxData->hBufferPool )
- {
- utils_nullMemoryFree(hOs, hTxData, sizeof(txData_t));
- return NULL;
- }
- /* allocate Timer to use for scheduler trigger */
- pTimer = os_timerCreate(hOs, txData_startTxSchedulerFromTimer, hTxData);
- if(!pTimer)
- {
- bufferPool_destroy( hTxData->hBufferPool );
- utils_nullMemoryFree(hOs, hTxData, sizeof(txData_t));
- return NULL;
- }
- /* allocate Timer for vad operation */
- pVadTimer = os_timerCreate(hOs, txData_vadTimeout, hTxData);
- if(!pVadTimer)
- {
- bufferPool_destroy( hTxData->hBufferPool );
- utils_nullTimerDestroy (hOs, pTimer);
- utils_nullMemoryFree(hOs, hTxData, sizeof(txData_t));
- return NULL;
- }
- #ifdef TI_DBG
- /* allocate timer for debug throughput per queue */
- pThroughputTimer = os_timerCreate(hOs, txData_printTxThroughputPerQueue, hTxData);
- if(!pThroughputTimer)
- {
- bufferPool_destroy( hTxData->hBufferPool );
- utils_nullTimerDestroy(hOs, pTimer);
- utils_nullMemoryFree(hOs, hTxData, sizeof(txData_t));
- return NULL;
- }
- /* allocate timer for debug throughput per queue */
- pAirThroughputTimer = os_timerCreate (hOs, txData_printTxAirThroughputPerQueue, hTxData);
- if (!pAirThroughputTimer)
- {
- bufferPool_destroy (hTxData->hBufferPool);
- utils_nullTimerDestroy (hOs, pTimer);
- utils_nullTimerDestroy (hOs, pThroughputTimer);
- utils_nullMemoryFree (hOs, hTxData, sizeof(txData_t));
- return NULL;
- }
- /* allocate timer for debug throughput per queue */
- pJitterTimer = os_timerCreate (hOs, txData_printJitter, hTxData);
- if (!pJitterTimer)
- {
- bufferPool_destroy (hTxData->hBufferPool);
- utils_nullTimerDestroy (hOs, pTimer);
- utils_nullTimerDestroy (hOs, pThroughputTimer);
- utils_nullTimerDestroy (hOs, pAirThroughputTimer);
- utils_nullMemoryFree (hOs, hTxData, sizeof(txData_t));
- return NULL;
- }
- #endif
- /* allocate timer for credit calculation */
- pCreditTimer = os_timerCreate(hOs, txData_calcCreditFromTimer, hTxData);
- if(!pCreditTimer)
- {
- bufferPool_destroy( hTxData->hBufferPool );
- utils_nullTimerDestroy(hOs, pTimer);
- #ifdef TI_DBG
- utils_nullTimerDestroy(hOs, pThroughputTimer);
- utils_nullTimerDestroy(hOs, pAirThroughputTimer);
- utils_nullTimerDestroy(hOs, pJitterTimer);
- #endif
- utils_nullMemoryFree(hOs, hTxData, sizeof(txData_t));
- return NULL;
- }
- /* initialize management queue */
- mgmtMsduList = msduList_CreateNewMsduList( hOs);
- if(!mgmtMsduList)
- {
- bufferPool_destroy( hTxData->hBufferPool );
- utils_nullTimerDestroy(hOs, pTimer);
- #ifdef TI_DBG
- utils_nullTimerDestroy(hOs, pThroughputTimer);
- utils_nullTimerDestroy(hOs, pAirThroughputTimer);
- utils_nullTimerDestroy(hOs, pJitterTimer);
- #endif
- utils_nullTimerDestroy(hOs, pCreditTimer);
- utils_nullMemoryFree(hOs, hTxData, sizeof(txData_t));
- return NULL;
- }
- /* initialize tx data queues */
- for(queueIndex = 0 ; queueIndex < MAX_NUM_OF_TX_QUEUES ; queueIndex++)
- {
- dataMsduListArr[queueIndex] = msduList_CreateNewMsduList( hOs);
- if(!dataMsduListArr[queueIndex])
- {
- bufferPool_destroy( hTxData->hBufferPool );
- utils_nullTimerDestroy(hOs, pTimer);
- #ifdef TI_DBG
- utils_nullTimerDestroy(hOs, pThroughputTimer);
- utils_nullTimerDestroy(hOs, pAirThroughputTimer);
- utils_nullTimerDestroy(hOs, pJitterTimer);
- #endif
- utils_nullTimerDestroy(hOs, pCreditTimer);
- utils_nullMemoryFree(hOs, mgmtMsduList, sizeof(MsduList_t));
- queueIndex--;
- for(; queueIndex >= 0 ; queueIndex--)
- {
- utils_nullMemoryFree(hOs, dataMsduListArr[queueIndex], sizeof(MsduList_t));
- }
- utils_nullMemoryFree(hOs, hTxData, sizeof(txData_t));
- return NULL;
- }
- }
- hTxData->txDataNumOfQueues = txDataInitParams->txDataNumOfDataQueues;
- /* Threshold to decide whether we drop the packet, or sending it to Fw */
- /* example: value of 75 will drop any MSDU that stayed it the Driver */
- /* Queues for more than 75% of the time that was originally defined for it */
- hTxData->uFracOfLifeTimeToDrop = txDataInitParams->uFracOfLifeTimeToDrop;
- hTxData->TxEventDistributor = DistributorMgr_Create(hOs,MAX_TX_NOTIF_REQ_ELMENTS);
- hTxData->mngMsduList = mgmtMsduList;
- for(queueIndex = 0 ; queueIndex < MAX_NUM_OF_TX_QUEUES ; queueIndex++)
- {
- hTxData->dataMsduListArr[queueIndex] = dataMsduListArr[queueIndex];
- }
- hTxData->pSchedulerTimer = pTimer;
- hTxData->pVadTimer = pVadTimer;
- hTxData->bSchedulerTimerRunning = FALSE;
- #ifdef TI_DBG
- hTxData->pThroughputTimer = pThroughputTimer;
- hTxData->pAirThroughputTimer = pAirThroughputTimer;
- hTxData->pJitterTimer = pJitterTimer;
- #endif
- hTxData->pCreditTimer = pCreditTimer;
- hTxData->hOs = hOs;
- hTxData->bVadTimerEnabled = FALSE;
- hTxData->vadTimerDuration = 0;
- hTxData->creditCalculationTimeout = txDataInitParams->creditCalculationTimeout;
- hTxData->bCreditCalcTimerEnabled = txDataInitParams->bCreditCalcTimerEnabled;
- hTxData->admCtrlDelayDueToMediumTimeOverUsage = txDataInitParams->admCtrlDelayDueToMediumTimeOverUsage;
- hTxData->admissionDownGradeEnable = txDataInitParams->admissionDownGradeEnable;
-
- return(hTxData);
- }
- /***************************************************************************
- * txData_config *
- ****************************************************************************
- * DESCRIPTION: This function configures the Tx Data module
- *
- * INPUTS: hTxData - The object
- * hCtrlData - Handle to the Ctrl Data object
- * hOs - Handle to the Os Abstraction Layer
- * hReport - Handle to the Report object
- * hMemMngr - Handle to the Memory manager object
- * OUTPUT:
- *
- * RETURNS: OK - Configuration unsuccessful
- * NOK - Configuration unsuccessful
- ***************************************************************************/
- TI_STATUS txData_config(TI_HANDLE hTxData,
- TI_HANDLE hCtrlData,
- TI_HANDLE hTnetwDrv,
- TI_HANDLE hWhalCtrl,
- TI_HANDLE hOs,
- TI_HANDLE hReport,
- TI_HANDLE hMemMngr,
- TI_HANDLE hSiteMgr,
- TI_HANDLE hEvHandler,
- TI_HANDLE hQosMngr,
- TI_HANDLE hPowerMgr)
- {
- int qIndex;
- txData_t *pTxData = (txData_t *)hTxData;
- /* configure modules handles */
- pTxData->hCtrlData = hCtrlData;
- pTxData->hTnetwDrv = hTnetwDrv;
- pTxData->hWhalCtrl= hWhalCtrl;
- pTxData->hOs = hOs;
- pTxData->hReport = hReport;
- pTxData->hMemMngr = hMemMngr;
- pTxData->hSiteMgr = hSiteMgr;
- pTxData->hEvHandler = hEvHandler;
- pTxData->hQosMngr = hQosMngr;
- pTxData->hPowerMgr = hPowerMgr;
- /* set Tx parameters */
- pTxData->txDataPortStatus = DEF_TX_PORT_STATUS;
- pTxData->savePortStatus = DEF_TX_PORT_STATUS;
- pTxData->txDataCurrentPrivacyInvokedMode = DEF_CURRENT_PRIVACY_INVOKED_MODE;
- pTxData->saveTxDataCurrentPrivacyInvokedMode = DEF_CURRENT_PRIVACY_INVOKED_MODE;
- pTxData->txDataEapolEncryptionStatus = DEF_EAPOL_ENCRYPTION_STATUS;
- pTxData->saveTxDataEapolEncryptionStatus = DEF_EAPOL_ENCRYPTION_STATUS;
- pTxData->txDataIsSchedulerInWork = DEF_IS_SCHEDULER_IN_WORK;
- pTxData->txDataHalInterfaceStatus = DEF_HAL_INTERFACE_STATUS;
- /* Initialize the parameters related to GWSI and to Scheduler in Work */
- pTxData->txDataGwsiInterfaceStatus = GWSI_OPEN;
- pTxData->txDataIsSchedulerInWork = FALSE;
- pTxData->bCreditCalcTimerRunning = FALSE;
-
- /* encryption header size */
- pTxData->encryptionFieldSize = 0;
- pTxData->saveEncryptionFieldSize = 0;
- /* configure the packet ID buffer pool */
- bufferPool_config( pTxData->hBufferPool, hReport );
- /* configure the Tx queues (msdu lists) */
- /* num of elements is configured by qosMngr */
- for (qIndex = 0; qIndex < MAX_NUM_OF_TX_QUEUES; qIndex++)
- {
- if( (msduList_ConfigMsduList( pTxData->dataMsduListArr[qIndex], pTxData->hMemMngr,
- pTxData->hReport,pTxData->hOs,0 )) != OK )
- {
- WLAN_REPORT_ERROR(pTxData->hReport, TX_DATA_MODULE_LOG,
- ("Error configure DataMsduList num: %d\n",qIndex));
- }
- /*
- * Mark all queues available for TX
- */
- pTxData->txDataAvailableQueue[qIndex] = TRUE;
- }
- if( (msduList_ConfigMsduList( pTxData->mngMsduList, pTxData->hMemMngr,
- pTxData->hReport, pTxData->hOs,MANAGEMENT_QUEUE_SIZE )) != OK )
- {
- WLAN_REPORT_ERROR(pTxData->hReport, TX_DATA_MODULE_LOG,
- ("Error configure MgmtMsduList\n"));
- }
- /* reset counters */
- txData_resetCounters (pTxData);
- txData_resetDbgCounters (pTxData);
- WLAN_REPORT_INIT(pTxData->hReport, TX_DATA_MODULE_LOG,
- (".....Tx Data configured successfully\n"));
- #ifdef NO_COPY_NDIS_BUFFERS
- WLAN_REPORT_INFORMATION(pTxData->hReport, TX_DATA_MODULE_LOG,
- ("Driver configured to work in NO COPY MSDU BUFFERS."));
- #else
- WLAN_REPORT_INFORMATION(pTxData->hReport, TX_DATA_MODULE_LOG,
- ("Driver is configured to work in COPY MSDU BUFFERS."));
- #endif
- return OK;
- }
- /***************************************************************************
- * txData_unLoad *
- ****************************************************************************
- * DESCRIPTION: This function unload the tx data module. It first free the
- * MsduLists and then free the Tx data control block
- *
- * INPUTS: hTxData - the object
- *
- * OUTPUT:
- *
- * RETURNS: OK - Unload succesfull
- * NOK - Unload unsuccesfull
- ***************************************************************************/
- TI_STATUS txData_unLoad(TI_HANDLE hTxData)
- {
- txData_t *pTxData = (txData_t *)hTxData;
- TI_STATUS status = OK;
- int queueIndex;
- /* check parameters validity */
- if( pTxData == NULL )
- {
- return NOK;
- }
- /* free Data queue msdu list */
- for(queueIndex = 0;queueIndex < MAX_NUM_OF_TX_QUEUES; queueIndex++)
- {
- if (msduList_FreeMsduList( pTxData->dataMsduListArr[queueIndex]) != OK)
- {
- WLAN_REPORT_ERROR(pTxData->hReport, TX_DATA_MODULE_LOG,
- (" txData_unLoad() : fail to free Data MsduList number: %d\n",queueIndex));
- status = NOK;
- }
- }
- /* free Mgmt queue msdu list */
- if (msduList_FreeMsduList( pTxData->mngMsduList) != OK)
- {
- WLAN_REPORT_ERROR(pTxData->hReport, TX_DATA_MODULE_LOG,
- (" txData_unLoad() : fail to free Mgmt MsduList \n"));
- status = NOK;
- }
- DistributorMgr_Destroy(pTxData->TxEventDistributor);
- /* free Timer */
- utils_nullTimerDestroy(pTxData->hOs, pTxData->pSchedulerTimer);
- utils_nullTimerDestroy(pTxData->hOs, pTxData->pVadTimer);
- #ifdef TI_DBG
- utils_nullTimerDestroy(pTxData->hOs, pTxData->pThroughputTimer);
- utils_nullTimerDestroy(pTxData->hOs, pTxData->pAirThroughputTimer);
- utils_nullTimerDestroy(pTxData->hOs, pTxData->pJitterTimer);
- #endif
- utils_nullTimerDestroy(pTxData->hOs, pTxData->pCreditTimer);
- /* release the packet ID buffer pool */
- bufferPool_destroy( pTxData->hBufferPool );
- /* free Tx Data control block */
- os_memoryFree(pTxData->hOs, pTxData, sizeof(txData_t));
- return status;
- }
- /****************************************************************************
- * txData_stop *
- *****************************************************************************
- * DESCRIPTION: this function stop the tx data. It empties the tx queues (msdu
- * lists) from the msdu's and return all tx data parameters to
- * default values
- *
- * INPUTS: hTxData - the object
- *
- * OUTPUT:
- *
- * RETURNS: OK - stop successful
- * NOK - stop unsuccessful
- ****************************************************************************/
- TI_STATUS txData_stop(TI_HANDLE hTxData)
- {
- txData_t *pTxData = (txData_t *)hTxData;
- int queueIndex;
- pTxData->savePortStatus = pTxData->txDataPortStatus;
- /* stop scheduler timer trigger */
- if ( TRUE == pTxData->bSchedulerTimerRunning )
- {
- os_timerStop(pTxData->hOs, pTxData->pSchedulerTimer);
- }
- /* stop vad timer */
- if ( TRUE == pTxData->bVadTimerEnabled )
- {
- os_timerStop(pTxData->hOs, pTxData->pVadTimer);
- }
- /* stop throughput timer */
- if(pTxData->txThroughputTimerEnable == TRUE)
- {
- os_timerStop(pTxData->hOs, pTxData->pThroughputTimer);
- pTxData->txThroughputTimerEnable = FALSE;
- }
- /* stop throughput timer */
- if (pTxData->txAirThroughputTimerEnable)
- {
- os_timerStop (pTxData->hOs, pTxData->pAirThroughputTimer);
- pTxData->txAirThroughputTimerEnable = FALSE;
- }
- /* stop credit calculation timer */
- if ( pTxData->bCreditCalcTimerRunning )
- {
- os_timerStop(pTxData->hOs, pTxData->pCreditTimer);
- pTxData->bCreditCalcTimerRunning = FALSE;
- }
- /* empty Tx data queue from Msdus */
- for(queueIndex = 0;queueIndex < MAX_NUM_OF_TX_QUEUES; queueIndex++)
- {
- if( msduList_EmptyMsduList( pTxData->dataMsduListArr[queueIndex] ) != OK)
- {
- WLAN_REPORT_ERROR(pTxData->hReport, TX_DATA_MODULE_LOG,
- (" txData_stop() : fail to empty Data Msdu List number: %d\n",queueIndex));
- return NOK;
- }
- }
- /* empty Tx Mgmt queue from Msdus */
- if( msduList_EmptyMsduList( pTxData->mngMsduList ) != OK)
- {
- WLAN_REPORT_ERROR(pTxData->hReport, TX_DATA_MODULE_LOG,
- (" txData_stop() : fail to empty Mgmt Msdu List \n"));
- return NOK;
- }
- /* set Tx parameters to default values */
- pTxData->txDataPortStatus = DEF_TX_PORT_STATUS;
- pTxData->saveTxDataCurrentPrivacyInvokedMode = pTxData->txDataCurrentPrivacyInvokedMode;
- pTxData->saveTxDataEapolEncryptionStatus = pTxData->txDataEapolEncryptionStatus;
- pTxData->saveEncryptionFieldSize = pTxData->encryptionFieldSize;
- pTxData->txDataCurrentPrivacyInvokedMode = DEF_CURRENT_PRIVACY_INVOKED_MODE;
- pTxData->txDataEapolEncryptionStatus = DEF_EAPOL_ENCRYPTION_STATUS;
- pTxData->encryptionFieldSize = 0;
- WLAN_REPORT_INFORMATION(pTxData->hReport, TX_DATA_MODULE_LOG,
- (" txData_stop() : Succeeded.\n"));
- return OK;
- }
- /****************************************************************************
- * txData_start *
- *****************************************************************************
- * DESCRIPTION: this function start the tx data.
- *
- * INPUTS: hTxData - the object
- *
- * OUTPUT:
- *
- * RETURNS: OK - stop succesfull
- * NOK - stop unsuccesfull
- ****************************************************************************/
- TI_STATUS txData_start(TI_HANDLE hTxData)
- {
- txData_t *pTxData = (txData_t *)hTxData;
- /* check parameters validity */
- if( pTxData == NULL )
- {
- WLAN_REPORT_ERROR(pTxData->hReport, TX_DATA_MODULE_LOG,
- (" txData_start() : Illegal value for hTxData\n"));
- return NOK;
- }
- pTxData->txDataPortStatus = pTxData->savePortStatus;
- return OK;
- }
-
- /****************************************************************************
- * txData_recoveryIndication *
- *****************************************************************************
- * DESCRIPTION: this function clears information on recovery.
- *
- * INPUTS: hTxData - the object
- *
- * OUTPUT:
- *
- * RETURNS:
- ****************************************************************************/
- void txData_recoveryIndication (TI_HANDLE hTxData)
- {
- txData_t *pTxData = (txData_t *)hTxData;
- int queueIndex;
- /* Reinitializes packet ID buffer pool (mark all buffers as available) */
- bufferPool_reinit (pTxData->hBufferPool);
- /* Empty Tx data queue from Msdus */
- for (queueIndex = 0; queueIndex < MAX_NUM_OF_TX_QUEUES; queueIndex++)
- {
- if (msduList_EmptyMsduList (pTxData->dataMsduListArr[queueIndex]) != OK)
- {
- WLAN_REPORT_ERROR(pTxData->hReport, TX_DATA_MODULE_LOG,
- (" txData_stop() : fail to empty data MSDU list number: %d\n", queueIndex));
- }
- }
- /* Empty Tx management queue from MSDU's */
- if (msduList_EmptyMsduList (pTxData->mngMsduList) != OK)
- {
- WLAN_REPORT_ERROR (pTxData->hReport, TX_DATA_MODULE_LOG,
- (" txData_stop() : fail to empty management MSDU list\n"));
- }
- /*
- * Set GWSI interfaces status as 'opened'
- * because it can be undefined upon recovery
- */
- pTxData->txDataGwsiInterfaceStatus = GWSI_OPEN;
- for (queueIndex = 0; queueIndex < MAX_NUM_OF_TX_QUEUES; queueIndex++)
- {
- /*
- * Mark all queues available for TX
- */
- pTxData->txDataAvailableQueue[queueIndex] = TRUE;
- }
- }
- /***************************************************************************
- * txData_checkQueueSize *
- ****************************************************************************
- * DESCRIPTION: Check the Tx Queue size
- *
- * INPUTS: hTxData - the object
- *
- * OUTPUT:
- *
- * RETURNS: OK
- * NOK - The queue is full
- ***************************************************************************/
- TI_STATUS txData_checkQueueSize(TI_HANDLE hTxData,UINT8 qIndex)
- {
- txData_t *pTxData = (txData_t *)hTxData;
- TI_STATUS Status = OK;
- txData_startTxScheduler(pTxData);
- if (pTxData->dataMsduListArr[qIndex]->CurrNumOfMsdu == pTxData->dataMsduListArr[qIndex]->maxNumOfMsdu)
- Status = NOK;
- return Status;
- }
- /***************************************************************************
- * txData_copyPacketToMsdu *
- ****************************************************************************
- * DESCRIPTION:
- *
- * INPUTS: hTxData - the object
- *
- * OUTPUT:
- *
- * RETURNS: OK
- * NOK - The queue is full
- ***************************************************************************/
- TI_STATUS txData_copyPacketToMsdu(TI_HANDLE hTxData,mem_MSDU_T **pMsdu, int FreeOldMsdu)
- {
- #ifdef NO_COPY_NDIS_BUFFERS
- txData_t *pTxData = (txData_t *)hTxData;
- TI_STATUS Status = OK;
- mem_BD_T *pCurrBd;
- mem_MSDU_T *tempMsdu;
- UINT8 *pMsduData;
- UINT8 *pCurrBufData;
- dot11_header_t *pdot11Header;
- /*
- * Allocate MSDU+BD+BUFFER+TX_DESCRIPTOR_SIZE to copy to !!
- */
- if(wlan_memMngrAllocMSDU(pTxData->hMemMngr,&tempMsdu,(*pMsdu)->dataLen+TX_TOTAL_OFFSET_BEFORE_DATA,TX_MODULE) != OK)
- {
- WLAN_REPORT_ERROR(pTxData->hReport, TX_DATA_MODULE_LOG,
- (" txData_copyPacketToMsdu() : No Memory in MemMgr \n"));
- return NOK;
- }
- tempMsdu->dataLen = 0;
- tempMsdu->firstBDPtr->length = 0;
- tempMsdu->txFlags = (*pMsdu)->txFlags;
- pCurrBd = (*pMsdu)->firstBDPtr;
- pMsduData = tempMsdu->firstBDPtr->data + TX_TOTAL_OFFSET_BEFORE_DATA;
- while(pCurrBd)
- {
- pCurrBufData = pCurrBd->data + pCurrBd->dataOffset;
- /* Copy the packet */
- os_memoryCopy(pTxData->hOs, pMsduData, pCurrBufData, pCurrBd->length);
- tempMsdu->dataLen += pCurrBd->length - TNETWIF_WRITE_OFFSET_BYTES;
- tempMsdu->firstBDPtr->length += pCurrBd->length;
- pMsduData += pCurrBd->length;
- pCurrBd = pCurrBd->nextBDPtr;
- }
- tempMsdu->headerLen = (*pMsdu)->headerLen;
- txData_convertEthToWlanHeader( pTxData, tempMsdu );
- /* set wep bit if needed */
- if((tempMsdu->txFlags & TX_DATA_DATA_MSDU) && (pTxData->txDataCurrentPrivacyInvokedMode))
- {
- pdot11Header = (dot11_header_t*)(memMgr_BufData(pMsdu->firstBDPtr) + memMgr_BufOffset(pMsdu->firstBDPtr));
- pdot11Header->fc |= DOT11_FC_WEP;
- }
- else if ((tempMsdu->txFlags & TX_DATA_EAPOL_MSDU ) && (pTxData->txDataEapolEncryptionStatus))
- {
- pdot11Header = (dot11_header_t*)(memMgr_BufData(pMsdu->firstBDPtr) + memMgr_BufOffset(pMsdu->firstBDPtr));
- pdot11Header->fc |= DOT11_FC_WEP;
- }
- if (FreeOldMsdu)
- wlan_memMngrFreeMSDU(pTxData->hMemMngr, memMgr_MsduHandle((*pMsdu)));
- (*pMsdu) = tempMsdu;
- #endif
- return OK;
- }
- /***************************************************************************
- * txData_sendPktToWlan *
- ****************************************************************************
- * DESCRIPTION: This function is called by the Os Abstraction Layer in order
- * to send packet to the wireless LAN. It calls the header
- * conversion function and passes the to sendMsdu function.
- *
- * INPUTS: hTxData - the object
- * pMsdu - pointer the packet in 802.3 format
- *
- * OUTPUT:
- *
- * RETURNS: OK
- * NOK
- ***************************************************************************/
- TI_STATUS txData_sendPktToWlan(TI_HANDLE hTxData, mem_MSDU_T *pMsdu, UINT8 pkt_DTag)
- {
- EthernetHeader_t *pEthHeader;
- UINT16 TypeLength;
- TI_STATUS Status;
- mem_BD_T* tempBd;
- BOOL UseConvertHeader = TRUE;
- txData_t *pTxData = (txData_t *)hTxData;
- /* check parameters validity */
- if( pTxData == NULL || pMsdu == NULL )
- {
- return NOK;
- }
- pEthHeader = (EthernetHeader_t*)(memMgr_BufData(pMsdu->firstBDPtr)+memMgr_BufOffset(pMsdu->firstBDPtr));
- /* check if the frame is multicast/broadcast - need for the transmission rate */
- if(IsMacAddressGroup( &pEthHeader->DstAddr ))
- pMsdu->txFlags |= TX_DATA_MULTICAST_FRAME;
- TypeLength = pEthHeader->TypeLength;
- /* Call the Classify function in the Control Module to set the qosTag of the MSDU */
- if (ctrlData_ClsfrClassifyTxMSDU(pTxData->hCtrlData, pMsdu, pkt_DTag) != OK)
- {
- WLAN_REPORT_DEBUG_TX(pTxData->hReport,
- (" txData_sendPktToWlan(): No matching classifier found\n"));
- }
- /* filter MSDU according to Tx Port Status and the Eth Type */
- if ( pTxData->txDataPortStatus != OPEN )
- {
- int queueIndex;
- int acIndex;
- WLAN_REPORT_WARNING(pTxData->hReport, TX_DATA_MODULE_LOG,
- (" txData_sendPktToWlan() : try to transmit Msdu while port is not open (txDataPortStatus = 0x%x)\n", pTxData->txDataPortStatus));
-
- /* Find AC and Tx-queue in order to update the correct Queue measurements */
- acIndex = GET_WME_AC_TYPE_FROM_MSDU(pMsdu);
- queueIndex = GET_QUEUE_INDEX(pTxData,acIndex);
-
-
- /* updating the measurements - dropped packet counter */
- pTxData->txDataReportedCounters[queueIndex].OtherFailCounter++;
- pTxData->txDataReportedCounters[queueIndex].NumPackets++;
-
- if((pTxData->txDataPortStatus == CLOSE) || (pTxData->txDataPortStatus == OPEN_NOTIFY) )
- {
- WLAN_REPORT_WARNING(pTxData->hReport, TX_DATA_MODULE_LOG,
- (" txData_sendPktToWlan() : try to transmit Msdu while port is not open (txDataPortStatus = 0x%x)\n", pTxData->txDataPortStatus));
- /* In case the function return status is NOK, no need to call Os free function */
- /* Set freefunc in the msdu to null. In this case the MemMngr will not call */
- /* the Os free function */
- memMgr_MsduFreeFuncGet(pMsdu) = NULL;
- /* free MSDU */
- if( (wlan_memMngrFreeMSDU(pTxData->hMemMngr, memMgr_MsduHandle(pMsdu))) != OK )
- {
- WLAN_REPORT_ERROR(pTxData->hReport, TX_DATA_MODULE_LOG,
- (" txData_sendPktToWlan() : free msdu failed \n"));
- }
- return NOK;
- }
- /* filter Data frames while port is open only for Eapol's */
- if( (pTxData->txDataPortStatus == OPEN_EAPOL) && (TypeLength != EAPOL_PACKET) )
- {
- WLAN_REPORT_WARNING(pTxData->hReport, TX_DATA_MODULE_LOG,
- (" txData_sendPktToWlan() : try to transmit Non Eapol packet while port is open for eapols only\n"));
- /* In case the function return status is NOK, no need to call Os free function. */
- /* Set freefunc in the msdu to null. In this case the MemMngr will not call */
- /* the Os free function - because the return staus to the Os is NOK the buffer */
- /* free by the Os */
- memMgr_MsduFreeFuncGet(pMsdu) = NULL;
- /* frre MSDU */
- if ((wlan_memMngrFreeMSDU(pTxData->hMemMngr, memMgr_MsduHandle(pMsdu))) != OK)
- {
- WLAN_REPORT_ERROR(pTxData->hReport, TX_DATA_MODULE_LOG,
- (" txData_sendPktToWlan() : free msdu failed \n"));
- }
- return NOK;
- }
- }
- /* PORT IS OPEN */
- #ifdef CORE_TX_DBG
- WLAN_REPORT_INFORMATION(pTxData->hReport, TX_DATA_MODULE_LOG,
- (" txData_sendPktToWlan: port is open \n"));
- #endif
-
- if( TypeLength != EAPOL_PACKET )
- {
- pMsdu->txFlags |= TX_DATA_DATA_MSDU;
- }
- else
- {
- WLAN_REPORT_INFORMATION(pTxData->hReport, TX_DATA_MODULE_LOG,
- (" txData_sendPktToWlan() : Tx an EAPOL frame tranferred to HAL\n"));
- /* because EAPOL is sent from Mgmt queue */
- pMsdu->txFlags |= TX_DATA_EAPOL_MSDU;
- }
- UseConvertHeader = TRUE; /* a patch for WinCe */
- #ifdef NO_COPY_NDIS_BUFFERS
- if (pMsdu->txFlags & TX_DATA_FROM_OS)
- UseConvertHeader = FALSE; /* don't convert on external (OS) packets */
- #endif
- if (UseConvertHeader == TRUE)
- {
- /* Header conversion from Ethernet to 802.11 */
- txData_convertEthToWlanHeader( pTxData, pMsdu );
- }
- /* update last BD */
- tempBd = pMsdu->firstBDPtr;
- while(tempBd->nextBDPtr)
- {
- tempBd = tempBd->nextBDPtr;
- }
- pMsdu->lastBDPtr = tempBd;
- Status = txData_txSendMsdu( pTxData, pMsdu );
- if( Status == NOK )
- {
- WLAN_REPORT_ERROR(pTxData->hReport, TX_DATA_MODULE_LOG,
- (" txData_sendPktToWlan() : txData_txSendMsdu failed \n"));
- }
- if ((OK == Status) && (GET_WME_AC_TYPE_FROM_MSDU(pMsdu) == QOS_AC_VO))
- {
- txData_resetVadTimer(pTxData);
- }
- return Status;
- }
- /***************************************************************************
- * txData_txSendMsdu *
- ****************************************************************************
- * DESCRIPTION: This function is insert the MSDU to transmit to the proper
- * tx queue and give a trigger to the scheduler to start
- * transmission to the wireless LAN.
- *
- * INPUTS: hTxData - the object
- * pMsdu - pointer the MSDU in 802.11 format
- *
- * OUTPUT:
- *
- * RETURNS: OK
- * NOK
- ***************************************************************************/
- TI_STATUS txData_txSendMsdu(TI_HANDLE hTxData, mem_MSDU_T *pMsdu )
- {
- dot11_header_t *pdot11Header;
- TI_STATUS Status = OK;
- int queueIndex;
- acTrfcType_e acIndex;
- txData_t *pTxData = (txData_t *)hTxData;
- /* ctrlData_txMsdu(pTxData->hCtrlData,&pMsdu); 4x related */
-
- if(pMsdu == NULL)
- {
- WLAN_REPORT_INFORMATION(pTxData->hReport, TX_DATA_MODULE_LOG,
- (" txData_txSendMsdu() : DISCARD Packet...... \n"));
- txData_startTxScheduler(pTxData);
- return NOK;
- }
- #ifndef NO_COPY_NDIS_BUFFERS /* buffers are copied by OAL*/
- /* set wep bit if needed */
- if((pMsdu->txFlags & TX_DATA_DATA_MSDU) && (pTxData->txDataCurrentPrivacyInvokedMode))
- {
- /* update offset of header */
- pdot11Header = (dot11_header_t*)(memMgr_BufData(pMsdu->firstBDPtr) + memMgr_BufOffset(pMsdu->firstBDPtr));
- pdot11Header->fc |= DOT11_FC_WEP;
- }
- else if ((pMsdu->txFlags & TX_DATA_EAPOL_MSDU ) && (pTxData->txDataEapolEncryptionStatus))
- {
- /* update offset of header */
- pdot11Header = (dot11_header_t*)(memMgr_BufData(pMsdu->firstBDPtr) + memMgr_BufOffset(pMsdu->firstBDPtr));
- pdot11Header->fc |= DOT11_FC_WEP;
- }
- #endif /*NO_COPY_NDIS_BUFFERS*/
- #ifdef EXC_MODULE_INCLUDED
- if ((pMsdu->txFlags & TX_DATA_IAPP_MSDU) && (pTxData->txDataCurrentPrivacyInvokedMode))
- {
- /* update offset of header */
- pdot11Header = (dot11_header_t*)(memMgr_BufData(pMsdu->firstBDPtr) + memMgr_BufOffset(pMsdu->firstBDPtr));
- pdot11Header->fc |= DOT11_FC_WEP;
- }
- #endif
- WLAN_REPORT_DEBUG_TX(pTxData->hReport,
- (" txData_txSendMsdu() : Sending PAcket pMsdu %x pMsdu->txFlags %x \n",pMsdu,pMsdu->txFlags));
- /* insert the msdu to the the appropriate queue */
- if( (pMsdu->txFlags & TX_DATA_DATA_MSDU) || (pMsdu->txFlags & TX_DATA_NULL_MSDU) )
- {
- /* Find Tx-queue and AC to use for Tx, and if downgraded from original one update the UP. */
- txData_selectQueueAndUpdateUserPriority (pTxData, pMsdu, &queueIndex, &acIndex);
-
- /* set insertion time for further expiry timeout calculation */
- pMsdu->insertionTime = os_timeStampUs (pTxData->hOs);
- /* see if the frame is tagged VO. */
- /* Note: Check actual tag even if current not working in WME, to support voice anyway. */
- if( GET_WME_AC_TYPE_FROM_MSDU(pMsdu) == QOS_AC_VO)
- {
- /*
- * If the frame is tagged VO and power save is on, send psPoll before the VO frame.
- */
- if(txData_acVoPsPollMode(pTxData) == TRUE)
- {
- mem_MSDU_T *pMsduPsPoll;
- if(txData_getPsPollFrame(pTxData,&pMsduPsPoll) == OK)
- {
- /* increment debug counters */
- pTxData->txDataDbgCounters.dbgInsertToMsduListBytes[queueIndex] += pMsduPsPoll->dataLen;
- pTxData->txDataDbgCounters.dbgInsertToMsduListPackets[queueIndex]++;
- /* set insertion time for further expiry timeout calculation */
- pMsduPsPoll->insertionTime = os_timeStampUs (pTxData->hOs);
- /* insert to queueIndex queue */
- if( msduList_Insert( pTxData->dataMsduListArr[queueIndex] , &pMsduPsPoll ) != OK )
- {
- pTxData->txDataDbgCounters.dbgDropedFromMsduListPackets[queueIndex]++;
- /* the first msdu in list has removed and the new one has inserted */
- WLAN_REPORT_WARNING(pTxData->hReport, TX_DATA_MODULE_LOG,
- (" txData_sendPktToWlan() : Msdu List num %d was full \n",queueIndex));
- /* free the msdu which removed from the list (returned in pMsdu) */
- /*---------------------------------------------------------------*/
- /* set msdu tx status to Fail (this status is used by OS) */
- memMgr_MsduFreeArg2Get(pMsduPsPoll) = NOK;
- /* free the msdu */
- wlan_memMngrFreeMSDU(pTxData->hMemMngr, memMgr_MsduHandle(pMsduPsPoll));
- pTxData->txDataDbgCounters.dbgDropedPacketsCounter++;
- }/*msduList_Insert*/
- }/*txData_getPsPollFrame*/
- }/*txData_acVoPsPollMode*/
- }
- /* insert to data queue */
- /* if we didn't succeed to insert psPolls exclude VO packet also */
- if( msduList_Insert( pTxData->dataMsduListArr[queueIndex] , &pMsdu ) != OK )
- {
- pTxData->txDataDbgCounters.dbgDropedFromMsduListPackets[queueIndex]++;
- /* the first msdu in list has removed and the new one has inserted */
- WLAN_REPORT_WARNING(pTxData->hReport, TX_DATA_MODULE_LOG,
- (" txData_txSendMsdu() : Data Msdu [%d] List was full \n",queueIndex));
- /* free the msdu which removed from the list (returned in pMsdu) */
- /*---------------------------------------------------------------*/
- /* set msdu tx status to Fail (this status is used by OS) */
- memMgr_MsduFreeArg2Get(pMsdu) = NOK;
- /* free the msdu */
- wlan_memMngrFreeMSDU(pTxData->hMemMngr, memMgr_MsduHandle(pMsdu));
- pTxData->txDataDbgCounters.dbgDropedPacketsCounter++;
-
- pTxData->txDataReportedCounters[queueIndex].NumPackets++;
- pTxData->txDataReportedCounters[queueIndex].OtherFailCounter++;
- return OK;
- }
- /* increament debug counters */
- pTxData->txDataDbgCounters.dbgInsertToMsduListBytes[queueIndex] += pMsdu->dataLen;
- pTxData->txDataDbgCounters.dbgInsertToMsduListPackets[queueIndex]++;
- WLAN_REPORT_DEBUG_TX(pTxData->hReport,
- (" txData_txSendMsdu() : insert data packet to queue # %d \n",queueIndex));
- }
- else
- {
- /* Management frame, Eapol and null frame (for measuring a non serving channel)
- are also sent from the mgmt queue */
- /* set insertion time for further expiry timeout calculation */
- pMsdu->insertionTime = os_timeStampUs (pTxData->hOs);
- WLAN_REPORT_DEBUG_TX(pTxData->hReport,
- (" txData_txSendMsdu() : insert mngt packet to Management queue pMsdu %x \n",pMsdu));
- if( msduList_Insert( pTxData->mngMsduList , &pMsdu ) != OK )
- {
- /* the first msdu in list has removed and the new one has inserted */
- WLAN_REPORT_WARNING(pTxData->hReport, TX_DATA_MODULE_LOG,
- (" txData_txSendMsdu() : Mgmt Msdu List was full \n"));
- /* free the msdu which removed from the list (returned in pMsdu) */
- /*---------------------------------------------------------------*/
- /* set msdu tx status to Fail (this status is used by OS) */
- memMgr_MsduFreeArg2Get(pMsdu) = NOK;
- /* free the msdu */
- wlan_memMngrFreeMSDU(pTxData->hMemMngr, memMgr_MsduHandle(pMsdu));
- pTxData->txDataDbgCounters.dbgDropedPacketsCounter++;
- }
- }
- {
- /* call the scheduler in order to transmit the frame to the Hal */
- Status = txData_startTxScheduler(pTxData);
- if ( Status == NOK )
- {
- WLAN_REPORT_ERROR(pTxData->hReport, TX_DATA_MODULE_LOG,
- (" txData_txSendMsdu() : txData_startTxScheduler error \n"));
- }
- }
- /* this is the status of the current Msdu */
- return OK;
- }
- /***************************************************************************
- * txData_startTxScheduler *
- ****************************************************************************
- * DESCRIPTION: This function start the transmission process.
- * It select msdu to transmit from the tx queues and send
- * it to the Hal
- *
- * INPUTS: hTxData - the object
- *
- * OUTPUT:
- *
- * RETURNS: OK
- * NOK
- ***************************************************************************/
- TI_STATUS txData_startTxScheduler(TI_HANDLE hTxData)
- {
- txData_t *pTxData = (txData_t *)hTxData;
- mem_MSDU_T *pMsdu;
- MsduList_t *pMsduList = NULL;
- txData_attr_t txAttr;
- UINT8 count, selectedQueueIndex;
- TI_STATUS txStatus;
- txPacketIdAttr_t *pPacketId;
- dot11_header_t *pDot11Header;
- bssType_e currBssType;
- macAddress_t currBssId;
- UINT32 msduTimeToExpiry;
- #ifdef SUPPORT_4X
- hwTxInformation_t hwTxInformation;
- BOOL fourXEnable;
- #endif
- /* check if HAL is open now - used for recovery only!!! */
- if ( pTxData->txDataHalInterfaceStatus == TX_DATA_CLOSED )
- {
- return OK; /* TODO ronen: doesn't seem to be used any more, remove */
- }
- /* Checking if Tx is now disabled */
- if(pTxData->txDisable == DISABLE_IMMEDIATELY)
- {
- WLAN_REPORT_WARNING(pTxData->hReport, TX_DATA_MODULE_LOG,
- (" txData_startTxScheduler() : Tx Disabled!!! \n"));
- /* start scheduler timer */
- if ( FALSE == pTxData->bSchedulerTimerRunning )
- {
- os_timerStart( pTxData->hOs, pTxData->pSchedulerTimer, SCHEDULER_TIMER, FALSE );
- pTxData->bSchedulerTimerRunning = TRUE;
- }
- pTxData->txDataIsSchedulerInWork = FALSE;
- return OK;
- }
- /*
- * in case of non serialized system no need to
- * run the scheduler if it is already in work
- */
- if(pTxData->txDataIsSchedulerInWork == TRUE)
- {
- WLAN_REPORT_WARNING(pTxData->hReport, TX_DATA_MODULE_LOG,
- (" txData_startTxScheduler() : Scheduler already in work...........!!!! \n"));
- return OK;
- }
- else
- {
- pTxData->txDataIsSchedulerInWork = TRUE;
- }
- /* try to transmit DEF_SCHEDULER_THRESHOLD MSDUs */
- count = DEF_SCHEDULER_THRESHOLD;
- /*
- * if non of the queues is available non msdu will be selected
- */
-
- while ( (0 < count--) && (GWSI_OPEN == pTxData->txDataGwsiInterfaceStatus) )
- {
- /* select queue to transmit from */
- if( txData_schedulerSelectQueueToTransmitFrom( pTxData, &pMsduList,&selectedQueueIndex ) != TX_QUEUE_SELECTED_OK)
- {
- WLAN_REPORT_DEBUG_TX(pTxData->hReport,
- (" txData_startTxScheduler() : No Msdu waiting to transmit \n"));
- pTxData->txDataIsSchedulerInWork = FALSE;
- return OK;
- }
- WLAN_REPORT_DEBUG_TX(pTxData->hReport,
- (" txData_startTxScheduler() : txData_schedulerSelectQueueToTransmitFrom Returned from selectedQueueIndex %d \n",selectedQueueIndex));
-
- #ifdef SUPPORT_4X
-
- ctrlData_get4xStatus(pTxData->hCtrlData,&fourXEnable);
- if(fourXEnable == TRUE && pMsduList != pTxData->mngMsduList)
- {
- /*
- * receive Acx tx queuue information for transmission decision
- */
- whalTx_getTxQueueInfo(pTxData->hWhalTx,
- DEFAULT_QUEUE_TO_HAL,
- &hwTxInformation.hwNumOfFreeMsdu,
- &hwTxInformation.hwNumOfBusyMsdu,
- &hwTxInformation.hwNumOfFreeBDs,
- &hwTxInformation.hwTotalAvailMem );
- /*
- * call ctrl Data - DequeueMsdu...
- * pMsdu - the msdu to transmit.
- * txAttr - the tx attributes for msdu transmission
- */
- status = ctrlData_txDequeueMsdu(pTxData->hCtrlData, &pMsdu, pMsduList, &txAttr, &hwTxInformation);
- if(status == DO_NOT_SEND_MSDU)
- {
- WLAN_REPORT_ERROR(pTxData->hReport,
- (" txData_startTxScheduler() : TX_STATUS_PENDING \n"));
- pTxData->txDataIsSchedulerInWork = FALSE;
- return TX_STATUS_PENDING;
- }
- }
- #else /* if not SUPPORT_4X */
- {
- /* increment debug counter */
- pTxData->txDataDbgCounters.dbgScheduledOutPackets[selectedQueueIndex]++;
- if( msduList_WatchFirst( pMsduList ,&pMsdu) != OK )
- {
- WLAN_REPORT_ERROR( pTxData->hReport, TX_DATA_MODULE_LOG,
- ("Unable to retrieve first MSDU from queue index:%d\n", selectedQueueIndex) );
- pTxData->txDataIsSchedulerInWork = FALSE;
- return OK;
- }
- WLAN_REPORT_DEBUG_TX(pTxData->hReport,
- (" txData_startTxScheduler() : After msduList_WatchFirst pMsdu %d \n",pMsdu));
- #ifdef NO_COPY_NDIS_BUFFERS
-
- if(pMsdu->txFlags & TX_DATA_FROM_OS)
- {
- if(txData_copyPacketToMsdu(pTxData, &pMsdu, 1 /* do FreeOldMsdu */) != OK)
- {
- WLAN_REPORT_ERROR(pTxData->hReport, TX_DATA_MODULE_LOG,
- (" txData_startTxScheduler() : txData_copyPacketToMsdu FAILED \n"));
- pTxData->txDataIsSchedulerInWork = FALSE;
- return NOK;
- }
- }
- #endif /* NO_COPY_NDIS_BUFFERS */
- }
- #endif /* SUPPORT_4X */
- /* check MSDU expiry time, and if it didn't expire send it to GWSI */
- if ((msduTimeToExpiry = txDataTimeToMsduExpiry (hTxData, pMsdu, selectedQueueIndex)) == 0)
- {
- /* MSDU time expired - drop it */
- WLAN_REPORT_INFORMATION(pTxData->hReport, TX_DATA_MODULE_LOG,
- ("txData_startTxScheduler drop msdu due to expiry time, queueId = %d \n",selectedQueueIndex));
- /* Get MSDU with dequeuing */
- if ( (msduList_GetFirst( pMsduList, &pMsdu )) != OK )
- {
- /* No MSDU is waiting to transmit */
- WLAN_REPORT_ERROR (pTxData->hReport, TX_DATA_MODULE_LOG,
- ("%s: can't get Msdu from pMsduList[ %d ] \n", __FUNCTION__, selectedQueueIndex));
- pTxData->txDataIsSchedulerInWork = FALSE;
- return NOK;
- }
- pTxData->txDataDbgCounters.dbgDroppedDueExpiryTimePackets[selectedQueueIndex]++;
-
- pTxData->txDataReportedCounters[selectedQueueIndex].NumPackets++;
- pTxData->txDataReportedCounters[selectedQueueIndex].OtherFailCounter++;
-
- /* free the MSDU */
- memMgr_MsduFreeArg2Get(pMsdu) = OK;
-
- if( (wlan_memMngrFreeMSDU(pTxData->hMemMngr, memMgr_MsduHandle(pMsdu))) != OK )
- {
- WLAN_REPORT_ERROR(pTxData->hReport, TX_DATA_MODULE_LOG,
- (" txData_startTxScheduler() : free msdu failed \n"));
- }
-
- /* continue to next packet */
- continue;
- }
- /* Collect txAttr from control */
- ctrlData_getTxAttributes(pTxData->hCtrlData, pMsdu->txFlags, &txAttr, selectedQueueIndex);
- /* allocate a buffer for packet ID storage */
- pPacketId = (txPacketIdAttr_t*)bufferPool_allocateBuffer( pTxData->hBufferPool );
- if ( BUFFER_POOL_NO_BUFFER == pPacketId )
- {
- WLAN_REPORT_ERROR (pTxData->hReport, TX_DATA_MODULE_LOG,
- (" %s : No PacketID Available!!\n", __FUNCTION__));
- /* shouldn't happen, since we have enough packet ID buffers as the FW has TX descriptors! */
- pTxData->txDataIsSchedulerInWork = FALSE;
- return NOK;
- }
- /* store necessary information in packet ID */
- pPacketId->pMsdu = pMsdu;
- if (pMsdu->txFlags & TX_DATA_DATA_MSDU)
- {
- pPacketId->bDataMsdu = TRUE;
- }
- else
- {
- pPacketId->bDataMsdu = FALSE;
- }
- pPacketId->txQid = selectedQueueIndex;
- pPacketId->txCompleteFlags = pMsdu->txCompleteFlags;
- pPacketId->maxTransmitRate = txAttr.HwRate;
- #ifdef TI_DBG
- os_memoryZero (pTxData->hOs, pPacketId->timeStamp, sizeof(pPacketId->timeStamp));
- pPacketId->timeStamp[0] = os_timeStampUs (pTxData->hOs);
- #endif
- pPacketId->msduDataLen = pMsdu->dataLen;
- /* destination mac */
- pDot11Header = (dot11_header_t*)(memMgr_BufData(pMsdu->firstBDPtr)+ memMgr_BufOffset(pMsdu->firstBDPtr));
- ctrlData_getCurrBssTypeAndCurrBssId(pTxData->hCtrlData, &currBssId, &currBssType);
- if(currBssType == BSS_INDEPENDENT)
- MAC_COPY( pTxData->hOs, &(pPacketId->destinationMac), &(pDot11Header->address1) );
- else
- MAC_COPY( pTxData->hOs, &(pPacketId->destinationMac), &(pDot11Header->address3) );
- /* mark in packet ID that XFER done and TX complete were not called yet */
- pPacketId->bTxCompleteCalled = pPacketId->bXferDoneCalled = FALSE;
- #ifdef TI_DBG
- if ((pMsdu->txFlags & TX_DATA_DATA_MSDU) != 0 && pMsdu->timeStampNum > 0)
- {
- UINT32 uCoreDelay;
- /* add time stamp */
- wlan_memMngrAddTimeStamp (pTxData->hMemMngr, pMsdu);
- uCoreDelay = pMsdu->timeStamp[pMsdu->timeStampNum - 1] - pMsdu->timeStamp[0];
- /* update core delay and jitter */
- pTxData->txJitter[selectedQueueIndex].jitter.core +=
- ABS (pTxData->txJitter[selectedQueueIndex].last_delay.core - uCoreDelay);
- pTxData->txJitter[selectedQueueIndex].last_delay.core = uCoreDelay;
- pTxData->txJitter[selectedQueueIndex].delay.core += uCoreDelay;
- pTxData->txJitter[selectedQueueIndex].count.core ++;
- if (uCoreDelay > pTxData->txJitter[selectedQueueIndex].max_delay.core)
- pTxData->txJitter[selectedQueueIndex].max_delay.core = uCoreDelay;
- }
- #endif
- /* send the packet to the GWSI layer */
- txStatus = CORE_AdaptTx_SendPacket( CORE_AdaptTx_handle, selectedQueueIndex, pMsdu, &txAttr, (UINT32)pPacketId, msduTimeToExpiry );
- WLAN_REPORT_DEBUG_TX (pTxData->hReport,
- ("txData_startTxScheduler(): called CORE_AdaptTx_SendPacket pMsdu=%d, selectedQueueIndex=%d,txStatus=%d\n",
- pMsdu,selectedQueueIndex,txStatus));
- switch ( txStatus )
- {
- /*
- * XFER_DONE is received when the packet has been synchronously transferred to the FW.
- * in this case, XFER complete will not be called, only TX complete
- */
- case SEND_PACKET_XFER_DONE:
- pPacketId->driverHandlingTime = (os_timeStampUs (pTxData->hOs) - pMsdu->insertionTime) / 1000;
- /* Get MSDU with dequeuing */
- if ( (msduList_GetFirst( pMsduList, &pMsdu )) != OK )
- {
- /* No MSDU is waiting to transmit */
- WLAN_REPORT_ERROR (pTxData->hReport, TX_DATA_MODULE_LOG,
- (" %s : can't get Msdu from pMsduList[ %d ] \n", __FUNCTION__, selectedQueueIndex));
- pTxData->txDataIsSchedulerInWork = FALSE;
- return NOK;
- }
- /* free the MSDU, since XFER complete won't be called */
- if ( (wlan_memMngrFreeMSDU(pTxData->hMemMngr, memMgr_MsduHandle(pMsdu))) != OK )
- {
- WLAN_REPORT_ERROR(pTxData->hReport, TX_DATA_MODULE_LOG,
- ("%s: free msdu failed \n", __FUNCTION__));
- pTxData->txDataIsSchedulerInWork = FALSE;
- return NOK;
- }
- else
- {
- pTxData->txDataDbgCounters.dbgNumOfMsduFreeInTxTransfer[ pPacketId->txQid ]++;
- }
- /* Nullify the MSDU pointer, just in case */
- pPacketId->pMsdu = NULL;
- /* mark in packet ID that XFER done was called */
- pPacketId->bXferDoneCalled = TRUE;
- /* increment debug counter */
- pTxData->txDataDbgCounters.dbgSendToGwsiQosPackets[ selectedQueueIndex ]++;
- pTxData->txDataDbgCounters.dbgNumOfMsduXferDoneInShceduler[ selectedQueueIndex ]++;
- break;
- /*
- * SUCCESS is received when the packet has not yet been sent to the FW, but another packet
- * transfer can start immediately
- */
- case SEND_PACKET_SUCCESS:
- /* Get msdu with dequeuing */
- if ( (msduList_GetFirst( pMsduList, &pMsdu )) != OK )
- {
- /* No msdu is waiting to transmit */
- WLAN_REPORT_ERROR (pTxData->hReport, TX_DATA_MODULE_LOG,
- (" %s : can't get Msdu from pMsduList[ %d ] \n", __FUNCTION__, selectedQueueIndex));
- pTxData->txDataIsSchedulerInWork = FALSE;
- return NOK;
- }
- /* increment debug counter */
- pTxData->txDataDbgCounters.dbgNumOfMsduSuccessInScheduler[ selectedQueueIndex ]++;
- pTxData->txDataDbgCounters.dbgSendToGwsiQosPackets[selectedQueueIndex]++;
- break;
- /*
- * PENDING is received when the packet has been received by the GWSI layer, and the double buffer
- * mechanism is busy. It indicates that no more packets (from all queues) are to be sent until a
- * XFER complete indication is received
- */
- case SEND_PACKET_PENDING:
- /* Get msdu with dequeuing */
- if ( (msduList_GetFirst( pMsduList, &pMsdu )) != OK )
- {
- /* No msdu is waiting to transmit */
- WLAN_REPORT_ERROR (pTxData->hReport, TX_DATA_MODULE_LOG,
- (" %s : can't get Msdu from pMsduList[ %d ] \n", __FUNCTION__, selectedQueueIndex));
- pTxData->txDataIsSchedulerInWork = FALSE;
- return NOK;
- }
- /* mark the GWSI interface state as pending (no more frames can be sent) */
- pTxData->txDataGwsiInterfaceStatus = GWSI_PENDING;
- /* increment debug counter */
- pTxData->txDataDbgCounters.dbgNumOfMsduPendingInScheduler[ selectedQueueIndex ]++;
- pTxData->txDataDbgCounters.dbgSendToGwsiQosPackets[selectedQueueIndex]++;
- break;
- /*
- * BUSY is received when the packet has NOT been received by the GWSI layer (and needs to be
- * retransmitted). It indicates that the specific FW queue is full and no more packets from this
- * specific queue are to be sent until a TX complete indication for this queue is received (but
- * packets from other queues may be sent).
- */
- case SEND_PACKET_BUSY:
- /* don't dequeue the packet! it was not sent! */
- /* in addition, release the packet ID buffer */
- bufferPool_releaseBuffer( pTxData->hBufferPool, pPacketId );
- /* mark the specific queue as not available */
- pTxData->txDataAvailableQueue[ selectedQueueIndex ] = FALSE;
- /* update debug counters */
- pTxData->txDataDbgCounters.dbgNumOfMsduBusyInScheduler[ selectedQueueIndex ]++;
- break;
- /*
- * ERROR is received when a frame is sent although a PENDING indication had been previously
- * received and no XFER complete had been receive since, or because a BUSY indication had been
- * received for a specific queue and no TX complete for this queue had been received since (and
- * a packet from this queue had been sent now).
- */
- case SEND_PACKET_ERROR:
- /* don't dequeue the packet! it was not sent! */
- /* in addition, release the packet ID buffer */
- bufferPool_releaseBuffer( pTxData->hBufferPool, pPacketId );
- /* start scheduler timer */
- if ( FALSE == pTxData->bSchedulerTimerRunning )
- {
- os_timerStart( pTxData->hOs, pTxData->pSchedulerTimer, SCHEDULER_TIMER, FALSE );
- pTxData->bSchedulerTimerRunning = TRUE;
- }
- pTxData->txDataIsSchedulerInWork = FALSE;
- WLAN_REPORT_ERROR( pTxData->hReport, TX_DATA_MODULE_LOG,
- (" %s: received status SEND_PACKET_ERROR from CORE_AdaptTx_SendPacket\n", __FUNCTION__) );
- /* update debug counters */
- pTxData->txDataDbgCounters.dbgNumOfMsduErrorInScheduler[ selectedQueueIndex ]++;
- return NOK;
- /* break; - unreachable*/
- case SEND_PACKET_RECOVERY:
- break;
- default:
- WLAN_REPORT_ERROR( pTxData->hReport, TX_DATA_MODULE_LOG,
- (" %s: received status %d from CORE_AdaptTx_SendPacket\n", __FUNCTION__, txStatus) );
- break;
- }
-
- WLAN_REPORT_INFORMATION (pTxData->hReport, TX_DATA_MODULE_LOG,
- ("txData_startTxScheduler() : MSDU sent: TxQ = %d TxStatus = %d\n", selectedQueueIndex, txStatus));
- } /* end of while (count) */
- pTxData->txDataIsSchedulerInWork = FALSE;
- return OK;
- }
- /***************************************************************************
- * txData_sendPacketTransfer *
- ****************************************************************************
- * DESCRIPTION: GWSI sendPacketTransfer CB. called after transferring a packet
- * to TNET.
- * The