2 ** $Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/nic/nic_tx.c#1 $
6 \brief Functions that provide TX operation in NIC Layer.
8 This file provides TX functions which are responsible for both Hardware and
9 Software Resource Management and keep their Synchronization.
17 * 06 13 2012 yuche.tsai
19 * Update maintrunk driver.
20 * Add support for driver compose assoc request frame.
22 * 11 18 2011 eddie.chen
23 * [WCXRP00001096] [MT6620 Wi-Fi][Driver/FW] Enhance the log function (xlog)
24 * Add log counter for tx
26 * 11 09 2011 eddie.chen
27 * [WCXRP00001096] [MT6620 Wi-Fi][Driver/FW] Enhance the log function (xlog)
28 * Add xlog for beacon timeout and sta aging timeout.
30 * 11 08 2011 eddie.chen
31 * [WCXRP00001096] [MT6620 Wi-Fi][Driver/FW] Enhance the log function (xlog)
35 * [WCXRP00000732] [MT6620 Wi-Fi][AIS] No need to switch back to IDLE state when DEAUTH frame is dropped due to bss disconnection
36 * when TX DONE status is TX_RESULT_DROPPED_IN_DRIVER, no need to switch back to IDLE state.
38 * 04 12 2011 eddie.chen
39 * [WCXRP00000617] [MT6620 Wi-Fi][DRV/FW] Fix for sigma
40 * Fix the sta index in processing security frame
41 * Simple flow control for TC4 to avoid mgt frames for PS STA to occupy the TC4
45 * [WCXRP00000631] [MT6620 Wi-Fi][Driver] Add an API for QM to retrieve current TC counter value and processing frame dropping cases for TC4 path
46 * remove unused variables.
49 * [WCXRP00000631] [MT6620 Wi-Fi][Driver] Add an API for QM to retrieve current TC counter value and processing frame dropping cases for TC4 path
50 * 1. add nicTxGetResource() API for QM to make decisions.
51 * 2. if management frames is decided by QM for dropping, the call back is invoked to indicate such a case.
54 * [WCXRP00000562] [MT6620 Wi-Fi][Driver] I/O buffer pre-allocation to avoid physically continuous memory shortage after system running for a long period
55 * use pre-allocated buffer for storing enhanced interrupt response as well
58 * [WCXRP00000559] [MT6620 Wi-Fi][Driver] Combine TX/RX DMA buffers into a single one to reduce physically continuous memory consumption
59 * 1. deprecate CFG_HANDLE_IST_IN_SDIO_CALLBACK
60 * 2. Use common coalescing buffer for both TX/RX directions
64 * [WCXRP00000449] [MT6620 Wi-Fi][Driver] Refine CMD queue handling by adding an extra API for checking availble count and modify behavior
65 * 1. add new API: nicTxGetFreeCmdCount()
66 * 2. when there is insufficient command descriptor, nicTxEnqueueMsdu() will drop command packets directly
69 * [WCXRP00000382] [MT6620 Wi-Fi][Driver] Track forwarding packet number with notifying tx thread for serving
70 * 1. add an extra counter for tracking pending forward frames.
71 * 2. notify TX service thread as well when there is pending forward frame
72 * 3. correct build errors leaded by introduction of Wi-Fi direct separation module
75 * [WCXRP00000356] [MT6620 Wi-Fi][Driver] fill mac header length for security frames 'cause hardware header translation needs such information
76 * fill mac header length information for 802.1x frames.
79 * [WCXRP00000335] [MT6620 Wi-Fi][Driver] change to use milliseconds sleep instead of delay to avoid blocking to system scheduling
80 * change to use msleep() and shorten waiting interval to reduce blocking to other task while Wi-Fi driver is being loaded
82 * 11 01 2010 yarco.yang
83 * [WCXRP00000149] [MT6620 WI-Fi][Driver]Fine tune performance on MT6516 platform
84 * Add GPIO debug function
87 * [WCXRP00000117] [MT6620 Wi-Fi][Driver] Add logic for suspending driver when MT6620 is not responding anymore
88 * 1. when wlanAdapterStop() failed to send POWER CTRL command to firmware, do not poll for ready bit dis-assertion
89 * 2. shorten polling count for shorter response time
90 * 3. if bad I/O operation is detected during TX resource polling, then further operation is aborted as well
93 * [WCXRP00000052] [MT6620 Wi-Fi][Driver] Eliminate Linux Compile Warning
94 * code reorganization to improve isolation between GLUE and CORE layers.
97 * [WCXRP00000072] [MT6620 Wi-Fi][Driver] Fix TKIP Counter Measure EAPoL callback register issue
98 * [MT6620 Wi-Fi][Driver] Fix TKIP Counter Measure EAPoL callback register issue.
102 * since the u2TxByteCount_UserPriority will or another setting, keep the overall buffer for avoid error
106 * [WCXRP000000058][MT6620 Wi-Fi][Driver] Fail to handshake with WAPI AP due the 802.1x frame send to fw with extra bytes padding.
110 * HIFSYS Clock Source Workaround
114 * API added: nicTxPendingPackets(), for simplifying porting layer
118 * eliminate klockwork errors
122 * adding the eapol callback setting.
124 * 08 18 2010 yarco.yang
126 * 1. Fixed HW checksum offload function not work under Linux issue.
127 * 2. Add debug message.
129 * 08 05 2010 yuche.tsai
135 * surpress compilation warning.
137 * 08 02 2010 jeffrey.chang
139 * 1) modify tx service thread to avoid busy looping
140 * 2) add spin lock declartion for linux build
144 * simplify post-handling after TX_DONE interrupt is handled.
146 * 07 19 2010 jeffrey.chang
148 * Linux port modification
152 * 1) MMPDUs are now sent to MT6620 by CMD queue for keeping strict order of 1X/MMPDU/CMD packets
153 * 2) integrate with qmGetFrameAction() for deciding which MMPDU/1X could pass checking for sending
154 * 2) enhance CMD_INFO_T descriptor number from 10 to 32 to avoid descriptor underflow under concurrent network operation
158 * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository.
160 * 06 29 2010 yarco.yang
161 * [WPD00003837][MT6620]Data Path Refine
162 * replace g_rQM with Adpater->rQM
165 * [WPD00003833][MT6620 and MT5931] Driver migration
166 * add API in que_mgt to retrieve sta-rec index for security frames.
169 * [WPD00003833][MT6620 and MT5931] Driver migration
170 * 802.1x and bluetooth-over-Wi-Fi security frames are now delievered to firmware via command path instead of data path.
172 * 06 23 2010 yarco.yang
173 * [WPD00003837][MT6620]Data Path Refine
174 * Merge g_arStaRec[] into adapter->arStaRec[]
177 * [WPD00003833][MT6620 and MT5931] Driver migration
178 * 1) add command warpper for STA-REC/BSS-INFO sync.
179 * 2) enhance command packet sending procedure for non-oid part
180 * 3) add command packet definitions for STA-REC/BSS-INFO sync.
183 * [WPD00003833][MT6620 and MT5931] Driver migration
184 * add checking for TX descriptor poll.
187 * [WPD00003833][MT6620 and MT5931] Driver migration
188 * TX descriptors are now allocated once for reducing allocation overhead
190 * 06 18 2010 cm.chang
191 * [WPD00003841][LITE Driver] Migrate RLM/CNM to host driver
192 * Provide cnmMgtPktAlloc() and alloc/free function of msg/buf
195 * [WPD00003833][MT6620 and MT5931] Driver migration
196 * change zero-padding for TX port access to HAL.
199 * [WPD00003833][MT6620 and MT5931] Driver migration
203 * [WPD00003833][MT6620 and MT5931] Driver migration
207 * [WPD00003833][MT6620 and MT5931] Driver migration
208 * fill extra information for revised HIF_TX_HEADER.
211 * [WPD00003833][MT6620 and MT5931] Driver migration
212 * 1) migrate assoc.c.
213 * 2) add ucTxSeqNum for tracking frames which needs TX-DONE awareness
214 * 3) add configuration options for CNM_MEM and RSN modules
215 * 4) add data path for management frames
216 * 5) eliminate rPacketInfo of MSDU_INFO_T
219 * [WPD00003833][MT6620 and MT5931] Driver migration
220 * change to enqueue TX frame infinitely.
223 * [WPD00003833][MT6620 and MT5931] Driver migration
224 * add TX_PACKET_MGMT to indicate the frame is coming from management modules
226 * 06 06 2010 kevin.huang
227 * [WPD00003832][MT6620 5931] Create driver base
228 * [MT6620 5931] Create driver base
231 * [WPD00003831][MT6620 Wi-Fi] Add framework for Wi-Fi Direct support
232 * fill network type field while doing frame identification.
235 * [WPD00001943]Create WiFi test driver framework on WinXP
236 * surpress compiler warning
238 * 04 06 2010 jeffrey.chang
239 * [WPD00003826]Initial import for Linux port
240 * Tag the packet for QoS on Tx path
243 * [WPD00001943]Create WiFi test driver framework on WinXP
244 * remove driver-land statistics.
246 * 03 29 2010 jeffrey.chang
247 * [WPD00003826]Initial import for Linux port
248 * improve none-glue code portability
250 * 03 24 2010 jeffrey.chang
251 * [WPD00003826]Initial import for Linux port
252 * initial import for Linux port
255 * [WPD00001943]Create WiFi test driver framework on WinXP
256 * generate information for OID_GEN_RCV_OK & OID_GEN_XMIT_OK
260 * [WPD00001943]Create WiFi test driver framework on WinXP
261 * code clean: removing unused variables and structure definitions
264 * [WPD00001943]Create WiFi test driver framework on WinXP
265 * 1) add another spin-lock to protect MsduInfoList due to it might be accessed by different thread.
266 * * * * 2) change own-back acquiring procedure to wait for up to 16.67 seconds
269 * [WPD00001943]Create WiFi test driver framework on WinXP
270 * add mutex to avoid multiple access to qmTxQueue simultaneously.
273 * [WPD00001943]Create WiFi test driver framework on WinXP
274 * avoid refering to NDIS-specific data structure directly from non-glue layer.
277 * [WPD00001943]Create WiFi test driver framework on WinXP
278 * add Ethernet destination address information in packet info for TX
281 * [WPD00001943]Create WiFi test driver framework on WinXP
282 * 1) remove unused function in nic_rx.c [which has been handled in que_mgt.c]
283 * * * * * * 2) firmware image length is now retrieved via NdisFileOpen
284 * * * * * * 3) firmware image is not structured by (P_IMG_SEC_HDR_T) anymore
285 * * * * * * 4) nicRxWaitResponse() revised
286 * * * * * * 5) another set of TQ counter default value is added for fw-download state
287 * * * * * * 6) Wi-Fi load address is now retrieved from registry too
290 * [WPD00001943]Create WiFi test driver framework on WinXP
291 * 1. Permanent and current MAC address are now retrieved by CMD/EVENT packets instead of hard-coded address
292 * * * * * * * * * 2. follow MSDN defined behavior when associates to another AP
293 * * * * * * * * * 3. for firmware download, packet size could be up to 2048 bytes
296 * [WPD00001943]Create WiFi test driver framework on WinXP
297 * prepare for implementing fw download logic
300 * [WPD00001943]Create WiFi test driver framework on WinXP
301 * 1. eliminate improper variable in rHifInfo
302 * * * * * * * * * 2. block TX/ordinary OID when RF test mode is engaged
303 * * * * * * * * * 3. wait until firmware finish operation when entering into and leaving from RF test mode
304 * * * * * * * * * 4. correct some HAL implementation
306 * 01 13 2010 tehuang.liu
307 * [WPD00001943]Create WiFi test driver framework on WinXP
308 * Enabled the Burst_End Indication mechanism
311 * [WPD00001943]Create WiFi test driver framework on WinXP
312 * TX: fill ucWlanHeaderLength/ucPktFormtId_Flags according to info provided by prMsduInfo
315 * [WPD00001943]Create WiFi test driver framework on WinXP
316 * 1) According to CMD/EVENT documentation v0.8,
317 * * * * * * * * * * OID_CUSTOM_TEST_RX_STATUS & OID_CUSTOM_TEST_TX_STATUS is no longer used,
318 * * * * * * * * * * and result is retrieved by get ATInfo instead
319 * * * * * * * * * * 2) add 4 counter for recording aggregation statistics
320 ** \main\maintrunk.MT6620WiFiDriver_Prj\44 2009-12-10 16:52:15 GMT mtk02752
322 ** \main\maintrunk.MT6620WiFiDriver_Prj\43 2009-12-07 22:44:24 GMT mtk02752
323 ** correct assertion criterion
324 ** \main\maintrunk.MT6620WiFiDriver_Prj\42 2009-12-07 21:15:52 GMT mtk02752
325 ** correct trivial mistake
326 ** \main\maintrunk.MT6620WiFiDriver_Prj\41 2009-12-04 15:47:21 GMT mtk02752
327 ** + always append a dword of zero on TX path to avoid TX aggregation to triggered on uninitialized data
328 ** + add more assertion for packet size check
329 ** \main\maintrunk.MT6620WiFiDriver_Prj\40 2009-12-04 14:51:55 GMT mtk02752
330 ** nicTxMsduInfo(): save ptr for next entry before attaching to qDataPort
331 ** \main\maintrunk.MT6620WiFiDriver_Prj\39 2009-12-04 11:54:54 GMT mtk02752
332 ** add 2 assertion for size check
333 ** \main\maintrunk.MT6620WiFiDriver_Prj\38 2009-12-03 16:20:35 GMT mtk01461
335 ** \main\maintrunk.MT6620WiFiDriver_Prj\37 2009-11-30 10:57:10 GMT mtk02752
336 ** 1st DW of WIFI_CMD_T is shared with HIF_TX_HEADER_T
337 ** \main\maintrunk.MT6620WiFiDriver_Prj\36 2009-11-30 09:20:43 GMT mtk02752
338 ** use TC4 instead of TC5 for command packet
339 ** \main\maintrunk.MT6620WiFiDriver_Prj\35 2009-11-27 11:08:11 GMT mtk02752
340 ** add flush for reset
341 ** \main\maintrunk.MT6620WiFiDriver_Prj\34 2009-11-26 20:31:22 GMT mtk02752
342 ** fill prMsduInfo->ucUserPriority
343 ** \main\maintrunk.MT6620WiFiDriver_Prj\33 2009-11-25 21:04:33 GMT mtk02752
345 ** \main\maintrunk.MT6620WiFiDriver_Prj\32 2009-11-24 20:52:12 GMT mtk02752
346 ** integration with SD1's data path API
347 ** \main\maintrunk.MT6620WiFiDriver_Prj\31 2009-11-24 19:54:25 GMT mtk02752
348 ** nicTxRetransmitOfOsSendQue & nicTxData but changed to use nicTxMsduInfoList
349 ** \main\maintrunk.MT6620WiFiDriver_Prj\30 2009-11-23 17:53:18 GMT mtk02752
350 ** add nicTxCmd() for SD1_SD3_DATAPATH_INTEGRATION, which will append only HIF_TX_HEADER. seqNum, WIFI_CMD_T will be created inside oid handler
351 ** \main\maintrunk.MT6620WiFiDriver_Prj\29 2009-11-20 15:10:24 GMT mtk02752
352 ** use TxAccquireResource instead of accessing TCQ directly.
353 ** \main\maintrunk.MT6620WiFiDriver_Prj\28 2009-11-17 22:40:57 GMT mtk01084
354 ** \main\maintrunk.MT6620WiFiDriver_Prj\27 2009-11-17 17:35:40 GMT mtk02752
355 ** add nicTxMsduInfoList () implementation
356 ** \main\maintrunk.MT6620WiFiDriver_Prj\26 2009-11-17 11:07:10 GMT mtk02752
357 ** add nicTxAdjustTcq() implementation
358 ** \main\maintrunk.MT6620WiFiDriver_Prj\25 2009-11-16 22:28:38 GMT mtk02752
359 ** move aucFreeBufferCount/aucMaxNumOfBuffer into another structure
360 ** \main\maintrunk.MT6620WiFiDriver_Prj\24 2009-11-16 21:45:32 GMT mtk02752
361 ** add SD1_SD3_DATAPATH_INTEGRATION data path handling
362 ** \main\maintrunk.MT6620WiFiDriver_Prj\23 2009-11-13 13:29:56 GMT mtk01084
363 ** modify TX hdr format, fix tx retransmission issue
364 ** \main\maintrunk.MT6620WiFiDriver_Prj\22 2009-11-11 10:36:21 GMT mtk01084
365 ** \main\maintrunk.MT6620WiFiDriver_Prj\21 2009-11-04 14:11:11 GMT mtk01084
366 ** modify TX SW data structure
367 ** \main\maintrunk.MT6620WiFiDriver_Prj\20 2009-10-29 19:56:17 GMT mtk01084
369 ** \main\maintrunk.MT6620WiFiDriver_Prj\19 2009-10-13 21:59:23 GMT mtk01084
370 ** update for new HW design
371 ** \main\maintrunk.MT6620WiFiDriver_Prj\18 2009-10-02 14:00:18 GMT mtk01725
372 ** \main\maintrunk.MT6620WiFiDriver_Prj\17 2009-05-20 12:26:06 GMT mtk01461
373 ** Assign SeqNum to CMD Packet
374 ** \main\maintrunk.MT6620WiFiDriver_Prj\16 2009-05-19 10:54:04 GMT mtk01461
376 ** \main\maintrunk.MT6620WiFiDriver_Prj\15 2009-05-12 09:41:55 GMT mtk01461
377 ** Fix Query Command need resp issue
378 ** \main\maintrunk.MT6620WiFiDriver_Prj\14 2009-04-29 15:44:38 GMT mtk01461
379 ** Move OS dependent code to kalQueryTxOOBData()
380 ** \main\maintrunk.MT6620WiFiDriver_Prj\13 2009-04-28 10:40:03 GMT mtk01461
381 ** Add nicTxReleaseResource() for SDIO_STATUS_ENHANCE, and also fix the TX aggregation issue for 1x packet to TX1 port
382 ** \main\maintrunk.MT6620WiFiDriver_Prj\12 2009-04-21 09:50:47 GMT mtk01461
383 ** Update nicTxCmd() for moving wait RESP function call to wlanSendCommand()
384 ** \main\maintrunk.MT6620WiFiDriver_Prj\11 2009-04-17 19:56:32 GMT mtk01461
385 ** Move the CMD_INFO_T related function to cmd_buf.c
386 ** \main\maintrunk.MT6620WiFiDriver_Prj\10 2009-04-17 18:14:40 GMT mtk01426
387 ** Update OOB query for TX packet
388 ** \main\maintrunk.MT6620WiFiDriver_Prj\9 2009-04-14 15:51:32 GMT mtk01426
390 ** \main\maintrunk.MT6620WiFiDriver_Prj\8 2009-04-02 17:26:40 GMT mtk01461
391 ** Add virtual OOB for HIF LOOPBACK SW PRETEST
392 ** \main\maintrunk.MT6620WiFiDriver_Prj\7 2009-04-01 10:54:43 GMT mtk01461
393 ** Add function for SDIO_TX_ENHANCE
394 ** \main\maintrunk.MT6620WiFiDriver_Prj\6 2009-03-23 21:53:47 GMT mtk01461
395 ** Add code for retransmit of rOsSendQueue, mpSendPacket(), and add code for TX Checksum offload, Loopback Test.
396 ** \main\maintrunk.MT6620WiFiDriver_Prj\5 2009-03-23 00:33:51 GMT mtk01461
397 ** Add code for TX Data & Cmd Packet
398 ** \main\maintrunk.MT6620WiFiDriver_Prj\4 2009-03-18 20:25:40 GMT mtk01461
400 ** \main\maintrunk.MT6620WiFiDriver_Prj\3 2009-03-16 09:10:30 GMT mtk01461
401 ** Update TX PATH API
402 ** \main\maintrunk.MT6620WiFiDriver_Prj\2 2009-03-10 20:26:04 GMT mtk01426
407 /*******************************************************************************
408 * C O M P I L E R F L A G S
409 ********************************************************************************
412 /*******************************************************************************
413 * E X T E R N A L R E F E R E N C E S
414 ********************************************************************************
418 /*******************************************************************************
420 ********************************************************************************
423 /*******************************************************************************
425 ********************************************************************************
428 /*******************************************************************************
429 * P U B L I C D A T A
430 ********************************************************************************
433 /*******************************************************************************
434 * P R I V A T E D A T A
435 ********************************************************************************
438 /*******************************************************************************
440 ********************************************************************************
443 /*******************************************************************************
444 * F U N C T I O N D E C L A R A T I O N S
445 ********************************************************************************
448 /*******************************************************************************
450 ********************************************************************************
452 /*----------------------------------------------------------------------------*/
454 * @brief This function will initial all variables in regard to SW TX Queues and
455 * all free lists of MSDU_INFO_T and SW_TFCB_T.
457 * @param prAdapter Pointer to the Adapter structure.
461 /*----------------------------------------------------------------------------*/
464 IN P_ADAPTER_T prAdapter
467 P_TX_CTRL_T prTxCtrl;
468 PUINT_8 pucMemHandle;
469 P_MSDU_INFO_T prMsduInfo;
471 KAL_SPIN_LOCK_DECLARATION();
473 DEBUGFUNC("nicTxInitialize");
476 prTxCtrl = &prAdapter->rTxCtrl;
478 //4 <1> Initialization of Traffic Class Queue Parameters
479 nicTxResetResource(prAdapter);
482 prTxCtrl->pucTxCoalescingBufPtr = prAdapter->pucCoalescingBufCached;
483 #endif /* CFG_SDIO_TX_AGG */
485 // allocate MSDU_INFO_T and link it into rFreeMsduInfoList
486 QUEUE_INITIALIZE(&prTxCtrl->rFreeMsduInfoList);
488 pucMemHandle = prTxCtrl->pucTxCached;
489 for (i = 0 ; i < CFG_TX_MAX_PKT_NUM ; i++) {
490 prMsduInfo = (P_MSDU_INFO_T)pucMemHandle;
491 kalMemZero(prMsduInfo, sizeof(MSDU_INFO_T));
493 KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_MSDU_INFO_LIST);
494 QUEUE_INSERT_TAIL(&prTxCtrl->rFreeMsduInfoList, (P_QUE_ENTRY_T)prMsduInfo);
495 KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_MSDU_INFO_LIST);
497 pucMemHandle += ALIGN_4(sizeof(MSDU_INFO_T));
500 ASSERT(prTxCtrl->rFreeMsduInfoList.u4NumElem == CFG_TX_MAX_PKT_NUM);
501 /* Check if the memory allocation consist with this initialization function */
502 ASSERT((UINT_32)(pucMemHandle - prTxCtrl->pucTxCached) == prTxCtrl->u4TxCachedSize);
504 QUEUE_INITIALIZE(&prTxCtrl->rTxMgmtTxingQueue);
505 prTxCtrl->i4TxMgmtPendingNum = 0;
507 #if CFG_HIF_STATISTICS
508 prTxCtrl->u4TotalTxAccessNum = 0;
509 prTxCtrl->u4TotalTxPacketNum = 0;
512 prTxCtrl->i4PendingFwdFrameCount = 0;
516 TX_RESET_ALL_CNTS(prTxCtrl);
519 } /* end of nicTxInitialize() */
522 /*----------------------------------------------------------------------------*/
524 * \brief Driver maintain a variable that is synchronous with the usage of individual
525 * TC Buffer Count. This function will check if has enough TC Buffer for incoming
526 * packet and then update the value after promise to provide the resources.
528 * \param[in] prAdapter Pointer to the Adapter structure.
529 * \param[in] ucTC Specify the resource of TC
531 * \retval WLAN_STATUS_SUCCESS Resource is available and been assigned.
532 * \retval WLAN_STATUS_RESOURCES Resource is not available.
534 /*----------------------------------------------------------------------------*/
536 nicTxAcquireResource (
537 IN P_ADAPTER_T prAdapter,
541 P_TX_CTRL_T prTxCtrl;
542 WLAN_STATUS u4Status = WLAN_STATUS_RESOURCES;
543 KAL_SPIN_LOCK_DECLARATION();
546 prTxCtrl = &prAdapter->rTxCtrl;
549 KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_RESOURCE);
551 // DbgPrint("nicTxAcquireResource prTxCtrl->rTc.aucFreeBufferCount[%d]=%d\n", ucTC, prTxCtrl->rTc.aucFreeBufferCount[ucTC]);
553 if (prTxCtrl->rTc.aucFreeBufferCount[ucTC]) {
555 prTxCtrl->rTc.aucFreeBufferCount[ucTC]--;
557 DBGLOG(TX, EVENT, ("Acquire: TC = %d aucFreeBufferCount = %d\n",
558 ucTC, prTxCtrl->rTc.aucFreeBufferCount[ucTC]));
560 u4Status = WLAN_STATUS_SUCCESS;
562 KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_RESOURCE);
566 }/* end of nicTxAcquireResourceAndTFCBs() */
569 /*----------------------------------------------------------------------------*/
571 * @brief Driver maintain a variable that is synchronous with the usage of individual
572 * TC Buffer Count. This function will do polling if FW has return the resource.
573 * Used when driver start up before enable interrupt.
575 * @param prAdapter Pointer to the Adapter structure.
576 * @param ucTC Specify the resource of TC
578 * @retval WLAN_STATUS_SUCCESS Resource is available.
579 * @retval WLAN_STATUS_FAILURE Resource is not available.
581 /*----------------------------------------------------------------------------*/
583 nicTxPollingResource (
584 IN P_ADAPTER_T prAdapter,
588 P_TX_CTRL_T prTxCtrl;
589 WLAN_STATUS u4Status = WLAN_STATUS_FAILURE;
590 INT_32 i = NIC_TX_RESOURCE_POLLING_TIMEOUT;
594 prTxCtrl = &prAdapter->rTxCtrl;
596 if (ucTC >= TC_NUM) {
597 return WLAN_STATUS_FAILURE;
600 if (prTxCtrl->rTc.aucFreeBufferCount[ucTC] > 0) {
601 return WLAN_STATUS_SUCCESS;
605 HAL_READ_TX_RELEASED_COUNT(prAdapter, au4WTSR);
607 if(kalIsCardRemoved(prAdapter->prGlueInfo) == TRUE
608 || fgIsBusAccessFailed == TRUE) {
609 u4Status = WLAN_STATUS_FAILURE;
612 else if (nicTxReleaseResource(prAdapter, (PUINT_8)au4WTSR)) {
613 if (prTxCtrl->rTc.aucFreeBufferCount[ucTC] > 0) {
614 u4Status = WLAN_STATUS_SUCCESS;
618 kalMsleep(NIC_TX_RESOURCE_POLLING_DELAY_MSEC);
622 kalMsleep(NIC_TX_RESOURCE_POLLING_DELAY_MSEC);
628 INT_32 i4Times = NIC_TX_RESOURCE_POLLING_TIMEOUT - (i+1);
631 DBGLOG(TX, TRACE, ("Polling MCR_WTSR delay %d times, %d msec\n",
632 i4Times, (i4Times * NIC_TX_RESOURCE_POLLING_DELAY_MSEC)));
639 } /* end of nicTxPollingResource() */
642 /*----------------------------------------------------------------------------*/
644 * \brief Driver maintain a variable that is synchronous with the usage of individual
645 * TC Buffer Count. This function will release TC Buffer count according to
646 * the given TX_STATUS COUNTER after TX Done.
648 * \param[in] prAdapter Pointer to the Adapter structure.
649 * \param[in] u4TxStatusCnt Value of TX STATUS
653 /*----------------------------------------------------------------------------*/
655 nicTxReleaseResource (
656 IN P_ADAPTER_T prAdapter,
657 IN UINT_8* aucTxRlsCnt
660 PUINT_32 pu4Tmp = (PUINT_32)aucTxRlsCnt;
661 P_TX_CTRL_T prTxCtrl;
662 BOOLEAN bStatus = FALSE;
665 KAL_SPIN_LOCK_DECLARATION();
669 prTxCtrl = &prAdapter->rTxCtrl;
671 if (pu4Tmp[0] | pu4Tmp[1]) {
673 KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_RESOURCE);
674 for (i = 0; i < TC_NUM; i++) {
675 prTxCtrl->rTc.aucFreeBufferCount[i] += aucTxRlsCnt[i];
677 if ((i==1) || (i==5)){
678 DBGLOG(TX, EVENT, ("Release: i = %d aucFreeBufferCount = %d\n",
679 i, prTxCtrl->rTc.aucFreeBufferCount[i]));
682 KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_RESOURCE);
684 for (i = 0; i < TC_NUM; i++) {
685 DBGLOG(INIT, TRACE, ("aucFreeBufferCount[%d]: %d, aucMaxNumOfBuffer[%d]: %d\n",
686 i, prTxCtrl->rTc.aucFreeBufferCount[i], i, prTxCtrl->rTc.aucMaxNumOfBuffer[i]));
688 DbgPrint("prTxCtrl->rTc.aucFreeBufferCount[0]=%d\n", prTxCtrl->rTc.aucFreeBufferCount[0]);
689 DbgPrint("prTxCtrl->rTc.aucFreeBufferCount[1]=%d\n", prTxCtrl->rTc.aucFreeBufferCount[1]);
690 DbgPrint("prTxCtrl->rTc.aucFreeBufferCount[2]=%d\n", prTxCtrl->rTc.aucFreeBufferCount[2]);
691 DbgPrint("prTxCtrl->rTc.aucFreeBufferCount[3]=%d\n", prTxCtrl->rTc.aucFreeBufferCount[3]);
692 DbgPrint("prTxCtrl->rTc.aucFreeBufferCount[4]=%d\n", prTxCtrl->rTc.aucFreeBufferCount[4]);
693 DbgPrint("prTxCtrl->rTc.aucFreeBufferCount[5]=%d\n", prTxCtrl->rTc.aucFreeBufferCount[5]);
695 ASSERT(prTxCtrl->rTc.aucFreeBufferCount[TC0_INDEX] <= prTxCtrl->rTc.aucMaxNumOfBuffer[TC0_INDEX]);
696 ASSERT(prTxCtrl->rTc.aucFreeBufferCount[TC1_INDEX] <= prTxCtrl->rTc.aucMaxNumOfBuffer[TC1_INDEX]);
697 ASSERT(prTxCtrl->rTc.aucFreeBufferCount[TC2_INDEX] <= prTxCtrl->rTc.aucMaxNumOfBuffer[TC2_INDEX]);
698 ASSERT(prTxCtrl->rTc.aucFreeBufferCount[TC3_INDEX] <= prTxCtrl->rTc.aucMaxNumOfBuffer[TC3_INDEX]);
699 ASSERT(prTxCtrl->rTc.aucFreeBufferCount[TC4_INDEX] <= prTxCtrl->rTc.aucMaxNumOfBuffer[TC4_INDEX]);
700 ASSERT(prTxCtrl->rTc.aucFreeBufferCount[TC5_INDEX] <= prTxCtrl->rTc.aucMaxNumOfBuffer[TC5_INDEX]);
705 } /* end of nicTxReleaseResource() */
708 /*----------------------------------------------------------------------------*/
710 * \brief Reset TC Buffer Count to initialized value
712 * \param[in] prAdapter Pointer to the Adapter structure.
714 * @return WLAN_STATUS_SUCCESS
716 /*----------------------------------------------------------------------------*/
719 IN P_ADAPTER_T prAdapter
722 P_TX_CTRL_T prTxCtrl;
724 KAL_SPIN_LOCK_DECLARATION();
726 DEBUGFUNC("nicTxResetResource");
729 prTxCtrl = &prAdapter->rTxCtrl;
731 KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_RESOURCE);
733 prTxCtrl->rTc.aucMaxNumOfBuffer[TC0_INDEX] = NIC_TX_BUFF_COUNT_TC0;
734 prTxCtrl->rTc.aucFreeBufferCount[TC0_INDEX] = NIC_TX_BUFF_COUNT_TC0;
736 prTxCtrl->rTc.aucMaxNumOfBuffer[TC1_INDEX] = NIC_TX_BUFF_COUNT_TC1;
737 prTxCtrl->rTc.aucFreeBufferCount[TC1_INDEX] = NIC_TX_BUFF_COUNT_TC1;
739 prTxCtrl->rTc.aucMaxNumOfBuffer[TC2_INDEX] = NIC_TX_BUFF_COUNT_TC2;
740 prTxCtrl->rTc.aucFreeBufferCount[TC2_INDEX] = NIC_TX_BUFF_COUNT_TC2;
742 prTxCtrl->rTc.aucMaxNumOfBuffer[TC3_INDEX] = NIC_TX_BUFF_COUNT_TC3;
743 prTxCtrl->rTc.aucFreeBufferCount[TC3_INDEX] = NIC_TX_BUFF_COUNT_TC3;
745 prTxCtrl->rTc.aucMaxNumOfBuffer[TC4_INDEX] = NIC_TX_BUFF_COUNT_TC4;
746 prTxCtrl->rTc.aucFreeBufferCount[TC4_INDEX] = NIC_TX_BUFF_COUNT_TC4;
748 prTxCtrl->rTc.aucMaxNumOfBuffer[TC5_INDEX] = NIC_TX_BUFF_COUNT_TC5;
749 prTxCtrl->rTc.aucFreeBufferCount[TC5_INDEX] = NIC_TX_BUFF_COUNT_TC5;
751 KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_RESOURCE);
753 return WLAN_STATUS_SUCCESS;
757 /*----------------------------------------------------------------------------*/
759 * @brief Driver maintain a variable that is synchronous with the usage of individual
760 * TC Buffer Count. This function will return the value for other component
761 * which needs this information for making decisions
763 * @param prAdapter Pointer to the Adapter structure.
764 * @param ucTC Specify the resource of TC
766 * @retval UINT_8 The number of corresponding TC number
768 /*----------------------------------------------------------------------------*/
771 IN P_ADAPTER_T prAdapter,
775 P_TX_CTRL_T prTxCtrl;
778 prTxCtrl = &prAdapter->rTxCtrl;
782 if (ucTC >= TC_NUM) {
786 return prTxCtrl->rTc.aucFreeBufferCount[ucTC];
791 /*----------------------------------------------------------------------------*/
793 * @brief In this function, we'll aggregate frame(PACKET_INFO_T)
794 * corresponding to HIF TX port
796 * @param prAdapter Pointer to the Adapter structure.
797 * @param prMsduInfoListHead a link list of P_MSDU_INFO_T
799 * @retval WLAN_STATUS_SUCCESS Bus access ok.
800 * @retval WLAN_STATUS_FAILURE Bus access fail.
802 /*----------------------------------------------------------------------------*/
805 IN P_ADAPTER_T prAdapter,
806 IN P_MSDU_INFO_T prMsduInfoListHead
809 P_MSDU_INFO_T prMsduInfo, prNextMsduInfo;
810 QUE_T qDataPort0, qDataPort1;
814 ASSERT(prMsduInfoListHead);
816 prMsduInfo = prMsduInfoListHead;
818 QUEUE_INITIALIZE(&qDataPort0);
819 QUEUE_INITIALIZE(&qDataPort1);
821 // Separate MSDU_INFO_T lists into 2 categories: for Port#0 & Port#1
823 prNextMsduInfo = (P_MSDU_INFO_T)QUEUE_GET_NEXT_ENTRY((P_QUE_ENTRY_T)prMsduInfo);
825 LOG_FUNC("nicTxMsduInfoList Acquire TC %d net %u mac len %u len %u Type %u 1x %u 11 %u\n",
827 prMsduInfo->ucNetworkType,
828 prMsduInfo->ucMacHeaderLength,
829 prMsduInfo->u2FrameLength,
830 prMsduInfo->ucPacketType,
831 prMsduInfo->fgIs802_1x,
832 prMsduInfo->fgIs802_11 );
834 LOG_FUNC("Dest Mac: " MACSTR "\n",
835 MAC2STR(prMsduInfo->aucEthDestAddr));
838 switch(prMsduInfo->ucTC) {
843 case TC5_INDEX: // Broadcast/multicast data packets
844 QUEUE_GET_NEXT_ENTRY((P_QUE_ENTRY_T)prMsduInfo) = NULL;
845 QUEUE_INSERT_TAIL(&qDataPort0, (P_QUE_ENTRY_T)prMsduInfo);
846 status = nicTxAcquireResource(prAdapter, prMsduInfo->ucTC);
847 ASSERT(status == WLAN_STATUS_SUCCESS)
851 case TC4_INDEX: // Command or 802.1x packets
852 QUEUE_GET_NEXT_ENTRY((P_QUE_ENTRY_T)prMsduInfo) = NULL;
853 QUEUE_INSERT_TAIL(&qDataPort1, (P_QUE_ENTRY_T)prMsduInfo);
855 status = nicTxAcquireResource(prAdapter, prMsduInfo->ucTC);
856 ASSERT(status == WLAN_STATUS_SUCCESS)
865 prMsduInfo = prNextMsduInfo;
868 if(qDataPort0.u4NumElem > 0) {
869 nicTxMsduQueue(prAdapter, 0, &qDataPort0);
872 if(qDataPort1.u4NumElem > 0) {
873 nicTxMsduQueue(prAdapter, 1, &qDataPort1);
876 return WLAN_STATUS_SUCCESS;
879 #if CFG_ENABLE_PKT_LIFETIME_PROFILE
881 #if CFG_PRINT_RTP_PROFILE
882 PKT_PROFILE_T rPrevRoundLastPkt;
885 nicTxLifetimePrintCheckRTP (
886 IN P_MSDU_INFO_T prPrevProfileMsduInfo,
887 IN P_PKT_PROFILE_T prPrevRoundLastPkt,
888 IN P_PKT_PROFILE_T prPktProfile,
889 IN OUT PBOOLEAN pfgGotFirst,
890 IN UINT_32 u4MaxDeltaTime,
891 IN UINT_8 ucSnToBePrinted
894 BOOLEAN fgPrintCurPkt = FALSE;
897 //4 1. check delta between current round first pkt and prevous round last pkt
901 if(prPrevRoundLastPkt->fgIsValid) {
902 if(CHK_PROFILES_DELTA(prPktProfile, prPrevRoundLastPkt, u4MaxDeltaTime)) {
903 PRINT_PKT_PROFILE(prPrevRoundLastPkt, "PR");
904 fgPrintCurPkt = TRUE;
909 //4 2. check delta between current pkt and previous pkt
910 if(prPrevProfileMsduInfo) {
911 if(CHK_PROFILES_DELTA(prPktProfile, &prPrevProfileMsduInfo->rPktProfile, u4MaxDeltaTime)) {
912 PRINT_PKT_PROFILE(&prPrevProfileMsduInfo->rPktProfile, "P");
913 fgPrintCurPkt = TRUE;
917 //4 3. check delta of current pkt lifetime
918 if(CHK_PROFILE_DELTA(prPktProfile, u4MaxDeltaTime)) {
919 fgPrintCurPkt = TRUE;
923 //4 4. print every X RTP packets
925 if((ucSnToBePrinted != 0) &&
926 (prPktProfile->u2RtpSn % ucSnToBePrinted) == 0) {
927 fgPrintCurPkt = TRUE;
931 return fgPrintCurPkt;
935 nicTxLifetimePrintCheckRTPSnSkip (
936 IN P_MSDU_INFO_T prPrevProfileMsduInfo,
937 IN P_PKT_PROFILE_T prPrevRoundLastPkt,
938 IN P_PKT_PROFILE_T prPktProfile,
939 IN OUT PBOOLEAN pfgGotFirst
942 BOOLEAN fgPrintCurPkt = FALSE;
943 UINT_16 u2PredictRtpSn = 0;
945 //4 1. check RTP SN between current round first pkt and prevous round last pkt
949 if(prPrevRoundLastPkt->fgIsValid) {
950 u2PredictRtpSn = prPrevRoundLastPkt->u2RtpSn + 1;
951 if(prPktProfile->u2RtpSn != u2PredictRtpSn) {
952 PRINT_PKT_PROFILE(prPrevRoundLastPkt, "PR");
953 fgPrintCurPkt = TRUE;
958 //4 2. check RTP SN between current pkt and previous pkt
959 if(prPrevProfileMsduInfo) {
960 u2PredictRtpSn = prPrevProfileMsduInfo->rPktProfile.u2RtpSn + 1;
961 if(prPktProfile->u2RtpSn != u2PredictRtpSn) {
962 PRINT_PKT_PROFILE(&prPrevProfileMsduInfo->rPktProfile, "P");
963 fgPrintCurPkt = TRUE;
967 return fgPrintCurPkt;
973 nicTxReturnMsduInfoProfiling (
974 IN P_ADAPTER_T prAdapter,
975 IN P_MSDU_INFO_T prMsduInfoListHead
978 P_MSDU_INFO_T prMsduInfo = prMsduInfoListHead, prNextMsduInfo;
979 P_PKT_PROFILE_T prPktProfile;
980 UINT_16 u2MagicCode = 0;
982 #if CFG_PRINT_RTP_PROFILE
983 P_MSDU_INFO_T prPrevProfileMsduInfo = NULL;
984 P_PKT_PROFILE_T prPrevRoundLastPkt = &rPrevRoundLastPkt;
986 BOOLEAN fgPrintCurPkt = FALSE;
987 BOOLEAN fgGotFirst = FALSE;
988 UINT_8 ucSnToBePrinted = 0;
990 UINT_32 u4MaxDeltaTime = 50; // in ms
993 #if CFG_ENABLE_PER_STA_STATISTICS
994 UINT_32 u4PktPrintPeriod = 0;
998 P_WFD_CFG_SETTINGS_T prWfdCfgSettings = (P_WFD_CFG_SETTINGS_T)NULL;
1000 if(prAdapter->fgIsP2PRegistered) {
1001 prWfdCfgSettings = &prAdapter->rWifiVar.prP2pFsmInfo->rWfdConfigureSettings;
1002 u2MagicCode = prWfdCfgSettings->u2WfdMaximumTp;
1003 if(prWfdCfgSettings->ucWfdEnable && (prWfdCfgSettings->u4WfdFlag & BIT(0))) {
1004 u2MagicCode = 0xE040;
1009 #if CFG_PRINT_RTP_PROFILE
1010 if((u2MagicCode >= 0xF000)) {
1011 ucSnToBePrinted = (UINT_8)(u2MagicCode & BITS(0, 7));
1012 u4MaxDeltaTime = (UINT_8)(((u2MagicCode & BITS(8, 11)) >> 8) * 10);
1015 ucSnToBePrinted = 0;
1020 #if CFG_ENABLE_PER_STA_STATISTICS
1021 if((u2MagicCode >= 0xE000) && (u2MagicCode < 0xF000)) {
1022 u4PktPrintPeriod = (UINT_32)((u2MagicCode & BITS(0, 7)) * 32);
1025 u4PktPrintPeriod = 0;
1030 prNextMsduInfo = (P_MSDU_INFO_T)QUEUE_GET_NEXT_ENTRY((P_QUE_ENTRY_T)prMsduInfo);
1031 prPktProfile = &prMsduInfo->rPktProfile;
1033 if(prPktProfile->fgIsValid) {
1035 prPktProfile->rHifTxDoneTimestamp = kalGetTimeTick();
1037 #if CFG_PRINT_RTP_PROFILE
1038 #if CFG_PRINT_RTP_SN_SKIP
1039 fgPrintCurPkt = nicTxLifetimePrintCheckRTPSnSkip(
1040 prPrevProfileMsduInfo,
1045 fgPrintCurPkt = nicTxLifetimePrintCheckRTP(
1046 prPrevProfileMsduInfo,
1054 /* Print current pkt profile */
1056 PRINT_PKT_PROFILE(prPktProfile, "C");
1059 prPrevProfileMsduInfo = prMsduInfo;
1060 fgPrintCurPkt = FALSE;
1063 #if CFG_ENABLE_PER_STA_STATISTICS
1065 P_STA_RECORD_T prStaRec = cnmGetStaRecByIndex(prAdapter, prMsduInfo->ucStaRecIndex);
1066 UINT_32 u4DeltaTime;
1067 P_QUE_MGT_T prQM = &prAdapter->rQM;
1070 u4DeltaTime = (UINT_32)(prPktProfile->rHifTxDoneTimestamp - prPktProfile->rHardXmitArrivalTimestamp);
1072 prStaRec->u4TotalTxPktsNumber++;
1073 prStaRec->u4TotalTxPktsTime += u4DeltaTime;
1074 if(u4DeltaTime > prStaRec->u4MaxTxPktsTime) {
1075 prStaRec->u4MaxTxPktsTime = u4DeltaTime;
1077 if(u4DeltaTime >= NIC_TX_TIME_THRESHOLD) {
1078 prStaRec->u4ThresholdCounter++;
1081 if(u4PktPrintPeriod && (prStaRec->u4TotalTxPktsNumber >= u4PktPrintPeriod)) {
1083 DBGLOG(TX, TRACE, ("N[%4lu] A[%5lu] M[%4lu] T[%4lu] E[%4lu]\n",
1084 prStaRec->u4TotalTxPktsNumber,
1085 (prStaRec->u4TotalTxPktsTime/prStaRec->u4TotalTxPktsNumber),
1086 prStaRec->u4MaxTxPktsTime,
1087 prStaRec->u4ThresholdCounter,
1088 prQM->au4QmTcResourceEmptyCounter[prStaRec->ucNetTypeIndex][TC2_INDEX]));
1090 prStaRec->u4TotalTxPktsNumber = 0;
1091 prStaRec->u4TotalTxPktsTime = 0;
1092 prStaRec->u4MaxTxPktsTime = 0;
1093 prStaRec->u4ThresholdCounter = 0;
1094 prQM->au4QmTcResourceEmptyCounter[prStaRec->ucNetTypeIndex][TC2_INDEX] = 0;
1102 prMsduInfo = prNextMsduInfo;
1105 #if CFG_PRINT_RTP_PROFILE
1106 //4 4. record the lifetime of current round last pkt
1107 if(prPrevProfileMsduInfo) {
1108 prPktProfile = &prPrevProfileMsduInfo->rPktProfile;
1109 prPrevRoundLastPkt->u2IpSn = prPktProfile->u2IpSn;
1110 prPrevRoundLastPkt->u2RtpSn = prPktProfile->u2RtpSn;
1111 prPrevRoundLastPkt->rHardXmitArrivalTimestamp = prPktProfile->rHardXmitArrivalTimestamp;
1112 prPrevRoundLastPkt->rEnqueueTimestamp = prPktProfile->rEnqueueTimestamp;
1113 prPrevRoundLastPkt->rDequeueTimestamp = prPktProfile->rDequeueTimestamp;
1114 prPrevRoundLastPkt->rHifTxDoneTimestamp = prPktProfile->rHifTxDoneTimestamp;
1115 prPrevRoundLastPkt->ucTcxFreeCount = prPktProfile->ucTcxFreeCount;
1116 prPrevRoundLastPkt->fgIsPrinted = prPktProfile->fgIsPrinted;
1117 prPrevRoundLastPkt->fgIsValid = TRUE;
1121 nicTxReturnMsduInfo(prAdapter, prMsduInfoListHead);
1128 nicTxLifetimeRecordEn (
1129 IN P_ADAPTER_T prAdapter,
1130 IN P_MSDU_INFO_T prMsduInfo,
1131 IN P_NATIVE_PACKET prPacket
1134 P_PKT_PROFILE_T prPktProfile = &prMsduInfo->rPktProfile;
1136 /* Enable packet lifetime profiling */
1137 prPktProfile->fgIsValid = TRUE;
1139 /* Packet arrival time at kernel Hard Xmit */
1140 prPktProfile->rHardXmitArrivalTimestamp = GLUE_GET_PKT_ARRIVAL_TIME(prPacket);
1142 /* Packet enqueue time */
1143 prPktProfile->rEnqueueTimestamp = (OS_SYSTIME)kalGetTimeTick();
1147 #if CFG_PRINT_RTP_PROFILE
1150 data RTP packet pointer
1153 0:audio 1: video, -1:none
1155 UINT8 checkRtpAV(PUINT_8 data, UINT_32 size)
1157 PUINT_8 buf = data+12;
1158 while (buf+188 <= data+size) {
1159 int pid = ((buf[1] << 8 ) & 0x1F00) | (buf[2] & 0xFF);
1160 if (pid == 0 || pid == 0x100 || pid == 0x1000) {
1163 else if (pid == 0x1100){
1166 else if (pid == 0x1011){
1174 nicTxLifetimeCheckRTP (
1175 IN P_ADAPTER_T prAdapter,
1176 IN P_MSDU_INFO_T prMsduInfo,
1177 IN P_NATIVE_PACKET prPacket,
1178 IN UINT_32 u4PacketLen,
1179 IN UINT_8 ucNetworkType
1182 struct sk_buff *prSkb = (struct sk_buff *) prPacket;
1183 UINT_16 u2EtherTypeLen;
1184 PUINT_8 aucLookAheadBuf = NULL;
1185 P_PKT_PROFILE_T prPktProfile = &prMsduInfo->rPktProfile;
1187 //UINT_8 ucRtpHdrOffset = 28;
1188 UINT_8 ucRtpSnOffset = 30;
1189 //UINT_32 u4RtpSrcPort = 15550;
1190 P_TX_CTRL_T prTxCtrl;
1192 P_WFD_CFG_SETTINGS_T prWfdCfgSettings = (P_WFD_CFG_SETTINGS_T)NULL;
1193 BOOLEAN fgEnProfiling = FALSE;
1195 if(prAdapter->fgIsP2PRegistered) {
1196 prWfdCfgSettings = &prAdapter->rWifiVar.prP2pFsmInfo->rWfdConfigureSettings;
1198 #if CFG_PRINT_RTP_SN_SKIP
1199 if(ucNetworkType == NETWORK_TYPE_P2P_INDEX) {
1200 fgEnProfiling = TRUE;
1204 if((prWfdCfgSettings->u2WfdMaximumTp >= 0xF000) &&
1205 (ucNetworkType == NETWORK_TYPE_P2P_INDEX)) {
1206 fgEnProfiling = TRUE;
1210 if(fgEnProfiling == FALSE) {
1211 //prPktProfile->fgIsValid = FALSE;
1216 prTxCtrl = &prAdapter->rTxCtrl;
1217 //prPktProfile->fgIsValid = FALSE;
1219 aucLookAheadBuf = prSkb->data;
1221 u2EtherTypeLen = (aucLookAheadBuf[ETH_TYPE_LEN_OFFSET] << 8) | (aucLookAheadBuf[ETH_TYPE_LEN_OFFSET + 1]);
1223 if ((u2EtherTypeLen == ETH_P_IP) &&
1224 (u4PacketLen >= LOOK_AHEAD_LEN)) {
1225 PUINT_8 pucIpHdr = &aucLookAheadBuf[ETH_HLEN];
1228 ucIpVersion = (pucIpHdr[0] & IPVH_VERSION_MASK) >> IPVH_VERSION_OFFSET;
1229 if (ucIpVersion == IPVERSION) {
1230 if(pucIpHdr[IPV4_HDR_IP_PROTOCOL_OFFSET] == IP_PROTOCOL_UDP) {
1232 //if(checkRtpAV(&pucIpHdr[ucRtpHdrOffset], (u4PacketLen - ETH_HLEN - ucRtpHdrOffset)) == 0) {
1234 if(prPktProfile->fgIsValid == FALSE) {
1235 nicTxLifetimeRecordEn(prAdapter, prMsduInfo, prPacket);
1238 prPktProfile->fgIsPrinted = FALSE;
1240 prPktProfile->ucTcxFreeCount = prTxCtrl->rTc.aucFreeBufferCount[TC2_INDEX];
1243 prPktProfile->u2RtpSn = pucIpHdr[ucRtpSnOffset] << 8 | pucIpHdr[ucRtpSnOffset + 1];
1246 prPktProfile->u2IpSn = pucIpHdr[IPV4_HDR_IP_IDENTIFICATION_OFFSET] << 8 |
1247 pucIpHdr[IPV4_HDR_IP_IDENTIFICATION_OFFSET + 1];
1256 #if CFG_ENABLE_PER_STA_STATISTICS
1258 nicTxLifetimeCheckByAC (
1259 IN P_ADAPTER_T prAdapter,
1260 IN P_MSDU_INFO_T prMsduInfo,
1261 IN P_NATIVE_PACKET prPacket,
1262 IN UINT_8 ucPriorityParam
1265 switch(ucPriorityParam){
1281 nicTxLifetimeRecordEn(prAdapter, prMsduInfo, prPacket);
1291 nicTxLifetimeCheck (
1292 IN P_ADAPTER_T prAdapter,
1293 IN P_MSDU_INFO_T prMsduInfo,
1294 IN P_NATIVE_PACKET prPacket,
1295 IN UINT_8 ucPriorityParam,
1296 IN UINT_32 u4PacketLen,
1297 IN UINT_8 ucNetworkType
1300 P_PKT_PROFILE_T prPktProfile = &prMsduInfo->rPktProfile;
1302 /* Reset packet profile */
1303 prPktProfile->fgIsValid = FALSE;
1305 #if CFG_ENABLE_PER_STA_STATISTICS
1306 nicTxLifetimeCheckByAC(prAdapter, prMsduInfo, prPacket, ucPriorityParam);
1309 #if CFG_PRINT_RTP_PROFILE
1310 nicTxLifetimeCheckRTP(prAdapter, prMsduInfo, prPacket, u4PacketLen, ucNetworkType);
1318 /*----------------------------------------------------------------------------*/
1320 * @brief In this function, we'll write frame(PACKET_INFO_T) into HIF.
1322 * @param prAdapter Pointer to the Adapter structure.
1323 * @param ucPortIdx Port Number
1324 * @param prQue a link list of P_MSDU_INFO_T
1326 * @retval WLAN_STATUS_SUCCESS Bus access ok.
1327 * @retval WLAN_STATUS_FAILURE Bus access fail.
1329 /*----------------------------------------------------------------------------*/
1332 IN P_ADAPTER_T prAdapter,
1337 P_MSDU_INFO_T prMsduInfo, prNextMsduInfo;
1338 HIF_TX_HEADER_T rHwTxHeader;
1339 P_NATIVE_PACKET prNativePacket;
1340 UINT_16 u2OverallBufferLength;
1341 UINT_8 ucEtherTypeOffsetInWord;
1342 PUINT_8 pucOutputBuf = (PUINT_8)NULL; /* Pointer to Transmit Data Structure Frame */
1343 UINT_32 u4TxHdrSize;
1344 UINT_32 u4ValidBufSize;
1345 UINT_32 u4TotalLength;
1346 P_TX_CTRL_T prTxCtrl;
1348 #if CFG_TCP_IP_CHKSUM_OFFLOAD
1349 UINT_8 ucChksumFlag;
1353 ASSERT(ucPortIdx < 2);
1356 prTxCtrl = &prAdapter->rTxCtrl;
1357 u4ValidBufSize = prAdapter->u4CoalescingBufCachedSize;
1359 #if CFG_HIF_STATISTICS
1360 prTxCtrl->u4TotalTxAccessNum++;
1361 prTxCtrl->u4TotalTxPacketNum += prQue->u4NumElem;
1364 QUEUE_INITIALIZE(&rFreeQueue);
1366 if(prQue->u4NumElem > 0) {
1367 prMsduInfo = (P_MSDU_INFO_T)QUEUE_GET_HEAD(prQue);
1368 pucOutputBuf = prTxCtrl->pucTxCoalescingBufPtr;
1373 kalMemZero(&rHwTxHeader, sizeof(rHwTxHeader));
1375 prNativePacket = prMsduInfo->prPacket;
1377 ASSERT(prNativePacket);
1379 u4TxHdrSize = TX_HDR_SIZE;
1381 u2OverallBufferLength = ((prMsduInfo->u2FrameLength + TX_HDR_SIZE) &
1382 (UINT_16)HIF_TX_HDR_TX_BYTE_COUNT_MASK);
1384 rHwTxHeader.u2TxByteCount_UserPriority = u2OverallBufferLength;
1385 rHwTxHeader.u2TxByteCount_UserPriority |=
1386 ((UINT_16)prMsduInfo->ucUserPriority << HIF_TX_HDR_USER_PRIORITY_OFFSET);
1388 if (prMsduInfo->fgIs802_11) {
1389 ucEtherTypeOffsetInWord =
1390 (TX_HDR_SIZE + prMsduInfo->ucMacHeaderLength + prMsduInfo->ucLlcLength) >> 1;
1393 ucEtherTypeOffsetInWord =
1394 ((ETHER_HEADER_LEN - ETHER_TYPE_LEN) + TX_HDR_SIZE) >> 1;
1397 rHwTxHeader.ucEtherTypeOffset =
1398 ucEtherTypeOffsetInWord & HIF_TX_HDR_ETHER_TYPE_OFFSET_MASK;
1400 rHwTxHeader.ucResource_PktType_CSflags = (prMsduInfo->ucTC) << HIF_TX_HDR_RESOURCE_OFFSET;
1401 rHwTxHeader.ucResource_PktType_CSflags |=
1402 (UINT_8)(((prMsduInfo->ucPacketType) << HIF_TX_HDR_PACKET_TYPE_OFFSET) &
1403 (HIF_TX_HDR_PACKET_TYPE_MASK));
1405 #if CFG_TCP_IP_CHKSUM_OFFLOAD
1406 if (prMsduInfo->eSrc == TX_PACKET_OS
1407 || prMsduInfo->eSrc == TX_PACKET_FORWARDING) {
1408 if (prAdapter->u4CSUMFlags &
1409 (CSUM_OFFLOAD_EN_TX_TCP |
1410 CSUM_OFFLOAD_EN_TX_UDP |
1411 CSUM_OFFLOAD_EN_TX_IP)) {
1412 kalQueryTxChksumOffloadParam(prNativePacket, &ucChksumFlag);
1414 if (ucChksumFlag & TX_CS_IP_GEN) {
1415 rHwTxHeader.ucResource_PktType_CSflags |= (UINT_8)HIF_TX_HDR_IP_CSUM;
1418 if (ucChksumFlag & TX_CS_TCP_UDP_GEN) {
1419 rHwTxHeader.ucResource_PktType_CSflags |= (UINT_8)HIF_TX_HDR_TCP_CSUM;
1423 #endif /* CFG_TCP_IP_CHKSUM_OFFLOAD */
1425 rHwTxHeader.u2LLH = prMsduInfo->u2PalLLH;
1426 rHwTxHeader.ucStaRecIdx = prMsduInfo->ucStaRecIndex;
1427 rHwTxHeader.ucForwardingType_SessionID_Reserved =
1428 (prMsduInfo->ucPsForwardingType) | ((prMsduInfo->ucPsSessionID) << HIF_TX_HDR_PS_SESSION_ID_OFFSET)
1429 | ((prMsduInfo->fgIsBurstEnd)? HIF_TX_HDR_BURST_END_MASK : 0);
1431 rHwTxHeader.ucWlanHeaderLength = (prMsduInfo->ucMacHeaderLength & HIF_TX_HDR_WLAN_HEADER_LEN_MASK);
1432 rHwTxHeader.ucPktFormtId_Flags =
1433 (prMsduInfo->ucFormatID & HIF_TX_HDR_FORMAT_ID_MASK)
1434 | ((prMsduInfo->ucNetworkType << HIF_TX_HDR_NETWORK_TYPE_OFFSET) & HIF_TX_HDR_NETWORK_TYPE_MASK)
1435 | ((prMsduInfo->fgIs802_1x << HIF_TX_HDR_FLAG_1X_FRAME_OFFSET) & HIF_TX_HDR_FLAG_1X_FRAME_MASK)
1436 | ((prMsduInfo->fgIs802_11 << HIF_TX_HDR_FLAG_802_11_FORMAT_OFFSET) & HIF_TX_HDR_FLAG_802_11_FORMAT_MASK);
1438 rHwTxHeader.u2SeqNo = prMsduInfo->u2AclSN;
1440 if(prMsduInfo->pfTxDoneHandler) {
1441 rHwTxHeader.ucPacketSeqNo = prMsduInfo->ucTxSeqNum;
1442 rHwTxHeader.ucAck_BIP_BasicRate = HIF_TX_HDR_NEED_ACK;
1445 rHwTxHeader.ucPacketSeqNo = 0;
1446 rHwTxHeader.ucAck_BIP_BasicRate = 0;
1449 if(prMsduInfo->fgIsBIP) {
1450 rHwTxHeader.ucAck_BIP_BasicRate |= HIF_TX_HDR_BIP;
1453 if(prMsduInfo->fgIsBasicRate) {
1454 rHwTxHeader.ucAck_BIP_BasicRate |= HIF_TX_HDR_BASIC_RATE;
1457 #if CFG_ENABLE_PKT_LIFETIME_PROFILE
1458 if(prMsduInfo->rPktProfile.fgIsValid) {
1459 prMsduInfo->rPktProfile.rDequeueTimestamp = kalGetTimeTick();
1464 // attach to coalescing buffer
1465 kalMemCopy(pucOutputBuf + u4TotalLength, &rHwTxHeader, u4TxHdrSize);
1466 u4TotalLength += u4TxHdrSize;
1468 if (prMsduInfo->eSrc == TX_PACKET_OS
1469 || prMsduInfo->eSrc == TX_PACKET_FORWARDING) {
1470 kalCopyFrame(prAdapter->prGlueInfo,
1472 pucOutputBuf + u4TotalLength);
1474 else if(prMsduInfo->eSrc == TX_PACKET_MGMT) {
1475 kalMemCopy(pucOutputBuf + u4TotalLength,
1477 prMsduInfo->u2FrameLength);
1483 u4TotalLength += ALIGN_4(prMsduInfo->u2FrameLength);
1486 kalMemCopy(pucOutputBuf, &rHwTxHeader, u4TxHdrSize);
1488 /* Copy Frame Body */
1489 if (prMsduInfo->eSrc == TX_PACKET_OS
1490 || prMsduInfo->eSrc == TX_PACKET_FORWARDING) {
1491 kalCopyFrame(prAdapter->prGlueInfo,
1493 pucOutputBuf + u4TxHdrSize);
1495 else if(prMsduInfo->eSrc == TX_PACKET_MGMT) {
1496 kalMemCopy(pucOutputBuf + u4TxHdrSize,
1498 prMsduInfo->u2FrameLength);
1504 ASSERT(u2OverallBufferLength <= u4ValidBufSize);
1506 HAL_WRITE_TX_PORT(prAdapter,
1508 (UINT_32)u2OverallBufferLength,
1509 (PUINT_8)pucOutputBuf,
1514 prNextMsduInfo = (P_MSDU_INFO_T)
1515 QUEUE_GET_NEXT_ENTRY(&prMsduInfo->rQueEntry);
1517 if (prMsduInfo->eSrc == TX_PACKET_MGMT) {
1518 GLUE_DEC_REF_CNT(prTxCtrl->i4TxMgmtPendingNum);
1520 if (prMsduInfo->pfTxDoneHandler == NULL) {
1521 cnmMgtPktFree(prAdapter, prMsduInfo);
1524 KAL_SPIN_LOCK_DECLARATION();
1525 DBGLOG(INIT, TRACE,("Wait TxSeqNum:%d\n", prMsduInfo->ucTxSeqNum));
1526 KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TXING_MGMT_LIST);
1527 QUEUE_INSERT_TAIL(&(prTxCtrl->rTxMgmtTxingQueue), (P_QUE_ENTRY_T)prMsduInfo);
1528 KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TXING_MGMT_LIST);
1532 /* only free MSDU when it is not a MGMT frame */
1533 QUEUE_INSERT_TAIL(&rFreeQueue, (P_QUE_ENTRY_T)prMsduInfo);
1535 if (prMsduInfo->eSrc == TX_PACKET_OS) {
1536 kalSendComplete(prAdapter->prGlueInfo,
1538 WLAN_STATUS_SUCCESS);
1540 else if(prMsduInfo->eSrc == TX_PACKET_FORWARDING) {
1541 GLUE_DEC_REF_CNT(prTxCtrl->i4PendingFwdFrameCount);
1545 prMsduInfo = prNextMsduInfo;
1549 ASSERT(u4TotalLength <= u4ValidBufSize);
1551 #if CFG_DBG_GPIO_PINS
1553 /* Start port write */
1554 mtk_wcn_stp_debug_gpio_assert(IDX_TX_PORT_WRITE, DBG_TIE_LOW);
1556 mtk_wcn_stp_debug_gpio_assert(IDX_TX_PORT_WRITE, DBG_TIE_HIGH);
1560 // send coalescing buffer
1561 HAL_WRITE_TX_PORT(prAdapter,
1564 (PUINT_8)pucOutputBuf,
1568 #if CFG_ENABLE_PKT_LIFETIME_PROFILE
1569 #if CFG_SUPPORT_WFD && CFG_PRINT_RTP_PROFILE && !CFG_ENABLE_PER_STA_STATISTICS
1571 P_WFD_CFG_SETTINGS_T prWfdCfgSettings = (P_WFD_CFG_SETTINGS_T)NULL;
1573 prWfdCfgSettings = &prAdapter->rWifiVar.prP2pFsmInfo->rWfdConfigureSettings;
1575 if((prWfdCfgSettings->u2WfdMaximumTp >= 0xF000)) {
1577 nicTxReturnMsduInfoProfiling(prAdapter, (P_MSDU_INFO_T)QUEUE_GET_HEAD(&rFreeQueue));
1581 nicTxReturnMsduInfo(prAdapter, (P_MSDU_INFO_T)QUEUE_GET_HEAD(&rFreeQueue));
1585 nicTxReturnMsduInfoProfiling(prAdapter, (P_MSDU_INFO_T)QUEUE_GET_HEAD(&rFreeQueue));
1589 nicTxReturnMsduInfo(prAdapter, (P_MSDU_INFO_T)QUEUE_GET_HEAD(&rFreeQueue));
1593 return WLAN_STATUS_SUCCESS;
1597 /*----------------------------------------------------------------------------*/
1599 * \brief In this function, we'll write Command(CMD_INFO_T) into HIF.
1601 * @param prAdapter Pointer to the Adapter structure.
1602 * @param prPacketInfo Pointer of CMD_INFO_T
1603 * @param ucTC Specify the resource of TC
1605 * @retval WLAN_STATUS_SUCCESS Bus access ok.
1606 * @retval WLAN_STATUS_FAILURE Bus access fail.
1608 /*----------------------------------------------------------------------------*/
1611 IN P_ADAPTER_T prAdapter,
1612 IN P_CMD_INFO_T prCmdInfo,
1616 P_WIFI_CMD_T prWifiCmd;
1617 UINT_16 u2OverallBufferLength;
1618 PUINT_8 pucOutputBuf = (PUINT_8)NULL; /* Pointer to Transmit Data Structure Frame */
1620 HIF_TX_HEADER_T rHwTxHeader;
1621 P_NATIVE_PACKET prNativePacket;
1622 UINT_8 ucEtherTypeOffsetInWord;
1623 P_MSDU_INFO_T prMsduInfo;
1624 P_TX_CTRL_T prTxCtrl;
1626 KAL_SPIN_LOCK_DECLARATION();
1632 prTxCtrl = &prAdapter->rTxCtrl;
1633 pucOutputBuf = prTxCtrl->pucTxCoalescingBufPtr;
1635 // <1> Assign Data Port
1636 if (ucTC != TC4_INDEX) {
1640 // Broadcast/multicast data frames, 1x frames, command packets, MMPDU
1644 if(prCmdInfo->eCmdType == COMMAND_TYPE_SECURITY_FRAME) {
1645 // <2> Compose HIF_TX_HEADER
1646 kalMemZero(&rHwTxHeader, sizeof(rHwTxHeader));
1648 prNativePacket = prCmdInfo->prPacket;
1650 ASSERT(prNativePacket);
1652 u2OverallBufferLength = TFCB_FRAME_PAD_TO_DW((prCmdInfo->u2InfoBufLen + TX_HDR_SIZE)
1653 & (UINT_16)HIF_TX_HDR_TX_BYTE_COUNT_MASK);
1655 rHwTxHeader.u2TxByteCount_UserPriority = ((prCmdInfo->u2InfoBufLen + TX_HDR_SIZE)
1656 & (UINT_16)HIF_TX_HDR_TX_BYTE_COUNT_MASK);
1657 ucEtherTypeOffsetInWord = ((ETHER_HEADER_LEN - ETHER_TYPE_LEN) + TX_HDR_SIZE) >> 1;
1659 rHwTxHeader.ucEtherTypeOffset =
1660 ucEtherTypeOffsetInWord & HIF_TX_HDR_ETHER_TYPE_OFFSET_MASK;
1662 rHwTxHeader.ucResource_PktType_CSflags = (ucTC << HIF_TX_HDR_RESOURCE_OFFSET);
1664 rHwTxHeader.ucStaRecIdx = prCmdInfo->ucStaRecIndex;
1665 rHwTxHeader.ucForwardingType_SessionID_Reserved = HIF_TX_HDR_BURST_END_MASK;
1667 rHwTxHeader.ucWlanHeaderLength = (ETH_HLEN & HIF_TX_HDR_WLAN_HEADER_LEN_MASK);
1668 rHwTxHeader.ucPktFormtId_Flags =
1669 (((UINT_8)(prCmdInfo->eNetworkType) << HIF_TX_HDR_NETWORK_TYPE_OFFSET) & HIF_TX_HDR_NETWORK_TYPE_MASK)
1670 | ((1 << HIF_TX_HDR_FLAG_1X_FRAME_OFFSET) & HIF_TX_HDR_FLAG_1X_FRAME_MASK);
1672 rHwTxHeader.u2SeqNo = 0;
1673 rHwTxHeader.ucPacketSeqNo = 0;
1674 rHwTxHeader.ucAck_BIP_BasicRate = 0;
1676 // <2.3> Copy HIF TX HEADER
1677 kalMemCopy((PVOID)&pucOutputBuf[0], (PVOID)&rHwTxHeader, TX_HDR_SIZE);
1679 // <3> Copy Frame Body Copy
1680 kalCopyFrame(prAdapter->prGlueInfo,
1682 pucOutputBuf + TX_HDR_SIZE);
1684 else if(prCmdInfo->eCmdType == COMMAND_TYPE_MANAGEMENT_FRAME) {
1685 prMsduInfo = (P_MSDU_INFO_T)prCmdInfo->prPacket;
1687 ASSERT(prMsduInfo->fgIs802_11 == TRUE);
1688 ASSERT(prMsduInfo->eSrc == TX_PACKET_MGMT);
1690 // <2> Compose HIF_TX_HEADER
1691 kalMemZero(&rHwTxHeader, sizeof(rHwTxHeader));
1693 u2OverallBufferLength = ((prMsduInfo->u2FrameLength + TX_HDR_SIZE) &
1694 (UINT_16)HIF_TX_HDR_TX_BYTE_COUNT_MASK);
1696 rHwTxHeader.u2TxByteCount_UserPriority = u2OverallBufferLength;
1697 rHwTxHeader.u2TxByteCount_UserPriority |=
1698 ((UINT_16)prMsduInfo->ucUserPriority << HIF_TX_HDR_USER_PRIORITY_OFFSET);
1700 ucEtherTypeOffsetInWord =
1701 (TX_HDR_SIZE + prMsduInfo->ucMacHeaderLength + prMsduInfo->ucLlcLength) >> 1;
1703 rHwTxHeader.ucEtherTypeOffset =
1704 ucEtherTypeOffsetInWord & HIF_TX_HDR_ETHER_TYPE_OFFSET_MASK;
1706 rHwTxHeader.ucResource_PktType_CSflags = (prMsduInfo->ucTC) << HIF_TX_HDR_RESOURCE_OFFSET;
1707 rHwTxHeader.ucResource_PktType_CSflags |=
1708 (UINT_8)(((prMsduInfo->ucPacketType) << HIF_TX_HDR_PACKET_TYPE_OFFSET) &
1709 (HIF_TX_HDR_PACKET_TYPE_MASK));
1711 rHwTxHeader.u2LLH = prMsduInfo->u2PalLLH;
1712 rHwTxHeader.ucStaRecIdx = prMsduInfo->ucStaRecIndex;
1713 rHwTxHeader.ucForwardingType_SessionID_Reserved =
1714 (prMsduInfo->ucPsForwardingType) | ((prMsduInfo->ucPsSessionID) << HIF_TX_HDR_PS_SESSION_ID_OFFSET)
1715 | ((prMsduInfo->fgIsBurstEnd)? HIF_TX_HDR_BURST_END_MASK : 0);
1717 rHwTxHeader.ucWlanHeaderLength = (prMsduInfo->ucMacHeaderLength & HIF_TX_HDR_WLAN_HEADER_LEN_MASK);
1718 rHwTxHeader.ucPktFormtId_Flags =
1719 (prMsduInfo->ucFormatID & HIF_TX_HDR_FORMAT_ID_MASK)
1720 | ((prMsduInfo->ucNetworkType << HIF_TX_HDR_NETWORK_TYPE_OFFSET) & HIF_TX_HDR_NETWORK_TYPE_MASK)
1721 | ((prMsduInfo->fgIs802_1x << HIF_TX_HDR_FLAG_1X_FRAME_OFFSET) & HIF_TX_HDR_FLAG_1X_FRAME_MASK)
1722 | ((prMsduInfo->fgIs802_11 << HIF_TX_HDR_FLAG_802_11_FORMAT_OFFSET) & HIF_TX_HDR_FLAG_802_11_FORMAT_MASK);
1724 rHwTxHeader.u2SeqNo = prMsduInfo->u2AclSN;
1726 if(prMsduInfo->pfTxDoneHandler) {
1727 rHwTxHeader.ucPacketSeqNo = prMsduInfo->ucTxSeqNum;
1728 rHwTxHeader.ucAck_BIP_BasicRate = HIF_TX_HDR_NEED_ACK;
1731 rHwTxHeader.ucPacketSeqNo = 0;
1732 rHwTxHeader.ucAck_BIP_BasicRate = 0;
1735 if(prMsduInfo->fgIsBIP) {
1736 rHwTxHeader.ucAck_BIP_BasicRate |= HIF_TX_HDR_BIP;
1739 if(prMsduInfo->fgIsBasicRate) {
1740 rHwTxHeader.ucAck_BIP_BasicRate |= HIF_TX_HDR_BASIC_RATE;
1743 // <2.3> Copy HIF TX HEADER
1744 kalMemCopy((PVOID)&pucOutputBuf[0], (PVOID)&rHwTxHeader, TX_HDR_SIZE);
1746 // <3> Copy Frame Body
1747 kalMemCopy(pucOutputBuf + TX_HDR_SIZE,
1748 prMsduInfo->prPacket,
1749 prMsduInfo->u2FrameLength);
1751 // <4> Management Frame Post-Processing
1752 GLUE_DEC_REF_CNT(prTxCtrl->i4TxMgmtPendingNum);
1754 if (prMsduInfo->pfTxDoneHandler == NULL) {
1755 cnmMgtPktFree(prAdapter, prMsduInfo);
1759 DBGLOG(INIT, TRACE,("Wait Cmd TxSeqNum:%d\n", prMsduInfo->ucTxSeqNum));
1761 KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TXING_MGMT_LIST);
1762 QUEUE_INSERT_TAIL(&(prTxCtrl->rTxMgmtTxingQueue), (P_QUE_ENTRY_T)prMsduInfo);
1763 KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TXING_MGMT_LIST);
1767 prWifiCmd = (P_WIFI_CMD_T)prCmdInfo->pucInfoBuffer;
1769 // <2> Compose the Header of Transmit Data Structure for CMD Packet
1770 u2OverallBufferLength = TFCB_FRAME_PAD_TO_DW(
1771 (prCmdInfo->u2InfoBufLen) & (UINT_16)HIF_TX_HDR_TX_BYTE_COUNT_MASK);
1773 prWifiCmd->u2TxByteCount_UserPriority = u2OverallBufferLength;
1774 prWifiCmd->ucEtherTypeOffset = 0;
1775 prWifiCmd->ucResource_PktType_CSflags = (ucTC << HIF_TX_HDR_RESOURCE_OFFSET)
1776 | (UINT_8)((HIF_TX_PKT_TYPE_CMD << HIF_TX_HDR_PACKET_TYPE_OFFSET) & (HIF_TX_HDR_PACKET_TYPE_MASK));
1779 // <3> Copy CMD Header to command buffer (by using pucCoalescingBufCached)
1780 kalMemCopy((PVOID)&pucOutputBuf[0],
1781 (PVOID)prCmdInfo->pucInfoBuffer,
1782 prCmdInfo->u2InfoBufLen);
1784 ASSERT(u2OverallBufferLength <= prAdapter->u4CoalescingBufCachedSize);
1787 // <4> Write frame to data port
1788 HAL_WRITE_TX_PORT(prAdapter,
1790 (UINT_32)u2OverallBufferLength,
1791 (PUINT_8)pucOutputBuf,
1792 (UINT_32)prAdapter->u4CoalescingBufCachedSize);
1794 return WLAN_STATUS_SUCCESS;
1795 } /* end of nicTxCmd() */
1798 /*----------------------------------------------------------------------------*/
1800 * @brief This function will clean up all the pending frames in internal SW Queues
1801 * by return the pending TX packet to the system.
1803 * @param prAdapter Pointer to the Adapter structure.
1807 /*----------------------------------------------------------------------------*/
1810 IN P_ADAPTER_T prAdapter
1813 P_TX_CTRL_T prTxCtrl;
1814 P_MSDU_INFO_T prMsduInfo;
1816 KAL_SPIN_LOCK_DECLARATION();
1820 prTxCtrl = &prAdapter->rTxCtrl;
1822 nicTxFlush(prAdapter);
1824 // free MSDU_INFO_T from rTxMgmtMsduInfoList
1826 KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TXING_MGMT_LIST);
1827 QUEUE_REMOVE_HEAD(&prTxCtrl->rTxMgmtTxingQueue, prMsduInfo, P_MSDU_INFO_T);
1828 KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TXING_MGMT_LIST);
1831 // the packet must be mgmt frame with tx done callback
1832 ASSERT(prMsduInfo->eSrc == TX_PACKET_MGMT);
1833 ASSERT(prMsduInfo->pfTxDoneHandler != NULL);
1835 // invoke done handler
1836 prMsduInfo->pfTxDoneHandler(prAdapter, prMsduInfo, TX_RESULT_LIFE_TIMEOUT);
1838 cnmMgtPktFree(prAdapter, prMsduInfo);
1846 } /* end of nicTxRelease() */
1849 /*----------------------------------------------------------------------------*/
1851 * @brief Process the TX Done interrupt and pull in more pending frames in SW
1852 * Queues for transmission.
1854 * @param prAdapter Pointer to the Adapter structure.
1858 /*----------------------------------------------------------------------------*/
1860 nicProcessTxInterrupt(
1861 IN P_ADAPTER_T prAdapter
1864 P_TX_CTRL_T prTxCtrl;
1865 #if CFG_SDIO_INTR_ENHANCE
1866 P_SDIO_CTRL_T prSDIOCtrl;
1868 UINT_32 au4TxCount[2];
1869 #endif /* CFG_SDIO_INTR_ENHANCE */
1873 prTxCtrl = &prAdapter->rTxCtrl;
1876 /* Get the TX STATUS */
1877 #if CFG_SDIO_INTR_ENHANCE
1879 prSDIOCtrl = prAdapter->prSDIOCtrl;
1881 //dumpMemory8((PUINT_8)prSDIOCtrl, sizeof(SDIO_CTRL_T));
1884 nicTxReleaseResource(prAdapter, (PUINT_8)&prSDIOCtrl->rTxInfo);
1885 kalMemZero(&prSDIOCtrl->rTxInfo, sizeof(prSDIOCtrl->rTxInfo));
1889 HAL_MCR_RD(prAdapter, MCR_WTSR0, &au4TxCount[0]);
1890 HAL_MCR_RD(prAdapter, MCR_WTSR1, &au4TxCount[1]);
1891 DBGLOG(EMU, TRACE, ("MCR_WTSR0: 0x%x, MCR_WTSR1: 0x%x\n", au4TxCount[0], au4TxCount[1]));
1893 nicTxReleaseResource(prAdapter, (PUINT_8)au4TxCount);
1895 #endif /* CFG_SDIO_INTR_ENHANCE */
1897 nicTxAdjustTcq(prAdapter);
1899 // Indicate Service Thread
1900 if(kalGetTxPendingCmdCount(prAdapter->prGlueInfo) > 0
1901 || wlanGetTxPendingFrameCount(prAdapter) > 0) {
1902 kalSetEvent(prAdapter->prGlueInfo);
1906 } /* end of nicProcessTxInterrupt() */
1909 /*----------------------------------------------------------------------------*/
1911 * @brief this function frees packet of P_MSDU_INFO_T linked-list
1913 * @param prAdapter Pointer to the Adapter structure.
1914 * @param prMsduInfoList a link list of P_MSDU_INFO_T
1918 /*----------------------------------------------------------------------------*/
1920 nicTxFreeMsduInfoPacket (
1921 IN P_ADAPTER_T prAdapter,
1922 IN P_MSDU_INFO_T prMsduInfoListHead
1925 P_NATIVE_PACKET prNativePacket;
1926 P_MSDU_INFO_T prMsduInfo = prMsduInfoListHead;
1927 P_TX_CTRL_T prTxCtrl;
1931 ASSERT(prMsduInfoListHead);
1933 prTxCtrl = &prAdapter->rTxCtrl;
1936 prNativePacket = prMsduInfo->prPacket;
1938 if(prMsduInfo->eSrc == TX_PACKET_OS) {
1939 kalSendComplete(prAdapter->prGlueInfo,
1941 WLAN_STATUS_FAILURE);
1943 else if(prMsduInfo->eSrc == TX_PACKET_MGMT) {
1944 if (prMsduInfo->pfTxDoneHandler) {
1945 prMsduInfo->pfTxDoneHandler(prAdapter, prMsduInfo, TX_RESULT_DROPPED_IN_DRIVER);
1947 cnmMemFree(prAdapter, prNativePacket);
1949 else if(prMsduInfo->eSrc == TX_PACKET_FORWARDING) {
1950 GLUE_DEC_REF_CNT(prTxCtrl->i4PendingFwdFrameCount);
1953 prMsduInfo = (P_MSDU_INFO_T)QUEUE_GET_NEXT_ENTRY((P_QUE_ENTRY_T)prMsduInfo);
1960 /*----------------------------------------------------------------------------*/
1962 * @brief this function returns P_MSDU_INFO_T of MsduInfoList to TxCtrl->rfreeMsduInfoList
1964 * @param prAdapter Pointer to the Adapter structure.
1965 * @param prMsduInfoList a link list of P_MSDU_INFO_T
1969 /*----------------------------------------------------------------------------*/
1971 nicTxReturnMsduInfo (
1972 IN P_ADAPTER_T prAdapter,
1973 IN P_MSDU_INFO_T prMsduInfoListHead
1976 P_TX_CTRL_T prTxCtrl;
1977 P_MSDU_INFO_T prMsduInfo = prMsduInfoListHead, prNextMsduInfo;
1979 KAL_SPIN_LOCK_DECLARATION();
1983 prTxCtrl = &prAdapter->rTxCtrl;
1987 prNextMsduInfo = (P_MSDU_INFO_T)QUEUE_GET_NEXT_ENTRY((P_QUE_ENTRY_T)prMsduInfo);
1989 switch(prMsduInfo->eSrc) {
1990 case TX_PACKET_FORWARDING:
1991 wlanReturnPacket(prAdapter, prMsduInfo->prPacket);
1994 case TX_PACKET_OS_OID:
1995 case TX_PACKET_MGMT:
2000 KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_MSDU_INFO_LIST);
2001 QUEUE_INSERT_TAIL(&prTxCtrl->rFreeMsduInfoList, (P_QUE_ENTRY_T)prMsduInfo);
2002 KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_MSDU_INFO_LIST);
2003 prMsduInfo = prNextMsduInfo;
2009 /*----------------------------------------------------------------------------*/
2011 * @brief this function fills packet information to P_MSDU_INFO_T
2013 * @param prAdapter Pointer to the Adapter structure.
2014 * @param prMsduInfo P_MSDU_INFO_T
2015 * @param prPacket P_NATIVE_PACKET
2017 * @retval TRUE Success to extract information
2018 * @retval FALSE Fail to extract correct information
2020 /*----------------------------------------------------------------------------*/
2023 IN P_ADAPTER_T prAdapter,
2024 IN P_MSDU_INFO_T prMsduInfo,
2025 IN P_NATIVE_PACKET prPacket
2028 P_GLUE_INFO_T prGlueInfo;
2029 UINT_8 ucPriorityParam;
2030 UINT_8 ucMacHeaderLen;
2031 UINT_8 aucEthDestAddr[PARAM_MAC_ADDR_LEN];
2032 BOOLEAN fgIs1x = FALSE;
2033 BOOLEAN fgIsPAL = FALSE;
2034 UINT_32 u4PacketLen;
2036 UINT_8 ucNetworkType;
2041 prGlueInfo = prAdapter->prGlueInfo;
2044 if (kalQoSFrameClassifierAndPacketInfo(prGlueInfo,
2051 &ucNetworkType) == FALSE) {
2055 #if CFG_ENABLE_PKT_LIFETIME_PROFILE
2056 nicTxLifetimeCheck (
2065 /* Save the value of Priority Parameter */
2066 GLUE_SET_PKT_TID(prPacket, ucPriorityParam);
2069 GLUE_SET_PKT_FLAG_1X(prPacket);
2073 GLUE_SET_PKT_FLAG_PAL(prPacket);
2076 ucMacHeaderLen = ETH_HLEN;
2078 /* Save the value of Header Length */
2079 GLUE_SET_PKT_HEADER_LEN(prPacket, ucMacHeaderLen);
2081 /* Save the value of Frame Length */
2082 GLUE_SET_PKT_FRAME_LEN(prPacket, (UINT_16)u4PacketLen);
2084 /* Save the value of Arrival Time*/
2085 u4SysTime = (OS_SYSTIME)kalGetTimeTick();
2086 GLUE_SET_PKT_ARRIVAL_TIME(prPacket, u4SysTime);
2088 prMsduInfo->prPacket = prPacket;
2089 prMsduInfo->fgIs802_1x = fgIs1x;
2090 prMsduInfo->fgIs802_11 = FALSE;
2091 prMsduInfo->ucNetworkType = ucNetworkType;
2092 prMsduInfo->ucUserPriority = ucPriorityParam;
2093 prMsduInfo->ucMacHeaderLength = ucMacHeaderLen;
2094 prMsduInfo->u2FrameLength = (UINT_16)u4PacketLen;
2095 COPY_MAC_ADDR(prMsduInfo->aucEthDestAddr, aucEthDestAddr);
2101 /*----------------------------------------------------------------------------*/
2103 * @brief this function update TCQ values by passing current status to txAdjustTcQuotas
2105 * @param prAdapter Pointer to the Adapter structure.
2107 * @retval WLAN_STATUS_SUCCESS Updated successfully
2109 /*----------------------------------------------------------------------------*/
2112 IN P_ADAPTER_T prAdapter
2116 TX_TCQ_ADJUST_T rTcqAdjust;
2117 P_TX_CTRL_T prTxCtrl;
2118 KAL_SPIN_LOCK_DECLARATION();
2122 prTxCtrl = &prAdapter->rTxCtrl;
2125 qmAdjustTcQuotas(prAdapter, &rTcqAdjust, &prTxCtrl->rTc);
2126 KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_RESOURCE);
2128 for (u4Num = 0 ; u4Num < TC_NUM ; u4Num++) {
2129 prTxCtrl->rTc.aucFreeBufferCount[u4Num] += rTcqAdjust.acVariation[u4Num];
2130 prTxCtrl->rTc.aucMaxNumOfBuffer[u4Num] += rTcqAdjust.acVariation[u4Num];
2132 ASSERT(prTxCtrl->rTc.aucFreeBufferCount[u4Num] >= 0);
2133 ASSERT(prTxCtrl->rTc.aucMaxNumOfBuffer[u4Num] >= 0);
2136 KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_RESOURCE);
2138 return WLAN_STATUS_SUCCESS;
2142 /*----------------------------------------------------------------------------*/
2144 * @brief this function flushes all packets queued in STA/AC queue
2146 * @param prAdapter Pointer to the Adapter structure.
2148 * @retval WLAN_STATUS_SUCCESS Flushed successfully
2150 /*----------------------------------------------------------------------------*/
2154 IN P_ADAPTER_T prAdapter
2157 P_MSDU_INFO_T prMsduInfo;
2158 KAL_SPIN_LOCK_DECLARATION();
2162 // ask Per STA/AC queue to be fllushed and return all queued packets
2163 KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_QM_TX_QUEUE);
2164 prMsduInfo = qmFlushTxQueues(prAdapter);
2165 KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_QM_TX_QUEUE);
2167 if(prMsduInfo != NULL) {
2168 nicTxFreeMsduInfoPacket(prAdapter, prMsduInfo);
2169 nicTxReturnMsduInfo(prAdapter, prMsduInfo);
2172 return WLAN_STATUS_SUCCESS;
2176 #if CFG_ENABLE_FW_DOWNLOAD
2177 /*----------------------------------------------------------------------------*/
2179 * \brief In this function, we'll write Command(CMD_INFO_T) into HIF.
2180 * However this function is used for INIT_CMD.
2182 * In order to avoid further maintainance issues, these 2 functions are separated
2184 * @param prAdapter Pointer to the Adapter structure.
2185 * @param prPacketInfo Pointer of CMD_INFO_T
2186 * @param ucTC Specify the resource of TC
2188 * @retval WLAN_STATUS_SUCCESS Bus access ok.
2189 * @retval WLAN_STATUS_FAILURE Bus access fail.
2191 /*----------------------------------------------------------------------------*/
2194 IN P_ADAPTER_T prAdapter,
2195 IN P_CMD_INFO_T prCmdInfo,
2199 P_INIT_HIF_TX_HEADER_T prInitTxHeader;
2200 UINT_16 u2OverallBufferLength;
2201 PUINT_8 pucOutputBuf = (PUINT_8)NULL; /* Pointer to Transmit Data Structure Frame */
2203 P_TX_CTRL_T prTxCtrl;
2207 ASSERT(ucTC == TC0_INDEX);
2209 prTxCtrl = &prAdapter->rTxCtrl;
2210 pucOutputBuf = prTxCtrl->pucTxCoalescingBufPtr;
2211 prInitTxHeader = (P_INIT_HIF_TX_HEADER_T)prCmdInfo->pucInfoBuffer;
2213 // <1> Compose the Header of Transmit Data Structure for CMD Packet
2214 u2OverallBufferLength = TFCB_FRAME_PAD_TO_DW(
2215 (prCmdInfo->u2InfoBufLen) & (UINT_16)HIF_TX_HDR_TX_BYTE_COUNT_MASK);
2217 prInitTxHeader->u2TxByteCount = u2OverallBufferLength;
2218 prInitTxHeader->ucEtherTypeOffset = 0;
2219 prInitTxHeader->ucCSflags = 0;
2221 // <2> Assign Data Port
2222 if (ucTC != TC4_INDEX) {
2225 else { // Broadcast/multicast data packets
2229 // <3> Copy CMD Header to command buffer (by using pucCoalescingBufCached)
2230 kalMemCopy((PVOID)&pucOutputBuf[0],
2231 (PVOID)prCmdInfo->pucInfoBuffer,
2232 prCmdInfo->u2InfoBufLen);
2234 ASSERT(u2OverallBufferLength <= prAdapter->u4CoalescingBufCachedSize);
2236 // <4> Write frame to data port
2237 HAL_WRITE_TX_PORT(prAdapter,
2239 (UINT_32)u2OverallBufferLength,
2240 (PUINT_8)pucOutputBuf,
2241 (UINT_32)prAdapter->u4CoalescingBufCachedSize);
2243 return WLAN_STATUS_SUCCESS;
2247 /*----------------------------------------------------------------------------*/
2249 * \brief In this function, we'll reset TX resource counter to initial value used
2250 * in F/W download state
2252 * @param prAdapter Pointer to the Adapter structure.
2254 * @retval WLAN_STATUS_SUCCESS Reset is done successfully.
2256 /*----------------------------------------------------------------------------*/
2258 nicTxInitResetResource (
2259 IN P_ADAPTER_T prAdapter
2262 P_TX_CTRL_T prTxCtrl;
2264 DEBUGFUNC("nicTxInitResetResource");
2267 prTxCtrl = &prAdapter->rTxCtrl;
2269 prTxCtrl->rTc.aucMaxNumOfBuffer[TC0_INDEX] = NIC_TX_INIT_BUFF_COUNT_TC0;
2270 prTxCtrl->rTc.aucFreeBufferCount[TC0_INDEX] = NIC_TX_INIT_BUFF_COUNT_TC0;
2272 prTxCtrl->rTc.aucMaxNumOfBuffer[TC1_INDEX] = NIC_TX_INIT_BUFF_COUNT_TC1;
2273 prTxCtrl->rTc.aucFreeBufferCount[TC1_INDEX] = NIC_TX_INIT_BUFF_COUNT_TC1;
2275 prTxCtrl->rTc.aucMaxNumOfBuffer[TC2_INDEX] = NIC_TX_INIT_BUFF_COUNT_TC2;
2276 prTxCtrl->rTc.aucFreeBufferCount[TC2_INDEX] = NIC_TX_INIT_BUFF_COUNT_TC2;
2278 prTxCtrl->rTc.aucMaxNumOfBuffer[TC3_INDEX] = NIC_TX_INIT_BUFF_COUNT_TC3;
2279 prTxCtrl->rTc.aucFreeBufferCount[TC3_INDEX] = NIC_TX_INIT_BUFF_COUNT_TC3;
2281 prTxCtrl->rTc.aucMaxNumOfBuffer[TC4_INDEX] = NIC_TX_INIT_BUFF_COUNT_TC4;
2282 prTxCtrl->rTc.aucFreeBufferCount[TC4_INDEX] = NIC_TX_INIT_BUFF_COUNT_TC4;
2284 prTxCtrl->rTc.aucMaxNumOfBuffer[TC5_INDEX] = NIC_TX_INIT_BUFF_COUNT_TC5;
2285 prTxCtrl->rTc.aucFreeBufferCount[TC5_INDEX] = NIC_TX_INIT_BUFF_COUNT_TC5;
2287 return WLAN_STATUS_SUCCESS;
2294 /*----------------------------------------------------------------------------*/
2296 * \brief this function enqueues MSDU_INFO_T into queue management,
2299 * @param prAdapter Pointer to the Adapter structure.
2300 * prMsduInfo Pointer to MSDU
2302 * @retval WLAN_STATUS_SUCCESS Reset is done successfully.
2304 /*----------------------------------------------------------------------------*/
2307 IN P_ADAPTER_T prAdapter,
2308 IN P_MSDU_INFO_T prMsduInfo
2311 P_TX_CTRL_T prTxCtrl;
2312 P_MSDU_INFO_T prNextMsduInfo, prRetMsduInfo, prMsduInfoHead;
2313 QUE_T qDataPort0, qDataPort1;
2314 P_CMD_INFO_T prCmdInfo;
2315 WLAN_STATUS u4Status = WLAN_STATUS_SUCCESS;
2316 KAL_SPIN_LOCK_DECLARATION();
2321 prTxCtrl = &prAdapter->rTxCtrl;
2324 QUEUE_INITIALIZE(&qDataPort0);
2325 QUEUE_INITIALIZE(&qDataPort1);
2327 /* check how many management frame are being queued */
2329 prNextMsduInfo = (P_MSDU_INFO_T)QUEUE_GET_NEXT_ENTRY((P_QUE_ENTRY_T)prMsduInfo);
2331 QUEUE_GET_NEXT_ENTRY((P_QUE_ENTRY_T)prMsduInfo) = NULL;
2333 if(prMsduInfo->eSrc == TX_PACKET_MGMT) {
2334 // MMPDU: force stick to TC4
2335 prMsduInfo->ucTC = TC4_INDEX;
2337 QUEUE_INSERT_TAIL(&qDataPort1, (P_QUE_ENTRY_T)prMsduInfo);
2340 QUEUE_INSERT_TAIL(&qDataPort0, (P_QUE_ENTRY_T)prMsduInfo);
2343 prMsduInfo = prNextMsduInfo;
2346 if(qDataPort0.u4NumElem) {
2348 KAL_SPIN_LOCK_DECLARATION();
2349 KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_QM_TX_QUEUE);
2350 prRetMsduInfo = qmEnqueueTxPackets(prAdapter, (P_MSDU_INFO_T)QUEUE_GET_HEAD(&qDataPort0));
2351 KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_QM_TX_QUEUE);
2353 /* post-process for dropped packets */
2354 if(prRetMsduInfo != NULL) { // unable to enqueue
2355 nicTxFreeMsduInfoPacket(prAdapter, prRetMsduInfo);
2356 nicTxReturnMsduInfo(prAdapter, prRetMsduInfo);
2360 if(qDataPort1.u4NumElem) {
2361 prMsduInfoHead = (P_MSDU_INFO_T)QUEUE_GET_HEAD(&qDataPort1);
2363 if(qDataPort1.u4NumElem > nicTxGetFreeCmdCount(prAdapter)) {
2364 // not enough descriptors for sending
2365 u4Status = WLAN_STATUS_FAILURE;
2368 while(prMsduInfoHead) {
2369 prNextMsduInfo = (P_MSDU_INFO_T) QUEUE_GET_NEXT_ENTRY(&prMsduInfoHead->rQueEntry);
2371 if (prMsduInfoHead->pfTxDoneHandler != NULL) {
2372 prMsduInfoHead->pfTxDoneHandler(prAdapter, prMsduInfoHead, TX_RESULT_DROPPED_IN_DRIVER);
2376 cnmMgtPktFree(prAdapter, prMsduInfoHead);
2378 prMsduInfoHead = prNextMsduInfo;
2382 /* send to command queue */
2383 while(prMsduInfoHead) {
2384 prNextMsduInfo = (P_MSDU_INFO_T) QUEUE_GET_NEXT_ENTRY(&prMsduInfoHead->rQueEntry);
2386 KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_CMD_RESOURCE);
2387 QUEUE_REMOVE_HEAD(&prAdapter->rFreeCmdList, prCmdInfo, P_CMD_INFO_T);
2388 KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_CMD_RESOURCE);
2391 GLUE_INC_REF_CNT(prTxCtrl->i4TxMgmtPendingNum);
2393 kalMemZero(prCmdInfo, sizeof(CMD_INFO_T));
2395 prCmdInfo->eCmdType = COMMAND_TYPE_MANAGEMENT_FRAME;
2396 prCmdInfo->u2InfoBufLen = prMsduInfoHead->u2FrameLength;
2397 prCmdInfo->pucInfoBuffer = NULL;
2398 prCmdInfo->prPacket = (P_NATIVE_PACKET)prMsduInfoHead;
2399 prCmdInfo->ucStaRecIndex = prMsduInfoHead->ucStaRecIndex;
2400 prCmdInfo->eNetworkType = prMsduInfoHead->ucNetworkType;
2401 prCmdInfo->pfCmdDoneHandler = NULL;
2402 prCmdInfo->pfCmdTimeoutHandler = NULL;
2403 prCmdInfo->fgIsOid = FALSE;
2404 prCmdInfo->fgSetQuery = TRUE;
2405 prCmdInfo->fgNeedResp = FALSE;
2407 kalEnqueueCommand(prAdapter->prGlueInfo, (P_QUE_ENTRY_T)prCmdInfo);
2410 /* Cmd free count is larger than expected, but allocation fail. */
2413 u4Status = WLAN_STATUS_FAILURE;
2414 cnmMgtPktFree(prAdapter, prMsduInfoHead);
2417 prMsduInfoHead = prNextMsduInfo;
2422 /* indicate service thread for sending */
2423 if(prTxCtrl->i4TxMgmtPendingNum > 0
2424 || kalGetTxPendingFrameCount(prAdapter->prGlueInfo) > 0) {
2425 kalSetEvent(prAdapter->prGlueInfo);
2432 /*----------------------------------------------------------------------------*/
2434 * \brief this function returns available count in command queue
2436 * @param prAdapter Pointer to the Adapter structure.
2440 /*----------------------------------------------------------------------------*/
2442 nicTxGetFreeCmdCount (
2443 IN P_ADAPTER_T prAdapter
2448 return prAdapter->rFreeCmdList.u4NumElem;