2 ** $Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_2/nic/nic_tx.c#1 $
6 \brief Functions that provide TX operation in NIC Layer.
8 This file provides TX functions which are responsible for both Hardware and
9 Software Resource Management and keep their Synchronization.
12 /*******************************************************************************
13 * Copyright (c) 2007 MediaTek Inc.
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
19 ********************************************************************************
22 /*******************************************************************************
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.
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.
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
51 ********************************************************************************
57 * 03 26 2012 yuche.tsai
58 * [ALPS00255551] [WiFi direct][Google Issue]GC can't send picture to GO sometimes,GO and GC can't ping each other
59 * Avoid ran out of driver resource when starting GO.
61 * 11 19 2011 eddie.chen
62 * [WCXRP00001096] [MT6620 Wi-Fi][Driver/FW] Enhance the log function (xlog)
65 * 11 09 2011 eddie.chen
66 * [WCXRP00001096] [MT6620 Wi-Fi][Driver/FW] Enhance the log function (xlog)
67 * Add xlog for beacon timeout and sta aging timeout.
69 * 11 08 2011 eddie.chen
70 * [WCXRP00001096] [MT6620 Wi-Fi][Driver/FW] Enhance the log function (xlog)
74 * [WCXRP00000732] [MT6620 Wi-Fi][AIS] No need to switch back to IDLE state when DEAUTH frame is dropped due to bss disconnection
75 * when TX DONE status is TX_RESULT_DROPPED_IN_DRIVER, no need to switch back to IDLE state.
77 * 04 12 2011 eddie.chen
78 * [WCXRP00000617] [MT6620 Wi-Fi][DRV/FW] Fix for sigma
79 * Fix the sta index in processing security frame
80 * Simple flow control for TC4 to avoid mgt frames for PS STA to occupy the TC4
84 * [WCXRP00000631] [MT6620 Wi-Fi][Driver] Add an API for QM to retrieve current TC counter value and processing frame dropping cases for TC4 path
85 * remove unused variables.
88 * [WCXRP00000631] [MT6620 Wi-Fi][Driver] Add an API for QM to retrieve current TC counter value and processing frame dropping cases for TC4 path
89 * 1. add nicTxGetResource() API for QM to make decisions.
90 * 2. if management frames is decided by QM for dropping, the call back is invoked to indicate such a case.
93 * [WCXRP00000577] [MT6620 Wi-Fi][Driver][FW] Create V2.0 branch for firmware and driver
94 * create V2.0 driver release based on label "MT6620_WIFI_DRIVER_V2_0_110318_1600" from main trunk
97 * [WCXRP00000562] [MT6620 Wi-Fi][Driver] I/O buffer pre-allocation to avoid physically continuous memory shortage after system running for a long period
98 * use pre-allocated buffer for storing enhanced interrupt response as well
101 * [WCXRP00000559] [MT6620 Wi-Fi][Driver] Combine TX/RX DMA buffers into a single one to reduce physically continuous memory consumption
102 * 1. deprecate CFG_HANDLE_IST_IN_SDIO_CALLBACK
103 * 2. Use common coalescing buffer for both TX/RX directions
107 * [WCXRP00000449] [MT6620 Wi-Fi][Driver] Refine CMD queue handling by adding an extra API for checking availble count and modify behavior
108 * 1. add new API: nicTxGetFreeCmdCount()
109 * 2. when there is insufficient command descriptor, nicTxEnqueueMsdu() will drop command packets directly
112 * [WCXRP00000382] [MT6620 Wi-Fi][Driver] Track forwarding packet number with notifying tx thread for serving
113 * 1. add an extra counter for tracking pending forward frames.
114 * 2. notify TX service thread as well when there is pending forward frame
115 * 3. correct build errors leaded by introduction of Wi-Fi direct separation module
118 * [WCXRP00000356] [MT6620 Wi-Fi][Driver] fill mac header length for security frames 'cause hardware header translation needs such information
119 * fill mac header length information for 802.1x frames.
122 * [WCXRP00000335] [MT6620 Wi-Fi][Driver] change to use milliseconds sleep instead of delay to avoid blocking to system scheduling
123 * change to use msleep() and shorten waiting interval to reduce blocking to other task while Wi-Fi driver is being loaded
125 * 11 01 2010 yarco.yang
126 * [WCXRP00000149] [MT6620 WI-Fi][Driver]Fine tune performance on MT6516 platform
127 * Add GPIO debug function
130 * [WCXRP00000117] [MT6620 Wi-Fi][Driver] Add logic for suspending driver when MT6620 is not responding anymore
131 * 1. when wlanAdapterStop() failed to send POWER CTRL command to firmware, do not poll for ready bit dis-assertion
132 * 2. shorten polling count for shorter response time
133 * 3. if bad I/O operation is detected during TX resource polling, then further operation is aborted as well
136 * [WCXRP00000052] [MT6620 Wi-Fi][Driver] Eliminate Linux Compile Warning
137 * code reorganization to improve isolation between GLUE and CORE layers.
140 * [WCXRP00000072] [MT6620 Wi-Fi][Driver] Fix TKIP Counter Measure EAPoL callback register issue
141 * [MT6620 Wi-Fi][Driver] Fix TKIP Counter Measure EAPoL callback register issue.
145 * since the u2TxByteCount_UserPriority will or another setting, keep the overall buffer for avoid error
149 * [WCXRP000000058][MT6620 Wi-Fi][Driver] Fail to handshake with WAPI AP due the 802.1x frame send to fw with extra bytes padding.
153 * HIFSYS Clock Source Workaround
157 * API added: nicTxPendingPackets(), for simplifying porting layer
161 * eliminate klockwork errors
165 * adding the eapol callback setting.
167 * 08 18 2010 yarco.yang
169 * 1. Fixed HW checksum offload function not work under Linux issue.
170 * 2. Add debug message.
172 * 08 05 2010 yuche.tsai
178 * surpress compilation warning.
180 * 08 02 2010 jeffrey.chang
182 * 1) modify tx service thread to avoid busy looping
183 * 2) add spin lock declartion for linux build
187 * simplify post-handling after TX_DONE interrupt is handled.
189 * 07 19 2010 jeffrey.chang
191 * Linux port modification
195 * 1) MMPDUs are now sent to MT6620 by CMD queue for keeping strict order of 1X/MMPDU/CMD packets
196 * 2) integrate with qmGetFrameAction() for deciding which MMPDU/1X could pass checking for sending
197 * 2) enhance CMD_INFO_T descriptor number from 10 to 32 to avoid descriptor underflow under concurrent network operation
201 * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository.
203 * 06 29 2010 yarco.yang
204 * [WPD00003837][MT6620]Data Path Refine
205 * replace g_rQM with Adpater->rQM
208 * [WPD00003833][MT6620 and MT5931] Driver migration
209 * add API in que_mgt to retrieve sta-rec index for security frames.
212 * [WPD00003833][MT6620 and MT5931] Driver migration
213 * 802.1x and bluetooth-over-Wi-Fi security frames are now delievered to firmware via command path instead of data path.
215 * 06 23 2010 yarco.yang
216 * [WPD00003837][MT6620]Data Path Refine
217 * Merge g_arStaRec[] into adapter->arStaRec[]
220 * [WPD00003833][MT6620 and MT5931] Driver migration
221 * 1) add command warpper for STA-REC/BSS-INFO sync.
222 * 2) enhance command packet sending procedure for non-oid part
223 * 3) add command packet definitions for STA-REC/BSS-INFO sync.
226 * [WPD00003833][MT6620 and MT5931] Driver migration
227 * add checking for TX descriptor poll.
230 * [WPD00003833][MT6620 and MT5931] Driver migration
231 * TX descriptors are now allocated once for reducing allocation overhead
233 * 06 18 2010 cm.chang
234 * [WPD00003841][LITE Driver] Migrate RLM/CNM to host driver
235 * Provide cnmMgtPktAlloc() and alloc/free function of msg/buf
238 * [WPD00003833][MT6620 and MT5931] Driver migration
239 * change zero-padding for TX port access to HAL.
242 * [WPD00003833][MT6620 and MT5931] Driver migration
246 * [WPD00003833][MT6620 and MT5931] Driver migration
250 * [WPD00003833][MT6620 and MT5931] Driver migration
251 * fill extra information for revised HIF_TX_HEADER.
254 * [WPD00003833][MT6620 and MT5931] Driver migration
255 * 1) migrate assoc.c.
256 * 2) add ucTxSeqNum for tracking frames which needs TX-DONE awareness
257 * 3) add configuration options for CNM_MEM and RSN modules
258 * 4) add data path for management frames
259 * 5) eliminate rPacketInfo of MSDU_INFO_T
262 * [WPD00003833][MT6620 and MT5931] Driver migration
263 * change to enqueue TX frame infinitely.
266 * [WPD00003833][MT6620 and MT5931] Driver migration
267 * add TX_PACKET_MGMT to indicate the frame is coming from management modules
269 * 06 06 2010 kevin.huang
270 * [WPD00003832][MT6620 5931] Create driver base
271 * [MT6620 5931] Create driver base
274 * [WPD00003831][MT6620 Wi-Fi] Add framework for Wi-Fi Direct support
275 * fill network type field while doing frame identification.
278 * [WPD00001943]Create WiFi test driver framework on WinXP
279 * surpress compiler warning
281 * 04 06 2010 jeffrey.chang
282 * [WPD00003826]Initial import for Linux port
283 * Tag the packet for QoS on Tx path
286 * [WPD00001943]Create WiFi test driver framework on WinXP
287 * remove driver-land statistics.
289 * 03 29 2010 jeffrey.chang
290 * [WPD00003826]Initial import for Linux port
291 * improve none-glue code portability
293 * 03 24 2010 jeffrey.chang
294 * [WPD00003826]Initial import for Linux port
295 * initial import for Linux port
298 * [WPD00001943]Create WiFi test driver framework on WinXP
299 * generate information for OID_GEN_RCV_OK & OID_GEN_XMIT_OK
303 * [WPD00001943]Create WiFi test driver framework on WinXP
304 * code clean: removing unused variables and structure definitions
307 * [WPD00001943]Create WiFi test driver framework on WinXP
308 * 1) add another spin-lock to protect MsduInfoList due to it might be accessed by different thread.
309 * * * * 2) change own-back acquiring procedure to wait for up to 16.67 seconds
312 * [WPD00001943]Create WiFi test driver framework on WinXP
313 * add mutex to avoid multiple access to qmTxQueue simultaneously.
316 * [WPD00001943]Create WiFi test driver framework on WinXP
317 * avoid refering to NDIS-specific data structure directly from non-glue layer.
320 * [WPD00001943]Create WiFi test driver framework on WinXP
321 * add Ethernet destination address information in packet info for TX
324 * [WPD00001943]Create WiFi test driver framework on WinXP
325 * 1) remove unused function in nic_rx.c [which has been handled in que_mgt.c]
326 * * * * * * 2) firmware image length is now retrieved via NdisFileOpen
327 * * * * * * 3) firmware image is not structured by (P_IMG_SEC_HDR_T) anymore
328 * * * * * * 4) nicRxWaitResponse() revised
329 * * * * * * 5) another set of TQ counter default value is added for fw-download state
330 * * * * * * 6) Wi-Fi load address is now retrieved from registry too
333 * [WPD00001943]Create WiFi test driver framework on WinXP
334 * 1. Permanent and current MAC address are now retrieved by CMD/EVENT packets instead of hard-coded address
335 * * * * * * * * * 2. follow MSDN defined behavior when associates to another AP
336 * * * * * * * * * 3. for firmware download, packet size could be up to 2048 bytes
339 * [WPD00001943]Create WiFi test driver framework on WinXP
340 * prepare for implementing fw download logic
343 * [WPD00001943]Create WiFi test driver framework on WinXP
344 * 1. eliminate improper variable in rHifInfo
345 * * * * * * * * * 2. block TX/ordinary OID when RF test mode is engaged
346 * * * * * * * * * 3. wait until firmware finish operation when entering into and leaving from RF test mode
347 * * * * * * * * * 4. correct some HAL implementation
349 * 01 13 2010 tehuang.liu
350 * [WPD00001943]Create WiFi test driver framework on WinXP
351 * Enabled the Burst_End Indication mechanism
354 * [WPD00001943]Create WiFi test driver framework on WinXP
355 * TX: fill ucWlanHeaderLength/ucPktFormtId_Flags according to info provided by prMsduInfo
358 * [WPD00001943]Create WiFi test driver framework on WinXP
359 * 1) According to CMD/EVENT documentation v0.8,
360 * * * * * * * * * * OID_CUSTOM_TEST_RX_STATUS & OID_CUSTOM_TEST_TX_STATUS is no longer used,
361 * * * * * * * * * * and result is retrieved by get ATInfo instead
362 * * * * * * * * * * 2) add 4 counter for recording aggregation statistics
363 ** \main\maintrunk.MT6620WiFiDriver_Prj\44 2009-12-10 16:52:15 GMT mtk02752
365 ** \main\maintrunk.MT6620WiFiDriver_Prj\43 2009-12-07 22:44:24 GMT mtk02752
366 ** correct assertion criterion
367 ** \main\maintrunk.MT6620WiFiDriver_Prj\42 2009-12-07 21:15:52 GMT mtk02752
368 ** correct trivial mistake
369 ** \main\maintrunk.MT6620WiFiDriver_Prj\41 2009-12-04 15:47:21 GMT mtk02752
370 ** + always append a dword of zero on TX path to avoid TX aggregation to triggered on uninitialized data
371 ** + add more assertion for packet size check
372 ** \main\maintrunk.MT6620WiFiDriver_Prj\40 2009-12-04 14:51:55 GMT mtk02752
373 ** nicTxMsduInfo(): save ptr for next entry before attaching to qDataPort
374 ** \main\maintrunk.MT6620WiFiDriver_Prj\39 2009-12-04 11:54:54 GMT mtk02752
375 ** add 2 assertion for size check
376 ** \main\maintrunk.MT6620WiFiDriver_Prj\38 2009-12-03 16:20:35 GMT mtk01461
378 ** \main\maintrunk.MT6620WiFiDriver_Prj\37 2009-11-30 10:57:10 GMT mtk02752
379 ** 1st DW of WIFI_CMD_T is shared with HIF_TX_HEADER_T
380 ** \main\maintrunk.MT6620WiFiDriver_Prj\36 2009-11-30 09:20:43 GMT mtk02752
381 ** use TC4 instead of TC5 for command packet
382 ** \main\maintrunk.MT6620WiFiDriver_Prj\35 2009-11-27 11:08:11 GMT mtk02752
383 ** add flush for reset
384 ** \main\maintrunk.MT6620WiFiDriver_Prj\34 2009-11-26 20:31:22 GMT mtk02752
385 ** fill prMsduInfo->ucUserPriority
386 ** \main\maintrunk.MT6620WiFiDriver_Prj\33 2009-11-25 21:04:33 GMT mtk02752
388 ** \main\maintrunk.MT6620WiFiDriver_Prj\32 2009-11-24 20:52:12 GMT mtk02752
389 ** integration with SD1's data path API
390 ** \main\maintrunk.MT6620WiFiDriver_Prj\31 2009-11-24 19:54:25 GMT mtk02752
391 ** nicTxRetransmitOfOsSendQue & nicTxData but changed to use nicTxMsduInfoList
392 ** \main\maintrunk.MT6620WiFiDriver_Prj\30 2009-11-23 17:53:18 GMT mtk02752
393 ** add nicTxCmd() for SD1_SD3_DATAPATH_INTEGRATION, which will append only HIF_TX_HEADER. seqNum, WIFI_CMD_T will be created inside oid handler
394 ** \main\maintrunk.MT6620WiFiDriver_Prj\29 2009-11-20 15:10:24 GMT mtk02752
395 ** use TxAccquireResource instead of accessing TCQ directly.
396 ** \main\maintrunk.MT6620WiFiDriver_Prj\28 2009-11-17 22:40:57 GMT mtk01084
397 ** \main\maintrunk.MT6620WiFiDriver_Prj\27 2009-11-17 17:35:40 GMT mtk02752
398 ** add nicTxMsduInfoList () implementation
399 ** \main\maintrunk.MT6620WiFiDriver_Prj\26 2009-11-17 11:07:10 GMT mtk02752
400 ** add nicTxAdjustTcq() implementation
401 ** \main\maintrunk.MT6620WiFiDriver_Prj\25 2009-11-16 22:28:38 GMT mtk02752
402 ** move aucFreeBufferCount/aucMaxNumOfBuffer into another structure
403 ** \main\maintrunk.MT6620WiFiDriver_Prj\24 2009-11-16 21:45:32 GMT mtk02752
404 ** add SD1_SD3_DATAPATH_INTEGRATION data path handling
405 ** \main\maintrunk.MT6620WiFiDriver_Prj\23 2009-11-13 13:29:56 GMT mtk01084
406 ** modify TX hdr format, fix tx retransmission issue
407 ** \main\maintrunk.MT6620WiFiDriver_Prj\22 2009-11-11 10:36:21 GMT mtk01084
408 ** \main\maintrunk.MT6620WiFiDriver_Prj\21 2009-11-04 14:11:11 GMT mtk01084
409 ** modify TX SW data structure
410 ** \main\maintrunk.MT6620WiFiDriver_Prj\20 2009-10-29 19:56:17 GMT mtk01084
412 ** \main\maintrunk.MT6620WiFiDriver_Prj\19 2009-10-13 21:59:23 GMT mtk01084
413 ** update for new HW design
414 ** \main\maintrunk.MT6620WiFiDriver_Prj\18 2009-10-02 14:00:18 GMT mtk01725
415 ** \main\maintrunk.MT6620WiFiDriver_Prj\17 2009-05-20 12:26:06 GMT mtk01461
416 ** Assign SeqNum to CMD Packet
417 ** \main\maintrunk.MT6620WiFiDriver_Prj\16 2009-05-19 10:54:04 GMT mtk01461
419 ** \main\maintrunk.MT6620WiFiDriver_Prj\15 2009-05-12 09:41:55 GMT mtk01461
420 ** Fix Query Command need resp issue
421 ** \main\maintrunk.MT6620WiFiDriver_Prj\14 2009-04-29 15:44:38 GMT mtk01461
422 ** Move OS dependent code to kalQueryTxOOBData()
423 ** \main\maintrunk.MT6620WiFiDriver_Prj\13 2009-04-28 10:40:03 GMT mtk01461
424 ** Add nicTxReleaseResource() for SDIO_STATUS_ENHANCE, and also fix the TX aggregation issue for 1x packet to TX1 port
425 ** \main\maintrunk.MT6620WiFiDriver_Prj\12 2009-04-21 09:50:47 GMT mtk01461
426 ** Update nicTxCmd() for moving wait RESP function call to wlanSendCommand()
427 ** \main\maintrunk.MT6620WiFiDriver_Prj\11 2009-04-17 19:56:32 GMT mtk01461
428 ** Move the CMD_INFO_T related function to cmd_buf.c
429 ** \main\maintrunk.MT6620WiFiDriver_Prj\10 2009-04-17 18:14:40 GMT mtk01426
430 ** Update OOB query for TX packet
431 ** \main\maintrunk.MT6620WiFiDriver_Prj\9 2009-04-14 15:51:32 GMT mtk01426
433 ** \main\maintrunk.MT6620WiFiDriver_Prj\8 2009-04-02 17:26:40 GMT mtk01461
434 ** Add virtual OOB for HIF LOOPBACK SW PRETEST
435 ** \main\maintrunk.MT6620WiFiDriver_Prj\7 2009-04-01 10:54:43 GMT mtk01461
436 ** Add function for SDIO_TX_ENHANCE
437 ** \main\maintrunk.MT6620WiFiDriver_Prj\6 2009-03-23 21:53:47 GMT mtk01461
438 ** Add code for retransmit of rOsSendQueue, mpSendPacket(), and add code for TX Checksum offload, Loopback Test.
439 ** \main\maintrunk.MT6620WiFiDriver_Prj\5 2009-03-23 00:33:51 GMT mtk01461
440 ** Add code for TX Data & Cmd Packet
441 ** \main\maintrunk.MT6620WiFiDriver_Prj\4 2009-03-18 20:25:40 GMT mtk01461
443 ** \main\maintrunk.MT6620WiFiDriver_Prj\3 2009-03-16 09:10:30 GMT mtk01461
444 ** Update TX PATH API
445 ** \main\maintrunk.MT6620WiFiDriver_Prj\2 2009-03-10 20:26:04 GMT mtk01426
450 /*******************************************************************************
451 * C O M P I L E R F L A G S
452 ********************************************************************************
455 /*******************************************************************************
456 * E X T E R N A L R E F E R E N C E S
457 ********************************************************************************
461 /*******************************************************************************
463 ********************************************************************************
466 /*******************************************************************************
468 ********************************************************************************
471 /*******************************************************************************
472 * P U B L I C D A T A
473 ********************************************************************************
476 /*******************************************************************************
477 * P R I V A T E D A T A
478 ********************************************************************************
481 /*******************************************************************************
483 ********************************************************************************
486 /*******************************************************************************
487 * F U N C T I O N D E C L A R A T I O N S
488 ********************************************************************************
491 /*******************************************************************************
493 ********************************************************************************
495 /*----------------------------------------------------------------------------*/
497 * @brief This function will initial all variables in regard to SW TX Queues and
498 * all free lists of MSDU_INFO_T and SW_TFCB_T.
500 * @param prAdapter Pointer to the Adapter structure.
504 /*----------------------------------------------------------------------------*/
507 IN P_ADAPTER_T prAdapter
510 P_TX_CTRL_T prTxCtrl;
511 PUINT_8 pucMemHandle;
512 P_MSDU_INFO_T prMsduInfo;
514 KAL_SPIN_LOCK_DECLARATION();
516 DEBUGFUNC("nicTxInitialize");
519 prTxCtrl = &prAdapter->rTxCtrl;
521 //4 <1> Initialization of Traffic Class Queue Parameters
522 nicTxResetResource(prAdapter);
525 prTxCtrl->pucTxCoalescingBufPtr = prAdapter->pucCoalescingBufCached;
526 #endif /* CFG_SDIO_TX_AGG */
528 // allocate MSDU_INFO_T and link it into rFreeMsduInfoList
529 QUEUE_INITIALIZE(&prTxCtrl->rFreeMsduInfoList);
531 pucMemHandle = prTxCtrl->pucTxCached;
532 for (i = 0 ; i < CFG_TX_MAX_PKT_NUM ; i++) {
533 prMsduInfo = (P_MSDU_INFO_T)pucMemHandle;
534 kalMemZero(prMsduInfo, sizeof(MSDU_INFO_T));
536 KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_MSDU_INFO_LIST);
537 QUEUE_INSERT_TAIL(&prTxCtrl->rFreeMsduInfoList, (P_QUE_ENTRY_T)prMsduInfo);
538 KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_MSDU_INFO_LIST);
540 pucMemHandle += ALIGN_4(sizeof(MSDU_INFO_T));
543 ASSERT(prTxCtrl->rFreeMsduInfoList.u4NumElem == CFG_TX_MAX_PKT_NUM);
544 /* Check if the memory allocation consist with this initialization function */
545 ASSERT((UINT_32)(pucMemHandle - prTxCtrl->pucTxCached) == prTxCtrl->u4TxCachedSize);
547 QUEUE_INITIALIZE(&prTxCtrl->rTxMgmtTxingQueue);
548 prTxCtrl->i4TxMgmtPendingNum = 0;
550 #if CFG_HIF_STATISTICS
551 prTxCtrl->u4TotalTxAccessNum = 0;
552 prTxCtrl->u4TotalTxPacketNum = 0;
555 prTxCtrl->i4PendingFwdFrameCount = 0;
559 TX_RESET_ALL_CNTS(prTxCtrl);
562 } /* end of nicTxInitialize() */
565 /*----------------------------------------------------------------------------*/
567 * \brief Driver maintain a variable that is synchronous with the usage of individual
568 * TC Buffer Count. This function will check if has enough TC Buffer for incoming
569 * packet and then update the value after promise to provide the resources.
571 * \param[in] prAdapter Pointer to the Adapter structure.
572 * \param[in] ucTC Specify the resource of TC
574 * \retval WLAN_STATUS_SUCCESS Resource is available and been assigned.
575 * \retval WLAN_STATUS_RESOURCES Resource is not available.
577 /*----------------------------------------------------------------------------*/
579 nicTxAcquireResource (
580 IN P_ADAPTER_T prAdapter,
584 P_TX_CTRL_T prTxCtrl;
585 WLAN_STATUS u4Status = WLAN_STATUS_RESOURCES;
586 KAL_SPIN_LOCK_DECLARATION();
589 prTxCtrl = &prAdapter->rTxCtrl;
592 KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_RESOURCE);
594 // DbgPrint("nicTxAcquireResource prTxCtrl->rTc.aucFreeBufferCount[%d]=%d\n", ucTC, prTxCtrl->rTc.aucFreeBufferCount[ucTC]);
596 if (prTxCtrl->rTc.aucFreeBufferCount[ucTC]) {
598 prTxCtrl->rTc.aucFreeBufferCount[ucTC]--;
600 DBGLOG(TX, EVENT, ("Acquire: TC = %d aucFreeBufferCount = %d\n",
601 ucTC, prTxCtrl->rTc.aucFreeBufferCount[ucTC]));
603 u4Status = WLAN_STATUS_SUCCESS;
605 KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_RESOURCE);
609 }/* end of nicTxAcquireResourceAndTFCBs() */
612 /*----------------------------------------------------------------------------*/
614 * @brief Driver maintain a variable that is synchronous with the usage of individual
615 * TC Buffer Count. This function will do polling if FW has return the resource.
616 * Used when driver start up before enable interrupt.
618 * @param prAdapter Pointer to the Adapter structure.
619 * @param ucTC Specify the resource of TC
621 * @retval WLAN_STATUS_SUCCESS Resource is available.
622 * @retval WLAN_STATUS_FAILURE Resource is not available.
624 /*----------------------------------------------------------------------------*/
626 nicTxPollingResource (
627 IN P_ADAPTER_T prAdapter,
631 P_TX_CTRL_T prTxCtrl;
632 WLAN_STATUS u4Status = WLAN_STATUS_FAILURE;
633 INT_32 i = NIC_TX_RESOURCE_POLLING_TIMEOUT;
637 prTxCtrl = &prAdapter->rTxCtrl;
639 if (ucTC >= TC_NUM) {
640 return WLAN_STATUS_FAILURE;
643 if (prTxCtrl->rTc.aucFreeBufferCount[ucTC] > 0) {
644 return WLAN_STATUS_SUCCESS;
648 HAL_READ_TX_RELEASED_COUNT(prAdapter, au4WTSR);
650 if(kalIsCardRemoved(prAdapter->prGlueInfo) == TRUE
651 || fgIsBusAccessFailed == TRUE) {
652 u4Status = WLAN_STATUS_FAILURE;
655 else if (nicTxReleaseResource(prAdapter, (PUINT_8)au4WTSR)) {
656 if (prTxCtrl->rTc.aucFreeBufferCount[ucTC] > 0) {
657 u4Status = WLAN_STATUS_SUCCESS;
661 kalMsleep(NIC_TX_RESOURCE_POLLING_DELAY_MSEC);
665 kalMsleep(NIC_TX_RESOURCE_POLLING_DELAY_MSEC);
671 INT_32 i4Times = NIC_TX_RESOURCE_POLLING_TIMEOUT - (i+1);
674 DBGLOG(TX, TRACE, ("Polling MCR_WTSR delay %d times, %d msec\n",
675 i4Times, (i4Times * NIC_TX_RESOURCE_POLLING_DELAY_MSEC)));
682 } /* end of nicTxPollingResource() */
685 /*----------------------------------------------------------------------------*/
687 * \brief Driver maintain a variable that is synchronous with the usage of individual
688 * TC Buffer Count. This function will release TC Buffer count according to
689 * the given TX_STATUS COUNTER after TX Done.
691 * \param[in] prAdapter Pointer to the Adapter structure.
692 * \param[in] u4TxStatusCnt Value of TX STATUS
696 /*----------------------------------------------------------------------------*/
698 nicTxReleaseResource (
699 IN P_ADAPTER_T prAdapter,
700 IN UINT_8* aucTxRlsCnt
703 PUINT_32 pu4Tmp = (PUINT_32)aucTxRlsCnt;
704 P_TX_CTRL_T prTxCtrl;
705 BOOLEAN bStatus = FALSE;
708 KAL_SPIN_LOCK_DECLARATION();
712 prTxCtrl = &prAdapter->rTxCtrl;
714 if (pu4Tmp[0] | pu4Tmp[1]) {
716 KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_RESOURCE);
717 for (i = 0; i < TC_NUM; i++) {
718 prTxCtrl->rTc.aucFreeBufferCount[i] += aucTxRlsCnt[i];
720 if ((i==1) || (i==5)){
721 DBGLOG(TX, EVENT, ("Release: i = %d aucFreeBufferCount = %d\n",
722 i, prTxCtrl->rTc.aucFreeBufferCount[i]));
725 KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_RESOURCE);
727 for (i = 0; i < TC_NUM; i++) {
728 DBGLOG(INIT, TRACE, ("aucFreeBufferCount[%d]: %d, aucMaxNumOfBuffer[%d]: %d\n",
729 i, prTxCtrl->rTc.aucFreeBufferCount[i], i, prTxCtrl->rTc.aucMaxNumOfBuffer[i]));
731 DbgPrint("prTxCtrl->rTc.aucFreeBufferCount[0]=%d\n", prTxCtrl->rTc.aucFreeBufferCount[0]);
732 DbgPrint("prTxCtrl->rTc.aucFreeBufferCount[1]=%d\n", prTxCtrl->rTc.aucFreeBufferCount[1]);
733 DbgPrint("prTxCtrl->rTc.aucFreeBufferCount[2]=%d\n", prTxCtrl->rTc.aucFreeBufferCount[2]);
734 DbgPrint("prTxCtrl->rTc.aucFreeBufferCount[3]=%d\n", prTxCtrl->rTc.aucFreeBufferCount[3]);
735 DbgPrint("prTxCtrl->rTc.aucFreeBufferCount[4]=%d\n", prTxCtrl->rTc.aucFreeBufferCount[4]);
736 DbgPrint("prTxCtrl->rTc.aucFreeBufferCount[5]=%d\n", prTxCtrl->rTc.aucFreeBufferCount[5]);
738 ASSERT(prTxCtrl->rTc.aucFreeBufferCount[TC0_INDEX] <= prTxCtrl->rTc.aucMaxNumOfBuffer[TC0_INDEX]);
739 ASSERT(prTxCtrl->rTc.aucFreeBufferCount[TC1_INDEX] <= prTxCtrl->rTc.aucMaxNumOfBuffer[TC1_INDEX]);
740 ASSERT(prTxCtrl->rTc.aucFreeBufferCount[TC2_INDEX] <= prTxCtrl->rTc.aucMaxNumOfBuffer[TC2_INDEX]);
741 ASSERT(prTxCtrl->rTc.aucFreeBufferCount[TC3_INDEX] <= prTxCtrl->rTc.aucMaxNumOfBuffer[TC3_INDEX]);
742 ASSERT(prTxCtrl->rTc.aucFreeBufferCount[TC4_INDEX] <= prTxCtrl->rTc.aucMaxNumOfBuffer[TC4_INDEX]);
743 ASSERT(prTxCtrl->rTc.aucFreeBufferCount[TC5_INDEX] <= prTxCtrl->rTc.aucMaxNumOfBuffer[TC5_INDEX]);
748 } /* end of nicTxReleaseResource() */
751 /*----------------------------------------------------------------------------*/
753 * \brief Reset TC Buffer Count to initialized value
755 * \param[in] prAdapter Pointer to the Adapter structure.
757 * @return WLAN_STATUS_SUCCESS
759 /*----------------------------------------------------------------------------*/
762 IN P_ADAPTER_T prAdapter
765 P_TX_CTRL_T prTxCtrl;
767 KAL_SPIN_LOCK_DECLARATION();
769 DEBUGFUNC("nicTxResetResource");
772 prTxCtrl = &prAdapter->rTxCtrl;
774 KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_RESOURCE);
776 prTxCtrl->rTc.aucMaxNumOfBuffer[TC0_INDEX] = NIC_TX_BUFF_COUNT_TC0;
777 prTxCtrl->rTc.aucFreeBufferCount[TC0_INDEX] = NIC_TX_BUFF_COUNT_TC0;
779 prTxCtrl->rTc.aucMaxNumOfBuffer[TC1_INDEX] = NIC_TX_BUFF_COUNT_TC1;
780 prTxCtrl->rTc.aucFreeBufferCount[TC1_INDEX] = NIC_TX_BUFF_COUNT_TC1;
782 prTxCtrl->rTc.aucMaxNumOfBuffer[TC2_INDEX] = NIC_TX_BUFF_COUNT_TC2;
783 prTxCtrl->rTc.aucFreeBufferCount[TC2_INDEX] = NIC_TX_BUFF_COUNT_TC2;
785 prTxCtrl->rTc.aucMaxNumOfBuffer[TC3_INDEX] = NIC_TX_BUFF_COUNT_TC3;
786 prTxCtrl->rTc.aucFreeBufferCount[TC3_INDEX] = NIC_TX_BUFF_COUNT_TC3;
788 prTxCtrl->rTc.aucMaxNumOfBuffer[TC4_INDEX] = NIC_TX_BUFF_COUNT_TC4;
789 prTxCtrl->rTc.aucFreeBufferCount[TC4_INDEX] = NIC_TX_BUFF_COUNT_TC4;
791 prTxCtrl->rTc.aucMaxNumOfBuffer[TC5_INDEX] = NIC_TX_BUFF_COUNT_TC5;
792 prTxCtrl->rTc.aucFreeBufferCount[TC5_INDEX] = NIC_TX_BUFF_COUNT_TC5;
794 KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_RESOURCE);
796 return WLAN_STATUS_SUCCESS;
800 /*----------------------------------------------------------------------------*/
802 * @brief Driver maintain a variable that is synchronous with the usage of individual
803 * TC Buffer Count. This function will return the value for other component
804 * which needs this information for making decisions
806 * @param prAdapter Pointer to the Adapter structure.
807 * @param ucTC Specify the resource of TC
809 * @retval UINT_8 The number of corresponding TC number
811 /*----------------------------------------------------------------------------*/
814 IN P_ADAPTER_T prAdapter,
818 P_TX_CTRL_T prTxCtrl;
821 prTxCtrl = &prAdapter->rTxCtrl;
825 if (ucTC >= TC_NUM) {
829 return prTxCtrl->rTc.aucFreeBufferCount[ucTC];
834 /*----------------------------------------------------------------------------*/
836 * @brief In this function, we'll aggregate frame(PACKET_INFO_T)
837 * corresponding to HIF TX port
839 * @param prAdapter Pointer to the Adapter structure.
840 * @param prMsduInfoListHead a link list of P_MSDU_INFO_T
842 * @retval WLAN_STATUS_SUCCESS Bus access ok.
843 * @retval WLAN_STATUS_FAILURE Bus access fail.
845 /*----------------------------------------------------------------------------*/
848 IN P_ADAPTER_T prAdapter,
849 IN P_MSDU_INFO_T prMsduInfoListHead
852 P_MSDU_INFO_T prMsduInfo, prNextMsduInfo;
853 QUE_T qDataPort0, qDataPort1;
857 ASSERT(prMsduInfoListHead);
859 prMsduInfo = prMsduInfoListHead;
861 QUEUE_INITIALIZE(&qDataPort0);
862 QUEUE_INITIALIZE(&qDataPort1);
864 // Separate MSDU_INFO_T lists into 2 categories: for Port#0 & Port#1
866 prNextMsduInfo = (P_MSDU_INFO_T)QUEUE_GET_NEXT_ENTRY((P_QUE_ENTRY_T)prMsduInfo);
868 LOG_FUNC("nicTxMsduInfoList Acquire TC %d net %u mac len %u len %u Type %u 1x %u 11 %u\n",
870 prMsduInfo->ucNetworkType,
871 prMsduInfo->ucMacHeaderLength,
872 prMsduInfo->u2FrameLength,
873 prMsduInfo->ucPacketType,
874 prMsduInfo->fgIs802_1x,
875 prMsduInfo->fgIs802_11 );
877 LOG_FUNC("Dest Mac: " MACSTR "\n",
878 MAC2STR(prMsduInfo->aucEthDestAddr));
881 switch(prMsduInfo->ucTC) {
886 case TC5_INDEX: // Broadcast/multicast data packets
887 QUEUE_GET_NEXT_ENTRY((P_QUE_ENTRY_T)prMsduInfo) = NULL;
888 QUEUE_INSERT_TAIL(&qDataPort0, (P_QUE_ENTRY_T)prMsduInfo);
889 status = nicTxAcquireResource(prAdapter, prMsduInfo->ucTC);
890 ASSERT(status == WLAN_STATUS_SUCCESS)
894 case TC4_INDEX: // Command or 802.1x packets
895 QUEUE_GET_NEXT_ENTRY((P_QUE_ENTRY_T)prMsduInfo) = NULL;
896 QUEUE_INSERT_TAIL(&qDataPort1, (P_QUE_ENTRY_T)prMsduInfo);
898 status = nicTxAcquireResource(prAdapter, prMsduInfo->ucTC);
899 ASSERT(status == WLAN_STATUS_SUCCESS)
908 prMsduInfo = prNextMsduInfo;
911 if(qDataPort0.u4NumElem > 0) {
912 nicTxMsduQueue(prAdapter, 0, &qDataPort0);
915 if(qDataPort1.u4NumElem > 0) {
916 nicTxMsduQueue(prAdapter, 1, &qDataPort1);
919 return WLAN_STATUS_SUCCESS;
923 /*----------------------------------------------------------------------------*/
925 * @brief In this function, we'll write frame(PACKET_INFO_T) into HIF.
927 * @param prAdapter Pointer to the Adapter structure.
928 * @param ucPortIdx Port Number
929 * @param prQue a link list of P_MSDU_INFO_T
931 * @retval WLAN_STATUS_SUCCESS Bus access ok.
932 * @retval WLAN_STATUS_FAILURE Bus access fail.
934 /*----------------------------------------------------------------------------*/
937 IN P_ADAPTER_T prAdapter,
942 P_MSDU_INFO_T prMsduInfo, prNextMsduInfo;
943 HIF_TX_HEADER_T rHwTxHeader;
944 P_NATIVE_PACKET prNativePacket;
945 UINT_16 u2OverallBufferLength;
946 UINT_8 ucEtherTypeOffsetInWord;
947 PUINT_8 pucOutputBuf = (PUINT_8)NULL; /* Pointer to Transmit Data Structure Frame */
949 UINT_32 u4ValidBufSize;
950 UINT_32 u4TotalLength;
951 P_TX_CTRL_T prTxCtrl;
953 #if CFG_TCP_IP_CHKSUM_OFFLOAD
958 ASSERT(ucPortIdx < 2);
961 prTxCtrl = &prAdapter->rTxCtrl;
962 u4ValidBufSize = prAdapter->u4CoalescingBufCachedSize;
964 #if CFG_HIF_STATISTICS
965 prTxCtrl->u4TotalTxAccessNum++;
966 prTxCtrl->u4TotalTxPacketNum += prQue->u4NumElem;
969 QUEUE_INITIALIZE(&rFreeQueue);
971 if(prQue->u4NumElem > 0) {
972 prMsduInfo = (P_MSDU_INFO_T)QUEUE_GET_HEAD(prQue);
973 pucOutputBuf = prTxCtrl->pucTxCoalescingBufPtr;
978 kalMemZero(&rHwTxHeader, sizeof(rHwTxHeader));
980 prNativePacket = prMsduInfo->prPacket;
982 ASSERT(prNativePacket);
984 u4TxHdrSize = TX_HDR_SIZE;
986 u2OverallBufferLength = ((prMsduInfo->u2FrameLength + TX_HDR_SIZE) &
987 (UINT_16)HIF_TX_HDR_TX_BYTE_COUNT_MASK);
989 rHwTxHeader.u2TxByteCount_UserPriority = u2OverallBufferLength;
990 rHwTxHeader.u2TxByteCount_UserPriority |=
991 ((UINT_16)prMsduInfo->ucUserPriority << HIF_TX_HDR_USER_PRIORITY_OFFSET);
993 if (prMsduInfo->fgIs802_11) {
994 ucEtherTypeOffsetInWord =
995 (TX_HDR_SIZE + prMsduInfo->ucMacHeaderLength + prMsduInfo->ucLlcLength) >> 1;
998 ucEtherTypeOffsetInWord =
999 ((ETHER_HEADER_LEN - ETHER_TYPE_LEN) + TX_HDR_SIZE) >> 1;
1002 rHwTxHeader.ucEtherTypeOffset =
1003 ucEtherTypeOffsetInWord & HIF_TX_HDR_ETHER_TYPE_OFFSET_MASK;
1005 rHwTxHeader.ucResource_PktType_CSflags = (prMsduInfo->ucTC) << HIF_TX_HDR_RESOURCE_OFFSET;
1006 rHwTxHeader.ucResource_PktType_CSflags |=
1007 (UINT_8)(((prMsduInfo->ucPacketType) << HIF_TX_HDR_PACKET_TYPE_OFFSET) &
1008 (HIF_TX_HDR_PACKET_TYPE_MASK));
1010 #if CFG_TCP_IP_CHKSUM_OFFLOAD
1011 if (prMsduInfo->eSrc == TX_PACKET_OS
1012 || prMsduInfo->eSrc == TX_PACKET_FORWARDING) {
1013 if (prAdapter->u4CSUMFlags &
1014 (CSUM_OFFLOAD_EN_TX_TCP |
1015 CSUM_OFFLOAD_EN_TX_UDP |
1016 CSUM_OFFLOAD_EN_TX_IP)) {
1017 kalQueryTxChksumOffloadParam(prNativePacket, &ucChksumFlag);
1019 if (ucChksumFlag & TX_CS_IP_GEN) {
1020 rHwTxHeader.ucResource_PktType_CSflags |= (UINT_8)HIF_TX_HDR_IP_CSUM;
1023 if (ucChksumFlag & TX_CS_TCP_UDP_GEN) {
1024 rHwTxHeader.ucResource_PktType_CSflags |= (UINT_8)HIF_TX_HDR_TCP_CSUM;
1028 #endif /* CFG_TCP_IP_CHKSUM_OFFLOAD */
1030 rHwTxHeader.u2LLH = prMsduInfo->u2PalLLH;
1031 rHwTxHeader.ucStaRecIdx = prMsduInfo->ucStaRecIndex;
1032 rHwTxHeader.ucForwardingType_SessionID_Reserved =
1033 (prMsduInfo->ucPsForwardingType) | ((prMsduInfo->ucPsSessionID) << HIF_TX_HDR_PS_SESSION_ID_OFFSET)
1034 | ((prMsduInfo->fgIsBurstEnd)? HIF_TX_HDR_BURST_END_MASK : 0);
1036 rHwTxHeader.ucWlanHeaderLength = (prMsduInfo->ucMacHeaderLength & HIF_TX_HDR_WLAN_HEADER_LEN_MASK);
1037 rHwTxHeader.ucPktFormtId_Flags =
1038 (prMsduInfo->ucFormatID & HIF_TX_HDR_FORMAT_ID_MASK)
1039 | ((prMsduInfo->ucNetworkType << HIF_TX_HDR_NETWORK_TYPE_OFFSET) & HIF_TX_HDR_NETWORK_TYPE_MASK)
1040 | ((prMsduInfo->fgIs802_1x << HIF_TX_HDR_FLAG_1X_FRAME_OFFSET) & HIF_TX_HDR_FLAG_1X_FRAME_MASK)
1041 | ((prMsduInfo->fgIs802_11 << HIF_TX_HDR_FLAG_802_11_FORMAT_OFFSET) & HIF_TX_HDR_FLAG_802_11_FORMAT_MASK);
1043 rHwTxHeader.u2SeqNo = prMsduInfo->u2AclSN;
1045 if(prMsduInfo->pfTxDoneHandler) {
1046 rHwTxHeader.ucPacketSeqNo = prMsduInfo->ucTxSeqNum;
1047 rHwTxHeader.ucAck_BIP_BasicRate = HIF_TX_HDR_NEED_ACK;
1050 rHwTxHeader.ucPacketSeqNo = 0;
1051 rHwTxHeader.ucAck_BIP_BasicRate = 0;
1054 if(prMsduInfo->fgIsBIP) {
1055 rHwTxHeader.ucAck_BIP_BasicRate |= HIF_TX_HDR_BIP;
1058 if(prMsduInfo->fgIsBasicRate) {
1059 rHwTxHeader.ucAck_BIP_BasicRate |= HIF_TX_HDR_BASIC_RATE;
1063 // attach to coalescing buffer
1064 kalMemCopy(pucOutputBuf + u4TotalLength, &rHwTxHeader, u4TxHdrSize);
1065 u4TotalLength += u4TxHdrSize;
1067 if (prMsduInfo->eSrc == TX_PACKET_OS
1068 || prMsduInfo->eSrc == TX_PACKET_FORWARDING) {
1069 kalCopyFrame(prAdapter->prGlueInfo,
1071 pucOutputBuf + u4TotalLength);
1073 else if(prMsduInfo->eSrc == TX_PACKET_MGMT) {
1074 kalMemCopy(pucOutputBuf + u4TotalLength,
1076 prMsduInfo->u2FrameLength);
1082 u4TotalLength += ALIGN_4(prMsduInfo->u2FrameLength);
1085 kalMemCopy(pucOutputBuf, &rHwTxHeader, u4TxHdrSize);
1087 /* Copy Frame Body */
1088 if (prMsduInfo->eSrc == TX_PACKET_OS
1089 || prMsduInfo->eSrc == TX_PACKET_FORWARDING) {
1090 kalCopyFrame(prAdapter->prGlueInfo,
1092 pucOutputBuf + u4TxHdrSize);
1094 else if(prMsduInfo->eSrc == TX_PACKET_MGMT) {
1095 kalMemCopy(pucOutputBuf + u4TxHdrSize,
1097 prMsduInfo->u2FrameLength);
1103 ASSERT(u2OverallBufferLength <= u4ValidBufSize);
1105 HAL_WRITE_TX_PORT(prAdapter,
1107 (UINT_32)u2OverallBufferLength,
1108 (PUINT_8)pucOutputBuf,
1113 prNextMsduInfo = (P_MSDU_INFO_T)
1114 QUEUE_GET_NEXT_ENTRY(&prMsduInfo->rQueEntry);
1116 if (prMsduInfo->eSrc == TX_PACKET_MGMT) {
1117 GLUE_DEC_REF_CNT(prTxCtrl->i4TxMgmtPendingNum);
1119 if (prMsduInfo->pfTxDoneHandler == NULL) {
1120 cnmMgtPktFree(prAdapter, prMsduInfo);
1123 KAL_SPIN_LOCK_DECLARATION();
1124 DBGLOG(INIT, TRACE,("Wait TxSeqNum:%d\n", prMsduInfo->ucTxSeqNum));
1125 KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TXING_MGMT_LIST);
1126 QUEUE_INSERT_TAIL(&(prTxCtrl->rTxMgmtTxingQueue), (P_QUE_ENTRY_T)prMsduInfo);
1127 KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TXING_MGMT_LIST);
1131 /* only free MSDU when it is not a MGMT frame */
1132 QUEUE_INSERT_TAIL(&rFreeQueue, (P_QUE_ENTRY_T)prMsduInfo);
1134 if (prMsduInfo->eSrc == TX_PACKET_OS) {
1135 kalSendComplete(prAdapter->prGlueInfo,
1137 WLAN_STATUS_SUCCESS);
1139 else if(prMsduInfo->eSrc == TX_PACKET_FORWARDING) {
1140 GLUE_DEC_REF_CNT(prTxCtrl->i4PendingFwdFrameCount);
1144 prMsduInfo = prNextMsduInfo;
1148 ASSERT(u4TotalLength <= u4ValidBufSize);
1150 #if CFG_DBG_GPIO_PINS
1152 /* Start port write */
1153 mtk_wcn_stp_debug_gpio_assert(IDX_TX_PORT_WRITE, DBG_TIE_LOW);
1155 mtk_wcn_stp_debug_gpio_assert(IDX_TX_PORT_WRITE, DBG_TIE_HIGH);
1159 // send coalescing buffer
1160 HAL_WRITE_TX_PORT(prAdapter,
1163 (PUINT_8)pucOutputBuf,
1168 nicTxReturnMsduInfo(prAdapter, (P_MSDU_INFO_T)QUEUE_GET_HEAD(&rFreeQueue));
1171 return WLAN_STATUS_SUCCESS;
1175 /*----------------------------------------------------------------------------*/
1177 * \brief In this function, we'll write Command(CMD_INFO_T) into HIF.
1179 * @param prAdapter Pointer to the Adapter structure.
1180 * @param prPacketInfo Pointer of CMD_INFO_T
1181 * @param ucTC Specify the resource of TC
1183 * @retval WLAN_STATUS_SUCCESS Bus access ok.
1184 * @retval WLAN_STATUS_FAILURE Bus access fail.
1186 /*----------------------------------------------------------------------------*/
1189 IN P_ADAPTER_T prAdapter,
1190 IN P_CMD_INFO_T prCmdInfo,
1194 P_WIFI_CMD_T prWifiCmd;
1195 UINT_16 u2OverallBufferLength;
1196 PUINT_8 pucOutputBuf = (PUINT_8)NULL; /* Pointer to Transmit Data Structure Frame */
1198 HIF_TX_HEADER_T rHwTxHeader;
1199 P_NATIVE_PACKET prNativePacket;
1200 UINT_8 ucEtherTypeOffsetInWord;
1201 P_MSDU_INFO_T prMsduInfo;
1202 P_TX_CTRL_T prTxCtrl;
1204 KAL_SPIN_LOCK_DECLARATION();
1210 prTxCtrl = &prAdapter->rTxCtrl;
1211 pucOutputBuf = prTxCtrl->pucTxCoalescingBufPtr;
1213 // <1> Assign Data Port
1214 if (ucTC != TC4_INDEX) {
1218 // Broadcast/multicast data frames, 1x frames, command packets, MMPDU
1222 if(prCmdInfo->eCmdType == COMMAND_TYPE_SECURITY_FRAME) {
1223 // <2> Compose HIF_TX_HEADER
1224 kalMemZero(&rHwTxHeader, sizeof(rHwTxHeader));
1226 prNativePacket = prCmdInfo->prPacket;
1228 ASSERT(prNativePacket);
1230 u2OverallBufferLength = TFCB_FRAME_PAD_TO_DW((prCmdInfo->u2InfoBufLen + TX_HDR_SIZE)
1231 & (UINT_16)HIF_TX_HDR_TX_BYTE_COUNT_MASK);
1233 rHwTxHeader.u2TxByteCount_UserPriority = ((prCmdInfo->u2InfoBufLen + TX_HDR_SIZE)
1234 & (UINT_16)HIF_TX_HDR_TX_BYTE_COUNT_MASK);
1235 ucEtherTypeOffsetInWord = ((ETHER_HEADER_LEN - ETHER_TYPE_LEN) + TX_HDR_SIZE) >> 1;
1237 rHwTxHeader.ucEtherTypeOffset =
1238 ucEtherTypeOffsetInWord & HIF_TX_HDR_ETHER_TYPE_OFFSET_MASK;
1240 rHwTxHeader.ucResource_PktType_CSflags = (ucTC << HIF_TX_HDR_RESOURCE_OFFSET);
1242 rHwTxHeader.ucStaRecIdx = prCmdInfo->ucStaRecIndex;
1243 rHwTxHeader.ucForwardingType_SessionID_Reserved = HIF_TX_HDR_BURST_END_MASK;
1245 rHwTxHeader.ucWlanHeaderLength = (ETH_HLEN & HIF_TX_HDR_WLAN_HEADER_LEN_MASK);
1246 rHwTxHeader.ucPktFormtId_Flags =
1247 (((UINT_8)(prCmdInfo->eNetworkType) << HIF_TX_HDR_NETWORK_TYPE_OFFSET) & HIF_TX_HDR_NETWORK_TYPE_MASK)
1248 | ((1 << HIF_TX_HDR_FLAG_1X_FRAME_OFFSET) & HIF_TX_HDR_FLAG_1X_FRAME_MASK);
1250 rHwTxHeader.u2SeqNo = 0;
1251 rHwTxHeader.ucPacketSeqNo = 0;
1252 rHwTxHeader.ucAck_BIP_BasicRate = 0;
1254 // <2.3> Copy HIF TX HEADER
1255 kalMemCopy((PVOID)&pucOutputBuf[0], (PVOID)&rHwTxHeader, TX_HDR_SIZE);
1257 // <3> Copy Frame Body Copy
1258 kalCopyFrame(prAdapter->prGlueInfo,
1260 pucOutputBuf + TX_HDR_SIZE);
1262 else if(prCmdInfo->eCmdType == COMMAND_TYPE_MANAGEMENT_FRAME) {
1263 prMsduInfo = (P_MSDU_INFO_T)prCmdInfo->prPacket;
1265 ASSERT(prMsduInfo->fgIs802_11 == TRUE);
1266 ASSERT(prMsduInfo->eSrc == TX_PACKET_MGMT);
1268 // <2> Compose HIF_TX_HEADER
1269 kalMemZero(&rHwTxHeader, sizeof(rHwTxHeader));
1271 u2OverallBufferLength = ((prMsduInfo->u2FrameLength + TX_HDR_SIZE) &
1272 (UINT_16)HIF_TX_HDR_TX_BYTE_COUNT_MASK);
1274 rHwTxHeader.u2TxByteCount_UserPriority = u2OverallBufferLength;
1275 rHwTxHeader.u2TxByteCount_UserPriority |=
1276 ((UINT_16)prMsduInfo->ucUserPriority << HIF_TX_HDR_USER_PRIORITY_OFFSET);
1278 ucEtherTypeOffsetInWord =
1279 (TX_HDR_SIZE + prMsduInfo->ucMacHeaderLength + prMsduInfo->ucLlcLength) >> 1;
1281 rHwTxHeader.ucEtherTypeOffset =
1282 ucEtherTypeOffsetInWord & HIF_TX_HDR_ETHER_TYPE_OFFSET_MASK;
1284 rHwTxHeader.ucResource_PktType_CSflags = (prMsduInfo->ucTC) << HIF_TX_HDR_RESOURCE_OFFSET;
1285 rHwTxHeader.ucResource_PktType_CSflags |=
1286 (UINT_8)(((prMsduInfo->ucPacketType) << HIF_TX_HDR_PACKET_TYPE_OFFSET) &
1287 (HIF_TX_HDR_PACKET_TYPE_MASK));
1289 rHwTxHeader.u2LLH = prMsduInfo->u2PalLLH;
1290 rHwTxHeader.ucStaRecIdx = prMsduInfo->ucStaRecIndex;
1291 rHwTxHeader.ucForwardingType_SessionID_Reserved =
1292 (prMsduInfo->ucPsForwardingType) | ((prMsduInfo->ucPsSessionID) << HIF_TX_HDR_PS_SESSION_ID_OFFSET)
1293 | ((prMsduInfo->fgIsBurstEnd)? HIF_TX_HDR_BURST_END_MASK : 0);
1295 rHwTxHeader.ucWlanHeaderLength = (prMsduInfo->ucMacHeaderLength & HIF_TX_HDR_WLAN_HEADER_LEN_MASK);
1296 rHwTxHeader.ucPktFormtId_Flags =
1297 (prMsduInfo->ucFormatID & HIF_TX_HDR_FORMAT_ID_MASK)
1298 | ((prMsduInfo->ucNetworkType << HIF_TX_HDR_NETWORK_TYPE_OFFSET) & HIF_TX_HDR_NETWORK_TYPE_MASK)
1299 | ((prMsduInfo->fgIs802_1x << HIF_TX_HDR_FLAG_1X_FRAME_OFFSET) & HIF_TX_HDR_FLAG_1X_FRAME_MASK)
1300 | ((prMsduInfo->fgIs802_11 << HIF_TX_HDR_FLAG_802_11_FORMAT_OFFSET) & HIF_TX_HDR_FLAG_802_11_FORMAT_MASK);
1302 rHwTxHeader.u2SeqNo = prMsduInfo->u2AclSN;
1304 if(prMsduInfo->pfTxDoneHandler) {
1305 rHwTxHeader.ucPacketSeqNo = prMsduInfo->ucTxSeqNum;
1306 rHwTxHeader.ucAck_BIP_BasicRate = HIF_TX_HDR_NEED_ACK;
1309 rHwTxHeader.ucPacketSeqNo = 0;
1310 rHwTxHeader.ucAck_BIP_BasicRate = 0;
1313 if(prMsduInfo->fgIsBIP) {
1314 rHwTxHeader.ucAck_BIP_BasicRate |= HIF_TX_HDR_BIP;
1317 if(prMsduInfo->fgIsBasicRate) {
1318 rHwTxHeader.ucAck_BIP_BasicRate |= HIF_TX_HDR_BASIC_RATE;
1321 // <2.3> Copy HIF TX HEADER
1322 kalMemCopy((PVOID)&pucOutputBuf[0], (PVOID)&rHwTxHeader, TX_HDR_SIZE);
1324 // <3> Copy Frame Body
1325 kalMemCopy(pucOutputBuf + TX_HDR_SIZE,
1326 prMsduInfo->prPacket,
1327 prMsduInfo->u2FrameLength);
1329 // <4> Management Frame Post-Processing
1330 GLUE_DEC_REF_CNT(prTxCtrl->i4TxMgmtPendingNum);
1332 if (prMsduInfo->pfTxDoneHandler == NULL) {
1333 cnmMgtPktFree(prAdapter, prMsduInfo);
1337 DBGLOG(INIT, TRACE,("Wait Cmd TxSeqNum:%d\n", prMsduInfo->ucTxSeqNum));
1339 KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TXING_MGMT_LIST);
1340 QUEUE_INSERT_TAIL(&(prTxCtrl->rTxMgmtTxingQueue), (P_QUE_ENTRY_T)prMsduInfo);
1341 KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TXING_MGMT_LIST);
1345 prWifiCmd = (P_WIFI_CMD_T)prCmdInfo->pucInfoBuffer;
1347 // <2> Compose the Header of Transmit Data Structure for CMD Packet
1348 u2OverallBufferLength = TFCB_FRAME_PAD_TO_DW(
1349 (prCmdInfo->u2InfoBufLen) & (UINT_16)HIF_TX_HDR_TX_BYTE_COUNT_MASK);
1351 prWifiCmd->u2TxByteCount_UserPriority = u2OverallBufferLength;
1352 prWifiCmd->ucEtherTypeOffset = 0;
1353 prWifiCmd->ucResource_PktType_CSflags = (ucTC << HIF_TX_HDR_RESOURCE_OFFSET)
1354 | (UINT_8)((HIF_TX_PKT_TYPE_CMD << HIF_TX_HDR_PACKET_TYPE_OFFSET) & (HIF_TX_HDR_PACKET_TYPE_MASK));
1357 // <3> Copy CMD Header to command buffer (by using pucCoalescingBufCached)
1358 kalMemCopy((PVOID)&pucOutputBuf[0],
1359 (PVOID)prCmdInfo->pucInfoBuffer,
1360 prCmdInfo->u2InfoBufLen);
1362 ASSERT(u2OverallBufferLength <= prAdapter->u4CoalescingBufCachedSize);
1365 // <4> Write frame to data port
1366 HAL_WRITE_TX_PORT(prAdapter,
1368 (UINT_32)u2OverallBufferLength,
1369 (PUINT_8)pucOutputBuf,
1370 (UINT_32)prAdapter->u4CoalescingBufCachedSize);
1372 return WLAN_STATUS_SUCCESS;
1373 } /* end of nicTxCmd() */
1376 /*----------------------------------------------------------------------------*/
1378 * @brief This function will clean up all the pending frames in internal SW Queues
1379 * by return the pending TX packet to the system.
1381 * @param prAdapter Pointer to the Adapter structure.
1385 /*----------------------------------------------------------------------------*/
1388 IN P_ADAPTER_T prAdapter
1391 P_TX_CTRL_T prTxCtrl;
1392 P_MSDU_INFO_T prMsduInfo;
1394 KAL_SPIN_LOCK_DECLARATION();
1398 prTxCtrl = &prAdapter->rTxCtrl;
1400 nicTxFlush(prAdapter);
1402 // free MSDU_INFO_T from rTxMgmtMsduInfoList
1404 KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TXING_MGMT_LIST);
1405 QUEUE_REMOVE_HEAD(&prTxCtrl->rTxMgmtTxingQueue, prMsduInfo, P_MSDU_INFO_T);
1406 KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TXING_MGMT_LIST);
1409 // the packet must be mgmt frame with tx done callback
1410 ASSERT(prMsduInfo->eSrc == TX_PACKET_MGMT);
1411 ASSERT(prMsduInfo->pfTxDoneHandler != NULL);
1413 // invoke done handler
1414 prMsduInfo->pfTxDoneHandler(prAdapter, prMsduInfo, TX_RESULT_LIFE_TIMEOUT);
1416 cnmMgtPktFree(prAdapter, prMsduInfo);
1424 } /* end of nicTxRelease() */
1427 /*----------------------------------------------------------------------------*/
1429 * @brief Process the TX Done interrupt and pull in more pending frames in SW
1430 * Queues for transmission.
1432 * @param prAdapter Pointer to the Adapter structure.
1436 /*----------------------------------------------------------------------------*/
1438 nicProcessTxInterrupt(
1439 IN P_ADAPTER_T prAdapter
1442 P_TX_CTRL_T prTxCtrl;
1443 #if CFG_SDIO_INTR_ENHANCE
1444 P_SDIO_CTRL_T prSDIOCtrl;
1446 UINT_32 au4TxCount[2];
1447 #endif /* CFG_SDIO_INTR_ENHANCE */
1451 prTxCtrl = &prAdapter->rTxCtrl;
1454 /* Get the TX STATUS */
1455 #if CFG_SDIO_INTR_ENHANCE
1457 prSDIOCtrl = prAdapter->prSDIOCtrl;
1459 //dumpMemory8((PUINT_8)prSDIOCtrl, sizeof(SDIO_CTRL_T));
1462 nicTxReleaseResource(prAdapter, (PUINT_8)&prSDIOCtrl->rTxInfo);
1463 kalMemZero(&prSDIOCtrl->rTxInfo, sizeof(prSDIOCtrl->rTxInfo));
1467 HAL_MCR_RD(prAdapter, MCR_WTSR0, &au4TxCount[0]);
1468 HAL_MCR_RD(prAdapter, MCR_WTSR1, &au4TxCount[1]);
1469 DBGLOG(EMU, TRACE, ("MCR_WTSR0: 0x%x, MCR_WTSR1: 0x%x\n", au4TxCount[0], au4TxCount[1]));
1471 nicTxReleaseResource(prAdapter, (PUINT_8)au4TxCount);
1473 #endif /* CFG_SDIO_INTR_ENHANCE */
1475 nicTxAdjustTcq(prAdapter);
1477 // Indicate Service Thread
1478 if(kalGetTxPendingCmdCount(prAdapter->prGlueInfo) > 0
1479 || wlanGetTxPendingFrameCount(prAdapter) > 0) {
1480 kalSetEvent(prAdapter->prGlueInfo);
1484 } /* end of nicProcessTxInterrupt() */
1487 /*----------------------------------------------------------------------------*/
1489 * @brief this function frees packet of P_MSDU_INFO_T linked-list
1491 * @param prAdapter Pointer to the Adapter structure.
1492 * @param prMsduInfoList a link list of P_MSDU_INFO_T
1496 /*----------------------------------------------------------------------------*/
1498 nicTxFreeMsduInfoPacket (
1499 IN P_ADAPTER_T prAdapter,
1500 IN P_MSDU_INFO_T prMsduInfoListHead
1503 P_NATIVE_PACKET prNativePacket;
1504 P_MSDU_INFO_T prMsduInfo = prMsduInfoListHead;
1505 P_TX_CTRL_T prTxCtrl;
1509 ASSERT(prMsduInfoListHead);
1511 prTxCtrl = &prAdapter->rTxCtrl;
1514 prNativePacket = prMsduInfo->prPacket;
1516 if(prMsduInfo->eSrc == TX_PACKET_OS) {
1517 kalSendComplete(prAdapter->prGlueInfo,
1519 WLAN_STATUS_FAILURE);
1521 else if(prMsduInfo->eSrc == TX_PACKET_MGMT) {
1522 if (prMsduInfo->pfTxDoneHandler) {
1523 prMsduInfo->pfTxDoneHandler(prAdapter, prMsduInfo, TX_RESULT_DROPPED_IN_DRIVER);
1525 cnmMemFree(prAdapter, prNativePacket);
1527 else if(prMsduInfo->eSrc == TX_PACKET_FORWARDING) {
1528 GLUE_DEC_REF_CNT(prTxCtrl->i4PendingFwdFrameCount);
1531 prMsduInfo = (P_MSDU_INFO_T)QUEUE_GET_NEXT_ENTRY((P_QUE_ENTRY_T)prMsduInfo);
1538 /*----------------------------------------------------------------------------*/
1540 * @brief this function returns P_MSDU_INFO_T of MsduInfoList to TxCtrl->rfreeMsduInfoList
1542 * @param prAdapter Pointer to the Adapter structure.
1543 * @param prMsduInfoList a link list of P_MSDU_INFO_T
1547 /*----------------------------------------------------------------------------*/
1549 nicTxReturnMsduInfo (
1550 IN P_ADAPTER_T prAdapter,
1551 IN P_MSDU_INFO_T prMsduInfoListHead
1554 P_TX_CTRL_T prTxCtrl;
1555 P_MSDU_INFO_T prMsduInfo = prMsduInfoListHead, prNextMsduInfo;
1557 KAL_SPIN_LOCK_DECLARATION();
1561 prTxCtrl = &prAdapter->rTxCtrl;
1565 prNextMsduInfo = (P_MSDU_INFO_T)QUEUE_GET_NEXT_ENTRY((P_QUE_ENTRY_T)prMsduInfo);
1567 switch(prMsduInfo->eSrc) {
1568 case TX_PACKET_FORWARDING:
1569 wlanReturnPacket(prAdapter, prMsduInfo->prPacket);
1572 case TX_PACKET_OS_OID:
1573 case TX_PACKET_MGMT:
1578 KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_MSDU_INFO_LIST);
1579 QUEUE_INSERT_TAIL(&prTxCtrl->rFreeMsduInfoList, (P_QUE_ENTRY_T)prMsduInfo);
1580 KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_MSDU_INFO_LIST);
1581 prMsduInfo = prNextMsduInfo;
1589 /*----------------------------------------------------------------------------*/
1591 * @brief this function fills packet information to P_MSDU_INFO_T
1593 * @param prAdapter Pointer to the Adapter structure.
1594 * @param prMsduInfo P_MSDU_INFO_T
1595 * @param prPacket P_NATIVE_PACKET
1597 * @retval TRUE Success to extract information
1598 * @retval FALSE Fail to extract correct information
1600 /*----------------------------------------------------------------------------*/
1603 IN P_ADAPTER_T prAdapter,
1604 IN P_MSDU_INFO_T prMsduInfo,
1605 IN P_NATIVE_PACKET prPacket
1608 P_GLUE_INFO_T prGlueInfo;
1609 UINT_8 ucPriorityParam;
1610 UINT_8 ucMacHeaderLen;
1611 UINT_8 aucEthDestAddr[PARAM_MAC_ADDR_LEN];
1612 BOOLEAN fgIs1x = FALSE;
1613 BOOLEAN fgIsPAL = FALSE;
1614 UINT_32 u4PacketLen;
1616 UINT_8 ucNetworkType;
1621 prGlueInfo = prAdapter->prGlueInfo;
1624 if (kalQoSFrameClassifierAndPacketInfo(prGlueInfo,
1631 &ucNetworkType) == FALSE) {
1635 /* Save the value of Priority Parameter */
1636 GLUE_SET_PKT_TID(prPacket, ucPriorityParam);
1639 GLUE_SET_PKT_FLAG_1X(prPacket);
1643 GLUE_SET_PKT_FLAG_PAL(prPacket);
1646 ucMacHeaderLen = ETH_HLEN;
1648 /* Save the value of Header Length */
1649 GLUE_SET_PKT_HEADER_LEN(prPacket, ucMacHeaderLen);
1651 /* Save the value of Frame Length */
1652 GLUE_SET_PKT_FRAME_LEN(prPacket, (UINT_16)u4PacketLen);
1654 /* Save the value of Arrival Time*/
1655 u4SysTime = (OS_SYSTIME)kalGetTimeTick();
1656 GLUE_SET_PKT_ARRIVAL_TIME(prPacket, u4SysTime);
1658 prMsduInfo->prPacket = prPacket;
1659 prMsduInfo->fgIs802_1x = fgIs1x;
1660 prMsduInfo->fgIs802_11 = FALSE;
1661 prMsduInfo->ucNetworkType = ucNetworkType;
1662 prMsduInfo->ucUserPriority = ucPriorityParam;
1663 prMsduInfo->ucMacHeaderLength = ucMacHeaderLen;
1664 prMsduInfo->u2FrameLength = (UINT_16)u4PacketLen;
1665 COPY_MAC_ADDR(prMsduInfo->aucEthDestAddr, aucEthDestAddr);
1671 /*----------------------------------------------------------------------------*/
1673 * @brief this function update TCQ values by passing current status to txAdjustTcQuotas
1675 * @param prAdapter Pointer to the Adapter structure.
1677 * @retval WLAN_STATUS_SUCCESS Updated successfully
1679 /*----------------------------------------------------------------------------*/
1682 IN P_ADAPTER_T prAdapter
1686 TX_TCQ_ADJUST_T rTcqAdjust;
1687 P_TX_CTRL_T prTxCtrl;
1688 KAL_SPIN_LOCK_DECLARATION();
1692 prTxCtrl = &prAdapter->rTxCtrl;
1695 qmAdjustTcQuotas(prAdapter, &rTcqAdjust, &prTxCtrl->rTc);
1696 KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_RESOURCE);
1698 for (u4Num = 0 ; u4Num < TC_NUM ; u4Num++) {
1699 prTxCtrl->rTc.aucFreeBufferCount[u4Num] += rTcqAdjust.acVariation[u4Num];
1700 prTxCtrl->rTc.aucMaxNumOfBuffer[u4Num] += rTcqAdjust.acVariation[u4Num];
1702 ASSERT(prTxCtrl->rTc.aucFreeBufferCount[u4Num] >= 0);
1703 ASSERT(prTxCtrl->rTc.aucMaxNumOfBuffer[u4Num] >= 0);
1706 KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_RESOURCE);
1708 return WLAN_STATUS_SUCCESS;
1712 /*----------------------------------------------------------------------------*/
1714 * @brief this function flushes all packets queued in STA/AC queue
1716 * @param prAdapter Pointer to the Adapter structure.
1718 * @retval WLAN_STATUS_SUCCESS Flushed successfully
1720 /*----------------------------------------------------------------------------*/
1724 IN P_ADAPTER_T prAdapter
1727 P_MSDU_INFO_T prMsduInfo;
1728 KAL_SPIN_LOCK_DECLARATION();
1732 // ask Per STA/AC queue to be fllushed and return all queued packets
1733 KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_QM_TX_QUEUE);
1734 prMsduInfo = qmFlushTxQueues(prAdapter);
1735 KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_QM_TX_QUEUE);
1737 if(prMsduInfo != NULL) {
1738 nicTxFreeMsduInfoPacket(prAdapter, prMsduInfo);
1739 nicTxReturnMsduInfo(prAdapter, prMsduInfo);
1742 return WLAN_STATUS_SUCCESS;
1746 #if CFG_ENABLE_FW_DOWNLOAD
1747 /*----------------------------------------------------------------------------*/
1749 * \brief In this function, we'll write Command(CMD_INFO_T) into HIF.
1750 * However this function is used for INIT_CMD.
1752 * In order to avoid further maintainance issues, these 2 functions are separated
1754 * @param prAdapter Pointer to the Adapter structure.
1755 * @param prPacketInfo Pointer of CMD_INFO_T
1756 * @param ucTC Specify the resource of TC
1758 * @retval WLAN_STATUS_SUCCESS Bus access ok.
1759 * @retval WLAN_STATUS_FAILURE Bus access fail.
1761 /*----------------------------------------------------------------------------*/
1764 IN P_ADAPTER_T prAdapter,
1765 IN P_CMD_INFO_T prCmdInfo,
1769 P_INIT_HIF_TX_HEADER_T prInitTxHeader;
1770 UINT_16 u2OverallBufferLength;
1771 PUINT_8 pucOutputBuf = (PUINT_8)NULL; /* Pointer to Transmit Data Structure Frame */
1773 P_TX_CTRL_T prTxCtrl;
1777 ASSERT(ucTC == TC0_INDEX);
1779 prTxCtrl = &prAdapter->rTxCtrl;
1780 pucOutputBuf = prTxCtrl->pucTxCoalescingBufPtr;
1781 prInitTxHeader = (P_INIT_HIF_TX_HEADER_T)prCmdInfo->pucInfoBuffer;
1783 // <1> Compose the Header of Transmit Data Structure for CMD Packet
1784 u2OverallBufferLength = TFCB_FRAME_PAD_TO_DW(
1785 (prCmdInfo->u2InfoBufLen) & (UINT_16)HIF_TX_HDR_TX_BYTE_COUNT_MASK);
1787 prInitTxHeader->u2TxByteCount = u2OverallBufferLength;
1788 prInitTxHeader->ucEtherTypeOffset = 0;
1789 prInitTxHeader->ucCSflags = 0;
1791 // <2> Assign Data Port
1792 if (ucTC != TC4_INDEX) {
1795 else { // Broadcast/multicast data packets
1799 // <3> Copy CMD Header to command buffer (by using pucCoalescingBufCached)
1800 kalMemCopy((PVOID)&pucOutputBuf[0],
1801 (PVOID)prCmdInfo->pucInfoBuffer,
1802 prCmdInfo->u2InfoBufLen);
1804 ASSERT(u2OverallBufferLength <= prAdapter->u4CoalescingBufCachedSize);
1806 // <4> Write frame to data port
1807 HAL_WRITE_TX_PORT(prAdapter,
1809 (UINT_32)u2OverallBufferLength,
1810 (PUINT_8)pucOutputBuf,
1811 (UINT_32)prAdapter->u4CoalescingBufCachedSize);
1813 return WLAN_STATUS_SUCCESS;
1817 /*----------------------------------------------------------------------------*/
1819 * \brief In this function, we'll reset TX resource counter to initial value used
1820 * in F/W download state
1822 * @param prAdapter Pointer to the Adapter structure.
1824 * @retval WLAN_STATUS_SUCCESS Reset is done successfully.
1826 /*----------------------------------------------------------------------------*/
1828 nicTxInitResetResource (
1829 IN P_ADAPTER_T prAdapter
1832 P_TX_CTRL_T prTxCtrl;
1834 DEBUGFUNC("nicTxInitResetResource");
1837 prTxCtrl = &prAdapter->rTxCtrl;
1839 prTxCtrl->rTc.aucMaxNumOfBuffer[TC0_INDEX] = NIC_TX_INIT_BUFF_COUNT_TC0;
1840 prTxCtrl->rTc.aucFreeBufferCount[TC0_INDEX] = NIC_TX_INIT_BUFF_COUNT_TC0;
1842 prTxCtrl->rTc.aucMaxNumOfBuffer[TC1_INDEX] = NIC_TX_INIT_BUFF_COUNT_TC1;
1843 prTxCtrl->rTc.aucFreeBufferCount[TC1_INDEX] = NIC_TX_INIT_BUFF_COUNT_TC1;
1845 prTxCtrl->rTc.aucMaxNumOfBuffer[TC2_INDEX] = NIC_TX_INIT_BUFF_COUNT_TC2;
1846 prTxCtrl->rTc.aucFreeBufferCount[TC2_INDEX] = NIC_TX_INIT_BUFF_COUNT_TC2;
1848 prTxCtrl->rTc.aucMaxNumOfBuffer[TC3_INDEX] = NIC_TX_INIT_BUFF_COUNT_TC3;
1849 prTxCtrl->rTc.aucFreeBufferCount[TC3_INDEX] = NIC_TX_INIT_BUFF_COUNT_TC3;
1851 prTxCtrl->rTc.aucMaxNumOfBuffer[TC4_INDEX] = NIC_TX_INIT_BUFF_COUNT_TC4;
1852 prTxCtrl->rTc.aucFreeBufferCount[TC4_INDEX] = NIC_TX_INIT_BUFF_COUNT_TC4;
1854 prTxCtrl->rTc.aucMaxNumOfBuffer[TC5_INDEX] = NIC_TX_INIT_BUFF_COUNT_TC5;
1855 prTxCtrl->rTc.aucFreeBufferCount[TC5_INDEX] = NIC_TX_INIT_BUFF_COUNT_TC5;
1857 return WLAN_STATUS_SUCCESS;
1864 /*----------------------------------------------------------------------------*/
1866 * \brief this function enqueues MSDU_INFO_T into queue management,
1869 * @param prAdapter Pointer to the Adapter structure.
1870 * prMsduInfo Pointer to MSDU
1872 * @retval WLAN_STATUS_SUCCESS Reset is done successfully.
1874 /*----------------------------------------------------------------------------*/
1877 IN P_ADAPTER_T prAdapter,
1878 IN P_MSDU_INFO_T prMsduInfo
1881 P_TX_CTRL_T prTxCtrl;
1882 P_MSDU_INFO_T prNextMsduInfo, prRetMsduInfo, prMsduInfoHead;
1883 QUE_T qDataPort0, qDataPort1;
1884 P_CMD_INFO_T prCmdInfo;
1885 WLAN_STATUS u4Status = WLAN_STATUS_SUCCESS;
1886 KAL_SPIN_LOCK_DECLARATION();
1891 prTxCtrl = &prAdapter->rTxCtrl;
1894 QUEUE_INITIALIZE(&qDataPort0);
1895 QUEUE_INITIALIZE(&qDataPort1);
1897 /* check how many management frame are being queued */
1899 prNextMsduInfo = (P_MSDU_INFO_T)QUEUE_GET_NEXT_ENTRY((P_QUE_ENTRY_T)prMsduInfo);
1901 QUEUE_GET_NEXT_ENTRY((P_QUE_ENTRY_T)prMsduInfo) = NULL;
1903 if(prMsduInfo->eSrc == TX_PACKET_MGMT) {
1904 // MMPDU: force stick to TC4
1905 prMsduInfo->ucTC = TC4_INDEX;
1907 QUEUE_INSERT_TAIL(&qDataPort1, (P_QUE_ENTRY_T)prMsduInfo);
1910 QUEUE_INSERT_TAIL(&qDataPort0, (P_QUE_ENTRY_T)prMsduInfo);
1913 prMsduInfo = prNextMsduInfo;
1916 if(qDataPort0.u4NumElem) {
1918 KAL_SPIN_LOCK_DECLARATION();
1919 KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_QM_TX_QUEUE);
1920 prRetMsduInfo = qmEnqueueTxPackets(prAdapter, (P_MSDU_INFO_T)QUEUE_GET_HEAD(&qDataPort0));
1921 KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_QM_TX_QUEUE);
1923 /* post-process for dropped packets */
1924 if(prRetMsduInfo != NULL) { // unable to enqueue
1925 nicTxFreeMsduInfoPacket(prAdapter, prRetMsduInfo);
1926 nicTxReturnMsduInfo(prAdapter, prRetMsduInfo);
1930 if(qDataPort1.u4NumElem) {
1931 prMsduInfoHead = (P_MSDU_INFO_T)QUEUE_GET_HEAD(&qDataPort1);
1933 if(qDataPort1.u4NumElem > nicTxGetFreeCmdCount(prAdapter)) {
1934 // not enough descriptors for sending
1935 u4Status = WLAN_STATUS_FAILURE;
1938 while(prMsduInfoHead) {
1939 prNextMsduInfo = (P_MSDU_INFO_T) QUEUE_GET_NEXT_ENTRY(&prMsduInfoHead->rQueEntry);
1941 if (prMsduInfoHead->pfTxDoneHandler != NULL) {
1942 prMsduInfoHead->pfTxDoneHandler(prAdapter, prMsduInfoHead, TX_RESULT_DROPPED_IN_DRIVER);
1946 cnmMgtPktFree(prAdapter, prMsduInfoHead);
1948 prMsduInfoHead = prNextMsduInfo;
1952 /* send to command queue */
1953 while(prMsduInfoHead) {
1954 prNextMsduInfo = (P_MSDU_INFO_T) QUEUE_GET_NEXT_ENTRY(&prMsduInfoHead->rQueEntry);
1956 KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_CMD_RESOURCE);
1957 QUEUE_REMOVE_HEAD(&prAdapter->rFreeCmdList, prCmdInfo, P_CMD_INFO_T);
1958 KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_CMD_RESOURCE);
1961 GLUE_INC_REF_CNT(prTxCtrl->i4TxMgmtPendingNum);
1963 kalMemZero(prCmdInfo, sizeof(CMD_INFO_T));
1965 prCmdInfo->eCmdType = COMMAND_TYPE_MANAGEMENT_FRAME;
1966 prCmdInfo->u2InfoBufLen = prMsduInfoHead->u2FrameLength;
1967 prCmdInfo->pucInfoBuffer = NULL;
1968 prCmdInfo->prPacket = (P_NATIVE_PACKET)prMsduInfoHead;
1969 prCmdInfo->ucStaRecIndex = prMsduInfoHead->ucStaRecIndex;
1970 prCmdInfo->eNetworkType = prMsduInfoHead->ucNetworkType;
1971 prCmdInfo->pfCmdDoneHandler = NULL;
1972 prCmdInfo->pfCmdTimeoutHandler = NULL;
1973 prCmdInfo->fgIsOid = FALSE;
1974 prCmdInfo->fgSetQuery = TRUE;
1975 prCmdInfo->fgNeedResp = FALSE;
1977 kalEnqueueCommand(prAdapter->prGlueInfo, (P_QUE_ENTRY_T)prCmdInfo);
1980 /* Cmd free count is larger than expected, but allocation fail. */
1983 u4Status = WLAN_STATUS_FAILURE;
1984 cnmMgtPktFree(prAdapter, prMsduInfoHead);
1987 prMsduInfoHead = prNextMsduInfo;
1992 /* indicate service thread for sending */
1993 if(prTxCtrl->i4TxMgmtPendingNum > 0
1994 || kalGetTxPendingFrameCount(prAdapter->prGlueInfo) > 0) {
1995 kalSetEvent(prAdapter->prGlueInfo);
2002 /*----------------------------------------------------------------------------*/
2004 * \brief this function returns available count in command queue
2006 * @param prAdapter Pointer to the Adapter structure.
2010 /*----------------------------------------------------------------------------*/
2012 nicTxGetFreeCmdCount (
2013 IN P_ADAPTER_T prAdapter
2018 return prAdapter->rFreeCmdList.u4NumElem;