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.
20 * Sync CFG80211 modification from branch 2,2.
22 * 02 23 2012 eddie.chen
23 * [WCXRP00001194] [MT6620][DRV/FW] follow admission control bit to change the enqueue rule
24 * Change the enqueue policy when ACM = 1.
26 * 11 22 2011 yuche.tsai
28 * Code refine, remove one #if 0 code.
30 * 11 19 2011 eddie.chen
31 * [WCXRP00001096] [MT6620 Wi-Fi][Driver/FW] Enhance the log function (xlog)
34 * 11 18 2011 yuche.tsai
36 * CONFIG P2P support RSSI query, default turned off.
38 * 11 18 2011 eddie.chen
39 * [WCXRP00001096] [MT6620 Wi-Fi][Driver/FW] Enhance the log function (xlog)
40 * Fix xlog format to hex format
42 * 11 17 2011 tsaiyuan.hsu
43 * [WCXRP00001115] [MT6620 Wi-Fi][DRV] avoid deactivating staRec when changing state 3 to 3.
44 * avoid deactivating staRec when changing state from 3 to 3.
46 * 11 11 2011 tsaiyuan.hsu
47 * [WCXRP00001083] [MT6620 Wi-Fi][DRV]] dump debug counter or frames when debugging is triggered
48 * add debug msg for xlog.
50 * 11 11 2011 tsaiyuan.hsu
51 * [WCXRP00001083] [MT6620 Wi-Fi][DRV]] dump debug counter or frames when debugging is triggered
52 * add debug counters of bb and ar for xlog.
54 * 11 10 2011 eddie.chen
55 * [WCXRP00001096] [MT6620 Wi-Fi][Driver/FW] Enhance the log function (xlog)
56 * Use short name for xlog.
58 * 11 10 2011 eddie.chen
59 * [WCXRP00001096] [MT6620 Wi-Fi][Driver/FW] Enhance the log function (xlog)
60 * Modify the QM xlog level and remove LOG_FUNC.
62 * 11 10 2011 chinglan.wang
64 * [WiFi WPS]Can't switch to new AP via WPS PBC when there existing a connection to another AP.
66 * 11 09 2011 chinglan.wang
68 * [WiFi direct]Can't make P2P connect via PBC.
70 * 11 08 2011 eddie.chen
71 * [WCXRP00001096] [MT6620 Wi-Fi][Driver/FW] Enhance the log function (xlog)
74 * 11 07 2011 tsaiyuan.hsu
75 * [WCXRP00001083] [MT6620 Wi-Fi][DRV]] dump debug counter or frames when debugging is triggered
76 * add debug counters and periodically dump counters for debugging.
78 * 11 01 2011 chinglan.wang
80 * Modify the Wi-Fi method of the flush TX queue when disconnect the AP.
81 * 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..
84 * [WCXRP00001059] [MT6620 Wi-Fi][Driver][P2P] Fixed sometimes data (1x) will not indicate to upper layer due ba check un-expect
85 * let the Rx BA accept even the sta not valid.
87 * 09 28 2011 tsaiyuan.hsu
88 * [WCXRP00000900] [MT5931 Wi-Fi] Improve balance of TX and RX
89 * enlarge window size only by 4.
91 * 09 01 2011 tsaiyuan.hsu
92 * [WCXRP00000900] [MT5931 Wi-Fi] Improve balance of TX and RX
93 * set rx window size as twice buffer size.
95 * 08 23 2011 yuche.tsai
97 * Fix multicast address list issue.
99 * 08 03 2011 tsaiyuan.hsu
100 * [WCXRP00000900] [MT5931 Wi-Fi] Improve balance of TX and RX
101 * force window size at least 16.
103 * 08 02 2011 yuche.tsai
104 * [WCXRP00000896] [Volunteer Patch][WiFi Direct][Driver] GO with multiple client, TX deauth to a disconnecting device issue.
105 * Fix GO send deauth frame issue.
107 * 07 26 2011 eddie.chen
108 * [WCXRP00000874] [MT5931][DRV] API for query the RX reorder queued packets counter
109 * API for query the RX reorder queued packets counter.
111 * 07 07 2011 eddie.chen
112 * [WCXRP00000834] [MT6620 Wi-Fi][DRV] Send 1x packet when peer STA is in PS.
113 * Add setEvent when free quota is updated.
115 * 07 05 2011 eddie.chen
116 * [WCXRP00000834] [MT6620 Wi-Fi][DRV] Send 1x packet when peer STA is in PS.
117 * Send 1x when peer STA is in PS.
119 * 05 31 2011 eddie.chen
120 * [WCXRP00000753] [MT5931 Wi-Fi][DRV] Adjust QM for MT5931
121 * Fix the QM quota in MT5931.
123 * 05 11 2011 eddie.chen
124 * [WCXRP00000709] [MT6620 Wi-Fi][Driver] Check free number before copying broadcast packet
125 * Fix dest type when GO packet copying.
127 * 05 09 2011 yuche.tsai
128 * [WCXRP00000712] [Volunteer Patch][MT6620][Driver] Sending deauth issue when Hot spot is disabled. (GO is dissolved)
129 * Deauthentication frame is not bound to network active status.
131 * 05 09 2011 eddie.chen
132 * [WCXRP00000709] [MT6620 Wi-Fi][Driver] Check free number before copying broadcast packet
133 * Check free number before copying broadcast packet.
135 * 04 14 2011 eddie.chen
136 * [WCXRP00000603] [MT6620 Wi-Fi][DRV] Fix Klocwork warning
137 * Check the SW RFB free. Fix the compile warning..
139 * 04 12 2011 eddie.chen
140 * [WCXRP00000617] [MT6620 Wi-Fi][DRV/FW] Fix for sigma
141 * Fix the sta index in processing security frame
142 * Simple flow control for TC4 to avoid mgt frames for PS STA to occupy the TC4
145 * 04 11 2011 yuche.tsai
146 * [WCXRP00000627] [Volunteer Patch][MT6620][Driver] Pending MMPUD of P2P Network may crash system issue.
147 * Fix kernel panic issue when MMPDU of P2P is pending in driver.
149 * 04 08 2011 eddie.chen
150 * [WCXRP00000617] [MT6620 Wi-Fi][DRV/FW] Fix for sigma
153 * 03 28 2011 eddie.chen
154 * [WCXRP00000603] [MT6620 Wi-Fi][DRV] Fix Klocwork warning
155 * Fix Klockwork warning.
157 * 03 28 2011 eddie.chen
158 * [WCXRP00000602] [MT6620 Wi-Fi][DRV] Fix wmm parameters in beacon for BOW
159 * Fix wmm parameters in beacon for BOW.
161 * 03 15 2011 eddie.chen
162 * [WCXRP00000554] [MT6620 Wi-Fi][DRV] Add sw control debug counter
163 * Add sw debug counter for QM.
165 * 02 23 2011 eddie.chen
166 * [WCXRP00000463] [MT6620 Wi-Fi][FW/Driver][Hotspot] Cannot update WMM PS STA's partital bitmap
167 * Fix parsing WMM INFO and bmp delivery bitmap definition.
169 * 02 17 2011 eddie.chen
170 * [WCXRP00000458] [MT6620 Wi-Fi][Driver] BOW Concurrent - ProbeResp was exist in other channel
171 * 1) Chnage GetFrameAction decision when BSS is absent.
172 * 2) Check channel and resource in processing ProbeRequest
174 * 02 08 2011 eddie.chen
175 * [WCXRP00000426] [MT6620 Wi-Fi][FW/Driver] Add STA aging timeout and defualtHwRatein AP mode
176 * Add event STA agint timeout
178 * 01 27 2011 tsaiyuan.hsu
179 * [WCXRP00000392] [MT6620 Wi-Fi][Driver] Add Roaming Support
181 * 1. not support 11r, only use strength of signal to determine roaming.
182 * 2. not enable CFG_SUPPORT_ROAMING until completion of full test.
183 * 3. in 6620, adopt work-around to avoid sign extension problem of cck of hw
184 * 4. assume that change of link quality in smooth way.
186 * 01 25 2011 yuche.tsai
187 * [WCXRP00000388] [Volunteer Patch][MT6620][Driver/Fw] change Station Type in station record.
188 * Change Station Type in Station Record, Modify MACRO definition for getting station type & network type index & Role.
190 * 01 24 2011 eddie.chen
191 * [WCXRP00000385] [MT6620 Wi-Fi][DRV] Add destination decision for forwarding packets
194 * 01 24 2011 eddie.chen
195 * [WCXRP00000385] [MT6620 Wi-Fi][DRV] Add destination decision for forwarding packets
196 * Add destination decision in AP mode.
199 * [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!!!
200 * Allow 802.1x can be send even the net is not active due the drver / fw sync issue.
202 * 01 13 2011 eddie.chen
203 * [WCXRP00000322] Add WMM IE in beacon,
204 Add per station flow control when STA is in PS
205 * Fix typo and compile error.
207 * 01 12 2011 eddie.chen
208 * [WCXRP00000322] Add WMM IE in beacon,
209 Add per station flow control when STA is in PS
210 * Fix WMM parameter condition for STA
212 * 01 12 2011 eddie.chen
213 * [WCXRP00000322] Add WMM IE in beacon,
214 Add per station flow control when STA is in PS
215 * 1) Check Bss if support QoS before adding WMMIE
216 * 2) Check if support prAdapter->rWifiVar QoS and uapsd in flow control
218 * 01 12 2011 george.huang
219 * [WCXRP00000355] [MT6620 Wi-Fi] Set WMM-PS related setting with qualifying AP capability
220 * Update MQM for WMM IE generation method
222 * 01 11 2011 eddie.chen
223 * [WCXRP00000322] Add WMM IE in beacon,
224 Add per station flow control when STA is in PS
226 * Add per STA flow control when STA is in PS mode
228 * 01 03 2011 george.huang
229 * [WCXRP00000152] [MT6620 Wi-Fi] AP mode power saving function
230 * update prStaRec->fgIsUapsdSupported flag.
232 * 12 29 2010 eddie.chen
233 * [WCXRP00000322] Add WMM IE in beacon,
234 Add per station flow control when STA is in PS
236 * Add WMM parameter for broadcast.
238 * 12 29 2010 eddie.chen
239 * [WCXRP00000322] Add WMM IE in beacon,
240 Add per station flow control when STA is in PS
242 * 1) PS flow control event
244 * 2) WMM IE in beacon, assoc resp, probe resp
246 * 12 23 2010 george.huang
247 * [WCXRP00000152] [MT6620 Wi-Fi] AP mode power saving function
248 * 1. update WMM IE parsing, with ASSOC REQ handling
249 * 2. extend U-APSD parameter passing from driver to FW
252 * [WCXRP00000099] [MT6620 Wi-Fi] [Driver] workaround to let the de-authentication can be send out
253 * use the #14 and modify the add code for check MMPDU.
256 * [WCXRP00000099] [MT6620 Wi-Fi] [Driver] workaround to let the de-authentication can be send out
257 * only MMPDU not check the netActive flag.
260 * [WCXRP00000099] [MT6620 Wi-Fi] [Driver] workaround to let the de-authentication can be send out
261 * not check the netActive flag for mgmt .
264 * [WCXRP00000077] [MT6620 Wi-Fi][Driver][FW] Eliminate use of ENUM_NETWORK_TYPE_T and replaced by ENUM_NETWORK_TYPE_INDEX_T only
265 * remove ENUM_NETWORK_TYPE_T definitions
267 * 09 21 2010 kevin.huang
268 * [WCXRP00000052] [MT6620 Wi-Fi][Driver] Eliminate Linux Compile Warning
269 * Eliminate Linux Compile Warning
271 * 08 30 2010 yarco.yang
273 * Fixed klockwork error message
275 * 08 18 2010 yarco.yang
277 * 1. Fixed HW checksum offload function not work under Linux issue.
278 * 2. Add debug message.
280 * 08 10 2010 yarco.yang
284 * 08 06 2010 yarco.yang
286 * Update qmGetFrameAction() to allow P2P MGMT frame w/o STA_Record still can perform TX action
290 * AIS-FSM FIX: return channel privilege even when the privilege is not granted yet
291 * QM: qmGetFrameAction() won't assert when corresponding STA-REC index is not found
293 * 07 20 2010 yarco.yang
295 * Add to SetEvent when BSS is from Absent to Present or STA from PS to Awake
297 * 07 16 2010 yarco.yang
299 * 1. Support BSS Absence/Presence Event
300 * 2. Support STA change PS mode Event
301 * 3. Support BMC forwarding for AP mode.
303 * 07 14 2010 yarco.yang
305 * 1. Remove CFG_MQM_MIGRATION
306 * 2. Add CMD_UPDATE_WMM_PARMS command
308 * 07 13 2010 yarco.yang
311 * [MT6620 and MT5931] SW Migration, add qmGetFrameAction() API for CMD Queue Processing
313 * 07 09 2010 yarco.yang
315 * [MT6620 and MT5931] SW Migration: Add ADDBA support
319 * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository.
321 * 07 08 2010 yarco.yang
322 * [WPD00003837][MT6620]Data Path Refine
325 * 07 06 2010 yarco.yang
326 * [WPD00003837][MT6620]Data Path Refine
327 * Use fgInUse instead of fgIsValid for De-queue judgement
329 * 07 06 2010 yarco.yang
330 * [WPD00003837][MT6620]Data Path Refine
331 * For MMPDU, STA_REC will be decided by caller module
333 * 07 06 2010 yarco.yang
334 * [WPD00003837][MT6620]Data Path Refine
335 * Add MGMT Packet type for HIF_TX_HEADER
337 * 06 29 2010 yarco.yang
338 * [WPD00003837][MT6620]Data Path Refine
339 * replace g_rQM with Adpater->rQM
342 * [WPD00003833][MT6620 and MT5931] Driver migration
343 * add API in que_mgt to retrieve sta-rec index for security frames.
345 * 06 23 2010 yarco.yang
346 * [WPD00003837][MT6620]Data Path Refine
347 * Merge g_arStaRec[] into adapter->arStaRec[]
349 * 06 21 2010 yarco.yang
350 * [WPD00003837][MT6620]Data Path Refine
351 * Support CFG_MQM_MIGRATION flag
354 * [WPD00003833][MT6620 and MT5931] Driver migration
355 * 1) migrate assoc.c.
356 * 2) add ucTxSeqNum for tracking frames which needs TX-DONE awareness
357 * 3) add configuration options for CNM_MEM and RSN modules
358 * 4) add data path for management frames
359 * 5) eliminate rPacketInfo of MSDU_INFO_T
361 * 06 06 2010 kevin.huang
362 * [WPD00003832][MT6620 5931] Create driver base
363 * [MT6620 5931] Create driver base
365 * 03 31 2010 tehuang.liu
366 * [WPD00001943]Create WiFi test driver framework on WinXP
367 * Refined the debug msg
370 * [WPD00001943]Create WiFi test driver framework on WinXP
371 * comment out one assertion which refer to undefined data member.
373 * 03 30 2010 tehuang.liu
374 * [WPD00001943]Create WiFi test driver framework on WinXP
375 * Enabled adaptive TC resource control
377 * 03 24 2010 jeffrey.chang
378 * [WPD00003826]Initial import for Linux port
379 * initial import for Linux port
381 * 03 17 2010 tehuang.liu
382 * [WPD00001943]Create WiFi test driver framework on WinXP
383 * Changed STA_REC index determination rules (DA=BMCAST always --> STA_REC_INDEX_BMCAST)
385 * 03 11 2010 tehuang.liu
386 * [WPD00001943]Create WiFi test driver framework on WinXP
387 * Fixed buffer leak when processing BAR frames
389 * 03 02 2010 tehuang.liu
390 * [WPD00001943]Create WiFi test driver framework on WinXP
391 * For TX packets with STA_REC index = STA_REC_INDEX_NOT_FOUND, use TC5
393 * 03 01 2010 tehuang.liu
394 * [WPD00001943]Create WiFi test driver framework on WinXP
395 * Fixed STA_REC index determination bug (fgIsValid shall be checked)
397 * 02 25 2010 tehuang.liu
398 * [WPD00001943]Create WiFi test driver framework on WinXP
399 * Refined function qmDetermineStaRecIndex() for BMCAST packets
401 * 02 25 2010 tehuang.liu
402 * [WPD00001943]Create WiFi test driver framework on WinXP
403 * Enabled multi-STA TX path with fairness
405 * 02 24 2010 tehuang.liu
406 * [WPD00001943]Create WiFi test driver framework on WinXP
407 * Enabled dynamically activating and deactivating STA_RECs
409 * 02 24 2010 tehuang.liu
410 * [WPD00001943]Create WiFi test driver framework on WinXP
411 * Added code for dynamic activating and deactivating STA_RECs.
413 * 01 13 2010 tehuang.liu
414 * [WPD00001943]Create WiFi test driver framework on WinXP
415 * Enabled the 802.1x path
417 * 01 13 2010 tehuang.liu
418 * [WPD00001943]Create WiFi test driver framework on WinXP
419 * Enabled the Burst_End Indication mechanism
420 ** \main\maintrunk.MT6620WiFiDriver_Prj\13 2009-12-14 15:01:37 GMT MTK02468
421 ** Fixed casting for qmAddRxBaEntry()
422 ** \main\maintrunk.MT6620WiFiDriver_Prj\12 2009-12-10 16:51:03 GMT mtk02752
423 ** remove SD1_SD3.. flag
424 ** \main\maintrunk.MT6620WiFiDriver_Prj\11 2009-12-09 14:07:25 GMT MTK02468
425 ** Added RX buffer reordering functions
426 ** \main\maintrunk.MT6620WiFiDriver_Prj\10 2009-12-04 13:34:16 GMT MTK02468
427 ** Modified Flush Queue function to let queues be reinitialized
428 ** \main\maintrunk.MT6620WiFiDriver_Prj\9 2009-12-04 13:18:25 GMT MTK02468
429 ** Added flushing per-Type queues code
430 ** \main\maintrunk.MT6620WiFiDriver_Prj\8 2009-12-02 23:39:49 GMT MTK02468
431 ** Added Debug msgs and fixed incorrect assert
432 ** \main\maintrunk.MT6620WiFiDriver_Prj\4 2009-11-26 23:50:27 GMT MTK02468
433 ** Bug fixing (qmDequeueTxPackets local variable initialization)
434 ** \main\maintrunk.MT6620WiFiDriver_Prj\3 2009-11-26 09:39:25 GMT mtk02752
435 ** correct and surpress PREfast warning
436 ** \main\maintrunk.MT6620WiFiDriver_Prj\2 2009-11-23 22:10:55 GMT mtk02468
437 ** Used SD1_SD3_DATAPATH_INTEGRATION
438 ** \main\maintrunk.MT6620WiFiDriver_Prj\1 2009-11-23 22:02:30 GMT mtk02468
443 /*******************************************************************************
444 * C O M P I L E R F L A G S
445 ********************************************************************************
448 /*******************************************************************************
449 * E X T E R N A L R E F E R E N C E S
450 ********************************************************************************
454 /*******************************************************************************
456 ********************************************************************************
459 /*******************************************************************************
461 ********************************************************************************
464 /*******************************************************************************
465 * P U B L I C D A T A
466 ********************************************************************************
468 OS_SYSTIME g_arMissTimeout[CFG_STA_REC_NUM][CFG_RX_MAX_BA_TID_NUM];
470 /*******************************************************************************
471 * P R I V A T E D A T A
472 ********************************************************************************
476 /*******************************************************************************
478 ********************************************************************************
481 /*******************************************************************************
482 * F U N C T I O N D E C L A R A T I O N S
483 ********************************************************************************
486 qmDetermineStaRecIndex(
487 IN P_ADAPTER_T prAdapter,
488 IN P_MSDU_INFO_T prMsduInfo
492 qmDequeueTxPacketsFromPerStaQueues(
493 IN P_ADAPTER_T prAdapter,
496 IN UINT_8 ucCurrentAvailableQuota,
497 IN UINT_8 ucTotalQuota
501 qmDequeueTxPacketsFromPerTypeQueues(
502 IN P_ADAPTER_T prAdapter,
508 /*******************************************************************************
510 ********************************************************************************
513 /*----------------------------------------------------------------------------*/
515 * \brief Init Queue Managment for TX
521 /*----------------------------------------------------------------------------*/
524 IN P_ADAPTER_T prAdapter
527 UINT_32 u4QueArrayIdx;
530 P_QUE_MGT_T prQM = &prAdapter->rQM;
532 //DbgPrint("QM: Enter qmInit()\n");
534 prAdapter->rWifiVar.fgSupportQoS = TRUE;
536 prAdapter->rWifiVar.fgSupportQoS = FALSE;
539 #if CFG_SUPPORT_AMPDU_RX
540 prAdapter->rWifiVar.fgSupportAmpduRx = TRUE;
542 prAdapter->rWifiVar.fgSupportAmpduRx = FALSE;
545 #if CFG_SUPPORT_AMPDU_TX
546 prAdapter->rWifiVar.fgSupportAmpduTx = TRUE;
548 prAdapter->rWifiVar.fgSupportAmpduTx = FALSE;
551 #if CFG_SUPPORT_TSPEC
552 prAdapter->rWifiVar.fgSupportTspec = TRUE;
554 prAdapter->rWifiVar.fgSupportTspec = FALSE;
557 #if CFG_SUPPORT_UAPSD
558 prAdapter->rWifiVar.fgSupportUAPSD= TRUE;
560 prAdapter->rWifiVar.fgSupportUAPSD = FALSE;
563 #if CFG_SUPPORT_UL_PSMP
564 prAdapter->rWifiVar.fgSupportULPSMP = TRUE;
566 prAdapter->rWifiVar.fgSupportULPSMP = FALSE;
569 #if CFG_SUPPORT_RX_SGI
570 prAdapter->rWifiVar.u8SupportRxSgi20 = 0;
571 prAdapter->rWifiVar.u8SupportRxSgi40 = 0;
573 prAdapter->rWifiVar.u8SupportRxSgi20 = 2;
574 prAdapter->rWifiVar.u8SupportRxSgi40 = 2;
577 #if CFG_SUPPORT_RX_HT_GF
578 prAdapter->rWifiVar.u8SupportRxGf = 0;
580 prAdapter->rWifiVar.u8SupportRxGf = 2;
584 //4 <2> Initialize other TX queues (queues not in STA_RECs)
585 for(u4QueArrayIdx = 0; u4QueArrayIdx < NUM_OF_PER_TYPE_TX_QUEUES; u4QueArrayIdx++){
586 QUEUE_INITIALIZE(&(prQM->arTxQueue[u4QueArrayIdx]));
589 //4 <3> Initialize the RX BA table and RX queues
590 /* Initialize the RX Reordering Parameters and Queues */
591 for(u4QueArrayIdx = 0; u4QueArrayIdx < CFG_NUM_OF_RX_BA_AGREEMENTS; u4QueArrayIdx++){
592 prQM->arRxBaTable[u4QueArrayIdx].fgIsValid = FALSE;
593 QUEUE_INITIALIZE(&(prQM->arRxBaTable[u4QueArrayIdx].rReOrderQue));
594 prQM->arRxBaTable[u4QueArrayIdx].u2WinStart = 0xFFFF;
595 prQM->arRxBaTable[u4QueArrayIdx].u2WinEnd = 0xFFFF;
597 prQM->arRxBaTable[u4QueArrayIdx].fgIsWaitingForPktWithSsn = FALSE;
600 prQM->ucRxBaCount = 0;
602 kalMemSet(&g_arMissTimeout, 0, sizeof(g_arMissTimeout));
604 #if QM_ADAPTIVE_TC_RESOURCE_CTRL
605 //4 <4> Initialize TC resource control variables
606 for(i = 0; i < TC_NUM; i++){
607 prQM->au4AverageQueLen[i] = 0;
609 prQM->u4TimeToAdjustTcResource = QM_INIT_TIME_TO_ADJUST_TC_RSC;
610 prQM->u4TimeToUpdateQueLen = QM_INIT_TIME_TO_UPDATE_QUE_LEN;
612 // ASSERT(prQM->u4TimeToAdjust && prQM->u4TimeToUpdateQueLen);
614 prQM->au4CurrentTcResource[TC0_INDEX] = NIC_TX_BUFF_COUNT_TC0;
615 prQM->au4CurrentTcResource[TC1_INDEX] = NIC_TX_BUFF_COUNT_TC1;
616 prQM->au4CurrentTcResource[TC2_INDEX] = NIC_TX_BUFF_COUNT_TC2;
617 prQM->au4CurrentTcResource[TC3_INDEX] = NIC_TX_BUFF_COUNT_TC3;
618 prQM->au4CurrentTcResource[TC4_INDEX] = NIC_TX_BUFF_COUNT_TC4; /* Not adjustable (TX port 1)*/
619 prQM->au4CurrentTcResource[TC5_INDEX] = NIC_TX_BUFF_COUNT_TC5;
621 prQM->au4MinReservedTcResource[TC0_INDEX] = QM_MIN_RESERVED_TC0_RESOURCE;
622 prQM->au4MinReservedTcResource[TC1_INDEX] = QM_MIN_RESERVED_TC1_RESOURCE;
623 prQM->au4MinReservedTcResource[TC2_INDEX] = QM_MIN_RESERVED_TC2_RESOURCE;
624 prQM->au4MinReservedTcResource[TC3_INDEX] = QM_MIN_RESERVED_TC3_RESOURCE;
625 prQM->au4MinReservedTcResource[TC4_INDEX] = QM_MIN_RESERVED_TC4_RESOURCE; /* Not adjustable (TX port 1)*/
626 prQM->au4MinReservedTcResource[TC5_INDEX] = QM_MIN_RESERVED_TC5_RESOURCE;
629 prQM->au4GuaranteedTcResource[TC0_INDEX] = QM_GUARANTEED_TC0_RESOURCE;
630 prQM->au4GuaranteedTcResource[TC1_INDEX] = QM_GUARANTEED_TC1_RESOURCE;
631 prQM->au4GuaranteedTcResource[TC2_INDEX] = QM_GUARANTEED_TC2_RESOURCE;
632 prQM->au4GuaranteedTcResource[TC3_INDEX] = QM_GUARANTEED_TC3_RESOURCE;
633 prQM->au4GuaranteedTcResource[TC4_INDEX] = QM_GUARANTEED_TC4_RESOURCE;
634 prQM->au4GuaranteedTcResource[TC5_INDEX] = QM_GUARANTEED_TC5_RESOURCE;
636 prQM->fgTcResourcePostAnnealing = FALSE;
638 ASSERT(QM_INITIAL_RESIDUAL_TC_RESOURCE < 64);
642 prQM->u4PktCount = 0;
644 #if QM_TEST_FAIR_FORWARDING
646 prQM->u4CurrentStaRecIndexToEnqueue = 0;
648 UINT_8 aucMacAddr[MAC_ADDR_LEN];
649 P_STA_RECORD_T prStaRec;
651 /* Irrelevant in case this STA is an AIS AP (see qmDetermineStaRecIndex()) */
652 aucMacAddr[0] = 0x11;
653 aucMacAddr[1] = 0x22;
654 aucMacAddr[2] = 0xAA;
655 aucMacAddr[3] = 0xBB;
656 aucMacAddr[4] = 0xCC;
657 aucMacAddr[5] = 0xDD;
659 prStaRec = &prAdapter->arStaRec[1];
662 prStaRec->fgIsValid = TRUE;
663 prStaRec->fgIsQoS = TRUE;
664 prStaRec->fgIsInPS = FALSE;
665 prStaRec->ucPsSessionID = 0xFF;
666 prStaRec->ucNetTypeIndex = NETWORK_TYPE_AIS_INDEX;
667 prStaRec->fgIsAp = TRUE;
668 COPY_MAC_ADDR((prStaRec)->aucMacAddr,aucMacAddr);
676 #if QM_FORWARDING_FAIRNESS
679 for (i=0; i < NUM_OF_PER_STA_TX_QUEUES; i++){
680 prQM->au4ForwardCount[i] = 0;
681 prQM->au4HeadStaRecIndex[i] = 0;
691 IN P_ADAPTER_T prAdapter
694 P_QUE_MGT_T prQM = &prAdapter->rQM;
696 DbgPrint("QM: ** TEST MODE **\n");
698 if(QM_TEST_STA_REC_DETERMINATION){
699 if(prAdapter->arStaRec[0].fgIsValid){
700 prAdapter->arStaRec[0].fgIsValid = FALSE;
701 DbgPrint("QM: (Test) Deactivate STA_REC[0]\n");
704 prAdapter->arStaRec[0].fgIsValid = TRUE;
705 DbgPrint("QM: (Test) Activate STA_REC[0]\n");
709 if(QM_TEST_STA_REC_DEACTIVATION){
710 /* Note that QM_STA_REC_HARD_CODING shall be set to 1 for this test */
712 if(prAdapter->arStaRec[0].fgIsValid){
714 DbgPrint("QM: (Test) Deactivate STA_REC[0]\n");
715 qmDeactivateStaRec(prAdapter,0);
719 UINT_8 aucMacAddr[MAC_ADDR_LEN];
721 /* Irrelevant in case this STA is an AIS AP (see qmDetermineStaRecIndex()) */
722 aucMacAddr[0] = 0x11;
723 aucMacAddr[1] = 0x22;
724 aucMacAddr[2] = 0xAA;
725 aucMacAddr[3] = 0xBB;
726 aucMacAddr[4] = 0xCC;
727 aucMacAddr[5] = 0xDD;
729 DbgPrint("QM: (Test) Activate STA_REC[0]\n");
731 prAdapter, /* Adapter pointer */
732 0, /* STA_REC index from FW */
734 NETWORK_TYPE_AIS_INDEX, /* Network type */
736 aucMacAddr /* MAC address */
741 if(QM_TEST_FAIR_FORWARDING){
742 if(prAdapter->arStaRec[1].fgIsValid){
743 prQM->u4CurrentStaRecIndexToEnqueue ++;
744 prQM->u4CurrentStaRecIndexToEnqueue %= 2;
745 DbgPrint("QM: (Test) Switch to STA_REC[%ld]\n", prQM->u4CurrentStaRecIndexToEnqueue);
752 /*----------------------------------------------------------------------------*/
754 * \brief Activate a STA_REC
756 * \param[in] prAdapter Pointer to the Adapter instance
757 * \param[in] u4StaRecIdx The index of the STA_REC
758 * \param[in] fgIsQoS Set to TRUE if this is a QoS STA
759 * \param[in] pucMacAddr The MAC address of the STA
763 /*----------------------------------------------------------------------------*/
766 IN P_ADAPTER_T prAdapter,
767 IN P_STA_RECORD_T prStaRec
771 //4 <1> Deactivate first
774 if(prStaRec->fgIsValid){ /* The STA_REC has been activated */
775 DBGLOG(QM, WARN, ("QM: (WARNING) Activating a STA_REC which has been activated \n"));
776 DBGLOG(QM, WARN, ("QM: (WARNING) Deactivating a STA_REC before re-activating \n"));
777 qmDeactivateStaRec(prAdapter, prStaRec->ucIndex); // To flush TX/RX queues and del RX BA agreements
780 //4 <2> Activate the STA_REC
781 /* Init the STA_REC */
782 prStaRec->fgIsValid = TRUE;
783 prStaRec->fgIsInPS = FALSE;
784 prStaRec->ucPsSessionID = 0xFF;
785 prStaRec->fgIsAp = (IS_AP_STA(prStaRec)) ? TRUE : FALSE;;
787 /* Done in qmInit() or qmDeactivateStaRec() */
789 /* At the beginning, no RX BA agreements have been established */
790 for(i =0; i<CFG_RX_MAX_BA_TID_NUM; i++){
791 (prStaRec->aprRxReorderParamRefTbl)[i] = NULL;
795 DBGLOG(QM, INFO, ("QM: +STA[%ld]\n", prStaRec->ucIndex));
798 /*----------------------------------------------------------------------------*/
800 * \brief Deactivate a STA_REC
802 * \param[in] prAdapter Pointer to the Adapter instance
803 * \param[in] u4StaRecIdx The index of the STA_REC
807 /*----------------------------------------------------------------------------*/
810 IN P_ADAPTER_T prAdapter,
811 IN UINT_32 u4StaRecIdx
814 P_STA_RECORD_T prStaRec;
816 P_MSDU_INFO_T prFlushedTxPacketList = NULL;
818 ASSERT(u4StaRecIdx < CFG_NUM_OF_STA_RECORD);
820 prStaRec = &prAdapter->arStaRec[u4StaRecIdx];
823 //4<1> Flush TX queues
824 prFlushedTxPacketList = qmFlushStaTxQueues(prAdapter, u4StaRecIdx);
826 if(prFlushedTxPacketList){
827 wlanProcessQueuedMsduInfo(prAdapter, prFlushedTxPacketList);
830 //4 <2> Flush RX queues and delete RX BA agreements
831 for(i =0; i < CFG_RX_MAX_BA_TID_NUM; i++){
832 /* Delete the RX BA entry with TID = i */
833 qmDelRxBaEntry(prAdapter, (UINT_8)u4StaRecIdx, (UINT_8)i, FALSE);
836 //4 <3> Deactivate the STA_REC
837 prStaRec->fgIsValid = FALSE;
838 prStaRec->fgIsInPS = FALSE;
840 DBGLOG(QM, INFO, ("QM: -STA[%ld]\n", u4StaRecIdx));
844 /*----------------------------------------------------------------------------*/
846 * \brief Deactivate a STA_REC
848 * \param[in] prAdapter Pointer to the Adapter instance
849 * \param[in] u4StaRecIdx The index of the network
853 /*----------------------------------------------------------------------------*/
857 IN P_ADAPTER_T prAdapter,
858 IN ENUM_NETWORK_TYPE_INDEX_T eNetworkTypeIdx
864 QUE_T rNeedToFreeQue;
866 P_QUE_T prNeedToFreeQue;
868 P_MSDU_INFO_T prMsduInfo;
871 prQM = &prAdapter->rQM;
872 prQue = &prQM->arTxQueue[TX_QUEUE_INDEX_BMCAST];
874 QUEUE_INITIALIZE(&rNeedToFreeQue);
875 QUEUE_INITIALIZE(&rTempQue);
877 prNeedToFreeQue = &rNeedToFreeQue;
878 prTempQue = &rTempQue;
880 QUEUE_MOVE_ALL(prTempQue, prQue);
882 QUEUE_REMOVE_HEAD(prTempQue, prMsduInfo, P_MSDU_INFO_T);
885 if(prMsduInfo->ucNetworkType == eNetworkTypeIdx) {
886 QUEUE_INSERT_TAIL(prNeedToFreeQue, (P_QUE_ENTRY_T)prMsduInfo);
889 QUEUE_INSERT_TAIL(prQue, (P_QUE_ENTRY_T)prMsduInfo);
892 QUEUE_REMOVE_HEAD(prTempQue, prMsduInfo, P_MSDU_INFO_T);
894 if(QUEUE_IS_NOT_EMPTY(prNeedToFreeQue)) {
895 wlanProcessQueuedMsduInfo(prAdapter, (P_MSDU_INFO_T)QUEUE_GET_HEAD(prNeedToFreeQue));
900 /*----------------------------------------------------------------------------*/
902 * \brief Flush all TX queues
906 * \return The flushed packets (in a list of MSDU_INFOs)
908 /*----------------------------------------------------------------------------*/
911 IN P_ADAPTER_T prAdapter
914 UINT_8 ucStaArrayIdx;
915 UINT_8 ucQueArrayIdx;
917 P_MSDU_INFO_T prMsduInfoListHead;
918 P_MSDU_INFO_T prMsduInfoListTail;
920 P_QUE_MGT_T prQM = &prAdapter->rQM;
922 DBGLOG(QM, TRACE, ("QM: Enter qmFlushTxQueues()\n"));
924 prMsduInfoListHead = NULL;
925 prMsduInfoListTail = NULL;
927 /* Concatenate all MSDU_INFOs in per-STA queues */
928 for(ucStaArrayIdx = 0; ucStaArrayIdx < CFG_NUM_OF_STA_RECORD; ucStaArrayIdx++){
930 /* Always check each STA_REC when flushing packets no matter it is inactive or active */
932 if(!prAdapter->arStaRec[ucStaArrayIdx].fgIsValid){
933 continue; /* Continue to check the next STA_REC */
937 for(ucQueArrayIdx = 0; ucQueArrayIdx < NUM_OF_PER_STA_TX_QUEUES; ucQueArrayIdx++){
938 if(QUEUE_IS_EMPTY(&(prAdapter->arStaRec[ucStaArrayIdx].arTxQueue[ucQueArrayIdx]))){
939 continue; /* Continue to check the next TX queue of the same STA */
942 if(!prMsduInfoListHead){
944 /* The first MSDU_INFO is found */
945 prMsduInfoListHead =(P_MSDU_INFO_T)
946 QUEUE_GET_HEAD(&prAdapter->arStaRec[ucStaArrayIdx].arTxQueue[ucQueArrayIdx]);
947 prMsduInfoListTail =(P_MSDU_INFO_T)
948 QUEUE_GET_TAIL(&prAdapter->arStaRec[ucStaArrayIdx].arTxQueue[ucQueArrayIdx]);
951 /* Concatenate the MSDU_INFO list with the existing list */
952 QM_TX_SET_NEXT_MSDU_INFO(prMsduInfoListTail,
953 QUEUE_GET_HEAD(&prAdapter->arStaRec[ucStaArrayIdx].arTxQueue[ucQueArrayIdx]));
955 prMsduInfoListTail = (P_MSDU_INFO_T)
956 QUEUE_GET_TAIL(&prAdapter->arStaRec[ucStaArrayIdx].arTxQueue[ucQueArrayIdx]);
959 QUEUE_INITIALIZE(&prAdapter->arStaRec[ucStaArrayIdx].arTxQueue[ucQueArrayIdx]);
963 /* Flush per-Type queues */
964 for(ucQueArrayIdx = 0; ucQueArrayIdx < NUM_OF_PER_TYPE_TX_QUEUES; ucQueArrayIdx++){
966 if(QUEUE_IS_EMPTY(&(prQM->arTxQueue[ucQueArrayIdx]))){
967 continue; /* Continue to check the next TX queue of the same STA */
970 if(!prMsduInfoListHead){
972 /* The first MSDU_INFO is found */
973 prMsduInfoListHead =(P_MSDU_INFO_T)
974 QUEUE_GET_HEAD(&prQM->arTxQueue[ucQueArrayIdx]);
975 prMsduInfoListTail =(P_MSDU_INFO_T)
976 QUEUE_GET_TAIL(&prQM->arTxQueue[ucQueArrayIdx]);
979 /* Concatenate the MSDU_INFO list with the existing list */
980 QM_TX_SET_NEXT_MSDU_INFO(prMsduInfoListTail,
981 QUEUE_GET_HEAD(&prQM->arTxQueue[ucQueArrayIdx]));
983 prMsduInfoListTail = (P_MSDU_INFO_T)
984 QUEUE_GET_TAIL(&prQM->arTxQueue[ucQueArrayIdx]);
987 QUEUE_INITIALIZE(&prQM->arTxQueue[ucQueArrayIdx]);
991 if(prMsduInfoListTail){
992 /* Terminate the MSDU_INFO list with a NULL pointer */
993 QM_TX_SET_NEXT_MSDU_INFO(prMsduInfoListTail, NULL);
996 return prMsduInfoListHead;
1000 /*----------------------------------------------------------------------------*/
1002 * \brief Flush TX packets for a particular STA
1004 * \param[in] u4StaRecIdx STA_REC index
1006 * \return The flushed packets (in a list of MSDU_INFOs)
1008 /*----------------------------------------------------------------------------*/
1011 IN P_ADAPTER_T prAdapter,
1012 IN UINT_32 u4StaRecIdx
1015 UINT_8 ucQueArrayIdx;
1016 P_MSDU_INFO_T prMsduInfoListHead;
1017 P_MSDU_INFO_T prMsduInfoListTail;
1018 P_STA_RECORD_T prStaRec;
1020 DBGLOG(QM, TRACE, ("QM: Enter qmFlushStaTxQueues(%ld)\n", u4StaRecIdx));
1022 ASSERT(u4StaRecIdx < CFG_NUM_OF_STA_RECORD);
1024 prMsduInfoListHead = NULL;
1025 prMsduInfoListTail = NULL;
1027 prStaRec = &prAdapter->arStaRec[u4StaRecIdx];
1030 /* No matter whether this is an activated STA_REC, do flush */
1032 if(!prStaRec->fgIsValid){
1037 /* Concatenate all MSDU_INFOs in TX queues of this STA_REC */
1038 for(ucQueArrayIdx = 0; ucQueArrayIdx < NUM_OF_PER_STA_TX_QUEUES; ucQueArrayIdx++){
1039 if(QUEUE_IS_EMPTY(&(prStaRec->arTxQueue[ucQueArrayIdx]))){
1043 if(!prMsduInfoListHead){
1044 /* The first MSDU_INFO is found */
1045 prMsduInfoListHead =(P_MSDU_INFO_T)
1046 QUEUE_GET_HEAD(&prStaRec->arTxQueue[ucQueArrayIdx]);
1047 prMsduInfoListTail =(P_MSDU_INFO_T)
1048 QUEUE_GET_TAIL(&prStaRec->arTxQueue[ucQueArrayIdx]); }
1050 /* Concatenate the MSDU_INFO list with the existing list */
1051 QM_TX_SET_NEXT_MSDU_INFO(prMsduInfoListTail,
1052 QUEUE_GET_HEAD(&prStaRec->arTxQueue[ucQueArrayIdx]));
1054 prMsduInfoListTail =
1055 (P_MSDU_INFO_T)QUEUE_GET_TAIL(&prStaRec->arTxQueue[ucQueArrayIdx]);
1058 QUEUE_INITIALIZE(&prStaRec->arTxQueue[ucQueArrayIdx]);
1063 if(prMsduInfoListTail){
1064 /* Terminate the MSDU_INFO list with a NULL pointer */
1065 QM_TX_SET_NEXT_MSDU_INFO(prMsduInfoListTail, nicGetPendingStaMMPDU(prAdapter, (UINT_8)u4StaRecIdx));
1068 prMsduInfoListHead = nicGetPendingStaMMPDU(prAdapter, (UINT_8)u4StaRecIdx);
1072 return prMsduInfoListHead;
1076 /*----------------------------------------------------------------------------*/
1078 * \brief Flush RX packets
1082 * \return The flushed packets (in a list of SW_RFBs)
1084 /*----------------------------------------------------------------------------*/
1087 IN P_ADAPTER_T prAdapter
1091 P_SW_RFB_T prSwRfbListHead;
1092 P_SW_RFB_T prSwRfbListTail;
1093 P_QUE_MGT_T prQM = &prAdapter->rQM;
1095 prSwRfbListHead = prSwRfbListTail = NULL;
1097 DBGLOG(QM, TRACE, ("QM: Enter qmFlushRxQueues()\n"));
1099 for(i =0; i<CFG_NUM_OF_RX_BA_AGREEMENTS; i++){
1100 if(QUEUE_IS_NOT_EMPTY(&(prQM->arRxBaTable[i].rReOrderQue))){
1101 if(!prSwRfbListHead){
1103 /* The first MSDU_INFO is found */
1104 prSwRfbListHead =(P_SW_RFB_T)
1105 QUEUE_GET_HEAD(&(prQM->arRxBaTable[i].rReOrderQue));
1106 prSwRfbListTail =(P_SW_RFB_T)
1107 QUEUE_GET_TAIL(&(prQM->arRxBaTable[i].rReOrderQue));
1110 /* Concatenate the MSDU_INFO list with the existing list */
1111 QM_TX_SET_NEXT_MSDU_INFO(prSwRfbListTail,
1112 QUEUE_GET_HEAD(&(prQM->arRxBaTable[i].rReOrderQue)));
1114 prSwRfbListTail = (P_SW_RFB_T)
1115 QUEUE_GET_TAIL(&(prQM->arRxBaTable[i].rReOrderQue));
1118 QUEUE_INITIALIZE(&(prQM->arRxBaTable[i].rReOrderQue));
1126 if(prSwRfbListTail){
1127 /* Terminate the MSDU_INFO list with a NULL pointer */
1128 QM_TX_SET_NEXT_SW_RFB(prSwRfbListTail, NULL);
1130 return prSwRfbListHead;
1135 /*----------------------------------------------------------------------------*/
1137 * \brief Flush RX packets with respect to a particular STA
1139 * \param[in] u4StaRecIdx STA_REC index
1140 * \param[in] u4Tid TID
1142 * \return The flushed packets (in a list of SW_RFBs)
1144 /*----------------------------------------------------------------------------*/
1147 IN P_ADAPTER_T prAdapter,
1148 IN UINT_32 u4StaRecIdx,
1153 P_SW_RFB_T prSwRfbListHead;
1154 P_SW_RFB_T prSwRfbListTail;
1155 P_RX_BA_ENTRY_T prReorderQueParm;
1156 P_STA_RECORD_T prStaRec;
1158 DBGLOG(QM, TRACE, ("QM: Enter qmFlushStaRxQueues(%ld)\n", u4StaRecIdx));
1160 prSwRfbListHead = prSwRfbListTail = NULL;
1162 prStaRec = &prAdapter->arStaRec[u4StaRecIdx];
1165 /* No matter whether this is an activated STA_REC, do flush */
1167 if(!prStaRec->fgIsValid){
1172 /* Obtain the RX BA Entry pointer */
1173 prReorderQueParm = ((prStaRec->aprRxReorderParamRefTbl)[u4Tid]);
1175 /* Note: For each queued packet, prCurrSwRfb->eDst equals RX_PKT_DESTINATION_HOST */
1176 if(prReorderQueParm){
1178 if(QUEUE_IS_NOT_EMPTY(&(prReorderQueParm->rReOrderQue))){
1180 prSwRfbListHead =(P_SW_RFB_T)
1181 QUEUE_GET_HEAD(&(prReorderQueParm->rReOrderQue));
1182 prSwRfbListTail =(P_SW_RFB_T)
1183 QUEUE_GET_TAIL(&(prReorderQueParm->rReOrderQue));
1186 QUEUE_INITIALIZE(&(prReorderQueParm->rReOrderQue));
1191 if(prSwRfbListTail){
1192 /* Terminate the MSDU_INFO list with a NULL pointer */
1193 QM_TX_SET_NEXT_SW_RFB(prSwRfbListTail, NULL);
1195 return prSwRfbListHead;
1201 /*----------------------------------------------------------------------------*/
1203 * \brief Enqueue TX packets
1205 * \param[in] prMsduInfoListHead Pointer to the list of TX packets
1207 * \return The freed packets, which are not enqueued
1209 /*----------------------------------------------------------------------------*/
1212 IN P_ADAPTER_T prAdapter,
1213 IN P_MSDU_INFO_T prMsduInfoListHead
1216 P_MSDU_INFO_T prMsduInfoReleaseList;
1217 P_MSDU_INFO_T prCurrentMsduInfo;
1218 P_MSDU_INFO_T prNextMsduInfo;
1220 P_STA_RECORD_T prStaRec;
1222 QUE_T rNotEnqueuedQue;
1225 UINT_8 ucPacketType;
1227 P_QUE_MGT_T prQM = &prAdapter->rQM;
1228 UINT_8 aucNextUP[WMM_AC_INDEX_NUM] = { 1 /* BEtoBK*/, 1 /*na*/, 0/*VItoBE*/ , 4 /*VOtoVI*/};
1230 DBGLOG(QM, LOUD, ("Enter qmEnqueueTxPackets\n"));
1232 ASSERT(prMsduInfoListHead);
1234 #if QM_ADAPTIVE_TC_RESOURCE_CTRL
1237 //4 <0> Update TC resource control related variables
1238 /* Keep track of the queue length */
1239 if (--prQM->u4TimeToUpdateQueLen == 0){
1240 prQM->u4TimeToUpdateQueLen = QM_INIT_TIME_TO_UPDATE_QUE_LEN;
1241 qmUpdateAverageTxQueLen(prAdapter);
1246 /* Push TX packets into STA_REC (for UNICAST) or prAdapter->rQM (for BMCAST) */
1248 prMsduInfoReleaseList = NULL;
1249 prCurrentMsduInfo = NULL;
1250 QUEUE_INITIALIZE(&rNotEnqueuedQue);
1251 prNextMsduInfo = prMsduInfoListHead;
1254 P_BSS_INFO_T prBssInfo;
1255 BOOLEAN fgCheckACMAgain;
1256 ENUM_WMM_ACI_T eAci = WMM_AC_BE_INDEX;
1257 prCurrentMsduInfo = prNextMsduInfo;
1258 prNextMsduInfo = QM_TX_GET_NEXT_MSDU_INFO(prCurrentMsduInfo);
1261 //4 <1> Lookup the STA_REC index
1262 /* The ucStaRecIndex will be set in this function */
1263 qmDetermineStaRecIndex(prAdapter, prCurrentMsduInfo);
1264 ucPacketType = HIF_TX_PACKET_TYPE_DATA;
1266 DBGLOG(QM, LOUD , ("***** ucStaRecIndex = %d *****\n",
1267 prCurrentMsduInfo->ucStaRecIndex));
1270 prBssInfo = &(prAdapter->rWifiVar.arBssInfo[prCurrentMsduInfo->ucNetworkType]);
1272 if(IS_NET_ACTIVE(prAdapter, prCurrentMsduInfo->ucNetworkType)) {
1274 switch (prCurrentMsduInfo->ucStaRecIndex){
1275 case STA_REC_INDEX_BMCAST:
1276 prTxQue = &prQM->arTxQueue[TX_QUEUE_INDEX_BMCAST];
1279 if(prCurrentMsduInfo->ucNetworkType == NETWORK_TYPE_P2P_INDEX
1280 && prCurrentMsduInfo->eSrc != TX_PACKET_MGMT
1282 if(LINK_IS_EMPTY(&prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_P2P_INDEX].rStaRecOfClientList)) {
1283 prTxQue = &rNotEnqueuedQue;
1284 TX_INC_CNT(&prAdapter->rTxCtrl,TX_AP_BORADCAST_DROP);
1289 QM_DBG_CNT_INC(prQM, QM_DBG_CNT_23);
1292 case STA_REC_INDEX_NOT_FOUND:
1295 if(prCurrentMsduInfo->eSrc == TX_PACKET_FORWARDING) {
1297 /* if the packet is the forward type. the packet should be freed */
1298 DBGLOG(QM, TRACE, ("Forwarding packet but Sta is STA_REC_INDEX_NOT_FOUND\n"));
1299 //prTxQue = &rNotEnqueuedQue;
1301 prTxQue = &prQM->arTxQueue[TX_QUEUE_INDEX_NO_STA_REC];
1302 QM_DBG_CNT_INC(prQM, QM_DBG_CNT_24);
1307 prStaRec = QM_GET_STA_REC_PTR_FROM_INDEX(prAdapter, prCurrentMsduInfo->ucStaRecIndex);
1310 ASSERT(prStaRec->fgIsValid);
1312 if(prCurrentMsduInfo->ucUserPriority < 8) {
1313 QM_DBG_CNT_INC(prQM, prCurrentMsduInfo->ucUserPriority + 15);
1314 /* QM_DBG_CNT_15 */ /* QM_DBG_CNT_16 */ /* QM_DBG_CNT_17 */ /* QM_DBG_CNT_18 */
1315 /* QM_DBG_CNT_19 */ /* QM_DBG_CNT_20 */ /* QM_DBG_CNT_21 */ /* QM_DBG_CNT_22 */
1318 eAci = WMM_AC_BE_INDEX;
1320 fgCheckACMAgain = FALSE;
1321 if (prStaRec->fgIsQoS){
1322 switch(prCurrentMsduInfo->ucUserPriority){
1325 prTxQue = &prStaRec->arTxQueue[TX_QUEUE_INDEX_AC0];
1327 eAci = WMM_AC_BK_INDEX;
1331 prTxQue = &prStaRec->arTxQueue[TX_QUEUE_INDEX_AC1];
1333 eAci = WMM_AC_BE_INDEX;
1337 prTxQue = &prStaRec->arTxQueue[TX_QUEUE_INDEX_AC2];
1339 eAci = WMM_AC_VI_INDEX;
1343 prTxQue = &prStaRec->arTxQueue[TX_QUEUE_INDEX_AC3];
1345 eAci = WMM_AC_VO_INDEX;
1348 prTxQue = &prStaRec->arTxQueue[TX_QUEUE_INDEX_AC1];
1350 eAci = WMM_AC_BE_INDEX;
1354 if(prBssInfo->arACQueParms[eAci].fgIsACMSet && eAci != WMM_AC_BK_INDEX) {
1355 prCurrentMsduInfo->ucUserPriority = aucNextUP[eAci];
1356 fgCheckACMAgain = TRUE;
1360 prTxQue = &prStaRec->arTxQueue[TX_QUEUE_INDEX_AC1];
1364 while(fgCheckACMAgain);
1366 //LOG_FUNC ("QoS %u UP %u TC %u",prStaRec->fgIsQoS,prCurrentMsduInfo->ucUserPriority, ucTC);
1369 } /* switch (prCurrentMsduInfo->ucStaRecIndex) */
1371 if(prCurrentMsduInfo->eSrc == TX_PACKET_FORWARDING) {
1372 if(prTxQue->u4NumElem > 32) {
1373 DBGLOG(QM, INFO, ("Drop the Packet for full Tx queue (forwarding) Bss %u\n", prCurrentMsduInfo->ucNetworkType));
1374 prTxQue = &rNotEnqueuedQue;
1375 TX_INC_CNT(&prAdapter->rTxCtrl,TX_FORWARD_OVERFLOW_DROP);
1382 DBGLOG(QM, INFO, ("Drop the Packet for inactive Bss %u\n", prCurrentMsduInfo->ucNetworkType));
1383 QM_DBG_CNT_INC(prQM, QM_DBG_CNT_31);
1384 prTxQue = &rNotEnqueuedQue;
1385 TX_INC_CNT(&prAdapter->rTxCtrl,TX_INACTIVE_BSS_DROP);
1388 //4 <3> Fill the MSDU_INFO for constructing HIF TX header
1390 /* TODO: Fill MSDU_INFO according to the network type,
1391 * EtherType, and STA status (for PS forwarding control).
1394 /* Note that the Network Type Index and STA_REC index are determined in
1395 * qmDetermineStaRecIndex(prCurrentMsduInfo).
1397 QM_TX_SET_MSDU_INFO_FOR_DATA_PACKET(
1398 prCurrentMsduInfo, /* MSDU_INFO ptr */
1400 ucPacketType, /* Packet Type */
1402 prCurrentMsduInfo->fgIs802_1x, /* Flag 802.1x */
1403 prCurrentMsduInfo->fgIs802_11, /* Flag 802.11 */
1406 PS_FORWARDING_TYPE_NON_PS, /* PS Forwarding Type */
1407 0 /* PS Session ID */
1410 //4 <4> Enqueue the packet
1411 QUEUE_INSERT_TAIL(prTxQue, (P_QUE_ENTRY_T)prCurrentMsduInfo);
1415 if (++prQM->u4PktCount == QM_TEST_TRIGGER_TX_COUNT){
1416 prQM->u4PktCount = 0;
1417 qmTestCases(prAdapter);
1422 DBGLOG(QM, LOUD, ("Current queue length = %u\n", prTxQue->u4NumElem));
1423 }while(prNextMsduInfo);
1425 if( QUEUE_IS_NOT_EMPTY(&rNotEnqueuedQue) ) {
1426 QM_TX_SET_NEXT_MSDU_INFO((P_MSDU_INFO_T)QUEUE_GET_TAIL(&rNotEnqueuedQue), NULL);
1427 prMsduInfoReleaseList = (P_MSDU_INFO_T)QUEUE_GET_HEAD(&rNotEnqueuedQue);
1431 return prMsduInfoReleaseList;
1434 /*----------------------------------------------------------------------------*/
1436 * \brief Determine the STA_REC index for a packet
1438 * \param[in] prMsduInfo Pointer to the packet
1442 /*----------------------------------------------------------------------------*/
1444 qmDetermineStaRecIndex(
1445 IN P_ADAPTER_T prAdapter,
1446 IN P_MSDU_INFO_T prMsduInfo
1451 P_STA_RECORD_T prTempStaRec;
1452 //P_QUE_MGT_T prQM = &prAdapter->rQM;
1454 prTempStaRec = NULL;
1459 if (IS_BMCAST_MAC_ADDR(prMsduInfo->aucEthDestAddr)){
1460 /* For intrastructure mode and P2P (playing as a GC), BMCAST frames shall be sent to the AP.
1461 * FW shall take care of this. The host driver is not able to distinguish these cases. */
1462 prMsduInfo->ucStaRecIndex = STA_REC_INDEX_BMCAST;
1463 DBGLOG(QM, LOUD, ("TX with DA = BMCAST\n"));
1468 //4 <2> Check if an AP STA is present
1469 for (i = 0; i < CFG_NUM_OF_STA_RECORD; i++){
1470 prTempStaRec = &(prAdapter->arStaRec[i]);
1472 if((prTempStaRec->ucNetTypeIndex == prMsduInfo->ucNetworkType)
1473 && (prTempStaRec->fgIsAp)
1474 && (prTempStaRec->fgIsValid)){
1475 prMsduInfo->ucStaRecIndex = prTempStaRec->ucIndex;
1483 //4 <3> Not BMCAST, No AP --> Compare DA (i.e., to see whether this is a unicast frame to a client)
1484 for (i = 0; i < CFG_NUM_OF_STA_RECORD; i++){
1485 prTempStaRec = &(prAdapter->arStaRec[i]);
1486 if (prTempStaRec->fgIsValid){
1487 if (EQUAL_MAC_ADDR(prTempStaRec->aucMacAddr, prMsduInfo->aucEthDestAddr)){
1488 prMsduInfo->ucStaRecIndex = prTempStaRec->ucIndex;
1495 //4 <4> No STA found, Not BMCAST --> Indicate NOT_FOUND to FW
1496 prMsduInfo->ucStaRecIndex = STA_REC_INDEX_NOT_FOUND;
1497 DBGLOG(QM, LOUD, ("QM: TX with STA_REC_INDEX_NOT_FOUND\n"));
1500 #if (QM_TEST_MODE && QM_TEST_FAIR_FORWARDING)
1501 prMsduInfo->ucStaRecIndex = (UINT_8)prQM->u4CurrentStaRecIndexToEnqueue;
1505 /*----------------------------------------------------------------------------*/
1507 * \brief Dequeue TX packets from a STA_REC for a particular TC
1509 * \param[out] prQue The queue to put the dequeued packets
1510 * \param[in] ucTC The TC index (TC0_INDEX to TC5_INDEX)
1511 * \param[in] ucMaxNum The maximum amount of dequeued packets
1515 /*----------------------------------------------------------------------------*/
1517 qmDequeueTxPacketsFromPerStaQueues(
1518 IN P_ADAPTER_T prAdapter,
1521 IN UINT_8 ucCurrentQuota,
1522 IN UINT_8 ucTotalQuota
1526 #if QM_FORWARDING_FAIRNESS
1527 UINT_32 i; /* Loop for */
1529 PUINT_32 pu4HeadStaRecIndex; /* The Head STA index */
1530 PUINT_32 pu4HeadStaRecForwardCount; /* The total forwarded packets for the head STA */
1532 P_STA_RECORD_T prStaRec; /* The current focused STA */
1533 P_BSS_INFO_T prBssInfo; /* The Bss for current focused STA */
1534 P_QUE_T prCurrQueue; /* The current TX queue to dequeue */
1535 P_MSDU_INFO_T prDequeuedPkt; /* The dequeued packet */
1537 UINT_32 u4ForwardCount; /* To remember the total forwarded packets for a STA */
1538 UINT_32 u4MaxForwardCount; /* The maximum number of packets a STA can forward */
1539 UINT_32 u4Resource; /* The TX resource amount */
1541 BOOLEAN fgChangeHeadSta; /* Whether a new head STA shall be determined at the end of the function */
1542 P_QUE_MGT_T prQM = &prAdapter->rQM;
1544 PUINT_8 pucFreeQuota;
1546 DBGLOG(QM, LOUD, ("Enter qmDequeueTxPacketsFromPerStaQueues (TC = %u)\n", ucTC));
1548 ASSERT(ucTC == TC0_INDEX || ucTC == TC1_INDEX ||
1549 ucTC == TC2_INDEX || ucTC == TC3_INDEX ||
1553 if(!ucCurrentQuota){
1554 DBGLOG(TX, LOUD, ("@@@@@ TC = %u ucCurrentQuota = %u @@@@@\n",
1555 ucTC, ucCurrentQuota));
1559 u4Resource = ucCurrentQuota;
1561 //4 <1> Determine the head STA
1562 /* The head STA shall be an active STA */
1564 pu4HeadStaRecIndex = &(prQM->au4HeadStaRecIndex[ucTC]);
1565 pu4HeadStaRecForwardCount = &(prQM->au4ForwardCount[ucTC]);
1567 DBGLOG(QM, LOUD, ("(Fairness) TID = %u Init Head STA = %u Resource = %u\n",
1568 ucTC, *pu4HeadStaRecIndex, u4Resource));
1571 /* From STA[x] to STA[x+1] to STA[x+2] to ... to STA[x] */
1572 for (i=0; i < CFG_NUM_OF_STA_RECORD + 1; i++){
1573 prStaRec = &prAdapter->arStaRec[(*pu4HeadStaRecIndex)];
1576 /* Only Data frame (1x was not included) will be queued in */
1577 if (prStaRec->fgIsValid){
1579 prBssInfo = &(prAdapter->rWifiVar.arBssInfo[prStaRec->ucNetTypeIndex]);
1581 ASSERT(prBssInfo->ucNetTypeIndex == prStaRec->ucNetTypeIndex);
1583 /* Determine how many packets the head STA is allowed to send in a round */
1585 QM_DBG_CNT_INC(prQM, QM_DBG_CNT_25);
1586 u4MaxForwardCount = ucTotalQuota;
1587 #if CFG_ENABLE_WIFI_DIRECT
1589 pucFreeQuota = NULL;
1590 if(prStaRec->fgIsInPS && (ucTC!=TC4_INDEX)) {
1591 // TODO: Change the threshold in coorperation with the PS forwarding mechanism
1592 // u4MaxForwardCount = ucTotalQuota;
1593 /* Per STA flow control when STA in PS mode */
1594 /* The PHASE 1: only update from ucFreeQuota (now) */
1595 /* XXX The PHASE 2: Decide by ucFreeQuota and ucBmpDeliveryAC (per queue ) aucFreeQuotaPerQueue[] */
1596 /* NOTE: other method to set u4Resource */
1598 if(prStaRec->fgIsQoS && prStaRec->fgIsUapsdSupported
1599 /* && prAdapter->rWifiVar.fgSupportQoS
1600 && prAdapter->rWifiVar.fgSupportUAPSD*/) {
1602 if( prStaRec->ucBmpTriggerAC & BIT(ucTC)) {
1603 u4MaxForwardCount = prStaRec->ucFreeQuotaForDelivery;
1604 pucFreeQuota = &prStaRec->ucFreeQuotaForDelivery;
1607 u4MaxForwardCount = prStaRec->ucFreeQuotaForNonDelivery;
1608 pucFreeQuota = &prStaRec->ucFreeQuotaForNonDelivery;
1613 ASSERT(prStaRec->ucFreeQuotaForDelivery == 0);
1614 u4MaxForwardCount = prStaRec->ucFreeQuotaForNonDelivery;
1615 pucFreeQuota = &prStaRec->ucFreeQuotaForNonDelivery;
1619 #endif /* CFG_ENABLE_WIFI_DIRECT */
1621 #if CFG_ENABLE_WIFI_DIRECT
1622 if(prBssInfo->fgIsNetAbsent && (ucTC!=TC4_INDEX)) {
1623 if(u4MaxForwardCount > prBssInfo->ucBssFreeQuota) {
1624 u4MaxForwardCount = prBssInfo->ucBssFreeQuota;
1628 #endif /* CFG_ENABLE_WIFI_DIRECT */
1630 /* Determine whether the head STA can continue to forward packets in this round */
1631 if((*pu4HeadStaRecForwardCount) < u4MaxForwardCount){
1635 } /* prStaRec->fgIsValid */
1637 /* The current Head STA has been deactivated, so search for a new head STA */
1640 (*pu4HeadStaRecIndex) ++;
1641 (*pu4HeadStaRecIndex) %= CFG_NUM_OF_STA_RECORD;
1643 /* Reset the forwarding count before searching (since this is for a new selected STA) */
1644 (*pu4HeadStaRecForwardCount) = 0;
1646 } /* i < CFG_NUM_OF_STA_RECORD + 1 */
1648 /* All STA_RECs are inactive, so exit */
1650 /* Under concurrent, it is possible that there is no candidcated STA.*/
1651 //DBGLOG(TX, EVENT, ("All STA_RECs are inactive\n"));
1655 DBGLOG(QM, LOUD, ("(Fairness) TID = %u Round Head STA = %lu\n",
1656 ucTC, *pu4HeadStaRecIndex));
1658 //4 <2> Dequeue packets from the head STA
1660 prCurrQueue = &prStaRec->arTxQueue[ucTC];
1661 prDequeuedPkt = NULL;
1662 fgChangeHeadSta = FALSE;
1667 #if QM_DEBUG_COUNTER
1669 if(ucTC <= TC4_INDEX) {
1670 if(QUEUE_IS_EMPTY(prCurrQueue)) {
1671 QM_DBG_CNT_INC(prQM, ucTC);
1672 /* QM_DBG_CNT_00 */ /* QM_DBG_CNT_01 */ /* QM_DBG_CNT_02 */ /* QM_DBG_CNT_03 */ /* QM_DBG_CNT_04 */
1674 if(u4Resource == 0) {
1675 QM_DBG_CNT_INC(prQM, ucTC + 5);
1676 /* QM_DBG_CNT_05 */ /* QM_DBG_CNT_06 */ /* QM_DBG_CNT_07 */ /* QM_DBG_CNT_08 */ /* QM_DBG_CNT_09 */
1678 if(((*pu4HeadStaRecForwardCount) >= u4MaxForwardCount)) {
1679 QM_DBG_CNT_INC(prQM, ucTC + 10);
1680 /* QM_DBG_CNT_10 */ /* QM_DBG_CNT_11 */ /* QM_DBG_CNT_12 */ /* QM_DBG_CNT_13 */ /* QM_DBG_CNT_14 */
1686 /* Three cases to break: (1) No resource (2) No packets (3) Fairness */
1687 if (QUEUE_IS_EMPTY(prCurrQueue) || ((*pu4HeadStaRecForwardCount) >= u4MaxForwardCount)){
1688 fgChangeHeadSta = TRUE;
1691 else if (u4Resource == 0){
1696 QUEUE_REMOVE_HEAD(prCurrQueue, prDequeuedPkt, P_MSDU_INFO_T);
1698 LOG_FUNC("Deq0 TC %d queued %u net %u mac len %u len %u Type %u 1x %u 11 %u\n",
1699 prDequeuedPkt->ucTC,
1700 prCurrQueue->u4NumElem,
1701 prDequeuedPkt->ucNetworkType,
1702 prDequeuedPkt->ucMacHeaderLength,
1703 prDequeuedPkt->u2FrameLength,
1704 prDequeuedPkt->ucPacketType,
1705 prDequeuedPkt->fgIs802_1x,
1706 prDequeuedPkt->fgIs802_11 );
1708 LOG_FUNC("Dest Mac: " MACSTR "\n",
1709 MAC2STR(prDequeuedPkt->aucEthDestAddr));
1713 struct sk_buff *prSkb = (struct sk_buff *) prDequeuedPkt->prPacket;
1714 dumpMemory8((PUINT_8)prSkb->data,prSkb->len);
1720 ASSERT(prDequeuedPkt->ucTC == ucTC);
1722 if(!QUEUE_IS_EMPTY(prCurrQueue)) {
1723 /* XXX: check all queues for STA */
1724 prDequeuedPkt->ucPsForwardingType = PS_FORWARDING_MORE_DATA_ENABLED;
1727 QUEUE_INSERT_TAIL(prQue,(P_QUE_ENTRY_T)prDequeuedPkt);
1729 (*pu4HeadStaRecForwardCount) ++;
1732 #if CFG_ENABLE_WIFI_DIRECT
1733 /* XXX The PHASE 2: decrease from aucFreeQuotaPerQueue[] */
1734 if(prStaRec->fgIsInPS && (ucTC!=TC4_INDEX)) {
1735 ASSERT(pucFreeQuota);
1736 ASSERT(*pucFreeQuota>0);
1737 if(*pucFreeQuota>0) {
1738 *pucFreeQuota = *pucFreeQuota - 1;
1741 #endif /* CFG_ENABLE_WIFI_DIRECT */
1743 #if CFG_ENABLE_WIFI_DIRECT
1744 if(prBssInfo->fgIsNetAbsent && (ucTC!=TC4_INDEX)) {
1745 if(prBssInfo->ucBssFreeQuota>0) {
1746 prBssInfo->ucBssFreeQuota--;
1749 #endif /* CFG_ENABLE_WIFI_DIRECT */
1754 if (*pu4HeadStaRecForwardCount){
1755 DBGLOG(QM, LOUD, ("TC = %u Round Head STA = %lu, u4HeadStaRecForwardCount = %lu\n", ucTC, *pu4HeadStaRecIndex, (*pu4HeadStaRecForwardCount)));
1758 #if QM_BURST_END_INFO_ENABLED
1759 /* Let FW know which packet is the last one dequeued from the STA */
1761 prDequeuedPkt->fgIsBurstEnd = TRUE;
1766 //4 <3> Dequeue from the other STAs if there is residual TX resource
1768 /* Check all of the STAs to continue forwarding packets (including the head STA) */
1769 for (i= 0; i< CFG_NUM_OF_STA_RECORD; i++){
1770 /* Break in case no reasource is available */
1771 if (u4Resource == 0){
1775 /* The current head STA will be examined when i = CFG_NUM_OF_STA_RECORD-1 */
1776 prStaRec = &prAdapter->arStaRec[((*pu4HeadStaRecIndex) + i + 1) % CFG_NUM_OF_STA_RECORD];
1779 if (prStaRec->fgIsValid) {
1781 prBssInfo = &(prAdapter->rWifiVar.arBssInfo[prStaRec->ucNetTypeIndex]);
1782 ASSERT(prBssInfo->ucNetTypeIndex == prStaRec->ucNetTypeIndex);
1784 DBGLOG(QM, LOUD, ("(Fairness) TID = %u Sharing STA = %u Resource = %lu\n",
1785 ucTC, prStaRec->ucIndex, u4Resource));
1787 prCurrQueue = &prStaRec->arTxQueue[ucTC];
1789 u4MaxForwardCount = ucTotalQuota;
1791 #if CFG_ENABLE_WIFI_DIRECT
1792 pucFreeQuota = NULL;
1793 if(prStaRec->fgIsInPS && (ucTC!=TC4_INDEX)) {
1794 // TODO: Change the threshold in coorperation with the PS forwarding mechanism
1795 // u4MaxForwardCount = ucTotalQuota;
1796 /* Per STA flow control when STA in PS mode */
1797 /* The PHASE 1: only update from ucFreeQuota (now) */
1798 /* XXX The PHASE 2: Decide by ucFreeQuota and ucBmpDeliveryAC (per queue ) aucFreeQuotaPerQueue[] */
1799 /* NOTE: other method to set u4Resource */
1800 if(prStaRec->fgIsQoS && prStaRec->fgIsUapsdSupported
1801 /* && prAdapter->rWifiVar.fgSupportQoS
1802 && prAdapter->rWifiVar.fgSupportUAPSD*/) {
1804 if( prStaRec->ucBmpTriggerAC & BIT(ucTC)) {
1805 u4MaxForwardCount = prStaRec->ucFreeQuotaForDelivery;
1806 pucFreeQuota = &prStaRec->ucFreeQuotaForDelivery;
1809 u4MaxForwardCount = prStaRec->ucFreeQuotaForNonDelivery;
1810 pucFreeQuota = &prStaRec->ucFreeQuotaForNonDelivery;
1815 ASSERT(prStaRec->ucFreeQuotaForDelivery == 0);
1816 u4MaxForwardCount = prStaRec->ucFreeQuotaForNonDelivery;
1817 pucFreeQuota = &prStaRec->ucFreeQuotaForNonDelivery;
1821 #endif /* CFG_ENABLE_WIFI_DIRECT */
1822 #if CFG_ENABLE_WIFI_DIRECT
1823 if(prBssInfo->fgIsNetAbsent && (ucTC!=TC4_INDEX)) {
1824 if(u4MaxForwardCount > prBssInfo->ucBssFreeQuota) {
1825 u4MaxForwardCount = prBssInfo->ucBssFreeQuota;
1829 #endif /* CFG_ENABLE_WIFI_DIRECT */
1830 } /* prStaRec->fgIsValid */
1833 /* Invalid STA, so check the next STA */
1838 /* Three cases to break: (1) No resource (2) No packets (3) Fairness */
1839 if ((u4Resource == 0) || QUEUE_IS_EMPTY(prCurrQueue) || (u4ForwardCount >= u4MaxForwardCount)){
1844 QUEUE_REMOVE_HEAD(prCurrQueue, prDequeuedPkt, P_MSDU_INFO_T);
1847 DBGLOG(QM, LOUD, ("Deq0 TC %d queued %u net %u mac len %u len %u Type %u 1x %u 11 %u\n",
1848 prDequeuedPkt->ucTC,
1849 prCurrQueue->u4NumElem,
1850 prDequeuedPkt->ucNetworkType,
1851 prDequeuedPkt->ucMacHeaderLength,
1852 prDequeuedPkt->u2FrameLength,
1853 prDequeuedPkt->ucPacketType,
1854 prDequeuedPkt->fgIs802_1x,
1855 prDequeuedPkt->fgIs802_11 ));
1857 DBGLOG(QM, LOUD,("Dest Mac: " MACSTR "\n",
1858 MAC2STR(prDequeuedPkt->aucEthDestAddr)));
1862 struct sk_buff *prSkb = (struct sk_buff *) prDequeuedPkt->prPacket;
1863 dumpMemory8((PUINT_8)prSkb->data,prSkb->len);
1870 ASSERT(prDequeuedPkt->ucTC == ucTC);
1872 if(!QUEUE_IS_EMPTY(prCurrQueue)) {
1873 prDequeuedPkt->ucPsForwardingType = PS_FORWARDING_MORE_DATA_ENABLED;
1876 QUEUE_INSERT_TAIL(prQue,(P_QUE_ENTRY_T)prDequeuedPkt);
1880 #if CFG_ENABLE_WIFI_DIRECT
1881 /* XXX The PHASE 2: decrease from aucFreeQuotaPerQueue[] */
1882 if(prStaRec->fgIsInPS && (ucTC!=TC4_INDEX)) {
1883 ASSERT(pucFreeQuota);
1884 ASSERT(*pucFreeQuota>0);
1885 if(*pucFreeQuota>0) {
1886 *pucFreeQuota = *pucFreeQuota - 1;
1889 #endif /* CFG_ENABLE_WIFI_DIRECT */
1892 #if CFG_ENABLE_WIFI_DIRECT
1893 ASSERT(prBssInfo->ucNetTypeIndex == prStaRec->ucNetTypeIndex);
1894 if(prBssInfo->fgIsNetAbsent && (ucTC!=TC4_INDEX)) {
1895 if(prBssInfo->ucBssFreeQuota>0) {
1896 prBssInfo->ucBssFreeQuota--;
1899 #endif /* CFG_ENABLE_WIFI_DIRECT */
1904 #if QM_BURST_END_INFO_ENABLED
1905 /* Let FW know which packet is the last one dequeued from the STA */
1906 if (u4ForwardCount){
1907 prDequeuedPkt->fgIsBurstEnd = TRUE;
1913 if (fgChangeHeadSta){
1914 (*pu4HeadStaRecIndex) ++;
1915 (*pu4HeadStaRecIndex) %= CFG_NUM_OF_STA_RECORD;
1916 (*pu4HeadStaRecForwardCount) = 0;
1917 DBGLOG(QM, LOUD, ("(Fairness) TID = %u Scheduled Head STA = %lu Left Resource = %lu\n",
1918 ucTC, (*pu4HeadStaRecIndex), u4Resource));
1922 /***************************************************************************************/
1924 UINT_8 ucStaRecIndex;
1925 P_STA_RECORD_T prStaRec;
1926 P_QUE_T prCurrQueue;
1928 P_MSDU_INFO_T prDequeuedPkt;
1930 DBGLOG(QM, LOUD, ("Enter qmDequeueTxPacketsFromPerStaQueues (TC = %u)\n", ucTC));
1932 if (ucCurrentQuota == 0){
1936 //4 <1> Determine the queue index and the head STA
1939 ucStaRecIndex = 0; /* TODO: Get the current head STA */
1940 prStaRec = QM_GET_STA_REC_PTR_FROM_INDEX(prAdapter, ucStaRecIndex);
1943 if(prStaRec == NULL) {
1947 /* The queue to pull out packets */
1948 ASSERT(ucTC == TC0_INDEX || ucTC == TC1_INDEX ||
1949 ucTC == TC2_INDEX || ucTC == TC3_INDEX ||
1952 prCurrQueue = &prStaRec->arTxQueue[ucTC];
1954 ucPktCount = ucCurrentQuota;
1955 prDequeuedPkt = NULL;
1957 //4 <2> Dequeue packets for the head STA
1959 if (!(prStaRec->fgIsValid) || ucPktCount ==0 || QUEUE_IS_EMPTY(prCurrQueue)){
1965 QUEUE_REMOVE_HEAD(prCurrQueue, prDequeuedPkt, P_MSDU_INFO_T);
1966 //DbgPrint("QM: Remove Queue Head, TC= %d\n", prDequeuedPkt->ucTC);
1967 ASSERT(prDequeuedPkt->ucTC == ucTC);
1969 QUEUE_INSERT_TAIL(prQue,(P_QUE_ENTRY_T)prDequeuedPkt);
1974 //DbgPrint("QM: Remaining number of queued packets = %d\n", prCurrQueue->u4NumElem);
1976 #if QM_BURST_END_INFO_ENABLED
1978 prDequeuedPkt->fgIsBurstEnd = TRUE;
1983 //4 <3> Update scheduling info
1986 //4 <4> Utilize the remainaing TX opportunities for non-head STAs
1992 /*----------------------------------------------------------------------------*/
1994 * \brief Dequeue TX packets from a per-Type-based Queue for a particular TC
1996 * \param[out] prQue The queue to put the dequeued packets
1997 * \param[in] ucTC The TC index (Shall always be TC5_INDEX)
1998 * \param[in] ucMaxNum The maximum amount of dequeued packets
2002 /*----------------------------------------------------------------------------*/
2004 qmDequeueTxPacketsFromPerTypeQueues(
2005 IN P_ADAPTER_T prAdapter,
2011 //UINT_8 ucQueIndex;
2012 //UINT_8 ucStaRecIndex;
2013 P_BSS_INFO_T prBssInfo;
2014 P_BSS_INFO_T parBssInfo;
2015 P_QUE_T prCurrQueue;
2017 P_MSDU_INFO_T prDequeuedPkt;
2018 P_MSDU_INFO_T prBurstEndPkt;
2023 DBGLOG(QM, LOUD, ("Enter qmDequeueTxPacketsFromPerTypeQueues (TC = %d, Max = %d)\n", ucTC, ucMaxNum));
2025 /* TC5: Broadcast/Multicast data packets */
2026 ASSERT(ucTC == TC5_INDEX);
2032 prQM = &prAdapter->rQM;
2033 //4 <1> Determine the queue
2035 prCurrQueue = &prQM->arTxQueue[TX_QUEUE_INDEX_BMCAST];
2036 ucPktCount = ucMaxNum;
2037 prDequeuedPkt = NULL;
2038 prBurstEndPkt = NULL;
2040 parBssInfo = prAdapter->rWifiVar.arBssInfo;
2042 QUEUE_INITIALIZE(&rMergeQue);
2043 prMergeQue = &rMergeQue;
2045 //4 <2> Dequeue packets
2047 if(ucPktCount ==0 || QUEUE_IS_EMPTY(prCurrQueue)){
2051 QUEUE_REMOVE_HEAD(prCurrQueue, prDequeuedPkt, P_MSDU_INFO_T);
2052 ASSERT(prDequeuedPkt->ucTC == ucTC);
2054 ASSERT(prDequeuedPkt->ucNetworkType < NETWORK_TYPE_INDEX_NUM);
2056 prBssInfo = &parBssInfo[prDequeuedPkt->ucNetworkType];
2058 if(IS_BSS_ACTIVE(prBssInfo)) {
2059 if( !prBssInfo->fgIsNetAbsent){
2060 QUEUE_INSERT_TAIL(prQue,(P_QUE_ENTRY_T)prDequeuedPkt);
2061 prBurstEndPkt = prDequeuedPkt;
2063 QM_DBG_CNT_INC(prQM, QM_DBG_CNT_26);
2065 LOG_FUNC("DeqType TC %d queued %u net %u mac len %u len %u Type %u 1x %u 11 %u\n",
2066 prDequeuedPkt->ucTC,
2067 prCurrQueue->u4NumElem,
2068 prDequeuedPkt->ucNetworkType,
2069 prDequeuedPkt->ucMacHeaderLength,
2070 prDequeuedPkt->u2FrameLength,
2071 prDequeuedPkt->ucPacketType,
2072 prDequeuedPkt->fgIs802_1x,
2073 prDequeuedPkt->fgIs802_11 );
2075 LOG_FUNC("Dest Mac: " MACSTR "\n",
2076 MAC2STR(prDequeuedPkt->aucEthDestAddr));
2080 struct sk_buff *prSkb = (struct sk_buff *) prDequeuedPkt->prPacket;
2081 dumpMemory8((PUINT_8)prSkb->data,prSkb->len);
2088 QUEUE_INSERT_TAIL(prMergeQue,(P_QUE_ENTRY_T)prDequeuedPkt);
2092 QM_TX_SET_NEXT_MSDU_INFO(prDequeuedPkt, NULL);
2093 wlanProcessQueuedMsduInfo(prAdapter,prDequeuedPkt);
2098 if(QUEUE_IS_NOT_EMPTY(prMergeQue)) {
2099 QUEUE_CONCATENATE_QUEUES(prMergeQue, prCurrQueue);
2100 QUEUE_MOVE_ALL(prCurrQueue, prMergeQue);
2101 QM_TX_SET_NEXT_MSDU_INFO((P_MSDU_INFO_T)QUEUE_GET_TAIL(prCurrQueue), NULL);
2104 #if QM_BURST_END_INFO_ENABLED
2106 prBurstEndPkt->fgIsBurstEnd = TRUE;
2109 } /* qmDequeueTxPacketsFromPerTypeQueues */
2114 /*----------------------------------------------------------------------------*/
2116 * \brief Dequeue TX packets to send to HIF TX
2118 * \param[in] prTcqStatus Info about the maximum amount of dequeued packets
2120 * \return The list of dequeued TX packets
2122 /*----------------------------------------------------------------------------*/
2125 IN P_ADAPTER_T prAdapter,
2126 IN P_TX_TCQ_STATUS_T prTcqStatus
2131 P_MSDU_INFO_T prReturnedPacketListHead;
2134 DBGLOG(QM, LOUD, ("Enter qmDequeueTxPackets\n"));
2136 QUEUE_INITIALIZE(&rReturnedQue);
2138 prReturnedPacketListHead = NULL;
2140 /* TC0 to TC4: AC0~AC3, 802.1x (commands packets are not handled by QM) */
2141 for(i = TC4_INDEX; i >= TC0_INDEX; i--){
2142 DBGLOG(QM, LOUD, ("Dequeue packets from Per-STA queue[%u]\n", i));
2144 qmDequeueTxPacketsFromPerStaQueues(
2148 prTcqStatus->aucFreeBufferCount[i],
2149 prTcqStatus->aucMaxNumOfBuffer[i]
2152 /* The aggregate number of dequeued packets */
2153 DBGLOG(QM, LOUD, ("DQA)[%u](%lu)\n", i, rReturnedQue.u4NumElem));
2157 /* TC5 (BMCAST or STA-NOT-FOUND packets) */
2158 qmDequeueTxPacketsFromPerTypeQueues(
2162 prTcqStatus->aucFreeBufferCount[TC5_INDEX]
2165 DBGLOG(QM, LOUD, ("Current total number of dequeued packets = %u\n", rReturnedQue.u4NumElem));
2167 if (QUEUE_IS_NOT_EMPTY(&rReturnedQue)){
2168 prReturnedPacketListHead = (P_MSDU_INFO_T)QUEUE_GET_HEAD(&rReturnedQue);
2169 QM_TX_SET_NEXT_MSDU_INFO((P_MSDU_INFO_T)QUEUE_GET_TAIL(&rReturnedQue), NULL);
2172 return prReturnedPacketListHead;
2175 /*----------------------------------------------------------------------------*/
2177 * \brief Adjust the TC quotas according to traffic demands
2179 * \param[out] prTcqAdjust The resulting adjustment
2180 * \param[in] prTcqStatus Info about the current TC quotas and counters
2184 /*----------------------------------------------------------------------------*/
2187 IN P_ADAPTER_T prAdapter,
2188 OUT P_TX_TCQ_ADJUST_T prTcqAdjust,
2189 IN P_TX_TCQ_STATUS_T prTcqStatus
2192 #if QM_ADAPTIVE_TC_RESOURCE_CTRL
2194 P_QUE_MGT_T prQM = &prAdapter->rQM;
2196 /* Must initialize */
2197 for (i = 0; i < TC_NUM; i++){
2198 prTcqAdjust->acVariation[i]= 0;
2201 //4 <1> If TC resource is not just adjusted, exit directly
2202 if (!prQM->fgTcResourcePostAnnealing){
2206 //4 <2> Adjust TcqStatus according to the updated prQM->au4CurrentTcResource
2208 INT_32 i4TotalExtraQuota = 0;
2209 INT_32 ai4ExtraQuota[TC_NUM];
2210 BOOLEAN fgResourceRedistributed = TRUE;
2212 /* Obtain the free-to-distribute resource */
2213 for (i = 0; i < TC_NUM; i++){
2214 ai4ExtraQuota[i] = (INT_32)prTcqStatus->aucMaxNumOfBuffer[i] - (INT_32)prQM->au4CurrentTcResource[i];
2216 if (ai4ExtraQuota[i] > 0){ /* The resource shall be reallocated to other TCs */
2217 if (ai4ExtraQuota[i] > prTcqStatus->aucFreeBufferCount[i]){
2218 ai4ExtraQuota[i] = prTcqStatus->aucFreeBufferCount[i];
2219 fgResourceRedistributed = FALSE;
2222 i4TotalExtraQuota += ai4ExtraQuota[i];
2223 prTcqAdjust->acVariation[i] = (INT_8)(-ai4ExtraQuota[i]);
2227 /* Distribute quotas to TCs which need extra resource according to prQM->au4CurrentTcResource */
2228 for (i = 0; i < TC_NUM; i++){
2229 if (ai4ExtraQuota[i] < 0){
2230 if ((-ai4ExtraQuota[i]) > i4TotalExtraQuota){
2231 ai4ExtraQuota[i] = (-i4TotalExtraQuota);
2232 fgResourceRedistributed = FALSE;
2235 i4TotalExtraQuota += ai4ExtraQuota[i];
2236 prTcqAdjust->acVariation[i] = (INT_8)(-ai4ExtraQuota[i]);
2240 /* In case some TC is waiting for TX Done, continue to adjust TC quotas upon TX Done */
2241 prQM->fgTcResourcePostAnnealing = (!fgResourceRedistributed);
2243 #if QM_PRINT_TC_RESOURCE_CTRL
2244 DBGLOG(QM, LOUD, ("QM: Curr Quota [0]=%u [1]=%u [2]=%u [3]=%u [4]=%u [5]=%u\n",
2245 prTcqStatus->aucFreeBufferCount[0],
2246 prTcqStatus->aucFreeBufferCount[1],
2247 prTcqStatus->aucFreeBufferCount[2],
2248 prTcqStatus->aucFreeBufferCount[3],
2249 prTcqStatus->aucFreeBufferCount[4],
2250 prTcqStatus->aucFreeBufferCount[5]
2257 for (i = 0; i < TC_NUM; i++){
2258 prTcqAdjust->acVariation[i]= 0;
2264 #if QM_ADAPTIVE_TC_RESOURCE_CTRL
2265 /*----------------------------------------------------------------------------*/
2267 * \brief Update the average TX queue length for the TC resource control mechanism
2273 /*----------------------------------------------------------------------------*/
2275 qmUpdateAverageTxQueLen(
2276 IN P_ADAPTER_T prAdapter
2279 INT_32 u4CurrQueLen, i, k;
2280 P_STA_RECORD_T prStaRec;
2281 P_QUE_MGT_T prQM = &prAdapter->rQM;
2283 //4 <1> Update the queue lengths for TC0 to TC3 (skip TC4) and TC5 */
2284 for (i = 0; i < NUM_OF_PER_STA_TX_QUEUES - 1; i++){
2287 for (k = 0; k < CFG_NUM_OF_STA_RECORD; k++){
2288 prStaRec = &prAdapter->arStaRec[k];
2291 /* If the STA is activated, get the queue length */
2292 if (prStaRec->fgIsValid &&
2293 (!prAdapter->rWifiVar.arBssInfo[prStaRec->ucNetTypeIndex].fgIsNetAbsent)
2297 u4CurrQueLen += (prStaRec->arTxQueue[i].u4NumElem);
2301 if (prQM->au4AverageQueLen[i] == 0){
2302 prQM->au4AverageQueLen[i] = (u4CurrQueLen << QM_QUE_LEN_MOVING_AVE_FACTOR);
2305 prQM->au4AverageQueLen[i] -= (prQM->au4AverageQueLen[i] >> QM_QUE_LEN_MOVING_AVE_FACTOR);
2306 prQM->au4AverageQueLen[i] += (u4CurrQueLen);
2311 /* Update the queue length for TC5 (BMCAST) */
2312 u4CurrQueLen = prQM->arTxQueue[TX_QUEUE_INDEX_BMCAST].u4NumElem;
2314 if (prQM->au4AverageQueLen[TC_NUM-1] == 0){
2315 prQM->au4AverageQueLen[TC_NUM-1] = (u4CurrQueLen << QM_QUE_LEN_MOVING_AVE_FACTOR);
2318 prQM->au4AverageQueLen[TC_NUM-1] -= (prQM->au4AverageQueLen[TC_NUM-1] >> QM_QUE_LEN_MOVING_AVE_FACTOR);
2319 prQM->au4AverageQueLen[TC_NUM-1] += (u4CurrQueLen);
2323 //4 <2> Adjust TC resource assignment
2324 /* Check whether it is time to adjust the TC resource assignment */
2325 if (--prQM->u4TimeToAdjustTcResource == 0){
2326 /* The last assignment has not been completely applied */
2327 if (prQM->fgTcResourcePostAnnealing){
2328 /* Upon the next qmUpdateAverageTxQueLen function call, do this check again */
2329 prQM->u4TimeToAdjustTcResource = 1;
2332 /* The last assignment has been applied */
2334 prQM->u4TimeToAdjustTcResource = QM_INIT_TIME_TO_ADJUST_TC_RSC;
2335 qmReassignTcResource(prAdapter);
2340 #if QM_PRINT_TC_RESOURCE_CTRL
2341 for (i=0; i<TC_NUM; i++){
2342 if(QM_GET_TX_QUEUE_LEN(prAdapter, i) >= 100){
2343 DBGLOG(QM, LOUD, ("QM: QueLen [%ld %ld %ld %ld %ld %ld]\n",
2344 QM_GET_TX_QUEUE_LEN(prAdapter, 0),
2345 QM_GET_TX_QUEUE_LEN(prAdapter, 1),
2346 QM_GET_TX_QUEUE_LEN(prAdapter, 2),
2347 QM_GET_TX_QUEUE_LEN(prAdapter, 3),
2348 QM_GET_TX_QUEUE_LEN(prAdapter, 4),
2349 QM_GET_TX_QUEUE_LEN(prAdapter, 5)
2360 /*----------------------------------------------------------------------------*/
2362 * \brief Assign TX resource for each TC according to TX queue length and current assignment
2368 /*----------------------------------------------------------------------------*/
2370 qmReassignTcResource(
2371 IN P_ADAPTER_T prAdapter
2374 INT_32 i4TotalResourceDemand = 0;
2375 UINT_32 u4ResidualResource = 0;
2377 INT_32 ai4PerTcResourceDemand[TC_NUM];
2378 UINT_32 u4ShareCount = 0;
2379 UINT_32 u4Share = 0 ;
2380 P_QUE_MGT_T prQM = &prAdapter->rQM;
2382 /* Note: After the new assignment is obtained, set prQM->fgTcResourcePostAnnealing to TRUE to
2383 * start the TC-quota adjusting procedure, which will be invoked upon every TX Done
2386 //4 <1> Determine the demands
2387 /* Determine the amount of extra resource to fulfill all of the demands */
2388 for (i=0; i<TC_NUM; i++){
2389 /* Skip TC4, which is not adjustable */
2390 if (i == TC4_INDEX) {
2394 /* Define: extra_demand = que_length + min_reserved_quota - current_quota */
2395 ai4PerTcResourceDemand[i] =
2396 ((UINT_32)(QM_GET_TX_QUEUE_LEN(prAdapter, i)) + prQM->au4MinReservedTcResource[i] - prQM->au4CurrentTcResource[i]);
2398 /* If there are queued packets, allocate extra resource for the TC (for TCP consideration) */
2399 if (QM_GET_TX_QUEUE_LEN(prAdapter, i)){
2400 ai4PerTcResourceDemand[i] += QM_EXTRA_RESERVED_RESOURCE_WHEN_BUSY;
2403 i4TotalResourceDemand += ai4PerTcResourceDemand[i];
2406 //4 <2> Case 1: Demand <= Total Resource
2407 if (i4TotalResourceDemand <= 0){
2408 //4 <2.1> Satisfy every TC
2409 for (i = 0; i < TC_NUM; i++){
2410 /* Skip TC4 (not adjustable) */
2411 if (i == TC4_INDEX) {
2415 prQM->au4CurrentTcResource[i] += ai4PerTcResourceDemand[i];
2418 //4 <2.2> Share the residual resource evenly
2419 u4ShareCount= (TC_NUM - 1); /* excluding TC4 */
2420 u4ResidualResource = (UINT_32)(-i4TotalResourceDemand);
2421 u4Share = (u4ResidualResource/u4ShareCount);
2423 for (i=0; i<TC_NUM; i++){
2424 /* Skip TC4 (not adjustable) */
2425 if (i == TC4_INDEX) {
2429 prQM->au4CurrentTcResource[i] += u4Share;
2431 /* Every TC is fully satisfied */
2432 ai4PerTcResourceDemand[i] = 0;
2434 /* The left resource will be allocated to TC3 */
2435 u4ResidualResource -= u4Share;
2438 //4 <2.3> Allocate the left resource to TC3 (VO)
2439 prQM->au4CurrentTcResource[TC3_INDEX] += (u4ResidualResource);
2443 //4 <3> Case 2: Demand > Total Resource --> Guarantee a minimum amount of resource for each TC
2445 u4ResidualResource = QM_INITIAL_RESIDUAL_TC_RESOURCE;
2447 //4 <3.1> Allocated resouce amount = minimum of (guaranteed, total demand)
2448 for (i=0; i<TC_NUM; i++){
2449 /* Skip TC4 (not adjustable) */
2450 if (i == TC4_INDEX) {
2454 /* The demand can be fulfilled with the guaranteed resource amount */
2455 if (prQM->au4CurrentTcResource[i] + ai4PerTcResourceDemand[i] < prQM->au4GuaranteedTcResource[i]){
2456 prQM->au4CurrentTcResource[i] += ai4PerTcResourceDemand[i];
2457 u4ResidualResource += (prQM->au4GuaranteedTcResource[i] - prQM->au4CurrentTcResource[i]);
2458 ai4PerTcResourceDemand[i] = 0;
2461 /* The demand can not be fulfilled with the guaranteed resource amount */
2463 ai4PerTcResourceDemand[i] -= (prQM->au4GuaranteedTcResource[i] - prQM->au4CurrentTcResource[i]);
2464 prQM->au4CurrentTcResource[i] = prQM->au4GuaranteedTcResource[i];
2469 //4 <3.2> Allocate the residual resource
2471 /* If there is no resource left, exit directly */
2472 if (u4ResidualResource == 0){
2476 /* This shall not happen */
2477 if (u4ShareCount == 0){
2478 prQM->au4CurrentTcResource[TC1_INDEX] += u4ResidualResource;
2479 DBGLOG(QM, ERROR, ("QM: (Error) u4ShareCount = 0\n"));
2483 /* Share the residual resource evenly */
2484 u4Share = (u4ResidualResource / u4ShareCount);
2486 for (i=0; i<TC_NUM; i++){
2487 /* Skip TC4 (not adjustable) */
2488 if (i == TC4_INDEX) {
2492 if (ai4PerTcResourceDemand[i]){
2493 if (ai4PerTcResourceDemand[i] - u4Share){
2494 prQM->au4CurrentTcResource[i] += u4Share;
2495 u4ResidualResource -= u4Share;
2496 ai4PerTcResourceDemand[i] -= u4Share;
2499 prQM->au4CurrentTcResource[i] += ai4PerTcResourceDemand[i];
2500 u4ResidualResource -= ai4PerTcResourceDemand[i];
2501 ai4PerTcResourceDemand[i] = 0;
2507 /* By priority, allocate the left resource that is not divisible by u4Share */
2508 if (u4ResidualResource == 0){
2512 if (ai4PerTcResourceDemand[TC3_INDEX]){ /* VO */
2513 prQM->au4CurrentTcResource[TC3_INDEX]++;
2514 if (--u4ResidualResource == 0) {
2519 if (ai4PerTcResourceDemand[TC2_INDEX]){ /* VI */
2520 prQM->au4CurrentTcResource[TC2_INDEX]++;
2521 if (--u4ResidualResource == 0) {
2526 if (ai4PerTcResourceDemand[TC5_INDEX]){ /* BMCAST */
2527 prQM->au4CurrentTcResource[TC5_INDEX]++;
2528 if (--u4ResidualResource == 0) {
2533 if (ai4PerTcResourceDemand[TC1_INDEX]){ /* BE */
2534 prQM->au4CurrentTcResource[TC1_INDEX]++;
2535 if (--u4ResidualResource == 0) {
2540 if (ai4PerTcResourceDemand[TC0_INDEX]){ /* BK */
2541 prQM->au4CurrentTcResource[TC0_INDEX]++;
2542 if (--u4ResidualResource == 0) {
2547 /* Allocate the left resource */
2548 prQM->au4CurrentTcResource[TC3_INDEX] += u4ResidualResource;
2553 prQM->fgTcResourcePostAnnealing = TRUE;
2555 #if QM_PRINT_TC_RESOURCE_CTRL
2557 DBGLOG(QM, LOUD, ("QM: TC Rsc %ld %ld %ld %ld %ld %ld\n",
2558 prQM->au4CurrentTcResource[0],
2559 prQM->au4CurrentTcResource[1],
2560 prQM->au4CurrentTcResource[2],
2561 prQM->au4CurrentTcResource[3],
2562 prQM->au4CurrentTcResource[4],
2563 prQM->au4CurrentTcResource[5]
2572 /*----------------------------------------------------------------------------*/
2573 /* RX-Related Queue Management */
2574 /*----------------------------------------------------------------------------*/
2575 /*----------------------------------------------------------------------------*/
2577 * \brief Init Queue Managment for RX
2583 /*----------------------------------------------------------------------------*/
2586 IN P_ADAPTER_T prAdapter
2589 //DbgPrint("QM: Enter qmInitRxQueues()\n");
2593 /*----------------------------------------------------------------------------*/
2595 * \brief Handle RX packets (buffer reordering)
2597 * \param[in] prSwRfbListHead The list of RX packets
2599 * \return The list of packets which are not buffered for reordering
2601 /*----------------------------------------------------------------------------*/
2604 IN P_ADAPTER_T prAdapter,
2605 IN P_SW_RFB_T prSwRfbListHead
2609 #if CFG_RX_REORDERING_ENABLED
2611 P_SW_RFB_T prCurrSwRfb;
2612 P_SW_RFB_T prNextSwRfb;
2613 P_HIF_RX_HEADER_T prHifRxHdr;
2615 PUINT_8 pucEthDestAddr;
2618 //DbgPrint("QM: Enter qmHandleRxPackets()\n");
2620 DEBUGFUNC("qmHandleRxPackets");
2622 ASSERT(prSwRfbListHead);
2624 QUEUE_INITIALIZE(&rReturnedQue);
2625 prNextSwRfb = prSwRfbListHead;
2628 prCurrSwRfb = prNextSwRfb;
2629 prNextSwRfb = QM_RX_GET_NEXT_SW_RFB(prCurrSwRfb);
2631 prHifRxHdr = prCurrSwRfb->prHifRxHdr; // TODO: (Tehuang) Use macro to obtain the pointer
2633 /* TODO: (Tehuang) Check if relaying */
2634 prCurrSwRfb->eDst = RX_PKT_DESTINATION_HOST;
2636 /* Decide the Destination */
2637 #if CFG_RX_PKTS_DUMP
2638 if (prAdapter->rRxCtrl.u4RxPktsDumpTypeMask & BIT(HIF_RX_PKT_TYPE_DATA)) {
2639 DBGLOG(SW4, INFO, ("QM RX DATA: net %u sta idx %u wlan idx %u ssn %u tid %u ptype %u 11 %u\n",
2640 HIF_RX_HDR_GET_NETWORK_IDX(prHifRxHdr),
2641 prHifRxHdr->ucStaRecIdx,
2642 prCurrSwRfb->ucWlanIdx,
2643 HIF_RX_HDR_GET_SN(prHifRxHdr), /* The new SN of the frame */
2644 HIF_RX_HDR_GET_TID(prHifRxHdr),
2645 prCurrSwRfb->ucPacketType,
2646 HIF_RX_HDR_GET_80211_FLAG(prHifRxHdr)));
2648 DBGLOG_MEM8(SW4, TRACE, (PUINT_8)prCurrSwRfb->pvHeader, prCurrSwRfb->u2PacketLen);
2653 if (!HIF_RX_HDR_GET_80211_FLAG(prHifRxHdr)){
2655 UINT_8 ucNetTypeIdx;
2656 P_BSS_INFO_T prBssInfo;
2658 pucEthDestAddr = prCurrSwRfb->pvHeader;
2659 ucNetTypeIdx = HIF_RX_HDR_GET_NETWORK_IDX(prHifRxHdr);
2661 prBssInfo = &(prAdapter->rWifiVar.arBssInfo[ucNetTypeIdx]);
2662 //DBGLOG_MEM8(QM, TRACE,prCurrSwRfb->pvHeader, 16);
2665 if (IS_BMCAST_MAC_ADDR(pucEthDestAddr) && (OP_MODE_ACCESS_POINT != prBssInfo->eCurrentOPMode)) {
2669 if( prAdapter->rRxCtrl.rFreeSwRfbList.u4NumElem
2670 > (CFG_RX_MAX_PKT_NUM - CFG_NUM_OF_QM_RX_PKT_NUM) ) {
2672 if(IS_BSS_ACTIVE(prBssInfo)) {
2673 if(OP_MODE_ACCESS_POINT == prBssInfo->eCurrentOPMode) {
2674 if (IS_BMCAST_MAC_ADDR(pucEthDestAddr)){
2675 prCurrSwRfb->eDst = RX_PKT_DESTINATION_HOST_WITH_FORWARD;
2677 else if(UNEQUAL_MAC_ADDR(prBssInfo->aucOwnMacAddr,pucEthDestAddr)) {
2678 prCurrSwRfb->eDst = RX_PKT_DESTINATION_FORWARD;
2679 /* TODO : need to check the dst mac is valid */
2680 /* If src mac is invalid, the packet will be freed in fw */
2682 } /* OP_MODE_ACCESS_POINT */
2685 DBGLOG(QM, TRACE, ("Mark NULL the Packet for inactive Bss %u\n",ucNetTypeIdx));
2686 prCurrSwRfb->eDst = RX_PKT_DESTINATION_NULL;
2687 QUEUE_INSERT_TAIL(&rReturnedQue, (P_QUE_ENTRY_T)prCurrSwRfb);
2693 /* Dont not occupy other SW RFB */
2694 DBGLOG(QM, TRACE, ("Mark NULL the Packet for less Free Sw Rfb\n"));
2695 prCurrSwRfb->eDst = RX_PKT_DESTINATION_NULL;
2696 QUEUE_INSERT_TAIL(&rReturnedQue, (P_QUE_ENTRY_T)prCurrSwRfb);
2703 if(HIF_RX_HDR_GET_BAR_FLAG(prHifRxHdr)){
2704 prCurrSwRfb->eDst = RX_PKT_DESTINATION_NULL;
2705 qmProcessBarFrame(prAdapter, prCurrSwRfb, &rReturnedQue);
2707 /* Reordering is not required for this packet, return it without buffering */
2708 else if(!HIF_RX_HDR_GET_REORDER_FLAG(prHifRxHdr) || fgIsBMC){
2710 if (!HIF_RX_HDR_GET_80211_FLAG(prHifRxHdr)){
2711 UINT_8 ucNetTypeIdx;
2712 P_BSS_INFO_T prBssInfo;
2714 pucEthDestAddr = prCurrSwRfb->pvHeader;
2715 ucNetTypeIdx = HIF_RX_HDR_GET_NETWORK_IDX(prHifRxHdr);
2717 prBssInfo = &(prAdapter->rWifiVar.arBssInfo[ucNetTypeIdx]);
2719 if (IS_BMCAST_MAC_ADDR(pucEthDestAddr) && (OP_MODE_ACCESS_POINT == prBssInfo->eCurrentOPMode)){
2720 prCurrSwRfb->eDst = RX_PKT_DESTINATION_HOST_WITH_FORWARD;
2724 QUEUE_INSERT_TAIL(&rReturnedQue, (P_QUE_ENTRY_T)prCurrSwRfb);
2726 /* Reordering is required for this packet */
2728 /* If this packet should dropped or indicated to the host immediately,
2729 * it should be enqueued into the rReturnedQue with specific flags. If
2730 * this packet should be buffered for reordering, it should be enqueued
2731 * into the reordering queue in the STA_REC rather than into the
2734 qmProcessPktWithReordering(prAdapter, prCurrSwRfb, &rReturnedQue);
2737 }while(prNextSwRfb);
2740 /* The returned list of SW_RFBs must end with a NULL pointer */
2741 if(QUEUE_IS_NOT_EMPTY(&rReturnedQue)){
2742 QM_TX_SET_NEXT_MSDU_INFO((P_SW_RFB_T)QUEUE_GET_TAIL(&rReturnedQue), NULL);
2745 return (P_SW_RFB_T)QUEUE_GET_HEAD(&rReturnedQue);
2749 //DbgPrint("QM: Enter qmHandleRxPackets()\n");
2750 return prSwRfbListHead;
2756 /*----------------------------------------------------------------------------*/
2758 * \brief Reorder the received packet
2760 * \param[in] prSwRfb The RX packet to process
2761 * \param[out] prReturnedQue The queue for indicating packets
2765 /*----------------------------------------------------------------------------*/
2767 qmProcessPktWithReordering(
2768 IN P_ADAPTER_T prAdapter,
2769 IN P_SW_RFB_T prSwRfb,
2770 OUT P_QUE_T prReturnedQue
2775 P_STA_RECORD_T prStaRec;
2776 P_HIF_RX_HEADER_T prHifRxHdr;
2777 P_RX_BA_ENTRY_T prReorderQueParm;
2782 P_QUE_T prReorderQue;
2783 //P_SW_RFB_T prReorderedSwRfb;
2785 DEBUGFUNC("qmProcessPktWithReordering");
2788 ASSERT(prReturnedQue);
2789 ASSERT(prSwRfb->prHifRxHdr);
2791 prHifRxHdr = prSwRfb->prHifRxHdr;
2792 prSwRfb->ucStaRecIdx = prHifRxHdr->ucStaRecIdx;
2793 prSwRfb->u2SSN = HIF_RX_HDR_GET_SN(prHifRxHdr); /* The new SN of the frame */
2794 prSwRfb->ucTid = (UINT_8)(HIF_RX_HDR_GET_TID(prHifRxHdr));
2795 //prSwRfb->eDst = RX_PKT_DESTINATION_HOST;
2797 /* Incorrect STA_REC index */
2798 if(prSwRfb->ucStaRecIdx >= CFG_NUM_OF_STA_RECORD){
2799 prSwRfb->eDst = RX_PKT_DESTINATION_NULL;
2800 QUEUE_INSERT_TAIL(prReturnedQue,(P_QUE_ENTRY_T)prSwRfb);
2801 DBGLOG(QM, WARN,("Reordering for a NULL STA_REC, ucStaRecIdx = %d\n",
2802 prSwRfb->ucStaRecIdx));
2807 /* Check whether the STA_REC is activated */
2808 prStaRec = &(prAdapter->arStaRec[prSwRfb->ucStaRecIdx]);
2812 if(!(prStaRec->fgIsValid)){
2813 /* TODO: (Tehuang) Handle the Host-FW sync issue. */
2814 prSwRfb->eDst = RX_PKT_DESTINATION_NULL;
2815 QUEUE_INSERT_TAIL(prReturnedQue,(P_QUE_ENTRY_T)prSwRfb);
2816 DBGLOG(QM, WARN, ("Reordering for an invalid STA_REC \n"));
2822 /* Check whether the BA agreement exists */
2823 prReorderQueParm = ((prStaRec->aprRxReorderParamRefTbl)[prSwRfb->ucTid]);
2824 if(!prReorderQueParm){
2825 /* TODO: (Tehuang) Handle the Host-FW sync issue.*/
2826 prSwRfb->eDst = RX_PKT_DESTINATION_NULL;
2827 QUEUE_INSERT_TAIL(prReturnedQue,(P_QUE_ENTRY_T)prSwRfb);
2828 DBGLOG(QM, WARN,("Reordering for a NULL ReorderQueParm \n"));
2835 /* Start to reorder packets */
2836 u4SeqNo = (UINT_32)(prSwRfb->u2SSN);
2837 prReorderQue = &(prReorderQueParm->rReOrderQue);
2838 u4WinStart = (UINT_32)(prReorderQueParm->u2WinStart);
2839 u4WinEnd = (UINT_32)(prReorderQueParm->u2WinEnd);
2842 //DbgPrint("QM:(R)[%d](%ld){%ld,%ld}\n", prSwRfb->ucTid, u4SeqNo, u4WinStart, u4WinEnd);
2844 /* Case 1: Fall within */
2845 if /* 0 - start - sn - end - 4095 */
2846 (((u4WinStart <= u4SeqNo) && (u4SeqNo <= u4WinEnd))
2847 /* 0 - end - start - sn - 4095 */
2848 || ((u4WinEnd < u4WinStart) && (u4WinStart <= u4SeqNo))
2849 /* 0 - sn - end - start - 4095 */
2850 || ((u4SeqNo <= u4WinEnd) && (u4WinEnd < u4WinStart))){
2852 qmInsertFallWithinReorderPkt(prSwRfb, prReorderQueParm, prReturnedQue);
2854 #if QM_RX_WIN_SSN_AUTO_ADVANCING
2855 if(prReorderQueParm->fgIsWaitingForPktWithSsn){
2856 /* Let the first received packet pass the reorder check */
2857 DBGLOG(QM, LOUD, ("QM:(A)[%d](%ld){%ld,%ld}\n", prSwRfb->ucTid, u4SeqNo, u4WinStart, u4WinEnd));
2859 prReorderQueParm->u2WinStart = (UINT_16)u4SeqNo;
2860 prReorderQueParm->u2WinEnd =
2861 ((prReorderQueParm->u2WinStart) + (prReorderQueParm->u2WinSize) - 1) % MAX_SEQ_NO_COUNT;
2862 prReorderQueParm->fgIsWaitingForPktWithSsn = FALSE;
2867 qmPopOutDueToFallWithin(prReorderQueParm, prReturnedQue);
2869 /* Case 2: Fall ahead */
2871 /* 0 - start - end - sn - (start+2048) - 4095 */
2872 (((u4WinStart < u4WinEnd)
2873 && (u4WinEnd < u4SeqNo)
2874 && (u4SeqNo < (u4WinStart + HALF_SEQ_NO_COUNT)))
2875 /* 0 - sn - (start+2048) - start - end - 4095 */
2876 || ((u4SeqNo < u4WinStart)
2877 && (u4WinStart < u4WinEnd)
2878 && ((u4SeqNo + MAX_SEQ_NO_COUNT) < (u4WinStart + HALF_SEQ_NO_COUNT)))
2879 /* 0 - end - sn - (start+2048) - start - 4095 */
2880 || ((u4WinEnd < u4SeqNo)
2881 && (u4SeqNo < u4WinStart)
2882 && ((u4SeqNo + MAX_SEQ_NO_COUNT) < (u4WinStart + HALF_SEQ_NO_COUNT)))){
2885 #if QM_RX_WIN_SSN_AUTO_ADVANCING
2886 if(prReorderQueParm->fgIsWaitingForPktWithSsn){
2887 prReorderQueParm->fgIsWaitingForPktWithSsn = FALSE;
2891 qmInsertFallAheadReorderPkt(prSwRfb, prReorderQueParm, prReturnedQue);
2893 /* Advance the window after inserting a new tail */
2894 prReorderQueParm->u2WinEnd = (UINT_16)u4SeqNo;
2895 prReorderQueParm->u2WinStart =
2896 (((prReorderQueParm->u2WinEnd) - (prReorderQueParm->u2WinSize) + MAX_SEQ_NO_COUNT + 1)
2897 % MAX_SEQ_NO_COUNT);
2899 qmPopOutDueToFallAhead(prReorderQueParm, prReturnedQue);
2902 /* Case 3: Fall behind */
2905 #if QM_RX_WIN_SSN_AUTO_ADVANCING
2906 #if QM_RX_INIT_FALL_BEHIND_PASS
2907 if(prReorderQueParm->fgIsWaitingForPktWithSsn){
2908 //?? prSwRfb->eDst = RX_PKT_DESTINATION_HOST;
2909 QUEUE_INSERT_TAIL(prReturnedQue,(P_QUE_ENTRY_T)prSwRfb);
2910 //DbgPrint("QM:(P)[%d](%ld){%ld,%ld}\n", prSwRfb->ucTid, u4SeqNo, u4WinStart, u4WinEnd);
2916 /* An erroneous packet */
2917 prSwRfb->eDst = RX_PKT_DESTINATION_NULL;
2918 QUEUE_INSERT_TAIL(prReturnedQue,(P_QUE_ENTRY_T)prSwRfb);
2919 //DbgPrint("QM:(D)[%d](%ld){%ld,%ld}\n", prSwRfb->ucTid, u4SeqNo, u4WinStart, u4WinEnd);
2930 IN P_ADAPTER_T prAdapter,
2931 IN P_SW_RFB_T prSwRfb,
2932 OUT P_QUE_T prReturnedQue
2936 P_STA_RECORD_T prStaRec;
2937 P_HIF_RX_HEADER_T prHifRxHdr;
2938 P_RX_BA_ENTRY_T prReorderQueParm;
2943 P_QUE_T prReorderQue;
2944 //P_SW_RFB_T prReorderedSwRfb;
2947 ASSERT(prReturnedQue);
2948 ASSERT(prSwRfb->prHifRxHdr);
2950 prHifRxHdr = prSwRfb->prHifRxHdr;
2951 prSwRfb->ucStaRecIdx = prHifRxHdr->ucStaRecIdx;
2952 prSwRfb->u2SSN = HIF_RX_HDR_GET_SN(prHifRxHdr); /* The new SSN */
2953 prSwRfb->ucTid = (UINT_8)(HIF_RX_HDR_GET_TID(prHifRxHdr));
2955 prSwRfb->eDst = RX_PKT_DESTINATION_NULL;
2956 QUEUE_INSERT_TAIL(prReturnedQue,(P_QUE_ENTRY_T)prSwRfb);
2958 /* Incorrect STA_REC index */
2959 if(prSwRfb->ucStaRecIdx >= CFG_NUM_OF_STA_RECORD){
2960 DBGLOG(QM, WARN, ("QM: (Warning) BAR for a NULL STA_REC, ucStaRecIdx = %d\n",
2961 prSwRfb->ucStaRecIdx));
2966 /* Check whether the STA_REC is activated */
2967 prStaRec = &(prAdapter->arStaRec[prSwRfb->ucStaRecIdx]);
2971 if(!(prStaRec->fgIsValid)){
2972 /* TODO: (Tehuang) Handle the Host-FW sync issue. */
2973 DbgPrint("QM: (Warning) BAR for an invalid STA_REC \n");
2979 /* Check whether the BA agreement exists */
2980 prReorderQueParm = ((prStaRec->aprRxReorderParamRefTbl)[prSwRfb->ucTid]);
2981 if(!prReorderQueParm){
2982 /* TODO: (Tehuang) Handle the Host-FW sync issue.*/
2983 DBGLOG(QM, WARN, ("QM: (Warning) BAR for a NULL ReorderQueParm \n"));
2989 u4SSN = (UINT_32)(prSwRfb->u2SSN);
2990 prReorderQue = &(prReorderQueParm->rReOrderQue);
2991 u4WinStart = (UINT_32)(prReorderQueParm->u2WinStart);
2992 u4WinEnd = (UINT_32)(prReorderQueParm->u2WinEnd);
2994 if(qmCompareSnIsLessThan(u4WinStart,u4SSN)){
2995 prReorderQueParm->u2WinStart = (UINT_16)u4SSN;
2996 prReorderQueParm->u2WinEnd =
2997 ((prReorderQueParm->u2WinStart) + (prReorderQueParm->u2WinSize) - 1) % MAX_SEQ_NO_COUNT;
2998 DBGLOG(QM, TRACE, ("QM:(BAR)[%d](%ld){%d,%d}\n", prSwRfb->ucTid, u4SSN, prReorderQueParm->u2WinStart, prReorderQueParm->u2WinEnd));
2999 qmPopOutDueToFallAhead(prReorderQueParm, prReturnedQue);
3002 DBGLOG(QM, TRACE, ("QM:(BAR)(%d)(%ld){%ld,%ld}\n", prSwRfb->ucTid, u4SSN, u4WinStart, u4WinEnd));
3009 qmInsertFallWithinReorderPkt(
3010 IN P_SW_RFB_T prSwRfb,
3011 IN P_RX_BA_ENTRY_T prReorderQueParm,
3012 OUT P_QUE_T prReturnedQue
3015 P_SW_RFB_T prExaminedQueuedSwRfb;
3016 P_QUE_T prReorderQue;
3018 ASSERT(prReorderQueParm);
3019 ASSERT(prReturnedQue);
3021 prReorderQue = &(prReorderQueParm->rReOrderQue);
3022 prExaminedQueuedSwRfb = (P_SW_RFB_T)QUEUE_GET_HEAD(prReorderQue);
3024 /* There are no packets queued in the Reorder Queue */
3025 if(prExaminedQueuedSwRfb == NULL){
3026 ((P_QUE_ENTRY_T)prSwRfb)->prPrev = NULL;
3027 ((P_QUE_ENTRY_T)prSwRfb)->prNext = NULL;
3028 prReorderQue->prHead = (P_QUE_ENTRY_T)prSwRfb;
3029 prReorderQue->prTail = (P_QUE_ENTRY_T)prSwRfb;
3030 prReorderQue->u4NumElem ++;
3033 /* Determine the insert position */
3036 /* Case 1: Terminate. A duplicate packet */
3037 if(((prExaminedQueuedSwRfb->u2SSN) == (prSwRfb->u2SSN))){
3038 prSwRfb->eDst = RX_PKT_DESTINATION_NULL;
3039 QUEUE_INSERT_TAIL(prReturnedQue,(P_QUE_ENTRY_T)prSwRfb);
3043 /* Case 2: Terminate. The insert point is found */
3044 else if(qmCompareSnIsLessThan(
3045 (prSwRfb->u2SSN),(prExaminedQueuedSwRfb->u2SSN))){
3049 /* Case 3: Insert point not found. Check the next SW_RFB in the Reorder Queue */
3051 prExaminedQueuedSwRfb =
3052 (P_SW_RFB_T)(((P_QUE_ENTRY_T)prExaminedQueuedSwRfb)->prNext);
3054 }while(prExaminedQueuedSwRfb);
3056 /* Update the Reorder Queue Parameters according to the found insert position */
3057 if(prExaminedQueuedSwRfb == NULL){
3058 /* The received packet shall be placed at the tail */
3059 ((P_QUE_ENTRY_T)prSwRfb)->prPrev = prReorderQue->prTail;
3060 ((P_QUE_ENTRY_T)prSwRfb)->prNext = NULL;
3061 (prReorderQue->prTail)->prNext = (P_QUE_ENTRY_T)(prSwRfb);
3062 prReorderQue->prTail = (P_QUE_ENTRY_T)(prSwRfb);
3065 ((P_QUE_ENTRY_T)prSwRfb)->prPrev = ((P_QUE_ENTRY_T)prExaminedQueuedSwRfb)->prPrev;
3066 ((P_QUE_ENTRY_T)prSwRfb)->prNext = (P_QUE_ENTRY_T)prExaminedQueuedSwRfb;
3067 if(((P_QUE_ENTRY_T)prExaminedQueuedSwRfb) == (prReorderQue->prHead)){
3068 /* The received packet will become the head */
3069 prReorderQue->prHead = (P_QUE_ENTRY_T)prSwRfb;
3072 (((P_QUE_ENTRY_T)prExaminedQueuedSwRfb)->prPrev)->prNext = (P_QUE_ENTRY_T)prSwRfb;
3074 ((P_QUE_ENTRY_T)prExaminedQueuedSwRfb)->prPrev = (P_QUE_ENTRY_T)prSwRfb;
3077 prReorderQue->u4NumElem ++;
3085 qmInsertFallAheadReorderPkt(
3086 IN P_SW_RFB_T prSwRfb,
3087 IN P_RX_BA_ENTRY_T prReorderQueParm,
3088 OUT P_QUE_T prReturnedQue
3091 P_QUE_T prReorderQue;
3093 ASSERT(prReorderQueParm);
3094 ASSERT(prReturnedQue);
3096 prReorderQue = &(prReorderQueParm->rReOrderQue);
3098 /* There are no packets queued in the Reorder Queue */
3099 if(QUEUE_IS_EMPTY(prReorderQue)){
3100 ((P_QUE_ENTRY_T)prSwRfb)->prPrev = NULL;
3101 ((P_QUE_ENTRY_T)prSwRfb)->prNext = NULL;
3102 prReorderQue->prHead = (P_QUE_ENTRY_T)prSwRfb;
3105 ((P_QUE_ENTRY_T)prSwRfb)->prPrev = prReorderQue->prTail;
3106 ((P_QUE_ENTRY_T)prSwRfb)->prNext = NULL;
3107 (prReorderQue->prTail)->prNext = (P_QUE_ENTRY_T)(prSwRfb);
3109 prReorderQue->prTail = (P_QUE_ENTRY_T)prSwRfb;
3110 prReorderQue->u4NumElem ++;
3116 qmPopOutDueToFallWithin(
3117 IN P_RX_BA_ENTRY_T prReorderQueParm,
3118 OUT P_QUE_T prReturnedQue
3121 P_SW_RFB_T prReorderedSwRfb;
3122 P_QUE_T prReorderQue;
3123 BOOLEAN fgDequeuHead, fgMissing;
3124 OS_SYSTIME rCurrentTime, *prMissTimeout;
3126 prReorderQue = &(prReorderQueParm->rReOrderQue);
3130 prMissTimeout = &(g_arMissTimeout[prReorderQueParm->ucStaRecIdx][prReorderQueParm->ucTid]);
3131 if ((*prMissTimeout)){
3133 GET_CURRENT_SYSTIME(&rCurrentTime);
3136 /* Check whether any packet can be indicated to the higher layer */
3138 if(QUEUE_IS_EMPTY(prReorderQue)){
3142 /* Always examine the head packet */
3143 prReorderedSwRfb = (P_SW_RFB_T)QUEUE_GET_HEAD(prReorderQue);
3144 fgDequeuHead = FALSE;
3146 /* SN == WinStart, so the head packet shall be indicated (advance the window) */
3147 if((prReorderedSwRfb->u2SSN) == (prReorderQueParm->u2WinStart)){
3149 fgDequeuHead = TRUE;
3150 prReorderQueParm->u2WinStart =
3151 (((prReorderedSwRfb->u2SSN) + 1)% MAX_SEQ_NO_COUNT);
3153 /* SN > WinStart, break to update WinEnd */
3155 if ((fgMissing == TRUE) &&
3156 CHECK_FOR_TIMEOUT(rCurrentTime, (*prMissTimeout),
3157 MSEC_TO_SYSTIME(QM_RX_BA_ENTRY_MISS_TIMEOUT_MS))) {
3158 DBGLOG(QM, TRACE, ("QM:RX BA Timout Next Tid %d SSN %d\n", prReorderQueParm->ucTid, prReorderedSwRfb->u2SSN));
3159 fgDequeuHead = TRUE;
3160 prReorderQueParm->u2WinStart =
3161 (((prReorderedSwRfb->u2SSN) + 1)% MAX_SEQ_NO_COUNT);
3169 /* Dequeue the head packet */
3172 if(((P_QUE_ENTRY_T)prReorderedSwRfb)->prNext == NULL){
3173 prReorderQue->prHead = NULL;
3174 prReorderQue->prTail = NULL;
3177 prReorderQue->prHead = ((P_QUE_ENTRY_T)prReorderedSwRfb)->prNext;
3178 (((P_QUE_ENTRY_T)prReorderedSwRfb)->prNext)->prPrev = NULL;
3180 prReorderQue->u4NumElem --;
3181 //DbgPrint("QM: [%d] %d (%d)\n", prReorderQueParm->ucTid, prReorderedSwRfb->u2PacketLen, prReorderedSwRfb->u2SSN);
3182 QUEUE_INSERT_TAIL(prReturnedQue,(P_QUE_ENTRY_T)prReorderedSwRfb);
3186 if (QUEUE_IS_EMPTY(prReorderQue)){
3190 if (fgMissing == FALSE) {
3191 GET_CURRENT_SYSTIME(prMissTimeout);
3195 /* After WinStart has been determined, update the WinEnd */
3196 prReorderQueParm->u2WinEnd =
3197 (((prReorderQueParm->u2WinStart) + (prReorderQueParm->u2WinSize) -1 )% MAX_SEQ_NO_COUNT);
3202 qmPopOutDueToFallAhead(
3203 IN P_RX_BA_ENTRY_T prReorderQueParm,
3204 OUT P_QUE_T prReturnedQue
3207 P_SW_RFB_T prReorderedSwRfb;
3208 P_QUE_T prReorderQue;
3209 BOOLEAN fgDequeuHead;
3211 prReorderQue = &(prReorderQueParm->rReOrderQue);
3213 /* Check whether any packet can be indicated to the higher layer */
3215 if(QUEUE_IS_EMPTY(prReorderQue)){
3219 /* Always examine the head packet */
3220 prReorderedSwRfb = (P_SW_RFB_T)QUEUE_GET_HEAD(prReorderQue);
3221 fgDequeuHead = FALSE;
3223 /* SN == WinStart, so the head packet shall be indicated (advance the window) */
3224 if((prReorderedSwRfb->u2SSN) == (prReorderQueParm->u2WinStart)){
3226 fgDequeuHead = TRUE;
3227 prReorderQueParm->u2WinStart =
3228 (((prReorderedSwRfb->u2SSN) + 1)% MAX_SEQ_NO_COUNT);
3231 /* SN < WinStart, so the head packet shall be indicated (do not advance the window) */
3232 else if(qmCompareSnIsLessThan(
3233 (UINT_32)(prReorderedSwRfb->u2SSN),
3234 (UINT_32)(prReorderQueParm->u2WinStart))){
3236 fgDequeuHead = TRUE;
3240 /* SN > WinStart, break to update WinEnd */
3246 /* Dequeue the head packet */
3249 if(((P_QUE_ENTRY_T)prReorderedSwRfb)->prNext == NULL){
3250 prReorderQue->prHead = NULL;
3251 prReorderQue->prTail = NULL;
3254 prReorderQue->prHead = ((P_QUE_ENTRY_T)prReorderedSwRfb)->prNext;
3255 (((P_QUE_ENTRY_T)prReorderedSwRfb)->prNext)->prPrev = NULL;
3257 prReorderQue->u4NumElem --;
3258 //DbgPrint("QM: [%d] %d (%d)\n", prReorderQueParm->ucTid, prReorderedSwRfb->u2PacketLen, prReorderedSwRfb->u2SSN);
3259 QUEUE_INSERT_TAIL(prReturnedQue,(P_QUE_ENTRY_T)prReorderedSwRfb);
3263 /* After WinStart has been determined, update the WinEnd */
3264 prReorderQueParm->u2WinEnd =
3265 (((prReorderQueParm->u2WinStart) + (prReorderQueParm->u2WinSize) -1)% MAX_SEQ_NO_COUNT);
3270 qmCompareSnIsLessThan(
3271 IN UINT_32 u4SnLess,
3272 IN UINT_32 u4SnGreater
3275 /* 0 <---> SnLess <--(gap>2048)--> SnGreater : SnLess > SnGreater */
3276 if((u4SnLess + HALF_SEQ_NO_COUNT) <= u4SnGreater){ /* Shall be <= */
3280 /* 0 <---> SnGreater <--(gap>2048)--> SnLess : SnLess < SnGreater */
3281 else if((u4SnGreater + HALF_SEQ_NO_COUNT) < u4SnLess){
3285 /* 0 <---> SnGreater <--(gap<2048)--> SnLess : SnLess > SnGreater */
3286 /* 0 <---> SnLess <--(gap<2048)--> SnGreater : SnLess < SnGreater */
3288 return (u4SnLess < u4SnGreater);
3293 /*----------------------------------------------------------------------------*/
3295 * \brief Handle Mailbox RX messages
3297 * \param[in] prMailboxRxMsg The received Mailbox message from the FW
3301 /*----------------------------------------------------------------------------*/
3303 qmHandleMailboxRxMessage(
3304 IN MAILBOX_MSG_T prMailboxRxMsg
3307 //DbgPrint("QM: Enter qmHandleMailboxRxMessage()\n");
3312 /*----------------------------------------------------------------------------*/
3314 * \brief Handle ADD RX BA Event from the FW
3316 * \param[in] prAdapter Adapter pointer
3317 * \param[in] prEvent The event packet from the FW
3321 /*----------------------------------------------------------------------------*/
3323 qmHandleEventRxAddBa(
3324 IN P_ADAPTER_T prAdapter,
3325 IN P_WIFI_EVENT_T prEvent
3328 P_EVENT_RX_ADDBA_T prEventRxAddBa;
3329 P_STA_RECORD_T prStaRec;
3333 DBGLOG(QM, INFO, ("QM:Event +RxBa\n"));
3335 prEventRxAddBa = (P_EVENT_RX_ADDBA_T)prEvent;
3336 prStaRec = QM_GET_STA_REC_PTR_FROM_INDEX(prAdapter, prEventRxAddBa->ucStaRecIdx);
3339 /* Invalid STA_REC index, discard the event packet */
3341 DBGLOG(QM, INFO, ("QM: (Warning) RX ADDBA Event for a NULL STA_REC\n"));
3346 if(!(prStaRec->fgIsValid)){
3347 /* TODO: (Tehuang) Handle the Host-FW synchronization issue */
3348 DBGLOG(QM, WARN, ("QM: (Warning) RX ADDBA Event for an invalid STA_REC\n"));
3354 u4Tid = (((prEventRxAddBa->u2BAParameterSet)& BA_PARAM_SET_TID_MASK)
3355 >> BA_PARAM_SET_TID_MASK_OFFSET);
3357 u4WinSize = (((prEventRxAddBa->u2BAParameterSet)& BA_PARAM_SET_BUFFER_SIZE_MASK)
3358 >> BA_PARAM_SET_BUFFER_SIZE_MASK_OFFSET);
3364 (prEventRxAddBa->u2BAStartSeqCtrl >> OFFSET_BAR_SSC_SN),
3365 (UINT_16)u4WinSize)){
3367 /* FW shall ensure the availabiilty of the free-to-use BA entry */
3368 DBGLOG(QM, ERROR, ("QM: (Error) qmAddRxBaEntry() failure\n"));
3374 /*----------------------------------------------------------------------------*/
3376 * \brief Handle DEL RX BA Event from the FW
3378 * \param[in] prAdapter Adapter pointer
3379 * \param[in] prEvent The event packet from the FW
3383 /*----------------------------------------------------------------------------*/
3385 qmHandleEventRxDelBa(
3386 IN P_ADAPTER_T prAdapter,
3387 IN P_WIFI_EVENT_T prEvent
3390 P_EVENT_RX_DELBA_T prEventRxDelBa;
3391 P_STA_RECORD_T prStaRec;
3393 //DbgPrint("QM:Event -RxBa\n");
3395 prEventRxDelBa = (P_EVENT_RX_DELBA_T)prEvent;
3396 prStaRec = QM_GET_STA_REC_PTR_FROM_INDEX(prAdapter, prEventRxDelBa->ucStaRecIdx);
3399 /* Invalid STA_REC index, discard the event packet */
3405 if(!(prStaRec->fgIsValid)){
3406 /* TODO: (Tehuang) Handle the Host-FW synchronization issue */
3412 qmDelRxBaEntry(prAdapter, prStaRec->ucIndex, prEventRxDelBa->ucTid, TRUE);
3418 IN P_ADAPTER_T prAdapter,
3424 P_QUE_MGT_T prQM = &prAdapter->rQM;
3426 //DbgPrint("QM: Enter qmLookupRxBaEntry()\n");
3428 for(i=0; i<CFG_NUM_OF_RX_BA_AGREEMENTS; i++){
3429 if(prQM->arRxBaTable[i].fgIsValid){
3430 if((prQM->arRxBaTable[i].ucStaRecIdx == ucStaRecIdx) &&
3431 (prQM->arRxBaTable[i].ucTid == ucTid)){
3432 return &prQM->arRxBaTable[i];
3441 IN P_ADAPTER_T prAdapter,
3442 IN UINT_8 ucStaRecIdx,
3444 IN UINT_16 u2WinStart,
3445 IN UINT_16 u2WinSize
3449 P_RX_BA_ENTRY_T prRxBaEntry = NULL;
3450 P_STA_RECORD_T prStaRec;
3451 P_QUE_MGT_T prQM = &prAdapter->rQM;
3453 ASSERT(ucStaRecIdx < CFG_NUM_OF_STA_RECORD);
3455 if(ucStaRecIdx >= CFG_NUM_OF_STA_RECORD){
3456 /* Invalid STA_REC index, discard the event packet */
3457 DBGLOG(QM, WARN, ("QM: (WARNING) RX ADDBA Event for a invalid ucStaRecIdx = %d\n", ucStaRecIdx));
3461 prStaRec = &prAdapter->arStaRec[ucStaRecIdx];
3464 //if(!(prStaRec->fgIsValid)){
3465 // DbgPrint("QM: (WARNING) Invalid STA when adding an RX BA \n");
3469 //4 <1> Delete before adding
3470 /* Remove the BA entry for the same (STA, TID) tuple if it exists */
3471 if(qmLookupRxBaEntry(prAdapter, ucStaRecIdx,ucTid)){
3472 qmDelRxBaEntry(prAdapter, ucStaRecIdx, ucTid, TRUE); /* prQM->ucRxBaCount-- */
3475 //4 <2> Add a new BA entry
3476 /* No available entry to store the BA agreement info. Retrun FALSE. */
3477 if(prQM->ucRxBaCount >= CFG_NUM_OF_RX_BA_AGREEMENTS){
3478 DBGLOG(QM, ERROR, ("QM: **failure** (limited resource, ucRxBaCount=%d)\n", prQM->ucRxBaCount));
3482 /* Find the free-to-use BA entry */
3483 for(i=0; i<CFG_NUM_OF_RX_BA_AGREEMENTS; i++){
3484 if(!prQM->arRxBaTable[i].fgIsValid){
3485 prRxBaEntry = &(prQM->arRxBaTable[i]);
3486 prQM->ucRxBaCount++;
3487 DBGLOG(QM, LOUD, ("QM: ucRxBaCount=%d\n", prQM->ucRxBaCount));
3492 /* If a free-to-use entry is found, configure it and associate it with the STA_REC */
3493 u2WinSize += CFG_RX_BA_INC_SIZE;
3495 prRxBaEntry->ucStaRecIdx = ucStaRecIdx;
3496 prRxBaEntry->ucTid = ucTid;
3497 prRxBaEntry->u2WinStart = u2WinStart;
3498 prRxBaEntry->u2WinSize= u2WinSize;
3499 prRxBaEntry->u2WinEnd = ((u2WinStart + u2WinSize - 1) % MAX_SEQ_NO_COUNT);
3500 prRxBaEntry->fgIsValid = TRUE;
3501 prRxBaEntry->fgIsWaitingForPktWithSsn = TRUE;
3503 g_arMissTimeout[ucStaRecIdx][ucTid] = 0;
3505 DBGLOG(QM, INFO, ("QM: +RxBA(STA=%d TID=%d WinStart=%d WinEnd=%d WinSize=%d)\n",
3507 prRxBaEntry->u2WinStart, prRxBaEntry->u2WinEnd, prRxBaEntry->u2WinSize));
3509 /* Update the BA entry reference table for per-packet lookup */
3510 prStaRec->aprRxReorderParamRefTbl[ucTid] = prRxBaEntry;
3513 /* This shall not happen because FW should keep track of the usage of RX BA entries */
3514 DBGLOG(QM, ERROR, ("QM: **AddBA Error** (ucRxBaCount=%d)\n", prQM->ucRxBaCount));
3523 IN P_ADAPTER_T prAdapter,
3524 IN UINT_8 ucStaRecIdx,
3526 IN BOOLEAN fgFlushToHost
3529 P_RX_BA_ENTRY_T prRxBaEntry;
3530 P_STA_RECORD_T prStaRec;
3531 P_SW_RFB_T prFlushedPacketList = NULL;
3532 P_QUE_MGT_T prQM = &prAdapter->rQM;
3534 ASSERT(ucStaRecIdx < CFG_NUM_OF_STA_RECORD);
3536 prStaRec = &prAdapter->arStaRec[ucStaRecIdx];
3540 if(!(prStaRec->fgIsValid)){
3541 DbgPrint("QM: (WARNING) Invalid STA when deleting an RX BA \n");
3546 /* Remove the BA entry for the same (STA, TID) tuple if it exists */
3547 prRxBaEntry = prStaRec->aprRxReorderParamRefTbl[ucTid];
3551 prFlushedPacketList = qmFlushStaRxQueue(prAdapter, ucStaRecIdx, ucTid);
3553 if(prFlushedPacketList){
3556 wlanProcessQueuedSwRfb(prAdapter, prFlushedPacketList);
3561 P_SW_RFB_T prNextSwRfb;
3562 prSwRfb = prFlushedPacketList;
3565 prNextSwRfb = (P_SW_RFB_T)QUEUE_GET_NEXT_ENTRY((P_QUE_ENTRY_T)prSwRfb);
3566 nicRxReturnRFB(prAdapter, prSwRfb);
3567 prSwRfb = prNextSwRfb;
3574 #if ((QM_TEST_MODE == 0) && (QM_TEST_STA_REC_DEACTIVATION == 0))
3575 /* Update RX BA entry state. Note that RX queue flush is not done here */
3576 prRxBaEntry->fgIsValid = FALSE;
3577 prQM->ucRxBaCount--;
3581 DbgPrint("QM: ucRxBaCount=%d\n", prQM->ucRxBaCount);
3584 /* Update STA RX BA table */
3585 prStaRec->aprRxReorderParamRefTbl[ucTid] = NULL;
3588 DBGLOG(QM, INFO, ("QM: -RxBA(STA=%d,TID=%d)\n", ucStaRecIdx, ucTid));
3594 #if CFG_HIF_RX_STARVATION_WARNING
3596 P_RX_CTRL_T prRxCtrl;
3597 prRxCtrl = &prAdapter->rRxCtrl;
3598 DBGLOG(QM, TRACE, ("QM: (RX DEBUG) Enqueued: %d / Dequeued: %d\n", prRxCtrl->u4QueuedCnt, prRxCtrl->u4DequeuedCnt));
3604 /*----------------------------------------------------------------------------*/
3606 * \brief To process WMM related IEs in ASSOC_RSP
3608 * \param[in] prAdapter Adapter pointer
3609 * \param[in] prSwRfb The received frame
3610 * \param[in] pucIE The pointer to the first IE in the frame
3611 * \param[in] u2IELength The total length of IEs in the frame
3615 /*----------------------------------------------------------------------------*/
3617 mqmProcessAssocReq (
3618 IN P_ADAPTER_T prAdapter,
3619 IN P_SW_RFB_T prSwRfb,
3621 IN UINT_16 u2IELength
3624 P_STA_RECORD_T prStaRec;
3627 UINT_8 aucWfaOui[] = VENDOR_OUI_WFA;
3628 P_IE_WMM_INFO_T prIeWmmInfo;
3630 DEBUGFUNC("mqmProcessAssocReq");
3635 prStaRec = cnmGetStaRecByIndex(prAdapter, prSwRfb->ucStaRecIdx);
3638 if(prStaRec == NULL) {
3642 prStaRec->fgIsQoS = FALSE;
3643 prStaRec->fgIsWmmSupported = prStaRec->fgIsUapsdSupported = FALSE;
3647 /* If the device does not support QoS or if WMM is not supported by the peer, exit.*/
3648 if (!prAdapter->rWifiVar.fgSupportQoS) {
3653 /* Determine whether QoS is enabled with the association */
3655 IE_FOR_EACH(pucIE, u2IELength, u2Offset) {
3656 switch (IE_ID(pucIE)) {
3659 if((WMM_IE_OUI_TYPE(pucIE) == VENDOR_OUI_TYPE_WMM) &&
3660 (!kalMemCmp(WMM_IE_OUI(pucIE),aucWfaOui,3))){
3662 switch(WMM_IE_OUI_SUBTYPE(pucIE)){
3663 case VENDOR_OUI_SUBTYPE_WMM_INFO:
3669 if(IE_LEN(pucIE) != 7){
3670 break; /* WMM Info IE with a wrong length */
3672 prStaRec->fgIsQoS = TRUE;
3673 prStaRec->fgIsWmmSupported = TRUE;
3675 prIeWmmInfo = (P_IE_WMM_INFO_T)pucIE;
3676 ucQosInfo = prIeWmmInfo->ucQosInfo;
3677 ucQosInfoAC = ucQosInfo & BITS(0, 3);
3679 prStaRec->fgIsUapsdSupported = ((ucQosInfoAC)? TRUE: FALSE) &
3680 prAdapter->rWifiVar.fgSupportUAPSD;
3684 if( ucQosInfoAC & WMM_QOS_INFO_VO_UAPSD) {
3685 ucBmpAC |= BIT(ACI_VO);
3687 if( ucQosInfoAC & WMM_QOS_INFO_VI_UAPSD) {
3688 ucBmpAC |= BIT(ACI_VI);
3690 if( ucQosInfoAC & WMM_QOS_INFO_BE_UAPSD) {
3691 ucBmpAC |= BIT(ACI_BE);
3693 if( ucQosInfoAC & WMM_QOS_INFO_BK_UAPSD) {
3694 ucBmpAC |= BIT(ACI_BK);
3697 prStaRec->ucBmpTriggerAC = prStaRec->ucBmpDeliveryAC = ucBmpAC;
3699 prStaRec->ucUapsdSp = (ucQosInfo & WMM_QOS_INFO_MAX_SP_LEN_MASK) >> 5;
3705 /* Other WMM QoS IEs. Ignore any */
3709 /* else: VENDOR_OUI_TYPE_WPA, VENDOR_OUI_TYPE_WPS */
3713 case ELEM_ID_HT_CAP:
3714 /* Some client won't put the WMM IE if client is 802.11n */
3715 if (IE_LEN(pucIE) == (sizeof(IE_HT_CAP_T) - 2)) {
3716 prStaRec->fgIsQoS = TRUE;
3724 DBGLOG(QM, TRACE, ("MQM: Assoc_Req Parsing (QoS Enabled=%d)\n", prStaRec->fgIsQoS));
3730 /*----------------------------------------------------------------------------*/
3732 * \brief To process WMM related IEs in ASSOC_RSP
3734 * \param[in] prAdapter Adapter pointer
3735 * \param[in] prSwRfb The received frame
3736 * \param[in] pucIE The pointer to the first IE in the frame
3737 * \param[in] u2IELength The total length of IEs in the frame
3741 /*----------------------------------------------------------------------------*/
3743 mqmProcessAssocRsp (
3744 IN P_ADAPTER_T prAdapter,
3745 IN P_SW_RFB_T prSwRfb,
3747 IN UINT_16 u2IELength
3750 P_STA_RECORD_T prStaRec;
3753 UINT_8 aucWfaOui[] = VENDOR_OUI_WFA;
3755 DEBUGFUNC("mqmProcessAssocRsp");
3760 prStaRec = cnmGetStaRecByIndex(prAdapter, prSwRfb->ucStaRecIdx);
3763 if(prStaRec == NULL) {
3767 prStaRec->fgIsQoS = FALSE;
3771 DBGLOG(QM, TRACE, ("QM: (fgIsWmmSupported=%d, fgSupportQoS=%d)\n",
3772 prStaRec->fgIsWmmSupported, prAdapter->rWifiVar.fgSupportQoS));
3774 /* If the device does not support QoS or if WMM is not supported by the peer, exit.*/
3775 //if((!prAdapter->rWifiVar.fgSupportQoS) || (!prStaRec->fgIsWmmSupported))
3776 if((!prAdapter->rWifiVar.fgSupportQoS))
3781 /* Determine whether QoS is enabled with the association */
3783 IE_FOR_EACH(pucIE, u2IELength, u2Offset) {
3784 switch (IE_ID(pucIE)) {
3786 if((WMM_IE_OUI_TYPE(pucIE) == VENDOR_OUI_TYPE_WMM) &&
3787 (!kalMemCmp(WMM_IE_OUI(pucIE),aucWfaOui,3))){
3789 switch(WMM_IE_OUI_SUBTYPE(pucIE)){
3790 case VENDOR_OUI_SUBTYPE_WMM_PARAM:
3791 if(IE_LEN(pucIE) != 24){
3792 break; /* WMM Info IE with a wrong length */
3794 prStaRec->fgIsQoS = TRUE;
3797 case VENDOR_OUI_SUBTYPE_WMM_INFO:
3798 if(IE_LEN(pucIE) != 7){
3799 break; /* WMM Info IE with a wrong length */
3801 prStaRec->fgIsQoS = TRUE;
3805 /* Other WMM QoS IEs. Ignore any */
3809 /* else: VENDOR_OUI_TYPE_WPA, VENDOR_OUI_TYPE_WPS */
3812 case ELEM_ID_HT_CAP:
3813 /* Some AP won't put the WMM IE if client is 802.11n */
3814 if ( IE_LEN(pucIE) == (sizeof(IE_HT_CAP_T) - 2)) {
3815 prStaRec->fgIsQoS = TRUE;
3823 /* Parse AC parameters and write to HW CRs */
3824 if((prStaRec->fgIsQoS) && (prStaRec->eStaType == STA_TYPE_LEGACY_AP)){
3825 mqmParseEdcaParameters(prAdapter, prSwRfb, pucIEStart, u2IELength, TRUE);
3828 DBGLOG(QM, TRACE, ("MQM: Assoc_Rsp Parsing (QoS Enabled=%d)\n", prStaRec->fgIsQoS));
3829 if(prStaRec->fgIsWmmSupported) {
3830 nicQmUpdateWmmParms(prAdapter, prStaRec->ucNetTypeIndex);
3836 /*----------------------------------------------------------------------------*/
3838 * \brief To parse WMM Parameter IE (in BCN or Assoc_Rsp)
3840 * \param[in] prAdapter Adapter pointer
3841 * \param[in] prSwRfb The received frame
3842 * \param[in] pucIE The pointer to the first IE in the frame
3843 * \param[in] u2IELength The total length of IEs in the frame
3844 * \param[in] fgForceOverride TRUE: If EDCA parameters are found, always set to HW CRs.
3848 /*----------------------------------------------------------------------------*/
3850 mqmParseEdcaParameters (
3851 IN P_ADAPTER_T prAdapter,
3852 IN P_SW_RFB_T prSwRfb,
3854 IN UINT_16 u2IELength,
3855 IN BOOLEAN fgForceOverride
3858 P_STA_RECORD_T prStaRec;
3860 UINT_8 aucWfaOui[] = VENDOR_OUI_WFA;
3861 P_BSS_INFO_T prBssInfo;
3863 DEBUGFUNC("mqmParseEdcaParameters");
3868 prStaRec = cnmGetStaRecByIndex(prAdapter, prSwRfb->ucStaRecIdx);
3871 if(prStaRec == NULL) {
3875 DBGLOG(QM, TRACE, ("QM: (fgIsWmmSupported=%d, fgIsQoS=%d)\n",
3876 prStaRec->fgIsWmmSupported, prStaRec->fgIsQoS));
3878 if((!prAdapter->rWifiVar.fgSupportQoS) || (!prStaRec->fgIsWmmSupported) || (!prStaRec->fgIsQoS)){
3882 prBssInfo = &(prAdapter->rWifiVar.arBssInfo[prStaRec->ucNetTypeIndex]);
3884 /* Goal: Obtain the EDCA parameters */
3885 IE_FOR_EACH(pucIE, u2IELength, u2Offset) {
3886 switch (IE_ID(pucIE)) {
3889 if((WMM_IE_OUI_TYPE(pucIE) == VENDOR_OUI_TYPE_WMM) &&
3890 (!kalMemCmp(WMM_IE_OUI(pucIE),aucWfaOui,3))){
3892 switch(WMM_IE_OUI_SUBTYPE(pucIE)){
3893 case VENDOR_OUI_SUBTYPE_WMM_PARAM:
3894 if(IE_LEN(pucIE) != 24){
3895 break; /* WMM Param IE with a wrong length */
3898 P_AC_QUE_PARMS_T prAcQueParams;
3899 P_IE_WMM_PARAM_T prIeWmmParam;
3900 ENUM_WMM_ACI_T eAci;
3901 PUINT_8 pucWmmParamSetCount;
3904 pucWmmParamSetCount = &(prBssInfo->ucWmmParamSetCount);
3906 prIeWmmParam = (P_IE_WMM_PARAM_T)pucIE;
3908 /* Check the Parameter Set Count to determine whether EDCA parameters have been changed */
3909 if(!fgForceOverride){
3910 if(*pucWmmParamSetCount == (prIeWmmParam->ucQosInfo & WMM_QOS_INFO_PARAM_SET_CNT)){
3911 break; /* Ignore the IE without updating HW CRs */
3915 /* Update Parameter Set Count */
3916 *pucWmmParamSetCount = (prIeWmmParam->ucQosInfo & WMM_QOS_INFO_PARAM_SET_CNT);
3918 /* Update EDCA parameters */
3919 for(eAci = 0; eAci < WMM_AC_INDEX_NUM; eAci++){
3921 prAcQueParams = &prBssInfo->arACQueParms[eAci];
3922 mqmFillAcQueParam(prIeWmmParam, eAci, prAcQueParams);
3924 prAcQueParams->fgIsACMSet =
3925 (prAcQueParams->u2Aifsn & WMM_ACIAIFSN_ACM) ? TRUE : FALSE;
3926 prAcQueParams->u2Aifsn &= WMM_ACIAIFSN_AIFSN;
3928 DBGLOG(QM, LOUD, ("MQM: eAci = %d, ACM = %d, Aifsn = %d, CWmin = %d, CWmax = %d, TxopLimit = %d\n",
3929 eAci, prAcQueParams->fgIsACMSet,
3930 prAcQueParams->u2Aifsn, prAcQueParams->u2CWmin,
3931 prAcQueParams->u2CWmax, prAcQueParams->u2TxopLimit));
3937 /* Other WMM QoS IEs. Ignore */
3942 /* else: VENDOR_OUI_TYPE_WPA, VENDOR_OUI_TYPE_WPS, ... (not cared) */
3951 /*----------------------------------------------------------------------------*/
3953 * \brief This function is used for parsing EDCA parameters specified in the WMM Parameter IE
3955 * \param[in] prAdapter Adapter pointer
3956 * \param[in] prIeWmmParam The pointer to the WMM Parameter IE
3957 * \param[in] u4AcOffset The offset specifying the AC queue for parsing
3958 * \param[in] prHwAcParams The parameter structure used to configure the HW CRs
3962 /*----------------------------------------------------------------------------*/
3965 IN P_IE_WMM_PARAM_T prIeWmmParam,
3966 IN UINT_32 u4AcOffset,
3967 OUT P_AC_QUE_PARMS_T prAcQueParams
3970 prAcQueParams->u2Aifsn = *((PUINT_8)(&(prIeWmmParam->ucAciAifsn_BE)) + (u4AcOffset * 4));
3972 prAcQueParams->u2CWmax =
3973 BIT(((*((PUINT_8)(&(prIeWmmParam->ucEcw_BE)) + (u4AcOffset * 4))) & WMM_ECW_WMAX_MASK)
3974 >> WMM_ECW_WMAX_OFFSET)-1;
3976 prAcQueParams->u2CWmin =
3977 BIT((*((PUINT_8)(&(prIeWmmParam->ucEcw_BE)) + (u4AcOffset * 4))) & WMM_ECW_WMIN_MASK)-1;
3979 WLAN_GET_FIELD_16(((PUINT_8)(&(prIeWmmParam->aucTxopLimit_BE)) + (u4AcOffset * 4)),&(prAcQueParams->u2TxopLimit));
3981 prAcQueParams->ucGuradTime = TXM_DEFAULT_FLUSH_QUEUE_GUARD_TIME;
3987 /*----------------------------------------------------------------------------*/
3989 * \brief To parse WMM/11n related IEs in scan results (only for AP peers)
3991 * \param[in] prAdapter Adapter pointer
3992 * \param[in] prScanResult The scan result which shall be parsed to obtain needed info
3993 * \param[out] prStaRec The obtained info is stored in the STA_REC
3997 /*----------------------------------------------------------------------------*/
3999 mqmProcessScanResult(
4000 IN P_ADAPTER_T prAdapter,
4001 IN P_BSS_DESC_T prScanResult,
4002 OUT P_STA_RECORD_T prStaRec
4008 UINT_8 aucWfaOui[] = VENDOR_OUI_WFA;
4010 DEBUGFUNC("mqmProcessScanResult");
4012 ASSERT(prScanResult);
4015 /* Reset the flag before parsing */
4016 prStaRec->fgIsWmmSupported = prStaRec->fgIsUapsdSupported = FALSE;
4018 if (!prAdapter->rWifiVar.fgSupportQoS){
4022 u2IELength = prScanResult->u2IELength;
4023 pucIE = prScanResult->aucIEBuf;
4025 /* Goal: Determine whether the peer supports WMM/QoS and UAPSDU */
4026 IE_FOR_EACH(pucIE, u2IELength, u2Offset) {
4027 switch (IE_ID(pucIE)) {
4029 if((WMM_IE_OUI_TYPE(pucIE) == VENDOR_OUI_TYPE_WMM) &&
4030 (!kalMemCmp(WMM_IE_OUI(pucIE),aucWfaOui,3))){
4032 switch(WMM_IE_OUI_SUBTYPE(pucIE)){
4033 case VENDOR_OUI_SUBTYPE_WMM_PARAM:
4034 if(IE_LEN(pucIE) != 24){
4035 break; /* WMM Param IE with a wrong length */
4038 prStaRec->fgIsWmmSupported = TRUE;
4039 prStaRec->fgIsUapsdSupported = (((((P_IE_WMM_PARAM_T)pucIE)->ucQosInfo) & WMM_QOS_INFO_UAPSD)? TRUE: FALSE);
4043 case VENDOR_OUI_SUBTYPE_WMM_INFO:
4044 if(IE_LEN(pucIE) != 7){
4045 break; /* WMM Info IE with a wrong length */
4048 prStaRec->fgIsWmmSupported = TRUE;
4049 prStaRec->fgIsUapsdSupported = (((((P_IE_WMM_INFO_T)pucIE)->ucQosInfo) & WMM_QOS_INFO_UAPSD)? TRUE: FALSE);
4054 /* A WMM QoS IE that doesn't matter. Ignore it. */
4058 /* else: VENDOR_OUI_TYPE_WPA, VENDOR_OUI_TYPE_WPS, ... (not cared) */
4063 /* A WMM IE that doesn't matter. Ignore it. */
4067 DBGLOG(QM, LOUD, ("MQM: Scan Result Parsing (WMM=%d, UAPSD=%d)\n",
4068 prStaRec->fgIsWmmSupported, prStaRec->fgIsUapsdSupported));
4074 IN P_ADAPTER_T prAdapter,
4075 IN PUINT_8 pucEthDestAddr,
4076 IN ENUM_NETWORK_TYPE_INDEX_T eNetworkType
4080 P_STA_RECORD_T prTempStaRec;
4082 prTempStaRec = NULL;
4087 if(IS_BMCAST_MAC_ADDR(pucEthDestAddr)){
4088 return STA_REC_INDEX_BMCAST;
4092 //4 <2> Check if an AP STA is present
4093 for(i = 0; i < CFG_NUM_OF_STA_RECORD; i++){
4094 prTempStaRec = &(prAdapter->arStaRec[i]);
4095 if((prTempStaRec->ucNetTypeIndex == eNetworkType)
4096 && (prTempStaRec->fgIsAp)
4097 && (prTempStaRec->fgIsValid)){
4098 return prTempStaRec->ucIndex;
4102 //4 <3> Not BMCAST, No AP --> Compare DA (i.e., to see whether this is a unicast frame to a client)
4103 for(i = 0; i < CFG_NUM_OF_STA_RECORD; i++){
4104 prTempStaRec = &(prAdapter->arStaRec[i]);
4105 if(prTempStaRec->fgIsValid){
4106 if(EQUAL_MAC_ADDR(prTempStaRec->aucMacAddr, pucEthDestAddr)){
4107 return prTempStaRec->ucIndex;
4113 //4 <4> No STA found, Not BMCAST --> Indicate NOT_FOUND to FW
4114 return STA_REC_INDEX_NOT_FOUND;
4118 /*----------------------------------------------------------------------------*/
4120 * @brief Generate the WMM Info IE
4122 * \param[in] prAdapter Adapter pointer
4123 * @param prMsduInfo The TX MMPDU
4127 /*----------------------------------------------------------------------------*/
4129 mqmGenerateWmmInfoIE (
4130 IN P_ADAPTER_T prAdapter,
4131 IN P_MSDU_INFO_T prMsduInfo
4134 P_IE_WMM_INFO_T prIeWmmInfo;
4135 UINT_32 ucUapsd[] = {
4136 WMM_QOS_INFO_BE_UAPSD,
4137 WMM_QOS_INFO_BK_UAPSD,
4138 WMM_QOS_INFO_VI_UAPSD,
4139 WMM_QOS_INFO_VO_UAPSD
4141 UINT_8 aucWfaOui[] = VENDOR_OUI_WFA;
4143 P_PM_PROFILE_SETUP_INFO_T prPmProfSetupInfo;
4144 P_BSS_INFO_T prBssInfo;
4145 P_STA_RECORD_T prStaRec;
4147 DEBUGFUNC("mqmGenerateWmmInfoIE");
4151 /* In case QoS is not turned off, exit directly */
4152 if(!prAdapter->rWifiVar.fgSupportQoS){
4156 prStaRec = cnmGetStaRecByIndex(prAdapter, prMsduInfo->ucStaRecIndex);
4159 if(prStaRec == NULL) {
4163 if(!prStaRec->fgIsWmmSupported) {
4167 prBssInfo = &(prAdapter->rWifiVar.arBssInfo[prStaRec->ucNetTypeIndex]);
4169 prPmProfSetupInfo = &prBssInfo->rPmProfSetupInfo;
4171 prIeWmmInfo = (P_IE_WMM_INFO_T)
4172 ((PUINT_8) prMsduInfo->prPacket + prMsduInfo->u2FrameLength);
4174 prIeWmmInfo->ucId = ELEM_ID_WMM;
4175 prIeWmmInfo->ucLength = ELEM_MAX_LEN_WMM_INFO;
4177 /* WMM-2.2.1 WMM Information Element Field Values */
4178 prIeWmmInfo->aucOui[0] = aucWfaOui[0];
4179 prIeWmmInfo->aucOui[1] = aucWfaOui[1];
4180 prIeWmmInfo->aucOui[2] = aucWfaOui[2];
4181 prIeWmmInfo->ucOuiType = VENDOR_OUI_TYPE_WMM;
4182 prIeWmmInfo->ucOuiSubtype = VENDOR_OUI_SUBTYPE_WMM_INFO;
4184 prIeWmmInfo->ucVersion = VERSION_WMM;
4185 prIeWmmInfo->ucQosInfo = 0;
4187 /* UAPSD intial queue configurations (delivery and trigger enabled)*/
4188 // if(prAdapter->rWifiVar.fgSupportUAPSD){
4189 if(prAdapter->rWifiVar.fgSupportUAPSD && prStaRec->fgIsUapsdSupported){
4191 UINT_8 ucQosInfo = 0;
4195 /* Static U-APSD setting */
4196 for(i = ACI_BE; i <= ACI_VO; i++){
4197 if (prPmProfSetupInfo->ucBmpDeliveryAC & prPmProfSetupInfo->ucBmpTriggerAC & BIT(i)){
4198 ucQosInfo |= (UINT_8)ucUapsd[i];
4203 if (prPmProfSetupInfo->ucBmpDeliveryAC & prPmProfSetupInfo->ucBmpTriggerAC) {
4204 switch (prPmProfSetupInfo->ucUapsdSp) {
4205 case WMM_MAX_SP_LENGTH_ALL:
4206 ucQosInfo |= WMM_QOS_INFO_MAX_SP_ALL;
4209 case WMM_MAX_SP_LENGTH_2:
4210 ucQosInfo |= WMM_QOS_INFO_MAX_SP_2;
4213 case WMM_MAX_SP_LENGTH_4:
4214 ucQosInfo |= WMM_QOS_INFO_MAX_SP_4;
4217 case WMM_MAX_SP_LENGTH_6:
4218 ucQosInfo |= WMM_QOS_INFO_MAX_SP_6;
4222 DBGLOG(QM, INFO, ("MQM: Incorrect SP length \n"));
4223 ucQosInfo |= WMM_QOS_INFO_MAX_SP_2;
4227 prIeWmmInfo->ucQosInfo = ucQosInfo;
4231 /* Increment the total IE length for the Element ID and Length fields. */
4232 prMsduInfo->u2FrameLength += IE_SIZE(prIeWmmInfo);
4238 /*----------------------------------------------------------------------------*/
4240 * @brief log2 calculation for CW
4242 * @param[in] val value
4246 /*----------------------------------------------------------------------------*/
4248 UINT_32 cwlog2(UINT_32 val) {
4253 while (val >= 512) { n+= 9; val = val >> 9; }
4254 while (val >= 16) { n+= 4; val >>= 4; }
4255 while (val >= 2) { n+= 1; val >>= 1; }
4261 /*----------------------------------------------------------------------------*/
4263 * @brief Generate the WMM Param IE
4265 * \param[in] prAdapter Adapter pointer
4266 * @param prMsduInfo The TX MMPDU
4270 /*----------------------------------------------------------------------------*/
4272 mqmGenerateWmmParamIE (
4273 IN P_ADAPTER_T prAdapter,
4274 IN P_MSDU_INFO_T prMsduInfo
4277 P_IE_WMM_PARAM_T prIeWmmParam;
4279 UINT_8 aucWfaOui[] = VENDOR_OUI_WFA;
4288 P_BSS_INFO_T prBssInfo;
4289 P_STA_RECORD_T prStaRec;
4290 ENUM_WMM_ACI_T eAci;
4292 DEBUGFUNC("mqmGenerateWmmParamIE");
4293 DBGLOG(QM, LOUD,("\n"));
4297 /* In case QoS is not turned off, exit directly */
4298 if(!prAdapter->rWifiVar.fgSupportQoS){
4302 prStaRec = cnmGetStaRecByIndex(prAdapter, prMsduInfo->ucStaRecIndex);
4305 if(!prStaRec->fgIsQoS) {
4310 prBssInfo = &(prAdapter->rWifiVar.arBssInfo[prMsduInfo->ucNetworkType]);
4312 if(!prBssInfo->fgIsQBSS) { return; }
4314 #if 0 // 20120220 frog: update beacon content & change OP mode is a separate event for P2P network.
4315 if( prBssInfo->eCurrentOPMode != OP_MODE_ACCESS_POINT &&
4316 prBssInfo->eCurrentOPMode != OP_MODE_BOW)
4322 prIeWmmParam = (P_IE_WMM_PARAM_T)
4323 ((PUINT_8) prMsduInfo->prPacket + prMsduInfo->u2FrameLength);
4325 prIeWmmParam->ucId = ELEM_ID_WMM;
4326 prIeWmmParam->ucLength = ELEM_MAX_LEN_WMM_PARAM;
4328 /* WMM-2.2.1 WMM Information Element Field Values */
4329 prIeWmmParam->aucOui[0] = aucWfaOui[0];
4330 prIeWmmParam->aucOui[1] = aucWfaOui[1];
4331 prIeWmmParam->aucOui[2] = aucWfaOui[2];
4332 prIeWmmParam->ucOuiType = VENDOR_OUI_TYPE_WMM;
4333 prIeWmmParam->ucOuiSubtype = VENDOR_OUI_SUBTYPE_WMM_PARAM;
4335 prIeWmmParam->ucVersion = VERSION_WMM;
4336 prIeWmmParam->ucQosInfo = (prBssInfo->ucWmmParamSetCount & WMM_QOS_INFO_PARAM_SET_CNT);
4338 /* UAPSD intial queue configurations (delivery and trigger enabled)*/
4339 if(prAdapter->rWifiVar.fgSupportUAPSD){
4341 prIeWmmParam->ucQosInfo |= WMM_QOS_INFO_UAPSD;
4345 /* EDCA parameter */
4347 for(eAci = 0; eAci < WMM_AC_INDEX_NUM; eAci++){
4349 //DBGLOG(QM, LOUD, ("MQM: eAci = %d, ACM = %d, Aifsn = %d, CWmin = %d, CWmax = %d, TxopLimit = %d\n",
4350 // eAci,prBssInfo->arACQueParmsForBcast[eAci].fgIsACMSet ,
4351 // prBssInfo->arACQueParmsForBcast[eAci].u2Aifsn,
4352 // prBssInfo->arACQueParmsForBcast[eAci].u2CWmin,
4353 // prBssInfo->arACQueParmsForBcast[eAci].u2CWmax,
4354 // prBssInfo->arACQueParmsForBcast[eAci].u2TxopLimit));
4356 *( ((PUINT_8)(&prIeWmmParam->ucAciAifsn_BE)) + (eAci <<2) ) = (UINT_8) (aucACI[eAci]
4357 | (prBssInfo->arACQueParmsForBcast[eAci].fgIsACMSet ? WMM_ACIAIFSN_ACM:0 )
4358 | (prBssInfo->arACQueParmsForBcast[eAci].u2Aifsn & (WMM_ACIAIFSN_AIFSN)));
4360 *( ((PUINT_8)(&prIeWmmParam->ucEcw_BE)) + (eAci <<2) ) = (UINT_8) (0
4361 | (((prBssInfo->aucCWminLog2ForBcast[eAci] )) & WMM_ECW_WMIN_MASK)
4362 | ((((prBssInfo->aucCWmaxLog2ForBcast[eAci] )) << WMM_ECW_WMAX_OFFSET ) & WMM_ECW_WMAX_MASK)
4365 *( ((PUINT_8)(&prIeWmmParam->ucEcw_BE)) + (eAci <<2) ) = (UINT_8) (0
4366 | (cwlog2((prBssInfo->arACQueParmsForBcast[eAci].u2CWmin + 1)) & WMM_ECW_WMIN_MASK)
4367 | ((cwlog2((prBssInfo->arACQueParmsForBcast[eAci].u2CWmax + 1)) << WMM_ECW_WMAX_OFFSET ) & WMM_ECW_WMAX_MASK)
4371 WLAN_SET_FIELD_16( ((PUINT_8)(prIeWmmParam->aucTxopLimit_BE)) + (eAci<<2)
4372 , prBssInfo->arACQueParmsForBcast[eAci].u2TxopLimit);
4376 /* Increment the total IE length for the Element ID and Length fields. */
4377 prMsduInfo->u2FrameLength += IE_SIZE(prIeWmmParam);
4386 IN P_ADAPTER_T prAdapter,
4387 IN ENUM_NETWORK_TYPE_INDEX_T eNetworkType,
4388 IN UINT_8 ucStaRecIdx,
4389 IN P_MSDU_INFO_T prMsduInfo,
4390 IN ENUM_FRAME_TYPE_IN_CMD_Q_T eFrameType
4393 P_BSS_INFO_T prBssInfo;
4394 P_STA_RECORD_T prStaRec;
4395 P_WLAN_MAC_HEADER_T prWlanFrame;
4396 UINT_16 u2TxFrameCtrl;
4398 DEBUGFUNC("qmGetFrameAction");
4400 #if (NIC_TX_BUFF_COUNT_TC4 > 2)
4401 #define QM_MGMT_QUUEUD_THRESHOLD 2
4403 #define QM_MGMT_QUUEUD_THRESHOLD 1
4406 DATA_STRUC_INSPECTING_ASSERT(QM_MGMT_QUUEUD_THRESHOLD <= (NIC_TX_BUFF_COUNT_TC4));
4407 DATA_STRUC_INSPECTING_ASSERT(QM_MGMT_QUUEUD_THRESHOLD > 0);
4409 prBssInfo = &(prAdapter->rWifiVar.arBssInfo[eNetworkType]);
4410 prStaRec = QM_GET_STA_REC_PTR_FROM_INDEX(prAdapter, ucStaRecIdx);
4412 /* XXX Check BOW P2P AIS time ot set active */
4413 if (!IS_BSS_ACTIVE(prBssInfo)) {
4414 if (eFrameType == FRAME_TYPE_MMPDU) {
4415 prWlanFrame = (P_WLAN_MAC_HEADER_T) prMsduInfo->prPacket;
4416 u2TxFrameCtrl = (prWlanFrame->u2FrameCtrl) & MASK_FRAME_TYPE; // Optimized for ARM
4417 if ((u2TxFrameCtrl == MAC_FRAME_DEAUTH) && (prMsduInfo->pfTxDoneHandler == NULL)) {
4418 return FRAME_ACTION_TX_PKT;
4423 DBGLOG(QM, INFO, ("Drop packets Action (Inactive %u).\n",prBssInfo->ucNetTypeIndex));
4424 TX_INC_CNT(&prAdapter->rTxCtrl, TX_INACTIVE_BSS_DROP);
4425 return FRAME_ACTION_DROP_PKT;
4428 /* TODO Handle disconnect issue */
4430 /* P2P probe Request frame */
4432 if(eFrameType == FRAME_TYPE_MMPDU) {
4433 ASSERT(prMsduInfo!=NULL);
4434 prWlanFrame = (P_WLAN_MAC_HEADER_T) prMsduInfo->prPacket;
4435 u2TxFrameCtrl = (prWlanFrame->u2FrameCtrl) & MASK_FRAME_TYPE; // Optimized for ARM
4437 if (u2TxFrameCtrl == MAC_FRAME_BEACON ) {
4438 if( prBssInfo->fgIsNetAbsent) {
4439 return FRAME_ACTION_DROP_PKT;
4442 else if (u2TxFrameCtrl == MAC_FRAME_PROBE_RSP) {
4443 if( prBssInfo->fgIsNetAbsent) {
4447 else if (u2TxFrameCtrl == MAC_FRAME_DEAUTH) {
4448 if( prBssInfo->fgIsNetAbsent) {
4451 DBGLOG(P2P, LOUD, ("Sending DEAUTH Frame\n"));
4452 return FRAME_ACTION_TX_PKT;
4454 /* MMPDU with prStaRec && fgIsInUse not check fgIsNetActive */
4455 else if(u2TxFrameCtrl == MAC_FRAME_ASSOC_REQ
4456 || u2TxFrameCtrl == MAC_FRAME_AUTH
4457 || u2TxFrameCtrl == MAC_FRAME_REASSOC_REQ
4458 || u2TxFrameCtrl == MAC_FRAME_PROBE_REQ
4459 || u2TxFrameCtrl == MAC_FRAME_ACTION) {
4462 if(prStaRec->fgIsInPS) {
4463 if( nicTxGetResource (prAdapter, TC4_INDEX)>= QM_MGMT_QUUEUD_THRESHOLD) {
4464 return FRAME_ACTION_TX_PKT;
4467 return FRAME_ACTION_QUEUE_PKT;
4471 return FRAME_ACTION_TX_PKT;
4475 return FRAME_ACTION_TX_PKT;
4478 if (!prStaRec->fgIsInUse) {
4479 return FRAME_ACTION_DROP_PKT;
4483 } /* FRAME_TYPE_MMPDU */
4484 else if ((eFrameType == FRAME_TYPE_802_1X)){
4487 return FRAME_ACTION_TX_PKT;
4490 if (!prStaRec->fgIsInUse) {
4491 return FRAME_ACTION_DROP_PKT;
4493 if(prStaRec->fgIsInPS) {
4494 if( nicTxGetResource (prAdapter, TC4_INDEX)>= QM_MGMT_QUUEUD_THRESHOLD) {
4495 return FRAME_ACTION_TX_PKT;
4498 return FRAME_ACTION_QUEUE_PKT;
4503 } /* FRAME_TYPE_802_1X */
4504 else if ((!IS_BSS_ACTIVE(prBssInfo))
4506 || (!prStaRec->fgIsInUse)){
4507 return FRAME_ACTION_DROP_PKT;
4511 if (prBssInfo->fgIsNetAbsent){
4512 DBGLOG(QM, LOUD, ("Queue packets (Absent %u).\n",prBssInfo->ucNetTypeIndex));
4513 return FRAME_ACTION_QUEUE_PKT;
4516 if (prStaRec && prStaRec->fgIsInPS){
4517 DBGLOG(QM, LOUD, ("Queue packets (PS %u).\n",prStaRec->fgIsInPS));
4518 return FRAME_ACTION_QUEUE_PKT;
4521 switch (eFrameType){
4522 case FRAME_TYPE_802_1X:
4523 if (!prStaRec->fgIsValid){
4524 return FRAME_ACTION_QUEUE_PKT;
4528 case FRAME_TYPE_MMPDU:
4536 return FRAME_ACTION_TX_PKT;
4540 /*----------------------------------------------------------------------------*/
4542 * \brief Handle BSS change operation Event from the FW
4544 * \param[in] prAdapter Adapter pointer
4545 * \param[in] prEvent The event packet from the FW
4549 /*----------------------------------------------------------------------------*/
4551 qmHandleEventBssAbsencePresence(
4552 IN P_ADAPTER_T prAdapter,
4553 IN P_WIFI_EVENT_T prEvent
4556 P_EVENT_BSS_ABSENCE_PRESENCE_T prEventBssStatus;
4557 P_BSS_INFO_T prBssInfo;
4558 BOOLEAN fgIsNetAbsentOld;
4560 prEventBssStatus = (P_EVENT_BSS_ABSENCE_PRESENCE_T)prEvent;
4561 prBssInfo = &(prAdapter->rWifiVar.arBssInfo[prEventBssStatus->ucNetTypeIdx]);
4562 fgIsNetAbsentOld = prBssInfo->fgIsNetAbsent;
4563 prBssInfo->fgIsNetAbsent = prEventBssStatus->fgIsAbsent;
4564 prBssInfo->ucBssFreeQuota = prEventBssStatus->ucBssFreeQuota;
4566 //DBGLOG(QM, TRACE, ("qmHandleEventBssAbsencePresence (ucNetTypeIdx=%d, fgIsAbsent=%d, FreeQuota=%d)\n",
4567 // prEventBssStatus->ucNetTypeIdx, prBssInfo->fgIsNetAbsent, prBssInfo->ucBssFreeQuota));
4569 DBGLOG(QM, TRACE, ("NAF=%d,%d,%d\n",
4570 prEventBssStatus->ucNetTypeIdx, prBssInfo->fgIsNetAbsent, prBssInfo->ucBssFreeQuota));
4572 if(!prBssInfo->fgIsNetAbsent) {
4573 QM_DBG_CNT_INC(&(prAdapter->rQM),QM_DBG_CNT_27);
4576 QM_DBG_CNT_INC(&(prAdapter->rQM),QM_DBG_CNT_28);
4578 /* From Absent to Present */
4579 if ((fgIsNetAbsentOld) && (!prBssInfo->fgIsNetAbsent)){
4580 kalSetEvent(prAdapter->prGlueInfo);
4585 /*----------------------------------------------------------------------------*/
4587 * \brief Handle STA change PS mode Event from the FW
4589 * \param[in] prAdapter Adapter pointer
4590 * \param[in] prEvent The event packet from the FW
4594 /*----------------------------------------------------------------------------*/
4596 qmHandleEventStaChangePsMode(
4597 IN P_ADAPTER_T prAdapter,
4598 IN P_WIFI_EVENT_T prEvent
4601 P_EVENT_STA_CHANGE_PS_MODE_T prEventStaChangePsMode;
4602 P_STA_RECORD_T prStaRec;
4603 BOOLEAN fgIsInPSOld;
4605 //DbgPrint("QM:Event -RxBa\n");
4607 prEventStaChangePsMode = (P_EVENT_STA_CHANGE_PS_MODE_T)prEvent;
4608 prStaRec = QM_GET_STA_REC_PTR_FROM_INDEX(prAdapter, prEventStaChangePsMode->ucStaRecIdx);
4610 if(prStaRec == NULL) {
4611 printk("Warning: driver & firmware don't sync");
4617 fgIsInPSOld = prStaRec->fgIsInPS;
4618 prStaRec->fgIsInPS = prEventStaChangePsMode->fgIsInPs;
4623 prEventStaChangePsMode->ucUpdateMode,
4624 prEventStaChangePsMode->ucFreeQuota);
4626 //DBGLOG(QM, TRACE, ("qmHandleEventStaChangePsMode (ucStaRecIdx=%d, fgIsInPs=%d)\n",
4627 // prEventStaChangePsMode->ucStaRecIdx, prStaRec->fgIsInPS));
4630 DBGLOG(QM, TRACE, ("PS=%d,%d\n",
4631 prEventStaChangePsMode->ucStaRecIdx, prStaRec->fgIsInPS));
4633 /* From PS to Awake */
4634 if ((fgIsInPSOld) && (!prStaRec->fgIsInPS)){
4635 kalSetEvent(prAdapter->prGlueInfo);
4640 /*----------------------------------------------------------------------------*/
4642 * \brief Update STA free quota Event from FW
4644 * \param[in] prAdapter Adapter pointer
4645 * \param[in] prEvent The event packet from the FW
4649 /*----------------------------------------------------------------------------*/
4651 qmHandleEventStaUpdateFreeQuota(
4652 IN P_ADAPTER_T prAdapter,
4653 IN P_WIFI_EVENT_T prEvent
4656 P_EVENT_STA_UPDATE_FREE_QUOTA_T prEventStaUpdateFreeQuota;
4657 P_STA_RECORD_T prStaRec;
4660 prEventStaUpdateFreeQuota = (P_EVENT_STA_UPDATE_FREE_QUOTA_T)prEvent;
4661 prStaRec = QM_GET_STA_REC_PTR_FROM_INDEX(prAdapter, prEventStaUpdateFreeQuota->ucStaRecIdx);
4665 if(prStaRec->fgIsInPS) {
4669 prEventStaUpdateFreeQuota->ucUpdateMode,
4670 prEventStaUpdateFreeQuota->ucFreeQuota);
4672 kalSetEvent(prAdapter->prGlueInfo);
4675 DBGLOG(QM, TRACE, ("qmHandleEventStaUpdateFreeQuota (ucStaRecIdx=%d, ucUpdateMode=%d, ucFreeQuota=%d)\n",
4676 prEventStaUpdateFreeQuota->ucStaRecIdx,
4677 prEventStaUpdateFreeQuota->ucUpdateMode,
4678 prEventStaUpdateFreeQuota->ucFreeQuota));
4681 DBGLOG(QM, TRACE, ("UFQ=%d,%d,%d\n",
4682 prEventStaUpdateFreeQuota->ucStaRecIdx,
4683 prEventStaUpdateFreeQuota->ucUpdateMode,
4684 prEventStaUpdateFreeQuota->ucFreeQuota));
4692 /*----------------------------------------------------------------------------*/
4694 * \brief Update STA free quota
4696 * \param[in] prStaRec the STA
4697 * \param[in] ucUpdateMode the method to update free quota
4698 * \param[in] ucFreeQuota the value for update
4702 /*----------------------------------------------------------------------------*/
4705 IN P_ADAPTER_T prAdapter,
4706 IN P_STA_RECORD_T prStaRec,
4707 IN UINT_8 ucUpdateMode,
4708 IN UINT_8 ucFreeQuota
4712 UINT_8 ucFreeQuotaForNonDelivery;
4713 UINT_8 ucFreeQuotaForDelivery;
4716 DBGLOG(QM, LOUD, ("qmUpdateFreeQuota orig ucFreeQuota=%d Mode %u New %u\n",
4717 prStaRec->ucFreeQuota, ucUpdateMode, ucFreeQuota ));
4719 if(!prStaRec->fgIsInPS)return;
4721 switch (ucUpdateMode) {
4722 case FREE_QUOTA_UPDATE_MODE_INIT:
4723 case FREE_QUOTA_UPDATE_MODE_OVERWRITE:
4724 prStaRec->ucFreeQuota = ucFreeQuota;
4726 case FREE_QUOTA_UPDATE_MODE_INCREASE:
4727 prStaRec->ucFreeQuota += ucFreeQuota;
4729 case FREE_QUOTA_UPDATE_MODE_DECREASE:
4730 prStaRec->ucFreeQuota -= ucFreeQuota;
4736 DBGLOG(QM, LOUD, ("qmUpdateFreeQuota new ucFreeQuota=%d)\n",
4737 prStaRec->ucFreeQuota ));
4739 ucFreeQuota = prStaRec->ucFreeQuota;
4741 ucFreeQuotaForNonDelivery = 0;
4742 ucFreeQuotaForDelivery = 0;
4744 if(ucFreeQuota > 0) {
4745 if( prStaRec->fgIsQoS && prStaRec->fgIsUapsdSupported
4746 /* && prAdapter->rWifiVar.fgSupportQoS
4747 && prAdapter->rWifiVar.fgSupportUAPSD*/) {
4748 /* XXX We should assign quota to aucFreeQuotaPerQueue[NUM_OF_PER_STA_TX_QUEUES] */
4750 if(prStaRec->ucFreeQuotaForNonDelivery > 0 && prStaRec->ucFreeQuotaForDelivery > 0) {
4751 ucFreeQuotaForNonDelivery = ucFreeQuota>>1;
4752 ucFreeQuotaForDelivery = ucFreeQuota - ucFreeQuotaForNonDelivery;
4754 else if(prStaRec->ucFreeQuotaForNonDelivery == 0 && prStaRec->ucFreeQuotaForDelivery == 0) {
4755 ucFreeQuotaForNonDelivery = ucFreeQuota>>1;
4756 ucFreeQuotaForDelivery = ucFreeQuota - ucFreeQuotaForNonDelivery;
4758 else if(prStaRec->ucFreeQuotaForNonDelivery > 0) {
4759 /* NonDelivery is not busy */
4760 if(ucFreeQuota >= 3 ) {
4761 ucFreeQuotaForNonDelivery = 2;
4762 ucFreeQuotaForDelivery = ucFreeQuota - ucFreeQuotaForNonDelivery ;
4765 ucFreeQuotaForDelivery = ucFreeQuota;
4766 ucFreeQuotaForNonDelivery = 0;
4769 else if(prStaRec->ucFreeQuotaForDelivery > 0) {
4770 /* Delivery is not busy */
4771 if(ucFreeQuota >= 3 ) {
4772 ucFreeQuotaForDelivery = 2;
4773 ucFreeQuotaForNonDelivery = ucFreeQuota - ucFreeQuotaForDelivery;
4776 ucFreeQuotaForNonDelivery = ucFreeQuota;
4777 ucFreeQuotaForDelivery = 0;
4783 /* !prStaRec->fgIsUapsdSupported */
4784 ucFreeQuotaForNonDelivery = ucFreeQuota;
4785 ucFreeQuotaForDelivery = 0;
4787 } /* ucFreeQuota > 0 */
4789 prStaRec->ucFreeQuotaForDelivery = ucFreeQuotaForDelivery;
4790 prStaRec->ucFreeQuotaForNonDelivery = ucFreeQuotaForNonDelivery;
4792 DBGLOG(QM, LOUD, ("new QuotaForDelivery = %d QuotaForNonDelivery = %d\n",
4793 prStaRec->ucFreeQuotaForDelivery, prStaRec->ucFreeQuotaForNonDelivery ));
4797 /*----------------------------------------------------------------------------*/
4799 * \brief Return the reorder queued RX packets
4803 * \return The number of queued RX packets
4805 /*----------------------------------------------------------------------------*/
4807 qmGetRxReorderQueuedBufferCount(
4808 IN P_ADAPTER_T prAdapter
4812 P_QUE_MGT_T prQM = &prAdapter->rQM;
4814 /* XXX The summation may impact the performance */
4815 for(i =0; i<CFG_NUM_OF_RX_BA_AGREEMENTS; i++){
4816 u4Total += prQM->arRxBaTable[i].rReOrderQue.u4NumElem;
4818 if(QUEUE_IS_EMPTY(&(prQM->arRxBaTable[i].rReOrderQue))){
4819 ASSERT(prQM->arRxBaTable[i].rReOrderQue == 0);
4823 ASSERT(u4Total <=( CFG_NUM_OF_QM_RX_PKT_NUM*2));