2 ** $Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/nic/que_mgt.c#1 $
6 \brief TX/RX queues management
8 The main tasks of queue management include TC-based HIF TX flow control,
9 adaptive TC quota adjustment, HIF TX grant scheduling, Power-Save
10 forwarding control, RX packet reordering, and RX BA agreement management.
18 ** 04 11 2013 yuche.tsai
19 ** [ALPS00542142] [Pre-SQC][6627][W]use wifi direct press cancel connect, phone all stop.
20 ** Drop the probe response packet when absent.
22 ** 04 09 2013 yuche.tsai
23 ** [ALPS00542142] [Pre-SQC][6627][W]use wifi direct press cancel connect, phone all stop.
24 ** Fix CMD buffer short issue.
26 ** 04 09 2013 yuche.tsai
27 ** [ALPS00542142] [Pre-SQC][6627][W]use wifi direct press cancel connect, phone all stop.
28 ** Fix CMD buffer short issue.
32 * Sync CFG80211 modification from branch 2,2.
34 * 02 23 2012 eddie.chen
35 * [WCXRP00001194] [MT6620][DRV/FW] follow admission control bit to change the enqueue rule
36 * Change the enqueue policy when ACM = 1.
38 * 11 22 2011 yuche.tsai
40 * Code refine, remove one #if 0 code.
42 * 11 19 2011 eddie.chen
43 * [WCXRP00001096] [MT6620 Wi-Fi][Driver/FW] Enhance the log function (xlog)
46 * 11 18 2011 yuche.tsai
48 * CONFIG P2P support RSSI query, default turned off.
50 * 11 18 2011 eddie.chen
51 * [WCXRP00001096] [MT6620 Wi-Fi][Driver/FW] Enhance the log function (xlog)
52 * Fix xlog format to hex format
54 * 11 17 2011 tsaiyuan.hsu
55 * [WCXRP00001115] [MT6620 Wi-Fi][DRV] avoid deactivating staRec when changing state 3 to 3.
56 * avoid deactivating staRec when changing state from 3 to 3.
58 * 11 11 2011 tsaiyuan.hsu
59 * [WCXRP00001083] [MT6620 Wi-Fi][DRV]] dump debug counter or frames when debugging is triggered
60 * add debug msg for xlog.
62 * 11 11 2011 tsaiyuan.hsu
63 * [WCXRP00001083] [MT6620 Wi-Fi][DRV]] dump debug counter or frames when debugging is triggered
64 * add debug counters of bb and ar for xlog.
66 * 11 10 2011 eddie.chen
67 * [WCXRP00001096] [MT6620 Wi-Fi][Driver/FW] Enhance the log function (xlog)
68 * Use short name for xlog.
70 * 11 10 2011 eddie.chen
71 * [WCXRP00001096] [MT6620 Wi-Fi][Driver/FW] Enhance the log function (xlog)
72 * Modify the QM xlog level and remove LOG_FUNC.
74 * 11 10 2011 chinglan.wang
76 * [WiFi WPS]Can't switch to new AP via WPS PBC when there existing a connection to another AP.
78 * 11 09 2011 chinglan.wang
80 * [WiFi direct]Can't make P2P connect via PBC.
82 * 11 08 2011 eddie.chen
83 * [WCXRP00001096] [MT6620 Wi-Fi][Driver/FW] Enhance the log function (xlog)
86 * 11 07 2011 tsaiyuan.hsu
87 * [WCXRP00001083] [MT6620 Wi-Fi][DRV]] dump debug counter or frames when debugging is triggered
88 * add debug counters and periodically dump counters for debugging.
90 * 11 01 2011 chinglan.wang
92 * Modify the Wi-Fi method of the flush TX queue when disconnect the AP.
93 * If disconnect the AP and flush all the data frame in the TX queue, WPS cannot do the 4-way handshake to connect to the AP..
96 * [WCXRP00001059] [MT6620 Wi-Fi][Driver][P2P] Fixed sometimes data (1x) will not indicate to upper layer due ba check un-expect
97 * let the Rx BA accept even the sta not valid.
99 * 09 28 2011 tsaiyuan.hsu
100 * [WCXRP00000900] [MT5931 Wi-Fi] Improve balance of TX and RX
101 * enlarge window size only by 4.
103 * 09 01 2011 tsaiyuan.hsu
104 * [WCXRP00000900] [MT5931 Wi-Fi] Improve balance of TX and RX
105 * set rx window size as twice buffer size.
107 * 08 23 2011 yuche.tsai
109 * Fix multicast address list issue.
111 * 08 03 2011 tsaiyuan.hsu
112 * [WCXRP00000900] [MT5931 Wi-Fi] Improve balance of TX and RX
113 * force window size at least 16.
115 * 08 02 2011 yuche.tsai
116 * [WCXRP00000896] [Volunteer Patch][WiFi Direct][Driver] GO with multiple client, TX deauth to a disconnecting device issue.
117 * Fix GO send deauth frame issue.
119 * 07 26 2011 eddie.chen
120 * [WCXRP00000874] [MT5931][DRV] API for query the RX reorder queued packets counter
121 * API for query the RX reorder queued packets counter.
123 * 07 07 2011 eddie.chen
124 * [WCXRP00000834] [MT6620 Wi-Fi][DRV] Send 1x packet when peer STA is in PS.
125 * Add setEvent when free quota is updated.
127 * 07 05 2011 eddie.chen
128 * [WCXRP00000834] [MT6620 Wi-Fi][DRV] Send 1x packet when peer STA is in PS.
129 * Send 1x when peer STA is in PS.
131 * 05 31 2011 eddie.chen
132 * [WCXRP00000753] [MT5931 Wi-Fi][DRV] Adjust QM for MT5931
133 * Fix the QM quota in MT5931.
135 * 05 11 2011 eddie.chen
136 * [WCXRP00000709] [MT6620 Wi-Fi][Driver] Check free number before copying broadcast packet
137 * Fix dest type when GO packet copying.
139 * 05 09 2011 yuche.tsai
140 * [WCXRP00000712] [Volunteer Patch][MT6620][Driver] Sending deauth issue when Hot spot is disabled. (GO is dissolved)
141 * Deauthentication frame is not bound to network active status.
143 * 05 09 2011 eddie.chen
144 * [WCXRP00000709] [MT6620 Wi-Fi][Driver] Check free number before copying broadcast packet
145 * Check free number before copying broadcast packet.
147 * 04 14 2011 eddie.chen
148 * [WCXRP00000603] [MT6620 Wi-Fi][DRV] Fix Klocwork warning
149 * Check the SW RFB free. Fix the compile warning..
151 * 04 12 2011 eddie.chen
152 * [WCXRP00000617] [MT6620 Wi-Fi][DRV/FW] Fix for sigma
153 * Fix the sta index in processing security frame
154 * Simple flow control for TC4 to avoid mgt frames for PS STA to occupy the TC4
157 * 04 11 2011 yuche.tsai
158 * [WCXRP00000627] [Volunteer Patch][MT6620][Driver] Pending MMPUD of P2P Network may crash system issue.
159 * Fix kernel panic issue when MMPDU of P2P is pending in driver.
161 * 04 08 2011 eddie.chen
162 * [WCXRP00000617] [MT6620 Wi-Fi][DRV/FW] Fix for sigma
165 * 03 28 2011 eddie.chen
166 * [WCXRP00000603] [MT6620 Wi-Fi][DRV] Fix Klocwork warning
167 * Fix Klockwork warning.
169 * 03 28 2011 eddie.chen
170 * [WCXRP00000602] [MT6620 Wi-Fi][DRV] Fix wmm parameters in beacon for BOW
171 * Fix wmm parameters in beacon for BOW.
173 * 03 15 2011 eddie.chen
174 * [WCXRP00000554] [MT6620 Wi-Fi][DRV] Add sw control debug counter
175 * Add sw debug counter for QM.
177 * 02 23 2011 eddie.chen
178 * [WCXRP00000463] [MT6620 Wi-Fi][FW/Driver][Hotspot] Cannot update WMM PS STA's partital bitmap
179 * Fix parsing WMM INFO and bmp delivery bitmap definition.
181 * 02 17 2011 eddie.chen
182 * [WCXRP00000458] [MT6620 Wi-Fi][Driver] BOW Concurrent - ProbeResp was exist in other channel
183 * 1) Chnage GetFrameAction decision when BSS is absent.
184 * 2) Check channel and resource in processing ProbeRequest
186 * 02 08 2011 eddie.chen
187 * [WCXRP00000426] [MT6620 Wi-Fi][FW/Driver] Add STA aging timeout and defualtHwRatein AP mode
188 * Add event STA agint timeout
190 * 01 27 2011 tsaiyuan.hsu
191 * [WCXRP00000392] [MT6620 Wi-Fi][Driver] Add Roaming Support
193 * 1. not support 11r, only use strength of signal to determine roaming.
194 * 2. not enable CFG_SUPPORT_ROAMING until completion of full test.
195 * 3. in 6620, adopt work-around to avoid sign extension problem of cck of hw
196 * 4. assume that change of link quality in smooth way.
198 * 01 25 2011 yuche.tsai
199 * [WCXRP00000388] [Volunteer Patch][MT6620][Driver/Fw] change Station Type in station record.
200 * Change Station Type in Station Record, Modify MACRO definition for getting station type & network type index & Role.
202 * 01 24 2011 eddie.chen
203 * [WCXRP00000385] [MT6620 Wi-Fi][DRV] Add destination decision for forwarding packets
206 * 01 24 2011 eddie.chen
207 * [WCXRP00000385] [MT6620 Wi-Fi][DRV] Add destination decision for forwarding packets
208 * Add destination decision in AP mode.
211 * [WCXRP00000099] [MT6620 Wi-Fi] [Driver] workaround to let the de-authentication can be send out[WCXRP00000326] [MT6620][Wi-Fi][Driver] check in the binary format gl_sec.o.new instead of use change type!!!
212 * Allow 802.1x can be send even the net is not active due the drver / fw sync issue.
214 * 01 13 2011 eddie.chen
215 * [WCXRP00000322] Add WMM IE in beacon,
216 Add per station flow control when STA is in PS
217 * Fix typo and compile error.
219 * 01 12 2011 eddie.chen
220 * [WCXRP00000322] Add WMM IE in beacon,
221 Add per station flow control when STA is in PS
222 * Fix WMM parameter condition for STA
224 * 01 12 2011 eddie.chen
225 * [WCXRP00000322] Add WMM IE in beacon,
226 Add per station flow control when STA is in PS
227 * 1) Check Bss if support QoS before adding WMMIE
228 * 2) Check if support prAdapter->rWifiVar QoS and uapsd in flow control
230 * 01 12 2011 george.huang
231 * [WCXRP00000355] [MT6620 Wi-Fi] Set WMM-PS related setting with qualifying AP capability
232 * Update MQM for WMM IE generation method
234 * 01 11 2011 eddie.chen
235 * [WCXRP00000322] Add WMM IE in beacon,
236 Add per station flow control when STA is in PS
238 * Add per STA flow control when STA is in PS mode
240 * 01 03 2011 george.huang
241 * [WCXRP00000152] [MT6620 Wi-Fi] AP mode power saving function
242 * update prStaRec->fgIsUapsdSupported flag.
244 * 12 29 2010 eddie.chen
245 * [WCXRP00000322] Add WMM IE in beacon,
246 Add per station flow control when STA is in PS
248 * Add WMM parameter for broadcast.
250 * 12 29 2010 eddie.chen
251 * [WCXRP00000322] Add WMM IE in beacon,
252 Add per station flow control when STA is in PS
254 * 1) PS flow control event
256 * 2) WMM IE in beacon, assoc resp, probe resp
258 * 12 23 2010 george.huang
259 * [WCXRP00000152] [MT6620 Wi-Fi] AP mode power saving function
260 * 1. update WMM IE parsing, with ASSOC REQ handling
261 * 2. extend U-APSD parameter passing from driver to FW
264 * [WCXRP00000099] [MT6620 Wi-Fi] [Driver] workaround to let the de-authentication can be send out
265 * use the #14 and modify the add code for check MMPDU.
268 * [WCXRP00000099] [MT6620 Wi-Fi] [Driver] workaround to let the de-authentication can be send out
269 * only MMPDU not check the netActive flag.
272 * [WCXRP00000099] [MT6620 Wi-Fi] [Driver] workaround to let the de-authentication can be send out
273 * not check the netActive flag for mgmt .
276 * [WCXRP00000077] [MT6620 Wi-Fi][Driver][FW] Eliminate use of ENUM_NETWORK_TYPE_T and replaced by ENUM_NETWORK_TYPE_INDEX_T only
277 * remove ENUM_NETWORK_TYPE_T definitions
279 * 09 21 2010 kevin.huang
280 * [WCXRP00000052] [MT6620 Wi-Fi][Driver] Eliminate Linux Compile Warning
281 * Eliminate Linux Compile Warning
283 * 08 30 2010 yarco.yang
285 * Fixed klockwork error message
287 * 08 18 2010 yarco.yang
289 * 1. Fixed HW checksum offload function not work under Linux issue.
290 * 2. Add debug message.
292 * 08 10 2010 yarco.yang
296 * 08 06 2010 yarco.yang
298 * Update qmGetFrameAction() to allow P2P MGMT frame w/o STA_Record still can perform TX action
302 * AIS-FSM FIX: return channel privilege even when the privilege is not granted yet
303 * QM: qmGetFrameAction() won't assert when corresponding STA-REC index is not found
305 * 07 20 2010 yarco.yang
307 * Add to SetEvent when BSS is from Absent to Present or STA from PS to Awake
309 * 07 16 2010 yarco.yang
311 * 1. Support BSS Absence/Presence Event
312 * 2. Support STA change PS mode Event
313 * 3. Support BMC forwarding for AP mode.
315 * 07 14 2010 yarco.yang
317 * 1. Remove CFG_MQM_MIGRATION
318 * 2. Add CMD_UPDATE_WMM_PARMS command
320 * 07 13 2010 yarco.yang
323 * [MT6620 and MT5931] SW Migration, add qmGetFrameAction() API for CMD Queue Processing
325 * 07 09 2010 yarco.yang
327 * [MT6620 and MT5931] SW Migration: Add ADDBA support
331 * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository.
333 * 07 08 2010 yarco.yang
334 * [WPD00003837][MT6620]Data Path Refine
337 * 07 06 2010 yarco.yang
338 * [WPD00003837][MT6620]Data Path Refine
339 * Use fgInUse instead of fgIsValid for De-queue judgement
341 * 07 06 2010 yarco.yang
342 * [WPD00003837][MT6620]Data Path Refine
343 * For MMPDU, STA_REC will be decided by caller module
345 * 07 06 2010 yarco.yang
346 * [WPD00003837][MT6620]Data Path Refine
347 * Add MGMT Packet type for HIF_TX_HEADER
349 * 06 29 2010 yarco.yang
350 * [WPD00003837][MT6620]Data Path Refine
351 * replace g_rQM with Adpater->rQM
354 * [WPD00003833][MT6620 and MT5931] Driver migration
355 * add API in que_mgt to retrieve sta-rec index for security frames.
357 * 06 23 2010 yarco.yang
358 * [WPD00003837][MT6620]Data Path Refine
359 * Merge g_arStaRec[] into adapter->arStaRec[]
361 * 06 21 2010 yarco.yang
362 * [WPD00003837][MT6620]Data Path Refine
363 * Support CFG_MQM_MIGRATION flag
366 * [WPD00003833][MT6620 and MT5931] Driver migration
367 * 1) migrate assoc.c.
368 * 2) add ucTxSeqNum for tracking frames which needs TX-DONE awareness
369 * 3) add configuration options for CNM_MEM and RSN modules
370 * 4) add data path for management frames
371 * 5) eliminate rPacketInfo of MSDU_INFO_T
373 * 06 06 2010 kevin.huang
374 * [WPD00003832][MT6620 5931] Create driver base
375 * [MT6620 5931] Create driver base
377 * 03 31 2010 tehuang.liu
378 * [WPD00001943]Create WiFi test driver framework on WinXP
379 * Refined the debug msg
382 * [WPD00001943]Create WiFi test driver framework on WinXP
383 * comment out one assertion which refer to undefined data member.
385 * 03 30 2010 tehuang.liu
386 * [WPD00001943]Create WiFi test driver framework on WinXP
387 * Enabled adaptive TC resource control
389 * 03 24 2010 jeffrey.chang
390 * [WPD00003826]Initial import for Linux port
391 * initial import for Linux port
393 * 03 17 2010 tehuang.liu
394 * [WPD00001943]Create WiFi test driver framework on WinXP
395 * Changed STA_REC index determination rules (DA=BMCAST always --> STA_REC_INDEX_BMCAST)
397 * 03 11 2010 tehuang.liu
398 * [WPD00001943]Create WiFi test driver framework on WinXP
399 * Fixed buffer leak when processing BAR frames
401 * 03 02 2010 tehuang.liu
402 * [WPD00001943]Create WiFi test driver framework on WinXP
403 * For TX packets with STA_REC index = STA_REC_INDEX_NOT_FOUND, use TC5
405 * 03 01 2010 tehuang.liu
406 * [WPD00001943]Create WiFi test driver framework on WinXP
407 * Fixed STA_REC index determination bug (fgIsValid shall be checked)
409 * 02 25 2010 tehuang.liu
410 * [WPD00001943]Create WiFi test driver framework on WinXP
411 * Refined function qmDetermineStaRecIndex() for BMCAST packets
413 * 02 25 2010 tehuang.liu
414 * [WPD00001943]Create WiFi test driver framework on WinXP
415 * Enabled multi-STA TX path with fairness
417 * 02 24 2010 tehuang.liu
418 * [WPD00001943]Create WiFi test driver framework on WinXP
419 * Enabled dynamically activating and deactivating STA_RECs
421 * 02 24 2010 tehuang.liu
422 * [WPD00001943]Create WiFi test driver framework on WinXP
423 * Added code for dynamic activating and deactivating STA_RECs.
425 * 01 13 2010 tehuang.liu
426 * [WPD00001943]Create WiFi test driver framework on WinXP
427 * Enabled the 802.1x path
429 * 01 13 2010 tehuang.liu
430 * [WPD00001943]Create WiFi test driver framework on WinXP
431 * Enabled the Burst_End Indication mechanism
432 ** \main\maintrunk.MT6620WiFiDriver_Prj\13 2009-12-14 15:01:37 GMT MTK02468
433 ** Fixed casting for qmAddRxBaEntry()
434 ** \main\maintrunk.MT6620WiFiDriver_Prj\12 2009-12-10 16:51:03 GMT mtk02752
435 ** remove SD1_SD3.. flag
436 ** \main\maintrunk.MT6620WiFiDriver_Prj\11 2009-12-09 14:07:25 GMT MTK02468
437 ** Added RX buffer reordering functions
438 ** \main\maintrunk.MT6620WiFiDriver_Prj\10 2009-12-04 13:34:16 GMT MTK02468
439 ** Modified Flush Queue function to let queues be reinitialized
440 ** \main\maintrunk.MT6620WiFiDriver_Prj\9 2009-12-04 13:18:25 GMT MTK02468
441 ** Added flushing per-Type queues code
442 ** \main\maintrunk.MT6620WiFiDriver_Prj\8 2009-12-02 23:39:49 GMT MTK02468
443 ** Added Debug msgs and fixed incorrect assert
444 ** \main\maintrunk.MT6620WiFiDriver_Prj\4 2009-11-26 23:50:27 GMT MTK02468
445 ** Bug fixing (qmDequeueTxPackets local variable initialization)
446 ** \main\maintrunk.MT6620WiFiDriver_Prj\3 2009-11-26 09:39:25 GMT mtk02752
447 ** correct and surpress PREfast warning
448 ** \main\maintrunk.MT6620WiFiDriver_Prj\2 2009-11-23 22:10:55 GMT mtk02468
449 ** Used SD1_SD3_DATAPATH_INTEGRATION
450 ** \main\maintrunk.MT6620WiFiDriver_Prj\1 2009-11-23 22:02:30 GMT mtk02468
455 /*******************************************************************************
456 * C O M P I L E R F L A G S
457 ********************************************************************************
460 /*******************************************************************************
461 * E X T E R N A L R E F E R E N C E S
462 ********************************************************************************
466 /*******************************************************************************
468 ********************************************************************************
471 /*******************************************************************************
473 ********************************************************************************
476 /*******************************************************************************
477 * P U B L I C D A T A
478 ********************************************************************************
480 OS_SYSTIME g_arMissTimeout
[CFG_STA_REC_NUM
][CFG_RX_MAX_BA_TID_NUM
];
482 /*******************************************************************************
483 * P R I V A T E D A T A
484 ********************************************************************************
488 /*******************************************************************************
490 ********************************************************************************
493 /*******************************************************************************
494 * F U N C T I O N D E C L A R A T I O N S
495 ********************************************************************************
498 qmDetermineStaRecIndex(
499 IN P_ADAPTER_T prAdapter
,
500 IN P_MSDU_INFO_T prMsduInfo
504 qmDequeueTxPacketsFromPerStaQueues(
505 IN P_ADAPTER_T prAdapter
,
508 IN UINT_8 ucCurrentAvailableQuota
,
509 IN UINT_8 ucTotalQuota
513 qmDequeueTxPacketsFromPerTypeQueues(
514 IN P_ADAPTER_T prAdapter
,
520 /*******************************************************************************
522 ********************************************************************************
525 /*----------------------------------------------------------------------------*/
527 * \brief Init Queue Managment for TX
533 /*----------------------------------------------------------------------------*/
536 IN P_ADAPTER_T prAdapter
539 UINT_32 u4QueArrayIdx
;
542 P_QUE_MGT_T prQM
= &prAdapter
->rQM
;
544 //DbgPrint("QM: Enter qmInit()\n");
546 prAdapter
->rWifiVar
.fgSupportQoS
= TRUE
;
548 prAdapter
->rWifiVar
.fgSupportQoS
= FALSE
;
551 #if CFG_SUPPORT_AMPDU_RX
552 prAdapter
->rWifiVar
.fgSupportAmpduRx
= TRUE
;
554 prAdapter
->rWifiVar
.fgSupportAmpduRx
= FALSE
;
557 #if CFG_SUPPORT_AMPDU_TX
558 prAdapter
->rWifiVar
.fgSupportAmpduTx
= TRUE
;
560 prAdapter
->rWifiVar
.fgSupportAmpduTx
= FALSE
;
563 #if CFG_SUPPORT_TSPEC
564 prAdapter
->rWifiVar
.fgSupportTspec
= TRUE
;
566 prAdapter
->rWifiVar
.fgSupportTspec
= FALSE
;
569 #if CFG_SUPPORT_UAPSD
570 prAdapter
->rWifiVar
.fgSupportUAPSD
= TRUE
;
572 prAdapter
->rWifiVar
.fgSupportUAPSD
= FALSE
;
575 #if CFG_SUPPORT_UL_PSMP
576 prAdapter
->rWifiVar
.fgSupportULPSMP
= TRUE
;
578 prAdapter
->rWifiVar
.fgSupportULPSMP
= FALSE
;
581 #if CFG_SUPPORT_RX_SGI
582 prAdapter
->rWifiVar
.u8SupportRxSgi20
= 0;
583 prAdapter
->rWifiVar
.u8SupportRxSgi40
= 0;
585 prAdapter
->rWifiVar
.u8SupportRxSgi20
= 2;
586 prAdapter
->rWifiVar
.u8SupportRxSgi40
= 2;
589 #if CFG_SUPPORT_RX_HT_GF
590 prAdapter
->rWifiVar
.u8SupportRxGf
= 0;
592 prAdapter
->rWifiVar
.u8SupportRxGf
= 2;
596 //4 <2> Initialize other TX queues (queues not in STA_RECs)
597 for(u4QueArrayIdx
= 0; u4QueArrayIdx
< NUM_OF_PER_TYPE_TX_QUEUES
; u4QueArrayIdx
++){
598 QUEUE_INITIALIZE(&(prQM
->arTxQueue
[u4QueArrayIdx
]));
601 //4 <3> Initialize the RX BA table and RX queues
602 /* Initialize the RX Reordering Parameters and Queues */
603 for(u4QueArrayIdx
= 0; u4QueArrayIdx
< CFG_NUM_OF_RX_BA_AGREEMENTS
; u4QueArrayIdx
++){
604 prQM
->arRxBaTable
[u4QueArrayIdx
].fgIsValid
= FALSE
;
605 QUEUE_INITIALIZE(&(prQM
->arRxBaTable
[u4QueArrayIdx
].rReOrderQue
));
606 prQM
->arRxBaTable
[u4QueArrayIdx
].u2WinStart
= 0xFFFF;
607 prQM
->arRxBaTable
[u4QueArrayIdx
].u2WinEnd
= 0xFFFF;
609 prQM
->arRxBaTable
[u4QueArrayIdx
].fgIsWaitingForPktWithSsn
= FALSE
;
612 prQM
->ucRxBaCount
= 0;
614 kalMemSet(&g_arMissTimeout
, 0, sizeof(g_arMissTimeout
));
616 #if QM_ADAPTIVE_TC_RESOURCE_CTRL
617 //4 <4> Initialize TC resource control variables
618 for(i
= 0; i
< TC_NUM
; i
++){
619 prQM
->au4AverageQueLen
[i
] = 0;
621 prQM
->u4TimeToAdjustTcResource
= QM_INIT_TIME_TO_ADJUST_TC_RSC
;
622 prQM
->u4TimeToUpdateQueLen
= QM_INIT_TIME_TO_UPDATE_QUE_LEN
;
623 prQM
->u4TxNumOfVi
= 0;
624 prQM
->u4TxNumOfVo
= 0;
626 // ASSERT(prQM->u4TimeToAdjust && prQM->u4TimeToUpdateQueLen);
629 prQM
->au4CurrentTcResource
[TC0_INDEX
] = NIC_TX_BUFF_COUNT_TC0
;
630 prQM
->au4CurrentTcResource
[TC1_INDEX
] = NIC_TX_BUFF_COUNT_TC1
;
631 prQM
->au4CurrentTcResource
[TC2_INDEX
] = NIC_TX_BUFF_COUNT_TC2
;
632 prQM
->au4CurrentTcResource
[TC3_INDEX
] = NIC_TX_BUFF_COUNT_TC3
;
633 prQM
->au4CurrentTcResource
[TC4_INDEX
] = NIC_TX_BUFF_COUNT_TC4
; /* Not adjustable (TX port 1)*/
634 prQM
->au4CurrentTcResource
[TC5_INDEX
] = NIC_TX_BUFF_COUNT_TC5
;
637 prQM
->au4MinReservedTcResource
[TC0_INDEX
] = QM_MIN_RESERVED_TC0_RESOURCE
;
638 prQM
->au4MinReservedTcResource
[TC1_INDEX
] = QM_MIN_RESERVED_TC1_RESOURCE
;
639 prQM
->au4MinReservedTcResource
[TC2_INDEX
] = QM_MIN_RESERVED_TC2_RESOURCE
;
640 prQM
->au4MinReservedTcResource
[TC3_INDEX
] = QM_MIN_RESERVED_TC3_RESOURCE
;
641 prQM
->au4MinReservedTcResource
[TC4_INDEX
] = QM_MIN_RESERVED_TC4_RESOURCE
; /* Not adjustable (TX port 1)*/
642 prQM
->au4MinReservedTcResource
[TC5_INDEX
] = QM_MIN_RESERVED_TC5_RESOURCE
;
645 prQM
->au4GuaranteedTcResource
[TC0_INDEX
] = QM_GUARANTEED_TC0_RESOURCE
;
646 prQM
->au4GuaranteedTcResource
[TC1_INDEX
] = QM_GUARANTEED_TC1_RESOURCE
;
647 prQM
->au4GuaranteedTcResource
[TC2_INDEX
] = QM_GUARANTEED_TC2_RESOURCE
;
648 prQM
->au4GuaranteedTcResource
[TC3_INDEX
] = QM_GUARANTEED_TC3_RESOURCE
;
649 prQM
->au4GuaranteedTcResource
[TC4_INDEX
] = QM_GUARANTEED_TC4_RESOURCE
;
650 prQM
->au4GuaranteedTcResource
[TC5_INDEX
] = QM_GUARANTEED_TC5_RESOURCE
;
652 prQM
->fgTcResourcePostAnnealing
= FALSE
;
654 ASSERT(QM_INITIAL_RESIDUAL_TC_RESOURCE
< 64);
658 prQM
->u4PktCount
= 0;
660 #if QM_TEST_FAIR_FORWARDING
662 prQM
->u4CurrentStaRecIndexToEnqueue
= 0;
664 UINT_8 aucMacAddr
[MAC_ADDR_LEN
];
665 P_STA_RECORD_T prStaRec
;
667 /* Irrelevant in case this STA is an AIS AP (see qmDetermineStaRecIndex()) */
668 aucMacAddr
[0] = 0x11;
669 aucMacAddr
[1] = 0x22;
670 aucMacAddr
[2] = 0xAA;
671 aucMacAddr
[3] = 0xBB;
672 aucMacAddr
[4] = 0xCC;
673 aucMacAddr
[5] = 0xDD;
675 prStaRec
= &prAdapter
->arStaRec
[1];
678 prStaRec
->fgIsValid
= TRUE
;
679 prStaRec
->fgIsQoS
= TRUE
;
680 prStaRec
->fgIsInPS
= FALSE
;
681 prStaRec
->ucPsSessionID
= 0xFF;
682 prStaRec
->ucNetTypeIndex
= NETWORK_TYPE_AIS_INDEX
;
683 prStaRec
->fgIsAp
= TRUE
;
684 COPY_MAC_ADDR((prStaRec
)->aucMacAddr
,aucMacAddr
);
692 #if QM_FORWARDING_FAIRNESS
695 for (i
=0; i
< NUM_OF_PER_STA_TX_QUEUES
; i
++){
696 prQM
->au4ForwardCount
[i
] = 0;
697 prQM
->au4HeadStaRecIndex
[i
] = 0;
702 #if QM_TC_RESOURCE_EMPTY_COUNTER
703 kalMemZero(prQM
->au4QmTcResourceEmptyCounter
, sizeof(prQM
->au4QmTcResourceEmptyCounter
));
711 IN P_ADAPTER_T prAdapter
714 P_QUE_MGT_T prQM
= &prAdapter
->rQM
;
716 DbgPrint("QM: ** TEST MODE **\n");
718 if(QM_TEST_STA_REC_DETERMINATION
){
719 if(prAdapter
->arStaRec
[0].fgIsValid
){
720 prAdapter
->arStaRec
[0].fgIsValid
= FALSE
;
721 DbgPrint("QM: (Test) Deactivate STA_REC[0]\n");
724 prAdapter
->arStaRec
[0].fgIsValid
= TRUE
;
725 DbgPrint("QM: (Test) Activate STA_REC[0]\n");
729 if(QM_TEST_STA_REC_DEACTIVATION
){
730 /* Note that QM_STA_REC_HARD_CODING shall be set to 1 for this test */
732 if(prAdapter
->arStaRec
[0].fgIsValid
){
734 DbgPrint("QM: (Test) Deactivate STA_REC[0]\n");
735 qmDeactivateStaRec(prAdapter
,0);
739 UINT_8 aucMacAddr
[MAC_ADDR_LEN
];
741 /* Irrelevant in case this STA is an AIS AP (see qmDetermineStaRecIndex()) */
742 aucMacAddr
[0] = 0x11;
743 aucMacAddr
[1] = 0x22;
744 aucMacAddr
[2] = 0xAA;
745 aucMacAddr
[3] = 0xBB;
746 aucMacAddr
[4] = 0xCC;
747 aucMacAddr
[5] = 0xDD;
749 DbgPrint("QM: (Test) Activate STA_REC[0]\n");
751 prAdapter
, /* Adapter pointer */
752 0, /* STA_REC index from FW */
754 NETWORK_TYPE_AIS_INDEX
, /* Network type */
756 aucMacAddr
/* MAC address */
761 if(QM_TEST_FAIR_FORWARDING
){
762 if(prAdapter
->arStaRec
[1].fgIsValid
){
763 prQM
->u4CurrentStaRecIndexToEnqueue
++;
764 prQM
->u4CurrentStaRecIndexToEnqueue
%= 2;
765 DbgPrint("QM: (Test) Switch to STA_REC[%u]\n", prQM
->u4CurrentStaRecIndexToEnqueue
);
772 /*----------------------------------------------------------------------------*/
774 * \brief Activate a STA_REC
776 * \param[in] prAdapter Pointer to the Adapter instance
777 * \param[in] u4StaRecIdx The index of the STA_REC
778 * \param[in] fgIsQoS Set to TRUE if this is a QoS STA
779 * \param[in] pucMacAddr The MAC address of the STA
783 /*----------------------------------------------------------------------------*/
786 IN P_ADAPTER_T prAdapter
,
787 IN P_STA_RECORD_T prStaRec
791 //4 <1> Deactivate first
794 if(prStaRec
->fgIsValid
){ /* The STA_REC has been activated */
795 DBGLOG(QM
, WARN
, ("QM: (WARNING) Activating a STA_REC which has been activated \n"));
796 DBGLOG(QM
, WARN
, ("QM: (WARNING) Deactivating a STA_REC before re-activating \n"));
797 qmDeactivateStaRec(prAdapter
, prStaRec
->ucIndex
); // To flush TX/RX queues and del RX BA agreements
800 //4 <2> Activate the STA_REC
801 /* Init the STA_REC */
802 prStaRec
->fgIsValid
= TRUE
;
803 prStaRec
->fgIsInPS
= FALSE
;
804 prStaRec
->ucPsSessionID
= 0xFF;
805 prStaRec
->fgIsAp
= (IS_AP_STA(prStaRec
)) ? TRUE
: FALSE
;;
807 /* Done in qmInit() or qmDeactivateStaRec() */
809 /* At the beginning, no RX BA agreements have been established */
810 for(i
=0; i
<CFG_RX_MAX_BA_TID_NUM
; i
++){
811 (prStaRec
->aprRxReorderParamRefTbl
)[i
] = NULL
;
815 DBGLOG(QM
, INFO
, ("QM: +STA[%u]\n",
816 (UINT_32
)prStaRec
->ucIndex
));
819 /*----------------------------------------------------------------------------*/
821 * \brief Deactivate a STA_REC
823 * \param[in] prAdapter Pointer to the Adapter instance
824 * \param[in] u4StaRecIdx The index of the STA_REC
828 /*----------------------------------------------------------------------------*/
831 IN P_ADAPTER_T prAdapter
,
832 IN UINT_32 u4StaRecIdx
835 P_STA_RECORD_T prStaRec
;
837 P_MSDU_INFO_T prFlushedTxPacketList
= NULL
;
839 ASSERT(u4StaRecIdx
< CFG_NUM_OF_STA_RECORD
);
841 prStaRec
= &prAdapter
->arStaRec
[u4StaRecIdx
];
844 //4<1> Flush TX queues
845 prFlushedTxPacketList
= qmFlushStaTxQueues(prAdapter
, u4StaRecIdx
);
847 if(prFlushedTxPacketList
){
848 wlanProcessQueuedMsduInfo(prAdapter
, prFlushedTxPacketList
);
851 //4 <2> Flush RX queues and delete RX BA agreements
852 for(i
=0; i
< CFG_RX_MAX_BA_TID_NUM
; i
++){
853 /* Delete the RX BA entry with TID = i */
854 qmDelRxBaEntry(prAdapter
, (UINT_8
)u4StaRecIdx
, (UINT_8
)i
, FALSE
);
857 //4 <3> Deactivate the STA_REC
858 prStaRec
->fgIsValid
= FALSE
;
859 prStaRec
->fgIsInPS
= FALSE
;
861 //To reduce printk for IOT sta to connect all the time,
862 //DBGLOG(QM, INFO, ("QM: -STA[%ld]\n", u4StaRecIdx));
866 /*----------------------------------------------------------------------------*/
868 * \brief Deactivate a STA_REC
870 * \param[in] prAdapter Pointer to the Adapter instance
871 * \param[in] u4StaRecIdx The index of the network
875 /*----------------------------------------------------------------------------*/
879 IN P_ADAPTER_T prAdapter
,
880 IN ENUM_NETWORK_TYPE_INDEX_T eNetworkTypeIdx
886 QUE_T rNeedToFreeQue
;
888 P_QUE_T prNeedToFreeQue
;
890 P_MSDU_INFO_T prMsduInfo
;
893 prQM
= &prAdapter
->rQM
;
894 prQue
= &prQM
->arTxQueue
[TX_QUEUE_INDEX_BMCAST
];
896 QUEUE_INITIALIZE(&rNeedToFreeQue
);
897 QUEUE_INITIALIZE(&rTempQue
);
899 prNeedToFreeQue
= &rNeedToFreeQue
;
900 prTempQue
= &rTempQue
;
902 QUEUE_MOVE_ALL(prTempQue
, prQue
);
904 QUEUE_REMOVE_HEAD(prTempQue
, prMsduInfo
, P_MSDU_INFO_T
);
907 if(prMsduInfo
->ucNetworkType
== eNetworkTypeIdx
) {
908 QUEUE_INSERT_TAIL(prNeedToFreeQue
, (P_QUE_ENTRY_T
)prMsduInfo
);
911 QUEUE_INSERT_TAIL(prQue
, (P_QUE_ENTRY_T
)prMsduInfo
);
914 QUEUE_REMOVE_HEAD(prTempQue
, prMsduInfo
, P_MSDU_INFO_T
);
916 if(QUEUE_IS_NOT_EMPTY(prNeedToFreeQue
)) {
917 wlanProcessQueuedMsduInfo(prAdapter
, (P_MSDU_INFO_T
)QUEUE_GET_HEAD(prNeedToFreeQue
));
922 /*----------------------------------------------------------------------------*/
924 * \brief Flush all TX queues
928 * \return The flushed packets (in a list of MSDU_INFOs)
930 /*----------------------------------------------------------------------------*/
933 IN P_ADAPTER_T prAdapter
936 UINT_8 ucStaArrayIdx
;
937 UINT_8 ucQueArrayIdx
;
939 P_MSDU_INFO_T prMsduInfoListHead
;
940 P_MSDU_INFO_T prMsduInfoListTail
;
942 P_QUE_MGT_T prQM
= &prAdapter
->rQM
;
944 DBGLOG(QM
, TRACE
, ("QM: Enter qmFlushTxQueues()\n"));
946 prMsduInfoListHead
= NULL
;
947 prMsduInfoListTail
= NULL
;
949 /* Concatenate all MSDU_INFOs in per-STA queues */
950 for(ucStaArrayIdx
= 0; ucStaArrayIdx
< CFG_NUM_OF_STA_RECORD
; ucStaArrayIdx
++){
952 /* Always check each STA_REC when flushing packets no matter it is inactive or active */
954 if(!prAdapter
->arStaRec
[ucStaArrayIdx
].fgIsValid
){
955 continue; /* Continue to check the next STA_REC */
959 for(ucQueArrayIdx
= 0; ucQueArrayIdx
< NUM_OF_PER_STA_TX_QUEUES
; ucQueArrayIdx
++){
960 if(QUEUE_IS_EMPTY(&(prAdapter
->arStaRec
[ucStaArrayIdx
].arTxQueue
[ucQueArrayIdx
]))){
961 continue; /* Continue to check the next TX queue of the same STA */
964 if(!prMsduInfoListHead
){
966 /* The first MSDU_INFO is found */
967 prMsduInfoListHead
=(P_MSDU_INFO_T
)
968 QUEUE_GET_HEAD(&prAdapter
->arStaRec
[ucStaArrayIdx
].arTxQueue
[ucQueArrayIdx
]);
969 prMsduInfoListTail
=(P_MSDU_INFO_T
)
970 QUEUE_GET_TAIL(&prAdapter
->arStaRec
[ucStaArrayIdx
].arTxQueue
[ucQueArrayIdx
]);
973 /* Concatenate the MSDU_INFO list with the existing list */
974 QM_TX_SET_NEXT_MSDU_INFO(prMsduInfoListTail
,
975 QUEUE_GET_HEAD(&prAdapter
->arStaRec
[ucStaArrayIdx
].arTxQueue
[ucQueArrayIdx
]));
977 prMsduInfoListTail
= (P_MSDU_INFO_T
)
978 QUEUE_GET_TAIL(&prAdapter
->arStaRec
[ucStaArrayIdx
].arTxQueue
[ucQueArrayIdx
]);
981 QUEUE_INITIALIZE(&prAdapter
->arStaRec
[ucStaArrayIdx
].arTxQueue
[ucQueArrayIdx
]);
985 /* Flush per-Type queues */
986 for(ucQueArrayIdx
= 0; ucQueArrayIdx
< NUM_OF_PER_TYPE_TX_QUEUES
; ucQueArrayIdx
++){
988 if(QUEUE_IS_EMPTY(&(prQM
->arTxQueue
[ucQueArrayIdx
]))){
989 continue; /* Continue to check the next TX queue of the same STA */
992 if(!prMsduInfoListHead
){
994 /* The first MSDU_INFO is found */
995 prMsduInfoListHead
=(P_MSDU_INFO_T
)
996 QUEUE_GET_HEAD(&prQM
->arTxQueue
[ucQueArrayIdx
]);
997 prMsduInfoListTail
=(P_MSDU_INFO_T
)
998 QUEUE_GET_TAIL(&prQM
->arTxQueue
[ucQueArrayIdx
]);
1001 /* Concatenate the MSDU_INFO list with the existing list */
1002 QM_TX_SET_NEXT_MSDU_INFO(prMsduInfoListTail
,
1003 QUEUE_GET_HEAD(&prQM
->arTxQueue
[ucQueArrayIdx
]));
1005 prMsduInfoListTail
= (P_MSDU_INFO_T
)
1006 QUEUE_GET_TAIL(&prQM
->arTxQueue
[ucQueArrayIdx
]);
1009 QUEUE_INITIALIZE(&prQM
->arTxQueue
[ucQueArrayIdx
]);
1013 if(prMsduInfoListTail
){
1014 /* Terminate the MSDU_INFO list with a NULL pointer */
1015 QM_TX_SET_NEXT_MSDU_INFO(prMsduInfoListTail
, NULL
);
1018 return prMsduInfoListHead
;
1022 /*----------------------------------------------------------------------------*/
1024 * \brief Flush TX packets for a particular STA
1026 * \param[in] u4StaRecIdx STA_REC index
1028 * \return The flushed packets (in a list of MSDU_INFOs)
1030 /*----------------------------------------------------------------------------*/
1033 IN P_ADAPTER_T prAdapter
,
1034 IN UINT_32 u4StaRecIdx
1037 UINT_8 ucQueArrayIdx
;
1038 P_MSDU_INFO_T prMsduInfoListHead
;
1039 P_MSDU_INFO_T prMsduInfoListTail
;
1040 P_STA_RECORD_T prStaRec
;
1042 //To reduce printk for IOT sta to connect all the time,
1043 //DBGLOG(QM, TRACE, ("QM: Enter qmFlushStaTxQueues(%ld)\n", u4StaRecIdx));
1045 ASSERT(u4StaRecIdx
< CFG_NUM_OF_STA_RECORD
);
1047 prMsduInfoListHead
= NULL
;
1048 prMsduInfoListTail
= NULL
;
1050 prStaRec
= &prAdapter
->arStaRec
[u4StaRecIdx
];
1053 /* No matter whether this is an activated STA_REC, do flush */
1055 if(!prStaRec
->fgIsValid
){
1060 /* Concatenate all MSDU_INFOs in TX queues of this STA_REC */
1061 for(ucQueArrayIdx
= 0; ucQueArrayIdx
< NUM_OF_PER_STA_TX_QUEUES
; ucQueArrayIdx
++){
1062 if(QUEUE_IS_EMPTY(&(prStaRec
->arTxQueue
[ucQueArrayIdx
]))){
1066 if(!prMsduInfoListHead
){
1067 /* The first MSDU_INFO is found */
1068 prMsduInfoListHead
=(P_MSDU_INFO_T
)
1069 QUEUE_GET_HEAD(&prStaRec
->arTxQueue
[ucQueArrayIdx
]);
1070 prMsduInfoListTail
=(P_MSDU_INFO_T
)
1071 QUEUE_GET_TAIL(&prStaRec
->arTxQueue
[ucQueArrayIdx
]); }
1073 /* Concatenate the MSDU_INFO list with the existing list */
1074 QM_TX_SET_NEXT_MSDU_INFO(prMsduInfoListTail
,
1075 QUEUE_GET_HEAD(&prStaRec
->arTxQueue
[ucQueArrayIdx
]));
1077 prMsduInfoListTail
=
1078 (P_MSDU_INFO_T
)QUEUE_GET_TAIL(&prStaRec
->arTxQueue
[ucQueArrayIdx
]);
1081 QUEUE_INITIALIZE(&prStaRec
->arTxQueue
[ucQueArrayIdx
]);
1086 if(prMsduInfoListTail
){
1087 /* Terminate the MSDU_INFO list with a NULL pointer */
1088 QM_TX_SET_NEXT_MSDU_INFO(prMsduInfoListTail
, nicGetPendingStaMMPDU(prAdapter
, (UINT_8
)u4StaRecIdx
));
1091 prMsduInfoListHead
= nicGetPendingStaMMPDU(prAdapter
, (UINT_8
)u4StaRecIdx
);
1095 return prMsduInfoListHead
;
1099 /*----------------------------------------------------------------------------*/
1101 * \brief Flush RX packets
1105 * \return The flushed packets (in a list of SW_RFBs)
1107 /*----------------------------------------------------------------------------*/
1110 IN P_ADAPTER_T prAdapter
1114 P_SW_RFB_T prSwRfbListHead
;
1115 P_SW_RFB_T prSwRfbListTail
;
1116 P_QUE_MGT_T prQM
= &prAdapter
->rQM
;
1118 prSwRfbListHead
= prSwRfbListTail
= NULL
;
1120 DBGLOG(QM
, TRACE
, ("QM: Enter qmFlushRxQueues()\n"));
1122 for(i
=0; i
<CFG_NUM_OF_RX_BA_AGREEMENTS
; i
++){
1123 if(QUEUE_IS_NOT_EMPTY(&(prQM
->arRxBaTable
[i
].rReOrderQue
))){
1124 if(!prSwRfbListHead
){
1126 /* The first MSDU_INFO is found */
1127 prSwRfbListHead
=(P_SW_RFB_T
)
1128 QUEUE_GET_HEAD(&(prQM
->arRxBaTable
[i
].rReOrderQue
));
1129 prSwRfbListTail
=(P_SW_RFB_T
)
1130 QUEUE_GET_TAIL(&(prQM
->arRxBaTable
[i
].rReOrderQue
));
1133 /* Concatenate the MSDU_INFO list with the existing list */
1134 QM_TX_SET_NEXT_MSDU_INFO(prSwRfbListTail
,
1135 QUEUE_GET_HEAD(&(prQM
->arRxBaTable
[i
].rReOrderQue
)));
1137 prSwRfbListTail
= (P_SW_RFB_T
)
1138 QUEUE_GET_TAIL(&(prQM
->arRxBaTable
[i
].rReOrderQue
));
1141 QUEUE_INITIALIZE(&(prQM
->arRxBaTable
[i
].rReOrderQue
));
1149 if(prSwRfbListTail
){
1150 /* Terminate the MSDU_INFO list with a NULL pointer */
1151 QM_TX_SET_NEXT_SW_RFB(prSwRfbListTail
, NULL
);
1153 return prSwRfbListHead
;
1158 /*----------------------------------------------------------------------------*/
1160 * \brief Flush RX packets with respect to a particular STA
1162 * \param[in] u4StaRecIdx STA_REC index
1163 * \param[in] u4Tid TID
1165 * \return The flushed packets (in a list of SW_RFBs)
1167 /*----------------------------------------------------------------------------*/
1170 IN P_ADAPTER_T prAdapter
,
1171 IN UINT_32 u4StaRecIdx
,
1176 P_SW_RFB_T prSwRfbListHead
;
1177 P_SW_RFB_T prSwRfbListTail
;
1178 P_RX_BA_ENTRY_T prReorderQueParm
;
1179 P_STA_RECORD_T prStaRec
;
1181 DBGLOG(QM
, TRACE
, ("QM: Enter qmFlushStaRxQueues(%u)\n", u4StaRecIdx
));
1183 prSwRfbListHead
= prSwRfbListTail
= NULL
;
1185 prStaRec
= &prAdapter
->arStaRec
[u4StaRecIdx
];
1188 /* No matter whether this is an activated STA_REC, do flush */
1190 if(!prStaRec
->fgIsValid
){
1195 /* Obtain the RX BA Entry pointer */
1196 prReorderQueParm
= ((prStaRec
->aprRxReorderParamRefTbl
)[u4Tid
]);
1198 /* Note: For each queued packet, prCurrSwRfb->eDst equals RX_PKT_DESTINATION_HOST */
1199 if(prReorderQueParm
){
1201 if(QUEUE_IS_NOT_EMPTY(&(prReorderQueParm
->rReOrderQue
))){
1203 prSwRfbListHead
=(P_SW_RFB_T
)
1204 QUEUE_GET_HEAD(&(prReorderQueParm
->rReOrderQue
));
1205 prSwRfbListTail
=(P_SW_RFB_T
)
1206 QUEUE_GET_TAIL(&(prReorderQueParm
->rReOrderQue
));
1209 QUEUE_INITIALIZE(&(prReorderQueParm
->rReOrderQue
));
1214 if(prSwRfbListTail
){
1215 /* Terminate the MSDU_INFO list with a NULL pointer */
1216 QM_TX_SET_NEXT_SW_RFB(prSwRfbListTail
, NULL
);
1218 return prSwRfbListHead
;
1224 /*----------------------------------------------------------------------------*/
1226 * \brief Enqueue TX packets
1228 * \param[in] prMsduInfoListHead Pointer to the list of TX packets
1230 * \return The freed packets, which are not enqueued
1232 /*----------------------------------------------------------------------------*/
1235 IN P_ADAPTER_T prAdapter
,
1236 IN P_MSDU_INFO_T prMsduInfoListHead
1239 P_MSDU_INFO_T prMsduInfoReleaseList
;
1240 P_MSDU_INFO_T prCurrentMsduInfo
;
1241 P_MSDU_INFO_T prNextMsduInfo
;
1243 P_STA_RECORD_T prStaRec
;
1245 QUE_T rNotEnqueuedQue
;
1248 UINT_8 ucPacketType
;
1250 P_QUE_MGT_T prQM
= &prAdapter
->rQM
;
1251 UINT_8 aucNextUP
[WMM_AC_INDEX_NUM
] = { 1 /* BEtoBK*/, 1 /*na*/, 0/*VItoBE*/ , 4 /*VOtoVI*/};
1253 DBGLOG(QM
, LOUD
, ("Enter qmEnqueueTxPackets\n"));
1255 ASSERT(prMsduInfoListHead
);
1257 #if QM_ADAPTIVE_TC_RESOURCE_CTRL
1260 //4 <0> Update TC resource control related variables
1261 /* Keep track of the queue length */
1262 if (--prQM
->u4TimeToUpdateQueLen
== 0){ /* -- only here */
1263 prQM
->u4TimeToUpdateQueLen
= QM_INIT_TIME_TO_UPDATE_QUE_LEN
;
1264 qmUpdateAverageTxQueLen(prAdapter
);
1269 /* Push TX packets into STA_REC (for UNICAST) or prAdapter->rQM (for BMCAST) */
1271 prMsduInfoReleaseList
= NULL
;
1272 prCurrentMsduInfo
= NULL
;
1273 QUEUE_INITIALIZE(&rNotEnqueuedQue
);
1274 prNextMsduInfo
= prMsduInfoListHead
;
1277 P_BSS_INFO_T prBssInfo
;
1278 BOOLEAN fgCheckACMAgain
;
1279 ENUM_WMM_ACI_T eAci
= WMM_AC_BE_INDEX
;
1280 prCurrentMsduInfo
= prNextMsduInfo
;
1281 prNextMsduInfo
= QM_TX_GET_NEXT_MSDU_INFO(prCurrentMsduInfo
);
1284 //4 <1> Lookup the STA_REC index
1285 /* The ucStaRecIndex will be set in this function */
1286 qmDetermineStaRecIndex(prAdapter
, prCurrentMsduInfo
);
1287 ucPacketType
= HIF_TX_PACKET_TYPE_DATA
;
1289 STATS_ENV_REPORT_DETECT(prAdapter
, prCurrentMsduInfo
->ucStaRecIndex
);
1291 DBGLOG(QM
, LOUD
, ("***** ucStaRecIndex = %d *****\n",
1292 prCurrentMsduInfo
->ucStaRecIndex
));
1295 prBssInfo
= &(prAdapter
->rWifiVar
.arBssInfo
[prCurrentMsduInfo
->ucNetworkType
]);
1297 #if (CONF_HIF_LOOPBACK_AUTO == 0)
1298 if(IS_NET_ACTIVE(prAdapter
, prCurrentMsduInfo
->ucNetworkType
)) {
1300 /* force to send the loopback test packet */
1302 SET_NET_ACTIVE(prAdapter
, prCurrentMsduInfo
->ucNetworkType
);
1303 prCurrentMsduInfo
->ucStaRecIndex
= STA_REC_INDEX_BMCAST
;
1304 ucPacketType
= HIF_TX_PKT_TYPE_HIF_LOOPBACK
;
1305 #endif /* End of CONF_HIF_LOOPBACK_AUTO */
1307 switch (prCurrentMsduInfo
->ucStaRecIndex
){
1308 case STA_REC_INDEX_BMCAST
:
1309 prTxQue
= &prQM
->arTxQueue
[TX_QUEUE_INDEX_BMCAST
];
1312 if(prCurrentMsduInfo
->ucNetworkType
== NETWORK_TYPE_P2P_INDEX
1313 && prCurrentMsduInfo
->eSrc
!= TX_PACKET_MGMT
1315 if(LINK_IS_EMPTY(&prAdapter
->rWifiVar
.arBssInfo
[NETWORK_TYPE_P2P_INDEX
].rStaRecOfClientList
)) {
1316 prTxQue
= &rNotEnqueuedQue
;
1317 TX_INC_CNT(&prAdapter
->rTxCtrl
,TX_AP_BORADCAST_DROP
);
1322 QM_DBG_CNT_INC(prQM
, QM_DBG_CNT_23
);
1325 case STA_REC_INDEX_NOT_FOUND
:
1328 if(prCurrentMsduInfo
->eSrc
== TX_PACKET_FORWARDING
) {
1330 /* if the packet is the forward type. the packet should be freed */
1331 DBGLOG(QM
, TRACE
, ("Forwarding packet but Sta is STA_REC_INDEX_NOT_FOUND\n"));
1332 //prTxQue = &rNotEnqueuedQue;
1334 prTxQue
= &prQM
->arTxQueue
[TX_QUEUE_INDEX_NO_STA_REC
];
1335 QM_DBG_CNT_INC(prQM
, QM_DBG_CNT_24
);
1340 prStaRec
= QM_GET_STA_REC_PTR_FROM_INDEX(prAdapter
, prCurrentMsduInfo
->ucStaRecIndex
);
1343 ASSERT(prStaRec
->fgIsValid
);
1345 if(prCurrentMsduInfo
->ucUserPriority
< 8) {
1346 QM_DBG_CNT_INC(prQM
, prCurrentMsduInfo
->ucUserPriority
+ 15);
1347 /* QM_DBG_CNT_15 */ /* QM_DBG_CNT_16 */ /* QM_DBG_CNT_17 */ /* QM_DBG_CNT_18 */
1348 /* QM_DBG_CNT_19 */ /* QM_DBG_CNT_20 */ /* QM_DBG_CNT_21 */ /* QM_DBG_CNT_22 */
1351 eAci
= WMM_AC_BE_INDEX
;
1353 fgCheckACMAgain
= FALSE
;
1354 if (prStaRec
->fgIsQoS
){
1355 switch(prCurrentMsduInfo
->ucUserPriority
){
1358 prTxQue
= &prStaRec
->arTxQueue
[TX_QUEUE_INDEX_AC0
];
1360 eAci
= WMM_AC_BK_INDEX
;
1364 prTxQue
= &prStaRec
->arTxQueue
[TX_QUEUE_INDEX_AC1
];
1366 eAci
= WMM_AC_BE_INDEX
;
1370 prTxQue
= &prStaRec
->arTxQueue
[TX_QUEUE_INDEX_AC2
];
1372 eAci
= WMM_AC_VI_INDEX
;
1373 #if QM_ADAPTIVE_TC_RESOURCE_CTRL
1374 prQM
->u4TxNumOfVi
++;
1379 prTxQue
= &prStaRec
->arTxQueue
[TX_QUEUE_INDEX_AC3
];
1381 eAci
= WMM_AC_VO_INDEX
;
1382 #if QM_ADAPTIVE_TC_RESOURCE_CTRL
1383 prQM
->u4TxNumOfVo
++;
1387 prTxQue
= &prStaRec
->arTxQueue
[TX_QUEUE_INDEX_AC1
];
1389 eAci
= WMM_AC_BE_INDEX
;
1393 if(prBssInfo
->arACQueParms
[eAci
].fgIsACMSet
&& eAci
!= WMM_AC_BK_INDEX
) {
1394 prCurrentMsduInfo
->ucUserPriority
= aucNextUP
[eAci
];
1395 fgCheckACMAgain
= TRUE
;
1399 prTxQue
= &prStaRec
->arTxQueue
[TX_QUEUE_INDEX_AC1
];
1403 while(fgCheckACMAgain
);
1405 //LOG_FUNC ("QoS %u UP %u TC %u",prStaRec->fgIsQoS,prCurrentMsduInfo->ucUserPriority, ucTC);
1407 #if QM_ADAPTIVE_TC_RESOURCE_CTRL
1409 In TDLS or AP mode, peer maybe enter "sleep mode".
1411 If QM_INIT_TIME_TO_UPDATE_QUE_LEN = 60 when peer is in sleep mode,
1412 we need to wait 60 * u4TimeToAdjustTcResource = 180 packets
1413 u4TimeToAdjustTcResource = 3,
1414 then we will adjust TC resouce for VI or VO.
1416 But in TDLS test case, the throughput is very low, only 0.8Mbps in 5.7,
1417 we will to wait about 12 seconds to collect 180 packets.
1418 but the test time is only 20 seconds.
1420 if ((prQM
->u4TxNumOfVi
== 10) || (prQM
->u4TxNumOfVo
== 10))
1422 /* force to do TC resouce update */
1423 prQM
->u4TimeToUpdateQueLen
= QM_INIT_TIME_TO_UPDATE_QUE_LEN_MIN
;
1424 prQM
->u4TimeToAdjustTcResource
= 1;
1429 } /* switch (prCurrentMsduInfo->ucStaRecIndex) */
1431 if(prCurrentMsduInfo
->eSrc
== TX_PACKET_FORWARDING
) {
1432 if(prTxQue
->u4NumElem
> 32) {
1433 DBGLOG(QM
, INFO
, ("Drop the Packet for full Tx queue (forwarding) Bss %u\n", prCurrentMsduInfo
->ucNetworkType
));
1434 prTxQue
= &rNotEnqueuedQue
;
1435 TX_INC_CNT(&prAdapter
->rTxCtrl
,TX_FORWARD_OVERFLOW_DROP
);
1442 DBGLOG(QM
, INFO
, ("Drop the Packet for inactive Bss %u\n", prCurrentMsduInfo
->ucNetworkType
));
1443 QM_DBG_CNT_INC(prQM
, QM_DBG_CNT_31
);
1444 prTxQue
= &rNotEnqueuedQue
;
1445 TX_INC_CNT(&prAdapter
->rTxCtrl
,TX_INACTIVE_BSS_DROP
);
1448 //4 <3> Fill the MSDU_INFO for constructing HIF TX header
1450 /* TODO: Fill MSDU_INFO according to the network type,
1451 * EtherType, and STA status (for PS forwarding control).
1454 /* Note that the Network Type Index and STA_REC index are determined in
1455 * qmDetermineStaRecIndex(prCurrentMsduInfo).
1457 QM_TX_SET_MSDU_INFO_FOR_DATA_PACKET(
1458 prCurrentMsduInfo
, /* MSDU_INFO ptr */
1460 ucPacketType
, /* Packet Type */
1462 prCurrentMsduInfo
->fgIs802_1x
, /* Flag 802.1x */
1463 prCurrentMsduInfo
->fgIs802_11
, /* Flag 802.11 */
1466 PS_FORWARDING_TYPE_NON_PS
, /* PS Forwarding Type */
1467 0 /* PS Session ID */
1470 //4 <4> Enqueue the packet to different AC queue (max 5 AC queues)
1471 QUEUE_INSERT_TAIL(prTxQue
, (P_QUE_ENTRY_T
)prCurrentMsduInfo
);
1472 #if QM_TC_RESOURCE_EMPTY_COUNTER
1474 P_TX_CTRL_T prTxCtrl
= &prAdapter
->rTxCtrl
;
1476 if(prTxCtrl
->rTc
.aucFreeBufferCount
[ucTC
] == 0) {
1477 prQM
->au4QmTcResourceEmptyCounter
[prCurrentMsduInfo
->ucNetworkType
][ucTC
]++;
1479 DBGLOG(QM, TRACE, ("TC%d Q Empty Count: [%d]%ld\n",
1481 prCurrentMsduInfo->ucNetworkType,
1482 prQM->au4QmTcResourceEmptyCounter[prCurrentMsduInfo->ucNetworkType][ucTC]));
1490 if (++prQM
->u4PktCount
== QM_TEST_TRIGGER_TX_COUNT
){
1491 prQM
->u4PktCount
= 0;
1492 qmTestCases(prAdapter
);
1497 DBGLOG(QM
, LOUD
, ("Current queue length = %u\n", prTxQue
->u4NumElem
));
1498 }while(prNextMsduInfo
);
1500 if( QUEUE_IS_NOT_EMPTY(&rNotEnqueuedQue
) ) {
1501 QM_TX_SET_NEXT_MSDU_INFO((P_MSDU_INFO_T
)QUEUE_GET_TAIL(&rNotEnqueuedQue
), NULL
);
1502 prMsduInfoReleaseList
= (P_MSDU_INFO_T
)QUEUE_GET_HEAD(&rNotEnqueuedQue
);
1506 return prMsduInfoReleaseList
;
1509 /*----------------------------------------------------------------------------*/
1511 * \brief Determine the STA_REC index for a packet
1513 * \param[in] prMsduInfo Pointer to the packet
1517 /*----------------------------------------------------------------------------*/
1519 qmDetermineStaRecIndex(
1520 IN P_ADAPTER_T prAdapter
,
1521 IN P_MSDU_INFO_T prMsduInfo
1526 P_STA_RECORD_T prTempStaRec
;
1527 //P_QUE_MGT_T prQM = &prAdapter->rQM;
1529 prTempStaRec
= NULL
;
1534 if (IS_BMCAST_MAC_ADDR(prMsduInfo
->aucEthDestAddr
)){
1535 /* For intrastructure mode and P2P (playing as a GC), BMCAST frames shall be sent to the AP.
1536 * FW shall take care of this. The host driver is not able to distinguish these cases. */
1537 prMsduInfo
->ucStaRecIndex
= STA_REC_INDEX_BMCAST
;
1538 DBGLOG(QM
, LOUD
, ("TX with DA = BMCAST\n"));
1543 #if (CFG_SUPPORT_TDLS == 1)
1544 /* Check if the peer is TDLS one */
1545 if (TdlsexStaRecIdxGet(prAdapter
, prMsduInfo
) == TDLS_STATUS_SUCCESS
)
1546 return; /* find a TDLS record */
1547 #endif /* CFG_SUPPORT_TDLS */
1550 //4 <2> Check if an AP STA is present
1551 for (i
= 0; i
< CFG_NUM_OF_STA_RECORD
; i
++){
1552 prTempStaRec
= &(prAdapter
->arStaRec
[i
]);
1554 if((prTempStaRec
->ucNetTypeIndex
== prMsduInfo
->ucNetworkType
)
1555 && (prTempStaRec
->fgIsAp
)
1556 && (prTempStaRec
->fgIsValid
)){
1557 prMsduInfo
->ucStaRecIndex
= prTempStaRec
->ucIndex
;
1565 //4 <3> Not BMCAST, No AP --> Compare DA (i.e., to see whether this is a unicast frame to a client)
1566 for (i
= 0; i
< CFG_NUM_OF_STA_RECORD
; i
++){
1567 prTempStaRec
= &(prAdapter
->arStaRec
[i
]);
1568 if (prTempStaRec
->fgIsValid
){
1569 if (EQUAL_MAC_ADDR(prTempStaRec
->aucMacAddr
, prMsduInfo
->aucEthDestAddr
)){
1570 prMsduInfo
->ucStaRecIndex
= prTempStaRec
->ucIndex
;
1577 //4 <4> No STA found, Not BMCAST --> Indicate NOT_FOUND to FW
1578 prMsduInfo
->ucStaRecIndex
= STA_REC_INDEX_NOT_FOUND
;
1579 DBGLOG(QM
, LOUD
, ("QM: TX with STA_REC_INDEX_NOT_FOUND\n"));
1582 #if (QM_TEST_MODE && QM_TEST_FAIR_FORWARDING)
1583 prMsduInfo
->ucStaRecIndex
= (UINT_8
)prQM
->u4CurrentStaRecIndexToEnqueue
;
1587 /*----------------------------------------------------------------------------*/
1589 * \brief Dequeue TX packets from a STA_REC for a particular TC
1591 * \param[out] prQue The queue to put the dequeued packets
1592 * \param[in] ucTC The TC index (TC0_INDEX to TC5_INDEX)
1593 * \param[in] ucMaxNum The maximum amount of dequeued packets
1597 /*----------------------------------------------------------------------------*/
1599 qmDequeueTxPacketsFromPerStaQueues(
1600 IN P_ADAPTER_T prAdapter
,
1603 IN UINT_8 ucCurrentQuota
,
1604 IN UINT_8 ucTotalQuota
1608 #if QM_FORWARDING_FAIRNESS
1609 UINT_32 i
; /* Loop for */
1611 PUINT_32 pu4HeadStaRecIndex
; /* The Head STA index */
1612 PUINT_32 pu4HeadStaRecForwardCount
; /* The total forwarded packets for the head STA */
1614 P_STA_RECORD_T prStaRec
; /* The current focused STA */
1615 P_BSS_INFO_T prBssInfo
; /* The Bss for current focused STA */
1616 P_QUE_T prCurrQueue
; /* The current TX queue to dequeue */
1617 P_MSDU_INFO_T prDequeuedPkt
; /* The dequeued packet */
1619 UINT_32 u4ForwardCount
; /* To remember the total forwarded packets for a STA */
1620 UINT_32 u4MaxForwardCount
; /* The maximum number of packets a STA can forward */
1621 UINT_32 u4Resource
; /* The TX resource amount */
1623 BOOLEAN fgChangeHeadSta
; /* Whether a new head STA shall be determined at the end of the function */
1624 P_QUE_MGT_T prQM
= &prAdapter
->rQM
;
1626 PUINT_8 pucFreeQuota
= NULL
;
1627 #if CFG_ENABLE_WIFI_DIRECT
1628 P_P2P_CHNL_REQ_INFO_T prChnlReqInfo
= &prAdapter
->rWifiVar
.prP2pFsmInfo
->rChnlReqInfo
;
1629 /*NFC Beam + Indication*/
1631 DBGLOG(QM
, LOUD
, ("Enter qmDequeueTxPacketsFromPerStaQueues (TC = %u)\n", ucTC
));
1633 ASSERT(ucTC
== TC0_INDEX
|| ucTC
== TC1_INDEX
||
1634 ucTC
== TC2_INDEX
|| ucTC
== TC3_INDEX
||
1638 if(!ucCurrentQuota
){
1639 DBGLOG(TX
, LOUD
, ("@@@@@ TC = %u ucCurrentQuota = %u @@@@@\n",
1640 ucTC
, ucCurrentQuota
));
1644 u4Resource
= ucCurrentQuota
;
1646 //4 <1> Determine the head STA
1647 /* The head STA shall be an active STA */
1649 pu4HeadStaRecIndex
= &(prQM
->au4HeadStaRecIndex
[ucTC
]);
1650 pu4HeadStaRecForwardCount
= &(prQM
->au4ForwardCount
[ucTC
]);
1652 DBGLOG(QM
, LOUD
, ("(Fairness) TID = %u Init Head STA = %u Resource = %u\n",
1653 ucTC
, *pu4HeadStaRecIndex
, u4Resource
));
1656 /* From STA[x] to STA[x+1] to STA[x+2] to ... to STA[x] */
1657 for (i
=0; i
< CFG_NUM_OF_STA_RECORD
+ 1; i
++){
1658 prStaRec
= &prAdapter
->arStaRec
[(*pu4HeadStaRecIndex
)];
1661 /* Only Data frame (1x was not included) will be queued in */
1662 if (prStaRec
->fgIsValid
){
1664 prBssInfo
= &(prAdapter
->rWifiVar
.arBssInfo
[prStaRec
->ucNetTypeIndex
]);
1666 ASSERT(prBssInfo
->ucNetTypeIndex
== prStaRec
->ucNetTypeIndex
);
1668 /* Determine how many packets the head STA is allowed to send in a round */
1670 QM_DBG_CNT_INC(prQM
, QM_DBG_CNT_25
);
1671 u4MaxForwardCount
= ucTotalQuota
;
1672 #if CFG_ENABLE_WIFI_DIRECT
1674 pucFreeQuota
= NULL
;
1675 if(prStaRec
->fgIsInPS
&& (ucTC
!=TC4_INDEX
)) {
1676 // TODO: Change the threshold in coorperation with the PS forwarding mechanism
1677 // u4MaxForwardCount = ucTotalQuota;
1678 /* Per STA flow control when STA in PS mode */
1679 /* The PHASE 1: only update from ucFreeQuota (now) */
1680 /* XXX The PHASE 2: Decide by ucFreeQuota and ucBmpDeliveryAC (per queue ) aucFreeQuotaPerQueue[] */
1681 /* NOTE: other method to set u4Resource */
1683 if(prStaRec
->fgIsQoS
&& prStaRec
->fgIsUapsdSupported
1684 /* && prAdapter->rWifiVar.fgSupportQoS
1685 && prAdapter->rWifiVar.fgSupportUAPSD*/) {
1687 if( prStaRec
->ucBmpTriggerAC
& BIT(ucTC
)) {
1688 u4MaxForwardCount
= prStaRec
->ucFreeQuotaForDelivery
;
1689 pucFreeQuota
= &prStaRec
->ucFreeQuotaForDelivery
;
1692 u4MaxForwardCount
= prStaRec
->ucFreeQuotaForNonDelivery
;
1693 pucFreeQuota
= &prStaRec
->ucFreeQuotaForNonDelivery
;
1698 ASSERT(prStaRec
->ucFreeQuotaForDelivery
== 0);
1699 u4MaxForwardCount
= prStaRec
->ucFreeQuotaForNonDelivery
;
1700 pucFreeQuota
= &prStaRec
->ucFreeQuotaForNonDelivery
;
1704 #endif /* CFG_ENABLE_WIFI_DIRECT */
1706 #if CFG_ENABLE_WIFI_DIRECT
1708 /*NFC Beam + Indication*/
1712 if(prBssInfo
->fgIsNetAbsent
&& (ucTC
!=TC4_INDEX
)) {
1713 if(prBssInfo
->eCurrentOPMode
==OP_MODE_ACCESS_POINT
)
1715 if(prChnlReqInfo
->NFC_BEAM
!=1/*||*/)
1717 if(u4MaxForwardCount
> prBssInfo
->ucBssFreeQuota
) {
1718 u4MaxForwardCount
= prBssInfo
->ucBssFreeQuota
;
1725 if(u4MaxForwardCount
> prBssInfo
->ucBssFreeQuota
) {
1726 u4MaxForwardCount
= prBssInfo
->ucBssFreeQuota
;
1731 #endif /* CFG_ENABLE_WIFI_DIRECT */
1733 /* Determine whether the head STA can continue to forward packets in this round */
1734 if((*pu4HeadStaRecForwardCount
) < u4MaxForwardCount
){
1738 } /* prStaRec->fgIsValid */
1740 /* The current Head STA has been deactivated, so search for a new head STA */
1743 (*pu4HeadStaRecIndex
) ++;
1744 (*pu4HeadStaRecIndex
) %= CFG_NUM_OF_STA_RECORD
;
1746 /* Reset the forwarding count before searching (since this is for a new selected STA) */
1747 (*pu4HeadStaRecForwardCount
) = 0;
1749 } /* i < CFG_NUM_OF_STA_RECORD + 1 */
1751 /* All STA_RECs are inactive, so exit */
1753 /* Under concurrent, it is possible that there is no candidcated STA.*/
1754 //DBGLOG(TX, EVENT, ("All STA_RECs are inactive\n"));
1758 DBGLOG(QM
, LOUD
, ("(Fairness) TID = %u Round Head STA = %u\n",
1759 ucTC
, *pu4HeadStaRecIndex
));
1761 //4 <2> Dequeue packets from the head STA
1763 prCurrQueue
= &prStaRec
->arTxQueue
[ucTC
];
1764 prDequeuedPkt
= NULL
;
1765 fgChangeHeadSta
= FALSE
;
1767 #if (CFG_SUPPORT_TDLS == 1)
1768 if (pucFreeQuota
!= NULL
)
1769 TdlsexTxQuotaCheck(prAdapter
->prGlueInfo
, prStaRec
, *pucFreeQuota
);
1770 #endif /* CFG_SUPPORT_TDLS */
1772 #if (CFG_SUPPORT_STATISTICS == 1)
1773 if (pucFreeQuota
!= NULL
)
1775 if (*pucFreeQuota
== 0)
1776 prStaRec
->u4NumOfNoTxQuota
++;
1778 #endif /* CFG_SUPPORT_STATISTICS */
1783 #if QM_DEBUG_COUNTER
1785 if(ucTC
<= TC4_INDEX
) {
1786 if(QUEUE_IS_EMPTY(prCurrQueue
)) {
1787 QM_DBG_CNT_INC(prQM
, ucTC
);
1788 /* QM_DBG_CNT_00 */ /* QM_DBG_CNT_01 */ /* QM_DBG_CNT_02 */ /* QM_DBG_CNT_03 */ /* QM_DBG_CNT_04 */
1790 if(u4Resource
== 0) {
1791 QM_DBG_CNT_INC(prQM
, ucTC
+ 5);
1792 /* QM_DBG_CNT_05 */ /* QM_DBG_CNT_06 */ /* QM_DBG_CNT_07 */ /* QM_DBG_CNT_08 */ /* QM_DBG_CNT_09 */
1794 if(((*pu4HeadStaRecForwardCount
) >= u4MaxForwardCount
)) {
1795 QM_DBG_CNT_INC(prQM
, ucTC
+ 10);
1796 /* QM_DBG_CNT_10 */ /* QM_DBG_CNT_11 */ /* QM_DBG_CNT_12 */ /* QM_DBG_CNT_13 */ /* QM_DBG_CNT_14 */
1802 /* Three cases to break: (1) No resource (2) No packets (3) Fairness */
1803 if (QUEUE_IS_EMPTY(prCurrQueue
) || ((*pu4HeadStaRecForwardCount
) >= u4MaxForwardCount
)){
1804 fgChangeHeadSta
= TRUE
;
1807 else if (u4Resource
== 0){
1812 QUEUE_REMOVE_HEAD(prCurrQueue
, prDequeuedPkt
, P_MSDU_INFO_T
);
1814 #if (CFG_SUPPORT_TDLS_DBG == 1)
1815 if (prDequeuedPkt
!= NULL
)
1817 struct sk_buff
*prSkb
= (struct sk_buff
*)prDequeuedPkt
->prPacket
;
1818 UINT8
*pkt
= prSkb
->data
;
1819 UINT16 u2Identifier
;
1820 if ((*(pkt
+12) == 0x08) && (*(pkt
+13) == 0x00))
1823 u2Identifier
= ((*(pkt
+18)) << 8) | (*(pkt
+19));
1824 printk("<d> %d\n", u2Identifier
);
1829 LOG_FUNC("Deq0 TC %d queued %u net %u mac len %u len %u Type %u 1x %u 11 %u\n",
1830 prDequeuedPkt
->ucTC
,
1831 prCurrQueue
->u4NumElem
,
1832 prDequeuedPkt
->ucNetworkType
,
1833 prDequeuedPkt
->ucMacHeaderLength
,
1834 prDequeuedPkt
->u2FrameLength
,
1835 prDequeuedPkt
->ucPacketType
,
1836 prDequeuedPkt
->fgIs802_1x
,
1837 prDequeuedPkt
->fgIs802_11
);
1839 LOG_FUNC("Dest Mac: " MACSTR
"\n",
1840 MAC2STR(prDequeuedPkt
->aucEthDestAddr
));
1844 struct sk_buff
*prSkb
= (struct sk_buff
*) prDequeuedPkt
->prPacket
;
1845 dumpMemory8((PUINT_8
)prSkb
->data
,prSkb
->len
);
1851 ASSERT(prDequeuedPkt
->ucTC
== ucTC
);
1853 if(!QUEUE_IS_EMPTY(prCurrQueue
)) {
1854 /* XXX: check all queues for STA */
1855 prDequeuedPkt
->ucPsForwardingType
= PS_FORWARDING_MORE_DATA_ENABLED
;
1858 QUEUE_INSERT_TAIL(prQue
,(P_QUE_ENTRY_T
)prDequeuedPkt
);
1860 (*pu4HeadStaRecForwardCount
) ++;
1863 #if CFG_ENABLE_WIFI_DIRECT
1864 /* XXX The PHASE 2: decrease from aucFreeQuotaPerQueue[] */
1865 if(prStaRec
->fgIsInPS
&& (ucTC
!=TC4_INDEX
)) {
1866 ASSERT(pucFreeQuota
);
1867 ASSERT(*pucFreeQuota
>0);
1868 if ((pucFreeQuota
) && (*pucFreeQuota
>0)) {
1869 *pucFreeQuota
= *pucFreeQuota
- 1;
1872 #endif /* CFG_ENABLE_WIFI_DIRECT */
1874 #if CFG_ENABLE_WIFI_DIRECT
1875 if(prBssInfo
->fgIsNetAbsent
&& (ucTC
!=TC4_INDEX
)) {
1876 if(prBssInfo
->ucBssFreeQuota
>0) {
1877 prBssInfo
->ucBssFreeQuota
--;
1880 #endif /* CFG_ENABLE_WIFI_DIRECT */
1885 if (*pu4HeadStaRecForwardCount
){
1886 DBGLOG(QM
, LOUD
, ("TC = %u Round Head STA = %u, u4HeadStaRecForwardCount = %u\n", ucTC
, *pu4HeadStaRecIndex
, (*pu4HeadStaRecForwardCount
)));
1889 #if QM_BURST_END_INFO_ENABLED
1890 /* Let FW know which packet is the last one dequeued from the STA */
1892 prDequeuedPkt
->fgIsBurstEnd
= TRUE
;
1897 //4 <3> Dequeue from the other STAs if there is residual TX resource
1899 /* Check all of the STAs to continue forwarding packets (including the head STA) */
1900 for (i
= 0; i
< CFG_NUM_OF_STA_RECORD
; i
++){
1901 /* Break in case no reasource is available */
1902 if (u4Resource
== 0){
1906 /* The current head STA will be examined when i = CFG_NUM_OF_STA_RECORD-1 */
1907 prStaRec
= &prAdapter
->arStaRec
[((*pu4HeadStaRecIndex
) + i
+ 1) % CFG_NUM_OF_STA_RECORD
];
1910 if (prStaRec
->fgIsValid
) {
1912 prBssInfo
= &(prAdapter
->rWifiVar
.arBssInfo
[prStaRec
->ucNetTypeIndex
]);
1913 ASSERT(prBssInfo
->ucNetTypeIndex
== prStaRec
->ucNetTypeIndex
);
1915 DBGLOG(QM
, LOUD
, ("(Fairness) TID = %u Sharing STA = %u Resource = %u\n",
1916 ucTC
, prStaRec
->ucIndex
, u4Resource
));
1918 prCurrQueue
= &prStaRec
->arTxQueue
[ucTC
];
1920 u4MaxForwardCount
= ucTotalQuota
;
1922 #if CFG_ENABLE_WIFI_DIRECT
1923 pucFreeQuota
= NULL
;
1924 if(prStaRec
->fgIsInPS
&& (ucTC
!=TC4_INDEX
)) {
1925 // TODO: Change the threshold in coorperation with the PS forwarding mechanism
1926 // u4MaxForwardCount = ucTotalQuota;
1927 /* Per STA flow control when STA in PS mode */
1928 /* The PHASE 1: only update from ucFreeQuota (now) */
1929 /* XXX The PHASE 2: Decide by ucFreeQuota and ucBmpDeliveryAC (per queue ) aucFreeQuotaPerQueue[] */
1930 /* NOTE: other method to set u4Resource */
1931 if(prStaRec
->fgIsQoS
&& prStaRec
->fgIsUapsdSupported
1932 /* && prAdapter->rWifiVar.fgSupportQoS
1933 && prAdapter->rWifiVar.fgSupportUAPSD*/) {
1935 if( prStaRec
->ucBmpTriggerAC
& BIT(ucTC
)) {
1936 u4MaxForwardCount
= prStaRec
->ucFreeQuotaForDelivery
;
1937 pucFreeQuota
= &prStaRec
->ucFreeQuotaForDelivery
;
1940 u4MaxForwardCount
= prStaRec
->ucFreeQuotaForNonDelivery
;
1941 pucFreeQuota
= &prStaRec
->ucFreeQuotaForNonDelivery
;
1946 ASSERT(prStaRec
->ucFreeQuotaForDelivery
== 0);
1947 u4MaxForwardCount
= prStaRec
->ucFreeQuotaForNonDelivery
;
1948 pucFreeQuota
= &prStaRec
->ucFreeQuotaForNonDelivery
;
1952 #endif /* CFG_ENABLE_WIFI_DIRECT */
1953 #if CFG_ENABLE_WIFI_DIRECT
1954 if(prBssInfo
->fgIsNetAbsent
&& (ucTC
!=TC4_INDEX
)) {
1955 if(u4MaxForwardCount
> prBssInfo
->ucBssFreeQuota
) {
1956 u4MaxForwardCount
= prBssInfo
->ucBssFreeQuota
;
1960 #endif /* CFG_ENABLE_WIFI_DIRECT */
1961 } /* prStaRec->fgIsValid */
1964 /* Invalid STA, so check the next STA */
1969 /* Three cases to break: (1) No resource (2) No packets (3) Fairness */
1970 if ((u4Resource
== 0) || QUEUE_IS_EMPTY(prCurrQueue
) || (u4ForwardCount
>= u4MaxForwardCount
)){
1975 QUEUE_REMOVE_HEAD(prCurrQueue
, prDequeuedPkt
, P_MSDU_INFO_T
);
1978 DBGLOG(QM
, LOUD
, ("Deq0 TC %d queued %u net %u mac len %u len %u Type %u 1x %u 11 %u\n",
1979 prDequeuedPkt
->ucTC
,
1980 prCurrQueue
->u4NumElem
,
1981 prDequeuedPkt
->ucNetworkType
,
1982 prDequeuedPkt
->ucMacHeaderLength
,
1983 prDequeuedPkt
->u2FrameLength
,
1984 prDequeuedPkt
->ucPacketType
,
1985 prDequeuedPkt
->fgIs802_1x
,
1986 prDequeuedPkt
->fgIs802_11
));
1988 DBGLOG(QM
, LOUD
,("Dest Mac: " MACSTR
"\n",
1989 MAC2STR(prDequeuedPkt
->aucEthDestAddr
)));
1993 struct sk_buff
*prSkb
= (struct sk_buff
*) prDequeuedPkt
->prPacket
;
1994 dumpMemory8((PUINT_8
)prSkb
->data
,prSkb
->len
);
2001 ASSERT(prDequeuedPkt
->ucTC
== ucTC
);
2003 if(!QUEUE_IS_EMPTY(prCurrQueue
)) {
2004 prDequeuedPkt
->ucPsForwardingType
= PS_FORWARDING_MORE_DATA_ENABLED
; /* more data field ? */
2007 QUEUE_INSERT_TAIL(prQue
,(P_QUE_ENTRY_T
)prDequeuedPkt
);
2011 #if CFG_ENABLE_WIFI_DIRECT
2012 /* XXX The PHASE 2: decrease from aucFreeQuotaPerQueue[] */
2013 if(prStaRec
->fgIsInPS
&& (ucTC
!=TC4_INDEX
)) {
2014 ASSERT(pucFreeQuota
);
2015 ASSERT(*pucFreeQuota
>0);
2016 if(*pucFreeQuota
>0) {
2017 *pucFreeQuota
= *pucFreeQuota
- 1;
2020 #endif /* CFG_ENABLE_WIFI_DIRECT */
2023 #if CFG_ENABLE_WIFI_DIRECT
2024 ASSERT(prBssInfo
->ucNetTypeIndex
== prStaRec
->ucNetTypeIndex
);
2025 if(prBssInfo
->fgIsNetAbsent
&& (ucTC
!=TC4_INDEX
)) {
2026 if(prBssInfo
->ucBssFreeQuota
>0) {
2027 prBssInfo
->ucBssFreeQuota
--;
2030 #endif /* CFG_ENABLE_WIFI_DIRECT */
2035 #if QM_BURST_END_INFO_ENABLED
2036 /* Let FW know which packet is the last one dequeued from the STA */
2037 if (u4ForwardCount
){
2038 prDequeuedPkt
->fgIsBurstEnd
= TRUE
;
2044 if (fgChangeHeadSta
){
2045 (*pu4HeadStaRecIndex
) ++;
2046 (*pu4HeadStaRecIndex
) %= CFG_NUM_OF_STA_RECORD
;
2047 (*pu4HeadStaRecForwardCount
) = 0;
2048 DBGLOG(QM
, LOUD
, ("(Fairness) TID = %u Scheduled Head STA = %u Left Resource = %u\n",
2049 ucTC
, (*pu4HeadStaRecIndex
), u4Resource
));
2053 /***************************************************************************************/
2055 UINT_8 ucStaRecIndex
;
2056 P_STA_RECORD_T prStaRec
;
2057 P_QUE_T prCurrQueue
;
2059 P_MSDU_INFO_T prDequeuedPkt
;
2061 DBGLOG(QM
, LOUD
, ("Enter qmDequeueTxPacketsFromPerStaQueues (TC = %u)\n", ucTC
));
2063 if (ucCurrentQuota
== 0){
2067 //4 <1> Determine the queue index and the head STA
2070 ucStaRecIndex
= 0; /* TODO: Get the current head STA */
2071 prStaRec
= QM_GET_STA_REC_PTR_FROM_INDEX(prAdapter
, ucStaRecIndex
);
2074 if(prStaRec
== NULL
) {
2078 /* The queue to pull out packets */
2079 ASSERT(ucTC
== TC0_INDEX
|| ucTC
== TC1_INDEX
||
2080 ucTC
== TC2_INDEX
|| ucTC
== TC3_INDEX
||
2083 prCurrQueue
= &prStaRec
->arTxQueue
[ucTC
];
2085 ucPktCount
= ucCurrentQuota
;
2086 prDequeuedPkt
= NULL
;
2088 //4 <2> Dequeue packets for the head STA
2090 if (!(prStaRec
->fgIsValid
) || ucPktCount
==0 || QUEUE_IS_EMPTY(prCurrQueue
)){
2096 QUEUE_REMOVE_HEAD(prCurrQueue
, prDequeuedPkt
, P_MSDU_INFO_T
);
2097 //DbgPrint("QM: Remove Queue Head, TC= %d\n", prDequeuedPkt->ucTC);
2098 ASSERT(prDequeuedPkt
->ucTC
== ucTC
);
2100 QUEUE_INSERT_TAIL(prQue
,(P_QUE_ENTRY_T
)prDequeuedPkt
);
2105 //DbgPrint("QM: Remaining number of queued packets = %d\n", prCurrQueue->u4NumElem);
2107 #if QM_BURST_END_INFO_ENABLED
2109 prDequeuedPkt
->fgIsBurstEnd
= TRUE
;
2114 //4 <3> Update scheduling info
2117 //4 <4> Utilize the remainaing TX opportunities for non-head STAs
2123 /*----------------------------------------------------------------------------*/
2125 * \brief Dequeue TX packets from a per-Type-based Queue for a particular TC
2127 * \param[out] prQue The queue to put the dequeued packets
2128 * \param[in] ucTC The TC index (Shall always be TC5_INDEX)
2129 * \param[in] ucMaxNum The maximum amount of dequeued packets
2133 /*----------------------------------------------------------------------------*/
2135 qmDequeueTxPacketsFromPerTypeQueues(
2136 IN P_ADAPTER_T prAdapter
,
2142 //UINT_8 ucQueIndex;
2143 //UINT_8 ucStaRecIndex;
2144 P_BSS_INFO_T prBssInfo
;
2145 P_BSS_INFO_T parBssInfo
;
2146 P_QUE_T prCurrQueue
;
2148 P_MSDU_INFO_T prDequeuedPkt
;
2149 P_MSDU_INFO_T prBurstEndPkt
;
2154 DBGLOG(QM
, LOUD
, ("Enter qmDequeueTxPacketsFromPerTypeQueues (TC = %d, Max = %d)\n", ucTC
, ucMaxNum
));
2156 /* TC5: Broadcast/Multicast data packets */
2157 ASSERT(ucTC
== TC5_INDEX
);
2163 prQM
= &prAdapter
->rQM
;
2164 //4 <1> Determine the queue
2166 prCurrQueue
= &prQM
->arTxQueue
[TX_QUEUE_INDEX_BMCAST
];
2167 ucPktCount
= ucMaxNum
;
2168 prDequeuedPkt
= NULL
;
2169 prBurstEndPkt
= NULL
;
2171 parBssInfo
= prAdapter
->rWifiVar
.arBssInfo
;
2173 QUEUE_INITIALIZE(&rMergeQue
);
2174 prMergeQue
= &rMergeQue
;
2176 //4 <2> Dequeue packets
2178 if(ucPktCount
==0 || QUEUE_IS_EMPTY(prCurrQueue
)){
2182 QUEUE_REMOVE_HEAD(prCurrQueue
, prDequeuedPkt
, P_MSDU_INFO_T
);
2183 ASSERT(prDequeuedPkt
->ucTC
== ucTC
);
2185 ASSERT(prDequeuedPkt
->ucNetworkType
< NETWORK_TYPE_INDEX_NUM
);
2187 prBssInfo
= &parBssInfo
[prDequeuedPkt
->ucNetworkType
];
2189 if(IS_BSS_ACTIVE(prBssInfo
)) {
2190 if( !prBssInfo
->fgIsNetAbsent
){
2191 QUEUE_INSERT_TAIL(prQue
,(P_QUE_ENTRY_T
)prDequeuedPkt
);
2192 prBurstEndPkt
= prDequeuedPkt
;
2194 QM_DBG_CNT_INC(prQM
, QM_DBG_CNT_26
);
2196 LOG_FUNC("DeqType TC %d queued %u net %u mac len %u len %u Type %u 1x %u 11 %u\n",
2197 prDequeuedPkt
->ucTC
,
2198 prCurrQueue
->u4NumElem
,
2199 prDequeuedPkt
->ucNetworkType
,
2200 prDequeuedPkt
->ucMacHeaderLength
,
2201 prDequeuedPkt
->u2FrameLength
,
2202 prDequeuedPkt
->ucPacketType
,
2203 prDequeuedPkt
->fgIs802_1x
,
2204 prDequeuedPkt
->fgIs802_11
);
2206 LOG_FUNC("Dest Mac: " MACSTR
"\n",
2207 MAC2STR(prDequeuedPkt
->aucEthDestAddr
));
2211 struct sk_buff
*prSkb
= (struct sk_buff
*) prDequeuedPkt
->prPacket
;
2212 dumpMemory8((PUINT_8
)prSkb
->data
,prSkb
->len
);
2219 QUEUE_INSERT_TAIL(prMergeQue
,(P_QUE_ENTRY_T
)prDequeuedPkt
);
2223 QM_TX_SET_NEXT_MSDU_INFO(prDequeuedPkt
, NULL
);
2224 wlanProcessQueuedMsduInfo(prAdapter
,prDequeuedPkt
);
2229 if(QUEUE_IS_NOT_EMPTY(prMergeQue
)) {
2230 QUEUE_CONCATENATE_QUEUES(prMergeQue
, prCurrQueue
);
2231 QUEUE_MOVE_ALL(prCurrQueue
, prMergeQue
);
2232 QM_TX_SET_NEXT_MSDU_INFO((P_MSDU_INFO_T
)QUEUE_GET_TAIL(prCurrQueue
), NULL
);
2235 #if QM_BURST_END_INFO_ENABLED
2237 prBurstEndPkt
->fgIsBurstEnd
= TRUE
;
2240 } /* qmDequeueTxPacketsFromPerTypeQueues */
2245 /*----------------------------------------------------------------------------*/
2247 * \brief Dequeue TX packets to send to HIF TX
2249 * \param[in] prTcqStatus Info about the maximum amount of dequeued packets
2251 * \return The list of dequeued TX packets
2253 /*----------------------------------------------------------------------------*/
2256 IN P_ADAPTER_T prAdapter
,
2257 IN P_TX_TCQ_STATUS_T prTcqStatus
2262 P_MSDU_INFO_T prReturnedPacketListHead
;
2265 DBGLOG(QM
, LOUD
, ("Enter qmDequeueTxPackets\n"));
2267 QUEUE_INITIALIZE(&rReturnedQue
);
2269 prReturnedPacketListHead
= NULL
;
2271 /* dequeue packets from different AC queue based on available aucFreeBufferCount */
2272 /* TC0 to TC4: AC0~AC3, 802.1x (commands packets are not handled by QM) */
2273 for(i
= TC4_INDEX
; i
>= TC0_INDEX
; i
--){
2274 DBGLOG(QM
, LOUD
, ("Dequeue packets from Per-STA queue[%d]\n", i
));
2277 in the function, we will re-calculate the ucFreeQuota.
2278 If any packet with any priority for the station will be sent, ucFreeQuota --
2280 Note1: ucFreeQuota will be decrease only when station is in power save mode.
2281 In active mode, we will sent the packet to the air directly.
2283 if(prStaRec->fgIsInPS && (ucTC!=TC4_INDEX)) {
2284 ASSERT(pucFreeQuota);
2285 ASSERT(*pucFreeQuota>0);
2286 if ((pucFreeQuota) && (*pucFreeQuota>0)) {
2287 *pucFreeQuota = *pucFreeQuota - 1;
2291 Note2: maximum queued number for a station is 10, TXM_MAX_BUFFER_PER_STA_DEF in fw
2292 i.e. default prStaRec->ucFreeQuota = 10
2294 Note3: In qmUpdateFreeQuota(), we will adjust
2295 ucFreeQuotaForNonDelivery = ucFreeQuota>>1;
2296 ucFreeQuotaForDelivery = ucFreeQuota - ucFreeQuotaForNonDelivery;
2298 qmDequeueTxPacketsFromPerStaQueues(
2302 prTcqStatus
->aucFreeBufferCount
[i
], /* maximum dequeue number */
2303 prTcqStatus
->aucMaxNumOfBuffer
[i
]
2306 /* The aggregate number of dequeued packets */
2307 DBGLOG(QM
, LOUD
, ("DQA)[%u](%u)\n", i
, rReturnedQue
.u4NumElem
));
2311 /* TC5 (BMCAST or STA-NOT-FOUND packets) */
2312 qmDequeueTxPacketsFromPerTypeQueues(
2316 prTcqStatus
->aucFreeBufferCount
[TC5_INDEX
]
2319 DBGLOG(QM
, LOUD
, ("Current total number of dequeued packets = %u\n",
2320 rReturnedQue
.u4NumElem
));
2322 if (QUEUE_IS_NOT_EMPTY(&rReturnedQue
)){
2323 prReturnedPacketListHead
= (P_MSDU_INFO_T
)QUEUE_GET_HEAD(&rReturnedQue
);
2324 QM_TX_SET_NEXT_MSDU_INFO((P_MSDU_INFO_T
)QUEUE_GET_TAIL(&rReturnedQue
), NULL
);
2327 return prReturnedPacketListHead
;
2330 /*----------------------------------------------------------------------------*/
2332 * \brief Adjust the TC quotas according to traffic demands
2334 * \param[out] prTcqAdjust The resulting adjustment
2335 * \param[in] prTcqStatus Info about the current TC quotas and counters
2339 /*----------------------------------------------------------------------------*/
2342 IN P_ADAPTER_T prAdapter
,
2343 OUT P_TX_TCQ_ADJUST_T prTcqAdjust
,
2344 IN P_TX_TCQ_STATUS_T prTcqStatus
2347 #if QM_ADAPTIVE_TC_RESOURCE_CTRL
2349 P_QUE_MGT_T prQM
= &prAdapter
->rQM
;
2352 for (i
= 0; i
< TC_NUM
; i
++){
2353 prTcqAdjust
->acVariation
[i
]= 0;
2356 //4 <1> If TC resource is not just adjusted, exit directly
2357 if (!prQM
->fgTcResourcePostAnnealing
){
2361 //4 <2> Adjust TcqStatus according to the updated prQM->au4CurrentTcResource
2363 INT_32 i4TotalExtraQuota
= 0;
2364 INT_32 ai4ExtraQuota
[TC_NUM
];
2365 BOOLEAN fgResourceRedistributed
= TRUE
;
2367 /* Obtain the free-to-distribute resource */
2368 for (i
= 0; i
< TC_NUM
; i
++){
2369 ai4ExtraQuota
[i
] = (INT_32
)prTcqStatus
->aucMaxNumOfBuffer
[i
] - (INT_32
)prQM
->au4CurrentTcResource
[i
];
2371 if (ai4ExtraQuota
[i
] > 0){ /* The resource shall be reallocated to other TCs */
2373 if (ai4ExtraQuota
[i
] > prTcqStatus
->aucFreeBufferCount
[i
]){
2375 we have residunt TC resources for the TC:
2376 EX: aucMaxNumOfBuffer[] = 20, au4CurrentTcResource[] = 5
2377 ai4ExtraQuota[] = 15, aucFreeBufferCount[] = 10
2379 so ai4ExtraQuota[] = aucFreeBufferCount[] = 10
2380 because we available TC resources actually is 10, not 20
2382 ai4ExtraQuota
[i
] = prTcqStatus
->aucFreeBufferCount
[i
];
2385 FALSE means we can re-do TC resource adjustment in tx done
2386 at next time, maybe more tx done is finished
2388 fgResourceRedistributed
= FALSE
;
2391 /* accumulate current all available TC resources */
2392 i4TotalExtraQuota
+= ai4ExtraQuota
[i
];
2394 /* deduce unused TC resources for the TC */
2395 prTcqAdjust
->acVariation
[i
] = (INT_8
)(-ai4ExtraQuota
[i
]);
2399 /* Distribute quotas to TCs which need extra resource according to prQM->au4CurrentTcResource */
2400 for (i
= 0; i
< TC_NUM
; i
++){
2401 if (ai4ExtraQuota
[i
] < 0){
2403 /* The TC needs extra resources */
2404 if ((-ai4ExtraQuota
[i
]) > i4TotalExtraQuota
){
2405 /* the number of needed extra resources is larger than total available */
2406 ai4ExtraQuota
[i
] = (-i4TotalExtraQuota
);
2408 /* wait for next tx done to do adjustment */
2409 fgResourceRedistributed
= FALSE
;
2412 /* decrease the total available */
2413 i4TotalExtraQuota
+= ai4ExtraQuota
[i
];
2415 /* mark to increase TC resources for the TC */
2416 prTcqAdjust
->acVariation
[i
] = (INT_8
)(-ai4ExtraQuota
[i
]);
2420 /* In case some TC is waiting for TX Done, continue to adjust TC quotas upon TX Done */
2423 if fgResourceRedistributed == TRUE, it means we will adjust at this time so
2424 we need to re-adjust TC resources (fgTcResourcePostAnnealing = FALSE).
2426 prQM
->fgTcResourcePostAnnealing
= (!fgResourceRedistributed
);
2428 #if QM_PRINT_TC_RESOURCE_CTRL
2429 DBGLOG(QM
, LOUD
, ("QM: Curr Quota [0]=%u [1]=%u [2]=%u [3]=%u [4]=%u [5]=%u\n",
2430 prTcqStatus
->aucFreeBufferCount
[0],
2431 prTcqStatus
->aucFreeBufferCount
[1],
2432 prTcqStatus
->aucFreeBufferCount
[2],
2433 prTcqStatus
->aucFreeBufferCount
[3],
2434 prTcqStatus
->aucFreeBufferCount
[4],
2435 prTcqStatus
->aucFreeBufferCount
[5]
2442 for (i
= 0; i
< TC_NUM
; i
++){
2443 prTcqAdjust
->acVariation
[i
]= 0;
2449 #if QM_ADAPTIVE_TC_RESOURCE_CTRL
2450 /*----------------------------------------------------------------------------*/
2452 * \brief Update the average TX queue length for the TC resource control mechanism
2458 /*----------------------------------------------------------------------------*/
2460 qmUpdateAverageTxQueLen(
2461 IN P_ADAPTER_T prAdapter
2464 INT_32 u4CurrQueLen
, i
, k
;
2465 P_STA_RECORD_T prStaRec
;
2466 P_QUE_MGT_T prQM
= &prAdapter
->rQM
;
2468 //4 <1> Update the queue lengths for TC0 to TC3 (skip TC4) and TC5 */
2469 /* use moving average algorithm to calculate au4AverageQueLen for every TC queue */
2470 for (i
= 0; i
< NUM_OF_PER_STA_TX_QUEUES
- 1; i
++){
2473 for (k
= 0; k
< CFG_NUM_OF_STA_RECORD
; k
++){
2474 prStaRec
= &prAdapter
->arStaRec
[k
];
2477 /* If the STA is activated, get the queue length */
2478 if (prStaRec
->fgIsValid
&&
2479 (!prAdapter
->rWifiVar
.arBssInfo
[prStaRec
->ucNetTypeIndex
].fgIsNetAbsent
)
2483 u4CurrQueLen
+= (prStaRec
->arTxQueue
[i
].u4NumElem
);
2487 if (prQM
->au4AverageQueLen
[i
] == 0){
2488 prQM
->au4AverageQueLen
[i
] = (u4CurrQueLen
<< QM_QUE_LEN_MOVING_AVE_FACTOR
); /* *8 */
2491 /* len => len - len/8 = 7/8 * len + new len */
2492 prQM
->au4AverageQueLen
[i
] -= (prQM
->au4AverageQueLen
[i
] >> QM_QUE_LEN_MOVING_AVE_FACTOR
);
2493 prQM
->au4AverageQueLen
[i
] += (u4CurrQueLen
);
2498 /* Update the queue length for TC5 (BMCAST) */
2499 u4CurrQueLen
= prQM
->arTxQueue
[TX_QUEUE_INDEX_BMCAST
].u4NumElem
;
2501 if (prQM
->au4AverageQueLen
[TC_NUM
-1] == 0){
2502 prQM
->au4AverageQueLen
[TC_NUM
-1] = (u4CurrQueLen
<< QM_QUE_LEN_MOVING_AVE_FACTOR
);
2505 prQM
->au4AverageQueLen
[TC_NUM
-1] -= (prQM
->au4AverageQueLen
[TC_NUM
-1] >> QM_QUE_LEN_MOVING_AVE_FACTOR
);
2506 prQM
->au4AverageQueLen
[TC_NUM
-1] += (u4CurrQueLen
);
2510 //4 <2> Adjust TC resource assignment every 3 times
2511 /* Check whether it is time to adjust the TC resource assignment */
2512 if (--prQM
->u4TimeToAdjustTcResource
== 0){ /* u4TimeToAdjustTcResource = 3 */
2514 /* The last assignment has not been completely applied */
2515 if (prQM
->fgTcResourcePostAnnealing
){
2516 /* Upon the next qmUpdateAverageTxQueLen function call, do this check again */
2518 /* wait for next time to do qmReassignTcResource */
2519 prQM
->u4TimeToAdjustTcResource
= 1;
2521 else{ /* The last assignment has been applied */
2522 prQM
->u4TimeToAdjustTcResource
= QM_INIT_TIME_TO_ADJUST_TC_RSC
;
2523 qmReassignTcResource(prAdapter
);
2528 #if QM_PRINT_TC_RESOURCE_CTRL
2529 for (i
=0; i
<TC_NUM
; i
++){
2530 if(QM_GET_TX_QUEUE_LEN(prAdapter
, i
) >= 100){
2531 DBGLOG(QM
, LOUD
, ("QM: QueLen [%u %u %u %u %u %u]\n",
2532 QM_GET_TX_QUEUE_LEN(prAdapter
, 0),
2533 QM_GET_TX_QUEUE_LEN(prAdapter
, 1),
2534 QM_GET_TX_QUEUE_LEN(prAdapter
, 2),
2535 QM_GET_TX_QUEUE_LEN(prAdapter
, 3),
2536 QM_GET_TX_QUEUE_LEN(prAdapter
, 4),
2537 QM_GET_TX_QUEUE_LEN(prAdapter
, 5)
2548 /*----------------------------------------------------------------------------*/
2550 * \brief Assign TX resource for each TC according to TX queue length and current assignment
2556 /*----------------------------------------------------------------------------*/
2558 qmReassignTcResource(
2559 IN P_ADAPTER_T prAdapter
2562 INT_32 i4TotalResourceDemand
= 0;
2563 UINT_32 u4ResidualResource
= 0;
2565 INT_32 ai4PerTcResourceDemand
[TC_NUM
];
2566 UINT_32 u4ShareCount
= 0;
2567 UINT_32 u4Share
= 0 ;
2568 P_QUE_MGT_T prQM
= &prAdapter
->rQM
;
2570 /* Note: After the new assignment is obtained, set prQM->fgTcResourcePostAnnealing to TRUE to
2571 * start the TC-quota adjusting procedure, which will be invoked upon every TX Done
2573 /* tx done -> nicProcessTxInterrupt() -> nicTxAdjustTcq() -> qmAdjustTcQuotas() -> check fgTcResourcePostAnnealing */
2575 //4 <1> Determine the demands
2576 /* Determine the amount of extra resource to fulfill all of the demands */
2577 for (i
=0; i
<TC_NUM
; i
++){
2578 /* Skip TC4, which is not adjustable */
2579 if (i
== TC4_INDEX
) {
2584 Define: extra_demand = average que_length (includes all station records) +
2585 min_reserved_quota -
2586 current available TC resources
2588 extra_demand means we need extra TC resources to transmit; other TCs can
2589 borrow their resources to us?
2591 ai4PerTcResourceDemand
[i
] =
2592 ((UINT_32
)(QM_GET_TX_QUEUE_LEN(prAdapter
, i
)) +
2593 prQM
->au4MinReservedTcResource
[i
] - prQM
->au4CurrentTcResource
[i
]);
2595 /* If there are queued packets, allocate extra resource for the TC (for TCP consideration) */
2596 if (QM_GET_TX_QUEUE_LEN(prAdapter
, i
)){
2597 ai4PerTcResourceDemand
[i
] += QM_EXTRA_RESERVED_RESOURCE_WHEN_BUSY
; /* 0 */
2601 accumulate all needed extra TC resources
2602 maybe someone need + resource, maybe someone need - resource
2604 i4TotalResourceDemand
+= ai4PerTcResourceDemand
[i
];
2608 //4 <2> Case 1: Demand <= Total Resource
2609 if (i4TotalResourceDemand
<= 0) {
2610 //4 <2.1> Satisfy every TC
2611 /* total TC resouces are enough, no extra TC resource is needed */
2613 /* adjust used TC resource to average TC resouces + min reserve TC resources */
2614 for (i
= 0; i
< TC_NUM
; i
++){
2615 /* Skip TC4 (not adjustable) */
2616 if (i
== TC4_INDEX
) {
2621 the number of resources that one TC releases can be used for
2624 EX: TC0 au4CurrentTcResource[0] = 10 ai4PerTcResourceDemand[0] = -5
2625 TC1 au4CurrentTcResource[1] = 5 ai4PerTcResourceDemand[0] = +5
2626 => TC0 au4CurrentTcResource[0] = 10 + (-5) = 5
2627 TC1 au4CurrentTcResource[1] = 5 + (+5) = 10
2629 prQM
->au4CurrentTcResource
[i
] += ai4PerTcResourceDemand
[i
];
2632 //4 <2.2> Share the residual resource evenly
2633 u4ShareCount
= (TC_NUM
- 1); /* 5, excluding TC4 */
2636 EX: i4TotalResourceDemand = -10
2637 means we have 10 available resources can be used.
2639 u4ResidualResource
= (UINT_32
)(-i4TotalResourceDemand
);
2640 u4Share
= (u4ResidualResource
/u4ShareCount
);
2642 /* share available TC resources to all TCs averagely */
2643 for (i
=0; i
<TC_NUM
; i
++){
2644 /* Skip TC4 (not adjustable) */
2645 if (i
== TC4_INDEX
) {
2649 /* allocate residual average resources to the TC */
2650 prQM
->au4CurrentTcResource
[i
] += u4Share
;
2652 /* Every TC is fully satisfied so no need extra resources */
2653 ai4PerTcResourceDemand
[i
] = 0;
2655 /* decrease the allocated resources */
2656 u4ResidualResource
-= u4Share
;
2659 /* if still have available resources, we decide to give them to VO (TC3) queue */
2660 //4 <2.3> Allocate the left resource to TC3 (VO)
2661 prQM
->au4CurrentTcResource
[TC3_INDEX
] += (u4ResidualResource
);
2665 //4 <3> Case 2: Demand > Total Resource --> Guarantee a minimum amount of resource for each TC
2668 u4ResidualResource means we at least need to keep
2669 QM_INITIAL_RESIDUAL_TC_RESOURCE available TC resources
2671 in 6628, u4ResidualResource = 26, max 28
2673 u4ResidualResource
= QM_INITIAL_RESIDUAL_TC_RESOURCE
;
2675 //4 <3.1> Allocated resource amount = minimum of (guaranteed, total demand)
2676 for (i
=0; i
<TC_NUM
; i
++){
2678 if (i
== TC4_INDEX
) {
2679 continue; /* Skip TC4 (not adjustable) */
2682 /* The demand can be fulfilled with the guaranteed resource amount 4 4 6 6 2 4 */
2685 ai4PerTcResourceDemand[i] =
2686 ((UINT_32)(QM_GET_TX_QUEUE_LEN(prAdapter, i)) +
2687 prQM->au4MinReservedTcResource[i] -
2688 prQM->au4CurrentTcResource[i]);
2690 so au4CurrentTcResource + ai4PerTcResourceDemand =
2692 ((UINT_32)(QM_GET_TX_QUEUE_LEN(prAdapter, i)) +
2693 prQM->au4MinReservedTcResource[i] =
2695 current average queue len + min TC resouces
2697 if (prQM
->au4CurrentTcResource
[i
] + ai4PerTcResourceDemand
[i
] < prQM
->au4GuaranteedTcResource
[i
]){
2699 /* avg queue len + min reserve still smaller than guarantee so enough */
2700 prQM
->au4CurrentTcResource
[i
] += ai4PerTcResourceDemand
[i
];
2702 /* accumulate available TC resources from the TC */
2703 u4ResidualResource
+= (prQM
->au4GuaranteedTcResource
[i
] - prQM
->au4CurrentTcResource
[i
]);
2704 ai4PerTcResourceDemand
[i
] = 0;
2707 /* The demand can not be fulfilled with the guaranteed resource amount */
2710 /* means even we use all guarantee resources for the TC is still not enough */
2713 guarantee number is always for the TC so extra resource number cannot
2714 include the guarantee number.
2716 EX: au4GuaranteedTcResource = 10, au4CurrentTcResource = 5
2717 ai4PerTcResourceDemand = 6
2719 ai4PerTcResourceDemand -= (10 - 5) ==> 1
2720 only need extra 1 TC resouce is enough.
2722 ai4PerTcResourceDemand
[i
] -= (prQM
->au4GuaranteedTcResource
[i
] - prQM
->au4CurrentTcResource
[i
]);
2724 /* update current avg TC resource to guarantee number */
2725 prQM
->au4CurrentTcResource
[i
] = prQM
->au4GuaranteedTcResource
[i
];
2727 /* count how many TC queues need to get extra resources */
2733 //4 <3.2> Allocate the residual resource
2735 /* If there is no resource left, exit directly */
2736 if (u4ResidualResource
== 0){
2740 /* This shall not happen */
2741 if (u4ShareCount
== 0){
2742 prQM
->au4CurrentTcResource
[TC1_INDEX
] += u4ResidualResource
;
2743 DBGLOG(QM
, ERROR
, ("QM: (Error) u4ShareCount = 0\n"));
2747 /* Share the residual resource evenly */
2748 u4Share
= (u4ResidualResource
/ u4ShareCount
);
2751 for (i
=0; i
<TC_NUM
; i
++){
2752 /* Skip TC4 (not adjustable) */
2753 if (i
== TC4_INDEX
) {
2757 if (ai4PerTcResourceDemand
[i
]){
2758 if (ai4PerTcResourceDemand
[i
] - u4Share
){
2759 /* still not enough but we just can give it u4Share resources */
2760 prQM
->au4CurrentTcResource
[i
] += u4Share
;
2761 u4ResidualResource
-= u4Share
;
2762 ai4PerTcResourceDemand
[i
] -= u4Share
;
2766 prQM
->au4CurrentTcResource
[i
] += ai4PerTcResourceDemand
[i
];
2767 u4ResidualResource
-= ai4PerTcResourceDemand
[i
];
2768 ai4PerTcResourceDemand
[i
] = 0;
2774 if (u4ResidualResource
== 0){
2777 /* By priority, allocate the left resource that is not divisible by u4Share */
2779 if (ai4PerTcResourceDemand
[TC3_INDEX
]){ /* VO */
2780 prQM
->au4CurrentTcResource
[TC3_INDEX
]++;
2781 if (--u4ResidualResource
== 0) {
2786 if (ai4PerTcResourceDemand
[TC2_INDEX
]){ /* VI */
2787 prQM
->au4CurrentTcResource
[TC2_INDEX
]++;
2788 if (--u4ResidualResource
== 0) {
2793 if (ai4PerTcResourceDemand
[TC5_INDEX
]){ /* BMCAST */
2794 prQM
->au4CurrentTcResource
[TC5_INDEX
]++;
2795 if (--u4ResidualResource
== 0) {
2800 if (ai4PerTcResourceDemand
[TC1_INDEX
]){ /* BE */
2801 prQM
->au4CurrentTcResource
[TC1_INDEX
]++;
2802 if (--u4ResidualResource
== 0) {
2807 if (ai4PerTcResourceDemand
[TC0_INDEX
]){ /* BK */
2808 prQM
->au4CurrentTcResource
[TC0_INDEX
]++;
2809 if (--u4ResidualResource
== 0) {
2814 /* Allocate the left resource */
2815 prQM
->au4CurrentTcResource
[TC3_INDEX
] += u4ResidualResource
;
2820 /* mark the flag that we can start to do TC resource adjustment after TX done handle */
2821 prQM
->fgTcResourcePostAnnealing
= TRUE
;
2823 #if QM_PRINT_TC_RESOURCE_CTRL
2825 DBGLOG(QM
, LOUD
, ("QM: TC Rsc %u %u %u %u %u %u\n",
2826 prQM
->au4CurrentTcResource
[0],
2827 prQM
->au4CurrentTcResource
[1],
2828 prQM
->au4CurrentTcResource
[2],
2829 prQM
->au4CurrentTcResource
[3],
2830 prQM
->au4CurrentTcResource
[4],
2831 prQM
->au4CurrentTcResource
[5]
2840 /*----------------------------------------------------------------------------*/
2841 /* RX-Related Queue Management */
2842 /*----------------------------------------------------------------------------*/
2843 /*----------------------------------------------------------------------------*/
2845 * \brief Init Queue Managment for RX
2851 /*----------------------------------------------------------------------------*/
2854 IN P_ADAPTER_T prAdapter
2857 //DbgPrint("QM: Enter qmInitRxQueues()\n");
2861 /*----------------------------------------------------------------------------*/
2863 * \brief Handle RX packets (buffer reordering)
2865 * \param[in] prSwRfbListHead The list of RX packets
2867 * \return The list of packets which are not buffered for reordering
2869 /*----------------------------------------------------------------------------*/
2872 IN P_ADAPTER_T prAdapter
,
2873 IN P_SW_RFB_T prSwRfbListHead
2877 #if CFG_RX_REORDERING_ENABLED
2879 P_SW_RFB_T prCurrSwRfb
;
2880 P_SW_RFB_T prNextSwRfb
;
2881 P_HIF_RX_HEADER_T prHifRxHdr
;
2883 PUINT_8 pucEthDestAddr
;
2886 //DbgPrint("QM: Enter qmHandleRxPackets()\n");
2888 DEBUGFUNC("qmHandleRxPackets");
2890 ASSERT(prSwRfbListHead
);
2892 QUEUE_INITIALIZE(&rReturnedQue
);
2893 prNextSwRfb
= prSwRfbListHead
;
2896 prCurrSwRfb
= prNextSwRfb
;
2897 prNextSwRfb
= QM_RX_GET_NEXT_SW_RFB(prCurrSwRfb
);
2899 prHifRxHdr
= prCurrSwRfb
->prHifRxHdr
; // TODO: (Tehuang) Use macro to obtain the pointer
2901 /* TODO: (Tehuang) Check if relaying */
2902 prCurrSwRfb
->eDst
= RX_PKT_DESTINATION_HOST
;
2904 /* Decide the Destination */
2905 #if CFG_RX_PKTS_DUMP
2906 if (prAdapter
->rRxCtrl
.u4RxPktsDumpTypeMask
& BIT(HIF_RX_PKT_TYPE_DATA
)) {
2907 DBGLOG(SW4
, INFO
, ("QM RX DATA: net %u sta idx %u wlan idx %u ssn %u tid %u ptype %u 11 %u\n",
2908 (UINT_32
)HIF_RX_HDR_GET_NETWORK_IDX(prHifRxHdr
),
2909 prHifRxHdr
->ucStaRecIdx
,
2910 prCurrSwRfb
->ucWlanIdx
,
2911 (UINT_32
)HIF_RX_HDR_GET_SN(prHifRxHdr
), /* The new SN of the frame */
2912 (UINT_32
)HIF_RX_HDR_GET_TID(prHifRxHdr
),
2913 prCurrSwRfb
->ucPacketType
,
2914 (UINT_32
)HIF_RX_HDR_GET_80211_FLAG(prHifRxHdr
)));
2916 DBGLOG_MEM8(SW4
, TRACE
, (PUINT_8
)prCurrSwRfb
->pvHeader
, prCurrSwRfb
->u2PacketLen
);
2921 if (!HIF_RX_HDR_GET_80211_FLAG(prHifRxHdr
)){
2923 UINT_8 ucNetTypeIdx
;
2924 P_BSS_INFO_T prBssInfo
;
2926 pucEthDestAddr
= prCurrSwRfb
->pvHeader
;
2927 ucNetTypeIdx
= HIF_RX_HDR_GET_NETWORK_IDX(prHifRxHdr
);
2929 prBssInfo
= &(prAdapter
->rWifiVar
.arBssInfo
[ucNetTypeIdx
]);
2930 //DBGLOG_MEM8(QM, TRACE,prCurrSwRfb->pvHeader, 16);
2933 if (IS_BMCAST_MAC_ADDR(pucEthDestAddr
) && (OP_MODE_ACCESS_POINT
!= prBssInfo
->eCurrentOPMode
)) {
2937 if( prAdapter
->rRxCtrl
.rFreeSwRfbList
.u4NumElem
2938 > (CFG_RX_MAX_PKT_NUM
- CFG_NUM_OF_QM_RX_PKT_NUM
) ) {
2940 if(IS_BSS_ACTIVE(prBssInfo
)) {
2941 if(OP_MODE_ACCESS_POINT
== prBssInfo
->eCurrentOPMode
) {
2942 if (IS_BMCAST_MAC_ADDR(pucEthDestAddr
)){
2943 prCurrSwRfb
->eDst
= RX_PKT_DESTINATION_HOST_WITH_FORWARD
;
2945 else if(UNEQUAL_MAC_ADDR(prBssInfo
->aucOwnMacAddr
,pucEthDestAddr
)) {
2946 prCurrSwRfb
->eDst
= RX_PKT_DESTINATION_FORWARD
;
2947 /* TODO : need to check the dst mac is valid */
2948 /* If src mac is invalid, the packet will be freed in fw */
2950 } /* OP_MODE_ACCESS_POINT */
2951 #if CFG_SUPPORT_HOTSPOT_2_0
2952 else if(hs20IsFrameFilterEnabled(prAdapter
, prBssInfo
) &&
2953 hs20IsUnsecuredFrame(prAdapter
, prBssInfo
, prCurrSwRfb
)) {
2954 DBGLOG(QM
, WARN
, ("Mark NULL the Packet for Dropped Packet %u\n", ucNetTypeIdx
));
2955 prCurrSwRfb
->eDst
= RX_PKT_DESTINATION_NULL
;
2956 QUEUE_INSERT_TAIL(&rReturnedQue
, (P_QUE_ENTRY_T
)prCurrSwRfb
);
2962 DBGLOG(QM
, TRACE
, ("Mark NULL the Packet for inactive Bss %u\n",ucNetTypeIdx
));
2963 prCurrSwRfb
->eDst
= RX_PKT_DESTINATION_NULL
;
2964 QUEUE_INSERT_TAIL(&rReturnedQue
, (P_QUE_ENTRY_T
)prCurrSwRfb
);
2970 /* Dont not occupy other SW RFB */
2971 DBGLOG(QM
, TRACE
, ("Mark NULL the Packet for less Free Sw Rfb\n"));
2972 prCurrSwRfb
->eDst
= RX_PKT_DESTINATION_NULL
;
2973 QUEUE_INSERT_TAIL(&rReturnedQue
, (P_QUE_ENTRY_T
)prCurrSwRfb
);
2978 #if CFG_SUPPORT_WAPI
2979 if (prCurrSwRfb
->u2PacketLen
> ETHER_HEADER_LEN
) {
2980 PUINT_8 pc
= (PUINT_8
) prCurrSwRfb
->pvHeader
;
2981 UINT_16 u2Etype
= 0;
2982 u2Etype
= (pc
[ETH_TYPE_LEN_OFFSET
] << 8) | (pc
[ETH_TYPE_LEN_OFFSET
+ 1]);
2983 /* for wapi integrity test. WPI_1x packet should be always in non-encrypted mode.
2984 if we received any WPI(0x88b4) packet that is encrypted, drop here. */
2985 if (u2Etype
== ETH_WPI_1X
&& HIF_RX_HDR_GET_SEC_MODE(prHifRxHdr
) != 0) {
2986 DBGLOG(QM
, INFO
, ("drop wpi packet with sec mode\n"));
2987 prCurrSwRfb
->eDst
= RX_PKT_DESTINATION_NULL
;
2988 QUEUE_INSERT_TAIL(&rReturnedQue
, (P_QUE_ENTRY_T
) prCurrSwRfb
);
2994 if(HIF_RX_HDR_GET_BAR_FLAG(prHifRxHdr
)){
2995 prCurrSwRfb
->eDst
= RX_PKT_DESTINATION_NULL
;
2996 qmProcessBarFrame(prAdapter
, prCurrSwRfb
, &rReturnedQue
);
2998 /* Reordering is not required for this packet, return it without buffering */
2999 else if(!HIF_RX_HDR_GET_REORDER_FLAG(prHifRxHdr
) || fgIsBMC
){
3001 if (!HIF_RX_HDR_GET_80211_FLAG(prHifRxHdr
)){
3002 UINT_8 ucNetTypeIdx
;
3003 P_BSS_INFO_T prBssInfo
;
3005 pucEthDestAddr
= prCurrSwRfb
->pvHeader
;
3006 ucNetTypeIdx
= HIF_RX_HDR_GET_NETWORK_IDX(prHifRxHdr
);
3008 prBssInfo
= &(prAdapter
->rWifiVar
.arBssInfo
[ucNetTypeIdx
]);
3010 if (IS_BMCAST_MAC_ADDR(pucEthDestAddr
) && (OP_MODE_ACCESS_POINT
== prBssInfo
->eCurrentOPMode
)){
3011 prCurrSwRfb
->eDst
= RX_PKT_DESTINATION_HOST_WITH_FORWARD
;
3015 QUEUE_INSERT_TAIL(&rReturnedQue
, (P_QUE_ENTRY_T
)prCurrSwRfb
);
3017 /* Reordering is required for this packet */
3019 /* If this packet should dropped or indicated to the host immediately,
3020 * it should be enqueued into the rReturnedQue with specific flags. If
3021 * this packet should be buffered for reordering, it should be enqueued
3022 * into the reordering queue in the STA_REC rather than into the
3025 qmProcessPktWithReordering(prAdapter
, prCurrSwRfb
, &rReturnedQue
);
3028 }while(prNextSwRfb
);
3031 /* RX_PKT_DESTINATION_HOST_WITH_FORWARD or RX_PKT_DESTINATION_FORWARD */
3032 /* The returned list of SW_RFBs must end with a NULL pointer */
3033 if(QUEUE_IS_NOT_EMPTY(&rReturnedQue
)){
3034 QM_TX_SET_NEXT_MSDU_INFO((P_SW_RFB_T
)QUEUE_GET_TAIL(&rReturnedQue
), NULL
);
3037 return (P_SW_RFB_T
)QUEUE_GET_HEAD(&rReturnedQue
);
3041 //DbgPrint("QM: Enter qmHandleRxPackets()\n");
3042 return prSwRfbListHead
;
3048 /*----------------------------------------------------------------------------*/
3050 * \brief Reorder the received packet
3052 * \param[in] prSwRfb The RX packet to process
3053 * \param[out] prReturnedQue The queue for indicating packets
3057 /*----------------------------------------------------------------------------*/
3059 qmProcessPktWithReordering(
3060 IN P_ADAPTER_T prAdapter
,
3061 IN P_SW_RFB_T prSwRfb
,
3062 OUT P_QUE_T prReturnedQue
3067 P_STA_RECORD_T prStaRec
;
3068 P_HIF_RX_HEADER_T prHifRxHdr
;
3069 P_RX_BA_ENTRY_T prReorderQueParm
;
3074 P_QUE_T prReorderQue
;
3075 //P_SW_RFB_T prReorderedSwRfb;
3077 DEBUGFUNC("qmProcessPktWithReordering");
3080 ASSERT(prReturnedQue
);
3081 ASSERT(prSwRfb
->prHifRxHdr
);
3083 prHifRxHdr
= prSwRfb
->prHifRxHdr
;
3084 prSwRfb
->ucStaRecIdx
= prHifRxHdr
->ucStaRecIdx
;
3085 prSwRfb
->u2SSN
= HIF_RX_HDR_GET_SN(prHifRxHdr
); /* The new SN of the frame */
3086 prSwRfb
->ucTid
= (UINT_8
)(HIF_RX_HDR_GET_TID(prHifRxHdr
));
3087 //prSwRfb->eDst = RX_PKT_DESTINATION_HOST;
3089 /* Incorrect STA_REC index */
3090 if(prSwRfb
->ucStaRecIdx
>= CFG_NUM_OF_STA_RECORD
){
3091 prSwRfb
->eDst
= RX_PKT_DESTINATION_NULL
;
3092 QUEUE_INSERT_TAIL(prReturnedQue
,(P_QUE_ENTRY_T
)prSwRfb
);
3093 DBGLOG(QM
, WARN
,("Reordering for a NULL STA_REC, ucStaRecIdx = %d\n",
3094 prSwRfb
->ucStaRecIdx
));
3099 /* Check whether the STA_REC is activated */
3100 prStaRec
= &(prAdapter
->arStaRec
[prSwRfb
->ucStaRecIdx
]);
3104 if(!(prStaRec
->fgIsValid
)){
3105 /* TODO: (Tehuang) Handle the Host-FW sync issue. */
3106 prSwRfb
->eDst
= RX_PKT_DESTINATION_NULL
;
3107 QUEUE_INSERT_TAIL(prReturnedQue
,(P_QUE_ENTRY_T
)prSwRfb
);
3108 DBGLOG(QM
, WARN
, ("Reordering for an invalid STA_REC \n"));
3114 /* Check whether the BA agreement exists */
3115 prReorderQueParm
= ((prStaRec
->aprRxReorderParamRefTbl
)[prSwRfb
->ucTid
]);
3116 if(!prReorderQueParm
){
3117 /* TODO: (Tehuang) Handle the Host-FW sync issue.*/
3118 prSwRfb
->eDst
= RX_PKT_DESTINATION_NULL
;
3119 QUEUE_INSERT_TAIL(prReturnedQue
,(P_QUE_ENTRY_T
)prSwRfb
);
3120 DBGLOG(QM
, WARN
,("Reordering for a NULL ReorderQueParm \n"));
3127 /* Start to reorder packets */
3128 u4SeqNo
= (UINT_32
)(prSwRfb
->u2SSN
);
3129 prReorderQue
= &(prReorderQueParm
->rReOrderQue
);
3130 u4WinStart
= (UINT_32
)(prReorderQueParm
->u2WinStart
);
3131 u4WinEnd
= (UINT_32
)(prReorderQueParm
->u2WinEnd
);
3134 //DbgPrint("QM:(R)[%d](%ld){%ld,%ld}\n", prSwRfb->ucTid, u4SeqNo, u4WinStart, u4WinEnd);
3136 /* Case 1: Fall within */
3137 if /* 0 - start - sn - end - 4095 */
3138 (((u4WinStart
<= u4SeqNo
) && (u4SeqNo
<= u4WinEnd
))
3139 /* 0 - end - start - sn - 4095 */
3140 || ((u4WinEnd
< u4WinStart
) && (u4WinStart
<= u4SeqNo
))
3141 /* 0 - sn - end - start - 4095 */
3142 || ((u4SeqNo
<= u4WinEnd
) && (u4WinEnd
< u4WinStart
))){
3144 qmInsertFallWithinReorderPkt(prSwRfb
, prReorderQueParm
, prReturnedQue
);
3146 #if QM_RX_WIN_SSN_AUTO_ADVANCING
3147 if(prReorderQueParm
->fgIsWaitingForPktWithSsn
){
3148 /* Let the first received packet pass the reorder check */
3149 DBGLOG(QM
, LOUD
, ("QM:(A)[%d](%u){%u,%u}\n", prSwRfb
->ucTid
, u4SeqNo
, u4WinStart
, u4WinEnd
));
3151 prReorderQueParm
->u2WinStart
= (UINT_16
)u4SeqNo
;
3152 prReorderQueParm
->u2WinEnd
=
3153 ((prReorderQueParm
->u2WinStart
) + (prReorderQueParm
->u2WinSize
) - 1) % MAX_SEQ_NO_COUNT
;
3154 prReorderQueParm
->fgIsWaitingForPktWithSsn
= FALSE
;
3158 if (qmPopOutDueToFallWithin(prReorderQueParm
, prReturnedQue
) == FALSE
)
3159 STATS_RX_REORDER_HOLE_INC(prStaRec
); /* record hole count */
3161 /* Case 2: Fall ahead */
3163 /* 0 - start - end - sn - (start+2048) - 4095 */
3164 (((u4WinStart
< u4WinEnd
)
3165 && (u4WinEnd
< u4SeqNo
)
3166 && (u4SeqNo
< (u4WinStart
+ HALF_SEQ_NO_COUNT
)))
3167 /* 0 - sn - (start+2048) - start - end - 4095 */
3168 || ((u4SeqNo
< u4WinStart
)
3169 && (u4WinStart
< u4WinEnd
)
3170 && ((u4SeqNo
+ MAX_SEQ_NO_COUNT
) < (u4WinStart
+ HALF_SEQ_NO_COUNT
)))
3171 /* 0 - end - sn - (start+2048) - start - 4095 */
3172 || ((u4WinEnd
< u4SeqNo
)
3173 && (u4SeqNo
< u4WinStart
)
3174 && ((u4SeqNo
+ MAX_SEQ_NO_COUNT
) < (u4WinStart
+ HALF_SEQ_NO_COUNT
)))){
3177 #if QM_RX_WIN_SSN_AUTO_ADVANCING
3178 if(prReorderQueParm
->fgIsWaitingForPktWithSsn
){
3179 prReorderQueParm
->fgIsWaitingForPktWithSsn
= FALSE
;
3183 qmInsertFallAheadReorderPkt(prSwRfb
, prReorderQueParm
, prReturnedQue
);
3185 /* Advance the window after inserting a new tail */
3186 prReorderQueParm
->u2WinEnd
= (UINT_16
)u4SeqNo
;
3187 prReorderQueParm
->u2WinStart
=
3188 (((prReorderQueParm
->u2WinEnd
) - (prReorderQueParm
->u2WinSize
) + MAX_SEQ_NO_COUNT
+ 1)
3189 % MAX_SEQ_NO_COUNT
);
3191 qmPopOutDueToFallAhead(prReorderQueParm
, prReturnedQue
);
3193 STATS_RX_REORDER_FALL_AHEAD_INC(prStaRec
);
3196 /* Case 3: Fall behind */
3199 #if QM_RX_WIN_SSN_AUTO_ADVANCING
3200 #if QM_RX_INIT_FALL_BEHIND_PASS
3201 if(prReorderQueParm
->fgIsWaitingForPktWithSsn
){
3202 //?? prSwRfb->eDst = RX_PKT_DESTINATION_HOST;
3203 QUEUE_INSERT_TAIL(prReturnedQue
,(P_QUE_ENTRY_T
)prSwRfb
);
3204 //DbgPrint("QM:(P)[%d](%ld){%ld,%ld}\n", prSwRfb->ucTid, u4SeqNo, u4WinStart, u4WinEnd);
3210 STATS_RX_REORDER_FALL_BEHIND_INC(prStaRec
);
3211 /* An erroneous packet */
3212 prSwRfb
->eDst
= RX_PKT_DESTINATION_NULL
;
3213 QUEUE_INSERT_TAIL(prReturnedQue
,(P_QUE_ENTRY_T
)prSwRfb
);
3214 //DbgPrint("QM:(D)[%d](%ld){%ld,%ld}\n", prSwRfb->ucTid, u4SeqNo, u4WinStart, u4WinEnd);
3225 IN P_ADAPTER_T prAdapter
,
3226 IN P_SW_RFB_T prSwRfb
,
3227 OUT P_QUE_T prReturnedQue
3231 P_STA_RECORD_T prStaRec
;
3232 P_HIF_RX_HEADER_T prHifRxHdr
;
3233 P_RX_BA_ENTRY_T prReorderQueParm
;
3238 P_QUE_T prReorderQue
;
3239 //P_SW_RFB_T prReorderedSwRfb;
3242 ASSERT(prReturnedQue
);
3243 ASSERT(prSwRfb
->prHifRxHdr
);
3245 prHifRxHdr
= prSwRfb
->prHifRxHdr
;
3246 prSwRfb
->ucStaRecIdx
= prHifRxHdr
->ucStaRecIdx
;
3247 prSwRfb
->u2SSN
= HIF_RX_HDR_GET_SN(prHifRxHdr
); /* The new SSN */
3248 prSwRfb
->ucTid
= (UINT_8
)(HIF_RX_HDR_GET_TID(prHifRxHdr
));
3250 prSwRfb
->eDst
= RX_PKT_DESTINATION_NULL
;
3251 QUEUE_INSERT_TAIL(prReturnedQue
,(P_QUE_ENTRY_T
)prSwRfb
);
3253 /* Incorrect STA_REC index */
3254 if(prSwRfb
->ucStaRecIdx
>= CFG_NUM_OF_STA_RECORD
){
3255 DBGLOG(QM
, WARN
, ("QM: (Warning) BAR for a NULL STA_REC, ucStaRecIdx = %d\n",
3256 prSwRfb
->ucStaRecIdx
));
3261 /* Check whether the STA_REC is activated */
3262 prStaRec
= &(prAdapter
->arStaRec
[prSwRfb
->ucStaRecIdx
]);
3266 if(!(prStaRec
->fgIsValid
)){
3267 /* TODO: (Tehuang) Handle the Host-FW sync issue. */
3268 DbgPrint("QM: (Warning) BAR for an invalid STA_REC \n");
3274 /* Check whether the BA agreement exists */
3275 prReorderQueParm
= ((prStaRec
->aprRxReorderParamRefTbl
)[prSwRfb
->ucTid
]);
3276 if(!prReorderQueParm
){
3277 /* TODO: (Tehuang) Handle the Host-FW sync issue.*/
3278 DBGLOG(QM
, WARN
, ("QM: (Warning) BAR for a NULL ReorderQueParm \n"));
3284 u4SSN
= (UINT_32
)(prSwRfb
->u2SSN
);
3285 prReorderQue
= &(prReorderQueParm
->rReOrderQue
);
3286 u4WinStart
= (UINT_32
)(prReorderQueParm
->u2WinStart
);
3287 u4WinEnd
= (UINT_32
)(prReorderQueParm
->u2WinEnd
);
3289 if(qmCompareSnIsLessThan(u4WinStart
,u4SSN
)){
3290 prReorderQueParm
->u2WinStart
= (UINT_16
)u4SSN
;
3291 prReorderQueParm
->u2WinEnd
=
3292 ((prReorderQueParm
->u2WinStart
) + (prReorderQueParm
->u2WinSize
) - 1) % MAX_SEQ_NO_COUNT
;
3293 DBGLOG(QM
, TRACE
, ("QM:(BAR)[%d](%u){%d,%d}\n", prSwRfb
->ucTid
, u4SSN
, prReorderQueParm
->u2WinStart
, prReorderQueParm
->u2WinEnd
));
3294 qmPopOutDueToFallAhead(prReorderQueParm
, prReturnedQue
);
3297 DBGLOG(QM
, TRACE
, ("QM:(BAR)(%d)(%u){%u,%u}\n", prSwRfb
->ucTid
, u4SSN
, u4WinStart
, u4WinEnd
));
3304 qmInsertFallWithinReorderPkt(
3305 IN P_SW_RFB_T prSwRfb
,
3306 IN P_RX_BA_ENTRY_T prReorderQueParm
,
3307 OUT P_QUE_T prReturnedQue
3310 P_SW_RFB_T prExaminedQueuedSwRfb
;
3311 P_QUE_T prReorderQue
;
3313 ASSERT(prReorderQueParm
);
3314 ASSERT(prReturnedQue
);
3316 prReorderQue
= &(prReorderQueParm
->rReOrderQue
);
3317 prExaminedQueuedSwRfb
= (P_SW_RFB_T
)QUEUE_GET_HEAD(prReorderQue
);
3319 /* There are no packets queued in the Reorder Queue */
3320 if(prExaminedQueuedSwRfb
== NULL
){
3321 ((P_QUE_ENTRY_T
)prSwRfb
)->prPrev
= NULL
;
3322 ((P_QUE_ENTRY_T
)prSwRfb
)->prNext
= NULL
;
3323 prReorderQue
->prHead
= (P_QUE_ENTRY_T
)prSwRfb
;
3324 prReorderQue
->prTail
= (P_QUE_ENTRY_T
)prSwRfb
;
3325 prReorderQue
->u4NumElem
++;
3328 /* Determine the insert position */
3331 /* Case 1: Terminate. A duplicate packet */
3332 if(((prExaminedQueuedSwRfb
->u2SSN
) == (prSwRfb
->u2SSN
))){
3333 prSwRfb
->eDst
= RX_PKT_DESTINATION_NULL
;
3334 QUEUE_INSERT_TAIL(prReturnedQue
,(P_QUE_ENTRY_T
)prSwRfb
);
3338 /* Case 2: Terminate. The insert point is found */
3339 else if(qmCompareSnIsLessThan(
3340 (prSwRfb
->u2SSN
),(prExaminedQueuedSwRfb
->u2SSN
))){
3344 /* Case 3: Insert point not found. Check the next SW_RFB in the Reorder Queue */
3346 prExaminedQueuedSwRfb
=
3347 (P_SW_RFB_T
)(((P_QUE_ENTRY_T
)prExaminedQueuedSwRfb
)->prNext
);
3349 }while(prExaminedQueuedSwRfb
);
3351 /* Update the Reorder Queue Parameters according to the found insert position */
3352 if(prExaminedQueuedSwRfb
== NULL
){
3353 /* The received packet shall be placed at the tail */
3354 ((P_QUE_ENTRY_T
)prSwRfb
)->prPrev
= prReorderQue
->prTail
;
3355 ((P_QUE_ENTRY_T
)prSwRfb
)->prNext
= NULL
;
3356 (prReorderQue
->prTail
)->prNext
= (P_QUE_ENTRY_T
)(prSwRfb
);
3357 prReorderQue
->prTail
= (P_QUE_ENTRY_T
)(prSwRfb
);
3360 ((P_QUE_ENTRY_T
)prSwRfb
)->prPrev
= ((P_QUE_ENTRY_T
)prExaminedQueuedSwRfb
)->prPrev
;
3361 ((P_QUE_ENTRY_T
)prSwRfb
)->prNext
= (P_QUE_ENTRY_T
)prExaminedQueuedSwRfb
;
3362 if(((P_QUE_ENTRY_T
)prExaminedQueuedSwRfb
) == (prReorderQue
->prHead
)){
3363 /* The received packet will become the head */
3364 prReorderQue
->prHead
= (P_QUE_ENTRY_T
)prSwRfb
;
3367 (((P_QUE_ENTRY_T
)prExaminedQueuedSwRfb
)->prPrev
)->prNext
= (P_QUE_ENTRY_T
)prSwRfb
;
3369 ((P_QUE_ENTRY_T
)prExaminedQueuedSwRfb
)->prPrev
= (P_QUE_ENTRY_T
)prSwRfb
;
3372 prReorderQue
->u4NumElem
++;
3380 qmInsertFallAheadReorderPkt(
3381 IN P_SW_RFB_T prSwRfb
,
3382 IN P_RX_BA_ENTRY_T prReorderQueParm
,
3383 OUT P_QUE_T prReturnedQue
3386 P_QUE_T prReorderQue
;
3388 ASSERT(prReorderQueParm
);
3389 ASSERT(prReturnedQue
);
3391 prReorderQue
= &(prReorderQueParm
->rReOrderQue
);
3393 /* There are no packets queued in the Reorder Queue */
3394 if(QUEUE_IS_EMPTY(prReorderQue
)){
3395 ((P_QUE_ENTRY_T
)prSwRfb
)->prPrev
= NULL
;
3396 ((P_QUE_ENTRY_T
)prSwRfb
)->prNext
= NULL
;
3397 prReorderQue
->prHead
= (P_QUE_ENTRY_T
)prSwRfb
;
3400 ((P_QUE_ENTRY_T
)prSwRfb
)->prPrev
= prReorderQue
->prTail
;
3401 ((P_QUE_ENTRY_T
)prSwRfb
)->prNext
= NULL
;
3402 (prReorderQue
->prTail
)->prNext
= (P_QUE_ENTRY_T
)(prSwRfb
);
3404 prReorderQue
->prTail
= (P_QUE_ENTRY_T
)prSwRfb
;
3405 prReorderQue
->u4NumElem
++;
3411 qmPopOutDueToFallWithin(
3412 IN P_RX_BA_ENTRY_T prReorderQueParm
,
3413 OUT P_QUE_T prReturnedQue
3416 P_SW_RFB_T prReorderedSwRfb
;
3417 P_QUE_T prReorderQue
;
3418 BOOLEAN fgDequeuHead
, fgMissing
;
3419 OS_SYSTIME rCurrentTime
, *prMissTimeout
;
3421 prReorderQue
= &(prReorderQueParm
->rReOrderQue
);
3425 prMissTimeout
= &(g_arMissTimeout
[prReorderQueParm
->ucStaRecIdx
][prReorderQueParm
->ucTid
]);
3426 if ((*prMissTimeout
)){
3428 GET_CURRENT_SYSTIME(&rCurrentTime
);
3431 /* Check whether any packet can be indicated to the higher layer */
3433 if(QUEUE_IS_EMPTY(prReorderQue
)){
3437 /* Always examine the head packet */
3438 prReorderedSwRfb
= (P_SW_RFB_T
)QUEUE_GET_HEAD(prReorderQue
);
3439 fgDequeuHead
= FALSE
;
3441 /* SN == WinStart, so the head packet shall be indicated (advance the window) */
3442 if((prReorderedSwRfb
->u2SSN
) == (prReorderQueParm
->u2WinStart
)){
3444 fgDequeuHead
= TRUE
;
3445 prReorderQueParm
->u2WinStart
=
3446 (((prReorderedSwRfb
->u2SSN
) + 1)% MAX_SEQ_NO_COUNT
);
3448 /* SN > WinStart, break to update WinEnd */
3450 if ((fgMissing
== TRUE
) &&
3451 CHECK_FOR_TIMEOUT(rCurrentTime
, (*prMissTimeout
),
3452 MSEC_TO_SYSTIME(QM_RX_BA_ENTRY_MISS_TIMEOUT_MS
))) {
3453 DBGLOG(QM
, TRACE
, ("QM:RX BA Timout Next Tid %d SSN %d\n", prReorderQueParm
->ucTid
, prReorderedSwRfb
->u2SSN
));
3454 fgDequeuHead
= TRUE
;
3455 prReorderQueParm
->u2WinStart
=
3456 (((prReorderedSwRfb
->u2SSN
) + 1)% MAX_SEQ_NO_COUNT
);
3464 /* Dequeue the head packet */
3467 if(((P_QUE_ENTRY_T
)prReorderedSwRfb
)->prNext
== NULL
){
3468 prReorderQue
->prHead
= NULL
;
3469 prReorderQue
->prTail
= NULL
;
3472 prReorderQue
->prHead
= ((P_QUE_ENTRY_T
)prReorderedSwRfb
)->prNext
;
3473 (((P_QUE_ENTRY_T
)prReorderedSwRfb
)->prNext
)->prPrev
= NULL
;
3475 prReorderQue
->u4NumElem
--;
3476 //DbgPrint("QM: [%d] %d (%d)\n", prReorderQueParm->ucTid, prReorderedSwRfb->u2PacketLen, prReorderedSwRfb->u2SSN);
3477 QUEUE_INSERT_TAIL(prReturnedQue
,(P_QUE_ENTRY_T
)prReorderedSwRfb
);
3481 if (QUEUE_IS_EMPTY(prReorderQue
)){
3485 if (fgMissing
== FALSE
) {
3486 GET_CURRENT_SYSTIME(prMissTimeout
);
3490 /* After WinStart has been determined, update the WinEnd */
3491 prReorderQueParm
->u2WinEnd
=
3492 (((prReorderQueParm
->u2WinStart
) + (prReorderQueParm
->u2WinSize
) -1 )% MAX_SEQ_NO_COUNT
);
3493 return QUEUE_IS_EMPTY(prReorderQue
);
3497 qmPopOutDueToFallAhead(
3498 IN P_RX_BA_ENTRY_T prReorderQueParm
,
3499 OUT P_QUE_T prReturnedQue
3502 P_SW_RFB_T prReorderedSwRfb
;
3503 P_QUE_T prReorderQue
;
3504 BOOLEAN fgDequeuHead
;
3506 prReorderQue
= &(prReorderQueParm
->rReOrderQue
);
3508 /* Check whether any packet can be indicated to the higher layer */
3510 if(QUEUE_IS_EMPTY(prReorderQue
)){
3514 /* Always examine the head packet */
3515 prReorderedSwRfb
= (P_SW_RFB_T
)QUEUE_GET_HEAD(prReorderQue
);
3516 fgDequeuHead
= FALSE
;
3518 /* SN == WinStart, so the head packet shall be indicated (advance the window) */
3519 if((prReorderedSwRfb
->u2SSN
) == (prReorderQueParm
->u2WinStart
)){
3521 fgDequeuHead
= TRUE
;
3522 prReorderQueParm
->u2WinStart
=
3523 (((prReorderedSwRfb
->u2SSN
) + 1)% MAX_SEQ_NO_COUNT
);
3526 /* SN < WinStart, so the head packet shall be indicated (do not advance the window) */
3527 else if(qmCompareSnIsLessThan(
3528 (UINT_32
)(prReorderedSwRfb
->u2SSN
),
3529 (UINT_32
)(prReorderQueParm
->u2WinStart
))){
3531 fgDequeuHead
= TRUE
;
3535 /* SN > WinStart, break to update WinEnd */
3541 /* Dequeue the head packet */
3544 if(((P_QUE_ENTRY_T
)prReorderedSwRfb
)->prNext
== NULL
){
3545 prReorderQue
->prHead
= NULL
;
3546 prReorderQue
->prTail
= NULL
;
3549 prReorderQue
->prHead
= ((P_QUE_ENTRY_T
)prReorderedSwRfb
)->prNext
;
3550 (((P_QUE_ENTRY_T
)prReorderedSwRfb
)->prNext
)->prPrev
= NULL
;
3552 prReorderQue
->u4NumElem
--;
3553 //DbgPrint("QM: [%d] %d (%d)\n", prReorderQueParm->ucTid, prReorderedSwRfb->u2PacketLen, prReorderedSwRfb->u2SSN);
3554 QUEUE_INSERT_TAIL(prReturnedQue
,(P_QUE_ENTRY_T
)prReorderedSwRfb
);
3558 /* After WinStart has been determined, update the WinEnd */
3559 prReorderQueParm
->u2WinEnd
=
3560 (((prReorderQueParm
->u2WinStart
) + (prReorderQueParm
->u2WinSize
) -1)% MAX_SEQ_NO_COUNT
);
3565 qmCompareSnIsLessThan(
3566 IN UINT_32 u4SnLess
,
3567 IN UINT_32 u4SnGreater
3570 /* 0 <---> SnLess <--(gap>2048)--> SnGreater : SnLess > SnGreater */
3571 if((u4SnLess
+ HALF_SEQ_NO_COUNT
) <= u4SnGreater
){ /* Shall be <= */
3575 /* 0 <---> SnGreater <--(gap>2048)--> SnLess : SnLess < SnGreater */
3576 else if((u4SnGreater
+ HALF_SEQ_NO_COUNT
) < u4SnLess
){
3580 /* 0 <---> SnGreater <--(gap<2048)--> SnLess : SnLess > SnGreater */
3581 /* 0 <---> SnLess <--(gap<2048)--> SnGreater : SnLess < SnGreater */
3583 return (u4SnLess
< u4SnGreater
);
3588 /*----------------------------------------------------------------------------*/
3590 * \brief Handle Mailbox RX messages
3592 * \param[in] prMailboxRxMsg The received Mailbox message from the FW
3596 /*----------------------------------------------------------------------------*/
3598 qmHandleMailboxRxMessage(
3599 IN MAILBOX_MSG_T prMailboxRxMsg
3602 //DbgPrint("QM: Enter qmHandleMailboxRxMessage()\n");
3607 /*----------------------------------------------------------------------------*/
3609 * \brief Handle ADD RX BA Event from the FW
3611 * \param[in] prAdapter Adapter pointer
3612 * \param[in] prEvent The event packet from the FW
3616 /*----------------------------------------------------------------------------*/
3618 qmHandleEventRxAddBa(
3619 IN P_ADAPTER_T prAdapter
,
3620 IN P_WIFI_EVENT_T prEvent
3623 P_EVENT_RX_ADDBA_T prEventRxAddBa
;
3624 P_STA_RECORD_T prStaRec
;
3628 DBGLOG(QM
, INFO
, ("QM:Event +RxBa\n"));
3630 prEventRxAddBa
= (P_EVENT_RX_ADDBA_T
)prEvent
;
3631 prStaRec
= QM_GET_STA_REC_PTR_FROM_INDEX(prAdapter
, prEventRxAddBa
->ucStaRecIdx
);
3634 /* Invalid STA_REC index, discard the event packet */
3636 DBGLOG(QM
, INFO
, ("QM: (Warning) RX ADDBA Event for a NULL STA_REC\n"));
3641 if(!(prStaRec
->fgIsValid
)){
3642 /* TODO: (Tehuang) Handle the Host-FW synchronization issue */
3643 DBGLOG(QM
, WARN
, ("QM: (Warning) RX ADDBA Event for an invalid STA_REC\n"));
3649 u4Tid
= (((prEventRxAddBa
->u2BAParameterSet
)& BA_PARAM_SET_TID_MASK
)
3650 >> BA_PARAM_SET_TID_MASK_OFFSET
);
3652 u4WinSize
= (((prEventRxAddBa
->u2BAParameterSet
)& BA_PARAM_SET_BUFFER_SIZE_MASK
)
3653 >> BA_PARAM_SET_BUFFER_SIZE_MASK_OFFSET
);
3659 (prEventRxAddBa
->u2BAStartSeqCtrl
>> OFFSET_BAR_SSC_SN
),
3660 (UINT_16
)u4WinSize
)){
3662 /* FW shall ensure the availabiilty of the free-to-use BA entry */
3663 DBGLOG(QM
, ERROR
, ("QM: (Error) qmAddRxBaEntry() failure\n"));
3669 /*----------------------------------------------------------------------------*/
3671 * \brief Handle DEL RX BA Event from the FW
3673 * \param[in] prAdapter Adapter pointer
3674 * \param[in] prEvent The event packet from the FW
3678 /*----------------------------------------------------------------------------*/
3680 qmHandleEventRxDelBa(
3681 IN P_ADAPTER_T prAdapter
,
3682 IN P_WIFI_EVENT_T prEvent
3685 P_EVENT_RX_DELBA_T prEventRxDelBa
;
3686 P_STA_RECORD_T prStaRec
;
3688 //DbgPrint("QM:Event -RxBa\n");
3690 prEventRxDelBa
= (P_EVENT_RX_DELBA_T
)prEvent
;
3691 prStaRec
= QM_GET_STA_REC_PTR_FROM_INDEX(prAdapter
, prEventRxDelBa
->ucStaRecIdx
);
3694 /* Invalid STA_REC index, discard the event packet */
3700 if(!(prStaRec
->fgIsValid
)){
3701 /* TODO: (Tehuang) Handle the Host-FW synchronization issue */
3707 qmDelRxBaEntry(prAdapter
, prStaRec
->ucIndex
, prEventRxDelBa
->ucTid
, TRUE
);
3713 IN P_ADAPTER_T prAdapter
,
3719 P_QUE_MGT_T prQM
= &prAdapter
->rQM
;
3721 //DbgPrint("QM: Enter qmLookupRxBaEntry()\n");
3723 for(i
=0; i
<CFG_NUM_OF_RX_BA_AGREEMENTS
; i
++){
3724 if(prQM
->arRxBaTable
[i
].fgIsValid
){
3725 if((prQM
->arRxBaTable
[i
].ucStaRecIdx
== ucStaRecIdx
) &&
3726 (prQM
->arRxBaTable
[i
].ucTid
== ucTid
)){
3727 return &prQM
->arRxBaTable
[i
];
3736 IN P_ADAPTER_T prAdapter
,
3737 IN UINT_8 ucStaRecIdx
,
3739 IN UINT_16 u2WinStart
,
3740 IN UINT_16 u2WinSize
3744 P_RX_BA_ENTRY_T prRxBaEntry
= NULL
;
3745 P_STA_RECORD_T prStaRec
;
3746 P_QUE_MGT_T prQM
= &prAdapter
->rQM
;
3748 ASSERT(ucStaRecIdx
< CFG_NUM_OF_STA_RECORD
);
3750 if(ucStaRecIdx
>= CFG_NUM_OF_STA_RECORD
){
3751 /* Invalid STA_REC index, discard the event packet */
3752 DBGLOG(QM
, WARN
, ("QM: (WARNING) RX ADDBA Event for a invalid ucStaRecIdx = %d\n", ucStaRecIdx
));
3756 prStaRec
= &prAdapter
->arStaRec
[ucStaRecIdx
];
3759 //if(!(prStaRec->fgIsValid)){
3760 // DbgPrint("QM: (WARNING) Invalid STA when adding an RX BA \n");
3764 //4 <1> Delete before adding
3765 /* Remove the BA entry for the same (STA, TID) tuple if it exists */
3766 if(qmLookupRxBaEntry(prAdapter
, ucStaRecIdx
,ucTid
)){
3767 qmDelRxBaEntry(prAdapter
, ucStaRecIdx
, ucTid
, TRUE
); /* prQM->ucRxBaCount-- */
3770 //4 <2> Add a new BA entry
3771 /* No available entry to store the BA agreement info. Retrun FALSE. */
3772 if(prQM
->ucRxBaCount
>= CFG_NUM_OF_RX_BA_AGREEMENTS
){
3773 DBGLOG(QM
, ERROR
, ("QM: **failure** (limited resource, ucRxBaCount=%d)\n", prQM
->ucRxBaCount
));
3777 /* Find the free-to-use BA entry */
3778 for(i
=0; i
<CFG_NUM_OF_RX_BA_AGREEMENTS
; i
++){
3779 if(!prQM
->arRxBaTable
[i
].fgIsValid
){
3780 prRxBaEntry
= &(prQM
->arRxBaTable
[i
]);
3781 prQM
->ucRxBaCount
++;
3782 DBGLOG(QM
, LOUD
, ("QM: ucRxBaCount=%d\n", prQM
->ucRxBaCount
));
3787 /* If a free-to-use entry is found, configure it and associate it with the STA_REC */
3788 u2WinSize
+= CFG_RX_BA_INC_SIZE
;
3790 prRxBaEntry
->ucStaRecIdx
= ucStaRecIdx
;
3791 prRxBaEntry
->ucTid
= ucTid
;
3792 prRxBaEntry
->u2WinStart
= u2WinStart
;
3793 prRxBaEntry
->u2WinSize
= u2WinSize
;
3794 prRxBaEntry
->u2WinEnd
= ((u2WinStart
+ u2WinSize
- 1) % MAX_SEQ_NO_COUNT
);
3795 prRxBaEntry
->fgIsValid
= TRUE
;
3796 prRxBaEntry
->fgIsWaitingForPktWithSsn
= TRUE
;
3798 g_arMissTimeout
[ucStaRecIdx
][ucTid
] = 0;
3800 DBGLOG(QM
, INFO
, ("QM: +RxBA(STA=%d TID=%d WinStart=%d WinEnd=%d WinSize=%d)\n",
3802 prRxBaEntry
->u2WinStart
, prRxBaEntry
->u2WinEnd
, prRxBaEntry
->u2WinSize
));
3804 /* Update the BA entry reference table for per-packet lookup */
3805 prStaRec
->aprRxReorderParamRefTbl
[ucTid
] = prRxBaEntry
;
3808 /* This shall not happen because FW should keep track of the usage of RX BA entries */
3809 DBGLOG(QM
, ERROR
, ("QM: **AddBA Error** (ucRxBaCount=%d)\n", prQM
->ucRxBaCount
));
3818 IN P_ADAPTER_T prAdapter
,
3819 IN UINT_8 ucStaRecIdx
,
3821 IN BOOLEAN fgFlushToHost
3824 P_RX_BA_ENTRY_T prRxBaEntry
;
3825 P_STA_RECORD_T prStaRec
;
3826 P_SW_RFB_T prFlushedPacketList
= NULL
;
3827 P_QUE_MGT_T prQM
= &prAdapter
->rQM
;
3829 ASSERT(ucStaRecIdx
< CFG_NUM_OF_STA_RECORD
);
3831 prStaRec
= &prAdapter
->arStaRec
[ucStaRecIdx
];
3835 if(!(prStaRec
->fgIsValid
)){
3836 DbgPrint("QM: (WARNING) Invalid STA when deleting an RX BA \n");
3841 /* Remove the BA entry for the same (STA, TID) tuple if it exists */
3842 prRxBaEntry
= prStaRec
->aprRxReorderParamRefTbl
[ucTid
];
3846 prFlushedPacketList
= qmFlushStaRxQueue(prAdapter
, ucStaRecIdx
, ucTid
);
3848 if(prFlushedPacketList
){
3851 wlanProcessQueuedSwRfb(prAdapter
, prFlushedPacketList
);
3856 P_SW_RFB_T prNextSwRfb
;
3857 prSwRfb
= prFlushedPacketList
;
3860 prNextSwRfb
= (P_SW_RFB_T
)QUEUE_GET_NEXT_ENTRY((P_QUE_ENTRY_T
)prSwRfb
);
3861 nicRxReturnRFB(prAdapter
, prSwRfb
);
3862 prSwRfb
= prNextSwRfb
;
3869 #if ((QM_TEST_MODE == 0) && (QM_TEST_STA_REC_DEACTIVATION == 0))
3870 /* Update RX BA entry state. Note that RX queue flush is not done here */
3871 prRxBaEntry
->fgIsValid
= FALSE
;
3872 prQM
->ucRxBaCount
--;
3876 DbgPrint("QM: ucRxBaCount=%d\n", prQM
->ucRxBaCount
);
3879 /* Update STA RX BA table */
3880 prStaRec
->aprRxReorderParamRefTbl
[ucTid
] = NULL
;
3883 DBGLOG(QM
, INFO
, ("QM: -RxBA(STA=%d,TID=%d)\n", ucStaRecIdx
, ucTid
));
3889 #if CFG_HIF_RX_STARVATION_WARNING
3891 P_RX_CTRL_T prRxCtrl
;
3892 prRxCtrl
= &prAdapter
->rRxCtrl
;
3893 DBGLOG(QM
, TRACE
, ("QM: (RX DEBUG) Enqueued: %d / Dequeued: %d\n", prRxCtrl
->u4QueuedCnt
, prRxCtrl
->u4DequeuedCnt
));
3899 /*----------------------------------------------------------------------------*/
3901 * \brief To process WMM related IEs in ASSOC_RSP
3903 * \param[in] prAdapter Adapter pointer
3904 * \param[in] prSwRfb The received frame
3905 * \param[in] pucIE The pointer to the first IE in the frame
3906 * \param[in] u2IELength The total length of IEs in the frame
3910 /*----------------------------------------------------------------------------*/
3912 mqmProcessAssocReq (
3913 IN P_ADAPTER_T prAdapter
,
3914 IN P_SW_RFB_T prSwRfb
,
3916 IN UINT_16 u2IELength
3919 P_STA_RECORD_T prStaRec
;
3922 UINT_8 aucWfaOui
[] = VENDOR_OUI_WFA
;
3923 P_IE_WMM_INFO_T prIeWmmInfo
;
3925 DEBUGFUNC("mqmProcessAssocReq");
3930 prStaRec
= cnmGetStaRecByIndex(prAdapter
, prSwRfb
->ucStaRecIdx
);
3933 if(prStaRec
== NULL
) {
3937 prStaRec
->fgIsQoS
= FALSE
;
3938 prStaRec
->fgIsWmmSupported
= prStaRec
->fgIsUapsdSupported
= FALSE
;
3942 /* If the device does not support QoS or if WMM is not supported by the peer, exit.*/
3943 if (!prAdapter
->rWifiVar
.fgSupportQoS
) {
3948 /* Determine whether QoS is enabled with the association */
3950 IE_FOR_EACH(pucIE
, u2IELength
, u2Offset
) {
3951 switch (IE_ID(pucIE
)) {
3954 if((WMM_IE_OUI_TYPE(pucIE
) == VENDOR_OUI_TYPE_WMM
) &&
3955 (!kalMemCmp(WMM_IE_OUI(pucIE
),aucWfaOui
,3))){
3957 switch(WMM_IE_OUI_SUBTYPE(pucIE
)){
3958 case VENDOR_OUI_SUBTYPE_WMM_INFO
:
3964 if(IE_LEN(pucIE
) != 7){
3965 break; /* WMM Info IE with a wrong length */
3967 prStaRec
->fgIsQoS
= TRUE
;
3968 prStaRec
->fgIsWmmSupported
= TRUE
;
3970 prIeWmmInfo
= (P_IE_WMM_INFO_T
)pucIE
;
3971 ucQosInfo
= prIeWmmInfo
->ucQosInfo
;
3972 ucQosInfoAC
= ucQosInfo
& BITS(0, 3);
3974 prStaRec
->fgIsUapsdSupported
= ((ucQosInfoAC
)? TRUE
: FALSE
) &
3975 prAdapter
->rWifiVar
.fgSupportUAPSD
;
3979 if( ucQosInfoAC
& WMM_QOS_INFO_VO_UAPSD
) {
3980 ucBmpAC
|= BIT(ACI_VO
);
3982 if( ucQosInfoAC
& WMM_QOS_INFO_VI_UAPSD
) {
3983 ucBmpAC
|= BIT(ACI_VI
);
3985 if( ucQosInfoAC
& WMM_QOS_INFO_BE_UAPSD
) {
3986 ucBmpAC
|= BIT(ACI_BE
);
3988 if( ucQosInfoAC
& WMM_QOS_INFO_BK_UAPSD
) {
3989 ucBmpAC
|= BIT(ACI_BK
);
3992 prStaRec
->ucBmpTriggerAC
= prStaRec
->ucBmpDeliveryAC
= ucBmpAC
;
3994 prStaRec
->ucUapsdSp
= (ucQosInfo
& WMM_QOS_INFO_MAX_SP_LEN_MASK
) >> 5;
4000 /* Other WMM QoS IEs. Ignore any */
4004 /* else: VENDOR_OUI_TYPE_WPA, VENDOR_OUI_TYPE_WPS */
4008 case ELEM_ID_HT_CAP
:
4009 /* Some client won't put the WMM IE if client is 802.11n */
4010 if (IE_LEN(pucIE
) == (sizeof(IE_HT_CAP_T
) - 2)) {
4011 prStaRec
->fgIsQoS
= TRUE
;
4019 DBGLOG(QM
, TRACE
, ("MQM: Assoc_Req Parsing (QoS Enabled=%d)\n", prStaRec
->fgIsQoS
));
4025 /*----------------------------------------------------------------------------*/
4027 * \brief To process WMM related IEs in ASSOC_RSP
4029 * \param[in] prAdapter Adapter pointer
4030 * \param[in] prSwRfb The received frame
4031 * \param[in] pucIE The pointer to the first IE in the frame
4032 * \param[in] u2IELength The total length of IEs in the frame
4036 /*----------------------------------------------------------------------------*/
4038 mqmProcessAssocRsp (
4039 IN P_ADAPTER_T prAdapter
,
4040 IN P_SW_RFB_T prSwRfb
,
4042 IN UINT_16 u2IELength
4045 P_STA_RECORD_T prStaRec
;
4048 UINT_8 aucWfaOui
[] = VENDOR_OUI_WFA
;
4050 DEBUGFUNC("mqmProcessAssocRsp");
4055 prStaRec
= cnmGetStaRecByIndex(prAdapter
, prSwRfb
->ucStaRecIdx
);
4058 if(prStaRec
== NULL
) {
4062 prStaRec
->fgIsQoS
= FALSE
;
4066 DBGLOG(QM
, TRACE
, ("QM: (fgIsWmmSupported=%d, fgSupportQoS=%d)\n",
4067 prStaRec
->fgIsWmmSupported
, prAdapter
->rWifiVar
.fgSupportQoS
));
4069 /* If the device does not support QoS or if WMM is not supported by the peer, exit.*/
4070 //if((!prAdapter->rWifiVar.fgSupportQoS) || (!prStaRec->fgIsWmmSupported))
4071 if((!prAdapter
->rWifiVar
.fgSupportQoS
))
4076 /* Determine whether QoS is enabled with the association */
4078 IE_FOR_EACH(pucIE
, u2IELength
, u2Offset
) {
4079 switch (IE_ID(pucIE
)) {
4081 if((WMM_IE_OUI_TYPE(pucIE
) == VENDOR_OUI_TYPE_WMM
) &&
4082 (!kalMemCmp(WMM_IE_OUI(pucIE
),aucWfaOui
,3))){
4084 switch(WMM_IE_OUI_SUBTYPE(pucIE
)){
4085 case VENDOR_OUI_SUBTYPE_WMM_PARAM
:
4086 if(IE_LEN(pucIE
) != 24){
4087 break; /* WMM Info IE with a wrong length */
4089 prStaRec
->fgIsQoS
= TRUE
;
4092 case VENDOR_OUI_SUBTYPE_WMM_INFO
:
4093 if(IE_LEN(pucIE
) != 7){
4094 break; /* WMM Info IE with a wrong length */
4096 prStaRec
->fgIsQoS
= TRUE
;
4100 /* Other WMM QoS IEs. Ignore any */
4104 /* else: VENDOR_OUI_TYPE_WPA, VENDOR_OUI_TYPE_WPS */
4107 case ELEM_ID_HT_CAP
:
4108 /* Some AP won't put the WMM IE if client is 802.11n */
4109 if ( IE_LEN(pucIE
) == (sizeof(IE_HT_CAP_T
) - 2)) {
4110 prStaRec
->fgIsQoS
= TRUE
;
4118 /* Parse AC parameters and write to HW CRs */
4119 if((prStaRec
->fgIsQoS
) && (prStaRec
->eStaType
== STA_TYPE_LEGACY_AP
)){
4120 mqmParseEdcaParameters(prAdapter
, prSwRfb
, pucIEStart
, u2IELength
, TRUE
);
4123 DBGLOG(QM
, TRACE
, ("MQM: Assoc_Rsp Parsing (QoS Enabled=%d)\n", prStaRec
->fgIsQoS
));
4124 if(prStaRec
->fgIsWmmSupported
) {
4125 nicQmUpdateWmmParms(prAdapter
, prStaRec
->ucNetTypeIndex
);
4131 /*----------------------------------------------------------------------------*/
4133 * \brief To parse WMM Parameter IE (in BCN or Assoc_Rsp)
4135 * \param[in] prAdapter Adapter pointer
4136 * \param[in] prSwRfb The received frame
4137 * \param[in] pucIE The pointer to the first IE in the frame
4138 * \param[in] u2IELength The total length of IEs in the frame
4139 * \param[in] fgForceOverride TRUE: If EDCA parameters are found, always set to HW CRs.
4143 /*----------------------------------------------------------------------------*/
4145 mqmParseEdcaParameters (
4146 IN P_ADAPTER_T prAdapter
,
4147 IN P_SW_RFB_T prSwRfb
,
4149 IN UINT_16 u2IELength
,
4150 IN BOOLEAN fgForceOverride
4153 P_STA_RECORD_T prStaRec
;
4155 UINT_8 aucWfaOui
[] = VENDOR_OUI_WFA
;
4156 P_BSS_INFO_T prBssInfo
;
4158 DEBUGFUNC("mqmParseEdcaParameters");
4163 prStaRec
= cnmGetStaRecByIndex(prAdapter
, prSwRfb
->ucStaRecIdx
);
4166 if(prStaRec
== NULL
) {
4170 DBGLOG(QM
, TRACE
, ("QM: (fgIsWmmSupported=%d, fgIsQoS=%d)\n",
4171 prStaRec
->fgIsWmmSupported
, prStaRec
->fgIsQoS
));
4173 if((!prAdapter
->rWifiVar
.fgSupportQoS
) || (!prStaRec
->fgIsWmmSupported
) || (!prStaRec
->fgIsQoS
)){
4177 prBssInfo
= &(prAdapter
->rWifiVar
.arBssInfo
[prStaRec
->ucNetTypeIndex
]);
4179 /* Goal: Obtain the EDCA parameters */
4180 IE_FOR_EACH(pucIE
, u2IELength
, u2Offset
) {
4181 switch (IE_ID(pucIE
)) {
4184 if((WMM_IE_OUI_TYPE(pucIE
) == VENDOR_OUI_TYPE_WMM
) &&
4185 (!kalMemCmp(WMM_IE_OUI(pucIE
),aucWfaOui
,3))){
4187 switch(WMM_IE_OUI_SUBTYPE(pucIE
)){
4188 case VENDOR_OUI_SUBTYPE_WMM_PARAM
:
4189 if(IE_LEN(pucIE
) != 24){
4190 break; /* WMM Param IE with a wrong length */
4193 P_AC_QUE_PARMS_T prAcQueParams
;
4194 P_IE_WMM_PARAM_T prIeWmmParam
;
4195 ENUM_WMM_ACI_T eAci
;
4196 PUINT_8 pucWmmParamSetCount
;
4199 pucWmmParamSetCount
= &(prBssInfo
->ucWmmParamSetCount
);
4201 prIeWmmParam
= (P_IE_WMM_PARAM_T
)pucIE
;
4203 /* Check the Parameter Set Count to determine whether EDCA parameters have been changed */
4204 if(!fgForceOverride
){
4205 if(*pucWmmParamSetCount
== (prIeWmmParam
->ucQosInfo
& WMM_QOS_INFO_PARAM_SET_CNT
)){
4206 break; /* Ignore the IE without updating HW CRs */
4210 /* Update Parameter Set Count */
4211 *pucWmmParamSetCount
= (prIeWmmParam
->ucQosInfo
& WMM_QOS_INFO_PARAM_SET_CNT
);
4213 /* Update EDCA parameters */
4214 for(eAci
= 0; eAci
< WMM_AC_INDEX_NUM
; eAci
++){
4216 prAcQueParams
= &prBssInfo
->arACQueParms
[eAci
];
4217 mqmFillAcQueParam(prIeWmmParam
, eAci
, prAcQueParams
);
4219 prAcQueParams
->fgIsACMSet
=
4220 (prAcQueParams
->u2Aifsn
& WMM_ACIAIFSN_ACM
) ? TRUE
: FALSE
;
4221 prAcQueParams
->u2Aifsn
&= WMM_ACIAIFSN_AIFSN
;
4223 DBGLOG(QM
, LOUD
, ("MQM: eAci = %d, ACM = %d, Aifsn = %d, CWmin = %d, CWmax = %d, TxopLimit = %d\n",
4224 eAci
, prAcQueParams
->fgIsACMSet
,
4225 prAcQueParams
->u2Aifsn
, prAcQueParams
->u2CWmin
,
4226 prAcQueParams
->u2CWmax
, prAcQueParams
->u2TxopLimit
));
4232 /* Other WMM QoS IEs. Ignore */
4237 /* else: VENDOR_OUI_TYPE_WPA, VENDOR_OUI_TYPE_WPS, ... (not cared) */
4246 /*----------------------------------------------------------------------------*/
4248 * \brief This function is used for parsing EDCA parameters specified in the WMM Parameter IE
4250 * \param[in] prAdapter Adapter pointer
4251 * \param[in] prIeWmmParam The pointer to the WMM Parameter IE
4252 * \param[in] u4AcOffset The offset specifying the AC queue for parsing
4253 * \param[in] prHwAcParams The parameter structure used to configure the HW CRs
4257 /*----------------------------------------------------------------------------*/
4260 IN P_IE_WMM_PARAM_T prIeWmmParam
,
4261 IN UINT_32 u4AcOffset
,
4262 OUT P_AC_QUE_PARMS_T prAcQueParams
4265 prAcQueParams
->u2Aifsn
= *((PUINT_8
)(&(prIeWmmParam
->ucAciAifsn_BE
)) + (u4AcOffset
* 4));
4267 prAcQueParams
->u2CWmax
=
4268 BIT(((*((PUINT_8
)(&(prIeWmmParam
->ucEcw_BE
)) + (u4AcOffset
* 4))) & WMM_ECW_WMAX_MASK
)
4269 >> WMM_ECW_WMAX_OFFSET
)-1;
4271 prAcQueParams
->u2CWmin
=
4272 BIT((*((PUINT_8
)(&(prIeWmmParam
->ucEcw_BE
)) + (u4AcOffset
* 4))) & WMM_ECW_WMIN_MASK
)-1;
4274 WLAN_GET_FIELD_16(((PUINT_8
)(&(prIeWmmParam
->aucTxopLimit_BE
)) + (u4AcOffset
* 4)),&(prAcQueParams
->u2TxopLimit
));
4276 prAcQueParams
->ucGuradTime
= TXM_DEFAULT_FLUSH_QUEUE_GUARD_TIME
;
4282 /*----------------------------------------------------------------------------*/
4284 * \brief To parse WMM/11n related IEs in scan results (only for AP peers)
4286 * \param[in] prAdapter Adapter pointer
4287 * \param[in] prScanResult The scan result which shall be parsed to obtain needed info
4288 * \param[out] prStaRec The obtained info is stored in the STA_REC
4292 /*----------------------------------------------------------------------------*/
4293 #if (CFG_SUPPORT_TDLS == 1) /* for test purpose */
4294 BOOLEAN flgTdlsTestExtCapElm
= FALSE
;
4295 UINT8 aucTdlsTestExtCapElm
[7];
4296 #endif /* CFG_SUPPORT_TDLS */
4298 mqmProcessScanResult(
4299 IN P_ADAPTER_T prAdapter
,
4300 IN P_BSS_DESC_T prScanResult
,
4301 OUT P_STA_RECORD_T prStaRec
4307 UINT_8 aucWfaOui
[] = VENDOR_OUI_WFA
;
4309 DEBUGFUNC("mqmProcessScanResult");
4311 ASSERT(prScanResult
);
4314 /* Reset the flag before parsing */
4315 prStaRec
->fgIsWmmSupported
= prStaRec
->fgIsUapsdSupported
= FALSE
;
4317 if (!prAdapter
->rWifiVar
.fgSupportQoS
){
4321 u2IELength
= prScanResult
->u2IELength
;
4322 pucIE
= prScanResult
->aucIEBuf
;
4324 #if (CFG_SUPPORT_TDLS == 1)
4325 /* TDLS test purpose */
4326 if (flgTdlsTestExtCapElm
== TRUE
)
4327 TdlsexBssExtCapParse(prStaRec
, aucTdlsTestExtCapElm
);
4328 #endif /* CFG_SUPPORT_TDLS */
4330 /* Goal: Determine whether the peer supports WMM/QoS and UAPSDU */
4331 IE_FOR_EACH(pucIE
, u2IELength
, u2Offset
) {
4332 switch (IE_ID(pucIE
)) {
4333 case ELEM_ID_EXTENDED_CAP
:
4334 #if (CFG_SUPPORT_TDLS == 1)
4335 TdlsexBssExtCapParse(prStaRec
, pucIE
);
4336 #endif /* CFG_SUPPORT_TDLS */
4340 if((WMM_IE_OUI_TYPE(pucIE
) == VENDOR_OUI_TYPE_WMM
) &&
4341 (!kalMemCmp(WMM_IE_OUI(pucIE
),aucWfaOui
,3))){
4343 switch(WMM_IE_OUI_SUBTYPE(pucIE
)){
4344 case VENDOR_OUI_SUBTYPE_WMM_PARAM
:
4345 if(IE_LEN(pucIE
) != 24){
4346 break; /* WMM Param IE with a wrong length */
4349 prStaRec
->fgIsWmmSupported
= TRUE
;
4350 prStaRec
->fgIsUapsdSupported
= (((((P_IE_WMM_PARAM_T
)pucIE
)->ucQosInfo
) & WMM_QOS_INFO_UAPSD
)? TRUE
: FALSE
);
4354 case VENDOR_OUI_SUBTYPE_WMM_INFO
:
4355 if(IE_LEN(pucIE
) != 7){
4356 break; /* WMM Info IE with a wrong length */
4359 prStaRec
->fgIsWmmSupported
= TRUE
;
4360 prStaRec
->fgIsUapsdSupported
= (((((P_IE_WMM_INFO_T
)pucIE
)->ucQosInfo
) & WMM_QOS_INFO_UAPSD
)? TRUE
: FALSE
);
4365 /* A WMM QoS IE that doesn't matter. Ignore it. */
4369 /* else: VENDOR_OUI_TYPE_WPA, VENDOR_OUI_TYPE_WPS, ... (not cared) */
4374 /* A WMM IE that doesn't matter. Ignore it. */
4378 DBGLOG(QM
, LOUD
, ("MQM: Scan Result Parsing (WMM=%d, UAPSD=%d)\n",
4379 prStaRec
->fgIsWmmSupported
, prStaRec
->fgIsUapsdSupported
));
4385 IN P_ADAPTER_T prAdapter
,
4386 IN PUINT_8 pucEthDestAddr
,
4387 IN ENUM_NETWORK_TYPE_INDEX_T eNetworkType
4391 P_STA_RECORD_T prTempStaRec
;
4393 prTempStaRec
= NULL
;
4398 if(IS_BMCAST_MAC_ADDR(pucEthDestAddr
)){
4399 return STA_REC_INDEX_BMCAST
;
4403 //4 <2> Check if an AP STA is present
4404 for(i
= 0; i
< CFG_NUM_OF_STA_RECORD
; i
++){
4405 prTempStaRec
= &(prAdapter
->arStaRec
[i
]);
4406 if((prTempStaRec
->ucNetTypeIndex
== eNetworkType
)
4407 && (prTempStaRec
->fgIsAp
)
4408 && (prTempStaRec
->fgIsValid
)){
4409 return prTempStaRec
->ucIndex
;
4413 //4 <3> Not BMCAST, No AP --> Compare DA (i.e., to see whether this is a unicast frame to a client)
4414 for(i
= 0; i
< CFG_NUM_OF_STA_RECORD
; i
++){
4415 prTempStaRec
= &(prAdapter
->arStaRec
[i
]);
4416 if(prTempStaRec
->fgIsValid
){
4417 if(EQUAL_MAC_ADDR(prTempStaRec
->aucMacAddr
, pucEthDestAddr
)){
4418 return prTempStaRec
->ucIndex
;
4424 //4 <4> No STA found, Not BMCAST --> Indicate NOT_FOUND to FW
4425 return STA_REC_INDEX_NOT_FOUND
;
4430 mqmGenerateWmmInfoIEByParam (
4431 BOOLEAN fgSupportUAPSD
,
4432 UINT_8 ucBmpDeliveryAC
,
4433 UINT_8 ucBmpTriggerAC
,
4438 P_IE_WMM_INFO_T prIeWmmInfo
;
4439 UINT_32 ucUapsd
[] = {
4440 WMM_QOS_INFO_BE_UAPSD
,
4441 WMM_QOS_INFO_BK_UAPSD
,
4442 WMM_QOS_INFO_VI_UAPSD
,
4443 WMM_QOS_INFO_VO_UAPSD
4445 UINT_8 aucWfaOui
[] = VENDOR_OUI_WFA
;
4449 prIeWmmInfo
= (P_IE_WMM_INFO_T
)pOutBuf
;
4451 prIeWmmInfo
->ucId
= ELEM_ID_WMM
;
4452 prIeWmmInfo
->ucLength
= ELEM_MAX_LEN_WMM_INFO
;
4454 /* WMM-2.2.1 WMM Information Element Field Values */
4455 prIeWmmInfo
->aucOui
[0] = aucWfaOui
[0];
4456 prIeWmmInfo
->aucOui
[1] = aucWfaOui
[1];
4457 prIeWmmInfo
->aucOui
[2] = aucWfaOui
[2];
4458 prIeWmmInfo
->ucOuiType
= VENDOR_OUI_TYPE_WMM
;
4459 prIeWmmInfo
->ucOuiSubtype
= VENDOR_OUI_SUBTYPE_WMM_INFO
;
4461 prIeWmmInfo
->ucVersion
= VERSION_WMM
;
4462 prIeWmmInfo
->ucQosInfo
= 0;
4464 /* UAPSD intial queue configurations (delivery and trigger enabled)*/
4467 UINT_8 ucQosInfo
= 0;
4471 /* Static U-APSD setting */
4472 for(i
= ACI_BE
; i
<= ACI_VO
; i
++){
4473 if (ucBmpDeliveryAC
& ucBmpTriggerAC
& BIT(i
)){
4474 ucQosInfo
|= (UINT_8
)ucUapsd
[i
];
4479 if (ucBmpDeliveryAC
& ucBmpTriggerAC
) {
4480 switch (ucUapsdSp
) {
4481 case WMM_MAX_SP_LENGTH_ALL
:
4482 ucQosInfo
|= WMM_QOS_INFO_MAX_SP_ALL
;
4485 case WMM_MAX_SP_LENGTH_2
:
4486 ucQosInfo
|= WMM_QOS_INFO_MAX_SP_2
;
4489 case WMM_MAX_SP_LENGTH_4
:
4490 ucQosInfo
|= WMM_QOS_INFO_MAX_SP_4
;
4493 case WMM_MAX_SP_LENGTH_6
:
4494 ucQosInfo
|= WMM_QOS_INFO_MAX_SP_6
;
4498 DBGLOG(QM
, INFO
, ("MQM: Incorrect SP length \n"));
4499 ucQosInfo
|= WMM_QOS_INFO_MAX_SP_2
;
4503 prIeWmmInfo
->ucQosInfo
= ucQosInfo
;
4507 /* Increment the total IE length for the Element ID and Length fields. */
4508 return IE_SIZE(prIeWmmInfo
);
4512 /*----------------------------------------------------------------------------*/
4514 * @brief Generate the WMM Info IE
4516 * \param[in] prAdapter Adapter pointer
4517 * @param prMsduInfo The TX MMPDU
4521 /*----------------------------------------------------------------------------*/
4523 mqmGenerateWmmInfoIE (
4524 IN P_ADAPTER_T prAdapter
,
4525 IN P_MSDU_INFO_T prMsduInfo
4528 P_IE_WMM_INFO_T prIeWmmInfo
;
4529 P_PM_PROFILE_SETUP_INFO_T prPmProfSetupInfo
;
4530 P_BSS_INFO_T prBssInfo
;
4531 P_STA_RECORD_T prStaRec
;
4533 DEBUGFUNC("mqmGenerateWmmInfoIE");
4537 /* In case QoS is not turned off, exit directly */
4538 if(!prAdapter
->rWifiVar
.fgSupportQoS
){
4542 prStaRec
= cnmGetStaRecByIndex(prAdapter
, prMsduInfo
->ucStaRecIndex
);
4545 if(prStaRec
== NULL
) {
4549 if(!prStaRec
->fgIsWmmSupported
) {
4553 prBssInfo
= &(prAdapter
->rWifiVar
.arBssInfo
[prStaRec
->ucNetTypeIndex
]);
4555 prPmProfSetupInfo
= &prBssInfo
->rPmProfSetupInfo
;
4557 prIeWmmInfo
= (P_IE_WMM_INFO_T
)
4558 ((PUINT_8
) prMsduInfo
->prPacket
+ prMsduInfo
->u2FrameLength
);
4561 prIeWmmInfo
->ucId
= ELEM_ID_WMM
;
4562 prIeWmmInfo
->ucLength
= ELEM_MAX_LEN_WMM_INFO
;
4564 /* WMM-2.2.1 WMM Information Element Field Values */
4565 prIeWmmInfo
->aucOui
[0] = aucWfaOui
[0];
4566 prIeWmmInfo
->aucOui
[1] = aucWfaOui
[1];
4567 prIeWmmInfo
->aucOui
[2] = aucWfaOui
[2];
4568 prIeWmmInfo
->ucOuiType
= VENDOR_OUI_TYPE_WMM
;
4569 prIeWmmInfo
->ucOuiSubtype
= VENDOR_OUI_SUBTYPE_WMM_INFO
;
4571 prIeWmmInfo
->ucVersion
= VERSION_WMM
;
4572 prIeWmmInfo
->ucQosInfo
= 0;
4574 /* UAPSD intial queue configurations (delivery and trigger enabled)*/
4575 // if(prAdapter->rWifiVar.fgSupportUAPSD){
4576 if(prAdapter
->rWifiVar
.fgSupportUAPSD
&& prStaRec
->fgIsUapsdSupported
){
4578 UINT_8 ucQosInfo
= 0;
4582 /* Static U-APSD setting */
4583 for(i
= ACI_BE
; i
<= ACI_VO
; i
++){
4584 if (prPmProfSetupInfo
->ucBmpDeliveryAC
& prPmProfSetupInfo
->ucBmpTriggerAC
& BIT(i
)){
4585 ucQosInfo
|= (UINT_8
)ucUapsd
[i
];
4590 if (prPmProfSetupInfo
->ucBmpDeliveryAC
& prPmProfSetupInfo
->ucBmpTriggerAC
) {
4591 switch (prPmProfSetupInfo
->ucUapsdSp
) {
4592 case WMM_MAX_SP_LENGTH_ALL
:
4593 ucQosInfo
|= WMM_QOS_INFO_MAX_SP_ALL
;
4596 case WMM_MAX_SP_LENGTH_2
:
4597 ucQosInfo
|= WMM_QOS_INFO_MAX_SP_2
;
4600 case WMM_MAX_SP_LENGTH_4
:
4601 ucQosInfo
|= WMM_QOS_INFO_MAX_SP_4
;
4604 case WMM_MAX_SP_LENGTH_6
:
4605 ucQosInfo
|= WMM_QOS_INFO_MAX_SP_6
;
4609 DBGLOG(QM
, INFO
, ("MQM: Incorrect SP length \n"));
4610 ucQosInfo
|= WMM_QOS_INFO_MAX_SP_2
;
4614 prIeWmmInfo
->ucQosInfo
= ucQosInfo
;
4618 /* Increment the total IE length for the Element ID and Length fields. */
4619 prMsduInfo
->u2FrameLength
+= IE_SIZE(prIeWmmInfo
);
4622 prMsduInfo
->u2FrameLength
+= mqmGenerateWmmInfoIEByParam(\
4623 (prAdapter
->rWifiVar
.fgSupportUAPSD
&& prStaRec
->fgIsUapsdSupported
),
4624 prPmProfSetupInfo
->ucBmpDeliveryAC
,
4625 prPmProfSetupInfo
->ucBmpTriggerAC
,
4626 prPmProfSetupInfo
->ucUapsdSp
,
4627 (UINT_8
*)prIeWmmInfo
);
4633 /*----------------------------------------------------------------------------*/
4635 * @brief log2 calculation for CW
4637 * @param[in] val value
4641 /*----------------------------------------------------------------------------*/
4643 UINT_32
cwlog2(UINT_32 val
) {
4648 while (val
>= 512) { n
+= 9; val
= val
>> 9; }
4649 while (val
>= 16) { n
+= 4; val
>>= 4; }
4650 while (val
>= 2) { n
+= 1; val
>>= 1; }
4657 mqmGenerateWmmParamIEByParam (
4658 P_ADAPTER_T prAdapter
,
4659 P_BSS_INFO_T prBssInfo
,
4663 P_IE_WMM_PARAM_T prIeWmmParam
;
4664 UINT_8 aucWfaOui
[] = VENDOR_OUI_WFA
;
4672 ENUM_WMM_ACI_T eAci
;
4677 prIeWmmParam
= (P_IE_WMM_PARAM_T
)pOutBuf
;
4679 prIeWmmParam
->ucId
= ELEM_ID_WMM
;
4680 prIeWmmParam
->ucLength
= ELEM_MAX_LEN_WMM_PARAM
;
4682 /* WMM-2.2.1 WMM Information Element Field Values */
4683 prIeWmmParam
->aucOui
[0] = aucWfaOui
[0];
4684 prIeWmmParam
->aucOui
[1] = aucWfaOui
[1];
4685 prIeWmmParam
->aucOui
[2] = aucWfaOui
[2];
4686 prIeWmmParam
->ucOuiType
= VENDOR_OUI_TYPE_WMM
;
4687 prIeWmmParam
->ucOuiSubtype
= VENDOR_OUI_SUBTYPE_WMM_PARAM
;
4689 prIeWmmParam
->ucVersion
= VERSION_WMM
;
4690 prIeWmmParam
->ucQosInfo
= (prBssInfo
->ucWmmParamSetCount
& WMM_QOS_INFO_PARAM_SET_CNT
);
4692 /* UAPSD intial queue configurations (delivery and trigger enabled)*/
4693 if (prAdapter
->rWifiVar
.fgSupportUAPSD
) {
4694 prIeWmmParam
->ucQosInfo
|= WMM_QOS_INFO_UAPSD
;
4697 /* EDCA parameter */
4699 for(eAci
= 0; eAci
< WMM_AC_INDEX_NUM
; eAci
++){
4701 //DBGLOG(QM, LOUD, ("MQM: eAci = %d, ACM = %d, Aifsn = %d, CWmin = %d, CWmax = %d, TxopLimit = %d\n",
4702 // eAci,prBssInfo->arACQueParmsForBcast[eAci].fgIsACMSet ,
4703 // prBssInfo->arACQueParmsForBcast[eAci].u2Aifsn,
4704 // prBssInfo->arACQueParmsForBcast[eAci].u2CWmin,
4705 // prBssInfo->arACQueParmsForBcast[eAci].u2CWmax,
4706 // prBssInfo->arACQueParmsForBcast[eAci].u2TxopLimit));
4708 *( ((PUINT_8
)(&prIeWmmParam
->ucAciAifsn_BE
)) + (eAci
<<2) ) = (UINT_8
) (aucACI
[eAci
]
4709 | (prBssInfo
->arACQueParmsForBcast
[eAci
].fgIsACMSet
? WMM_ACIAIFSN_ACM
:0 )
4710 | (prBssInfo
->arACQueParmsForBcast
[eAci
].u2Aifsn
& (WMM_ACIAIFSN_AIFSN
)));
4712 *( ((PUINT_8
)(&prIeWmmParam
->ucEcw_BE
)) + (eAci
<<2) ) = (UINT_8
) (0
4713 | (((prBssInfo
->aucCWminLog2ForBcast
[eAci
] )) & WMM_ECW_WMIN_MASK
)
4714 | ((((prBssInfo
->aucCWmaxLog2ForBcast
[eAci
] )) << WMM_ECW_WMAX_OFFSET
) & WMM_ECW_WMAX_MASK
)
4717 *( ((PUINT_8
)(&prIeWmmParam
->ucEcw_BE
)) + (eAci
<<2) ) = (UINT_8
) (0
4718 | (cwlog2((prBssInfo
->arACQueParmsForBcast
[eAci
].u2CWmin
+ 1)) & WMM_ECW_WMIN_MASK
)
4719 | ((cwlog2((prBssInfo
->arACQueParmsForBcast
[eAci
].u2CWmax
+ 1)) << WMM_ECW_WMAX_OFFSET
) & WMM_ECW_WMAX_MASK
)
4723 WLAN_SET_FIELD_16( ((PUINT_8
)(prIeWmmParam
->aucTxopLimit_BE
)) + (eAci
<<2)
4724 , prBssInfo
->arACQueParmsForBcast
[eAci
].u2TxopLimit
);
4728 /* Increment the total IE length for the Element ID and Length fields. */
4729 return IE_SIZE(prIeWmmParam
);
4733 /*----------------------------------------------------------------------------*/
4735 * @brief Generate the WMM Param IE
4737 * \param[in] prAdapter Adapter pointer
4738 * @param prMsduInfo The TX MMPDU
4742 /*----------------------------------------------------------------------------*/
4744 mqmGenerateWmmParamIE (
4745 IN P_ADAPTER_T prAdapter
,
4746 IN P_MSDU_INFO_T prMsduInfo
4749 P_IE_WMM_PARAM_T prIeWmmParam
;
4752 UINT_8 aucWfaOui
[] = VENDOR_OUI_WFA
;
4760 ENUM_WMM_ACI_T eAci
;
4763 P_BSS_INFO_T prBssInfo
;
4764 P_STA_RECORD_T prStaRec
;
4766 DEBUGFUNC("mqmGenerateWmmParamIE");
4767 DBGLOG(QM
, LOUD
,("\n"));
4771 /* In case QoS is not turned off, exit directly */
4772 if(!prAdapter
->rWifiVar
.fgSupportQoS
){
4776 prStaRec
= cnmGetStaRecByIndex(prAdapter
, prMsduInfo
->ucStaRecIndex
);
4779 if(!prStaRec
->fgIsQoS
) {
4784 prBssInfo
= &(prAdapter
->rWifiVar
.arBssInfo
[prMsduInfo
->ucNetworkType
]);
4786 if(!prBssInfo
->fgIsQBSS
) { return; }
4788 #if 0 // 20120220 frog: update beacon content & change OP mode is a separate event for P2P network.
4789 if( prBssInfo
->eCurrentOPMode
!= OP_MODE_ACCESS_POINT
&&
4790 prBssInfo
->eCurrentOPMode
!= OP_MODE_BOW
)
4796 prIeWmmParam
= (P_IE_WMM_PARAM_T
)
4797 ((PUINT_8
) prMsduInfo
->prPacket
+ prMsduInfo
->u2FrameLength
);
4800 prIeWmmParam
->ucId
= ELEM_ID_WMM
;
4801 prIeWmmParam
->ucLength
= ELEM_MAX_LEN_WMM_PARAM
;
4803 /* WMM-2.2.1 WMM Information Element Field Values */
4804 prIeWmmParam
->aucOui
[0] = aucWfaOui
[0];
4805 prIeWmmParam
->aucOui
[1] = aucWfaOui
[1];
4806 prIeWmmParam
->aucOui
[2] = aucWfaOui
[2];
4807 prIeWmmParam
->ucOuiType
= VENDOR_OUI_TYPE_WMM
;
4808 prIeWmmParam
->ucOuiSubtype
= VENDOR_OUI_SUBTYPE_WMM_PARAM
;
4810 prIeWmmParam
->ucVersion
= VERSION_WMM
;
4811 prIeWmmParam
->ucQosInfo
= (prBssInfo
->ucWmmParamSetCount
& WMM_QOS_INFO_PARAM_SET_CNT
);
4813 /* UAPSD intial queue configurations (delivery and trigger enabled)*/
4814 if(prAdapter
->rWifiVar
.fgSupportUAPSD
){
4816 prIeWmmParam
->ucQosInfo
|= WMM_QOS_INFO_UAPSD
;
4820 /* EDCA parameter */
4822 for(eAci
= 0; eAci
< WMM_AC_INDEX_NUM
; eAci
++){
4824 //DBGLOG(QM, LOUD, ("MQM: eAci = %d, ACM = %d, Aifsn = %d, CWmin = %d, CWmax = %d, TxopLimit = %d\n",
4825 // eAci,prBssInfo->arACQueParmsForBcast[eAci].fgIsACMSet ,
4826 // prBssInfo->arACQueParmsForBcast[eAci].u2Aifsn,
4827 // prBssInfo->arACQueParmsForBcast[eAci].u2CWmin,
4828 // prBssInfo->arACQueParmsForBcast[eAci].u2CWmax,
4829 // prBssInfo->arACQueParmsForBcast[eAci].u2TxopLimit));
4831 *( ((PUINT_8
)(&prIeWmmParam
->ucAciAifsn_BE
)) + (eAci
<<2) ) = (UINT_8
) (aucACI
[eAci
]
4832 | (prBssInfo
->arACQueParmsForBcast
[eAci
].fgIsACMSet
? WMM_ACIAIFSN_ACM
:0 )
4833 | (prBssInfo
->arACQueParmsForBcast
[eAci
].u2Aifsn
& (WMM_ACIAIFSN_AIFSN
)));
4835 *( ((PUINT_8
)(&prIeWmmParam
->ucEcw_BE
)) + (eAci
<<2) ) = (UINT_8
) (0
4836 | (((prBssInfo
->aucCWminLog2ForBcast
[eAci
] )) & WMM_ECW_WMIN_MASK
)
4837 | ((((prBssInfo
->aucCWmaxLog2ForBcast
[eAci
] )) << WMM_ECW_WMAX_OFFSET
) & WMM_ECW_WMAX_MASK
)
4840 *( ((PUINT_8
)(&prIeWmmParam
->ucEcw_BE
)) + (eAci
<<2) ) = (UINT_8
) (0
4841 | (cwlog2((prBssInfo
->arACQueParmsForBcast
[eAci
].u2CWmin
+ 1)) & WMM_ECW_WMIN_MASK
)
4842 | ((cwlog2((prBssInfo
->arACQueParmsForBcast
[eAci
].u2CWmax
+ 1)) << WMM_ECW_WMAX_OFFSET
) & WMM_ECW_WMAX_MASK
)
4846 WLAN_SET_FIELD_16( ((PUINT_8
)(prIeWmmParam
->aucTxopLimit_BE
)) + (eAci
<<2)
4847 , prBssInfo
->arACQueParmsForBcast
[eAci
].u2TxopLimit
);
4851 /* Increment the total IE length for the Element ID and Length fields. */
4852 prMsduInfo
->u2FrameLength
+= IE_SIZE(prIeWmmParam
);
4855 prMsduInfo
->u2FrameLength
+= mqmGenerateWmmParamIEByParam(\
4856 prAdapter
, prBssInfo
, (UINT_8
*)prIeWmmParam
);
4865 IN P_ADAPTER_T prAdapter
,
4866 IN ENUM_NETWORK_TYPE_INDEX_T eNetworkType
,
4867 IN UINT_8 ucStaRecIdx
,
4868 IN P_MSDU_INFO_T prMsduInfo
,
4869 IN ENUM_FRAME_TYPE_IN_CMD_Q_T eFrameType
4872 P_BSS_INFO_T prBssInfo
;
4873 P_STA_RECORD_T prStaRec
;
4874 P_WLAN_MAC_HEADER_T prWlanFrame
;
4875 UINT_16 u2TxFrameCtrl
;
4877 DEBUGFUNC("qmGetFrameAction");
4879 #if (NIC_TX_BUFF_COUNT_TC4 > 2)
4880 #define QM_MGMT_QUUEUD_THRESHOLD 2
4882 #define QM_MGMT_QUUEUD_THRESHOLD 1
4885 DATA_STRUC_INSPECTING_ASSERT(QM_MGMT_QUUEUD_THRESHOLD
<= (NIC_TX_BUFF_COUNT_TC4
));
4886 DATA_STRUC_INSPECTING_ASSERT(QM_MGMT_QUUEUD_THRESHOLD
> 0);
4888 prBssInfo
= &(prAdapter
->rWifiVar
.arBssInfo
[eNetworkType
]);
4889 prStaRec
= QM_GET_STA_REC_PTR_FROM_INDEX(prAdapter
, ucStaRecIdx
);
4891 /* XXX Check BOW P2P AIS time ot set active */
4892 if (!IS_BSS_ACTIVE(prBssInfo
)) {
4893 if (eFrameType
== FRAME_TYPE_MMPDU
) {
4894 prWlanFrame
= (P_WLAN_MAC_HEADER_T
) prMsduInfo
->prPacket
;
4895 u2TxFrameCtrl
= (prWlanFrame
->u2FrameCtrl
) & MASK_FRAME_TYPE
; // Optimized for ARM
4896 if (((u2TxFrameCtrl
== MAC_FRAME_DEAUTH
) && (prMsduInfo
->pfTxDoneHandler
== NULL
)) ||
4897 (u2TxFrameCtrl
== MAC_FRAME_ACTION
)) { /* whsu */
4898 return FRAME_ACTION_TX_PKT
;
4902 DBGLOG(QM
, INFO
, ("Drop packets Action (Inactive %u).\n",prBssInfo
->ucNetTypeIndex
));
4903 TX_INC_CNT(&prAdapter
->rTxCtrl
, TX_INACTIVE_BSS_DROP
);
4904 return FRAME_ACTION_DROP_PKT
;
4907 /* TODO Handle disconnect issue */
4909 /* P2P probe Request frame */
4911 if(eFrameType
== FRAME_TYPE_MMPDU
) {
4912 ASSERT(prMsduInfo
!=NULL
);
4913 prWlanFrame
= (P_WLAN_MAC_HEADER_T
) prMsduInfo
->prPacket
;
4914 u2TxFrameCtrl
= (prWlanFrame
->u2FrameCtrl
) & MASK_FRAME_TYPE
; // Optimized for ARM
4916 if (u2TxFrameCtrl
== MAC_FRAME_BEACON
) {
4917 if( prBssInfo
->fgIsNetAbsent
) {
4918 return FRAME_ACTION_DROP_PKT
;
4921 else if (u2TxFrameCtrl
== MAC_FRAME_PROBE_RSP
) {
4922 if( prBssInfo
->fgIsNetAbsent
) {
4923 return FRAME_ACTION_DROP_PKT
;
4926 else if (u2TxFrameCtrl
== MAC_FRAME_DEAUTH
) {
4927 if( prBssInfo
->fgIsNetAbsent
) {
4930 DBGLOG(P2P
, LOUD
, ("Sending DEAUTH Frame\n"));
4931 return FRAME_ACTION_TX_PKT
;
4933 /* MMPDU with prStaRec && fgIsInUse not check fgIsNetActive */
4934 else if(u2TxFrameCtrl
== MAC_FRAME_ASSOC_REQ
4935 || u2TxFrameCtrl
== MAC_FRAME_AUTH
4936 || u2TxFrameCtrl
== MAC_FRAME_REASSOC_REQ
4937 || u2TxFrameCtrl
== MAC_FRAME_PROBE_REQ
4938 || u2TxFrameCtrl
== MAC_FRAME_ACTION
) {
4941 if(prStaRec
->fgIsInPS
) {
4942 if( nicTxGetResource (prAdapter
, TC4_INDEX
)>= QM_MGMT_QUUEUD_THRESHOLD
) {
4943 return FRAME_ACTION_TX_PKT
;
4946 return FRAME_ACTION_QUEUE_PKT
;
4950 return FRAME_ACTION_TX_PKT
;
4954 return FRAME_ACTION_TX_PKT
;
4957 if (!prStaRec
->fgIsInUse
) {
4958 return FRAME_ACTION_DROP_PKT
;
4962 } /* FRAME_TYPE_MMPDU */
4963 else if ((eFrameType
== FRAME_TYPE_802_1X
)){
4966 return FRAME_ACTION_TX_PKT
;
4969 if (!prStaRec
->fgIsInUse
) {
4970 return FRAME_ACTION_DROP_PKT
;
4972 if(prStaRec
->fgIsInPS
) {
4973 if( nicTxGetResource (prAdapter
, TC4_INDEX
)>= QM_MGMT_QUUEUD_THRESHOLD
) {
4974 return FRAME_ACTION_TX_PKT
;
4977 return FRAME_ACTION_QUEUE_PKT
;
4982 } /* FRAME_TYPE_802_1X */
4983 else if ((!IS_BSS_ACTIVE(prBssInfo
))
4985 || (!prStaRec
->fgIsInUse
)){
4986 return FRAME_ACTION_DROP_PKT
;
4990 if (prBssInfo
->fgIsNetAbsent
){
4991 DBGLOG(QM
, LOUD
, ("Queue packets (Absent %u).\n",prBssInfo
->ucNetTypeIndex
));
4992 return FRAME_ACTION_QUEUE_PKT
;
4995 if (prStaRec
&& prStaRec
->fgIsInPS
){
4996 DBGLOG(QM
, LOUD
, ("Queue packets (PS %u).\n",prStaRec
->fgIsInPS
));
4997 return FRAME_ACTION_QUEUE_PKT
;
5000 switch (eFrameType
){
5001 case FRAME_TYPE_802_1X
:
5002 if (!prStaRec
->fgIsValid
){
5003 return FRAME_ACTION_QUEUE_PKT
;
5007 case FRAME_TYPE_MMPDU
:
5015 return FRAME_ACTION_TX_PKT
;
5019 /*----------------------------------------------------------------------------*/
5021 * \brief Handle BSS change operation Event from the FW
5023 * \param[in] prAdapter Adapter pointer
5024 * \param[in] prEvent The event packet from the FW
5028 /*----------------------------------------------------------------------------*/
5030 qmHandleEventBssAbsencePresence(
5031 IN P_ADAPTER_T prAdapter
,
5032 IN P_WIFI_EVENT_T prEvent
5035 P_EVENT_BSS_ABSENCE_PRESENCE_T prEventBssStatus
;
5036 P_BSS_INFO_T prBssInfo
;
5037 BOOLEAN fgIsNetAbsentOld
;
5039 prEventBssStatus
= (P_EVENT_BSS_ABSENCE_PRESENCE_T
)prEvent
;
5040 prBssInfo
= &(prAdapter
->rWifiVar
.arBssInfo
[prEventBssStatus
->ucNetTypeIdx
]);
5041 fgIsNetAbsentOld
= prBssInfo
->fgIsNetAbsent
;
5042 prBssInfo
->fgIsNetAbsent
= prEventBssStatus
->fgIsAbsent
;
5043 prBssInfo
->ucBssFreeQuota
= prEventBssStatus
->ucBssFreeQuota
;
5045 //DBGLOG(QM, TRACE, ("qmHandleEventBssAbsencePresence (ucNetTypeIdx=%d, fgIsAbsent=%d, FreeQuota=%d)\n",
5046 // prEventBssStatus->ucNetTypeIdx, prBssInfo->fgIsNetAbsent, prBssInfo->ucBssFreeQuota));
5048 DBGLOG(QM
, TRACE
, ("NAF=%d,%d,%d\n",
5049 prEventBssStatus
->ucNetTypeIdx
, prBssInfo
->fgIsNetAbsent
, prBssInfo
->ucBssFreeQuota
));
5051 if(!prBssInfo
->fgIsNetAbsent
) {
5052 QM_DBG_CNT_INC(&(prAdapter
->rQM
),QM_DBG_CNT_27
);
5055 QM_DBG_CNT_INC(&(prAdapter
->rQM
),QM_DBG_CNT_28
);
5057 /* From Absent to Present */
5058 if ((fgIsNetAbsentOld
) && (!prBssInfo
->fgIsNetAbsent
)){
5059 kalSetEvent(prAdapter
->prGlueInfo
);
5064 /*----------------------------------------------------------------------------*/
5066 * \brief Handle STA change PS mode Event from the FW
5068 * \param[in] prAdapter Adapter pointer
5069 * \param[in] prEvent The event packet from the FW
5073 /*----------------------------------------------------------------------------*/
5075 qmHandleEventStaChangePsMode(
5076 IN P_ADAPTER_T prAdapter
,
5077 IN P_WIFI_EVENT_T prEvent
5080 P_EVENT_STA_CHANGE_PS_MODE_T prEventStaChangePsMode
;
5081 P_STA_RECORD_T prStaRec
;
5082 BOOLEAN fgIsInPSOld
;
5084 //DbgPrint("QM:Event -RxBa\n");
5086 prEventStaChangePsMode
= (P_EVENT_STA_CHANGE_PS_MODE_T
)prEvent
;
5087 prStaRec
= QM_GET_STA_REC_PTR_FROM_INDEX(prAdapter
, prEventStaChangePsMode
->ucStaRecIdx
);
5092 fgIsInPSOld
= prStaRec
->fgIsInPS
;
5093 prStaRec
->fgIsInPS
= prEventStaChangePsMode
->fgIsInPs
;
5098 prEventStaChangePsMode
->ucUpdateMode
,
5099 prEventStaChangePsMode
->ucFreeQuota
,
5102 //DBGLOG(QM, TRACE, ("qmHandleEventStaChangePsMode (ucStaRecIdx=%d, fgIsInPs=%d)\n",
5103 // prEventStaChangePsMode->ucStaRecIdx, prStaRec->fgIsInPS));
5106 DBGLOG(QM
, TRACE
, ("PS=%d,%d\n",
5107 prEventStaChangePsMode
->ucStaRecIdx
, prStaRec
->fgIsInPS
));
5109 /* From PS to Awake */
5110 if ((fgIsInPSOld
) && (!prStaRec
->fgIsInPS
)){
5111 kalSetEvent(prAdapter
->prGlueInfo
);
5116 /*----------------------------------------------------------------------------*/
5118 * \brief Update STA free quota Event from FW
5120 * \param[in] prAdapter Adapter pointer
5121 * \param[in] prEvent The event packet from the FW
5125 /*----------------------------------------------------------------------------*/
5127 qmHandleEventStaUpdateFreeQuota(
5128 IN P_ADAPTER_T prAdapter
,
5129 IN P_WIFI_EVENT_T prEvent
5132 P_EVENT_STA_UPDATE_FREE_QUOTA_T prEventStaUpdateFreeQuota
;
5133 P_STA_RECORD_T prStaRec
;
5136 prEventStaUpdateFreeQuota
= (P_EVENT_STA_UPDATE_FREE_QUOTA_T
)prEvent
;
5137 prStaRec
= QM_GET_STA_REC_PTR_FROM_INDEX(prAdapter
, prEventStaUpdateFreeQuota
->ucStaRecIdx
);
5141 if(prStaRec
->fgIsInPS
) {
5145 prEventStaUpdateFreeQuota
->ucUpdateMode
,
5146 prEventStaUpdateFreeQuota
->ucFreeQuota
,
5147 prEventStaUpdateFreeQuota
->aucReserved
[0]);
5149 kalSetEvent(prAdapter
->prGlueInfo
);
5152 DBGLOG(QM
, TRACE
, ("qmHandleEventStaUpdateFreeQuota (ucStaRecIdx=%d, ucUpdateMode=%d, ucFreeQuota=%d)\n",
5153 prEventStaUpdateFreeQuota
->ucStaRecIdx
,
5154 prEventStaUpdateFreeQuota
->ucUpdateMode
,
5155 prEventStaUpdateFreeQuota
->ucFreeQuota
));
5158 DBGLOG(QM
, TRACE
, ("UFQ=%d,%d,%d\n",
5159 prEventStaUpdateFreeQuota
->ucStaRecIdx
,
5160 prEventStaUpdateFreeQuota
->ucUpdateMode
,
5161 prEventStaUpdateFreeQuota
->ucFreeQuota
));
5169 /*----------------------------------------------------------------------------*/
5171 * \brief Update STA free quota
5173 * \param[in] prStaRec the STA
5174 * \param[in] ucUpdateMode the method to update free quota
5175 * \param[in] ucFreeQuota the value for update
5179 /*----------------------------------------------------------------------------*/
5182 IN P_ADAPTER_T prAdapter
,
5183 IN P_STA_RECORD_T prStaRec
,
5184 IN UINT_8 ucUpdateMode
,
5185 IN UINT_8 ucFreeQuota
,
5186 IN UINT_8 ucNumOfTxDone
5190 UINT_8 ucFreeQuotaForNonDelivery
;
5191 UINT_8 ucFreeQuotaForDelivery
;
5192 BOOLEAN flgIsUpdateForcedToDelivery
;
5195 DBGLOG(QM
, LOUD
, ("qmUpdateFreeQuota orig ucFreeQuota=%d Mode %u New %u\n",
5196 prStaRec
->ucFreeQuota
, ucUpdateMode
, ucFreeQuota
));
5198 if(!prStaRec
->fgIsInPS
)return;
5200 flgIsUpdateForcedToDelivery
= FALSE
;
5202 if (ucNumOfTxDone
> 0)
5205 update free quota by
5206 num of tx done + resident free quota (delivery + non-delivery)
5208 UINT_8 ucAvailQuota
;
5209 ucAvailQuota
= ucNumOfTxDone
+ prStaRec
->ucFreeQuotaForDelivery
+\
5210 prStaRec
->ucFreeQuotaForNonDelivery
;
5211 if (ucAvailQuota
> ucFreeQuota
) /* sanity check */
5212 ucAvailQuota
= ucFreeQuota
;
5214 /* update current free quota */
5215 ucFreeQuota
= ucAvailQuota
;
5217 /* check if the update is from last packet */
5218 if (ucFreeQuota
== (prStaRec
->ucFreeQuota
+1))
5220 /* just add the extra quota to delivery queue */
5224 1. TDLS peer enters power save
5225 2. When the last 2 VI packets are tx done, we will receive 2 update events
5226 3. 1st update event: ucFreeQuota = 9
5227 4. We will correct new quota for delivey and non-delivery to 7:2
5228 5. 2rd update event: ucFreeQuota = 10
5229 6. We will re-correct new quota for delivery and non-delivery to 5:5
5231 But non-delivery queue is not busy.
5232 So in the case, we will have wrong decision, i.e. higher queue always quota 5
5234 Solution: skip the 2rd update event and just add the extra quota to delivery.
5237 flgIsUpdateForcedToDelivery
= TRUE
;
5241 switch (ucUpdateMode
) {
5242 case FREE_QUOTA_UPDATE_MODE_INIT
:
5243 case FREE_QUOTA_UPDATE_MODE_OVERWRITE
:
5244 prStaRec
->ucFreeQuota
= ucFreeQuota
;
5246 case FREE_QUOTA_UPDATE_MODE_INCREASE
:
5247 prStaRec
->ucFreeQuota
+= ucFreeQuota
;
5249 case FREE_QUOTA_UPDATE_MODE_DECREASE
:
5250 prStaRec
->ucFreeQuota
-= ucFreeQuota
;
5256 DBGLOG(QM
, LOUD
, ("qmUpdateFreeQuota new ucFreeQuota=%d)\n",
5257 prStaRec
->ucFreeQuota
));
5259 ucFreeQuota
= prStaRec
->ucFreeQuota
;
5261 ucFreeQuotaForNonDelivery
= 0;
5262 ucFreeQuotaForDelivery
= 0;
5264 if(ucFreeQuota
> 0) {
5265 if( prStaRec
->fgIsQoS
&& prStaRec
->fgIsUapsdSupported
5266 /* && prAdapter->rWifiVar.fgSupportQoS
5267 && prAdapter->rWifiVar.fgSupportUAPSD*/) {
5268 /* XXX We should assign quota to aucFreeQuotaPerQueue[NUM_OF_PER_STA_TX_QUEUES] */
5270 if (flgIsUpdateForcedToDelivery
== FALSE
)
5272 if(prStaRec
->ucFreeQuotaForNonDelivery
> 0 && prStaRec
->ucFreeQuotaForDelivery
> 0) {
5273 ucFreeQuotaForNonDelivery
= ucFreeQuota
>>1;
5274 ucFreeQuotaForDelivery
= ucFreeQuota
- ucFreeQuotaForNonDelivery
;
5276 else if(prStaRec
->ucFreeQuotaForNonDelivery
== 0 && prStaRec
->ucFreeQuotaForDelivery
== 0) {
5277 ucFreeQuotaForNonDelivery
= ucFreeQuota
>>1;
5278 ucFreeQuotaForDelivery
= ucFreeQuota
- ucFreeQuotaForNonDelivery
;
5280 else if(prStaRec
->ucFreeQuotaForNonDelivery
> 0) {
5281 /* NonDelivery is not busy */
5282 if(ucFreeQuota
>= 3 ) {
5283 ucFreeQuotaForNonDelivery
= 2;
5284 ucFreeQuotaForDelivery
= ucFreeQuota
- ucFreeQuotaForNonDelivery
;
5287 ucFreeQuotaForDelivery
= ucFreeQuota
;
5288 ucFreeQuotaForNonDelivery
= 0;
5291 else if(prStaRec
->ucFreeQuotaForDelivery
> 0) {
5292 /* Delivery is not busy */
5293 if(ucFreeQuota
>= 3 ) {
5294 ucFreeQuotaForDelivery
= 2;
5295 ucFreeQuotaForNonDelivery
= ucFreeQuota
- ucFreeQuotaForDelivery
;
5298 ucFreeQuotaForNonDelivery
= ucFreeQuota
;
5299 ucFreeQuotaForDelivery
= 0;
5305 ucFreeQuotaForNonDelivery
= 2;
5306 ucFreeQuotaForDelivery
= ucFreeQuota
- ucFreeQuotaForNonDelivery
;
5311 /* !prStaRec->fgIsUapsdSupported */
5312 ucFreeQuotaForNonDelivery
= ucFreeQuota
;
5313 ucFreeQuotaForDelivery
= 0;
5315 } /* ucFreeQuota > 0 */
5317 prStaRec
->ucFreeQuotaForDelivery
= ucFreeQuotaForDelivery
;
5318 prStaRec
->ucFreeQuotaForNonDelivery
= ucFreeQuotaForNonDelivery
;
5320 #if (CFG_SUPPORT_TDLS_DBG == 1)
5321 if (IS_TDLS_STA(prStaRec
))
5322 printk("<tx> quota %d %d %d\n",
5323 ucFreeQuota
, ucFreeQuotaForDelivery
, ucFreeQuotaForNonDelivery
);
5326 DBGLOG(QM
, LOUD
, ("new QuotaForDelivery = %d QuotaForNonDelivery = %d\n",
5327 prStaRec
->ucFreeQuotaForDelivery
, prStaRec
->ucFreeQuotaForNonDelivery
));
5331 /*----------------------------------------------------------------------------*/
5333 * \brief Return the reorder queued RX packets
5337 * \return The number of queued RX packets
5339 /*----------------------------------------------------------------------------*/
5341 qmGetRxReorderQueuedBufferCount(
5342 IN P_ADAPTER_T prAdapter
5346 P_QUE_MGT_T prQM
= &prAdapter
->rQM
;
5348 /* XXX The summation may impact the performance */
5349 for(i
=0; i
<CFG_NUM_OF_RX_BA_AGREEMENTS
; i
++){
5350 u4Total
+= prQM
->arRxBaTable
[i
].rReOrderQue
.u4NumElem
;
5352 if(QUEUE_IS_EMPTY(&(prQM
->arRxBaTable
[i
].rReOrderQue
))){
5353 ASSERT(prQM
->arRxBaTable
[i
].rReOrderQue
== 0);
5357 ASSERT(u4Total
<=( CFG_NUM_OF_QM_RX_PKT_NUM
*2));