PageRenderTime 90ms CodeModel.GetById 27ms RepoModel.GetById 1ms app.codeStats 1ms

/drivers/net/wireless/tiwlan1251/common/src/core/data_ctrl/Tx/tx.c

https://bitbucket.org/cyanogenmod/cm-kernel
C | 4557 lines | 2530 code | 740 blank | 1287 comment | 393 complexity | 8704803afbf2a443c63ec0d0070266de MD5 | raw file
Possible License(s): GPL-2.0, LGPL-2.0, AGPL-1.0
  1. /****************************************************************************
  2. **+-----------------------------------------------------------------------+**
  3. **| |**
  4. **| Copyright(c) 1998 - 2008 Texas Instruments. All rights reserved. |**
  5. **| All rights reserved. |**
  6. **| |**
  7. **| Redistribution and use in source and binary forms, with or without |**
  8. **| modification, are permitted provided that the following conditions |**
  9. **| are met: |**
  10. **| |**
  11. **| * Redistributions of source code must retain the above copyright |**
  12. **| notice, this list of conditions and the following disclaimer. |**
  13. **| * Redistributions in binary form must reproduce the above copyright |**
  14. **| notice, this list of conditions and the following disclaimer in |**
  15. **| the documentation and/or other materials provided with the |**
  16. **| distribution. |**
  17. **| * Neither the name Texas Instruments nor the names of its |**
  18. **| contributors may be used to endorse or promote products derived |**
  19. **| from this software without specific prior written permission. |**
  20. **| |**
  21. **| THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |**
  22. **| "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |**
  23. **| LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |**
  24. **| A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |**
  25. **| OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |**
  26. **| SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |**
  27. **| LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |**
  28. **| DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |**
  29. **| THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |**
  30. **| (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |**
  31. **| OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |**
  32. **| |**
  33. **+-----------------------------------------------------------------------+**
  34. ****************************************************************************/
  35. /***************************************************************************/
  36. /* */
  37. /* MODULE: Tx.c */
  38. /* PURPOSE: Tx module functions */
  39. /* */
  40. /***************************************************************************/
  41. #include "osTIType.h"
  42. #include "paramIn.h"
  43. #include "paramOut.h"
  44. #include "osApi.h"
  45. #include "tx.h"
  46. #include "DataCtrl_Api.h"
  47. #include "siteMgrApi.h"
  48. #include "802_11Defs.h"
  49. #include "Ethernet.h"
  50. /* GWSI_LAYER */
  51. #include "Core_AdaptTx.h"
  52. #include "memMngrEx.h"
  53. #include "report.h"
  54. #include "utils.h"
  55. #include "measurementMgrApi.h"
  56. #include "TI_IPC_Api.h"
  57. #include "EvHandler.h"
  58. #include "qosMngr_API.h"
  59. #include "PowerMgr_API.h"
  60. #include "bufferPoolApi.h"
  61. #include "TNETW_Driver_api.h"
  62. /*
  63. This is an Ethernet Version 2 frame:
  64. +--------------+
  65. | | The destination address is a six byte Media Access
  66. | Destination | Control (MAC) address, usually burned into the
  67. | 6 bytes | ROM of the Ethernet card.
  68. +--------------+
  69. | | The source address is a six byte MAC address, and
  70. | Source | can signify a physical station or a broadcast.
  71. | 6 bytes |
  72. +--------------+
  73. | Type | The Type field it must be grater then 1500 dec.
  74. | 2 bytes |
  75. +--------------+
  76. | | Any higher layer information is placed in the
  77. | Data | data field, which could contain protocol
  78. | | information or user data.
  79. ~ ~
  80. ~ ~
  81. | 46 to 1500 |
  82. | bytes |
  83. | |
  84. +--------------+
  85. | FCS |
  86. | 4 bytes |
  87. +--------------+
  88. */
  89. /*
  90. 802.2 SNAP DATA Frame
  91. +----------------+
  92. | |
  93. | Destination |
  94. | 6 bytes |
  95. +----------------+
  96. | |
  97. | Source |
  98. | 6 bytes |
  99. +----------------+
  100. | Frame Length | Must be <= 1500 Dec.
  101. | 2 bytes |
  102. +----------------+
  103. | DSAP - 1 byte | = 0xAA ( SNAP )
  104. +----------------+
  105. | SSAP - 1 byte | = 0xAA ( SNAP )
  106. +----------------+
  107. |Control - 1 byte| = 0x03
  108. +----------------+
  109. | OUI - 3 bytes | = 0x0
  110. | |
  111. +----------------+
  112. | Type - 2 bytes | = Ethernet type (IP=0x0800)
  113. +----------------+
  114. | |
  115. | Data |
  116. | |
  117. ~ ~
  118. ~ ~
  119. | 46 to 1500 |
  120. | bytes |
  121. | |
  122. +----------------+
  123. | FCS |
  124. | 4 bytes |
  125. +----------------+
  126. 802.11 DATA Frame
  127. +----------------+
  128. | |
  129. | Frame Control |
  130. | 2 bytes |
  131. +----------------+
  132. | |
  133. | Duration ID |
  134. | 2 bytes |
  135. +----------------+
  136. | |
  137. | Address 1 |
  138. | 6 bytes |
  139. +----------------+
  140. | |
  141. | Address 2 |
  142. | 6 bytes |
  143. +----------------+
  144. | |
  145. | Address 3 |
  146. | 6 bytes |
  147. +----------------+
  148. | |
  149. | Sequence Cntrl |
  150. | 2 bytes |
  151. +----------------+
  152. | |
  153. | Address 4 |
  154. | 6 bytes |
  155. +----------------+
  156. | DSAP - 1 byte | = 0xAA ( SNAP )
  157. +----------------+
  158. | SSAP - 1 byte | = 0xAA ( SNAP )
  159. +----------------+
  160. |Control - 1 byte| = 0x03
  161. +----------------+
  162. | OUI - 3 bytes | = 0x0
  163. | |
  164. +----------------+
  165. | Type - 2 bytes | = Ethernet type (IP=0x0800)
  166. +----------------+
  167. | |
  168. | Data |
  169. | |
  170. ~ ~
  171. ~ ~
  172. | 46 to 1500 |
  173. | bytes |
  174. | |
  175. +----------------+
  176. | FCS |
  177. | 4 bytes |
  178. +----------------+
  179. */
  180. /* Tx queue selection definitions */
  181. #define Q_LEAST_WEIGHT 0xFFFFFFFF /* Use least possible weight as init value (highest value is lowest priority). */
  182. #define Q_SELECTION_HISTORY_LEVEL 5 /* Count down from this value if queue is selected to Tx. */
  183. #define MANAGEMENT_QUEUE_SIZE 16
  184. #define DEFAULT_QUEUE_TO_HAL 1
  185. #define EAPOL_PACKET 0x8E88
  186. /* defined in QosMngr.c - used to update QosControl (userPriority) of a given packet after it has been "downgraded" due to admission control */
  187. extern UINT8 wmeAcToUpIndex[MAX_NUM_OF_AC];
  188. /* defined in qosMngr.c - used to identify voice packets in NON QOS APs */
  189. extern int WMEQosTagToACTable[MAX_NUM_OF_802_1d_TAGS];
  190. /* this macro accesses the WME Tag-to-AC conversion array in order to enable identifying voice packets even on NON QOS APs */
  191. #define GET_WME_AC_TYPE_FROM_MSDU(pMsdu) (WMEQosTagToACTable[pMsdu->qosTag])
  192. #define GET_QUEUE_INDEX(pTxData,acIndex) (pTxData->txDataAcTrfcCtrl[acIndex].QueueIndex)
  193. #define ABS(a) (((int)(a) >= 0) ? (a) : -((int)(a)))
  194. static void txData_convertEthToWlanHeader (txData_t *pTxData, mem_MSDU_T *pMsdu);
  195. static TI_STATUS txData_schedulerSelectQueueToTransmitFrom( TI_HANDLE hTxData, MsduList_t** pMsduListPtr,UINT8 *selectedQueueIndex );
  196. static void txData_startTxSchedulerFromTimer(TI_HANDLE hTxData);
  197. static void txData_calcCreditFromTimer(TI_HANDLE hTxData);
  198. static void txData_UpdateTxCounters( TI_HANDLE hTxData, txCompleteAttr_t *pTxCompleteAttr );
  199. static void txData_SetTxDelayCounters( TI_HANDLE hTxData, UINT32 txQid, txCompleteAttr_t *pTxCompleteAttr, UINT32 driverDelay );
  200. static int txData_selectQueueAndUpdateUserPriority (txData_t *pTxData, mem_MSDU_T *pMsdu, int *selectedQueue, acTrfcType_e *selectedAc);
  201. static int txData_getHighestAdmittedAc(txData_t *pTxData, int startingAcIndex);
  202. static void txData_startVadTimer(TI_HANDLE hTxData, UINT16 voiceDuration);
  203. static void txData_stopVadTimer(TI_HANDLE hTxData);
  204. static void txData_setVadTimer(TI_HANDLE hTxData, BOOL vadEnabled, UINT16 duration);
  205. static void txData_resetVadTimer(TI_HANDLE hTxData);
  206. static void txData_vadTimeout(TI_HANDLE hTxData);
  207. #ifdef TI_DBG
  208. static void txData_printTxThroughputPerQueue(TI_HANDLE hTxData);
  209. static void txData_printTxAirThroughputPerQueue(TI_HANDLE hTxData);
  210. static void txData_printJitter(TI_HANDLE hTxData);
  211. #endif
  212. static BOOL txData_acVoPsPollMode(txData_t *pTxData);
  213. static UINT32 txDataTimeToMsduExpiry( TI_HANDLE htxData, mem_MSDU_T* pMsdu, UINT8 Qid);
  214. static UINT8 txData_GetAcIdFromQid(TI_HANDLE hTxData,UINT8 Qid);
  215. TI_STATUS txData_setMediumUsageThresholds(TI_HANDLE hTxData,
  216. UINT8 acID,
  217. INT32 highMediumUsageThreshold,
  218. INT32 lowMediumUsageThreshold);
  219. static void txData_SetQidToAcTable(TI_HANDLE hTxData,UINT8 QidStart, UINT8 QidEnd,UINT8 AcId);
  220. /* The TX delay histogram ranges start and end in msec. */
  221. static UINT32 txDelayRangeStart[TX_DELAY_RANGES_NUM] = { 0, 1, 10, 20, 40, 60, 80, 100, 200 };
  222. static UINT32 txDelayRangeEnd [TX_DELAY_RANGES_NUM] = { 1, 10, 20, 40, 60, 80, 100, 200, 0xFFFFFFFF };
  223. /*************************************************************************
  224. * txData_create *
  225. **************************************************************************
  226. * DESCRIPTION: This function initializes the Tx module.
  227. *
  228. * INPUT: hOs - handle to Os Abstraction Layer
  229. * txDataInitParams - Tx Data creation parameters
  230. * OUTPUT:
  231. *
  232. * RETURN: Handle to the allocated Tx data control block
  233. *************************************************************************/
  234. TI_HANDLE txData_create(txDataInitParams_t *txDataInitParams,
  235. TI_HANDLE hOs)
  236. {
  237. txData_t *hTxData;
  238. MsduList_t *mgmtMsduList;
  239. MsduList_t *dataMsduListArr[MAX_NUM_OF_TX_QUEUES];
  240. void* pTimer;
  241. #ifdef TI_DBG
  242. void* pThroughputTimer;
  243. void* pAirThroughputTimer;
  244. void* pJitterTimer;
  245. #endif
  246. void* pCreditTimer;
  247. void* pVadTimer;
  248. int queueIndex = 0;
  249. /* check parameters validity */
  250. if( txDataInitParams->txDataNumOfDataQueues > MAX_NUM_OF_TX_QUEUES ||
  251. txDataInitParams->txDataNumOfDataQueues <= 0 )
  252. {
  253. WLAN_OS_REPORT(("FATAL ERROR - UNABLE TO CREATE TX MODULE. Number of queues error = %d.",txDataInitParams->txDataNumOfDataQueues));
  254. return NULL;
  255. }
  256. /* allocate Tx module control block */
  257. hTxData = os_memoryAlloc(hOs, (sizeof(txData_t)));
  258. if(!hTxData)
  259. return NULL;
  260. /* reset tx control block */
  261. os_memoryZero(hOs, hTxData, (sizeof(txData_t)));
  262. /* allocate the buffer pool */
  263. hTxData->hBufferPool = bufferPool_create( hOs,
  264. HAL_CTRL_ACX_TX_DESC_DEF * MAX_NUM_OF_TX_QUEUES,
  265. sizeof(txPacketIdAttr_t) );
  266. if ( NULL == hTxData->hBufferPool )
  267. {
  268. utils_nullMemoryFree(hOs, hTxData, sizeof(txData_t));
  269. return NULL;
  270. }
  271. /* allocate Timer to use for scheduler trigger */
  272. pTimer = os_timerCreate(hOs, txData_startTxSchedulerFromTimer, hTxData);
  273. if(!pTimer)
  274. {
  275. bufferPool_destroy( hTxData->hBufferPool );
  276. utils_nullMemoryFree(hOs, hTxData, sizeof(txData_t));
  277. return NULL;
  278. }
  279. /* allocate Timer for vad operation */
  280. pVadTimer = os_timerCreate(hOs, txData_vadTimeout, hTxData);
  281. if(!pVadTimer)
  282. {
  283. bufferPool_destroy( hTxData->hBufferPool );
  284. utils_nullTimerDestroy (hOs, pTimer);
  285. utils_nullMemoryFree(hOs, hTxData, sizeof(txData_t));
  286. return NULL;
  287. }
  288. #ifdef TI_DBG
  289. /* allocate timer for debug throughput per queue */
  290. pThroughputTimer = os_timerCreate(hOs, txData_printTxThroughputPerQueue, hTxData);
  291. if(!pThroughputTimer)
  292. {
  293. bufferPool_destroy( hTxData->hBufferPool );
  294. utils_nullTimerDestroy(hOs, pTimer);
  295. utils_nullMemoryFree(hOs, hTxData, sizeof(txData_t));
  296. return NULL;
  297. }
  298. /* allocate timer for debug throughput per queue */
  299. pAirThroughputTimer = os_timerCreate (hOs, txData_printTxAirThroughputPerQueue, hTxData);
  300. if (!pAirThroughputTimer)
  301. {
  302. bufferPool_destroy (hTxData->hBufferPool);
  303. utils_nullTimerDestroy (hOs, pTimer);
  304. utils_nullTimerDestroy (hOs, pThroughputTimer);
  305. utils_nullMemoryFree (hOs, hTxData, sizeof(txData_t));
  306. return NULL;
  307. }
  308. /* allocate timer for debug throughput per queue */
  309. pJitterTimer = os_timerCreate (hOs, txData_printJitter, hTxData);
  310. if (!pJitterTimer)
  311. {
  312. bufferPool_destroy (hTxData->hBufferPool);
  313. utils_nullTimerDestroy (hOs, pTimer);
  314. utils_nullTimerDestroy (hOs, pThroughputTimer);
  315. utils_nullTimerDestroy (hOs, pAirThroughputTimer);
  316. utils_nullMemoryFree (hOs, hTxData, sizeof(txData_t));
  317. return NULL;
  318. }
  319. #endif
  320. /* allocate timer for credit calculation */
  321. pCreditTimer = os_timerCreate(hOs, txData_calcCreditFromTimer, hTxData);
  322. if(!pCreditTimer)
  323. {
  324. bufferPool_destroy( hTxData->hBufferPool );
  325. utils_nullTimerDestroy(hOs, pTimer);
  326. #ifdef TI_DBG
  327. utils_nullTimerDestroy(hOs, pThroughputTimer);
  328. utils_nullTimerDestroy(hOs, pAirThroughputTimer);
  329. utils_nullTimerDestroy(hOs, pJitterTimer);
  330. #endif
  331. utils_nullMemoryFree(hOs, hTxData, sizeof(txData_t));
  332. return NULL;
  333. }
  334. /* initialize management queue */
  335. mgmtMsduList = msduList_CreateNewMsduList( hOs);
  336. if(!mgmtMsduList)
  337. {
  338. bufferPool_destroy( hTxData->hBufferPool );
  339. utils_nullTimerDestroy(hOs, pTimer);
  340. #ifdef TI_DBG
  341. utils_nullTimerDestroy(hOs, pThroughputTimer);
  342. utils_nullTimerDestroy(hOs, pAirThroughputTimer);
  343. utils_nullTimerDestroy(hOs, pJitterTimer);
  344. #endif
  345. utils_nullTimerDestroy(hOs, pCreditTimer);
  346. utils_nullMemoryFree(hOs, hTxData, sizeof(txData_t));
  347. return NULL;
  348. }
  349. /* initialize tx data queues */
  350. for(queueIndex = 0 ; queueIndex < MAX_NUM_OF_TX_QUEUES ; queueIndex++)
  351. {
  352. dataMsduListArr[queueIndex] = msduList_CreateNewMsduList( hOs);
  353. if(!dataMsduListArr[queueIndex])
  354. {
  355. bufferPool_destroy( hTxData->hBufferPool );
  356. utils_nullTimerDestroy(hOs, pTimer);
  357. #ifdef TI_DBG
  358. utils_nullTimerDestroy(hOs, pThroughputTimer);
  359. utils_nullTimerDestroy(hOs, pAirThroughputTimer);
  360. utils_nullTimerDestroy(hOs, pJitterTimer);
  361. #endif
  362. utils_nullTimerDestroy(hOs, pCreditTimer);
  363. utils_nullMemoryFree(hOs, mgmtMsduList, sizeof(MsduList_t));
  364. queueIndex--;
  365. for(; queueIndex >= 0 ; queueIndex--)
  366. {
  367. utils_nullMemoryFree(hOs, dataMsduListArr[queueIndex], sizeof(MsduList_t));
  368. }
  369. utils_nullMemoryFree(hOs, hTxData, sizeof(txData_t));
  370. return NULL;
  371. }
  372. }
  373. hTxData->txDataNumOfQueues = txDataInitParams->txDataNumOfDataQueues;
  374. /* Threshold to decide whether we drop the packet, or sending it to Fw */
  375. /* example: value of 75 will drop any MSDU that stayed it the Driver */
  376. /* Queues for more than 75% of the time that was originally defined for it */
  377. hTxData->uFracOfLifeTimeToDrop = txDataInitParams->uFracOfLifeTimeToDrop;
  378. hTxData->TxEventDistributor = DistributorMgr_Create(hOs,MAX_TX_NOTIF_REQ_ELMENTS);
  379. hTxData->mngMsduList = mgmtMsduList;
  380. for(queueIndex = 0 ; queueIndex < MAX_NUM_OF_TX_QUEUES ; queueIndex++)
  381. {
  382. hTxData->dataMsduListArr[queueIndex] = dataMsduListArr[queueIndex];
  383. }
  384. hTxData->pSchedulerTimer = pTimer;
  385. hTxData->pVadTimer = pVadTimer;
  386. hTxData->bSchedulerTimerRunning = FALSE;
  387. #ifdef TI_DBG
  388. hTxData->pThroughputTimer = pThroughputTimer;
  389. hTxData->pAirThroughputTimer = pAirThroughputTimer;
  390. hTxData->pJitterTimer = pJitterTimer;
  391. #endif
  392. hTxData->pCreditTimer = pCreditTimer;
  393. hTxData->hOs = hOs;
  394. hTxData->bVadTimerEnabled = FALSE;
  395. hTxData->vadTimerDuration = 0;
  396. hTxData->creditCalculationTimeout = txDataInitParams->creditCalculationTimeout;
  397. hTxData->bCreditCalcTimerEnabled = txDataInitParams->bCreditCalcTimerEnabled;
  398. hTxData->admCtrlDelayDueToMediumTimeOverUsage = txDataInitParams->admCtrlDelayDueToMediumTimeOverUsage;
  399. hTxData->admissionDownGradeEnable = txDataInitParams->admissionDownGradeEnable;
  400. return(hTxData);
  401. }
  402. /***************************************************************************
  403. * txData_config *
  404. ****************************************************************************
  405. * DESCRIPTION: This function configures the Tx Data module
  406. *
  407. * INPUTS: hTxData - The object
  408. * hCtrlData - Handle to the Ctrl Data object
  409. * hOs - Handle to the Os Abstraction Layer
  410. * hReport - Handle to the Report object
  411. * hMemMngr - Handle to the Memory manager object
  412. * OUTPUT:
  413. *
  414. * RETURNS: OK - Configuration unsuccessful
  415. * NOK - Configuration unsuccessful
  416. ***************************************************************************/
  417. TI_STATUS txData_config(TI_HANDLE hTxData,
  418. TI_HANDLE hCtrlData,
  419. TI_HANDLE hTnetwDrv,
  420. TI_HANDLE hWhalCtrl,
  421. TI_HANDLE hOs,
  422. TI_HANDLE hReport,
  423. TI_HANDLE hMemMngr,
  424. TI_HANDLE hSiteMgr,
  425. TI_HANDLE hEvHandler,
  426. TI_HANDLE hQosMngr,
  427. TI_HANDLE hPowerMgr)
  428. {
  429. int qIndex;
  430. txData_t *pTxData = (txData_t *)hTxData;
  431. /* configure modules handles */
  432. pTxData->hCtrlData = hCtrlData;
  433. pTxData->hTnetwDrv = hTnetwDrv;
  434. pTxData->hWhalCtrl= hWhalCtrl;
  435. pTxData->hOs = hOs;
  436. pTxData->hReport = hReport;
  437. pTxData->hMemMngr = hMemMngr;
  438. pTxData->hSiteMgr = hSiteMgr;
  439. pTxData->hEvHandler = hEvHandler;
  440. pTxData->hQosMngr = hQosMngr;
  441. pTxData->hPowerMgr = hPowerMgr;
  442. /* set Tx parameters */
  443. pTxData->txDataPortStatus = DEF_TX_PORT_STATUS;
  444. pTxData->savePortStatus = DEF_TX_PORT_STATUS;
  445. pTxData->txDataCurrentPrivacyInvokedMode = DEF_CURRENT_PRIVACY_INVOKED_MODE;
  446. pTxData->saveTxDataCurrentPrivacyInvokedMode = DEF_CURRENT_PRIVACY_INVOKED_MODE;
  447. pTxData->txDataEapolEncryptionStatus = DEF_EAPOL_ENCRYPTION_STATUS;
  448. pTxData->saveTxDataEapolEncryptionStatus = DEF_EAPOL_ENCRYPTION_STATUS;
  449. pTxData->txDataIsSchedulerInWork = DEF_IS_SCHEDULER_IN_WORK;
  450. pTxData->txDataHalInterfaceStatus = DEF_HAL_INTERFACE_STATUS;
  451. /* Initialize the parameters related to GWSI and to Scheduler in Work */
  452. pTxData->txDataGwsiInterfaceStatus = GWSI_OPEN;
  453. pTxData->txDataIsSchedulerInWork = FALSE;
  454. pTxData->bCreditCalcTimerRunning = FALSE;
  455. /* encryption header size */
  456. pTxData->encryptionFieldSize = 0;
  457. pTxData->saveEncryptionFieldSize = 0;
  458. /* configure the packet ID buffer pool */
  459. bufferPool_config( pTxData->hBufferPool, hReport );
  460. /* configure the Tx queues (msdu lists) */
  461. /* num of elements is configured by qosMngr */
  462. for (qIndex = 0; qIndex < MAX_NUM_OF_TX_QUEUES; qIndex++)
  463. {
  464. if( (msduList_ConfigMsduList( pTxData->dataMsduListArr[qIndex], pTxData->hMemMngr,
  465. pTxData->hReport,pTxData->hOs,0 )) != OK )
  466. {
  467. WLAN_REPORT_ERROR(pTxData->hReport, TX_DATA_MODULE_LOG,
  468. ("Error configure DataMsduList num: %d\n",qIndex));
  469. }
  470. /*
  471. * Mark all queues available for TX
  472. */
  473. pTxData->txDataAvailableQueue[qIndex] = TRUE;
  474. }
  475. if( (msduList_ConfigMsduList( pTxData->mngMsduList, pTxData->hMemMngr,
  476. pTxData->hReport, pTxData->hOs,MANAGEMENT_QUEUE_SIZE )) != OK )
  477. {
  478. WLAN_REPORT_ERROR(pTxData->hReport, TX_DATA_MODULE_LOG,
  479. ("Error configure MgmtMsduList\n"));
  480. }
  481. /* reset counters */
  482. txData_resetCounters (pTxData);
  483. txData_resetDbgCounters (pTxData);
  484. WLAN_REPORT_INIT(pTxData->hReport, TX_DATA_MODULE_LOG,
  485. (".....Tx Data configured successfully\n"));
  486. #ifdef NO_COPY_NDIS_BUFFERS
  487. WLAN_REPORT_INFORMATION(pTxData->hReport, TX_DATA_MODULE_LOG,
  488. ("Driver configured to work in NO COPY MSDU BUFFERS."));
  489. #else
  490. WLAN_REPORT_INFORMATION(pTxData->hReport, TX_DATA_MODULE_LOG,
  491. ("Driver is configured to work in COPY MSDU BUFFERS."));
  492. #endif
  493. return OK;
  494. }
  495. /***************************************************************************
  496. * txData_unLoad *
  497. ****************************************************************************
  498. * DESCRIPTION: This function unload the tx data module. It first free the
  499. * MsduLists and then free the Tx data control block
  500. *
  501. * INPUTS: hTxData - the object
  502. *
  503. * OUTPUT:
  504. *
  505. * RETURNS: OK - Unload succesfull
  506. * NOK - Unload unsuccesfull
  507. ***************************************************************************/
  508. TI_STATUS txData_unLoad(TI_HANDLE hTxData)
  509. {
  510. txData_t *pTxData = (txData_t *)hTxData;
  511. TI_STATUS status = OK;
  512. int queueIndex;
  513. /* check parameters validity */
  514. if( pTxData == NULL )
  515. {
  516. return NOK;
  517. }
  518. /* free Data queue msdu list */
  519. for(queueIndex = 0;queueIndex < MAX_NUM_OF_TX_QUEUES; queueIndex++)
  520. {
  521. if (msduList_FreeMsduList( pTxData->dataMsduListArr[queueIndex]) != OK)
  522. {
  523. WLAN_REPORT_ERROR(pTxData->hReport, TX_DATA_MODULE_LOG,
  524. (" txData_unLoad() : fail to free Data MsduList number: %d\n",queueIndex));
  525. status = NOK;
  526. }
  527. }
  528. /* free Mgmt queue msdu list */
  529. if (msduList_FreeMsduList( pTxData->mngMsduList) != OK)
  530. {
  531. WLAN_REPORT_ERROR(pTxData->hReport, TX_DATA_MODULE_LOG,
  532. (" txData_unLoad() : fail to free Mgmt MsduList \n"));
  533. status = NOK;
  534. }
  535. DistributorMgr_Destroy(pTxData->TxEventDistributor);
  536. /* free Timer */
  537. utils_nullTimerDestroy(pTxData->hOs, pTxData->pSchedulerTimer);
  538. utils_nullTimerDestroy(pTxData->hOs, pTxData->pVadTimer);
  539. #ifdef TI_DBG
  540. utils_nullTimerDestroy(pTxData->hOs, pTxData->pThroughputTimer);
  541. utils_nullTimerDestroy(pTxData->hOs, pTxData->pAirThroughputTimer);
  542. utils_nullTimerDestroy(pTxData->hOs, pTxData->pJitterTimer);
  543. #endif
  544. utils_nullTimerDestroy(pTxData->hOs, pTxData->pCreditTimer);
  545. /* release the packet ID buffer pool */
  546. bufferPool_destroy( pTxData->hBufferPool );
  547. /* free Tx Data control block */
  548. os_memoryFree(pTxData->hOs, pTxData, sizeof(txData_t));
  549. return status;
  550. }
  551. /****************************************************************************
  552. * txData_stop *
  553. *****************************************************************************
  554. * DESCRIPTION: this function stop the tx data. It empties the tx queues (msdu
  555. * lists) from the msdu's and return all tx data parameters to
  556. * default values
  557. *
  558. * INPUTS: hTxData - the object
  559. *
  560. * OUTPUT:
  561. *
  562. * RETURNS: OK - stop successful
  563. * NOK - stop unsuccessful
  564. ****************************************************************************/
  565. TI_STATUS txData_stop(TI_HANDLE hTxData)
  566. {
  567. txData_t *pTxData = (txData_t *)hTxData;
  568. int queueIndex;
  569. pTxData->savePortStatus = pTxData->txDataPortStatus;
  570. /* stop scheduler timer trigger */
  571. if ( TRUE == pTxData->bSchedulerTimerRunning )
  572. {
  573. os_timerStop(pTxData->hOs, pTxData->pSchedulerTimer);
  574. }
  575. /* stop vad timer */
  576. if ( TRUE == pTxData->bVadTimerEnabled )
  577. {
  578. os_timerStop(pTxData->hOs, pTxData->pVadTimer);
  579. }
  580. /* stop throughput timer */
  581. if(pTxData->txThroughputTimerEnable == TRUE)
  582. {
  583. os_timerStop(pTxData->hOs, pTxData->pThroughputTimer);
  584. pTxData->txThroughputTimerEnable = FALSE;
  585. }
  586. /* stop throughput timer */
  587. if (pTxData->txAirThroughputTimerEnable)
  588. {
  589. os_timerStop (pTxData->hOs, pTxData->pAirThroughputTimer);
  590. pTxData->txAirThroughputTimerEnable = FALSE;
  591. }
  592. /* stop credit calculation timer */
  593. if ( pTxData->bCreditCalcTimerRunning )
  594. {
  595. os_timerStop(pTxData->hOs, pTxData->pCreditTimer);
  596. pTxData->bCreditCalcTimerRunning = FALSE;
  597. }
  598. /* empty Tx data queue from Msdus */
  599. for(queueIndex = 0;queueIndex < MAX_NUM_OF_TX_QUEUES; queueIndex++)
  600. {
  601. if( msduList_EmptyMsduList( pTxData->dataMsduListArr[queueIndex] ) != OK)
  602. {
  603. WLAN_REPORT_ERROR(pTxData->hReport, TX_DATA_MODULE_LOG,
  604. (" txData_stop() : fail to empty Data Msdu List number: %d\n",queueIndex));
  605. return NOK;
  606. }
  607. }
  608. /* empty Tx Mgmt queue from Msdus */
  609. if( msduList_EmptyMsduList( pTxData->mngMsduList ) != OK)
  610. {
  611. WLAN_REPORT_ERROR(pTxData->hReport, TX_DATA_MODULE_LOG,
  612. (" txData_stop() : fail to empty Mgmt Msdu List \n"));
  613. return NOK;
  614. }
  615. /* set Tx parameters to default values */
  616. pTxData->txDataPortStatus = DEF_TX_PORT_STATUS;
  617. pTxData->saveTxDataCurrentPrivacyInvokedMode = pTxData->txDataCurrentPrivacyInvokedMode;
  618. pTxData->saveTxDataEapolEncryptionStatus = pTxData->txDataEapolEncryptionStatus;
  619. pTxData->saveEncryptionFieldSize = pTxData->encryptionFieldSize;
  620. pTxData->txDataCurrentPrivacyInvokedMode = DEF_CURRENT_PRIVACY_INVOKED_MODE;
  621. pTxData->txDataEapolEncryptionStatus = DEF_EAPOL_ENCRYPTION_STATUS;
  622. pTxData->encryptionFieldSize = 0;
  623. WLAN_REPORT_INFORMATION(pTxData->hReport, TX_DATA_MODULE_LOG,
  624. (" txData_stop() : Succeeded.\n"));
  625. return OK;
  626. }
  627. /****************************************************************************
  628. * txData_start *
  629. *****************************************************************************
  630. * DESCRIPTION: this function start the tx data.
  631. *
  632. * INPUTS: hTxData - the object
  633. *
  634. * OUTPUT:
  635. *
  636. * RETURNS: OK - stop succesfull
  637. * NOK - stop unsuccesfull
  638. ****************************************************************************/
  639. TI_STATUS txData_start(TI_HANDLE hTxData)
  640. {
  641. txData_t *pTxData = (txData_t *)hTxData;
  642. /* check parameters validity */
  643. if( pTxData == NULL )
  644. {
  645. WLAN_REPORT_ERROR(pTxData->hReport, TX_DATA_MODULE_LOG,
  646. (" txData_start() : Illegal value for hTxData\n"));
  647. return NOK;
  648. }
  649. pTxData->txDataPortStatus = pTxData->savePortStatus;
  650. return OK;
  651. }
  652. /****************************************************************************
  653. * txData_recoveryIndication *
  654. *****************************************************************************
  655. * DESCRIPTION: this function clears information on recovery.
  656. *
  657. * INPUTS: hTxData - the object
  658. *
  659. * OUTPUT:
  660. *
  661. * RETURNS:
  662. ****************************************************************************/
  663. void txData_recoveryIndication (TI_HANDLE hTxData)
  664. {
  665. txData_t *pTxData = (txData_t *)hTxData;
  666. int queueIndex;
  667. /* Reinitializes packet ID buffer pool (mark all buffers as available) */
  668. bufferPool_reinit (pTxData->hBufferPool);
  669. /* Empty Tx data queue from Msdus */
  670. for (queueIndex = 0; queueIndex < MAX_NUM_OF_TX_QUEUES; queueIndex++)
  671. {
  672. if (msduList_EmptyMsduList (pTxData->dataMsduListArr[queueIndex]) != OK)
  673. {
  674. WLAN_REPORT_ERROR(pTxData->hReport, TX_DATA_MODULE_LOG,
  675. (" txData_stop() : fail to empty data MSDU list number: %d\n", queueIndex));
  676. }
  677. }
  678. /* Empty Tx management queue from MSDU's */
  679. if (msduList_EmptyMsduList (pTxData->mngMsduList) != OK)
  680. {
  681. WLAN_REPORT_ERROR (pTxData->hReport, TX_DATA_MODULE_LOG,
  682. (" txData_stop() : fail to empty management MSDU list\n"));
  683. }
  684. /*
  685. * Set GWSI interfaces status as 'opened'
  686. * because it can be undefined upon recovery
  687. */
  688. pTxData->txDataGwsiInterfaceStatus = GWSI_OPEN;
  689. for (queueIndex = 0; queueIndex < MAX_NUM_OF_TX_QUEUES; queueIndex++)
  690. {
  691. /*
  692. * Mark all queues available for TX
  693. */
  694. pTxData->txDataAvailableQueue[queueIndex] = TRUE;
  695. }
  696. }
  697. /***************************************************************************
  698. * txData_checkQueueSize *
  699. ****************************************************************************
  700. * DESCRIPTION: Check the Tx Queue size
  701. *
  702. * INPUTS: hTxData - the object
  703. *
  704. * OUTPUT:
  705. *
  706. * RETURNS: OK
  707. * NOK - The queue is full
  708. ***************************************************************************/
  709. TI_STATUS txData_checkQueueSize(TI_HANDLE hTxData,UINT8 qIndex)
  710. {
  711. txData_t *pTxData = (txData_t *)hTxData;
  712. TI_STATUS Status = OK;
  713. txData_startTxScheduler(pTxData);
  714. if (pTxData->dataMsduListArr[qIndex]->CurrNumOfMsdu == pTxData->dataMsduListArr[qIndex]->maxNumOfMsdu)
  715. Status = NOK;
  716. return Status;
  717. }
  718. /***************************************************************************
  719. * txData_copyPacketToMsdu *
  720. ****************************************************************************
  721. * DESCRIPTION:
  722. *
  723. * INPUTS: hTxData - the object
  724. *
  725. * OUTPUT:
  726. *
  727. * RETURNS: OK
  728. * NOK - The queue is full
  729. ***************************************************************************/
  730. TI_STATUS txData_copyPacketToMsdu(TI_HANDLE hTxData,mem_MSDU_T **pMsdu, int FreeOldMsdu)
  731. {
  732. #ifdef NO_COPY_NDIS_BUFFERS
  733. txData_t *pTxData = (txData_t *)hTxData;
  734. TI_STATUS Status = OK;
  735. mem_BD_T *pCurrBd;
  736. mem_MSDU_T *tempMsdu;
  737. UINT8 *pMsduData;
  738. UINT8 *pCurrBufData;
  739. dot11_header_t *pdot11Header;
  740. /*
  741. * Allocate MSDU+BD+BUFFER+TX_DESCRIPTOR_SIZE to copy to !!
  742. */
  743. if(wlan_memMngrAllocMSDU(pTxData->hMemMngr,&tempMsdu,(*pMsdu)->dataLen+TX_TOTAL_OFFSET_BEFORE_DATA,TX_MODULE) != OK)
  744. {
  745. WLAN_REPORT_ERROR(pTxData->hReport, TX_DATA_MODULE_LOG,
  746. (" txData_copyPacketToMsdu() : No Memory in MemMgr \n"));
  747. return NOK;
  748. }
  749. tempMsdu->dataLen = 0;
  750. tempMsdu->firstBDPtr->length = 0;
  751. tempMsdu->txFlags = (*pMsdu)->txFlags;
  752. pCurrBd = (*pMsdu)->firstBDPtr;
  753. pMsduData = tempMsdu->firstBDPtr->data + TX_TOTAL_OFFSET_BEFORE_DATA;
  754. while(pCurrBd)
  755. {
  756. pCurrBufData = pCurrBd->data + pCurrBd->dataOffset;
  757. /* Copy the packet */
  758. os_memoryCopy(pTxData->hOs, pMsduData, pCurrBufData, pCurrBd->length);
  759. tempMsdu->dataLen += pCurrBd->length - TNETWIF_WRITE_OFFSET_BYTES;
  760. tempMsdu->firstBDPtr->length += pCurrBd->length;
  761. pMsduData += pCurrBd->length;
  762. pCurrBd = pCurrBd->nextBDPtr;
  763. }
  764. tempMsdu->headerLen = (*pMsdu)->headerLen;
  765. txData_convertEthToWlanHeader( pTxData, tempMsdu );
  766. /* set wep bit if needed */
  767. if((tempMsdu->txFlags & TX_DATA_DATA_MSDU) && (pTxData->txDataCurrentPrivacyInvokedMode))
  768. {
  769. pdot11Header = (dot11_header_t*)(memMgr_BufData(pMsdu->firstBDPtr) + memMgr_BufOffset(pMsdu->firstBDPtr));
  770. pdot11Header->fc |= DOT11_FC_WEP;
  771. }
  772. else if ((tempMsdu->txFlags & TX_DATA_EAPOL_MSDU ) && (pTxData->txDataEapolEncryptionStatus))
  773. {
  774. pdot11Header = (dot11_header_t*)(memMgr_BufData(pMsdu->firstBDPtr) + memMgr_BufOffset(pMsdu->firstBDPtr));
  775. pdot11Header->fc |= DOT11_FC_WEP;
  776. }
  777. if (FreeOldMsdu)
  778. wlan_memMngrFreeMSDU(pTxData->hMemMngr, memMgr_MsduHandle((*pMsdu)));
  779. (*pMsdu) = tempMsdu;
  780. #endif
  781. return OK;
  782. }
  783. /***************************************************************************
  784. * txData_sendPktToWlan *
  785. ****************************************************************************
  786. * DESCRIPTION: This function is called by the Os Abstraction Layer in order
  787. * to send packet to the wireless LAN. It calls the header
  788. * conversion function and passes the to sendMsdu function.
  789. *
  790. * INPUTS: hTxData - the object
  791. * pMsdu - pointer the packet in 802.3 format
  792. *
  793. * OUTPUT:
  794. *
  795. * RETURNS: OK
  796. * NOK
  797. ***************************************************************************/
  798. TI_STATUS txData_sendPktToWlan(TI_HANDLE hTxData, mem_MSDU_T *pMsdu, UINT8 pkt_DTag)
  799. {
  800. EthernetHeader_t *pEthHeader;
  801. UINT16 TypeLength;
  802. TI_STATUS Status;
  803. mem_BD_T* tempBd;
  804. BOOL UseConvertHeader = TRUE;
  805. txData_t *pTxData = (txData_t *)hTxData;
  806. /* check parameters validity */
  807. if( pTxData == NULL || pMsdu == NULL )
  808. {
  809. return NOK;
  810. }
  811. pEthHeader = (EthernetHeader_t*)(memMgr_BufData(pMsdu->firstBDPtr)+memMgr_BufOffset(pMsdu->firstBDPtr));
  812. /* check if the frame is multicast/broadcast - need for the transmission rate */
  813. if(IsMacAddressGroup( &pEthHeader->DstAddr ))
  814. pMsdu->txFlags |= TX_DATA_MULTICAST_FRAME;
  815. TypeLength = pEthHeader->TypeLength;
  816. /* Call the Classify function in the Control Module to set the qosTag of the MSDU */
  817. if (ctrlData_ClsfrClassifyTxMSDU(pTxData->hCtrlData, pMsdu, pkt_DTag) != OK)
  818. {
  819. WLAN_REPORT_DEBUG_TX(pTxData->hReport,
  820. (" txData_sendPktToWlan(): No matching classifier found\n"));
  821. }
  822. /* filter MSDU according to Tx Port Status and the Eth Type */
  823. if ( pTxData->txDataPortStatus != OPEN )
  824. {
  825. int queueIndex;
  826. int acIndex;
  827. WLAN_REPORT_WARNING(pTxData->hReport, TX_DATA_MODULE_LOG,
  828. (" txData_sendPktToWlan() : try to transmit Msdu while port is not open (txDataPortStatus = 0x%x)\n", pTxData->txDataPortStatus));
  829. /* Find AC and Tx-queue in order to update the correct Queue measurements */
  830. acIndex = GET_WME_AC_TYPE_FROM_MSDU(pMsdu);
  831. queueIndex = GET_QUEUE_INDEX(pTxData,acIndex);
  832. /* updating the measurements - dropped packet counter */
  833. pTxData->txDataReportedCounters[queueIndex].OtherFailCounter++;
  834. pTxData->txDataReportedCounters[queueIndex].NumPackets++;
  835. if((pTxData->txDataPortStatus == CLOSE) || (pTxData->txDataPortStatus == OPEN_NOTIFY) )
  836. {
  837. WLAN_REPORT_WARNING(pTxData->hReport, TX_DATA_MODULE_LOG,
  838. (" txData_sendPktToWlan() : try to transmit Msdu while port is not open (txDataPortStatus = 0x%x)\n", pTxData->txDataPortStatus));
  839. /* In case the function return status is NOK, no need to call Os free function */
  840. /* Set freefunc in the msdu to null. In this case the MemMngr will not call */
  841. /* the Os free function */
  842. memMgr_MsduFreeFuncGet(pMsdu) = NULL;
  843. /* free MSDU */
  844. if( (wlan_memMngrFreeMSDU(pTxData->hMemMngr, memMgr_MsduHandle(pMsdu))) != OK )
  845. {
  846. WLAN_REPORT_ERROR(pTxData->hReport, TX_DATA_MODULE_LOG,
  847. (" txData_sendPktToWlan() : free msdu failed \n"));
  848. }
  849. return NOK;
  850. }
  851. /* filter Data frames while port is open only for Eapol's */
  852. if( (pTxData->txDataPortStatus == OPEN_EAPOL) && (TypeLength != EAPOL_PACKET) )
  853. {
  854. WLAN_REPORT_WARNING(pTxData->hReport, TX_DATA_MODULE_LOG,
  855. (" txData_sendPktToWlan() : try to transmit Non Eapol packet while port is open for eapols only\n"));
  856. /* In case the function return status is NOK, no need to call Os free function. */
  857. /* Set freefunc in the msdu to null. In this case the MemMngr will not call */
  858. /* the Os free function - because the return staus to the Os is NOK the buffer */
  859. /* free by the Os */
  860. memMgr_MsduFreeFuncGet(pMsdu) = NULL;
  861. /* frre MSDU */
  862. if ((wlan_memMngrFreeMSDU(pTxData->hMemMngr, memMgr_MsduHandle(pMsdu))) != OK)
  863. {
  864. WLAN_REPORT_ERROR(pTxData->hReport, TX_DATA_MODULE_LOG,
  865. (" txData_sendPktToWlan() : free msdu failed \n"));
  866. }
  867. return NOK;
  868. }
  869. }
  870. /* PORT IS OPEN */
  871. #ifdef CORE_TX_DBG
  872. WLAN_REPORT_INFORMATION(pTxData->hReport, TX_DATA_MODULE_LOG,
  873. (" txData_sendPktToWlan: port is open \n"));
  874. #endif
  875. if( TypeLength != EAPOL_PACKET )
  876. {
  877. pMsdu->txFlags |= TX_DATA_DATA_MSDU;
  878. }
  879. else
  880. {
  881. WLAN_REPORT_INFORMATION(pTxData->hReport, TX_DATA_MODULE_LOG,
  882. (" txData_sendPktToWlan() : Tx an EAPOL frame tranferred to HAL\n"));
  883. /* because EAPOL is sent from Mgmt queue */
  884. pMsdu->txFlags |= TX_DATA_EAPOL_MSDU;
  885. }
  886. UseConvertHeader = TRUE; /* a patch for WinCe */
  887. #ifdef NO_COPY_NDIS_BUFFERS
  888. if (pMsdu->txFlags & TX_DATA_FROM_OS)
  889. UseConvertHeader = FALSE; /* don't convert on external (OS) packets */
  890. #endif
  891. if (UseConvertHeader == TRUE)
  892. {
  893. /* Header conversion from Ethernet to 802.11 */
  894. txData_convertEthToWlanHeader( pTxData, pMsdu );
  895. }
  896. /* update last BD */
  897. tempBd = pMsdu->firstBDPtr;
  898. while(tempBd->nextBDPtr)
  899. {
  900. tempBd = tempBd->nextBDPtr;
  901. }
  902. pMsdu->lastBDPtr = tempBd;
  903. Status = txData_txSendMsdu( pTxData, pMsdu );
  904. if( Status == NOK )
  905. {
  906. WLAN_REPORT_ERROR(pTxData->hReport, TX_DATA_MODULE_LOG,
  907. (" txData_sendPktToWlan() : txData_txSendMsdu failed \n"));
  908. }
  909. if ((OK == Status) && (GET_WME_AC_TYPE_FROM_MSDU(pMsdu) == QOS_AC_VO))
  910. {
  911. txData_resetVadTimer(pTxData);
  912. }
  913. return Status;
  914. }
  915. /***************************************************************************
  916. * txData_txSendMsdu *
  917. ****************************************************************************
  918. * DESCRIPTION: This function is insert the MSDU to transmit to the proper
  919. * tx queue and give a trigger to the scheduler to start
  920. * transmission to the wireless LAN.
  921. *
  922. * INPUTS: hTxData - the object
  923. * pMsdu - pointer the MSDU in 802.11 format
  924. *
  925. * OUTPUT:
  926. *
  927. * RETURNS: OK
  928. * NOK
  929. ***************************************************************************/
  930. TI_STATUS txData_txSendMsdu(TI_HANDLE hTxData, mem_MSDU_T *pMsdu )
  931. {
  932. dot11_header_t *pdot11Header;
  933. TI_STATUS Status = OK;
  934. int queueIndex;
  935. acTrfcType_e acIndex;
  936. txData_t *pTxData = (txData_t *)hTxData;
  937. /* ctrlData_txMsdu(pTxData->hCtrlData,&pMsdu); 4x related */
  938. if(pMsdu == NULL)
  939. {
  940. WLAN_REPORT_INFORMATION(pTxData->hReport, TX_DATA_MODULE_LOG,
  941. (" txData_txSendMsdu() : DISCARD Packet...... \n"));
  942. txData_startTxScheduler(pTxData);
  943. return NOK;
  944. }
  945. #ifndef NO_COPY_NDIS_BUFFERS /* buffers are copied by OAL*/
  946. /* set wep bit if needed */
  947. if((pMsdu->txFlags & TX_DATA_DATA_MSDU) && (pTxData->txDataCurrentPrivacyInvokedMode))
  948. {
  949. /* update offset of header */
  950. pdot11Header = (dot11_header_t*)(memMgr_BufData(pMsdu->firstBDPtr) + memMgr_BufOffset(pMsdu->firstBDPtr));
  951. pdot11Header->fc |= DOT11_FC_WEP;
  952. }
  953. else if ((pMsdu->txFlags & TX_DATA_EAPOL_MSDU ) && (pTxData->txDataEapolEncryptionStatus))
  954. {
  955. /* update offset of header */
  956. pdot11Header = (dot11_header_t*)(memMgr_BufData(pMsdu->firstBDPtr) + memMgr_BufOffset(pMsdu->firstBDPtr));
  957. pdot11Header->fc |= DOT11_FC_WEP;
  958. }
  959. #endif /*NO_COPY_NDIS_BUFFERS*/
  960. #ifdef EXC_MODULE_INCLUDED
  961. if ((pMsdu->txFlags & TX_DATA_IAPP_MSDU) && (pTxData->txDataCurrentPrivacyInvokedMode))
  962. {
  963. /* update offset of header */
  964. pdot11Header = (dot11_header_t*)(memMgr_BufData(pMsdu->firstBDPtr) + memMgr_BufOffset(pMsdu->firstBDPtr));
  965. pdot11Header->fc |= DOT11_FC_WEP;
  966. }
  967. #endif
  968. WLAN_REPORT_DEBUG_TX(pTxData->hReport,
  969. (" txData_txSendMsdu() : Sending PAcket pMsdu %x pMsdu->txFlags %x \n",pMsdu,pMsdu->txFlags));
  970. /* insert the msdu to the the appropriate queue */
  971. if( (pMsdu->txFlags & TX_DATA_DATA_MSDU) || (pMsdu->txFlags & TX_DATA_NULL_MSDU) )
  972. {
  973. /* Find Tx-queue and AC to use for Tx, and if downgraded from original one update the UP. */
  974. txData_selectQueueAndUpdateUserPriority (pTxData, pMsdu, &queueIndex, &acIndex);
  975. /* set insertion time for further expiry timeout calculation */
  976. pMsdu->insertionTime = os_timeStampUs (pTxData->hOs);
  977. /* see if the frame is tagged VO. */
  978. /* Note: Check actual tag even if current not working in WME, to support voice anyway. */
  979. if( GET_WME_AC_TYPE_FROM_MSDU(pMsdu) == QOS_AC_VO)
  980. {
  981. /*
  982. * If the frame is tagged VO and power save is on, send psPoll before the VO frame.
  983. */
  984. if(txData_acVoPsPollMode(pTxData) == TRUE)
  985. {
  986. mem_MSDU_T *pMsduPsPoll;
  987. if(txData_getPsPollFrame(pTxData,&pMsduPsPoll) == OK)
  988. {
  989. /* increment debug counters */
  990. pTxData->txDataDbgCounters.dbgInsertToMsduListBytes[queueIndex] += pMsduPsPoll->dataLen;
  991. pTxData->txDataDbgCounters.dbgInsertToMsduListPackets[queueIndex]++;
  992. /* set insertion time for further expiry timeout calculation */
  993. pMsduPsPoll->insertionTime = os_timeStampUs (pTxData->hOs);
  994. /* insert to queueIndex queue */
  995. if( msduList_Insert( pTxData->dataMsduListArr[queueIndex] , &pMsduPsPoll ) != OK )
  996. {
  997. pTxData->txDataDbgCounters.dbgDropedFromMsduListPackets[queueIndex]++;
  998. /* the first msdu in list has removed and the new one has inserted */
  999. WLAN_REPORT_WARNING(pTxData->hReport, TX_DATA_MODULE_LOG,
  1000. (" txData_sendPktToWlan() : Msdu List num %d was full \n",queueIndex));
  1001. /* free the msdu which removed from the list (returned in pMsdu) */
  1002. /*---------------------------------------------------------------*/
  1003. /* set msdu tx status to Fail (this status is used by OS) */
  1004. memMgr_MsduFreeArg2Get(pMsduPsPoll) = NOK;
  1005. /* free the msdu */
  1006. wlan_memMngrFreeMSDU(pTxData->hMemMngr, memMgr_MsduHandle(pMsduPsPoll));
  1007. pTxData->txDataDbgCounters.dbgDropedPacketsCounter++;
  1008. }/*msduList_Insert*/
  1009. }/*txData_getPsPollFrame*/
  1010. }/*txData_acVoPsPollMode*/
  1011. }
  1012. /* insert to data queue */
  1013. /* if we didn't succeed to insert psPolls exclude VO packet also */
  1014. if( msduList_Insert( pTxData->dataMsduListArr[queueIndex] , &pMsdu ) != OK )
  1015. {
  1016. pTxData->txDataDbgCounters.dbgDropedFromMsduListPackets[queueIndex]++;
  1017. /* the first msdu in list has removed and the new one has inserted */
  1018. WLAN_REPORT_WARNING(pTxData->hReport, TX_DATA_MODULE_LOG,
  1019. (" txData_txSendMsdu() : Data Msdu [%d] List was full \n",queueIndex));
  1020. /* free the msdu which removed from the list (returned in pMsdu) */
  1021. /*---------------------------------------------------------------*/
  1022. /* set msdu tx status to Fail (this status is used by OS) */
  1023. memMgr_MsduFreeArg2Get(pMsdu) = NOK;
  1024. /* free the msdu */
  1025. wlan_memMngrFreeMSDU(pTxData->hMemMngr, memMgr_MsduHandle(pMsdu));
  1026. pTxData->txDataDbgCounters.dbgDropedPacketsCounter++;
  1027. pTxData->txDataReportedCounters[queueIndex].NumPackets++;
  1028. pTxData->txDataReportedCounters[queueIndex].OtherFailCounter++;
  1029. return OK;
  1030. }
  1031. /* increament debug counters */
  1032. pTxData->txDataDbgCounters.dbgInsertToMsduListBytes[queueIndex] += pMsdu->dataLen;
  1033. pTxData->txDataDbgCounters.dbgInsertToMsduListPackets[queueIndex]++;
  1034. WLAN_REPORT_DEBUG_TX(pTxData->hReport,
  1035. (" txData_txSendMsdu() : insert data packet to queue # %d \n",queueIndex));
  1036. }
  1037. else
  1038. {
  1039. /* Management frame, Eapol and null frame (for measuring a non serving channel)
  1040. are also sent from the mgmt queue */
  1041. /* set insertion time for further expiry timeout calculation */
  1042. pMsdu->insertionTime = os_timeStampUs (pTxData->hOs);
  1043. WLAN_REPORT_DEBUG_TX(pTxData->hReport,
  1044. (" txData_txSendMsdu() : insert mngt packet to Management queue pMsdu %x \n",pMsdu));
  1045. if( msduList_Insert( pTxData->mngMsduList , &pMsdu ) != OK )
  1046. {
  1047. /* the first msdu in list has removed and the new one has inserted */
  1048. WLAN_REPORT_WARNING(pTxData->hReport, TX_DATA_MODULE_LOG,
  1049. (" txData_txSendMsdu() : Mgmt Msdu List was full \n"));
  1050. /* free the msdu which removed from the list (returned in pMsdu) */
  1051. /*---------------------------------------------------------------*/
  1052. /* set msdu tx status to Fail (this status is used by OS) */
  1053. memMgr_MsduFreeArg2Get(pMsdu) = NOK;
  1054. /* free the msdu */
  1055. wlan_memMngrFreeMSDU(pTxData->hMemMngr, memMgr_MsduHandle(pMsdu));
  1056. pTxData->txDataDbgCounters.dbgDropedPacketsCounter++;
  1057. }
  1058. }
  1059. {
  1060. /* call the scheduler in order to transmit the frame to the Hal */
  1061. Status = txData_startTxScheduler(pTxData);
  1062. if ( Status == NOK )
  1063. {
  1064. WLAN_REPORT_ERROR(pTxData->hReport, TX_DATA_MODULE_LOG,
  1065. (" txData_txSendMsdu() : txData_startTxScheduler error \n"));
  1066. }
  1067. }
  1068. /* this is the status of the current Msdu */
  1069. return OK;
  1070. }
  1071. /***************************************************************************
  1072. * txData_startTxScheduler *
  1073. ****************************************************************************
  1074. * DESCRIPTION: This function start the transmission process.
  1075. * It select msdu to transmit from the tx queues and send
  1076. * it to the Hal
  1077. *
  1078. * INPUTS: hTxData - the object
  1079. *
  1080. * OUTPUT:
  1081. *
  1082. * RETURNS: OK
  1083. * NOK
  1084. ***************************************************************************/
  1085. TI_STATUS txData_startTxScheduler(TI_HANDLE hTxData)
  1086. {
  1087. txData_t *pTxData = (txData_t *)hTxData;
  1088. mem_MSDU_T *pMsdu;
  1089. MsduList_t *pMsduList = NULL;
  1090. txData_attr_t txAttr;
  1091. UINT8 count, selectedQueueIndex;
  1092. TI_STATUS txStatus;
  1093. txPacketIdAttr_t *pPacketId;
  1094. dot11_header_t *pDot11Header;
  1095. bssType_e currBssType;
  1096. macAddress_t currBssId;
  1097. UINT32 msduTimeToExpiry;
  1098. #ifdef SUPPORT_4X
  1099. hwTxInformation_t hwTxInformation;
  1100. BOOL fourXEnable;
  1101. #endif
  1102. /* check if HAL is open now - used for recovery only!!! */
  1103. if ( pTxData->txDataHalInterfaceStatus == TX_DATA_CLOSED )
  1104. {
  1105. return OK; /* TODO ronen: doesn't seem to be used any more, remove */
  1106. }
  1107. /* Checking if Tx is now disabled */
  1108. if(pTxData->txDisable == DISABLE_IMMEDIATELY)
  1109. {
  1110. WLAN_REPORT_WARNING(pTxData->hReport, TX_DATA_MODULE_LOG,
  1111. (" txData_startTxScheduler() : Tx Disabled!!! \n"));
  1112. /* start scheduler timer */
  1113. if ( FALSE == pTxData->bSchedulerTimerRunning )
  1114. {
  1115. os_timerStart( pTxData->hOs, pTxData->pSchedulerTimer, SCHEDULER_TIMER, FALSE );
  1116. pTxData->bSchedulerTimerRunning = TRUE;
  1117. }
  1118. pTxData->txDataIsSchedulerInWork = FALSE;
  1119. return OK;
  1120. }
  1121. /*
  1122. * in case of non serialized system no need to
  1123. * run the scheduler if it is already in work
  1124. */
  1125. if(pTxData->txDataIsSchedulerInWork == TRUE)
  1126. {
  1127. WLAN_REPORT_WARNING(pTxData->hReport, TX_DATA_MODULE_LOG,
  1128. (" txData_startTxScheduler() : Scheduler already in work...........!!!! \n"));
  1129. return OK;
  1130. }
  1131. else
  1132. {
  1133. pTxData->txDataIsSchedulerInWork = TRUE;
  1134. }
  1135. /* try to transmit DEF_SCHEDULER_THRESHOLD MSDUs */
  1136. count = DEF_SCHEDULER_THRESHOLD;
  1137. /*
  1138. * if non of the queues is available non msdu will be selected
  1139. */
  1140. while ( (0 < count--) && (GWSI_OPEN == pTxData->txDataGwsiInterfaceStatus) )
  1141. {
  1142. /* select queue to transmit from */
  1143. if( txData_schedulerSelectQueueToTransmitFrom( pTxData, &pMsduList,&selectedQueueIndex ) != TX_QUEUE_SELECTED_OK)
  1144. {
  1145. WLAN_REPORT_DEBUG_TX(pTxData->hReport,
  1146. (" txData_startTxScheduler() : No Msdu waiting to transmit \n"));
  1147. pTxData->txDataIsSchedulerInWork = FALSE;
  1148. return OK;
  1149. }
  1150. WLAN_REPORT_DEBUG_TX(pTxData->hReport,
  1151. (" txData_startTxScheduler() : txData_schedulerSelectQueueToTransmitFrom Returned from selectedQueueIndex %d \n",selectedQueueIndex));
  1152. #ifdef SUPPORT_4X
  1153. ctrlData_get4xStatus(pTxData->hCtrlData,&fourXEnable);
  1154. if(fourXEnable == TRUE && pMsduList != pTxData->mngMsduList)
  1155. {
  1156. /*
  1157. * receive Acx tx queuue information for transmission decision
  1158. */
  1159. whalTx_getTxQueueInfo(pTxData->hWhalTx,
  1160. DEFAULT_QUEUE_TO_HAL,
  1161. &hwTxInformation.hwNumOfFreeMsdu,
  1162. &hwTxInformation.hwNumOfBusyMsdu,
  1163. &hwTxInformation.hwNumOfFreeBDs,
  1164. &hwTxInformation.hwTotalAvailMem );
  1165. /*
  1166. * call ctrl Data - DequeueMsdu...
  1167. * pMsdu - the msdu to transmit.
  1168. * txAttr - the tx attributes for msdu transmission
  1169. */
  1170. status = ctrlData_txDequeueMsdu(pTxData->hCtrlData, &pMsdu, pMsduList, &txAttr, &hwTxInformation);
  1171. if(status == DO_NOT_SEND_MSDU)
  1172. {
  1173. WLAN_REPORT_ERROR(pTxData->hReport,
  1174. (" txData_startTxScheduler() : TX_STATUS_PENDING \n"));
  1175. pTxData->txDataIsSchedulerInWork = FALSE;
  1176. return TX_STATUS_PENDING;
  1177. }
  1178. }
  1179. #else /* if not SUPPORT_4X */
  1180. {
  1181. /* increment debug counter */
  1182. pTxData->txDataDbgCounters.dbgScheduledOutPackets[selectedQueueIndex]++;
  1183. if( msduList_WatchFirst( pMsduList ,&pMsdu) != OK )
  1184. {
  1185. WLAN_REPORT_ERROR( pTxData->hReport, TX_DATA_MODULE_LOG,
  1186. ("Unable to retrieve first MSDU from queue index:%d\n", selectedQueueIndex) );
  1187. pTxData->txDataIsSchedulerInWork = FALSE;
  1188. return OK;
  1189. }
  1190. WLAN_REPORT_DEBUG_TX(pTxData->hReport,
  1191. (" txData_startTxScheduler() : After msduList_WatchFirst pMsdu %d \n",pMsdu));
  1192. #ifdef NO_COPY_NDIS_BUFFERS
  1193. if(pMsdu->txFlags & TX_DATA_FROM_OS)
  1194. {
  1195. if(txData_copyPacketToMsdu(pTxData, &pMsdu, 1 /* do FreeOldMsdu */) != OK)
  1196. {
  1197. WLAN_REPORT_ERROR(pTxData->hReport, TX_DATA_MODULE_LOG,
  1198. (" txData_startTxScheduler() : txData_copyPacketToMsdu FAILED \n"));
  1199. pTxData->txDataIsSchedulerInWork = FALSE;
  1200. return NOK;
  1201. }
  1202. }
  1203. #endif /* NO_COPY_NDIS_BUFFERS */
  1204. }
  1205. #endif /* SUPPORT_4X */
  1206. /* check MSDU expiry time, and if it didn't expire send it to GWSI */
  1207. if ((msduTimeToExpiry = txDataTimeToMsduExpiry (hTxData, pMsdu, selectedQueueIndex)) == 0)
  1208. {
  1209. /* MSDU time expired - drop it */
  1210. WLAN_REPORT_INFORMATION(pTxData->hReport, TX_DATA_MODULE_LOG,
  1211. ("txData_startTxScheduler drop msdu due to expiry time, queueId = %d \n",selectedQueueIndex));
  1212. /* Get MSDU with dequeuing */
  1213. if ( (msduList_GetFirst( pMsduList, &pMsdu )) != OK )
  1214. {
  1215. /* No MSDU is waiting to transmit */
  1216. WLAN_REPORT_ERROR (pTxData->hReport, TX_DATA_MODULE_LOG,
  1217. ("%s: can't get Msdu from pMsduList[ %d ] \n", __FUNCTION__, selectedQueueIndex));
  1218. pTxData->txDataIsSchedulerInWork = FALSE;
  1219. return NOK;
  1220. }
  1221. pTxData->txDataDbgCounters.dbgDroppedDueExpiryTimePackets[selectedQueueIndex]++;
  1222. pTxData->txDataReportedCounters[selectedQueueIndex].NumPackets++;
  1223. pTxData->txDataReportedCounters[selectedQueueIndex].OtherFailCounter++;
  1224. /* free the MSDU */
  1225. memMgr_MsduFreeArg2Get(pMsdu) = OK;
  1226. if( (wlan_memMngrFreeMSDU(pTxData->hMemMngr, memMgr_MsduHandle(pMsdu))) != OK )
  1227. {
  1228. WLAN_REPORT_ERROR(pTxData->hReport, TX_DATA_MODULE_LOG,
  1229. (" txData_startTxScheduler() : free msdu failed \n"));
  1230. }
  1231. /* continue to next packet */
  1232. continue;
  1233. }
  1234. /* Collect txAttr from control */
  1235. ctrlData_getTxAttributes(pTxData->hCtrlData, pMsdu->txFlags, &txAttr, selectedQueueIndex);
  1236. /* allocate a buffer for packet ID storage */
  1237. pPacketId = (txPacketIdAttr_t*)bufferPool_allocateBuffer( pTxData->hBufferPool );
  1238. if ( BUFFER_POOL_NO_BUFFER == pPacketId )
  1239. {
  1240. WLAN_REPORT_ERROR (pTxData->hReport, TX_DATA_MODULE_LOG,
  1241. (" %s : No PacketID Available!!\n", __FUNCTION__));
  1242. /* shouldn't happen, since we have enough packet ID buffers as the FW has TX descriptors! */
  1243. pTxData->txDataIsSchedulerInWork = FALSE;
  1244. return NOK;
  1245. }
  1246. /* store necessary information in packet ID */
  1247. pPacketId->pMsdu = pMsdu;
  1248. if (pMsdu->txFlags & TX_DATA_DATA_MSDU)
  1249. {
  1250. pPacketId->bDataMsdu = TRUE;
  1251. }
  1252. else
  1253. {
  1254. pPacketId->bDataMsdu = FALSE;
  1255. }
  1256. pPacketId->txQid = selectedQueueIndex;
  1257. pPacketId->txCompleteFlags = pMsdu->txCompleteFlags;
  1258. pPacketId->maxTransmitRate = txAttr.HwRate;
  1259. #ifdef TI_DBG
  1260. os_memoryZero (pTxData->hOs, pPacketId->timeStamp, sizeof(pPacketId->timeStamp));
  1261. pPacketId->timeStamp[0] = os_timeStampUs (pTxData->hOs);
  1262. #endif
  1263. pPacketId->msduDataLen = pMsdu->dataLen;
  1264. /* destination mac */
  1265. pDot11Header = (dot11_header_t*)(memMgr_BufData(pMsdu->firstBDPtr)+ memMgr_BufOffset(pMsdu->firstBDPtr));
  1266. ctrlData_getCurrBssTypeAndCurrBssId(pTxData->hCtrlData, &currBssId, &currBssType);
  1267. if(currBssType == BSS_INDEPENDENT)
  1268. MAC_COPY( pTxData->hOs, &(pPacketId->destinationMac), &(pDot11Header->address1) );
  1269. else
  1270. MAC_COPY( pTxData->hOs, &(pPacketId->destinationMac), &(pDot11Header->address3) );
  1271. /* mark in packet ID that XFER done and TX complete were not called yet */
  1272. pPacketId->bTxCompleteCalled = pPacketId->bXferDoneCalled = FALSE;
  1273. #ifdef TI_DBG
  1274. if ((pMsdu->txFlags & TX_DATA_DATA_MSDU) != 0 && pMsdu->timeStampNum > 0)
  1275. {
  1276. UINT32 uCoreDelay;
  1277. /* add time stamp */
  1278. wlan_memMngrAddTimeStamp (pTxData->hMemMngr, pMsdu);
  1279. uCoreDelay = pMsdu->timeStamp[pMsdu->timeStampNum - 1] - pMsdu->timeStamp[0];
  1280. /* update core delay and jitter */
  1281. pTxData->txJitter[selectedQueueIndex].jitter.core +=
  1282. ABS (pTxData->txJitter[selectedQueueIndex].last_delay.core - uCoreDelay);
  1283. pTxData->txJitter[selectedQueueIndex].last_delay.core = uCoreDelay;
  1284. pTxData->txJitter[selectedQueueIndex].delay.core += uCoreDelay;
  1285. pTxData->txJitter[selectedQueueIndex].count.core ++;
  1286. if (uCoreDelay > pTxData->txJitter[selectedQueueIndex].max_delay.core)
  1287. pTxData->txJitter[selectedQueueIndex].max_delay.core = uCoreDelay;
  1288. }
  1289. #endif
  1290. /* send the packet to the GWSI layer */
  1291. txStatus = CORE_AdaptTx_SendPacket( CORE_AdaptTx_handle, selectedQueueIndex, pMsdu, &txAttr, (UINT32)pPacketId, msduTimeToExpiry );
  1292. WLAN_REPORT_DEBUG_TX (pTxData->hReport,
  1293. ("txData_startTxScheduler(): called CORE_AdaptTx_SendPacket pMsdu=%d, selectedQueueIndex=%d,txStatus=%d\n",
  1294. pMsdu,selectedQueueIndex,txStatus));
  1295. switch ( txStatus )
  1296. {
  1297. /*
  1298. * XFER_DONE is received when the packet has been synchronously transferred to the FW.
  1299. * in this case, XFER complete will not be called, only TX complete
  1300. */
  1301. case SEND_PACKET_XFER_DONE:
  1302. pPacketId->driverHandlingTime = (os_timeStampUs (pTxData->hOs) - pMsdu->insertionTime) / 1000;
  1303. /* Get MSDU with dequeuing */
  1304. if ( (msduList_GetFirst( pMsduList, &pMsdu )) != OK )
  1305. {
  1306. /* No MSDU is waiting to transmit */
  1307. WLAN_REPORT_ERROR (pTxData->hReport, TX_DATA_MODULE_LOG,
  1308. (" %s : can't get Msdu from pMsduList[ %d ] \n", __FUNCTION__, selectedQueueIndex));
  1309. pTxData->txDataIsSchedulerInWork = FALSE;
  1310. return NOK;
  1311. }
  1312. /* free the MSDU, since XFER complete won't be called */
  1313. if ( (wlan_memMngrFreeMSDU(pTxData->hMemMngr, memMgr_MsduHandle(pMsdu))) != OK )
  1314. {
  1315. WLAN_REPORT_ERROR(pTxData->hReport, TX_DATA_MODULE_LOG,
  1316. ("%s: free msdu failed \n", __FUNCTION__));
  1317. pTxData->txDataIsSchedulerInWork = FALSE;
  1318. return NOK;
  1319. }
  1320. else
  1321. {
  1322. pTxData->txDataDbgCounters.dbgNumOfMsduFreeInTxTransfer[ pPacketId->txQid ]++;
  1323. }
  1324. /* Nullify the MSDU pointer, just in case */
  1325. pPacketId->pMsdu = NULL;
  1326. /* mark in packet ID that XFER done was called */
  1327. pPacketId->bXferDoneCalled = TRUE;
  1328. /* increment debug counter */
  1329. pTxData->txDataDbgCounters.dbgSendToGwsiQosPackets[ selectedQueueIndex ]++;
  1330. pTxData->txDataDbgCounters.dbgNumOfMsduXferDoneInShceduler[ selectedQueueIndex ]++;
  1331. break;
  1332. /*
  1333. * SUCCESS is received when the packet has not yet been sent to the FW, but another packet
  1334. * transfer can start immediately
  1335. */
  1336. case SEND_PACKET_SUCCESS:
  1337. /* Get msdu with dequeuing */
  1338. if ( (msduList_GetFirst( pMsduList, &pMsdu )) != OK )
  1339. {
  1340. /* No msdu is waiting to transmit */
  1341. WLAN_REPORT_ERROR (pTxData->hReport, TX_DATA_MODULE_LOG,
  1342. (" %s : can't get Msdu from pMsduList[ %d ] \n", __FUNCTION__, selectedQueueIndex));
  1343. pTxData->txDataIsSchedulerInWork = FALSE;
  1344. return NOK;
  1345. }
  1346. /* increment debug counter */
  1347. pTxData->txDataDbgCounters.dbgNumOfMsduSuccessInScheduler[ selectedQueueIndex ]++;
  1348. pTxData->txDataDbgCounters.dbgSendToGwsiQosPackets[selectedQueueIndex]++;
  1349. break;
  1350. /*
  1351. * PENDING is received when the packet has been received by the GWSI layer, and the double buffer
  1352. * mechanism is busy. It indicates that no more packets (from all queues) are to be sent until a
  1353. * XFER complete indication is received
  1354. */
  1355. case SEND_PACKET_PENDING:
  1356. /* Get msdu with dequeuing */
  1357. if ( (msduList_GetFirst( pMsduList, &pMsdu )) != OK )
  1358. {
  1359. /* No msdu is waiting to transmit */
  1360. WLAN_REPORT_ERROR (pTxData->hReport, TX_DATA_MODULE_LOG,
  1361. (" %s : can't get Msdu from pMsduList[ %d ] \n", __FUNCTION__, selectedQueueIndex));
  1362. pTxData->txDataIsSchedulerInWork = FALSE;
  1363. return NOK;
  1364. }
  1365. /* mark the GWSI interface state as pending (no more frames can be sent) */
  1366. pTxData->txDataGwsiInterfaceStatus = GWSI_PENDING;
  1367. /* increment debug counter */
  1368. pTxData->txDataDbgCounters.dbgNumOfMsduPendingInScheduler[ selectedQueueIndex ]++;
  1369. pTxData->txDataDbgCounters.dbgSendToGwsiQosPackets[selectedQueueIndex]++;
  1370. break;
  1371. /*
  1372. * BUSY is received when the packet has NOT been received by the GWSI layer (and needs to be
  1373. * retransmitted). It indicates that the specific FW queue is full and no more packets from this
  1374. * specific queue are to be sent until a TX complete indication for this queue is received (but
  1375. * packets from other queues may be sent).
  1376. */
  1377. case SEND_PACKET_BUSY:
  1378. /* don't dequeue the packet! it was not sent! */
  1379. /* in addition, release the packet ID buffer */
  1380. bufferPool_releaseBuffer( pTxData->hBufferPool, pPacketId );
  1381. /* mark the specific queue as not available */
  1382. pTxData->txDataAvailableQueue[ selectedQueueIndex ] = FALSE;
  1383. /* update debug counters */
  1384. pTxData->txDataDbgCounters.dbgNumOfMsduBusyInScheduler[ selectedQueueIndex ]++;
  1385. break;
  1386. /*
  1387. * ERROR is received when a frame is sent although a PENDING indication had been previously
  1388. * received and no XFER complete had been receive since, or because a BUSY indication had been
  1389. * received for a specific queue and no TX complete for this queue had been received since (and
  1390. * a packet from this queue had been sent now).
  1391. */
  1392. case SEND_PACKET_ERROR:
  1393. /* don't dequeue the packet! it was not sent! */
  1394. /* in addition, release the packet ID buffer */
  1395. bufferPool_releaseBuffer( pTxData->hBufferPool, pPacketId );
  1396. /* start scheduler timer */
  1397. if ( FALSE == pTxData->bSchedulerTimerRunning )
  1398. {
  1399. os_timerStart( pTxData->hOs, pTxData->pSchedulerTimer, SCHEDULER_TIMER, FALSE );
  1400. pTxData->bSchedulerTimerRunning = TRUE;
  1401. }
  1402. pTxData->txDataIsSchedulerInWork = FALSE;
  1403. WLAN_REPORT_ERROR( pTxData->hReport, TX_DATA_MODULE_LOG,
  1404. (" %s: received status SEND_PACKET_ERROR from CORE_AdaptTx_SendPacket\n", __FUNCTION__) );
  1405. /* update debug counters */
  1406. pTxData->txDataDbgCounters.dbgNumOfMsduErrorInScheduler[ selectedQueueIndex ]++;
  1407. return NOK;
  1408. /* break; - unreachable*/
  1409. case SEND_PACKET_RECOVERY:
  1410. break;
  1411. default:
  1412. WLAN_REPORT_ERROR( pTxData->hReport, TX_DATA_MODULE_LOG,
  1413. (" %s: received status %d from CORE_AdaptTx_SendPacket\n", __FUNCTION__, txStatus) );
  1414. break;
  1415. }
  1416. WLAN_REPORT_INFORMATION (pTxData->hReport, TX_DATA_MODULE_LOG,
  1417. ("txData_startTxScheduler() : MSDU sent: TxQ = %d TxStatus = %d\n", selectedQueueIndex, txStatus));
  1418. } /* end of while (count) */
  1419. pTxData->txDataIsSchedulerInWork = FALSE;
  1420. return OK;
  1421. }
  1422. /***************************************************************************
  1423. * txData_sendPacketTransfer *
  1424. ****************************************************************************
  1425. * DESCRIPTION: GWSI sendPacketTransfer CB. called after transferring a packet
  1426. * to TNET.
  1427. * The function free the transfered MSDU and set GWSI port status
  1428. * to OPEN. This is the only function which synchronized GWSI port
  1429. * status.
  1430. * TNET queues buffer status are updated and the scheduler is executed
  1431. * trying to send another MSDU.
  1432. *
  1433. * INPUTS: hTxData - the object
  1434. *
  1435. * OUTPUT:
  1436. *
  1437. * RETURNS: void
  1438. *
  1439. ***************************************************************************/
  1440. void txData_sendPacketTransfer(TI_HANDLE hTxData,
  1441. UINT32 aPacketIdAttr)
  1442. {
  1443. txData_t *pTxData = (txData_t *)hTxData;
  1444. txPacketIdAttr_t* pPacketId = (txPacketIdAttr_t*)aPacketIdAttr;
  1445. WLAN_REPORT_INFORMATION(pTxData->hReport, TX_DATA_MODULE_LOG,
  1446. ("%s: XFER complete CB called\n", __FUNCTION__));
  1447. pTxData->txDataDbgCounters.dbgNumOfMsduTxTransferCB[ pPacketId->txQid ]++;
  1448. WLAN_REPORT_DEBUG_TX(pTxData->hReport,
  1449. ("%s: XFER complete CB called\n", __FUNCTION__));
  1450. /* updating GWSI status to open */
  1451. pTxData->txDataGwsiInterfaceStatus = GWSI_OPEN;
  1452. /* free the MSDU */
  1453. if ( pPacketId->pMsdu != NULL )
  1454. {
  1455. pPacketId->driverHandlingTime = (os_timeStampUs (pTxData->hOs) - pPacketId->pMsdu->insertionTime) / 1000;
  1456. if( (wlan_memMngrFreeMSDU(pTxData->hMemMngr, memMgr_MsduHandle(pPacketId->pMsdu))) != OK )
  1457. {
  1458. WLAN_REPORT_ERROR(pTxData->hReport, TX_DATA_MODULE_LOG,
  1459. ("%s: free msdu failed \n", __FUNCTION__));
  1460. }
  1461. else
  1462. {
  1463. pTxData->txDataDbgCounters.dbgNumOfMsduFreeInTxTransfer[ pPacketId->txQid ]++;
  1464. }
  1465. }
  1466. else
  1467. {
  1468. WLAN_REPORT_ERROR(pTxData->hReport, TX_DATA_MODULE_LOG,
  1469. ("%s: pMsdu = NULL !!!!\n", __FUNCTION__));
  1470. pTxData->txDataDbgCounters.dbgNumOfNullMsdu++;
  1471. }
  1472. /* nullify the MSDU pointer, just in case */
  1473. pPacketId->pMsdu = NULL;
  1474. /* mark in packet ID that XFER done was called */
  1475. pPacketId->bXferDoneCalled = TRUE;
  1476. /*
  1477. * and check if to release packet ID. In rare cases, TX complete can be called before XFER done. In these
  1478. * cases, the packet ID should be released here.
  1479. */
  1480. if ( TRUE == pPacketId->bTxCompleteCalled )
  1481. {
  1482. bufferPool_releaseBuffer( pTxData->hBufferPool, (bufferPool_buffer_t)aPacketIdAttr );
  1483. }
  1484. /*
  1485. * check port status - if it is disconnected, it means the STA is disconnected, and thus
  1486. * the XFER complete is ignored, to avoid race conditions (when, for example, the MSDU was
  1487. * already freed on txData_stop)
  1488. */
  1489. if ( CLOSE == pTxData->txDataPortStatus )
  1490. {
  1491. WLAN_REPORT_WARNING( pTxData->hReport, TX_DATA_MODULE_LOG,
  1492. (" %s: XFER complete CB called when port is CLOSED!", __FUNCTION__));
  1493. return;
  1494. }
  1495. /* try to schedule another MSDU */
  1496. txData_startTxScheduler(hTxData);
  1497. }
  1498. /***************************************************************************
  1499. * txData_txCompleteUpdate *
  1500. ****************************************************************************
  1501. * DESCRIPTION: check if there are more packets in the queue to transmit,
  1502. * and that the queues in the HW are empty. if so then release
  1503. * the HW. else call to the scheduler.
  1504. *
  1505. * INPUTS: hTxData - the object
  1506. * txStatus - status of Tx (OK = ok, other = failed)
  1507. * TxQid - The Tx queue index.
  1508. *
  1509. * OUTPUT:
  1510. *
  1511. * RETURNS: TI_STATUS - is success then OK, else NOK
  1512. *
  1513. ***************************************************************************/
  1514. TI_STATUS txData_txCompleteUpdate(TI_HANDLE hTxData, txCompleteAttr_t *pCmpltAttr)
  1515. {
  1516. txData_t *pTxData = (txData_t *)hTxData;
  1517. UINT8 qIndex;
  1518. txPacketIdAttr_t* pPacketId = (txPacketIdAttr_t*)pCmpltAttr->packetId;
  1519. /*
  1520. * when host processes the packets , we not working with Queue free event
  1521. * so queue status in TNET is updated in tx complete and the scheduler is triggered.
  1522. */
  1523. qIndex = pPacketId->txQid;
  1524. WLAN_REPORT_INFORMATION(pTxData->hReport, TX_DATA_MODULE_LOG,
  1525. ("txData_txCompleteUpdate , queueId: %d status: %d\n", qIndex, pCmpltAttr->status));
  1526. /*
  1527. * first update that TNET Queue is available to get another packet
  1528. */
  1529. pTxData->txDataAvailableQueue[qIndex] = TRUE;
  1530. /* update TX counters for txDistributer */
  1531. txData_UpdateTxCounters( hTxData, pCmpltAttr );
  1532. /* update dbg counters */
  1533. pTxData->txDataDbgCounters.dbgNumOfsendPacketComplete[qIndex]++;
  1534. if (pCmpltAttr->status == SEND_COMPLETE_SUCCESS)
  1535. {
  1536. pTxData->txDataDbgCounters.dbgTxCmpltOk[qIndex]++;
  1537. pTxData->txDataDbgCounters.dbgTxCmpltOkBytes[qIndex] += pPacketId->msduDataLen;
  1538. #if defined(TI_DBG)
  1539. pTxData->txJitter[qIndex].jitter.air +=
  1540. ABS (pTxData->txJitter[qIndex].last_delay.air - pCmpltAttr->actualDurationInAir);
  1541. pTxData->txJitter[qIndex].jitter.fw +=
  1542. ABS (pTxData->txJitter[qIndex].last_delay.fw - pCmpltAttr->fwHandlingTime);
  1543. pTxData->txJitter[qIndex].last_delay.fw = pCmpltAttr->fwHandlingTime;
  1544. pTxData->txJitter[qIndex].last_delay.air = pCmpltAttr->actualDurationInAir;
  1545. pTxData->txJitter[qIndex].delay.fw += pCmpltAttr->fwHandlingTime;
  1546. pTxData->txJitter[qIndex].delay.air += pCmpltAttr->actualDurationInAir;
  1547. if (pCmpltAttr->fwHandlingTime > pTxData->txJitter[qIndex].max_delay.fw)
  1548. pTxData->txJitter[qIndex].max_delay.fw = pCmpltAttr->fwHandlingTime;
  1549. if (pCmpltAttr->actualDurationInAir > pTxData->txJitter[qIndex].max_delay.air)
  1550. pTxData->txJitter[qIndex].max_delay.air = pCmpltAttr->actualDurationInAir;
  1551. #endif
  1552. }
  1553. else
  1554. {
  1555. pTxData->txDataDbgCounters.dbgTxCmpltError[qIndex]++;
  1556. /* on error, update TX counters (xmit error count) */
  1557. }
  1558. /* check asynchronous in packetId */
  1559. if ( (pTxData->txDataDbgCounters.dbgNumOfMsduTxTransferCB[qIndex] + pTxData->txDataDbgCounters.dbgNumOfMsduXferDoneInShceduler[qIndex])<
  1560. pTxData->txDataDbgCounters.dbgNumOfsendPacketComplete[qIndex])
  1561. {
  1562. WLAN_REPORT_INFORMATION(pTxData->hReport, TX_DATA_MODULE_LOG,
  1563. ("txData_txCompleteUpdate , qIndex = %d Num of XFER done CB + XFER done status = %d dbgNumOfsendPacketComplete = %d!!!!\n",
  1564. qIndex, pTxData->txDataDbgCounters.dbgNumOfMsduTxTransferCB[qIndex] +
  1565. pTxData->txDataDbgCounters.dbgNumOfMsduXferDoneInShceduler[qIndex],
  1566. pTxData->txDataDbgCounters.dbgNumOfsendPacketComplete[qIndex]));
  1567. }
  1568. /* check if XFER done was called for this packet */
  1569. if ( TRUE == pPacketId->bXferDoneCalled )
  1570. {
  1571. /* free the packet ID buffer */
  1572. bufferPool_releaseBuffer( pTxData->hBufferPool, (bufferPool_buffer_t)pPacketId );
  1573. }
  1574. else
  1575. {
  1576. /*
  1577. * in rare cases, TX complete can be called before XFER done. If this is the case,
  1578. * simply mark that TX complete was called. The packet ID will be freed on XFER done
  1579. */
  1580. pPacketId->bTxCompleteCalled = TRUE;
  1581. }
  1582. /* run the scheduler */
  1583. txData_startTxScheduler(hTxData);
  1584. return OK;
  1585. }
  1586. /***************************************************************************
  1587. * txData_sendPacketDebug *
  1588. ****************************************************************************
  1589. * DESCRIPTION: GWSI sendPacketDebug CB, called upon issuing interrupt to TNET.
  1590. * The function calculates GWSI delay and jitter.
  1591. *
  1592. * INPUTS: hTxData - the object
  1593. * uPacketId - packet handle
  1594. * OUTPUT:
  1595. *
  1596. * RETURNS: void
  1597. *
  1598. ***************************************************************************/
  1599. #ifdef TI_DBG
  1600. void txData_sendPacketDebug (TI_HANDLE hTxData, UINT32 uPacketId, UINT32 uDebugInfo)
  1601. {
  1602. txData_t *pTxData = (txData_t *)hTxData;
  1603. txPacketIdAttr_t* pPacketId = (txPacketIdAttr_t *)uPacketId;
  1604. if (pTxData != NULL && pPacketId != NULL)
  1605. {
  1606. UINT32 uXferDelay = os_timeStampUs (pTxData->hOs);
  1607. switch (uDebugInfo)
  1608. {
  1609. case 0:
  1610. /* Calculate full XFER delay */
  1611. if (uXferDelay >= pPacketId->timeStamp[0])
  1612. {
  1613. uXferDelay -= pPacketId->timeStamp[0];
  1614. /* Update jitter statistics */
  1615. pTxData->txJitter[pPacketId->txQid].delay.xfer += uXferDelay;
  1616. pTxData->txJitter[pPacketId->txQid].jitter.xfer +=
  1617. ABS (uXferDelay - pTxData->txJitter[pPacketId->txQid].last_delay.xfer);
  1618. pTxData->txJitter[pPacketId->txQid].last_delay.xfer = uXferDelay;
  1619. pTxData->txJitter[pPacketId->txQid].count.xfer ++;
  1620. if (uXferDelay > pTxData->txJitter[pPacketId->txQid].max_delay.xfer)
  1621. pTxData->txJitter[pPacketId->txQid].max_delay.xfer = uXferDelay;
  1622. }
  1623. break;
  1624. default:
  1625. if (uDebugInfo < 5)
  1626. pPacketId->timeStamp[uDebugInfo] = uXferDelay;
  1627. break;
  1628. }
  1629. }
  1630. }
  1631. #endif
  1632. /***************************************************************************
  1633. * txData_getHighestAdmittedAc *
  1634. ****************************************************************************
  1635. * DESCRIPTION: This function calculate the highest admitted AC starting from
  1636. * a given ac index. if it fails it returns acIndex of Best effort.
  1637. *
  1638. * INPUTS: hTxData - the object
  1639. * qosTag - Qos tag
  1640. *
  1641. * OUTPUT:
  1642. *
  1643. * RETURNS: OK
  1644. * NOK
  1645. ***************************************************************************/
  1646. static int txData_getHighestAdmittedAc(txData_t *pTxData, int startingAcIndex)
  1647. {
  1648. int qIndex;
  1649. if ((startingAcIndex > MAX_NUM_OF_AC - 1) || (startingAcIndex < FIRST_AC_INDEX))
  1650. {
  1651. WLAN_REPORT_ERROR(pTxData->hReport, TX_DATA_MODULE_LOG,
  1652. (" txData_getHighestAdmittedAc() : failed, startingAcIndex = %d \n",startingAcIndex));
  1653. return QOS_AC_BE;
  1654. }
  1655. qIndex = GET_QUEUE_INDEX(pTxData, startingAcIndex);
  1656. /* If desired queue is not admitted, find highest Tx queue that doesn't require admission. */
  1657. if(pTxData->dataMsduListArr[qIndex]->admissionState == AC_NOT_ADMITTED)
  1658. {
  1659. while(qIndex >= 0)
  1660. {
  1661. if(pTxData->dataMsduListArr[qIndex]->admissionRequired == ADMISSION_NOT_REQUIRED)
  1662. break;
  1663. qIndex--;
  1664. }
  1665. }
  1666. if(qIndex < 0)
  1667. {
  1668. WLAN_REPORT_ERROR(pTxData->hReport, TX_DATA_MODULE_LOG,
  1669. (" txData_getHighestAdmittedAc() : failed, qIndex = %d \n",qIndex));
  1670. return startingAcIndex;
  1671. }
  1672. return pTxData->dataMsduListArr[qIndex]->acId;
  1673. }
  1674. /***************************************************************************
  1675. * txData_selectQueueAndUpdateUserPriority *
  1676. ****************************************************************************
  1677. * DESCRIPTION: This function calculate the queue index according to msdu qos tag
  1678. * if the queue isn't admitted tt returns the highest admitted queue
  1679. * bellow.
  1680. * In addition, if the MSDU has been downgraded due to admission control,
  1681. * we update the QosControl accordingly
  1682. *
  1683. * INPUTS: hTxData - the object
  1684. * pMSDU - pointer to packet
  1685. *
  1686. * OUTPUT: selectedQueue - pointer to result variable which will hold the selected queue index
  1687. * acIndex - selected admission control
  1688. *
  1689. * RETURNS: OK
  1690. * NOK
  1691. ***************************************************************************/
  1692. static int txData_selectQueueAndUpdateUserPriority (txData_t *pTxData, mem_MSDU_T *pMsdu, int *selectedQueue, acTrfcType_e *selectedAc)
  1693. {
  1694. int startingAcIndex;
  1695. int acIndex;
  1696. dot11_header_t *pdot11Header;
  1697. if (pMsdu->qosTag > MAX_NUM_OF_802_1d_TAGS - 1)
  1698. {
  1699. WLAN_REPORT_ERROR(pTxData->hReport, TX_DATA_MODULE_LOG,
  1700. (" txData_selectQueueAndUpdateUserPriority() : txData_getQueueIndex failed, pMsdu->qosTag = %d \n",pMsdu->qosTag));
  1701. *selectedAc = QOS_AC_BE;
  1702. *selectedQueue = GET_QUEUE_INDEX(pTxData, QOS_AC_BE);
  1703. return NOK;
  1704. }
  1705. /* calc ac according tag to ac table */
  1706. acIndex = startingAcIndex = pTxData->txDataQosParams.tag_ToAcClsfrTable[pMsdu->qosTag];
  1707. /* get highest admitted AC */
  1708. if(pTxData->admissionDownGradeEnable == TRUE)
  1709. acIndex = txData_getHighestAdmittedAc(pTxData,startingAcIndex);
  1710. /* If the highest admitted AC is not the "starting" AC that we originally desired, we were downgraded due to admission control
  1711. and we should update the QosControl field accordingly
  1712. In addition, we do not want to modify the QosControl unless the header actually contains Qos data */
  1713. if ((acIndex != startingAcIndex) && (pTxData->txDataQosParams.headerConverMode == QOS_CONVERT))
  1714. {
  1715. pdot11Header = (dot11_header_t*)(memMgr_BufData(pMsdu->firstBDPtr)+ memMgr_BufOffset(pMsdu->firstBDPtr));
  1716. pdot11Header->qosControl = wmeAcToUpIndex[acIndex];
  1717. }
  1718. /* convert acIndex to qIndex */
  1719. *selectedQueue = pTxData->txDataAcTrfcCtrl[acIndex].QueueIndex;
  1720. *selectedAc = (acTrfcType_e)acIndex;
  1721. return OK;
  1722. }
  1723. /***************************************************************************
  1724. * txData_acVoPsPollMode *
  1725. ****************************************************************************
  1726. * DESCRIPTION: This function determines if we are current in power save mode
  1727. * sending voice packet with SW ps-poll method.
  1728. *
  1729. * INPUTS: hTxData - the object
  1730. * qosTag - Qos tag
  1731. *
  1732. * OUTPUT:
  1733. *
  1734. * RETURNS: TRUE
  1735. * FALSE
  1736. ***************************************************************************/
  1737. static BOOL txData_acVoPsPollMode(txData_t *pTxData)
  1738. {
  1739. BOOL ps_status = FALSE;
  1740. ps_status = PowerMgr_getPsStatus(pTxData->hPowerMgr);
  1741. if (ps_status &&
  1742. pTxData->txDataAcTrfcCtrl[QOS_AC_VO].PsMode == PS_SCHEME_LEGACY_PSPOLL)
  1743. {
  1744. return TRUE;
  1745. }
  1746. return FALSE;
  1747. }
  1748. /***************************************************************************
  1749. * txData_disableTransmission *
  1750. ****************************************************************************
  1751. * DESCRIPTION: This function sets an internal flag in order to diable
  1752. * transmission.
  1753. *
  1754. * INPUTS: hTxData - the object
  1755. * reason - indicates if the reason for transmission disable
  1756. * is measuring of non serving channel or Switch Channel command
  1757. *
  1758. * OUTPUT:
  1759. *
  1760. * RETURNS: OK on success, NOK otherwise
  1761. ***************************************************************************/
  1762. TI_STATUS txData_disableTransmission(TI_HANDLE hTxData,txDisableReason_e reason)
  1763. {
  1764. txData_t *pTxData = (txData_t *)hTxData;
  1765. pTxData->txDisable = reason;
  1766. return OK;
  1767. }
  1768. /***************************************************************************
  1769. * txData_enableTransmission *
  1770. ****************************************************************************
  1771. * DESCRIPTION: This function sets an internal flag in order to enable
  1772. * back the transmission.
  1773. *
  1774. * INPUTS: hTxData - the object
  1775. *
  1776. *
  1777. * OUTPUT:
  1778. *
  1779. * RETURNS: OK on success, NOK otherwise
  1780. ***************************************************************************/
  1781. TI_STATUS txData_enableTransmission(TI_HANDLE hTxData)
  1782. {
  1783. txData_t *pTxData = (txData_t *)hTxData;
  1784. pTxData->txDisable = NO_DISABLE;
  1785. txData_startTxScheduler(pTxData);
  1786. return OK;
  1787. }
  1788. /***************************************************************************
  1789. * txData_schedulerSelectQueueToTransmitFrom *
  1790. ****************************************************************************
  1791. * DESCRIPTION: This function selects the tx queue to transmit MSDU from.
  1792. * Management MSDUs are selected in first priority.
  1793. * For data MSDUs, the queue selection is done by the following order:
  1794. * 1) The queue is not empty.
  1795. * 2) It is permitted to transmit (admitted and not blocked by mediumTime).
  1796. * 3) It has minimal number of Hw blocks waiting for Tx.
  1797. * Note: this is to fill all queues for efficient EDCA process in FW.
  1798. * 4) It has minimal history-counter (shows it wasn't selected lately).
  1799. * 5) It is the highest priority queue.
  1800. *
  1801. * Note: Selection between queues is done by step 'n' only if all steps before it
  1802. * gave identical results. Also, steps 1 & 2 are mandatory for selection.
  1803. *
  1804. * INPUTS: hTxData - the object
  1805. *
  1806. * OUTPUT: pMsduListPtr - a pointer to the selected queue list-pointer.
  1807. * selectedQueueIndex - a pointer to the selected queue index.
  1808. *
  1809. * RETURNS: TX_QUEUE_SELECTED_OK - a queue was selected.
  1810. * NO_TX_QUEUE_SELECTED - no msdu to transmit.
  1811. ***************************************************************************/
  1812. static TI_STATUS txData_schedulerSelectQueueToTransmitFrom( TI_HANDLE hTxData, MsduList_t** pMsduListPtr,UINT8 *selectedQueueIndex )
  1813. {
  1814. txData_t *pTxData = (txData_t *)hTxData;
  1815. UINT8 acIndex;
  1816. int qIndex;
  1817. UINT32 currentTimeStamp = os_timeStampMs(pTxData->hOs);
  1818. UINT32 AllQueuesMinTime = 0;
  1819. UINT32 currQueuesTime = 0;
  1820. MsduList_t *pMsduList;
  1821. UINT32 currentQueueWeight;
  1822. UINT32 bestWeight = Q_LEAST_WEIGHT; /* Weight of preferred queue (lowest value is selected). */
  1823. int bestWeightQueueIndex = 0; /* Index of preferred queue. */
  1824. MsduList_t *bestWeightQueueList = NULL; /* Pointer to the preferred queue list. */
  1825. /* If management MSDU is waiting, select it and return. */
  1826. if( pTxData->mngMsduList->CurrNumOfMsdu > 0 )
  1827. {
  1828. *pMsduListPtr = pTxData->mngMsduList;
  1829. /* get highest admitted AC starting from VO */
  1830. acIndex = txData_getHighestAdmittedAc(pTxData,QOS_AC_VO);
  1831. /* convert acIndex to queue index */
  1832. *selectedQueueIndex = GET_QUEUE_INDEX(pTxData,acIndex);
  1833. if (pTxData->txDataAvailableQueue[*selectedQueueIndex] == TRUE)
  1834. {
  1835. WLAN_REPORT_INFORMATION (pTxData->hReport, TX_DATA_MODULE_LOG,
  1836. (" txData_schedulerSelectQueueToTransmitFrom() : Management MSDU selected to Tx\n"));
  1837. return TX_QUEUE_SELECTED_OK;
  1838. }
  1839. else
  1840. {
  1841. WLAN_REPORT_INFORMATION (pTxData->hReport, TX_DATA_MODULE_LOG,
  1842. (" txData_schedulerSelectQueueToTransmitFrom() : pTxData->txDataAvailableQueue[%d] = FALSE \n",*selectedQueueIndex));
  1843. }
  1844. }
  1845. /*
  1846. * Loop over all core data Tx queues and look for the preferred one to transmit from:
  1847. * =================================================================================
  1848. * Note: Starting from the highest priority ensures that if multiple queues have
  1849. * identical status, the highest priority one among them will be selected.
  1850. */
  1851. for (qIndex = MAX_NUM_OF_TX_QUEUES - 1; qIndex >= 0; qIndex--)
  1852. {
  1853. pMsduList = pTxData->dataMsduListArr[qIndex];
  1854. if (pMsduList->selectionHistoryCounter)
  1855. pMsduList->selectionHistoryCounter--;
  1856. /* If queue is empty or is not admitted to transmit, continue to next queue. */
  1857. if ((pMsduList->CurrNumOfMsdu == 0) || (pMsduList->admissionState != AC_ADMITTED))
  1858. continue;
  1859. /*
  1860. * see only if Queue is available.
  1861. * continue to the next Q if not available
  1862. */
  1863. if (pTxData->txDataAvailableQueue[qIndex] == FALSE)
  1864. continue;
  1865. /* If we are configured to enforce excess Tx time limits, handle the algorithm. */
  1866. if (pMsduList->useAdmissionAlgo)
  1867. {
  1868. /* Handle case of timer wraparound. */
  1869. if (currentTimeStamp < pMsduList->lastTimeStamp)
  1870. pMsduList->lastTimeStamp = 0;
  1871. /* If we it's not time to enable Tx yet for this queue, update time to try again if needed. */
  1872. if (currentTimeStamp < pMsduList->lastTimeStamp + pMsduList->enableTransmissionTime)
  1873. {
  1874. /* currQueuesTime represents the amount of time the tx scheduler has to wait before
  1875. it will be able to transmit from this queue. */
  1876. currQueuesTime = (pMsduList->lastTimeStamp + pMsduList->enableTransmissionTime - currentTimeStamp);
  1877. /* Update the minimum time left till we can Tx from any of the queues. */
  1878. if (AllQueuesMinTime == 0)
  1879. AllQueuesMinTime = currQueuesTime;
  1880. else
  1881. AllQueuesMinTime = MIN(AllQueuesMinTime, currQueuesTime);
  1882. /* We can't Tx from this queue yet so continue to next queue. */
  1883. continue;
  1884. }
  1885. }
  1886. /**** If we got here, this queue has something to Tx and it is permitted to Tx now. ****/
  1887. /* Now calculate this queue's weight for selection:
  1888. * Higher 16 bits: Number of used HW blocks by this AC.
  1889. * Lower 16 bits: Count down from last time it was selected. */
  1890. currentQueueWeight = (UINT32)TnetwDrv_txHwQueue_GetUsedHwBlks( pTxData->hTnetwDrv, qIndex ) << 16;
  1891. currentQueueWeight |= (UINT32)pMsduList->selectionHistoryCounter;
  1892. /* If current queue's weight isn't lower (lower is better!) than previous queues,
  1893. continue to next queue. */
  1894. if (currentQueueWeight >= bestWeight)
  1895. continue;
  1896. /* Save weight, index and list-pointer of best candidate queue so far . */
  1897. bestWeight = currentQueueWeight;
  1898. bestWeightQueueIndex = qIndex;
  1899. bestWeightQueueList = pMsduList;
  1900. }
  1901. /* If we have a delayed queue, we need to re-trigger the scheduler later by timer. */
  1902. if (AllQueuesMinTime != 0)
  1903. {
  1904. /* msdu is waiting to transmit */
  1905. WLAN_REPORT_INFORMATION (pTxData->hReport, TX_DATA_MODULE_LOG,
  1906. (" txData_schedulerSelectQueueToTransmitFrom() : Start mediumTime timer for - %d ms\n", AllQueuesMinTime));
  1907. if ( pTxData->bSchedulerTimerRunning == TRUE )
  1908. {
  1909. os_timerStop(pTxData->hOs, pTxData->pSchedulerTimer);
  1910. }
  1911. os_timerStart(pTxData->hOs,pTxData->pSchedulerTimer, AllQueuesMinTime, FALSE);
  1912. pTxData->bSchedulerTimerRunning = TRUE;
  1913. }
  1914. /* If we have a queue we can transmit from: */
  1915. if (bestWeight != Q_LEAST_WEIGHT)
  1916. {
  1917. /* Set selected queue history counter to its initial value, indicating it was selected
  1918. lately and its priority is temporarily reduced. */
  1919. bestWeightQueueList->selectionHistoryCounter = Q_SELECTION_HISTORY_LEVEL;
  1920. /* Provide the selected queue index and list pointer. */
  1921. *pMsduListPtr = bestWeightQueueList;
  1922. *selectedQueueIndex = bestWeightQueueIndex;
  1923. WLAN_REPORT_INFORMATION (pTxData->hReport, TX_DATA_MODULE_LOG,
  1924. (" txData_schedulerSelectQueueToTransmitFrom() : Selected-TxQ = %d, Weight = 0x%x\n",
  1925. bestWeightQueueIndex, bestWeight));
  1926. return TX_QUEUE_SELECTED_OK;
  1927. }
  1928. /* If we got here, no queue is currently suitable for transmition. */
  1929. WLAN_REPORT_DEBUG_TX(pTxData->hReport,
  1930. (" txData_schedulerSelectQueueToTransmitFrom() : No queue selected for Tx\n"));
  1931. return NO_TX_QUEUE_SELECTED;
  1932. }
  1933. /***************************************************************************
  1934. * txData_getParam *
  1935. ****************************************************************************
  1936. * DESCRIPTION: get a specific parameter
  1937. *
  1938. * INPUTS: hTxData - the object
  1939. *
  1940. * OUTPUT: pParamInfo - structure which include the value of
  1941. * the requested parameter
  1942. *
  1943. * RETURNS: OK
  1944. * NOK
  1945. ***************************************************************************/
  1946. TI_STATUS txData_getParam(TI_HANDLE hTxData, paramInfo_t *pParamInfo)
  1947. {
  1948. txData_t *pTxData = (txData_t *)hTxData;
  1949. UINT32 tID;
  1950. /* check handle validity */
  1951. if( pTxData == NULL )
  1952. {
  1953. WLAN_REPORT_ERROR(pTxData->hReport, TX_DATA_MODULE_LOG,
  1954. (" txData_getParam() : Illegal parametrs value \n"));
  1955. return NOK;
  1956. }
  1957. switch (pParamInfo->paramType)
  1958. {
  1959. case TX_DATA_PORT_STATUS_PARAM:
  1960. pParamInfo->content.txDataPortStatus = pTxData->txDataPortStatus;
  1961. break;
  1962. case TX_DATA_CURRENT_PRIVACY_INVOKE_MODE_PARAM:
  1963. pParamInfo->content.txDataCurrentPrivacyInvokedMode = pTxData->txDataCurrentPrivacyInvokedMode;
  1964. break;
  1965. case TX_DATA_EAPOL_ENCRYPTION_STATUS_PARAM:
  1966. pParamInfo->content.txDataEapolEncryptionStatus = pTxData->txDataEapolEncryptionStatus;
  1967. break;
  1968. case TX_DATA_CONVERT_HEADER_MODE:
  1969. pParamInfo->content.txDataQosParams.qosParams.headerConverMode = pTxData->txDataQosParams.headerConverMode;
  1970. break;
  1971. case TX_DATA_COUNTERS_PARAM:
  1972. os_memoryCopy( pTxData->hOs, &(pTxData->tempTxDataCounters[ 0 ]), &(pTxData->txDataCounters[ 0 ]),
  1973. sizeof(txDataCounters_t) * MAX_NUM_OF_TX_QUEUES );
  1974. pParamInfo->content.pTxDataCounters = &(pTxData->tempTxDataCounters[ 0 ]);
  1975. break;
  1976. case TX_DATA_REPORT_TS_STATISTICS:
  1977. tID = GET_QUEUE_INDEX(pTxData, pParamInfo->content.tsMetricsCounters.acID);
  1978. os_memoryCopy(pTxData->hOs,
  1979. pParamInfo->content.tsMetricsCounters.pTxDataCounters,
  1980. &(pTxData->txDataReportedCounters[tID]),
  1981. sizeof(txDataCounters_t));
  1982. os_memoryZero(pTxData->hOs,
  1983. &(pTxData->txDataReportedCounters[tID]),
  1984. sizeof(txDataCounters_t));
  1985. break;
  1986. case TX_DATA_GET_VAD:
  1987. pParamInfo->content.txDataVadTimerParams.vadTimerEnabled = pTxData->bVadTimerEnabled;
  1988. pParamInfo->content.txDataVadTimerParams.vadTimerDuration = pTxData->vadTimerDuration;
  1989. WLAN_REPORT_INFORMATION(pTxData->hReport, TX_DATA_MODULE_LOG,
  1990. ("txData_setParams: GET_VAD (enable=%d; duration=%d ms)\n",
  1991. pTxData->bVadTimerEnabled, pTxData->vadTimerDuration));
  1992. break;
  1993. default:
  1994. return (PARAM_NOT_SUPPORTED);
  1995. /* WLAN_REPORT_ERROR(pTxData->hReport, TX_DATA_MODULE_LOG,
  1996. (" txData_getParam() : PARAMETER NOT SUPPORTED \n"));
  1997. return NOK;
  1998. break; - unreachable*/
  1999. }
  2000. return (OK);
  2001. }
  2002. /***************************************************************************
  2003. * txData_setParam *
  2004. ****************************************************************************
  2005. * DESCRIPTION: set a specific parameter
  2006. *
  2007. * INPUTS: hTxData - the object
  2008. * pParamInfo - structure which include the value to set for
  2009. * the requested parameter
  2010. *
  2011. * OUTPUT:
  2012. *
  2013. * RETURNS: OK
  2014. * NOK
  2015. ***************************************************************************/
  2016. TI_STATUS txData_setParam(TI_HANDLE hTxData, paramInfo_t *pParamInfo)
  2017. {
  2018. txData_t *pTxData = (txData_t *)hTxData;
  2019. UINT8 queueIndex;
  2020. UINT8 acID = pParamInfo->content.txDataQosParams.acID; /* Note: acID is relevant only in
  2021. some of the param-types!! */
  2022. /* check handle validity */
  2023. if( pTxData == NULL )
  2024. {
  2025. WLAN_REPORT_ERROR(pTxData->hReport, TX_DATA_MODULE_LOG,
  2026. (" txData_setParam() : Illegal parametrs value \n"));
  2027. return NOK;
  2028. }
  2029. switch (pParamInfo->paramType)
  2030. {
  2031. case TX_DATA_PORT_STATUS_PARAM:
  2032. {
  2033. /* Set the new TX port status CLOSE/OPEN_NOTIFY/OPEN_EAPOL/OPEN */
  2034. WLAN_REPORT_DEBUG_TX (pTxData->hReport,
  2035. (("txData_setParam: Set txDataPortStatus from 0x%x to 0x%x\n"),
  2036. pTxData->txDataPortStatus , pParamInfo->content.txDataPortStatus));
  2037. pTxData->txDataPortStatus = pParamInfo->content.txDataPortStatus;
  2038. break;
  2039. }
  2040. case TX_DATA_CURRENT_PRIVACY_INVOKE_MODE_PARAM:
  2041. pTxData->txDataCurrentPrivacyInvokedMode = pParamInfo->content.txDataCurrentPrivacyInvokedMode;
  2042. break;
  2043. case TX_DATA_EAPOL_ENCRYPTION_STATUS_PARAM:
  2044. pTxData->txDataEapolEncryptionStatus = pParamInfo->content.txDataEapolEncryptionStatus;
  2045. break;
  2046. case TX_DATA_HAL_INTERFACE_STATUS_PARAM:
  2047. pTxData->txDataHalInterfaceStatus = pParamInfo->content.txDataHalInterfaceStatus;
  2048. break;
  2049. case TX_DATA_PS_MODE_PARAM:
  2050. pTxData->txDataAcTrfcCtrl[acID].PsMode =
  2051. pParamInfo->content.txDataQosParams.acTrfcCtrl.PsMode;
  2052. break;
  2053. case TX_DATA_CONFIG_TX_QUEUE_SIZE:
  2054. queueIndex = pParamInfo->content.txDataQosParams.acTrfcCtrl.QueueIndex;
  2055. pTxData->txDataAcTrfcCtrl[acID].TxQueueSize =
  2056. pParamInfo->content.txDataQosParams.acTrfcCtrl.TxQueueSize;
  2057. if(queueIndex >= MAX_NUM_OF_TX_QUEUES)
  2058. {
  2059. WLAN_REPORT_ERROR(pTxData->hReport, TX_DATA_MODULE_LOG,
  2060. ("Error configure Data MsduList , wrong queue index = %d\n", queueIndex));
  2061. return NOK;
  2062. }
  2063. pTxData->dataMsduListArr[queueIndex]->acId = acID;
  2064. pTxData->txDataAcTrfcCtrl[acID].QueueIndex = queueIndex;
  2065. /* also set the opposute direction conversion table (queue ID -> ac ID) */
  2066. txData_SetQidToAcTable( hTxData, queueIndex, queueIndex, acID );
  2067. if( (msduList_SetMsduListNumOfElements( pTxData->dataMsduListArr[queueIndex],
  2068. pTxData->txDataAcTrfcCtrl[acID].TxQueueSize)) != OK )
  2069. {
  2070. WLAN_REPORT_ERROR(pTxData->hReport, TX_DATA_MODULE_LOG,
  2071. ("Error configure MgmtMsduList\n"));
  2072. return NOK;
  2073. }
  2074. break;
  2075. case TX_DATA_CONFIG_TX_QUEUE_OVFLOW_POLICY:
  2076. queueIndex = pParamInfo->content.txDataQosParams.acTrfcCtrl.QueueIndex;
  2077. pTxData->txDataAcTrfcCtrl[acID].QueueOvFlowPolicy = pParamInfo->content.txDataQosParams.acTrfcCtrl.QueueOvFlowPolicy;
  2078. if(queueIndex >= MAX_NUM_OF_TX_QUEUES)
  2079. {
  2080. WLAN_REPORT_ERROR(pTxData->hReport, TX_DATA_MODULE_LOG,
  2081. ("Error configure MsduList over flow policy , wrong queue index = %d\n",queueIndex));
  2082. return NOK;
  2083. }
  2084. pTxData->txDataAcTrfcCtrl[acID].QueueIndex = queueIndex;
  2085. msduList_SetMsduListOverFlowPolicy(pTxData->dataMsduListArr[pTxData->txDataAcTrfcCtrl[acID].QueueIndex],
  2086. pTxData->txDataAcTrfcCtrl[acID].QueueOvFlowPolicy);
  2087. break;
  2088. case TX_DATA_CONFIG_AC_MSDU_LIFE_TIME:
  2089. pTxData->txDataAcTrfcCtrl[acID].MsduLifeTime = 1000 * pParamInfo->content.txDataQosParams.acTrfcCtrl.MsduLifeTime;
  2090. break;
  2091. case TX_DATA_CONFIG_AC_ACK_POLICY:
  2092. pTxData->txDataAcTrfcCtrl[acID].ackPolicy = pParamInfo->content.txDataQosParams.acTrfcCtrl.ackPolicy;
  2093. break;
  2094. case TX_DATA_AC_ADMISSION_STATE:
  2095. pTxData->dataMsduListArr[GET_QUEUE_INDEX(pTxData, acID)]->admissionRequired =
  2096. pParamInfo->content.txDataQosParams.qosParams.admissionRequired;
  2097. pTxData->dataMsduListArr[GET_QUEUE_INDEX(pTxData, acID)]->admissionState =
  2098. pParamInfo->content.txDataQosParams.qosParams.admissionState;
  2099. break;
  2100. case TX_DATA_CONVERT_HEADER_MODE:
  2101. pTxData->txDataQosParams.headerConverMode = pParamInfo->content.txDataQosParams.qosParams.headerConverMode;
  2102. break;
  2103. case TX_DATA_TAG_TO_AC_CLASSIFIER_TABLE:
  2104. os_memoryCopy(pTxData->hOs,(pTxData->txDataQosParams.tag_ToAcClsfrTable),
  2105. pParamInfo->content.txDataQosParams.qosParams.tag_ToAcClsfrTable,sizeof(acTrfcType_e) * MAX_NUM_OF_802_1d_TAGS);
  2106. break;
  2107. case TX_DATA_SET_AC_QUEUE_INDEX:
  2108. queueIndex = pParamInfo->content.txDataQosParams.acTrfcCtrl.QueueIndex;
  2109. pTxData->txDataAcTrfcCtrl[pParamInfo->content.txDataQosParams.acID].QueueIndex = queueIndex;
  2110. /* also set the opposute direction conversion table (queue ID -> ac ID) */
  2111. txData_SetQidToAcTable( hTxData, queueIndex, queueIndex, acID );
  2112. break;
  2113. case TX_DATA_SET_MEDIUM_USAGE_THRESHOLD:
  2114. txData_setMediumUsageThresholds (hTxData,
  2115. (UINT8)pParamInfo->content.txDataMediumUsageThreshold.uAC,
  2116. pParamInfo->content.txDataMediumUsageThreshold.uHighThreshold,
  2117. pParamInfo->content.txDataMediumUsageThreshold.uLowThreshold);
  2118. break;
  2119. case TX_DATA_GET_MEDIUM_USAGE_THRESHOLD:
  2120. /* SET operation is performed, but actually this is only for AC parameter transfer from Utility Adapter to driver, since copy
  2121. of user supplied block of data (and vice versa) is only performed in SetParam calls, the driver can also modify the supplied
  2122. structure and thus return it to user mode */
  2123. queueIndex = pTxData->txDataAcTrfcCtrl[pParamInfo->content.txDataMediumUsageThreshold.uAC].QueueIndex;
  2124. /* get threshold */
  2125. pParamInfo->content.txDataMediumUsageThreshold.uHighThreshold = pTxData->dataMsduListArr[queueIndex]->highMediumUsageThreshold;
  2126. pParamInfo->content.txDataMediumUsageThreshold.uLowThreshold = pTxData->dataMsduListArr[queueIndex]->lowMediumUsageThreshold;
  2127. break;
  2128. case TX_DATA_POLL_AP_PACKETS_FROM_AC:
  2129. queueIndex = pTxData->txDataAcTrfcCtrl[pParamInfo->content.txDataPollApPacketsFromACid].QueueIndex;
  2130. if (queueIndex <= QOS_AC_MAX)
  2131. return (txData_sendVadFrame (pTxData, queueIndex));
  2132. else
  2133. return PARAM_VALUE_NOT_VALID;
  2134. /* break; - unreachable */
  2135. case TX_DATA_ENCRYPTION_FIELD_SIZE:
  2136. /* set the space to reserve for encrypted frames */
  2137. pTxData->encryptionFieldSize = pParamInfo->content.txDataEncryptionFieldSize;
  2138. break;
  2139. case TX_DATA_RESET_COUNTERS_PARAM:
  2140. txData_resetCounters( hTxData );
  2141. break;
  2142. case TX_DATA_SET_VAD:
  2143. {
  2144. BOOL bVadTimerEnabled;
  2145. UINT16 vadTimerDuration;
  2146. bVadTimerEnabled = pParamInfo->content.txDataVadTimerParams.vadTimerEnabled;
  2147. vadTimerDuration = pParamInfo->content.txDataVadTimerParams.vadTimerDuration;
  2148. WLAN_REPORT_INFORMATION(pTxData->hReport, TX_DATA_MODULE_LOG,
  2149. ("txData_setParams: SET_VAD (enable=%d; duration=%d ms)\n",
  2150. bVadTimerEnabled, vadTimerDuration));
  2151. txData_setVadTimer(hTxData, bVadTimerEnabled, vadTimerDuration);
  2152. }
  2153. break;
  2154. default:
  2155. return (PARAM_NOT_SUPPORTED);
  2156. /* WLAN_REPORT_ERROR(pTxData->hReport, TX_DATA_MODULE_LOG,
  2157. (" txData_setParam() : PARAMETER NOT SUPPORTED \n"));
  2158. return NOK;
  2159. break; - unreachable */
  2160. }
  2161. return (OK);
  2162. }
  2163. /***************************************************************************
  2164. * txData_convertEthToWlanHeader *
  2165. ****************************************************************************
  2166. * DESCRIPTION: this function convert the msdu header from ethernet format
  2167. * to the 802.11 header format
  2168. *
  2169. * INPUTS: hTxData - the object
  2170. * pMsdu - msdu in ethernet format
  2171. *
  2172. * OUTPUT: pMsdu - msdu in 802.11 format
  2173. *
  2174. * RETURNS:
  2175. ***************************************************************************/
  2176. static void txData_convertEthToWlanHeader (txData_t *pTxData, mem_MSDU_T *pMsdu)
  2177. {
  2178. EthernetHeader_t *pEthHeader;
  2179. dot11_header_t dot11Header;
  2180. Wlan_LlcHeader_T WlanSnapHeader;
  2181. UINT16 swapedTypeLength;
  2182. bssType_e currBssType;
  2183. macAddress_t currBssId;
  2184. UINT8 SNAP_OUI_802_1H[] = SNAP_OUI_802_1H_BYTES;
  2185. UINT8 SNAP_OUI_RFC1042[] = SNAP_OUI_RFC1042_BYTES;
  2186. acTrfcType_e acIndex;
  2187. char* pData;
  2188. /* initialize the frame header length */
  2189. pMsdu->headerLen = txData_GetWlanHeaderLength( pTxData,
  2190. memMgr_BufData(pMsdu->firstBDPtr) +
  2191. memMgr_BufOffset(pMsdu->firstBDPtr),
  2192. pMsdu->txFlags );
  2193. /*
  2194. * Set the Eth pointer to the beginning of the first Bd
  2195. */
  2196. pEthHeader = (EthernetHeader_t*)(memMgr_BufData(pMsdu->firstBDPtr) + memMgr_BufOffset(pMsdu->firstBDPtr));
  2197. /*
  2198. * Initialize working copy of the dot11header to zero
  2199. */
  2200. os_memoryZero(pTxData->hOs,&dot11Header,sizeof(dot11_header_t));
  2201. /*
  2202. * Convert the header 802.3 ---> 802.11 onto the dot11Header working copy
  2203. */
  2204. /* set Qos control */
  2205. if( pTxData->txDataQosParams.headerConverMode == QOS_CONVERT )
  2206. {
  2207. /* set qos Tag */
  2208. dot11Header.qosControl = ((UINT16)pMsdu->qosTag & QOS_CONTROL_TAG_MASK);
  2209. /*
  2210. * set ac ack policy according to the
  2211. * Ack policy defined for the particular AC
  2212. */
  2213. acIndex = (acTrfcType_e)GET_WME_AC_TYPE_FROM_MSDU(pMsdu);
  2214. if(pTxData->txDataAcTrfcCtrl[acIndex].ackPolicy == ACK_POLICY_LEGACY)
  2215. {
  2216. dot11Header.qosControl &= ~DOT11_QOS_CONTROL_DONT_ACK;
  2217. }
  2218. else
  2219. {
  2220. dot11Header.qosControl |= DOT11_QOS_CONTROL_DONT_ACK;
  2221. }
  2222. }
  2223. /* receive BssId and Bss Type from control module */
  2224. ctrlData_getCurrBssTypeAndCurrBssId(pTxData->hCtrlData, &currBssId, &currBssType);
  2225. if (currBssType == BSS_INDEPENDENT)
  2226. {
  2227. MAC_COPY(pTxData->hOs,(&dot11Header.address1),(&pEthHeader->DstAddr));
  2228. MAC_COPY(pTxData->hOs,(&dot11Header.address2),(&pEthHeader->SrcAddr));
  2229. MAC_COPY(pTxData->hOs,(&dot11Header.address3),(&currBssId));
  2230. if( pTxData->txDataQosParams.headerConverMode == QOS_CONVERT )
  2231. dot11Header.fc = DOT11_FC_DATA_QOS;
  2232. else
  2233. dot11Header.fc = DOT11_FC_DATA;
  2234. }
  2235. else /* infrastructure BSS */
  2236. {
  2237. MAC_COPY(pTxData->hOs,(&dot11Header.address1),(&currBssId));
  2238. MAC_COPY(pTxData->hOs,(&dot11Header.address2),(&pEthHeader->SrcAddr));
  2239. MAC_COPY(pTxData->hOs,(&dot11Header.address3),(&pEthHeader->DstAddr));
  2240. if( pTxData->txDataQosParams.headerConverMode == QOS_CONVERT )
  2241. dot11Header.fc = DOT11_FC_DATA_QOS | DOT11_FC_TO_DS;
  2242. else
  2243. dot11Header.fc = DOT11_FC_DATA | DOT11_FC_TO_DS;
  2244. }
  2245. swapedTypeLength = wlan_htons(pEthHeader->TypeLength);
  2246. /* Detect the packet type and decide if to create a */
  2247. /* new SNAP or leave the original LLC. */
  2248. /*------------------------------------------------------*/
  2249. if( swapedTypeLength > ETHERNET_MAX_PAYLOAD_SIZE )
  2250. {
  2251. /* Create the SNAP Header: */
  2252. /*-----------------------------*/
  2253. /*
  2254. * Make a working copy of the SNAP header
  2255. * initialised to zero
  2256. */
  2257. os_memoryZero(pTxData->hOs,&WlanSnapHeader,sizeof(Wlan_LlcHeader_T));
  2258. WlanSnapHeader.DSAP = SNAP_CHANNEL_ID;
  2259. WlanSnapHeader.SSAP = SNAP_CHANNEL_ID;
  2260. WlanSnapHeader.Control = LLC_CONTROL_UNNUMBERED_INFORMATION;
  2261. /* Check to see if the Ethertype matches anything in the translation */
  2262. /* table (Appletalk AARP or DixII/IPX). If so, add the 802.1h */
  2263. /* SNAP. */
  2264. if(( ETHERTYPE_APPLE_AARP == swapedTypeLength ) ||
  2265. ( ETHERTYPE_DIX_II_IPX == swapedTypeLength ))
  2266. {
  2267. /* Fill out the SNAP Header with 802.1H extention */
  2268. os_memoryCopy(pTxData->hOs, &WlanSnapHeader.OUI, SNAP_OUI_802_1H,
  2269. sizeof( WlanSnapHeader.OUI ) );
  2270. }
  2271. else
  2272. {
  2273. /* otherwise, add the RFC1042 SNAP */
  2274. os_memoryCopy(pTxData->hOs, &WlanSnapHeader.OUI, SNAP_OUI_RFC1042,
  2275. sizeof( WlanSnapHeader.OUI) );
  2276. }
  2277. /* set type length */
  2278. WlanSnapHeader.Type = pEthHeader->TypeLength;
  2279. }
  2280. /*
  2281. * Now - copy wlan header and snap overriding Ethernet header.
  2282. */
  2283. /*
  2284. first the wlan header
  2285. the header might not include the qosControl which will be erase
  2286. later by the snap header
  2287. */
  2288. /* pData starts after the reserved place for bus txn and the TxDescriptor */
  2289. /* update data offset - bus txn extra space + TxDescriptor */
  2290. memMgr_BufOffset(pMsdu->firstBDPtr) = TX_TOTAL_OFFSET_BEFORE_DATA;
  2291. pData = memMgr_BufData(pMsdu->firstBDPtr) + memMgr_BufOffset(pMsdu->firstBDPtr);
  2292. os_memoryCopy(pTxData->hOs,pData,&dot11Header,pMsdu->headerLen);
  2293. /* update data length */
  2294. pMsdu->dataLen = pMsdu->dataLen - ETHERNET_HDR_LEN + pMsdu->headerLen;
  2295. /* now the snap */
  2296. if( swapedTypeLength > ETHERNET_MAX_PAYLOAD_SIZE )
  2297. {
  2298. pData += (pMsdu->headerLen - sizeof(Wlan_LlcHeader_T));
  2299. os_memoryCopy(pTxData->hOs,pData,&WlanSnapHeader,sizeof(Wlan_LlcHeader_T));
  2300. }
  2301. return;
  2302. }
  2303. /***************************************************************************
  2304. * txData_resetCounters *
  2305. ****************************************************************************
  2306. * DESCRIPTION: Reset the tx data module counters
  2307. *
  2308. * INPUTS: hTxData - the object
  2309. *
  2310. * OUTPUT:
  2311. *
  2312. * RETURNS:
  2313. ***************************************************************************/
  2314. void txData_resetCounters(TI_HANDLE hTxData)
  2315. {
  2316. txData_t *pTxData = (txData_t *)hTxData;
  2317. os_memoryZero(pTxData->hOs, &pTxData->txDataCounters, sizeof(txDataCounters_t) * MAX_NUM_OF_TX_QUEUES);
  2318. pTxData->currentConsecutiveRetryFail = 0;
  2319. }
  2320. /***************************************************************************
  2321. * txData_resetDbgCounters *
  2322. ****************************************************************************
  2323. * DESCRIPTION: Reset the tx data module debug counters
  2324. *
  2325. * INPUTS: hTxData - the object
  2326. *
  2327. * OUTPUT:
  2328. *
  2329. * RETURNS:
  2330. ***************************************************************************/
  2331. void txData_resetDbgCounters(TI_HANDLE hTxData)
  2332. {
  2333. txData_t *pTxData = (txData_t *)hTxData;
  2334. os_memoryZero(pTxData->hOs, &pTxData->txDataDbgCounters, sizeof(txDataDbgCounters_t));
  2335. }
  2336. /***************************************************************************
  2337. * txData_DistributorTxEvent *
  2338. ****************************************************************************
  2339. * DESCRIPTION:
  2340. *
  2341. *
  2342. * INPUTS:
  2343. *
  2344. *
  2345. *
  2346. * OUTPUT:
  2347. *
  2348. * RETURNS:
  2349. *
  2350. ***************************************************************************/
  2351. static VOID txData_DistributorTxEvent(txData_t *pTxData,UINT16 Mask,int DataLen)
  2352. {
  2353. if(pTxData->TxEventDistributor)
  2354. DistributorMgr_EventCall(pTxData->TxEventDistributor,Mask,DataLen);
  2355. }
  2356. /***************************************************************************
  2357. * txData_RegNotif *
  2358. ****************************************************************************/
  2359. TI_HANDLE txData_RegNotif(TI_HANDLE hTxData,UINT16 EventMask,GeneralEventCall_t CallBack,TI_HANDLE context,UINT32 Cookie)
  2360. {
  2361. txData_t *pTxData = (txData_t *)hTxData;
  2362. if (!hTxData)
  2363. return NULL;
  2364. return DistributorMgr_Reg(pTxData->TxEventDistributor,EventMask,(TI_HANDLE)CallBack,context,Cookie);
  2365. }
  2366. /***************************************************************************
  2367. * txData_AddToNotifMask *
  2368. ****************************************************************************/
  2369. TI_STATUS txData_AddToNotifMask(TI_HANDLE hTxData,TI_HANDLE Notifh,UINT16 EventMask)
  2370. {
  2371. txData_t *pTxData = (txData_t *)hTxData;
  2372. if (!hTxData)
  2373. return NOK;
  2374. return DistributorMgr_AddToMask(pTxData->TxEventDistributor,Notifh,EventMask);
  2375. }
  2376. /***************************************************************************
  2377. * TxData_UnRegNotif *
  2378. ****************************************************************************/
  2379. TI_STATUS txData_UnRegNotif(TI_HANDLE hTxData,TI_HANDLE RegEventHandle)
  2380. {
  2381. TI_STATUS status;
  2382. txData_t *pTxData = (txData_t *)hTxData;
  2383. if (!hTxData)
  2384. return NOK;
  2385. status = DistributorMgr_UnReg(pTxData->TxEventDistributor,RegEventHandle);
  2386. return status;
  2387. }
  2388. /****************************************************************************
  2389. * txData_SetTxDelayCounters()
  2390. ****************************************************************************
  2391. * DESCRIPTION: Update transmission path delay counters.
  2392. *
  2393. * INPUTS: hTxData - the object
  2394. * txQid - the queue to count delay for
  2395. * pTxCompleteAttr - struct containing the necessary FW delay data
  2396. * driverDelay - the time consumed in driver for packet transmission
  2397. *
  2398. * OUTPUT:
  2399. *
  2400. * RETURNS:
  2401. ****************************************************************************/
  2402. static void txData_SetTxDelayCounters( TI_HANDLE hTxData, UINT32 txQid, txCompleteAttr_t *pTxCompleteAttr, UINT32 driverDelay )
  2403. {
  2404. txData_t *pTxData = (txData_t *)hTxData;
  2405. int rangeIndex;
  2406. UINT32 totalTxDelayMs;
  2407. /* Add 1 to the total time so that Total time will always be greater than fwHandlingTime */
  2408. totalTxDelayMs = driverDelay + (pTxCompleteAttr->fwHandlingTime / 1000) + 1;
  2409. /* Increment the delay range counter that the current packet Tx delay falls in. */
  2410. for (rangeIndex = TX_DELAY_RANGE_MIN; rangeIndex <= TX_DELAY_RANGE_MAX; rangeIndex++)
  2411. {
  2412. if ( (totalTxDelayMs >= txDelayRangeStart[rangeIndex]) &&
  2413. (totalTxDelayMs <= txDelayRangeEnd [rangeIndex]) )
  2414. {
  2415. pTxData->txDataCounters[ txQid ].txDelayHistogram[ rangeIndex ]++;
  2416. pTxData->txDataReportedCounters[ txQid ].txDelayHistogram[ rangeIndex ]++;
  2417. break;
  2418. }
  2419. }
  2420. /* Update total delay and MAC delay sums and packets number for average delay calculation. */
  2421. if (pTxData->txDataCounters[ txQid ].SumTotalDelayMs < 0x7FFFFFFF) /* verify we are not close to the edge. */
  2422. {
  2423. pTxData->txDataCounters[ txQid ].NumPackets++;
  2424. pTxData->txDataCounters[ txQid ].SumTotalDelayMs += totalTxDelayMs;
  2425. pTxData->txDataCounters[ txQid ].SumFWDelayUs += pTxCompleteAttr->fwHandlingTime;
  2426. pTxData->txDataCounters[ txQid ].SumMacDelayUs += pTxCompleteAttr->mediumDelay;
  2427. }
  2428. else /* If we get close to overflow, restart average accumulation. */
  2429. {
  2430. pTxData->txDataCounters[ txQid ].NumPackets = 1;
  2431. pTxData->txDataCounters[ txQid ].SumTotalDelayMs = totalTxDelayMs;
  2432. pTxData->txDataCounters[ txQid ].SumFWDelayUs = pTxCompleteAttr->fwHandlingTime;
  2433. pTxData->txDataCounters[ txQid ].SumMacDelayUs = pTxCompleteAttr->mediumDelay;
  2434. }
  2435. pTxData->txDataReportedCounters[ txQid ].NumPackets++;
  2436. pTxData->txDataReportedCounters[ txQid ].SumTotalDelayMs += totalTxDelayMs;
  2437. pTxData->txDataReportedCounters[ txQid ].SumFWDelayUs += pTxCompleteAttr->fwHandlingTime;
  2438. pTxData->txDataReportedCounters[ txQid ].SumMacDelayUs += pTxCompleteAttr->mediumDelay;
  2439. }
  2440. /***************************************************************************
  2441. * txData_UpdateTxCounters *
  2442. ****************************************************************************
  2443. * DESCRIPTION: free the transmitted msdu
  2444. *
  2445. * INPUTS: hTxData - the object
  2446. * pTxCompletAttr - all atributes passed along with the TX
  2447. * complete indication
  2448. *
  2449. * OUTPUT:
  2450. *
  2451. * RETURNS:
  2452. ***************************************************************************/
  2453. void txData_UpdateTxCounters( TI_HANDLE hTxData, txCompleteAttr_t *pTxCompleteAttr )
  2454. {
  2455. txData_t *pTxData = (txData_t*)hTxData;
  2456. txPacketIdAttr_t *pPacketId = (txPacketIdAttr_t *)(pTxCompleteAttr->packetId);
  2457. UINT16 EventMask = 0;
  2458. UINT32 dataLen, TxQid = pPacketId->txQid;
  2459. UINT32 retryHistogramIndex;
  2460. switch ( pTxCompleteAttr->status )
  2461. {
  2462. case SEND_COMPLETE_SUCCESS:
  2463. /* update the retry histogram */
  2464. retryHistogramIndex = (pTxCompleteAttr->ackFailures >= TX_RETRY_HISTOGRAM_SIZE ?
  2465. TX_RETRY_HISTOGRAM_SIZE - 1 :
  2466. pTxCompleteAttr->ackFailures);
  2467. pTxData->txDataCounters[ TxQid ].RetryHistogram[ retryHistogramIndex ]++;
  2468. /* update delay histogram */
  2469. txData_SetTxDelayCounters( hTxData, TxQid, pTxCompleteAttr, pPacketId->driverHandlingTime );
  2470. if ( (TRUE == pPacketId->bDataMsdu) && (pTxData->txDataQosParams.headerConverMode == QOS_CONVERT) )
  2471. {
  2472. dataLen = pPacketId->msduDataLen - (WLAN_WITH_SNAP_QOS_HEADER_MAX_SIZE - ETHERNET_HDR_LEN);
  2473. }
  2474. else
  2475. {
  2476. dataLen = pPacketId->msduDataLen - (WLAN_WITH_SNAP_HEADER_MAX_SIZE - ETHERNET_HDR_LEN);
  2477. }
  2478. if ( IsMacAddressDirected( &(pPacketId->destinationMac) ) )
  2479. {
  2480. /* Directed frame */
  2481. pTxData->txDataCounters[TxQid].DirectedFramesXmit++;
  2482. pTxData->txDataCounters[TxQid].DirectedBytesXmit += dataLen;
  2483. EventMask |= DIRECTED_BYTES_XFER;
  2484. EventMask |= DIRECTED_FRAMES_XFER;
  2485. }
  2486. else if ( IsMacAddressBroadcast( &(pPacketId->destinationMac) ) )
  2487. {
  2488. /* Broadcast frame */
  2489. pTxData->txDataCounters[TxQid].BroadcastFramesXmit++;
  2490. pTxData->txDataCounters[TxQid].BroadcastBytesXmit += dataLen;
  2491. EventMask |= BROADCAST_BYTES_XFER;
  2492. EventMask |= BROADCAST_FRAMES_XFER;
  2493. }
  2494. else
  2495. {
  2496. /* Multicast Address */
  2497. pTxData->txDataCounters[TxQid].MulticastFramesXmit++;
  2498. pTxData->txDataCounters[TxQid].MulticastBytesXmit += dataLen;
  2499. EventMask |= MULTICAST_BYTES_XFER;
  2500. EventMask |= MULTICAST_FRAMES_XFER;
  2501. }
  2502. pTxData->txDataCounters[TxQid].XmitOk++;
  2503. EventMask |= XFER_OK;
  2504. /* update the max consecutive retry failures (if needed) */
  2505. if (pTxData->currentConsecutiveRetryFail > pTxData->txDataCounters[ TxQid ].MaxConsecutiveRetryFail)
  2506. {
  2507. pTxData->txDataCounters[TxQid].MaxConsecutiveRetryFail = pTxData->currentConsecutiveRetryFail;
  2508. }
  2509. pTxData->currentConsecutiveRetryFail = 0;
  2510. txData_DistributorTxEvent( pTxData, EventMask, dataLen );
  2511. break;
  2512. case SEND_COMPLETE_RETRY_EXCEEDED:
  2513. pTxData->txDataCounters[ TxQid ].RetryFailCounter++;
  2514. pTxData->currentConsecutiveRetryFail++;
  2515. pTxData->txDataReportedCounters[ TxQid ].OtherFailCounter++;
  2516. break;
  2517. case SEND_COMPLETE_LIFETIME_EXCEEDED:
  2518. pTxData->txDataCounters[ TxQid ].TxTimeoutCounter++;
  2519. pTxData->txDataReportedCounters[ TxQid ].OtherFailCounter++;
  2520. break;
  2521. case SEND_COMPLETE_NO_LINK:
  2522. pTxData->txDataCounters[ TxQid ].NoLinkCounter++;
  2523. pTxData->txDataReportedCounters[ TxQid ].OtherFailCounter++;
  2524. break;
  2525. case SEND_COMPLETE_MAC_CRASHED: /* curently not used */
  2526. default:
  2527. pTxData->txDataCounters[ TxQid ].OtherFailCounter++;
  2528. pTxData->txDataReportedCounters[ TxQid ].OtherFailCounter++;
  2529. break;
  2530. }
  2531. }
  2532. static void txData_startVadTimer(TI_HANDLE hTxData, UINT16 voiceDuration)
  2533. {
  2534. txData_t *pTxData = (txData_t*)hTxData;
  2535. if (FALSE == pTxData->bVadTimerEnabled)
  2536. {
  2537. WLAN_REPORT_INFORMATION(pTxData->hReport, TX_DATA_MODULE_LOG,
  2538. ("txData_startVadTimer: (voiceDuration is %d) .....................\n", voiceDuration));
  2539. pTxData->vadTimerDuration = voiceDuration;
  2540. pTxData->bVadTimerEnabled = TRUE;
  2541. os_timerStart(pTxData->hOs, pTxData->pVadTimer, voiceDuration, TRUE);
  2542. }
  2543. else
  2544. {
  2545. WLAN_REPORT_INFORMATION(pTxData->hReport, TX_DATA_MODULE_LOG,
  2546. ("txData_startVadTimer: nothing done. VAD is already started ........\n", voiceDuration));
  2547. }
  2548. }
  2549. static void txData_stopVadTimer(TI_HANDLE hTxData)
  2550. {
  2551. txData_t *pTxData = (txData_t*)hTxData;
  2552. if (pTxData->bVadTimerEnabled)
  2553. {
  2554. WLAN_REPORT_INFORMATION(pTxData->hReport, TX_DATA_MODULE_LOG, ("txData_stopVadTimer ...\n"));
  2555. os_timerStop(pTxData->hOs, pTxData->pVadTimer);
  2556. pTxData->bVadTimerEnabled = FALSE;
  2557. }
  2558. }
  2559. static void txData_setVadTimer(TI_HANDLE hTxData, BOOL vadEnabled, UINT16 duration)
  2560. {
  2561. txData_t *pTxData = (txData_t*)hTxData;
  2562. WLAN_REPORT_INFORMATION(pTxData->hReport, TX_DATA_MODULE_LOG, ("txData_setVadTimer (%d, %d)\n", vadEnabled, duration));
  2563. if (vadEnabled)
  2564. txData_startVadTimer(hTxData, duration);
  2565. else
  2566. txData_stopVadTimer(hTxData);
  2567. }
  2568. static void txData_resetVadTimer(TI_HANDLE hTxData)
  2569. {
  2570. txData_t *pTxData = (txData_t*)hTxData;
  2571. // UINT32 timeStamp;
  2572. if (pTxData->bVadTimerEnabled)
  2573. {
  2574. /*
  2575. timeStamp = os_timeStampMs(pTxData->hOs);
  2576. printk("resetVadTimer: timestamp = %d\n", timeStamp);
  2577. */
  2578. os_timerStop(pTxData->hOs, pTxData->pVadTimer);
  2579. os_timerStart(pTxData->hOs, pTxData->pVadTimer, pTxData->vadTimerDuration, TRUE);
  2580. }
  2581. }
  2582. static void txData_vadTimeout(TI_HANDLE hTxData)
  2583. {
  2584. txData_t *pTxData = (txData_t*)hTxData;
  2585. // UINT32 timeStamp;
  2586. /*
  2587. timeStamp = os_timeStampMs(pTxData->hOs);
  2588. printk("vadTimeout: timestamp = %d\n", timeStamp);
  2589. */
  2590. txData_sendVadFrame (pTxData, QOS_AC_VO);
  2591. }
  2592. /***************************************************************************
  2593. * txData_startTxSchedulerFromTimer *
  2594. ****************************************************************************
  2595. * DESCRIPTION:
  2596. *
  2597. * INPUTS:
  2598. *
  2599. * OUTPUT:
  2600. *
  2601. * RETURNS:
  2602. ***************************************************************************/
  2603. static void txData_startTxSchedulerFromTimer(TI_HANDLE hTxData)
  2604. {
  2605. WLAN_REPORT_DEBUG_TX(((txData_t *)hTxData)->hReport,
  2606. ("in txData_startTxSchedulerFromTimer.....................\n"));
  2607. txData_startTxScheduler(hTxData);
  2608. }
  2609. /***********************************************************************
  2610. * txData_sendNullFrame
  2611. ***********************************************************************
  2612. DESCRIPTION: Send Null frame Function.
  2613. The function does the following:
  2614. - Builds Null Data Frame with PS bit set to On or Off.
  2615. - Allocates MSDU frame.
  2616. - Sends the frame.
  2617. INPUT: hTxData - Tx Data Pointer.
  2618. powerSaveMode - Indicates if to switch the Power Save
  2619. mode to On or Off.
  2620. module - The calling module.
  2621. OUTPUT: None
  2622. RETURN: OK on success, NOK otherwise
  2623. ************************************************************************/
  2624. TI_STATUS txData_sendNullFrame(TI_HANDLE hTxData,
  2625. BOOL powerSaveOn,
  2626. allocatingModule_e module)
  2627. {
  2628. TI_STATUS status;
  2629. mem_MSDU_T *pMsdu;
  2630. paramInfo_t daParam, saParam;
  2631. dot11_header_t *pFrame; /* Note : there is no body for null frame */
  2632. txData_t *pTxData = (txData_t *)hTxData;
  2633. /* Getting new msdu */
  2634. status = wlan_memMngrAllocMSDU(pTxData->hMemMngr, &pMsdu, WLAN_HDR_LEN + TX_TOTAL_OFFSET_BEFORE_DATA, module);
  2635. if (status != OK)
  2636. return NOK;
  2637. pFrame = (dot11_header_t*)(pMsdu->firstBDPtr->data + TX_TOTAL_OFFSET_BEFORE_DATA);
  2638. /* Setting the Frame Control with Data frame type and Null frame sub type*/
  2639. pFrame->fc = 0;
  2640. pFrame->fc |= DOT11_FC_DATA_NULL_FUNCTION;
  2641. pFrame->fc |= DOT11_FC_TO_DS;
  2642. /* setting the Power Save bit in the Frame control field*/
  2643. if(powerSaveOn == TRUE)
  2644. pFrame->fc |= (0x1 << DOT11_FC_PWR_MGMT_SHIFT);
  2645. daParam.paramType = CTRL_DATA_CURRENT_BSSID_PARAM;
  2646. status = ctrlData_getParam(pTxData->hCtrlData, &daParam);
  2647. if (status != OK)
  2648. {
  2649. wlan_memMngrFreeMSDU(pTxData->hMemMngr, pMsdu->handle);
  2650. return NOK;
  2651. }
  2652. /* copy destination mac address */
  2653. MAC_COPY(pTxData->hOs, (&pFrame->address3), (&daParam.content.ctrlDataCurrentBSSID));
  2654. saParam.paramType = CTRL_DATA_MAC_ADDRESS;
  2655. status = ctrlData_getParam(pTxData->hCtrlData, &saParam);
  2656. if (status != OK)
  2657. {
  2658. wlan_memMngrFreeMSDU(pTxData->hMemMngr, pMsdu->handle);
  2659. return NOK;
  2660. }
  2661. /* copy source mac address */
  2662. MAC_COPY(pTxData->hOs, (&pFrame->address2), (&saParam.content.ctrlDataCurrentBSSID));
  2663. /* copy BSSID (destination mac address) */
  2664. MAC_COPY(pTxData->hOs, (&pFrame->address1), (&daParam.content.ctrlDataCurrentBSSID));
  2665. /* Update MSDU parameters */
  2666. pMsdu->headerLen = pMsdu->dataLen = WLAN_HDR_LEN;
  2667. pMsdu->firstBDPtr->length = pMsdu->dataLen + TX_TOTAL_OFFSET_BEFORE_DATA;
  2668. /* send the packet to the TX */
  2669. pMsdu->qosTag = 0;
  2670. pMsdu->txFlags |= TX_DATA_NULL_MSDU;
  2671. status = txData_txSendMsdu(hTxData, pMsdu);
  2672. return status;
  2673. }
  2674. /***********************************************************************
  2675. * txData_sendVadFrame
  2676. ***********************************************************************
  2677. DESCRIPTION: Send a polling frame to retrieve downlink traffic from
  2678. the AP. Activated by the voice application when there is
  2679. no uplink traffic during a voice call.
  2680. The polling is either PS-Poll (for legacy PS) or QoS-Null
  2681. (for UPSD).
  2682. Null frame is currently added after PS-Poll to trigger
  2683. the triggered-scan which is only triggered by data frames!
  2684. Note that currently the acID parameter is ignored to insure this
  2685. function is not activated for other ACs than Voice (to add this
  2686. flexibility the txData_txSendMsdu() function should be updated.
  2687. INPUT: acID - Currently not used! Supporting only AC_VO!
  2688. OUTPUT: None
  2689. RETURN: OK on success, NOK otherwise
  2690. ************************************************************************/
  2691. TI_STATUS txData_sendVadFrame(TI_HANDLE hTxData, UINT8 acID)
  2692. {
  2693. mem_MSDU_T *pMsdu;
  2694. TI_STATUS status;
  2695. txData_t *pTxData = (txData_t *)hTxData;
  2696. paramInfo_t param;
  2697. if (pTxData->txDataPortStatus != OPEN)
  2698. {
  2699. WLAN_REPORT_INFORMATION(pTxData->hReport, TX_DATA_MODULE_LOG,
  2700. ("txData_sendVadFrame(): While port status is %d\n", pTxData->txDataPortStatus ));
  2701. return NOK;
  2702. }
  2703. param.paramType = QOS_MNGR_ACTIVE_PROTOCOL;
  2704. status = qosMngr_getParams(pTxData->hQosMngr, &param);
  2705. /* For WME - send QoS-Null-Data. */
  2706. if (param.content.qosSiteProtocol == WME)
  2707. {
  2708. /* Send QoS-Null frame to retrieve downlink packets and to trigger the triggered-scan. */
  2709. /* Note: If VO mode is PSPOLL, the txData_txSendMsdu() will add the PS-Poll frame. */
  2710. if((status = txData_buildQosNullDataFrame(pTxData,&pMsdu,wmeAcToUpIndex[QOS_AC_VO])) == OK)
  2711. status = txData_txSendMsdu(hTxData, pMsdu);
  2712. WLAN_REPORT_INFORMATION(pTxData->hReport, TX_DATA_MODULE_LOG,
  2713. ("txData_sendVadFrame(): WME site...Sending QoS-Null frame, Status=%d\n", status));
  2714. }
  2715. /* For non-WME - send PS-Poll plus Null-Data. */
  2716. else
  2717. {
  2718. /* Send PS-Poll to retrieve downlink packets. */
  2719. if((status = txData_getPsPollFrame(pTxData,&pMsdu)) == OK)
  2720. status = txData_txSendMsdu(hTxData, pMsdu);
  2721. /* Send also a null frame to trigger the triggered-scan in the FW. */
  2722. /* Note: Needed because the scan is triggered only by data frames, so PS-Poll is not enough!. */
  2723. /* Note: The txData_txSendMsdu() won't send another PS-Poll before the null frame since
  2724. pMsdu->qosTag is set to 0 for null (and not voice). */
  2725. status = txData_sendNullFrame(hTxData, FALSE, TX_MODULE);
  2726. WLAN_REPORT_INFORMATION(pTxData->hReport, TX_DATA_MODULE_LOG,
  2727. ("txData_sendVadFrame(): Non-WME site...Sending PS-Poll and Null frame, Status=%d\n", status));
  2728. }
  2729. return status;
  2730. }
  2731. /***********************************************************************
  2732. * txData_getPsPollFrame
  2733. ***********************************************************************
  2734. DESCRIPTION: builds PS POLL frame Function.
  2735. The function does the following:
  2736. - Builds PS POLL Control Frame with PS bit set to On .
  2737. - Allocates MSDU frame.
  2738. - Sends the frame.
  2739. ----------------------------
  2740. PS Poll - 802.11 Mac Header
  2741. ----------------------------
  2742. Version 0
  2743. Type %01 (Control)
  2744. Subtype %1010 (PS Poll)
  2745. Frame Control Flag %00010000 (Power Management Bit set -> Power Save mode)
  2746. Assoc ID association ID
  2747. BSSID MAC addr of BSSID
  2748. Transmitter MAC addr of sender
  2749. ----------------------------
  2750. typedef struct
  2751. {
  2752. UINT16 fc;
  2753. UINT16 AID;
  2754. macAddress_t BSSID;
  2755. macAddress_t TA;
  2756. } dot11_PsPollFrameHeader_t;
  2757. INPUT:
  2758. OUTPUT: None
  2759. RETURN: OK on success, NOK otherwise
  2760. ************************************************************************/
  2761. TI_STATUS txData_getPsPollFrame(TI_HANDLE hTxData,mem_MSDU_T **pMsduPsPoll)
  2762. {
  2763. TI_STATUS status = OK;
  2764. UINT32 timeStamp ;
  2765. paramInfo_t daParam, saParam;
  2766. whalParamInfo_t whalParam;
  2767. dot11_PsPollFrameHeader_t *pFrame; /* Note : there is no body for null frame */
  2768. txData_t *pTxData = (txData_t *)hTxData;
  2769. mem_MSDU_T *pMsdu;
  2770. /* Getting new msdu */
  2771. status = wlan_memMngrAllocMSDU(pTxData->hMemMngr, &pMsdu, WLAN_HDR_LEN + TX_TOTAL_OFFSET_BEFORE_DATA, TX_MODULE);
  2772. if (status != OK)
  2773. {
  2774. return NOK;
  2775. }
  2776. pFrame = (dot11_PsPollFrameHeader_t*)(pMsdu->firstBDPtr->data + TX_TOTAL_OFFSET_BEFORE_DATA);
  2777. /*
  2778. ** Building the Frame Control word (16 bits)
  2779. ** ---------------------------------------------
  2780. */
  2781. pFrame->fc = 0;
  2782. /*
  2783. ** Type = Control
  2784. ** SubType = Power Save (PS) POLL, */
  2785. pFrame->fc |= DOT11_FC_PS_POLL;
  2786. /*
  2787. ** setting the Power Management bit in the Frame control field
  2788. ** to be "Power Save mode"
  2789. */
  2790. pFrame->fc |= (0x1 << DOT11_FC_PWR_MGMT_SHIFT);
  2791. /*
  2792. ** Association ID
  2793. ** -----------------
  2794. */
  2795. whalParam.paramType = HAL_CTRL_AID_PARAM;
  2796. status = whalCtrl_GetParam (pTxData->hWhalCtrl, &whalParam) ;
  2797. if (status != OK)
  2798. {
  2799. wlan_memMngrFreeMSDU(pTxData->hMemMngr, pMsdu->handle);
  2800. return NOK;
  2801. }
  2802. /* AID should have its two MSB bit Set to "1"*/
  2803. pFrame->AID = whalParam.content.halCtrlAid | 0xC000;
  2804. WLAN_REPORT_WARNING(pTxData->hReport, TX_DATA_MODULE_LOG,
  2805. (" AID 4 = %d \n", (whalParam.content.halCtrlAid | 0xC000)));
  2806. /*
  2807. ** BSSID
  2808. ** ---------
  2809. */
  2810. daParam.paramType = CTRL_DATA_CURRENT_BSSID_PARAM;
  2811. status = ctrlData_getParam(pTxData->hCtrlData, &daParam);
  2812. if (status != OK)
  2813. {
  2814. wlan_memMngrFreeMSDU(pTxData->hMemMngr, pMsdu->handle);
  2815. return NOK;
  2816. }
  2817. /* copy destination mac address */
  2818. MAC_COPY(pTxData->hOs, (&pFrame->BSSID), (&daParam.content.ctrlDataCurrentBSSID));
  2819. /*
  2820. ** TA - Transmiter (MAC) Address
  2821. ** -------------------------------
  2822. */
  2823. saParam.paramType = CTRL_DATA_MAC_ADDRESS;
  2824. status = ctrlData_getParam(pTxData->hCtrlData, &saParam);
  2825. if (status != OK)
  2826. {
  2827. wlan_memMngrFreeMSDU(pTxData->hMemMngr, pMsdu->handle);
  2828. return NOK;
  2829. }
  2830. /* copy source mac address */
  2831. MAC_COPY(pTxData->hOs, (&pFrame->TA), (&saParam.content.ctrlDataCurrentBSSID));
  2832. timeStamp = os_timeStampMs(pTxData->hOs);
  2833. WLAN_REPORT_INFORMATION(pTxData->hReport, TX_DATA_MODULE_LOG,
  2834. (" txData_sendPsPollFrame() : time = %d insert PS_POLL frame to Driver queue \n", timeStamp));
  2835. /* Update MSDU parameters */
  2836. pMsdu->headerLen = pMsdu->dataLen = sizeof(dot11_PsPollFrameHeader_t);
  2837. pMsdu->firstBDPtr->length = pMsdu->dataLen + TX_TOTAL_OFFSET_BEFORE_DATA;
  2838. pMsdu->txFlags |= TX_DATA_PS_POLL;
  2839. if (status == OK)
  2840. WLAN_REPORT_INFORMATION(pTxData->hReport, TX_DATA_MODULE_LOG,
  2841. ("in txData_sendPsPollFrame: enter PS_POLL to queue\n"));
  2842. else
  2843. WLAN_REPORT_INFORMATION(pTxData->hReport, TX_DATA_MODULE_LOG,
  2844. ("in txData_sendPsPollFrame: didn't enter PS_POLL to queue\n"));
  2845. *pMsduPsPoll = pMsdu;
  2846. return status;
  2847. }
  2848. /***********************************************************************
  2849. * txData_updateUsedTime
  2850. ***********************************************************************
  2851. DESCRIPTION: This function is called for every txComplete in order
  2852. to update the transmisssion time.
  2853. INPUT: hTxData - handale to the ts data object
  2854. qNum - the queue that the frame transmitted from
  2855. usedTime - the time of the transmission (in microseconds)
  2856. OUTPUT: None
  2857. RETURN: OK on success
  2858. ************************************************************************/
  2859. TI_STATUS txData_updateUsedTime(TI_HANDLE hTxData, UINT32 qNum, UINT16 usedTime)
  2860. {
  2861. txData_t *pTxData = (txData_t *)hTxData;
  2862. /* addd the used time for the specific queue */
  2863. pTxData->dataMsduListArr[qNum]->totalUsedTime += usedTime;
  2864. return OK;
  2865. }
  2866. /***********************************************************************
  2867. * txData_calcCreditFromTimer
  2868. ***********************************************************************
  2869. DESCRIPTION: This function is called when credit calculation timer
  2870. is expired. it calculate the credit for the admission ctrl
  2871. credit algorithm
  2872. INPUT: hTxData - handle to the ts data object
  2873. OUTPUT: None
  2874. RETURN: void
  2875. ************************************************************************/
  2876. static void txData_calcCreditFromTimer(TI_HANDLE hTxData)
  2877. {
  2878. UINT32 qNum;
  2879. OS_802_11_THRESHOLD_CROSS_INDICATION_PARAMS mediumTimeCross;
  2880. txData_t *pTxData = (txData_t *)hTxData;
  2881. INT32 prevCredit;
  2882. INT32 highCreditThreshold;
  2883. INT32 lowCreditThreshold;
  2884. MsduList_t *pMsduList;
  2885. INT32 usageRatio;
  2886. INT32 currUsage;
  2887. INT32 prevUsage;
  2888. /* get current time stamp */
  2889. UINT32 currentTimeStamp = os_timeStampMs(pTxData->hOs);
  2890. for(qNum = 0 ; qNum< MAX_NUM_OF_TX_QUEUES ; qNum++)
  2891. {
  2892. pMsduList = pTxData->dataMsduListArr[qNum];
  2893. /* check if this queue is under admission ctrl opration */
  2894. if(pMsduList->mediumTime == 0)
  2895. {
  2896. WLAN_REPORT_INFORMATION(pTxData->hReport, TX_DATA_MODULE_LOG,
  2897. (" txData_calcCreditFromTimer() :qNum = %d mediumTime = 0 \n",qNum));
  2898. continue;
  2899. }
  2900. /* in case of wraparound */
  2901. if(currentTimeStamp < pMsduList->lastTimeStamp)
  2902. pMsduList->lastTimeStamp = 0;
  2903. /* store prev credit */
  2904. prevCredit = pMsduList->credit;
  2905. /* Calculate the medium usage ratio: totalUsedTime / mediumTime * 1000
  2906. Note that since the totalUsedTime is in usec and not msec we don't multiply by 1000. */
  2907. usageRatio = pMsduList->totalUsedTime / pMsduList->mediumTime;
  2908. /* calculate credit */
  2909. pMsduList->credit = pMsduList->credit + (currentTimeStamp - pMsduList->lastTimeStamp) - usageRatio;
  2910. /* update last time stamp */
  2911. pMsduList->lastTimeStamp = currentTimeStamp;
  2912. /* check if credit exceeds above mediumTime or below -mediumTime */
  2913. if (pMsduList->credit > (INT32)(pMsduList->mediumTime) )
  2914. {
  2915. /* in case of credit is big than mediumTime -> set credit to medium time */
  2916. pMsduList->credit = pMsduList->mediumTime;
  2917. pMsduList->enableTransmissionTime = 0;
  2918. }
  2919. /* If credit is lower than -mediumTime we exceed the admitted time. */
  2920. else if (pMsduList->credit <= (INT32)(0 - pMsduList->mediumTime))
  2921. {
  2922. /* Only delay transmission on this AC if the "delay" registry key is TRUE */
  2923. if(pTxData->admCtrlDelayDueToMediumTimeOverUsage == TRUE)
  2924. pMsduList->enableTransmissionTime = (0 - pMsduList->credit) - pMsduList->mediumTime;
  2925. }
  2926. WLAN_REPORT_INFORMATION(pTxData->hReport, TX_DATA_MODULE_LOG,
  2927. ("credit = %d | TotalUsedTime = %d | enableTransmissionTime = %d\n",
  2928. pMsduList->credit, pMsduList->totalUsedTime/1000, pMsduList->enableTransmissionTime));
  2929. /* Check medium-usage threshold cross events */
  2930. /*********************************************/
  2931. /*
  2932. * The medium-usage events are defined as follows:
  2933. * The high threshold triggers event only when crossed upward (traffic increased above threshold).
  2934. * The low threshold triggers event only when crossed downward (traffic decreased below threshold).
  2935. * Thus, the two thresholds provide hysteresis and prevent multiple triggering.
  2936. * The high threshold should be greater than the low threshold.
  2937. */
  2938. highCreditThreshold = (INT32)((pMsduList->mediumTime)*(pMsduList->highMediumUsageThreshold)/100);
  2939. lowCreditThreshold = (INT32)((pMsduList->mediumTime)*(pMsduList->lowMediumUsageThreshold)/100);
  2940. /* The credit is getting more negative as we get closer to the medium usage limit, so we invert
  2941. it before comparing to the thresholds (lower credit means higher usage). */
  2942. currUsage = -pMsduList->credit;
  2943. prevUsage = -prevCredit;
  2944. /* crossing below the low threshold */
  2945. if ( (currUsage < lowCreditThreshold) && (prevUsage >= lowCreditThreshold) )
  2946. {
  2947. /* send event */
  2948. mediumTimeCross.uAC = txData_GetAcIdFromQid( hTxData, qNum );
  2949. mediumTimeCross.uHighOrLowThresholdFlag = (UINT32)LOW_THRESHOLD_CROSS;
  2950. mediumTimeCross.uAboveOrBelowFlag = (UINT32)CROSS_BELOW;
  2951. EvHandlerSendEvent(pTxData->hEvHandler, IPC_EVENT_MEDIUM_TIME_CROSS, (UINT8 *)&mediumTimeCross,sizeof(OS_802_11_THRESHOLD_CROSS_INDICATION_PARAMS));
  2952. WLAN_REPORT_INFORMATION(pTxData->hReport, TX_DATA_MODULE_LOG,
  2953. ("crossed below low threshold !!! prevUsage = %d, currUsage = %d, lowCreditThreshold = %d\n",
  2954. prevUsage, currUsage, lowCreditThreshold));
  2955. }
  2956. /* crossing above the high threshold */
  2957. else if ( (currUsage > highCreditThreshold) && (prevUsage <= highCreditThreshold) )
  2958. {
  2959. /* send event */
  2960. mediumTimeCross.uAC = txData_GetAcIdFromQid( hTxData, qNum );
  2961. mediumTimeCross.uHighOrLowThresholdFlag = (UINT32)HIGH_THRESHOLD_CROSS;
  2962. mediumTimeCross.uAboveOrBelowFlag = (UINT32)CROSS_ABOVE;
  2963. EvHandlerSendEvent(pTxData->hEvHandler, IPC_EVENT_MEDIUM_TIME_CROSS, (UINT8 *)&mediumTimeCross,sizeof(OS_802_11_THRESHOLD_CROSS_INDICATION_PARAMS));
  2964. WLAN_REPORT_INFORMATION(pTxData->hReport, TX_DATA_MODULE_LOG,
  2965. ("crossed above high threshold !!! prevUsage = %d, currUsage = %d, highCreditThreshold = %d\n",
  2966. prevUsage, currUsage, highCreditThreshold));
  2967. }
  2968. /* reset totalUsedTime */
  2969. pMsduList->totalUsedTime = 0;
  2970. }
  2971. }
  2972. /***********************************************************************
  2973. * txData_setAdmisionCtrlParams
  2974. ***********************************************************************
  2975. DESCRIPTION: This function is called for add/delete a tspec in order
  2976. to update parameters.
  2977. INPUT: hTxData - handale to the ts data object
  2978. acID - the AC of the tspec
  2979. mediumTime - tha alocated medium time for this UP
  2980. minimumPHYRate - the min phy rate to send a packet of this UP
  2981. admFlag - indicate if the its addition or deletion of tspec
  2982. OUTPUT: None
  2983. RETURN: void
  2984. ************************************************************************/
  2985. TI_STATUS txData_setAdmisionCtrlParams(TI_HANDLE hTxData,
  2986. UINT8 acID,
  2987. UINT16 mediumTime,
  2988. UINT32 minimumPHYRate,
  2989. BOOL admFlag)
  2990. {
  2991. UINT8 queueIndex;
  2992. UINT8 i;
  2993. txData_t *pTxData = (txData_t *)hTxData;
  2994. MsduList_t *pMsduList;
  2995. /* find queue from AC */
  2996. queueIndex = pTxData->txDataAcTrfcCtrl[acID].QueueIndex;
  2997. pMsduList = pTxData->dataMsduListArr[queueIndex];
  2998. if(admFlag == TRUE)
  2999. {
  3000. /* tspaec added */
  3001. pMsduList->mediumTime = mediumTime;
  3002. /* in case of medium time>0 set relevant parameters to the credit algo calculation */
  3003. pMsduList->admissionState = AC_ADMITTED;
  3004. /* enable admission algo for this queue */
  3005. pMsduList->useAdmissionAlgo = TRUE;
  3006. pMsduList->lastTimeStamp = os_timeStampMs(pTxData->hOs);
  3007. pMsduList->enableTransmissionTime = 0;
  3008. pMsduList->credit = mediumTime;
  3009. }
  3010. else
  3011. {
  3012. /* tspaec deleted */
  3013. pMsduList->mediumTime = 0;
  3014. /* in case of medium time=0 reset relevant parameters */
  3015. pMsduList->admissionState = AC_NOT_ADMITTED;
  3016. pMsduList->useAdmissionAlgo = FALSE;
  3017. pMsduList->lastTimeStamp = 0;
  3018. pMsduList->enableTransmissionTime = 0;
  3019. pMsduList->credit = 0;
  3020. }
  3021. /* If the timer was not enabled in registry than we will never set it */
  3022. if ( pTxData->bCreditCalcTimerEnabled )
  3023. {
  3024. /* enable disable credit calculation timer */
  3025. for(i = 0 ; i < MAX_NUM_OF_TX_QUEUES ; i++)
  3026. {
  3027. if(pTxData->dataMsduListArr[i]->useAdmissionAlgo == TRUE)
  3028. {
  3029. if(pTxData->bCreditCalcTimerRunning == FALSE)
  3030. {
  3031. pTxData->bCreditCalcTimerRunning = TRUE;
  3032. os_timerStart(pTxData->hOs, pTxData->pCreditTimer, pTxData->creditCalculationTimeout, TRUE);
  3033. }
  3034. return OK;
  3035. }
  3036. }
  3037. /* in all queues useAdmissionAlgo is not TRUE */
  3038. if ( pTxData->bCreditCalcTimerRunning )
  3039. {
  3040. os_timerStop(pTxData->hOs, pTxData->pCreditTimer);
  3041. pTxData->bCreditCalcTimerRunning = FALSE;
  3042. }
  3043. }
  3044. return OK;
  3045. }
  3046. /***********************************************************************
  3047. * txData_setPsVoiceDeliveryMode
  3048. ***********************************************************************
  3049. DESCRIPTION: This function is called for add/delete a tspec in order
  3050. to set the PS mode for a specific UP
  3051. INPUT: hTxData - handale to the ts data object
  3052. userPriority - the user priority of the tspec
  3053. PsMode - tha PS mode for the specific UP
  3054. OUTPUT: None
  3055. RETURN: OK on success, NOK otherwise
  3056. ************************************************************************/
  3057. TI_STATUS txData_setPsVoiceDeliveryMode(TI_HANDLE hTxData, PSScheme_e PsMode)
  3058. {
  3059. txData_t *pTxData = (txData_t *)hTxData;
  3060. pTxData->txDataAcTrfcCtrl[QOS_AC_VO].PsMode = PsMode;
  3061. return OK;
  3062. }
  3063. /***********************************************************************
  3064. * txData_setMediumUsageThresholds
  3065. ***********************************************************************
  3066. DESCRIPTION: This function is called in order to set the threshold
  3067. for the medium time usage
  3068. INPUT: hTxData - handale to the ts data object
  3069. acID - the AC
  3070. highMediumUsageThreshold - high threshold
  3071. lowMediumUsageThreshold - lowhreshold
  3072. OUTPUT: None
  3073. RETURN: OK on success, NOK otherwise
  3074. ************************************************************************/
  3075. TI_STATUS txData_setMediumUsageThresholds(TI_HANDLE hTxData,
  3076. UINT8 acID,
  3077. INT32 highMediumUsageThreshold,
  3078. INT32 lowMediumUsageThreshold)
  3079. {
  3080. txData_t *pTxData = (txData_t *)hTxData;
  3081. UINT8 queueIndex;
  3082. /* validate AC */
  3083. if(acID >= MAX_NUM_OF_AC)
  3084. return NOK;
  3085. /* find queu from ac */
  3086. queueIndex = pTxData->txDataAcTrfcCtrl[acID].QueueIndex;
  3087. /* set threshold */
  3088. pTxData->dataMsduListArr[queueIndex]->lowMediumUsageThreshold = lowMediumUsageThreshold;
  3089. pTxData->dataMsduListArr[queueIndex]->highMediumUsageThreshold = highMediumUsageThreshold;
  3090. return OK;
  3091. }
  3092. /***********************************************************************
  3093. * txData_isQueueUseMediumTime
  3094. ***********************************************************************
  3095. DESCRIPTION:
  3096. INPUT: hTxData - handale to the ts data object
  3097. OUTPUT: None
  3098. RETURN: OK on success, NOK otherwise
  3099. ************************************************************************/
  3100. BOOL txData_isQueueUseMediumTime(TI_HANDLE hTxData, UINT8 qNum)
  3101. {
  3102. txData_t *pTxData = (txData_t *)hTxData;
  3103. if(pTxData->dataMsduListArr[qNum]->mediumTime == 0)
  3104. return FALSE;
  3105. else
  3106. return TRUE;
  3107. }
  3108. void Test_HeaderConvertion(TI_HANDLE hTxData, mem_MSDU_T *pMsdu)
  3109. {
  3110. txData_t *pTxData = (txData_t *)hTxData;
  3111. print_MsduDataHeader(pTxData->hMemMngr, pMsdu);
  3112. txData_convertEthToWlanHeader( pTxData, pMsdu );
  3113. print_MsduDataHeader(pTxData->hMemMngr, pMsdu);
  3114. }
  3115. #ifdef TI_DBG
  3116. void txData_printTxBlock(TI_HANDLE hTxData)
  3117. {
  3118. txData_t *pTxData = (txData_t *)hTxData;
  3119. int i;
  3120. WLAN_OS_REPORT(("hCtrlData = 0x%X\n", pTxData->hCtrlData));
  3121. WLAN_OS_REPORT(("hTnetwDrv = 0x%X\n", pTxData->hTnetwDrv));
  3122. WLAN_OS_REPORT(("hOs = 0x%X\n", pTxData->hOs));
  3123. WLAN_OS_REPORT(("hReport = 0x%X\n", pTxData->hReport));
  3124. WLAN_OS_REPORT(("hMemMngr = 0x%X\n", pTxData->hMemMngr));
  3125. WLAN_OS_REPORT(("pSchedulerTimer = 0x%X\n", pTxData->pSchedulerTimer));
  3126. WLAN_OS_REPORT(("hCriticalSectionProtect = 0x%X\n", pTxData->hCriticalSectionProtect));
  3127. WLAN_OS_REPORT(("txDataPortStatus = %d\n", pTxData->txDataPortStatus));
  3128. WLAN_OS_REPORT(("txDataCurrentPrivacyInvokedMode = %d\n", pTxData->txDataCurrentPrivacyInvokedMode));
  3129. WLAN_OS_REPORT(("txDataEapolEncryptionStatus = %d\n", pTxData->txDataEapolEncryptionStatus));
  3130. WLAN_OS_REPORT(("txDataIsSchedulerInWork = %d\n", pTxData->txDataIsSchedulerInWork));
  3131. WLAN_OS_REPORT(("txDataNumOfQueues = %d\n", pTxData->txDataNumOfQueues));
  3132. WLAN_OS_REPORT(("mngMsduList = 0x%X\n", pTxData->mngMsduList));
  3133. for(i=0 ; i < MAX_NUM_OF_TX_QUEUES; i++ )
  3134. {
  3135. WLAN_OS_REPORT(("dataMsduList %d = 0x%X\n",i, pTxData->dataMsduListArr[i]));
  3136. }
  3137. }
  3138. /*
  3139. void printFullMsduList(MsduList_t *this);
  3140. void printMsduList(MsduList_t *this);
  3141. */
  3142. void txData_printDataMsduList(TI_HANDLE hTxData)
  3143. {
  3144. txData_t *pTxData = (txData_t *)hTxData;
  3145. int i;
  3146. for(i=0 ; i < MAX_NUM_OF_TX_QUEUES; i++ )
  3147. {
  3148. WLAN_OS_REPORT(("List : %d \n", i));
  3149. printMsduList(pTxData->dataMsduListArr[i]);
  3150. }
  3151. }
  3152. void txData_fullPrintDataMsduList(TI_HANDLE hTxData)
  3153. {
  3154. txData_t *pTxData = (txData_t *)hTxData;
  3155. int i;
  3156. for(i=0 ; i < MAX_NUM_OF_TX_QUEUES; i++ )
  3157. {
  3158. WLAN_OS_REPORT(("List : %d \n", i));
  3159. printFullMsduList(pTxData->dataMsduListArr[i]);
  3160. }
  3161. }
  3162. void txData_printMgmtMsduList(TI_HANDLE hTxData)
  3163. {
  3164. txData_t *pTxData = (txData_t *)hTxData;
  3165. printMsduList(pTxData->mngMsduList);
  3166. }
  3167. void txData_fullPrintMgmtMsduList(TI_HANDLE hTxData)
  3168. {
  3169. txData_t *pTxData = (txData_t *)hTxData;
  3170. printFullMsduList(pTxData->mngMsduList);
  3171. }
  3172. void txData_printTxCounters(TI_HANDLE hTxData)
  3173. {
  3174. txData_t *pTxData = (txData_t *)hTxData;
  3175. int TxQid;
  3176. for (TxQid = 0; TxQid < MAX_NUM_OF_TX_QUEUES; TxQid++)
  3177. {
  3178. WLAN_OS_REPORT(("Tx Queue %d:\n", TxQid));
  3179. WLAN_OS_REPORT(("===========\n"));
  3180. WLAN_OS_REPORT(("XmitOk = %d\n", pTxData->txDataCounters[TxQid].XmitOk));
  3181. WLAN_OS_REPORT(("DirectedBytesXmit = %d\n", pTxData->txDataCounters[TxQid].DirectedBytesXmit));
  3182. WLAN_OS_REPORT(("DirectedFramesXmit = %d\n", pTxData->txDataCounters[TxQid].DirectedFramesXmit));
  3183. WLAN_OS_REPORT(("MulticastBytesXmit = %d\n", pTxData->txDataCounters[TxQid].MulticastBytesXmit));
  3184. WLAN_OS_REPORT(("MulticastFramesXmit = %d\n", pTxData->txDataCounters[TxQid].MulticastFramesXmit));
  3185. WLAN_OS_REPORT(("BroadcastBytesXmit = %d\n", pTxData->txDataCounters[TxQid].BroadcastBytesXmit));
  3186. WLAN_OS_REPORT(("BroadcastFramesXmit = %d\n", pTxData->txDataCounters[TxQid].BroadcastFramesXmit));
  3187. }
  3188. /* dbg functions */
  3189. WLAN_OS_REPORT(("\nTx Debug info:\n", TxQid));
  3190. WLAN_OS_REPORT(("==============\n"));
  3191. WLAN_OS_REPORT(("DropedPacketsCounter = %d\n", pTxData->txDataDbgCounters.dbgDropedPacketsCounter));
  3192. WLAN_OS_REPORT(("NumOfNullMsdu (in sendPacketTransfer) = %d\n", pTxData->txDataDbgCounters.dbgNumOfNullMsdu));
  3193. }
  3194. void txData_printTxQosCounters(TI_HANDLE hTxData)
  3195. {
  3196. txData_t *pTxData = (txData_t *)hTxData;
  3197. int qIndex;
  3198. WLAN_OS_REPORT(("-------------- Tx Queues Statistics ---------------\n\n"));
  3199. WLAN_OS_REPORT(("Successed copied = Scheduled - Droped\n"));
  3200. WLAN_OS_REPORT(("Successed copied = Scheduled out - check size failed\n"));
  3201. WLAN_OS_REPORT(("-------------- Scheduled To Core queues ---------------\n"));
  3202. for(qIndex = 0; qIndex < MAX_NUM_OF_TX_QUEUES; qIndex++)
  3203. {
  3204. WLAN_OS_REPORT(("Queue %d = %d\n",qIndex, pTxData->txDataDbgCounters.dbgInsertToMsduListPackets[qIndex]));
  3205. }
  3206. WLAN_OS_REPORT(("-------------- Droped From Core queues ---------------\n"));
  3207. for(qIndex = 0; qIndex < MAX_NUM_OF_TX_QUEUES; qIndex++)
  3208. {
  3209. WLAN_OS_REPORT(("Queue %d = %d\n",qIndex, pTxData->txDataDbgCounters.dbgDropedFromMsduListPackets[qIndex]));
  3210. }
  3211. WLAN_OS_REPORT(("-------------- Scheduled out from Core queues ---------------\n"));
  3212. for(qIndex = 0; qIndex < MAX_NUM_OF_TX_QUEUES; qIndex++)
  3213. {
  3214. WLAN_OS_REPORT(("Queue %d = %d\n",qIndex, pTxData->txDataDbgCounters.dbgScheduledOutPackets[qIndex]));
  3215. }
  3216. WLAN_OS_REPORT(("--Dropped due Expiry Time in Core Queues (dropped after %d %% of total time)--\n",pTxData->uFracOfLifeTimeToDrop));
  3217. for(qIndex = 0; qIndex < MAX_NUM_OF_TX_QUEUES; qIndex++)
  3218. {
  3219. WLAN_OS_REPORT(("Queue %d = %d\n",qIndex, pTxData->txDataDbgCounters.dbgDroppedDueExpiryTimePackets[qIndex]));
  3220. }
  3221. WLAN_OS_REPORT(("-------------- Free MSDUs in sendPacketTransfer ---------------\n"));
  3222. for(qIndex = 0; qIndex < MAX_NUM_OF_TX_QUEUES; qIndex++)
  3223. {
  3224. WLAN_OS_REPORT(("Queue %d = %d\n",qIndex, pTxData->txDataDbgCounters.dbgNumOfMsduFreeInTxTransfer[qIndex]));
  3225. }
  3226. WLAN_OS_REPORT(("-------------- sendPacketTransfer CB number ---------------\n"));
  3227. for(qIndex = 0; qIndex < MAX_NUM_OF_TX_QUEUES; qIndex++)
  3228. {
  3229. WLAN_OS_REPORT(("Queue %d = %d\n",qIndex, pTxData->txDataDbgCounters.dbgNumOfMsduTxTransferCB[qIndex]));
  3230. }
  3231. WLAN_OS_REPORT(("-------------- XFER done in scheduler ---------------\n"));
  3232. for(qIndex = 0; qIndex < MAX_NUM_OF_TX_QUEUES; qIndex++)
  3233. {
  3234. WLAN_OS_REPORT(("Queue %d = %d\n",qIndex, pTxData->txDataDbgCounters.dbgNumOfMsduXferDoneInShceduler[qIndex]));
  3235. }
  3236. WLAN_OS_REPORT(("-------------- Success in scheduler ---------------\n"));
  3237. for(qIndex = 0; qIndex < MAX_NUM_OF_TX_QUEUES; qIndex++)
  3238. {
  3239. WLAN_OS_REPORT(("Queue %d = %d\n",qIndex, pTxData->txDataDbgCounters.dbgNumOfMsduSuccessInScheduler[qIndex]));
  3240. }
  3241. WLAN_OS_REPORT(("-------------- Pending in scheduler ---------------\n"));
  3242. for(qIndex = 0; qIndex < MAX_NUM_OF_TX_QUEUES; qIndex++)
  3243. {
  3244. WLAN_OS_REPORT(("Queue %d = %d\n",qIndex, pTxData->txDataDbgCounters.dbgNumOfMsduPendingInScheduler[qIndex]));
  3245. }
  3246. WLAN_OS_REPORT(("-------------- Busy in scheduler ---------------\n"));
  3247. for(qIndex = 0; qIndex < MAX_NUM_OF_TX_QUEUES; qIndex++)
  3248. {
  3249. WLAN_OS_REPORT(("Queue %d = %d\n",qIndex, pTxData->txDataDbgCounters.dbgNumOfMsduBusyInScheduler[qIndex]));
  3250. }
  3251. WLAN_OS_REPORT(("-------------- Error in scheduler ---------------\n"));
  3252. for(qIndex = 0; qIndex < MAX_NUM_OF_TX_QUEUES; qIndex++)
  3253. {
  3254. WLAN_OS_REPORT(("Queue %d = %d\n",qIndex, pTxData->txDataDbgCounters.dbgNumOfMsduErrorInScheduler[qIndex]));
  3255. }
  3256. WLAN_OS_REPORT(("-------------- sendPacketComplete ---------------\n"));
  3257. for(qIndex = 0; qIndex < MAX_NUM_OF_TX_QUEUES; qIndex++)
  3258. {
  3259. WLAN_OS_REPORT(("Queue %d = %d\n",qIndex, pTxData->txDataDbgCounters.dbgNumOfsendPacketComplete[qIndex]));
  3260. }
  3261. WLAN_OS_REPORT(("-------------- sendPacketComplete Error---------------\n"));
  3262. for(qIndex = 0; qIndex < MAX_NUM_OF_TX_QUEUES; qIndex++)
  3263. {
  3264. WLAN_OS_REPORT(("Queue %d = %d\n",qIndex, pTxData->txDataDbgCounters.dbgTxCmpltError[qIndex]));
  3265. }
  3266. WLAN_OS_REPORT(("-------------- Number of MSDUs successfuly sent to GWSI layer ---------------\n"));
  3267. for(qIndex = 0; qIndex < MAX_NUM_OF_TX_QUEUES; qIndex++)
  3268. {
  3269. WLAN_OS_REPORT(("Queue %d = %d\n",qIndex, pTxData->txDataDbgCounters.dbgSendToGwsiQosPackets[qIndex]));
  3270. }
  3271. WLAN_OS_REPORT(("-------------- Current GWSI port status: %s --------------\n",
  3272. (GWSI_OPEN == pTxData->txDataGwsiInterfaceStatus ? "OPEN" : "PENDING") ));
  3273. WLAN_OS_REPORT(("-------------- HW queue available status ---------------\n"));
  3274. for(qIndex = 0; qIndex < MAX_NUM_OF_TX_QUEUES; qIndex++)
  3275. {
  3276. WLAN_OS_REPORT(("Queue %d %s\n",qIndex,
  3277. (TRUE == pTxData->txDataAvailableQueue[qIndex] ? "Available" : "Not available") ));
  3278. }
  3279. }
  3280. void txData_printQosParams(TI_HANDLE hTxData)
  3281. {
  3282. UINT8 acID;
  3283. UINT8 qIndex;
  3284. txData_t *pTxData = (txData_t *)hTxData;
  3285. for(acID = FIRST_AC_INDEX;acID < MAX_NUM_OF_AC; acID++)
  3286. {
  3287. switch(acID)
  3288. {
  3289. case QOS_AC_BE:
  3290. WLAN_OS_REPORT(("BE Params:\n"));
  3291. break;
  3292. case QOS_AC_BK:
  3293. WLAN_OS_REPORT(("BK params:\n"));
  3294. break;
  3295. case QOS_AC_VI:
  3296. WLAN_OS_REPORT(("VI params:\n"));
  3297. break;
  3298. case QOS_AC_VO:
  3299. WLAN_OS_REPORT(("VO params:\n"));
  3300. break;
  3301. default:
  3302. break;
  3303. }
  3304. switch(pTxData->txDataAcTrfcCtrl[acID].PsMode)
  3305. {
  3306. case PS_SCHEME_UPSD_TRIGGER:
  3307. WLAN_OS_REPORT(("PsMode = UPSD\n"));
  3308. break;
  3309. case PS_SCHEME_LEGACY_PSPOLL:
  3310. WLAN_OS_REPORT(("PsMode = PS_POLL\n"));
  3311. break;
  3312. case PS_SCHEME_LEGACY:
  3313. WLAN_OS_REPORT(("PsMode = PS_SCHEME_REGULAR\n"));
  3314. break;
  3315. case PS_SCHEME_SAPSD:
  3316. WLAN_OS_REPORT(("PsMode = S-APSD\n"));
  3317. break;
  3318. default:
  3319. WLAN_OS_REPORT(("Error: PsMode = %d\n", pTxData->txDataAcTrfcCtrl[acID].PsMode));
  3320. break;
  3321. }
  3322. WLAN_OS_REPORT(("QueueIndex = %d\n", pTxData->txDataAcTrfcCtrl[acID].QueueIndex));
  3323. WLAN_OS_REPORT(("TxQueueSize = %d\n", pTxData->txDataAcTrfcCtrl[acID].TxQueueSize));
  3324. qIndex = GET_QUEUE_INDEX(pTxData, acID);
  3325. if(pTxData->dataMsduListArr[qIndex]->admissionState == AC_NOT_ADMITTED)
  3326. WLAN_OS_REPORT(("admissionState = Not Admitted\n\n" ));
  3327. else
  3328. WLAN_OS_REPORT(("admissionState = Admitted\n\n" ));
  3329. }
  3330. switch(pTxData->txDataQosParams.headerConverMode)
  3331. {
  3332. case NO_CONVERT:
  3333. WLAN_OS_REPORT(("headerConverMode = NO_CONVERT\n"));
  3334. break;
  3335. case QOS_CONVERT:
  3336. WLAN_OS_REPORT(("headerConverMode = QOS_CONVERT\n"));
  3337. break;
  3338. case LEGACY_CONVERT:
  3339. WLAN_OS_REPORT(("headerConverMode = LEGACY_CONVERT\n"));
  3340. break;
  3341. }
  3342. WLAN_OS_REPORT(("tag_ToQueueClfrTable = %d, %d, %d, %d, %d, %d, %d, %d\n",
  3343. pTxData->txDataQosParams.tag_ToAcClsfrTable[0],
  3344. pTxData->txDataQosParams.tag_ToAcClsfrTable[1],
  3345. pTxData->txDataQosParams.tag_ToAcClsfrTable[2],
  3346. pTxData->txDataQosParams.tag_ToAcClsfrTable[3],
  3347. pTxData->txDataQosParams.tag_ToAcClsfrTable[4],
  3348. pTxData->txDataQosParams.tag_ToAcClsfrTable[5],
  3349. pTxData->txDataQosParams.tag_ToAcClsfrTable[6],
  3350. pTxData->txDataQosParams.tag_ToAcClsfrTable[7]));
  3351. }
  3352. void txData_StartTxThroughputTimer(TI_HANDLE hTxData)
  3353. {
  3354. int counterIndex;
  3355. txData_t *pTxData = (txData_t *)hTxData;
  3356. if(pTxData->txThroughputTimerEnable == FALSE)
  3357. {
  3358. for(counterIndex = 0 ; counterIndex < MAX_NUM_OF_TX_QUEUES ; counterIndex++)
  3359. {
  3360. /* reset throughput counters */
  3361. pTxData->txDataDbgCounters.dbgInsertToMsduListBytes[counterIndex] = 0;
  3362. }
  3363. pTxData->txThroughputTimerEnable = TRUE;
  3364. /* start throughput timer */
  3365. os_timerStart(pTxData->hOs, pTxData->pThroughputTimer, THROUGHPUT_TIMER, TRUE);
  3366. }
  3367. }
  3368. void txData_StopTxThroughputTimer(TI_HANDLE hTxData)
  3369. {
  3370. txData_t *pTxData = (txData_t *)hTxData;
  3371. if(pTxData->txThroughputTimerEnable == TRUE)
  3372. {
  3373. os_timerStop(pTxData->hOs, pTxData->pThroughputTimer);
  3374. pTxData->txThroughputTimerEnable = FALSE;
  3375. }
  3376. }
  3377. static void txData_printTxThroughputPerQueue(TI_HANDLE hTxData)
  3378. {
  3379. txData_t *pTxData = (txData_t *)hTxData;
  3380. int qIndex;
  3381. WLAN_OS_REPORT(("\n"));
  3382. WLAN_OS_REPORT(("\n"));
  3383. WLAN_OS_REPORT(("-------------- Tx Throughput per Queues Statistics ---------------\n"));
  3384. WLAN_OS_REPORT(("-------------- Send To Wlan Per Queue Throughput---------------\n"));
  3385. for(qIndex = 0 ; qIndex < MAX_NUM_OF_TX_QUEUES ; qIndex++)
  3386. {
  3387. WLAN_OS_REPORT(("Queue %d = %d KBits/sec\n", qIndex,pTxData->txDataDbgCounters.dbgInsertToMsduListBytes[qIndex]*8/1024));
  3388. /* reset throughput counters */
  3389. pTxData->txDataDbgCounters.dbgInsertToMsduListBytes[qIndex] = 0;
  3390. }
  3391. }
  3392. void txData_StartTxAirThroughputTimer (TI_HANDLE hTxData)
  3393. {
  3394. unsigned counterIndex;
  3395. txData_t *pTxData = (txData_t *)hTxData;
  3396. if (!pTxData->txAirThroughputTimerEnable)
  3397. {
  3398. for (counterIndex = 0; counterIndex < MAX_NUM_OF_TX_QUEUES; counterIndex++)
  3399. {
  3400. /* reset throughput counters */
  3401. pTxData->txDataDbgCounters.dbgTxCmpltOkBytes[counterIndex] = 0;
  3402. }
  3403. pTxData->txAirThroughputTimerEnable = TRUE;
  3404. /* start throughput timer */
  3405. os_timerStart (pTxData->hOs, pTxData->pAirThroughputTimer, THROUGHPUT_TIMER, TRUE);
  3406. }
  3407. }
  3408. void txData_StopTxAirThroughputTimer (TI_HANDLE hTxData)
  3409. {
  3410. txData_t *pTxData = (txData_t *)hTxData;
  3411. if (pTxData->txAirThroughputTimerEnable)
  3412. {
  3413. os_timerStop (pTxData->hOs, pTxData->pAirThroughputTimer);
  3414. pTxData->txAirThroughputTimerEnable = FALSE;
  3415. }
  3416. }
  3417. static void txData_printTxAirThroughputPerQueue (TI_HANDLE hTxData)
  3418. {
  3419. txData_t *pTxData = (txData_t *)hTxData;
  3420. int qIndex;
  3421. WLAN_OS_REPORT (("\n"));
  3422. WLAN_OS_REPORT (("\n"));
  3423. WLAN_OS_REPORT (("-------------- Tx Air Throughput per Queue Statistics ---------------\n"));
  3424. WLAN_OS_REPORT (("-------------- Send to WLAN per Queue Throughput---------------\n"));
  3425. for (qIndex = 0; qIndex < MAX_NUM_OF_TX_QUEUES; qIndex++)
  3426. {
  3427. WLAN_OS_REPORT (("Queue %d = %d KBits/sec\n", qIndex, pTxData->txDataDbgCounters.dbgTxCmpltOkBytes[qIndex] * 8 / 1024));
  3428. /* reset throughput counters */
  3429. pTxData->txDataDbgCounters.dbgTxCmpltOkBytes[qIndex] = 0;
  3430. }
  3431. }
  3432. void txData_StartJitterTimer (TI_HANDLE hTxData)
  3433. {
  3434. unsigned u_ac;
  3435. txData_t *pTxData = (txData_t *)hTxData;
  3436. if (!pTxData->txJitterTimerEnable)
  3437. {
  3438. for (u_ac = 0; u_ac < MAX_NUM_OF_TX_QUEUES; u_ac++)
  3439. {
  3440. /* reset jitter intervals */
  3441. pTxData->txJitter[u_ac].jitter.core = 0;
  3442. pTxData->txJitter[u_ac].jitter.xfer = 0;
  3443. pTxData->txJitter[u_ac].jitter.air = 0;
  3444. pTxData->txJitter[u_ac].jitter.fw = 0;
  3445. pTxData->txJitter[u_ac].delay.core = 0;
  3446. pTxData->txJitter[u_ac].delay.xfer = 0;
  3447. pTxData->txJitter[u_ac].delay.wait = 0;
  3448. pTxData->txJitter[u_ac].delay.fw = 0;
  3449. pTxData->txJitter[u_ac].delay.air = 0;
  3450. pTxData->txJitter[u_ac].last_delay.core = 0;
  3451. pTxData->txJitter[u_ac].last_delay.xfer = 0;
  3452. pTxData->txJitter[u_ac].last_delay.fw = 0;
  3453. pTxData->txJitter[u_ac].last_delay.air = 0;
  3454. pTxData->txJitter[u_ac].max_delay.core = 0;
  3455. pTxData->txJitter[u_ac].max_delay.xfer = 0;
  3456. pTxData->txJitter[u_ac].max_delay.fw = 0;
  3457. pTxData->txJitter[u_ac].max_delay.air = 0;
  3458. pTxData->txJitter[u_ac].count.core = 0;
  3459. pTxData->txJitter[u_ac].count.xfer = 0;
  3460. pTxData->txJitter[u_ac].count.wait = 0;
  3461. pTxData->txJitter[u_ac].count.fw =
  3462. pTxData->txDataDbgCounters.dbgTxCmpltOk[u_ac];
  3463. pTxData->txJitter[u_ac].count.fw_err =
  3464. pTxData->txDataDbgCounters.dbgTxCmpltError[u_ac];
  3465. }
  3466. pTxData->txJitterTimerEnable = TRUE;
  3467. /* start throughput timer */
  3468. os_timerStart (pTxData->hOs, pTxData->pJitterTimer, THROUGHPUT_TIMER, TRUE);
  3469. }
  3470. }
  3471. void txData_StopJitterTimer (TI_HANDLE hTxData)
  3472. {
  3473. txData_t *pTxData = (txData_t *)hTxData;
  3474. if (pTxData->txJitterTimerEnable)
  3475. {
  3476. os_timerStop (pTxData->hOs, pTxData->pJitterTimer);
  3477. pTxData->txJitterTimerEnable = FALSE;
  3478. }
  3479. }
  3480. static void txData_printJitter (TI_HANDLE hTxData)
  3481. {
  3482. unsigned u_ac;
  3483. txData_t *pTxData = (txData_t *)hTxData;
  3484. WLAN_OS_REPORT (("\n"));
  3485. WLAN_OS_REPORT (("\n"));
  3486. WLAN_OS_REPORT (("-------------- Tx Jitter per Queue Statistics ---------------\n"));
  3487. for (u_ac = 0; u_ac < MAX_NUM_OF_TX_QUEUES; u_ac ++)
  3488. {
  3489. UINT32 u_ok = pTxData->txDataDbgCounters.dbgTxCmpltOk[u_ac] -
  3490. pTxData->txJitter[u_ac].count.fw;
  3491. UINT32 u_nok = pTxData->txDataDbgCounters.dbgTxCmpltError[u_ac] -
  3492. pTxData->txJitter[u_ac].count.fw_err;
  3493. if (u_ok + u_nok)
  3494. {
  3495. WLAN_OS_REPORT (("Queue [%d], drop=%d%%\n", u_ac, u_nok * 100 / (u_ok + u_nok)));
  3496. if (pTxData->txJitter[u_ac].count.core)
  3497. {
  3498. WLAN_OS_REPORT ((" Core: avg.delay=%6d, max.delay=%6d, jitter=%6d\n",
  3499. pTxData->txJitter[u_ac].delay.core / pTxData->txJitter[u_ac].count.core,
  3500. pTxData->txJitter[u_ac].max_delay.core,
  3501. pTxData->txJitter[u_ac].jitter.core / pTxData->txJitter[u_ac].count.core));
  3502. }
  3503. if (pTxData->txJitter[u_ac].count.xfer)
  3504. {
  3505. WLAN_OS_REPORT ((" Xfer: avg.delay=%6d, max.delay=%6d, jitter=%6d\n",
  3506. pTxData->txJitter[u_ac].delay.xfer / pTxData->txJitter[u_ac].count.xfer,
  3507. pTxData->txJitter[u_ac].max_delay.xfer,
  3508. pTxData->txJitter[u_ac].jitter.xfer / pTxData->txJitter[u_ac].count.xfer));
  3509. }
  3510. if (pTxData->txJitter[u_ac].count.wait)
  3511. {
  3512. WLAN_OS_REPORT ((" Wait: avg.delay=%6d\n",
  3513. pTxData->txJitter[u_ac].delay.wait / pTxData->txJitter[u_ac].count.wait));
  3514. }
  3515. if (u_ok > 0)
  3516. {
  3517. WLAN_OS_REPORT ((" Fw: avg.delay=%6d, max.delay=%6d, jitter=%6d\n",
  3518. pTxData->txJitter[u_ac].delay.fw / u_ok,
  3519. pTxData->txJitter[u_ac].max_delay.fw,
  3520. pTxData->txJitter[u_ac].jitter.fw / u_ok));
  3521. WLAN_OS_REPORT ((" Air: avg.delay=%6d, max.delay=%6d, jitter=%6d\n",
  3522. pTxData->txJitter[u_ac].delay.air / u_ok,
  3523. pTxData->txJitter[u_ac].max_delay.air,
  3524. pTxData->txJitter[u_ac].jitter.air / u_ok));
  3525. }
  3526. }
  3527. /* Update/reset jitter info */
  3528. pTxData->txJitter[u_ac].jitter.core = 0;
  3529. pTxData->txJitter[u_ac].jitter.xfer = 0;
  3530. pTxData->txJitter[u_ac].jitter.fw = 0;
  3531. pTxData->txJitter[u_ac].jitter.air = 0;
  3532. pTxData->txJitter[u_ac].delay.core = 0;
  3533. pTxData->txJitter[u_ac].delay.xfer = 0;
  3534. pTxData->txJitter[u_ac].delay.wait = 0;
  3535. pTxData->txJitter[u_ac].delay.fw = 0;
  3536. pTxData->txJitter[u_ac].delay.air = 0;
  3537. pTxData->txJitter[u_ac].max_delay.core = 0;
  3538. pTxData->txJitter[u_ac].max_delay.xfer = 0;
  3539. pTxData->txJitter[u_ac].max_delay.fw = 0;
  3540. pTxData->txJitter[u_ac].max_delay.air = 0;
  3541. pTxData->txJitter[u_ac].count.core = 0;
  3542. pTxData->txJitter[u_ac].count.xfer = 0;
  3543. pTxData->txJitter[u_ac].count.wait = 0;
  3544. pTxData->txJitter[u_ac].count.fw =
  3545. pTxData->txDataDbgCounters.dbgTxCmpltOk[u_ac];
  3546. pTxData->txJitter[u_ac].count.fw_err =
  3547. pTxData->txDataDbgCounters.dbgTxCmpltError[u_ac];
  3548. }
  3549. }
  3550. #endif /* TI_BDG */
  3551. /***********************************************************************
  3552. * txData_buildQosNullDataFrame
  3553. ***********************************************************************
  3554. DESCRIPTION: builds QOS_NULL_DATA frame.
  3555. INPUT:
  3556. OUTPUT: None
  3557. RETURN: OK on success, NOK otherwise
  3558. ************************************************************************/
  3559. TI_STATUS txData_buildQosNullDataFrame(TI_HANDLE hTxData,mem_MSDU_T **pMsduPsPoll, UINT8 userPriority)
  3560. {
  3561. TI_STATUS status = OK;
  3562. paramInfo_t daParam, saParam;
  3563. dot11_header_t *pFrame; /* Note : there is no body for null frame */
  3564. txData_t *pTxData = (txData_t *)hTxData;
  3565. mem_MSDU_T *pMsdu;
  3566. status = wlan_memMngrAllocMSDU(pTxData->hMemMngr, &pMsdu, WLAN_QOS_HDR_LEN + TX_TOTAL_OFFSET_BEFORE_DATA, TX_MODULE);
  3567. if (status != OK)
  3568. {
  3569. return NOK;
  3570. }
  3571. pFrame = (dot11_header_t*)(pMsdu->firstBDPtr->data+ TX_TOTAL_OFFSET_BEFORE_DATA);
  3572. /* Build frame control */
  3573. pFrame->fc = DOT11_FC_DATA_NULL_QOS;
  3574. pFrame->fc |= (0x1 << DOT11_FC_TO_DS_SHIFT);
  3575. pFrame->qosControl = (userPriority << QOS_CONTROL_UP_SHIFT);
  3576. pFrame->fc = ENDIAN_HANDLE_WORD(pFrame->fc);
  3577. /* BSSID */
  3578. daParam.paramType = CTRL_DATA_CURRENT_BSSID_PARAM;
  3579. status = ctrlData_getParam(pTxData->hCtrlData, &daParam);
  3580. if (status != OK)
  3581. {
  3582. wlan_memMngrFreeMSDU(pTxData->hMemMngr, pMsdu->handle);
  3583. return NOK;
  3584. }
  3585. MAC_COPY(pTxData->hOs, (&pFrame->address3), (&daParam.content.ctrlDataCurrentBSSID));
  3586. MAC_COPY(pTxData->hOs, (&pFrame->address1), (&daParam.content.ctrlDataCurrentBSSID));
  3587. /* Source MAC address */
  3588. saParam.paramType = CTRL_DATA_MAC_ADDRESS;
  3589. status = ctrlData_getParam(pTxData->hCtrlData, &saParam);
  3590. if (status != OK)
  3591. {
  3592. wlan_memMngrFreeMSDU(pTxData->hMemMngr, pMsdu->handle);
  3593. return NOK;
  3594. }
  3595. /* copy source mac address */
  3596. MAC_COPY(pTxData->hOs, (&pFrame->address2), (&saParam.content.ctrlDataDeviceMacAddress));
  3597. /* Update MSDU parameters */
  3598. pMsdu->headerLen = WLAN_QOS_HDR_LEN;
  3599. pMsdu->dataLen = WLAN_QOS_HDR_LEN;
  3600. pMsdu->firstBDPtr->length = WLAN_QOS_HDR_LEN;
  3601. pMsdu->qosTag = userPriority;
  3602. pMsdu->txFlags |= TX_DATA_NULL_MSDU;
  3603. // all data or mgmt packets built on host must have the correct
  3604. // offset set to point to the start of the mac frame
  3605. memMgr_BufOffset(pMsdu->firstBDPtr) = TX_TOTAL_OFFSET_BEFORE_DATA;
  3606. *pMsduPsPoll = pMsdu;
  3607. return status;
  3608. }
  3609. /****************************************************************************
  3610. * txData_SetQidToAcTable()
  3611. ****************************************************************************
  3612. * DESCRIPTION: set Qid according to Queue ID
  3613. ****************************************************************************/
  3614. void txData_SetQidToAcTable(TI_HANDLE hTxData,UINT8 QidStart, UINT8 QidEnd,UINT8 AcId)
  3615. {
  3616. int i;
  3617. txData_t *pTxData = (txData_t *)hTxData;
  3618. for(i = QidStart ; i <= QidEnd; i++)
  3619. pTxData->QidToAcTable[i] = AcId;
  3620. }
  3621. /****************************************************************************
  3622. * txData_GetAcIdFromQid()
  3623. ****************************************************************************
  3624. * DESCRIPTION: Get the Ac Id according to the Queue id
  3625. ****************************************************************************/
  3626. UINT8 txData_GetAcIdFromQid(TI_HANDLE hTxData,UINT8 Qid)
  3627. {
  3628. txData_t *pTxData = (txData_t *)hTxData;
  3629. return (pTxData->QidToAcTable[Qid]);
  3630. }
  3631. /****************************************************************************
  3632. * txData_GetWlanHeaderLength()
  3633. ****************************************************************************
  3634. * DESCRIPTION: calculates the WLAN header length, according to QoS,
  3635. * current encryption, and packet type
  3636. ****************************************************************************/
  3637. UINT32 txData_GetWlanHeaderLength( TI_HANDLE hTxData, void *pData, UINT32 txFlags )
  3638. {
  3639. txData_t *pTxData = (txData_t*)hTxData;
  3640. UINT32 wlanHeaderLength = 0;
  3641. EthernetHeader_t *pEthHeader;
  3642. UINT16 swapedTypeLength;
  3643. /* management frames never have QoS or encryption padding */
  3644. if ( txFlags & TX_DATA_MGMT_MSDU )
  3645. {
  3646. return WLAN_HDR_LEN;
  3647. }
  3648. /*
  3649. * Determine 802.11 header length
  3650. * QoS Header is longer (2 Bytes)
  3651. */
  3652. if ( pTxData->txDataQosParams.headerConverMode == QOS_CONVERT )
  3653. {
  3654. wlanHeaderLength = WLAN_QOS_HDR_LEN;
  3655. }
  3656. else
  3657. {
  3658. wlanHeaderLength = WLAN_HDR_LEN;
  3659. }
  3660. if ( txFlags & TX_DATA_EAPOL_MSDU )
  3661. {
  3662. /* EAPOLs should always contain SNAP */
  3663. wlanHeaderLength += WLAN_SNAP_HDR_LEN;
  3664. /* EAPOL encryption is set by the RSN module */
  3665. if ( TRUE == pTxData->txDataEapolEncryptionStatus )
  3666. {
  3667. wlanHeaderLength += pTxData->encryptionFieldSize;
  3668. }
  3669. return wlanHeaderLength;
  3670. }
  3671. /* add encryption overhead - 4 bytes for TKIP, 8 for AES. Actual decision was done at RSN */
  3672. if (pTxData->txDataCurrentPrivacyInvokedMode == TRUE)
  3673. {
  3674. wlanHeaderLength += pTxData->encryptionFieldSize;
  3675. }
  3676. /*
  3677. * IAPP header should always include SNAP, but this is already included in the frame
  3678. * body itself, so it is not added here
  3679. */
  3680. if ( txFlags & TX_DATA_IAPP_MSDU )
  3681. {
  3682. return wlanHeaderLength;
  3683. }
  3684. /* stat frames are checked if they already contain SNAP header or not */
  3685. if ( txFlags & TX_DATA_DATA_MSDU )
  3686. {
  3687. /*
  3688. * Detect the packet type and decide if to create a
  3689. * new SNAP or leave the original LLC.
  3690. */
  3691. pEthHeader = (EthernetHeader_t *)pData;
  3692. swapedTypeLength = wlan_htons(pEthHeader->TypeLength);
  3693. /*
  3694. * if the "type" field is greater than 1500 bytes, it means the frame we received has
  3695. * Ethernet II header (destination MAC, source MAC, type, 14 bytes total), and therefore
  3696. * we need to reserve 8 more bytes after the 802.11 header for LLC/SNAP header.
  3697. * If this field is smaller than or equal to 1500, this is not really a "type" field of
  3698. * Ethernet II header, but rather a 802.3 size field. since 802.3 already has 8 bytes
  3699. * LLC/SNAP header (other than the 802.3 14 bytes of destination MAC, source MAC and size),
  3700. * there is no need to reserve 8 more bytes.
  3701. */
  3702. if ( swapedTypeLength > ETHERNET_MAX_PAYLOAD_SIZE )
  3703. {
  3704. return wlanHeaderLength + WLAN_SNAP_HDR_LEN;
  3705. }
  3706. else
  3707. {
  3708. return wlanHeaderLength;
  3709. }
  3710. }
  3711. else
  3712. {
  3713. WLAN_REPORT_ERROR( pTxData->hReport, TX_DATA_MODULE_LOG,
  3714. (" %s: trying to get header length for packet with txFlags: 0x%x\n", __FUNCTION__, txFlags) );
  3715. return 0;
  3716. }
  3717. }
  3718. /****************************************************************************
  3719. * txDataMsduTimeExpired()
  3720. ****************************************************************************
  3721. * DESCRIPTION: calculates the time left until MSDU will expire, retunrs the
  3722. * time in TUs, or 0 if the MSDU has already expired.
  3723. ****************************************************************************/
  3724. UINT32 txDataTimeToMsduExpiry (TI_HANDLE hTxData, mem_MSDU_T* pMsdu, UINT8 qID)
  3725. {
  3726. txData_t *pTxData = (txData_t*)hTxData;
  3727. UINT32 acID, uPassedTime;
  3728. /* translate queue ID to AC ID */
  3729. acID = txData_GetAcIdFromQid (hTxData, qID);
  3730. /* get time passed since insertion */
  3731. uPassedTime = os_timeStampUs (pTxData->hOs) - pMsdu->insertionTime;
  3732. /* if the passed time is smaller than a certain proportion of the MsduLifeTime - it's O.K. */
  3733. if (uPassedTime <
  3734. ((pTxData->uFracOfLifeTimeToDrop * pTxData->txDataAcTrfcCtrl[acID].MsduLifeTime) / 100))
  3735. {
  3736. return (pTxData->txDataAcTrfcCtrl[acID].MsduLifeTime - uPassedTime) >> 10;
  3737. }
  3738. /* timer expired, or about to expire --> drop it.*/
  3739. return 0;
  3740. }
  3741. /****************************************************************************
  3742. * txData_startAfterRecovery *
  3743. *****************************************************************************
  3744. * DESCRIPTION: This function start the tx data after recovery.
  3745. * It uses params that save before recovery.
  3746. *
  3747. * INPUTS: hTxData - the object
  3748. *
  3749. * OUTPUT:
  3750. *
  3751. * RETURNS: OK - stop succesfull
  3752. * NOK - stop unsuccesfull
  3753. ****************************************************************************/
  3754. TI_STATUS txData_startAfterRecovery(TI_HANDLE hTxData)
  3755. {
  3756. txData_t *pTxData = (txData_t *)hTxData;
  3757. /* check parameters validity */
  3758. if( pTxData == NULL )
  3759. {
  3760. WLAN_REPORT_ERROR(pTxData->hReport, TX_DATA_MODULE_LOG,
  3761. (" txData_start() : Illegal value for hTxData\n"));
  3762. return NOK;
  3763. }
  3764. pTxData->txDataPortStatus = pTxData->savePortStatus;
  3765. pTxData->txDataCurrentPrivacyInvokedMode = pTxData->saveTxDataCurrentPrivacyInvokedMode;
  3766. pTxData->txDataEapolEncryptionStatus = pTxData->saveTxDataEapolEncryptionStatus;
  3767. pTxData->encryptionFieldSize = pTxData->saveEncryptionFieldSize;
  3768. /* start scheduler timer */
  3769. os_timerStart(pTxData->hOs, pTxData->pSchedulerTimer, SCHEDULER_TIMER, TRUE);
  3770. pTxData->bSchedulerTimerRunning = TRUE;
  3771. return OK;
  3772. }