f08c307bec7f18514e6b80398847088b4e5d0fc4
[firefly-linux-kernel-4.4.55.git] / drivers / net / wireless / rockchip_wlan / mt5931_kk / drv_wlan / nic / nic_tx.c
1 /*
2 ** $Id: //Department/DaVinci/BRANCHES/MT662X_593X_WIFI_DRIVER_V2_3/nic/nic_tx.c#2 $
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 * Copyright (c) 2007 MediaTek Inc.
14 *
15 * All rights reserved. Copying, compilation, modification, distribution
16 * or any other use whatsoever of this material is strictly prohibited
17 * except in accordance with a Software License Agreement with
18 * MediaTek Inc.
19 ********************************************************************************
20 */
21
22 /*******************************************************************************
23 * LEGAL DISCLAIMER
24 *
25 * BY OPENING THIS FILE, BUYER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND
26 * AGREES THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK
27 * SOFTWARE") RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE
28 * PROVIDED TO BUYER ON AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY
29 * DISCLAIMS ANY AND ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT
30 * LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
31 * PARTICULAR PURPOSE OR NONINFRINGEMENT. NEITHER DOES MEDIATEK PROVIDE
32 * ANY WARRANTY WHATSOEVER WITH RESPECT TO THE SOFTWARE OF ANY THIRD PARTY
33 * WHICH MAY BE USED BY, INCORPORATED IN, OR SUPPLIED WITH THE MEDIATEK
34 * SOFTWARE, AND BUYER AGREES TO LOOK ONLY TO SUCH THIRD PARTY FOR ANY
35 * WARRANTY CLAIM RELATING THERETO. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE
36 * FOR ANY MEDIATEK SOFTWARE RELEASES MADE TO BUYER'S SPECIFICATION OR TO
37 * CONFORM TO A PARTICULAR STANDARD OR OPEN FORUM.
38 *
39 * BUYER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND CUMULATIVE
40 * LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL
41 * BE, AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT
42 * ISSUE, OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY
43 * BUYER TO MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
44 *
45 * THE TRANSACTION CONTEMPLATED HEREUNDER SHALL BE CONSTRUED IN ACCORDANCE
46 * WITH THE LAWS OF THE STATE OF CALIFORNIA, USA, EXCLUDING ITS CONFLICT
47 * OF LAWS PRINCIPLES.  ANY DISPUTES, CONTROVERSIES OR CLAIMS ARISING
48 * THEREOF AND RELATED THERETO SHALL BE SETTLED BY ARBITRATION IN SAN
49 * FRANCISCO, CA, UNDER THE RULES OF THE INTERNATIONAL CHAMBER OF COMMERCE
50 * (ICC).
51 ********************************************************************************
52 */
53
54 /*
55 ** $Log: nic_tx.c $
56 **
57 ** 12 27 2012 cp.wu
58 ** no need to do TX checksum offloading for forwarding packets
59 ** 
60 ** 08 28 2012 cp.wu
61 ** [WCXRP00001270] [MT6620 Wi-Fi][Driver] Fix non-aggregated TX path for experimental purpose
62 ** fix: pucTxCoalescingBufPtr is also used by non-aggregated TX path
63  *
64  * 06 13 2012 yuche.tsai
65  * NULL
66  * Update maintrunk driver.
67  * Add support for driver compose assoc request frame.
68  *
69  * 11 18 2011 eddie.chen
70  * [WCXRP00001096] [MT6620 Wi-Fi][Driver/FW] Enhance the log function (xlog)
71  * Add log counter for tx
72  *
73  * 11 09 2011 eddie.chen
74  * [WCXRP00001096] [MT6620 Wi-Fi][Driver/FW] Enhance the log function (xlog)
75  * Add xlog for beacon timeout and sta aging timeout.
76  *
77  * 11 08 2011 eddie.chen
78  * [WCXRP00001096] [MT6620 Wi-Fi][Driver/FW] Enhance the log function (xlog)
79  * Add xlog function.
80  *
81  * 05 17 2011 cp.wu
82  * [WCXRP00000732] [MT6620 Wi-Fi][AIS] No need to switch back to IDLE state when DEAUTH frame is dropped due to bss disconnection
83  * when TX DONE status is TX_RESULT_DROPPED_IN_DRIVER, no need to switch back to IDLE state.
84  *
85  * 04 12 2011 eddie.chen
86  * [WCXRP00000617] [MT6620 Wi-Fi][DRV/FW] Fix for sigma
87  * Fix the sta index in processing security frame
88  * Simple flow control for TC4 to avoid mgt frames for PS STA to occupy the TC4
89  * Add debug message.
90  *
91  * 04 12 2011 cp.wu
92  * [WCXRP00000631] [MT6620 Wi-Fi][Driver] Add an API for QM to retrieve current TC counter value and processing frame dropping cases for TC4 path
93  * remove unused variables.
94  *
95  * 04 12 2011 cp.wu
96  * [WCXRP00000631] [MT6620 Wi-Fi][Driver] Add an API for QM to retrieve current TC counter value and processing frame dropping cases for TC4 path
97  * 1. add nicTxGetResource() API for QM to make decisions.
98  * 2. if management frames is decided by QM for dropping, the call back is invoked to indicate such a case.
99  *
100  * 03 17 2011 cp.wu
101  * [WCXRP00000562] [MT6620 Wi-Fi][Driver] I/O buffer pre-allocation to avoid physically continuous memory shortage after system running for a long period
102  * use pre-allocated buffer for storing enhanced interrupt response as well
103  *
104  * 03 15 2011 cp.wu
105  * [WCXRP00000559] [MT6620 Wi-Fi][Driver] Combine TX/RX DMA buffers into a single one to reduce physically continuous memory consumption
106  * 1. deprecate CFG_HANDLE_IST_IN_SDIO_CALLBACK
107  * 2. Use common coalescing buffer for both TX/RX directions
108  * 
109  *
110  * 02 16 2011 cp.wu
111  * [WCXRP00000449] [MT6620 Wi-Fi][Driver] Refine CMD queue handling by adding an extra API for checking availble count and modify behavior
112  * 1. add new API: nicTxGetFreeCmdCount()
113  * 2. when there is insufficient command descriptor, nicTxEnqueueMsdu() will drop command packets directly
114  *
115  * 01 24 2011 cp.wu
116  * [WCXRP00000382] [MT6620 Wi-Fi][Driver] Track forwarding packet number with notifying tx thread for serving
117  * 1. add an extra counter for tracking pending forward frames.
118  * 2. notify TX service thread as well when there is pending forward frame
119  * 3. correct build errors leaded by introduction of Wi-Fi direct separation module
120  *
121  * 01 12 2011 cp.wu
122  * [WCXRP00000356] [MT6620 Wi-Fi][Driver] fill mac header length for security frames 'cause hardware header translation needs such information
123  * fill mac header length information for 802.1x frames.
124  *
125  * 12 31 2010 cp.wu
126  * [WCXRP00000335] [MT6620 Wi-Fi][Driver] change to use milliseconds sleep instead of delay to avoid blocking to system scheduling
127  * change to use msleep() and shorten waiting interval to reduce blocking to other task while Wi-Fi driver is being loaded
128  *
129  * 11 01 2010 yarco.yang
130  * [WCXRP00000149] [MT6620 WI-Fi][Driver]Fine tune performance on MT6516 platform
131  * Add GPIO debug function
132  *
133  * 10 18 2010 cp.wu
134  * [WCXRP00000117] [MT6620 Wi-Fi][Driver] Add logic for suspending driver when MT6620 is not responding anymore
135  * 1. when wlanAdapterStop() failed to send POWER CTRL command to firmware, do not poll for ready bit dis-assertion
136  * 2. shorten polling count for shorter response time
137  * 3. if bad I/O operation is detected during TX resource polling, then further operation is aborted as well
138  *
139  * 10 06 2010 cp.wu
140  * [WCXRP00000052] [MT6620 Wi-Fi][Driver] Eliminate Linux Compile Warning
141  * code reorganization to improve isolation between GLUE and CORE layers.
142  *
143  * 09 29 2010 wh.su
144  * [WCXRP00000072] [MT6620 Wi-Fi][Driver] Fix TKIP Counter Measure EAPoL callback register issue
145  * [MT6620 Wi-Fi][Driver] Fix TKIP Counter Measure EAPoL callback register issue.
146  *
147  * 09 27 2010 wh.su
148  * NULL
149  * since the u2TxByteCount_UserPriority will or another setting, keep the overall buffer for avoid error
150  *
151  * 09 24 2010 wh.su
152  * NULL
153  * [WCXRP000000058][MT6620 Wi-Fi][Driver] Fail to handshake with WAPI AP due the 802.1x frame send to fw with extra bytes padding.
154  *
155  * 09 01 2010 cp.wu
156  * NULL
157  * HIFSYS Clock Source Workaround
158  *
159  * 08 30 2010 cp.wu
160  * NULL
161  * API added: nicTxPendingPackets(), for simplifying porting layer
162  *
163  * 08 30 2010 cp.wu
164  * NULL
165  * eliminate klockwork errors
166  *
167  * 08 20 2010 wh.su
168  * NULL
169  * adding the eapol callback setting.
170  *
171  * 08 18 2010 yarco.yang
172  * NULL
173  * 1. Fixed HW checksum offload function not work under Linux issue.
174  * 2. Add debug message.
175  *
176  * 08 05 2010 yuche.tsai
177  * NULL
178  * .
179  *
180  * 08 03 2010 cp.wu
181  * NULL
182  * surpress compilation warning.
183  *
184  * 08 02 2010 jeffrey.chang
185  * NULL
186  * 1) modify tx service thread to avoid busy looping
187  * 2) add spin lock declartion for linux build
188  *
189  * 07 29 2010 cp.wu
190  * NULL
191  * simplify post-handling after TX_DONE interrupt is handled.
192  *
193  * 07 19 2010 jeffrey.chang
194  *
195  * Linux port modification
196  *
197  * 07 13 2010 cp.wu
198  *
199  * 1) MMPDUs are now sent to MT6620 by CMD queue for keeping strict order of 1X/MMPDU/CMD packets
200  * 2) integrate with qmGetFrameAction() for deciding which MMPDU/1X could pass checking for sending
201  * 2) enhance CMD_INFO_T descriptor number from 10 to 32 to avoid descriptor underflow under concurrent network operation
202  *
203  * 07 08 2010 cp.wu
204  *
205  * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository.
206  *
207  * 06 29 2010 yarco.yang
208  * [WPD00003837][MT6620]Data Path Refine
209  * replace g_rQM with Adpater->rQM
210  *
211  * 06 25 2010 cp.wu
212  * [WPD00003833][MT6620 and MT5931] Driver migration
213  * add API in que_mgt to retrieve sta-rec index for security frames.
214  *
215  * 06 24 2010 cp.wu
216  * [WPD00003833][MT6620 and MT5931] Driver migration
217  * 802.1x and bluetooth-over-Wi-Fi security frames are now delievered to firmware via command path instead of data path.
218  *
219  * 06 23 2010 yarco.yang
220  * [WPD00003837][MT6620]Data Path Refine
221  * Merge g_arStaRec[] into adapter->arStaRec[]
222  *
223  * 06 22 2010 cp.wu
224  * [WPD00003833][MT6620 and MT5931] Driver migration
225  * 1) add command warpper for STA-REC/BSS-INFO sync.
226  * 2) enhance command packet sending procedure for non-oid part
227  * 3) add command packet definitions for STA-REC/BSS-INFO sync.
228  *
229  * 06 21 2010 cp.wu
230  * [WPD00003833][MT6620 and MT5931] Driver migration
231  * add checking for TX descriptor poll.
232  *
233  * 06 21 2010 cp.wu
234  * [WPD00003833][MT6620 and MT5931] Driver migration
235  * TX descriptors are now allocated once for reducing allocation overhead
236  *
237  * 06 18 2010 cm.chang
238  * [WPD00003841][LITE Driver] Migrate RLM/CNM to host driver
239  * Provide cnmMgtPktAlloc() and alloc/free function of msg/buf
240  *
241  * 06 15 2010 cp.wu
242  * [WPD00003833][MT6620 and MT5931] Driver migration
243  * change zero-padding for TX port access to HAL.
244  *
245  * 06 15 2010 cp.wu
246  * [WPD00003833][MT6620 and MT5931] Driver migration
247  * .
248  *
249  * 06 15 2010 cp.wu
250  * [WPD00003833][MT6620 and MT5931] Driver migration
251  * .
252  *
253  * 06 14 2010 cp.wu
254  * [WPD00003833][MT6620 and MT5931] Driver migration
255  * fill extra information for revised HIF_TX_HEADER.
256  *
257  * 06 11 2010 cp.wu
258  * [WPD00003833][MT6620 and MT5931] Driver migration
259  * 1) migrate assoc.c.
260  * 2) add ucTxSeqNum for tracking frames which needs TX-DONE awareness
261  * 3) add configuration options for CNM_MEM and RSN modules
262  * 4) add data path for management frames
263  * 5) eliminate rPacketInfo of MSDU_INFO_T
264  *
265  * 06 10 2010 cp.wu
266  * [WPD00003833][MT6620 and MT5931] Driver migration
267  * change to enqueue TX frame infinitely.
268  *
269  * 06 09 2010 cp.wu
270  * [WPD00003833][MT6620 and MT5931] Driver migration
271  * add TX_PACKET_MGMT to indicate the frame is coming from management modules
272  *
273  * 06 06 2010 kevin.huang
274  * [WPD00003832][MT6620 5931] Create driver base
275  * [MT6620 5931] Create driver base
276  *
277  * 05 10 2010 cp.wu
278  * [WPD00003831][MT6620 Wi-Fi] Add framework for Wi-Fi Direct support
279  * fill network type field while doing frame identification.
280  *
281  * 04 23 2010 cp.wu
282  * [WPD00001943]Create WiFi test driver framework on WinXP
283  * surpress compiler warning
284  *
285  * 04 06 2010 jeffrey.chang
286  * [WPD00003826]Initial import for Linux port
287  * Tag the packet for QoS on Tx path
288  *
289  * 03 30 2010 cp.wu
290  * [WPD00001943]Create WiFi test driver framework on WinXP
291  * remove driver-land statistics.
292  *
293  * 03 29 2010 jeffrey.chang
294  * [WPD00003826]Initial import for Linux port
295  * improve none-glue code portability
296  *
297  * 03 24 2010 jeffrey.chang
298  * [WPD00003826]Initial import for Linux port
299  * initial import for Linux port
300  *
301  * 03 24 2010 cp.wu
302  * [WPD00001943]Create WiFi test driver framework on WinXP
303  * generate information for OID_GEN_RCV_OK & OID_GEN_XMIT_OK
304  *  *  *  *  *
305  *
306 * 03 10 2010 cp.wu
307  * [WPD00001943]Create WiFi test driver framework on WinXP
308  * code clean: removing unused variables and structure definitions
309  *
310  * 03 08 2010 cp.wu
311  * [WPD00001943]Create WiFi test driver framework on WinXP
312  * 1) add another spin-lock to protect MsduInfoList due to it might be accessed by different thread.
313  *  *  *  * 2) change own-back acquiring procedure to wait for up to 16.67 seconds
314  *
315  * 03 02 2010 cp.wu
316  * [WPD00001943]Create WiFi test driver framework on WinXP
317  * add mutex to avoid multiple access to qmTxQueue simultaneously.
318  *
319  * 02 26 2010 cp.wu
320  * [WPD00001943]Create WiFi test driver framework on WinXP
321  * avoid refering to NDIS-specific data structure directly from non-glue layer.
322  *
323  * 02 24 2010 cp.wu
324  * [WPD00001943]Create WiFi test driver framework on WinXP
325  * add Ethernet destination address information in packet info for TX
326  *
327  * 02 10 2010 cp.wu
328  * [WPD00001943]Create WiFi test driver framework on WinXP
329  * 1) remove unused function in nic_rx.c [which has been handled in que_mgt.c]
330  *  *  *  *  *  * 2) firmware image length is now retrieved via NdisFileOpen
331  *  *  *  *  *  * 3) firmware image is not structured by (P_IMG_SEC_HDR_T) anymore
332  *  *  *  *  *  * 4) nicRxWaitResponse() revised
333  *  *  *  *  *  * 5) another set of TQ counter default value is added for fw-download state
334  *  *  *  *  *  * 6) Wi-Fi load address is now retrieved from registry too
335  *
336  * 02 09 2010 cp.wu
337  * [WPD00001943]Create WiFi test driver framework on WinXP
338  * 1. Permanent and current MAC address are now retrieved by CMD/EVENT packets instead of hard-coded address
339  *  *  *  *  *  *  *  *  * 2. follow MSDN defined behavior when associates to another AP
340  *  *  *  *  *  *  *  *  * 3. for firmware download, packet size could be up to 2048 bytes
341  *
342  * 02 08 2010 cp.wu
343  * [WPD00001943]Create WiFi test driver framework on WinXP
344  * prepare for implementing fw download logic
345  *
346  * 01 27 2010 cp.wu
347  * [WPD00001943]Create WiFi test driver framework on WinXP
348  * 1. eliminate improper variable in rHifInfo
349  *  *  *  *  *  *  *  *  * 2. block TX/ordinary OID when RF test mode is engaged
350  *  *  *  *  *  *  *  *  * 3. wait until firmware finish operation when entering into and leaving from RF test mode
351  *  *  *  *  *  *  *  *  * 4. correct some HAL implementation
352  *
353  * 01 13 2010 tehuang.liu
354  * [WPD00001943]Create WiFi test driver framework on WinXP
355  * Enabled the Burst_End Indication mechanism
356  *
357  * 01 13 2010 cp.wu
358  * [WPD00001943]Create WiFi test driver framework on WinXP
359  * TX: fill ucWlanHeaderLength/ucPktFormtId_Flags according to info provided by prMsduInfo
360  *
361  * 12 30 2009 cp.wu
362  * [WPD00001943]Create WiFi test driver framework on WinXP
363  * 1) According to CMD/EVENT documentation v0.8,
364  *  *  *  *  *  *  *  *  *  * OID_CUSTOM_TEST_RX_STATUS & OID_CUSTOM_TEST_TX_STATUS is no longer used,
365  *  *  *  *  *  *  *  *  *  * and result is retrieved by get ATInfo instead
366  *  *  *  *  *  *  *  *  *  * 2) add 4 counter for recording aggregation statistics
367 **  \main\maintrunk.MT6620WiFiDriver_Prj\44 2009-12-10 16:52:15 GMT mtk02752
368 **  remove unused API
369 **  \main\maintrunk.MT6620WiFiDriver_Prj\43 2009-12-07 22:44:24 GMT mtk02752
370 **  correct assertion criterion
371 **  \main\maintrunk.MT6620WiFiDriver_Prj\42 2009-12-07 21:15:52 GMT mtk02752
372 **  correct trivial mistake
373 **  \main\maintrunk.MT6620WiFiDriver_Prj\41 2009-12-04 15:47:21 GMT mtk02752
374 **  + always append a dword of zero on TX path to avoid TX aggregation to triggered on uninitialized data
375 **  + add more assertion for packet size check
376 **  \main\maintrunk.MT6620WiFiDriver_Prj\40 2009-12-04 14:51:55 GMT mtk02752
377 **  nicTxMsduInfo(): save ptr for next entry before attaching to qDataPort
378 **  \main\maintrunk.MT6620WiFiDriver_Prj\39 2009-12-04 11:54:54 GMT mtk02752
379 **  add 2 assertion for size check
380 **  \main\maintrunk.MT6620WiFiDriver_Prj\38 2009-12-03 16:20:35 GMT mtk01461
381 **  Add debug message
382 **  \main\maintrunk.MT6620WiFiDriver_Prj\37 2009-11-30 10:57:10 GMT mtk02752
383 **  1st DW of WIFI_CMD_T is shared with HIF_TX_HEADER_T
384 **  \main\maintrunk.MT6620WiFiDriver_Prj\36 2009-11-30 09:20:43 GMT mtk02752
385 **  use TC4 instead of TC5 for command packet
386 **  \main\maintrunk.MT6620WiFiDriver_Prj\35 2009-11-27 11:08:11 GMT mtk02752
387 **  add flush for reset
388 **  \main\maintrunk.MT6620WiFiDriver_Prj\34 2009-11-26 20:31:22 GMT mtk02752
389 **  fill prMsduInfo->ucUserPriority
390 **  \main\maintrunk.MT6620WiFiDriver_Prj\33 2009-11-25 21:04:33 GMT mtk02752
391 **  fill u2SeqNo
392 **  \main\maintrunk.MT6620WiFiDriver_Prj\32 2009-11-24 20:52:12 GMT mtk02752
393 **  integration with SD1's data path API
394 **  \main\maintrunk.MT6620WiFiDriver_Prj\31 2009-11-24 19:54:25 GMT mtk02752
395 **  nicTxRetransmitOfOsSendQue & nicTxData but changed to use nicTxMsduInfoList
396 **  \main\maintrunk.MT6620WiFiDriver_Prj\30 2009-11-23 17:53:18 GMT mtk02752
397 **  add nicTxCmd() for SD1_SD3_DATAPATH_INTEGRATION, which will append only HIF_TX_HEADER. seqNum, WIFI_CMD_T will be created inside oid handler
398 **  \main\maintrunk.MT6620WiFiDriver_Prj\29 2009-11-20 15:10:24 GMT mtk02752
399 **  use TxAccquireResource instead of accessing TCQ directly.
400 **  \main\maintrunk.MT6620WiFiDriver_Prj\28 2009-11-17 22:40:57 GMT mtk01084
401 **  \main\maintrunk.MT6620WiFiDriver_Prj\27 2009-11-17 17:35:40 GMT mtk02752
402 **  add nicTxMsduInfoList () implementation
403 **  \main\maintrunk.MT6620WiFiDriver_Prj\26 2009-11-17 11:07:10 GMT mtk02752
404 **  add nicTxAdjustTcq() implementation
405 **  \main\maintrunk.MT6620WiFiDriver_Prj\25 2009-11-16 22:28:38 GMT mtk02752
406 **  move aucFreeBufferCount/aucMaxNumOfBuffer into another structure
407 **  \main\maintrunk.MT6620WiFiDriver_Prj\24 2009-11-16 21:45:32 GMT mtk02752
408 **  add SD1_SD3_DATAPATH_INTEGRATION data path handling
409 **  \main\maintrunk.MT6620WiFiDriver_Prj\23 2009-11-13 13:29:56 GMT mtk01084
410 **  modify TX hdr format, fix tx retransmission issue
411 **  \main\maintrunk.MT6620WiFiDriver_Prj\22 2009-11-11 10:36:21 GMT mtk01084
412 **  \main\maintrunk.MT6620WiFiDriver_Prj\21 2009-11-04 14:11:11 GMT mtk01084
413 **  modify TX SW data structure
414 **  \main\maintrunk.MT6620WiFiDriver_Prj\20 2009-10-29 19:56:17 GMT mtk01084
415 **  modify HAL part
416 **  \main\maintrunk.MT6620WiFiDriver_Prj\19 2009-10-13 21:59:23 GMT mtk01084
417 **  update for new HW design
418 **  \main\maintrunk.MT6620WiFiDriver_Prj\18 2009-10-02 14:00:18 GMT mtk01725
419 **  \main\maintrunk.MT6620WiFiDriver_Prj\17 2009-05-20 12:26:06 GMT mtk01461
420 **  Assign SeqNum to CMD Packet
421 **  \main\maintrunk.MT6620WiFiDriver_Prj\16 2009-05-19 10:54:04 GMT mtk01461
422 **  Add debug message
423 **  \main\maintrunk.MT6620WiFiDriver_Prj\15 2009-05-12 09:41:55 GMT mtk01461
424 **  Fix Query Command need resp issue
425 **  \main\maintrunk.MT6620WiFiDriver_Prj\14 2009-04-29 15:44:38 GMT mtk01461
426 **  Move OS dependent code to kalQueryTxOOBData()
427 **  \main\maintrunk.MT6620WiFiDriver_Prj\13 2009-04-28 10:40:03 GMT mtk01461
428 **  Add nicTxReleaseResource() for SDIO_STATUS_ENHANCE, and also fix the TX aggregation issue for 1x packet to TX1 port
429 **  \main\maintrunk.MT6620WiFiDriver_Prj\12 2009-04-21 09:50:47 GMT mtk01461
430 **  Update nicTxCmd() for moving wait RESP function call to wlanSendCommand()
431 **  \main\maintrunk.MT6620WiFiDriver_Prj\11 2009-04-17 19:56:32 GMT mtk01461
432 **  Move the CMD_INFO_T related function to cmd_buf.c
433 **  \main\maintrunk.MT6620WiFiDriver_Prj\10 2009-04-17 18:14:40 GMT mtk01426
434 **  Update OOB query for TX packet
435 **  \main\maintrunk.MT6620WiFiDriver_Prj\9 2009-04-14 15:51:32 GMT mtk01426
436 **  Support PKGUIO
437 **  \main\maintrunk.MT6620WiFiDriver_Prj\8 2009-04-02 17:26:40 GMT mtk01461
438 **  Add virtual OOB for HIF LOOPBACK SW PRETEST
439 **  \main\maintrunk.MT6620WiFiDriver_Prj\7 2009-04-01 10:54:43 GMT mtk01461
440 **  Add function for SDIO_TX_ENHANCE
441 **  \main\maintrunk.MT6620WiFiDriver_Prj\6 2009-03-23 21:53:47 GMT mtk01461
442 **  Add code for retransmit of rOsSendQueue, mpSendPacket(), and add code for TX Checksum offload, Loopback Test.
443 **  \main\maintrunk.MT6620WiFiDriver_Prj\5 2009-03-23 00:33:51 GMT mtk01461
444 **  Add code for TX Data & Cmd Packet
445 **  \main\maintrunk.MT6620WiFiDriver_Prj\4 2009-03-18 20:25:40 GMT mtk01461
446 **  Fix LINT warning
447 **  \main\maintrunk.MT6620WiFiDriver_Prj\3 2009-03-16 09:10:30 GMT mtk01461
448 **  Update TX PATH API
449 **  \main\maintrunk.MT6620WiFiDriver_Prj\2 2009-03-10 20:26:04 GMT mtk01426
450 **  Init for develop
451 **
452 */
453
454 /*******************************************************************************
455 *                         C O M P I L E R   F L A G S
456 ********************************************************************************
457 */
458
459 /*******************************************************************************
460 *                    E X T E R N A L   R E F E R E N C E S
461 ********************************************************************************
462 */
463 #include "precomp.h"
464
465 /*******************************************************************************
466 *                              C O N S T A N T S
467 ********************************************************************************
468 */
469
470 /*******************************************************************************
471 *                             D A T A   T Y P E S
472 ********************************************************************************
473 */
474
475 /*******************************************************************************
476 *                            P U B L I C   D A T A
477 ********************************************************************************
478 */
479
480 /*******************************************************************************
481 *                           P R I V A T E   D A T A
482 ********************************************************************************
483 */
484
485 /*******************************************************************************
486 *                                 M A C R O S
487 ********************************************************************************
488 */
489
490 /*******************************************************************************
491 *                  F U N C T I O N   D E C L A R A T I O N S
492 ********************************************************************************
493 */
494
495 /*******************************************************************************
496 *                              F U N C T I O N S
497 ********************************************************************************
498 */
499 /*----------------------------------------------------------------------------*/
500 /*!
501 * @brief This function will initial all variables in regard to SW TX Queues and
502 *        all free lists of MSDU_INFO_T and SW_TFCB_T.
503 *
504 * @param prAdapter  Pointer to the Adapter structure.
505 *
506 * @return (none)
507 */
508 /*----------------------------------------------------------------------------*/
509 VOID
510 nicTxInitialize (
511     IN P_ADAPTER_T  prAdapter
512     )
513 {
514     P_TX_CTRL_T prTxCtrl;
515     PUINT_8 pucMemHandle;
516     P_MSDU_INFO_T prMsduInfo;
517     UINT_32 i;
518     KAL_SPIN_LOCK_DECLARATION();
519
520     DEBUGFUNC("nicTxInitialize");
521
522     ASSERT(prAdapter);
523     prTxCtrl = &prAdapter->rTxCtrl;
524
525     //4 <1> Initialization of Traffic Class Queue Parameters
526     nicTxResetResource(prAdapter);
527
528 #if CFG_SDIO_TX_AGG
529     prTxCtrl->pucTxCoalescingBufPtr = prAdapter->pucCoalescingBufCached;
530 #endif /* CFG_SDIO_TX_AGG */
531
532     // allocate MSDU_INFO_T and link it into rFreeMsduInfoList
533     QUEUE_INITIALIZE(&prTxCtrl->rFreeMsduInfoList);
534
535     pucMemHandle = prTxCtrl->pucTxCached;
536     for (i = 0 ; i < CFG_TX_MAX_PKT_NUM ; i++) {
537         prMsduInfo = (P_MSDU_INFO_T)pucMemHandle;
538         kalMemZero(prMsduInfo, sizeof(MSDU_INFO_T));
539
540         KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_MSDU_INFO_LIST);
541         QUEUE_INSERT_TAIL(&prTxCtrl->rFreeMsduInfoList, (P_QUE_ENTRY_T)prMsduInfo);
542         KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_MSDU_INFO_LIST);
543
544         pucMemHandle += ALIGN_4(sizeof(MSDU_INFO_T));
545     }
546
547     ASSERT(prTxCtrl->rFreeMsduInfoList.u4NumElem == CFG_TX_MAX_PKT_NUM);
548     /* Check if the memory allocation consist with this initialization function */
549     ASSERT((UINT_32)(pucMemHandle - prTxCtrl->pucTxCached) == prTxCtrl->u4TxCachedSize);
550
551     QUEUE_INITIALIZE(&prTxCtrl->rTxMgmtTxingQueue);
552     prTxCtrl->i4TxMgmtPendingNum = 0;
553
554 #if CFG_HIF_STATISTICS
555     prTxCtrl->u4TotalTxAccessNum = 0;
556     prTxCtrl->u4TotalTxPacketNum = 0;
557 #endif
558
559     prTxCtrl->i4PendingFwdFrameCount = 0;
560
561     qmInit(prAdapter);
562
563     TX_RESET_ALL_CNTS(prTxCtrl);
564
565     return;
566 } /* end of nicTxInitialize() */
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 check if has enough TC Buffer for incoming
573 *        packet and then update the value after promise to provide the resources.
574 *
575 * \param[in] prAdapter              Pointer to the Adapter structure.
576 * \param[in] ucTC                   Specify the resource of TC
577 *
578 * \retval WLAN_STATUS_SUCCESS   Resource is available and been assigned.
579 * \retval WLAN_STATUS_RESOURCES Resource is not available.
580 */
581 /*----------------------------------------------------------------------------*/
582 WLAN_STATUS
583 nicTxAcquireResource (
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_RESOURCES;
590     KAL_SPIN_LOCK_DECLARATION();
591
592     ASSERT(prAdapter);
593     prTxCtrl = &prAdapter->rTxCtrl;
594
595
596     KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_RESOURCE);
597
598 //    DbgPrint("nicTxAcquireResource prTxCtrl->rTc.aucFreeBufferCount[%d]=%d\n", ucTC, prTxCtrl->rTc.aucFreeBufferCount[ucTC]);
599
600     if (prTxCtrl->rTc.aucFreeBufferCount[ucTC]) {
601
602         prTxCtrl->rTc.aucFreeBufferCount[ucTC]--;
603
604         DBGLOG(TX, EVENT, ("Acquire: TC = %d aucFreeBufferCount = %d\n",
605             ucTC, prTxCtrl->rTc.aucFreeBufferCount[ucTC]));
606
607         u4Status = WLAN_STATUS_SUCCESS;
608     }
609     KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_RESOURCE);
610
611     return u4Status;
612
613 }/* end of nicTxAcquireResourceAndTFCBs() */
614
615
616 /*----------------------------------------------------------------------------*/
617 /*!
618 * @brief Driver maintain a variable that is synchronous with the usage of individual
619 *        TC Buffer Count. This function will do polling if FW has return the resource.
620 *        Used when driver start up before enable interrupt.
621 *
622 * @param prAdapter      Pointer to the Adapter structure.
623 * @param ucTC           Specify the resource of TC
624 *
625 * @retval WLAN_STATUS_SUCCESS   Resource is available.
626 * @retval WLAN_STATUS_FAILURE   Resource is not available.
627 */
628 /*----------------------------------------------------------------------------*/
629 WLAN_STATUS
630 nicTxPollingResource (
631     IN P_ADAPTER_T  prAdapter,
632     IN UINT_8       ucTC
633     )
634 {
635     P_TX_CTRL_T prTxCtrl;
636     WLAN_STATUS u4Status = WLAN_STATUS_FAILURE;
637     INT_32 i = NIC_TX_RESOURCE_POLLING_TIMEOUT;
638     UINT_32 au4WTSR[2];
639
640     ASSERT(prAdapter);
641     prTxCtrl = &prAdapter->rTxCtrl;
642
643     if (ucTC >= TC_NUM) {
644         return WLAN_STATUS_FAILURE;
645     }
646
647     if (prTxCtrl->rTc.aucFreeBufferCount[ucTC] > 0) {
648         return WLAN_STATUS_SUCCESS;
649     }
650
651     while (i-- > 0) {
652         HAL_READ_TX_RELEASED_COUNT(prAdapter, au4WTSR);
653
654         if(kalIsCardRemoved(prAdapter->prGlueInfo) == TRUE
655                 || fgIsBusAccessFailed == TRUE) {
656             u4Status = WLAN_STATUS_FAILURE;
657             break;
658         }
659         else if (nicTxReleaseResource(prAdapter, (PUINT_8)au4WTSR)) {
660             if (prTxCtrl->rTc.aucFreeBufferCount[ucTC] > 0) {
661                 u4Status = WLAN_STATUS_SUCCESS;
662                 break;
663             }
664             else {
665                 kalMsleep(NIC_TX_RESOURCE_POLLING_DELAY_MSEC);
666             }
667         }
668         else {
669             kalMsleep(NIC_TX_RESOURCE_POLLING_DELAY_MSEC);
670         }
671     }
672
673 #if DBG
674     {
675         INT_32 i4Times = NIC_TX_RESOURCE_POLLING_TIMEOUT - (i+1);
676
677         if (i4Times) {
678             DBGLOG(TX, TRACE, ("Polling MCR_WTSR delay %d times, %d msec\n",
679                 i4Times, (i4Times * NIC_TX_RESOURCE_POLLING_DELAY_MSEC)));
680         }
681     }
682 #endif /* DBG */
683
684     return u4Status;
685
686 } /* end of nicTxPollingResource() */
687
688
689 /*----------------------------------------------------------------------------*/
690 /*!
691 * \brief Driver maintain a variable that is synchronous with the usage of individual
692 *        TC Buffer Count. This function will release TC Buffer count according to
693 *        the given TX_STATUS COUNTER after TX Done.
694 *
695 * \param[in] prAdapter              Pointer to the Adapter structure.
696 * \param[in] u4TxStatusCnt          Value of TX STATUS
697 *
698 * @return (none)
699 */
700 /*----------------------------------------------------------------------------*/
701 BOOLEAN
702 nicTxReleaseResource (
703     IN P_ADAPTER_T  prAdapter,
704     IN UINT_8*      aucTxRlsCnt
705     )
706 {
707     PUINT_32 pu4Tmp = (PUINT_32)aucTxRlsCnt;
708     P_TX_CTRL_T prTxCtrl;
709     BOOLEAN bStatus = FALSE;
710     UINT_32 i;
711
712     KAL_SPIN_LOCK_DECLARATION();
713
714
715     ASSERT(prAdapter);
716     prTxCtrl = &prAdapter->rTxCtrl;
717
718     if (pu4Tmp[0] | pu4Tmp[1]) {
719
720         KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_RESOURCE);
721         for (i = 0; i < TC_NUM; i++) {
722             prTxCtrl->rTc.aucFreeBufferCount[i] += aucTxRlsCnt[i];
723
724             if ((i==1) || (i==5)){
725                 DBGLOG(TX, EVENT, ("Release: i = %d aucFreeBufferCount = %d\n",
726                     i, prTxCtrl->rTc.aucFreeBufferCount[i]));
727             }
728         }
729         KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_RESOURCE);
730 #if 0
731         for (i = 0; i < TC_NUM; i++) {
732             DBGLOG(INIT, TRACE, ("aucFreeBufferCount[%d]: %d, aucMaxNumOfBuffer[%d]: %d\n",
733                 i, prTxCtrl->rTc.aucFreeBufferCount[i], i, prTxCtrl->rTc.aucMaxNumOfBuffer[i]));
734         }
735         DbgPrint("prTxCtrl->rTc.aucFreeBufferCount[0]=%d\n", prTxCtrl->rTc.aucFreeBufferCount[0]);
736         DbgPrint("prTxCtrl->rTc.aucFreeBufferCount[1]=%d\n", prTxCtrl->rTc.aucFreeBufferCount[1]);
737         DbgPrint("prTxCtrl->rTc.aucFreeBufferCount[2]=%d\n", prTxCtrl->rTc.aucFreeBufferCount[2]);
738         DbgPrint("prTxCtrl->rTc.aucFreeBufferCount[3]=%d\n", prTxCtrl->rTc.aucFreeBufferCount[3]);
739         DbgPrint("prTxCtrl->rTc.aucFreeBufferCount[4]=%d\n", prTxCtrl->rTc.aucFreeBufferCount[4]);
740         DbgPrint("prTxCtrl->rTc.aucFreeBufferCount[5]=%d\n", prTxCtrl->rTc.aucFreeBufferCount[5]);
741 #endif
742         ASSERT(prTxCtrl->rTc.aucFreeBufferCount[TC0_INDEX] <= prTxCtrl->rTc.aucMaxNumOfBuffer[TC0_INDEX]);
743         ASSERT(prTxCtrl->rTc.aucFreeBufferCount[TC1_INDEX] <= prTxCtrl->rTc.aucMaxNumOfBuffer[TC1_INDEX]);
744         ASSERT(prTxCtrl->rTc.aucFreeBufferCount[TC2_INDEX] <= prTxCtrl->rTc.aucMaxNumOfBuffer[TC2_INDEX]);
745         ASSERT(prTxCtrl->rTc.aucFreeBufferCount[TC3_INDEX] <= prTxCtrl->rTc.aucMaxNumOfBuffer[TC3_INDEX]);
746         ASSERT(prTxCtrl->rTc.aucFreeBufferCount[TC4_INDEX] <= prTxCtrl->rTc.aucMaxNumOfBuffer[TC4_INDEX]);
747         ASSERT(prTxCtrl->rTc.aucFreeBufferCount[TC5_INDEX] <= prTxCtrl->rTc.aucMaxNumOfBuffer[TC5_INDEX]);
748         bStatus = TRUE;
749     }
750
751     return bStatus;
752 } /* end of nicTxReleaseResource() */
753
754
755 /*----------------------------------------------------------------------------*/
756 /*!
757 * \brief Reset TC Buffer Count to initialized value
758 *
759 * \param[in] prAdapter              Pointer to the Adapter structure.
760 *
761 * @return WLAN_STATUS_SUCCESS
762 */
763 /*----------------------------------------------------------------------------*/
764 WLAN_STATUS
765 nicTxResetResource (
766     IN P_ADAPTER_T  prAdapter
767     )
768 {
769     P_TX_CTRL_T prTxCtrl;
770
771     KAL_SPIN_LOCK_DECLARATION();
772
773     DEBUGFUNC("nicTxResetResource");
774
775     ASSERT(prAdapter);
776     prTxCtrl = &prAdapter->rTxCtrl;
777
778     KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_RESOURCE);
779
780     prTxCtrl->rTc.aucMaxNumOfBuffer[TC0_INDEX] = NIC_TX_BUFF_COUNT_TC0;
781     prTxCtrl->rTc.aucFreeBufferCount[TC0_INDEX] = NIC_TX_BUFF_COUNT_TC0;
782
783     prTxCtrl->rTc.aucMaxNumOfBuffer[TC1_INDEX] = NIC_TX_BUFF_COUNT_TC1;
784     prTxCtrl->rTc.aucFreeBufferCount[TC1_INDEX] = NIC_TX_BUFF_COUNT_TC1;
785
786     prTxCtrl->rTc.aucMaxNumOfBuffer[TC2_INDEX] = NIC_TX_BUFF_COUNT_TC2;
787     prTxCtrl->rTc.aucFreeBufferCount[TC2_INDEX] = NIC_TX_BUFF_COUNT_TC2;
788
789     prTxCtrl->rTc.aucMaxNumOfBuffer[TC3_INDEX] = NIC_TX_BUFF_COUNT_TC3;
790     prTxCtrl->rTc.aucFreeBufferCount[TC3_INDEX] = NIC_TX_BUFF_COUNT_TC3;
791
792     prTxCtrl->rTc.aucMaxNumOfBuffer[TC4_INDEX] = NIC_TX_BUFF_COUNT_TC4;
793     prTxCtrl->rTc.aucFreeBufferCount[TC4_INDEX] = NIC_TX_BUFF_COUNT_TC4;
794
795     prTxCtrl->rTc.aucMaxNumOfBuffer[TC5_INDEX] = NIC_TX_BUFF_COUNT_TC5;
796     prTxCtrl->rTc.aucFreeBufferCount[TC5_INDEX] = NIC_TX_BUFF_COUNT_TC5;
797
798     KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_RESOURCE);
799
800     return WLAN_STATUS_SUCCESS;
801 }
802
803
804 /*----------------------------------------------------------------------------*/
805 /*!
806 * @brief Driver maintain a variable that is synchronous with the usage of individual
807 *        TC Buffer Count. This function will return the value for other component
808 *        which needs this information for making decisions
809 *
810 * @param prAdapter      Pointer to the Adapter structure.
811 * @param ucTC           Specify the resource of TC
812 *
813 * @retval UINT_8        The number of corresponding TC number
814 */
815 /*----------------------------------------------------------------------------*/
816 UINT_8
817 nicTxGetResource (
818     IN P_ADAPTER_T  prAdapter,
819     IN UINT_8       ucTC
820     )
821 {
822     P_TX_CTRL_T prTxCtrl;
823
824     ASSERT(prAdapter);
825     prTxCtrl = &prAdapter->rTxCtrl;
826
827     ASSERT(prTxCtrl);
828
829     if (ucTC >= TC_NUM) {
830         return 0;
831     }
832     else {
833         return prTxCtrl->rTc.aucFreeBufferCount[ucTC];
834     }
835 }
836
837
838 /*----------------------------------------------------------------------------*/
839 /*!
840 * @brief In this function, we'll aggregate frame(PACKET_INFO_T)
841 * corresponding to HIF TX port
842 *
843 * @param prAdapter              Pointer to the Adapter structure.
844 * @param prMsduInfoListHead     a link list of P_MSDU_INFO_T
845 *
846 * @retval WLAN_STATUS_SUCCESS   Bus access ok.
847 * @retval WLAN_STATUS_FAILURE   Bus access fail.
848 */
849 /*----------------------------------------------------------------------------*/
850 WLAN_STATUS
851 nicTxMsduInfoList (
852     IN P_ADAPTER_T      prAdapter,
853     IN P_MSDU_INFO_T    prMsduInfoListHead
854     )
855 {
856     P_MSDU_INFO_T prMsduInfo, prNextMsduInfo;
857     QUE_T qDataPort0, qDataPort1;
858     WLAN_STATUS status;
859
860     ASSERT(prAdapter);
861     ASSERT(prMsduInfoListHead);
862
863     prMsduInfo = prMsduInfoListHead;
864
865     QUEUE_INITIALIZE(&qDataPort0);
866     QUEUE_INITIALIZE(&qDataPort1);
867
868     // Separate MSDU_INFO_T lists into 2 categories: for Port#0 & Port#1
869     while(prMsduInfo) {
870         prNextMsduInfo = (P_MSDU_INFO_T)QUEUE_GET_NEXT_ENTRY((P_QUE_ENTRY_T)prMsduInfo);
871 #if DBG && 0
872         LOG_FUNC("nicTxMsduInfoList Acquire TC %d net %u mac len %u len %u Type %u 1x %u 11 %u\n",
873             prMsduInfo->ucTC,
874                 prMsduInfo->ucNetworkType,
875                 prMsduInfo->ucMacHeaderLength,
876             prMsduInfo->u2FrameLength,
877             prMsduInfo->ucPacketType,
878             prMsduInfo->fgIs802_1x,
879             prMsduInfo->fgIs802_11 );
880
881         LOG_FUNC("Dest Mac: " MACSTR "\n",
882                 MAC2STR(prMsduInfo->aucEthDestAddr));
883 #endif
884
885         switch(prMsduInfo->ucTC) {
886         case TC0_INDEX:
887         case TC1_INDEX:
888         case TC2_INDEX:
889         case TC3_INDEX:
890         case TC5_INDEX: // Broadcast/multicast data packets
891             QUEUE_GET_NEXT_ENTRY((P_QUE_ENTRY_T)prMsduInfo) = NULL;
892             QUEUE_INSERT_TAIL(&qDataPort0, (P_QUE_ENTRY_T)prMsduInfo);
893             status = nicTxAcquireResource(prAdapter, prMsduInfo->ucTC);
894             ASSERT(status == WLAN_STATUS_SUCCESS)
895
896             break;
897
898         case TC4_INDEX: // Command or 802.1x packets
899             QUEUE_GET_NEXT_ENTRY((P_QUE_ENTRY_T)prMsduInfo) = NULL;
900             QUEUE_INSERT_TAIL(&qDataPort1, (P_QUE_ENTRY_T)prMsduInfo);
901
902             status = nicTxAcquireResource(prAdapter, prMsduInfo->ucTC);
903             ASSERT(status == WLAN_STATUS_SUCCESS)
904
905             break;
906
907         default:
908             ASSERT(0);
909             break;
910         }
911
912         prMsduInfo = prNextMsduInfo;
913     }
914
915     if(qDataPort0.u4NumElem > 0) {
916         nicTxMsduQueue(prAdapter, 0, &qDataPort0);
917     }
918
919     if(qDataPort1.u4NumElem > 0) {
920         nicTxMsduQueue(prAdapter, 1, &qDataPort1);
921     }
922
923     return WLAN_STATUS_SUCCESS;
924 }
925
926 #if CFG_ENABLE_PKT_LIFETIME_PROFILE
927
928 PKT_PROFILE_T rPrevRoundLastPkt;
929
930 VOID
931 nicTxReturnMsduInfoProfiling (
932     IN P_ADAPTER_T    prAdapter,
933     IN P_MSDU_INFO_T  prMsduInfoListHead
934     )
935 {
936     P_MSDU_INFO_T prMsduInfo = prMsduInfoListHead, prNextMsduInfo;
937     
938     P_MSDU_INFO_T prFirstProfileMsduInfo = NULL;
939     P_MSDU_INFO_T prPrevProfileMsduInfo = NULL;
940     P_PKT_PROFILE_T prPrevRoundLastPkt = &rPrevRoundLastPkt;
941     P_PKT_PROFILE_T prPktProfile;
942     
943     BOOLEAN fgGotFirst = FALSE;
944     BOOLEAN fgPrintCurPkt = FALSE;
945     BOOLEAN fgIsPrevPrinted = FALSE;
946
947     UINT_32 u4MaxDeltaTime = 50; // in ms
948
949     while(prMsduInfo) {
950         prNextMsduInfo = (P_MSDU_INFO_T)QUEUE_GET_NEXT_ENTRY((P_QUE_ENTRY_T)prMsduInfo);
951         prPktProfile = &prMsduInfo->rPktProfile;
952         fgPrintCurPkt = FALSE;
953             
954         if(prPktProfile->fgIsValid) {
955             prPktProfile->rHifTxDoneTimestamp = kalGetTimeTick();
956
957             //4 1. check delta between current round first pkt and prevous round last pkt
958             if(!fgGotFirst) {
959                 prFirstProfileMsduInfo = prMsduInfo;
960                 fgGotFirst = TRUE;
961
962                 if(prPrevRoundLastPkt->fgIsValid) {
963                     if(CHK_PROFILES_DELTA(prPktProfile, prPrevRoundLastPkt, u4MaxDeltaTime)) {
964                         PRINT_PKT_PROFILE(prPrevRoundLastPkt, "PR");
965                         fgPrintCurPkt = TRUE;
966                     }
967                 }
968             }
969
970             //4 2. check delta between current pkt and previous pkt
971             if(prPrevProfileMsduInfo) {
972                 if(CHK_PROFILES_DELTA(prPktProfile, &prPrevProfileMsduInfo->rPktProfile, u4MaxDeltaTime)) {
973                     PRINT_PKT_PROFILE(&prPrevProfileMsduInfo->rPktProfile, "P");
974                     fgPrintCurPkt = TRUE;
975                 }
976             }
977
978             //4 3. check delta of current pkt lifetime
979             if(CHK_PROFILE_DELTA(prPktProfile, u4MaxDeltaTime)) {
980                 fgPrintCurPkt = TRUE;
981             }
982
983             /* Print current pkt profile */
984             if(fgPrintCurPkt) {
985                 PRINT_PKT_PROFILE(prPktProfile, "C");
986             }
987
988             fgIsPrevPrinted = fgPrintCurPkt;
989             prPrevProfileMsduInfo = prMsduInfo;
990         }
991
992         prMsduInfo = prNextMsduInfo;
993     };
994
995     //4 4. record the lifetime of current round last pkt
996     if(prPrevProfileMsduInfo) {
997         prPktProfile = &prPrevProfileMsduInfo->rPktProfile;
998         prPrevRoundLastPkt->u2IpSn = prPktProfile->u2IpSn;
999         prPrevRoundLastPkt->u2RtpSn = prPktProfile->u2RtpSn;
1000         prPrevRoundLastPkt->rHardXmitArrivalTimestamp = prPktProfile->rHardXmitArrivalTimestamp;
1001         prPrevRoundLastPkt->rEnqueueTimestamp = prPktProfile->rEnqueueTimestamp;
1002         prPrevRoundLastPkt->rDequeueTimestamp = prPktProfile->rDequeueTimestamp;
1003         prPrevRoundLastPkt->rHifTxDoneTimestamp = prPktProfile->rHifTxDoneTimestamp;
1004         prPrevRoundLastPkt->fgIsPrinted = prPktProfile->fgIsPrinted;
1005         prPrevRoundLastPkt->fgIsValid = TRUE;
1006     }
1007     
1008     nicTxReturnMsduInfo(prAdapter, prMsduInfoListHead);
1009
1010     return;
1011 }
1012 #endif
1013
1014 /*----------------------------------------------------------------------------*/
1015 /*!
1016 * @brief In this function, we'll write frame(PACKET_INFO_T) into HIF.
1017 *
1018 * @param prAdapter              Pointer to the Adapter structure.
1019 * @param ucPortIdx              Port Number
1020 * @param prQue                  a link list of P_MSDU_INFO_T
1021 *
1022 * @retval WLAN_STATUS_SUCCESS   Bus access ok.
1023 * @retval WLAN_STATUS_FAILURE   Bus access fail.
1024 */
1025 /*----------------------------------------------------------------------------*/
1026 WLAN_STATUS
1027 nicTxMsduQueue (
1028     IN P_ADAPTER_T  prAdapter,
1029     UINT_8          ucPortIdx,
1030     P_QUE_T         prQue
1031     )
1032 {
1033     P_MSDU_INFO_T prMsduInfo, prNextMsduInfo;
1034     HIF_TX_HEADER_T rHwTxHeader;
1035     P_NATIVE_PACKET prNativePacket;
1036     UINT_16 u2OverallBufferLength;
1037     UINT_8 ucEtherTypeOffsetInWord;
1038     PUINT_8 pucOutputBuf = (PUINT_8)NULL; /* Pointer to Transmit Data Structure Frame */
1039     UINT_32 u4TxHdrSize;
1040     UINT_32 u4ValidBufSize;
1041     UINT_32 u4TotalLength;
1042     P_TX_CTRL_T prTxCtrl;
1043     QUE_T rFreeQueue;
1044 #if CFG_TCP_IP_CHKSUM_OFFLOAD
1045     UINT_8 ucChksumFlag;
1046 #endif
1047
1048     ASSERT(prAdapter);
1049     ASSERT(ucPortIdx < 2);
1050     ASSERT(prQue);
1051
1052     prTxCtrl = &prAdapter->rTxCtrl;
1053     u4ValidBufSize = prAdapter->u4CoalescingBufCachedSize;
1054
1055 #if CFG_HIF_STATISTICS
1056     prTxCtrl->u4TotalTxAccessNum++;
1057     prTxCtrl->u4TotalTxPacketNum += prQue->u4NumElem;
1058 #endif
1059
1060     QUEUE_INITIALIZE(&rFreeQueue);
1061
1062     if(prQue->u4NumElem > 0) {
1063         prMsduInfo = (P_MSDU_INFO_T)QUEUE_GET_HEAD(prQue);
1064         pucOutputBuf = prTxCtrl->pucTxCoalescingBufPtr;
1065         u4TotalLength = 0;
1066
1067         while(prMsduInfo) {
1068
1069             kalMemZero(&rHwTxHeader, sizeof(rHwTxHeader));
1070
1071             prNativePacket = prMsduInfo->prPacket;
1072
1073             ASSERT(prNativePacket);
1074
1075             u4TxHdrSize = TX_HDR_SIZE;
1076
1077             u2OverallBufferLength = ((prMsduInfo->u2FrameLength + TX_HDR_SIZE) &
1078                     (UINT_16)HIF_TX_HDR_TX_BYTE_COUNT_MASK);
1079
1080             rHwTxHeader.u2TxByteCount_UserPriority = u2OverallBufferLength;
1081             rHwTxHeader.u2TxByteCount_UserPriority |=
1082                 ((UINT_16)prMsduInfo->ucUserPriority << HIF_TX_HDR_USER_PRIORITY_OFFSET);
1083
1084             if (prMsduInfo->fgIs802_11) {
1085                 ucEtherTypeOffsetInWord =
1086                     (TX_HDR_SIZE + prMsduInfo->ucMacHeaderLength + prMsduInfo->ucLlcLength) >> 1;
1087             }
1088             else {
1089                 ucEtherTypeOffsetInWord =
1090                     ((ETHER_HEADER_LEN - ETHER_TYPE_LEN) + TX_HDR_SIZE) >> 1;
1091             }
1092
1093             rHwTxHeader.ucEtherTypeOffset =
1094                 ucEtherTypeOffsetInWord & HIF_TX_HDR_ETHER_TYPE_OFFSET_MASK;
1095
1096             rHwTxHeader.ucResource_PktType_CSflags = (prMsduInfo->ucTC) << HIF_TX_HDR_RESOURCE_OFFSET;
1097             rHwTxHeader.ucResource_PktType_CSflags |=
1098                 (UINT_8)(((prMsduInfo->ucPacketType) << HIF_TX_HDR_PACKET_TYPE_OFFSET) &
1099                         (HIF_TX_HDR_PACKET_TYPE_MASK));
1100
1101 #if CFG_TCP_IP_CHKSUM_OFFLOAD
1102             if (prMsduInfo->eSrc == TX_PACKET_OS) {
1103                 if (prAdapter->u4CSUMFlags &
1104                         (CSUM_OFFLOAD_EN_TX_TCP |
1105                          CSUM_OFFLOAD_EN_TX_UDP |
1106                          CSUM_OFFLOAD_EN_TX_IP)) {
1107                     kalQueryTxChksumOffloadParam(prNativePacket, &ucChksumFlag);
1108
1109                     if (ucChksumFlag & TX_CS_IP_GEN) {
1110                         rHwTxHeader.ucResource_PktType_CSflags |= (UINT_8)HIF_TX_HDR_IP_CSUM;
1111                     }
1112
1113                     if (ucChksumFlag & TX_CS_TCP_UDP_GEN) {
1114                         rHwTxHeader.ucResource_PktType_CSflags |= (UINT_8)HIF_TX_HDR_TCP_CSUM;
1115                     }
1116                 }
1117             }
1118 #endif /* CFG_TCP_IP_CHKSUM_OFFLOAD */
1119
1120             rHwTxHeader.u2LLH = prMsduInfo->u2PalLLH;
1121             rHwTxHeader.ucStaRecIdx = prMsduInfo->ucStaRecIndex;
1122             rHwTxHeader.ucForwardingType_SessionID_Reserved =
1123                 (prMsduInfo->ucPsForwardingType) | ((prMsduInfo->ucPsSessionID) << HIF_TX_HDR_PS_SESSION_ID_OFFSET)
1124                 | ((prMsduInfo->fgIsBurstEnd)? HIF_TX_HDR_BURST_END_MASK : 0);
1125
1126             rHwTxHeader.ucWlanHeaderLength = (prMsduInfo->ucMacHeaderLength & HIF_TX_HDR_WLAN_HEADER_LEN_MASK);
1127             rHwTxHeader.ucPktFormtId_Flags =
1128                 (prMsduInfo->ucFormatID & HIF_TX_HDR_FORMAT_ID_MASK)
1129                 | ((prMsduInfo->ucNetworkType << HIF_TX_HDR_NETWORK_TYPE_OFFSET) & HIF_TX_HDR_NETWORK_TYPE_MASK)
1130                 | ((prMsduInfo->fgIs802_1x << HIF_TX_HDR_FLAG_1X_FRAME_OFFSET) & HIF_TX_HDR_FLAG_1X_FRAME_MASK)
1131                 | ((prMsduInfo->fgIs802_11 << HIF_TX_HDR_FLAG_802_11_FORMAT_OFFSET) & HIF_TX_HDR_FLAG_802_11_FORMAT_MASK);
1132
1133             rHwTxHeader.u2SeqNo = prMsduInfo->u2AclSN;
1134
1135             if(prMsduInfo->pfTxDoneHandler) {
1136                 rHwTxHeader.ucPacketSeqNo = prMsduInfo->ucTxSeqNum;
1137                 rHwTxHeader.ucAck_BIP_BasicRate = HIF_TX_HDR_NEED_ACK;
1138             }
1139             else {
1140                 rHwTxHeader.ucPacketSeqNo = 0;
1141                 rHwTxHeader.ucAck_BIP_BasicRate = 0;
1142             }
1143
1144             if(prMsduInfo->fgIsBIP) {
1145                 rHwTxHeader.ucAck_BIP_BasicRate |= HIF_TX_HDR_BIP;
1146             }
1147
1148             if(prMsduInfo->fgIsBasicRate) {
1149                 rHwTxHeader.ucAck_BIP_BasicRate |= HIF_TX_HDR_BASIC_RATE;
1150             }
1151
1152 #if CFG_ENABLE_PKT_LIFETIME_PROFILE
1153             if(prMsduInfo->rPktProfile.fgIsValid) {
1154                 prMsduInfo->rPktProfile.rDequeueTimestamp = kalGetTimeTick();
1155             }
1156 #endif            
1157
1158 #if CFG_SDIO_TX_AGG
1159             // attach to coalescing buffer
1160             kalMemCopy(pucOutputBuf + u4TotalLength, &rHwTxHeader, u4TxHdrSize);
1161             u4TotalLength += u4TxHdrSize;
1162
1163             if (prMsduInfo->eSrc == TX_PACKET_OS
1164                     || prMsduInfo->eSrc == TX_PACKET_FORWARDING) {
1165                 kalCopyFrame(prAdapter->prGlueInfo,
1166                         prNativePacket,
1167                         pucOutputBuf + u4TotalLength);
1168             }
1169             else if(prMsduInfo->eSrc == TX_PACKET_MGMT) {
1170                 kalMemCopy(pucOutputBuf + u4TotalLength,
1171                         prNativePacket,
1172                         prMsduInfo->u2FrameLength);
1173             }
1174             else {
1175                 ASSERT(0);
1176             }
1177
1178             u4TotalLength += ALIGN_4(prMsduInfo->u2FrameLength);
1179
1180 #else
1181             kalMemCopy(pucOutputBuf, &rHwTxHeader, u4TxHdrSize);
1182
1183             /* Copy Frame Body */
1184             if (prMsduInfo->eSrc == TX_PACKET_OS
1185                     || prMsduInfo->eSrc == TX_PACKET_FORWARDING) {
1186                 kalCopyFrame(prAdapter->prGlueInfo,
1187                         prNativePacket,
1188                         pucOutputBuf + u4TxHdrSize);
1189             }
1190             else if(prMsduInfo->eSrc == TX_PACKET_MGMT) {
1191                 kalMemCopy(pucOutputBuf + u4TxHdrSize,
1192                         prNativePacket,
1193                         prMsduInfo->u2FrameLength);
1194             }
1195             else {
1196                 ASSERT(0);
1197             }
1198
1199             ASSERT(u2OverallBufferLength <= u4ValidBufSize);
1200
1201             HAL_WRITE_TX_PORT(prAdapter,
1202                     ucPortIdx,
1203                     (UINT_32)u2OverallBufferLength,
1204                     (PUINT_8)pucOutputBuf,
1205                     u4ValidBufSize);
1206
1207             // send immediately
1208 #endif
1209             prNextMsduInfo = (P_MSDU_INFO_T)
1210                         QUEUE_GET_NEXT_ENTRY(&prMsduInfo->rQueEntry);
1211
1212             if (prMsduInfo->eSrc == TX_PACKET_MGMT) {
1213                 GLUE_DEC_REF_CNT(prTxCtrl->i4TxMgmtPendingNum);
1214
1215                 if (prMsduInfo->pfTxDoneHandler == NULL) {
1216                     cnmMgtPktFree(prAdapter, prMsduInfo);
1217                 }
1218                 else {
1219                     KAL_SPIN_LOCK_DECLARATION();
1220                     DBGLOG(INIT, TRACE,("Wait TxSeqNum:%d\n", prMsduInfo->ucTxSeqNum));
1221                     KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TXING_MGMT_LIST);
1222                     QUEUE_INSERT_TAIL(&(prTxCtrl->rTxMgmtTxingQueue), (P_QUE_ENTRY_T)prMsduInfo);
1223                     KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TXING_MGMT_LIST);
1224                 }
1225             }
1226             else {
1227                 /* only free MSDU when it is not a MGMT frame */
1228                 QUEUE_INSERT_TAIL(&rFreeQueue, (P_QUE_ENTRY_T)prMsduInfo);
1229
1230                 if (prMsduInfo->eSrc == TX_PACKET_OS) {
1231                     kalSendComplete(prAdapter->prGlueInfo,
1232                             prNativePacket,
1233                             WLAN_STATUS_SUCCESS);
1234                 }
1235                 else if(prMsduInfo->eSrc == TX_PACKET_FORWARDING) {
1236                     GLUE_DEC_REF_CNT(prTxCtrl->i4PendingFwdFrameCount);
1237                 }
1238             }
1239
1240             prMsduInfo = prNextMsduInfo;
1241         }
1242
1243 #if CFG_SDIO_TX_AGG
1244         ASSERT(u4TotalLength <= u4ValidBufSize);
1245
1246     #if CFG_DBG_GPIO_PINS
1247         {
1248             /* Start port write */
1249             mtk_wcn_stp_debug_gpio_assert(IDX_TX_PORT_WRITE, DBG_TIE_LOW);
1250             kalUdelay(1);
1251             mtk_wcn_stp_debug_gpio_assert(IDX_TX_PORT_WRITE, DBG_TIE_HIGH);
1252         }
1253     #endif
1254
1255         // send coalescing buffer
1256         HAL_WRITE_TX_PORT(prAdapter,
1257                 ucPortIdx,
1258                 u4TotalLength,
1259                 (PUINT_8)pucOutputBuf,
1260                 u4ValidBufSize);
1261 #endif
1262
1263 #if CFG_ENABLE_PKT_LIFETIME_PROFILE
1264         nicTxReturnMsduInfoProfiling(prAdapter, (P_MSDU_INFO_T)QUEUE_GET_HEAD(&rFreeQueue));
1265 #else
1266         // return
1267         nicTxReturnMsduInfo(prAdapter, (P_MSDU_INFO_T)QUEUE_GET_HEAD(&rFreeQueue));
1268 #endif
1269     }
1270
1271     return WLAN_STATUS_SUCCESS;
1272 }
1273
1274
1275 /*----------------------------------------------------------------------------*/
1276 /*!
1277 * \brief In this function, we'll write Command(CMD_INFO_T) into HIF.
1278 *
1279 * @param prAdapter      Pointer to the Adapter structure.
1280 * @param prPacketInfo   Pointer of CMD_INFO_T
1281 * @param ucTC           Specify the resource of TC
1282 *
1283 * @retval WLAN_STATUS_SUCCESS   Bus access ok.
1284 * @retval WLAN_STATUS_FAILURE   Bus access fail.
1285 */
1286 /*----------------------------------------------------------------------------*/
1287 WLAN_STATUS
1288 nicTxCmd (
1289     IN P_ADAPTER_T      prAdapter,
1290     IN P_CMD_INFO_T     prCmdInfo,
1291     IN UINT_8           ucTC
1292     )
1293 {
1294     P_WIFI_CMD_T prWifiCmd;
1295     UINT_16 u2OverallBufferLength;
1296     PUINT_8 pucOutputBuf = (PUINT_8)NULL; /* Pointer to Transmit Data Structure Frame */
1297     UINT_8 ucPortIdx;
1298     HIF_TX_HEADER_T rHwTxHeader;
1299     P_NATIVE_PACKET prNativePacket;
1300     UINT_8 ucEtherTypeOffsetInWord;
1301     P_MSDU_INFO_T prMsduInfo;
1302     P_TX_CTRL_T prTxCtrl;
1303
1304     KAL_SPIN_LOCK_DECLARATION();
1305
1306
1307     ASSERT(prAdapter);
1308     ASSERT(prCmdInfo);
1309
1310     prTxCtrl = &prAdapter->rTxCtrl;
1311     pucOutputBuf = prTxCtrl->pucTxCoalescingBufPtr;
1312
1313     // <1> Assign Data Port
1314     if (ucTC != TC4_INDEX) {
1315         ucPortIdx = 0;
1316     }
1317     else {
1318         // Broadcast/multicast data frames, 1x frames, command packets, MMPDU
1319         ucPortIdx = 1;
1320     }
1321
1322     if(prCmdInfo->eCmdType == COMMAND_TYPE_SECURITY_FRAME) {
1323         // <2> Compose HIF_TX_HEADER
1324         kalMemZero(&rHwTxHeader, sizeof(rHwTxHeader));
1325
1326         prNativePacket = prCmdInfo->prPacket;
1327
1328         ASSERT(prNativePacket);
1329
1330         u2OverallBufferLength = TFCB_FRAME_PAD_TO_DW((prCmdInfo->u2InfoBufLen + TX_HDR_SIZE)
1331                 & (UINT_16)HIF_TX_HDR_TX_BYTE_COUNT_MASK);
1332
1333         rHwTxHeader.u2TxByteCount_UserPriority = ((prCmdInfo->u2InfoBufLen + TX_HDR_SIZE)
1334                 & (UINT_16)HIF_TX_HDR_TX_BYTE_COUNT_MASK);
1335         ucEtherTypeOffsetInWord = ((ETHER_HEADER_LEN - ETHER_TYPE_LEN) + TX_HDR_SIZE) >> 1;
1336
1337         rHwTxHeader.ucEtherTypeOffset =
1338             ucEtherTypeOffsetInWord & HIF_TX_HDR_ETHER_TYPE_OFFSET_MASK;
1339
1340         rHwTxHeader.ucResource_PktType_CSflags = (ucTC << HIF_TX_HDR_RESOURCE_OFFSET);
1341
1342         rHwTxHeader.ucStaRecIdx = prCmdInfo->ucStaRecIndex;
1343         rHwTxHeader.ucForwardingType_SessionID_Reserved = HIF_TX_HDR_BURST_END_MASK;
1344
1345         rHwTxHeader.ucWlanHeaderLength = (ETH_HLEN & HIF_TX_HDR_WLAN_HEADER_LEN_MASK);
1346         rHwTxHeader.ucPktFormtId_Flags =
1347             (((UINT_8)(prCmdInfo->eNetworkType) << HIF_TX_HDR_NETWORK_TYPE_OFFSET) & HIF_TX_HDR_NETWORK_TYPE_MASK)
1348             | ((1 << HIF_TX_HDR_FLAG_1X_FRAME_OFFSET) & HIF_TX_HDR_FLAG_1X_FRAME_MASK);
1349
1350         rHwTxHeader.u2SeqNo = 0;
1351         rHwTxHeader.ucPacketSeqNo = 0;
1352         rHwTxHeader.ucAck_BIP_BasicRate = 0;
1353
1354         // <2.3> Copy HIF TX HEADER
1355         kalMemCopy((PVOID)&pucOutputBuf[0], (PVOID)&rHwTxHeader, TX_HDR_SIZE);
1356
1357         // <3> Copy Frame Body Copy
1358         kalCopyFrame(prAdapter->prGlueInfo,
1359                 prNativePacket,
1360                 pucOutputBuf + TX_HDR_SIZE);
1361     }
1362     else if(prCmdInfo->eCmdType == COMMAND_TYPE_MANAGEMENT_FRAME) {
1363         prMsduInfo = (P_MSDU_INFO_T)prCmdInfo->prPacket;
1364
1365         ASSERT(prMsduInfo->fgIs802_11 == TRUE);
1366         ASSERT(prMsduInfo->eSrc == TX_PACKET_MGMT);
1367
1368         // <2> Compose HIF_TX_HEADER
1369         kalMemZero(&rHwTxHeader, sizeof(rHwTxHeader));
1370
1371         u2OverallBufferLength = ((prMsduInfo->u2FrameLength + TX_HDR_SIZE) &
1372                                   (UINT_16)HIF_TX_HDR_TX_BYTE_COUNT_MASK);
1373
1374         rHwTxHeader.u2TxByteCount_UserPriority = u2OverallBufferLength;
1375         rHwTxHeader.u2TxByteCount_UserPriority |=
1376                 ((UINT_16)prMsduInfo->ucUserPriority << HIF_TX_HDR_USER_PRIORITY_OFFSET);
1377
1378         ucEtherTypeOffsetInWord =
1379                 (TX_HDR_SIZE + prMsduInfo->ucMacHeaderLength + prMsduInfo->ucLlcLength) >> 1;
1380
1381         rHwTxHeader.ucEtherTypeOffset =
1382                 ucEtherTypeOffsetInWord & HIF_TX_HDR_ETHER_TYPE_OFFSET_MASK;
1383
1384         rHwTxHeader.ucResource_PktType_CSflags = (prMsduInfo->ucTC) << HIF_TX_HDR_RESOURCE_OFFSET;
1385         rHwTxHeader.ucResource_PktType_CSflags |=
1386                 (UINT_8)(((prMsduInfo->ucPacketType) << HIF_TX_HDR_PACKET_TYPE_OFFSET) &
1387                                     (HIF_TX_HDR_PACKET_TYPE_MASK));
1388
1389         rHwTxHeader.u2LLH = prMsduInfo->u2PalLLH;
1390         rHwTxHeader.ucStaRecIdx = prMsduInfo->ucStaRecIndex;
1391         rHwTxHeader.ucForwardingType_SessionID_Reserved =
1392             (prMsduInfo->ucPsForwardingType) | ((prMsduInfo->ucPsSessionID) << HIF_TX_HDR_PS_SESSION_ID_OFFSET)
1393             | ((prMsduInfo->fgIsBurstEnd)? HIF_TX_HDR_BURST_END_MASK : 0);
1394
1395         rHwTxHeader.ucWlanHeaderLength = (prMsduInfo->ucMacHeaderLength & HIF_TX_HDR_WLAN_HEADER_LEN_MASK);
1396         rHwTxHeader.ucPktFormtId_Flags =
1397             (prMsduInfo->ucFormatID & HIF_TX_HDR_FORMAT_ID_MASK)
1398             | ((prMsduInfo->ucNetworkType << HIF_TX_HDR_NETWORK_TYPE_OFFSET) & HIF_TX_HDR_NETWORK_TYPE_MASK)
1399             | ((prMsduInfo->fgIs802_1x << HIF_TX_HDR_FLAG_1X_FRAME_OFFSET) & HIF_TX_HDR_FLAG_1X_FRAME_MASK)
1400             | ((prMsduInfo->fgIs802_11 << HIF_TX_HDR_FLAG_802_11_FORMAT_OFFSET) & HIF_TX_HDR_FLAG_802_11_FORMAT_MASK);
1401
1402         rHwTxHeader.u2SeqNo = prMsduInfo->u2AclSN;
1403
1404         if(prMsduInfo->pfTxDoneHandler) {
1405             rHwTxHeader.ucPacketSeqNo = prMsduInfo->ucTxSeqNum;
1406             rHwTxHeader.ucAck_BIP_BasicRate = HIF_TX_HDR_NEED_ACK;
1407         }
1408         else {
1409             rHwTxHeader.ucPacketSeqNo = 0;
1410             rHwTxHeader.ucAck_BIP_BasicRate = 0;
1411         }
1412
1413         if(prMsduInfo->fgIsBIP) {
1414             rHwTxHeader.ucAck_BIP_BasicRate |= HIF_TX_HDR_BIP;
1415         }
1416
1417         if(prMsduInfo->fgIsBasicRate) {
1418             rHwTxHeader.ucAck_BIP_BasicRate |= HIF_TX_HDR_BASIC_RATE;
1419         }
1420
1421         // <2.3> Copy HIF TX HEADER
1422         kalMemCopy((PVOID)&pucOutputBuf[0], (PVOID)&rHwTxHeader, TX_HDR_SIZE);
1423
1424         // <3> Copy Frame Body
1425         kalMemCopy(pucOutputBuf + TX_HDR_SIZE,
1426                 prMsduInfo->prPacket,
1427                 prMsduInfo->u2FrameLength);
1428
1429         // <4> Management Frame Post-Processing
1430         GLUE_DEC_REF_CNT(prTxCtrl->i4TxMgmtPendingNum);
1431
1432         if (prMsduInfo->pfTxDoneHandler == NULL) {
1433             cnmMgtPktFree(prAdapter, prMsduInfo);
1434         }
1435         else {
1436
1437             DBGLOG(INIT, TRACE,("Wait Cmd TxSeqNum:%d\n", prMsduInfo->ucTxSeqNum));
1438
1439             KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TXING_MGMT_LIST);
1440             QUEUE_INSERT_TAIL(&(prTxCtrl->rTxMgmtTxingQueue), (P_QUE_ENTRY_T)prMsduInfo);
1441             KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TXING_MGMT_LIST);
1442         }
1443     }
1444     else {
1445         prWifiCmd = (P_WIFI_CMD_T)prCmdInfo->pucInfoBuffer;
1446
1447         // <2> Compose the Header of Transmit Data Structure for CMD Packet
1448         u2OverallBufferLength = TFCB_FRAME_PAD_TO_DW(
1449                (prCmdInfo->u2InfoBufLen) & (UINT_16)HIF_TX_HDR_TX_BYTE_COUNT_MASK);
1450
1451         prWifiCmd->u2TxByteCount_UserPriority = u2OverallBufferLength;
1452         prWifiCmd->ucEtherTypeOffset = 0;
1453         prWifiCmd->ucResource_PktType_CSflags = (ucTC << HIF_TX_HDR_RESOURCE_OFFSET)
1454             | (UINT_8)((HIF_TX_PKT_TYPE_CMD << HIF_TX_HDR_PACKET_TYPE_OFFSET) & (HIF_TX_HDR_PACKET_TYPE_MASK));
1455
1456
1457         // <3> Copy CMD Header to command buffer (by using pucCoalescingBufCached)
1458         kalMemCopy((PVOID)&pucOutputBuf[0],
1459                    (PVOID)prCmdInfo->pucInfoBuffer,
1460                    prCmdInfo->u2InfoBufLen);
1461
1462         ASSERT(u2OverallBufferLength <= prAdapter->u4CoalescingBufCachedSize);
1463     }
1464
1465     // <4> Write frame to data port
1466     HAL_WRITE_TX_PORT(prAdapter,
1467             ucPortIdx,
1468             (UINT_32)u2OverallBufferLength,
1469             (PUINT_8)pucOutputBuf,
1470             (UINT_32)prAdapter->u4CoalescingBufCachedSize);
1471
1472     return WLAN_STATUS_SUCCESS;
1473 } /* end of nicTxCmd() */
1474
1475
1476 /*----------------------------------------------------------------------------*/
1477 /*!
1478 * @brief This function will clean up all the pending frames in internal SW Queues
1479 *        by return the pending TX packet to the system.
1480 *
1481 * @param prAdapter  Pointer to the Adapter structure.
1482 *
1483 * @return (none)
1484 */
1485 /*----------------------------------------------------------------------------*/
1486 VOID
1487 nicTxRelease (
1488     IN P_ADAPTER_T  prAdapter
1489     )
1490 {
1491     P_TX_CTRL_T prTxCtrl;
1492     P_MSDU_INFO_T prMsduInfo;
1493
1494     KAL_SPIN_LOCK_DECLARATION();
1495
1496     ASSERT(prAdapter);
1497
1498     prTxCtrl = &prAdapter->rTxCtrl;
1499
1500     nicTxFlush(prAdapter);
1501
1502     // free MSDU_INFO_T from rTxMgmtMsduInfoList
1503     do {
1504         KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TXING_MGMT_LIST);
1505         QUEUE_REMOVE_HEAD(&prTxCtrl->rTxMgmtTxingQueue, prMsduInfo, P_MSDU_INFO_T);
1506         KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TXING_MGMT_LIST);
1507
1508         if(prMsduInfo) {
1509             // the packet must be mgmt frame with tx done callback
1510             ASSERT(prMsduInfo->eSrc == TX_PACKET_MGMT);
1511             ASSERT(prMsduInfo->pfTxDoneHandler != NULL);
1512
1513             // invoke done handler
1514             prMsduInfo->pfTxDoneHandler(prAdapter, prMsduInfo, TX_RESULT_LIFE_TIMEOUT);
1515
1516             cnmMgtPktFree(prAdapter, prMsduInfo);
1517         }
1518         else {
1519             break;
1520         }
1521     } while(TRUE);
1522
1523     return;
1524 } /* end of nicTxRelease() */
1525
1526
1527 /*----------------------------------------------------------------------------*/
1528 /*!
1529 * @brief Process the TX Done interrupt and pull in more pending frames in SW
1530 *        Queues for transmission.
1531 *
1532 * @param prAdapter  Pointer to the Adapter structure.
1533 *
1534 * @return (none)
1535 */
1536 /*----------------------------------------------------------------------------*/
1537 VOID
1538 nicProcessTxInterrupt(
1539     IN P_ADAPTER_T prAdapter
1540     )
1541 {
1542     P_TX_CTRL_T prTxCtrl;
1543 #if CFG_SDIO_INTR_ENHANCE
1544     P_SDIO_CTRL_T prSDIOCtrl;
1545 #else
1546     UINT_32 au4TxCount[2];
1547 #endif /* CFG_SDIO_INTR_ENHANCE */
1548
1549     ASSERT(prAdapter);
1550
1551     prTxCtrl = &prAdapter->rTxCtrl;
1552     ASSERT(prTxCtrl);
1553
1554      /* Get the TX STATUS */
1555 #if CFG_SDIO_INTR_ENHANCE
1556
1557     prSDIOCtrl = prAdapter->prSDIOCtrl;
1558     #if DBG
1559     //dumpMemory8((PUINT_8)prSDIOCtrl, sizeof(SDIO_CTRL_T));
1560     #endif
1561
1562     nicTxReleaseResource(prAdapter, (PUINT_8)&prSDIOCtrl->rTxInfo);
1563     kalMemZero(&prSDIOCtrl->rTxInfo, sizeof(prSDIOCtrl->rTxInfo));
1564
1565 #else
1566
1567     HAL_MCR_RD(prAdapter, MCR_WTSR0, &au4TxCount[0]);
1568     HAL_MCR_RD(prAdapter, MCR_WTSR1, &au4TxCount[1]);
1569     DBGLOG(EMU, TRACE, ("MCR_WTSR0: 0x%x, MCR_WTSR1: 0x%x\n", au4TxCount[0], au4TxCount[1]));
1570
1571     nicTxReleaseResource(prAdapter, (PUINT_8)au4TxCount);
1572
1573 #endif /* CFG_SDIO_INTR_ENHANCE */
1574
1575     nicTxAdjustTcq(prAdapter);
1576
1577     // Indicate Service Thread
1578     if(kalGetTxPendingCmdCount(prAdapter->prGlueInfo) > 0
1579             || wlanGetTxPendingFrameCount(prAdapter) > 0) {
1580         kalSetEvent(prAdapter->prGlueInfo);
1581     }
1582
1583     return;
1584 } /* end of nicProcessTxInterrupt() */
1585
1586
1587 /*----------------------------------------------------------------------------*/
1588 /*!
1589 * @brief this function frees packet of P_MSDU_INFO_T linked-list
1590 *
1591 * @param prAdapter              Pointer to the Adapter structure.
1592 * @param prMsduInfoList         a link list of P_MSDU_INFO_T
1593 *
1594 * @return (none)
1595 */
1596 /*----------------------------------------------------------------------------*/
1597 VOID
1598 nicTxFreeMsduInfoPacket (
1599     IN P_ADAPTER_T    prAdapter,
1600     IN P_MSDU_INFO_T  prMsduInfoListHead
1601     )
1602 {
1603     P_NATIVE_PACKET prNativePacket;
1604     P_MSDU_INFO_T prMsduInfo = prMsduInfoListHead;
1605     P_TX_CTRL_T prTxCtrl;
1606
1607
1608     ASSERT(prAdapter);
1609     ASSERT(prMsduInfoListHead);
1610
1611     prTxCtrl = &prAdapter->rTxCtrl;
1612
1613     while(prMsduInfo) {
1614         prNativePacket = prMsduInfo->prPacket;
1615
1616         if(prMsduInfo->eSrc == TX_PACKET_OS) {
1617             kalSendComplete(prAdapter->prGlueInfo,
1618                     prNativePacket,
1619                     WLAN_STATUS_FAILURE);
1620         }
1621         else if(prMsduInfo->eSrc == TX_PACKET_MGMT) {
1622             if (prMsduInfo->pfTxDoneHandler) {
1623                 prMsduInfo->pfTxDoneHandler(prAdapter, prMsduInfo, TX_RESULT_DROPPED_IN_DRIVER);
1624             }
1625             cnmMemFree(prAdapter, prNativePacket);
1626         }
1627         else if(prMsduInfo->eSrc == TX_PACKET_FORWARDING) {
1628             GLUE_DEC_REF_CNT(prTxCtrl->i4PendingFwdFrameCount);
1629         }
1630
1631         prMsduInfo = (P_MSDU_INFO_T)QUEUE_GET_NEXT_ENTRY((P_QUE_ENTRY_T)prMsduInfo);
1632     }
1633
1634     return;
1635 }
1636
1637
1638 /*----------------------------------------------------------------------------*/
1639 /*!
1640 * @brief this function returns P_MSDU_INFO_T of MsduInfoList to TxCtrl->rfreeMsduInfoList
1641 *
1642 * @param prAdapter              Pointer to the Adapter structure.
1643 * @param prMsduInfoList         a link list of P_MSDU_INFO_T
1644 *
1645 * @return (none)
1646 */
1647 /*----------------------------------------------------------------------------*/
1648 VOID
1649 nicTxReturnMsduInfo (
1650     IN P_ADAPTER_T    prAdapter,
1651     IN P_MSDU_INFO_T  prMsduInfoListHead
1652     )
1653 {
1654     P_TX_CTRL_T prTxCtrl;
1655     P_MSDU_INFO_T prMsduInfo = prMsduInfoListHead, prNextMsduInfo;
1656
1657     KAL_SPIN_LOCK_DECLARATION();
1658
1659     ASSERT(prAdapter);
1660
1661     prTxCtrl = &prAdapter->rTxCtrl;
1662     ASSERT(prTxCtrl);
1663
1664     while(prMsduInfo) {
1665         prNextMsduInfo = (P_MSDU_INFO_T)QUEUE_GET_NEXT_ENTRY((P_QUE_ENTRY_T)prMsduInfo);
1666
1667         switch(prMsduInfo->eSrc) {
1668         case TX_PACKET_FORWARDING:
1669             wlanReturnPacket(prAdapter, prMsduInfo->prPacket);
1670             break;
1671         case TX_PACKET_OS:
1672         case TX_PACKET_OS_OID:
1673         case TX_PACKET_MGMT:
1674         default:
1675             break;
1676         }
1677
1678         KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_MSDU_INFO_LIST);
1679         QUEUE_INSERT_TAIL(&prTxCtrl->rFreeMsduInfoList, (P_QUE_ENTRY_T)prMsduInfo);
1680         KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_MSDU_INFO_LIST);
1681         prMsduInfo = prNextMsduInfo;
1682     };
1683
1684     return;
1685 }
1686
1687
1688
1689 /*----------------------------------------------------------------------------*/
1690 /*!
1691 * @brief this function fills packet information to P_MSDU_INFO_T
1692 *
1693 * @param prAdapter              Pointer to the Adapter structure.
1694 * @param prMsduInfo             P_MSDU_INFO_T
1695 * @param prPacket               P_NATIVE_PACKET
1696 *
1697 * @retval TRUE      Success to extract information
1698 * @retval FALSE     Fail to extract correct information
1699 */
1700 /*----------------------------------------------------------------------------*/
1701 BOOLEAN
1702 nicTxFillMsduInfo (
1703     IN P_ADAPTER_T     prAdapter,
1704     IN P_MSDU_INFO_T   prMsduInfo,
1705     IN P_NATIVE_PACKET prPacket
1706     )
1707 {
1708     P_GLUE_INFO_T   prGlueInfo;
1709     UINT_8          ucPriorityParam;
1710     UINT_8          ucMacHeaderLen;
1711     UINT_8          aucEthDestAddr[PARAM_MAC_ADDR_LEN];
1712     BOOLEAN         fgIs1x = FALSE;
1713     BOOLEAN         fgIsPAL = FALSE;
1714     UINT_32         u4PacketLen;
1715     ULONG           u4SysTime;
1716     UINT_8          ucNetworkType;
1717
1718
1719     ASSERT(prAdapter);
1720
1721     prGlueInfo = prAdapter->prGlueInfo;
1722     ASSERT(prGlueInfo);
1723
1724     if (kalQoSFrameClassifierAndPacketInfo(prGlueInfo,
1725                 prPacket,
1726                 &ucPriorityParam,
1727                 &u4PacketLen,
1728                 aucEthDestAddr,
1729                 &fgIs1x,
1730                 &fgIsPAL,
1731                 &ucNetworkType) == FALSE) {
1732         return FALSE;
1733     }
1734
1735     #if CFG_ENABLE_PKT_LIFETIME_PROFILE
1736     do {        
1737         struct sk_buff *prSkb = (struct sk_buff *) prPacket;
1738         UINT_16 u2EtherTypeLen;        
1739         PUINT_8 aucLookAheadBuf = NULL;
1740         P_PKT_PROFILE_T prPktProfile = &prMsduInfo->rPktProfile;
1741
1742         UINT_8 ucRtpSnOffset = 30;
1743         UINT_32 u4RtpSrcPort = 15550;
1744         
1745
1746         prPktProfile->fgIsValid = FALSE;
1747
1748         aucLookAheadBuf = prSkb->data;
1749
1750         u2EtherTypeLen = (aucLookAheadBuf[ETH_TYPE_LEN_OFFSET] << 8) | (aucLookAheadBuf[ETH_TYPE_LEN_OFFSET + 1]);
1751
1752         if ((u2EtherTypeLen == ETH_P_IP) &&
1753             (u4PacketLen >= LOOK_AHEAD_LEN)) {
1754             PUINT_8 pucIpHdr = &aucLookAheadBuf[ETH_HLEN];
1755             UINT_8 ucIpVersion;
1756         
1757             ucIpVersion = (pucIpHdr[0] & IPVH_VERSION_MASK) >> IPVH_VERSION_OFFSET;
1758             if (ucIpVersion == IPVERSION) {
1759                 if(pucIpHdr[IPV4_HDR_IP_PROTOCOL_OFFSET] == IP_PROTOCOL_UDP) {
1760
1761                     /* Enable packet lifetime profiling */
1762                     prPktProfile->fgIsValid = TRUE;
1763
1764                     prPktProfile->fgIsPrinted = FALSE;
1765
1766                     /* RTP SN */
1767                     prPktProfile->u2RtpSn = pucIpHdr[ucRtpSnOffset] << 8 | pucIpHdr[ucRtpSnOffset + 1];
1768
1769                     /* IP SN */
1770                     prPktProfile->u2IpSn = pucIpHdr[IPV4_HDR_IP_IDENTIFICATION_OFFSET] << 8 |
1771                                                                     pucIpHdr[IPV4_HDR_IP_IDENTIFICATION_OFFSET + 1];
1772
1773                     /* Packet arrival time at kernel Hard Xmit */
1774                     prPktProfile->rHardXmitArrivalTimestamp = GLUE_GET_PKT_ARRIVAL_TIME(prPacket);
1775
1776                     /* Packet enqueue time */
1777                     prPktProfile->rEnqueueTimestamp = (OS_SYSTIME)kalGetTimeTick();
1778                 }
1779             }
1780         }
1781     }while(FALSE);
1782     #endif
1783
1784     /* Save the value of Priority Parameter */
1785     GLUE_SET_PKT_TID(prPacket, ucPriorityParam);
1786
1787     if (fgIs1x) {
1788         GLUE_SET_PKT_FLAG_1X(prPacket);
1789     }
1790
1791     if (fgIsPAL) {
1792         GLUE_SET_PKT_FLAG_PAL(prPacket);
1793     }
1794
1795     ucMacHeaderLen = ETH_HLEN;
1796
1797     /* Save the value of Header Length */
1798     GLUE_SET_PKT_HEADER_LEN(prPacket, ucMacHeaderLen);
1799
1800     /* Save the value of Frame Length */
1801     GLUE_SET_PKT_FRAME_LEN(prPacket, (UINT_16)u4PacketLen);
1802
1803     /* Save the value of Arrival Time*/
1804     u4SysTime = (OS_SYSTIME)kalGetTimeTick();
1805     GLUE_SET_PKT_ARRIVAL_TIME(prPacket, u4SysTime);
1806
1807     prMsduInfo->prPacket = prPacket;
1808     prMsduInfo->fgIs802_1x = fgIs1x;
1809     prMsduInfo->fgIs802_11 = FALSE;
1810     prMsduInfo->ucNetworkType = ucNetworkType;
1811     prMsduInfo->ucUserPriority = ucPriorityParam;
1812     prMsduInfo->ucMacHeaderLength = ucMacHeaderLen;
1813     prMsduInfo->u2FrameLength = (UINT_16)u4PacketLen;
1814     COPY_MAC_ADDR(prMsduInfo->aucEthDestAddr, aucEthDestAddr);
1815
1816     return TRUE;
1817 }
1818
1819
1820 /*----------------------------------------------------------------------------*/
1821 /*!
1822 * @brief this function update TCQ values by passing current status to txAdjustTcQuotas
1823 *
1824 * @param prAdapter              Pointer to the Adapter structure.
1825 *
1826 * @retval WLAN_STATUS_SUCCESS   Updated successfully
1827 */
1828 /*----------------------------------------------------------------------------*/
1829 WLAN_STATUS
1830 nicTxAdjustTcq (
1831     IN P_ADAPTER_T  prAdapter
1832     )
1833 {
1834     UINT_32 u4Num;
1835     TX_TCQ_ADJUST_T rTcqAdjust;
1836     P_TX_CTRL_T prTxCtrl;
1837     KAL_SPIN_LOCK_DECLARATION();
1838
1839     ASSERT(prAdapter);
1840
1841     prTxCtrl = &prAdapter->rTxCtrl;
1842     ASSERT(prTxCtrl);
1843
1844     qmAdjustTcQuotas(prAdapter, &rTcqAdjust, &prTxCtrl->rTc);
1845     KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_RESOURCE);
1846
1847     for (u4Num = 0 ; u4Num < TC_NUM ; u4Num++) {
1848         prTxCtrl->rTc.aucFreeBufferCount[u4Num] += rTcqAdjust.acVariation[u4Num];
1849         prTxCtrl->rTc.aucMaxNumOfBuffer[u4Num] += rTcqAdjust.acVariation[u4Num];
1850
1851         ASSERT(prTxCtrl->rTc.aucFreeBufferCount[u4Num] >= 0);
1852         ASSERT(prTxCtrl->rTc.aucMaxNumOfBuffer[u4Num] >= 0);
1853     }
1854
1855     KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_RESOURCE);
1856
1857     return WLAN_STATUS_SUCCESS;
1858 }
1859
1860
1861 /*----------------------------------------------------------------------------*/
1862 /*!
1863 * @brief this function flushes all packets queued in STA/AC queue
1864 *
1865 * @param prAdapter              Pointer to the Adapter structure.
1866 *
1867 * @retval WLAN_STATUS_SUCCESS   Flushed successfully
1868 */
1869 /*----------------------------------------------------------------------------*/
1870
1871 WLAN_STATUS
1872 nicTxFlush (
1873     IN P_ADAPTER_T  prAdapter
1874     )
1875 {
1876     P_MSDU_INFO_T prMsduInfo;
1877     KAL_SPIN_LOCK_DECLARATION();
1878
1879     ASSERT(prAdapter);
1880
1881     // ask Per STA/AC queue to be fllushed and return all queued packets
1882     KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_QM_TX_QUEUE);
1883     prMsduInfo = qmFlushTxQueues(prAdapter);
1884     KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_QM_TX_QUEUE);
1885
1886     if(prMsduInfo != NULL) {
1887         nicTxFreeMsduInfoPacket(prAdapter, prMsduInfo);
1888         nicTxReturnMsduInfo(prAdapter, prMsduInfo);
1889     }
1890
1891     return WLAN_STATUS_SUCCESS;
1892 }
1893
1894
1895 #if CFG_ENABLE_FW_DOWNLOAD
1896 /*----------------------------------------------------------------------------*/
1897 /*!
1898 * \brief In this function, we'll write Command(CMD_INFO_T) into HIF.
1899 *        However this function is used for INIT_CMD.
1900 *
1901 *        In order to avoid further maintainance issues, these 2 functions are separated
1902 *
1903 * @param prAdapter      Pointer to the Adapter structure.
1904 * @param prPacketInfo   Pointer of CMD_INFO_T
1905 * @param ucTC           Specify the resource of TC
1906 *
1907 * @retval WLAN_STATUS_SUCCESS   Bus access ok.
1908 * @retval WLAN_STATUS_FAILURE   Bus access fail.
1909 */
1910 /*----------------------------------------------------------------------------*/
1911 WLAN_STATUS
1912 nicTxInitCmd (
1913     IN P_ADAPTER_T      prAdapter,
1914     IN P_CMD_INFO_T     prCmdInfo,
1915     IN UINT_8           ucTC
1916     )
1917 {
1918     P_INIT_HIF_TX_HEADER_T prInitTxHeader;
1919     UINT_16 u2OverallBufferLength;
1920     PUINT_8 pucOutputBuf = (PUINT_8)NULL; /* Pointer to Transmit Data Structure Frame */
1921     UINT_32 ucPortIdx;
1922     P_TX_CTRL_T prTxCtrl;
1923
1924     ASSERT(prAdapter);
1925     ASSERT(prCmdInfo);
1926     ASSERT(ucTC == TC0_INDEX);
1927
1928     prTxCtrl = &prAdapter->rTxCtrl;
1929     pucOutputBuf = prTxCtrl->pucTxCoalescingBufPtr;
1930     prInitTxHeader = (P_INIT_HIF_TX_HEADER_T)prCmdInfo->pucInfoBuffer;
1931
1932     // <1> Compose the Header of Transmit Data Structure for CMD Packet
1933     u2OverallBufferLength = TFCB_FRAME_PAD_TO_DW(
1934             (prCmdInfo->u2InfoBufLen) & (UINT_16)HIF_TX_HDR_TX_BYTE_COUNT_MASK);
1935
1936     prInitTxHeader->u2TxByteCount = u2OverallBufferLength;
1937     prInitTxHeader->ucEtherTypeOffset = 0;
1938     prInitTxHeader->ucCSflags = 0;
1939
1940     // <2> Assign Data Port
1941     if (ucTC != TC4_INDEX) {
1942         ucPortIdx = 0;
1943     }
1944     else { // Broadcast/multicast data packets
1945         ucPortIdx = 1;
1946     }
1947
1948     // <3> Copy CMD Header to command buffer (by using pucCoalescingBufCached)
1949     kalMemCopy((PVOID)&pucOutputBuf[0],
1950                (PVOID)prCmdInfo->pucInfoBuffer,
1951                prCmdInfo->u2InfoBufLen);
1952
1953     ASSERT(u2OverallBufferLength <= prAdapter->u4CoalescingBufCachedSize);
1954
1955     // <4> Write frame to data port
1956     HAL_WRITE_TX_PORT(prAdapter,
1957             ucPortIdx,
1958             (UINT_32)u2OverallBufferLength,
1959             (PUINT_8)pucOutputBuf,
1960             (UINT_32)prAdapter->u4CoalescingBufCachedSize);
1961
1962     return WLAN_STATUS_SUCCESS;
1963 }
1964
1965
1966 /*----------------------------------------------------------------------------*/
1967 /*!
1968 * \brief In this function, we'll reset TX resource counter to initial value used
1969 *        in F/W download state
1970 *
1971 * @param prAdapter      Pointer to the Adapter structure.
1972 *
1973 * @retval WLAN_STATUS_SUCCESS   Reset is done successfully.
1974 */
1975 /*----------------------------------------------------------------------------*/
1976 WLAN_STATUS
1977 nicTxInitResetResource (
1978     IN P_ADAPTER_T  prAdapter
1979     )
1980 {
1981     P_TX_CTRL_T prTxCtrl;
1982
1983     DEBUGFUNC("nicTxInitResetResource");
1984
1985     ASSERT(prAdapter);
1986     prTxCtrl = &prAdapter->rTxCtrl;
1987
1988     prTxCtrl->rTc.aucMaxNumOfBuffer[TC0_INDEX] = NIC_TX_INIT_BUFF_COUNT_TC0;
1989     prTxCtrl->rTc.aucFreeBufferCount[TC0_INDEX] = NIC_TX_INIT_BUFF_COUNT_TC0;
1990
1991     prTxCtrl->rTc.aucMaxNumOfBuffer[TC1_INDEX] = NIC_TX_INIT_BUFF_COUNT_TC1;
1992     prTxCtrl->rTc.aucFreeBufferCount[TC1_INDEX] = NIC_TX_INIT_BUFF_COUNT_TC1;
1993
1994     prTxCtrl->rTc.aucMaxNumOfBuffer[TC2_INDEX] = NIC_TX_INIT_BUFF_COUNT_TC2;
1995     prTxCtrl->rTc.aucFreeBufferCount[TC2_INDEX] = NIC_TX_INIT_BUFF_COUNT_TC2;
1996
1997     prTxCtrl->rTc.aucMaxNumOfBuffer[TC3_INDEX] = NIC_TX_INIT_BUFF_COUNT_TC3;
1998     prTxCtrl->rTc.aucFreeBufferCount[TC3_INDEX] = NIC_TX_INIT_BUFF_COUNT_TC3;
1999
2000     prTxCtrl->rTc.aucMaxNumOfBuffer[TC4_INDEX] = NIC_TX_INIT_BUFF_COUNT_TC4;
2001     prTxCtrl->rTc.aucFreeBufferCount[TC4_INDEX] = NIC_TX_INIT_BUFF_COUNT_TC4;
2002
2003     prTxCtrl->rTc.aucMaxNumOfBuffer[TC5_INDEX] = NIC_TX_INIT_BUFF_COUNT_TC5;
2004     prTxCtrl->rTc.aucFreeBufferCount[TC5_INDEX] = NIC_TX_INIT_BUFF_COUNT_TC5;
2005
2006     return WLAN_STATUS_SUCCESS;
2007
2008 }
2009
2010 #endif
2011
2012
2013 /*----------------------------------------------------------------------------*/
2014 /*!
2015 * \brief this function enqueues MSDU_INFO_T into queue management,
2016 *        or command queue
2017 *
2018 * @param prAdapter      Pointer to the Adapter structure.
2019 *        prMsduInfo     Pointer to MSDU
2020 *
2021 * @retval WLAN_STATUS_SUCCESS   Reset is done successfully.
2022 */
2023 /*----------------------------------------------------------------------------*/
2024 WLAN_STATUS
2025 nicTxEnqueueMsdu (
2026     IN P_ADAPTER_T      prAdapter,
2027     IN P_MSDU_INFO_T    prMsduInfo
2028     )
2029 {
2030     P_TX_CTRL_T prTxCtrl;
2031     P_MSDU_INFO_T prNextMsduInfo, prRetMsduInfo, prMsduInfoHead;
2032     QUE_T qDataPort0, qDataPort1;
2033     P_CMD_INFO_T prCmdInfo;
2034     WLAN_STATUS u4Status = WLAN_STATUS_SUCCESS;
2035     KAL_SPIN_LOCK_DECLARATION();
2036
2037     ASSERT(prAdapter);
2038     ASSERT(prMsduInfo);
2039
2040     prTxCtrl = &prAdapter->rTxCtrl;
2041     ASSERT(prTxCtrl);
2042
2043     QUEUE_INITIALIZE(&qDataPort0);
2044     QUEUE_INITIALIZE(&qDataPort1);
2045
2046     /* check how many management frame are being queued */
2047     while(prMsduInfo) {
2048         prNextMsduInfo = (P_MSDU_INFO_T)QUEUE_GET_NEXT_ENTRY((P_QUE_ENTRY_T)prMsduInfo);
2049
2050         QUEUE_GET_NEXT_ENTRY((P_QUE_ENTRY_T)prMsduInfo) = NULL;
2051
2052         if(prMsduInfo->eSrc == TX_PACKET_MGMT) {
2053             // MMPDU: force stick to TC4
2054             prMsduInfo->ucTC = TC4_INDEX;
2055
2056             QUEUE_INSERT_TAIL(&qDataPort1, (P_QUE_ENTRY_T)prMsduInfo);
2057         }
2058         else {
2059             QUEUE_INSERT_TAIL(&qDataPort0, (P_QUE_ENTRY_T)prMsduInfo);
2060         }
2061
2062         prMsduInfo = prNextMsduInfo;
2063     }
2064
2065     if(qDataPort0.u4NumElem) {
2066         /* send to QM */
2067         KAL_SPIN_LOCK_DECLARATION();
2068         KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_QM_TX_QUEUE);
2069         prRetMsduInfo = qmEnqueueTxPackets(prAdapter, (P_MSDU_INFO_T)QUEUE_GET_HEAD(&qDataPort0));
2070         KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_QM_TX_QUEUE);
2071
2072         /* post-process for dropped packets */
2073         if(prRetMsduInfo != NULL) { // unable to enqueue
2074             nicTxFreeMsduInfoPacket(prAdapter, prRetMsduInfo);
2075             nicTxReturnMsduInfo(prAdapter, prRetMsduInfo);
2076         }
2077     }
2078
2079     if(qDataPort1.u4NumElem) {
2080         prMsduInfoHead = (P_MSDU_INFO_T)QUEUE_GET_HEAD(&qDataPort1);
2081
2082         if(qDataPort1.u4NumElem > nicTxGetFreeCmdCount(prAdapter)) {
2083             // not enough descriptors for sending
2084             u4Status = WLAN_STATUS_FAILURE;
2085
2086             // free all MSDUs
2087             while(prMsduInfoHead) {
2088                 prNextMsduInfo = (P_MSDU_INFO_T) QUEUE_GET_NEXT_ENTRY(&prMsduInfoHead->rQueEntry);
2089
2090                 if (prMsduInfoHead->pfTxDoneHandler != NULL) {
2091                     prMsduInfoHead->pfTxDoneHandler(prAdapter, prMsduInfoHead, TX_RESULT_DROPPED_IN_DRIVER);
2092                 }
2093
2094
2095                 cnmMgtPktFree(prAdapter, prMsduInfoHead);
2096
2097                 prMsduInfoHead = prNextMsduInfo;
2098             }
2099         }
2100         else {
2101             /* send to command queue */
2102             while(prMsduInfoHead) {
2103                 prNextMsduInfo = (P_MSDU_INFO_T) QUEUE_GET_NEXT_ENTRY(&prMsduInfoHead->rQueEntry);
2104
2105                 KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_CMD_RESOURCE);
2106                 QUEUE_REMOVE_HEAD(&prAdapter->rFreeCmdList, prCmdInfo, P_CMD_INFO_T);
2107                 KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_CMD_RESOURCE);
2108
2109                 if (prCmdInfo) {
2110                     GLUE_INC_REF_CNT(prTxCtrl->i4TxMgmtPendingNum);
2111
2112                     kalMemZero(prCmdInfo, sizeof(CMD_INFO_T));
2113
2114                     prCmdInfo->eCmdType             = COMMAND_TYPE_MANAGEMENT_FRAME;
2115                     prCmdInfo->u2InfoBufLen         = prMsduInfoHead->u2FrameLength;
2116                     prCmdInfo->pucInfoBuffer        = NULL;
2117                     prCmdInfo->prPacket             = (P_NATIVE_PACKET)prMsduInfoHead;
2118                     prCmdInfo->ucStaRecIndex        = prMsduInfoHead->ucStaRecIndex;
2119                     prCmdInfo->eNetworkType         = prMsduInfoHead->ucNetworkType;
2120                     prCmdInfo->pfCmdDoneHandler     = NULL;
2121                     prCmdInfo->pfCmdTimeoutHandler  = NULL;
2122                     prCmdInfo->fgIsOid              = FALSE;
2123                     prCmdInfo->fgSetQuery           = TRUE;
2124                     prCmdInfo->fgNeedResp           = FALSE;
2125
2126                     kalEnqueueCommand(prAdapter->prGlueInfo, (P_QUE_ENTRY_T)prCmdInfo);
2127                 }
2128                 else {
2129                     /* Cmd free count is larger than expected, but allocation fail. */
2130                     ASSERT(0);
2131
2132                     u4Status = WLAN_STATUS_FAILURE;
2133                     cnmMgtPktFree(prAdapter, prMsduInfoHead);
2134                 }
2135
2136                 prMsduInfoHead = prNextMsduInfo;
2137             }
2138         }
2139     }
2140
2141     /* indicate service thread for sending */
2142     if(prTxCtrl->i4TxMgmtPendingNum > 0
2143             || kalGetTxPendingFrameCount(prAdapter->prGlueInfo) > 0) {
2144         kalSetEvent(prAdapter->prGlueInfo);
2145     }
2146
2147     return u4Status;
2148 }
2149
2150
2151 /*----------------------------------------------------------------------------*/
2152 /*!
2153 * \brief this function returns available count in command queue
2154 *
2155 * @param prAdapter      Pointer to the Adapter structure.
2156 *
2157 * @retval
2158 */
2159 /*----------------------------------------------------------------------------*/
2160 UINT_32
2161 nicTxGetFreeCmdCount (
2162     IN P_ADAPTER_T  prAdapter
2163     )
2164 {
2165     ASSERT(prAdapter);
2166
2167     return prAdapter->rFreeCmdList.u4NumElem;
2168 }
2169