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];
469 /*******************************************************************************
470 * P R I V A T E D A T A
471 ********************************************************************************
475 /*******************************************************************************
477 ********************************************************************************
480 /*******************************************************************************
481 * F U N C T I O N D E C L A R A T I O N S
482 ********************************************************************************
485 qmDetermineStaRecIndex(
486 IN P_ADAPTER_T prAdapter,
487 IN P_MSDU_INFO_T prMsduInfo
491 qmDequeueTxPacketsFromPerStaQueues(
492 IN P_ADAPTER_T prAdapter,
495 IN UINT_8 ucCurrentAvailableQuota,
496 IN UINT_8 ucTotalQuota
500 qmDequeueTxPacketsFromPerTypeQueues(
501 IN P_ADAPTER_T prAdapter,
507 /*******************************************************************************
509 ********************************************************************************
512 /*----------------------------------------------------------------------------*/
514 * \brief Init Queue Managment for TX
520 /*----------------------------------------------------------------------------*/
523 IN P_ADAPTER_T prAdapter
526 UINT_32 u4QueArrayIdx;
529 P_QUE_MGT_T prQM = &prAdapter->rQM;
531 //DbgPrint("QM: Enter qmInit()\n");
533 prAdapter->rWifiVar.fgSupportQoS = TRUE;
535 prAdapter->rWifiVar.fgSupportQoS = FALSE;
538 #if CFG_SUPPORT_AMPDU_RX
539 prAdapter->rWifiVar.fgSupportAmpduRx = TRUE;
541 prAdapter->rWifiVar.fgSupportAmpduRx = FALSE;
544 #if CFG_SUPPORT_AMPDU_TX
545 prAdapter->rWifiVar.fgSupportAmpduTx = TRUE;
547 prAdapter->rWifiVar.fgSupportAmpduTx = FALSE;
550 #if CFG_SUPPORT_TSPEC
551 prAdapter->rWifiVar.fgSupportTspec = TRUE;
553 prAdapter->rWifiVar.fgSupportTspec = FALSE;
556 #if CFG_SUPPORT_UAPSD
557 prAdapter->rWifiVar.fgSupportUAPSD= TRUE;
559 prAdapter->rWifiVar.fgSupportUAPSD = FALSE;
562 #if CFG_SUPPORT_UL_PSMP
563 prAdapter->rWifiVar.fgSupportULPSMP = TRUE;
565 prAdapter->rWifiVar.fgSupportULPSMP = FALSE;
568 //4 <2> Initialize other TX queues (queues not in STA_RECs)
569 for(u4QueArrayIdx = 0; u4QueArrayIdx < NUM_OF_PER_TYPE_TX_QUEUES; u4QueArrayIdx++){
570 QUEUE_INITIALIZE(&(prQM->arTxQueue[u4QueArrayIdx]));
573 //4 <3> Initialize the RX BA table and RX queues
574 /* Initialize the RX Reordering Parameters and Queues */
575 for(u4QueArrayIdx = 0; u4QueArrayIdx < CFG_NUM_OF_RX_BA_AGREEMENTS; u4QueArrayIdx++){
576 prQM->arRxBaTable[u4QueArrayIdx].fgIsValid = FALSE;
577 QUEUE_INITIALIZE(&(prQM->arRxBaTable[u4QueArrayIdx].rReOrderQue));
578 prQM->arRxBaTable[u4QueArrayIdx].u2WinStart = 0xFFFF;
579 prQM->arRxBaTable[u4QueArrayIdx].u2WinEnd = 0xFFFF;
581 prQM->arRxBaTable[u4QueArrayIdx].fgIsWaitingForPktWithSsn = FALSE;
584 prQM->ucRxBaCount = 0;
585 kalMemSet(&g_arMissTimeout, 0, sizeof(g_arMissTimeout));
587 #if QM_ADAPTIVE_TC_RESOURCE_CTRL
588 //4 <4> Initialize TC resource control variables
589 for(i = 0; i < TC_NUM; i++){
590 prQM->au4AverageQueLen[i] = 0;
592 prQM->u4TimeToAdjustTcResource = QM_INIT_TIME_TO_ADJUST_TC_RSC;
593 prQM->u4TimeToUpdateQueLen = QM_INIT_TIME_TO_UPDATE_QUE_LEN;
595 // ASSERT(prQM->u4TimeToAdjust && prQM->u4TimeToUpdateQueLen);
597 prQM->au4CurrentTcResource[TC0_INDEX] = NIC_TX_BUFF_COUNT_TC0;
598 prQM->au4CurrentTcResource[TC1_INDEX] = NIC_TX_BUFF_COUNT_TC1;
599 prQM->au4CurrentTcResource[TC2_INDEX] = NIC_TX_BUFF_COUNT_TC2;
600 prQM->au4CurrentTcResource[TC3_INDEX] = NIC_TX_BUFF_COUNT_TC3;
601 prQM->au4CurrentTcResource[TC4_INDEX] = NIC_TX_BUFF_COUNT_TC4; /* Not adjustable (TX port 1)*/
602 prQM->au4CurrentTcResource[TC5_INDEX] = NIC_TX_BUFF_COUNT_TC5;
604 prQM->au4MinReservedTcResource[TC0_INDEX] = QM_MIN_RESERVED_TC0_RESOURCE;
605 prQM->au4MinReservedTcResource[TC1_INDEX] = QM_MIN_RESERVED_TC1_RESOURCE;
606 prQM->au4MinReservedTcResource[TC2_INDEX] = QM_MIN_RESERVED_TC2_RESOURCE;
607 prQM->au4MinReservedTcResource[TC3_INDEX] = QM_MIN_RESERVED_TC3_RESOURCE;
608 prQM->au4MinReservedTcResource[TC4_INDEX] = QM_MIN_RESERVED_TC4_RESOURCE; /* Not adjustable (TX port 1)*/
609 prQM->au4MinReservedTcResource[TC5_INDEX] = QM_MIN_RESERVED_TC5_RESOURCE;
612 prQM->au4GuaranteedTcResource[TC0_INDEX] = QM_GUARANTEED_TC0_RESOURCE;
613 prQM->au4GuaranteedTcResource[TC1_INDEX] = QM_GUARANTEED_TC1_RESOURCE;
614 prQM->au4GuaranteedTcResource[TC2_INDEX] = QM_GUARANTEED_TC2_RESOURCE;
615 prQM->au4GuaranteedTcResource[TC3_INDEX] = QM_GUARANTEED_TC3_RESOURCE;
616 prQM->au4GuaranteedTcResource[TC4_INDEX] = QM_GUARANTEED_TC4_RESOURCE;
617 prQM->au4GuaranteedTcResource[TC5_INDEX] = QM_GUARANTEED_TC5_RESOURCE;
619 prQM->fgTcResourcePostAnnealing = FALSE;
621 ASSERT(QM_INITIAL_RESIDUAL_TC_RESOURCE < 64);
625 prQM->u4PktCount = 0;
627 #if QM_TEST_FAIR_FORWARDING
629 prQM->u4CurrentStaRecIndexToEnqueue = 0;
631 UINT_8 aucMacAddr[MAC_ADDR_LEN];
632 P_STA_RECORD_T prStaRec;
634 /* Irrelevant in case this STA is an AIS AP (see qmDetermineStaRecIndex()) */
635 aucMacAddr[0] = 0x11;
636 aucMacAddr[1] = 0x22;
637 aucMacAddr[2] = 0xAA;
638 aucMacAddr[3] = 0xBB;
639 aucMacAddr[4] = 0xCC;
640 aucMacAddr[5] = 0xDD;
642 prStaRec = &prAdapter->arStaRec[1];
645 prStaRec->fgIsValid = TRUE;
646 prStaRec->fgIsQoS = TRUE;
647 prStaRec->fgIsInPS = FALSE;
648 prStaRec->ucPsSessionID = 0xFF;
649 prStaRec->ucNetTypeIndex = NETWORK_TYPE_AIS_INDEX;
650 prStaRec->fgIsAp = TRUE;
651 COPY_MAC_ADDR((prStaRec)->aucMacAddr,aucMacAddr);
659 #if QM_FORWARDING_FAIRNESS
662 for (i=0; i < NUM_OF_PER_STA_TX_QUEUES; i++){
663 prQM->au4ForwardCount[i] = 0;
664 prQM->au4HeadStaRecIndex[i] = 0;
674 IN P_ADAPTER_T prAdapter
677 P_QUE_MGT_T prQM = &prAdapter->rQM;
679 DbgPrint("QM: ** TEST MODE **\n");
681 if(QM_TEST_STA_REC_DETERMINATION){
682 if(prAdapter->arStaRec[0].fgIsValid){
683 prAdapter->arStaRec[0].fgIsValid = FALSE;
684 DbgPrint("QM: (Test) Deactivate STA_REC[0]\n");
687 prAdapter->arStaRec[0].fgIsValid = TRUE;
688 DbgPrint("QM: (Test) Activate STA_REC[0]\n");
692 if(QM_TEST_STA_REC_DEACTIVATION){
693 /* Note that QM_STA_REC_HARD_CODING shall be set to 1 for this test */
695 if(prAdapter->arStaRec[0].fgIsValid){
697 DbgPrint("QM: (Test) Deactivate STA_REC[0]\n");
698 qmDeactivateStaRec(prAdapter,0);
702 UINT_8 aucMacAddr[MAC_ADDR_LEN];
704 /* Irrelevant in case this STA is an AIS AP (see qmDetermineStaRecIndex()) */
705 aucMacAddr[0] = 0x11;
706 aucMacAddr[1] = 0x22;
707 aucMacAddr[2] = 0xAA;
708 aucMacAddr[3] = 0xBB;
709 aucMacAddr[4] = 0xCC;
710 aucMacAddr[5] = 0xDD;
712 DbgPrint("QM: (Test) Activate STA_REC[0]\n");
714 prAdapter, /* Adapter pointer */
715 0, /* STA_REC index from FW */
717 NETWORK_TYPE_AIS_INDEX, /* Network type */
719 aucMacAddr /* MAC address */
724 if(QM_TEST_FAIR_FORWARDING){
725 if(prAdapter->arStaRec[1].fgIsValid){
726 prQM->u4CurrentStaRecIndexToEnqueue ++;
727 prQM->u4CurrentStaRecIndexToEnqueue %= 2;
728 DbgPrint("QM: (Test) Switch to STA_REC[%ld]\n", prQM->u4CurrentStaRecIndexToEnqueue);
735 /*----------------------------------------------------------------------------*/
737 * \brief Activate a STA_REC
739 * \param[in] prAdapter Pointer to the Adapter instance
740 * \param[in] u4StaRecIdx The index of the STA_REC
741 * \param[in] fgIsQoS Set to TRUE if this is a QoS STA
742 * \param[in] pucMacAddr The MAC address of the STA
746 /*----------------------------------------------------------------------------*/
749 IN P_ADAPTER_T prAdapter,
750 IN P_STA_RECORD_T prStaRec
754 //4 <1> Deactivate first
757 if(prStaRec->fgIsValid){ /* The STA_REC has been activated */
758 DBGLOG(QM, WARN, ("QM: (WARNING) Activating a STA_REC which has been activated \n"));
759 DBGLOG(QM, WARN, ("QM: (WARNING) Deactivating a STA_REC before re-activating \n"));
760 qmDeactivateStaRec(prAdapter, prStaRec->ucIndex); // To flush TX/RX queues and del RX BA agreements
763 //4 <2> Activate the STA_REC
764 /* Init the STA_REC */
765 prStaRec->fgIsValid = TRUE;
766 prStaRec->fgIsInPS = FALSE;
767 prStaRec->ucPsSessionID = 0xFF;
768 prStaRec->fgIsAp = (IS_AP_STA(prStaRec)) ? TRUE : FALSE;;
770 /* Done in qmInit() or qmDeactivateStaRec() */
772 /* At the beginning, no RX BA agreements have been established */
773 for(i =0; i<CFG_RX_MAX_BA_TID_NUM; i++){
774 (prStaRec->aprRxReorderParamRefTbl)[i] = NULL;
778 DBGLOG(QM, INFO, ("QM: +STA[%ld]\n", prStaRec->ucIndex));
781 /*----------------------------------------------------------------------------*/
783 * \brief Deactivate a STA_REC
785 * \param[in] prAdapter Pointer to the Adapter instance
786 * \param[in] u4StaRecIdx The index of the STA_REC
790 /*----------------------------------------------------------------------------*/
793 IN P_ADAPTER_T prAdapter,
794 IN UINT_32 u4StaRecIdx
797 P_STA_RECORD_T prStaRec;
799 P_MSDU_INFO_T prFlushedTxPacketList = NULL;
801 ASSERT(u4StaRecIdx < CFG_NUM_OF_STA_RECORD);
803 prStaRec = &prAdapter->arStaRec[u4StaRecIdx];
806 //4<1> Flush TX queues
807 prFlushedTxPacketList = qmFlushStaTxQueues(prAdapter, u4StaRecIdx);
809 if(prFlushedTxPacketList){
810 wlanProcessQueuedMsduInfo(prAdapter, prFlushedTxPacketList);
813 //4 <2> Flush RX queues and delete RX BA agreements
814 for(i =0; i < CFG_RX_MAX_BA_TID_NUM; i++){
815 /* Delete the RX BA entry with TID = i */
816 qmDelRxBaEntry(prAdapter, (UINT_8)u4StaRecIdx, (UINT_8)i, FALSE);
819 //4 <3> Deactivate the STA_REC
820 prStaRec->fgIsValid = FALSE;
821 prStaRec->fgIsInPS = FALSE;
823 DBGLOG(QM, INFO, ("QM: -STA[%ld]\n", u4StaRecIdx));
827 /*----------------------------------------------------------------------------*/
829 * \brief Deactivate a STA_REC
831 * \param[in] prAdapter Pointer to the Adapter instance
832 * \param[in] u4StaRecIdx The index of the network
836 /*----------------------------------------------------------------------------*/
840 IN P_ADAPTER_T prAdapter,
841 IN ENUM_NETWORK_TYPE_INDEX_T eNetworkTypeIdx
847 QUE_T rNeedToFreeQue;
849 P_QUE_T prNeedToFreeQue;
851 P_MSDU_INFO_T prMsduInfo;
854 prQM = &prAdapter->rQM;
855 prQue = &prQM->arTxQueue[TX_QUEUE_INDEX_BMCAST];
857 QUEUE_INITIALIZE(&rNeedToFreeQue);
858 QUEUE_INITIALIZE(&rTempQue);
860 prNeedToFreeQue = &rNeedToFreeQue;
861 prTempQue = &rTempQue;
863 QUEUE_MOVE_ALL(prTempQue, prQue);
865 QUEUE_REMOVE_HEAD(prTempQue, prMsduInfo, P_MSDU_INFO_T);
868 if(prMsduInfo->ucNetworkType == eNetworkTypeIdx) {
869 QUEUE_INSERT_TAIL(prNeedToFreeQue, (P_QUE_ENTRY_T)prMsduInfo);
872 QUEUE_INSERT_TAIL(prQue, (P_QUE_ENTRY_T)prMsduInfo);
875 QUEUE_REMOVE_HEAD(prTempQue, prMsduInfo, P_MSDU_INFO_T);
877 if(QUEUE_IS_NOT_EMPTY(prNeedToFreeQue)) {
878 wlanProcessQueuedMsduInfo(prAdapter, (P_MSDU_INFO_T)QUEUE_GET_HEAD(prNeedToFreeQue));
883 /*----------------------------------------------------------------------------*/
885 * \brief Flush all TX queues
889 * \return The flushed packets (in a list of MSDU_INFOs)
891 /*----------------------------------------------------------------------------*/
894 IN P_ADAPTER_T prAdapter
897 UINT_8 ucStaArrayIdx;
898 UINT_8 ucQueArrayIdx;
900 P_MSDU_INFO_T prMsduInfoListHead;
901 P_MSDU_INFO_T prMsduInfoListTail;
903 P_QUE_MGT_T prQM = &prAdapter->rQM;
905 DBGLOG(QM, TRACE, ("QM: Enter qmFlushTxQueues()\n"));
907 prMsduInfoListHead = NULL;
908 prMsduInfoListTail = NULL;
910 /* Concatenate all MSDU_INFOs in per-STA queues */
911 for(ucStaArrayIdx = 0; ucStaArrayIdx < CFG_NUM_OF_STA_RECORD; ucStaArrayIdx++){
913 /* Always check each STA_REC when flushing packets no matter it is inactive or active */
915 if(!prAdapter->arStaRec[ucStaArrayIdx].fgIsValid){
916 continue; /* Continue to check the next STA_REC */
920 for(ucQueArrayIdx = 0; ucQueArrayIdx < NUM_OF_PER_STA_TX_QUEUES; ucQueArrayIdx++){
921 if(QUEUE_IS_EMPTY(&(prAdapter->arStaRec[ucStaArrayIdx].arTxQueue[ucQueArrayIdx]))){
922 continue; /* Continue to check the next TX queue of the same STA */
925 if(!prMsduInfoListHead){
927 /* The first MSDU_INFO is found */
928 prMsduInfoListHead =(P_MSDU_INFO_T)
929 QUEUE_GET_HEAD(&prAdapter->arStaRec[ucStaArrayIdx].arTxQueue[ucQueArrayIdx]);
930 prMsduInfoListTail =(P_MSDU_INFO_T)
931 QUEUE_GET_TAIL(&prAdapter->arStaRec[ucStaArrayIdx].arTxQueue[ucQueArrayIdx]);
934 /* Concatenate the MSDU_INFO list with the existing list */
935 QM_TX_SET_NEXT_MSDU_INFO(prMsduInfoListTail,
936 QUEUE_GET_HEAD(&prAdapter->arStaRec[ucStaArrayIdx].arTxQueue[ucQueArrayIdx]));
938 prMsduInfoListTail = (P_MSDU_INFO_T)
939 QUEUE_GET_TAIL(&prAdapter->arStaRec[ucStaArrayIdx].arTxQueue[ucQueArrayIdx]);
942 QUEUE_INITIALIZE(&prAdapter->arStaRec[ucStaArrayIdx].arTxQueue[ucQueArrayIdx]);
946 /* Flush per-Type queues */
947 for(ucQueArrayIdx = 0; ucQueArrayIdx < NUM_OF_PER_TYPE_TX_QUEUES; ucQueArrayIdx++){
949 if(QUEUE_IS_EMPTY(&(prQM->arTxQueue[ucQueArrayIdx]))){
950 continue; /* Continue to check the next TX queue of the same STA */
953 if(!prMsduInfoListHead){
955 /* The first MSDU_INFO is found */
956 prMsduInfoListHead =(P_MSDU_INFO_T)
957 QUEUE_GET_HEAD(&prQM->arTxQueue[ucQueArrayIdx]);
958 prMsduInfoListTail =(P_MSDU_INFO_T)
959 QUEUE_GET_TAIL(&prQM->arTxQueue[ucQueArrayIdx]);
962 /* Concatenate the MSDU_INFO list with the existing list */
963 QM_TX_SET_NEXT_MSDU_INFO(prMsduInfoListTail,
964 QUEUE_GET_HEAD(&prQM->arTxQueue[ucQueArrayIdx]));
966 prMsduInfoListTail = (P_MSDU_INFO_T)
967 QUEUE_GET_TAIL(&prQM->arTxQueue[ucQueArrayIdx]);
970 QUEUE_INITIALIZE(&prQM->arTxQueue[ucQueArrayIdx]);
974 if(prMsduInfoListTail){
975 /* Terminate the MSDU_INFO list with a NULL pointer */
976 QM_TX_SET_NEXT_MSDU_INFO(prMsduInfoListTail, NULL);
979 return prMsduInfoListHead;
983 /*----------------------------------------------------------------------------*/
985 * \brief Flush TX packets for a particular STA
987 * \param[in] u4StaRecIdx STA_REC index
989 * \return The flushed packets (in a list of MSDU_INFOs)
991 /*----------------------------------------------------------------------------*/
994 IN P_ADAPTER_T prAdapter,
995 IN UINT_32 u4StaRecIdx
998 UINT_8 ucQueArrayIdx;
999 P_MSDU_INFO_T prMsduInfoListHead;
1000 P_MSDU_INFO_T prMsduInfoListTail;
1001 P_STA_RECORD_T prStaRec;
1003 DBGLOG(QM, TRACE, ("QM: Enter qmFlushStaTxQueues(%ld)\n", u4StaRecIdx));
1005 ASSERT(u4StaRecIdx < CFG_NUM_OF_STA_RECORD);
1007 prMsduInfoListHead = NULL;
1008 prMsduInfoListTail = NULL;
1010 prStaRec = &prAdapter->arStaRec[u4StaRecIdx];
1013 /* No matter whether this is an activated STA_REC, do flush */
1015 if(!prStaRec->fgIsValid){
1020 /* Concatenate all MSDU_INFOs in TX queues of this STA_REC */
1021 for(ucQueArrayIdx = 0; ucQueArrayIdx < NUM_OF_PER_STA_TX_QUEUES; ucQueArrayIdx++){
1022 if(QUEUE_IS_EMPTY(&(prStaRec->arTxQueue[ucQueArrayIdx]))){
1026 if(!prMsduInfoListHead){
1027 /* The first MSDU_INFO is found */
1028 prMsduInfoListHead =(P_MSDU_INFO_T)
1029 QUEUE_GET_HEAD(&prStaRec->arTxQueue[ucQueArrayIdx]);
1030 prMsduInfoListTail =(P_MSDU_INFO_T)
1031 QUEUE_GET_TAIL(&prStaRec->arTxQueue[ucQueArrayIdx]); }
1033 /* Concatenate the MSDU_INFO list with the existing list */
1034 QM_TX_SET_NEXT_MSDU_INFO(prMsduInfoListTail,
1035 QUEUE_GET_HEAD(&prStaRec->arTxQueue[ucQueArrayIdx]));
1037 prMsduInfoListTail =
1038 (P_MSDU_INFO_T)QUEUE_GET_TAIL(&prStaRec->arTxQueue[ucQueArrayIdx]);
1041 QUEUE_INITIALIZE(&prStaRec->arTxQueue[ucQueArrayIdx]);
1046 if(prMsduInfoListTail){
1047 /* Terminate the MSDU_INFO list with a NULL pointer */
1048 QM_TX_SET_NEXT_MSDU_INFO(prMsduInfoListTail, nicGetPendingStaMMPDU(prAdapter, (UINT_8)u4StaRecIdx));
1051 prMsduInfoListHead = nicGetPendingStaMMPDU(prAdapter, (UINT_8)u4StaRecIdx);
1055 return prMsduInfoListHead;
1059 /*----------------------------------------------------------------------------*/
1061 * \brief Flush RX packets
1065 * \return The flushed packets (in a list of SW_RFBs)
1067 /*----------------------------------------------------------------------------*/
1070 IN P_ADAPTER_T prAdapter
1074 P_SW_RFB_T prSwRfbListHead;
1075 P_SW_RFB_T prSwRfbListTail;
1076 P_QUE_MGT_T prQM = &prAdapter->rQM;
1078 prSwRfbListHead = prSwRfbListTail = NULL;
1080 DBGLOG(QM, TRACE, ("QM: Enter qmFlushRxQueues()\n"));
1082 for(i =0; i<CFG_NUM_OF_RX_BA_AGREEMENTS; i++){
1083 if(QUEUE_IS_NOT_EMPTY(&(prQM->arRxBaTable[i].rReOrderQue))){
1084 if(!prSwRfbListHead){
1086 /* The first MSDU_INFO is found */
1087 prSwRfbListHead =(P_SW_RFB_T)
1088 QUEUE_GET_HEAD(&(prQM->arRxBaTable[i].rReOrderQue));
1089 prSwRfbListTail =(P_SW_RFB_T)
1090 QUEUE_GET_TAIL(&(prQM->arRxBaTable[i].rReOrderQue));
1093 /* Concatenate the MSDU_INFO list with the existing list */
1094 QM_TX_SET_NEXT_MSDU_INFO(prSwRfbListTail,
1095 QUEUE_GET_HEAD(&(prQM->arRxBaTable[i].rReOrderQue)));
1097 prSwRfbListTail = (P_SW_RFB_T)
1098 QUEUE_GET_TAIL(&(prQM->arRxBaTable[i].rReOrderQue));
1101 QUEUE_INITIALIZE(&(prQM->arRxBaTable[i].rReOrderQue));
1109 if(prSwRfbListTail){
1110 /* Terminate the MSDU_INFO list with a NULL pointer */
1111 QM_TX_SET_NEXT_SW_RFB(prSwRfbListTail, NULL);
1113 return prSwRfbListHead;
1118 /*----------------------------------------------------------------------------*/
1120 * \brief Flush RX packets with respect to a particular STA
1122 * \param[in] u4StaRecIdx STA_REC index
1123 * \param[in] u4Tid TID
1125 * \return The flushed packets (in a list of SW_RFBs)
1127 /*----------------------------------------------------------------------------*/
1130 IN P_ADAPTER_T prAdapter,
1131 IN UINT_32 u4StaRecIdx,
1136 P_SW_RFB_T prSwRfbListHead;
1137 P_SW_RFB_T prSwRfbListTail;
1138 P_RX_BA_ENTRY_T prReorderQueParm;
1139 P_STA_RECORD_T prStaRec;
1141 DBGLOG(QM, TRACE, ("QM: Enter qmFlushStaRxQueues(%ld)\n", u4StaRecIdx));
1143 prSwRfbListHead = prSwRfbListTail = NULL;
1145 prStaRec = &prAdapter->arStaRec[u4StaRecIdx];
1148 /* No matter whether this is an activated STA_REC, do flush */
1150 if(!prStaRec->fgIsValid){
1155 /* Obtain the RX BA Entry pointer */
1156 prReorderQueParm = ((prStaRec->aprRxReorderParamRefTbl)[u4Tid]);
1158 /* Note: For each queued packet, prCurrSwRfb->eDst equals RX_PKT_DESTINATION_HOST */
1159 if(prReorderQueParm){
1161 if(QUEUE_IS_NOT_EMPTY(&(prReorderQueParm->rReOrderQue))){
1163 prSwRfbListHead =(P_SW_RFB_T)
1164 QUEUE_GET_HEAD(&(prReorderQueParm->rReOrderQue));
1165 prSwRfbListTail =(P_SW_RFB_T)
1166 QUEUE_GET_TAIL(&(prReorderQueParm->rReOrderQue));
1169 QUEUE_INITIALIZE(&(prReorderQueParm->rReOrderQue));
1174 if(prSwRfbListTail){
1175 /* Terminate the MSDU_INFO list with a NULL pointer */
1176 QM_TX_SET_NEXT_SW_RFB(prSwRfbListTail, NULL);
1178 return prSwRfbListHead;
1184 /*----------------------------------------------------------------------------*/
1186 * \brief Enqueue TX packets
1188 * \param[in] prMsduInfoListHead Pointer to the list of TX packets
1190 * \return The freed packets, which are not enqueued
1192 /*----------------------------------------------------------------------------*/
1195 IN P_ADAPTER_T prAdapter,
1196 IN P_MSDU_INFO_T prMsduInfoListHead
1199 P_MSDU_INFO_T prMsduInfoReleaseList;
1200 P_MSDU_INFO_T prCurrentMsduInfo;
1201 P_MSDU_INFO_T prNextMsduInfo;
1203 P_STA_RECORD_T prStaRec;
1205 QUE_T rNotEnqueuedQue;
1208 UINT_8 ucPacketType;
1210 P_QUE_MGT_T prQM = &prAdapter->rQM;
1211 UINT_8 aucNextUP[WMM_AC_INDEX_NUM] = { 1 /* BEtoBK*/, 1 /*na*/, 0/*VItoBE*/ , 4 /*VOtoVI*/};
1213 DBGLOG(QM, LOUD, ("Enter qmEnqueueTxPackets\n"));
1215 ASSERT(prMsduInfoListHead);
1217 #if QM_ADAPTIVE_TC_RESOURCE_CTRL
1220 //4 <0> Update TC resource control related variables
1221 /* Keep track of the queue length */
1222 if (--prQM->u4TimeToUpdateQueLen == 0){
1223 prQM->u4TimeToUpdateQueLen = QM_INIT_TIME_TO_UPDATE_QUE_LEN;
1224 qmUpdateAverageTxQueLen(prAdapter);
1229 /* Push TX packets into STA_REC (for UNICAST) or prAdapter->rQM (for BMCAST) */
1231 prMsduInfoReleaseList = NULL;
1232 prCurrentMsduInfo = NULL;
1233 QUEUE_INITIALIZE(&rNotEnqueuedQue);
1234 prNextMsduInfo = prMsduInfoListHead;
1237 P_BSS_INFO_T prBssInfo;
1238 BOOLEAN fgCheckACMAgain;
1239 ENUM_WMM_ACI_T eAci = WMM_AC_BE_INDEX;
1240 prCurrentMsduInfo = prNextMsduInfo;
1241 prNextMsduInfo = QM_TX_GET_NEXT_MSDU_INFO(prCurrentMsduInfo);
1244 //4 <1> Lookup the STA_REC index
1245 /* The ucStaRecIndex will be set in this function */
1246 qmDetermineStaRecIndex(prAdapter, prCurrentMsduInfo);
1247 ucPacketType = HIF_TX_PACKET_TYPE_DATA;
1249 DBGLOG(QM, LOUD , ("***** ucStaRecIndex = %d *****\n",
1250 prCurrentMsduInfo->ucStaRecIndex));
1253 prBssInfo = &(prAdapter->rWifiVar.arBssInfo[prCurrentMsduInfo->ucNetworkType]);
1255 if(IS_NET_ACTIVE(prAdapter, prCurrentMsduInfo->ucNetworkType)) {
1257 switch (prCurrentMsduInfo->ucStaRecIndex){
1258 case STA_REC_INDEX_BMCAST:
1259 prTxQue = &prQM->arTxQueue[TX_QUEUE_INDEX_BMCAST];
1262 if(prCurrentMsduInfo->ucNetworkType == NETWORK_TYPE_P2P_INDEX
1263 && prCurrentMsduInfo->eSrc != TX_PACKET_MGMT
1265 if(LINK_IS_EMPTY(&prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_P2P_INDEX].rStaRecOfClientList)) {
1266 prTxQue = &rNotEnqueuedQue;
1267 TX_INC_CNT(&prAdapter->rTxCtrl,TX_AP_BORADCAST_DROP);
1272 QM_DBG_CNT_INC(prQM, QM_DBG_CNT_23);
1275 case STA_REC_INDEX_NOT_FOUND:
1278 if(prCurrentMsduInfo->eSrc == TX_PACKET_FORWARDING) {
1280 /* if the packet is the forward type. the packet should be freed */
1281 DBGLOG(QM, TRACE, ("Forwarding packet but Sta is STA_REC_INDEX_NOT_FOUND\n"));
1282 //prTxQue = &rNotEnqueuedQue;
1284 prTxQue = &prQM->arTxQueue[TX_QUEUE_INDEX_NO_STA_REC];
1285 QM_DBG_CNT_INC(prQM, QM_DBG_CNT_24);
1290 prStaRec = QM_GET_STA_REC_PTR_FROM_INDEX(prAdapter, prCurrentMsduInfo->ucStaRecIndex);
1293 ASSERT(prStaRec->fgIsValid);
1295 if(prCurrentMsduInfo->ucUserPriority < 8) {
1296 QM_DBG_CNT_INC(prQM, prCurrentMsduInfo->ucUserPriority + 15);
1297 /* QM_DBG_CNT_15 */ /* QM_DBG_CNT_16 */ /* QM_DBG_CNT_17 */ /* QM_DBG_CNT_18 */
1298 /* QM_DBG_CNT_19 */ /* QM_DBG_CNT_20 */ /* QM_DBG_CNT_21 */ /* QM_DBG_CNT_22 */
1301 eAci = WMM_AC_BE_INDEX;
1303 fgCheckACMAgain = FALSE;
1304 if (prStaRec->fgIsQoS){
1305 switch(prCurrentMsduInfo->ucUserPriority){
1308 prTxQue = &prStaRec->arTxQueue[TX_QUEUE_INDEX_AC0];
1310 eAci = WMM_AC_BK_INDEX;
1314 prTxQue = &prStaRec->arTxQueue[TX_QUEUE_INDEX_AC1];
1316 eAci = WMM_AC_BE_INDEX;
1320 prTxQue = &prStaRec->arTxQueue[TX_QUEUE_INDEX_AC2];
1322 eAci = WMM_AC_VI_INDEX;
1326 prTxQue = &prStaRec->arTxQueue[TX_QUEUE_INDEX_AC3];
1328 eAci = WMM_AC_VO_INDEX;
1331 prTxQue = &prStaRec->arTxQueue[TX_QUEUE_INDEX_AC1];
1333 eAci = WMM_AC_BE_INDEX;
1337 if(prBssInfo->arACQueParms[eAci].fgIsACMSet && eAci != WMM_AC_BK_INDEX) {
1338 prCurrentMsduInfo->ucUserPriority = aucNextUP[eAci];
1339 fgCheckACMAgain = TRUE;
1343 prTxQue = &prStaRec->arTxQueue[TX_QUEUE_INDEX_AC1];
1347 while(fgCheckACMAgain);
1349 //LOG_FUNC ("QoS %u UP %u TC %u",prStaRec->fgIsQoS,prCurrentMsduInfo->ucUserPriority, ucTC);
1352 } /* switch (prCurrentMsduInfo->ucStaRecIndex) */
1354 if(prCurrentMsduInfo->eSrc == TX_PACKET_FORWARDING) {
1355 if(prTxQue->u4NumElem > 32) {
1356 DBGLOG(QM, INFO, ("Drop the Packet for full Tx queue (forwarding) Bss %u\n", prCurrentMsduInfo->ucNetworkType));
1357 prTxQue = &rNotEnqueuedQue;
1358 TX_INC_CNT(&prAdapter->rTxCtrl,TX_FORWARD_OVERFLOW_DROP);
1365 DBGLOG(QM, INFO, ("Drop the Packet for inactive Bss %u\n", prCurrentMsduInfo->ucNetworkType));
1366 QM_DBG_CNT_INC(prQM, QM_DBG_CNT_31);
1367 prTxQue = &rNotEnqueuedQue;
1368 TX_INC_CNT(&prAdapter->rTxCtrl,TX_INACTIVE_BSS_DROP);
1371 //4 <3> Fill the MSDU_INFO for constructing HIF TX header
1373 /* TODO: Fill MSDU_INFO according to the network type,
1374 * EtherType, and STA status (for PS forwarding control).
1377 /* Note that the Network Type Index and STA_REC index are determined in
1378 * qmDetermineStaRecIndex(prCurrentMsduInfo).
1380 QM_TX_SET_MSDU_INFO_FOR_DATA_PACKET(
1381 prCurrentMsduInfo, /* MSDU_INFO ptr */
1383 ucPacketType, /* Packet Type */
1385 prCurrentMsduInfo->fgIs802_1x, /* Flag 802.1x */
1386 prCurrentMsduInfo->fgIs802_11, /* Flag 802.11 */
1389 PS_FORWARDING_TYPE_NON_PS, /* PS Forwarding Type */
1390 0 /* PS Session ID */
1393 //4 <4> Enqueue the packet
1394 QUEUE_INSERT_TAIL(prTxQue, (P_QUE_ENTRY_T)prCurrentMsduInfo);
1398 if (++prQM->u4PktCount == QM_TEST_TRIGGER_TX_COUNT){
1399 prQM->u4PktCount = 0;
1400 qmTestCases(prAdapter);
1405 DBGLOG(QM, LOUD, ("Current queue length = %u\n", prTxQue->u4NumElem));
1406 }while(prNextMsduInfo);
1408 if( QUEUE_IS_NOT_EMPTY(&rNotEnqueuedQue) ) {
1409 QM_TX_SET_NEXT_MSDU_INFO((P_MSDU_INFO_T)QUEUE_GET_TAIL(&rNotEnqueuedQue), NULL);
1410 prMsduInfoReleaseList = (P_MSDU_INFO_T)QUEUE_GET_HEAD(&rNotEnqueuedQue);
1414 return prMsduInfoReleaseList;
1417 /*----------------------------------------------------------------------------*/
1419 * \brief Determine the STA_REC index for a packet
1421 * \param[in] prMsduInfo Pointer to the packet
1425 /*----------------------------------------------------------------------------*/
1427 qmDetermineStaRecIndex(
1428 IN P_ADAPTER_T prAdapter,
1429 IN P_MSDU_INFO_T prMsduInfo
1434 P_STA_RECORD_T prTempStaRec;
1435 //P_QUE_MGT_T prQM = &prAdapter->rQM;
1437 prTempStaRec = NULL;
1442 if (IS_BMCAST_MAC_ADDR(prMsduInfo->aucEthDestAddr)){
1443 /* For intrastructure mode and P2P (playing as a GC), BMCAST frames shall be sent to the AP.
1444 * FW shall take care of this. The host driver is not able to distinguish these cases. */
1445 prMsduInfo->ucStaRecIndex = STA_REC_INDEX_BMCAST;
1446 DBGLOG(QM, LOUD, ("TX with DA = BMCAST\n"));
1451 //4 <2> Check if an AP STA is present
1452 for (i = 0; i < CFG_NUM_OF_STA_RECORD; i++){
1453 prTempStaRec = &(prAdapter->arStaRec[i]);
1455 if((prTempStaRec->ucNetTypeIndex == prMsduInfo->ucNetworkType)
1456 && (prTempStaRec->fgIsAp)
1457 && (prTempStaRec->fgIsValid)){
1458 prMsduInfo->ucStaRecIndex = prTempStaRec->ucIndex;
1466 //4 <3> Not BMCAST, No AP --> Compare DA (i.e., to see whether this is a unicast frame to a client)
1467 for (i = 0; i < CFG_NUM_OF_STA_RECORD; i++){
1468 prTempStaRec = &(prAdapter->arStaRec[i]);
1469 if (prTempStaRec->fgIsValid){
1470 if (EQUAL_MAC_ADDR(prTempStaRec->aucMacAddr, prMsduInfo->aucEthDestAddr)){
1471 prMsduInfo->ucStaRecIndex = prTempStaRec->ucIndex;
1478 //4 <4> No STA found, Not BMCAST --> Indicate NOT_FOUND to FW
1479 prMsduInfo->ucStaRecIndex = STA_REC_INDEX_NOT_FOUND;
1480 DBGLOG(QM, LOUD, ("QM: TX with STA_REC_INDEX_NOT_FOUND\n"));
1483 #if (QM_TEST_MODE && QM_TEST_FAIR_FORWARDING)
1484 prMsduInfo->ucStaRecIndex = (UINT_8)prQM->u4CurrentStaRecIndexToEnqueue;
1488 /*----------------------------------------------------------------------------*/
1490 * \brief Dequeue TX packets from a STA_REC for a particular TC
1492 * \param[out] prQue The queue to put the dequeued packets
1493 * \param[in] ucTC The TC index (TC0_INDEX to TC5_INDEX)
1494 * \param[in] ucMaxNum The maximum amount of dequeued packets
1498 /*----------------------------------------------------------------------------*/
1500 qmDequeueTxPacketsFromPerStaQueues(
1501 IN P_ADAPTER_T prAdapter,
1504 IN UINT_8 ucCurrentQuota,
1505 IN UINT_8 ucTotalQuota
1509 #if QM_FORWARDING_FAIRNESS
1510 UINT_32 i; /* Loop for */
1512 PUINT_32 pu4HeadStaRecIndex; /* The Head STA index */
1513 PUINT_32 pu4HeadStaRecForwardCount; /* The total forwarded packets for the head STA */
1515 P_STA_RECORD_T prStaRec; /* The current focused STA */
1516 P_BSS_INFO_T prBssInfo; /* The Bss for current focused STA */
1517 P_QUE_T prCurrQueue; /* The current TX queue to dequeue */
1518 P_MSDU_INFO_T prDequeuedPkt; /* The dequeued packet */
1520 UINT_32 u4ForwardCount; /* To remember the total forwarded packets for a STA */
1521 UINT_32 u4MaxForwardCount; /* The maximum number of packets a STA can forward */
1522 UINT_32 u4Resource; /* The TX resource amount */
1524 BOOLEAN fgChangeHeadSta; /* Whether a new head STA shall be determined at the end of the function */
1525 P_QUE_MGT_T prQM = &prAdapter->rQM;
1527 PUINT_8 pucFreeQuota;
1529 DBGLOG(QM, LOUD, ("Enter qmDequeueTxPacketsFromPerStaQueues (TC = %u)\n", ucTC));
1531 ASSERT(ucTC == TC0_INDEX || ucTC == TC1_INDEX ||
1532 ucTC == TC2_INDEX || ucTC == TC3_INDEX ||
1536 if(!ucCurrentQuota){
1537 DBGLOG(TX, LOUD, ("@@@@@ TC = %u ucCurrentQuota = %u @@@@@\n",
1538 ucTC, ucCurrentQuota));
1542 u4Resource = ucCurrentQuota;
1544 //4 <1> Determine the head STA
1545 /* The head STA shall be an active STA */
1547 pu4HeadStaRecIndex = &(prQM->au4HeadStaRecIndex[ucTC]);
1548 pu4HeadStaRecForwardCount = &(prQM->au4ForwardCount[ucTC]);
1550 DBGLOG(QM, LOUD, ("(Fairness) TID = %u Init Head STA = %u Resource = %u\n",
1551 ucTC, *pu4HeadStaRecIndex, u4Resource));
1554 /* From STA[x] to STA[x+1] to STA[x+2] to ... to STA[x] */
1555 for (i=0; i < CFG_NUM_OF_STA_RECORD + 1; i++){
1556 prStaRec = &prAdapter->arStaRec[(*pu4HeadStaRecIndex)];
1559 /* Only Data frame (1x was not included) will be queued in */
1560 if (prStaRec->fgIsValid){
1562 prBssInfo = &(prAdapter->rWifiVar.arBssInfo[prStaRec->ucNetTypeIndex]);
1564 ASSERT(prBssInfo->ucNetTypeIndex == prStaRec->ucNetTypeIndex);
1566 /* Determine how many packets the head STA is allowed to send in a round */
1568 QM_DBG_CNT_INC(prQM, QM_DBG_CNT_25);
1569 u4MaxForwardCount = ucTotalQuota;
1570 #if CFG_ENABLE_WIFI_DIRECT
1572 pucFreeQuota = NULL;
1573 if(prStaRec->fgIsInPS && (ucTC!=TC4_INDEX)) {
1574 // TODO: Change the threshold in coorperation with the PS forwarding mechanism
1575 // u4MaxForwardCount = ucTotalQuota;
1576 /* Per STA flow control when STA in PS mode */
1577 /* The PHASE 1: only update from ucFreeQuota (now) */
1578 /* XXX The PHASE 2: Decide by ucFreeQuota and ucBmpDeliveryAC (per queue ) aucFreeQuotaPerQueue[] */
1579 /* NOTE: other method to set u4Resource */
1581 if(prStaRec->fgIsQoS && prStaRec->fgIsUapsdSupported
1582 /* && prAdapter->rWifiVar.fgSupportQoS
1583 && prAdapter->rWifiVar.fgSupportUAPSD*/) {
1585 if( prStaRec->ucBmpTriggerAC & BIT(ucTC)) {
1586 u4MaxForwardCount = prStaRec->ucFreeQuotaForDelivery;
1587 pucFreeQuota = &prStaRec->ucFreeQuotaForDelivery;
1590 u4MaxForwardCount = prStaRec->ucFreeQuotaForNonDelivery;
1591 pucFreeQuota = &prStaRec->ucFreeQuotaForNonDelivery;
1596 ASSERT(prStaRec->ucFreeQuotaForDelivery == 0);
1597 u4MaxForwardCount = prStaRec->ucFreeQuotaForNonDelivery;
1598 pucFreeQuota = &prStaRec->ucFreeQuotaForNonDelivery;
1602 #endif /* CFG_ENABLE_WIFI_DIRECT */
1604 #if CFG_ENABLE_WIFI_DIRECT
1605 if(prBssInfo->fgIsNetAbsent && (ucTC!=TC4_INDEX)) {
1606 if(u4MaxForwardCount > prBssInfo->ucBssFreeQuota) {
1607 u4MaxForwardCount = prBssInfo->ucBssFreeQuota;
1611 #endif /* CFG_ENABLE_WIFI_DIRECT */
1613 /* Determine whether the head STA can continue to forward packets in this round */
1614 if((*pu4HeadStaRecForwardCount) < u4MaxForwardCount){
1618 } /* prStaRec->fgIsValid */
1620 /* The current Head STA has been deactivated, so search for a new head STA */
1623 (*pu4HeadStaRecIndex) ++;
1624 (*pu4HeadStaRecIndex) %= CFG_NUM_OF_STA_RECORD;
1626 /* Reset the forwarding count before searching (since this is for a new selected STA) */
1627 (*pu4HeadStaRecForwardCount) = 0;
1629 } /* i < CFG_NUM_OF_STA_RECORD + 1 */
1631 /* All STA_RECs are inactive, so exit */
1633 /* Under concurrent, it is possible that there is no candidcated STA.*/
1634 //DBGLOG(TX, EVENT, ("All STA_RECs are inactive\n"));
1638 DBGLOG(QM, LOUD, ("(Fairness) TID = %u Round Head STA = %lu\n",
1639 ucTC, *pu4HeadStaRecIndex));
1641 //4 <2> Dequeue packets from the head STA
1643 prCurrQueue = &prStaRec->arTxQueue[ucTC];
1644 prDequeuedPkt = NULL;
1645 fgChangeHeadSta = FALSE;
1650 #if QM_DEBUG_COUNTER
1652 if(ucTC <= TC4_INDEX) {
1653 if(QUEUE_IS_EMPTY(prCurrQueue)) {
1654 QM_DBG_CNT_INC(prQM, ucTC);
1655 /* QM_DBG_CNT_00 */ /* QM_DBG_CNT_01 */ /* QM_DBG_CNT_02 */ /* QM_DBG_CNT_03 */ /* QM_DBG_CNT_04 */
1657 if(u4Resource == 0) {
1658 QM_DBG_CNT_INC(prQM, ucTC + 5);
1659 /* QM_DBG_CNT_05 */ /* QM_DBG_CNT_06 */ /* QM_DBG_CNT_07 */ /* QM_DBG_CNT_08 */ /* QM_DBG_CNT_09 */
1661 if(((*pu4HeadStaRecForwardCount) >= u4MaxForwardCount)) {
1662 QM_DBG_CNT_INC(prQM, ucTC + 10);
1663 /* QM_DBG_CNT_10 */ /* QM_DBG_CNT_11 */ /* QM_DBG_CNT_12 */ /* QM_DBG_CNT_13 */ /* QM_DBG_CNT_14 */
1669 /* Three cases to break: (1) No resource (2) No packets (3) Fairness */
1670 if (QUEUE_IS_EMPTY(prCurrQueue) || ((*pu4HeadStaRecForwardCount) >= u4MaxForwardCount)){
1671 fgChangeHeadSta = TRUE;
1674 else if (u4Resource == 0){
1679 QUEUE_REMOVE_HEAD(prCurrQueue, prDequeuedPkt, P_MSDU_INFO_T);
1681 LOG_FUNC("Deq0 TC %d queued %u net %u mac len %u len %u Type %u 1x %u 11 %u\n",
1682 prDequeuedPkt->ucTC,
1683 prCurrQueue->u4NumElem,
1684 prDequeuedPkt->ucNetworkType,
1685 prDequeuedPkt->ucMacHeaderLength,
1686 prDequeuedPkt->u2FrameLength,
1687 prDequeuedPkt->ucPacketType,
1688 prDequeuedPkt->fgIs802_1x,
1689 prDequeuedPkt->fgIs802_11 );
1691 LOG_FUNC("Dest Mac: " MACSTR "\n",
1692 MAC2STR(prDequeuedPkt->aucEthDestAddr));
1696 struct sk_buff *prSkb = (struct sk_buff *) prDequeuedPkt->prPacket;
1697 dumpMemory8((PUINT_8)prSkb->data,prSkb->len);
1703 ASSERT(prDequeuedPkt->ucTC == ucTC);
1705 if(!QUEUE_IS_EMPTY(prCurrQueue)) {
1706 /* XXX: check all queues for STA */
1707 prDequeuedPkt->ucPsForwardingType = PS_FORWARDING_MORE_DATA_ENABLED;
1710 QUEUE_INSERT_TAIL(prQue,(P_QUE_ENTRY_T)prDequeuedPkt);
1712 (*pu4HeadStaRecForwardCount) ++;
1715 #if CFG_ENABLE_WIFI_DIRECT
1716 /* XXX The PHASE 2: decrease from aucFreeQuotaPerQueue[] */
1717 if(prStaRec->fgIsInPS && (ucTC!=TC4_INDEX)) {
1718 ASSERT(pucFreeQuota);
1719 ASSERT(*pucFreeQuota>0);
1720 if(*pucFreeQuota>0) {
1721 *pucFreeQuota = *pucFreeQuota - 1;
1724 #endif /* CFG_ENABLE_WIFI_DIRECT */
1726 #if CFG_ENABLE_WIFI_DIRECT
1727 if(prBssInfo->fgIsNetAbsent && (ucTC!=TC4_INDEX)) {
1728 if(prBssInfo->ucBssFreeQuota>0) {
1729 prBssInfo->ucBssFreeQuota--;
1732 #endif /* CFG_ENABLE_WIFI_DIRECT */
1737 if (*pu4HeadStaRecForwardCount){
1738 DBGLOG(QM, LOUD, ("TC = %u Round Head STA = %lu, u4HeadStaRecForwardCount = %lu\n", ucTC, *pu4HeadStaRecIndex, (*pu4HeadStaRecForwardCount)));
1741 #if QM_BURST_END_INFO_ENABLED
1742 /* Let FW know which packet is the last one dequeued from the STA */
1744 prDequeuedPkt->fgIsBurstEnd = TRUE;
1749 //4 <3> Dequeue from the other STAs if there is residual TX resource
1751 /* Check all of the STAs to continue forwarding packets (including the head STA) */
1752 for (i= 0; i< CFG_NUM_OF_STA_RECORD; i++){
1753 /* Break in case no reasource is available */
1754 if (u4Resource == 0){
1758 /* The current head STA will be examined when i = CFG_NUM_OF_STA_RECORD-1 */
1759 prStaRec = &prAdapter->arStaRec[((*pu4HeadStaRecIndex) + i + 1) % CFG_NUM_OF_STA_RECORD];
1762 if (prStaRec->fgIsValid) {
1764 prBssInfo = &(prAdapter->rWifiVar.arBssInfo[prStaRec->ucNetTypeIndex]);
1765 ASSERT(prBssInfo->ucNetTypeIndex == prStaRec->ucNetTypeIndex);
1767 DBGLOG(QM, LOUD, ("(Fairness) TID = %u Sharing STA = %u Resource = %lu\n",
1768 ucTC, prStaRec->ucIndex, u4Resource));
1770 prCurrQueue = &prStaRec->arTxQueue[ucTC];
1772 u4MaxForwardCount = ucTotalQuota;
1774 #if CFG_ENABLE_WIFI_DIRECT
1775 pucFreeQuota = NULL;
1776 if(prStaRec->fgIsInPS && (ucTC!=TC4_INDEX)) {
1777 // TODO: Change the threshold in coorperation with the PS forwarding mechanism
1778 // u4MaxForwardCount = ucTotalQuota;
1779 /* Per STA flow control when STA in PS mode */
1780 /* The PHASE 1: only update from ucFreeQuota (now) */
1781 /* XXX The PHASE 2: Decide by ucFreeQuota and ucBmpDeliveryAC (per queue ) aucFreeQuotaPerQueue[] */
1782 /* NOTE: other method to set u4Resource */
1783 if(prStaRec->fgIsQoS && prStaRec->fgIsUapsdSupported
1784 /* && prAdapter->rWifiVar.fgSupportQoS
1785 && prAdapter->rWifiVar.fgSupportUAPSD*/) {
1787 if( prStaRec->ucBmpTriggerAC & BIT(ucTC)) {
1788 u4MaxForwardCount = prStaRec->ucFreeQuotaForDelivery;
1789 pucFreeQuota = &prStaRec->ucFreeQuotaForDelivery;
1792 u4MaxForwardCount = prStaRec->ucFreeQuotaForNonDelivery;
1793 pucFreeQuota = &prStaRec->ucFreeQuotaForNonDelivery;
1798 ASSERT(prStaRec->ucFreeQuotaForDelivery == 0);
1799 u4MaxForwardCount = prStaRec->ucFreeQuotaForNonDelivery;
1800 pucFreeQuota = &prStaRec->ucFreeQuotaForNonDelivery;
1804 #endif /* CFG_ENABLE_WIFI_DIRECT */
1805 #if CFG_ENABLE_WIFI_DIRECT
1806 if(prBssInfo->fgIsNetAbsent && (ucTC!=TC4_INDEX)) {
1807 if(u4MaxForwardCount > prBssInfo->ucBssFreeQuota) {
1808 u4MaxForwardCount = prBssInfo->ucBssFreeQuota;
1812 #endif /* CFG_ENABLE_WIFI_DIRECT */
1813 } /* prStaRec->fgIsValid */
1816 /* Invalid STA, so check the next STA */
1821 /* Three cases to break: (1) No resource (2) No packets (3) Fairness */
1822 if ((u4Resource == 0) || QUEUE_IS_EMPTY(prCurrQueue) || (u4ForwardCount >= u4MaxForwardCount)){
1827 QUEUE_REMOVE_HEAD(prCurrQueue, prDequeuedPkt, P_MSDU_INFO_T);
1830 DBGLOG(QM, LOUD, ("Deq0 TC %d queued %u net %u mac len %u len %u Type %u 1x %u 11 %u\n",
1831 prDequeuedPkt->ucTC,
1832 prCurrQueue->u4NumElem,
1833 prDequeuedPkt->ucNetworkType,
1834 prDequeuedPkt->ucMacHeaderLength,
1835 prDequeuedPkt->u2FrameLength,
1836 prDequeuedPkt->ucPacketType,
1837 prDequeuedPkt->fgIs802_1x,
1838 prDequeuedPkt->fgIs802_11 ));
1840 DBGLOG(QM, LOUD,("Dest Mac: " MACSTR "\n",
1841 MAC2STR(prDequeuedPkt->aucEthDestAddr)));
1845 struct sk_buff *prSkb = (struct sk_buff *) prDequeuedPkt->prPacket;
1846 dumpMemory8((PUINT_8)prSkb->data,prSkb->len);
1853 ASSERT(prDequeuedPkt->ucTC == ucTC);
1855 if(!QUEUE_IS_EMPTY(prCurrQueue)) {
1856 prDequeuedPkt->ucPsForwardingType = PS_FORWARDING_MORE_DATA_ENABLED;
1859 QUEUE_INSERT_TAIL(prQue,(P_QUE_ENTRY_T)prDequeuedPkt);
1863 #if CFG_ENABLE_WIFI_DIRECT
1864 /* XXX The PHASE 2: decrease from aucFreeQuotaPerQueue[] */
1865 if(prStaRec->fgIsInPS && (ucTC!=TC4_INDEX)) {
1866 ASSERT(pucFreeQuota);
1867 ASSERT(*pucFreeQuota>0);
1868 if(*pucFreeQuota>0) {
1869 *pucFreeQuota = *pucFreeQuota - 1;
1872 #endif /* CFG_ENABLE_WIFI_DIRECT */
1875 #if CFG_ENABLE_WIFI_DIRECT
1876 ASSERT(prBssInfo->ucNetTypeIndex == prStaRec->ucNetTypeIndex);
1877 if(prBssInfo->fgIsNetAbsent && (ucTC!=TC4_INDEX)) {
1878 if(prBssInfo->ucBssFreeQuota>0) {
1879 prBssInfo->ucBssFreeQuota--;
1882 #endif /* CFG_ENABLE_WIFI_DIRECT */
1887 #if QM_BURST_END_INFO_ENABLED
1888 /* Let FW know which packet is the last one dequeued from the STA */
1889 if (u4ForwardCount){
1890 prDequeuedPkt->fgIsBurstEnd = TRUE;
1896 if (fgChangeHeadSta){
1897 (*pu4HeadStaRecIndex) ++;
1898 (*pu4HeadStaRecIndex) %= CFG_NUM_OF_STA_RECORD;
1899 (*pu4HeadStaRecForwardCount) = 0;
1900 DBGLOG(QM, LOUD, ("(Fairness) TID = %u Scheduled Head STA = %lu Left Resource = %lu\n",
1901 ucTC, (*pu4HeadStaRecIndex), u4Resource));
1905 /***************************************************************************************/
1907 UINT_8 ucStaRecIndex;
1908 P_STA_RECORD_T prStaRec;
1909 P_QUE_T prCurrQueue;
1911 P_MSDU_INFO_T prDequeuedPkt;
1913 DBGLOG(QM, LOUD, ("Enter qmDequeueTxPacketsFromPerStaQueues (TC = %u)\n", ucTC));
1915 if (ucCurrentQuota == 0){
1919 //4 <1> Determine the queue index and the head STA
1922 ucStaRecIndex = 0; /* TODO: Get the current head STA */
1923 prStaRec = QM_GET_STA_REC_PTR_FROM_INDEX(prAdapter, ucStaRecIndex);
1926 if(prStaRec == NULL) {
1930 /* The queue to pull out packets */
1931 ASSERT(ucTC == TC0_INDEX || ucTC == TC1_INDEX ||
1932 ucTC == TC2_INDEX || ucTC == TC3_INDEX ||
1935 prCurrQueue = &prStaRec->arTxQueue[ucTC];
1937 ucPktCount = ucCurrentQuota;
1938 prDequeuedPkt = NULL;
1940 //4 <2> Dequeue packets for the head STA
1942 if (!(prStaRec->fgIsValid) || ucPktCount ==0 || QUEUE_IS_EMPTY(prCurrQueue)){
1948 QUEUE_REMOVE_HEAD(prCurrQueue, prDequeuedPkt, P_MSDU_INFO_T);
1949 //DbgPrint("QM: Remove Queue Head, TC= %d\n", prDequeuedPkt->ucTC);
1950 ASSERT(prDequeuedPkt->ucTC == ucTC);
1952 QUEUE_INSERT_TAIL(prQue,(P_QUE_ENTRY_T)prDequeuedPkt);
1957 //DbgPrint("QM: Remaining number of queued packets = %d\n", prCurrQueue->u4NumElem);
1959 #if QM_BURST_END_INFO_ENABLED
1961 prDequeuedPkt->fgIsBurstEnd = TRUE;
1966 //4 <3> Update scheduling info
1969 //4 <4> Utilize the remainaing TX opportunities for non-head STAs
1975 /*----------------------------------------------------------------------------*/
1977 * \brief Dequeue TX packets from a per-Type-based Queue for a particular TC
1979 * \param[out] prQue The queue to put the dequeued packets
1980 * \param[in] ucTC The TC index (Shall always be TC5_INDEX)
1981 * \param[in] ucMaxNum The maximum amount of dequeued packets
1985 /*----------------------------------------------------------------------------*/
1987 qmDequeueTxPacketsFromPerTypeQueues(
1988 IN P_ADAPTER_T prAdapter,
1994 //UINT_8 ucQueIndex;
1995 //UINT_8 ucStaRecIndex;
1996 P_BSS_INFO_T prBssInfo;
1997 P_BSS_INFO_T parBssInfo;
1998 P_QUE_T prCurrQueue;
2000 P_MSDU_INFO_T prDequeuedPkt;
2001 P_MSDU_INFO_T prBurstEndPkt;
2006 DBGLOG(QM, LOUD, ("Enter qmDequeueTxPacketsFromPerTypeQueues (TC = %d, Max = %d)\n", ucTC, ucMaxNum));
2008 /* TC5: Broadcast/Multicast data packets */
2009 ASSERT(ucTC == TC5_INDEX);
2015 prQM = &prAdapter->rQM;
2016 //4 <1> Determine the queue
2018 prCurrQueue = &prQM->arTxQueue[TX_QUEUE_INDEX_BMCAST];
2019 ucPktCount = ucMaxNum;
2020 prDequeuedPkt = NULL;
2021 prBurstEndPkt = NULL;
2023 parBssInfo = prAdapter->rWifiVar.arBssInfo;
2025 QUEUE_INITIALIZE(&rMergeQue);
2026 prMergeQue = &rMergeQue;
2028 //4 <2> Dequeue packets
2030 if(ucPktCount ==0 || QUEUE_IS_EMPTY(prCurrQueue)){
2034 QUEUE_REMOVE_HEAD(prCurrQueue, prDequeuedPkt, P_MSDU_INFO_T);
2035 ASSERT(prDequeuedPkt->ucTC == ucTC);
2037 ASSERT(prDequeuedPkt->ucNetworkType < NETWORK_TYPE_INDEX_NUM);
2039 prBssInfo = &parBssInfo[prDequeuedPkt->ucNetworkType];
2041 if(IS_BSS_ACTIVE(prBssInfo)) {
2042 if( !prBssInfo->fgIsNetAbsent){
2043 QUEUE_INSERT_TAIL(prQue,(P_QUE_ENTRY_T)prDequeuedPkt);
2044 prBurstEndPkt = prDequeuedPkt;
2046 QM_DBG_CNT_INC(prQM, QM_DBG_CNT_26);
2048 LOG_FUNC("DeqType TC %d queued %u net %u mac len %u len %u Type %u 1x %u 11 %u\n",
2049 prDequeuedPkt->ucTC,
2050 prCurrQueue->u4NumElem,
2051 prDequeuedPkt->ucNetworkType,
2052 prDequeuedPkt->ucMacHeaderLength,
2053 prDequeuedPkt->u2FrameLength,
2054 prDequeuedPkt->ucPacketType,
2055 prDequeuedPkt->fgIs802_1x,
2056 prDequeuedPkt->fgIs802_11 );
2058 LOG_FUNC("Dest Mac: " MACSTR "\n",
2059 MAC2STR(prDequeuedPkt->aucEthDestAddr));
2063 struct sk_buff *prSkb = (struct sk_buff *) prDequeuedPkt->prPacket;
2064 dumpMemory8((PUINT_8)prSkb->data,prSkb->len);
2071 QUEUE_INSERT_TAIL(prMergeQue,(P_QUE_ENTRY_T)prDequeuedPkt);
2075 QM_TX_SET_NEXT_MSDU_INFO(prDequeuedPkt, NULL);
2076 wlanProcessQueuedMsduInfo(prAdapter,prDequeuedPkt);
2081 if(QUEUE_IS_NOT_EMPTY(prMergeQue)) {
2082 QUEUE_CONCATENATE_QUEUES(prMergeQue, prCurrQueue);
2083 QUEUE_MOVE_ALL(prCurrQueue, prMergeQue);
2084 QM_TX_SET_NEXT_MSDU_INFO((P_MSDU_INFO_T)QUEUE_GET_TAIL(prCurrQueue), NULL);
2087 #if QM_BURST_END_INFO_ENABLED
2089 prBurstEndPkt->fgIsBurstEnd = TRUE;
2092 } /* qmDequeueTxPacketsFromPerTypeQueues */
2097 /*----------------------------------------------------------------------------*/
2099 * \brief Dequeue TX packets to send to HIF TX
2101 * \param[in] prTcqStatus Info about the maximum amount of dequeued packets
2103 * \return The list of dequeued TX packets
2105 /*----------------------------------------------------------------------------*/
2108 IN P_ADAPTER_T prAdapter,
2109 IN P_TX_TCQ_STATUS_T prTcqStatus
2114 P_MSDU_INFO_T prReturnedPacketListHead;
2117 DBGLOG(QM, LOUD, ("Enter qmDequeueTxPackets\n"));
2119 QUEUE_INITIALIZE(&rReturnedQue);
2121 prReturnedPacketListHead = NULL;
2123 /* TC0 to TC4: AC0~AC3, 802.1x (commands packets are not handled by QM) */
2124 for(i = TC4_INDEX; i >= TC0_INDEX; i--){
2125 DBGLOG(QM, LOUD, ("Dequeue packets from Per-STA queue[%u]\n", i));
2127 qmDequeueTxPacketsFromPerStaQueues(
2131 prTcqStatus->aucFreeBufferCount[i],
2132 prTcqStatus->aucMaxNumOfBuffer[i]
2135 /* The aggregate number of dequeued packets */
2136 DBGLOG(QM, LOUD, ("DQA)[%u](%lu)\n", i, rReturnedQue.u4NumElem));
2140 /* TC5 (BMCAST or STA-NOT-FOUND packets) */
2141 qmDequeueTxPacketsFromPerTypeQueues(
2145 prTcqStatus->aucFreeBufferCount[TC5_INDEX]
2148 DBGLOG(QM, LOUD, ("Current total number of dequeued packets = %u\n", rReturnedQue.u4NumElem));
2150 if (QUEUE_IS_NOT_EMPTY(&rReturnedQue)){
2151 prReturnedPacketListHead = (P_MSDU_INFO_T)QUEUE_GET_HEAD(&rReturnedQue);
2152 QM_TX_SET_NEXT_MSDU_INFO((P_MSDU_INFO_T)QUEUE_GET_TAIL(&rReturnedQue), NULL);
2155 return prReturnedPacketListHead;
2158 /*----------------------------------------------------------------------------*/
2160 * \brief Adjust the TC quotas according to traffic demands
2162 * \param[out] prTcqAdjust The resulting adjustment
2163 * \param[in] prTcqStatus Info about the current TC quotas and counters
2167 /*----------------------------------------------------------------------------*/
2170 IN P_ADAPTER_T prAdapter,
2171 OUT P_TX_TCQ_ADJUST_T prTcqAdjust,
2172 IN P_TX_TCQ_STATUS_T prTcqStatus
2175 #if QM_ADAPTIVE_TC_RESOURCE_CTRL
2177 P_QUE_MGT_T prQM = &prAdapter->rQM;
2179 /* Must initialize */
2180 for (i = 0; i < TC_NUM; i++){
2181 prTcqAdjust->acVariation[i]= 0;
2184 //4 <1> If TC resource is not just adjusted, exit directly
2185 if (!prQM->fgTcResourcePostAnnealing){
2189 //4 <2> Adjust TcqStatus according to the updated prQM->au4CurrentTcResource
2191 INT_32 i4TotalExtraQuota = 0;
2192 INT_32 ai4ExtraQuota[TC_NUM];
2193 BOOLEAN fgResourceRedistributed = TRUE;
2195 /* Obtain the free-to-distribute resource */
2196 for (i = 0; i < TC_NUM; i++){
2197 ai4ExtraQuota[i] = (INT_32)prTcqStatus->aucMaxNumOfBuffer[i] - (INT_32)prQM->au4CurrentTcResource[i];
2199 if (ai4ExtraQuota[i] > 0){ /* The resource shall be reallocated to other TCs */
2200 if (ai4ExtraQuota[i] > prTcqStatus->aucFreeBufferCount[i]){
2201 ai4ExtraQuota[i] = prTcqStatus->aucFreeBufferCount[i];
2202 fgResourceRedistributed = FALSE;
2205 i4TotalExtraQuota += ai4ExtraQuota[i];
2206 prTcqAdjust->acVariation[i] = (INT_8)(-ai4ExtraQuota[i]);
2210 /* Distribute quotas to TCs which need extra resource according to prQM->au4CurrentTcResource */
2211 for (i = 0; i < TC_NUM; i++){
2212 if (ai4ExtraQuota[i] < 0){
2213 if ((-ai4ExtraQuota[i]) > i4TotalExtraQuota){
2214 ai4ExtraQuota[i] = (-i4TotalExtraQuota);
2215 fgResourceRedistributed = FALSE;
2218 i4TotalExtraQuota += ai4ExtraQuota[i];
2219 prTcqAdjust->acVariation[i] = (INT_8)(-ai4ExtraQuota[i]);
2223 /* In case some TC is waiting for TX Done, continue to adjust TC quotas upon TX Done */
2224 prQM->fgTcResourcePostAnnealing = (!fgResourceRedistributed);
2226 #if QM_PRINT_TC_RESOURCE_CTRL
2227 DBGLOG(QM, LOUD, ("QM: Curr Quota [0]=%u [1]=%u [2]=%u [3]=%u [4]=%u [5]=%u\n",
2228 prTcqStatus->aucFreeBufferCount[0],
2229 prTcqStatus->aucFreeBufferCount[1],
2230 prTcqStatus->aucFreeBufferCount[2],
2231 prTcqStatus->aucFreeBufferCount[3],
2232 prTcqStatus->aucFreeBufferCount[4],
2233 prTcqStatus->aucFreeBufferCount[5]
2240 for (i = 0; i < TC_NUM; i++){
2241 prTcqAdjust->acVariation[i]= 0;
2247 #if QM_ADAPTIVE_TC_RESOURCE_CTRL
2248 /*----------------------------------------------------------------------------*/
2250 * \brief Update the average TX queue length for the TC resource control mechanism
2256 /*----------------------------------------------------------------------------*/
2258 qmUpdateAverageTxQueLen(
2259 IN P_ADAPTER_T prAdapter
2262 INT_32 u4CurrQueLen, i, k;
2263 P_STA_RECORD_T prStaRec;
2264 P_QUE_MGT_T prQM = &prAdapter->rQM;
2266 //4 <1> Update the queue lengths for TC0 to TC3 (skip TC4) and TC5 */
2267 for (i = 0; i < NUM_OF_PER_STA_TX_QUEUES - 1; i++){
2270 for (k = 0; k < CFG_NUM_OF_STA_RECORD; k++){
2271 prStaRec = &prAdapter->arStaRec[k];
2274 /* If the STA is activated, get the queue length */
2275 if (prStaRec->fgIsValid &&
2276 (!prAdapter->rWifiVar.arBssInfo[prStaRec->ucNetTypeIndex].fgIsNetAbsent)
2280 u4CurrQueLen += (prStaRec->arTxQueue[i].u4NumElem);
2284 if (prQM->au4AverageQueLen[i] == 0){
2285 prQM->au4AverageQueLen[i] = (u4CurrQueLen << QM_QUE_LEN_MOVING_AVE_FACTOR);
2288 prQM->au4AverageQueLen[i] -= (prQM->au4AverageQueLen[i] >> QM_QUE_LEN_MOVING_AVE_FACTOR);
2289 prQM->au4AverageQueLen[i] += (u4CurrQueLen);
2294 /* Update the queue length for TC5 (BMCAST) */
2295 u4CurrQueLen = prQM->arTxQueue[TX_QUEUE_INDEX_BMCAST].u4NumElem;
2297 if (prQM->au4AverageQueLen[TC_NUM-1] == 0){
2298 prQM->au4AverageQueLen[TC_NUM-1] = (u4CurrQueLen << QM_QUE_LEN_MOVING_AVE_FACTOR);
2301 prQM->au4AverageQueLen[TC_NUM-1] -= (prQM->au4AverageQueLen[TC_NUM-1] >> QM_QUE_LEN_MOVING_AVE_FACTOR);
2302 prQM->au4AverageQueLen[TC_NUM-1] += (u4CurrQueLen);
2306 //4 <2> Adjust TC resource assignment
2307 /* Check whether it is time to adjust the TC resource assignment */
2308 if (--prQM->u4TimeToAdjustTcResource == 0){
2309 /* The last assignment has not been completely applied */
2310 if (prQM->fgTcResourcePostAnnealing){
2311 /* Upon the next qmUpdateAverageTxQueLen function call, do this check again */
2312 prQM->u4TimeToAdjustTcResource = 1;
2315 /* The last assignment has been applied */
2317 prQM->u4TimeToAdjustTcResource = QM_INIT_TIME_TO_ADJUST_TC_RSC;
2318 qmReassignTcResource(prAdapter);
2323 #if QM_PRINT_TC_RESOURCE_CTRL
2324 for (i=0; i<TC_NUM; i++){
2325 if(QM_GET_TX_QUEUE_LEN(prAdapter, i) >= 100){
2326 DBGLOG(QM, LOUD, ("QM: QueLen [%ld %ld %ld %ld %ld %ld]\n",
2327 QM_GET_TX_QUEUE_LEN(prAdapter, 0),
2328 QM_GET_TX_QUEUE_LEN(prAdapter, 1),
2329 QM_GET_TX_QUEUE_LEN(prAdapter, 2),
2330 QM_GET_TX_QUEUE_LEN(prAdapter, 3),
2331 QM_GET_TX_QUEUE_LEN(prAdapter, 4),
2332 QM_GET_TX_QUEUE_LEN(prAdapter, 5)
2343 /*----------------------------------------------------------------------------*/
2345 * \brief Assign TX resource for each TC according to TX queue length and current assignment
2351 /*----------------------------------------------------------------------------*/
2353 qmReassignTcResource(
2354 IN P_ADAPTER_T prAdapter
2357 INT_32 i4TotalResourceDemand = 0;
2358 UINT_32 u4ResidualResource = 0;
2360 INT_32 ai4PerTcResourceDemand[TC_NUM];
2361 UINT_32 u4ShareCount = 0;
2362 UINT_32 u4Share = 0 ;
2363 P_QUE_MGT_T prQM = &prAdapter->rQM;
2365 /* Note: After the new assignment is obtained, set prQM->fgTcResourcePostAnnealing to TRUE to
2366 * start the TC-quota adjusting procedure, which will be invoked upon every TX Done
2369 //4 <1> Determine the demands
2370 /* Determine the amount of extra resource to fulfill all of the demands */
2371 for (i=0; i<TC_NUM; i++){
2372 /* Skip TC4, which is not adjustable */
2373 if (i == TC4_INDEX) {
2377 /* Define: extra_demand = que_length + min_reserved_quota - current_quota */
2378 ai4PerTcResourceDemand[i] =
2379 ((UINT_32)(QM_GET_TX_QUEUE_LEN(prAdapter, i)) + prQM->au4MinReservedTcResource[i] - prQM->au4CurrentTcResource[i]);
2381 /* If there are queued packets, allocate extra resource for the TC (for TCP consideration) */
2382 if (QM_GET_TX_QUEUE_LEN(prAdapter, i)){
2383 ai4PerTcResourceDemand[i] += QM_EXTRA_RESERVED_RESOURCE_WHEN_BUSY;
2386 i4TotalResourceDemand += ai4PerTcResourceDemand[i];
2389 //4 <2> Case 1: Demand <= Total Resource
2390 if (i4TotalResourceDemand <= 0){
2391 //4 <2.1> Satisfy every TC
2392 for (i = 0; i < TC_NUM; i++){
2393 /* Skip TC4 (not adjustable) */
2394 if (i == TC4_INDEX) {
2398 prQM->au4CurrentTcResource[i] += ai4PerTcResourceDemand[i];
2401 //4 <2.2> Share the residual resource evenly
2402 u4ShareCount= (TC_NUM - 1); /* excluding TC4 */
2403 u4ResidualResource = (UINT_32)(-i4TotalResourceDemand);
2404 u4Share = (u4ResidualResource/u4ShareCount);
2406 for (i=0; i<TC_NUM; i++){
2407 /* Skip TC4 (not adjustable) */
2408 if (i == TC4_INDEX) {
2412 prQM->au4CurrentTcResource[i] += u4Share;
2414 /* Every TC is fully satisfied */
2415 ai4PerTcResourceDemand[i] = 0;
2417 /* The left resource will be allocated to TC3 */
2418 u4ResidualResource -= u4Share;
2421 //4 <2.3> Allocate the left resource to TC3 (VO)
2422 prQM->au4CurrentTcResource[TC3_INDEX] += (u4ResidualResource);
2426 //4 <3> Case 2: Demand > Total Resource --> Guarantee a minimum amount of resource for each TC
2428 u4ResidualResource = QM_INITIAL_RESIDUAL_TC_RESOURCE;
2430 //4 <3.1> Allocated resouce amount = minimum of (guaranteed, total demand)
2431 for (i=0; i<TC_NUM; i++){
2432 /* Skip TC4 (not adjustable) */
2433 if (i == TC4_INDEX) {
2437 /* The demand can be fulfilled with the guaranteed resource amount */
2438 if (prQM->au4CurrentTcResource[i] + ai4PerTcResourceDemand[i] < prQM->au4GuaranteedTcResource[i]){
2439 prQM->au4CurrentTcResource[i] += ai4PerTcResourceDemand[i];
2440 u4ResidualResource += (prQM->au4GuaranteedTcResource[i] - prQM->au4CurrentTcResource[i]);
2441 ai4PerTcResourceDemand[i] = 0;
2444 /* The demand can not be fulfilled with the guaranteed resource amount */
2446 ai4PerTcResourceDemand[i] -= (prQM->au4GuaranteedTcResource[i] - prQM->au4CurrentTcResource[i]);
2447 prQM->au4CurrentTcResource[i] = prQM->au4GuaranteedTcResource[i];
2452 //4 <3.2> Allocate the residual resource
2454 /* If there is no resource left, exit directly */
2455 if (u4ResidualResource == 0){
2459 /* This shall not happen */
2460 if (u4ShareCount == 0){
2461 prQM->au4CurrentTcResource[TC1_INDEX] += u4ResidualResource;
2462 DBGLOG(QM, ERROR, ("QM: (Error) u4ShareCount = 0\n"));
2466 /* Share the residual resource evenly */
2467 u4Share = (u4ResidualResource / u4ShareCount);
2469 for (i=0; i<TC_NUM; i++){
2470 /* Skip TC4 (not adjustable) */
2471 if (i == TC4_INDEX) {
2475 if (ai4PerTcResourceDemand[i]){
2476 if (ai4PerTcResourceDemand[i] - u4Share){
2477 prQM->au4CurrentTcResource[i] += u4Share;
2478 u4ResidualResource -= u4Share;
2479 ai4PerTcResourceDemand[i] -= u4Share;
2482 prQM->au4CurrentTcResource[i] += ai4PerTcResourceDemand[i];
2483 u4ResidualResource -= ai4PerTcResourceDemand[i];
2484 ai4PerTcResourceDemand[i] = 0;
2490 /* By priority, allocate the left resource that is not divisible by u4Share */
2491 if (u4ResidualResource == 0){
2495 if (ai4PerTcResourceDemand[TC3_INDEX]){ /* VO */
2496 prQM->au4CurrentTcResource[TC3_INDEX]++;
2497 if (--u4ResidualResource == 0) {
2502 if (ai4PerTcResourceDemand[TC2_INDEX]){ /* VI */
2503 prQM->au4CurrentTcResource[TC2_INDEX]++;
2504 if (--u4ResidualResource == 0) {
2509 if (ai4PerTcResourceDemand[TC5_INDEX]){ /* BMCAST */
2510 prQM->au4CurrentTcResource[TC5_INDEX]++;
2511 if (--u4ResidualResource == 0) {
2516 if (ai4PerTcResourceDemand[TC1_INDEX]){ /* BE */
2517 prQM->au4CurrentTcResource[TC1_INDEX]++;
2518 if (--u4ResidualResource == 0) {
2523 if (ai4PerTcResourceDemand[TC0_INDEX]){ /* BK */
2524 prQM->au4CurrentTcResource[TC0_INDEX]++;
2525 if (--u4ResidualResource == 0) {
2530 /* Allocate the left resource */
2531 prQM->au4CurrentTcResource[TC3_INDEX] += u4ResidualResource;
2536 prQM->fgTcResourcePostAnnealing = TRUE;
2538 #if QM_PRINT_TC_RESOURCE_CTRL
2540 DBGLOG(QM, LOUD, ("QM: TC Rsc %ld %ld %ld %ld %ld %ld\n",
2541 prQM->au4CurrentTcResource[0],
2542 prQM->au4CurrentTcResource[1],
2543 prQM->au4CurrentTcResource[2],
2544 prQM->au4CurrentTcResource[3],
2545 prQM->au4CurrentTcResource[4],
2546 prQM->au4CurrentTcResource[5]
2555 /*----------------------------------------------------------------------------*/
2556 /* RX-Related Queue Management */
2557 /*----------------------------------------------------------------------------*/
2558 /*----------------------------------------------------------------------------*/
2560 * \brief Init Queue Managment for RX
2566 /*----------------------------------------------------------------------------*/
2569 IN P_ADAPTER_T prAdapter
2572 //DbgPrint("QM: Enter qmInitRxQueues()\n");
2576 /*----------------------------------------------------------------------------*/
2578 * \brief Handle RX packets (buffer reordering)
2580 * \param[in] prSwRfbListHead The list of RX packets
2582 * \return The list of packets which are not buffered for reordering
2584 /*----------------------------------------------------------------------------*/
2587 IN P_ADAPTER_T prAdapter,
2588 IN P_SW_RFB_T prSwRfbListHead
2592 #if CFG_RX_REORDERING_ENABLED
2594 P_SW_RFB_T prCurrSwRfb;
2595 P_SW_RFB_T prNextSwRfb;
2596 P_HIF_RX_HEADER_T prHifRxHdr;
2598 PUINT_8 pucEthDestAddr;
2600 //DbgPrint("QM: Enter qmHandleRxPackets()\n");
2602 DEBUGFUNC("qmHandleRxPackets");
2604 ASSERT(prSwRfbListHead);
2606 QUEUE_INITIALIZE(&rReturnedQue);
2607 prNextSwRfb = prSwRfbListHead;
2610 prCurrSwRfb = prNextSwRfb;
2611 prNextSwRfb = QM_RX_GET_NEXT_SW_RFB(prCurrSwRfb);
2613 prHifRxHdr = prCurrSwRfb->prHifRxHdr; // TODO: (Tehuang) Use macro to obtain the pointer
2615 /* TODO: (Tehuang) Check if relaying */
2616 prCurrSwRfb->eDst = RX_PKT_DESTINATION_HOST;
2618 /* Decide the Destination */
2619 #if CFG_RX_PKTS_DUMP
2620 if (prAdapter->rRxCtrl.u4RxPktsDumpTypeMask & BIT(HIF_RX_PKT_TYPE_DATA)) {
2621 DBGLOG(SW4, INFO, ("QM RX DATA: net %u sta idx %u wlan idx %u ssn %u tid %u ptype %u 11 %u\n",
2622 HIF_RX_HDR_GET_NETWORK_IDX(prHifRxHdr),
2623 prHifRxHdr->ucStaRecIdx,
2624 prCurrSwRfb->ucWlanIdx,
2625 HIF_RX_HDR_GET_SN(prHifRxHdr), /* The new SN of the frame */
2626 HIF_RX_HDR_GET_TID(prHifRxHdr),
2627 prCurrSwRfb->ucPacketType,
2628 HIF_RX_HDR_GET_80211_FLAG(prHifRxHdr)));
2630 DBGLOG_MEM8(SW4, TRACE, (PUINT_8)prCurrSwRfb->pvHeader, prCurrSwRfb->u2PacketLen);
2633 // DBGLOG(RX, TRACE, ("SN=%d, TID=%d\n", HIF_RX_HDR_GET_SN(prHifRxHdr), HIF_RX_HDR_GET_TID(prHifRxHdr)));
2635 if (!HIF_RX_HDR_GET_80211_FLAG(prHifRxHdr)){
2637 UINT_8 ucNetTypeIdx;
2638 P_BSS_INFO_T prBssInfo;
2640 pucEthDestAddr = prCurrSwRfb->pvHeader;
2641 ucNetTypeIdx = HIF_RX_HDR_GET_NETWORK_IDX(prHifRxHdr);
2643 prBssInfo = &(prAdapter->rWifiVar.arBssInfo[ucNetTypeIdx]);
2644 //DBGLOG_MEM8(QM, TRACE,prCurrSwRfb->pvHeader, 16);
2647 if( prAdapter->rRxCtrl.rFreeSwRfbList.u4NumElem
2648 > (CFG_RX_MAX_PKT_NUM - CFG_NUM_OF_QM_RX_PKT_NUM) ) {
2650 if(IS_BSS_ACTIVE(prBssInfo)) {
2651 if(OP_MODE_ACCESS_POINT == prBssInfo->eCurrentOPMode) {
2652 if (IS_BMCAST_MAC_ADDR(pucEthDestAddr)){
2653 prCurrSwRfb->eDst = RX_PKT_DESTINATION_HOST_WITH_FORWARD;
2655 else if(UNEQUAL_MAC_ADDR(prBssInfo->aucOwnMacAddr,pucEthDestAddr)) {
2656 prCurrSwRfb->eDst = RX_PKT_DESTINATION_FORWARD;
2657 /* TODO : need to check the dst mac is valid */
2658 /* If src mac is invalid, the packet will be freed in fw */
2660 } /* OP_MODE_ACCESS_POINT */
2663 DBGLOG(QM, TRACE, ("Mark NULL the Packet for inactive Bss %u\n",ucNetTypeIdx));
2664 prCurrSwRfb->eDst = RX_PKT_DESTINATION_NULL;
2665 QUEUE_INSERT_TAIL(&rReturnedQue, (P_QUE_ENTRY_T)prCurrSwRfb);
2671 /* Dont not occupy other SW RFB */
2672 DBGLOG(QM, TRACE, ("Mark NULL the Packet for less Free Sw Rfb\n"));
2673 prCurrSwRfb->eDst = RX_PKT_DESTINATION_NULL;
2674 QUEUE_INSERT_TAIL(&rReturnedQue, (P_QUE_ENTRY_T)prCurrSwRfb);
2681 if(HIF_RX_HDR_GET_BAR_FLAG(prHifRxHdr)){
2682 prCurrSwRfb->eDst = RX_PKT_DESTINATION_NULL;
2683 qmProcessBarFrame(prAdapter, prCurrSwRfb, &rReturnedQue);
2685 /* Reordering is not required for this packet, return it without buffering */
2686 else if(!HIF_RX_HDR_GET_REORDER_FLAG(prHifRxHdr)){
2688 if (!HIF_RX_HDR_GET_80211_FLAG(prHifRxHdr)){
2689 UINT_8 ucNetTypeIdx;
2690 P_BSS_INFO_T prBssInfo;
2692 pucEthDestAddr = prCurrSwRfb->pvHeader;
2693 ucNetTypeIdx = HIF_RX_HDR_GET_NETWORK_IDX(prHifRxHdr);
2695 prBssInfo = &(prAdapter->rWifiVar.arBssInfo[ucNetTypeIdx]);
2697 if (IS_BMCAST_MAC_ADDR(pucEthDestAddr) && (OP_MODE_ACCESS_POINT == prBssInfo->eCurrentOPMode)){
2698 prCurrSwRfb->eDst = RX_PKT_DESTINATION_HOST_WITH_FORWARD;
2702 QUEUE_INSERT_TAIL(&rReturnedQue, (P_QUE_ENTRY_T)prCurrSwRfb);
2704 /* Reordering is required for this packet */
2706 /* If this packet should dropped or indicated to the host immediately,
2707 * it should be enqueued into the rReturnedQue with specific flags. If
2708 * this packet should be buffered for reordering, it should be enqueued
2709 * into the reordering queue in the STA_REC rather than into the
2712 qmProcessPktWithReordering(prAdapter, prCurrSwRfb, &rReturnedQue);
2715 }while(prNextSwRfb);
2718 /* The returned list of SW_RFBs must end with a NULL pointer */
2719 if(QUEUE_IS_NOT_EMPTY(&rReturnedQue)){
2720 QM_TX_SET_NEXT_MSDU_INFO((P_SW_RFB_T)QUEUE_GET_TAIL(&rReturnedQue), NULL);
2723 return (P_SW_RFB_T)QUEUE_GET_HEAD(&rReturnedQue);
2727 //DbgPrint("QM: Enter qmHandleRxPackets()\n");
2728 return prSwRfbListHead;
2734 /*----------------------------------------------------------------------------*/
2736 * \brief Reorder the received packet
2738 * \param[in] prSwRfb The RX packet to process
2739 * \param[out] prReturnedQue The queue for indicating packets
2743 /*----------------------------------------------------------------------------*/
2745 qmProcessPktWithReordering(
2746 IN P_ADAPTER_T prAdapter,
2747 IN P_SW_RFB_T prSwRfb,
2748 OUT P_QUE_T prReturnedQue
2753 P_STA_RECORD_T prStaRec;
2754 P_HIF_RX_HEADER_T prHifRxHdr;
2755 P_RX_BA_ENTRY_T prReorderQueParm;
2760 P_QUE_T prReorderQue;
2761 //P_SW_RFB_T prReorderedSwRfb;
2763 DEBUGFUNC("qmProcessPktWithReordering");
2766 ASSERT(prReturnedQue);
2767 ASSERT(prSwRfb->prHifRxHdr);
2769 prHifRxHdr = prSwRfb->prHifRxHdr;
2770 prSwRfb->ucStaRecIdx = prHifRxHdr->ucStaRecIdx;
2771 prSwRfb->u2SSN = HIF_RX_HDR_GET_SN(prHifRxHdr); /* The new SN of the frame */
2772 prSwRfb->ucTid = (UINT_8)(HIF_RX_HDR_GET_TID(prHifRxHdr));
2773 //prSwRfb->eDst = RX_PKT_DESTINATION_HOST;
2775 /* Incorrect STA_REC index */
2776 if(prSwRfb->ucStaRecIdx >= CFG_NUM_OF_STA_RECORD){
2777 prSwRfb->eDst = RX_PKT_DESTINATION_NULL;
2778 QUEUE_INSERT_TAIL(prReturnedQue,(P_QUE_ENTRY_T)prSwRfb);
2779 DBGLOG(QM, WARN,("Reordering for a NULL STA_REC, ucStaRecIdx = %d\n",
2780 prSwRfb->ucStaRecIdx));
2785 /* Check whether the STA_REC is activated */
2786 prStaRec = &(prAdapter->arStaRec[prSwRfb->ucStaRecIdx]);
2790 if(!(prStaRec->fgIsValid)){
2791 /* TODO: (Tehuang) Handle the Host-FW sync issue. */
2792 prSwRfb->eDst = RX_PKT_DESTINATION_NULL;
2793 QUEUE_INSERT_TAIL(prReturnedQue,(P_QUE_ENTRY_T)prSwRfb);
2794 DBGLOG(QM, WARN, ("Reordering for an invalid STA_REC \n"));
2800 /* Check whether the BA agreement exists */
2801 prReorderQueParm = ((prStaRec->aprRxReorderParamRefTbl)[prSwRfb->ucTid]);
2802 if(!prReorderQueParm){
2803 /* TODO: (Tehuang) Handle the Host-FW sync issue.*/
2804 prSwRfb->eDst = RX_PKT_DESTINATION_NULL;
2805 QUEUE_INSERT_TAIL(prReturnedQue,(P_QUE_ENTRY_T)prSwRfb);
2806 DBGLOG(QM, WARN,("Reordering for a NULL ReorderQueParm \n"));
2813 /* Start to reorder packets */
2814 u4SeqNo = (UINT_32)(prSwRfb->u2SSN);
2815 prReorderQue = &(prReorderQueParm->rReOrderQue);
2816 u4WinStart = (UINT_32)(prReorderQueParm->u2WinStart);
2817 u4WinEnd = (UINT_32)(prReorderQueParm->u2WinEnd);
2820 //DbgPrint("QM:(R)[%d](%ld){%ld,%ld}\n", prSwRfb->ucTid, u4SeqNo, u4WinStart, u4WinEnd);
2822 /* Case 1: Fall within */
2823 if /* 0 - start - sn - end - 4095 */
2824 (((u4WinStart <= u4SeqNo) && (u4SeqNo <= u4WinEnd))
2825 /* 0 - end - start - sn - 4095 */
2826 || ((u4WinEnd < u4WinStart) && (u4WinStart <= u4SeqNo))
2827 /* 0 - sn - end - start - 4095 */
2828 || ((u4SeqNo <= u4WinEnd) && (u4WinEnd < u4WinStart))){
2830 qmInsertFallWithinReorderPkt(prSwRfb, prReorderQueParm, prReturnedQue);
2832 #if QM_RX_WIN_SSN_AUTO_ADVANCING
2833 if(prReorderQueParm->fgIsWaitingForPktWithSsn){
2834 /* Let the first received packet pass the reorder check */
2835 DBGLOG(QM, LOUD, ("QM:(A)[%d](%ld){%ld,%ld}\n", prSwRfb->ucTid, u4SeqNo, u4WinStart, u4WinEnd));
2837 prReorderQueParm->u2WinStart = (UINT_16)u4SeqNo;
2838 prReorderQueParm->u2WinEnd =
2839 ((prReorderQueParm->u2WinStart) + (prReorderQueParm->u2WinSize) - 1) % MAX_SEQ_NO_COUNT;
2840 prReorderQueParm->fgIsWaitingForPktWithSsn = FALSE;
2845 qmPopOutDueToFallWithin(prReorderQueParm, prReturnedQue);
2847 /* Case 2: Fall ahead */
2849 /* 0 - start - end - sn - (start+2048) - 4095 */
2850 (((u4WinStart < u4WinEnd)
2851 && (u4WinEnd < u4SeqNo)
2852 && (u4SeqNo < (u4WinStart + HALF_SEQ_NO_COUNT)))
2853 /* 0 - sn - (start+2048) - start - end - 4095 */
2854 || ((u4SeqNo < u4WinStart)
2855 && (u4WinStart < u4WinEnd)
2856 && ((u4SeqNo + MAX_SEQ_NO_COUNT) < (u4WinStart + HALF_SEQ_NO_COUNT)))
2857 /* 0 - end - sn - (start+2048) - start - 4095 */
2858 || ((u4WinEnd < u4SeqNo)
2859 && (u4SeqNo < u4WinStart)
2860 && ((u4SeqNo + MAX_SEQ_NO_COUNT) < (u4WinStart + HALF_SEQ_NO_COUNT)))){
2863 #if QM_RX_WIN_SSN_AUTO_ADVANCING
2864 if(prReorderQueParm->fgIsWaitingForPktWithSsn){
2865 prReorderQueParm->fgIsWaitingForPktWithSsn = FALSE;
2869 qmInsertFallAheadReorderPkt(prSwRfb, prReorderQueParm, prReturnedQue);
2871 /* Advance the window after inserting a new tail */
2872 prReorderQueParm->u2WinEnd = (UINT_16)u4SeqNo;
2873 prReorderQueParm->u2WinStart =
2874 (((prReorderQueParm->u2WinEnd) - (prReorderQueParm->u2WinSize) + MAX_SEQ_NO_COUNT + 1)
2875 % MAX_SEQ_NO_COUNT);
2877 qmPopOutDueToFallAhead(prReorderQueParm, prReturnedQue);
2880 /* Case 3: Fall behind */
2883 #if QM_RX_WIN_SSN_AUTO_ADVANCING
2884 #if QM_RX_INIT_FALL_BEHIND_PASS
2885 if(prReorderQueParm->fgIsWaitingForPktWithSsn){
2886 //?? prSwRfb->eDst = RX_PKT_DESTINATION_HOST;
2887 QUEUE_INSERT_TAIL(prReturnedQue,(P_QUE_ENTRY_T)prSwRfb);
2888 //DbgPrint("QM:(P)[%d](%ld){%ld,%ld}\n", prSwRfb->ucTid, u4SeqNo, u4WinStart, u4WinEnd);
2894 /* An erroneous packet */
2895 prSwRfb->eDst = RX_PKT_DESTINATION_NULL;
2896 QUEUE_INSERT_TAIL(prReturnedQue,(P_QUE_ENTRY_T)prSwRfb);
2897 //DbgPrint("QM:(D)[%d](%ld){%ld,%ld}\n", prSwRfb->ucTid, u4SeqNo, u4WinStart, u4WinEnd);
2908 IN P_ADAPTER_T prAdapter,
2909 IN P_SW_RFB_T prSwRfb,
2910 OUT P_QUE_T prReturnedQue
2914 P_STA_RECORD_T prStaRec;
2915 P_HIF_RX_HEADER_T prHifRxHdr;
2916 P_RX_BA_ENTRY_T prReorderQueParm;
2921 P_QUE_T prReorderQue;
2922 //P_SW_RFB_T prReorderedSwRfb;
2925 ASSERT(prReturnedQue);
2926 ASSERT(prSwRfb->prHifRxHdr);
2928 prHifRxHdr = prSwRfb->prHifRxHdr;
2929 prSwRfb->ucStaRecIdx = prHifRxHdr->ucStaRecIdx;
2930 prSwRfb->u2SSN = HIF_RX_HDR_GET_SN(prHifRxHdr); /* The new SSN */
2931 prSwRfb->ucTid = (UINT_8)(HIF_RX_HDR_GET_TID(prHifRxHdr));
2933 prSwRfb->eDst = RX_PKT_DESTINATION_NULL;
2934 QUEUE_INSERT_TAIL(prReturnedQue,(P_QUE_ENTRY_T)prSwRfb);
2936 /* Incorrect STA_REC index */
2937 if(prSwRfb->ucStaRecIdx >= CFG_NUM_OF_STA_RECORD){
2938 DBGLOG(QM, WARN, ("QM: (Warning) BAR for a NULL STA_REC, ucStaRecIdx = %d\n",
2939 prSwRfb->ucStaRecIdx));
2944 /* Check whether the STA_REC is activated */
2945 prStaRec = &(prAdapter->arStaRec[prSwRfb->ucStaRecIdx]);
2949 if(!(prStaRec->fgIsValid)){
2950 /* TODO: (Tehuang) Handle the Host-FW sync issue. */
2951 DbgPrint("QM: (Warning) BAR for an invalid STA_REC \n");
2957 /* Check whether the BA agreement exists */
2958 prReorderQueParm = ((prStaRec->aprRxReorderParamRefTbl)[prSwRfb->ucTid]);
2959 if(!prReorderQueParm){
2960 /* TODO: (Tehuang) Handle the Host-FW sync issue.*/
2961 DBGLOG(QM, WARN, ("QM: (Warning) BAR for a NULL ReorderQueParm \n"));
2967 u4SSN = (UINT_32)(prSwRfb->u2SSN);
2968 prReorderQue = &(prReorderQueParm->rReOrderQue);
2969 u4WinStart = (UINT_32)(prReorderQueParm->u2WinStart);
2970 u4WinEnd = (UINT_32)(prReorderQueParm->u2WinEnd);
2972 if(qmCompareSnIsLessThan(u4WinStart,u4SSN)){
2973 prReorderQueParm->u2WinStart = (UINT_16)u4SSN;
2974 prReorderQueParm->u2WinEnd =
2975 ((prReorderQueParm->u2WinStart) + (prReorderQueParm->u2WinSize) - 1) % MAX_SEQ_NO_COUNT;
2976 DBGLOG(QM, TRACE, ("QM:(BAR)[%d](%ld){%d,%d}\n", prSwRfb->ucTid, u4SSN, prReorderQueParm->u2WinStart, prReorderQueParm->u2WinEnd));
2977 qmPopOutDueToFallAhead(prReorderQueParm, prReturnedQue);
2980 DBGLOG(QM, TRACE, ("QM:(BAR)(%d)(%ld){%ld,%ld}\n", prSwRfb->ucTid, u4SSN, u4WinStart, u4WinEnd));
2987 qmInsertFallWithinReorderPkt(
2988 IN P_SW_RFB_T prSwRfb,
2989 IN P_RX_BA_ENTRY_T prReorderQueParm,
2990 OUT P_QUE_T prReturnedQue
2993 P_SW_RFB_T prExaminedQueuedSwRfb;
2994 P_QUE_T prReorderQue;
2996 ASSERT(prReorderQueParm);
2997 ASSERT(prReturnedQue);
2999 prReorderQue = &(prReorderQueParm->rReOrderQue);
3000 prExaminedQueuedSwRfb = (P_SW_RFB_T)QUEUE_GET_HEAD(prReorderQue);
3002 /* There are no packets queued in the Reorder Queue */
3003 if(prExaminedQueuedSwRfb == NULL){
3004 ((P_QUE_ENTRY_T)prSwRfb)->prPrev = NULL;
3005 ((P_QUE_ENTRY_T)prSwRfb)->prNext = NULL;
3006 prReorderQue->prHead = (P_QUE_ENTRY_T)prSwRfb;
3007 prReorderQue->prTail = (P_QUE_ENTRY_T)prSwRfb;
3008 prReorderQue->u4NumElem ++;
3011 /* Determine the insert position */
3014 /* Case 1: Terminate. A duplicate packet */
3015 if(((prExaminedQueuedSwRfb->u2SSN) == (prSwRfb->u2SSN))){
3016 prSwRfb->eDst = RX_PKT_DESTINATION_NULL;
3017 QUEUE_INSERT_TAIL(prReturnedQue,(P_QUE_ENTRY_T)prSwRfb);
3021 /* Case 2: Terminate. The insert point is found */
3022 else if(qmCompareSnIsLessThan(
3023 (prSwRfb->u2SSN),(prExaminedQueuedSwRfb->u2SSN))){
3027 /* Case 3: Insert point not found. Check the next SW_RFB in the Reorder Queue */
3029 prExaminedQueuedSwRfb =
3030 (P_SW_RFB_T)(((P_QUE_ENTRY_T)prExaminedQueuedSwRfb)->prNext);
3032 }while(prExaminedQueuedSwRfb);
3034 /* Update the Reorder Queue Parameters according to the found insert position */
3035 if(prExaminedQueuedSwRfb == NULL){
3036 /* The received packet shall be placed at the tail */
3037 ((P_QUE_ENTRY_T)prSwRfb)->prPrev = prReorderQue->prTail;
3038 ((P_QUE_ENTRY_T)prSwRfb)->prNext = NULL;
3039 (prReorderQue->prTail)->prNext = (P_QUE_ENTRY_T)(prSwRfb);
3040 prReorderQue->prTail = (P_QUE_ENTRY_T)(prSwRfb);
3043 ((P_QUE_ENTRY_T)prSwRfb)->prPrev = ((P_QUE_ENTRY_T)prExaminedQueuedSwRfb)->prPrev;
3044 ((P_QUE_ENTRY_T)prSwRfb)->prNext = (P_QUE_ENTRY_T)prExaminedQueuedSwRfb;
3045 if(((P_QUE_ENTRY_T)prExaminedQueuedSwRfb) == (prReorderQue->prHead)){
3046 /* The received packet will become the head */
3047 prReorderQue->prHead = (P_QUE_ENTRY_T)prSwRfb;
3050 (((P_QUE_ENTRY_T)prExaminedQueuedSwRfb)->prPrev)->prNext = (P_QUE_ENTRY_T)prSwRfb;
3052 ((P_QUE_ENTRY_T)prExaminedQueuedSwRfb)->prPrev = (P_QUE_ENTRY_T)prSwRfb;
3055 prReorderQue->u4NumElem ++;
3063 qmInsertFallAheadReorderPkt(
3064 IN P_SW_RFB_T prSwRfb,
3065 IN P_RX_BA_ENTRY_T prReorderQueParm,
3066 OUT P_QUE_T prReturnedQue
3069 P_QUE_T prReorderQue;
3071 ASSERT(prReorderQueParm);
3072 ASSERT(prReturnedQue);
3074 prReorderQue = &(prReorderQueParm->rReOrderQue);
3076 /* There are no packets queued in the Reorder Queue */
3077 if(QUEUE_IS_EMPTY(prReorderQue)){
3078 ((P_QUE_ENTRY_T)prSwRfb)->prPrev = NULL;
3079 ((P_QUE_ENTRY_T)prSwRfb)->prNext = NULL;
3080 prReorderQue->prHead = (P_QUE_ENTRY_T)prSwRfb;
3083 ((P_QUE_ENTRY_T)prSwRfb)->prPrev = prReorderQue->prTail;
3084 ((P_QUE_ENTRY_T)prSwRfb)->prNext = NULL;
3085 (prReorderQue->prTail)->prNext = (P_QUE_ENTRY_T)(prSwRfb);
3087 prReorderQue->prTail = (P_QUE_ENTRY_T)prSwRfb;
3088 prReorderQue->u4NumElem ++;
3094 qmPopOutDueToFallWithin(
3095 IN P_RX_BA_ENTRY_T prReorderQueParm,
3096 OUT P_QUE_T prReturnedQue
3099 P_SW_RFB_T prReorderedSwRfb;
3100 P_QUE_T prReorderQue;
3101 BOOLEAN fgDequeuHead, fgMissing;
3102 OS_SYSTIME rCurrentTime, *prMissTimeout;
3104 prReorderQue = &(prReorderQueParm->rReOrderQue);
3107 prMissTimeout = &(g_arMissTimeout[prReorderQueParm->ucStaRecIdx][prReorderQueParm->ucTid]);
3108 if (*prMissTimeout) {
3110 GET_CURRENT_SYSTIME(&rCurrentTime);
3113 /* Check whether any packet can be indicated to the higher layer */
3115 if(QUEUE_IS_EMPTY(prReorderQue)){
3119 /* Always examine the head packet */
3120 prReorderedSwRfb = (P_SW_RFB_T)QUEUE_GET_HEAD(prReorderQue);
3121 fgDequeuHead = FALSE;
3123 /* SN == WinStart, so the head packet shall be indicated (advance the window) */
3124 if((prReorderedSwRfb->u2SSN) == (prReorderQueParm->u2WinStart)){
3126 fgDequeuHead = TRUE;
3127 prReorderQueParm->u2WinStart =
3128 (((prReorderedSwRfb->u2SSN) + 1)% MAX_SEQ_NO_COUNT);
3130 /* SN > WinStart, break to update WinEnd */
3132 if (TRUE == fgMissing &&
3133 CHECK_FOR_TIMEOUT(rCurrentTime, (*prMissTimeout),
3134 //MSEC_TO_SEC(QM_RX_BA_ENTRY_MISS_TIMEOUT_MS))) {
3135 MSEC_TO_SYSTIME(QM_RX_BA_ENTRY_MISS_TIMEOUT_MS))) {
3136 DBGLOG(QM, TRACE, ("RX BA timeout, next tid %d, SSN %d\n",
3137 prReorderQueParm->ucTid, prReorderedSwRfb->u2SSN));
3138 fgDequeuHead = TRUE;
3139 prReorderQueParm->u2WinStart = (((prReorderedSwRfb->u2SSN) + 1) % MAX_SEQ_NO_COUNT);
3149 /* Dequeue the head packet */
3152 if(((P_QUE_ENTRY_T)prReorderedSwRfb)->prNext == NULL){
3153 prReorderQue->prHead = NULL;
3154 prReorderQue->prTail = NULL;
3157 prReorderQue->prHead = ((P_QUE_ENTRY_T)prReorderedSwRfb)->prNext;
3158 (((P_QUE_ENTRY_T)prReorderedSwRfb)->prNext)->prPrev = NULL;
3160 prReorderQue->u4NumElem --;
3161 //DbgPrint("QM: [%d] %d (%d)\n", prReorderQueParm->ucTid, prReorderedSwRfb->u2PacketLen, prReorderedSwRfb->u2SSN);
3162 QUEUE_INSERT_TAIL(prReturnedQue,(P_QUE_ENTRY_T)prReorderedSwRfb);
3166 if (QUEUE_IS_EMPTY(prReorderQue)) {
3170 if (FALSE == fgMissing) {
3171 GET_CURRENT_SYSTIME(prMissTimeout);
3174 /* After WinStart has been determined, update the WinEnd */
3175 prReorderQueParm->u2WinEnd =
3176 (((prReorderQueParm->u2WinStart) + (prReorderQueParm->u2WinSize) -1 )% MAX_SEQ_NO_COUNT);
3181 qmPopOutDueToFallAhead(
3182 IN P_RX_BA_ENTRY_T prReorderQueParm,
3183 OUT P_QUE_T prReturnedQue
3186 P_SW_RFB_T prReorderedSwRfb;
3187 P_QUE_T prReorderQue;
3188 BOOLEAN fgDequeuHead;
3190 prReorderQue = &(prReorderQueParm->rReOrderQue);
3192 /* Check whether any packet can be indicated to the higher layer */
3194 if(QUEUE_IS_EMPTY(prReorderQue)){
3198 /* Always examine the head packet */
3199 prReorderedSwRfb = (P_SW_RFB_T)QUEUE_GET_HEAD(prReorderQue);
3200 fgDequeuHead = FALSE;
3202 /* SN == WinStart, so the head packet shall be indicated (advance the window) */
3203 if((prReorderedSwRfb->u2SSN) == (prReorderQueParm->u2WinStart)){
3205 fgDequeuHead = TRUE;
3206 prReorderQueParm->u2WinStart =
3207 (((prReorderedSwRfb->u2SSN) + 1)% MAX_SEQ_NO_COUNT);
3210 /* SN < WinStart, so the head packet shall be indicated (do not advance the window) */
3211 else if(qmCompareSnIsLessThan(
3212 (UINT_32)(prReorderedSwRfb->u2SSN),
3213 (UINT_32)(prReorderQueParm->u2WinStart))){
3215 fgDequeuHead = TRUE;
3219 /* SN > WinStart, break to update WinEnd */
3225 /* Dequeue the head packet */
3228 if(((P_QUE_ENTRY_T)prReorderedSwRfb)->prNext == NULL){
3229 prReorderQue->prHead = NULL;
3230 prReorderQue->prTail = NULL;
3233 prReorderQue->prHead = ((P_QUE_ENTRY_T)prReorderedSwRfb)->prNext;
3234 (((P_QUE_ENTRY_T)prReorderedSwRfb)->prNext)->prPrev = NULL;
3236 prReorderQue->u4NumElem --;
3237 //DbgPrint("QM: [%d] %d (%d)\n", prReorderQueParm->ucTid, prReorderedSwRfb->u2PacketLen, prReorderedSwRfb->u2SSN);
3238 QUEUE_INSERT_TAIL(prReturnedQue,(P_QUE_ENTRY_T)prReorderedSwRfb);
3242 /* After WinStart has been determined, update the WinEnd */
3243 prReorderQueParm->u2WinEnd =
3244 (((prReorderQueParm->u2WinStart) + (prReorderQueParm->u2WinSize) -1)% MAX_SEQ_NO_COUNT);
3249 qmCompareSnIsLessThan(
3250 IN UINT_32 u4SnLess,
3251 IN UINT_32 u4SnGreater
3254 /* 0 <---> SnLess <--(gap>2048)--> SnGreater : SnLess > SnGreater */
3255 if((u4SnLess + HALF_SEQ_NO_COUNT) <= u4SnGreater){ /* Shall be <= */
3259 /* 0 <---> SnGreater <--(gap>2048)--> SnLess : SnLess < SnGreater */
3260 else if((u4SnGreater + HALF_SEQ_NO_COUNT) < u4SnLess){
3264 /* 0 <---> SnGreater <--(gap<2048)--> SnLess : SnLess > SnGreater */
3265 /* 0 <---> SnLess <--(gap<2048)--> SnGreater : SnLess < SnGreater */
3267 return (u4SnLess < u4SnGreater);
3272 /*----------------------------------------------------------------------------*/
3274 * \brief Handle Mailbox RX messages
3276 * \param[in] prMailboxRxMsg The received Mailbox message from the FW
3280 /*----------------------------------------------------------------------------*/
3282 qmHandleMailboxRxMessage(
3283 IN MAILBOX_MSG_T prMailboxRxMsg
3286 //DbgPrint("QM: Enter qmHandleMailboxRxMessage()\n");
3291 /*----------------------------------------------------------------------------*/
3293 * \brief Handle ADD RX BA Event from the FW
3295 * \param[in] prAdapter Adapter pointer
3296 * \param[in] prEvent The event packet from the FW
3300 /*----------------------------------------------------------------------------*/
3302 qmHandleEventRxAddBa(
3303 IN P_ADAPTER_T prAdapter,
3304 IN P_WIFI_EVENT_T prEvent
3307 P_EVENT_RX_ADDBA_T prEventRxAddBa;
3308 P_STA_RECORD_T prStaRec;
3312 DBGLOG(QM, INFO, ("QM:Event +RxBa\n"));
3314 prEventRxAddBa = (P_EVENT_RX_ADDBA_T)prEvent;
3315 prStaRec = QM_GET_STA_REC_PTR_FROM_INDEX(prAdapter, prEventRxAddBa->ucStaRecIdx);
3318 /* Invalid STA_REC index, discard the event packet */
3320 DBGLOG(QM, INFO, ("QM: (Warning) RX ADDBA Event for a NULL STA_REC\n"));
3325 if(!(prStaRec->fgIsValid)){
3326 /* TODO: (Tehuang) Handle the Host-FW synchronization issue */
3327 DBGLOG(QM, WARN, ("QM: (Warning) RX ADDBA Event for an invalid STA_REC\n"));
3333 u4Tid = (((prEventRxAddBa->u2BAParameterSet)& BA_PARAM_SET_TID_MASK)
3334 >> BA_PARAM_SET_TID_MASK_OFFSET);
3336 u4WinSize = (((prEventRxAddBa->u2BAParameterSet)& BA_PARAM_SET_BUFFER_SIZE_MASK)
3337 >> BA_PARAM_SET_BUFFER_SIZE_MASK_OFFSET);
3343 (prEventRxAddBa->u2BAStartSeqCtrl >> OFFSET_BAR_SSC_SN),
3344 (UINT_16)u4WinSize)){
3346 /* FW shall ensure the availabiilty of the free-to-use BA entry */
3347 DBGLOG(QM, ERROR, ("QM: (Error) qmAddRxBaEntry() failure\n"));
3353 /*----------------------------------------------------------------------------*/
3355 * \brief Handle DEL RX BA Event from the FW
3357 * \param[in] prAdapter Adapter pointer
3358 * \param[in] prEvent The event packet from the FW
3362 /*----------------------------------------------------------------------------*/
3364 qmHandleEventRxDelBa(
3365 IN P_ADAPTER_T prAdapter,
3366 IN P_WIFI_EVENT_T prEvent
3369 P_EVENT_RX_DELBA_T prEventRxDelBa;
3370 P_STA_RECORD_T prStaRec;
3372 //DbgPrint("QM:Event -RxBa\n");
3374 prEventRxDelBa = (P_EVENT_RX_DELBA_T)prEvent;
3375 prStaRec = QM_GET_STA_REC_PTR_FROM_INDEX(prAdapter, prEventRxDelBa->ucStaRecIdx);
3378 /* Invalid STA_REC index, discard the event packet */
3384 if(!(prStaRec->fgIsValid)){
3385 /* TODO: (Tehuang) Handle the Host-FW synchronization issue */
3391 qmDelRxBaEntry(prAdapter, prStaRec->ucIndex, prEventRxDelBa->ucTid, TRUE);
3397 IN P_ADAPTER_T prAdapter,
3403 P_QUE_MGT_T prQM = &prAdapter->rQM;
3405 //DbgPrint("QM: Enter qmLookupRxBaEntry()\n");
3407 for(i=0; i<CFG_NUM_OF_RX_BA_AGREEMENTS; i++){
3408 if(prQM->arRxBaTable[i].fgIsValid){
3409 if((prQM->arRxBaTable[i].ucStaRecIdx == ucStaRecIdx) &&
3410 (prQM->arRxBaTable[i].ucTid == ucTid)){
3411 return &prQM->arRxBaTable[i];
3420 IN P_ADAPTER_T prAdapter,
3421 IN UINT_8 ucStaRecIdx,
3423 IN UINT_16 u2WinStart,
3424 IN UINT_16 u2WinSize
3428 P_RX_BA_ENTRY_T prRxBaEntry = NULL;
3429 P_STA_RECORD_T prStaRec;
3430 P_QUE_MGT_T prQM = &prAdapter->rQM;
3432 ASSERT(ucStaRecIdx < CFG_NUM_OF_STA_RECORD);
3434 if(ucStaRecIdx >= CFG_NUM_OF_STA_RECORD){
3435 /* Invalid STA_REC index, discard the event packet */
3436 DBGLOG(QM, WARN, ("QM: (WARNING) RX ADDBA Event for a invalid ucStaRecIdx = %d\n", ucStaRecIdx));
3440 prStaRec = &prAdapter->arStaRec[ucStaRecIdx];
3443 //if(!(prStaRec->fgIsValid)){
3444 // DbgPrint("QM: (WARNING) Invalid STA when adding an RX BA \n");
3448 //4 <1> Delete before adding
3449 /* Remove the BA entry for the same (STA, TID) tuple if it exists */
3450 if(qmLookupRxBaEntry(prAdapter, ucStaRecIdx,ucTid)){
3451 qmDelRxBaEntry(prAdapter, ucStaRecIdx, ucTid, TRUE); /* prQM->ucRxBaCount-- */
3454 //4 <2> Add a new BA entry
3455 /* No available entry to store the BA agreement info. Retrun FALSE. */
3456 if(prQM->ucRxBaCount >= CFG_NUM_OF_RX_BA_AGREEMENTS){
3457 DBGLOG(QM, ERROR, ("QM: **failure** (limited resource, ucRxBaCount=%d)\n", prQM->ucRxBaCount));
3461 /* Find the free-to-use BA entry */
3462 for(i=0; i<CFG_NUM_OF_RX_BA_AGREEMENTS; i++){
3463 if(!prQM->arRxBaTable[i].fgIsValid){
3464 prRxBaEntry = &(prQM->arRxBaTable[i]);
3465 prQM->ucRxBaCount++;
3466 DBGLOG(QM, LOUD, ("QM: ucRxBaCount=%d\n", prQM->ucRxBaCount));
3471 /* If a free-to-use entry is found, configure it and associate it with the STA_REC */
3472 u2WinSize += CFG_RX_BA_INC_SIZE;
3474 prRxBaEntry->ucStaRecIdx = ucStaRecIdx;
3475 prRxBaEntry->ucTid = ucTid;
3476 prRxBaEntry->u2WinStart = u2WinStart;
3477 prRxBaEntry->u2WinSize= u2WinSize;
3478 prRxBaEntry->u2WinEnd = ((u2WinStart + u2WinSize - 1) % MAX_SEQ_NO_COUNT);
3479 prRxBaEntry->fgIsValid = TRUE;
3480 prRxBaEntry->fgIsWaitingForPktWithSsn = TRUE;
3482 g_arMissTimeout[ucStaRecIdx][ucTid] = 0;
3484 DBGLOG(QM, INFO, ("QM: +RxBA(STA=%d TID=%d WinStart=%d WinEnd=%d WinSize=%d)\n",
3486 prRxBaEntry->u2WinStart, prRxBaEntry->u2WinEnd, prRxBaEntry->u2WinSize));
3488 /* Update the BA entry reference table for per-packet lookup */
3489 prStaRec->aprRxReorderParamRefTbl[ucTid] = prRxBaEntry;
3492 /* This shall not happen because FW should keep track of the usage of RX BA entries */
3493 DBGLOG(QM, ERROR, ("QM: **AddBA Error** (ucRxBaCount=%d)\n", prQM->ucRxBaCount));
3502 IN P_ADAPTER_T prAdapter,
3503 IN UINT_8 ucStaRecIdx,
3505 IN BOOLEAN fgFlushToHost
3508 P_RX_BA_ENTRY_T prRxBaEntry;
3509 P_STA_RECORD_T prStaRec;
3510 P_SW_RFB_T prFlushedPacketList = NULL;
3511 P_QUE_MGT_T prQM = &prAdapter->rQM;
3513 ASSERT(ucStaRecIdx < CFG_NUM_OF_STA_RECORD);
3515 prStaRec = &prAdapter->arStaRec[ucStaRecIdx];
3519 if(!(prStaRec->fgIsValid)){
3520 DbgPrint("QM: (WARNING) Invalid STA when deleting an RX BA \n");
3525 /* Remove the BA entry for the same (STA, TID) tuple if it exists */
3526 prRxBaEntry = prStaRec->aprRxReorderParamRefTbl[ucTid];
3530 prFlushedPacketList = qmFlushStaRxQueue(prAdapter, ucStaRecIdx, ucTid);
3532 if(prFlushedPacketList){
3535 wlanProcessQueuedSwRfb(prAdapter, prFlushedPacketList);
3540 P_SW_RFB_T prNextSwRfb;
3541 prSwRfb = prFlushedPacketList;
3544 prNextSwRfb = (P_SW_RFB_T)QUEUE_GET_NEXT_ENTRY((P_QUE_ENTRY_T)prSwRfb);
3545 nicRxReturnRFB(prAdapter, prSwRfb);
3546 prSwRfb = prNextSwRfb;
3553 #if ((QM_TEST_MODE == 0) && (QM_TEST_STA_REC_DEACTIVATION == 0))
3554 /* Update RX BA entry state. Note that RX queue flush is not done here */
3555 prRxBaEntry->fgIsValid = FALSE;
3556 prQM->ucRxBaCount--;
3560 DbgPrint("QM: ucRxBaCount=%d\n", prQM->ucRxBaCount);
3563 /* Update STA RX BA table */
3564 prStaRec->aprRxReorderParamRefTbl[ucTid] = NULL;
3567 DBGLOG(QM, INFO, ("QM: -RxBA(STA=%d,TID=%d)\n", ucStaRecIdx, ucTid));
3573 #if CFG_HIF_RX_STARVATION_WARNING
3575 P_RX_CTRL_T prRxCtrl;
3576 prRxCtrl = &prAdapter->rRxCtrl;
3577 DBGLOG(QM, TRACE, ("QM: (RX DEBUG) Enqueued: %d / Dequeued: %d\n", prRxCtrl->u4QueuedCnt, prRxCtrl->u4DequeuedCnt));
3583 /*----------------------------------------------------------------------------*/
3585 * \brief To process WMM related IEs in ASSOC_RSP
3587 * \param[in] prAdapter Adapter pointer
3588 * \param[in] prSwRfb The received frame
3589 * \param[in] pucIE The pointer to the first IE in the frame
3590 * \param[in] u2IELength The total length of IEs in the frame
3594 /*----------------------------------------------------------------------------*/
3596 mqmProcessAssocReq (
3597 IN P_ADAPTER_T prAdapter,
3598 IN P_SW_RFB_T prSwRfb,
3600 IN UINT_16 u2IELength
3603 P_STA_RECORD_T prStaRec;
3606 UINT_8 aucWfaOui[] = VENDOR_OUI_WFA;
3607 P_IE_WMM_INFO_T prIeWmmInfo;
3609 DEBUGFUNC("mqmProcessAssocReq");
3614 prStaRec = cnmGetStaRecByIndex(prAdapter, prSwRfb->ucStaRecIdx);
3617 if(prStaRec == NULL) {
3621 prStaRec->fgIsQoS = FALSE;
3622 prStaRec->fgIsWmmSupported = prStaRec->fgIsUapsdSupported = FALSE;
3626 /* If the device does not support QoS or if WMM is not supported by the peer, exit.*/
3627 if (!prAdapter->rWifiVar.fgSupportQoS) {
3632 /* Determine whether QoS is enabled with the association */
3634 IE_FOR_EACH(pucIE, u2IELength, u2Offset) {
3635 switch (IE_ID(pucIE)) {
3638 if((WMM_IE_OUI_TYPE(pucIE) == VENDOR_OUI_TYPE_WMM) &&
3639 (!kalMemCmp(WMM_IE_OUI(pucIE),aucWfaOui,3))){
3641 switch(WMM_IE_OUI_SUBTYPE(pucIE)){
3642 case VENDOR_OUI_SUBTYPE_WMM_INFO:
3648 if(IE_LEN(pucIE) != 7){
3649 break; /* WMM Info IE with a wrong length */
3651 prStaRec->fgIsQoS = TRUE;
3652 prStaRec->fgIsWmmSupported = TRUE;
3654 prIeWmmInfo = (P_IE_WMM_INFO_T)pucIE;
3655 ucQosInfo = prIeWmmInfo->ucQosInfo;
3656 ucQosInfoAC = ucQosInfo & BITS(0, 3);
3658 prStaRec->fgIsUapsdSupported = ((ucQosInfoAC)? TRUE: FALSE) &
3659 prAdapter->rWifiVar.fgSupportUAPSD;
3663 if( ucQosInfoAC & WMM_QOS_INFO_VO_UAPSD) {
3664 ucBmpAC |= BIT(ACI_VO);
3666 if( ucQosInfoAC & WMM_QOS_INFO_VI_UAPSD) {
3667 ucBmpAC |= BIT(ACI_VI);
3669 if( ucQosInfoAC & WMM_QOS_INFO_BE_UAPSD) {
3670 ucBmpAC |= BIT(ACI_BE);
3672 if( ucQosInfoAC & WMM_QOS_INFO_BK_UAPSD) {
3673 ucBmpAC |= BIT(ACI_BK);
3676 prStaRec->ucBmpTriggerAC = prStaRec->ucBmpDeliveryAC = ucBmpAC;
3678 prStaRec->ucUapsdSp = (ucQosInfo & WMM_QOS_INFO_MAX_SP_LEN_MASK) >> 5;
3684 /* Other WMM QoS IEs. Ignore any */
3688 /* else: VENDOR_OUI_TYPE_WPA, VENDOR_OUI_TYPE_WPS */
3692 case ELEM_ID_HT_CAP:
3693 /* Some client won't put the WMM IE if client is 802.11n */
3694 if (IE_LEN(pucIE) == (sizeof(IE_HT_CAP_T) - 2)) {
3695 prStaRec->fgIsQoS = TRUE;
3703 DBGLOG(QM, TRACE, ("MQM: Assoc_Req Parsing (QoS Enabled=%d)\n", prStaRec->fgIsQoS));
3709 /*----------------------------------------------------------------------------*/
3711 * \brief To process WMM related IEs in ASSOC_RSP
3713 * \param[in] prAdapter Adapter pointer
3714 * \param[in] prSwRfb The received frame
3715 * \param[in] pucIE The pointer to the first IE in the frame
3716 * \param[in] u2IELength The total length of IEs in the frame
3720 /*----------------------------------------------------------------------------*/
3722 mqmProcessAssocRsp (
3723 IN P_ADAPTER_T prAdapter,
3724 IN P_SW_RFB_T prSwRfb,
3726 IN UINT_16 u2IELength
3729 P_STA_RECORD_T prStaRec;
3732 UINT_8 aucWfaOui[] = VENDOR_OUI_WFA;
3734 DEBUGFUNC("mqmProcessAssocRsp");
3739 prStaRec = cnmGetStaRecByIndex(prAdapter, prSwRfb->ucStaRecIdx);
3742 if(prStaRec == NULL) {
3746 prStaRec->fgIsQoS = FALSE;
3750 DBGLOG(QM, TRACE, ("QM: (fgIsWmmSupported=%d, fgSupportQoS=%d)\n",
3751 prStaRec->fgIsWmmSupported, prAdapter->rWifiVar.fgSupportQoS));
3753 /* If the device does not support QoS or if WMM is not supported by the peer, exit.*/
3754 //if((!prAdapter->rWifiVar.fgSupportQoS) || (!prStaRec->fgIsWmmSupported))
3755 if((!prAdapter->rWifiVar.fgSupportQoS))
3760 /* Determine whether QoS is enabled with the association */
3762 IE_FOR_EACH(pucIE, u2IELength, u2Offset) {
3763 switch (IE_ID(pucIE)) {
3765 if((WMM_IE_OUI_TYPE(pucIE) == VENDOR_OUI_TYPE_WMM) &&
3766 (!kalMemCmp(WMM_IE_OUI(pucIE),aucWfaOui,3))){
3768 switch(WMM_IE_OUI_SUBTYPE(pucIE)){
3769 case VENDOR_OUI_SUBTYPE_WMM_PARAM:
3770 if(IE_LEN(pucIE) != 24){
3771 break; /* WMM Info IE with a wrong length */
3773 prStaRec->fgIsQoS = TRUE;
3776 case VENDOR_OUI_SUBTYPE_WMM_INFO:
3777 if(IE_LEN(pucIE) != 7){
3778 break; /* WMM Info IE with a wrong length */
3780 prStaRec->fgIsQoS = TRUE;
3784 /* Other WMM QoS IEs. Ignore any */
3788 /* else: VENDOR_OUI_TYPE_WPA, VENDOR_OUI_TYPE_WPS */
3791 case ELEM_ID_HT_CAP:
3792 /* Some AP won't put the WMM IE if client is 802.11n */
3793 if ( IE_LEN(pucIE) == (sizeof(IE_HT_CAP_T) - 2)) {
3794 prStaRec->fgIsQoS = TRUE;
3802 /* Parse AC parameters and write to HW CRs */
3803 if((prStaRec->fgIsQoS) && (prStaRec->eStaType == STA_TYPE_LEGACY_AP)){
3804 mqmParseEdcaParameters(prAdapter, prSwRfb, pucIEStart, u2IELength, TRUE);
3807 DBGLOG(QM, TRACE, ("MQM: Assoc_Rsp Parsing (QoS Enabled=%d)\n", prStaRec->fgIsQoS));
3808 if(prStaRec->fgIsWmmSupported) {
3809 nicQmUpdateWmmParms(prAdapter, prStaRec->ucNetTypeIndex);
3815 /*----------------------------------------------------------------------------*/
3817 * \brief To parse WMM Parameter IE (in BCN or Assoc_Rsp)
3819 * \param[in] prAdapter Adapter pointer
3820 * \param[in] prSwRfb The received frame
3821 * \param[in] pucIE The pointer to the first IE in the frame
3822 * \param[in] u2IELength The total length of IEs in the frame
3823 * \param[in] fgForceOverride TRUE: If EDCA parameters are found, always set to HW CRs.
3827 /*----------------------------------------------------------------------------*/
3829 mqmParseEdcaParameters (
3830 IN P_ADAPTER_T prAdapter,
3831 IN P_SW_RFB_T prSwRfb,
3833 IN UINT_16 u2IELength,
3834 IN BOOLEAN fgForceOverride
3837 P_STA_RECORD_T prStaRec;
3839 UINT_8 aucWfaOui[] = VENDOR_OUI_WFA;
3840 P_BSS_INFO_T prBssInfo;
3842 DEBUGFUNC("mqmParseEdcaParameters");
3847 prStaRec = cnmGetStaRecByIndex(prAdapter, prSwRfb->ucStaRecIdx);
3850 if(prStaRec == NULL) {
3854 DBGLOG(QM, TRACE, ("QM: (fgIsWmmSupported=%d, fgIsQoS=%d)\n",
3855 prStaRec->fgIsWmmSupported, prStaRec->fgIsQoS));
3857 if((!prAdapter->rWifiVar.fgSupportQoS) || (!prStaRec->fgIsWmmSupported) || (!prStaRec->fgIsQoS)){
3861 prBssInfo = &(prAdapter->rWifiVar.arBssInfo[prStaRec->ucNetTypeIndex]);
3863 /* Goal: Obtain the EDCA parameters */
3864 IE_FOR_EACH(pucIE, u2IELength, u2Offset) {
3865 switch (IE_ID(pucIE)) {
3868 if((WMM_IE_OUI_TYPE(pucIE) == VENDOR_OUI_TYPE_WMM) &&
3869 (!kalMemCmp(WMM_IE_OUI(pucIE),aucWfaOui,3))){
3871 switch(WMM_IE_OUI_SUBTYPE(pucIE)){
3872 case VENDOR_OUI_SUBTYPE_WMM_PARAM:
3873 if(IE_LEN(pucIE) != 24){
3874 break; /* WMM Param IE with a wrong length */
3877 P_AC_QUE_PARMS_T prAcQueParams;
3878 P_IE_WMM_PARAM_T prIeWmmParam;
3879 ENUM_WMM_ACI_T eAci;
3880 PUINT_8 pucWmmParamSetCount;
3883 pucWmmParamSetCount = &(prBssInfo->ucWmmParamSetCount);
3885 prIeWmmParam = (P_IE_WMM_PARAM_T)pucIE;
3887 /* Check the Parameter Set Count to determine whether EDCA parameters have been changed */
3888 if(!fgForceOverride){
3889 if(*pucWmmParamSetCount == (prIeWmmParam->ucQosInfo & WMM_QOS_INFO_PARAM_SET_CNT)){
3890 break; /* Ignore the IE without updating HW CRs */
3894 /* Update Parameter Set Count */
3895 *pucWmmParamSetCount = (prIeWmmParam->ucQosInfo & WMM_QOS_INFO_PARAM_SET_CNT);
3897 /* Update EDCA parameters */
3898 for(eAci = 0; eAci < WMM_AC_INDEX_NUM; eAci++){
3900 prAcQueParams = &prBssInfo->arACQueParms[eAci];
3901 mqmFillAcQueParam(prIeWmmParam, eAci, prAcQueParams);
3903 prAcQueParams->fgIsACMSet =
3904 (prAcQueParams->u2Aifsn & WMM_ACIAIFSN_ACM) ? TRUE : FALSE;
3905 prAcQueParams->u2Aifsn &= WMM_ACIAIFSN_AIFSN;
3907 DBGLOG(QM, LOUD, ("MQM: eAci = %d, ACM = %d, Aifsn = %d, CWmin = %d, CWmax = %d, TxopLimit = %d\n",
3908 eAci, prAcQueParams->fgIsACMSet,
3909 prAcQueParams->u2Aifsn, prAcQueParams->u2CWmin,
3910 prAcQueParams->u2CWmax, prAcQueParams->u2TxopLimit));
3916 /* Other WMM QoS IEs. Ignore */
3921 /* else: VENDOR_OUI_TYPE_WPA, VENDOR_OUI_TYPE_WPS, ... (not cared) */
3930 /*----------------------------------------------------------------------------*/
3932 * \brief This function is used for parsing EDCA parameters specified in the WMM Parameter IE
3934 * \param[in] prAdapter Adapter pointer
3935 * \param[in] prIeWmmParam The pointer to the WMM Parameter IE
3936 * \param[in] u4AcOffset The offset specifying the AC queue for parsing
3937 * \param[in] prHwAcParams The parameter structure used to configure the HW CRs
3941 /*----------------------------------------------------------------------------*/
3944 IN P_IE_WMM_PARAM_T prIeWmmParam,
3945 IN UINT_32 u4AcOffset,
3946 OUT P_AC_QUE_PARMS_T prAcQueParams
3949 prAcQueParams->u2Aifsn = *((PUINT_8)(&(prIeWmmParam->ucAciAifsn_BE)) + (u4AcOffset * 4));
3951 prAcQueParams->u2CWmax =
3952 BIT(((*((PUINT_8)(&(prIeWmmParam->ucEcw_BE)) + (u4AcOffset * 4))) & WMM_ECW_WMAX_MASK)
3953 >> WMM_ECW_WMAX_OFFSET)-1;
3955 prAcQueParams->u2CWmin =
3956 BIT((*((PUINT_8)(&(prIeWmmParam->ucEcw_BE)) + (u4AcOffset * 4))) & WMM_ECW_WMIN_MASK)-1;
3958 WLAN_GET_FIELD_16(((PUINT_8)(&(prIeWmmParam->aucTxopLimit_BE)) + (u4AcOffset * 4)),&(prAcQueParams->u2TxopLimit));
3960 prAcQueParams->ucGuradTime = TXM_DEFAULT_FLUSH_QUEUE_GUARD_TIME;
3966 /*----------------------------------------------------------------------------*/
3968 * \brief To parse WMM/11n related IEs in scan results (only for AP peers)
3970 * \param[in] prAdapter Adapter pointer
3971 * \param[in] prScanResult The scan result which shall be parsed to obtain needed info
3972 * \param[out] prStaRec The obtained info is stored in the STA_REC
3976 /*----------------------------------------------------------------------------*/
3978 mqmProcessScanResult(
3979 IN P_ADAPTER_T prAdapter,
3980 IN P_BSS_DESC_T prScanResult,
3981 OUT P_STA_RECORD_T prStaRec
3987 UINT_8 aucWfaOui[] = VENDOR_OUI_WFA;
3989 DEBUGFUNC("mqmProcessScanResult");
3991 ASSERT(prScanResult);
3994 /* Reset the flag before parsing */
3995 prStaRec->fgIsWmmSupported = prStaRec->fgIsUapsdSupported = FALSE;
3997 if (!prAdapter->rWifiVar.fgSupportQoS){
4001 u2IELength = prScanResult->u2IELength;
4002 pucIE = prScanResult->aucIEBuf;
4004 /* Goal: Determine whether the peer supports WMM/QoS and UAPSDU */
4005 IE_FOR_EACH(pucIE, u2IELength, u2Offset) {
4006 switch (IE_ID(pucIE)) {
4008 if((WMM_IE_OUI_TYPE(pucIE) == VENDOR_OUI_TYPE_WMM) &&
4009 (!kalMemCmp(WMM_IE_OUI(pucIE),aucWfaOui,3))){
4011 switch(WMM_IE_OUI_SUBTYPE(pucIE)){
4012 case VENDOR_OUI_SUBTYPE_WMM_PARAM:
4013 if(IE_LEN(pucIE) != 24){
4014 break; /* WMM Param IE with a wrong length */
4017 prStaRec->fgIsWmmSupported = TRUE;
4018 prStaRec->fgIsUapsdSupported = (((((P_IE_WMM_PARAM_T)pucIE)->ucQosInfo) & WMM_QOS_INFO_UAPSD)? TRUE: FALSE);
4022 case VENDOR_OUI_SUBTYPE_WMM_INFO:
4023 if(IE_LEN(pucIE) != 7){
4024 break; /* WMM Info IE with a wrong length */
4027 prStaRec->fgIsWmmSupported = TRUE;
4028 prStaRec->fgIsUapsdSupported = (((((P_IE_WMM_INFO_T)pucIE)->ucQosInfo) & WMM_QOS_INFO_UAPSD)? TRUE: FALSE);
4033 /* A WMM QoS IE that doesn't matter. Ignore it. */
4037 /* else: VENDOR_OUI_TYPE_WPA, VENDOR_OUI_TYPE_WPS, ... (not cared) */
4042 /* A WMM IE that doesn't matter. Ignore it. */
4046 DBGLOG(QM, LOUD, ("MQM: Scan Result Parsing (WMM=%d, UAPSD=%d)\n",
4047 prStaRec->fgIsWmmSupported, prStaRec->fgIsUapsdSupported));
4053 IN P_ADAPTER_T prAdapter,
4054 IN PUINT_8 pucEthDestAddr,
4055 IN ENUM_NETWORK_TYPE_INDEX_T eNetworkType
4059 P_STA_RECORD_T prTempStaRec;
4061 prTempStaRec = NULL;
4066 if(IS_BMCAST_MAC_ADDR(pucEthDestAddr)){
4067 return STA_REC_INDEX_BMCAST;
4071 //4 <2> Check if an AP STA is present
4072 for(i = 0; i < CFG_NUM_OF_STA_RECORD; i++){
4073 prTempStaRec = &(prAdapter->arStaRec[i]);
4074 if((prTempStaRec->ucNetTypeIndex == eNetworkType)
4075 && (prTempStaRec->fgIsAp)
4076 && (prTempStaRec->fgIsValid)){
4077 return prTempStaRec->ucIndex;
4081 //4 <3> Not BMCAST, No AP --> Compare DA (i.e., to see whether this is a unicast frame to a client)
4082 for(i = 0; i < CFG_NUM_OF_STA_RECORD; i++){
4083 prTempStaRec = &(prAdapter->arStaRec[i]);
4084 if(prTempStaRec->fgIsValid){
4085 if(EQUAL_MAC_ADDR(prTempStaRec->aucMacAddr, pucEthDestAddr)){
4086 return prTempStaRec->ucIndex;
4092 //4 <4> No STA found, Not BMCAST --> Indicate NOT_FOUND to FW
4093 return STA_REC_INDEX_NOT_FOUND;
4097 /*----------------------------------------------------------------------------*/
4099 * @brief Generate the WMM Info IE
4101 * \param[in] prAdapter Adapter pointer
4102 * @param prMsduInfo The TX MMPDU
4106 /*----------------------------------------------------------------------------*/
4108 mqmGenerateWmmInfoIE (
4109 IN P_ADAPTER_T prAdapter,
4110 IN P_MSDU_INFO_T prMsduInfo
4113 P_IE_WMM_INFO_T prIeWmmInfo;
4114 UINT_32 ucUapsd[] = {
4115 WMM_QOS_INFO_BE_UAPSD,
4116 WMM_QOS_INFO_BK_UAPSD,
4117 WMM_QOS_INFO_VI_UAPSD,
4118 WMM_QOS_INFO_VO_UAPSD
4120 UINT_8 aucWfaOui[] = VENDOR_OUI_WFA;
4122 P_PM_PROFILE_SETUP_INFO_T prPmProfSetupInfo;
4123 P_BSS_INFO_T prBssInfo;
4124 P_STA_RECORD_T prStaRec;
4126 DEBUGFUNC("mqmGenerateWmmInfoIE");
4130 /* In case QoS is not turned off, exit directly */
4131 if(!prAdapter->rWifiVar.fgSupportQoS){
4135 prStaRec = cnmGetStaRecByIndex(prAdapter, prMsduInfo->ucStaRecIndex);
4138 if(prStaRec == NULL) {
4142 if(!prStaRec->fgIsWmmSupported) {
4146 prBssInfo = &(prAdapter->rWifiVar.arBssInfo[prStaRec->ucNetTypeIndex]);
4148 prPmProfSetupInfo = &prBssInfo->rPmProfSetupInfo;
4150 prIeWmmInfo = (P_IE_WMM_INFO_T)
4151 ((PUINT_8) prMsduInfo->prPacket + prMsduInfo->u2FrameLength);
4153 prIeWmmInfo->ucId = ELEM_ID_WMM;
4154 prIeWmmInfo->ucLength = ELEM_MAX_LEN_WMM_INFO;
4156 /* WMM-2.2.1 WMM Information Element Field Values */
4157 prIeWmmInfo->aucOui[0] = aucWfaOui[0];
4158 prIeWmmInfo->aucOui[1] = aucWfaOui[1];
4159 prIeWmmInfo->aucOui[2] = aucWfaOui[2];
4160 prIeWmmInfo->ucOuiType = VENDOR_OUI_TYPE_WMM;
4161 prIeWmmInfo->ucOuiSubtype = VENDOR_OUI_SUBTYPE_WMM_INFO;
4163 prIeWmmInfo->ucVersion = VERSION_WMM;
4164 prIeWmmInfo->ucQosInfo = 0;
4166 /* UAPSD intial queue configurations (delivery and trigger enabled)*/
4167 // if(prAdapter->rWifiVar.fgSupportUAPSD){
4168 if(prAdapter->rWifiVar.fgSupportUAPSD && prStaRec->fgIsUapsdSupported){
4170 UINT_8 ucQosInfo = 0;
4174 /* Static U-APSD setting */
4175 for(i = ACI_BE; i <= ACI_VO; i++){
4176 if (prPmProfSetupInfo->ucBmpDeliveryAC & prPmProfSetupInfo->ucBmpTriggerAC & BIT(i)){
4177 ucQosInfo |= (UINT_8)ucUapsd[i];
4182 if (prPmProfSetupInfo->ucBmpDeliveryAC & prPmProfSetupInfo->ucBmpTriggerAC) {
4183 switch (prPmProfSetupInfo->ucUapsdSp) {
4184 case WMM_MAX_SP_LENGTH_ALL:
4185 ucQosInfo |= WMM_QOS_INFO_MAX_SP_ALL;
4188 case WMM_MAX_SP_LENGTH_2:
4189 ucQosInfo |= WMM_QOS_INFO_MAX_SP_2;
4192 case WMM_MAX_SP_LENGTH_4:
4193 ucQosInfo |= WMM_QOS_INFO_MAX_SP_4;
4196 case WMM_MAX_SP_LENGTH_6:
4197 ucQosInfo |= WMM_QOS_INFO_MAX_SP_6;
4201 DBGLOG(QM, INFO, ("MQM: Incorrect SP length \n"));
4202 ucQosInfo |= WMM_QOS_INFO_MAX_SP_2;
4206 prIeWmmInfo->ucQosInfo = ucQosInfo;
4210 /* Increment the total IE length for the Element ID and Length fields. */
4211 prMsduInfo->u2FrameLength += IE_SIZE(prIeWmmInfo);
4217 /*----------------------------------------------------------------------------*/
4219 * @brief log2 calculation for CW
4221 * @param[in] val value
4225 /*----------------------------------------------------------------------------*/
4227 UINT_32 cwlog2(UINT_32 val) {
4232 while (val >= 512) { n+= 9; val = val >> 9; }
4233 while (val >= 16) { n+= 4; val >>= 4; }
4234 while (val >= 2) { n+= 1; val >>= 1; }
4240 /*----------------------------------------------------------------------------*/
4242 * @brief Generate the WMM Param IE
4244 * \param[in] prAdapter Adapter pointer
4245 * @param prMsduInfo The TX MMPDU
4249 /*----------------------------------------------------------------------------*/
4251 mqmGenerateWmmParamIE (
4252 IN P_ADAPTER_T prAdapter,
4253 IN P_MSDU_INFO_T prMsduInfo
4256 P_IE_WMM_PARAM_T prIeWmmParam;
4258 UINT_8 aucWfaOui[] = VENDOR_OUI_WFA;
4267 P_BSS_INFO_T prBssInfo;
4268 P_STA_RECORD_T prStaRec;
4269 ENUM_WMM_ACI_T eAci;
4271 DEBUGFUNC("mqmGenerateWmmParamIE");
4272 DBGLOG(QM, LOUD,("\n"));
4276 /* In case QoS is not turned off, exit directly */
4277 if(!prAdapter->rWifiVar.fgSupportQoS){
4281 prStaRec = cnmGetStaRecByIndex(prAdapter, prMsduInfo->ucStaRecIndex);
4284 if(!prStaRec->fgIsQoS) {
4289 prBssInfo = &(prAdapter->rWifiVar.arBssInfo[prMsduInfo->ucNetworkType]);
4291 if(!prBssInfo->fgIsQBSS) { return; }
4293 #if 0 // 20120220 frog: update beacon content & change OP mode is a separate event for P2P network.
4294 if( prBssInfo->eCurrentOPMode != OP_MODE_ACCESS_POINT &&
4295 prBssInfo->eCurrentOPMode != OP_MODE_BOW)
4301 prIeWmmParam = (P_IE_WMM_PARAM_T)
4302 ((PUINT_8) prMsduInfo->prPacket + prMsduInfo->u2FrameLength);
4304 prIeWmmParam->ucId = ELEM_ID_WMM;
4305 prIeWmmParam->ucLength = ELEM_MAX_LEN_WMM_PARAM;
4307 /* WMM-2.2.1 WMM Information Element Field Values */
4308 prIeWmmParam->aucOui[0] = aucWfaOui[0];
4309 prIeWmmParam->aucOui[1] = aucWfaOui[1];
4310 prIeWmmParam->aucOui[2] = aucWfaOui[2];
4311 prIeWmmParam->ucOuiType = VENDOR_OUI_TYPE_WMM;
4312 prIeWmmParam->ucOuiSubtype = VENDOR_OUI_SUBTYPE_WMM_PARAM;
4314 prIeWmmParam->ucVersion = VERSION_WMM;
4315 prIeWmmParam->ucQosInfo = (prBssInfo->ucWmmParamSetCount & WMM_QOS_INFO_PARAM_SET_CNT);
4317 /* UAPSD intial queue configurations (delivery and trigger enabled)*/
4318 if(prAdapter->rWifiVar.fgSupportUAPSD){
4320 prIeWmmParam->ucQosInfo |= WMM_QOS_INFO_UAPSD;
4324 /* EDCA parameter */
4326 for(eAci = 0; eAci < WMM_AC_INDEX_NUM; eAci++){
4328 //DBGLOG(QM, LOUD, ("MQM: eAci = %d, ACM = %d, Aifsn = %d, CWmin = %d, CWmax = %d, TxopLimit = %d\n",
4329 // eAci,prBssInfo->arACQueParmsForBcast[eAci].fgIsACMSet ,
4330 // prBssInfo->arACQueParmsForBcast[eAci].u2Aifsn,
4331 // prBssInfo->arACQueParmsForBcast[eAci].u2CWmin,
4332 // prBssInfo->arACQueParmsForBcast[eAci].u2CWmax,
4333 // prBssInfo->arACQueParmsForBcast[eAci].u2TxopLimit));
4335 *( ((PUINT_8)(&prIeWmmParam->ucAciAifsn_BE)) + (eAci <<2) ) = (UINT_8) (aucACI[eAci]
4336 | (prBssInfo->arACQueParmsForBcast[eAci].fgIsACMSet ? WMM_ACIAIFSN_ACM:0 )
4337 | (prBssInfo->arACQueParmsForBcast[eAci].u2Aifsn & (WMM_ACIAIFSN_AIFSN)));
4339 *( ((PUINT_8)(&prIeWmmParam->ucEcw_BE)) + (eAci <<2) ) = (UINT_8) (0
4340 | (((prBssInfo->aucCWminLog2ForBcast[eAci] )) & WMM_ECW_WMIN_MASK)
4341 | ((((prBssInfo->aucCWmaxLog2ForBcast[eAci] )) << WMM_ECW_WMAX_OFFSET ) & WMM_ECW_WMAX_MASK)
4344 *( ((PUINT_8)(&prIeWmmParam->ucEcw_BE)) + (eAci <<2) ) = (UINT_8) (0
4345 | (cwlog2((prBssInfo->arACQueParmsForBcast[eAci].u2CWmin + 1)) & WMM_ECW_WMIN_MASK)
4346 | ((cwlog2((prBssInfo->arACQueParmsForBcast[eAci].u2CWmax + 1)) << WMM_ECW_WMAX_OFFSET ) & WMM_ECW_WMAX_MASK)
4350 WLAN_SET_FIELD_16( ((PUINT_8)(prIeWmmParam->aucTxopLimit_BE)) + (eAci<<2)
4351 , prBssInfo->arACQueParmsForBcast[eAci].u2TxopLimit);
4355 /* Increment the total IE length for the Element ID and Length fields. */
4356 prMsduInfo->u2FrameLength += IE_SIZE(prIeWmmParam);
4365 IN P_ADAPTER_T prAdapter,
4366 IN ENUM_NETWORK_TYPE_INDEX_T eNetworkType,
4367 IN UINT_8 ucStaRecIdx,
4368 IN P_MSDU_INFO_T prMsduInfo,
4369 IN ENUM_FRAME_TYPE_IN_CMD_Q_T eFrameType
4372 P_BSS_INFO_T prBssInfo;
4373 P_STA_RECORD_T prStaRec;
4374 P_WLAN_MAC_HEADER_T prWlanFrame;
4375 UINT_16 u2TxFrameCtrl;
4377 DEBUGFUNC("qmGetFrameAction");
4379 #if (NIC_TX_BUFF_COUNT_TC4 > 2)
4380 #define QM_MGMT_QUUEUD_THRESHOLD 2
4382 #define QM_MGMT_QUUEUD_THRESHOLD 1
4385 DATA_STRUC_INSPECTING_ASSERT(QM_MGMT_QUUEUD_THRESHOLD <= (NIC_TX_BUFF_COUNT_TC4));
4386 DATA_STRUC_INSPECTING_ASSERT(QM_MGMT_QUUEUD_THRESHOLD > 0);
4388 prBssInfo = &(prAdapter->rWifiVar.arBssInfo[eNetworkType]);
4389 prStaRec = QM_GET_STA_REC_PTR_FROM_INDEX(prAdapter, ucStaRecIdx);
4391 /* XXX Check BOW P2P AIS time ot set active */
4392 if (!IS_BSS_ACTIVE(prBssInfo)) {
4393 if (eFrameType == FRAME_TYPE_MMPDU) {
4394 prWlanFrame = (P_WLAN_MAC_HEADER_T) prMsduInfo->prPacket;
4395 u2TxFrameCtrl = (prWlanFrame->u2FrameCtrl) & MASK_FRAME_TYPE; // Optimized for ARM
4396 if ((u2TxFrameCtrl == MAC_FRAME_DEAUTH) && (prMsduInfo->pfTxDoneHandler == NULL)) {
4397 return FRAME_ACTION_TX_PKT;
4402 DBGLOG(QM, INFO, ("Drop packets Action (Inactive %u).\n",prBssInfo->ucNetTypeIndex));
4403 TX_INC_CNT(&prAdapter->rTxCtrl, TX_INACTIVE_BSS_DROP);
4404 return FRAME_ACTION_DROP_PKT;
4407 /* TODO Handle disconnect issue */
4409 /* P2P probe Request frame */
4411 if(eFrameType == FRAME_TYPE_MMPDU) {
4412 ASSERT(prMsduInfo!=NULL);
4413 prWlanFrame = (P_WLAN_MAC_HEADER_T) prMsduInfo->prPacket;
4414 u2TxFrameCtrl = (prWlanFrame->u2FrameCtrl) & MASK_FRAME_TYPE; // Optimized for ARM
4416 if (u2TxFrameCtrl == MAC_FRAME_BEACON ) {
4417 if( prBssInfo->fgIsNetAbsent) {
4418 return FRAME_ACTION_DROP_PKT;
4421 else if (u2TxFrameCtrl == MAC_FRAME_PROBE_RSP) {
4422 if( prBssInfo->fgIsNetAbsent) {
4426 else if (u2TxFrameCtrl == MAC_FRAME_DEAUTH) {
4427 if( prBssInfo->fgIsNetAbsent) {
4430 DBGLOG(P2P, LOUD, ("Sending DEAUTH Frame\n"));
4431 return FRAME_ACTION_TX_PKT;
4433 /* MMPDU with prStaRec && fgIsInUse not check fgIsNetActive */
4434 else if(u2TxFrameCtrl == MAC_FRAME_ASSOC_REQ
4435 || u2TxFrameCtrl == MAC_FRAME_AUTH
4436 || u2TxFrameCtrl == MAC_FRAME_REASSOC_REQ
4437 || u2TxFrameCtrl == MAC_FRAME_PROBE_REQ
4438 || u2TxFrameCtrl == MAC_FRAME_ACTION) {
4441 if(prStaRec->fgIsInPS) {
4442 if( nicTxGetResource (prAdapter, TC4_INDEX)>= QM_MGMT_QUUEUD_THRESHOLD) {
4443 return FRAME_ACTION_TX_PKT;
4446 return FRAME_ACTION_QUEUE_PKT;
4450 return FRAME_ACTION_TX_PKT;
4454 return FRAME_ACTION_TX_PKT;
4457 if (!prStaRec->fgIsInUse) {
4458 return FRAME_ACTION_DROP_PKT;
4462 } /* FRAME_TYPE_MMPDU */
4463 else if ((eFrameType == FRAME_TYPE_802_1X)){
4466 return FRAME_ACTION_TX_PKT;
4469 if (!prStaRec->fgIsInUse) {
4470 return FRAME_ACTION_DROP_PKT;
4472 if(prStaRec->fgIsInPS) {
4473 if( nicTxGetResource (prAdapter, TC4_INDEX)>= QM_MGMT_QUUEUD_THRESHOLD) {
4474 return FRAME_ACTION_TX_PKT;
4477 return FRAME_ACTION_QUEUE_PKT;
4482 } /* FRAME_TYPE_802_1X */
4483 else if ((!IS_BSS_ACTIVE(prBssInfo))
4485 || (!prStaRec->fgIsInUse)){
4486 return FRAME_ACTION_DROP_PKT;
4490 if (prBssInfo->fgIsNetAbsent){
4491 DBGLOG(QM, LOUD, ("Queue packets (Absent %u).\n",prBssInfo->ucNetTypeIndex));
4492 return FRAME_ACTION_QUEUE_PKT;
4495 if (prStaRec && prStaRec->fgIsInPS){
4496 DBGLOG(QM, LOUD, ("Queue packets (PS %u).\n",prStaRec->fgIsInPS));
4497 return FRAME_ACTION_QUEUE_PKT;
4500 switch (eFrameType){
4501 case FRAME_TYPE_802_1X:
4502 if (!prStaRec->fgIsValid){
4503 return FRAME_ACTION_QUEUE_PKT;
4507 case FRAME_TYPE_MMPDU:
4515 return FRAME_ACTION_TX_PKT;
4519 /*----------------------------------------------------------------------------*/
4521 * \brief Handle BSS change operation Event from the FW
4523 * \param[in] prAdapter Adapter pointer
4524 * \param[in] prEvent The event packet from the FW
4528 /*----------------------------------------------------------------------------*/
4530 qmHandleEventBssAbsencePresence(
4531 IN P_ADAPTER_T prAdapter,
4532 IN P_WIFI_EVENT_T prEvent
4535 P_EVENT_BSS_ABSENCE_PRESENCE_T prEventBssStatus;
4536 P_BSS_INFO_T prBssInfo;
4537 BOOLEAN fgIsNetAbsentOld;
4539 prEventBssStatus = (P_EVENT_BSS_ABSENCE_PRESENCE_T)prEvent;
4540 prBssInfo = &(prAdapter->rWifiVar.arBssInfo[prEventBssStatus->ucNetTypeIdx]);
4541 fgIsNetAbsentOld = prBssInfo->fgIsNetAbsent;
4542 prBssInfo->fgIsNetAbsent = prEventBssStatus->fgIsAbsent;
4543 prBssInfo->ucBssFreeQuota = prEventBssStatus->ucBssFreeQuota;
4545 //DBGLOG(QM, TRACE, ("qmHandleEventBssAbsencePresence (ucNetTypeIdx=%d, fgIsAbsent=%d, FreeQuota=%d)\n",
4546 // prEventBssStatus->ucNetTypeIdx, prBssInfo->fgIsNetAbsent, prBssInfo->ucBssFreeQuota));
4548 DBGLOG(QM, TRACE, ("NAF=%d,%d,%d\n",
4549 prEventBssStatus->ucNetTypeIdx, prBssInfo->fgIsNetAbsent, prBssInfo->ucBssFreeQuota));
4551 if(!prBssInfo->fgIsNetAbsent) {
4552 QM_DBG_CNT_INC(&(prAdapter->rQM),QM_DBG_CNT_27);
4555 QM_DBG_CNT_INC(&(prAdapter->rQM),QM_DBG_CNT_28);
4557 /* From Absent to Present */
4558 if ((fgIsNetAbsentOld) && (!prBssInfo->fgIsNetAbsent)){
4559 kalSetEvent(prAdapter->prGlueInfo);
4564 /*----------------------------------------------------------------------------*/
4566 * \brief Handle STA change PS mode Event from the FW
4568 * \param[in] prAdapter Adapter pointer
4569 * \param[in] prEvent The event packet from the FW
4573 /*----------------------------------------------------------------------------*/
4575 qmHandleEventStaChangePsMode(
4576 IN P_ADAPTER_T prAdapter,
4577 IN P_WIFI_EVENT_T prEvent
4580 P_EVENT_STA_CHANGE_PS_MODE_T prEventStaChangePsMode;
4581 P_STA_RECORD_T prStaRec;
4582 BOOLEAN fgIsInPSOld;
4584 //DbgPrint("QM:Event -RxBa\n");
4586 prEventStaChangePsMode = (P_EVENT_STA_CHANGE_PS_MODE_T)prEvent;
4587 prStaRec = QM_GET_STA_REC_PTR_FROM_INDEX(prAdapter, prEventStaChangePsMode->ucStaRecIdx);
4592 fgIsInPSOld = prStaRec->fgIsInPS;
4593 prStaRec->fgIsInPS = prEventStaChangePsMode->fgIsInPs;
4598 prEventStaChangePsMode->ucUpdateMode,
4599 prEventStaChangePsMode->ucFreeQuota);
4601 //DBGLOG(QM, TRACE, ("qmHandleEventStaChangePsMode (ucStaRecIdx=%d, fgIsInPs=%d)\n",
4602 // prEventStaChangePsMode->ucStaRecIdx, prStaRec->fgIsInPS));
4605 //DBGLOG(QM, TRACE, ("PS=%d,%d\n",
4606 // prEventStaChangePsMode->ucStaRecIdx, prStaRec->fgIsInPS));
4608 /* From PS to Awake */
4609 if ((fgIsInPSOld) && (!prStaRec->fgIsInPS)){
4610 kalSetEvent(prAdapter->prGlueInfo);
4615 /*----------------------------------------------------------------------------*/
4617 * \brief Update STA free quota Event from FW
4619 * \param[in] prAdapter Adapter pointer
4620 * \param[in] prEvent The event packet from the FW
4624 /*----------------------------------------------------------------------------*/
4626 qmHandleEventStaUpdateFreeQuota(
4627 IN P_ADAPTER_T prAdapter,
4628 IN P_WIFI_EVENT_T prEvent
4631 P_EVENT_STA_UPDATE_FREE_QUOTA_T prEventStaUpdateFreeQuota;
4632 P_STA_RECORD_T prStaRec;
4635 prEventStaUpdateFreeQuota = (P_EVENT_STA_UPDATE_FREE_QUOTA_T)prEvent;
4636 prStaRec = QM_GET_STA_REC_PTR_FROM_INDEX(prAdapter, prEventStaUpdateFreeQuota->ucStaRecIdx);
4640 if(prStaRec->fgIsInPS) {
4644 prEventStaUpdateFreeQuota->ucUpdateMode,
4645 prEventStaUpdateFreeQuota->ucFreeQuota);
4647 kalSetEvent(prAdapter->prGlueInfo);
4650 DBGLOG(QM, TRACE, ("qmHandleEventStaUpdateFreeQuota (ucStaRecIdx=%d, ucUpdateMode=%d, ucFreeQuota=%d)\n",
4651 prEventStaUpdateFreeQuota->ucStaRecIdx,
4652 prEventStaUpdateFreeQuota->ucUpdateMode,
4653 prEventStaUpdateFreeQuota->ucFreeQuota));
4656 DBGLOG(QM, TRACE, ("UFQ=%d,%d,%d\n",
4657 prEventStaUpdateFreeQuota->ucStaRecIdx,
4658 prEventStaUpdateFreeQuota->ucUpdateMode,
4659 prEventStaUpdateFreeQuota->ucFreeQuota));
4667 /*----------------------------------------------------------------------------*/
4669 * \brief Update STA free quota
4671 * \param[in] prStaRec the STA
4672 * \param[in] ucUpdateMode the method to update free quota
4673 * \param[in] ucFreeQuota the value for update
4677 /*----------------------------------------------------------------------------*/
4680 IN P_ADAPTER_T prAdapter,
4681 IN P_STA_RECORD_T prStaRec,
4682 IN UINT_8 ucUpdateMode,
4683 IN UINT_8 ucFreeQuota
4687 UINT_8 ucFreeQuotaForNonDelivery;
4688 UINT_8 ucFreeQuotaForDelivery;
4691 DBGLOG(QM, LOUD, ("qmUpdateFreeQuota orig ucFreeQuota=%d Mode %u New %u\n",
4692 prStaRec->ucFreeQuota, ucUpdateMode, ucFreeQuota ));
4694 if(!prStaRec->fgIsInPS)return;
4696 switch (ucUpdateMode) {
4697 case FREE_QUOTA_UPDATE_MODE_INIT:
4698 case FREE_QUOTA_UPDATE_MODE_OVERWRITE:
4699 prStaRec->ucFreeQuota = ucFreeQuota;
4701 case FREE_QUOTA_UPDATE_MODE_INCREASE:
4702 prStaRec->ucFreeQuota += ucFreeQuota;
4704 case FREE_QUOTA_UPDATE_MODE_DECREASE:
4705 prStaRec->ucFreeQuota -= ucFreeQuota;
4711 DBGLOG(QM, LOUD, ("qmUpdateFreeQuota new ucFreeQuota=%d)\n",
4712 prStaRec->ucFreeQuota ));
4714 ucFreeQuota = prStaRec->ucFreeQuota;
4716 ucFreeQuotaForNonDelivery = 0;
4717 ucFreeQuotaForDelivery = 0;
4719 if(ucFreeQuota > 0) {
4720 if( prStaRec->fgIsQoS && prStaRec->fgIsUapsdSupported
4721 /* && prAdapter->rWifiVar.fgSupportQoS
4722 && prAdapter->rWifiVar.fgSupportUAPSD*/) {
4723 /* XXX We should assign quota to aucFreeQuotaPerQueue[NUM_OF_PER_STA_TX_QUEUES] */
4725 if(prStaRec->ucFreeQuotaForNonDelivery > 0 && prStaRec->ucFreeQuotaForDelivery > 0) {
4726 ucFreeQuotaForNonDelivery = ucFreeQuota>>1;
4727 ucFreeQuotaForDelivery = ucFreeQuota - ucFreeQuotaForNonDelivery;
4729 else if(prStaRec->ucFreeQuotaForNonDelivery == 0 && prStaRec->ucFreeQuotaForDelivery == 0) {
4730 ucFreeQuotaForNonDelivery = ucFreeQuota>>1;
4731 ucFreeQuotaForDelivery = ucFreeQuota - ucFreeQuotaForNonDelivery;
4733 else if(prStaRec->ucFreeQuotaForNonDelivery > 0) {
4734 /* NonDelivery is not busy */
4735 if(ucFreeQuota >= 3 ) {
4736 ucFreeQuotaForNonDelivery = 2;
4737 ucFreeQuotaForDelivery = ucFreeQuota - ucFreeQuotaForNonDelivery ;
4740 ucFreeQuotaForDelivery = ucFreeQuota;
4741 ucFreeQuotaForNonDelivery = 0;
4744 else if(prStaRec->ucFreeQuotaForDelivery > 0) {
4745 /* Delivery is not busy */
4746 if(ucFreeQuota >= 3 ) {
4747 ucFreeQuotaForDelivery = 2;
4748 ucFreeQuotaForNonDelivery = ucFreeQuota - ucFreeQuotaForDelivery;
4751 ucFreeQuotaForNonDelivery = ucFreeQuota;
4752 ucFreeQuotaForDelivery = 0;
4758 /* !prStaRec->fgIsUapsdSupported */
4759 ucFreeQuotaForNonDelivery = ucFreeQuota;
4760 ucFreeQuotaForDelivery = 0;
4762 } /* ucFreeQuota > 0 */
4764 prStaRec->ucFreeQuotaForDelivery = ucFreeQuotaForDelivery;
4765 prStaRec->ucFreeQuotaForNonDelivery = ucFreeQuotaForNonDelivery;
4767 DBGLOG(QM, LOUD, ("new QuotaForDelivery = %d QuotaForNonDelivery = %d\n",
4768 prStaRec->ucFreeQuotaForDelivery, prStaRec->ucFreeQuotaForNonDelivery ));
4772 /*----------------------------------------------------------------------------*/
4774 * \brief Return the reorder queued RX packets
4778 * \return The number of queued RX packets
4780 /*----------------------------------------------------------------------------*/
4782 qmGetRxReorderQueuedBufferCount(
4783 IN P_ADAPTER_T prAdapter
4787 P_QUE_MGT_T prQM = &prAdapter->rQM;
4789 /* XXX The summation may impact the performance */
4790 for(i =0; i<CFG_NUM_OF_RX_BA_AGREEMENTS; i++){
4791 u4Total += prQM->arRxBaTable[i].rReOrderQue.u4NumElem;
4793 if(QUEUE_IS_EMPTY(&(prQM->arRxBaTable[i].rReOrderQue))){
4794 ASSERT(prQM->arRxBaTable[i].rReOrderQue == 0);
4798 ASSERT(u4Total <=( CFG_NUM_OF_QM_RX_PKT_NUM*2));