support different wifi bt chip auto compatible
[firefly-linux-kernel-4.4.55.git] / drivers / net / wireless / rockchip_wlan / mt5931 / nic / nic_tx.c
1 /*
2 ** $Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/nic/nic_tx.c#1 $
3 */
4
5 /*! \file   nic_tx.c
6     \brief  Functions that provide TX operation in NIC Layer.
7
8     This file provides TX functions which are responsible for both Hardware and
9     Software Resource Management and keep their Synchronization.
10 */
11
12
13
14 /*
15 ** $Log: nic_tx.c $
16  *
17  * 06 13 2012 yuche.tsai
18  * NULL
19  * Update maintrunk driver.
20  * Add support for driver compose assoc request frame.
21  *
22  * 11 18 2011 eddie.chen
23  * [WCXRP00001096] [MT6620 Wi-Fi][Driver/FW] Enhance the log function (xlog)
24  * Add log counter for tx
25  *
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.
29  *
30  * 11 08 2011 eddie.chen
31  * [WCXRP00001096] [MT6620 Wi-Fi][Driver/FW] Enhance the log function (xlog)
32  * Add xlog function.
33  *
34  * 05 17 2011 cp.wu
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.
37  *
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
42  * Add debug message.
43  *
44  * 04 12 2011 cp.wu
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.
47  *
48  * 04 12 2011 cp.wu
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.
52  *
53  * 03 17 2011 cp.wu
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
56  *
57  * 03 15 2011 cp.wu
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
61  * 
62  *
63  * 02 16 2011 cp.wu
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
67  *
68  * 01 24 2011 cp.wu
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
73  *
74  * 01 12 2011 cp.wu
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.
77  *
78  * 12 31 2010 cp.wu
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
81  *
82  * 11 01 2010 yarco.yang
83  * [WCXRP00000149] [MT6620 WI-Fi][Driver]Fine tune performance on MT6516 platform
84  * Add GPIO debug function
85  *
86  * 10 18 2010 cp.wu
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
91  *
92  * 10 06 2010 cp.wu
93  * [WCXRP00000052] [MT6620 Wi-Fi][Driver] Eliminate Linux Compile Warning
94  * code reorganization to improve isolation between GLUE and CORE layers.
95  *
96  * 09 29 2010 wh.su
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.
99  *
100  * 09 27 2010 wh.su
101  * NULL
102  * since the u2TxByteCount_UserPriority will or another setting, keep the overall buffer for avoid error
103  *
104  * 09 24 2010 wh.su
105  * NULL
106  * [WCXRP000000058][MT6620 Wi-Fi][Driver] Fail to handshake with WAPI AP due the 802.1x frame send to fw with extra bytes padding.
107  *
108  * 09 01 2010 cp.wu
109  * NULL
110  * HIFSYS Clock Source Workaround
111  *
112  * 08 30 2010 cp.wu
113  * NULL
114  * API added: nicTxPendingPackets(), for simplifying porting layer
115  *
116  * 08 30 2010 cp.wu
117  * NULL
118  * eliminate klockwork errors
119  *
120  * 08 20 2010 wh.su
121  * NULL
122  * adding the eapol callback setting.
123  *
124  * 08 18 2010 yarco.yang
125  * NULL
126  * 1. Fixed HW checksum offload function not work under Linux issue.
127  * 2. Add debug message.
128  *
129  * 08 05 2010 yuche.tsai
130  * NULL
131  * .
132  *
133  * 08 03 2010 cp.wu
134  * NULL
135  * surpress compilation warning.
136  *
137  * 08 02 2010 jeffrey.chang
138  * NULL
139  * 1) modify tx service thread to avoid busy looping
140  * 2) add spin lock declartion for linux build
141  *
142  * 07 29 2010 cp.wu
143  * NULL
144  * simplify post-handling after TX_DONE interrupt is handled.
145  *
146  * 07 19 2010 jeffrey.chang
147  *
148  * Linux port modification
149  *
150  * 07 13 2010 cp.wu
151  *
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
155  *
156  * 07 08 2010 cp.wu
157  *
158  * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository.
159  *
160  * 06 29 2010 yarco.yang
161  * [WPD00003837][MT6620]Data Path Refine
162  * replace g_rQM with Adpater->rQM
163  *
164  * 06 25 2010 cp.wu
165  * [WPD00003833][MT6620 and MT5931] Driver migration
166  * add API in que_mgt to retrieve sta-rec index for security frames.
167  *
168  * 06 24 2010 cp.wu
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.
171  *
172  * 06 23 2010 yarco.yang
173  * [WPD00003837][MT6620]Data Path Refine
174  * Merge g_arStaRec[] into adapter->arStaRec[]
175  *
176  * 06 22 2010 cp.wu
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.
181  *
182  * 06 21 2010 cp.wu
183  * [WPD00003833][MT6620 and MT5931] Driver migration
184  * add checking for TX descriptor poll.
185  *
186  * 06 21 2010 cp.wu
187  * [WPD00003833][MT6620 and MT5931] Driver migration
188  * TX descriptors are now allocated once for reducing allocation overhead
189  *
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
193  *
194  * 06 15 2010 cp.wu
195  * [WPD00003833][MT6620 and MT5931] Driver migration
196  * change zero-padding for TX port access to HAL.
197  *
198  * 06 15 2010 cp.wu
199  * [WPD00003833][MT6620 and MT5931] Driver migration
200  * .
201  *
202  * 06 15 2010 cp.wu
203  * [WPD00003833][MT6620 and MT5931] Driver migration
204  * .
205  *
206  * 06 14 2010 cp.wu
207  * [WPD00003833][MT6620 and MT5931] Driver migration
208  * fill extra information for revised HIF_TX_HEADER.
209  *
210  * 06 11 2010 cp.wu
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
217  *
218  * 06 10 2010 cp.wu
219  * [WPD00003833][MT6620 and MT5931] Driver migration
220  * change to enqueue TX frame infinitely.
221  *
222  * 06 09 2010 cp.wu
223  * [WPD00003833][MT6620 and MT5931] Driver migration
224  * add TX_PACKET_MGMT to indicate the frame is coming from management modules
225  *
226  * 06 06 2010 kevin.huang
227  * [WPD00003832][MT6620 5931] Create driver base
228  * [MT6620 5931] Create driver base
229  *
230  * 05 10 2010 cp.wu
231  * [WPD00003831][MT6620 Wi-Fi] Add framework for Wi-Fi Direct support
232  * fill network type field while doing frame identification.
233  *
234  * 04 23 2010 cp.wu
235  * [WPD00001943]Create WiFi test driver framework on WinXP
236  * surpress compiler warning
237  *
238  * 04 06 2010 jeffrey.chang
239  * [WPD00003826]Initial import for Linux port
240  * Tag the packet for QoS on Tx path
241  *
242  * 03 30 2010 cp.wu
243  * [WPD00001943]Create WiFi test driver framework on WinXP
244  * remove driver-land statistics.
245  *
246  * 03 29 2010 jeffrey.chang
247  * [WPD00003826]Initial import for Linux port
248  * improve none-glue code portability
249  *
250  * 03 24 2010 jeffrey.chang
251  * [WPD00003826]Initial import for Linux port
252  * initial import for Linux port
253  *
254  * 03 24 2010 cp.wu
255  * [WPD00001943]Create WiFi test driver framework on WinXP
256  * generate information for OID_GEN_RCV_OK & OID_GEN_XMIT_OK
257  *  *  *  *  *
258  *
259 * 03 10 2010 cp.wu
260  * [WPD00001943]Create WiFi test driver framework on WinXP
261  * code clean: removing unused variables and structure definitions
262  *
263  * 03 08 2010 cp.wu
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
267  *
268  * 03 02 2010 cp.wu
269  * [WPD00001943]Create WiFi test driver framework on WinXP
270  * add mutex to avoid multiple access to qmTxQueue simultaneously.
271  *
272  * 02 26 2010 cp.wu
273  * [WPD00001943]Create WiFi test driver framework on WinXP
274  * avoid refering to NDIS-specific data structure directly from non-glue layer.
275  *
276  * 02 24 2010 cp.wu
277  * [WPD00001943]Create WiFi test driver framework on WinXP
278  * add Ethernet destination address information in packet info for TX
279  *
280  * 02 10 2010 cp.wu
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
288  *
289  * 02 09 2010 cp.wu
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
294  *
295  * 02 08 2010 cp.wu
296  * [WPD00001943]Create WiFi test driver framework on WinXP
297  * prepare for implementing fw download logic
298  *
299  * 01 27 2010 cp.wu
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
305  *
306  * 01 13 2010 tehuang.liu
307  * [WPD00001943]Create WiFi test driver framework on WinXP
308  * Enabled the Burst_End Indication mechanism
309  *
310  * 01 13 2010 cp.wu
311  * [WPD00001943]Create WiFi test driver framework on WinXP
312  * TX: fill ucWlanHeaderLength/ucPktFormtId_Flags according to info provided by prMsduInfo
313  *
314  * 12 30 2009 cp.wu
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
321 **  remove unused API
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
334 **  Add debug message
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
344 **  fill u2SeqNo
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
368 **  modify HAL part
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
375 **  Add debug message
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
389 **  Support PKGUIO
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
399 **  Fix LINT warning
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
403 **  Init for develop
404 **
405 */
406
407 /*******************************************************************************
408 *                         C O M P I L E R   F L A G S
409 ********************************************************************************
410 */
411
412 /*******************************************************************************
413 *                    E X T E R N A L   R E F E R E N C E S
414 ********************************************************************************
415 */
416 #include "precomp.h"
417
418 /*******************************************************************************
419 *                              C O N S T A N T S
420 ********************************************************************************
421 */
422
423 /*******************************************************************************
424 *                             D A T A   T Y P E S
425 ********************************************************************************
426 */
427
428 /*******************************************************************************
429 *                            P U B L I C   D A T A
430 ********************************************************************************
431 */
432
433 /*******************************************************************************
434 *                           P R I V A T E   D A T A
435 ********************************************************************************
436 */
437
438 /*******************************************************************************
439 *                                 M A C R O S
440 ********************************************************************************
441 */
442
443 /*******************************************************************************
444 *                  F U N C T I O N   D E C L A R A T I O N S
445 ********************************************************************************
446 */
447
448 /*******************************************************************************
449 *                              F U N C T I O N S
450 ********************************************************************************
451 */
452 /*----------------------------------------------------------------------------*/
453 /*!
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.
456 *
457 * @param prAdapter  Pointer to the Adapter structure.
458 *
459 * @return (none)
460 */
461 /*----------------------------------------------------------------------------*/
462 VOID
463 nicTxInitialize (
464     IN P_ADAPTER_T  prAdapter
465     )
466 {
467     P_TX_CTRL_T prTxCtrl;
468     PUINT_8 pucMemHandle;
469     P_MSDU_INFO_T prMsduInfo;
470     UINT_32 i;
471     KAL_SPIN_LOCK_DECLARATION();
472
473     DEBUGFUNC("nicTxInitialize");
474
475     ASSERT(prAdapter);
476     prTxCtrl = &prAdapter->rTxCtrl;
477
478     //4 <1> Initialization of Traffic Class Queue Parameters
479     nicTxResetResource(prAdapter);
480
481 #if CFG_SDIO_TX_AGG
482     prTxCtrl->pucTxCoalescingBufPtr = prAdapter->pucCoalescingBufCached;
483 #endif /* CFG_SDIO_TX_AGG */
484
485     // allocate MSDU_INFO_T and link it into rFreeMsduInfoList
486     QUEUE_INITIALIZE(&prTxCtrl->rFreeMsduInfoList);
487
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));
492
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);
496
497         pucMemHandle += ALIGN_4(sizeof(MSDU_INFO_T));
498     }
499
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);
503
504     QUEUE_INITIALIZE(&prTxCtrl->rTxMgmtTxingQueue);
505     prTxCtrl->i4TxMgmtPendingNum = 0;
506
507 #if CFG_HIF_STATISTICS
508     prTxCtrl->u4TotalTxAccessNum = 0;
509     prTxCtrl->u4TotalTxPacketNum = 0;
510 #endif
511
512     prTxCtrl->i4PendingFwdFrameCount = 0;
513
514     qmInit(prAdapter);
515
516     TX_RESET_ALL_CNTS(prTxCtrl);
517
518     return;
519 } /* end of nicTxInitialize() */
520
521
522 /*----------------------------------------------------------------------------*/
523 /*!
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.
527 *
528 * \param[in] prAdapter              Pointer to the Adapter structure.
529 * \param[in] ucTC                   Specify the resource of TC
530 *
531 * \retval WLAN_STATUS_SUCCESS   Resource is available and been assigned.
532 * \retval WLAN_STATUS_RESOURCES Resource is not available.
533 */
534 /*----------------------------------------------------------------------------*/
535 WLAN_STATUS
536 nicTxAcquireResource (
537     IN P_ADAPTER_T  prAdapter,
538     IN UINT_8       ucTC
539     )
540 {
541     P_TX_CTRL_T prTxCtrl;
542     WLAN_STATUS u4Status = WLAN_STATUS_RESOURCES;
543     KAL_SPIN_LOCK_DECLARATION();
544
545     ASSERT(prAdapter);
546     prTxCtrl = &prAdapter->rTxCtrl;
547
548
549     KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_RESOURCE);
550
551 //    DbgPrint("nicTxAcquireResource prTxCtrl->rTc.aucFreeBufferCount[%d]=%d\n", ucTC, prTxCtrl->rTc.aucFreeBufferCount[ucTC]);
552
553     if (prTxCtrl->rTc.aucFreeBufferCount[ucTC]) {
554
555         prTxCtrl->rTc.aucFreeBufferCount[ucTC]--;
556
557         DBGLOG(TX, EVENT, ("Acquire: TC = %d aucFreeBufferCount = %d\n",
558             ucTC, prTxCtrl->rTc.aucFreeBufferCount[ucTC]));
559
560         u4Status = WLAN_STATUS_SUCCESS;
561     }
562     KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_RESOURCE);
563
564     return u4Status;
565
566 }/* end of nicTxAcquireResourceAndTFCBs() */
567
568
569 /*----------------------------------------------------------------------------*/
570 /*!
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.
574 *
575 * @param prAdapter      Pointer to the Adapter structure.
576 * @param ucTC           Specify the resource of TC
577 *
578 * @retval WLAN_STATUS_SUCCESS   Resource is available.
579 * @retval WLAN_STATUS_FAILURE   Resource is not available.
580 */
581 /*----------------------------------------------------------------------------*/
582 WLAN_STATUS
583 nicTxPollingResource (
584     IN P_ADAPTER_T  prAdapter,
585     IN UINT_8       ucTC
586     )
587 {
588     P_TX_CTRL_T prTxCtrl;
589     WLAN_STATUS u4Status = WLAN_STATUS_FAILURE;
590     INT_32 i = NIC_TX_RESOURCE_POLLING_TIMEOUT;
591     UINT_32 au4WTSR[2];
592
593     ASSERT(prAdapter);
594     prTxCtrl = &prAdapter->rTxCtrl;
595
596     if (ucTC >= TC_NUM) {
597         return WLAN_STATUS_FAILURE;
598     }
599
600     if (prTxCtrl->rTc.aucFreeBufferCount[ucTC] > 0) {
601         return WLAN_STATUS_SUCCESS;
602     }
603
604     while (i-- > 0) {
605         HAL_READ_TX_RELEASED_COUNT(prAdapter, au4WTSR);
606
607         if(kalIsCardRemoved(prAdapter->prGlueInfo) == TRUE
608                 || fgIsBusAccessFailed == TRUE) {
609             u4Status = WLAN_STATUS_FAILURE;
610             break;
611         }
612         else if (nicTxReleaseResource(prAdapter, (PUINT_8)au4WTSR)) {
613             if (prTxCtrl->rTc.aucFreeBufferCount[ucTC] > 0) {
614                 u4Status = WLAN_STATUS_SUCCESS;
615                 break;
616             }
617             else {
618                 kalMsleep(NIC_TX_RESOURCE_POLLING_DELAY_MSEC);
619             }
620         }
621         else {
622             kalMsleep(NIC_TX_RESOURCE_POLLING_DELAY_MSEC);
623         }
624     }
625
626 #if DBG
627     {
628         INT_32 i4Times = NIC_TX_RESOURCE_POLLING_TIMEOUT - (i+1);
629
630         if (i4Times) {
631             DBGLOG(TX, TRACE, ("Polling MCR_WTSR delay %d times, %d msec\n",
632                 i4Times, (i4Times * NIC_TX_RESOURCE_POLLING_DELAY_MSEC)));
633         }
634     }
635 #endif /* DBG */
636
637     return u4Status;
638
639 } /* end of nicTxPollingResource() */
640
641
642 /*----------------------------------------------------------------------------*/
643 /*!
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.
647 *
648 * \param[in] prAdapter              Pointer to the Adapter structure.
649 * \param[in] u4TxStatusCnt          Value of TX STATUS
650 *
651 * @return (none)
652 */
653 /*----------------------------------------------------------------------------*/
654 BOOLEAN
655 nicTxReleaseResource (
656     IN P_ADAPTER_T  prAdapter,
657     IN UINT_8*      aucTxRlsCnt
658     )
659 {
660     PUINT_32 pu4Tmp = (PUINT_32)aucTxRlsCnt;
661     P_TX_CTRL_T prTxCtrl;
662     BOOLEAN bStatus = FALSE;
663     UINT_32 i;
664
665     KAL_SPIN_LOCK_DECLARATION();
666
667
668     ASSERT(prAdapter);
669     prTxCtrl = &prAdapter->rTxCtrl;
670
671     // DBGLOG(TX, TRACE, ("\n"));
672
673     if (pu4Tmp[0] | pu4Tmp[1]) {
674
675         KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_RESOURCE);
676         for (i = 0; i < TC_NUM; i++) {
677             prTxCtrl->rTc.aucFreeBufferCount[i] += aucTxRlsCnt[i];
678
679             if ((i==1) || (i==5)){
680                 DBGLOG(TX, EVENT, ("Release: i = %d aucFreeBufferCount = %d\n",
681                     i, prTxCtrl->rTc.aucFreeBufferCount[i]));
682             }
683         }
684         KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_RESOURCE);
685 #if 0
686         for (i = 0; i < TC_NUM; i++) {
687             DBGLOG(INIT, TRACE, ("aucFreeBufferCount[%d]: %d, aucMaxNumOfBuffer[%d]: %d\n",
688                 i, prTxCtrl->rTc.aucFreeBufferCount[i], i, prTxCtrl->rTc.aucMaxNumOfBuffer[i]));
689         }
690         DbgPrint("prTxCtrl->rTc.aucFreeBufferCount[0]=%d\n", prTxCtrl->rTc.aucFreeBufferCount[0]);
691         DbgPrint("prTxCtrl->rTc.aucFreeBufferCount[1]=%d\n", prTxCtrl->rTc.aucFreeBufferCount[1]);
692         DbgPrint("prTxCtrl->rTc.aucFreeBufferCount[2]=%d\n", prTxCtrl->rTc.aucFreeBufferCount[2]);
693         DbgPrint("prTxCtrl->rTc.aucFreeBufferCount[3]=%d\n", prTxCtrl->rTc.aucFreeBufferCount[3]);
694         DbgPrint("prTxCtrl->rTc.aucFreeBufferCount[4]=%d\n", prTxCtrl->rTc.aucFreeBufferCount[4]);
695         DbgPrint("prTxCtrl->rTc.aucFreeBufferCount[5]=%d\n", prTxCtrl->rTc.aucFreeBufferCount[5]);
696 #endif
697         ASSERT(prTxCtrl->rTc.aucFreeBufferCount[TC0_INDEX] <= prTxCtrl->rTc.aucMaxNumOfBuffer[TC0_INDEX]);
698         ASSERT(prTxCtrl->rTc.aucFreeBufferCount[TC1_INDEX] <= prTxCtrl->rTc.aucMaxNumOfBuffer[TC1_INDEX]);
699         ASSERT(prTxCtrl->rTc.aucFreeBufferCount[TC2_INDEX] <= prTxCtrl->rTc.aucMaxNumOfBuffer[TC2_INDEX]);
700         ASSERT(prTxCtrl->rTc.aucFreeBufferCount[TC3_INDEX] <= prTxCtrl->rTc.aucMaxNumOfBuffer[TC3_INDEX]);
701         ASSERT(prTxCtrl->rTc.aucFreeBufferCount[TC4_INDEX] <= prTxCtrl->rTc.aucMaxNumOfBuffer[TC4_INDEX]);
702         ASSERT(prTxCtrl->rTc.aucFreeBufferCount[TC5_INDEX] <= prTxCtrl->rTc.aucMaxNumOfBuffer[TC5_INDEX]);
703         bStatus = TRUE;
704     }
705
706     return bStatus;
707 } /* end of nicTxReleaseResource() */
708
709
710 /*----------------------------------------------------------------------------*/
711 /*!
712 * \brief Reset TC Buffer Count to initialized value
713 *
714 * \param[in] prAdapter              Pointer to the Adapter structure.
715 *
716 * @return WLAN_STATUS_SUCCESS
717 */
718 /*----------------------------------------------------------------------------*/
719 WLAN_STATUS
720 nicTxResetResource (
721     IN P_ADAPTER_T  prAdapter
722     )
723 {
724     P_TX_CTRL_T prTxCtrl;
725
726     KAL_SPIN_LOCK_DECLARATION();
727
728     DEBUGFUNC("nicTxResetResource");
729
730     ASSERT(prAdapter);
731     prTxCtrl = &prAdapter->rTxCtrl;
732
733     KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_RESOURCE);
734
735     prTxCtrl->rTc.aucMaxNumOfBuffer[TC0_INDEX] = NIC_TX_BUFF_COUNT_TC0;
736     prTxCtrl->rTc.aucFreeBufferCount[TC0_INDEX] = NIC_TX_BUFF_COUNT_TC0;
737
738     prTxCtrl->rTc.aucMaxNumOfBuffer[TC1_INDEX] = NIC_TX_BUFF_COUNT_TC1;
739     prTxCtrl->rTc.aucFreeBufferCount[TC1_INDEX] = NIC_TX_BUFF_COUNT_TC1;
740
741     prTxCtrl->rTc.aucMaxNumOfBuffer[TC2_INDEX] = NIC_TX_BUFF_COUNT_TC2;
742     prTxCtrl->rTc.aucFreeBufferCount[TC2_INDEX] = NIC_TX_BUFF_COUNT_TC2;
743
744     prTxCtrl->rTc.aucMaxNumOfBuffer[TC3_INDEX] = NIC_TX_BUFF_COUNT_TC3;
745     prTxCtrl->rTc.aucFreeBufferCount[TC3_INDEX] = NIC_TX_BUFF_COUNT_TC3;
746
747     prTxCtrl->rTc.aucMaxNumOfBuffer[TC4_INDEX] = NIC_TX_BUFF_COUNT_TC4;
748     prTxCtrl->rTc.aucFreeBufferCount[TC4_INDEX] = NIC_TX_BUFF_COUNT_TC4;
749
750     prTxCtrl->rTc.aucMaxNumOfBuffer[TC5_INDEX] = NIC_TX_BUFF_COUNT_TC5;
751     prTxCtrl->rTc.aucFreeBufferCount[TC5_INDEX] = NIC_TX_BUFF_COUNT_TC5;
752
753     KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_RESOURCE);
754
755     return WLAN_STATUS_SUCCESS;
756 }
757
758
759 /*----------------------------------------------------------------------------*/
760 /*!
761 * @brief Driver maintain a variable that is synchronous with the usage of individual
762 *        TC Buffer Count. This function will return the value for other component
763 *        which needs this information for making decisions
764 *
765 * @param prAdapter      Pointer to the Adapter structure.
766 * @param ucTC           Specify the resource of TC
767 *
768 * @retval UINT_8        The number of corresponding TC number
769 */
770 /*----------------------------------------------------------------------------*/
771 UINT_8
772 nicTxGetResource (
773     IN P_ADAPTER_T  prAdapter,
774     IN UINT_8       ucTC
775     )
776 {
777     P_TX_CTRL_T prTxCtrl;
778
779     ASSERT(prAdapter);
780     prTxCtrl = &prAdapter->rTxCtrl;
781
782     ASSERT(prTxCtrl);
783
784     if (ucTC >= TC_NUM) {
785         return 0;
786     }
787     else {
788         return prTxCtrl->rTc.aucFreeBufferCount[ucTC];
789     }
790 }
791
792
793 /*----------------------------------------------------------------------------*/
794 /*!
795 * @brief In this function, we'll aggregate frame(PACKET_INFO_T)
796 * corresponding to HIF TX port
797 *
798 * @param prAdapter              Pointer to the Adapter structure.
799 * @param prMsduInfoListHead     a link list of P_MSDU_INFO_T
800 *
801 * @retval WLAN_STATUS_SUCCESS   Bus access ok.
802 * @retval WLAN_STATUS_FAILURE   Bus access fail.
803 */
804 /*----------------------------------------------------------------------------*/
805 WLAN_STATUS
806 nicTxMsduInfoList (
807     IN P_ADAPTER_T      prAdapter,
808     IN P_MSDU_INFO_T    prMsduInfoListHead
809     )
810 {
811     P_MSDU_INFO_T prMsduInfo, prNextMsduInfo;
812     QUE_T qDataPort0, qDataPort1;
813     WLAN_STATUS status;
814
815     ASSERT(prAdapter);
816     ASSERT(prMsduInfoListHead);
817
818     prMsduInfo = prMsduInfoListHead;
819
820     QUEUE_INITIALIZE(&qDataPort0);
821     QUEUE_INITIALIZE(&qDataPort1);
822
823     // Separate MSDU_INFO_T lists into 2 categories: for Port#0 & Port#1
824     while(prMsduInfo) {
825         prNextMsduInfo = (P_MSDU_INFO_T)QUEUE_GET_NEXT_ENTRY((P_QUE_ENTRY_T)prMsduInfo);
826 #if DBG && 0
827         LOG_FUNC("nicTxMsduInfoList Acquire TC %d net %u mac len %u len %u Type %u 1x %u 11 %u\n",
828             prMsduInfo->ucTC,
829                 prMsduInfo->ucNetworkType,
830                 prMsduInfo->ucMacHeaderLength,
831             prMsduInfo->u2FrameLength,
832             prMsduInfo->ucPacketType,
833             prMsduInfo->fgIs802_1x,
834             prMsduInfo->fgIs802_11 );
835
836         LOG_FUNC("Dest Mac: " MACSTR "\n",
837                 MAC2STR(prMsduInfo->aucEthDestAddr));
838 #endif
839
840         switch(prMsduInfo->ucTC) {
841         case TC0_INDEX:
842         case TC1_INDEX:
843         case TC2_INDEX:
844         case TC3_INDEX:
845         case TC5_INDEX: // Broadcast/multicast data packets
846             QUEUE_GET_NEXT_ENTRY((P_QUE_ENTRY_T)prMsduInfo) = NULL;
847             QUEUE_INSERT_TAIL(&qDataPort0, (P_QUE_ENTRY_T)prMsduInfo);
848             status = nicTxAcquireResource(prAdapter, prMsduInfo->ucTC);
849             ASSERT(status == WLAN_STATUS_SUCCESS)
850
851             break;
852
853         case TC4_INDEX: // Command or 802.1x packets
854             QUEUE_GET_NEXT_ENTRY((P_QUE_ENTRY_T)prMsduInfo) = NULL;
855             QUEUE_INSERT_TAIL(&qDataPort1, (P_QUE_ENTRY_T)prMsduInfo);
856
857             status = nicTxAcquireResource(prAdapter, prMsduInfo->ucTC);
858             ASSERT(status == WLAN_STATUS_SUCCESS)
859
860             break;
861
862         default:
863             ASSERT(0);
864             break;
865         }
866
867         prMsduInfo = prNextMsduInfo;
868     }
869
870     if(qDataPort0.u4NumElem > 0) {
871         nicTxMsduQueue(prAdapter, 0, &qDataPort0);
872     }
873
874     if(qDataPort1.u4NumElem > 0) {
875         nicTxMsduQueue(prAdapter, 1, &qDataPort1);
876     }
877
878     return WLAN_STATUS_SUCCESS;
879 }
880
881
882 /*----------------------------------------------------------------------------*/
883 /*!
884 * @brief In this function, we'll write frame(PACKET_INFO_T) into HIF.
885 *
886 * @param prAdapter              Pointer to the Adapter structure.
887 * @param ucPortIdx              Port Number
888 * @param prQue                  a link list of P_MSDU_INFO_T
889 *
890 * @retval WLAN_STATUS_SUCCESS   Bus access ok.
891 * @retval WLAN_STATUS_FAILURE   Bus access fail.
892 */
893 /*----------------------------------------------------------------------------*/
894 WLAN_STATUS
895 nicTxMsduQueue (
896     IN P_ADAPTER_T  prAdapter,
897     UINT_8          ucPortIdx,
898     P_QUE_T         prQue
899     )
900 {
901     P_MSDU_INFO_T prMsduInfo, prNextMsduInfo;
902     HIF_TX_HEADER_T rHwTxHeader;
903     P_NATIVE_PACKET prNativePacket;
904     UINT_16 u2OverallBufferLength;
905     UINT_8 ucEtherTypeOffsetInWord;
906     PUINT_8 pucOutputBuf = (PUINT_8)NULL; /* Pointer to Transmit Data Structure Frame */
907     UINT_32 u4TxHdrSize;
908     UINT_32 u4ValidBufSize;
909     UINT_32 u4TotalLength;
910     P_TX_CTRL_T prTxCtrl;
911     QUE_T rFreeQueue;
912 #if CFG_TCP_IP_CHKSUM_OFFLOAD
913     UINT_8 ucChksumFlag;
914 #endif
915
916     ASSERT(prAdapter);
917     ASSERT(ucPortIdx < 2);
918     ASSERT(prQue);
919
920     prTxCtrl = &prAdapter->rTxCtrl;
921     u4ValidBufSize = prAdapter->u4CoalescingBufCachedSize;
922
923 #if CFG_HIF_STATISTICS
924     prTxCtrl->u4TotalTxAccessNum++;
925     prTxCtrl->u4TotalTxPacketNum += prQue->u4NumElem;
926 #endif
927
928     QUEUE_INITIALIZE(&rFreeQueue);
929
930     if(prQue->u4NumElem > 0) {
931         prMsduInfo = (P_MSDU_INFO_T)QUEUE_GET_HEAD(prQue);
932         pucOutputBuf = prTxCtrl->pucTxCoalescingBufPtr;
933         u4TotalLength = 0;
934
935         while(prMsduInfo) {
936
937            //  DBGLOG(TX, TRACE, ("SN %d, len %d\n", prMsduInfo->ucTxSeqNum, prMsduInfo->u2FrameLength));
938
939             kalMemZero(&rHwTxHeader, sizeof(rHwTxHeader));
940
941             prNativePacket = prMsduInfo->prPacket;
942
943             ASSERT(prNativePacket);
944
945             u4TxHdrSize = TX_HDR_SIZE;
946
947             u2OverallBufferLength = ((prMsduInfo->u2FrameLength + TX_HDR_SIZE) &
948                     (UINT_16)HIF_TX_HDR_TX_BYTE_COUNT_MASK);
949
950             rHwTxHeader.u2TxByteCount_UserPriority = u2OverallBufferLength;
951             rHwTxHeader.u2TxByteCount_UserPriority |=
952                 ((UINT_16)prMsduInfo->ucUserPriority << HIF_TX_HDR_USER_PRIORITY_OFFSET);
953
954             if (prMsduInfo->fgIs802_11) {
955                 ucEtherTypeOffsetInWord =
956                     (TX_HDR_SIZE + prMsduInfo->ucMacHeaderLength + prMsduInfo->ucLlcLength) >> 1;
957             }
958             else {
959                 ucEtherTypeOffsetInWord =
960                     ((ETHER_HEADER_LEN - ETHER_TYPE_LEN) + TX_HDR_SIZE) >> 1;
961             }
962
963             rHwTxHeader.ucEtherTypeOffset =
964                 ucEtherTypeOffsetInWord & HIF_TX_HDR_ETHER_TYPE_OFFSET_MASK;
965
966             rHwTxHeader.ucResource_PktType_CSflags = (prMsduInfo->ucTC) << HIF_TX_HDR_RESOURCE_OFFSET;
967             rHwTxHeader.ucResource_PktType_CSflags |=
968                 (UINT_8)(((prMsduInfo->ucPacketType) << HIF_TX_HDR_PACKET_TYPE_OFFSET) &
969                         (HIF_TX_HDR_PACKET_TYPE_MASK));
970
971 #if CFG_TCP_IP_CHKSUM_OFFLOAD
972             if (prMsduInfo->eSrc == TX_PACKET_OS
973                     || prMsduInfo->eSrc == TX_PACKET_FORWARDING) {
974                 if (prAdapter->u4CSUMFlags &
975                         (CSUM_OFFLOAD_EN_TX_TCP |
976                          CSUM_OFFLOAD_EN_TX_UDP |
977                          CSUM_OFFLOAD_EN_TX_IP)) {
978                     kalQueryTxChksumOffloadParam(prNativePacket, &ucChksumFlag);
979
980                     if (ucChksumFlag & TX_CS_IP_GEN) {
981                         rHwTxHeader.ucResource_PktType_CSflags |= (UINT_8)HIF_TX_HDR_IP_CSUM;
982                     }
983
984                     if (ucChksumFlag & TX_CS_TCP_UDP_GEN) {
985                         rHwTxHeader.ucResource_PktType_CSflags |= (UINT_8)HIF_TX_HDR_TCP_CSUM;
986                     }
987                 }
988             }
989 #endif /* CFG_TCP_IP_CHKSUM_OFFLOAD */
990
991             rHwTxHeader.u2LLH = prMsduInfo->u2PalLLH;
992             rHwTxHeader.ucStaRecIdx = prMsduInfo->ucStaRecIndex;
993             rHwTxHeader.ucForwardingType_SessionID_Reserved =
994                 (prMsduInfo->ucPsForwardingType) | ((prMsduInfo->ucPsSessionID) << HIF_TX_HDR_PS_SESSION_ID_OFFSET)
995                 | ((prMsduInfo->fgIsBurstEnd)? HIF_TX_HDR_BURST_END_MASK : 0);
996
997             rHwTxHeader.ucWlanHeaderLength = (prMsduInfo->ucMacHeaderLength & HIF_TX_HDR_WLAN_HEADER_LEN_MASK);
998             rHwTxHeader.ucPktFormtId_Flags =
999                 (prMsduInfo->ucFormatID & HIF_TX_HDR_FORMAT_ID_MASK)
1000                 | ((prMsduInfo->ucNetworkType << HIF_TX_HDR_NETWORK_TYPE_OFFSET) & HIF_TX_HDR_NETWORK_TYPE_MASK)
1001                 | ((prMsduInfo->fgIs802_1x << HIF_TX_HDR_FLAG_1X_FRAME_OFFSET) & HIF_TX_HDR_FLAG_1X_FRAME_MASK)
1002                 | ((prMsduInfo->fgIs802_11 << HIF_TX_HDR_FLAG_802_11_FORMAT_OFFSET) & HIF_TX_HDR_FLAG_802_11_FORMAT_MASK);
1003
1004             rHwTxHeader.u2SeqNo = prMsduInfo->u2AclSN;
1005
1006             if(prMsduInfo->pfTxDoneHandler) {
1007                 rHwTxHeader.ucPacketSeqNo = prMsduInfo->ucTxSeqNum;
1008                 rHwTxHeader.ucAck_BIP_BasicRate = HIF_TX_HDR_NEED_ACK;
1009             }
1010             else {
1011                 rHwTxHeader.ucPacketSeqNo = 0;
1012                 rHwTxHeader.ucAck_BIP_BasicRate = 0;
1013             }
1014
1015             if(prMsduInfo->fgIsBIP) {
1016                 rHwTxHeader.ucAck_BIP_BasicRate |= HIF_TX_HDR_BIP;
1017             }
1018
1019             if(prMsduInfo->fgIsBasicRate) {
1020                 rHwTxHeader.ucAck_BIP_BasicRate |= HIF_TX_HDR_BASIC_RATE;
1021             }
1022
1023 #if CFG_SDIO_TX_AGG
1024             // attach to coalescing buffer
1025             kalMemCopy(pucOutputBuf + u4TotalLength, &rHwTxHeader, u4TxHdrSize);
1026             u4TotalLength += u4TxHdrSize;
1027
1028             if (prMsduInfo->eSrc == TX_PACKET_OS
1029                     || prMsduInfo->eSrc == TX_PACKET_FORWARDING) {
1030                 kalCopyFrame(prAdapter->prGlueInfo,
1031                         prNativePacket,
1032                         pucOutputBuf + u4TotalLength);
1033             }
1034             else if(prMsduInfo->eSrc == TX_PACKET_MGMT) {
1035                 kalMemCopy(pucOutputBuf + u4TotalLength,
1036                         prNativePacket,
1037                         prMsduInfo->u2FrameLength);
1038             }
1039             else {
1040                 ASSERT(0);
1041             }
1042
1043             u4TotalLength += ALIGN_4(prMsduInfo->u2FrameLength);
1044
1045 #else
1046             kalMemCopy(pucOutputBuf, &rHwTxHeader, u4TxHdrSize);
1047
1048             /* Copy Frame Body */
1049             if (prMsduInfo->eSrc == TX_PACKET_OS
1050                     || prMsduInfo->eSrc == TX_PACKET_FORWARDING) {
1051                 kalCopyFrame(prAdapter->prGlueInfo,
1052                         prNativePacket,
1053                         pucOutputBuf + u4TxHdrSize);
1054             }
1055             else if(prMsduInfo->eSrc == TX_PACKET_MGMT) {
1056                 kalMemCopy(pucOutputBuf + u4TxHdrSize,
1057                         prNativePacket,
1058                         prMsduInfo->u2FrameLength);
1059             }
1060             else {
1061                 ASSERT(0);
1062             }
1063
1064             ASSERT(u2OverallBufferLength <= u4ValidBufSize);
1065
1066             HAL_WRITE_TX_PORT(prAdapter,
1067                     ucPortIdx,
1068                     (UINT_32)u2OverallBufferLength,
1069                     (PUINT_8)pucOutputBuf,
1070                     u4ValidBufSize);
1071
1072             // send immediately
1073 #endif
1074             prNextMsduInfo = (P_MSDU_INFO_T)
1075                         QUEUE_GET_NEXT_ENTRY(&prMsduInfo->rQueEntry);
1076
1077             if (prMsduInfo->eSrc == TX_PACKET_MGMT) {
1078                 GLUE_DEC_REF_CNT(prTxCtrl->i4TxMgmtPendingNum);
1079
1080                 if (prMsduInfo->pfTxDoneHandler == NULL) {
1081                     cnmMgtPktFree(prAdapter, prMsduInfo);
1082                 }
1083                 else {
1084                     KAL_SPIN_LOCK_DECLARATION();
1085                     DBGLOG(INIT, TRACE,("Wait TxSeqNum:%d\n", prMsduInfo->ucTxSeqNum));
1086                     KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TXING_MGMT_LIST);
1087                     QUEUE_INSERT_TAIL(&(prTxCtrl->rTxMgmtTxingQueue), (P_QUE_ENTRY_T)prMsduInfo);
1088                     KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TXING_MGMT_LIST);
1089                 }
1090             }
1091             else {
1092                 /* only free MSDU when it is not a MGMT frame */
1093                 QUEUE_INSERT_TAIL(&rFreeQueue, (P_QUE_ENTRY_T)prMsduInfo);
1094
1095                 if (prMsduInfo->eSrc == TX_PACKET_OS) {
1096                     kalSendComplete(prAdapter->prGlueInfo,
1097                             prNativePacket,
1098                             WLAN_STATUS_SUCCESS);
1099                 }
1100                 else if(prMsduInfo->eSrc == TX_PACKET_FORWARDING) {
1101                     GLUE_DEC_REF_CNT(prTxCtrl->i4PendingFwdFrameCount);
1102                 }
1103             }
1104
1105             prMsduInfo = prNextMsduInfo;
1106         }
1107
1108 #if CFG_SDIO_TX_AGG
1109         ASSERT(u4TotalLength <= u4ValidBufSize);
1110
1111     #if CFG_DBG_GPIO_PINS
1112         {
1113             /* Start port write */
1114             mtk_wcn_stp_debug_gpio_assert(IDX_TX_PORT_WRITE, DBG_TIE_LOW);
1115             kalUdelay(1);
1116             mtk_wcn_stp_debug_gpio_assert(IDX_TX_PORT_WRITE, DBG_TIE_HIGH);
1117         }
1118     #endif
1119
1120         // send coalescing buffer
1121         HAL_WRITE_TX_PORT(prAdapter,
1122                 ucPortIdx,
1123                 u4TotalLength,
1124                 (PUINT_8)pucOutputBuf,
1125                 u4ValidBufSize);
1126 #endif
1127
1128         // return
1129         nicTxReturnMsduInfo(prAdapter, (P_MSDU_INFO_T)QUEUE_GET_HEAD(&rFreeQueue));
1130     }
1131
1132     return WLAN_STATUS_SUCCESS;
1133 }
1134
1135
1136 /*----------------------------------------------------------------------------*/
1137 /*!
1138 * \brief In this function, we'll write Command(CMD_INFO_T) into HIF.
1139 *
1140 * @param prAdapter      Pointer to the Adapter structure.
1141 * @param prPacketInfo   Pointer of CMD_INFO_T
1142 * @param ucTC           Specify the resource of TC
1143 *
1144 * @retval WLAN_STATUS_SUCCESS   Bus access ok.
1145 * @retval WLAN_STATUS_FAILURE   Bus access fail.
1146 */
1147 /*----------------------------------------------------------------------------*/
1148 WLAN_STATUS
1149 nicTxCmd (
1150     IN P_ADAPTER_T      prAdapter,
1151     IN P_CMD_INFO_T     prCmdInfo,
1152     IN UINT_8           ucTC
1153     )
1154 {
1155     P_WIFI_CMD_T prWifiCmd;
1156     UINT_16 u2OverallBufferLength;
1157     PUINT_8 pucOutputBuf = (PUINT_8)NULL; /* Pointer to Transmit Data Structure Frame */
1158     UINT_8 ucPortIdx;
1159     HIF_TX_HEADER_T rHwTxHeader;
1160     P_NATIVE_PACKET prNativePacket;
1161     UINT_8 ucEtherTypeOffsetInWord;
1162     P_MSDU_INFO_T prMsduInfo;
1163     P_TX_CTRL_T prTxCtrl;
1164
1165     KAL_SPIN_LOCK_DECLARATION();
1166
1167
1168     ASSERT(prAdapter);
1169     ASSERT(prCmdInfo);
1170
1171     prTxCtrl = &prAdapter->rTxCtrl;
1172     pucOutputBuf = prTxCtrl->pucTxCoalescingBufPtr;
1173
1174     // <1> Assign Data Port
1175     if (ucTC != TC4_INDEX) {
1176         ucPortIdx = 0;
1177     }
1178     else {
1179         // Broadcast/multicast data frames, 1x frames, command packets, MMPDU
1180         ucPortIdx = 1;
1181     }
1182
1183     if(prCmdInfo->eCmdType == COMMAND_TYPE_SECURITY_FRAME) {
1184         // <2> Compose HIF_TX_HEADER
1185         kalMemZero(&rHwTxHeader, sizeof(rHwTxHeader));
1186
1187         prNativePacket = prCmdInfo->prPacket;
1188
1189         ASSERT(prNativePacket);
1190
1191         u2OverallBufferLength = TFCB_FRAME_PAD_TO_DW((prCmdInfo->u2InfoBufLen + TX_HDR_SIZE)
1192                 & (UINT_16)HIF_TX_HDR_TX_BYTE_COUNT_MASK);
1193
1194         rHwTxHeader.u2TxByteCount_UserPriority = ((prCmdInfo->u2InfoBufLen + TX_HDR_SIZE)
1195                 & (UINT_16)HIF_TX_HDR_TX_BYTE_COUNT_MASK);
1196         ucEtherTypeOffsetInWord = ((ETHER_HEADER_LEN - ETHER_TYPE_LEN) + TX_HDR_SIZE) >> 1;
1197
1198         rHwTxHeader.ucEtherTypeOffset =
1199             ucEtherTypeOffsetInWord & HIF_TX_HDR_ETHER_TYPE_OFFSET_MASK;
1200
1201         rHwTxHeader.ucResource_PktType_CSflags = (ucTC << HIF_TX_HDR_RESOURCE_OFFSET);
1202
1203         rHwTxHeader.ucStaRecIdx = prCmdInfo->ucStaRecIndex;
1204         rHwTxHeader.ucForwardingType_SessionID_Reserved = HIF_TX_HDR_BURST_END_MASK;
1205
1206         rHwTxHeader.ucWlanHeaderLength = (ETH_HLEN & HIF_TX_HDR_WLAN_HEADER_LEN_MASK);
1207         rHwTxHeader.ucPktFormtId_Flags =
1208             (((UINT_8)(prCmdInfo->eNetworkType) << HIF_TX_HDR_NETWORK_TYPE_OFFSET) & HIF_TX_HDR_NETWORK_TYPE_MASK)
1209             | ((1 << HIF_TX_HDR_FLAG_1X_FRAME_OFFSET) & HIF_TX_HDR_FLAG_1X_FRAME_MASK);
1210
1211         rHwTxHeader.u2SeqNo = 0;
1212         rHwTxHeader.ucPacketSeqNo = 0;
1213         rHwTxHeader.ucAck_BIP_BasicRate = 0;
1214
1215         // <2.3> Copy HIF TX HEADER
1216         kalMemCopy((PVOID)&pucOutputBuf[0], (PVOID)&rHwTxHeader, TX_HDR_SIZE);
1217
1218         // <3> Copy Frame Body Copy
1219         kalCopyFrame(prAdapter->prGlueInfo,
1220                 prNativePacket,
1221                 pucOutputBuf + TX_HDR_SIZE);
1222     }
1223     else if(prCmdInfo->eCmdType == COMMAND_TYPE_MANAGEMENT_FRAME) {
1224         prMsduInfo = (P_MSDU_INFO_T)prCmdInfo->prPacket;
1225
1226         ASSERT(prMsduInfo->fgIs802_11 == TRUE);
1227         ASSERT(prMsduInfo->eSrc == TX_PACKET_MGMT);
1228
1229         // <2> Compose HIF_TX_HEADER
1230         kalMemZero(&rHwTxHeader, sizeof(rHwTxHeader));
1231
1232         u2OverallBufferLength = ((prMsduInfo->u2FrameLength + TX_HDR_SIZE) &
1233                                   (UINT_16)HIF_TX_HDR_TX_BYTE_COUNT_MASK);
1234
1235         rHwTxHeader.u2TxByteCount_UserPriority = u2OverallBufferLength;
1236         rHwTxHeader.u2TxByteCount_UserPriority |=
1237                 ((UINT_16)prMsduInfo->ucUserPriority << HIF_TX_HDR_USER_PRIORITY_OFFSET);
1238
1239         ucEtherTypeOffsetInWord =
1240                 (TX_HDR_SIZE + prMsduInfo->ucMacHeaderLength + prMsduInfo->ucLlcLength) >> 1;
1241
1242         rHwTxHeader.ucEtherTypeOffset =
1243                 ucEtherTypeOffsetInWord & HIF_TX_HDR_ETHER_TYPE_OFFSET_MASK;
1244
1245         rHwTxHeader.ucResource_PktType_CSflags = (prMsduInfo->ucTC) << HIF_TX_HDR_RESOURCE_OFFSET;
1246         rHwTxHeader.ucResource_PktType_CSflags |=
1247                 (UINT_8)(((prMsduInfo->ucPacketType) << HIF_TX_HDR_PACKET_TYPE_OFFSET) &
1248                                     (HIF_TX_HDR_PACKET_TYPE_MASK));
1249
1250         rHwTxHeader.u2LLH = prMsduInfo->u2PalLLH;
1251         rHwTxHeader.ucStaRecIdx = prMsduInfo->ucStaRecIndex;
1252         rHwTxHeader.ucForwardingType_SessionID_Reserved =
1253             (prMsduInfo->ucPsForwardingType) | ((prMsduInfo->ucPsSessionID) << HIF_TX_HDR_PS_SESSION_ID_OFFSET)
1254             | ((prMsduInfo->fgIsBurstEnd)? HIF_TX_HDR_BURST_END_MASK : 0);
1255
1256         rHwTxHeader.ucWlanHeaderLength = (prMsduInfo->ucMacHeaderLength & HIF_TX_HDR_WLAN_HEADER_LEN_MASK);
1257         rHwTxHeader.ucPktFormtId_Flags =
1258             (prMsduInfo->ucFormatID & HIF_TX_HDR_FORMAT_ID_MASK)
1259             | ((prMsduInfo->ucNetworkType << HIF_TX_HDR_NETWORK_TYPE_OFFSET) & HIF_TX_HDR_NETWORK_TYPE_MASK)
1260             | ((prMsduInfo->fgIs802_1x << HIF_TX_HDR_FLAG_1X_FRAME_OFFSET) & HIF_TX_HDR_FLAG_1X_FRAME_MASK)
1261             | ((prMsduInfo->fgIs802_11 << HIF_TX_HDR_FLAG_802_11_FORMAT_OFFSET) & HIF_TX_HDR_FLAG_802_11_FORMAT_MASK);
1262
1263         rHwTxHeader.u2SeqNo = prMsduInfo->u2AclSN;
1264
1265         if(prMsduInfo->pfTxDoneHandler) {
1266             rHwTxHeader.ucPacketSeqNo = prMsduInfo->ucTxSeqNum;
1267             rHwTxHeader.ucAck_BIP_BasicRate = HIF_TX_HDR_NEED_ACK;
1268         }
1269         else {
1270             rHwTxHeader.ucPacketSeqNo = 0;
1271             rHwTxHeader.ucAck_BIP_BasicRate = 0;
1272         }
1273
1274         if(prMsduInfo->fgIsBIP) {
1275             rHwTxHeader.ucAck_BIP_BasicRate |= HIF_TX_HDR_BIP;
1276         }
1277
1278         if(prMsduInfo->fgIsBasicRate) {
1279             rHwTxHeader.ucAck_BIP_BasicRate |= HIF_TX_HDR_BASIC_RATE;
1280         }
1281
1282         // <2.3> Copy HIF TX HEADER
1283         kalMemCopy((PVOID)&pucOutputBuf[0], (PVOID)&rHwTxHeader, TX_HDR_SIZE);
1284
1285         // <3> Copy Frame Body
1286         kalMemCopy(pucOutputBuf + TX_HDR_SIZE,
1287                 prMsduInfo->prPacket,
1288                 prMsduInfo->u2FrameLength);
1289
1290         // <4> Management Frame Post-Processing
1291         GLUE_DEC_REF_CNT(prTxCtrl->i4TxMgmtPendingNum);
1292
1293         if (prMsduInfo->pfTxDoneHandler == NULL) {
1294             cnmMgtPktFree(prAdapter, prMsduInfo);
1295         }
1296         else {
1297
1298             DBGLOG(INIT, TRACE,("Wait Cmd TxSeqNum:%d\n", prMsduInfo->ucTxSeqNum));
1299
1300             KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TXING_MGMT_LIST);
1301             QUEUE_INSERT_TAIL(&(prTxCtrl->rTxMgmtTxingQueue), (P_QUE_ENTRY_T)prMsduInfo);
1302             KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TXING_MGMT_LIST);
1303         }
1304     }
1305     else {
1306         prWifiCmd = (P_WIFI_CMD_T)prCmdInfo->pucInfoBuffer;
1307
1308         // <2> Compose the Header of Transmit Data Structure for CMD Packet
1309         u2OverallBufferLength = TFCB_FRAME_PAD_TO_DW(
1310                (prCmdInfo->u2InfoBufLen) & (UINT_16)HIF_TX_HDR_TX_BYTE_COUNT_MASK);
1311
1312         prWifiCmd->u2TxByteCount_UserPriority = u2OverallBufferLength;
1313         prWifiCmd->ucEtherTypeOffset = 0;
1314         prWifiCmd->ucResource_PktType_CSflags = (ucTC << HIF_TX_HDR_RESOURCE_OFFSET)
1315             | (UINT_8)((HIF_TX_PKT_TYPE_CMD << HIF_TX_HDR_PACKET_TYPE_OFFSET) & (HIF_TX_HDR_PACKET_TYPE_MASK));
1316
1317
1318         // <3> Copy CMD Header to command buffer (by using pucCoalescingBufCached)
1319         kalMemCopy((PVOID)&pucOutputBuf[0],
1320                    (PVOID)prCmdInfo->pucInfoBuffer,
1321                    prCmdInfo->u2InfoBufLen);
1322
1323         ASSERT(u2OverallBufferLength <= prAdapter->u4CoalescingBufCachedSize);
1324     }
1325
1326     // <4> Write frame to data port
1327     HAL_WRITE_TX_PORT(prAdapter,
1328             ucPortIdx,
1329             (UINT_32)u2OverallBufferLength,
1330             (PUINT_8)pucOutputBuf,
1331             (UINT_32)prAdapter->u4CoalescingBufCachedSize);
1332
1333     return WLAN_STATUS_SUCCESS;
1334 } /* end of nicTxCmd() */
1335
1336
1337 /*----------------------------------------------------------------------------*/
1338 /*!
1339 * @brief This function will clean up all the pending frames in internal SW Queues
1340 *        by return the pending TX packet to the system.
1341 *
1342 * @param prAdapter  Pointer to the Adapter structure.
1343 *
1344 * @return (none)
1345 */
1346 /*----------------------------------------------------------------------------*/
1347 VOID
1348 nicTxRelease (
1349     IN P_ADAPTER_T  prAdapter
1350     )
1351 {
1352     P_TX_CTRL_T prTxCtrl;
1353     P_MSDU_INFO_T prMsduInfo;
1354
1355     KAL_SPIN_LOCK_DECLARATION();
1356
1357     ASSERT(prAdapter);
1358
1359     prTxCtrl = &prAdapter->rTxCtrl;
1360
1361     nicTxFlush(prAdapter);
1362
1363     // free MSDU_INFO_T from rTxMgmtMsduInfoList
1364     do {
1365         KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TXING_MGMT_LIST);
1366         QUEUE_REMOVE_HEAD(&prTxCtrl->rTxMgmtTxingQueue, prMsduInfo, P_MSDU_INFO_T);
1367         KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TXING_MGMT_LIST);
1368
1369         if(prMsduInfo) {
1370             // the packet must be mgmt frame with tx done callback
1371             ASSERT(prMsduInfo->eSrc == TX_PACKET_MGMT);
1372             ASSERT(prMsduInfo->pfTxDoneHandler != NULL);
1373
1374             // invoke done handler
1375             prMsduInfo->pfTxDoneHandler(prAdapter, prMsduInfo, TX_RESULT_LIFE_TIMEOUT);
1376
1377             cnmMgtPktFree(prAdapter, prMsduInfo);
1378         }
1379         else {
1380             break;
1381         }
1382     } while(TRUE);
1383
1384     return;
1385 } /* end of nicTxRelease() */
1386
1387
1388 /*----------------------------------------------------------------------------*/
1389 /*!
1390 * @brief Process the TX Done interrupt and pull in more pending frames in SW
1391 *        Queues for transmission.
1392 *
1393 * @param prAdapter  Pointer to the Adapter structure.
1394 *
1395 * @return (none)
1396 */
1397 /*----------------------------------------------------------------------------*/
1398 VOID
1399 nicProcessTxInterrupt(
1400     IN P_ADAPTER_T prAdapter
1401     )
1402 {
1403     P_TX_CTRL_T prTxCtrl;
1404 #if CFG_SDIO_INTR_ENHANCE
1405     P_SDIO_CTRL_T prSDIOCtrl;
1406 #else
1407     UINT_32 au4TxCount[2];
1408 #endif /* CFG_SDIO_INTR_ENHANCE */
1409
1410     ASSERT(prAdapter);
1411
1412     prTxCtrl = &prAdapter->rTxCtrl;
1413     ASSERT(prTxCtrl);
1414
1415      /* Get the TX STATUS */
1416 #if CFG_SDIO_INTR_ENHANCE
1417
1418     prSDIOCtrl = prAdapter->prSDIOCtrl;
1419     #if DBG
1420     //dumpMemory8((PUINT_8)prSDIOCtrl, sizeof(SDIO_CTRL_T));
1421     #endif
1422
1423     nicTxReleaseResource(prAdapter, (PUINT_8)&prSDIOCtrl->rTxInfo);
1424     kalMemZero(&prSDIOCtrl->rTxInfo, sizeof(prSDIOCtrl->rTxInfo));
1425
1426 #else
1427
1428     HAL_MCR_RD(prAdapter, MCR_WTSR0, &au4TxCount[0]);
1429     HAL_MCR_RD(prAdapter, MCR_WTSR1, &au4TxCount[1]);
1430     DBGLOG(EMU, TRACE, ("MCR_WTSR0: 0x%x, MCR_WTSR1: 0x%x\n", au4TxCount[0], au4TxCount[1]));
1431
1432     nicTxReleaseResource(prAdapter, (PUINT_8)au4TxCount);
1433
1434 #endif /* CFG_SDIO_INTR_ENHANCE */
1435
1436     nicTxAdjustTcq(prAdapter);
1437
1438     // Indicate Service Thread
1439     if(kalGetTxPendingCmdCount(prAdapter->prGlueInfo) > 0
1440             || wlanGetTxPendingFrameCount(prAdapter) > 0) {
1441         kalSetEvent(prAdapter->prGlueInfo);
1442     }
1443
1444     return;
1445 } /* end of nicProcessTxInterrupt() */
1446
1447
1448 /*----------------------------------------------------------------------------*/
1449 /*!
1450 * @brief this function frees packet of P_MSDU_INFO_T linked-list
1451 *
1452 * @param prAdapter              Pointer to the Adapter structure.
1453 * @param prMsduInfoList         a link list of P_MSDU_INFO_T
1454 *
1455 * @return (none)
1456 */
1457 /*----------------------------------------------------------------------------*/
1458 VOID
1459 nicTxFreeMsduInfoPacket (
1460     IN P_ADAPTER_T    prAdapter,
1461     IN P_MSDU_INFO_T  prMsduInfoListHead
1462     )
1463 {
1464     P_NATIVE_PACKET prNativePacket;
1465     P_MSDU_INFO_T prMsduInfo = prMsduInfoListHead;
1466     P_TX_CTRL_T prTxCtrl;
1467
1468
1469     ASSERT(prAdapter);
1470     ASSERT(prMsduInfoListHead);
1471
1472     prTxCtrl = &prAdapter->rTxCtrl;
1473
1474     while(prMsduInfo) {
1475         prNativePacket = prMsduInfo->prPacket;
1476
1477         if(prMsduInfo->eSrc == TX_PACKET_OS) {
1478             kalSendComplete(prAdapter->prGlueInfo,
1479                     prNativePacket,
1480                     WLAN_STATUS_FAILURE);
1481         }
1482         else if(prMsduInfo->eSrc == TX_PACKET_MGMT) {
1483             if (prMsduInfo->pfTxDoneHandler) {
1484                 prMsduInfo->pfTxDoneHandler(prAdapter, prMsduInfo, TX_RESULT_DROPPED_IN_DRIVER);
1485             }
1486             cnmMemFree(prAdapter, prNativePacket);
1487         }
1488         else if(prMsduInfo->eSrc == TX_PACKET_FORWARDING) {
1489             GLUE_DEC_REF_CNT(prTxCtrl->i4PendingFwdFrameCount);
1490         }
1491
1492         prMsduInfo = (P_MSDU_INFO_T)QUEUE_GET_NEXT_ENTRY((P_QUE_ENTRY_T)prMsduInfo);
1493     }
1494
1495     return;
1496 }
1497
1498
1499 /*----------------------------------------------------------------------------*/
1500 /*!
1501 * @brief this function returns P_MSDU_INFO_T of MsduInfoList to TxCtrl->rfreeMsduInfoList
1502 *
1503 * @param prAdapter              Pointer to the Adapter structure.
1504 * @param prMsduInfoList         a link list of P_MSDU_INFO_T
1505 *
1506 * @return (none)
1507 */
1508 /*----------------------------------------------------------------------------*/
1509 VOID
1510 nicTxReturnMsduInfo (
1511     IN P_ADAPTER_T    prAdapter,
1512     IN P_MSDU_INFO_T  prMsduInfoListHead
1513     )
1514 {
1515     P_TX_CTRL_T prTxCtrl;
1516     P_MSDU_INFO_T prMsduInfo = prMsduInfoListHead, prNextMsduInfo;
1517
1518     KAL_SPIN_LOCK_DECLARATION();
1519
1520     ASSERT(prAdapter);
1521
1522     prTxCtrl = &prAdapter->rTxCtrl;
1523     ASSERT(prTxCtrl);
1524
1525     while(prMsduInfo) {
1526         prNextMsduInfo = (P_MSDU_INFO_T)QUEUE_GET_NEXT_ENTRY((P_QUE_ENTRY_T)prMsduInfo);
1527
1528         switch(prMsduInfo->eSrc) {
1529         case TX_PACKET_FORWARDING:
1530             wlanReturnPacket(prAdapter, prMsduInfo->prPacket);
1531             break;
1532         case TX_PACKET_OS:
1533         case TX_PACKET_OS_OID:
1534         case TX_PACKET_MGMT:
1535         default:
1536             break;
1537         }
1538
1539         KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_MSDU_INFO_LIST);
1540         QUEUE_INSERT_TAIL(&prTxCtrl->rFreeMsduInfoList, (P_QUE_ENTRY_T)prMsduInfo);
1541         KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_MSDU_INFO_LIST);
1542         prMsduInfo = prNextMsduInfo;
1543     };
1544
1545     return;
1546 }
1547
1548
1549
1550 /*----------------------------------------------------------------------------*/
1551 /*!
1552 * @brief this function fills packet information to P_MSDU_INFO_T
1553 *
1554 * @param prAdapter              Pointer to the Adapter structure.
1555 * @param prMsduInfo             P_MSDU_INFO_T
1556 * @param prPacket               P_NATIVE_PACKET
1557 *
1558 * @retval TRUE      Success to extract information
1559 * @retval FALSE     Fail to extract correct information
1560 */
1561 /*----------------------------------------------------------------------------*/
1562 BOOLEAN
1563 nicTxFillMsduInfo (
1564     IN P_ADAPTER_T     prAdapter,
1565     IN P_MSDU_INFO_T   prMsduInfo,
1566     IN P_NATIVE_PACKET prPacket
1567     )
1568 {
1569     P_GLUE_INFO_T   prGlueInfo;
1570     UINT_8          ucPriorityParam;
1571     UINT_8          ucMacHeaderLen;
1572     UINT_8          aucEthDestAddr[PARAM_MAC_ADDR_LEN];
1573     BOOLEAN         fgIs1x = FALSE;
1574     BOOLEAN         fgIsPAL = FALSE;
1575     UINT_32         u4PacketLen;
1576     ULONG           u4SysTime;
1577     UINT_8          ucNetworkType;
1578
1579
1580     ASSERT(prAdapter);
1581
1582     prGlueInfo = prAdapter->prGlueInfo;
1583     ASSERT(prGlueInfo);
1584
1585     if (kalQoSFrameClassifierAndPacketInfo(prGlueInfo,
1586                 prPacket,
1587                 &ucPriorityParam,
1588                 &u4PacketLen,
1589                 aucEthDestAddr,
1590                 &fgIs1x,
1591                 &fgIsPAL,
1592                 &ucNetworkType) == FALSE) {
1593         return FALSE;
1594     }
1595
1596     /* Save the value of Priority Parameter */
1597     GLUE_SET_PKT_TID(prPacket, ucPriorityParam);
1598
1599     if (fgIs1x) {
1600         GLUE_SET_PKT_FLAG_1X(prPacket);
1601     }
1602
1603     if (fgIsPAL) {
1604         GLUE_SET_PKT_FLAG_PAL(prPacket);
1605     }
1606
1607     ucMacHeaderLen = ETH_HLEN;
1608
1609     /* Save the value of Header Length */
1610     GLUE_SET_PKT_HEADER_LEN(prPacket, ucMacHeaderLen);
1611
1612     /* Save the value of Frame Length */
1613     GLUE_SET_PKT_FRAME_LEN(prPacket, (UINT_16)u4PacketLen);
1614
1615     /* Save the value of Arrival Time*/
1616     u4SysTime = (OS_SYSTIME)kalGetTimeTick();
1617     GLUE_SET_PKT_ARRIVAL_TIME(prPacket, u4SysTime);
1618
1619     prMsduInfo->prPacket = prPacket;
1620     prMsduInfo->fgIs802_1x = fgIs1x;
1621     prMsduInfo->fgIs802_11 = FALSE;
1622     prMsduInfo->ucNetworkType = ucNetworkType;
1623     prMsduInfo->ucUserPriority = ucPriorityParam;
1624     prMsduInfo->ucMacHeaderLength = ucMacHeaderLen;
1625     prMsduInfo->u2FrameLength = (UINT_16)u4PacketLen;
1626     COPY_MAC_ADDR(prMsduInfo->aucEthDestAddr, aucEthDestAddr);
1627
1628     return TRUE;
1629 }
1630
1631
1632 /*----------------------------------------------------------------------------*/
1633 /*!
1634 * @brief this function update TCQ values by passing current status to txAdjustTcQuotas
1635 *
1636 * @param prAdapter              Pointer to the Adapter structure.
1637 *
1638 * @retval WLAN_STATUS_SUCCESS   Updated successfully
1639 */
1640 /*----------------------------------------------------------------------------*/
1641 WLAN_STATUS
1642 nicTxAdjustTcq (
1643     IN P_ADAPTER_T  prAdapter
1644     )
1645 {
1646     UINT_32 u4Num;
1647     TX_TCQ_ADJUST_T rTcqAdjust;
1648     P_TX_CTRL_T prTxCtrl;
1649     KAL_SPIN_LOCK_DECLARATION();
1650
1651     ASSERT(prAdapter);
1652
1653     prTxCtrl = &prAdapter->rTxCtrl;
1654     ASSERT(prTxCtrl);
1655
1656     qmAdjustTcQuotas(prAdapter, &rTcqAdjust, &prTxCtrl->rTc);
1657     KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_RESOURCE);
1658
1659     for (u4Num = 0 ; u4Num < TC_NUM ; u4Num++) {
1660         prTxCtrl->rTc.aucFreeBufferCount[u4Num] += rTcqAdjust.acVariation[u4Num];
1661         prTxCtrl->rTc.aucMaxNumOfBuffer[u4Num] += rTcqAdjust.acVariation[u4Num];
1662
1663         ASSERT(prTxCtrl->rTc.aucFreeBufferCount[u4Num] >= 0);
1664         ASSERT(prTxCtrl->rTc.aucMaxNumOfBuffer[u4Num] >= 0);
1665     }
1666
1667     KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_RESOURCE);
1668
1669     return WLAN_STATUS_SUCCESS;
1670 }
1671
1672
1673 /*----------------------------------------------------------------------------*/
1674 /*!
1675 * @brief this function flushes all packets queued in STA/AC queue
1676 *
1677 * @param prAdapter              Pointer to the Adapter structure.
1678 *
1679 * @retval WLAN_STATUS_SUCCESS   Flushed successfully
1680 */
1681 /*----------------------------------------------------------------------------*/
1682
1683 WLAN_STATUS
1684 nicTxFlush (
1685     IN P_ADAPTER_T  prAdapter
1686     )
1687 {
1688     P_MSDU_INFO_T prMsduInfo;
1689     KAL_SPIN_LOCK_DECLARATION();
1690
1691     ASSERT(prAdapter);
1692
1693     // ask Per STA/AC queue to be fllushed and return all queued packets
1694     KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_QM_TX_QUEUE);
1695     prMsduInfo = qmFlushTxQueues(prAdapter);
1696     KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_QM_TX_QUEUE);
1697
1698     if(prMsduInfo != NULL) {
1699         nicTxFreeMsduInfoPacket(prAdapter, prMsduInfo);
1700         nicTxReturnMsduInfo(prAdapter, prMsduInfo);
1701     }
1702
1703     return WLAN_STATUS_SUCCESS;
1704 }
1705
1706
1707 #if CFG_ENABLE_FW_DOWNLOAD
1708 /*----------------------------------------------------------------------------*/
1709 /*!
1710 * \brief In this function, we'll write Command(CMD_INFO_T) into HIF.
1711 *        However this function is used for INIT_CMD.
1712 *
1713 *        In order to avoid further maintainance issues, these 2 functions are separated
1714 *
1715 * @param prAdapter      Pointer to the Adapter structure.
1716 * @param prPacketInfo   Pointer of CMD_INFO_T
1717 * @param ucTC           Specify the resource of TC
1718 *
1719 * @retval WLAN_STATUS_SUCCESS   Bus access ok.
1720 * @retval WLAN_STATUS_FAILURE   Bus access fail.
1721 */
1722 /*----------------------------------------------------------------------------*/
1723 WLAN_STATUS
1724 nicTxInitCmd (
1725     IN P_ADAPTER_T      prAdapter,
1726     IN P_CMD_INFO_T     prCmdInfo,
1727     IN UINT_8           ucTC
1728     )
1729 {
1730     P_INIT_HIF_TX_HEADER_T prInitTxHeader;
1731     UINT_16 u2OverallBufferLength;
1732     PUINT_8 pucOutputBuf = (PUINT_8)NULL; /* Pointer to Transmit Data Structure Frame */
1733     UINT_32 ucPortIdx;
1734     P_TX_CTRL_T prTxCtrl;
1735
1736     ASSERT(prAdapter);
1737     ASSERT(prCmdInfo);
1738     ASSERT(ucTC == TC0_INDEX);
1739
1740     prTxCtrl = &prAdapter->rTxCtrl;
1741     pucOutputBuf = prTxCtrl->pucTxCoalescingBufPtr;
1742     prInitTxHeader = (P_INIT_HIF_TX_HEADER_T)prCmdInfo->pucInfoBuffer;
1743
1744     // <1> Compose the Header of Transmit Data Structure for CMD Packet
1745     u2OverallBufferLength = TFCB_FRAME_PAD_TO_DW(
1746             (prCmdInfo->u2InfoBufLen) & (UINT_16)HIF_TX_HDR_TX_BYTE_COUNT_MASK);
1747
1748     prInitTxHeader->u2TxByteCount = u2OverallBufferLength;
1749     prInitTxHeader->ucEtherTypeOffset = 0;
1750     prInitTxHeader->ucCSflags = 0;
1751
1752     // <2> Assign Data Port
1753     if (ucTC != TC4_INDEX) {
1754         ucPortIdx = 0;
1755     }
1756     else { // Broadcast/multicast data packets
1757         ucPortIdx = 1;
1758     }
1759
1760     // <3> Copy CMD Header to command buffer (by using pucCoalescingBufCached)
1761     kalMemCopy((PVOID)&pucOutputBuf[0],
1762                (PVOID)prCmdInfo->pucInfoBuffer,
1763                prCmdInfo->u2InfoBufLen);
1764
1765     ASSERT(u2OverallBufferLength <= prAdapter->u4CoalescingBufCachedSize);
1766
1767     // <4> Write frame to data port
1768     HAL_WRITE_TX_PORT(prAdapter,
1769             ucPortIdx,
1770             (UINT_32)u2OverallBufferLength,
1771             (PUINT_8)pucOutputBuf,
1772             (UINT_32)prAdapter->u4CoalescingBufCachedSize);
1773
1774     return WLAN_STATUS_SUCCESS;
1775 }
1776
1777
1778 /*----------------------------------------------------------------------------*/
1779 /*!
1780 * \brief In this function, we'll reset TX resource counter to initial value used
1781 *        in F/W download state
1782 *
1783 * @param prAdapter      Pointer to the Adapter structure.
1784 *
1785 * @retval WLAN_STATUS_SUCCESS   Reset is done successfully.
1786 */
1787 /*----------------------------------------------------------------------------*/
1788 WLAN_STATUS
1789 nicTxInitResetResource (
1790     IN P_ADAPTER_T  prAdapter
1791     )
1792 {
1793     P_TX_CTRL_T prTxCtrl;
1794
1795     DEBUGFUNC("nicTxInitResetResource");
1796
1797     ASSERT(prAdapter);
1798     prTxCtrl = &prAdapter->rTxCtrl;
1799
1800     prTxCtrl->rTc.aucMaxNumOfBuffer[TC0_INDEX] = NIC_TX_INIT_BUFF_COUNT_TC0;
1801     prTxCtrl->rTc.aucFreeBufferCount[TC0_INDEX] = NIC_TX_INIT_BUFF_COUNT_TC0;
1802
1803     prTxCtrl->rTc.aucMaxNumOfBuffer[TC1_INDEX] = NIC_TX_INIT_BUFF_COUNT_TC1;
1804     prTxCtrl->rTc.aucFreeBufferCount[TC1_INDEX] = NIC_TX_INIT_BUFF_COUNT_TC1;
1805
1806     prTxCtrl->rTc.aucMaxNumOfBuffer[TC2_INDEX] = NIC_TX_INIT_BUFF_COUNT_TC2;
1807     prTxCtrl->rTc.aucFreeBufferCount[TC2_INDEX] = NIC_TX_INIT_BUFF_COUNT_TC2;
1808
1809     prTxCtrl->rTc.aucMaxNumOfBuffer[TC3_INDEX] = NIC_TX_INIT_BUFF_COUNT_TC3;
1810     prTxCtrl->rTc.aucFreeBufferCount[TC3_INDEX] = NIC_TX_INIT_BUFF_COUNT_TC3;
1811
1812     prTxCtrl->rTc.aucMaxNumOfBuffer[TC4_INDEX] = NIC_TX_INIT_BUFF_COUNT_TC4;
1813     prTxCtrl->rTc.aucFreeBufferCount[TC4_INDEX] = NIC_TX_INIT_BUFF_COUNT_TC4;
1814
1815     prTxCtrl->rTc.aucMaxNumOfBuffer[TC5_INDEX] = NIC_TX_INIT_BUFF_COUNT_TC5;
1816     prTxCtrl->rTc.aucFreeBufferCount[TC5_INDEX] = NIC_TX_INIT_BUFF_COUNT_TC5;
1817
1818     return WLAN_STATUS_SUCCESS;
1819
1820 }
1821
1822 #endif
1823
1824
1825 /*----------------------------------------------------------------------------*/
1826 /*!
1827 * \brief this function enqueues MSDU_INFO_T into queue management,
1828 *        or command queue
1829 *
1830 * @param prAdapter      Pointer to the Adapter structure.
1831 *        prMsduInfo     Pointer to MSDU
1832 *
1833 * @retval WLAN_STATUS_SUCCESS   Reset is done successfully.
1834 */
1835 /*----------------------------------------------------------------------------*/
1836 WLAN_STATUS
1837 nicTxEnqueueMsdu (
1838     IN P_ADAPTER_T      prAdapter,
1839     IN P_MSDU_INFO_T    prMsduInfo
1840     )
1841 {
1842     P_TX_CTRL_T prTxCtrl;
1843     P_MSDU_INFO_T prNextMsduInfo, prRetMsduInfo, prMsduInfoHead;
1844     QUE_T qDataPort0, qDataPort1;
1845     P_CMD_INFO_T prCmdInfo;
1846     WLAN_STATUS u4Status = WLAN_STATUS_SUCCESS;
1847     KAL_SPIN_LOCK_DECLARATION();
1848
1849     ASSERT(prAdapter);
1850     ASSERT(prMsduInfo);
1851
1852     prTxCtrl = &prAdapter->rTxCtrl;
1853     ASSERT(prTxCtrl);
1854
1855     QUEUE_INITIALIZE(&qDataPort0);
1856     QUEUE_INITIALIZE(&qDataPort1);
1857
1858     /* check how many management frame are being queued */
1859     while(prMsduInfo) {
1860         prNextMsduInfo = (P_MSDU_INFO_T)QUEUE_GET_NEXT_ENTRY((P_QUE_ENTRY_T)prMsduInfo);
1861
1862         QUEUE_GET_NEXT_ENTRY((P_QUE_ENTRY_T)prMsduInfo) = NULL;
1863
1864         if(prMsduInfo->eSrc == TX_PACKET_MGMT) {
1865             // MMPDU: force stick to TC4
1866             prMsduInfo->ucTC = TC4_INDEX;
1867
1868             QUEUE_INSERT_TAIL(&qDataPort1, (P_QUE_ENTRY_T)prMsduInfo);
1869         }
1870         else {
1871             QUEUE_INSERT_TAIL(&qDataPort0, (P_QUE_ENTRY_T)prMsduInfo);
1872         }
1873
1874         prMsduInfo = prNextMsduInfo;
1875     }
1876
1877     if(qDataPort0.u4NumElem) {
1878         /* send to QM */
1879         KAL_SPIN_LOCK_DECLARATION();
1880         KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_QM_TX_QUEUE);
1881         prRetMsduInfo = qmEnqueueTxPackets(prAdapter, (P_MSDU_INFO_T)QUEUE_GET_HEAD(&qDataPort0));
1882         KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_QM_TX_QUEUE);
1883
1884         /* post-process for dropped packets */
1885         if(prRetMsduInfo != NULL) { // unable to enqueue
1886             nicTxFreeMsduInfoPacket(prAdapter, prRetMsduInfo);
1887             nicTxReturnMsduInfo(prAdapter, prRetMsduInfo);
1888         }
1889     }
1890
1891     if(qDataPort1.u4NumElem) {
1892         prMsduInfoHead = (P_MSDU_INFO_T)QUEUE_GET_HEAD(&qDataPort1);
1893
1894         if(qDataPort1.u4NumElem > nicTxGetFreeCmdCount(prAdapter)) {
1895             // not enough descriptors for sending
1896             u4Status = WLAN_STATUS_FAILURE;
1897
1898             // free all MSDUs
1899             while(prMsduInfoHead) {
1900                 prNextMsduInfo = (P_MSDU_INFO_T) QUEUE_GET_NEXT_ENTRY(&prMsduInfoHead->rQueEntry);
1901
1902                 if (prMsduInfoHead->pfTxDoneHandler != NULL) {
1903                     prMsduInfoHead->pfTxDoneHandler(prAdapter, prMsduInfoHead, TX_RESULT_DROPPED_IN_DRIVER);
1904                 }
1905
1906
1907                 cnmMgtPktFree(prAdapter, prMsduInfoHead);
1908
1909                 prMsduInfoHead = prNextMsduInfo;
1910             }
1911         }
1912         else {
1913             /* send to command queue */
1914             while(prMsduInfoHead) {
1915                 prNextMsduInfo = (P_MSDU_INFO_T) QUEUE_GET_NEXT_ENTRY(&prMsduInfoHead->rQueEntry);
1916
1917                 KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_CMD_RESOURCE);
1918                 QUEUE_REMOVE_HEAD(&prAdapter->rFreeCmdList, prCmdInfo, P_CMD_INFO_T);
1919                 KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_CMD_RESOURCE);
1920
1921                 if (prCmdInfo) {
1922                     GLUE_INC_REF_CNT(prTxCtrl->i4TxMgmtPendingNum);
1923
1924                     kalMemZero(prCmdInfo, sizeof(CMD_INFO_T));
1925
1926                     prCmdInfo->eCmdType             = COMMAND_TYPE_MANAGEMENT_FRAME;
1927                     prCmdInfo->u2InfoBufLen         = prMsduInfoHead->u2FrameLength;
1928                     prCmdInfo->pucInfoBuffer        = NULL;
1929                     prCmdInfo->prPacket             = (P_NATIVE_PACKET)prMsduInfoHead;
1930                     prCmdInfo->ucStaRecIndex        = prMsduInfoHead->ucStaRecIndex;
1931                     prCmdInfo->eNetworkType         = prMsduInfoHead->ucNetworkType;
1932                     prCmdInfo->pfCmdDoneHandler     = NULL;
1933                     prCmdInfo->pfCmdTimeoutHandler  = NULL;
1934                     prCmdInfo->fgIsOid              = FALSE;
1935                     prCmdInfo->fgSetQuery           = TRUE;
1936                     prCmdInfo->fgNeedResp           = FALSE;
1937
1938                     kalEnqueueCommand(prAdapter->prGlueInfo, (P_QUE_ENTRY_T)prCmdInfo);
1939                 }
1940                 else {
1941                     /* Cmd free count is larger than expected, but allocation fail. */
1942                     ASSERT(0);
1943
1944                     u4Status = WLAN_STATUS_FAILURE;
1945                     cnmMgtPktFree(prAdapter, prMsduInfoHead);
1946                 }
1947
1948                 prMsduInfoHead = prNextMsduInfo;
1949             }
1950         }
1951     }
1952
1953     /* indicate service thread for sending */
1954     if(prTxCtrl->i4TxMgmtPendingNum > 0
1955             || kalGetTxPendingFrameCount(prAdapter->prGlueInfo) > 0) {
1956         kalSetEvent(prAdapter->prGlueInfo);
1957     }
1958
1959     return u4Status;
1960 }
1961
1962
1963 /*----------------------------------------------------------------------------*/
1964 /*!
1965 * \brief this function returns available count in command queue
1966 *
1967 * @param prAdapter      Pointer to the Adapter structure.
1968 *
1969 * @retval
1970 */
1971 /*----------------------------------------------------------------------------*/
1972 UINT_32
1973 nicTxGetFreeCmdCount (
1974     IN P_ADAPTER_T  prAdapter
1975     )
1976 {
1977     ASSERT(prAdapter);
1978
1979     return prAdapter->rFreeCmdList.u4NumElem;
1980 }
1981