que_mgt.c 155 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743374437453746374737483749375037513752375337543755375637573758375937603761376237633764376537663767376837693770377137723773377437753776377737783779378037813782378337843785378637873788378937903791379237933794379537963797379837993800380138023803380438053806380738083809381038113812381338143815381638173818381938203821382238233824382538263827382838293830383138323833383438353836383738383839384038413842384338443845384638473848384938503851385238533854385538563857385838593860386138623863386438653866386738683869387038713872387338743875387638773878387938803881388238833884388538863887388838893890389138923893389438953896389738983899390039013902390339043905390639073908390939103911391239133914391539163917391839193920392139223923392439253926392739283929393039313932393339343935393639373938393939403941394239433944394539463947394839493950395139523953395439553956395739583959396039613962396339643965396639673968396939703971397239733974397539763977397839793980398139823983398439853986398739883989399039913992399339943995399639973998399940004001400240034004400540064007400840094010401140124013401440154016401740184019402040214022402340244025402640274028402940304031403240334034403540364037403840394040404140424043404440454046404740484049405040514052405340544055405640574058405940604061406240634064406540664067406840694070407140724073407440754076407740784079408040814082408340844085408640874088408940904091409240934094409540964097409840994100410141024103410441054106410741084109411041114112411341144115411641174118411941204121412241234124412541264127412841294130413141324133413441354136413741384139414041414142414341444145414641474148414941504151415241534154415541564157415841594160416141624163416441654166416741684169417041714172417341744175417641774178417941804181418241834184418541864187418841894190419141924193419441954196419741984199420042014202420342044205420642074208420942104211421242134214421542164217421842194220422142224223422442254226422742284229423042314232423342344235423642374238423942404241424242434244424542464247424842494250425142524253425442554256425742584259426042614262426342644265426642674268426942704271427242734274427542764277427842794280428142824283428442854286428742884289429042914292429342944295429642974298429943004301430243034304430543064307430843094310431143124313431443154316431743184319432043214322432343244325432643274328432943304331433243334334433543364337433843394340434143424343434443454346434743484349435043514352435343544355435643574358435943604361436243634364436543664367436843694370437143724373437443754376437743784379438043814382438343844385438643874388438943904391439243934394439543964397439843994400440144024403440444054406440744084409441044114412441344144415441644174418441944204421442244234424442544264427442844294430443144324433443444354436443744384439444044414442444344444445444644474448444944504451445244534454445544564457445844594460446144624463446444654466446744684469447044714472447344744475447644774478447944804481448244834484448544864487448844894490449144924493449444954496449744984499450045014502450345044505450645074508450945104511451245134514451545164517451845194520452145224523452445254526452745284529453045314532453345344535453645374538453945404541454245434544454545464547454845494550455145524553455445554556455745584559456045614562456345644565456645674568456945704571457245734574457545764577457845794580458145824583458445854586458745884589459045914592459345944595459645974598459946004601460246034604460546064607460846094610461146124613461446154616461746184619462046214622462346244625462646274628462946304631463246334634463546364637463846394640464146424643464446454646464746484649465046514652465346544655465646574658465946604661466246634664466546664667466846694670467146724673467446754676467746784679468046814682468346844685468646874688468946904691469246934694469546964697469846994700470147024703470447054706470747084709471047114712471347144715471647174718471947204721472247234724472547264727472847294730473147324733473447354736473747384739474047414742474347444745474647474748474947504751475247534754475547564757475847594760476147624763476447654766476747684769477047714772477347744775477647774778477947804781478247834784478547864787478847894790479147924793479447954796479747984799480048014802480348044805480648074808480948104811481248134814481548164817481848194820482148224823482448254826482748284829483048314832483348344835483648374838483948404841484248434844484548464847484848494850485148524853485448554856485748584859486048614862486348644865486648674868486948704871487248734874487548764877487848794880488148824883488448854886488748884889489048914892489348944895489648974898489949004901490249034904490549064907490849094910491149124913491449154916491749184919492049214922492349244925492649274928492949304931493249334934493549364937493849394940494149424943494449454946494749484949495049514952495349544955495649574958495949604961496249634964496549664967496849694970497149724973497449754976497749784979498049814982498349844985498649874988498949904991499249934994499549964997499849995000500150025003500450055006500750085009501050115012501350145015501650175018501950205021
  1. /*
  2. ** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/nic/que_mgt.c#1
  3. */
  4. /*! \file "que_mgt.c"
  5. \brief TX/RX queues management
  6. The main tasks of queue management include TC-based HIF TX flow control,
  7. adaptive TC quota adjustment, HIF TX grant scheduling, Power-Save
  8. forwarding control, RX packet reordering, and RX BA agreement management.
  9. */
  10. /*
  11. ** Log: que_mgt.c
  12. **
  13. ** 04 11 2013 yuche.tsai
  14. ** [ALPS00542142] [Pre-SQC][6627][W]use wifi direct press cancel connect, phone all stop.
  15. ** Drop the probe response packet when absent.
  16. **
  17. ** 04 09 2013 yuche.tsai
  18. ** [ALPS00542142] [Pre-SQC][6627][W]use wifi direct press cancel connect, phone all stop.
  19. ** Fix CMD buffer short issue.
  20. **
  21. ** 04 09 2013 yuche.tsai
  22. ** [ALPS00542142] [Pre-SQC][6627][W]use wifi direct press cancel connect, phone all stop.
  23. ** Fix CMD buffer short issue.
  24. *
  25. * 03 02 2012 terry.wu
  26. * NULL
  27. * Sync CFG80211 modification from branch 2,2.
  28. *
  29. * 02 23 2012 eddie.chen
  30. * [WCXRP00001194] [MT6620][DRV/FW] follow admission control bit to change the enqueue rule
  31. * Change the enqueue policy when ACM = 1.
  32. *
  33. * 11 22 2011 yuche.tsai
  34. * NULL
  35. * Code refine, remove one #if 0 code.
  36. *
  37. * 11 19 2011 eddie.chen
  38. * [WCXRP00001096] [MT6620 Wi-Fi][Driver/FW] Enhance the log function (xlog)
  39. * Add xlog for tx
  40. *
  41. * 11 18 2011 yuche.tsai
  42. * NULL
  43. * CONFIG P2P support RSSI query, default turned off.
  44. *
  45. * 11 18 2011 eddie.chen
  46. * [WCXRP00001096] [MT6620 Wi-Fi][Driver/FW] Enhance the log function (xlog)
  47. * Fix xlog format to hex format
  48. *
  49. * 11 17 2011 tsaiyuan.hsu
  50. * [WCXRP00001115] [MT6620 Wi-Fi][DRV] avoid deactivating staRec when changing state 3 to 3.
  51. * avoid deactivating staRec when changing state from 3 to 3.
  52. *
  53. * 11 11 2011 tsaiyuan.hsu
  54. * [WCXRP00001083] [MT6620 Wi-Fi][DRV]] dump debug counter or frames when debugging is triggered
  55. * add debug msg for xlog.
  56. *
  57. * 11 11 2011 tsaiyuan.hsu
  58. * [WCXRP00001083] [MT6620 Wi-Fi][DRV]] dump debug counter or frames when debugging is triggered
  59. * add debug counters of bb and ar for xlog.
  60. *
  61. * 11 10 2011 eddie.chen
  62. * [WCXRP00001096] [MT6620 Wi-Fi][Driver/FW] Enhance the log function (xlog)
  63. * Use short name for xlog.
  64. *
  65. * 11 10 2011 eddie.chen
  66. * [WCXRP00001096] [MT6620 Wi-Fi][Driver/FW] Enhance the log function (xlog)
  67. * Modify the QM xlog level and remove LOG_FUNC.
  68. *
  69. * 11 10 2011 chinglan.wang
  70. * NULL
  71. * [WiFi WPS]Can't switch to new AP via WPS PBC when there existing a connection to another AP.
  72. *
  73. * 11 09 2011 chinglan.wang
  74. * NULL
  75. * [WiFi direct]Can't make P2P connect via PBC.
  76. *
  77. * 11 08 2011 eddie.chen
  78. * [WCXRP00001096] [MT6620 Wi-Fi][Driver/FW] Enhance the log function (xlog)
  79. * Add xlog function.
  80. *
  81. * 11 07 2011 tsaiyuan.hsu
  82. * [WCXRP00001083] [MT6620 Wi-Fi][DRV]] dump debug counter or frames when debugging is triggered
  83. * add debug counters and periodically dump counters for debugging.
  84. *
  85. * 11 01 2011 chinglan.wang
  86. * NULL
  87. * Modify the Wi-Fi method of the flush TX queue when disconnect the AP.
  88. * If disconnect the AP and flush all the data frame in the TX queue, WPS cannot do the 4-way handshake to connect to
  89. * the AP..
  90. *
  91. * 10 25 2011 wh.su
  92. * [WCXRP00001059] [MT6620 Wi-Fi][Driver][P2P] Fixed sometimes data (1x) will not indicate to upper layer due ba check
  93. * un-expect
  94. * let the Rx BA accept even the sta not valid.
  95. *
  96. * 09 28 2011 tsaiyuan.hsu
  97. * [WCXRP00000900] [MT5931 Wi-Fi] Improve balance of TX and RX
  98. * enlarge window size only by 4.
  99. *
  100. * 09 01 2011 tsaiyuan.hsu
  101. * [WCXRP00000900] [MT5931 Wi-Fi] Improve balance of TX and RX
  102. * set rx window size as twice buffer size.
  103. *
  104. * 08 23 2011 yuche.tsai
  105. * NULL
  106. * Fix multicast address list issue.
  107. *
  108. * 08 03 2011 tsaiyuan.hsu
  109. * [WCXRP00000900] [MT5931 Wi-Fi] Improve balance of TX and RX
  110. * force window size at least 16.
  111. *
  112. * 08 02 2011 yuche.tsai
  113. * [WCXRP00000896] [Volunteer Patch][WiFi Direct][Driver] GO with multiple client, TX deauth to a disconnecting device
  114. * issue.
  115. * Fix GO send deauth frame issue.
  116. *
  117. * 07 26 2011 eddie.chen
  118. * [WCXRP00000874] [MT5931][DRV] API for query the RX reorder queued packets counter
  119. * API for query the RX reorder queued packets counter.
  120. *
  121. * 07 07 2011 eddie.chen
  122. * [WCXRP00000834] [MT6620 Wi-Fi][DRV] Send 1x packet when peer STA is in PS.
  123. * Add setEvent when free quota is updated.
  124. *
  125. * 07 05 2011 eddie.chen
  126. * [WCXRP00000834] [MT6620 Wi-Fi][DRV] Send 1x packet when peer STA is in PS.
  127. * Send 1x when peer STA is in PS.
  128. *
  129. * 05 31 2011 eddie.chen
  130. * [WCXRP00000753] [MT5931 Wi-Fi][DRV] Adjust QM for MT5931
  131. * Fix the QM quota in MT5931.
  132. *
  133. * 05 11 2011 eddie.chen
  134. * [WCXRP00000709] [MT6620 Wi-Fi][Driver] Check free number before copying broadcast packet
  135. * Fix dest type when GO packet copying.
  136. *
  137. * 05 09 2011 yuche.tsai
  138. * [WCXRP00000712] [Volunteer Patch][MT6620][Driver] Sending deauth issue when Hot spot is disabled. (GO is dissolved)
  139. * Deauthentication frame is not bound to network active status.
  140. *
  141. * 05 09 2011 eddie.chen
  142. * [WCXRP00000709] [MT6620 Wi-Fi][Driver] Check free number before copying broadcast packet
  143. * Check free number before copying broadcast packet.
  144. *
  145. * 04 14 2011 eddie.chen
  146. * [WCXRP00000603] [MT6620 Wi-Fi][DRV] Fix Klocwork warning
  147. * Check the SW RFB free. Fix the compile warning..
  148. *
  149. * 04 12 2011 eddie.chen
  150. * [WCXRP00000617] [MT6620 Wi-Fi][DRV/FW] Fix for sigma
  151. * Fix the sta index in processing security frame
  152. * Simple flow control for TC4 to avoid mgt frames for PS STA to occupy the TC4
  153. * Add debug message.
  154. *
  155. * 04 11 2011 yuche.tsai
  156. * [WCXRP00000627] [Volunteer Patch][MT6620][Driver] Pending MMPUD of P2P Network may crash system issue.
  157. * Fix kernel panic issue when MMPDU of P2P is pending in driver.
  158. *
  159. * 04 08 2011 eddie.chen
  160. * [WCXRP00000617] [MT6620 Wi-Fi][DRV/FW] Fix for sigma
  161. * Fix for sigma
  162. *
  163. * 03 28 2011 eddie.chen
  164. * [WCXRP00000603] [MT6620 Wi-Fi][DRV] Fix Klocwork warning
  165. * Fix Klockwork warning.
  166. *
  167. * 03 28 2011 eddie.chen
  168. * [WCXRP00000602] [MT6620 Wi-Fi][DRV] Fix wmm parameters in beacon for BOW
  169. * Fix wmm parameters in beacon for BOW.
  170. *
  171. * 03 15 2011 eddie.chen
  172. * [WCXRP00000554] [MT6620 Wi-Fi][DRV] Add sw control debug counter
  173. * Add sw debug counter for QM.
  174. *
  175. * 02 23 2011 eddie.chen
  176. * [WCXRP00000463] [MT6620 Wi-Fi][FW/Driver][Hotspot] Cannot update WMM PS STA's partital bitmap
  177. * Fix parsing WMM INFO and bmp delivery bitmap definition.
  178. *
  179. * 02 17 2011 eddie.chen
  180. * [WCXRP00000458] [MT6620 Wi-Fi][Driver] BOW Concurrent - ProbeResp was exist in other channel
  181. * 1) Change GetFrameAction decision when BSS is absent.
  182. * 2) Check channel and resource in processing ProbeRequest
  183. *
  184. * 02 08 2011 eddie.chen
  185. * [WCXRP00000426] [MT6620 Wi-Fi][FW/Driver] Add STA aging timeout and defualtHwRatein AP mode
  186. * Add event STA agint timeout
  187. *
  188. * 01 27 2011 tsaiyuan.hsu
  189. * [WCXRP00000392] [MT6620 Wi-Fi][Driver] Add Roaming Support
  190. * add roaming fsm
  191. * 1. not support 11r, only use strength of signal to determine roaming.
  192. * 2. not enable CFG_SUPPORT_ROAMING until completion of full test.
  193. * 3. in 6620, adopt work-around to avoid sign extension problem of cck of hw
  194. * 4. assume that change of link quality in smooth way.
  195. *
  196. * 01 25 2011 yuche.tsai
  197. * [WCXRP00000388] [Volunteer Patch][MT6620][Driver/Fw] change Station Type in station record.
  198. * Change Station Type in Station Record, Modify MACRO definition for getting station type & network type index & Role.
  199. *
  200. * 01 24 2011 eddie.chen
  201. * [WCXRP00000385] [MT6620 Wi-Fi][DRV] Add destination decision for forwarding packets
  202. * Remove comments.
  203. *
  204. * 01 24 2011 eddie.chen
  205. * [WCXRP00000385] [MT6620 Wi-Fi][DRV] Add destination decision for forwarding packets
  206. * Add destination decision in AP mode.
  207. *
  208. * 01 14 2011 wh.su
  209. * [WCXRP00000099] [MT6620 Wi-Fi] [Driver] workaround to let the de-authentication can be send out[WCXRP00000326]
  210. * [MT6620][Wi-Fi][Driver] check in the binary format gl_sec.o.new instead of use change type!!!
  211. * Allow 802.1x can be send even the net is not active due the drver / fw sync issue.
  212. *
  213. * 01 13 2011 eddie.chen
  214. * [WCXRP00000322] Add WMM IE in beacon,
  215. Add per station flow control when STA is in PS
  216. * Fix typo and compile error.
  217. *
  218. * 01 12 2011 eddie.chen
  219. * [WCXRP00000322] Add WMM IE in beacon,
  220. Add per station flow control when STA is in PS
  221. * Fix WMM parameter condition for STA
  222. *
  223. * 01 12 2011 eddie.chen
  224. * [WCXRP00000322] Add WMM IE in beacon,
  225. Add per station flow control when STA is in PS
  226. * 1) Check Bss if support QoS before adding WMMIE
  227. * 2) Check if support prAdapter->rWifiVar QoS and uapsd in flow control
  228. *
  229. * 01 12 2011 george.huang
  230. * [WCXRP00000355] [MT6620 Wi-Fi] Set WMM-PS related setting with qualifying AP capability
  231. * Update MQM for WMM IE generation method
  232. *
  233. * 01 11 2011 eddie.chen
  234. * [WCXRP00000322] Add WMM IE in beacon,
  235. Add per station flow control when STA is in PS
  236. * Add per STA flow control when STA is in PS mode
  237. *
  238. * 01 03 2011 george.huang
  239. * [WCXRP00000152] [MT6620 Wi-Fi] AP mode power saving function
  240. * update prStaRec->fgIsUapsdSupported flag.
  241. *
  242. * 12 29 2010 eddie.chen
  243. * [WCXRP00000322] Add WMM IE in beacon,
  244. Add per station flow control when STA is in PS
  245. * Add WMM parameter for broadcast.
  246. *
  247. * 12 29 2010 eddie.chen
  248. * [WCXRP00000322] Add WMM IE in beacon,
  249. Add per station flow control when STA is in PS
  250. * 1) PS flow control event
  251. *
  252. * 2) WMM IE in beacon, assoc resp, probe resp
  253. *
  254. * 12 23 2010 george.huang
  255. * [WCXRP00000152] [MT6620 Wi-Fi] AP mode power saving function
  256. * 1. update WMM IE parsing, with ASSOC REQ handling
  257. * 2. extend U-APSD parameter passing from driver to FW
  258. *
  259. * 10 14 2010 wh.su
  260. * [WCXRP00000099] [MT6620 Wi-Fi] [Driver] workaround to let the de-authentication can be send out
  261. * use the #14 and modify the add code for check MMPDU.
  262. *
  263. * 10 14 2010 wh.su
  264. * [WCXRP00000099] [MT6620 Wi-Fi] [Driver] workaround to let the de-authentication can be send out
  265. * only MMPDU not check the netActive flag.
  266. *
  267. * 10 14 2010 wh.su
  268. * [WCXRP00000099] [MT6620 Wi-Fi] [Driver] workaround to let the de-authentication can be send out
  269. * not check the netActive flag for mgmt .
  270. *
  271. * 10 04 2010 cp.wu
  272. * [WCXRP00000077] [MT6620 Wi-Fi][Driver][FW] Eliminate use of ENUM_NETWORK_TYPE_T and replaced by
  273. * ENUM_NETWORK_TYPE_INDEX_T only
  274. * remove ENUM_NETWORK_TYPE_T definitions
  275. *
  276. * 09 21 2010 kevin.huang
  277. * [WCXRP00000052] [MT6620 Wi-Fi][Driver] Eliminate Linux Compile Warning
  278. * Eliminate Linux Compile Warning
  279. *
  280. * 08 30 2010 yarco.yang
  281. * NULL
  282. * Fixed klockwork error message
  283. *
  284. * 08 18 2010 yarco.yang
  285. * NULL
  286. * 1. Fixed HW checksum offload function not work under Linux issue.
  287. * 2. Add debug message.
  288. *
  289. * 08 10 2010 yarco.yang
  290. * NULL
  291. * Code refine
  292. *
  293. * 08 06 2010 yarco.yang
  294. * NULL
  295. * Update qmGetFrameAction() to allow P2P MGMT frame w/o STA_Record still can perform TX action
  296. *
  297. * 07 26 2010 cp.wu
  298. *
  299. * AIS-FSM FIX: return channel privilege even when the privilege is not granted yet
  300. * QM: qmGetFrameAction() won't assert when corresponding STA-REC index is not found
  301. *
  302. * 07 20 2010 yarco.yang
  303. *
  304. * Add to SetEvent when BSS is from Absent to Present or STA from PS to Awake
  305. *
  306. * 07 16 2010 yarco.yang
  307. *
  308. * 1. Support BSS Absence/Presence Event
  309. * 2. Support STA change PS mode Event
  310. * 3. Support BMC forwarding for AP mode.
  311. *
  312. * 07 14 2010 yarco.yang
  313. *
  314. * 1. Remove CFG_MQM_MIGRATION
  315. * 2. Add CMD_UPDATE_WMM_PARMS command
  316. *
  317. * 07 13 2010 yarco.yang
  318. *
  319. * [WPD00003849]
  320. * [MT6620 and MT5931] SW Migration, add qmGetFrameAction() API for CMD Queue Processing
  321. *
  322. * 07 09 2010 yarco.yang
  323. *
  324. * [MT6620 and MT5931] SW Migration: Add ADDBA support
  325. *
  326. * 07 08 2010 cp.wu
  327. *
  328. * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository.
  329. *
  330. * 07 08 2010 yarco.yang
  331. * [WPD00003837][MT6620]Data Path Refine
  332. * .
  333. *
  334. * 07 06 2010 yarco.yang
  335. * [WPD00003837][MT6620]Data Path Refine
  336. * Use fgInUse instead of fgIsValid for De-queue judgement
  337. *
  338. * 07 06 2010 yarco.yang
  339. * [WPD00003837][MT6620]Data Path Refine
  340. * For MMPDU, STA_REC will be decided by caller module
  341. *
  342. * 07 06 2010 yarco.yang
  343. * [WPD00003837][MT6620]Data Path Refine
  344. * Add MGMT Packet type for HIF_TX_HEADER
  345. *
  346. * 06 29 2010 yarco.yang
  347. * [WPD00003837][MT6620]Data Path Refine
  348. * replace g_rQM with Adpater->rQM
  349. *
  350. * 06 25 2010 cp.wu
  351. * [WPD00003833][MT6620 and MT5931] Driver migration
  352. * add API in que_mgt to retrieve sta-rec index for security frames.
  353. *
  354. * 06 23 2010 yarco.yang
  355. * [WPD00003837][MT6620]Data Path Refine
  356. * Merge g_arStaRec[] into adapter->arStaRec[]
  357. *
  358. * 06 21 2010 yarco.yang
  359. * [WPD00003837][MT6620]Data Path Refine
  360. * Support CFG_MQM_MIGRATION flag
  361. *
  362. * 06 11 2010 cp.wu
  363. * [WPD00003833][MT6620 and MT5931] Driver migration
  364. * 1) migrate assoc.c.
  365. * 2) add ucTxSeqNum for tracking frames which needs TX-DONE awareness
  366. * 3) add configuration options for CNM_MEM and RSN modules
  367. * 4) add data path for management frames
  368. * 5) eliminate rPacketInfo of MSDU_INFO_T
  369. *
  370. * 06 06 2010 kevin.huang
  371. * [WPD00003832][MT6620 5931] Create driver base
  372. * [MT6620 5931] Create driver base
  373. *
  374. * 03 31 2010 tehuang.liu
  375. * [WPD00001943]Create WiFi test driver framework on WinXP
  376. * Refined the debug msg
  377. *
  378. * 03 30 2010 cp.wu
  379. * [WPD00001943]Create WiFi test driver framework on WinXP
  380. * comment out one assertion which refer to undefined data member.
  381. *
  382. * 03 30 2010 tehuang.liu
  383. * [WPD00001943]Create WiFi test driver framework on WinXP
  384. * Enabled adaptive TC resource control
  385. *
  386. * 03 24 2010 jeffrey.chang
  387. * [WPD00003826]Initial import for Linux port
  388. * initial import for Linux port
  389. *
  390. * 03 17 2010 tehuang.liu
  391. * [WPD00001943]Create WiFi test driver framework on WinXP
  392. * Changed STA_REC index determination rules (DA=BMCAST always --> STA_REC_INDEX_BMCAST)
  393. *
  394. * 03 11 2010 tehuang.liu
  395. * [WPD00001943]Create WiFi test driver framework on WinXP
  396. * Fixed buffer leak when processing BAR frames
  397. *
  398. * 03 02 2010 tehuang.liu
  399. * [WPD00001943]Create WiFi test driver framework on WinXP
  400. * For TX packets with STA_REC index = STA_REC_INDEX_NOT_FOUND, use TC5
  401. *
  402. * 03 01 2010 tehuang.liu
  403. * [WPD00001943]Create WiFi test driver framework on WinXP
  404. * Fixed STA_REC index determination bug (fgIsValid shall be checked)
  405. *
  406. * 02 25 2010 tehuang.liu
  407. * [WPD00001943]Create WiFi test driver framework on WinXP
  408. * Refined function qmDetermineStaRecIndex() for BMCAST packets
  409. *
  410. * 02 25 2010 tehuang.liu
  411. * [WPD00001943]Create WiFi test driver framework on WinXP
  412. * Enabled multi-STA TX path with fairness
  413. *
  414. * 02 24 2010 tehuang.liu
  415. * [WPD00001943]Create WiFi test driver framework on WinXP
  416. * Enabled dynamically activating and deactivating STA_RECs
  417. *
  418. * 02 24 2010 tehuang.liu
  419. * [WPD00001943]Create WiFi test driver framework on WinXP
  420. * Added code for dynamic activating and deactivating STA_RECs.
  421. *
  422. * 01 13 2010 tehuang.liu
  423. * [WPD00001943]Create WiFi test driver framework on WinXP
  424. * Enabled the 802.1x path
  425. *
  426. * 01 13 2010 tehuang.liu
  427. * [WPD00001943]Create WiFi test driver framework on WinXP
  428. * Enabled the Burst_End Indication mechanism
  429. ** \main\maintrunk.MT6620WiFiDriver_Prj\13 2009-12-14 15:01:37 GMT MTK02468
  430. ** Fixed casting for qmAddRxBaEntry()
  431. ** \main\maintrunk.MT6620WiFiDriver_Prj\12 2009-12-10 16:51:03 GMT mtk02752
  432. ** remove SD1_SD3.. flag
  433. ** \main\maintrunk.MT6620WiFiDriver_Prj\11 2009-12-09 14:07:25 GMT MTK02468
  434. ** Added RX buffer reordering functions
  435. ** \main\maintrunk.MT6620WiFiDriver_Prj\10 2009-12-04 13:34:16 GMT MTK02468
  436. ** Modified Flush Queue function to let queues be reinitialized
  437. ** \main\maintrunk.MT6620WiFiDriver_Prj\9 2009-12-04 13:18:25 GMT MTK02468
  438. ** Added flushing per-Type queues code
  439. ** \main\maintrunk.MT6620WiFiDriver_Prj\8 2009-12-02 23:39:49 GMT MTK02468
  440. ** Added Debug msgs and fixed incorrect assert
  441. ** \main\maintrunk.MT6620WiFiDriver_Prj\4 2009-11-26 23:50:27 GMT MTK02468
  442. ** Bug fixing (qmDequeueTxPackets local variable initialization)
  443. ** \main\maintrunk.MT6620WiFiDriver_Prj\3 2009-11-26 09:39:25 GMT mtk02752
  444. ** correct and surpress PREfast warning
  445. ** \main\maintrunk.MT6620WiFiDriver_Prj\2 2009-11-23 22:10:55 GMT mtk02468
  446. ** Used SD1_SD3_DATAPATH_INTEGRATION
  447. ** \main\maintrunk.MT6620WiFiDriver_Prj\1 2009-11-23 22:02:30 GMT mtk02468
  448. ** Initial version
  449. **
  450. */
  451. /*******************************************************************************
  452. * C O M P I L E R F L A G S
  453. ********************************************************************************
  454. */
  455. /*******************************************************************************
  456. * E X T E R N A L R E F E R E N C E S
  457. ********************************************************************************
  458. */
  459. #include "precomp.h"
  460. /*******************************************************************************
  461. * C O N S T A N T S
  462. ********************************************************************************
  463. */
  464. /*******************************************************************************
  465. * D A T A T Y P E S
  466. ********************************************************************************
  467. */
  468. /*******************************************************************************
  469. * P U B L I C D A T A
  470. ********************************************************************************
  471. */
  472. OS_SYSTIME g_arMissTimeout[CFG_STA_REC_NUM][CFG_RX_MAX_BA_TID_NUM];
  473. /*******************************************************************************
  474. * P R I V A T E D A T A
  475. ********************************************************************************
  476. */
  477. #if ARP_MONITER_ENABLE
  478. static UINT_16 arpMoniter;
  479. static UINT_8 apIp[4];
  480. #endif
  481. /*******************************************************************************
  482. * M A C R O S
  483. ********************************************************************************
  484. */
  485. /*******************************************************************************
  486. * F U N C T I O N D E C L A R A T I O N S
  487. ********************************************************************************
  488. */
  489. static inline VOID qmDetermineStaRecIndex(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo);
  490. static inline VOID
  491. qmDequeueTxPacketsFromPerStaQueues(IN P_ADAPTER_T prAdapter,
  492. OUT P_QUE_T prQue,
  493. IN UINT_8 ucTC, IN UINT_8 ucCurrentAvailableQuota, IN UINT_8 ucTotalQuota);
  494. static inline VOID
  495. qmDequeueTxPacketsFromPerTypeQueues(IN P_ADAPTER_T prAdapter, OUT P_QUE_T prQue, IN UINT_8 ucTC, IN UINT_8 ucMaxNum);
  496. /*******************************************************************************
  497. * F U N C T I O N S
  498. ********************************************************************************
  499. */
  500. /*----------------------------------------------------------------------------*/
  501. /*!
  502. * \brief Init Queue Management for TX
  503. *
  504. * \param[in] (none)
  505. *
  506. * \return (none)
  507. */
  508. /*----------------------------------------------------------------------------*/
  509. VOID qmInit(IN P_ADAPTER_T prAdapter)
  510. {
  511. UINT_32 u4QueArrayIdx;
  512. UINT_32 i;
  513. P_QUE_MGT_T prQM = &prAdapter->rQM;
  514. /* DbgPrint("QM: Enter qmInit()\n"); */
  515. #if CFG_SUPPORT_QOS
  516. prAdapter->rWifiVar.fgSupportQoS = TRUE;
  517. #else
  518. prAdapter->rWifiVar.fgSupportQoS = FALSE;
  519. #endif
  520. #if CFG_SUPPORT_AMPDU_RX
  521. prAdapter->rWifiVar.fgSupportAmpduRx = TRUE;
  522. #else
  523. prAdapter->rWifiVar.fgSupportAmpduRx = FALSE;
  524. #endif
  525. #if CFG_SUPPORT_AMPDU_TX
  526. prAdapter->rWifiVar.fgSupportAmpduTx = TRUE;
  527. #else
  528. prAdapter->rWifiVar.fgSupportAmpduTx = FALSE;
  529. #endif
  530. #if CFG_SUPPORT_TSPEC
  531. prAdapter->rWifiVar.fgSupportTspec = TRUE;
  532. #else
  533. prAdapter->rWifiVar.fgSupportTspec = FALSE;
  534. #endif
  535. #if CFG_SUPPORT_UAPSD
  536. prAdapter->rWifiVar.fgSupportUAPSD = TRUE;
  537. #else
  538. prAdapter->rWifiVar.fgSupportUAPSD = FALSE;
  539. #endif
  540. #if CFG_SUPPORT_UL_PSMP
  541. prAdapter->rWifiVar.fgSupportULPSMP = TRUE;
  542. #else
  543. prAdapter->rWifiVar.fgSupportULPSMP = FALSE;
  544. #endif
  545. #if CFG_SUPPORT_RX_SGI
  546. prAdapter->rWifiVar.u8SupportRxSgi20 = 0;
  547. prAdapter->rWifiVar.u8SupportRxSgi40 = 0;
  548. #else
  549. prAdapter->rWifiVar.u8SupportRxSgi20 = 2;
  550. prAdapter->rWifiVar.u8SupportRxSgi40 = 2;
  551. #endif
  552. #if CFG_SUPPORT_RX_HT_GF
  553. prAdapter->rWifiVar.u8SupportRxGf = 0;
  554. #else
  555. prAdapter->rWifiVar.u8SupportRxGf = 2;
  556. #endif
  557. /* 4 <2> Initialize other TX queues (queues not in STA_RECs) */
  558. for (u4QueArrayIdx = 0; u4QueArrayIdx < NUM_OF_PER_TYPE_TX_QUEUES; u4QueArrayIdx++)
  559. QUEUE_INITIALIZE(&(prQM->arTxQueue[u4QueArrayIdx]));
  560. /* 4 <3> Initialize the RX BA table and RX queues */
  561. /* Initialize the RX Reordering Parameters and Queues */
  562. for (u4QueArrayIdx = 0; u4QueArrayIdx < CFG_NUM_OF_RX_BA_AGREEMENTS; u4QueArrayIdx++) {
  563. prQM->arRxBaTable[u4QueArrayIdx].fgIsValid = FALSE;
  564. QUEUE_INITIALIZE(&(prQM->arRxBaTable[u4QueArrayIdx].rReOrderQue));
  565. prQM->arRxBaTable[u4QueArrayIdx].u2WinStart = 0xFFFF;
  566. prQM->arRxBaTable[u4QueArrayIdx].u2WinEnd = 0xFFFF;
  567. prQM->arRxBaTable[u4QueArrayIdx].fgIsWaitingForPktWithSsn = FALSE;
  568. }
  569. prQM->ucRxBaCount = 0;
  570. kalMemSet(&g_arMissTimeout, 0, sizeof(g_arMissTimeout));
  571. #if QM_ADAPTIVE_TC_RESOURCE_CTRL
  572. /* 4 <4> Initialize TC resource control variables */
  573. for (i = 0; i < TC_NUM; i++)
  574. prQM->au4AverageQueLen[i] = 0;
  575. prQM->u4TimeToAdjustTcResource = QM_INIT_TIME_TO_ADJUST_TC_RSC;
  576. prQM->u4TimeToUpdateQueLen = QM_INIT_TIME_TO_UPDATE_QUE_LEN;
  577. prQM->u4TxNumOfVi = 0;
  578. prQM->u4TxNumOfVo = 0;
  579. /* ASSERT(prQM->u4TimeToAdjust && prQM->u4TimeToUpdateQueLen); */
  580. /* 1 20 1 1 4 1 */
  581. prQM->au4CurrentTcResource[TC0_INDEX] = NIC_TX_BUFF_COUNT_TC0;
  582. prQM->au4CurrentTcResource[TC1_INDEX] = NIC_TX_BUFF_COUNT_TC1;
  583. prQM->au4CurrentTcResource[TC2_INDEX] = NIC_TX_BUFF_COUNT_TC2;
  584. prQM->au4CurrentTcResource[TC3_INDEX] = NIC_TX_BUFF_COUNT_TC3;
  585. prQM->au4CurrentTcResource[TC4_INDEX] = NIC_TX_BUFF_COUNT_TC4; /* Not adjustable (TX port 1) */
  586. prQM->au4CurrentTcResource[TC5_INDEX] = NIC_TX_BUFF_COUNT_TC5;
  587. DBGLOG(QM, TRACE, "QM: NIC_TX_BUFF_COUNT_TC0 = %d\n", NIC_TX_BUFF_COUNT_TC0);
  588. DBGLOG(QM, TRACE, "QM: NIC_TX_BUFF_COUNT_TC1 = %d\n", NIC_TX_BUFF_COUNT_TC1);
  589. DBGLOG(QM, TRACE, "QM: NIC_TX_BUFF_COUNT_TC2 = %d\n", NIC_TX_BUFF_COUNT_TC2);
  590. DBGLOG(QM, TRACE, "QM: NIC_TX_BUFF_COUNT_TC3 = %d\n", NIC_TX_BUFF_COUNT_TC3);
  591. DBGLOG(QM, TRACE, "QM: NIC_TX_BUFF_COUNT_TC4 = %d\n", NIC_TX_BUFF_COUNT_TC4);
  592. DBGLOG(QM, TRACE, "QM: NIC_TX_BUFF_COUNT_TC5 = %d\n", NIC_TX_BUFF_COUNT_TC5);
  593. /* 1 1 1 1 2 1 */
  594. prQM->au4MinReservedTcResource[TC0_INDEX] = QM_MIN_RESERVED_TC0_RESOURCE;
  595. prQM->au4MinReservedTcResource[TC1_INDEX] = QM_MIN_RESERVED_TC1_RESOURCE;
  596. prQM->au4MinReservedTcResource[TC2_INDEX] = QM_MIN_RESERVED_TC2_RESOURCE;
  597. prQM->au4MinReservedTcResource[TC3_INDEX] = QM_MIN_RESERVED_TC3_RESOURCE;
  598. prQM->au4MinReservedTcResource[TC4_INDEX] = QM_MIN_RESERVED_TC4_RESOURCE; /* Not adjustable (TX port 1) */
  599. prQM->au4MinReservedTcResource[TC5_INDEX] = QM_MIN_RESERVED_TC5_RESOURCE;
  600. /* 4 4 6 6 2 4 */
  601. prQM->au4GuaranteedTcResource[TC0_INDEX] = QM_GUARANTEED_TC0_RESOURCE;
  602. prQM->au4GuaranteedTcResource[TC1_INDEX] = QM_GUARANTEED_TC1_RESOURCE;
  603. prQM->au4GuaranteedTcResource[TC2_INDEX] = QM_GUARANTEED_TC2_RESOURCE;
  604. prQM->au4GuaranteedTcResource[TC3_INDEX] = QM_GUARANTEED_TC3_RESOURCE;
  605. prQM->au4GuaranteedTcResource[TC4_INDEX] = QM_GUARANTEED_TC4_RESOURCE;
  606. prQM->au4GuaranteedTcResource[TC5_INDEX] = QM_GUARANTEED_TC5_RESOURCE;
  607. prQM->fgTcResourcePostAnnealing = FALSE;
  608. ASSERT(QM_INITIAL_RESIDUAL_TC_RESOURCE < 64);
  609. #endif
  610. #if QM_TEST_MODE
  611. prQM->u4PktCount = 0;
  612. #if QM_TEST_FAIR_FORWARDING
  613. prQM->u4CurrentStaRecIndexToEnqueue = 0;
  614. {
  615. UINT_8 aucMacAddr[MAC_ADDR_LEN];
  616. P_STA_RECORD_T prStaRec;
  617. /* Irrelevant in case this STA is an AIS AP (see qmDetermineStaRecIndex()) */
  618. aucMacAddr[0] = 0x11;
  619. aucMacAddr[1] = 0x22;
  620. aucMacAddr[2] = 0xAA;
  621. aucMacAddr[3] = 0xBB;
  622. aucMacAddr[4] = 0xCC;
  623. aucMacAddr[5] = 0xDD;
  624. prStaRec = &prAdapter->arStaRec[1];
  625. ASSERT(prStaRec);
  626. prStaRec->fgIsValid = TRUE;
  627. prStaRec->fgIsQoS = TRUE;
  628. prStaRec->fgIsInPS = FALSE;
  629. prStaRec->ucPsSessionID = 0xFF;
  630. prStaRec->ucNetTypeIndex = NETWORK_TYPE_AIS_INDEX;
  631. prStaRec->fgIsAp = TRUE;
  632. COPY_MAC_ADDR((prStaRec)->aucMacAddr, aucMacAddr);
  633. }
  634. #endif
  635. #endif
  636. #if QM_FORWARDING_FAIRNESS
  637. {
  638. UINT_32 i;
  639. for (i = 0; i < NUM_OF_PER_STA_TX_QUEUES; i++) {
  640. prQM->au4ForwardCount[i] = 0;
  641. prQM->au4HeadStaRecIndex[i] = 0;
  642. }
  643. }
  644. #endif
  645. #if QM_TC_RESOURCE_EMPTY_COUNTER
  646. kalMemZero(prQM->au4QmTcResourceEmptyCounter, sizeof(prQM->au4QmTcResourceEmptyCounter));
  647. #endif
  648. }
  649. #if QM_TEST_MODE
  650. VOID qmTestCases(IN P_ADAPTER_T prAdapter)
  651. {
  652. P_QUE_MGT_T prQM = &prAdapter->rQM;
  653. DbgPrint("QM: ** TEST MODE **\n");
  654. if (QM_TEST_STA_REC_DETERMINATION) {
  655. if (prAdapter->arStaRec[0].fgIsValid) {
  656. prAdapter->arStaRec[0].fgIsValid = FALSE;
  657. DbgPrint("QM: (Test) Deactivate STA_REC[0]\n");
  658. } else {
  659. prAdapter->arStaRec[0].fgIsValid = TRUE;
  660. DbgPrint("QM: (Test) Activate STA_REC[0]\n");
  661. }
  662. }
  663. if (QM_TEST_STA_REC_DEACTIVATION) {
  664. /* Note that QM_STA_REC_HARD_CODING shall be set to 1 for this test */
  665. if (prAdapter->arStaRec[0].fgIsValid) {
  666. DbgPrint("QM: (Test) Deactivate STA_REC[0]\n");
  667. qmDeactivateStaRec(prAdapter, 0);
  668. } else {
  669. UINT_8 aucMacAddr[MAC_ADDR_LEN];
  670. /* Irrelevant in case this STA is an AIS AP (see qmDetermineStaRecIndex()) */
  671. aucMacAddr[0] = 0x11;
  672. aucMacAddr[1] = 0x22;
  673. aucMacAddr[2] = 0xAA;
  674. aucMacAddr[3] = 0xBB;
  675. aucMacAddr[4] = 0xCC;
  676. aucMacAddr[5] = 0xDD;
  677. DbgPrint("QM: (Test) Activate STA_REC[0]\n");
  678. qmActivateStaRec(prAdapter, /* Adapter pointer */
  679. 0, /* STA_REC index from FW */
  680. TRUE, /* fgIsQoS */
  681. NETWORK_TYPE_AIS_INDEX, /* Network type */
  682. TRUE, /* fgIsAp */
  683. aucMacAddr /* MAC address */
  684. );
  685. }
  686. }
  687. if (QM_TEST_FAIR_FORWARDING) {
  688. if (prAdapter->arStaRec[1].fgIsValid) {
  689. prQM->u4CurrentStaRecIndexToEnqueue++;
  690. prQM->u4CurrentStaRecIndexToEnqueue %= 2;
  691. DbgPrint("QM: (Test) Switch to STA_REC[%u]\n", prQM->u4CurrentStaRecIndexToEnqueue);
  692. }
  693. }
  694. }
  695. #endif
  696. /*----------------------------------------------------------------------------*/
  697. /*!
  698. * \brief Activate a STA_REC
  699. *
  700. * \param[in] prAdapter Pointer to the Adapter instance
  701. * \param[in] u4StaRecIdx The index of the STA_REC
  702. * \param[in] fgIsQoS Set to TRUE if this is a QoS STA
  703. * \param[in] pucMacAddr The MAC address of the STA
  704. *
  705. * \return (none)
  706. */
  707. /*----------------------------------------------------------------------------*/
  708. VOID qmActivateStaRec(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec)
  709. {
  710. /* 4 <1> Deactivate first */
  711. ASSERT(prStaRec);
  712. if (prStaRec->fgIsValid) { /* The STA_REC has been activated */
  713. DBGLOG(QM, WARN, "QM: (WARNING) Activating a STA_REC which has been activated\n");
  714. DBGLOG(QM, WARN, "QM: (WARNING) Deactivating a STA_REC before re-activating\n");
  715. /* To flush TX/RX queues and del RX BA agreements */
  716. qmDeactivateStaRec(prAdapter, prStaRec->ucIndex);
  717. }
  718. /* 4 <2> Activate the STA_REC */
  719. /* Init the STA_REC */
  720. prStaRec->fgIsValid = TRUE;
  721. prStaRec->fgIsInPS = FALSE;
  722. prStaRec->ucPsSessionID = 0xFF;
  723. prStaRec->fgIsAp = (IS_AP_STA(prStaRec)) ? TRUE : FALSE;
  724. /* Done in qmInit() or qmDeactivateStaRec() */
  725. #if 0
  726. /* At the beginning, no RX BA agreements have been established */
  727. for (i = 0; i < CFG_RX_MAX_BA_TID_NUM; i++)
  728. (prStaRec->aprRxReorderParamRefTbl)[i] = NULL;
  729. #endif
  730. DBGLOG(QM, TRACE, "QM: +STA[%u]\n", (UINT_32) prStaRec->ucIndex);
  731. }
  732. /*----------------------------------------------------------------------------*/
  733. /*!
  734. * \brief Deactivate a STA_REC
  735. *
  736. * \param[in] prAdapter Pointer to the Adapter instance
  737. * \param[in] u4StaRecIdx The index of the STA_REC
  738. *
  739. * \return (none)
  740. */
  741. /*----------------------------------------------------------------------------*/
  742. VOID qmDeactivateStaRec(IN P_ADAPTER_T prAdapter, IN UINT_32 u4StaRecIdx)
  743. {
  744. P_STA_RECORD_T prStaRec;
  745. UINT_32 i;
  746. P_MSDU_INFO_T prFlushedTxPacketList = NULL;
  747. ASSERT(u4StaRecIdx < CFG_NUM_OF_STA_RECORD);
  748. prStaRec = &prAdapter->arStaRec[u4StaRecIdx];
  749. ASSERT(prStaRec);
  750. /* 4<1> Flush TX queues */
  751. prFlushedTxPacketList = qmFlushStaTxQueues(prAdapter, u4StaRecIdx);
  752. if (prFlushedTxPacketList)
  753. wlanProcessQueuedMsduInfo(prAdapter, prFlushedTxPacketList);
  754. /* 4 <2> Flush RX queues and delete RX BA agreements */
  755. for (i = 0; i < CFG_RX_MAX_BA_TID_NUM; i++) {
  756. /* Delete the RX BA entry with TID = i */
  757. qmDelRxBaEntry(prAdapter, (UINT_8) u4StaRecIdx, (UINT_8) i, FALSE);
  758. }
  759. /* 4 <3> Deactivate the STA_REC */
  760. prStaRec->fgIsValid = FALSE;
  761. prStaRec->fgIsInPS = FALSE;
  762. /* To reduce printk for IOT sta to connect all the time, */
  763. /* DBGLOG(QM, INFO, ("QM: -STA[%ld]\n", u4StaRecIdx)); */
  764. }
  765. /*----------------------------------------------------------------------------*/
  766. /*!
  767. * \brief Deactivate a STA_REC
  768. *
  769. * \param[in] prAdapter Pointer to the Adapter instance
  770. * \param[in] u4StaRecIdx The index of the network
  771. *
  772. * \return (none)
  773. */
  774. /*----------------------------------------------------------------------------*/
  775. VOID qmFreeAllByNetType(IN P_ADAPTER_T prAdapter, IN ENUM_NETWORK_TYPE_INDEX_T eNetworkTypeIdx)
  776. {
  777. P_QUE_MGT_T prQM;
  778. P_QUE_T prQue;
  779. QUE_T rNeedToFreeQue;
  780. QUE_T rTempQue;
  781. P_QUE_T prNeedToFreeQue;
  782. P_QUE_T prTempQue;
  783. P_MSDU_INFO_T prMsduInfo;
  784. prQM = &prAdapter->rQM;
  785. prQue = &prQM->arTxQueue[TX_QUEUE_INDEX_BMCAST];
  786. QUEUE_INITIALIZE(&rNeedToFreeQue);
  787. QUEUE_INITIALIZE(&rTempQue);
  788. prNeedToFreeQue = &rNeedToFreeQue;
  789. prTempQue = &rTempQue;
  790. QUEUE_MOVE_ALL(prTempQue, prQue);
  791. QUEUE_REMOVE_HEAD(prTempQue, prMsduInfo, P_MSDU_INFO_T);
  792. while (prMsduInfo) {
  793. if (prMsduInfo->ucNetworkType == eNetworkTypeIdx) {
  794. /* QUEUE_INSERT_TAIL */
  795. QUEUE_INSERT_TAIL(prNeedToFreeQue, (P_QUE_ENTRY_T) prMsduInfo);
  796. } else {
  797. /* QUEUE_INSERT_TAIL */
  798. QUEUE_INSERT_TAIL(prQue, (P_QUE_ENTRY_T) prMsduInfo);
  799. }
  800. QUEUE_REMOVE_HEAD(prTempQue, prMsduInfo, P_MSDU_INFO_T);
  801. }
  802. if (QUEUE_IS_NOT_EMPTY(prNeedToFreeQue))
  803. wlanProcessQueuedMsduInfo(prAdapter, (P_MSDU_INFO_T) QUEUE_GET_HEAD(prNeedToFreeQue));
  804. }
  805. /*----------------------------------------------------------------------------*/
  806. /*!
  807. * \brief Flush all TX queues
  808. *
  809. * \param[in] (none)
  810. *
  811. * \return The flushed packets (in a list of MSDU_INFOs)
  812. */
  813. /*----------------------------------------------------------------------------*/
  814. P_MSDU_INFO_T qmFlushTxQueues(IN P_ADAPTER_T prAdapter)
  815. {
  816. UINT_8 ucStaArrayIdx;
  817. UINT_8 ucQueArrayIdx;
  818. P_MSDU_INFO_T prMsduInfoListHead;
  819. P_MSDU_INFO_T prMsduInfoListTail;
  820. P_QUE_MGT_T prQM = &prAdapter->rQM;
  821. DBGLOG(QM, TRACE, "QM: Enter qmFlushTxQueues()\n");
  822. prMsduInfoListHead = NULL;
  823. prMsduInfoListTail = NULL;
  824. /* Concatenate all MSDU_INFOs in per-STA queues */
  825. for (ucStaArrayIdx = 0; ucStaArrayIdx < CFG_NUM_OF_STA_RECORD; ucStaArrayIdx++) {
  826. /* Always check each STA_REC when flushing packets no matter it is inactive or active */
  827. #if 0
  828. if (!prAdapter->arStaRec[ucStaArrayIdx].fgIsValid)
  829. continue; /* Continue to check the next STA_REC */
  830. #endif
  831. for (ucQueArrayIdx = 0; ucQueArrayIdx < NUM_OF_PER_STA_TX_QUEUES; ucQueArrayIdx++) {
  832. if (QUEUE_IS_EMPTY(&(prAdapter->arStaRec[ucStaArrayIdx].arTxQueue[ucQueArrayIdx])))
  833. continue; /* Continue to check the next TX queue of the same STA */
  834. if (!prMsduInfoListHead) {
  835. /* The first MSDU_INFO is found */
  836. prMsduInfoListHead = (P_MSDU_INFO_T)
  837. QUEUE_GET_HEAD(&prAdapter->arStaRec[ucStaArrayIdx].arTxQueue[ucQueArrayIdx]);
  838. prMsduInfoListTail = (P_MSDU_INFO_T)
  839. QUEUE_GET_TAIL(&prAdapter->arStaRec[ucStaArrayIdx].arTxQueue[ucQueArrayIdx]);
  840. } else {
  841. /* Concatenate the MSDU_INFO list with the existing list */
  842. QM_TX_SET_NEXT_MSDU_INFO(prMsduInfoListTail,
  843. QUEUE_GET_HEAD(&prAdapter->
  844. arStaRec[ucStaArrayIdx].arTxQueue
  845. [ucQueArrayIdx]));
  846. prMsduInfoListTail = (P_MSDU_INFO_T)
  847. QUEUE_GET_TAIL(&prAdapter->arStaRec[ucStaArrayIdx].arTxQueue[ucQueArrayIdx]);
  848. }
  849. QUEUE_INITIALIZE(&prAdapter->arStaRec[ucStaArrayIdx].arTxQueue[ucQueArrayIdx]);
  850. }
  851. }
  852. /* Flush per-Type queues */
  853. for (ucQueArrayIdx = 0; ucQueArrayIdx < NUM_OF_PER_TYPE_TX_QUEUES; ucQueArrayIdx++) {
  854. if (QUEUE_IS_EMPTY(&(prQM->arTxQueue[ucQueArrayIdx])))
  855. continue; /* Continue to check the next TX queue of the same STA */
  856. if (!prMsduInfoListHead) {
  857. /* The first MSDU_INFO is found */
  858. prMsduInfoListHead = (P_MSDU_INFO_T)
  859. QUEUE_GET_HEAD(&prQM->arTxQueue[ucQueArrayIdx]);
  860. prMsduInfoListTail = (P_MSDU_INFO_T)
  861. QUEUE_GET_TAIL(&prQM->arTxQueue[ucQueArrayIdx]);
  862. } else {
  863. /* Concatenate the MSDU_INFO list with the existing list */
  864. QM_TX_SET_NEXT_MSDU_INFO(prMsduInfoListTail, QUEUE_GET_HEAD(&prQM->arTxQueue[ucQueArrayIdx]));
  865. prMsduInfoListTail = (P_MSDU_INFO_T)
  866. QUEUE_GET_TAIL(&prQM->arTxQueue[ucQueArrayIdx]);
  867. }
  868. QUEUE_INITIALIZE(&prQM->arTxQueue[ucQueArrayIdx]);
  869. }
  870. if (prMsduInfoListTail) {
  871. /* Terminate the MSDU_INFO list with a NULL pointer */
  872. QM_TX_SET_NEXT_MSDU_INFO(prMsduInfoListTail, NULL);
  873. }
  874. return prMsduInfoListHead;
  875. }
  876. /*----------------------------------------------------------------------------*/
  877. /*!
  878. * \brief Flush TX packets for a particular STA
  879. *
  880. * \param[in] u4StaRecIdx STA_REC index
  881. *
  882. * \return The flushed packets (in a list of MSDU_INFOs)
  883. */
  884. /*----------------------------------------------------------------------------*/
  885. P_MSDU_INFO_T qmFlushStaTxQueues(IN P_ADAPTER_T prAdapter, IN UINT_32 u4StaRecIdx)
  886. {
  887. UINT_8 ucQueArrayIdx;
  888. P_MSDU_INFO_T prMsduInfoListHead;
  889. P_MSDU_INFO_T prMsduInfoListTail;
  890. P_STA_RECORD_T prStaRec;
  891. /* To reduce printk for IOT sta to connect all the time, */
  892. /* DBGLOG(QM, TRACE, ("QM: Enter qmFlushStaTxQueues(%ld)\n", u4StaRecIdx)); */
  893. ASSERT(u4StaRecIdx < CFG_NUM_OF_STA_RECORD);
  894. prMsduInfoListHead = NULL;
  895. prMsduInfoListTail = NULL;
  896. prStaRec = &prAdapter->arStaRec[u4StaRecIdx];
  897. ASSERT(prStaRec);
  898. /* No matter whether this is an activated STA_REC, do flush */
  899. #if 0
  900. if (!prStaRec->fgIsValid)
  901. return NULL;
  902. #endif
  903. /* Concatenate all MSDU_INFOs in TX queues of this STA_REC */
  904. for (ucQueArrayIdx = 0; ucQueArrayIdx < NUM_OF_PER_STA_TX_QUEUES; ucQueArrayIdx++) {
  905. if (QUEUE_IS_EMPTY(&(prStaRec->arTxQueue[ucQueArrayIdx])))
  906. continue;
  907. if (!prMsduInfoListHead) {
  908. /* The first MSDU_INFO is found */
  909. prMsduInfoListHead = (P_MSDU_INFO_T)
  910. QUEUE_GET_HEAD(&prStaRec->arTxQueue[ucQueArrayIdx]);
  911. prMsduInfoListTail = (P_MSDU_INFO_T)
  912. QUEUE_GET_TAIL(&prStaRec->arTxQueue[ucQueArrayIdx]);
  913. } else {
  914. /* Concatenate the MSDU_INFO list with the existing list */
  915. QM_TX_SET_NEXT_MSDU_INFO(prMsduInfoListTail,
  916. QUEUE_GET_HEAD(&prStaRec->arTxQueue[ucQueArrayIdx]));
  917. prMsduInfoListTail = (P_MSDU_INFO_T) QUEUE_GET_TAIL(&prStaRec->arTxQueue[ucQueArrayIdx]);
  918. }
  919. QUEUE_INITIALIZE(&prStaRec->arTxQueue[ucQueArrayIdx]);
  920. }
  921. #if 0
  922. if (prMsduInfoListTail) {
  923. /* Terminate the MSDU_INFO list with a NULL pointer */
  924. QM_TX_SET_NEXT_MSDU_INFO(prMsduInfoListTail, nicGetPendingStaMMPDU(prAdapter, (UINT_8) u4StaRecIdx));
  925. } else {
  926. prMsduInfoListHead = nicGetPendingStaMMPDU(prAdapter, (UINT_8) u4StaRecIdx);
  927. }
  928. #endif
  929. return prMsduInfoListHead;
  930. }
  931. /*----------------------------------------------------------------------------*/
  932. /*!
  933. * \brief Flush RX packets
  934. *
  935. * \param[in] (none)
  936. *
  937. * \return The flushed packets (in a list of SW_RFBs)
  938. */
  939. /*----------------------------------------------------------------------------*/
  940. P_SW_RFB_T qmFlushRxQueues(IN P_ADAPTER_T prAdapter)
  941. {
  942. UINT_32 i;
  943. P_SW_RFB_T prSwRfbListHead;
  944. P_SW_RFB_T prSwRfbListTail;
  945. P_QUE_MGT_T prQM = &prAdapter->rQM;
  946. prSwRfbListHead = prSwRfbListTail = NULL;
  947. DBGLOG(QM, TRACE, "QM: Enter qmFlushRxQueues()\n");
  948. for (i = 0; i < CFG_NUM_OF_RX_BA_AGREEMENTS; i++) {
  949. if (QUEUE_IS_NOT_EMPTY(&(prQM->arRxBaTable[i].rReOrderQue))) {
  950. if (!prSwRfbListHead) {
  951. /* The first MSDU_INFO is found */
  952. prSwRfbListHead = (P_SW_RFB_T)
  953. QUEUE_GET_HEAD(&(prQM->arRxBaTable[i].rReOrderQue));
  954. prSwRfbListTail = (P_SW_RFB_T)
  955. QUEUE_GET_TAIL(&(prQM->arRxBaTable[i].rReOrderQue));
  956. } else {
  957. /* Concatenate the MSDU_INFO list with the existing list */
  958. QM_TX_SET_NEXT_MSDU_INFO(prSwRfbListTail,
  959. QUEUE_GET_HEAD(&(prQM->arRxBaTable[i].rReOrderQue)));
  960. prSwRfbListTail = (P_SW_RFB_T)
  961. QUEUE_GET_TAIL(&(prQM->arRxBaTable[i].rReOrderQue));
  962. }
  963. QUEUE_INITIALIZE(&(prQM->arRxBaTable[i].rReOrderQue));
  964. } else {
  965. continue;
  966. }
  967. }
  968. if (prSwRfbListTail) {
  969. /* Terminate the MSDU_INFO list with a NULL pointer */
  970. QM_TX_SET_NEXT_SW_RFB(prSwRfbListTail, NULL);
  971. }
  972. return prSwRfbListHead;
  973. }
  974. /*----------------------------------------------------------------------------*/
  975. /*!
  976. * \brief Flush RX packets with respect to a particular STA
  977. *
  978. * \param[in] u4StaRecIdx STA_REC index
  979. * \param[in] u4Tid TID
  980. *
  981. * \return The flushed packets (in a list of SW_RFBs)
  982. */
  983. /*----------------------------------------------------------------------------*/
  984. P_SW_RFB_T qmFlushStaRxQueue(IN P_ADAPTER_T prAdapter, IN UINT_32 u4StaRecIdx, IN UINT_32 u4Tid)
  985. {
  986. /* UINT_32 i; */
  987. P_SW_RFB_T prSwRfbListHead;
  988. P_SW_RFB_T prSwRfbListTail;
  989. P_RX_BA_ENTRY_T prReorderQueParm;
  990. P_STA_RECORD_T prStaRec;
  991. DBGLOG(QM, TRACE, "QM: Enter qmFlushStaRxQueues(%u)\n", u4StaRecIdx);
  992. prSwRfbListHead = prSwRfbListTail = NULL;
  993. prStaRec = &prAdapter->arStaRec[u4StaRecIdx];
  994. ASSERT(prStaRec);
  995. /* No matter whether this is an activated STA_REC, do flush */
  996. #if 0
  997. if (!prStaRec->fgIsValid)
  998. return NULL;
  999. #endif
  1000. /* Obtain the RX BA Entry pointer */
  1001. prReorderQueParm = ((prStaRec->aprRxReorderParamRefTbl)[u4Tid]);
  1002. /* Note: For each queued packet, prCurrSwRfb->eDst equals RX_PKT_DESTINATION_HOST */
  1003. if (prReorderQueParm) {
  1004. if (QUEUE_IS_NOT_EMPTY(&(prReorderQueParm->rReOrderQue))) {
  1005. prSwRfbListHead = (P_SW_RFB_T)
  1006. QUEUE_GET_HEAD(&(prReorderQueParm->rReOrderQue));
  1007. prSwRfbListTail = (P_SW_RFB_T)
  1008. QUEUE_GET_TAIL(&(prReorderQueParm->rReOrderQue));
  1009. QUEUE_INITIALIZE(&(prReorderQueParm->rReOrderQue));
  1010. }
  1011. }
  1012. if (prSwRfbListTail) {
  1013. /* Terminate the MSDU_INFO list with a NULL pointer */
  1014. QM_TX_SET_NEXT_SW_RFB(prSwRfbListTail, NULL);
  1015. }
  1016. return prSwRfbListHead;
  1017. }
  1018. /*----------------------------------------------------------------------------*/
  1019. /*!
  1020. * \brief Enqueue TX packets
  1021. *
  1022. * \param[in] prMsduInfoListHead Pointer to the list of TX packets
  1023. *
  1024. * \return The freed packets, which are not enqueued
  1025. */
  1026. /*----------------------------------------------------------------------------*/
  1027. P_MSDU_INFO_T qmEnqueueTxPackets(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfoListHead)
  1028. {
  1029. P_MSDU_INFO_T prMsduInfoReleaseList;
  1030. P_MSDU_INFO_T prCurrentMsduInfo;
  1031. P_MSDU_INFO_T prNextMsduInfo;
  1032. P_STA_RECORD_T prStaRec;
  1033. QUE_T rNotEnqueuedQue;
  1034. P_QUE_T prTxQue = &rNotEnqueuedQue;
  1035. UINT_8 ucPacketType;
  1036. UINT_8 ucTC;
  1037. P_QUE_MGT_T prQM = &prAdapter->rQM;
  1038. UINT_8 aucNextUP[WMM_AC_INDEX_NUM] = { 1 /* BEtoBK */ , 1 /*na */ , 0 /*VItoBE */ , 4 /*VOtoVI */ };
  1039. DBGLOG(QM, LOUD, "Enter qmEnqueueTxPackets\n");
  1040. ASSERT(prMsduInfoListHead);
  1041. #if QM_ADAPTIVE_TC_RESOURCE_CTRL
  1042. {
  1043. /* UINT_32 i; */
  1044. /* 4 <0> Update TC resource control related variables */
  1045. /* Keep track of the queue length */
  1046. if (--prQM->u4TimeToUpdateQueLen == 0) { /* -- only here */
  1047. prQM->u4TimeToUpdateQueLen = QM_INIT_TIME_TO_UPDATE_QUE_LEN;
  1048. qmUpdateAverageTxQueLen(prAdapter);
  1049. }
  1050. }
  1051. #endif
  1052. /* Push TX packets into STA_REC (for UNICAST) or prAdapter->rQM (for BMCAST) */
  1053. prStaRec = NULL;
  1054. prMsduInfoReleaseList = NULL;
  1055. prCurrentMsduInfo = NULL;
  1056. QUEUE_INITIALIZE(&rNotEnqueuedQue);
  1057. prNextMsduInfo = prMsduInfoListHead;
  1058. do {
  1059. P_BSS_INFO_T prBssInfo;
  1060. BOOLEAN fgCheckACMAgain;
  1061. ENUM_WMM_ACI_T eAci = WMM_AC_BE_INDEX;
  1062. prCurrentMsduInfo = prNextMsduInfo;
  1063. prNextMsduInfo = QM_TX_GET_NEXT_MSDU_INFO(prCurrentMsduInfo);
  1064. ucTC = TC1_INDEX;
  1065. /* 4 <1> Lookup the STA_REC index */
  1066. /* The ucStaRecIndex will be set in this function */
  1067. qmDetermineStaRecIndex(prAdapter, prCurrentMsduInfo);
  1068. ucPacketType = HIF_TX_PACKET_TYPE_DATA;
  1069. STATS_ENV_REPORT_DETECT(prAdapter, prCurrentMsduInfo->ucStaRecIndex);
  1070. DBGLOG(QM, LOUD, "***** ucStaRecIndex = %d *****\n", prCurrentMsduInfo->ucStaRecIndex);
  1071. prBssInfo = &(prAdapter->rWifiVar.arBssInfo[prCurrentMsduInfo->ucNetworkType]);
  1072. #if (CONF_HIF_LOOPBACK_AUTO == 0)
  1073. if (IS_NET_ACTIVE(prAdapter, prCurrentMsduInfo->ucNetworkType)) {
  1074. #else
  1075. /* force to send the loopback test packet */
  1076. if (1) {
  1077. SET_NET_ACTIVE(prAdapter, prCurrentMsduInfo->ucNetworkType);
  1078. prCurrentMsduInfo->ucStaRecIndex = STA_REC_INDEX_BMCAST;
  1079. ucPacketType = HIF_TX_PKT_TYPE_HIF_LOOPBACK;
  1080. #endif /* End of CONF_HIF_LOOPBACK_AUTO */
  1081. switch (prCurrentMsduInfo->ucStaRecIndex) {
  1082. case STA_REC_INDEX_BMCAST:
  1083. prTxQue = &prQM->arTxQueue[TX_QUEUE_INDEX_BMCAST];
  1084. ucTC = TC5_INDEX;
  1085. #if 0
  1086. if (prCurrentMsduInfo->ucNetworkType == NETWORK_TYPE_P2P_INDEX
  1087. && prCurrentMsduInfo->eSrc != TX_PACKET_MGMT) {
  1088. if (LINK_IS_EMPTY
  1089. (&prAdapter->rWifiVar.
  1090. arBssInfo[NETWORK_TYPE_P2P_INDEX].rStaRecOfClientList)) {
  1091. prTxQue = &rNotEnqueuedQue;
  1092. TX_INC_CNT(&prAdapter->rTxCtrl, TX_AP_BORADCAST_DROP);
  1093. }
  1094. }
  1095. #endif
  1096. QM_DBG_CNT_INC(prQM, QM_DBG_CNT_23);
  1097. break;
  1098. case STA_REC_INDEX_NOT_FOUND:
  1099. ucTC = TC5_INDEX;
  1100. if (prCurrentMsduInfo->eSrc == TX_PACKET_FORWARDING) {
  1101. /* if the packet is the forward type. the packet should be freed */
  1102. DBGLOG(QM, TRACE, "Forwarding packet but Sta is STA_REC_INDEX_NOT_FOUND\n");
  1103. /* prTxQue = &rNotEnqueuedQue; */
  1104. }
  1105. prTxQue = &prQM->arTxQueue[TX_QUEUE_INDEX_NO_STA_REC];
  1106. QM_DBG_CNT_INC(prQM, QM_DBG_CNT_24);
  1107. break;
  1108. default:
  1109. prStaRec = QM_GET_STA_REC_PTR_FROM_INDEX(prAdapter, prCurrentMsduInfo->ucStaRecIndex);
  1110. if (!prStaRec) {
  1111. DBGLOG(QM, ERROR, "prStaRec is NULL\n");
  1112. break;
  1113. }
  1114. ASSERT(prStaRec->fgIsValid);
  1115. if (prCurrentMsduInfo->ucUserPriority < 8) {
  1116. QM_DBG_CNT_INC(prQM, prCurrentMsduInfo->ucUserPriority + 15);
  1117. /* QM_DBG_CNT_15 *//* QM_DBG_CNT_16 *//* QM_DBG_CNT_17 *//* QM_DBG_CNT_18 */
  1118. /* QM_DBG_CNT_19 *//* QM_DBG_CNT_20 *//* QM_DBG_CNT_21 *//* QM_DBG_CNT_22 */
  1119. }
  1120. eAci = WMM_AC_BE_INDEX;
  1121. do {
  1122. fgCheckACMAgain = FALSE;
  1123. if (!prStaRec->fgIsQoS) {
  1124. prTxQue = &prStaRec->arTxQueue[TX_QUEUE_INDEX_AC1];
  1125. ucTC = TC1_INDEX;
  1126. break;
  1127. }
  1128. switch (prCurrentMsduInfo->ucUserPriority) {
  1129. case 1:
  1130. case 2:
  1131. prTxQue = &prStaRec->arTxQueue[TX_QUEUE_INDEX_AC0];
  1132. ucTC = TC0_INDEX;
  1133. eAci = WMM_AC_BK_INDEX;
  1134. break;
  1135. case 0:
  1136. case 3:
  1137. prTxQue = &prStaRec->arTxQueue[TX_QUEUE_INDEX_AC1];
  1138. ucTC = TC1_INDEX;
  1139. eAci = WMM_AC_BE_INDEX;
  1140. break;
  1141. case 4:
  1142. case 5:
  1143. prTxQue = &prStaRec->arTxQueue[TX_QUEUE_INDEX_AC2];
  1144. ucTC = TC2_INDEX;
  1145. eAci = WMM_AC_VI_INDEX;
  1146. #if QM_ADAPTIVE_TC_RESOURCE_CTRL
  1147. prQM->u4TxNumOfVi++;
  1148. #endif
  1149. break;
  1150. case 6:
  1151. case 7:
  1152. prTxQue = &prStaRec->arTxQueue[TX_QUEUE_INDEX_AC3];
  1153. ucTC = TC3_INDEX;
  1154. eAci = WMM_AC_VO_INDEX;
  1155. #if QM_ADAPTIVE_TC_RESOURCE_CTRL
  1156. prQM->u4TxNumOfVo++;
  1157. #endif
  1158. break;
  1159. default:
  1160. prTxQue = &prStaRec->arTxQueue[TX_QUEUE_INDEX_AC1];
  1161. ucTC = TC1_INDEX;
  1162. eAci = WMM_AC_BE_INDEX;
  1163. ASSERT(0);
  1164. break;
  1165. }
  1166. if (prBssInfo->arACQueParms[eAci].fgIsACMSet && eAci
  1167. != WMM_AC_BK_INDEX) {
  1168. prCurrentMsduInfo->ucUserPriority = aucNextUP[eAci];
  1169. fgCheckACMAgain = TRUE;
  1170. }
  1171. } while (fgCheckACMAgain);
  1172. /* LOG_FUNC ("QoS %u UP %u TC %u", */
  1173. /* prStaRec->fgIsQoS,prCurrentMsduInfo->ucUserPriority, ucTC); */
  1174. #if QM_ADAPTIVE_TC_RESOURCE_CTRL
  1175. /*
  1176. In TDLS or AP mode, peer maybe enter "sleep mode".
  1177. If QM_INIT_TIME_TO_UPDATE_QUE_LEN = 60 when peer is in sleep mode,
  1178. we need to wait 60 * u4TimeToAdjustTcResource = 180 packets
  1179. u4TimeToAdjustTcResource = 3,
  1180. then we will adjust TC resouce for VI or VO.
  1181. But in TDLS test case, the throughput is very low, only 0.8Mbps in 5.7,
  1182. we will to wait about 12 seconds to collect 180 packets.
  1183. but the test time is only 20 seconds.
  1184. */
  1185. if ((prQM->u4TxNumOfVi == 10) || (prQM->u4TxNumOfVo == 10)) {
  1186. /* force to do TC resouce update */
  1187. prQM->u4TimeToUpdateQueLen = QM_INIT_TIME_TO_UPDATE_QUE_LEN_MIN;
  1188. prQM->u4TimeToAdjustTcResource = 1;
  1189. }
  1190. #endif
  1191. #if ARP_MONITER_ENABLE
  1192. if (IS_STA_IN_AIS(prStaRec) && prCurrentMsduInfo->eSrc == TX_PACKET_OS)
  1193. qmDetectArpNoResponse(prAdapter, prCurrentMsduInfo);
  1194. #endif
  1195. break; /*default */
  1196. } /* switch (prCurrentMsduInfo->ucStaRecIndex) */
  1197. if (prCurrentMsduInfo->eSrc == TX_PACKET_FORWARDING) {
  1198. if (prTxQue->u4NumElem > 32) {
  1199. DBGLOG(QM, WARN,
  1200. "Drop the Packet for full Tx queue (forwarding) Bss %u\n",
  1201. prCurrentMsduInfo->ucNetworkType);
  1202. prTxQue = &rNotEnqueuedQue;
  1203. TX_INC_CNT(&prAdapter->rTxCtrl, TX_FORWARD_OVERFLOW_DROP);
  1204. }
  1205. }
  1206. } else {
  1207. DBGLOG(QM, WARN, "Drop the Packet for inactive Bss %u\n", prCurrentMsduInfo->ucNetworkType);
  1208. QM_DBG_CNT_INC(prQM, QM_DBG_CNT_31);
  1209. prTxQue = &rNotEnqueuedQue;
  1210. TX_INC_CNT(&prAdapter->rTxCtrl, TX_INACTIVE_BSS_DROP);
  1211. }
  1212. /* 4 <3> Fill the MSDU_INFO for constructing HIF TX header */
  1213. /* TODO: Fill MSDU_INFO according to the network type,
  1214. * EtherType, and STA status (for PS forwarding control).
  1215. */
  1216. /* Note that the Network Type Index and STA_REC index are determined in
  1217. * qmDetermineStaRecIndex(prCurrentMsduInfo).
  1218. */
  1219. QM_TX_SET_MSDU_INFO_FOR_DATA_PACKET(prCurrentMsduInfo, /* MSDU_INFO ptr */
  1220. ucTC, /* TC tag */
  1221. ucPacketType, /* Packet Type */
  1222. 0, /* Format ID */
  1223. prCurrentMsduInfo->fgIs802_1x, /* Flag 802.1x */
  1224. prCurrentMsduInfo->fgIs802_11, /* Flag 802.11 */
  1225. 0, /* PAL LLH */
  1226. 0, /* ACL SN */
  1227. PS_FORWARDING_TYPE_NON_PS, /* PS Forwarding Type */
  1228. 0 /* PS Session ID */
  1229. );
  1230. /* 4 <4> Enqueue the packet to different AC queue (max 5 AC queues) */
  1231. QUEUE_INSERT_TAIL(prTxQue, (P_QUE_ENTRY_T) prCurrentMsduInfo);
  1232. #if QM_TC_RESOURCE_EMPTY_COUNTER
  1233. {
  1234. P_TX_CTRL_T prTxCtrl = &prAdapter->rTxCtrl;
  1235. if (prTxCtrl->rTc.aucFreeBufferCount[ucTC] == 0) {
  1236. prQM->au4QmTcResourceEmptyCounter[prCurrentMsduInfo->ucNetworkType][ucTC]++;
  1237. /*
  1238. DBGLOG(QM, TRACE, ("TC%d Q Empty Count: [%d]%ld\n",
  1239. ucTC,
  1240. prCurrentMsduInfo->ucNetworkType,
  1241. prQM->au4QmTcResourceEmptyCounter[prCurrentMsduInfo->ucNetworkType][ucTC]));
  1242. */
  1243. }
  1244. }
  1245. #endif
  1246. #if QM_TEST_MODE
  1247. if (++prQM->u4PktCount == QM_TEST_TRIGGER_TX_COUNT) {
  1248. prQM->u4PktCount = 0;
  1249. qmTestCases(prAdapter);
  1250. }
  1251. #endif
  1252. DBGLOG(QM, LOUD, "Current queue length = %u\n", prTxQue->u4NumElem);
  1253. } while (prNextMsduInfo);
  1254. if (QUEUE_IS_NOT_EMPTY(&rNotEnqueuedQue)) {
  1255. QM_TX_SET_NEXT_MSDU_INFO((P_MSDU_INFO_T) QUEUE_GET_TAIL(&rNotEnqueuedQue), NULL);
  1256. prMsduInfoReleaseList = (P_MSDU_INFO_T) QUEUE_GET_HEAD(&rNotEnqueuedQue);
  1257. }
  1258. return prMsduInfoReleaseList;
  1259. }
  1260. /*----------------------------------------------------------------------------*/
  1261. /*!
  1262. * \brief Determine the STA_REC index for a packet
  1263. *
  1264. * \param[in] prMsduInfo Pointer to the packet
  1265. *
  1266. * \return (none)
  1267. */
  1268. /*----------------------------------------------------------------------------*/
  1269. static VOID qmDetermineStaRecIndex(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo)
  1270. {
  1271. UINT_32 i;
  1272. P_STA_RECORD_T prTempStaRec;
  1273. /* P_QUE_MGT_T prQM = &prAdapter->rQM; */
  1274. prTempStaRec = NULL;
  1275. ASSERT(prMsduInfo);
  1276. /* 4 <1> DA = BMCAST */
  1277. if (IS_BMCAST_MAC_ADDR(prMsduInfo->aucEthDestAddr)) {
  1278. /* For intrastructure mode and P2P (playing as a GC), BMCAST frames shall be sent to the AP.
  1279. * FW shall take care of this. The host driver is not able to distinguish these cases. */
  1280. prMsduInfo->ucStaRecIndex = STA_REC_INDEX_BMCAST;
  1281. DBGLOG(QM, LOUD, "TX with DA = BMCAST\n");
  1282. return;
  1283. }
  1284. #if (CFG_SUPPORT_TDLS == 1)
  1285. /* Check if the peer is TDLS one */
  1286. if (TdlsexStaRecIdxGet(prAdapter, prMsduInfo) == TDLS_STATUS_SUCCESS)
  1287. return; /* find a TDLS record */
  1288. #endif /* CFG_SUPPORT_TDLS */
  1289. /* 4 <2> Check if an AP STA is present */
  1290. for (i = 0; i < CFG_NUM_OF_STA_RECORD; i++) {
  1291. prTempStaRec = &(prAdapter->arStaRec[i]);
  1292. if ((prTempStaRec->ucNetTypeIndex == prMsduInfo->ucNetworkType)
  1293. && (prTempStaRec->fgIsAp)
  1294. && (prTempStaRec->fgIsValid)) {
  1295. prMsduInfo->ucStaRecIndex = prTempStaRec->ucIndex;
  1296. return;
  1297. }
  1298. }
  1299. /* 4 <3> Not BMCAST, No AP --> Compare DA (i.e., to see whether this is a unicast frame to a client) */
  1300. for (i = 0; i < CFG_NUM_OF_STA_RECORD; i++) {
  1301. prTempStaRec = &(prAdapter->arStaRec[i]);
  1302. if (prTempStaRec->fgIsValid) {
  1303. if (EQUAL_MAC_ADDR(prTempStaRec->aucMacAddr, prMsduInfo->aucEthDestAddr)) {
  1304. prMsduInfo->ucStaRecIndex = prTempStaRec->ucIndex;
  1305. return;
  1306. }
  1307. }
  1308. }
  1309. /* 4 <4> No STA found, Not BMCAST --> Indicate NOT_FOUND to FW */
  1310. prMsduInfo->ucStaRecIndex = STA_REC_INDEX_NOT_FOUND;
  1311. DBGLOG(QM, LOUD, "QM: TX with STA_REC_INDEX_NOT_FOUND\n");
  1312. #if (QM_TEST_MODE && QM_TEST_FAIR_FORWARDING)
  1313. prMsduInfo->ucStaRecIndex = (UINT_8) prQM->u4CurrentStaRecIndexToEnqueue;
  1314. #endif
  1315. }
  1316. /*----------------------------------------------------------------------------*/
  1317. /*!
  1318. * \brief Dequeue TX packets from a STA_REC for a particular TC
  1319. *
  1320. * \param[out] prQue The queue to put the dequeued packets
  1321. * \param[in] ucTC The TC index (TC0_INDEX to TC5_INDEX)
  1322. * \param[in] ucMaxNum The maximum amount of dequeued packets
  1323. *
  1324. * \return (none)
  1325. */
  1326. /*----------------------------------------------------------------------------*/
  1327. static VOID
  1328. qmDequeueTxPacketsFromPerStaQueues(IN P_ADAPTER_T prAdapter,
  1329. OUT P_QUE_T prQue, IN UINT_8 ucTC, IN UINT_8 ucCurrentQuota, IN UINT_8 ucTotalQuota)
  1330. {
  1331. #if QM_FORWARDING_FAIRNESS
  1332. UINT_32 i; /* Loop for */
  1333. PUINT_32 pu4HeadStaRecIndex; /* The Head STA index */
  1334. PUINT_32 pu4HeadStaRecForwardCount; /* The total forwarded packets for the head STA */
  1335. P_STA_RECORD_T prStaRec; /* The current focused STA */
  1336. P_BSS_INFO_T prBssInfo; /* The Bss for current focused STA */
  1337. P_QUE_T prCurrQueue; /* The current TX queue to dequeue */
  1338. P_MSDU_INFO_T prDequeuedPkt; /* The dequeued packet */
  1339. UINT_32 u4ForwardCount; /* To remember the total forwarded packets for a STA */
  1340. UINT_32 u4MaxForwardCount; /* The maximum number of packets a STA can forward */
  1341. UINT_32 u4Resource; /* The TX resource amount */
  1342. BOOLEAN fgChangeHeadSta; /* Whether a new head STA shall be determined at the end of the function */
  1343. P_QUE_MGT_T prQM = &prAdapter->rQM;
  1344. PUINT_8 pucFreeQuota = NULL;
  1345. #if CFG_ENABLE_WIFI_DIRECT
  1346. P_P2P_CHNL_REQ_INFO_T prChnlReqInfo = &prAdapter->rWifiVar.prP2pFsmInfo->rChnlReqInfo;
  1347. /*NFC Beam + Indication */
  1348. #endif
  1349. DBGLOG(QM, LOUD, "Enter qmDequeueTxPacketsFromPerStaQueues (TC = %u)\n", ucTC);
  1350. ASSERT(ucTC == TC0_INDEX || ucTC == TC1_INDEX || ucTC == TC2_INDEX || ucTC == TC3_INDEX || ucTC == TC4_INDEX);
  1351. if (!ucCurrentQuota) {
  1352. DBGLOG(TX, LOUD, "@@@@@ TC = %u ucCurrentQuota = %u @@@@@\n", ucTC, ucCurrentQuota);
  1353. return;
  1354. }
  1355. u4Resource = ucCurrentQuota;
  1356. /* 4 <1> Determine the head STA */
  1357. /* The head STA shall be an active STA */
  1358. pu4HeadStaRecIndex = &(prQM->au4HeadStaRecIndex[ucTC]);
  1359. pu4HeadStaRecForwardCount = &(prQM->au4ForwardCount[ucTC]);
  1360. DBGLOG(QM, LOUD, "(Fairness) TID = %u Init Head STA = %u Resource = %u\n",
  1361. ucTC, *pu4HeadStaRecIndex, u4Resource);
  1362. /* From STA[x] to STA[x+1] to STA[x+2] to ... to STA[x] */
  1363. for (i = 0; i < CFG_NUM_OF_STA_RECORD + 1; i++) {
  1364. prStaRec = &prAdapter->arStaRec[(*pu4HeadStaRecIndex)];
  1365. ASSERT(prStaRec);
  1366. /* Only Data frame (1x was not included) will be queued in */
  1367. if (prStaRec->fgIsValid) {
  1368. prBssInfo = &(prAdapter->rWifiVar.arBssInfo[prStaRec->ucNetTypeIndex]);
  1369. ASSERT(prBssInfo->ucNetTypeIndex == prStaRec->ucNetTypeIndex);
  1370. /* Determine how many packets the head STA is allowed to send in a round */
  1371. QM_DBG_CNT_INC(prQM, QM_DBG_CNT_25);
  1372. u4MaxForwardCount = ucTotalQuota;
  1373. #if CFG_ENABLE_WIFI_DIRECT
  1374. pucFreeQuota = NULL;
  1375. if (prStaRec->fgIsInPS && (ucTC != TC4_INDEX)) {
  1376. /* TODO: Change the threshold in coorperation with the PS forwarding mechanism */
  1377. /* u4MaxForwardCount = ucTotalQuota; */
  1378. /* Per STA flow control when STA in PS mode */
  1379. /* The PHASE 1: only update from ucFreeQuota (now) */
  1380. /* XXX The PHASE 2: Decide by ucFreeQuota and ucBmpDeliveryAC (per queue ) */
  1381. /* aucFreeQuotaPerQueue[] */
  1382. /* NOTE: other method to set u4Resource */
  1383. if (prStaRec->fgIsQoS && prStaRec->fgIsUapsdSupported
  1384. /* && prAdapter->rWifiVar.fgSupportQoS
  1385. && prAdapter->rWifiVar.fgSupportUAPSD */) {
  1386. if (prStaRec->ucBmpTriggerAC & BIT(ucTC)) {
  1387. u4MaxForwardCount = prStaRec->ucFreeQuotaForDelivery;
  1388. pucFreeQuota = &prStaRec->ucFreeQuotaForDelivery;
  1389. } else {
  1390. u4MaxForwardCount = prStaRec->ucFreeQuotaForNonDelivery;
  1391. pucFreeQuota = &prStaRec->ucFreeQuotaForNonDelivery;
  1392. }
  1393. } else {
  1394. ASSERT(prStaRec->ucFreeQuotaForDelivery == 0);
  1395. u4MaxForwardCount = prStaRec->ucFreeQuotaForNonDelivery;
  1396. pucFreeQuota = &prStaRec->ucFreeQuotaForNonDelivery;
  1397. }
  1398. } /* fgIsInPS */
  1399. #endif /* CFG_ENABLE_WIFI_DIRECT */
  1400. #if CFG_ENABLE_WIFI_DIRECT
  1401. /*NFC Beam + Indication */
  1402. if (prBssInfo->fgIsNetAbsent && (ucTC != TC4_INDEX)) {
  1403. if (prBssInfo->eCurrentOPMode == OP_MODE_ACCESS_POINT) {
  1404. if ((prChnlReqInfo->NFC_BEAM != 1) &&
  1405. (u4MaxForwardCount > prBssInfo->ucBssFreeQuota))
  1406. u4MaxForwardCount = prBssInfo->ucBssFreeQuota;
  1407. } else {
  1408. if (u4MaxForwardCount > prBssInfo->ucBssFreeQuota)
  1409. u4MaxForwardCount = prBssInfo->ucBssFreeQuota;
  1410. }
  1411. }
  1412. #endif /* CFG_ENABLE_WIFI_DIRECT */
  1413. /* Determine whether the head STA can continue to forward packets in this round */
  1414. if ((*pu4HeadStaRecForwardCount) < u4MaxForwardCount)
  1415. break;
  1416. } /* prStaRec->fgIsValid */
  1417. else {
  1418. /* The current Head STA has been deactivated, so search for a new head STA */
  1419. prStaRec = NULL;
  1420. prBssInfo = NULL;
  1421. (*pu4HeadStaRecIndex)++;
  1422. (*pu4HeadStaRecIndex) %= CFG_NUM_OF_STA_RECORD;
  1423. /* Reset the forwarding count before searching (since this is for a new selected STA) */
  1424. (*pu4HeadStaRecForwardCount) = 0;
  1425. }
  1426. } /* i < CFG_NUM_OF_STA_RECORD + 1 */
  1427. /* All STA_RECs are inactive, so exit */
  1428. if (!prStaRec) {
  1429. /* Under concurrent, it is possible that there is no candidcated STA. */
  1430. /* DBGLOG(TX, EVENT, ("All STA_RECs are inactive\n")); */
  1431. return;
  1432. }
  1433. DBGLOG(QM, LOUD, "(Fairness) TID = %u Round Head STA = %u\n", ucTC, *pu4HeadStaRecIndex);
  1434. /* 4 <2> Dequeue packets from the head STA */
  1435. prCurrQueue = &prStaRec->arTxQueue[ucTC];
  1436. prDequeuedPkt = NULL;
  1437. fgChangeHeadSta = FALSE;
  1438. #if (CFG_SUPPORT_TDLS == 1)
  1439. if (pucFreeQuota != NULL)
  1440. TdlsexTxQuotaCheck(prAdapter->prGlueInfo, prStaRec, *pucFreeQuota);
  1441. #endif /* CFG_SUPPORT_TDLS */
  1442. while (prCurrQueue) {
  1443. #if QM_DEBUG_COUNTER
  1444. if (ucTC <= TC4_INDEX) {
  1445. if (QUEUE_IS_EMPTY(prCurrQueue)) {
  1446. QM_DBG_CNT_INC(prQM, ucTC);
  1447. /* QM_DBG_CNT_00 *//* QM_DBG_CNT_01 *//* QM_DBG_CNT_02 */
  1448. /* QM_DBG_CNT_03 *//* QM_DBG_CNT_04 */
  1449. }
  1450. if (u4Resource == 0) {
  1451. QM_DBG_CNT_INC(prQM, ucTC + 5);
  1452. /* QM_DBG_CNT_05 *//* QM_DBG_CNT_06 *//* QM_DBG_CNT_07 */
  1453. /* QM_DBG_CNT_08 *//* QM_DBG_CNT_09 */
  1454. }
  1455. if (((*pu4HeadStaRecForwardCount) >= u4MaxForwardCount)) {
  1456. QM_DBG_CNT_INC(prQM, ucTC + 10);
  1457. /* QM_DBG_CNT_10 *//* QM_DBG_CNT_11 *//* QM_DBG_CNT_12 */
  1458. /* QM_DBG_CNT_13 *//* QM_DBG_CNT_14 */
  1459. }
  1460. }
  1461. #endif
  1462. /* Three cases to break: (1) No resource (2) No packets (3) Fairness */
  1463. if (QUEUE_IS_EMPTY(prCurrQueue) || ((*pu4HeadStaRecForwardCount) >= u4MaxForwardCount)) {
  1464. fgChangeHeadSta = TRUE;
  1465. break;
  1466. } else if (u4Resource == 0) {
  1467. #if (CFG_SUPPORT_STATISTICS == 1)
  1468. prStaRec->u4NumOfNoTxQuota++;
  1469. #endif /* CFG_SUPPORT_STATISTICS */
  1470. break;
  1471. }
  1472. QUEUE_REMOVE_HEAD(prCurrQueue, prDequeuedPkt, P_MSDU_INFO_T);
  1473. #if (CFG_SUPPORT_TDLS_DBG == 1)
  1474. if (prDequeuedPkt != NULL) {
  1475. struct sk_buff *prSkb = (struct sk_buff *)prDequeuedPkt->prPacket;
  1476. UINT8 *pkt = prSkb->data;
  1477. UINT16 u2Identifier;
  1478. if ((*(pkt + 12) == 0x08) && (*(pkt + 13) == 0x00)) {
  1479. /* ip */
  1480. u2Identifier = ((*(pkt + 18)) << 8) | (*(pkt + 19));
  1481. DBGLOG(QM, LOUD, "<d> %d\n", u2Identifier);
  1482. }
  1483. }
  1484. #endif
  1485. #if DBG && 0
  1486. LOG_FUNC("Deq0 TC %d queued %u net %u mac len %u len %u Type %u 1x %u 11 %u\n",
  1487. prDequeuedPkt->ucTC,
  1488. prCurrQueue->u4NumElem,
  1489. prDequeuedPkt->ucNetworkType,
  1490. prDequeuedPkt->ucMacHeaderLength,
  1491. prDequeuedPkt->u2FrameLength,
  1492. prDequeuedPkt->ucPacketType, prDequeuedPkt->fgIs802_1x, prDequeuedPkt->fgIs802_11);
  1493. LOG_FUNC("Dest Mac: %pM\n", prDequeuedPkt->aucEthDestAddr);
  1494. #if LINUX
  1495. {
  1496. struct sk_buff *prSkb = (struct sk_buff *)prDequeuedPkt->prPacket;
  1497. dumpMemory8((PUINT_8) prSkb->data, prSkb->len);
  1498. }
  1499. #endif
  1500. #endif
  1501. ASSERT(prDequeuedPkt->ucTC == ucTC);
  1502. if (!QUEUE_IS_EMPTY(prCurrQueue)) {
  1503. /* XXX: check all queues for STA */
  1504. prDequeuedPkt->ucPsForwardingType = PS_FORWARDING_MORE_DATA_ENABLED;
  1505. }
  1506. QUEUE_INSERT_TAIL(prQue, (P_QUE_ENTRY_T) prDequeuedPkt);
  1507. u4Resource--;
  1508. (*pu4HeadStaRecForwardCount)++;
  1509. #if CFG_ENABLE_WIFI_DIRECT
  1510. /* XXX The PHASE 2: decrease from aucFreeQuotaPerQueue[] */
  1511. if (prStaRec->fgIsInPS && (ucTC != TC4_INDEX)) {
  1512. if ((pucFreeQuota) && (*pucFreeQuota > 0))
  1513. *pucFreeQuota = *pucFreeQuota - 1;
  1514. }
  1515. #endif /* CFG_ENABLE_WIFI_DIRECT */
  1516. #if CFG_ENABLE_WIFI_DIRECT
  1517. if (prBssInfo->fgIsNetAbsent && (ucTC != TC4_INDEX)) {
  1518. if (prBssInfo->ucBssFreeQuota > 0)
  1519. prBssInfo->ucBssFreeQuota--;
  1520. }
  1521. #endif /* CFG_ENABLE_WIFI_DIRECT */
  1522. }
  1523. if (*pu4HeadStaRecForwardCount) {
  1524. DBGLOG(QM, LOUD,
  1525. "TC = %u Round Head STA = %u, u4HeadStaRecForwardCount = %u\n", ucTC, *pu4HeadStaRecIndex,
  1526. (*pu4HeadStaRecForwardCount));
  1527. }
  1528. #if QM_BURST_END_INFO_ENABLED
  1529. /* Let FW know which packet is the last one dequeued from the STA */
  1530. if (prDequeuedPkt)
  1531. prDequeuedPkt->fgIsBurstEnd = TRUE;
  1532. #endif
  1533. /* 4 <3> Dequeue from the other STAs if there is residual TX resource */
  1534. /* Check all of the STAs to continue forwarding packets (including the head STA) */
  1535. for (i = 0; i < CFG_NUM_OF_STA_RECORD; i++) {
  1536. /* Break in case no reasource is available */
  1537. if (u4Resource == 0)
  1538. break;
  1539. /* The current head STA will be examined when i = CFG_NUM_OF_STA_RECORD-1 */
  1540. prStaRec = &prAdapter->arStaRec[((*pu4HeadStaRecIndex) + i + 1) % CFG_NUM_OF_STA_RECORD];
  1541. ASSERT(prStaRec);
  1542. if (prStaRec->fgIsValid) {
  1543. prBssInfo = &(prAdapter->rWifiVar.arBssInfo[prStaRec->ucNetTypeIndex]);
  1544. ASSERT(prBssInfo->ucNetTypeIndex == prStaRec->ucNetTypeIndex);
  1545. DBGLOG(QM, LOUD, "(Fairness) TID = %u Sharing STA = %u Resource = %u\n",
  1546. ucTC, prStaRec->ucIndex, u4Resource);
  1547. prCurrQueue = &prStaRec->arTxQueue[ucTC];
  1548. u4ForwardCount = 0;
  1549. u4MaxForwardCount = ucTotalQuota;
  1550. #if CFG_ENABLE_WIFI_DIRECT
  1551. pucFreeQuota = NULL;
  1552. if (prStaRec->fgIsInPS && (ucTC != TC4_INDEX)) {
  1553. /* TODO: Change the threshold in coorperation with the PS forwarding mechanism */
  1554. /* u4MaxForwardCount = ucTotalQuota; */
  1555. /* Per STA flow control when STA in PS mode */
  1556. /* The PHASE 1: only update from ucFreeQuota (now) */
  1557. /* XXX The PHASE 2: Decide by ucFreeQuota and ucBmpDeliveryAC (per queue ) */
  1558. /* aucFreeQuotaPerQueue[] */
  1559. /* NOTE: other method to set u4Resource */
  1560. if (prStaRec->fgIsQoS && prStaRec->fgIsUapsdSupported
  1561. /* && prAdapter->rWifiVar.fgSupportQoS
  1562. && prAdapter->rWifiVar.fgSupportUAPSD */) {
  1563. if (prStaRec->ucBmpTriggerAC & BIT(ucTC)) {
  1564. u4MaxForwardCount = prStaRec->ucFreeQuotaForDelivery;
  1565. pucFreeQuota = &prStaRec->ucFreeQuotaForDelivery;
  1566. } else {
  1567. u4MaxForwardCount = prStaRec->ucFreeQuotaForNonDelivery;
  1568. pucFreeQuota = &prStaRec->ucFreeQuotaForNonDelivery;
  1569. }
  1570. } else {
  1571. ASSERT(prStaRec->ucFreeQuotaForDelivery == 0);
  1572. u4MaxForwardCount = prStaRec->ucFreeQuotaForNonDelivery;
  1573. pucFreeQuota = &prStaRec->ucFreeQuotaForNonDelivery;
  1574. }
  1575. }
  1576. #endif /* CFG_ENABLE_WIFI_DIRECT */
  1577. #if CFG_ENABLE_WIFI_DIRECT
  1578. if (prBssInfo->fgIsNetAbsent && (ucTC != TC4_INDEX)) {
  1579. if (u4MaxForwardCount > prBssInfo->ucBssFreeQuota)
  1580. u4MaxForwardCount = prBssInfo->ucBssFreeQuota;
  1581. }
  1582. #endif /* CFG_ENABLE_WIFI_DIRECT */
  1583. } /* prStaRec->fgIsValid */
  1584. else {
  1585. prBssInfo = NULL;
  1586. /* Invalid STA, so check the next STA */
  1587. continue;
  1588. }
  1589. while (prCurrQueue) {
  1590. /* Three cases to break: (1) No resource (2) No packets (3) Fairness */
  1591. if ((u4Resource == 0) || QUEUE_IS_EMPTY(prCurrQueue) || (u4ForwardCount >= u4MaxForwardCount))
  1592. break;
  1593. QUEUE_REMOVE_HEAD(prCurrQueue, prDequeuedPkt, P_MSDU_INFO_T);
  1594. #if DBG && 0
  1595. DBGLOG(QM, LOUD, "Deq0 TC %d queued %u net %u mac len %u len %u Type %u 1x %u 11 %u\n",
  1596. prDequeuedPkt->ucTC,
  1597. prCurrQueue->u4NumElem,
  1598. prDequeuedPkt->ucNetworkType,
  1599. prDequeuedPkt->ucMacHeaderLength,
  1600. prDequeuedPkt->u2FrameLength,
  1601. prDequeuedPkt->ucPacketType,
  1602. prDequeuedPkt->fgIs802_1x, prDequeuedPkt->fgIs802_11));
  1603. DBGLOG(QM, LOUD, "Dest Mac: %pM\n", prDequeuedPkt->aucEthDestAddr);
  1604. #if LINUX
  1605. {
  1606. struct sk_buff *prSkb = (struct sk_buff *)prDequeuedPkt->prPacket;
  1607. dumpMemory8((PUINT_8) prSkb->data, prSkb->len);
  1608. }
  1609. #endif
  1610. #endif
  1611. ASSERT(prDequeuedPkt->ucTC == ucTC);
  1612. if (!QUEUE_IS_EMPTY(prCurrQueue))
  1613. /* more data field ? */
  1614. prDequeuedPkt->ucPsForwardingType = PS_FORWARDING_MORE_DATA_ENABLED;
  1615. QUEUE_INSERT_TAIL(prQue, (P_QUE_ENTRY_T) prDequeuedPkt);
  1616. u4Resource--;
  1617. u4ForwardCount++;
  1618. #if CFG_ENABLE_WIFI_DIRECT
  1619. /* XXX The PHASE 2: decrease from aucFreeQuotaPerQueue[] */
  1620. if (prStaRec->fgIsInPS && (ucTC != TC4_INDEX)) {
  1621. ASSERT(pucFreeQuota);
  1622. ASSERT(*pucFreeQuota > 0);
  1623. if (*pucFreeQuota > 0)
  1624. *pucFreeQuota = *pucFreeQuota - 1;
  1625. }
  1626. #endif /* CFG_ENABLE_WIFI_DIRECT */
  1627. #if CFG_ENABLE_WIFI_DIRECT
  1628. ASSERT(prBssInfo->ucNetTypeIndex == prStaRec->ucNetTypeIndex);
  1629. if (prBssInfo->fgIsNetAbsent && (ucTC != TC4_INDEX)) {
  1630. if (prBssInfo->ucBssFreeQuota > 0)
  1631. prBssInfo->ucBssFreeQuota--;
  1632. }
  1633. #endif /* CFG_ENABLE_WIFI_DIRECT */
  1634. }
  1635. #if QM_BURST_END_INFO_ENABLED
  1636. /* Let FW know which packet is the last one dequeued from the STA */
  1637. if (u4ForwardCount)
  1638. prDequeuedPkt->fgIsBurstEnd = TRUE;
  1639. #endif
  1640. }
  1641. if (fgChangeHeadSta) {
  1642. (*pu4HeadStaRecIndex)++;
  1643. (*pu4HeadStaRecIndex) %= CFG_NUM_OF_STA_RECORD;
  1644. (*pu4HeadStaRecForwardCount) = 0;
  1645. DBGLOG(QM, LOUD, "(Fairness) TID = %u Scheduled Head STA = %u Left Resource = %u\n",
  1646. ucTC, (*pu4HeadStaRecIndex), u4Resource);
  1647. }
  1648. /***************************************************************************************/
  1649. #else
  1650. UINT_8 ucStaRecIndex;
  1651. P_STA_RECORD_T prStaRec;
  1652. P_QUE_T prCurrQueue;
  1653. UINT_8 ucPktCount;
  1654. P_MSDU_INFO_T prDequeuedPkt;
  1655. DBGLOG(QM, LOUD, "Enter qmDequeueTxPacketsFromPerStaQueues (TC = %u)\n", ucTC);
  1656. if (ucCurrentQuota == 0)
  1657. return;
  1658. /* 4 <1> Determine the queue index and the head STA */
  1659. /* The head STA */
  1660. ucStaRecIndex = 0; /* TODO: Get the current head STA */
  1661. prStaRec = QM_GET_STA_REC_PTR_FROM_INDEX(prAdapter, ucStaRecIndex);
  1662. ASSERT(prStaRec);
  1663. if (prStaRec == NULL)
  1664. return;
  1665. /* The queue to pull out packets */
  1666. ASSERT(ucTC == TC0_INDEX || ucTC == TC1_INDEX || ucTC == TC2_INDEX || ucTC == TC3_INDEX || ucTC == TC4_INDEX);
  1667. prCurrQueue = &prStaRec->arTxQueue[ucTC];
  1668. ucPktCount = ucCurrentQuota;
  1669. prDequeuedPkt = NULL;
  1670. /* 4 <2> Dequeue packets for the head STA */
  1671. while (TRUE) {
  1672. if (!(prStaRec->fgIsValid) || ucPktCount == 0 || QUEUE_IS_EMPTY(prCurrQueue)) {
  1673. break;
  1674. } else {
  1675. QUEUE_REMOVE_HEAD(prCurrQueue, prDequeuedPkt, P_MSDU_INFO_T);
  1676. /* DbgPrint("QM: Remove Queue Head, TC= %d\n", prDequeuedPkt->ucTC); */
  1677. ASSERT(prDequeuedPkt->ucTC == ucTC);
  1678. QUEUE_INSERT_TAIL(prQue, (P_QUE_ENTRY_T) prDequeuedPkt);
  1679. ucPktCount--;
  1680. }
  1681. }
  1682. /* DbgPrint("QM: Remaining number of queued packets = %d\n", prCurrQueue->u4NumElem); */
  1683. #if QM_BURST_END_INFO_ENABLED
  1684. if (prDequeuedPkt)
  1685. prDequeuedPkt->fgIsBurstEnd = TRUE;
  1686. #endif
  1687. /* 4 <3> Update scheduling info */
  1688. /* TODO */
  1689. /* 4 <4> Utilize the remainaing TX opportunities for non-head STAs */
  1690. /* TODO */
  1691. #endif
  1692. }
  1693. /*----------------------------------------------------------------------------*/
  1694. /*!
  1695. * \brief Dequeue TX packets from a per-Type-based Queue for a particular TC
  1696. *
  1697. * \param[out] prQue The queue to put the dequeued packets
  1698. * \param[in] ucTC The TC index (Shall always be TC5_INDEX)
  1699. * \param[in] ucMaxNum The maximum amount of dequeued packets
  1700. *
  1701. * \return (none)
  1702. */
  1703. /*----------------------------------------------------------------------------*/
  1704. static VOID
  1705. qmDequeueTxPacketsFromPerTypeQueues(IN P_ADAPTER_T prAdapter, OUT P_QUE_T prQue, IN UINT_8 ucTC, IN UINT_8 ucMaxNum)
  1706. {
  1707. /* UINT_8 ucQueIndex; */
  1708. /* UINT_8 ucStaRecIndex; */
  1709. P_BSS_INFO_T prBssInfo;
  1710. P_BSS_INFO_T parBssInfo;
  1711. P_QUE_T prCurrQueue;
  1712. UINT_8 ucPktCount;
  1713. P_MSDU_INFO_T prDequeuedPkt;
  1714. P_MSDU_INFO_T prBurstEndPkt;
  1715. QUE_T rMergeQue;
  1716. P_QUE_T prMergeQue;
  1717. P_QUE_MGT_T prQM;
  1718. DBGLOG(QM, LOUD, "Enter qmDequeueTxPacketsFromPerTypeQueues (TC = %d, Max = %d)\n", ucTC, ucMaxNum);
  1719. /* TC5: Broadcast/Multicast data packets */
  1720. ASSERT(ucTC == TC5_INDEX);
  1721. if (ucMaxNum == 0)
  1722. return;
  1723. prQM = &prAdapter->rQM;
  1724. /* 4 <1> Determine the queue */
  1725. prCurrQueue = &prQM->arTxQueue[TX_QUEUE_INDEX_BMCAST];
  1726. ucPktCount = ucMaxNum;
  1727. prDequeuedPkt = NULL;
  1728. prBurstEndPkt = NULL;
  1729. parBssInfo = prAdapter->rWifiVar.arBssInfo;
  1730. QUEUE_INITIALIZE(&rMergeQue);
  1731. prMergeQue = &rMergeQue;
  1732. /* 4 <2> Dequeue packets */
  1733. while (TRUE) {
  1734. if (ucPktCount == 0 || QUEUE_IS_EMPTY(prCurrQueue))
  1735. break;
  1736. QUEUE_REMOVE_HEAD(prCurrQueue, prDequeuedPkt, P_MSDU_INFO_T);
  1737. ASSERT(prDequeuedPkt->ucTC == ucTC);
  1738. ASSERT(prDequeuedPkt->ucNetworkType < NETWORK_TYPE_INDEX_NUM);
  1739. prBssInfo = &parBssInfo[prDequeuedPkt->ucNetworkType];
  1740. if (IS_BSS_ACTIVE(prBssInfo)) {
  1741. if (!prBssInfo->fgIsNetAbsent) {
  1742. QUEUE_INSERT_TAIL(prQue, (P_QUE_ENTRY_T) prDequeuedPkt);
  1743. prBurstEndPkt = prDequeuedPkt;
  1744. ucPktCount--;
  1745. QM_DBG_CNT_INC(prQM, QM_DBG_CNT_26);
  1746. #if DBG && 0
  1747. LOG_FUNC
  1748. ("DeqType TC %d queued %u net %u mac len %u len %u Type %u 1x %u 11 %u\n",
  1749. prDequeuedPkt->ucTC, prCurrQueue->u4NumElem, prDequeuedPkt->ucNetworkType,
  1750. prDequeuedPkt->ucMacHeaderLength, prDequeuedPkt->u2FrameLength,
  1751. prDequeuedPkt->ucPacketType, prDequeuedPkt->fgIs802_1x,
  1752. prDequeuedPkt->fgIs802_11);
  1753. LOG_FUNC("Dest Mac: %pM\n", prDequeuedPkt->aucEthDestAddr);
  1754. #if LINUX
  1755. {
  1756. struct sk_buff *prSkb = (struct sk_buff *)prDequeuedPkt->prPacket;
  1757. dumpMemory8((PUINT_8) prSkb->data, prSkb->len);
  1758. }
  1759. #endif
  1760. #endif
  1761. } else {
  1762. QUEUE_INSERT_TAIL(prMergeQue, (P_QUE_ENTRY_T) prDequeuedPkt);
  1763. }
  1764. } else {
  1765. QM_TX_SET_NEXT_MSDU_INFO(prDequeuedPkt, NULL);
  1766. wlanProcessQueuedMsduInfo(prAdapter, prDequeuedPkt);
  1767. }
  1768. }
  1769. if (QUEUE_IS_NOT_EMPTY(prMergeQue)) {
  1770. QUEUE_CONCATENATE_QUEUES(prMergeQue, prCurrQueue);
  1771. QUEUE_MOVE_ALL(prCurrQueue, prMergeQue);
  1772. if (QUEUE_GET_TAIL(prCurrQueue))
  1773. QM_TX_SET_NEXT_MSDU_INFO((P_MSDU_INFO_T) QUEUE_GET_TAIL(prCurrQueue), NULL);
  1774. }
  1775. #if QM_BURST_END_INFO_ENABLED
  1776. if (prBurstEndPkt)
  1777. prBurstEndPkt->fgIsBurstEnd = TRUE;
  1778. #endif
  1779. } /* qmDequeueTxPacketsFromPerTypeQueues */
  1780. /*----------------------------------------------------------------------------*/
  1781. /*!
  1782. * \brief Dequeue TX packets to send to HIF TX
  1783. *
  1784. * \param[in] prTcqStatus Info about the maximum amount of dequeued packets
  1785. *
  1786. * \return The list of dequeued TX packets
  1787. */
  1788. /*----------------------------------------------------------------------------*/
  1789. P_MSDU_INFO_T qmDequeueTxPackets(IN P_ADAPTER_T prAdapter, IN P_TX_TCQ_STATUS_T prTcqStatus)
  1790. {
  1791. INT32 i;
  1792. P_MSDU_INFO_T prReturnedPacketListHead;
  1793. QUE_T rReturnedQue;
  1794. DBGLOG(QM, LOUD, "Enter qmDequeueTxPackets\n");
  1795. QUEUE_INITIALIZE(&rReturnedQue);
  1796. prReturnedPacketListHead = NULL;
  1797. /* dequeue packets from different AC queue based on available aucFreeBufferCount */
  1798. /* TC0 to TC4: AC0~AC3, 802.1x (commands packets are not handled by QM) */
  1799. for (i = TC4_INDEX; i >= TC0_INDEX; i--) {
  1800. DBGLOG(QM, LOUD, "Dequeue packets from Per-STA queue[%d]\n", i);
  1801. /*
  1802. in the function, we will re-calculate the ucFreeQuota.
  1803. If any packet with any priority for the station will be sent, ucFreeQuota --
  1804. Note1: ucFreeQuota will be decrease only when station is in power save mode.
  1805. In active mode, we will sent the packet to the air directly.
  1806. if(prStaRec->fgIsInPS && (ucTC!=TC4_INDEX)) {
  1807. ASSERT(pucFreeQuota);
  1808. ASSERT(*pucFreeQuota>0);
  1809. if ((pucFreeQuota) && (*pucFreeQuota>0)) {
  1810. *pucFreeQuota = *pucFreeQuota - 1;
  1811. }
  1812. }
  1813. Note2: maximum queued number for a station is 10, TXM_MAX_BUFFER_PER_STA_DEF in fw
  1814. i.e. default prStaRec->ucFreeQuota = 10
  1815. Note3: In qmUpdateFreeQuota(), we will adjust
  1816. ucFreeQuotaForNonDelivery = ucFreeQuota>>1;
  1817. ucFreeQuotaForDelivery = ucFreeQuota - ucFreeQuotaForNonDelivery;
  1818. */
  1819. qmDequeueTxPacketsFromPerStaQueues(prAdapter,
  1820. &rReturnedQue,
  1821. (UINT_8) i,
  1822. prTcqStatus->aucFreeBufferCount[i], /* maximum dequeue number */
  1823. prTcqStatus->aucMaxNumOfBuffer[i]);
  1824. /* The aggregate number of dequeued packets */
  1825. DBGLOG(QM, LOUD, "DQA)[%u](%u)\n", i, rReturnedQue.u4NumElem);
  1826. }
  1827. /* TC5 (BMCAST or STA-NOT-FOUND packets) */
  1828. qmDequeueTxPacketsFromPerTypeQueues(prAdapter,
  1829. &rReturnedQue, TC5_INDEX, prTcqStatus->aucFreeBufferCount[TC5_INDEX]
  1830. );
  1831. DBGLOG(QM, LOUD, "Current total number of dequeued packets = %u\n", rReturnedQue.u4NumElem);
  1832. if (QUEUE_IS_NOT_EMPTY(&rReturnedQue)) {
  1833. prReturnedPacketListHead = (P_MSDU_INFO_T) QUEUE_GET_HEAD(&rReturnedQue);
  1834. QM_TX_SET_NEXT_MSDU_INFO((P_MSDU_INFO_T) QUEUE_GET_TAIL(&rReturnedQue), NULL);
  1835. }
  1836. return prReturnedPacketListHead;
  1837. }
  1838. /*----------------------------------------------------------------------------*/
  1839. /*!
  1840. * \brief Adjust the TC quotas according to traffic demands
  1841. *
  1842. * \param[out] prTcqAdjust The resulting adjustment
  1843. * \param[in] prTcqStatus Info about the current TC quotas and counters
  1844. *
  1845. * \return (none)
  1846. */
  1847. /*----------------------------------------------------------------------------*/
  1848. VOID qmAdjustTcQuotas(IN P_ADAPTER_T prAdapter, OUT P_TX_TCQ_ADJUST_T prTcqAdjust, IN P_TX_TCQ_STATUS_T prTcqStatus)
  1849. {
  1850. #if QM_ADAPTIVE_TC_RESOURCE_CTRL
  1851. UINT_32 i;
  1852. P_QUE_MGT_T prQM = &prAdapter->rQM;
  1853. /* Must reset */
  1854. for (i = 0; i < TC_NUM; i++)
  1855. prTcqAdjust->acVariation[i] = 0;
  1856. /* 4 <1> If TC resource is not just adjusted, exit directly */
  1857. if (!prQM->fgTcResourcePostAnnealing)
  1858. return;
  1859. /* 4 <2> Adjust TcqStatus according to the updated prQM->au4CurrentTcResource */
  1860. else {
  1861. INT_32 i4TotalExtraQuota = 0;
  1862. INT_32 ai4ExtraQuota[TC_NUM];
  1863. BOOLEAN fgResourceRedistributed = TRUE;
  1864. /* Obtain the free-to-distribute resource */
  1865. for (i = 0; i < TC_NUM; i++) {
  1866. ai4ExtraQuota[i] =
  1867. (INT_32) prTcqStatus->aucMaxNumOfBuffer[i] - (INT_32) prQM->au4CurrentTcResource[i];
  1868. if (ai4ExtraQuota[i] > 0) { /* The resource shall be reallocated to other TCs */
  1869. if (ai4ExtraQuota[i] > prTcqStatus->aucFreeBufferCount[i]) {
  1870. /*
  1871. we have residunt TC resources for the TC:
  1872. EX: aucMaxNumOfBuffer[] = 20, au4CurrentTcResource[] = 5
  1873. ai4ExtraQuota[] = 15, aucFreeBufferCount[] = 10
  1874. so ai4ExtraQuota[] = aucFreeBufferCount[] = 10
  1875. because we available TC resources actually is 10, not 20
  1876. */
  1877. ai4ExtraQuota[i] = prTcqStatus->aucFreeBufferCount[i];
  1878. /*
  1879. FALSE means we can re-do TC resource adjustment in tx done
  1880. at next time, maybe more tx done is finished
  1881. */
  1882. fgResourceRedistributed = FALSE;
  1883. }
  1884. /* accumulate current all available TC resources */
  1885. i4TotalExtraQuota += ai4ExtraQuota[i];
  1886. /* deduce unused TC resources for the TC */
  1887. prTcqAdjust->acVariation[i] = (INT_8) (-ai4ExtraQuota[i]);
  1888. }
  1889. }
  1890. /* Distribute quotas to TCs which need extra resource according to prQM->au4CurrentTcResource */
  1891. for (i = 0; i < TC_NUM; i++) {
  1892. if (ai4ExtraQuota[i] < 0) {
  1893. /* The TC needs extra resources */
  1894. if ((-ai4ExtraQuota[i]) > i4TotalExtraQuota) {
  1895. /* the number of needed extra resources is larger than total available */
  1896. ai4ExtraQuota[i] = (-i4TotalExtraQuota);
  1897. /* wait for next tx done to do adjustment */
  1898. fgResourceRedistributed = FALSE;
  1899. }
  1900. /* decrease the total available */
  1901. i4TotalExtraQuota += ai4ExtraQuota[i];
  1902. /* mark to increase TC resources for the TC */
  1903. prTcqAdjust->acVariation[i] = (INT_8) (-ai4ExtraQuota[i]);
  1904. }
  1905. }
  1906. /* In case some TC is waiting for TX Done, continue to adjust TC quotas upon TX Done */
  1907. /*
  1908. if fgResourceRedistributed == TRUE, it means we will adjust at this time so
  1909. we need to re-adjust TC resources (fgTcResourcePostAnnealing = FALSE).
  1910. */
  1911. prQM->fgTcResourcePostAnnealing = (!fgResourceRedistributed);
  1912. #if QM_PRINT_TC_RESOURCE_CTRL
  1913. DBGLOG(QM, LOUD, "QM: Curr Quota [0]=%u [1]=%u [2]=%u [3]=%u [4]=%u [5]=%u\n",
  1914. prTcqStatus->aucFreeBufferCount[0],
  1915. prTcqStatus->aucFreeBufferCount[1],
  1916. prTcqStatus->aucFreeBufferCount[2],
  1917. prTcqStatus->aucFreeBufferCount[3],
  1918. prTcqStatus->aucFreeBufferCount[4], prTcqStatus->aucFreeBufferCount[5]
  1919. ));
  1920. #endif
  1921. }
  1922. #else
  1923. UINT_32 i;
  1924. for (i = 0; i < TC_NUM; i++)
  1925. prTcqAdjust->acVariation[i] = 0;
  1926. #endif
  1927. }
  1928. #if QM_ADAPTIVE_TC_RESOURCE_CTRL
  1929. /*----------------------------------------------------------------------------*/
  1930. /*!
  1931. * \brief Update the average TX queue length for the TC resource control mechanism
  1932. *
  1933. * \param (none)
  1934. *
  1935. * \return (none)
  1936. */
  1937. /*----------------------------------------------------------------------------*/
  1938. VOID qmUpdateAverageTxQueLen(IN P_ADAPTER_T prAdapter)
  1939. {
  1940. INT_32 u4CurrQueLen, i, k;
  1941. P_STA_RECORD_T prStaRec;
  1942. P_QUE_MGT_T prQM = &prAdapter->rQM;
  1943. /* 4 <1> Update the queue lengths for TC0 to TC3 (skip TC4) and TC5 */
  1944. /* use moving average algorithm to calculate au4AverageQueLen for every TC queue */
  1945. for (i = 0; i < NUM_OF_PER_STA_TX_QUEUES - 1; i++) {
  1946. u4CurrQueLen = 0;
  1947. for (k = 0; k < CFG_NUM_OF_STA_RECORD; k++) {
  1948. prStaRec = &prAdapter->arStaRec[k];
  1949. ASSERT(prStaRec);
  1950. /* If the STA is activated, get the queue length */
  1951. if (prStaRec->fgIsValid &&
  1952. (!prAdapter->rWifiVar.arBssInfo[prStaRec->ucNetTypeIndex].fgIsNetAbsent)
  1953. ) {
  1954. u4CurrQueLen += (prStaRec->arTxQueue[i].u4NumElem);
  1955. }
  1956. }
  1957. if (prQM->au4AverageQueLen[i] == 0) {
  1958. prQM->au4AverageQueLen[i] = (u4CurrQueLen << QM_QUE_LEN_MOVING_AVE_FACTOR); /* *8 */
  1959. } else {
  1960. /* len => len - len/8 = 7/8 * len + new len */
  1961. prQM->au4AverageQueLen[i] -= (prQM->au4AverageQueLen[i] >> QM_QUE_LEN_MOVING_AVE_FACTOR);
  1962. prQM->au4AverageQueLen[i] += (u4CurrQueLen);
  1963. }
  1964. }
  1965. /* Update the queue length for TC5 (BMCAST) */
  1966. u4CurrQueLen = prQM->arTxQueue[TX_QUEUE_INDEX_BMCAST].u4NumElem;
  1967. if (prQM->au4AverageQueLen[TC_NUM - 1] == 0) {
  1968. prQM->au4AverageQueLen[TC_NUM - 1] = (u4CurrQueLen << QM_QUE_LEN_MOVING_AVE_FACTOR);
  1969. } else {
  1970. prQM->au4AverageQueLen[TC_NUM - 1] -=
  1971. (prQM->au4AverageQueLen[TC_NUM - 1] >> QM_QUE_LEN_MOVING_AVE_FACTOR);
  1972. prQM->au4AverageQueLen[TC_NUM - 1] += (u4CurrQueLen);
  1973. }
  1974. /* 4 <2> Adjust TC resource assignment every 3 times */
  1975. /* Check whether it is time to adjust the TC resource assignment */
  1976. if (--prQM->u4TimeToAdjustTcResource == 0) { /* u4TimeToAdjustTcResource = 3 */
  1977. /* The last assignment has not been completely applied */
  1978. if (prQM->fgTcResourcePostAnnealing) {
  1979. /* Upon the next qmUpdateAverageTxQueLen function call, do this check again */
  1980. /* wait for next time to do qmReassignTcResource */
  1981. prQM->u4TimeToAdjustTcResource = 1;
  1982. } else { /* The last assignment has been applied */
  1983. prQM->u4TimeToAdjustTcResource = QM_INIT_TIME_TO_ADJUST_TC_RSC;
  1984. qmReassignTcResource(prAdapter);
  1985. }
  1986. }
  1987. /* Debug */
  1988. #if QM_PRINT_TC_RESOURCE_CTRL
  1989. for (i = 0; i < TC_NUM; i++) {
  1990. if (QM_GET_TX_QUEUE_LEN(prAdapter, i) >= 100) {
  1991. DBGLOG(QM, LOUD, "QM: QueLen [%u %u %u %u %u %u]\n",
  1992. QM_GET_TX_QUEUE_LEN(prAdapter, 0),
  1993. QM_GET_TX_QUEUE_LEN(prAdapter, 1),
  1994. QM_GET_TX_QUEUE_LEN(prAdapter, 2),
  1995. QM_GET_TX_QUEUE_LEN(prAdapter, 3),
  1996. QM_GET_TX_QUEUE_LEN(prAdapter, 4), QM_GET_TX_QUEUE_LEN(prAdapter, 5)
  1997. ));
  1998. break;
  1999. }
  2000. }
  2001. #endif
  2002. }
  2003. /*----------------------------------------------------------------------------*/
  2004. /*!
  2005. * \brief Assign TX resource for each TC according to TX queue length and current assignment
  2006. *
  2007. * \param (none)
  2008. *
  2009. * \return (none)
  2010. */
  2011. /*----------------------------------------------------------------------------*/
  2012. VOID qmReassignTcResource(IN P_ADAPTER_T prAdapter)
  2013. {
  2014. INT_32 i4TotalResourceDemand = 0;
  2015. UINT_32 u4ResidualResource = 0;
  2016. UINT_32 i;
  2017. INT_32 ai4PerTcResourceDemand[TC_NUM];
  2018. UINT_32 u4ShareCount = 0;
  2019. UINT_32 u4Share = 0;
  2020. P_QUE_MGT_T prQM = &prAdapter->rQM;
  2021. /* Note: After the new assignment is obtained, set prQM->fgTcResourcePostAnnealing to TRUE to
  2022. * start the TC-quota adjusting procedure, which will be invoked upon every TX Done
  2023. */
  2024. /* tx done -> nicProcessTxInterrupt() -> nicTxAdjustTcq()
  2025. * -> qmAdjustTcQuotas() -> check fgTcResourcePostAnnealing */
  2026. /* 4 <1> Determine the demands */
  2027. /* Determine the amount of extra resource to fulfill all of the demands */
  2028. for (i = 0; i < TC_NUM; i++) {
  2029. /* Skip TC4, which is not adjustable */
  2030. if (i == TC4_INDEX)
  2031. continue;
  2032. /*
  2033. Define: extra_demand = average que_length (includes all station records) +
  2034. min_reserved_quota -
  2035. current available TC resources
  2036. extra_demand means we need extra TC resources to transmit; other TCs can
  2037. borrow their resources to us?
  2038. */
  2039. ai4PerTcResourceDemand[i] =
  2040. ((UINT_32) (QM_GET_TX_QUEUE_LEN(prAdapter, i)) +
  2041. prQM->au4MinReservedTcResource[i] - prQM->au4CurrentTcResource[i]);
  2042. /* If there are queued packets, allocate extra resource for the TC (for TCP consideration) */
  2043. if (QM_GET_TX_QUEUE_LEN(prAdapter, i))
  2044. ai4PerTcResourceDemand[i] += QM_EXTRA_RESERVED_RESOURCE_WHEN_BUSY; /* 0 */
  2045. /*
  2046. accumulate all needed extra TC resources
  2047. maybe someone need + resource, maybe someone need - resource
  2048. */
  2049. i4TotalResourceDemand += ai4PerTcResourceDemand[i];
  2050. }
  2051. /* 4 <2> Case 1: Demand <= Total Resource */
  2052. if (i4TotalResourceDemand <= 0) {
  2053. /* 4 <2.1> Satisfy every TC */
  2054. /* total TC resources are enough, no extra TC resources is needed */
  2055. /* adjust used TC resources to average TC resources + min reserve TC resources */
  2056. for (i = 0; i < TC_NUM; i++) {
  2057. /* Skip TC4 (not adjustable) */
  2058. if (i == TC4_INDEX)
  2059. continue;
  2060. /*
  2061. the number of resources that one TC releases can be used for
  2062. other TCs
  2063. EX: TC0 au4CurrentTcResource[0] = 10 ai4PerTcResourceDemand[0] = -5
  2064. TC1 au4CurrentTcResource[1] = 5 ai4PerTcResourceDemand[0] = +5
  2065. => TC0 au4CurrentTcResource[0] = 10 + (-5) = 5
  2066. TC1 au4CurrentTcResource[1] = 5 + (+5) = 10
  2067. */
  2068. prQM->au4CurrentTcResource[i] += ai4PerTcResourceDemand[i];
  2069. }
  2070. /* 4 <2.2> Share the residual resource evenly */
  2071. u4ShareCount = (TC_NUM - 1); /* 5, excluding TC4 */
  2072. /*
  2073. EX: i4TotalResourceDemand = -10
  2074. means we have 10 available resources can be used.
  2075. */
  2076. u4ResidualResource = (UINT_32) (-i4TotalResourceDemand);
  2077. u4Share = (u4ResidualResource / u4ShareCount);
  2078. /* share available TC resources to all TCs averagely */
  2079. for (i = 0; i < TC_NUM; i++) {
  2080. /* Skip TC4 (not adjustable) */
  2081. if (i == TC4_INDEX)
  2082. continue;
  2083. /* allocate residual average resources to the TC */
  2084. prQM->au4CurrentTcResource[i] += u4Share;
  2085. /* Every TC is fully satisfied so no need extra resources */
  2086. ai4PerTcResourceDemand[i] = 0;
  2087. /* decrease the allocated resources */
  2088. u4ResidualResource -= u4Share;
  2089. }
  2090. /* if still have available resources, we decide to give them to VO (TC3) queue */
  2091. /* 4 <2.3> Allocate the left resource to TC3 (VO) */
  2092. prQM->au4CurrentTcResource[TC3_INDEX] += (u4ResidualResource);
  2093. }
  2094. /* 4 <3> Case 2: Demand > Total Resource --> Guarantee a minimum amount of resource for each TC */
  2095. else {
  2096. /*
  2097. u4ResidualResource means we at least need to keep
  2098. QM_INITIAL_RESIDUAL_TC_RESOURCE available TC resources
  2099. in 6628, u4ResidualResource = 26, max 28
  2100. */
  2101. u4ResidualResource = QM_INITIAL_RESIDUAL_TC_RESOURCE;
  2102. /* 4 <3.1> Allocated resource amount = minimum of (guaranteed, total demand) */
  2103. for (i = 0; i < TC_NUM; i++) {
  2104. if (i == TC4_INDEX)
  2105. continue; /* Skip TC4 (not adjustable) */
  2106. /* The demand can be fulfilled with the guaranteed resource amount 4 4 6 6 2 4 */
  2107. /*
  2108. ai4PerTcResourceDemand[i] =
  2109. ((UINT_32)(QM_GET_TX_QUEUE_LEN(prAdapter, i)) +
  2110. prQM->au4MinReservedTcResource[i] -
  2111. prQM->au4CurrentTcResource[i]);
  2112. so au4CurrentTcResource + ai4PerTcResourceDemand =
  2113. ((UINT_32)(QM_GET_TX_QUEUE_LEN(prAdapter, i)) +
  2114. prQM->au4MinReservedTcResource[i] =
  2115. current average queue len + min TC resources
  2116. */
  2117. if (prQM->au4CurrentTcResource[i] + ai4PerTcResourceDemand[i] <
  2118. prQM->au4GuaranteedTcResource[i]) {
  2119. /* avg queue len + min reserve still smaller than guarantee so enough */
  2120. prQM->au4CurrentTcResource[i] += ai4PerTcResourceDemand[i];
  2121. /* accumulate available TC resources from the TC */
  2122. u4ResidualResource +=
  2123. (prQM->au4GuaranteedTcResource[i] - prQM->au4CurrentTcResource[i]);
  2124. ai4PerTcResourceDemand[i] = 0;
  2125. }
  2126. /* The demand can not be fulfilled with the guaranteed resource amount */
  2127. else {
  2128. /* means even we use all guarantee resources for the TC is still not enough */
  2129. /*
  2130. guarantee number is always for the TC so extra resource number cannot
  2131. include the guarantee number.
  2132. EX: au4GuaranteedTcResource = 10, au4CurrentTcResource = 5
  2133. ai4PerTcResourceDemand = 6
  2134. ai4PerTcResourceDemand -= (10 - 5) ==> 1
  2135. only need extra 1 TC resouce is enough.
  2136. */
  2137. ai4PerTcResourceDemand[i] -=
  2138. (prQM->au4GuaranteedTcResource[i] - prQM->au4CurrentTcResource[i]);
  2139. /* update current avg TC resource to guarantee number */
  2140. prQM->au4CurrentTcResource[i] = prQM->au4GuaranteedTcResource[i];
  2141. /* count how many TC queues need to get extra resources */
  2142. u4ShareCount++;
  2143. }
  2144. }
  2145. /* 4 <3.2> Allocate the residual resource */
  2146. do {
  2147. /* If there is no resource left, exit directly */
  2148. if (u4ResidualResource == 0)
  2149. break;
  2150. /* This shall not happen */
  2151. if (u4ShareCount == 0) {
  2152. prQM->au4CurrentTcResource[TC1_INDEX] += u4ResidualResource;
  2153. DBGLOG(QM, ERROR, "QM: (Error) u4ShareCount = 0\n");
  2154. break;
  2155. }
  2156. /* Share the residual resource evenly */
  2157. u4Share = (u4ResidualResource / u4ShareCount);
  2158. if (u4Share) {
  2159. for (i = 0; i < TC_NUM; i++) {
  2160. /* Skip TC4 (not adjustable) */
  2161. if (i == TC4_INDEX)
  2162. continue;
  2163. if (ai4PerTcResourceDemand[i] == 0)
  2164. continue;
  2165. if (ai4PerTcResourceDemand[i] - u4Share) {
  2166. /* still not enough but we just can give it u4Share resources */
  2167. prQM->au4CurrentTcResource[i] += u4Share;
  2168. u4ResidualResource -= u4Share;
  2169. ai4PerTcResourceDemand[i] -= u4Share;
  2170. } else {
  2171. /* enough */
  2172. prQM->au4CurrentTcResource[i] += ai4PerTcResourceDemand[i];
  2173. u4ResidualResource -= ai4PerTcResourceDemand[i];
  2174. ai4PerTcResourceDemand[i] = 0;
  2175. }
  2176. }
  2177. }
  2178. if (u4ResidualResource == 0)
  2179. break;
  2180. /* By priority, allocate the left resource that is not divisible by u4Share */
  2181. if (ai4PerTcResourceDemand[TC3_INDEX]) { /* VO */
  2182. prQM->au4CurrentTcResource[TC3_INDEX]++;
  2183. if (--u4ResidualResource == 0)
  2184. break;
  2185. }
  2186. if (ai4PerTcResourceDemand[TC2_INDEX]) { /* VI */
  2187. prQM->au4CurrentTcResource[TC2_INDEX]++;
  2188. if (--u4ResidualResource == 0)
  2189. break;
  2190. }
  2191. if (ai4PerTcResourceDemand[TC5_INDEX]) { /* BMCAST */
  2192. prQM->au4CurrentTcResource[TC5_INDEX]++;
  2193. if (--u4ResidualResource == 0)
  2194. break;
  2195. }
  2196. if (ai4PerTcResourceDemand[TC1_INDEX]) { /* BE */
  2197. prQM->au4CurrentTcResource[TC1_INDEX]++;
  2198. if (--u4ResidualResource == 0)
  2199. break;
  2200. }
  2201. if (ai4PerTcResourceDemand[TC0_INDEX]) { /* BK */
  2202. prQM->au4CurrentTcResource[TC0_INDEX]++;
  2203. if (--u4ResidualResource == 0)
  2204. break;
  2205. }
  2206. /* Allocate the left resource */
  2207. prQM->au4CurrentTcResource[TC3_INDEX] += u4ResidualResource;
  2208. } while (FALSE);
  2209. }
  2210. /* mark the flag that we can start to do TC resource adjustment after TX done handle */
  2211. prQM->fgTcResourcePostAnnealing = TRUE;
  2212. #if QM_PRINT_TC_RESOURCE_CTRL
  2213. /* Debug print */
  2214. DBGLOG(QM, LOUD, "QM: TC Rsc %u %u %u %u %u %u\n",
  2215. prQM->au4CurrentTcResource[0],
  2216. prQM->au4CurrentTcResource[1],
  2217. prQM->au4CurrentTcResource[2],
  2218. prQM->au4CurrentTcResource[3], prQM->au4CurrentTcResource[4], prQM->au4CurrentTcResource[5]
  2219. ));
  2220. #endif
  2221. }
  2222. #endif
  2223. /*----------------------------------------------------------------------------*/
  2224. /* RX-Related Queue Management */
  2225. /*----------------------------------------------------------------------------*/
  2226. /*----------------------------------------------------------------------------*/
  2227. /*!
  2228. * \brief Init Queue Management for RX
  2229. *
  2230. * \param[in] (none)
  2231. *
  2232. * \return (none)
  2233. */
  2234. /*----------------------------------------------------------------------------*/
  2235. VOID qmInitRxQueues(IN P_ADAPTER_T prAdapter)
  2236. {
  2237. /* DbgPrint("QM: Enter qmInitRxQueues()\n"); */
  2238. /* TODO */
  2239. }
  2240. /*----------------------------------------------------------------------------*/
  2241. /*!
  2242. * \brief Handle RX packets (buffer reordering)
  2243. *
  2244. * \param[in] prSwRfbListHead The list of RX packets
  2245. *
  2246. * \return The list of packets which are not buffered for reordering
  2247. */
  2248. /*----------------------------------------------------------------------------*/
  2249. P_SW_RFB_T qmHandleRxPackets(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfbListHead)
  2250. {
  2251. #if CFG_RX_REORDERING_ENABLED
  2252. /* UINT_32 i; */
  2253. P_SW_RFB_T prCurrSwRfb;
  2254. P_SW_RFB_T prNextSwRfb;
  2255. P_HIF_RX_HEADER_T prHifRxHdr;
  2256. QUE_T rReturnedQue;
  2257. PUINT_8 pucEthDestAddr;
  2258. BOOLEAN fgIsBMC;
  2259. /* DbgPrint("QM: Enter qmHandleRxPackets()\n"); */
  2260. DEBUGFUNC("qmHandleRxPackets");
  2261. ASSERT(prSwRfbListHead);
  2262. QUEUE_INITIALIZE(&rReturnedQue);
  2263. prNextSwRfb = prSwRfbListHead;
  2264. do {
  2265. prCurrSwRfb = prNextSwRfb;
  2266. prNextSwRfb = QM_RX_GET_NEXT_SW_RFB(prCurrSwRfb);
  2267. prHifRxHdr = prCurrSwRfb->prHifRxHdr; /* TODO: (Tehuang) Use macro to obtain the pointer */
  2268. /* TODO: (Tehuang) Check if relaying */
  2269. prCurrSwRfb->eDst = RX_PKT_DESTINATION_HOST;
  2270. /* Decide the Destination */
  2271. #if CFG_RX_PKTS_DUMP
  2272. if (prAdapter->rRxCtrl.u4RxPktsDumpTypeMask & BIT(HIF_RX_PKT_TYPE_DATA)) {
  2273. DBGLOG(SW4, INFO, "QM RX DATA: net %u sta idx %u wlan idx %u ssn %u tid %u ptype %u 11 %u\n",
  2274. (UINT_32) HIF_RX_HDR_GET_NETWORK_IDX(prHifRxHdr),
  2275. prHifRxHdr->ucStaRecIdx, prCurrSwRfb->ucWlanIdx,
  2276. (UINT_32) HIF_RX_HDR_GET_SN(prHifRxHdr), /* The new SN of the frame */
  2277. (UINT_32) HIF_RX_HDR_GET_TID(prHifRxHdr),
  2278. prCurrSwRfb->ucPacketType,
  2279. (UINT_32) HIF_RX_HDR_GET_80211_FLAG(prHifRxHdr));
  2280. DBGLOG_MEM8(SW4, TRACE, (PUINT_8) prCurrSwRfb->pvHeader, prCurrSwRfb->u2PacketLen);
  2281. }
  2282. #endif
  2283. fgIsBMC = FALSE;
  2284. if (!HIF_RX_HDR_GET_80211_FLAG(prHifRxHdr)) {
  2285. UINT_8 ucNetTypeIdx;
  2286. P_BSS_INFO_T prBssInfo;
  2287. pucEthDestAddr = prCurrSwRfb->pvHeader;
  2288. ucNetTypeIdx = HIF_RX_HDR_GET_NETWORK_IDX(prHifRxHdr);
  2289. prBssInfo = &(prAdapter->rWifiVar.arBssInfo[ucNetTypeIdx]);
  2290. /* DBGLOG_MEM8(QM, TRACE,prCurrSwRfb->pvHeader, 16); */
  2291. /* */
  2292. if (IS_BMCAST_MAC_ADDR(pucEthDestAddr) && (OP_MODE_ACCESS_POINT != prBssInfo->eCurrentOPMode))
  2293. fgIsBMC = TRUE;
  2294. if (prAdapter->rRxCtrl.rFreeSwRfbList.u4NumElem >
  2295. (CFG_RX_MAX_PKT_NUM - CFG_NUM_OF_QM_RX_PKT_NUM)) {
  2296. if (!IS_BSS_ACTIVE(prBssInfo)) {
  2297. DBGLOG(QM, WARN, "Mark NULL the Packet for inactive Bss %u\n", ucNetTypeIdx);
  2298. prCurrSwRfb->eDst = RX_PKT_DESTINATION_NULL;
  2299. QUEUE_INSERT_TAIL(&rReturnedQue, (P_QUE_ENTRY_T) prCurrSwRfb);
  2300. continue;
  2301. }
  2302. if (OP_MODE_ACCESS_POINT == prBssInfo->eCurrentOPMode) {
  2303. if (IS_BMCAST_MAC_ADDR(pucEthDestAddr))
  2304. prCurrSwRfb->eDst = RX_PKT_DESTINATION_HOST_WITH_FORWARD;
  2305. else if (UNEQUAL_MAC_ADDR(prBssInfo->aucOwnMacAddr, pucEthDestAddr) &&
  2306. bssGetClientByAddress(prBssInfo, pucEthDestAddr))
  2307. prCurrSwRfb->eDst = RX_PKT_DESTINATION_FORWARD;
  2308. /* TODO : need to check the dst mac is valid */
  2309. /* If src mac is invalid, the packet will be freed in fw */
  2310. } /* OP_MODE_ACCESS_POINT */
  2311. #if CFG_SUPPORT_HOTSPOT_2_0
  2312. else if (hs20IsFrameFilterEnabled(prAdapter, prBssInfo) &&
  2313. hs20IsUnsecuredFrame(prAdapter, prBssInfo, prCurrSwRfb)) {
  2314. DBGLOG(QM, WARN,
  2315. "Mark NULL the Packet for Dropped Packet %u\n", ucNetTypeIdx);
  2316. prCurrSwRfb->eDst = RX_PKT_DESTINATION_NULL;
  2317. QUEUE_INSERT_TAIL(&rReturnedQue, (P_QUE_ENTRY_T) prCurrSwRfb);
  2318. continue;
  2319. }
  2320. #endif
  2321. } else {
  2322. /* Dont not occupy other SW RFB */
  2323. DBGLOG(QM, WARN, "Mark NULL the Packet for less Free Sw Rfb\n");
  2324. prCurrSwRfb->eDst = RX_PKT_DESTINATION_NULL;
  2325. QUEUE_INSERT_TAIL(&rReturnedQue, (P_QUE_ENTRY_T) prCurrSwRfb);
  2326. continue;
  2327. }
  2328. }
  2329. #if CFG_SUPPORT_WAPI
  2330. if (prCurrSwRfb->u2PacketLen > ETHER_HEADER_LEN) {
  2331. PUINT_8 pc = (PUINT_8) prCurrSwRfb->pvHeader;
  2332. UINT_16 u2Etype = 0;
  2333. u2Etype = (pc[ETH_TYPE_LEN_OFFSET] << 8) | (pc[ETH_TYPE_LEN_OFFSET + 1]);
  2334. /* for wapi integrity test. WPI_1x packet should be always in non-encrypted mode.
  2335. if we received any WPI(0x88b4) packet that is encrypted, drop here. */
  2336. if (u2Etype == ETH_WPI_1X && HIF_RX_HDR_GET_SEC_MODE(prHifRxHdr) != 0) {
  2337. DBGLOG(QM, INFO, "drop wpi packet with sec mode\n");
  2338. prCurrSwRfb->eDst = RX_PKT_DESTINATION_NULL;
  2339. QUEUE_INSERT_TAIL(&rReturnedQue, (P_QUE_ENTRY_T) prCurrSwRfb);
  2340. continue;
  2341. }
  2342. }
  2343. #endif
  2344. /* BAR frame */
  2345. if (HIF_RX_HDR_GET_BAR_FLAG(prHifRxHdr)) {
  2346. prCurrSwRfb->eDst = RX_PKT_DESTINATION_NULL;
  2347. qmProcessBarFrame(prAdapter, prCurrSwRfb, &rReturnedQue);
  2348. }
  2349. /* Reordering is not required for this packet, return it without buffering */
  2350. else if (!HIF_RX_HDR_GET_REORDER_FLAG(prHifRxHdr) || fgIsBMC) {
  2351. #if 0
  2352. if (!HIF_RX_HDR_GET_80211_FLAG(prHifRxHdr)) {
  2353. UINT_8 ucNetTypeIdx;
  2354. P_BSS_INFO_T prBssInfo;
  2355. pucEthDestAddr = prCurrSwRfb->pvHeader;
  2356. ucNetTypeIdx = HIF_RX_HDR_GET_NETWORK_IDX(prHifRxHdr);
  2357. prBssInfo = &(prAdapter->rWifiVar.arBssInfo[ucNetTypeIdx]);
  2358. if (IS_BMCAST_MAC_ADDR(pucEthDestAddr)
  2359. && (OP_MODE_ACCESS_POINT == prBssInfo->eCurrentOPMode)) {
  2360. prCurrSwRfb->eDst = RX_PKT_DESTINATION_HOST_WITH_FORWARD;
  2361. }
  2362. }
  2363. #endif
  2364. QUEUE_INSERT_TAIL(&rReturnedQue, (P_QUE_ENTRY_T) prCurrSwRfb);
  2365. }
  2366. /* Reordering is required for this packet */
  2367. else {
  2368. /* If this packet should dropped or indicated to the host immediately,
  2369. * it should be enqueued into the rReturnedQue with specific flags. If
  2370. * this packet should be buffered for reordering, it should be enqueued
  2371. * into the reordering queue in the STA_REC rather than into the
  2372. * rReturnedQue.
  2373. */
  2374. qmProcessPktWithReordering(prAdapter, prCurrSwRfb, &rReturnedQue);
  2375. }
  2376. } while (prNextSwRfb);
  2377. /* RX_PKT_DESTINATION_HOST_WITH_FORWARD or RX_PKT_DESTINATION_FORWARD */
  2378. /* The returned list of SW_RFBs must end with a NULL pointer */
  2379. if (QUEUE_IS_NOT_EMPTY(&rReturnedQue))
  2380. QM_TX_SET_NEXT_MSDU_INFO((P_SW_RFB_T) QUEUE_GET_TAIL(&rReturnedQue), NULL);
  2381. return (P_SW_RFB_T) QUEUE_GET_HEAD(&rReturnedQue);
  2382. #else
  2383. /* DbgPrint("QM: Enter qmHandleRxPackets()\n"); */
  2384. return prSwRfbListHead;
  2385. #endif
  2386. }
  2387. /*----------------------------------------------------------------------------*/
  2388. /*!
  2389. * \brief Reorder the received packet
  2390. *
  2391. * \param[in] prSwRfb The RX packet to process
  2392. * \param[out] prReturnedQue The queue for indicating packets
  2393. *
  2394. * \return (none)
  2395. */
  2396. /*----------------------------------------------------------------------------*/
  2397. VOID qmProcessPktWithReordering(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb, OUT P_QUE_T prReturnedQue)
  2398. {
  2399. P_STA_RECORD_T prStaRec;
  2400. P_HIF_RX_HEADER_T prHifRxHdr;
  2401. P_RX_BA_ENTRY_T prReorderQueParm;
  2402. UINT_32 u4SeqNo;
  2403. UINT_32 u4WinStart;
  2404. UINT_32 u4WinEnd;
  2405. P_QUE_T prReorderQue;
  2406. /* P_SW_RFB_T prReorderedSwRfb; */
  2407. BOOLEAN fgIsBaTimeout;
  2408. DEBUGFUNC("qmProcessPktWithReordering");
  2409. if ((prSwRfb == NULL) || (prReturnedQue == NULL) || (prSwRfb->prHifRxHdr == NULL)) {
  2410. ASSERT(FALSE);
  2411. return;
  2412. }
  2413. prHifRxHdr = prSwRfb->prHifRxHdr;
  2414. prSwRfb->ucStaRecIdx = prHifRxHdr->ucStaRecIdx;
  2415. prSwRfb->u2SSN = HIF_RX_HDR_GET_SN(prHifRxHdr); /* The new SN of the frame */
  2416. prSwRfb->ucTid = (UINT_8) (HIF_RX_HDR_GET_TID(prHifRxHdr));
  2417. /* prSwRfb->eDst = RX_PKT_DESTINATION_HOST; */
  2418. /* Incorrect STA_REC index */
  2419. if (prSwRfb->ucStaRecIdx >= CFG_NUM_OF_STA_RECORD) {
  2420. prSwRfb->eDst = RX_PKT_DESTINATION_NULL;
  2421. QUEUE_INSERT_TAIL(prReturnedQue, (P_QUE_ENTRY_T) prSwRfb);
  2422. DBGLOG(QM, WARN, "Reordering for a NULL STA_REC, ucStaRecIdx = %d\n", prSwRfb->ucStaRecIdx);
  2423. /* ASSERT(0); */
  2424. return;
  2425. }
  2426. /* Check whether the STA_REC is activated */
  2427. prStaRec = &(prAdapter->arStaRec[prSwRfb->ucStaRecIdx]);
  2428. ASSERT(prStaRec);
  2429. #if 0
  2430. if (!(prStaRec->fgIsValid)) {
  2431. /* TODO: (Tehuang) Handle the Host-FW sync issue. */
  2432. prSwRfb->eDst = RX_PKT_DESTINATION_NULL;
  2433. QUEUE_INSERT_TAIL(prReturnedQue, (P_QUE_ENTRY_T) prSwRfb);
  2434. DBGLOG(QM, WARN, "Reordering for an invalid STA_REC\n");
  2435. /* ASSERT(0); */
  2436. return;
  2437. }
  2438. #endif
  2439. /* Check whether the BA agreement exists */
  2440. prReorderQueParm = ((prStaRec->aprRxReorderParamRefTbl)[prSwRfb->ucTid]);
  2441. if (!prReorderQueParm) {
  2442. /* TODO: (Tehuang) Handle the Host-FW sync issue. */
  2443. prSwRfb->eDst = RX_PKT_DESTINATION_NULL;
  2444. QUEUE_INSERT_TAIL(prReturnedQue, (P_QUE_ENTRY_T) prSwRfb);
  2445. DBGLOG(QM, WARN, "Reordering for a NULL ReorderQueParm\n");
  2446. /* ASSERT(0); */
  2447. return;
  2448. }
  2449. /* Start to reorder packets */
  2450. u4SeqNo = (UINT_32) (prSwRfb->u2SSN);
  2451. prReorderQue = &(prReorderQueParm->rReOrderQue);
  2452. u4WinStart = (UINT_32) (prReorderQueParm->u2WinStart);
  2453. u4WinEnd = (UINT_32) (prReorderQueParm->u2WinEnd);
  2454. /* Debug */
  2455. /* DbgPrint("QM:(R)[%d](%ld){%ld,%ld}\n", prSwRfb->ucTid, u4SeqNo, u4WinStart, u4WinEnd); */
  2456. /* Case 1: Fall within */
  2457. if /* 0 - start - sn - end - 4095 */
  2458. (((u4WinStart <= u4SeqNo) && (u4SeqNo <= u4WinEnd))
  2459. /* 0 - end - start - sn - 4095 */
  2460. || ((u4WinEnd < u4WinStart) && (u4WinStart <= u4SeqNo))
  2461. /* 0 - sn - end - start - 4095 */
  2462. || ((u4SeqNo <= u4WinEnd) && (u4WinEnd < u4WinStart))) {
  2463. qmInsertFallWithinReorderPkt(prSwRfb, prReorderQueParm, prReturnedQue);
  2464. #if QM_RX_WIN_SSN_AUTO_ADVANCING
  2465. if (prReorderQueParm->fgIsWaitingForPktWithSsn) {
  2466. /* Let the first received packet pass the reorder check */
  2467. DBGLOG(QM, LOUD, "QM:(A)[%d](%u){%u,%u}\n", prSwRfb->ucTid, u4SeqNo, u4WinStart, u4WinEnd);
  2468. prReorderQueParm->u2WinStart = (UINT_16) u4SeqNo;
  2469. prReorderQueParm->u2WinEnd =
  2470. ((prReorderQueParm->u2WinStart) + (prReorderQueParm->u2WinSize) - 1) % MAX_SEQ_NO_COUNT;
  2471. prReorderQueParm->fgIsWaitingForPktWithSsn = FALSE;
  2472. }
  2473. #endif
  2474. if (qmPopOutDueToFallWithin(prReorderQueParm, prReturnedQue, &fgIsBaTimeout) == FALSE)
  2475. STATS_RX_REORDER_HOLE_INC(prStaRec); /* record hole count */
  2476. STATS_RX_REORDER_HOLE_TIMEOUT_INC(prStaRec, fgIsBaTimeout);
  2477. }
  2478. /* Case 2: Fall ahead */
  2479. else if
  2480. /* 0 - start - end - sn - (start+2048) - 4095 */
  2481. (((u4WinStart < u4WinEnd)
  2482. && (u4WinEnd < u4SeqNo)
  2483. && (u4SeqNo < (u4WinStart + HALF_SEQ_NO_COUNT)))
  2484. /* 0 - sn - (start+2048) - start - end - 4095 */
  2485. || ((u4SeqNo < u4WinStart)
  2486. && (u4WinStart < u4WinEnd)
  2487. && ((u4SeqNo + MAX_SEQ_NO_COUNT) < (u4WinStart + HALF_SEQ_NO_COUNT)))
  2488. /* 0 - end - sn - (start+2048) - start - 4095 */
  2489. || ((u4WinEnd < u4SeqNo)
  2490. && (u4SeqNo < u4WinStart)
  2491. && ((u4SeqNo + MAX_SEQ_NO_COUNT) < (u4WinStart + HALF_SEQ_NO_COUNT)))) {
  2492. #if QM_RX_WIN_SSN_AUTO_ADVANCING
  2493. if (prReorderQueParm->fgIsWaitingForPktWithSsn)
  2494. prReorderQueParm->fgIsWaitingForPktWithSsn = FALSE;
  2495. #endif
  2496. qmInsertFallAheadReorderPkt(prSwRfb, prReorderQueParm, prReturnedQue);
  2497. /* Advance the window after inserting a new tail */
  2498. prReorderQueParm->u2WinEnd = (UINT_16) u4SeqNo;
  2499. prReorderQueParm->u2WinStart =
  2500. (((prReorderQueParm->u2WinEnd) - (prReorderQueParm->u2WinSize) + MAX_SEQ_NO_COUNT + 1)
  2501. % MAX_SEQ_NO_COUNT);
  2502. qmPopOutDueToFallAhead(prReorderQueParm, prReturnedQue);
  2503. STATS_RX_REORDER_FALL_AHEAD_INC(prStaRec);
  2504. }
  2505. /* Case 3: Fall behind */
  2506. else {
  2507. #if QM_RX_WIN_SSN_AUTO_ADVANCING
  2508. #if QM_RX_INIT_FALL_BEHIND_PASS
  2509. if (prReorderQueParm->fgIsWaitingForPktWithSsn) {
  2510. /* ?? prSwRfb->eDst = RX_PKT_DESTINATION_HOST; */
  2511. QUEUE_INSERT_TAIL(prReturnedQue, (P_QUE_ENTRY_T) prSwRfb);
  2512. /* DbgPrint("QM:(P)[%d](%ld){%ld,%ld}\n", prSwRfb->ucTid, u4SeqNo, u4WinStart, u4WinEnd); */
  2513. return;
  2514. }
  2515. #endif
  2516. #endif
  2517. STATS_RX_REORDER_FALL_BEHIND_INC(prStaRec);
  2518. /* An erroneous packet */
  2519. prSwRfb->eDst = RX_PKT_DESTINATION_NULL;
  2520. QUEUE_INSERT_TAIL(prReturnedQue, (P_QUE_ENTRY_T) prSwRfb);
  2521. /* DbgPrint("QM:(D)[%d](%ld){%ld,%ld}\n", prSwRfb->ucTid, u4SeqNo, u4WinStart, u4WinEnd); */
  2522. return;
  2523. }
  2524. return;
  2525. }
  2526. VOID qmProcessBarFrame(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb, OUT P_QUE_T prReturnedQue)
  2527. {
  2528. P_STA_RECORD_T prStaRec;
  2529. P_HIF_RX_HEADER_T prHifRxHdr;
  2530. P_RX_BA_ENTRY_T prReorderQueParm;
  2531. UINT_32 u4SSN;
  2532. UINT_32 u4WinStart;
  2533. UINT_32 u4WinEnd;
  2534. P_QUE_T prReorderQue;
  2535. /* P_SW_RFB_T prReorderedSwRfb; */
  2536. if ((prSwRfb == NULL) || (prReturnedQue == NULL) || (prSwRfb->prHifRxHdr == NULL)) {
  2537. ASSERT(FALSE);
  2538. return;
  2539. }
  2540. prHifRxHdr = prSwRfb->prHifRxHdr;
  2541. prSwRfb->ucStaRecIdx = prHifRxHdr->ucStaRecIdx;
  2542. prSwRfb->u2SSN = HIF_RX_HDR_GET_SN(prHifRxHdr); /* The new SSN */
  2543. prSwRfb->ucTid = (UINT_8) (HIF_RX_HDR_GET_TID(prHifRxHdr));
  2544. prSwRfb->eDst = RX_PKT_DESTINATION_NULL;
  2545. QUEUE_INSERT_TAIL(prReturnedQue, (P_QUE_ENTRY_T) prSwRfb);
  2546. /* Incorrect STA_REC index */
  2547. if (prSwRfb->ucStaRecIdx >= CFG_NUM_OF_STA_RECORD) {
  2548. DBGLOG(QM, WARN, "QM: (Warning) BAR for a NULL STA_REC, ucStaRecIdx = %d\n", prSwRfb->ucStaRecIdx);
  2549. /* ASSERT(0); */
  2550. return;
  2551. }
  2552. /* Check whether the STA_REC is activated */
  2553. prStaRec = &(prAdapter->arStaRec[prSwRfb->ucStaRecIdx]);
  2554. ASSERT(prStaRec);
  2555. #if 0
  2556. if (!(prStaRec->fgIsValid)) {
  2557. /* TODO: (Tehuang) Handle the Host-FW sync issue. */
  2558. DbgPrint("QM: (Warning) BAR for an invalid STA_REC\n");
  2559. /* ASSERT(0); */
  2560. return;
  2561. }
  2562. #endif
  2563. /* Check whether the BA agreement exists */
  2564. prReorderQueParm = ((prStaRec->aprRxReorderParamRefTbl)[prSwRfb->ucTid]);
  2565. if (!prReorderQueParm) {
  2566. /* TODO: (Tehuang) Handle the Host-FW sync issue. */
  2567. DBGLOG(QM, WARN, "QM: (Warning) BAR for a NULL ReorderQueParm\n");
  2568. /* ASSERT(0); */
  2569. return;
  2570. }
  2571. u4SSN = (UINT_32) (prSwRfb->u2SSN);
  2572. prReorderQue = &(prReorderQueParm->rReOrderQue);
  2573. u4WinStart = (UINT_32) (prReorderQueParm->u2WinStart);
  2574. u4WinEnd = (UINT_32) (prReorderQueParm->u2WinEnd);
  2575. if (qmCompareSnIsLessThan(u4WinStart, u4SSN)) {
  2576. prReorderQueParm->u2WinStart = (UINT_16) u4SSN;
  2577. prReorderQueParm->u2WinEnd =
  2578. ((prReorderQueParm->u2WinStart) + (prReorderQueParm->u2WinSize) - 1) % MAX_SEQ_NO_COUNT;
  2579. DBGLOG(QM, TRACE,
  2580. "QM:(BAR)[%d](%u){%d,%d}\n", prSwRfb->ucTid, u4SSN, prReorderQueParm->u2WinStart,
  2581. prReorderQueParm->u2WinEnd);
  2582. qmPopOutDueToFallAhead(prReorderQueParm, prReturnedQue);
  2583. } else {
  2584. DBGLOG(QM, TRACE, "QM:(BAR)(%d)(%u){%u,%u}\n", prSwRfb->ucTid, u4SSN, u4WinStart, u4WinEnd);
  2585. }
  2586. }
  2587. VOID qmInsertFallWithinReorderPkt(IN P_SW_RFB_T prSwRfb, IN P_RX_BA_ENTRY_T prReorderQueParm, OUT P_QUE_T prReturnedQue)
  2588. {
  2589. P_SW_RFB_T prExaminedQueuedSwRfb;
  2590. P_QUE_T prReorderQue;
  2591. ASSERT(prSwRfb);
  2592. ASSERT(prReorderQueParm);
  2593. ASSERT(prReturnedQue);
  2594. prReorderQue = &(prReorderQueParm->rReOrderQue);
  2595. prExaminedQueuedSwRfb = (P_SW_RFB_T) QUEUE_GET_HEAD(prReorderQue);
  2596. /* There are no packets queued in the Reorder Queue */
  2597. if (prExaminedQueuedSwRfb == NULL) {
  2598. ((P_QUE_ENTRY_T) prSwRfb)->prPrev = NULL;
  2599. ((P_QUE_ENTRY_T) prSwRfb)->prNext = NULL;
  2600. prReorderQue->prHead = (P_QUE_ENTRY_T) prSwRfb;
  2601. prReorderQue->prTail = (P_QUE_ENTRY_T) prSwRfb;
  2602. prReorderQue->u4NumElem++;
  2603. }
  2604. /* Determine the insert position */
  2605. else {
  2606. do {
  2607. /* Case 1: Terminate. A duplicate packet */
  2608. if (((prExaminedQueuedSwRfb->u2SSN) == (prSwRfb->u2SSN))) {
  2609. prSwRfb->eDst = RX_PKT_DESTINATION_NULL;
  2610. QUEUE_INSERT_TAIL(prReturnedQue, (P_QUE_ENTRY_T) prSwRfb);
  2611. return;
  2612. }
  2613. /* Case 2: Terminate. The insert point is found */
  2614. else if (qmCompareSnIsLessThan((prSwRfb->u2SSN), (prExaminedQueuedSwRfb->u2SSN)))
  2615. break;
  2616. /* Case 3: Insert point not found. Check the next SW_RFB in the Reorder Queue */
  2617. else
  2618. prExaminedQueuedSwRfb = (P_SW_RFB_T) (((P_QUE_ENTRY_T) prExaminedQueuedSwRfb)->prNext);
  2619. } while (prExaminedQueuedSwRfb);
  2620. /* Update the Reorder Queue Parameters according to the found insert position */
  2621. if (prExaminedQueuedSwRfb == NULL) {
  2622. /* The received packet shall be placed at the tail */
  2623. ((P_QUE_ENTRY_T) prSwRfb)->prPrev = prReorderQue->prTail;
  2624. ((P_QUE_ENTRY_T) prSwRfb)->prNext = NULL;
  2625. (prReorderQue->prTail)->prNext = (P_QUE_ENTRY_T) (prSwRfb);
  2626. prReorderQue->prTail = (P_QUE_ENTRY_T) (prSwRfb);
  2627. } else {
  2628. ((P_QUE_ENTRY_T) prSwRfb)->prPrev = ((P_QUE_ENTRY_T) prExaminedQueuedSwRfb)->prPrev;
  2629. ((P_QUE_ENTRY_T) prSwRfb)->prNext = (P_QUE_ENTRY_T) prExaminedQueuedSwRfb;
  2630. if (((P_QUE_ENTRY_T) prExaminedQueuedSwRfb) == (prReorderQue->prHead)) {
  2631. /* The received packet will become the head */
  2632. prReorderQue->prHead = (P_QUE_ENTRY_T) prSwRfb;
  2633. } else {
  2634. (((P_QUE_ENTRY_T) prExaminedQueuedSwRfb)->prPrev)->prNext = (P_QUE_ENTRY_T) prSwRfb;
  2635. }
  2636. ((P_QUE_ENTRY_T) prExaminedQueuedSwRfb)->prPrev = (P_QUE_ENTRY_T) prSwRfb;
  2637. }
  2638. prReorderQue->u4NumElem++;
  2639. }
  2640. }
  2641. VOID qmInsertFallAheadReorderPkt(IN P_SW_RFB_T prSwRfb, IN P_RX_BA_ENTRY_T prReorderQueParm, OUT P_QUE_T prReturnedQue)
  2642. {
  2643. P_QUE_T prReorderQue;
  2644. ASSERT(prSwRfb);
  2645. ASSERT(prReorderQueParm);
  2646. ASSERT(prReturnedQue);
  2647. prReorderQue = &(prReorderQueParm->rReOrderQue);
  2648. /* There are no packets queued in the Reorder Queue */
  2649. if (QUEUE_IS_EMPTY(prReorderQue)) {
  2650. ((P_QUE_ENTRY_T) prSwRfb)->prPrev = NULL;
  2651. ((P_QUE_ENTRY_T) prSwRfb)->prNext = NULL;
  2652. prReorderQue->prHead = (P_QUE_ENTRY_T) prSwRfb;
  2653. } else {
  2654. ((P_QUE_ENTRY_T) prSwRfb)->prPrev = prReorderQue->prTail;
  2655. ((P_QUE_ENTRY_T) prSwRfb)->prNext = NULL;
  2656. (prReorderQue->prTail)->prNext = (P_QUE_ENTRY_T) (prSwRfb);
  2657. }
  2658. prReorderQue->prTail = (P_QUE_ENTRY_T) prSwRfb;
  2659. prReorderQue->u4NumElem++;
  2660. }
  2661. BOOLEAN
  2662. qmPopOutDueToFallWithin(IN P_RX_BA_ENTRY_T prReorderQueParm, OUT P_QUE_T prReturnedQue, OUT BOOLEAN *fgIsTimeout)
  2663. {
  2664. P_SW_RFB_T prReorderedSwRfb;
  2665. P_QUE_T prReorderQue;
  2666. BOOLEAN fgDequeuHead, fgMissing;
  2667. OS_SYSTIME rCurrentTime, *prMissTimeout;
  2668. prReorderQue = &(prReorderQueParm->rReOrderQue);
  2669. *fgIsTimeout = FALSE;
  2670. fgMissing = FALSE;
  2671. rCurrentTime = 0;
  2672. prMissTimeout = &(g_arMissTimeout[prReorderQueParm->ucStaRecIdx][prReorderQueParm->ucTid]);
  2673. if ((*prMissTimeout)) {
  2674. fgMissing = TRUE;
  2675. GET_CURRENT_SYSTIME(&rCurrentTime);
  2676. }
  2677. /* Check whether any packet can be indicated to the higher layer */
  2678. while (TRUE) {
  2679. if (QUEUE_IS_EMPTY(prReorderQue))
  2680. break;
  2681. /* Always examine the head packet */
  2682. prReorderedSwRfb = (P_SW_RFB_T) QUEUE_GET_HEAD(prReorderQue);
  2683. fgDequeuHead = FALSE;
  2684. /* SN == WinStart, so the head packet shall be indicated (advance the window) */
  2685. if ((prReorderedSwRfb->u2SSN) == (prReorderQueParm->u2WinStart)) {
  2686. fgDequeuHead = TRUE;
  2687. prReorderQueParm->u2WinStart = (((prReorderedSwRfb->u2SSN) + 1) % MAX_SEQ_NO_COUNT);
  2688. }
  2689. /* SN > WinStart, break to update WinEnd */
  2690. else {
  2691. if ((fgMissing == TRUE) &&
  2692. CHECK_FOR_TIMEOUT(rCurrentTime, (*prMissTimeout),
  2693. MSEC_TO_SYSTIME(QM_RX_BA_ENTRY_MISS_TIMEOUT_MS))) {
  2694. DBGLOG(QM, TRACE,
  2695. "QM:RX BA Timout Next Tid %d SSN %d\n", prReorderQueParm->ucTid,
  2696. prReorderedSwRfb->u2SSN);
  2697. fgDequeuHead = TRUE;
  2698. prReorderQueParm->u2WinStart = (((prReorderedSwRfb->u2SSN) + 1) % MAX_SEQ_NO_COUNT);
  2699. fgMissing = FALSE;
  2700. *fgIsTimeout = TRUE;
  2701. } else
  2702. break;
  2703. }
  2704. /* Dequeue the head packet */
  2705. if (fgDequeuHead) {
  2706. if (((P_QUE_ENTRY_T) prReorderedSwRfb)->prNext == NULL) {
  2707. prReorderQue->prHead = NULL;
  2708. prReorderQue->prTail = NULL;
  2709. } else {
  2710. prReorderQue->prHead = ((P_QUE_ENTRY_T) prReorderedSwRfb)->prNext;
  2711. (((P_QUE_ENTRY_T) prReorderedSwRfb)->prNext)->prPrev = NULL;
  2712. }
  2713. prReorderQue->u4NumElem--;
  2714. /* DbgPrint("QM: [%d] %d (%d)\n",
  2715. prReorderQueParm->ucTid,
  2716. prReorderedSwRfb->u2PacketLen,
  2717. prReorderedSwRfb->u2SSN); */
  2718. QUEUE_INSERT_TAIL(prReturnedQue, (P_QUE_ENTRY_T) prReorderedSwRfb);
  2719. }
  2720. }
  2721. if (QUEUE_IS_EMPTY(prReorderQue))
  2722. *prMissTimeout = 0;
  2723. else {
  2724. if (fgMissing == FALSE)
  2725. GET_CURRENT_SYSTIME(prMissTimeout);
  2726. }
  2727. /* After WinStart has been determined, update the WinEnd */
  2728. prReorderQueParm->u2WinEnd =
  2729. (((prReorderQueParm->u2WinStart) + (prReorderQueParm->u2WinSize) - 1) % MAX_SEQ_NO_COUNT);
  2730. return QUEUE_IS_EMPTY(prReorderQue);
  2731. }
  2732. VOID qmPopOutDueToFallAhead(IN P_RX_BA_ENTRY_T prReorderQueParm, OUT P_QUE_T prReturnedQue)
  2733. {
  2734. P_SW_RFB_T prReorderedSwRfb;
  2735. P_QUE_T prReorderQue;
  2736. BOOLEAN fgDequeuHead;
  2737. prReorderQue = &(prReorderQueParm->rReOrderQue);
  2738. /* Check whether any packet can be indicated to the higher layer */
  2739. while (TRUE) {
  2740. if (QUEUE_IS_EMPTY(prReorderQue))
  2741. break;
  2742. /* Always examine the head packet */
  2743. prReorderedSwRfb = (P_SW_RFB_T) QUEUE_GET_HEAD(prReorderQue);
  2744. fgDequeuHead = FALSE;
  2745. /* SN == WinStart, so the head packet shall be indicated (advance the window) */
  2746. if ((prReorderedSwRfb->u2SSN) == (prReorderQueParm->u2WinStart)) {
  2747. fgDequeuHead = TRUE;
  2748. prReorderQueParm->u2WinStart = (((prReorderedSwRfb->u2SSN) + 1) % MAX_SEQ_NO_COUNT);
  2749. }
  2750. /* SN < WinStart, so the head packet shall be indicated (do not advance the window) */
  2751. else if (qmCompareSnIsLessThan((UINT_32) (prReorderedSwRfb->u2SSN),
  2752. (UINT_32) (prReorderQueParm->u2WinStart)))
  2753. fgDequeuHead = TRUE;
  2754. /* SN > WinStart, break to update WinEnd */
  2755. else
  2756. break;
  2757. /* Dequeue the head packet */
  2758. if (fgDequeuHead) {
  2759. if (((P_QUE_ENTRY_T) prReorderedSwRfb)->prNext == NULL) {
  2760. prReorderQue->prHead = NULL;
  2761. prReorderQue->prTail = NULL;
  2762. } else {
  2763. prReorderQue->prHead = ((P_QUE_ENTRY_T) prReorderedSwRfb)->prNext;
  2764. (((P_QUE_ENTRY_T) prReorderedSwRfb)->prNext)->prPrev = NULL;
  2765. }
  2766. prReorderQue->u4NumElem--;
  2767. /* DbgPrint("QM: [%d] %d (%d)\n", */
  2768. /* prReorderQueParm->ucTid, prReorderedSwRfb->u2PacketLen, prReorderedSwRfb->u2SSN); */
  2769. QUEUE_INSERT_TAIL(prReturnedQue, (P_QUE_ENTRY_T) prReorderedSwRfb);
  2770. }
  2771. }
  2772. /* After WinStart has been determined, update the WinEnd */
  2773. prReorderQueParm->u2WinEnd =
  2774. (((prReorderQueParm->u2WinStart) + (prReorderQueParm->u2WinSize) - 1) % MAX_SEQ_NO_COUNT);
  2775. }
  2776. BOOLEAN qmCompareSnIsLessThan(IN UINT_32 u4SnLess, IN UINT_32 u4SnGreater)
  2777. {
  2778. /* 0 <---> SnLess <--(gap>2048)--> SnGreater : SnLess > SnGreater */
  2779. if ((u4SnLess + HALF_SEQ_NO_COUNT) <= u4SnGreater) /* Shall be <= */
  2780. return FALSE;
  2781. /* 0 <---> SnGreater <--(gap>2048)--> SnLess : SnLess < SnGreater */
  2782. else if ((u4SnGreater + HALF_SEQ_NO_COUNT) < u4SnLess)
  2783. return TRUE;
  2784. /* 0 <---> SnGreater <--(gap<2048)--> SnLess : SnLess > SnGreater */
  2785. /* 0 <---> SnLess <--(gap<2048)--> SnGreater : SnLess < SnGreater */
  2786. else if (u4SnLess < u4SnGreater)
  2787. return TRUE;
  2788. else
  2789. return FALSE;
  2790. }
  2791. /*----------------------------------------------------------------------------*/
  2792. /*!
  2793. * \brief Handle Mailbox RX messages
  2794. *
  2795. * \param[in] prMailboxRxMsg The received Mailbox message from the FW
  2796. *
  2797. * \return (none)
  2798. */
  2799. /*----------------------------------------------------------------------------*/
  2800. VOID qmHandleMailboxRxMessage(IN MAILBOX_MSG_T prMailboxRxMsg)
  2801. {
  2802. /* DbgPrint("QM: Enter qmHandleMailboxRxMessage()\n"); */
  2803. /* TODO */
  2804. }
  2805. /*----------------------------------------------------------------------------*/
  2806. /*!
  2807. * \brief Handle ADD RX BA Event from the FW
  2808. *
  2809. * \param[in] prAdapter Adapter pointer
  2810. * \param[in] prEvent The event packet from the FW
  2811. *
  2812. * \return (none)
  2813. */
  2814. /*----------------------------------------------------------------------------*/
  2815. VOID qmHandleEventRxAddBa(IN P_ADAPTER_T prAdapter, IN P_WIFI_EVENT_T prEvent)
  2816. {
  2817. P_EVENT_RX_ADDBA_T prEventRxAddBa;
  2818. P_STA_RECORD_T prStaRec;
  2819. UINT_32 u4Tid;
  2820. UINT_32 u4WinSize;
  2821. DBGLOG(QM, INFO, "QM:Event +RxBa\n");
  2822. prEventRxAddBa = (P_EVENT_RX_ADDBA_T) prEvent;
  2823. prStaRec = QM_GET_STA_REC_PTR_FROM_INDEX(prAdapter, prEventRxAddBa->ucStaRecIdx);
  2824. if (!prStaRec) {
  2825. /* Invalid STA_REC index, discard the event packet */
  2826. /* ASSERT(0); */
  2827. DBGLOG(QM, WARN, "QM: (Warning) RX ADDBA Event for a NULL STA_REC\n");
  2828. return;
  2829. }
  2830. #if 0
  2831. if (!(prStaRec->fgIsValid)) {
  2832. /* TODO: (Tehuang) Handle the Host-FW synchronization issue */
  2833. DBGLOG(QM, WARN, "QM: (Warning) RX ADDBA Event for an invalid STA_REC\n");
  2834. /* ASSERT(0); */
  2835. /* return; */
  2836. }
  2837. #endif
  2838. u4Tid = (((prEventRxAddBa->u2BAParameterSet) & BA_PARAM_SET_TID_MASK)
  2839. >> BA_PARAM_SET_TID_MASK_OFFSET);
  2840. u4WinSize = (((prEventRxAddBa->u2BAParameterSet) & BA_PARAM_SET_BUFFER_SIZE_MASK)
  2841. >> BA_PARAM_SET_BUFFER_SIZE_MASK_OFFSET);
  2842. if (!qmAddRxBaEntry(prAdapter,
  2843. prStaRec->ucIndex,
  2844. (UINT_8) u4Tid,
  2845. (prEventRxAddBa->u2BAStartSeqCtrl >> OFFSET_BAR_SSC_SN), (UINT_16) u4WinSize)) {
  2846. /* FW shall ensure the availabiilty of the free-to-use BA entry */
  2847. DBGLOG(QM, ERROR, "QM: (Error) qmAddRxBaEntry() failure\n");
  2848. ASSERT(0);
  2849. }
  2850. }
  2851. /*----------------------------------------------------------------------------*/
  2852. /*!
  2853. * \brief Handle DEL RX BA Event from the FW
  2854. *
  2855. * \param[in] prAdapter Adapter pointer
  2856. * \param[in] prEvent The event packet from the FW
  2857. *
  2858. * \return (none)
  2859. */
  2860. /*----------------------------------------------------------------------------*/
  2861. VOID qmHandleEventRxDelBa(IN P_ADAPTER_T prAdapter, IN P_WIFI_EVENT_T prEvent)
  2862. {
  2863. P_EVENT_RX_DELBA_T prEventRxDelBa;
  2864. P_STA_RECORD_T prStaRec;
  2865. /* DbgPrint("QM:Event -RxBa\n"); */
  2866. prEventRxDelBa = (P_EVENT_RX_DELBA_T) prEvent;
  2867. prStaRec = QM_GET_STA_REC_PTR_FROM_INDEX(prAdapter, prEventRxDelBa->ucStaRecIdx);
  2868. if (!prStaRec)
  2869. /* Invalid STA_REC index, discard the event packet */
  2870. /* ASSERT(0); */
  2871. return;
  2872. #if 0
  2873. if (!(prStaRec->fgIsValid))
  2874. /* TODO: (Tehuang) Handle the Host-FW synchronization issue */
  2875. /* ASSERT(0); */
  2876. return;
  2877. #endif
  2878. qmDelRxBaEntry(prAdapter, prStaRec->ucIndex, prEventRxDelBa->ucTid, TRUE);
  2879. }
  2880. P_RX_BA_ENTRY_T qmLookupRxBaEntry(IN P_ADAPTER_T prAdapter, UINT_8 ucStaRecIdx, UINT_8 ucTid)
  2881. {
  2882. int i;
  2883. P_QUE_MGT_T prQM = &prAdapter->rQM;
  2884. /* DbgPrint("QM: Enter qmLookupRxBaEntry()\n"); */
  2885. for (i = 0; i < CFG_NUM_OF_RX_BA_AGREEMENTS; i++) {
  2886. if (prQM->arRxBaTable[i].fgIsValid) {
  2887. if ((prQM->arRxBaTable[i].ucStaRecIdx == ucStaRecIdx) && (prQM->arRxBaTable[i].ucTid == ucTid))
  2888. return &prQM->arRxBaTable[i];
  2889. }
  2890. }
  2891. return NULL;
  2892. }
  2893. BOOLEAN
  2894. qmAddRxBaEntry(IN P_ADAPTER_T prAdapter,
  2895. IN UINT_8 ucStaRecIdx, IN UINT_8 ucTid, IN UINT_16 u2WinStart, IN UINT_16 u2WinSize)
  2896. {
  2897. int i;
  2898. P_RX_BA_ENTRY_T prRxBaEntry = NULL;
  2899. P_STA_RECORD_T prStaRec;
  2900. P_QUE_MGT_T prQM = &prAdapter->rQM;
  2901. ASSERT(ucStaRecIdx < CFG_NUM_OF_STA_RECORD);
  2902. if (ucStaRecIdx >= CFG_NUM_OF_STA_RECORD) {
  2903. /* Invalid STA_REC index, discard the event packet */
  2904. DBGLOG(QM, WARN, "QM: (WARNING) RX ADDBA Event for a invalid ucStaRecIdx = %d\n", ucStaRecIdx);
  2905. return FALSE;
  2906. }
  2907. prStaRec = &prAdapter->arStaRec[ucStaRecIdx];
  2908. ASSERT(prStaRec);
  2909. /* if(!(prStaRec->fgIsValid)){ */
  2910. /* DbgPrint("QM: (WARNING) Invalid STA when adding an RX BA\n"); */
  2911. /* return FALSE; */
  2912. /* } */
  2913. /* 4 <1> Delete before adding */
  2914. /* Remove the BA entry for the same (STA, TID) tuple if it exists */
  2915. if (qmLookupRxBaEntry(prAdapter, ucStaRecIdx, ucTid))
  2916. qmDelRxBaEntry(prAdapter, ucStaRecIdx, ucTid, TRUE); /* prQM->ucRxBaCount-- */
  2917. /* 4 <2> Add a new BA entry */
  2918. /* No available entry to store the BA agreement info. Retrun FALSE. */
  2919. if (prQM->ucRxBaCount >= CFG_NUM_OF_RX_BA_AGREEMENTS) {
  2920. DBGLOG(QM, ERROR, "QM: **failure** (limited resource, ucRxBaCount=%d)\n", prQM->ucRxBaCount);
  2921. return FALSE;
  2922. }
  2923. /* Find the free-to-use BA entry */
  2924. for (i = 0; i < CFG_NUM_OF_RX_BA_AGREEMENTS; i++) {
  2925. if (!prQM->arRxBaTable[i].fgIsValid) {
  2926. prRxBaEntry = &(prQM->arRxBaTable[i]);
  2927. prQM->ucRxBaCount++;
  2928. DBGLOG(QM, LOUD, "QM: ucRxBaCount=%d\n", prQM->ucRxBaCount);
  2929. break;
  2930. }
  2931. }
  2932. /* If a free-to-use entry is found, configure it and associate it with the STA_REC */
  2933. u2WinSize += CFG_RX_BA_INC_SIZE;
  2934. if (prRxBaEntry) {
  2935. prRxBaEntry->ucStaRecIdx = ucStaRecIdx;
  2936. prRxBaEntry->ucTid = ucTid;
  2937. prRxBaEntry->u2WinStart = u2WinStart;
  2938. prRxBaEntry->u2WinSize = u2WinSize;
  2939. prRxBaEntry->u2WinEnd = ((u2WinStart + u2WinSize - 1) % MAX_SEQ_NO_COUNT);
  2940. prRxBaEntry->fgIsValid = TRUE;
  2941. prRxBaEntry->fgIsWaitingForPktWithSsn = TRUE;
  2942. g_arMissTimeout[ucStaRecIdx][ucTid] = 0;
  2943. DBGLOG(QM, INFO, "QM: +RxBA(STA=%d TID=%d WinStart=%d WinEnd=%d WinSize=%d)\n",
  2944. ucStaRecIdx, ucTid,
  2945. prRxBaEntry->u2WinStart, prRxBaEntry->u2WinEnd, prRxBaEntry->u2WinSize);
  2946. /* Update the BA entry reference table for per-packet lookup */
  2947. prStaRec->aprRxReorderParamRefTbl[ucTid] = prRxBaEntry;
  2948. } else {
  2949. /* This shall not happen because FW should keep track of the usage of RX BA entries */
  2950. DBGLOG(QM, ERROR, "QM: **AddBA Error** (ucRxBaCount=%d)\n", prQM->ucRxBaCount);
  2951. return FALSE;
  2952. }
  2953. return TRUE;
  2954. }
  2955. VOID qmDelRxBaEntry(IN P_ADAPTER_T prAdapter, IN UINT_8 ucStaRecIdx, IN UINT_8 ucTid, IN BOOLEAN fgFlushToHost)
  2956. {
  2957. P_RX_BA_ENTRY_T prRxBaEntry;
  2958. P_STA_RECORD_T prStaRec;
  2959. P_SW_RFB_T prFlushedPacketList = NULL;
  2960. P_QUE_MGT_T prQM = &prAdapter->rQM;
  2961. ASSERT(ucStaRecIdx < CFG_NUM_OF_STA_RECORD);
  2962. prStaRec = &prAdapter->arStaRec[ucStaRecIdx];
  2963. ASSERT(prStaRec);
  2964. #if 0
  2965. if (!(prStaRec->fgIsValid)) {
  2966. DbgPrint("QM: (WARNING) Invalid STA when deleting an RX BA\n");
  2967. return;
  2968. }
  2969. #endif
  2970. /* Remove the BA entry for the same (STA, TID) tuple if it exists */
  2971. prRxBaEntry = prStaRec->aprRxReorderParamRefTbl[ucTid];
  2972. if (prRxBaEntry) {
  2973. prFlushedPacketList = qmFlushStaRxQueue(prAdapter, ucStaRecIdx, ucTid);
  2974. if (prFlushedPacketList) {
  2975. if (fgFlushToHost) {
  2976. wlanProcessQueuedSwRfb(prAdapter, prFlushedPacketList);
  2977. } else {
  2978. P_SW_RFB_T prSwRfb;
  2979. P_SW_RFB_T prNextSwRfb;
  2980. prSwRfb = prFlushedPacketList;
  2981. do {
  2982. prNextSwRfb = (P_SW_RFB_T) QUEUE_GET_NEXT_ENTRY((P_QUE_ENTRY_T) prSwRfb);
  2983. nicRxReturnRFB(prAdapter, prSwRfb);
  2984. prSwRfb = prNextSwRfb;
  2985. } while (prSwRfb);
  2986. }
  2987. }
  2988. #if ((QM_TEST_MODE == 0) && (QM_TEST_STA_REC_DEACTIVATION == 0))
  2989. /* Update RX BA entry state. Note that RX queue flush is not done here */
  2990. prRxBaEntry->fgIsValid = FALSE;
  2991. prQM->ucRxBaCount--;
  2992. /* Debug */
  2993. #if 0
  2994. DbgPrint("QM: ucRxBaCount=%d\n", prQM->ucRxBaCount);
  2995. #endif
  2996. /* Update STA RX BA table */
  2997. prStaRec->aprRxReorderParamRefTbl[ucTid] = NULL;
  2998. #endif
  2999. DBGLOG(QM, INFO, "QM: -RxBA(STA=%d,TID=%d)\n", ucStaRecIdx, ucTid);
  3000. }
  3001. /* Debug */
  3002. #if CFG_HIF_RX_STARVATION_WARNING
  3003. {
  3004. P_RX_CTRL_T prRxCtrl;
  3005. prRxCtrl = &prAdapter->rRxCtrl;
  3006. DBGLOG(QM, TRACE,
  3007. "QM: (RX DEBUG) Enqueued: %d / Dequeued: %d\n", prRxCtrl->u4QueuedCnt,
  3008. prRxCtrl->u4DequeuedCnt);
  3009. }
  3010. #endif
  3011. }
  3012. /*----------------------------------------------------------------------------*/
  3013. /*!
  3014. * \brief To process WMM related IEs in ASSOC_RSP
  3015. *
  3016. * \param[in] prAdapter Adapter pointer
  3017. * \param[in] prSwRfb The received frame
  3018. * \param[in] pucIE The pointer to the first IE in the frame
  3019. * \param[in] u2IELength The total length of IEs in the frame
  3020. *
  3021. * \return none
  3022. */
  3023. /*----------------------------------------------------------------------------*/
  3024. VOID mqmProcessAssocReq(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb, IN PUINT_8 pucIE, IN UINT_16 u2IELength)
  3025. {
  3026. P_STA_RECORD_T prStaRec;
  3027. UINT_16 u2Offset;
  3028. PUINT_8 pucIEStart;
  3029. UINT_8 aucWfaOui[] = VENDOR_OUI_WFA;
  3030. P_IE_WMM_INFO_T prIeWmmInfo;
  3031. UINT_8 ucQosInfo;
  3032. UINT_8 ucQosInfoAC;
  3033. UINT_8 ucBmpAC;
  3034. DEBUGFUNC("mqmProcessAssocReq");
  3035. ASSERT(prSwRfb);
  3036. ASSERT(pucIE);
  3037. prStaRec = cnmGetStaRecByIndex(prAdapter, prSwRfb->ucStaRecIdx);
  3038. ASSERT(prStaRec);
  3039. if (prStaRec == NULL)
  3040. return;
  3041. prStaRec->fgIsQoS = FALSE;
  3042. prStaRec->fgIsWmmSupported = prStaRec->fgIsUapsdSupported = FALSE;
  3043. pucIEStart = pucIE;
  3044. /* If the device does not support QoS or if WMM is not supported by the peer, exit. */
  3045. if (!prAdapter->rWifiVar.fgSupportQoS)
  3046. return;
  3047. /* Determine whether QoS is enabled with the association */
  3048. IE_FOR_EACH(pucIE, u2IELength, u2Offset) {
  3049. switch (IE_ID(pucIE)) {
  3050. case ELEM_ID_WMM:
  3051. if ((WMM_IE_OUI_TYPE(pucIE) == VENDOR_OUI_TYPE_WMM) &&
  3052. (!kalMemCmp(WMM_IE_OUI(pucIE), aucWfaOui, 3))) {
  3053. switch (WMM_IE_OUI_SUBTYPE(pucIE)) {
  3054. case VENDOR_OUI_SUBTYPE_WMM_INFO:
  3055. if (IE_LEN(pucIE) != 7)
  3056. break; /* WMM Info IE with a wrong length */
  3057. prStaRec->fgIsQoS = TRUE;
  3058. prStaRec->fgIsWmmSupported = TRUE;
  3059. prIeWmmInfo = (P_IE_WMM_INFO_T) pucIE;
  3060. ucQosInfo = prIeWmmInfo->ucQosInfo;
  3061. ucQosInfoAC = ucQosInfo & BITS(0, 3);
  3062. prStaRec->fgIsUapsdSupported = ((ucQosInfoAC) ? TRUE : FALSE) &
  3063. prAdapter->rWifiVar.fgSupportUAPSD;
  3064. ucBmpAC = 0;
  3065. if (ucQosInfoAC & WMM_QOS_INFO_VO_UAPSD)
  3066. ucBmpAC |= BIT(ACI_VO);
  3067. if (ucQosInfoAC & WMM_QOS_INFO_VI_UAPSD)
  3068. ucBmpAC |= BIT(ACI_VI);
  3069. if (ucQosInfoAC & WMM_QOS_INFO_BE_UAPSD)
  3070. ucBmpAC |= BIT(ACI_BE);
  3071. if (ucQosInfoAC & WMM_QOS_INFO_BK_UAPSD)
  3072. ucBmpAC |= BIT(ACI_BK);
  3073. prStaRec->ucBmpTriggerAC = prStaRec->ucBmpDeliveryAC = ucBmpAC;
  3074. prStaRec->ucUapsdSp =
  3075. (ucQosInfo & WMM_QOS_INFO_MAX_SP_LEN_MASK) >> 5;
  3076. break;
  3077. default:
  3078. /* Other WMM QoS IEs. Ignore any */
  3079. break;
  3080. }
  3081. }
  3082. /* else: VENDOR_OUI_TYPE_WPA, VENDOR_OUI_TYPE_WPS */
  3083. break;
  3084. case ELEM_ID_HT_CAP:
  3085. /* Some client won't put the WMM IE if client is 802.11n */
  3086. if (IE_LEN(pucIE) == (sizeof(IE_HT_CAP_T) - 2))
  3087. prStaRec->fgIsQoS = TRUE;
  3088. break;
  3089. default:
  3090. break;
  3091. }
  3092. }
  3093. DBGLOG(QM, TRACE, "MQM: Assoc_Req Parsing (QoS Enabled=%d)\n", prStaRec->fgIsQoS);
  3094. }
  3095. /*----------------------------------------------------------------------------*/
  3096. /*!
  3097. * \brief To process WMM related IEs in ASSOC_RSP
  3098. *
  3099. * \param[in] prAdapter Adapter pointer
  3100. * \param[in] prSwRfb The received frame
  3101. * \param[in] pucIE The pointer to the first IE in the frame
  3102. * \param[in] u2IELength The total length of IEs in the frame
  3103. *
  3104. * \return none
  3105. */
  3106. /*----------------------------------------------------------------------------*/
  3107. VOID mqmProcessAssocRsp(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb, IN PUINT_8 pucIE, IN UINT_16 u2IELength)
  3108. {
  3109. P_STA_RECORD_T prStaRec;
  3110. UINT_16 u2Offset;
  3111. PUINT_8 pucIEStart;
  3112. UINT_8 aucWfaOui[] = VENDOR_OUI_WFA;
  3113. DEBUGFUNC("mqmProcessAssocRsp");
  3114. ASSERT(prSwRfb);
  3115. ASSERT(pucIE);
  3116. prStaRec = cnmGetStaRecByIndex(prAdapter, prSwRfb->ucStaRecIdx);
  3117. ASSERT(prStaRec);
  3118. if (prStaRec == NULL)
  3119. return;
  3120. prStaRec->fgIsQoS = FALSE;
  3121. pucIEStart = pucIE;
  3122. DBGLOG(QM, TRACE, "QM: (fgIsWmmSupported=%d, fgSupportQoS=%d)\n",
  3123. prStaRec->fgIsWmmSupported, prAdapter->rWifiVar.fgSupportQoS);
  3124. /* If the device does not support QoS or if WMM is not supported by the peer, exit. */
  3125. /* if((!prAdapter->rWifiVar.fgSupportQoS) || (!prStaRec->fgIsWmmSupported)) */
  3126. if ((!prAdapter->rWifiVar.fgSupportQoS))
  3127. return;
  3128. /* Determine whether QoS is enabled with the association */
  3129. IE_FOR_EACH(pucIE, u2IELength, u2Offset) {
  3130. switch (IE_ID(pucIE)) {
  3131. case ELEM_ID_WMM:
  3132. if ((WMM_IE_OUI_TYPE(pucIE) == VENDOR_OUI_TYPE_WMM) &&
  3133. (!kalMemCmp(WMM_IE_OUI(pucIE), aucWfaOui, 3))) {
  3134. switch (WMM_IE_OUI_SUBTYPE(pucIE)) {
  3135. case VENDOR_OUI_SUBTYPE_WMM_PARAM:
  3136. if (IE_LEN(pucIE) != 24)
  3137. break; /* WMM Info IE with a wrong length */
  3138. prStaRec->fgIsQoS = TRUE;
  3139. break;
  3140. case VENDOR_OUI_SUBTYPE_WMM_INFO:
  3141. if (IE_LEN(pucIE) != 7)
  3142. break; /* WMM Info IE with a wrong length */
  3143. prStaRec->fgIsQoS = TRUE;
  3144. break;
  3145. default:
  3146. /* Other WMM QoS IEs. Ignore any */
  3147. break;
  3148. }
  3149. }
  3150. /* else: VENDOR_OUI_TYPE_WPA, VENDOR_OUI_TYPE_WPS */
  3151. break;
  3152. case ELEM_ID_HT_CAP:
  3153. /* Some AP won't put the WMM IE if client is 802.11n */
  3154. if (IE_LEN(pucIE) == (sizeof(IE_HT_CAP_T) - 2))
  3155. prStaRec->fgIsQoS = TRUE;
  3156. break;
  3157. default:
  3158. break;
  3159. }
  3160. }
  3161. /* Parse AC parameters and write to HW CRs */
  3162. if ((prStaRec->fgIsQoS) && (prStaRec->eStaType == STA_TYPE_LEGACY_AP)) {
  3163. mqmParseEdcaParameters(prAdapter, prSwRfb, pucIEStart, u2IELength, TRUE);
  3164. #if ARP_MONITER_ENABLE
  3165. qmResetArpDetect();
  3166. #endif
  3167. }
  3168. DBGLOG(QM, TRACE, "MQM: Assoc_Rsp Parsing (QoS Enabled=%d)\n", prStaRec->fgIsQoS);
  3169. if (prStaRec->fgIsWmmSupported)
  3170. nicQmUpdateWmmParms(prAdapter, prStaRec->ucNetTypeIndex);
  3171. }
  3172. /*----------------------------------------------------------------------------*/
  3173. /*!
  3174. * \brief To parse WMM Parameter IE (in BCN or Assoc_Rsp)
  3175. *
  3176. * \param[in] prAdapter Adapter pointer
  3177. * \param[in] prSwRfb The received frame
  3178. * \param[in] pucIE The pointer to the first IE in the frame
  3179. * \param[in] u2IELength The total length of IEs in the frame
  3180. * \param[in] fgForceOverride TRUE: If EDCA parameters are found, always set to HW CRs.
  3181. *
  3182. * \return none
  3183. */
  3184. /*----------------------------------------------------------------------------*/
  3185. VOID
  3186. mqmParseEdcaParameters(IN P_ADAPTER_T prAdapter,
  3187. IN P_SW_RFB_T prSwRfb, IN PUINT_8 pucIE, IN UINT_16 u2IELength, IN BOOLEAN fgForceOverride)
  3188. {
  3189. P_STA_RECORD_T prStaRec;
  3190. UINT_16 u2Offset;
  3191. UINT_8 aucWfaOui[] = VENDOR_OUI_WFA;
  3192. P_BSS_INFO_T prBssInfo;
  3193. P_AC_QUE_PARMS_T prAcQueParams;
  3194. P_IE_WMM_PARAM_T prIeWmmParam;
  3195. ENUM_WMM_ACI_T eAci;
  3196. PUINT_8 pucWmmParamSetCount;
  3197. DEBUGFUNC("mqmParseEdcaParameters");
  3198. ASSERT(prSwRfb);
  3199. ASSERT(pucIE);
  3200. prStaRec = cnmGetStaRecByIndex(prAdapter, prSwRfb->ucStaRecIdx);
  3201. ASSERT(prStaRec);
  3202. if (prStaRec == NULL)
  3203. return;
  3204. DBGLOG(QM, TRACE, "QM: (fgIsWmmSupported=%d, fgIsQoS=%d)\n", prStaRec->fgIsWmmSupported, prStaRec->fgIsQoS);
  3205. if ((!prAdapter->rWifiVar.fgSupportQoS) || (!prStaRec->fgIsWmmSupported) || (!prStaRec->fgIsQoS))
  3206. return;
  3207. prBssInfo = &(prAdapter->rWifiVar.arBssInfo[prStaRec->ucNetTypeIndex]);
  3208. /* Goal: Obtain the EDCA parameters */
  3209. IE_FOR_EACH(pucIE, u2IELength, u2Offset) {
  3210. switch (IE_ID(pucIE)) {
  3211. case ELEM_ID_WMM:
  3212. if ((WMM_IE_OUI_TYPE(pucIE) != VENDOR_OUI_TYPE_WMM) ||
  3213. (kalMemCmp(WMM_IE_OUI(pucIE), aucWfaOui, 3)))
  3214. break;
  3215. switch (WMM_IE_OUI_SUBTYPE(pucIE)) {
  3216. case VENDOR_OUI_SUBTYPE_WMM_PARAM:
  3217. if (IE_LEN(pucIE) != 24)
  3218. break; /* WMM Param IE with a wrong length */
  3219. pucWmmParamSetCount = &(prBssInfo->ucWmmParamSetCount);
  3220. prIeWmmParam = (P_IE_WMM_PARAM_T) pucIE;
  3221. /* Check the Parameter Set Count to determine whether EDCA parameters */
  3222. /* have been changed */
  3223. if (!fgForceOverride && (*pucWmmParamSetCount
  3224. == (prIeWmmParam->ucQosInfo & WMM_QOS_INFO_PARAM_SET_CNT)))
  3225. break; /* Ignore the IE without updating HW CRs */
  3226. /* Update Parameter Set Count */
  3227. *pucWmmParamSetCount =
  3228. (prIeWmmParam->ucQosInfo & WMM_QOS_INFO_PARAM_SET_CNT);
  3229. /* Update EDCA parameters */
  3230. for (eAci = 0; eAci < WMM_AC_INDEX_NUM; eAci++) {
  3231. prAcQueParams = &prBssInfo->arACQueParms[eAci];
  3232. mqmFillAcQueParam(prIeWmmParam, eAci, prAcQueParams);
  3233. prAcQueParams->fgIsACMSet =
  3234. (prAcQueParams->u2Aifsn & WMM_ACIAIFSN_ACM) ? TRUE : FALSE;
  3235. prAcQueParams->u2Aifsn &= WMM_ACIAIFSN_AIFSN;
  3236. DBGLOG(QM, LOUD,
  3237. "eAci:%d, ACM:%d, Aifsn:%d, CWmin:%d, CWmax:%d, TxopLmt:%d\n",
  3238. eAci, prAcQueParams->fgIsACMSet, prAcQueParams->u2Aifsn,
  3239. prAcQueParams->u2CWmin, prAcQueParams->u2CWmax,
  3240. prAcQueParams->u2TxopLimit);
  3241. }
  3242. break;
  3243. default:
  3244. /* Other WMM QoS IEs. Ignore */
  3245. break;
  3246. }
  3247. /* else: VENDOR_OUI_TYPE_WPA, VENDOR_OUI_TYPE_WPS, ... (not cared) */
  3248. break;
  3249. default:
  3250. break;
  3251. }
  3252. }
  3253. }
  3254. /*----------------------------------------------------------------------------*/
  3255. /*!
  3256. * \brief This function is used for parsing EDCA parameters specified in the WMM Parameter IE
  3257. *
  3258. * \param[in] prAdapter Adapter pointer
  3259. * \param[in] prIeWmmParam The pointer to the WMM Parameter IE
  3260. * \param[in] u4AcOffset The offset specifying the AC queue for parsing
  3261. * \param[in] prHwAcParams The parameter structure used to configure the HW CRs
  3262. *
  3263. * \return none
  3264. */
  3265. /*----------------------------------------------------------------------------*/
  3266. VOID mqmFillAcQueParam(IN P_IE_WMM_PARAM_T prIeWmmParam, IN UINT_32 u4AcOffset, OUT P_AC_QUE_PARMS_T prAcQueParams)
  3267. {
  3268. prAcQueParams->u2Aifsn = *((PUINT_8) (&(prIeWmmParam->ucAciAifsn_BE)) + (u4AcOffset * 4));
  3269. prAcQueParams->u2CWmax = BIT(((*((PUINT_8) (&(prIeWmmParam->ucEcw_BE)) + (u4AcOffset * 4))) & WMM_ECW_WMAX_MASK)
  3270. >> WMM_ECW_WMAX_OFFSET) - 1;
  3271. prAcQueParams->u2CWmin =
  3272. BIT((*((PUINT_8) (&(prIeWmmParam->ucEcw_BE)) + (u4AcOffset * 4))) & WMM_ECW_WMIN_MASK) - 1;
  3273. WLAN_GET_FIELD_16(((PUINT_8) (&(prIeWmmParam->aucTxopLimit_BE)) + (u4AcOffset * 4)),
  3274. &(prAcQueParams->u2TxopLimit));
  3275. prAcQueParams->ucGuradTime = TXM_DEFAULT_FLUSH_QUEUE_GUARD_TIME;
  3276. }
  3277. /*----------------------------------------------------------------------------*/
  3278. /*!
  3279. * \brief To parse WMM/11n related IEs in scan results (only for AP peers)
  3280. *
  3281. * \param[in] prAdapter Adapter pointer
  3282. * \param[in] prScanResult The scan result which shall be parsed to obtain needed info
  3283. * \param[out] prStaRec The obtained info is stored in the STA_REC
  3284. *
  3285. * \return none
  3286. */
  3287. /*----------------------------------------------------------------------------*/
  3288. #if (CFG_SUPPORT_TDLS == 1) /* for test purpose */
  3289. BOOLEAN flgTdlsTestExtCapElm = FALSE;
  3290. UINT8 aucTdlsTestExtCapElm[7];
  3291. #endif /* CFG_SUPPORT_TDLS */
  3292. VOID mqmProcessScanResult(IN P_ADAPTER_T prAdapter, IN P_BSS_DESC_T prScanResult, OUT P_STA_RECORD_T prStaRec)
  3293. {
  3294. PUINT_8 pucIE;
  3295. UINT_16 u2IELength;
  3296. UINT_16 u2Offset;
  3297. UINT_8 aucWfaOui[] = VENDOR_OUI_WFA;
  3298. DEBUGFUNC("mqmProcessScanResult");
  3299. ASSERT(prScanResult);
  3300. ASSERT(prStaRec);
  3301. /* Reset the flag before parsing */
  3302. prStaRec->fgIsWmmSupported = prStaRec->fgIsUapsdSupported = FALSE;
  3303. if (!prAdapter->rWifiVar.fgSupportQoS)
  3304. return;
  3305. u2IELength = prScanResult->u2IELength;
  3306. pucIE = prScanResult->aucIEBuf;
  3307. #if (CFG_SUPPORT_TDLS == 1)
  3308. /* TDLS test purpose */
  3309. if (flgTdlsTestExtCapElm == TRUE)
  3310. TdlsexBssExtCapParse(prStaRec, aucTdlsTestExtCapElm);
  3311. #endif /* CFG_SUPPORT_TDLS */
  3312. /* Goal: Determine whether the peer supports WMM/QoS and UAPSDU */
  3313. IE_FOR_EACH(pucIE, u2IELength, u2Offset) {
  3314. switch (IE_ID(pucIE)) {
  3315. case ELEM_ID_EXTENDED_CAP:
  3316. #if (CFG_SUPPORT_TDLS == 1)
  3317. TdlsexBssExtCapParse(prStaRec, pucIE);
  3318. #endif /* CFG_SUPPORT_TDLS */
  3319. break;
  3320. case ELEM_ID_WMM:
  3321. if ((WMM_IE_OUI_TYPE(pucIE) == VENDOR_OUI_TYPE_WMM) &&
  3322. (!kalMemCmp(WMM_IE_OUI(pucIE), aucWfaOui, 3))) {
  3323. switch (WMM_IE_OUI_SUBTYPE(pucIE)) {
  3324. case VENDOR_OUI_SUBTYPE_WMM_PARAM:
  3325. if (IE_LEN(pucIE) != 24)
  3326. break; /* WMM Param IE with a wrong length */
  3327. prStaRec->fgIsWmmSupported = TRUE;
  3328. prStaRec->fgIsUapsdSupported =
  3329. (((((P_IE_WMM_PARAM_T) pucIE)->ucQosInfo) & WMM_QOS_INFO_UAPSD) ?
  3330. TRUE : FALSE);
  3331. break;
  3332. case VENDOR_OUI_SUBTYPE_WMM_INFO:
  3333. if (IE_LEN(pucIE) != 7)
  3334. break; /* WMM Info IE with a wrong length */
  3335. prStaRec->fgIsWmmSupported = TRUE;
  3336. prStaRec->fgIsUapsdSupported =
  3337. (((((P_IE_WMM_INFO_T) pucIE)->ucQosInfo) & WMM_QOS_INFO_UAPSD) ?
  3338. TRUE : FALSE);
  3339. break;
  3340. default:
  3341. /* A WMM QoS IE that doesn't matter. Ignore it. */
  3342. break;
  3343. }
  3344. }
  3345. /* else: VENDOR_OUI_TYPE_WPA, VENDOR_OUI_TYPE_WPS, ... (not cared) */
  3346. break;
  3347. default:
  3348. /* A WMM IE that doesn't matter. Ignore it. */
  3349. break;
  3350. }
  3351. }
  3352. DBGLOG(QM, LOUD, "MQM: Scan Result Parsing (WMM=%d, UAPSD=%d)\n",
  3353. prStaRec->fgIsWmmSupported, prStaRec->fgIsUapsdSupported);
  3354. }
  3355. UINT_8 qmGetStaRecIdx(IN P_ADAPTER_T prAdapter, IN PUINT_8 pucEthDestAddr, IN ENUM_NETWORK_TYPE_INDEX_T eNetworkType)
  3356. {
  3357. UINT_32 i;
  3358. P_STA_RECORD_T prTempStaRec;
  3359. prTempStaRec = NULL;
  3360. ASSERT(prAdapter);
  3361. /* 4 <1> DA = BMCAST */
  3362. if (IS_BMCAST_MAC_ADDR(pucEthDestAddr))
  3363. return STA_REC_INDEX_BMCAST;
  3364. /* 4 <2> Check if an AP STA is present */
  3365. for (i = 0; i < CFG_NUM_OF_STA_RECORD; i++) {
  3366. prTempStaRec = &(prAdapter->arStaRec[i]);
  3367. if ((prTempStaRec->ucNetTypeIndex == eNetworkType)
  3368. && (prTempStaRec->fgIsAp)
  3369. && (prTempStaRec->fgIsValid)) {
  3370. return prTempStaRec->ucIndex;
  3371. }
  3372. }
  3373. /* 4 <3> Not BMCAST, No AP --> Compare DA (i.e., to see whether this is a unicast frame to a client) */
  3374. for (i = 0; i < CFG_NUM_OF_STA_RECORD; i++) {
  3375. prTempStaRec = &(prAdapter->arStaRec[i]);
  3376. if (prTempStaRec->fgIsValid) {
  3377. if (EQUAL_MAC_ADDR(prTempStaRec->aucMacAddr, pucEthDestAddr))
  3378. return prTempStaRec->ucIndex;
  3379. }
  3380. }
  3381. /* 4 <4> No STA found, Not BMCAST --> Indicate NOT_FOUND to FW */
  3382. return STA_REC_INDEX_NOT_FOUND;
  3383. }
  3384. UINT_32
  3385. mqmGenerateWmmInfoIEByParam(BOOLEAN fgSupportUAPSD,
  3386. UINT_8 ucBmpDeliveryAC, UINT_8 ucBmpTriggerAC, UINT_8 ucUapsdSp, UINT_8 *pOutBuf)
  3387. {
  3388. P_IE_WMM_INFO_T prIeWmmInfo;
  3389. UINT_32 ucUapsd[] = {
  3390. WMM_QOS_INFO_BE_UAPSD,
  3391. WMM_QOS_INFO_BK_UAPSD,
  3392. WMM_QOS_INFO_VI_UAPSD,
  3393. WMM_QOS_INFO_VO_UAPSD
  3394. };
  3395. UINT_8 aucWfaOui[] = VENDOR_OUI_WFA;
  3396. ASSERT(pOutBuf);
  3397. prIeWmmInfo = (P_IE_WMM_INFO_T) pOutBuf;
  3398. prIeWmmInfo->ucId = ELEM_ID_WMM;
  3399. prIeWmmInfo->ucLength = ELEM_MAX_LEN_WMM_INFO;
  3400. /* WMM-2.2.1 WMM Information Element Field Values */
  3401. prIeWmmInfo->aucOui[0] = aucWfaOui[0];
  3402. prIeWmmInfo->aucOui[1] = aucWfaOui[1];
  3403. prIeWmmInfo->aucOui[2] = aucWfaOui[2];
  3404. prIeWmmInfo->ucOuiType = VENDOR_OUI_TYPE_WMM;
  3405. prIeWmmInfo->ucOuiSubtype = VENDOR_OUI_SUBTYPE_WMM_INFO;
  3406. prIeWmmInfo->ucVersion = VERSION_WMM;
  3407. prIeWmmInfo->ucQosInfo = 0;
  3408. /* UAPSD initial queue configurations (delivery and trigger enabled) */
  3409. if (fgSupportUAPSD) {
  3410. UINT_8 ucQosInfo = 0;
  3411. UINT_8 i;
  3412. /* Static U-APSD setting */
  3413. for (i = ACI_BE; i <= ACI_VO; i++) {
  3414. if (ucBmpDeliveryAC & ucBmpTriggerAC & BIT(i))
  3415. ucQosInfo |= (UINT_8) ucUapsd[i];
  3416. }
  3417. if (ucBmpDeliveryAC & ucBmpTriggerAC) {
  3418. switch (ucUapsdSp) {
  3419. case WMM_MAX_SP_LENGTH_ALL:
  3420. ucQosInfo |= WMM_QOS_INFO_MAX_SP_ALL;
  3421. break;
  3422. case WMM_MAX_SP_LENGTH_2:
  3423. ucQosInfo |= WMM_QOS_INFO_MAX_SP_2;
  3424. break;
  3425. case WMM_MAX_SP_LENGTH_4:
  3426. ucQosInfo |= WMM_QOS_INFO_MAX_SP_4;
  3427. break;
  3428. case WMM_MAX_SP_LENGTH_6:
  3429. ucQosInfo |= WMM_QOS_INFO_MAX_SP_6;
  3430. break;
  3431. default:
  3432. DBGLOG(QM, WARN, "MQM: Incorrect SP length\n");
  3433. ucQosInfo |= WMM_QOS_INFO_MAX_SP_2;
  3434. break;
  3435. }
  3436. }
  3437. prIeWmmInfo->ucQosInfo = ucQosInfo;
  3438. }
  3439. /* Increment the total IE length for the Element ID and Length fields. */
  3440. return IE_SIZE(prIeWmmInfo);
  3441. }
  3442. /*----------------------------------------------------------------------------*/
  3443. /*!
  3444. * @brief Generate the WMM Info IE
  3445. *
  3446. * \param[in] prAdapter Adapter pointer
  3447. * @param prMsduInfo The TX MMPDU
  3448. *
  3449. * @return (none)
  3450. */
  3451. /*----------------------------------------------------------------------------*/
  3452. VOID mqmGenerateWmmInfoIE(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo)
  3453. {
  3454. P_IE_WMM_INFO_T prIeWmmInfo;
  3455. P_PM_PROFILE_SETUP_INFO_T prPmProfSetupInfo;
  3456. P_BSS_INFO_T prBssInfo;
  3457. P_STA_RECORD_T prStaRec;
  3458. DEBUGFUNC("mqmGenerateWmmInfoIE");
  3459. ASSERT(prMsduInfo);
  3460. /* In case QoS is not turned off, exit directly */
  3461. if (!prAdapter->rWifiVar.fgSupportQoS)
  3462. return;
  3463. prStaRec = cnmGetStaRecByIndex(prAdapter, prMsduInfo->ucStaRecIndex);
  3464. ASSERT(prStaRec);
  3465. if (prStaRec == NULL)
  3466. return;
  3467. if (!prStaRec->fgIsWmmSupported)
  3468. return;
  3469. prBssInfo = &(prAdapter->rWifiVar.arBssInfo[prStaRec->ucNetTypeIndex]);
  3470. prPmProfSetupInfo = &prBssInfo->rPmProfSetupInfo;
  3471. prIeWmmInfo = (P_IE_WMM_INFO_T)
  3472. ((PUINT_8) prMsduInfo->prPacket + prMsduInfo->u2FrameLength);
  3473. #if 0
  3474. prIeWmmInfo->ucId = ELEM_ID_WMM;
  3475. prIeWmmInfo->ucLength = ELEM_MAX_LEN_WMM_INFO;
  3476. /* WMM-2.2.1 WMM Information Element Field Values */
  3477. prIeWmmInfo->aucOui[0] = aucWfaOui[0];
  3478. prIeWmmInfo->aucOui[1] = aucWfaOui[1];
  3479. prIeWmmInfo->aucOui[2] = aucWfaOui[2];
  3480. prIeWmmInfo->ucOuiType = VENDOR_OUI_TYPE_WMM;
  3481. prIeWmmInfo->ucOuiSubtype = VENDOR_OUI_SUBTYPE_WMM_INFO;
  3482. prIeWmmInfo->ucVersion = VERSION_WMM;
  3483. prIeWmmInfo->ucQosInfo = 0;
  3484. /* UAPSD initial queue configurations (delivery and trigger enabled) */
  3485. /* if(prAdapter->rWifiVar.fgSupportUAPSD){ */
  3486. if (prAdapter->rWifiVar.fgSupportUAPSD && prStaRec->fgIsUapsdSupported) {
  3487. UINT_8 ucQosInfo = 0;
  3488. UINT_8 i;
  3489. /* Static U-APSD setting */
  3490. for (i = ACI_BE; i <= ACI_VO; i++) {
  3491. if (prPmProfSetupInfo->ucBmpDeliveryAC & prPmProfSetupInfo->ucBmpTriggerAC & BIT(i))
  3492. ucQosInfo |= (UINT_8) ucUapsd[i];
  3493. }
  3494. if (prPmProfSetupInfo->ucBmpDeliveryAC & prPmProfSetupInfo->ucBmpTriggerAC) {
  3495. switch (prPmProfSetupInfo->ucUapsdSp) {
  3496. case WMM_MAX_SP_LENGTH_ALL:
  3497. ucQosInfo |= WMM_QOS_INFO_MAX_SP_ALL;
  3498. break;
  3499. case WMM_MAX_SP_LENGTH_2:
  3500. ucQosInfo |= WMM_QOS_INFO_MAX_SP_2;
  3501. break;
  3502. case WMM_MAX_SP_LENGTH_4:
  3503. ucQosInfo |= WMM_QOS_INFO_MAX_SP_4;
  3504. break;
  3505. case WMM_MAX_SP_LENGTH_6:
  3506. ucQosInfo |= WMM_QOS_INFO_MAX_SP_6;
  3507. break;
  3508. default:
  3509. DBGLOG(QM, INFO, "MQM: Incorrect SP length\n");
  3510. ucQosInfo |= WMM_QOS_INFO_MAX_SP_2;
  3511. break;
  3512. }
  3513. }
  3514. prIeWmmInfo->ucQosInfo = ucQosInfo;
  3515. }
  3516. /* Increment the total IE length for the Element ID and Length fields. */
  3517. prMsduInfo->u2FrameLength += IE_SIZE(prIeWmmInfo);
  3518. #else
  3519. prMsduInfo->u2FrameLength += mqmGenerateWmmInfoIEByParam((prAdapter->rWifiVar.fgSupportUAPSD
  3520. && prStaRec->fgIsUapsdSupported),
  3521. prPmProfSetupInfo->ucBmpDeliveryAC,
  3522. prPmProfSetupInfo->ucBmpTriggerAC,
  3523. prPmProfSetupInfo->ucUapsdSp, (UINT_8 *) prIeWmmInfo);
  3524. #endif
  3525. }
  3526. #if 0
  3527. /*----------------------------------------------------------------------------*/
  3528. /*!
  3529. * @brief log2 calculation for CW
  3530. *
  3531. * @param[in] val value
  3532. *
  3533. * @return log2(val)
  3534. */
  3535. /*----------------------------------------------------------------------------*/
  3536. UINT_32 cwlog2(UINT_32 val)
  3537. {
  3538. UINT_32 n;
  3539. n = 0;
  3540. while (val >= 512) {
  3541. n += 9;
  3542. val = val >> 9;
  3543. }
  3544. while (val >= 16) {
  3545. n += 4;
  3546. val >>= 4;
  3547. }
  3548. while (val >= 2) {
  3549. n += 1;
  3550. val >>= 1;
  3551. }
  3552. return n;
  3553. }
  3554. #endif
  3555. UINT_32 mqmGenerateWmmParamIEByParam(P_ADAPTER_T prAdapter,
  3556. P_BSS_INFO_T prBssInfo, UINT_8 *pOutBuf, ENUM_OP_MODE_T ucOpMode)
  3557. {
  3558. P_IE_WMM_PARAM_T prIeWmmParam;
  3559. UINT_8 aucWfaOui[] = VENDOR_OUI_WFA;
  3560. UINT_8 aucACI[] = {
  3561. WMM_ACI_AC_BE,
  3562. WMM_ACI_AC_BK,
  3563. WMM_ACI_AC_VI,
  3564. WMM_ACI_AC_VO
  3565. };
  3566. ENUM_WMM_ACI_T eAci;
  3567. UCHAR *pucAciAifsn, *pucEcw, *pucTxopLimit;
  3568. ASSERT(pOutBuf);
  3569. prIeWmmParam = (P_IE_WMM_PARAM_T) pOutBuf;
  3570. prIeWmmParam->ucId = ELEM_ID_WMM;
  3571. prIeWmmParam->ucLength = ELEM_MAX_LEN_WMM_PARAM;
  3572. /* WMM-2.2.1 WMM Information Element Field Values */
  3573. prIeWmmParam->aucOui[0] = aucWfaOui[0];
  3574. prIeWmmParam->aucOui[1] = aucWfaOui[1];
  3575. prIeWmmParam->aucOui[2] = aucWfaOui[2];
  3576. prIeWmmParam->ucOuiType = VENDOR_OUI_TYPE_WMM;
  3577. prIeWmmParam->ucOuiSubtype = VENDOR_OUI_SUBTYPE_WMM_PARAM;
  3578. prIeWmmParam->ucVersion = VERSION_WMM;
  3579. prIeWmmParam->ucQosInfo = (prBssInfo->ucWmmParamSetCount & WMM_QOS_INFO_PARAM_SET_CNT);
  3580. /* UAPSD initial queue configurations (delivery and trigger enabled) */
  3581. if (prAdapter->rWifiVar.fgSupportUAPSD) {
  3582. if (ucOpMode == OP_MODE_INFRASTRUCTURE)
  3583. prIeWmmParam->ucQosInfo = 0xf;
  3584. else
  3585. prIeWmmParam->ucQosInfo |= WMM_QOS_INFO_UAPSD;
  3586. }
  3587. /* EDCA parameter */
  3588. for (eAci = 0; eAci < WMM_AC_INDEX_NUM; eAci++) {
  3589. /* DBGLOG(QM, LOUD, */
  3590. /* ("MQM: eAci = %d, ACM = %d, Aifsn = %d, CWmin = %d, CWmax = %d, TxopLimit = %d\n", */
  3591. /* eAci,prBssInfo->arACQueParmsForBcast[eAci].fgIsACMSet , */
  3592. /* prBssInfo->arACQueParmsForBcast[eAci].u2Aifsn, */
  3593. /* prBssInfo->arACQueParmsForBcast[eAci].u2CWmin, */
  3594. /* prBssInfo->arACQueParmsForBcast[eAci].u2CWmax, */
  3595. /* prBssInfo->arACQueParmsForBcast[eAci].u2TxopLimit)); */
  3596. #if 0
  3597. *(((PUINT_8) (&prIeWmmParam->ucAciAifsn_BE)) + (eAci << 2)) = (UINT_8) (aucACI[eAci]
  3598. |
  3599. (prBssInfo->arACQueParmsForBcast
  3600. [eAci].fgIsACMSet ?
  3601. WMM_ACIAIFSN_ACM : 0)
  3602. |
  3603. (prBssInfo->arACQueParmsForBcast
  3604. [eAci].u2Aifsn &
  3605. (WMM_ACIAIFSN_AIFSN)));
  3606. #else
  3607. /* avoid compile warnings in Klockwork tool */
  3608. if (eAci == WMM_AC_BE_INDEX) {
  3609. pucAciAifsn = &prIeWmmParam->ucAciAifsn_BE;
  3610. pucEcw = &prIeWmmParam->ucEcw_BE;
  3611. pucTxopLimit = prIeWmmParam->aucTxopLimit_BE;
  3612. } else if (eAci == WMM_AC_BK_INDEX) {
  3613. pucAciAifsn = &prIeWmmParam->ucAciAifsn_BG;
  3614. pucEcw = &prIeWmmParam->ucEcw_BG;
  3615. pucTxopLimit = prIeWmmParam->aucTxopLimit_BG;
  3616. } else if (eAci == WMM_AC_VI_INDEX) {
  3617. pucAciAifsn = &prIeWmmParam->ucAciAifsn_VI;
  3618. pucEcw = &prIeWmmParam->ucEcw_VI;
  3619. pucTxopLimit = prIeWmmParam->aucTxopLimit_VI;
  3620. } else if (eAci == WMM_AC_VO_INDEX) {
  3621. pucAciAifsn = &prIeWmmParam->ucAciAifsn_VO;
  3622. pucEcw = &prIeWmmParam->ucEcw_VO;
  3623. pucTxopLimit = prIeWmmParam->aucTxopLimit_VO;
  3624. }
  3625. *pucAciAifsn = (UINT_8) (aucACI[eAci]
  3626. | (prBssInfo->arACQueParmsForBcast[eAci].fgIsACMSet ? WMM_ACIAIFSN_ACM : 0)
  3627. | (prBssInfo->arACQueParmsForBcast[eAci].u2Aifsn & (WMM_ACIAIFSN_AIFSN)));
  3628. #endif
  3629. #if 1
  3630. /* *( ((PUINT_8)(&prIeWmmParam->ucEcw_BE)) + (eAci <<2) ) = (UINT_8) (0 */
  3631. *pucEcw = (UINT_8) (0 | (((prBssInfo->aucCWminLog2ForBcast[eAci])) & WMM_ECW_WMIN_MASK)
  3632. | ((((prBssInfo->aucCWmaxLog2ForBcast[eAci])) << WMM_ECW_WMAX_OFFSET) &
  3633. WMM_ECW_WMAX_MASK)
  3634. );
  3635. #else
  3636. *(((PUINT_8) (&prIeWmmParam->ucEcw_BE)) + (eAci << 2)) = (UINT_8) (0
  3637. |
  3638. (cwlog2
  3639. ((prBssInfo->arACQueParmsForBcast
  3640. [eAci].u2CWmin +
  3641. 1)) & WMM_ECW_WMIN_MASK)
  3642. |
  3643. ((cwlog2
  3644. ((prBssInfo->arACQueParmsForBcast
  3645. [eAci].u2CWmax +
  3646. 1)) << WMM_ECW_WMAX_OFFSET) &
  3647. WMM_ECW_WMAX_MASK)
  3648. );
  3649. #endif
  3650. #if 0
  3651. WLAN_SET_FIELD_16(((PUINT_8) (prIeWmmParam->aucTxopLimit_BE)) + (eAci << 2)
  3652. , prBssInfo->arACQueParmsForBcast[eAci].u2TxopLimit);
  3653. #else
  3654. WLAN_SET_FIELD_16(pucTxopLimit, prBssInfo->arACQueParmsForBcast[eAci].u2TxopLimit);
  3655. #endif
  3656. }
  3657. /* Increment the total IE length for the Element ID and Length fields. */
  3658. return IE_SIZE(prIeWmmParam);
  3659. }
  3660. /*----------------------------------------------------------------------------*/
  3661. /*!
  3662. * @brief Generate the WMM Param IE
  3663. *
  3664. * \param[in] prAdapter Adapter pointer
  3665. * @param prMsduInfo The TX MMPDU
  3666. *
  3667. * @return (none)
  3668. */
  3669. /*----------------------------------------------------------------------------*/
  3670. VOID mqmGenerateWmmParamIE(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo)
  3671. {
  3672. P_IE_WMM_PARAM_T prIeWmmParam;
  3673. #if 0
  3674. UINT_8 aucWfaOui[] = VENDOR_OUI_WFA;
  3675. UINT_8 aucACI[] = {
  3676. WMM_ACI_AC_BE,
  3677. WMM_ACI_AC_BK,
  3678. WMM_ACI_AC_VI,
  3679. WMM_ACI_AC_VO
  3680. };
  3681. ENUM_WMM_ACI_T eAci;
  3682. #endif
  3683. P_BSS_INFO_T prBssInfo;
  3684. P_STA_RECORD_T prStaRec;
  3685. DEBUGFUNC("mqmGenerateWmmParamIE");
  3686. DBGLOG(QM, LOUD, "\n");
  3687. ASSERT(prMsduInfo);
  3688. /* In case QoS is not turned off, exit directly */
  3689. if (!prAdapter->rWifiVar.fgSupportQoS)
  3690. return;
  3691. prStaRec = cnmGetStaRecByIndex(prAdapter, prMsduInfo->ucStaRecIndex);
  3692. if (prStaRec) {
  3693. if (!prStaRec->fgIsQoS)
  3694. return;
  3695. }
  3696. prBssInfo = &(prAdapter->rWifiVar.arBssInfo[prMsduInfo->ucNetworkType]);
  3697. if (!prBssInfo->fgIsQBSS)
  3698. return;
  3699. /* 20120220 frog: update beacon content & change OP mode is a separate event for P2P network. */
  3700. #if 0
  3701. if (prBssInfo->eCurrentOPMode != OP_MODE_ACCESS_POINT && prBssInfo->eCurrentOPMode != OP_MODE_BOW)
  3702. return;
  3703. #endif
  3704. prIeWmmParam = (P_IE_WMM_PARAM_T)
  3705. ((PUINT_8) prMsduInfo->prPacket + prMsduInfo->u2FrameLength);
  3706. #if 0
  3707. prIeWmmParam->ucId = ELEM_ID_WMM;
  3708. prIeWmmParam->ucLength = ELEM_MAX_LEN_WMM_PARAM;
  3709. /* WMM-2.2.1 WMM Information Element Field Values */
  3710. prIeWmmParam->aucOui[0] = aucWfaOui[0];
  3711. prIeWmmParam->aucOui[1] = aucWfaOui[1];
  3712. prIeWmmParam->aucOui[2] = aucWfaOui[2];
  3713. prIeWmmParam->ucOuiType = VENDOR_OUI_TYPE_WMM;
  3714. prIeWmmParam->ucOuiSubtype = VENDOR_OUI_SUBTYPE_WMM_PARAM;
  3715. prIeWmmParam->ucVersion = VERSION_WMM;
  3716. prIeWmmParam->ucQosInfo = (prBssInfo->ucWmmParamSetCount & WMM_QOS_INFO_PARAM_SET_CNT);
  3717. /* UAPSD initial queue configurations (delivery and trigger enabled) */
  3718. if (prAdapter->rWifiVar.fgSupportUAPSD)
  3719. prIeWmmParam->ucQosInfo |= WMM_QOS_INFO_UAPSD;
  3720. /* EDCA parameter */
  3721. for (eAci = 0; eAci < WMM_AC_INDEX_NUM; eAci++) {
  3722. /* DBGLOG(QM, LOUD, */
  3723. /* ("MQM: eAci = %d, ACM = %d, Aifsn = %d, CWmin = %d, CWmax = %d, TxopLimit = %d\n", */
  3724. /* eAci,prBssInfo->arACQueParmsForBcast[eAci].fgIsACMSet , */
  3725. /* prBssInfo->arACQueParmsForBcast[eAci].u2Aifsn, */
  3726. /* prBssInfo->arACQueParmsForBcast[eAci].u2CWmin, */
  3727. /* prBssInfo->arACQueParmsForBcast[eAci].u2CWmax, */
  3728. /* prBssInfo->arACQueParmsForBcast[eAci].u2TxopLimit)); */
  3729. *(((PUINT_8) (&prIeWmmParam->ucAciAifsn_BE)) + (eAci << 2)) = (UINT_8) (aucACI[eAci]
  3730. |
  3731. (prBssInfo->arACQueParmsForBcast
  3732. [eAci].fgIsACMSet ?
  3733. WMM_ACIAIFSN_ACM : 0)
  3734. |
  3735. (prBssInfo->arACQueParmsForBcast
  3736. [eAci].u2Aifsn &
  3737. (WMM_ACIAIFSN_AIFSN)));
  3738. #if 1
  3739. *(((PUINT_8) (&prIeWmmParam->ucEcw_BE)) + (eAci << 2)) = (UINT_8) (0
  3740. |
  3741. (((prBssInfo->aucCWminLog2ForBcast
  3742. [eAci])) & WMM_ECW_WMIN_MASK)
  3743. |
  3744. ((((prBssInfo->aucCWmaxLog2ForBcast
  3745. [eAci])) << WMM_ECW_WMAX_OFFSET)
  3746. & WMM_ECW_WMAX_MASK)
  3747. );
  3748. #else
  3749. *(((PUINT_8) (&prIeWmmParam->ucEcw_BE)) + (eAci << 2)) = (UINT_8) (0
  3750. |
  3751. (cwlog2
  3752. ((prBssInfo->arACQueParmsForBcast
  3753. [eAci].u2CWmin +
  3754. 1)) & WMM_ECW_WMIN_MASK)
  3755. |
  3756. ((cwlog2
  3757. ((prBssInfo->arACQueParmsForBcast
  3758. [eAci].u2CWmax +
  3759. 1)) << WMM_ECW_WMAX_OFFSET) &
  3760. WMM_ECW_WMAX_MASK)
  3761. );
  3762. #endif
  3763. WLAN_SET_FIELD_16(((PUINT_8) (prIeWmmParam->aucTxopLimit_BE)) + (eAci << 2)
  3764. , prBssInfo->arACQueParmsForBcast[eAci].u2TxopLimit);
  3765. }
  3766. /* Increment the total IE length for the Element ID and Length fields. */
  3767. prMsduInfo->u2FrameLength += IE_SIZE(prIeWmmParam);
  3768. #else
  3769. prMsduInfo->u2FrameLength += mqmGenerateWmmParamIEByParam(prAdapter,
  3770. prBssInfo, (UINT_8 *) prIeWmmParam, OP_MODE_ACCESS_POINT);
  3771. #endif
  3772. }
  3773. ENUM_FRAME_ACTION_T
  3774. qmGetFrameAction(IN P_ADAPTER_T prAdapter,
  3775. IN ENUM_NETWORK_TYPE_INDEX_T eNetworkType,
  3776. IN UINT_8 ucStaRecIdx, IN P_MSDU_INFO_T prMsduInfo, IN ENUM_FRAME_TYPE_IN_CMD_Q_T eFrameType)
  3777. {
  3778. P_BSS_INFO_T prBssInfo;
  3779. P_STA_RECORD_T prStaRec;
  3780. P_WLAN_MAC_HEADER_T prWlanFrame;
  3781. UINT_16 u2TxFrameCtrl;
  3782. DEBUGFUNC("qmGetFrameAction");
  3783. #if (NIC_TX_BUFF_COUNT_TC4 > 2)
  3784. #define QM_MGMT_QUUEUD_THRESHOLD 2
  3785. #else
  3786. #define QM_MGMT_QUUEUD_THRESHOLD 1
  3787. #endif
  3788. DATA_STRUCT_INSPECTING_ASSERT(QM_MGMT_QUUEUD_THRESHOLD <= (NIC_TX_BUFF_COUNT_TC4));
  3789. DATA_STRUCT_INSPECTING_ASSERT(QM_MGMT_QUUEUD_THRESHOLD > 0);
  3790. prBssInfo = &(prAdapter->rWifiVar.arBssInfo[eNetworkType]);
  3791. prStaRec = QM_GET_STA_REC_PTR_FROM_INDEX(prAdapter, ucStaRecIdx);
  3792. /* XXX Check BOW P2P AIS time ot set active */
  3793. if (!IS_BSS_ACTIVE(prBssInfo)) {
  3794. if (eFrameType == FRAME_TYPE_MMPDU) {
  3795. prWlanFrame = (P_WLAN_MAC_HEADER_T) prMsduInfo->prPacket;
  3796. u2TxFrameCtrl = (prWlanFrame->u2FrameCtrl) & MASK_FRAME_TYPE; /* Optimized for ARM */
  3797. if (((u2TxFrameCtrl == MAC_FRAME_DEAUTH)
  3798. && (prMsduInfo->pfTxDoneHandler == NULL))
  3799. || (u2TxFrameCtrl == MAC_FRAME_ACTION)) /* whsu */
  3800. return FRAME_ACTION_TX_PKT;
  3801. }
  3802. DBGLOG(QM, WARN, "Drop packets Action, eFrameType: %d (Bss Index %u).\n",
  3803. eFrameType, prBssInfo->ucNetTypeIndex);
  3804. TX_INC_CNT(&prAdapter->rTxCtrl, TX_INACTIVE_BSS_DROP);
  3805. return FRAME_ACTION_DROP_PKT;
  3806. }
  3807. /* TODO Handle disconnect issue */
  3808. /* P2P probe Request frame */
  3809. do {
  3810. if (eFrameType == FRAME_TYPE_MMPDU) {
  3811. prWlanFrame = (P_WLAN_MAC_HEADER_T) prMsduInfo->prPacket;
  3812. u2TxFrameCtrl = (prWlanFrame->u2FrameCtrl) & MASK_FRAME_TYPE; /* Optimized for ARM */
  3813. if (u2TxFrameCtrl == MAC_FRAME_BEACON) {
  3814. if (prBssInfo->fgIsNetAbsent)
  3815. return FRAME_ACTION_DROP_PKT;
  3816. } else if (u2TxFrameCtrl == MAC_FRAME_PROBE_RSP) {
  3817. if (prBssInfo->fgIsNetAbsent)
  3818. return FRAME_ACTION_DROP_PKT;
  3819. } else if (u2TxFrameCtrl == MAC_FRAME_DEAUTH) {
  3820. if (prBssInfo->fgIsNetAbsent)
  3821. break;
  3822. DBGLOG(P2P, LOUD, "Sending DEAUTH Frame\n");
  3823. return FRAME_ACTION_TX_PKT;
  3824. }
  3825. /* MMPDU with prStaRec && fgIsInUse not check fgIsNetActive */
  3826. else if (u2TxFrameCtrl == MAC_FRAME_ASSOC_REQ
  3827. || u2TxFrameCtrl == MAC_FRAME_AUTH
  3828. || u2TxFrameCtrl == MAC_FRAME_REASSOC_REQ
  3829. || u2TxFrameCtrl == MAC_FRAME_PROBE_REQ || u2TxFrameCtrl == MAC_FRAME_ACTION) {
  3830. if ((prStaRec) && (prStaRec->fgIsInPS)) {
  3831. if (nicTxGetResource(prAdapter, TC4_INDEX) >= QM_MGMT_QUUEUD_THRESHOLD)
  3832. return FRAME_ACTION_TX_PKT;
  3833. else
  3834. return FRAME_ACTION_QUEUE_PKT;
  3835. }
  3836. return FRAME_ACTION_TX_PKT;
  3837. }
  3838. if (!prStaRec)
  3839. return FRAME_ACTION_TX_PKT;
  3840. if (!prStaRec->fgIsInUse)
  3841. return FRAME_ACTION_DROP_PKT;
  3842. } /* FRAME_TYPE_MMPDU */
  3843. else if (eFrameType == FRAME_TYPE_802_1X) {
  3844. if (!prStaRec)
  3845. return FRAME_ACTION_TX_PKT;
  3846. if (!prStaRec->fgIsInUse)
  3847. return FRAME_ACTION_DROP_PKT;
  3848. if (prStaRec->fgIsInPS) {
  3849. if (nicTxGetResource(prAdapter, TC4_INDEX) >= QM_MGMT_QUUEUD_THRESHOLD)
  3850. return FRAME_ACTION_TX_PKT;
  3851. else
  3852. return FRAME_ACTION_QUEUE_PKT;
  3853. }
  3854. } /* FRAME_TYPE_802_1X */
  3855. else if ((!IS_BSS_ACTIVE(prBssInfo))
  3856. || (!prStaRec)
  3857. || (!prStaRec->fgIsInUse)) {
  3858. return FRAME_ACTION_DROP_PKT;
  3859. }
  3860. } while (0);
  3861. if (prBssInfo->fgIsNetAbsent) {
  3862. DBGLOG(QM, LOUD, "Queue packets (Absent %u).\n", prBssInfo->ucNetTypeIndex);
  3863. return FRAME_ACTION_QUEUE_PKT;
  3864. }
  3865. if (prStaRec && prStaRec->fgIsInPS) {
  3866. DBGLOG(QM, LOUD, "Queue packets (PS %u).\n", prStaRec->fgIsInPS);
  3867. return FRAME_ACTION_QUEUE_PKT;
  3868. }
  3869. switch (eFrameType) {
  3870. case FRAME_TYPE_802_1X:
  3871. if (!prStaRec->fgIsValid)
  3872. return FRAME_ACTION_QUEUE_PKT;
  3873. break;
  3874. case FRAME_TYPE_MMPDU:
  3875. break;
  3876. default:
  3877. ASSERT(0);
  3878. }
  3879. return FRAME_ACTION_TX_PKT;
  3880. }
  3881. /*----------------------------------------------------------------------------*/
  3882. /*!
  3883. * \brief Handle BSS change operation Event from the FW
  3884. *
  3885. * \param[in] prAdapter Adapter pointer
  3886. * \param[in] prEvent The event packet from the FW
  3887. *
  3888. * \return (none)
  3889. */
  3890. /*----------------------------------------------------------------------------*/
  3891. VOID qmHandleEventBssAbsencePresence(IN P_ADAPTER_T prAdapter, IN P_WIFI_EVENT_T prEvent)
  3892. {
  3893. P_EVENT_BSS_ABSENCE_PRESENCE_T prEventBssStatus;
  3894. P_BSS_INFO_T prBssInfo;
  3895. BOOLEAN fgIsNetAbsentOld;
  3896. prEventBssStatus = (P_EVENT_BSS_ABSENCE_PRESENCE_T) prEvent;
  3897. prBssInfo = &(prAdapter->rWifiVar.arBssInfo[prEventBssStatus->ucNetTypeIdx]);
  3898. fgIsNetAbsentOld = prBssInfo->fgIsNetAbsent;
  3899. prBssInfo->fgIsNetAbsent = prEventBssStatus->fgIsAbsent;
  3900. prBssInfo->ucBssFreeQuota = prEventBssStatus->ucBssFreeQuota;
  3901. /* DBGLOG(QM, TRACE, ("qmHandleEventBssAbsencePresence (ucNetTypeIdx=%d, fgIsAbsent=%d, FreeQuota=%d)\n", */
  3902. /* prEventBssStatus->ucNetTypeIdx, prBssInfo->fgIsNetAbsent, prBssInfo->ucBssFreeQuota)); */
  3903. DBGLOG(QM, INFO, "NAF=%d,%d,%d\n",
  3904. prEventBssStatus->ucNetTypeIdx, prBssInfo->fgIsNetAbsent, prBssInfo->ucBssFreeQuota);
  3905. if (!prBssInfo->fgIsNetAbsent) {
  3906. /* QM_DBG_CNT_27 */
  3907. QM_DBG_CNT_INC(&(prAdapter->rQM), QM_DBG_CNT_27);
  3908. } else {
  3909. /* QM_DBG_CNT_28 */
  3910. QM_DBG_CNT_INC(&(prAdapter->rQM), QM_DBG_CNT_28);
  3911. }
  3912. /* From Absent to Present */
  3913. if ((fgIsNetAbsentOld) && (!prBssInfo->fgIsNetAbsent))
  3914. kalSetEvent(prAdapter->prGlueInfo);
  3915. }
  3916. /*----------------------------------------------------------------------------*/
  3917. /*!
  3918. * \brief Handle STA change PS mode Event from the FW
  3919. *
  3920. * \param[in] prAdapter Adapter pointer
  3921. * \param[in] prEvent The event packet from the FW
  3922. *
  3923. * \return (none)
  3924. */
  3925. /*----------------------------------------------------------------------------*/
  3926. VOID qmHandleEventStaChangePsMode(IN P_ADAPTER_T prAdapter, IN P_WIFI_EVENT_T prEvent)
  3927. {
  3928. P_EVENT_STA_CHANGE_PS_MODE_T prEventStaChangePsMode;
  3929. P_STA_RECORD_T prStaRec;
  3930. BOOLEAN fgIsInPSOld;
  3931. /* DbgPrint("QM:Event -RxBa\n"); */
  3932. prEventStaChangePsMode = (P_EVENT_STA_CHANGE_PS_MODE_T) prEvent;
  3933. prStaRec = QM_GET_STA_REC_PTR_FROM_INDEX(prAdapter, prEventStaChangePsMode->ucStaRecIdx);
  3934. ASSERT(prStaRec);
  3935. if (prStaRec) {
  3936. fgIsInPSOld = prStaRec->fgIsInPS;
  3937. prStaRec->fgIsInPS = prEventStaChangePsMode->fgIsInPs;
  3938. qmUpdateFreeQuota(prAdapter,
  3939. prStaRec,
  3940. prEventStaChangePsMode->ucUpdateMode, prEventStaChangePsMode->ucFreeQuota, 0);
  3941. /* DBGLOG(QM, TRACE, ("qmHandleEventStaChangePsMode (ucStaRecIdx=%d, fgIsInPs=%d)\n", */
  3942. /* prEventStaChangePsMode->ucStaRecIdx, prStaRec->fgIsInPS)); */
  3943. DBGLOG(QM, TRACE, "PS=%d,%d\n", prEventStaChangePsMode->ucStaRecIdx, prStaRec->fgIsInPS);
  3944. /* From PS to Awake */
  3945. if ((fgIsInPSOld) && (!prStaRec->fgIsInPS))
  3946. kalSetEvent(prAdapter->prGlueInfo);
  3947. }
  3948. }
  3949. /*----------------------------------------------------------------------------*/
  3950. /*!
  3951. * \brief Update STA free quota Event from FW
  3952. *
  3953. * \param[in] prAdapter Adapter pointer
  3954. * \param[in] prEvent The event packet from the FW
  3955. *
  3956. * \return (none)
  3957. */
  3958. /*----------------------------------------------------------------------------*/
  3959. VOID qmHandleEventStaUpdateFreeQuota(IN P_ADAPTER_T prAdapter, IN P_WIFI_EVENT_T prEvent)
  3960. {
  3961. P_EVENT_STA_UPDATE_FREE_QUOTA_T prEventStaUpdateFreeQuota;
  3962. P_STA_RECORD_T prStaRec;
  3963. prEventStaUpdateFreeQuota = (P_EVENT_STA_UPDATE_FREE_QUOTA_T) prEvent;
  3964. prStaRec = QM_GET_STA_REC_PTR_FROM_INDEX(prAdapter, prEventStaUpdateFreeQuota->ucStaRecIdx);
  3965. ASSERT(prStaRec);
  3966. if (prStaRec) {
  3967. if (prStaRec->fgIsInPS) {
  3968. qmUpdateFreeQuota(prAdapter,
  3969. prStaRec,
  3970. prEventStaUpdateFreeQuota->ucUpdateMode,
  3971. prEventStaUpdateFreeQuota->ucFreeQuota,
  3972. prEventStaUpdateFreeQuota->aucReserved[0]);
  3973. kalSetEvent(prAdapter->prGlueInfo);
  3974. }
  3975. #if 0
  3976. DBGLOG(QM, TRACE,
  3977. "qmHandleEventStaUpdateFreeQuota (ucStaRecIdx=%d, ucUpdateMode=%d, ucFreeQuota=%d)\n",
  3978. prEventStaUpdateFreeQuota->ucStaRecIdx, prEventStaUpdateFreeQuota->ucUpdateMode,
  3979. prEventStaUpdateFreeQuota->ucFreeQuota);
  3980. #endif
  3981. DBGLOG(QM, TRACE, "UFQ=%d,%d,%d\n",
  3982. prEventStaUpdateFreeQuota->ucStaRecIdx,
  3983. prEventStaUpdateFreeQuota->ucUpdateMode, prEventStaUpdateFreeQuota->ucFreeQuota);
  3984. }
  3985. }
  3986. /*----------------------------------------------------------------------------*/
  3987. /*!
  3988. * \brief Update STA free quota
  3989. *
  3990. * \param[in] prStaRec the STA
  3991. * \param[in] ucUpdateMode the method to update free quota
  3992. * \param[in] ucFreeQuota the value for update
  3993. *
  3994. * \return (none)
  3995. */
  3996. /*----------------------------------------------------------------------------*/
  3997. VOID
  3998. qmUpdateFreeQuota(IN P_ADAPTER_T prAdapter,
  3999. IN P_STA_RECORD_T prStaRec, IN UINT_8 ucUpdateMode, IN UINT_8 ucFreeQuota, IN UINT_8 ucNumOfTxDone)
  4000. {
  4001. UINT_8 ucFreeQuotaForNonDelivery;
  4002. UINT_8 ucFreeQuotaForDelivery;
  4003. BOOLEAN flgIsUpdateForcedToDelivery;
  4004. ASSERT(prStaRec);
  4005. DBGLOG(QM, LOUD, "qmUpdateFreeQuota orig ucFreeQuota=%d Mode %u New %u\n",
  4006. prStaRec->ucFreeQuota, ucUpdateMode, ucFreeQuota);
  4007. if (!prStaRec->fgIsInPS)
  4008. return;
  4009. flgIsUpdateForcedToDelivery = FALSE;
  4010. if (ucNumOfTxDone > 0) {
  4011. /*
  4012. update free quota by
  4013. num of tx done + resident free quota (delivery + non-delivery)
  4014. */
  4015. UINT_8 ucAvailQuota;
  4016. ucAvailQuota = ucNumOfTxDone + prStaRec->ucFreeQuotaForDelivery + prStaRec->ucFreeQuotaForNonDelivery;
  4017. if (ucAvailQuota > ucFreeQuota) /* sanity check */
  4018. ucAvailQuota = ucFreeQuota;
  4019. /* update current free quota */
  4020. ucFreeQuota = ucAvailQuota;
  4021. /* check if the update is from last packet */
  4022. if (ucFreeQuota == (prStaRec->ucFreeQuota + 1)) {
  4023. /* just add the extra quota to delivery queue */
  4024. /*
  4025. EX:
  4026. 1. TDLS peer enters power save
  4027. 2. When the last 2 VI packets are tx done, we will receive 2 update events
  4028. 3. 1st update event: ucFreeQuota = 9
  4029. 4. We will correct new quota for delivey and non-delivery to 7:2
  4030. 5. 2rd update event: ucFreeQuota = 10
  4031. 6. We will re-correct new quota for delivery and non-delivery to 5:5
  4032. But non-delivery queue is not busy.
  4033. So in the case, we will have wrong decision, i.e. higher queue always quota 5
  4034. Solution: skip the 2rd update event and just add the extra quota to delivery.
  4035. */
  4036. flgIsUpdateForcedToDelivery = TRUE;
  4037. }
  4038. }
  4039. switch (ucUpdateMode) {
  4040. case FREE_QUOTA_UPDATE_MODE_INIT:
  4041. case FREE_QUOTA_UPDATE_MODE_OVERWRITE:
  4042. prStaRec->ucFreeQuota = ucFreeQuota;
  4043. break;
  4044. case FREE_QUOTA_UPDATE_MODE_INCREASE:
  4045. prStaRec->ucFreeQuota += ucFreeQuota;
  4046. break;
  4047. case FREE_QUOTA_UPDATE_MODE_DECREASE:
  4048. prStaRec->ucFreeQuota -= ucFreeQuota;
  4049. break;
  4050. default:
  4051. ASSERT(0);
  4052. }
  4053. DBGLOG(QM, LOUD, "qmUpdateFreeQuota new ucFreeQuota=%d)\n", prStaRec->ucFreeQuota);
  4054. ucFreeQuota = prStaRec->ucFreeQuota;
  4055. ucFreeQuotaForNonDelivery = 0;
  4056. ucFreeQuotaForDelivery = 0;
  4057. if (ucFreeQuota > 0) {
  4058. if (prStaRec->fgIsQoS && prStaRec->fgIsUapsdSupported
  4059. /* && prAdapter->rWifiVar.fgSupportQoS
  4060. && prAdapter->rWifiVar.fgSupportUAPSD */) {
  4061. /* XXX We should assign quota to aucFreeQuotaPerQueue[NUM_OF_PER_STA_TX_QUEUES] */
  4062. if (flgIsUpdateForcedToDelivery == FALSE) {
  4063. if (prStaRec->ucFreeQuotaForNonDelivery > 0 && prStaRec->ucFreeQuotaForDelivery > 0) {
  4064. ucFreeQuotaForNonDelivery = ucFreeQuota >> 1;
  4065. ucFreeQuotaForDelivery = ucFreeQuota - ucFreeQuotaForNonDelivery;
  4066. } else if (prStaRec->ucFreeQuotaForNonDelivery == 0
  4067. && prStaRec->ucFreeQuotaForDelivery == 0) {
  4068. ucFreeQuotaForNonDelivery = ucFreeQuota >> 1;
  4069. ucFreeQuotaForDelivery = ucFreeQuota - ucFreeQuotaForNonDelivery;
  4070. } else if (prStaRec->ucFreeQuotaForNonDelivery > 0) {
  4071. /* NonDelivery is not busy */
  4072. if (ucFreeQuota >= 3) {
  4073. ucFreeQuotaForNonDelivery = 2;
  4074. ucFreeQuotaForDelivery = ucFreeQuota - ucFreeQuotaForNonDelivery;
  4075. } else {
  4076. ucFreeQuotaForDelivery = ucFreeQuota;
  4077. ucFreeQuotaForNonDelivery = 0;
  4078. }
  4079. } else if (prStaRec->ucFreeQuotaForDelivery > 0) {
  4080. /* Delivery is not busy */
  4081. if (ucFreeQuota >= 3) {
  4082. ucFreeQuotaForDelivery = 2;
  4083. ucFreeQuotaForNonDelivery = ucFreeQuota - ucFreeQuotaForDelivery;
  4084. } else {
  4085. ucFreeQuotaForNonDelivery = ucFreeQuota;
  4086. ucFreeQuotaForDelivery = 0;
  4087. }
  4088. }
  4089. } else {
  4090. ucFreeQuotaForNonDelivery = 2;
  4091. ucFreeQuotaForDelivery = ucFreeQuota - ucFreeQuotaForNonDelivery;
  4092. }
  4093. } else {
  4094. /* no use ? */
  4095. /* !prStaRec->fgIsUapsdSupported */
  4096. ucFreeQuotaForNonDelivery = ucFreeQuota;
  4097. ucFreeQuotaForDelivery = 0;
  4098. }
  4099. }
  4100. /* ucFreeQuota > 0 */
  4101. prStaRec->ucFreeQuotaForDelivery = ucFreeQuotaForDelivery;
  4102. prStaRec->ucFreeQuotaForNonDelivery = ucFreeQuotaForNonDelivery;
  4103. #if (CFG_SUPPORT_TDLS_DBG == 1)
  4104. if (IS_TDLS_STA(prStaRec))
  4105. DBGLOG(QM, LOUD, "<tx> quota %d %d %d\n",
  4106. ucFreeQuota, ucFreeQuotaForDelivery, ucFreeQuotaForNonDelivery);
  4107. #endif
  4108. DBGLOG(QM, LOUD, "new QuotaForDelivery = %d QuotaForNonDelivery = %d\n",
  4109. prStaRec->ucFreeQuotaForDelivery, prStaRec->ucFreeQuotaForNonDelivery);
  4110. }
  4111. /*----------------------------------------------------------------------------*/
  4112. /*!
  4113. * \brief Return the reorder queued RX packets
  4114. *
  4115. * \param[in] (none)
  4116. *
  4117. * \return The number of queued RX packets
  4118. */
  4119. /*----------------------------------------------------------------------------*/
  4120. UINT_32 qmGetRxReorderQueuedBufferCount(IN P_ADAPTER_T prAdapter)
  4121. {
  4122. UINT_32 i, u4Total;
  4123. P_QUE_MGT_T prQM = &prAdapter->rQM;
  4124. u4Total = 0;
  4125. /* XXX The summation may impact the performance */
  4126. for (i = 0; i < CFG_NUM_OF_RX_BA_AGREEMENTS; i++) {
  4127. u4Total += prQM->arRxBaTable[i].rReOrderQue.u4NumElem;
  4128. #if DBG && 0
  4129. if (QUEUE_IS_EMPTY(&(prQM->arRxBaTable[i].rReOrderQue)))
  4130. ASSERT(prQM->arRxBaTable[i].rReOrderQue == 0);
  4131. #endif
  4132. }
  4133. ASSERT(u4Total <= (CFG_NUM_OF_QM_RX_PKT_NUM * 2));
  4134. return u4Total;
  4135. }
  4136. #if ARP_MONITER_ENABLE
  4137. VOID qmDetectArpNoResponse(P_ADAPTER_T prAdapter, P_MSDU_INFO_T prMsduInfo)
  4138. {
  4139. struct sk_buff *prSkb = NULL;
  4140. PUINT_8 pucData = NULL;
  4141. UINT_16 u2EtherType = 0;
  4142. int arpOpCode = 0;
  4143. prSkb = (struct sk_buff *)prMsduInfo->prPacket;
  4144. if (!prSkb || (prSkb->len <= ETHER_HEADER_LEN))
  4145. return;
  4146. pucData = prSkb->data;
  4147. if (!pucData)
  4148. return;
  4149. u2EtherType = (pucData[ETH_TYPE_LEN_OFFSET] << 8) | (pucData[ETH_TYPE_LEN_OFFSET + 1]);
  4150. if (u2EtherType != ETH_P_ARP || (apIp[0] | apIp[1] | apIp[2] | apIp[3]) == 0)
  4151. return;
  4152. if (kalMemCmp(apIp, &pucData[ETH_TYPE_LEN_OFFSET + 26], sizeof(apIp))) /* dest ip address */
  4153. return;
  4154. arpOpCode = (pucData[ETH_TYPE_LEN_OFFSET + 8] << 8) | (pucData[ETH_TYPE_LEN_OFFSET + 8 + 1]);
  4155. if (arpOpCode == ARP_PRO_REQ) {
  4156. arpMoniter++;
  4157. if (arpMoniter > 20) {
  4158. DBGLOG(INIT, WARN, "IOT Critical issue, arp no resp, check AP!\n");
  4159. aisBssBeaconTimeout(prAdapter);
  4160. arpMoniter = 0;
  4161. kalMemZero(apIp, sizeof(apIp));
  4162. }
  4163. }
  4164. }
  4165. VOID qmHandleRxArpPackets(P_ADAPTER_T prAdapter, P_SW_RFB_T prSwRfb)
  4166. {
  4167. PUINT_8 pucData = NULL;
  4168. UINT_16 u2EtherType = 0;
  4169. int arpOpCode = 0;
  4170. P_BSS_INFO_T prBssInfo = NULL;
  4171. if (prSwRfb->u2PacketLen <= ETHER_HEADER_LEN)
  4172. return;
  4173. pucData = (PUINT_8)prSwRfb->pvHeader;
  4174. if (!pucData)
  4175. return;
  4176. u2EtherType = (pucData[ETH_TYPE_LEN_OFFSET] << 8) | (pucData[ETH_TYPE_LEN_OFFSET + 1]);
  4177. if (u2EtherType != ETH_P_ARP)
  4178. return;
  4179. arpOpCode = (pucData[ETH_TYPE_LEN_OFFSET + 8] << 8) | (pucData[ETH_TYPE_LEN_OFFSET + 8 + 1]);
  4180. prBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX]);
  4181. if (arpOpCode == ARP_PRO_RSP) {
  4182. arpMoniter = 0;
  4183. if (prBssInfo && prBssInfo->prStaRecOfAP && prBssInfo->prStaRecOfAP->aucMacAddr) {
  4184. if (EQUAL_MAC_ADDR(&(pucData[ETH_TYPE_LEN_OFFSET + 10]), /* source hardware address */
  4185. prBssInfo->prStaRecOfAP->aucMacAddr)) {
  4186. kalMemCopy(apIp, &(pucData[ETH_TYPE_LEN_OFFSET + 16]), sizeof(apIp));
  4187. DBGLOG(INIT, TRACE, "get arp response from AP %d.%d.%d.%d\n",
  4188. apIp[0], apIp[1], apIp[2], apIp[3]);
  4189. }
  4190. }
  4191. }
  4192. }
  4193. VOID qmResetArpDetect(VOID)
  4194. {
  4195. arpMoniter = 0;
  4196. kalMemZero(apIp, sizeof(apIp));
  4197. }
  4198. #endif