2 ** $Id: //Department/DaVinci/BRANCHES/MT662X_593X_WIFI_DRIVER_V2_3/nic/nic_tx.c#2 $
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 ********************************************************************************
58 ** no need to do TX checksum offloading for forwarding packets
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
64 * 06 13 2012 yuche.tsai
66 * Update maintrunk driver.
67 * Add support for driver compose assoc request frame.
69 * 11 18 2011 eddie.chen
70 * [WCXRP00001096] [MT6620 Wi-Fi][Driver/FW] Enhance the log function (xlog)
71 * Add log counter for tx
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.
77 * 11 08 2011 eddie.chen
78 * [WCXRP00001096] [MT6620 Wi-Fi][Driver/FW] Enhance the log function (xlog)
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.
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
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.
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.
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
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
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
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
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.
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
129 * 11 01 2010 yarco.yang
130 * [WCXRP00000149] [MT6620 WI-Fi][Driver]Fine tune performance on MT6516 platform
131 * Add GPIO debug function
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
140 * [WCXRP00000052] [MT6620 Wi-Fi][Driver] Eliminate Linux Compile Warning
141 * code reorganization to improve isolation between GLUE and CORE layers.
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.
149 * since the u2TxByteCount_UserPriority will or another setting, keep the overall buffer for avoid error
153 * [WCXRP000000058][MT6620 Wi-Fi][Driver] Fail to handshake with WAPI AP due the 802.1x frame send to fw with extra bytes padding.
157 * HIFSYS Clock Source Workaround
161 * API added: nicTxPendingPackets(), for simplifying porting layer
165 * eliminate klockwork errors
169 * adding the eapol callback setting.
171 * 08 18 2010 yarco.yang
173 * 1. Fixed HW checksum offload function not work under Linux issue.
174 * 2. Add debug message.
176 * 08 05 2010 yuche.tsai
182 * surpress compilation warning.
184 * 08 02 2010 jeffrey.chang
186 * 1) modify tx service thread to avoid busy looping
187 * 2) add spin lock declartion for linux build
191 * simplify post-handling after TX_DONE interrupt is handled.
193 * 07 19 2010 jeffrey.chang
195 * Linux port modification
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
205 * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository.
207 * 06 29 2010 yarco.yang
208 * [WPD00003837][MT6620]Data Path Refine
209 * replace g_rQM with Adpater->rQM
212 * [WPD00003833][MT6620 and MT5931] Driver migration
213 * add API in que_mgt to retrieve sta-rec index for security frames.
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.
219 * 06 23 2010 yarco.yang
220 * [WPD00003837][MT6620]Data Path Refine
221 * Merge g_arStaRec[] into adapter->arStaRec[]
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.
230 * [WPD00003833][MT6620 and MT5931] Driver migration
231 * add checking for TX descriptor poll.
234 * [WPD00003833][MT6620 and MT5931] Driver migration
235 * TX descriptors are now allocated once for reducing allocation overhead
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
242 * [WPD00003833][MT6620 and MT5931] Driver migration
243 * change zero-padding for TX port access to HAL.
246 * [WPD00003833][MT6620 and MT5931] Driver migration
250 * [WPD00003833][MT6620 and MT5931] Driver migration
254 * [WPD00003833][MT6620 and MT5931] Driver migration
255 * fill extra information for revised HIF_TX_HEADER.
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
266 * [WPD00003833][MT6620 and MT5931] Driver migration
267 * change to enqueue TX frame infinitely.
270 * [WPD00003833][MT6620 and MT5931] Driver migration
271 * add TX_PACKET_MGMT to indicate the frame is coming from management modules
273 * 06 06 2010 kevin.huang
274 * [WPD00003832][MT6620 5931] Create driver base
275 * [MT6620 5931] Create driver base
278 * [WPD00003831][MT6620 Wi-Fi] Add framework for Wi-Fi Direct support
279 * fill network type field while doing frame identification.
282 * [WPD00001943]Create WiFi test driver framework on WinXP
283 * surpress compiler warning
285 * 04 06 2010 jeffrey.chang
286 * [WPD00003826]Initial import for Linux port
287 * Tag the packet for QoS on Tx path
290 * [WPD00001943]Create WiFi test driver framework on WinXP
291 * remove driver-land statistics.
293 * 03 29 2010 jeffrey.chang
294 * [WPD00003826]Initial import for Linux port
295 * improve none-glue code portability
297 * 03 24 2010 jeffrey.chang
298 * [WPD00003826]Initial import for Linux port
299 * initial import for Linux port
302 * [WPD00001943]Create WiFi test driver framework on WinXP
303 * generate information for OID_GEN_RCV_OK & OID_GEN_XMIT_OK
307 * [WPD00001943]Create WiFi test driver framework on WinXP
308 * code clean: removing unused variables and structure definitions
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
316 * [WPD00001943]Create WiFi test driver framework on WinXP
317 * add mutex to avoid multiple access to qmTxQueue simultaneously.
320 * [WPD00001943]Create WiFi test driver framework on WinXP
321 * avoid refering to NDIS-specific data structure directly from non-glue layer.
324 * [WPD00001943]Create WiFi test driver framework on WinXP
325 * add Ethernet destination address information in packet info for TX
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
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
343 * [WPD00001943]Create WiFi test driver framework on WinXP
344 * prepare for implementing fw download logic
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
353 * 01 13 2010 tehuang.liu
354 * [WPD00001943]Create WiFi test driver framework on WinXP
355 * Enabled the Burst_End Indication mechanism
358 * [WPD00001943]Create WiFi test driver framework on WinXP
359 * TX: fill ucWlanHeaderLength/ucPktFormtId_Flags according to info provided by prMsduInfo
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
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
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
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
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
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
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
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
454 /*******************************************************************************
455 * C O M P I L E R F L A G S
456 ********************************************************************************
459 /*******************************************************************************
460 * E X T E R N A L R E F E R E N C E S
461 ********************************************************************************
465 /*******************************************************************************
467 ********************************************************************************
470 /*******************************************************************************
472 ********************************************************************************
475 /*******************************************************************************
476 * P U B L I C D A T A
477 ********************************************************************************
480 /*******************************************************************************
481 * P R I V A T E D A T A
482 ********************************************************************************
485 /*******************************************************************************
487 ********************************************************************************
490 /*******************************************************************************
491 * F U N C T I O N D E C L A R A T I O N S
492 ********************************************************************************
495 /*******************************************************************************
497 ********************************************************************************
499 /*----------------------------------------------------------------------------*/
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.
504 * @param prAdapter Pointer to the Adapter structure.
508 /*----------------------------------------------------------------------------*/
511 IN P_ADAPTER_T prAdapter
514 P_TX_CTRL_T prTxCtrl;
515 PUINT_8 pucMemHandle;
516 P_MSDU_INFO_T prMsduInfo;
518 KAL_SPIN_LOCK_DECLARATION();
520 DEBUGFUNC("nicTxInitialize");
523 prTxCtrl = &prAdapter->rTxCtrl;
525 //4 <1> Initialization of Traffic Class Queue Parameters
526 nicTxResetResource(prAdapter);
529 prTxCtrl->pucTxCoalescingBufPtr = prAdapter->pucCoalescingBufCached;
530 #endif /* CFG_SDIO_TX_AGG */
532 // allocate MSDU_INFO_T and link it into rFreeMsduInfoList
533 QUEUE_INITIALIZE(&prTxCtrl->rFreeMsduInfoList);
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));
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);
544 pucMemHandle += ALIGN_4(sizeof(MSDU_INFO_T));
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);
551 QUEUE_INITIALIZE(&prTxCtrl->rTxMgmtTxingQueue);
552 prTxCtrl->i4TxMgmtPendingNum = 0;
554 #if CFG_HIF_STATISTICS
555 prTxCtrl->u4TotalTxAccessNum = 0;
556 prTxCtrl->u4TotalTxPacketNum = 0;
559 prTxCtrl->i4PendingFwdFrameCount = 0;
563 TX_RESET_ALL_CNTS(prTxCtrl);
566 } /* end of nicTxInitialize() */
569 /*----------------------------------------------------------------------------*/
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.
575 * \param[in] prAdapter Pointer to the Adapter structure.
576 * \param[in] ucTC Specify the resource of TC
578 * \retval WLAN_STATUS_SUCCESS Resource is available and been assigned.
579 * \retval WLAN_STATUS_RESOURCES Resource is not available.
581 /*----------------------------------------------------------------------------*/
583 nicTxAcquireResource (
584 IN P_ADAPTER_T prAdapter,
588 P_TX_CTRL_T prTxCtrl;
589 WLAN_STATUS u4Status = WLAN_STATUS_RESOURCES;
590 KAL_SPIN_LOCK_DECLARATION();
593 prTxCtrl = &prAdapter->rTxCtrl;
596 KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_RESOURCE);
598 // DbgPrint("nicTxAcquireResource prTxCtrl->rTc.aucFreeBufferCount[%d]=%d\n", ucTC, prTxCtrl->rTc.aucFreeBufferCount[ucTC]);
600 if (prTxCtrl->rTc.aucFreeBufferCount[ucTC]) {
602 prTxCtrl->rTc.aucFreeBufferCount[ucTC]--;
604 DBGLOG(TX, EVENT, ("Acquire: TC = %d aucFreeBufferCount = %d\n",
605 ucTC, prTxCtrl->rTc.aucFreeBufferCount[ucTC]));
607 u4Status = WLAN_STATUS_SUCCESS;
609 KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_RESOURCE);
613 }/* end of nicTxAcquireResourceAndTFCBs() */
616 /*----------------------------------------------------------------------------*/
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.
622 * @param prAdapter Pointer to the Adapter structure.
623 * @param ucTC Specify the resource of TC
625 * @retval WLAN_STATUS_SUCCESS Resource is available.
626 * @retval WLAN_STATUS_FAILURE Resource is not available.
628 /*----------------------------------------------------------------------------*/
630 nicTxPollingResource (
631 IN P_ADAPTER_T prAdapter,
635 P_TX_CTRL_T prTxCtrl;
636 WLAN_STATUS u4Status = WLAN_STATUS_FAILURE;
637 INT_32 i = NIC_TX_RESOURCE_POLLING_TIMEOUT;
641 prTxCtrl = &prAdapter->rTxCtrl;
643 if (ucTC >= TC_NUM) {
644 return WLAN_STATUS_FAILURE;
647 if (prTxCtrl->rTc.aucFreeBufferCount[ucTC] > 0) {
648 return WLAN_STATUS_SUCCESS;
652 HAL_READ_TX_RELEASED_COUNT(prAdapter, au4WTSR);
654 if(kalIsCardRemoved(prAdapter->prGlueInfo) == TRUE
655 || fgIsBusAccessFailed == TRUE) {
656 u4Status = WLAN_STATUS_FAILURE;
659 else if (nicTxReleaseResource(prAdapter, (PUINT_8)au4WTSR)) {
660 if (prTxCtrl->rTc.aucFreeBufferCount[ucTC] > 0) {
661 u4Status = WLAN_STATUS_SUCCESS;
665 kalMsleep(NIC_TX_RESOURCE_POLLING_DELAY_MSEC);
669 kalMsleep(NIC_TX_RESOURCE_POLLING_DELAY_MSEC);
675 INT_32 i4Times = NIC_TX_RESOURCE_POLLING_TIMEOUT - (i+1);
678 DBGLOG(TX, TRACE, ("Polling MCR_WTSR delay %d times, %d msec\n",
679 i4Times, (i4Times * NIC_TX_RESOURCE_POLLING_DELAY_MSEC)));
686 } /* end of nicTxPollingResource() */
689 /*----------------------------------------------------------------------------*/
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.
695 * \param[in] prAdapter Pointer to the Adapter structure.
696 * \param[in] u4TxStatusCnt Value of TX STATUS
700 /*----------------------------------------------------------------------------*/
702 nicTxReleaseResource (
703 IN P_ADAPTER_T prAdapter,
704 IN UINT_8* aucTxRlsCnt
707 PUINT_32 pu4Tmp = (PUINT_32)aucTxRlsCnt;
708 P_TX_CTRL_T prTxCtrl;
709 BOOLEAN bStatus = FALSE;
712 KAL_SPIN_LOCK_DECLARATION();
716 prTxCtrl = &prAdapter->rTxCtrl;
718 if (pu4Tmp[0] | pu4Tmp[1]) {
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];
724 if ((i==1) || (i==5)){
725 DBGLOG(TX, EVENT, ("Release: i = %d aucFreeBufferCount = %d\n",
726 i, prTxCtrl->rTc.aucFreeBufferCount[i]));
729 KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_RESOURCE);
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]));
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]);
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]);
752 } /* end of nicTxReleaseResource() */
755 /*----------------------------------------------------------------------------*/
757 * \brief Reset TC Buffer Count to initialized value
759 * \param[in] prAdapter Pointer to the Adapter structure.
761 * @return WLAN_STATUS_SUCCESS
763 /*----------------------------------------------------------------------------*/
766 IN P_ADAPTER_T prAdapter
769 P_TX_CTRL_T prTxCtrl;
771 KAL_SPIN_LOCK_DECLARATION();
773 DEBUGFUNC("nicTxResetResource");
776 prTxCtrl = &prAdapter->rTxCtrl;
778 KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_RESOURCE);
780 prTxCtrl->rTc.aucMaxNumOfBuffer[TC0_INDEX] = NIC_TX_BUFF_COUNT_TC0;
781 prTxCtrl->rTc.aucFreeBufferCount[TC0_INDEX] = NIC_TX_BUFF_COUNT_TC0;
783 prTxCtrl->rTc.aucMaxNumOfBuffer[TC1_INDEX] = NIC_TX_BUFF_COUNT_TC1;
784 prTxCtrl->rTc.aucFreeBufferCount[TC1_INDEX] = NIC_TX_BUFF_COUNT_TC1;
786 prTxCtrl->rTc.aucMaxNumOfBuffer[TC2_INDEX] = NIC_TX_BUFF_COUNT_TC2;
787 prTxCtrl->rTc.aucFreeBufferCount[TC2_INDEX] = NIC_TX_BUFF_COUNT_TC2;
789 prTxCtrl->rTc.aucMaxNumOfBuffer[TC3_INDEX] = NIC_TX_BUFF_COUNT_TC3;
790 prTxCtrl->rTc.aucFreeBufferCount[TC3_INDEX] = NIC_TX_BUFF_COUNT_TC3;
792 prTxCtrl->rTc.aucMaxNumOfBuffer[TC4_INDEX] = NIC_TX_BUFF_COUNT_TC4;
793 prTxCtrl->rTc.aucFreeBufferCount[TC4_INDEX] = NIC_TX_BUFF_COUNT_TC4;
795 prTxCtrl->rTc.aucMaxNumOfBuffer[TC5_INDEX] = NIC_TX_BUFF_COUNT_TC5;
796 prTxCtrl->rTc.aucFreeBufferCount[TC5_INDEX] = NIC_TX_BUFF_COUNT_TC5;
798 KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_RESOURCE);
800 return WLAN_STATUS_SUCCESS;
804 /*----------------------------------------------------------------------------*/
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
810 * @param prAdapter Pointer to the Adapter structure.
811 * @param ucTC Specify the resource of TC
813 * @retval UINT_8 The number of corresponding TC number
815 /*----------------------------------------------------------------------------*/
818 IN P_ADAPTER_T prAdapter,
822 P_TX_CTRL_T prTxCtrl;
825 prTxCtrl = &prAdapter->rTxCtrl;
829 if (ucTC >= TC_NUM) {
833 return prTxCtrl->rTc.aucFreeBufferCount[ucTC];
838 /*----------------------------------------------------------------------------*/
840 * @brief In this function, we'll aggregate frame(PACKET_INFO_T)
841 * corresponding to HIF TX port
843 * @param prAdapter Pointer to the Adapter structure.
844 * @param prMsduInfoListHead a link list of P_MSDU_INFO_T
846 * @retval WLAN_STATUS_SUCCESS Bus access ok.
847 * @retval WLAN_STATUS_FAILURE Bus access fail.
849 /*----------------------------------------------------------------------------*/
852 IN P_ADAPTER_T prAdapter,
853 IN P_MSDU_INFO_T prMsduInfoListHead
856 P_MSDU_INFO_T prMsduInfo, prNextMsduInfo;
857 QUE_T qDataPort0, qDataPort1;
861 ASSERT(prMsduInfoListHead);
863 prMsduInfo = prMsduInfoListHead;
865 QUEUE_INITIALIZE(&qDataPort0);
866 QUEUE_INITIALIZE(&qDataPort1);
868 // Separate MSDU_INFO_T lists into 2 categories: for Port#0 & Port#1
870 prNextMsduInfo = (P_MSDU_INFO_T)QUEUE_GET_NEXT_ENTRY((P_QUE_ENTRY_T)prMsduInfo);
872 LOG_FUNC("nicTxMsduInfoList Acquire TC %d net %u mac len %u len %u Type %u 1x %u 11 %u\n",
874 prMsduInfo->ucNetworkType,
875 prMsduInfo->ucMacHeaderLength,
876 prMsduInfo->u2FrameLength,
877 prMsduInfo->ucPacketType,
878 prMsduInfo->fgIs802_1x,
879 prMsduInfo->fgIs802_11 );
881 LOG_FUNC("Dest Mac: " MACSTR "\n",
882 MAC2STR(prMsduInfo->aucEthDestAddr));
885 switch(prMsduInfo->ucTC) {
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)
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);
902 status = nicTxAcquireResource(prAdapter, prMsduInfo->ucTC);
903 ASSERT(status == WLAN_STATUS_SUCCESS)
912 prMsduInfo = prNextMsduInfo;
915 if(qDataPort0.u4NumElem > 0) {
916 nicTxMsduQueue(prAdapter, 0, &qDataPort0);
919 if(qDataPort1.u4NumElem > 0) {
920 nicTxMsduQueue(prAdapter, 1, &qDataPort1);
923 return WLAN_STATUS_SUCCESS;
926 #if CFG_ENABLE_PKT_LIFETIME_PROFILE
928 PKT_PROFILE_T rPrevRoundLastPkt;
931 nicTxReturnMsduInfoProfiling (
932 IN P_ADAPTER_T prAdapter,
933 IN P_MSDU_INFO_T prMsduInfoListHead
936 P_MSDU_INFO_T prMsduInfo = prMsduInfoListHead, prNextMsduInfo;
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;
943 BOOLEAN fgGotFirst = FALSE;
944 BOOLEAN fgPrintCurPkt = FALSE;
945 BOOLEAN fgIsPrevPrinted = FALSE;
947 UINT_32 u4MaxDeltaTime = 50; // in ms
950 prNextMsduInfo = (P_MSDU_INFO_T)QUEUE_GET_NEXT_ENTRY((P_QUE_ENTRY_T)prMsduInfo);
951 prPktProfile = &prMsduInfo->rPktProfile;
952 fgPrintCurPkt = FALSE;
954 if(prPktProfile->fgIsValid) {
955 prPktProfile->rHifTxDoneTimestamp = kalGetTimeTick();
957 //4 1. check delta between current round first pkt and prevous round last pkt
959 prFirstProfileMsduInfo = prMsduInfo;
962 if(prPrevRoundLastPkt->fgIsValid) {
963 if(CHK_PROFILES_DELTA(prPktProfile, prPrevRoundLastPkt, u4MaxDeltaTime)) {
964 PRINT_PKT_PROFILE(prPrevRoundLastPkt, "PR");
965 fgPrintCurPkt = TRUE;
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;
978 //4 3. check delta of current pkt lifetime
979 if(CHK_PROFILE_DELTA(prPktProfile, u4MaxDeltaTime)) {
980 fgPrintCurPkt = TRUE;
983 /* Print current pkt profile */
985 PRINT_PKT_PROFILE(prPktProfile, "C");
988 fgIsPrevPrinted = fgPrintCurPkt;
989 prPrevProfileMsduInfo = prMsduInfo;
992 prMsduInfo = prNextMsduInfo;
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;
1008 nicTxReturnMsduInfo(prAdapter, prMsduInfoListHead);
1014 /*----------------------------------------------------------------------------*/
1016 * @brief In this function, we'll write frame(PACKET_INFO_T) into HIF.
1018 * @param prAdapter Pointer to the Adapter structure.
1019 * @param ucPortIdx Port Number
1020 * @param prQue a link list of P_MSDU_INFO_T
1022 * @retval WLAN_STATUS_SUCCESS Bus access ok.
1023 * @retval WLAN_STATUS_FAILURE Bus access fail.
1025 /*----------------------------------------------------------------------------*/
1028 IN P_ADAPTER_T prAdapter,
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;
1044 #if CFG_TCP_IP_CHKSUM_OFFLOAD
1045 UINT_8 ucChksumFlag;
1049 ASSERT(ucPortIdx < 2);
1052 prTxCtrl = &prAdapter->rTxCtrl;
1053 u4ValidBufSize = prAdapter->u4CoalescingBufCachedSize;
1055 #if CFG_HIF_STATISTICS
1056 prTxCtrl->u4TotalTxAccessNum++;
1057 prTxCtrl->u4TotalTxPacketNum += prQue->u4NumElem;
1060 QUEUE_INITIALIZE(&rFreeQueue);
1062 if(prQue->u4NumElem > 0) {
1063 prMsduInfo = (P_MSDU_INFO_T)QUEUE_GET_HEAD(prQue);
1064 pucOutputBuf = prTxCtrl->pucTxCoalescingBufPtr;
1069 kalMemZero(&rHwTxHeader, sizeof(rHwTxHeader));
1071 prNativePacket = prMsduInfo->prPacket;
1073 ASSERT(prNativePacket);
1075 u4TxHdrSize = TX_HDR_SIZE;
1077 u2OverallBufferLength = ((prMsduInfo->u2FrameLength + TX_HDR_SIZE) &
1078 (UINT_16)HIF_TX_HDR_TX_BYTE_COUNT_MASK);
1080 rHwTxHeader.u2TxByteCount_UserPriority = u2OverallBufferLength;
1081 rHwTxHeader.u2TxByteCount_UserPriority |=
1082 ((UINT_16)prMsduInfo->ucUserPriority << HIF_TX_HDR_USER_PRIORITY_OFFSET);
1084 if (prMsduInfo->fgIs802_11) {
1085 ucEtherTypeOffsetInWord =
1086 (TX_HDR_SIZE + prMsduInfo->ucMacHeaderLength + prMsduInfo->ucLlcLength) >> 1;
1089 ucEtherTypeOffsetInWord =
1090 ((ETHER_HEADER_LEN - ETHER_TYPE_LEN) + TX_HDR_SIZE) >> 1;
1093 rHwTxHeader.ucEtherTypeOffset =
1094 ucEtherTypeOffsetInWord & HIF_TX_HDR_ETHER_TYPE_OFFSET_MASK;
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));
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);
1109 if (ucChksumFlag & TX_CS_IP_GEN) {
1110 rHwTxHeader.ucResource_PktType_CSflags |= (UINT_8)HIF_TX_HDR_IP_CSUM;
1113 if (ucChksumFlag & TX_CS_TCP_UDP_GEN) {
1114 rHwTxHeader.ucResource_PktType_CSflags |= (UINT_8)HIF_TX_HDR_TCP_CSUM;
1118 #endif /* CFG_TCP_IP_CHKSUM_OFFLOAD */
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);
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);
1133 rHwTxHeader.u2SeqNo = prMsduInfo->u2AclSN;
1135 if(prMsduInfo->pfTxDoneHandler) {
1136 rHwTxHeader.ucPacketSeqNo = prMsduInfo->ucTxSeqNum;
1137 rHwTxHeader.ucAck_BIP_BasicRate = HIF_TX_HDR_NEED_ACK;
1140 rHwTxHeader.ucPacketSeqNo = 0;
1141 rHwTxHeader.ucAck_BIP_BasicRate = 0;
1144 if(prMsduInfo->fgIsBIP) {
1145 rHwTxHeader.ucAck_BIP_BasicRate |= HIF_TX_HDR_BIP;
1148 if(prMsduInfo->fgIsBasicRate) {
1149 rHwTxHeader.ucAck_BIP_BasicRate |= HIF_TX_HDR_BASIC_RATE;
1152 #if CFG_ENABLE_PKT_LIFETIME_PROFILE
1153 if(prMsduInfo->rPktProfile.fgIsValid) {
1154 prMsduInfo->rPktProfile.rDequeueTimestamp = kalGetTimeTick();
1159 // attach to coalescing buffer
1160 kalMemCopy(pucOutputBuf + u4TotalLength, &rHwTxHeader, u4TxHdrSize);
1161 u4TotalLength += u4TxHdrSize;
1163 if (prMsduInfo->eSrc == TX_PACKET_OS
1164 || prMsduInfo->eSrc == TX_PACKET_FORWARDING) {
1165 kalCopyFrame(prAdapter->prGlueInfo,
1167 pucOutputBuf + u4TotalLength);
1169 else if(prMsduInfo->eSrc == TX_PACKET_MGMT) {
1170 kalMemCopy(pucOutputBuf + u4TotalLength,
1172 prMsduInfo->u2FrameLength);
1178 u4TotalLength += ALIGN_4(prMsduInfo->u2FrameLength);
1181 kalMemCopy(pucOutputBuf, &rHwTxHeader, u4TxHdrSize);
1183 /* Copy Frame Body */
1184 if (prMsduInfo->eSrc == TX_PACKET_OS
1185 || prMsduInfo->eSrc == TX_PACKET_FORWARDING) {
1186 kalCopyFrame(prAdapter->prGlueInfo,
1188 pucOutputBuf + u4TxHdrSize);
1190 else if(prMsduInfo->eSrc == TX_PACKET_MGMT) {
1191 kalMemCopy(pucOutputBuf + u4TxHdrSize,
1193 prMsduInfo->u2FrameLength);
1199 ASSERT(u2OverallBufferLength <= u4ValidBufSize);
1201 HAL_WRITE_TX_PORT(prAdapter,
1203 (UINT_32)u2OverallBufferLength,
1204 (PUINT_8)pucOutputBuf,
1209 prNextMsduInfo = (P_MSDU_INFO_T)
1210 QUEUE_GET_NEXT_ENTRY(&prMsduInfo->rQueEntry);
1212 if (prMsduInfo->eSrc == TX_PACKET_MGMT) {
1213 GLUE_DEC_REF_CNT(prTxCtrl->i4TxMgmtPendingNum);
1215 if (prMsduInfo->pfTxDoneHandler == NULL) {
1216 cnmMgtPktFree(prAdapter, prMsduInfo);
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);
1227 /* only free MSDU when it is not a MGMT frame */
1228 QUEUE_INSERT_TAIL(&rFreeQueue, (P_QUE_ENTRY_T)prMsduInfo);
1230 if (prMsduInfo->eSrc == TX_PACKET_OS) {
1231 kalSendComplete(prAdapter->prGlueInfo,
1233 WLAN_STATUS_SUCCESS);
1235 else if(prMsduInfo->eSrc == TX_PACKET_FORWARDING) {
1236 GLUE_DEC_REF_CNT(prTxCtrl->i4PendingFwdFrameCount);
1240 prMsduInfo = prNextMsduInfo;
1244 ASSERT(u4TotalLength <= u4ValidBufSize);
1246 #if CFG_DBG_GPIO_PINS
1248 /* Start port write */
1249 mtk_wcn_stp_debug_gpio_assert(IDX_TX_PORT_WRITE, DBG_TIE_LOW);
1251 mtk_wcn_stp_debug_gpio_assert(IDX_TX_PORT_WRITE, DBG_TIE_HIGH);
1255 // send coalescing buffer
1256 HAL_WRITE_TX_PORT(prAdapter,
1259 (PUINT_8)pucOutputBuf,
1263 #if CFG_ENABLE_PKT_LIFETIME_PROFILE
1264 nicTxReturnMsduInfoProfiling(prAdapter, (P_MSDU_INFO_T)QUEUE_GET_HEAD(&rFreeQueue));
1267 nicTxReturnMsduInfo(prAdapter, (P_MSDU_INFO_T)QUEUE_GET_HEAD(&rFreeQueue));
1271 return WLAN_STATUS_SUCCESS;
1275 /*----------------------------------------------------------------------------*/
1277 * \brief In this function, we'll write Command(CMD_INFO_T) into HIF.
1279 * @param prAdapter Pointer to the Adapter structure.
1280 * @param prPacketInfo Pointer of CMD_INFO_T
1281 * @param ucTC Specify the resource of TC
1283 * @retval WLAN_STATUS_SUCCESS Bus access ok.
1284 * @retval WLAN_STATUS_FAILURE Bus access fail.
1286 /*----------------------------------------------------------------------------*/
1289 IN P_ADAPTER_T prAdapter,
1290 IN P_CMD_INFO_T prCmdInfo,
1294 P_WIFI_CMD_T prWifiCmd;
1295 UINT_16 u2OverallBufferLength;
1296 PUINT_8 pucOutputBuf = (PUINT_8)NULL; /* Pointer to Transmit Data Structure Frame */
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;
1304 KAL_SPIN_LOCK_DECLARATION();
1310 prTxCtrl = &prAdapter->rTxCtrl;
1311 pucOutputBuf = prTxCtrl->pucTxCoalescingBufPtr;
1313 // <1> Assign Data Port
1314 if (ucTC != TC4_INDEX) {
1318 // Broadcast/multicast data frames, 1x frames, command packets, MMPDU
1322 if(prCmdInfo->eCmdType == COMMAND_TYPE_SECURITY_FRAME) {
1323 // <2> Compose HIF_TX_HEADER
1324 kalMemZero(&rHwTxHeader, sizeof(rHwTxHeader));
1326 prNativePacket = prCmdInfo->prPacket;
1328 ASSERT(prNativePacket);
1330 u2OverallBufferLength = TFCB_FRAME_PAD_TO_DW((prCmdInfo->u2InfoBufLen + TX_HDR_SIZE)
1331 & (UINT_16)HIF_TX_HDR_TX_BYTE_COUNT_MASK);
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;
1337 rHwTxHeader.ucEtherTypeOffset =
1338 ucEtherTypeOffsetInWord & HIF_TX_HDR_ETHER_TYPE_OFFSET_MASK;
1340 rHwTxHeader.ucResource_PktType_CSflags = (ucTC << HIF_TX_HDR_RESOURCE_OFFSET);
1342 rHwTxHeader.ucStaRecIdx = prCmdInfo->ucStaRecIndex;
1343 rHwTxHeader.ucForwardingType_SessionID_Reserved = HIF_TX_HDR_BURST_END_MASK;
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);
1350 rHwTxHeader.u2SeqNo = 0;
1351 rHwTxHeader.ucPacketSeqNo = 0;
1352 rHwTxHeader.ucAck_BIP_BasicRate = 0;
1354 // <2.3> Copy HIF TX HEADER
1355 kalMemCopy((PVOID)&pucOutputBuf[0], (PVOID)&rHwTxHeader, TX_HDR_SIZE);
1357 // <3> Copy Frame Body Copy
1358 kalCopyFrame(prAdapter->prGlueInfo,
1360 pucOutputBuf + TX_HDR_SIZE);
1362 else if(prCmdInfo->eCmdType == COMMAND_TYPE_MANAGEMENT_FRAME) {
1363 prMsduInfo = (P_MSDU_INFO_T)prCmdInfo->prPacket;
1365 ASSERT(prMsduInfo->fgIs802_11 == TRUE);
1366 ASSERT(prMsduInfo->eSrc == TX_PACKET_MGMT);
1368 // <2> Compose HIF_TX_HEADER
1369 kalMemZero(&rHwTxHeader, sizeof(rHwTxHeader));
1371 u2OverallBufferLength = ((prMsduInfo->u2FrameLength + TX_HDR_SIZE) &
1372 (UINT_16)HIF_TX_HDR_TX_BYTE_COUNT_MASK);
1374 rHwTxHeader.u2TxByteCount_UserPriority = u2OverallBufferLength;
1375 rHwTxHeader.u2TxByteCount_UserPriority |=
1376 ((UINT_16)prMsduInfo->ucUserPriority << HIF_TX_HDR_USER_PRIORITY_OFFSET);
1378 ucEtherTypeOffsetInWord =
1379 (TX_HDR_SIZE + prMsduInfo->ucMacHeaderLength + prMsduInfo->ucLlcLength) >> 1;
1381 rHwTxHeader.ucEtherTypeOffset =
1382 ucEtherTypeOffsetInWord & HIF_TX_HDR_ETHER_TYPE_OFFSET_MASK;
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));
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);
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);
1402 rHwTxHeader.u2SeqNo = prMsduInfo->u2AclSN;
1404 if(prMsduInfo->pfTxDoneHandler) {
1405 rHwTxHeader.ucPacketSeqNo = prMsduInfo->ucTxSeqNum;
1406 rHwTxHeader.ucAck_BIP_BasicRate = HIF_TX_HDR_NEED_ACK;
1409 rHwTxHeader.ucPacketSeqNo = 0;
1410 rHwTxHeader.ucAck_BIP_BasicRate = 0;
1413 if(prMsduInfo->fgIsBIP) {
1414 rHwTxHeader.ucAck_BIP_BasicRate |= HIF_TX_HDR_BIP;
1417 if(prMsduInfo->fgIsBasicRate) {
1418 rHwTxHeader.ucAck_BIP_BasicRate |= HIF_TX_HDR_BASIC_RATE;
1421 // <2.3> Copy HIF TX HEADER
1422 kalMemCopy((PVOID)&pucOutputBuf[0], (PVOID)&rHwTxHeader, TX_HDR_SIZE);
1424 // <3> Copy Frame Body
1425 kalMemCopy(pucOutputBuf + TX_HDR_SIZE,
1426 prMsduInfo->prPacket,
1427 prMsduInfo->u2FrameLength);
1429 // <4> Management Frame Post-Processing
1430 GLUE_DEC_REF_CNT(prTxCtrl->i4TxMgmtPendingNum);
1432 if (prMsduInfo->pfTxDoneHandler == NULL) {
1433 cnmMgtPktFree(prAdapter, prMsduInfo);
1437 DBGLOG(INIT, TRACE,("Wait Cmd TxSeqNum:%d\n", prMsduInfo->ucTxSeqNum));
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);
1445 prWifiCmd = (P_WIFI_CMD_T)prCmdInfo->pucInfoBuffer;
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);
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));
1457 // <3> Copy CMD Header to command buffer (by using pucCoalescingBufCached)
1458 kalMemCopy((PVOID)&pucOutputBuf[0],
1459 (PVOID)prCmdInfo->pucInfoBuffer,
1460 prCmdInfo->u2InfoBufLen);
1462 ASSERT(u2OverallBufferLength <= prAdapter->u4CoalescingBufCachedSize);
1465 // <4> Write frame to data port
1466 HAL_WRITE_TX_PORT(prAdapter,
1468 (UINT_32)u2OverallBufferLength,
1469 (PUINT_8)pucOutputBuf,
1470 (UINT_32)prAdapter->u4CoalescingBufCachedSize);
1472 return WLAN_STATUS_SUCCESS;
1473 } /* end of nicTxCmd() */
1476 /*----------------------------------------------------------------------------*/
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.
1481 * @param prAdapter Pointer to the Adapter structure.
1485 /*----------------------------------------------------------------------------*/
1488 IN P_ADAPTER_T prAdapter
1491 P_TX_CTRL_T prTxCtrl;
1492 P_MSDU_INFO_T prMsduInfo;
1494 KAL_SPIN_LOCK_DECLARATION();
1498 prTxCtrl = &prAdapter->rTxCtrl;
1500 nicTxFlush(prAdapter);
1502 // free MSDU_INFO_T from rTxMgmtMsduInfoList
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);
1509 // the packet must be mgmt frame with tx done callback
1510 ASSERT(prMsduInfo->eSrc == TX_PACKET_MGMT);
1511 ASSERT(prMsduInfo->pfTxDoneHandler != NULL);
1513 // invoke done handler
1514 prMsduInfo->pfTxDoneHandler(prAdapter, prMsduInfo, TX_RESULT_LIFE_TIMEOUT);
1516 cnmMgtPktFree(prAdapter, prMsduInfo);
1524 } /* end of nicTxRelease() */
1527 /*----------------------------------------------------------------------------*/
1529 * @brief Process the TX Done interrupt and pull in more pending frames in SW
1530 * Queues for transmission.
1532 * @param prAdapter Pointer to the Adapter structure.
1536 /*----------------------------------------------------------------------------*/
1538 nicProcessTxInterrupt(
1539 IN P_ADAPTER_T prAdapter
1542 P_TX_CTRL_T prTxCtrl;
1543 #if CFG_SDIO_INTR_ENHANCE
1544 P_SDIO_CTRL_T prSDIOCtrl;
1546 UINT_32 au4TxCount[2];
1547 #endif /* CFG_SDIO_INTR_ENHANCE */
1551 prTxCtrl = &prAdapter->rTxCtrl;
1554 /* Get the TX STATUS */
1555 #if CFG_SDIO_INTR_ENHANCE
1557 prSDIOCtrl = prAdapter->prSDIOCtrl;
1559 //dumpMemory8((PUINT_8)prSDIOCtrl, sizeof(SDIO_CTRL_T));
1562 nicTxReleaseResource(prAdapter, (PUINT_8)&prSDIOCtrl->rTxInfo);
1563 kalMemZero(&prSDIOCtrl->rTxInfo, sizeof(prSDIOCtrl->rTxInfo));
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]));
1571 nicTxReleaseResource(prAdapter, (PUINT_8)au4TxCount);
1573 #endif /* CFG_SDIO_INTR_ENHANCE */
1575 nicTxAdjustTcq(prAdapter);
1577 // Indicate Service Thread
1578 if(kalGetTxPendingCmdCount(prAdapter->prGlueInfo) > 0
1579 || wlanGetTxPendingFrameCount(prAdapter) > 0) {
1580 kalSetEvent(prAdapter->prGlueInfo);
1584 } /* end of nicProcessTxInterrupt() */
1587 /*----------------------------------------------------------------------------*/
1589 * @brief this function frees packet of P_MSDU_INFO_T linked-list
1591 * @param prAdapter Pointer to the Adapter structure.
1592 * @param prMsduInfoList a link list of P_MSDU_INFO_T
1596 /*----------------------------------------------------------------------------*/
1598 nicTxFreeMsduInfoPacket (
1599 IN P_ADAPTER_T prAdapter,
1600 IN P_MSDU_INFO_T prMsduInfoListHead
1603 P_NATIVE_PACKET prNativePacket;
1604 P_MSDU_INFO_T prMsduInfo = prMsduInfoListHead;
1605 P_TX_CTRL_T prTxCtrl;
1609 ASSERT(prMsduInfoListHead);
1611 prTxCtrl = &prAdapter->rTxCtrl;
1614 prNativePacket = prMsduInfo->prPacket;
1616 if(prMsduInfo->eSrc == TX_PACKET_OS) {
1617 kalSendComplete(prAdapter->prGlueInfo,
1619 WLAN_STATUS_FAILURE);
1621 else if(prMsduInfo->eSrc == TX_PACKET_MGMT) {
1622 if (prMsduInfo->pfTxDoneHandler) {
1623 prMsduInfo->pfTxDoneHandler(prAdapter, prMsduInfo, TX_RESULT_DROPPED_IN_DRIVER);
1625 cnmMemFree(prAdapter, prNativePacket);
1627 else if(prMsduInfo->eSrc == TX_PACKET_FORWARDING) {
1628 GLUE_DEC_REF_CNT(prTxCtrl->i4PendingFwdFrameCount);
1631 prMsduInfo = (P_MSDU_INFO_T)QUEUE_GET_NEXT_ENTRY((P_QUE_ENTRY_T)prMsduInfo);
1638 /*----------------------------------------------------------------------------*/
1640 * @brief this function returns P_MSDU_INFO_T of MsduInfoList to TxCtrl->rfreeMsduInfoList
1642 * @param prAdapter Pointer to the Adapter structure.
1643 * @param prMsduInfoList a link list of P_MSDU_INFO_T
1647 /*----------------------------------------------------------------------------*/
1649 nicTxReturnMsduInfo (
1650 IN P_ADAPTER_T prAdapter,
1651 IN P_MSDU_INFO_T prMsduInfoListHead
1654 P_TX_CTRL_T prTxCtrl;
1655 P_MSDU_INFO_T prMsduInfo = prMsduInfoListHead, prNextMsduInfo;
1657 KAL_SPIN_LOCK_DECLARATION();
1661 prTxCtrl = &prAdapter->rTxCtrl;
1665 prNextMsduInfo = (P_MSDU_INFO_T)QUEUE_GET_NEXT_ENTRY((P_QUE_ENTRY_T)prMsduInfo);
1667 switch(prMsduInfo->eSrc) {
1668 case TX_PACKET_FORWARDING:
1669 wlanReturnPacket(prAdapter, prMsduInfo->prPacket);
1672 case TX_PACKET_OS_OID:
1673 case TX_PACKET_MGMT:
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;
1689 /*----------------------------------------------------------------------------*/
1691 * @brief this function fills packet information to P_MSDU_INFO_T
1693 * @param prAdapter Pointer to the Adapter structure.
1694 * @param prMsduInfo P_MSDU_INFO_T
1695 * @param prPacket P_NATIVE_PACKET
1697 * @retval TRUE Success to extract information
1698 * @retval FALSE Fail to extract correct information
1700 /*----------------------------------------------------------------------------*/
1703 IN P_ADAPTER_T prAdapter,
1704 IN P_MSDU_INFO_T prMsduInfo,
1705 IN P_NATIVE_PACKET prPacket
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;
1716 UINT_8 ucNetworkType;
1721 prGlueInfo = prAdapter->prGlueInfo;
1724 if (kalQoSFrameClassifierAndPacketInfo(prGlueInfo,
1731 &ucNetworkType) == FALSE) {
1735 #if CFG_ENABLE_PKT_LIFETIME_PROFILE
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;
1742 UINT_8 ucRtpSnOffset = 30;
1743 UINT_32 u4RtpSrcPort = 15550;
1746 prPktProfile->fgIsValid = FALSE;
1748 aucLookAheadBuf = prSkb->data;
1750 u2EtherTypeLen = (aucLookAheadBuf[ETH_TYPE_LEN_OFFSET] << 8) | (aucLookAheadBuf[ETH_TYPE_LEN_OFFSET + 1]);
1752 if ((u2EtherTypeLen == ETH_P_IP) &&
1753 (u4PacketLen >= LOOK_AHEAD_LEN)) {
1754 PUINT_8 pucIpHdr = &aucLookAheadBuf[ETH_HLEN];
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) {
1761 /* Enable packet lifetime profiling */
1762 prPktProfile->fgIsValid = TRUE;
1764 prPktProfile->fgIsPrinted = FALSE;
1767 prPktProfile->u2RtpSn = pucIpHdr[ucRtpSnOffset] << 8 | pucIpHdr[ucRtpSnOffset + 1];
1770 prPktProfile->u2IpSn = pucIpHdr[IPV4_HDR_IP_IDENTIFICATION_OFFSET] << 8 |
1771 pucIpHdr[IPV4_HDR_IP_IDENTIFICATION_OFFSET + 1];
1773 /* Packet arrival time at kernel Hard Xmit */
1774 prPktProfile->rHardXmitArrivalTimestamp = GLUE_GET_PKT_ARRIVAL_TIME(prPacket);
1776 /* Packet enqueue time */
1777 prPktProfile->rEnqueueTimestamp = (OS_SYSTIME)kalGetTimeTick();
1784 /* Save the value of Priority Parameter */
1785 GLUE_SET_PKT_TID(prPacket, ucPriorityParam);
1788 GLUE_SET_PKT_FLAG_1X(prPacket);
1792 GLUE_SET_PKT_FLAG_PAL(prPacket);
1795 ucMacHeaderLen = ETH_HLEN;
1797 /* Save the value of Header Length */
1798 GLUE_SET_PKT_HEADER_LEN(prPacket, ucMacHeaderLen);
1800 /* Save the value of Frame Length */
1801 GLUE_SET_PKT_FRAME_LEN(prPacket, (UINT_16)u4PacketLen);
1803 /* Save the value of Arrival Time*/
1804 u4SysTime = (OS_SYSTIME)kalGetTimeTick();
1805 GLUE_SET_PKT_ARRIVAL_TIME(prPacket, u4SysTime);
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);
1820 /*----------------------------------------------------------------------------*/
1822 * @brief this function update TCQ values by passing current status to txAdjustTcQuotas
1824 * @param prAdapter Pointer to the Adapter structure.
1826 * @retval WLAN_STATUS_SUCCESS Updated successfully
1828 /*----------------------------------------------------------------------------*/
1831 IN P_ADAPTER_T prAdapter
1835 TX_TCQ_ADJUST_T rTcqAdjust;
1836 P_TX_CTRL_T prTxCtrl;
1837 KAL_SPIN_LOCK_DECLARATION();
1841 prTxCtrl = &prAdapter->rTxCtrl;
1844 qmAdjustTcQuotas(prAdapter, &rTcqAdjust, &prTxCtrl->rTc);
1845 KAL_ACQUIRE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_RESOURCE);
1847 for (u4Num = 0 ; u4Num < TC_NUM ; u4Num++) {
1848 prTxCtrl->rTc.aucFreeBufferCount[u4Num] += rTcqAdjust.acVariation[u4Num];
1849 prTxCtrl->rTc.aucMaxNumOfBuffer[u4Num] += rTcqAdjust.acVariation[u4Num];
1851 ASSERT(prTxCtrl->rTc.aucFreeBufferCount[u4Num] >= 0);
1852 ASSERT(prTxCtrl->rTc.aucMaxNumOfBuffer[u4Num] >= 0);
1855 KAL_RELEASE_SPIN_LOCK(prAdapter, SPIN_LOCK_TX_RESOURCE);
1857 return WLAN_STATUS_SUCCESS;
1861 /*----------------------------------------------------------------------------*/
1863 * @brief this function flushes all packets queued in STA/AC queue
1865 * @param prAdapter Pointer to the Adapter structure.
1867 * @retval WLAN_STATUS_SUCCESS Flushed successfully
1869 /*----------------------------------------------------------------------------*/
1873 IN P_ADAPTER_T prAdapter
1876 P_MSDU_INFO_T prMsduInfo;
1877 KAL_SPIN_LOCK_DECLARATION();
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);
1886 if(prMsduInfo != NULL) {
1887 nicTxFreeMsduInfoPacket(prAdapter, prMsduInfo);
1888 nicTxReturnMsduInfo(prAdapter, prMsduInfo);
1891 return WLAN_STATUS_SUCCESS;
1895 #if CFG_ENABLE_FW_DOWNLOAD
1896 /*----------------------------------------------------------------------------*/
1898 * \brief In this function, we'll write Command(CMD_INFO_T) into HIF.
1899 * However this function is used for INIT_CMD.
1901 * In order to avoid further maintainance issues, these 2 functions are separated
1903 * @param prAdapter Pointer to the Adapter structure.
1904 * @param prPacketInfo Pointer of CMD_INFO_T
1905 * @param ucTC Specify the resource of TC
1907 * @retval WLAN_STATUS_SUCCESS Bus access ok.
1908 * @retval WLAN_STATUS_FAILURE Bus access fail.
1910 /*----------------------------------------------------------------------------*/
1913 IN P_ADAPTER_T prAdapter,
1914 IN P_CMD_INFO_T prCmdInfo,
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 */
1922 P_TX_CTRL_T prTxCtrl;
1926 ASSERT(ucTC == TC0_INDEX);
1928 prTxCtrl = &prAdapter->rTxCtrl;
1929 pucOutputBuf = prTxCtrl->pucTxCoalescingBufPtr;
1930 prInitTxHeader = (P_INIT_HIF_TX_HEADER_T)prCmdInfo->pucInfoBuffer;
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);
1936 prInitTxHeader->u2TxByteCount = u2OverallBufferLength;
1937 prInitTxHeader->ucEtherTypeOffset = 0;
1938 prInitTxHeader->ucCSflags = 0;
1940 // <2> Assign Data Port
1941 if (ucTC != TC4_INDEX) {
1944 else { // Broadcast/multicast data packets
1948 // <3> Copy CMD Header to command buffer (by using pucCoalescingBufCached)
1949 kalMemCopy((PVOID)&pucOutputBuf[0],
1950 (PVOID)prCmdInfo->pucInfoBuffer,
1951 prCmdInfo->u2InfoBufLen);
1953 ASSERT(u2OverallBufferLength <= prAdapter->u4CoalescingBufCachedSize);
1955 // <4> Write frame to data port
1956 HAL_WRITE_TX_PORT(prAdapter,
1958 (UINT_32)u2OverallBufferLength,
1959 (PUINT_8)pucOutputBuf,
1960 (UINT_32)prAdapter->u4CoalescingBufCachedSize);
1962 return WLAN_STATUS_SUCCESS;
1966 /*----------------------------------------------------------------------------*/
1968 * \brief In this function, we'll reset TX resource counter to initial value used
1969 * in F/W download state
1971 * @param prAdapter Pointer to the Adapter structure.
1973 * @retval WLAN_STATUS_SUCCESS Reset is done successfully.
1975 /*----------------------------------------------------------------------------*/
1977 nicTxInitResetResource (
1978 IN P_ADAPTER_T prAdapter
1981 P_TX_CTRL_T prTxCtrl;
1983 DEBUGFUNC("nicTxInitResetResource");
1986 prTxCtrl = &prAdapter->rTxCtrl;
1988 prTxCtrl->rTc.aucMaxNumOfBuffer[TC0_INDEX] = NIC_TX_INIT_BUFF_COUNT_TC0;
1989 prTxCtrl->rTc.aucFreeBufferCount[TC0_INDEX] = NIC_TX_INIT_BUFF_COUNT_TC0;
1991 prTxCtrl->rTc.aucMaxNumOfBuffer[TC1_INDEX] = NIC_TX_INIT_BUFF_COUNT_TC1;
1992 prTxCtrl->rTc.aucFreeBufferCount[TC1_INDEX] = NIC_TX_INIT_BUFF_COUNT_TC1;
1994 prTxCtrl->rTc.aucMaxNumOfBuffer[TC2_INDEX] = NIC_TX_INIT_BUFF_COUNT_TC2;
1995 prTxCtrl->rTc.aucFreeBufferCount[TC2_INDEX] = NIC_TX_INIT_BUFF_COUNT_TC2;
1997 prTxCtrl->rTc.aucMaxNumOfBuffer[TC3_INDEX] = NIC_TX_INIT_BUFF_COUNT_TC3;
1998 prTxCtrl->rTc.aucFreeBufferCount[TC3_INDEX] = NIC_TX_INIT_BUFF_COUNT_TC3;
2000 prTxCtrl->rTc.aucMaxNumOfBuffer[TC4_INDEX] = NIC_TX_INIT_BUFF_COUNT_TC4;
2001 prTxCtrl->rTc.aucFreeBufferCount[TC4_INDEX] = NIC_TX_INIT_BUFF_COUNT_TC4;
2003 prTxCtrl->rTc.aucMaxNumOfBuffer[TC5_INDEX] = NIC_TX_INIT_BUFF_COUNT_TC5;
2004 prTxCtrl->rTc.aucFreeBufferCount[TC5_INDEX] = NIC_TX_INIT_BUFF_COUNT_TC5;
2006 return WLAN_STATUS_SUCCESS;
2013 /*----------------------------------------------------------------------------*/
2015 * \brief this function enqueues MSDU_INFO_T into queue management,
2018 * @param prAdapter Pointer to the Adapter structure.
2019 * prMsduInfo Pointer to MSDU
2021 * @retval WLAN_STATUS_SUCCESS Reset is done successfully.
2023 /*----------------------------------------------------------------------------*/
2026 IN P_ADAPTER_T prAdapter,
2027 IN P_MSDU_INFO_T prMsduInfo
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();
2040 prTxCtrl = &prAdapter->rTxCtrl;
2043 QUEUE_INITIALIZE(&qDataPort0);
2044 QUEUE_INITIALIZE(&qDataPort1);
2046 /* check how many management frame are being queued */
2048 prNextMsduInfo = (P_MSDU_INFO_T)QUEUE_GET_NEXT_ENTRY((P_QUE_ENTRY_T)prMsduInfo);
2050 QUEUE_GET_NEXT_ENTRY((P_QUE_ENTRY_T)prMsduInfo) = NULL;
2052 if(prMsduInfo->eSrc == TX_PACKET_MGMT) {
2053 // MMPDU: force stick to TC4
2054 prMsduInfo->ucTC = TC4_INDEX;
2056 QUEUE_INSERT_TAIL(&qDataPort1, (P_QUE_ENTRY_T)prMsduInfo);
2059 QUEUE_INSERT_TAIL(&qDataPort0, (P_QUE_ENTRY_T)prMsduInfo);
2062 prMsduInfo = prNextMsduInfo;
2065 if(qDataPort0.u4NumElem) {
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);
2072 /* post-process for dropped packets */
2073 if(prRetMsduInfo != NULL) { // unable to enqueue
2074 nicTxFreeMsduInfoPacket(prAdapter, prRetMsduInfo);
2075 nicTxReturnMsduInfo(prAdapter, prRetMsduInfo);
2079 if(qDataPort1.u4NumElem) {
2080 prMsduInfoHead = (P_MSDU_INFO_T)QUEUE_GET_HEAD(&qDataPort1);
2082 if(qDataPort1.u4NumElem > nicTxGetFreeCmdCount(prAdapter)) {
2083 // not enough descriptors for sending
2084 u4Status = WLAN_STATUS_FAILURE;
2087 while(prMsduInfoHead) {
2088 prNextMsduInfo = (P_MSDU_INFO_T) QUEUE_GET_NEXT_ENTRY(&prMsduInfoHead->rQueEntry);
2090 if (prMsduInfoHead->pfTxDoneHandler != NULL) {
2091 prMsduInfoHead->pfTxDoneHandler(prAdapter, prMsduInfoHead, TX_RESULT_DROPPED_IN_DRIVER);
2095 cnmMgtPktFree(prAdapter, prMsduInfoHead);
2097 prMsduInfoHead = prNextMsduInfo;
2101 /* send to command queue */
2102 while(prMsduInfoHead) {
2103 prNextMsduInfo = (P_MSDU_INFO_T) QUEUE_GET_NEXT_ENTRY(&prMsduInfoHead->rQueEntry);
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);
2110 GLUE_INC_REF_CNT(prTxCtrl->i4TxMgmtPendingNum);
2112 kalMemZero(prCmdInfo, sizeof(CMD_INFO_T));
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;
2126 kalEnqueueCommand(prAdapter->prGlueInfo, (P_QUE_ENTRY_T)prCmdInfo);
2129 /* Cmd free count is larger than expected, but allocation fail. */
2132 u4Status = WLAN_STATUS_FAILURE;
2133 cnmMgtPktFree(prAdapter, prMsduInfoHead);
2136 prMsduInfoHead = prNextMsduInfo;
2141 /* indicate service thread for sending */
2142 if(prTxCtrl->i4TxMgmtPendingNum > 0
2143 || kalGetTxPendingFrameCount(prAdapter->prGlueInfo) > 0) {
2144 kalSetEvent(prAdapter->prGlueInfo);
2151 /*----------------------------------------------------------------------------*/
2153 * \brief this function returns available count in command queue
2155 * @param prAdapter Pointer to the Adapter structure.
2159 /*----------------------------------------------------------------------------*/
2161 nicTxGetFreeCmdCount (
2162 IN P_ADAPTER_T prAdapter
2167 return prAdapter->rFreeCmdList.u4NumElem;