| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832383338343835383638373838383938403841384238433844384538463847384838493850385138523853385438553856385738583859386038613862386338643865386638673868386938703871387238733874387538763877387838793880388138823883388438853886388738883889389038913892389338943895389638973898389939003901390239033904390539063907390839093910391139123913391439153916391739183919392039213922392339243925392639273928392939303931393239333934393539363937393839393940394139423943394439453946394739483949395039513952395339543955395639573958395939603961396239633964396539663967396839693970397139723973397439753976397739783979398039813982398339843985398639873988398939903991399239933994399539963997399839994000400140024003400440054006400740084009401040114012401340144015401640174018401940204021402240234024402540264027402840294030403140324033403440354036403740384039404040414042404340444045404640474048404940504051405240534054405540564057405840594060406140624063406440654066406740684069407040714072407340744075407640774078407940804081408240834084408540864087408840894090409140924093409440954096409740984099410041014102410341044105410641074108410941104111411241134114411541164117411841194120412141224123412441254126412741284129413041314132413341344135413641374138413941404141414241434144414541464147414841494150415141524153415441554156415741584159416041614162416341644165416641674168416941704171417241734174417541764177417841794180418141824183418441854186418741884189419041914192419341944195419641974198419942004201420242034204420542064207420842094210421142124213421442154216421742184219422042214222422342244225422642274228422942304231423242334234423542364237423842394240424142424243424442454246424742484249425042514252425342544255425642574258425942604261426242634264426542664267426842694270427142724273427442754276427742784279428042814282428342844285428642874288428942904291429242934294429542964297429842994300430143024303430443054306430743084309431043114312431343144315431643174318431943204321432243234324432543264327432843294330433143324333433443354336433743384339434043414342434343444345434643474348434943504351435243534354435543564357435843594360436143624363436443654366436743684369437043714372437343744375437643774378437943804381438243834384438543864387438843894390439143924393439443954396439743984399440044014402440344044405440644074408440944104411441244134414441544164417441844194420442144224423442444254426442744284429443044314432443344344435443644374438443944404441444244434444444544464447444844494450445144524453445444554456445744584459446044614462446344644465446644674468446944704471447244734474447544764477447844794480448144824483448444854486448744884489449044914492449344944495449644974498449945004501450245034504450545064507450845094510451145124513451445154516451745184519452045214522452345244525452645274528452945304531453245334534453545364537453845394540454145424543454445454546454745484549455045514552455345544555455645574558455945604561456245634564456545664567456845694570457145724573457445754576457745784579458045814582458345844585458645874588458945904591459245934594459545964597459845994600460146024603460446054606460746084609461046114612461346144615461646174618461946204621462246234624462546264627462846294630463146324633463446354636463746384639464046414642464346444645464646474648464946504651465246534654465546564657465846594660466146624663466446654666466746684669467046714672467346744675467646774678467946804681468246834684468546864687468846894690469146924693469446954696469746984699470047014702470347044705470647074708470947104711471247134714471547164717471847194720472147224723472447254726472747284729473047314732473347344735473647374738473947404741474247434744474547464747474847494750475147524753475447554756475747584759476047614762476347644765476647674768476947704771477247734774477547764777477847794780478147824783478447854786478747884789479047914792479347944795479647974798479948004801480248034804480548064807480848094810481148124813481448154816481748184819482048214822482348244825482648274828482948304831483248334834483548364837483848394840484148424843484448454846484748484849485048514852485348544855485648574858485948604861486248634864486548664867486848694870487148724873487448754876487748784879488048814882488348844885488648874888488948904891489248934894489548964897489848994900490149024903490449054906490749084909491049114912491349144915491649174918491949204921492249234924492549264927492849294930493149324933493449354936493749384939494049414942494349444945494649474948494949504951495249534954495549564957495849594960496149624963496449654966496749684969497049714972497349744975497649774978497949804981498249834984498549864987498849894990499149924993499449954996499749984999500050015002500350045005500650075008500950105011501250135014501550165017501850195020502150225023502450255026502750285029503050315032503350345035503650375038503950405041504250435044504550465047504850495050505150525053505450555056505750585059506050615062506350645065506650675068506950705071507250735074507550765077507850795080508150825083508450855086508750885089509050915092509350945095509650975098509951005101510251035104510551065107510851095110511151125113511451155116511751185119512051215122512351245125512651275128512951305131513251335134513551365137513851395140514151425143514451455146514751485149515051515152515351545155515651575158515951605161516251635164516551665167516851695170517151725173517451755176517751785179518051815182518351845185518651875188518951905191519251935194519551965197519851995200520152025203520452055206520752085209521052115212521352145215521652175218 |
- /*
- ** Id: //Department/DaVinci/BRANCHES/MT6620_WIFI_DRIVER_V2_3/nic/que_mgt.c#1
- */
- /*! \file "que_mgt.c"
- \brief TX/RX queues management
- The main tasks of queue management include TC-based HIF TX flow control,
- adaptive TC quota adjustment, HIF TX grant scheduling, Power-Save
- forwarding control, RX packet reordering, and RX BA agreement management.
- */
- /*
- ** Log: que_mgt.c
- **
- ** 04 11 2013 yuche.tsai
- ** [ALPS00542142] [Pre-SQC][6627][W]use wifi direct press cancel connect, phone all stop.
- ** Drop the probe response packet when absent.
- **
- ** 04 09 2013 yuche.tsai
- ** [ALPS00542142] [Pre-SQC][6627][W]use wifi direct press cancel connect, phone all stop.
- ** Fix CMD buffer short issue.
- **
- ** 04 09 2013 yuche.tsai
- ** [ALPS00542142] [Pre-SQC][6627][W]use wifi direct press cancel connect, phone all stop.
- ** Fix CMD buffer short issue.
- *
- * 03 02 2012 terry.wu
- * NULL
- * Sync CFG80211 modification from branch 2,2.
- *
- * 02 23 2012 eddie.chen
- * [WCXRP00001194] [MT6620][DRV/FW] follow admission control bit to change the enqueue rule
- * Change the enqueue policy when ACM = 1.
- *
- * 11 22 2011 yuche.tsai
- * NULL
- * Code refine, remove one #if 0 code.
- *
- * 11 19 2011 eddie.chen
- * [WCXRP00001096] [MT6620 Wi-Fi][Driver/FW] Enhance the log function (xlog)
- * Add xlog for tx
- *
- * 11 18 2011 yuche.tsai
- * NULL
- * CONFIG P2P support RSSI query, default turned off.
- *
- * 11 18 2011 eddie.chen
- * [WCXRP00001096] [MT6620 Wi-Fi][Driver/FW] Enhance the log function (xlog)
- * Fix xlog format to hex format
- *
- * 11 17 2011 tsaiyuan.hsu
- * [WCXRP00001115] [MT6620 Wi-Fi][DRV] avoid deactivating staRec when changing state 3 to 3.
- * avoid deactivating staRec when changing state from 3 to 3.
- *
- * 11 11 2011 tsaiyuan.hsu
- * [WCXRP00001083] [MT6620 Wi-Fi][DRV]] dump debug counter or frames when debugging is triggered
- * add debug msg for xlog.
- *
- * 11 11 2011 tsaiyuan.hsu
- * [WCXRP00001083] [MT6620 Wi-Fi][DRV]] dump debug counter or frames when debugging is triggered
- * add debug counters of bb and ar for xlog.
- *
- * 11 10 2011 eddie.chen
- * [WCXRP00001096] [MT6620 Wi-Fi][Driver/FW] Enhance the log function (xlog)
- * Use short name for xlog.
- *
- * 11 10 2011 eddie.chen
- * [WCXRP00001096] [MT6620 Wi-Fi][Driver/FW] Enhance the log function (xlog)
- * Modify the QM xlog level and remove LOG_FUNC.
- *
- * 11 10 2011 chinglan.wang
- * NULL
- * [WiFi WPS]Can't switch to new AP via WPS PBC when there existing a connection to another AP.
- *
- * 11 09 2011 chinglan.wang
- * NULL
- * [WiFi direct]Can't make P2P connect via PBC.
- *
- * 11 08 2011 eddie.chen
- * [WCXRP00001096] [MT6620 Wi-Fi][Driver/FW] Enhance the log function (xlog)
- * Add xlog function.
- *
- * 11 07 2011 tsaiyuan.hsu
- * [WCXRP00001083] [MT6620 Wi-Fi][DRV]] dump debug counter or frames when debugging is triggered
- * add debug counters and periodically dump counters for debugging.
- *
- * 11 01 2011 chinglan.wang
- * NULL
- * Modify the Wi-Fi method of the flush TX queue when disconnect the AP.
- * If disconnect the AP and flush all the data frame in the TX queue, WPS cannot do the 4-way handshake to connect to
- * the AP..
- *
- * 10 25 2011 wh.su
- * [WCXRP00001059] [MT6620 Wi-Fi][Driver][P2P] Fixed sometimes data (1x) will not indicate to upper layer due ba check
- * un-expect
- * let the Rx BA accept even the sta not valid.
- *
- * 09 28 2011 tsaiyuan.hsu
- * [WCXRP00000900] [MT5931 Wi-Fi] Improve balance of TX and RX
- * enlarge window size only by 4.
- *
- * 09 01 2011 tsaiyuan.hsu
- * [WCXRP00000900] [MT5931 Wi-Fi] Improve balance of TX and RX
- * set rx window size as twice buffer size.
- *
- * 08 23 2011 yuche.tsai
- * NULL
- * Fix multicast address list issue.
- *
- * 08 03 2011 tsaiyuan.hsu
- * [WCXRP00000900] [MT5931 Wi-Fi] Improve balance of TX and RX
- * force window size at least 16.
- *
- * 08 02 2011 yuche.tsai
- * [WCXRP00000896] [Volunteer Patch][WiFi Direct][Driver] GO with multiple client, TX deauth to a disconnecting device
- * issue.
- * Fix GO send deauth frame issue.
- *
- * 07 26 2011 eddie.chen
- * [WCXRP00000874] [MT5931][DRV] API for query the RX reorder queued packets counter
- * API for query the RX reorder queued packets counter.
- *
- * 07 07 2011 eddie.chen
- * [WCXRP00000834] [MT6620 Wi-Fi][DRV] Send 1x packet when peer STA is in PS.
- * Add setEvent when free quota is updated.
- *
- * 07 05 2011 eddie.chen
- * [WCXRP00000834] [MT6620 Wi-Fi][DRV] Send 1x packet when peer STA is in PS.
- * Send 1x when peer STA is in PS.
- *
- * 05 31 2011 eddie.chen
- * [WCXRP00000753] [MT5931 Wi-Fi][DRV] Adjust QM for MT5931
- * Fix the QM quota in MT5931.
- *
- * 05 11 2011 eddie.chen
- * [WCXRP00000709] [MT6620 Wi-Fi][Driver] Check free number before copying broadcast packet
- * Fix dest type when GO packet copying.
- *
- * 05 09 2011 yuche.tsai
- * [WCXRP00000712] [Volunteer Patch][MT6620][Driver] Sending deauth issue when Hot spot is disabled. (GO is dissolved)
- * Deauthentication frame is not bound to network active status.
- *
- * 05 09 2011 eddie.chen
- * [WCXRP00000709] [MT6620 Wi-Fi][Driver] Check free number before copying broadcast packet
- * Check free number before copying broadcast packet.
- *
- * 04 14 2011 eddie.chen
- * [WCXRP00000603] [MT6620 Wi-Fi][DRV] Fix Klocwork warning
- * Check the SW RFB free. Fix the compile warning..
- *
- * 04 12 2011 eddie.chen
- * [WCXRP00000617] [MT6620 Wi-Fi][DRV/FW] Fix for sigma
- * Fix the sta index in processing security frame
- * Simple flow control for TC4 to avoid mgt frames for PS STA to occupy the TC4
- * Add debug message.
- *
- * 04 11 2011 yuche.tsai
- * [WCXRP00000627] [Volunteer Patch][MT6620][Driver] Pending MMPUD of P2P Network may crash system issue.
- * Fix kernel panic issue when MMPDU of P2P is pending in driver.
- *
- * 04 08 2011 eddie.chen
- * [WCXRP00000617] [MT6620 Wi-Fi][DRV/FW] Fix for sigma
- * Fix for sigma
- *
- * 03 28 2011 eddie.chen
- * [WCXRP00000603] [MT6620 Wi-Fi][DRV] Fix Klocwork warning
- * Fix Klockwork warning.
- *
- * 03 28 2011 eddie.chen
- * [WCXRP00000602] [MT6620 Wi-Fi][DRV] Fix wmm parameters in beacon for BOW
- * Fix wmm parameters in beacon for BOW.
- *
- * 03 15 2011 eddie.chen
- * [WCXRP00000554] [MT6620 Wi-Fi][DRV] Add sw control debug counter
- * Add sw debug counter for QM.
- *
- * 02 23 2011 eddie.chen
- * [WCXRP00000463] [MT6620 Wi-Fi][FW/Driver][Hotspot] Cannot update WMM PS STA's partital bitmap
- * Fix parsing WMM INFO and bmp delivery bitmap definition.
- *
- * 02 17 2011 eddie.chen
- * [WCXRP00000458] [MT6620 Wi-Fi][Driver] BOW Concurrent - ProbeResp was exist in other channel
- * 1) Change GetFrameAction decision when BSS is absent.
- * 2) Check channel and resource in processing ProbeRequest
- *
- * 02 08 2011 eddie.chen
- * [WCXRP00000426] [MT6620 Wi-Fi][FW/Driver] Add STA aging timeout and defualtHwRatein AP mode
- * Add event STA agint timeout
- *
- * 01 27 2011 tsaiyuan.hsu
- * [WCXRP00000392] [MT6620 Wi-Fi][Driver] Add Roaming Support
- * add roaming fsm
- * 1. not support 11r, only use strength of signal to determine roaming.
- * 2. not enable CFG_SUPPORT_ROAMING until completion of full test.
- * 3. in 6620, adopt work-around to avoid sign extension problem of cck of hw
- * 4. assume that change of link quality in smooth way.
- *
- * 01 25 2011 yuche.tsai
- * [WCXRP00000388] [Volunteer Patch][MT6620][Driver/Fw] change Station Type in station record.
- * Change Station Type in Station Record, Modify MACRO definition for getting station type & network type index & Role.
- *
- * 01 24 2011 eddie.chen
- * [WCXRP00000385] [MT6620 Wi-Fi][DRV] Add destination decision for forwarding packets
- * Remove comments.
- *
- * 01 24 2011 eddie.chen
- * [WCXRP00000385] [MT6620 Wi-Fi][DRV] Add destination decision for forwarding packets
- * Add destination decision in AP mode.
- *
- * 01 14 2011 wh.su
- * [WCXRP00000099] [MT6620 Wi-Fi] [Driver] workaround to let the de-authentication can be send out[WCXRP00000326]
- * [MT6620][Wi-Fi][Driver] check in the binary format gl_sec.o.new instead of use change type!!!
- * Allow 802.1x can be send even the net is not active due the drver / fw sync issue.
- *
- * 01 13 2011 eddie.chen
- * [WCXRP00000322] Add WMM IE in beacon,
- Add per station flow control when STA is in PS
- * Fix typo and compile error.
- *
- * 01 12 2011 eddie.chen
- * [WCXRP00000322] Add WMM IE in beacon,
- Add per station flow control when STA is in PS
- * Fix WMM parameter condition for STA
- *
- * 01 12 2011 eddie.chen
- * [WCXRP00000322] Add WMM IE in beacon,
- Add per station flow control when STA is in PS
- * 1) Check Bss if support QoS before adding WMMIE
- * 2) Check if support prAdapter->rWifiVar QoS and uapsd in flow control
- *
- * 01 12 2011 george.huang
- * [WCXRP00000355] [MT6620 Wi-Fi] Set WMM-PS related setting with qualifying AP capability
- * Update MQM for WMM IE generation method
- *
- * 01 11 2011 eddie.chen
- * [WCXRP00000322] Add WMM IE in beacon,
- Add per station flow control when STA is in PS
- * Add per STA flow control when STA is in PS mode
- *
- * 01 03 2011 george.huang
- * [WCXRP00000152] [MT6620 Wi-Fi] AP mode power saving function
- * update prStaRec->fgIsUapsdSupported flag.
- *
- * 12 29 2010 eddie.chen
- * [WCXRP00000322] Add WMM IE in beacon,
- Add per station flow control when STA is in PS
- * Add WMM parameter for broadcast.
- *
- * 12 29 2010 eddie.chen
- * [WCXRP00000322] Add WMM IE in beacon,
- Add per station flow control when STA is in PS
- * 1) PS flow control event
- *
- * 2) WMM IE in beacon, assoc resp, probe resp
- *
- * 12 23 2010 george.huang
- * [WCXRP00000152] [MT6620 Wi-Fi] AP mode power saving function
- * 1. update WMM IE parsing, with ASSOC REQ handling
- * 2. extend U-APSD parameter passing from driver to FW
- *
- * 10 14 2010 wh.su
- * [WCXRP00000099] [MT6620 Wi-Fi] [Driver] workaround to let the de-authentication can be send out
- * use the #14 and modify the add code for check MMPDU.
- *
- * 10 14 2010 wh.su
- * [WCXRP00000099] [MT6620 Wi-Fi] [Driver] workaround to let the de-authentication can be send out
- * only MMPDU not check the netActive flag.
- *
- * 10 14 2010 wh.su
- * [WCXRP00000099] [MT6620 Wi-Fi] [Driver] workaround to let the de-authentication can be send out
- * not check the netActive flag for mgmt .
- *
- * 10 04 2010 cp.wu
- * [WCXRP00000077] [MT6620 Wi-Fi][Driver][FW] Eliminate use of ENUM_NETWORK_TYPE_T and replaced by
- * ENUM_NETWORK_TYPE_INDEX_T only
- * remove ENUM_NETWORK_TYPE_T definitions
- *
- * 09 21 2010 kevin.huang
- * [WCXRP00000052] [MT6620 Wi-Fi][Driver] Eliminate Linux Compile Warning
- * Eliminate Linux Compile Warning
- *
- * 08 30 2010 yarco.yang
- * NULL
- * Fixed klockwork error message
- *
- * 08 18 2010 yarco.yang
- * NULL
- * 1. Fixed HW checksum offload function not work under Linux issue.
- * 2. Add debug message.
- *
- * 08 10 2010 yarco.yang
- * NULL
- * Code refine
- *
- * 08 06 2010 yarco.yang
- * NULL
- * Update qmGetFrameAction() to allow P2P MGMT frame w/o STA_Record still can perform TX action
- *
- * 07 26 2010 cp.wu
- *
- * AIS-FSM FIX: return channel privilege even when the privilege is not granted yet
- * QM: qmGetFrameAction() won't assert when corresponding STA-REC index is not found
- *
- * 07 20 2010 yarco.yang
- *
- * Add to SetEvent when BSS is from Absent to Present or STA from PS to Awake
- *
- * 07 16 2010 yarco.yang
- *
- * 1. Support BSS Absence/Presence Event
- * 2. Support STA change PS mode Event
- * 3. Support BMC forwarding for AP mode.
- *
- * 07 14 2010 yarco.yang
- *
- * 1. Remove CFG_MQM_MIGRATION
- * 2. Add CMD_UPDATE_WMM_PARMS command
- *
- * 07 13 2010 yarco.yang
- *
- * [WPD00003849]
- * [MT6620 and MT5931] SW Migration, add qmGetFrameAction() API for CMD Queue Processing
- *
- * 07 09 2010 yarco.yang
- *
- * [MT6620 and MT5931] SW Migration: Add ADDBA support
- *
- * 07 08 2010 cp.wu
- *
- * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository.
- *
- * 07 08 2010 yarco.yang
- * [WPD00003837][MT6620]Data Path Refine
- * .
- *
- * 07 06 2010 yarco.yang
- * [WPD00003837][MT6620]Data Path Refine
- * Use fgInUse instead of fgIsValid for De-queue judgement
- *
- * 07 06 2010 yarco.yang
- * [WPD00003837][MT6620]Data Path Refine
- * For MMPDU, STA_REC will be decided by caller module
- *
- * 07 06 2010 yarco.yang
- * [WPD00003837][MT6620]Data Path Refine
- * Add MGMT Packet type for HIF_TX_HEADER
- *
- * 06 29 2010 yarco.yang
- * [WPD00003837][MT6620]Data Path Refine
- * replace g_rQM with Adpater->rQM
- *
- * 06 25 2010 cp.wu
- * [WPD00003833][MT6620 and MT5931] Driver migration
- * add API in que_mgt to retrieve sta-rec index for security frames.
- *
- * 06 23 2010 yarco.yang
- * [WPD00003837][MT6620]Data Path Refine
- * Merge g_arStaRec[] into adapter->arStaRec[]
- *
- * 06 21 2010 yarco.yang
- * [WPD00003837][MT6620]Data Path Refine
- * Support CFG_MQM_MIGRATION flag
- *
- * 06 11 2010 cp.wu
- * [WPD00003833][MT6620 and MT5931] Driver migration
- * 1) migrate assoc.c.
- * 2) add ucTxSeqNum for tracking frames which needs TX-DONE awareness
- * 3) add configuration options for CNM_MEM and RSN modules
- * 4) add data path for management frames
- * 5) eliminate rPacketInfo of MSDU_INFO_T
- *
- * 06 06 2010 kevin.huang
- * [WPD00003832][MT6620 5931] Create driver base
- * [MT6620 5931] Create driver base
- *
- * 03 31 2010 tehuang.liu
- * [WPD00001943]Create WiFi test driver framework on WinXP
- * Refined the debug msg
- *
- * 03 30 2010 cp.wu
- * [WPD00001943]Create WiFi test driver framework on WinXP
- * comment out one assertion which refer to undefined data member.
- *
- * 03 30 2010 tehuang.liu
- * [WPD00001943]Create WiFi test driver framework on WinXP
- * Enabled adaptive TC resource control
- *
- * 03 24 2010 jeffrey.chang
- * [WPD00003826]Initial import for Linux port
- * initial import for Linux port
- *
- * 03 17 2010 tehuang.liu
- * [WPD00001943]Create WiFi test driver framework on WinXP
- * Changed STA_REC index determination rules (DA=BMCAST always --> STA_REC_INDEX_BMCAST)
- *
- * 03 11 2010 tehuang.liu
- * [WPD00001943]Create WiFi test driver framework on WinXP
- * Fixed buffer leak when processing BAR frames
- *
- * 03 02 2010 tehuang.liu
- * [WPD00001943]Create WiFi test driver framework on WinXP
- * For TX packets with STA_REC index = STA_REC_INDEX_NOT_FOUND, use TC5
- *
- * 03 01 2010 tehuang.liu
- * [WPD00001943]Create WiFi test driver framework on WinXP
- * Fixed STA_REC index determination bug (fgIsValid shall be checked)
- *
- * 02 25 2010 tehuang.liu
- * [WPD00001943]Create WiFi test driver framework on WinXP
- * Refined function qmDetermineStaRecIndex() for BMCAST packets
- *
- * 02 25 2010 tehuang.liu
- * [WPD00001943]Create WiFi test driver framework on WinXP
- * Enabled multi-STA TX path with fairness
- *
- * 02 24 2010 tehuang.liu
- * [WPD00001943]Create WiFi test driver framework on WinXP
- * Enabled dynamically activating and deactivating STA_RECs
- *
- * 02 24 2010 tehuang.liu
- * [WPD00001943]Create WiFi test driver framework on WinXP
- * Added code for dynamic activating and deactivating STA_RECs.
- *
- * 01 13 2010 tehuang.liu
- * [WPD00001943]Create WiFi test driver framework on WinXP
- * Enabled the 802.1x path
- *
- * 01 13 2010 tehuang.liu
- * [WPD00001943]Create WiFi test driver framework on WinXP
- * Enabled the Burst_End Indication mechanism
- ** \main\maintrunk.MT6620WiFiDriver_Prj\13 2009-12-14 15:01:37 GMT MTK02468
- ** Fixed casting for qmAddRxBaEntry()
- ** \main\maintrunk.MT6620WiFiDriver_Prj\12 2009-12-10 16:51:03 GMT mtk02752
- ** remove SD1_SD3.. flag
- ** \main\maintrunk.MT6620WiFiDriver_Prj\11 2009-12-09 14:07:25 GMT MTK02468
- ** Added RX buffer reordering functions
- ** \main\maintrunk.MT6620WiFiDriver_Prj\10 2009-12-04 13:34:16 GMT MTK02468
- ** Modified Flush Queue function to let queues be reinitialized
- ** \main\maintrunk.MT6620WiFiDriver_Prj\9 2009-12-04 13:18:25 GMT MTK02468
- ** Added flushing per-Type queues code
- ** \main\maintrunk.MT6620WiFiDriver_Prj\8 2009-12-02 23:39:49 GMT MTK02468
- ** Added Debug msgs and fixed incorrect assert
- ** \main\maintrunk.MT6620WiFiDriver_Prj\4 2009-11-26 23:50:27 GMT MTK02468
- ** Bug fixing (qmDequeueTxPackets local variable initialization)
- ** \main\maintrunk.MT6620WiFiDriver_Prj\3 2009-11-26 09:39:25 GMT mtk02752
- ** correct and surpress PREfast warning
- ** \main\maintrunk.MT6620WiFiDriver_Prj\2 2009-11-23 22:10:55 GMT mtk02468
- ** Used SD1_SD3_DATAPATH_INTEGRATION
- ** \main\maintrunk.MT6620WiFiDriver_Prj\1 2009-11-23 22:02:30 GMT mtk02468
- ** Initial version
- **
- */
- /*******************************************************************************
- * C O M P I L E R F L A G S
- ********************************************************************************
- */
- /*******************************************************************************
- * E X T E R N A L R E F E R E N C E S
- ********************************************************************************
- */
- #include "precomp.h"
- /*******************************************************************************
- * C O N S T A N T S
- ********************************************************************************
- */
- /*******************************************************************************
- * D A T A T Y P E S
- ********************************************************************************
- */
- /*******************************************************************************
- * P U B L I C D A T A
- ********************************************************************************
- */
- OS_SYSTIME g_arMissTimeout[CFG_STA_REC_NUM][CFG_RX_MAX_BA_TID_NUM];
- /*******************************************************************************
- * P R I V A T E D A T A
- ********************************************************************************
- */
- #if ARP_MONITER_ENABLE
- static UINT_16 arpMoniter;
- static UINT_8 apIp[4];
- #endif
- /*******************************************************************************
- * M A C R O S
- ********************************************************************************
- */
- /*******************************************************************************
- * F U N C T I O N D E C L A R A T I O N S
- ********************************************************************************
- */
- static inline VOID qmDetermineStaRecIndex(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo);
- static inline VOID
- qmDequeueTxPacketsFromPerStaQueues(IN P_ADAPTER_T prAdapter,
- OUT P_QUE_T prQue,
- IN UINT_8 ucTC, IN UINT_8 ucCurrentAvailableQuota, IN UINT_8 ucTotalQuota);
- static inline VOID
- qmDequeueTxPacketsFromPerTypeQueues(IN P_ADAPTER_T prAdapter, OUT P_QUE_T prQue, IN UINT_8 ucTC, IN UINT_8 ucMaxNum);
- /*******************************************************************************
- * F U N C T I O N S
- ********************************************************************************
- */
- /*----------------------------------------------------------------------------*/
- /*!
- * \brief Init Queue Management for TX
- *
- * \param[in] (none)
- *
- * \return (none)
- */
- /*----------------------------------------------------------------------------*/
- VOID qmInit(IN P_ADAPTER_T prAdapter)
- {
- UINT_32 u4QueArrayIdx;
- UINT_32 i;
- P_QUE_MGT_T prQM = &prAdapter->rQM;
- /* DbgPrint("QM: Enter qmInit()\n"); */
- #if CFG_SUPPORT_QOS
- prAdapter->rWifiVar.fgSupportQoS = TRUE;
- #else
- prAdapter->rWifiVar.fgSupportQoS = FALSE;
- #endif
- #if CFG_SUPPORT_AMPDU_RX
- prAdapter->rWifiVar.fgSupportAmpduRx = TRUE;
- #else
- prAdapter->rWifiVar.fgSupportAmpduRx = FALSE;
- #endif
- #if CFG_SUPPORT_AMPDU_TX
- prAdapter->rWifiVar.fgSupportAmpduTx = TRUE;
- #else
- prAdapter->rWifiVar.fgSupportAmpduTx = FALSE;
- #endif
- #if CFG_SUPPORT_TSPEC
- prAdapter->rWifiVar.fgSupportTspec = TRUE;
- #else
- prAdapter->rWifiVar.fgSupportTspec = FALSE;
- #endif
- #if CFG_SUPPORT_UAPSD
- prAdapter->rWifiVar.fgSupportUAPSD = TRUE;
- #else
- prAdapter->rWifiVar.fgSupportUAPSD = FALSE;
- #endif
- #if CFG_SUPPORT_UL_PSMP
- prAdapter->rWifiVar.fgSupportULPSMP = TRUE;
- #else
- prAdapter->rWifiVar.fgSupportULPSMP = FALSE;
- #endif
- #if CFG_SUPPORT_RX_SGI
- prAdapter->rWifiVar.u8SupportRxSgi20 = 0;
- prAdapter->rWifiVar.u8SupportRxSgi40 = 0;
- #else
- prAdapter->rWifiVar.u8SupportRxSgi20 = 2;
- prAdapter->rWifiVar.u8SupportRxSgi40 = 2;
- #endif
- #if CFG_SUPPORT_RX_HT_GF
- prAdapter->rWifiVar.u8SupportRxGf = 0;
- #else
- prAdapter->rWifiVar.u8SupportRxGf = 2;
- #endif
- /* 4 <2> Initialize other TX queues (queues not in STA_RECs) */
- for (u4QueArrayIdx = 0; u4QueArrayIdx < NUM_OF_PER_TYPE_TX_QUEUES; u4QueArrayIdx++)
- QUEUE_INITIALIZE(&(prQM->arTxQueue[u4QueArrayIdx]));
- /* 4 <3> Initialize the RX BA table and RX queues */
- /* Initialize the RX Reordering Parameters and Queues */
- for (u4QueArrayIdx = 0; u4QueArrayIdx < CFG_NUM_OF_RX_BA_AGREEMENTS; u4QueArrayIdx++) {
- prQM->arRxBaTable[u4QueArrayIdx].fgIsValid = FALSE;
- QUEUE_INITIALIZE(&(prQM->arRxBaTable[u4QueArrayIdx].rReOrderQue));
- prQM->arRxBaTable[u4QueArrayIdx].u2WinStart = 0xFFFF;
- prQM->arRxBaTable[u4QueArrayIdx].u2WinEnd = 0xFFFF;
- prQM->arRxBaTable[u4QueArrayIdx].fgIsWaitingForPktWithSsn = FALSE;
- prQM->arRxBaTable[u4QueArrayIdx].fgHasBubble = FALSE;
- cnmTimerInitTimer(prAdapter,
- &(prQM->arRxBaTable[u4QueArrayIdx].rReorderBubbleTimer),
- (PFN_MGMT_TIMEOUT_FUNC) qmHandleReorderBubbleTimeout,
- (ULONG) (&prQM->arRxBaTable[u4QueArrayIdx]));
- }
- prQM->ucRxBaCount = 0;
- kalMemSet(&g_arMissTimeout, 0, sizeof(g_arMissTimeout));
- #if QM_ADAPTIVE_TC_RESOURCE_CTRL
- /* 4 <4> Initialize TC resource control variables */
- for (i = 0; i < TC_NUM; i++)
- prQM->au4AverageQueLen[i] = 0;
- prQM->u4TimeToAdjustTcResource = QM_INIT_TIME_TO_ADJUST_TC_RSC;
- prQM->u4TimeToUpdateQueLen = QM_INIT_TIME_TO_UPDATE_QUE_LEN;
- prQM->u4TxNumOfVi = 0;
- prQM->u4TxNumOfVo = 0;
- /* ASSERT(prQM->u4TimeToAdjust && prQM->u4TimeToUpdateQueLen); */
- /* 1 20 1 1 4 1 */
- prQM->au4CurrentTcResource[TC0_INDEX] = NIC_TX_BUFF_COUNT_TC0;
- prQM->au4CurrentTcResource[TC1_INDEX] = NIC_TX_BUFF_COUNT_TC1;
- prQM->au4CurrentTcResource[TC2_INDEX] = NIC_TX_BUFF_COUNT_TC2;
- prQM->au4CurrentTcResource[TC3_INDEX] = NIC_TX_BUFF_COUNT_TC3;
- prQM->au4CurrentTcResource[TC4_INDEX] = NIC_TX_BUFF_COUNT_TC4; /* Not adjustable (TX port 1) */
- prQM->au4CurrentTcResource[TC5_INDEX] = NIC_TX_BUFF_COUNT_TC5;
- DBGLOG(QM, TRACE, "QM: NIC_TX_BUFF_COUNT_TC0 = %d\n", NIC_TX_BUFF_COUNT_TC0);
- DBGLOG(QM, TRACE, "QM: NIC_TX_BUFF_COUNT_TC1 = %d\n", NIC_TX_BUFF_COUNT_TC1);
- DBGLOG(QM, TRACE, "QM: NIC_TX_BUFF_COUNT_TC2 = %d\n", NIC_TX_BUFF_COUNT_TC2);
- DBGLOG(QM, TRACE, "QM: NIC_TX_BUFF_COUNT_TC3 = %d\n", NIC_TX_BUFF_COUNT_TC3);
- DBGLOG(QM, TRACE, "QM: NIC_TX_BUFF_COUNT_TC4 = %d\n", NIC_TX_BUFF_COUNT_TC4);
- DBGLOG(QM, TRACE, "QM: NIC_TX_BUFF_COUNT_TC5 = %d\n", NIC_TX_BUFF_COUNT_TC5);
- /* 1 1 1 1 2 1 */
- prQM->au4MinReservedTcResource[TC0_INDEX] = QM_MIN_RESERVED_TC0_RESOURCE;
- prQM->au4MinReservedTcResource[TC1_INDEX] = QM_MIN_RESERVED_TC1_RESOURCE;
- prQM->au4MinReservedTcResource[TC2_INDEX] = QM_MIN_RESERVED_TC2_RESOURCE;
- prQM->au4MinReservedTcResource[TC3_INDEX] = QM_MIN_RESERVED_TC3_RESOURCE;
- prQM->au4MinReservedTcResource[TC4_INDEX] = QM_MIN_RESERVED_TC4_RESOURCE; /* Not adjustable (TX port 1) */
- prQM->au4MinReservedTcResource[TC5_INDEX] = QM_MIN_RESERVED_TC5_RESOURCE;
- /* 4 4 6 6 2 4 */
- prQM->au4GuaranteedTcResource[TC0_INDEX] = QM_GUARANTEED_TC0_RESOURCE;
- prQM->au4GuaranteedTcResource[TC1_INDEX] = QM_GUARANTEED_TC1_RESOURCE;
- prQM->au4GuaranteedTcResource[TC2_INDEX] = QM_GUARANTEED_TC2_RESOURCE;
- prQM->au4GuaranteedTcResource[TC3_INDEX] = QM_GUARANTEED_TC3_RESOURCE;
- prQM->au4GuaranteedTcResource[TC4_INDEX] = QM_GUARANTEED_TC4_RESOURCE;
- prQM->au4GuaranteedTcResource[TC5_INDEX] = QM_GUARANTEED_TC5_RESOURCE;
- prQM->fgTcResourcePostAnnealing = FALSE;
- ASSERT(QM_INITIAL_RESIDUAL_TC_RESOURCE < 64);
- #endif
- #if QM_TEST_MODE
- prQM->u4PktCount = 0;
- #if QM_TEST_FAIR_FORWARDING
- prQM->u4CurrentStaRecIndexToEnqueue = 0;
- {
- UINT_8 aucMacAddr[MAC_ADDR_LEN];
- P_STA_RECORD_T prStaRec;
- /* Irrelevant in case this STA is an AIS AP (see qmDetermineStaRecIndex()) */
- aucMacAddr[0] = 0x11;
- aucMacAddr[1] = 0x22;
- aucMacAddr[2] = 0xAA;
- aucMacAddr[3] = 0xBB;
- aucMacAddr[4] = 0xCC;
- aucMacAddr[5] = 0xDD;
- prStaRec = &prAdapter->arStaRec[1];
- ASSERT(prStaRec);
- prStaRec->fgIsValid = TRUE;
- prStaRec->fgIsQoS = TRUE;
- prStaRec->fgIsInPS = FALSE;
- prStaRec->ucPsSessionID = 0xFF;
- prStaRec->ucNetTypeIndex = NETWORK_TYPE_AIS_INDEX;
- prStaRec->fgIsAp = TRUE;
- COPY_MAC_ADDR((prStaRec)->aucMacAddr, aucMacAddr);
- }
- #endif
- #endif
- #if QM_FORWARDING_FAIRNESS
- {
- UINT_32 i;
- for (i = 0; i < NUM_OF_PER_STA_TX_QUEUES; i++) {
- prQM->au4ForwardCount[i] = 0;
- prQM->au4HeadStaRecIndex[i] = 0;
- }
- }
- #endif
- #if QM_TC_RESOURCE_EMPTY_COUNTER
- kalMemZero(prQM->au4QmTcResourceEmptyCounter, sizeof(prQM->au4QmTcResourceEmptyCounter));
- #endif
- }
- #if QM_TEST_MODE
- VOID qmTestCases(IN P_ADAPTER_T prAdapter)
- {
- P_QUE_MGT_T prQM = &prAdapter->rQM;
- DbgPrint("QM: ** TEST MODE **\n");
- if (QM_TEST_STA_REC_DETERMINATION) {
- if (prAdapter->arStaRec[0].fgIsValid) {
- prAdapter->arStaRec[0].fgIsValid = FALSE;
- DbgPrint("QM: (Test) Deactivate STA_REC[0]\n");
- } else {
- prAdapter->arStaRec[0].fgIsValid = TRUE;
- DbgPrint("QM: (Test) Activate STA_REC[0]\n");
- }
- }
- if (QM_TEST_STA_REC_DEACTIVATION) {
- /* Note that QM_STA_REC_HARD_CODING shall be set to 1 for this test */
- if (prAdapter->arStaRec[0].fgIsValid) {
- DbgPrint("QM: (Test) Deactivate STA_REC[0]\n");
- qmDeactivateStaRec(prAdapter, 0);
- } else {
- UINT_8 aucMacAddr[MAC_ADDR_LEN];
- /* Irrelevant in case this STA is an AIS AP (see qmDetermineStaRecIndex()) */
- aucMacAddr[0] = 0x11;
- aucMacAddr[1] = 0x22;
- aucMacAddr[2] = 0xAA;
- aucMacAddr[3] = 0xBB;
- aucMacAddr[4] = 0xCC;
- aucMacAddr[5] = 0xDD;
- DbgPrint("QM: (Test) Activate STA_REC[0]\n");
- qmActivateStaRec(prAdapter, /* Adapter pointer */
- 0, /* STA_REC index from FW */
- TRUE, /* fgIsQoS */
- NETWORK_TYPE_AIS_INDEX, /* Network type */
- TRUE, /* fgIsAp */
- aucMacAddr /* MAC address */
- );
- }
- }
- if (QM_TEST_FAIR_FORWARDING) {
- if (prAdapter->arStaRec[1].fgIsValid) {
- prQM->u4CurrentStaRecIndexToEnqueue++;
- prQM->u4CurrentStaRecIndexToEnqueue %= 2;
- DbgPrint("QM: (Test) Switch to STA_REC[%u]\n", prQM->u4CurrentStaRecIndexToEnqueue);
- }
- }
- }
- #endif
- /*----------------------------------------------------------------------------*/
- /*!
- * \brief Activate a STA_REC
- *
- * \param[in] prAdapter Pointer to the Adapter instance
- * \param[in] u4StaRecIdx The index of the STA_REC
- * \param[in] fgIsQoS Set to TRUE if this is a QoS STA
- * \param[in] pucMacAddr The MAC address of the STA
- *
- * \return (none)
- */
- /*----------------------------------------------------------------------------*/
- VOID qmActivateStaRec(IN P_ADAPTER_T prAdapter, IN P_STA_RECORD_T prStaRec)
- {
- /* 4 <1> Deactivate first */
- ASSERT(prStaRec);
- if (prStaRec->fgIsValid) { /* The STA_REC has been activated */
- DBGLOG(QM, WARN, "QM: (WARNING) Activating a STA_REC which has been activated\n");
- DBGLOG(QM, WARN, "QM: (WARNING) Deactivating a STA_REC before re-activating\n");
- /* To flush TX/RX queues and del RX BA agreements */
- qmDeactivateStaRec(prAdapter, prStaRec->ucIndex);
- }
- /* 4 <2> Activate the STA_REC */
- /* Init the STA_REC */
- prStaRec->fgIsValid = TRUE;
- prStaRec->fgIsInPS = FALSE;
- prStaRec->ucPsSessionID = 0xFF;
- prStaRec->fgIsAp = (IS_AP_STA(prStaRec)) ? TRUE : FALSE;
- /* Done in qmInit() or qmDeactivateStaRec() */
- #if 0
- /* At the beginning, no RX BA agreements have been established */
- for (i = 0; i < CFG_RX_MAX_BA_TID_NUM; i++)
- (prStaRec->aprRxReorderParamRefTbl)[i] = NULL;
- #endif
- DBGLOG(QM, TRACE, "QM: +STA[%u]\n", (UINT_32) prStaRec->ucIndex);
- }
- /*----------------------------------------------------------------------------*/
- /*!
- * \brief Deactivate a STA_REC
- *
- * \param[in] prAdapter Pointer to the Adapter instance
- * \param[in] u4StaRecIdx The index of the STA_REC
- *
- * \return (none)
- */
- /*----------------------------------------------------------------------------*/
- VOID qmDeactivateStaRec(IN P_ADAPTER_T prAdapter, IN UINT_32 u4StaRecIdx)
- {
- P_STA_RECORD_T prStaRec;
- UINT_32 i;
- P_MSDU_INFO_T prFlushedTxPacketList = NULL;
- ASSERT(u4StaRecIdx < CFG_NUM_OF_STA_RECORD);
- prStaRec = &prAdapter->arStaRec[u4StaRecIdx];
- ASSERT(prStaRec);
- /* 4<1> Flush TX queues */
- prFlushedTxPacketList = qmFlushStaTxQueues(prAdapter, u4StaRecIdx);
- if (prFlushedTxPacketList)
- wlanProcessQueuedMsduInfo(prAdapter, prFlushedTxPacketList);
- /* 4 <2> Flush RX queues and delete RX BA agreements */
- for (i = 0; i < CFG_RX_MAX_BA_TID_NUM; i++) {
- /* Delete the RX BA entry with TID = i */
- qmDelRxBaEntry(prAdapter, (UINT_8) u4StaRecIdx, (UINT_8) i, FALSE);
- }
- /* 4 <3> Deactivate the STA_REC */
- prStaRec->fgIsValid = FALSE;
- prStaRec->fgIsInPS = FALSE;
- /* To reduce printk for IOT sta to connect all the time, */
- /* DBGLOG(QM, INFO, ("QM: -STA[%ld]\n", u4StaRecIdx)); */
- }
- /*----------------------------------------------------------------------------*/
- /*!
- * \brief Deactivate a STA_REC
- *
- * \param[in] prAdapter Pointer to the Adapter instance
- * \param[in] u4StaRecIdx The index of the network
- *
- * \return (none)
- */
- /*----------------------------------------------------------------------------*/
- VOID qmFreeAllByNetType(IN P_ADAPTER_T prAdapter, IN ENUM_NETWORK_TYPE_INDEX_T eNetworkTypeIdx)
- {
- P_QUE_MGT_T prQM;
- P_QUE_T prQue;
- QUE_T rNeedToFreeQue;
- QUE_T rTempQue;
- P_QUE_T prNeedToFreeQue;
- P_QUE_T prTempQue;
- P_MSDU_INFO_T prMsduInfo;
- prQM = &prAdapter->rQM;
- prQue = &prQM->arTxQueue[TX_QUEUE_INDEX_BMCAST];
- QUEUE_INITIALIZE(&rNeedToFreeQue);
- QUEUE_INITIALIZE(&rTempQue);
- prNeedToFreeQue = &rNeedToFreeQue;
- prTempQue = &rTempQue;
- QUEUE_MOVE_ALL(prTempQue, prQue);
- QUEUE_REMOVE_HEAD(prTempQue, prMsduInfo, P_MSDU_INFO_T);
- while (prMsduInfo) {
- if (prMsduInfo->ucNetworkType == eNetworkTypeIdx) {
- /* QUEUE_INSERT_TAIL */
- QUEUE_INSERT_TAIL(prNeedToFreeQue, (P_QUE_ENTRY_T) prMsduInfo);
- } else {
- /* QUEUE_INSERT_TAIL */
- QUEUE_INSERT_TAIL(prQue, (P_QUE_ENTRY_T) prMsduInfo);
- }
- QUEUE_REMOVE_HEAD(prTempQue, prMsduInfo, P_MSDU_INFO_T);
- }
- if (QUEUE_IS_NOT_EMPTY(prNeedToFreeQue))
- wlanProcessQueuedMsduInfo(prAdapter, (P_MSDU_INFO_T) QUEUE_GET_HEAD(prNeedToFreeQue));
- }
- /*----------------------------------------------------------------------------*/
- /*!
- * \brief Flush all TX queues
- *
- * \param[in] (none)
- *
- * \return The flushed packets (in a list of MSDU_INFOs)
- */
- /*----------------------------------------------------------------------------*/
- P_MSDU_INFO_T qmFlushTxQueues(IN P_ADAPTER_T prAdapter)
- {
- UINT_8 ucStaArrayIdx;
- UINT_8 ucQueArrayIdx;
- P_MSDU_INFO_T prMsduInfoListHead;
- P_MSDU_INFO_T prMsduInfoListTail;
- P_QUE_MGT_T prQM = &prAdapter->rQM;
- DBGLOG(QM, TRACE, "QM: Enter qmFlushTxQueues()\n");
- prMsduInfoListHead = NULL;
- prMsduInfoListTail = NULL;
- /* Concatenate all MSDU_INFOs in per-STA queues */
- for (ucStaArrayIdx = 0; ucStaArrayIdx < CFG_NUM_OF_STA_RECORD; ucStaArrayIdx++) {
- /* Always check each STA_REC when flushing packets no matter it is inactive or active */
- #if 0
- if (!prAdapter->arStaRec[ucStaArrayIdx].fgIsValid)
- continue; /* Continue to check the next STA_REC */
- #endif
- for (ucQueArrayIdx = 0; ucQueArrayIdx < NUM_OF_PER_STA_TX_QUEUES; ucQueArrayIdx++) {
- if (QUEUE_IS_EMPTY(&(prAdapter->arStaRec[ucStaArrayIdx].arTxQueue[ucQueArrayIdx])))
- continue; /* Continue to check the next TX queue of the same STA */
- if (!prMsduInfoListHead) {
- /* The first MSDU_INFO is found */
- prMsduInfoListHead = (P_MSDU_INFO_T)
- QUEUE_GET_HEAD(&prAdapter->arStaRec[ucStaArrayIdx].arTxQueue[ucQueArrayIdx]);
- prMsduInfoListTail = (P_MSDU_INFO_T)
- QUEUE_GET_TAIL(&prAdapter->arStaRec[ucStaArrayIdx].arTxQueue[ucQueArrayIdx]);
- } else {
- /* Concatenate the MSDU_INFO list with the existing list */
- QM_TX_SET_NEXT_MSDU_INFO(prMsduInfoListTail,
- QUEUE_GET_HEAD(&prAdapter->
- arStaRec[ucStaArrayIdx].arTxQueue
- [ucQueArrayIdx]));
- prMsduInfoListTail = (P_MSDU_INFO_T)
- QUEUE_GET_TAIL(&prAdapter->arStaRec[ucStaArrayIdx].arTxQueue[ucQueArrayIdx]);
- }
- QUEUE_INITIALIZE(&prAdapter->arStaRec[ucStaArrayIdx].arTxQueue[ucQueArrayIdx]);
- }
- }
- /* Flush per-Type queues */
- for (ucQueArrayIdx = 0; ucQueArrayIdx < NUM_OF_PER_TYPE_TX_QUEUES; ucQueArrayIdx++) {
- if (QUEUE_IS_EMPTY(&(prQM->arTxQueue[ucQueArrayIdx])))
- continue; /* Continue to check the next TX queue of the same STA */
- if (!prMsduInfoListHead) {
- /* The first MSDU_INFO is found */
- prMsduInfoListHead = (P_MSDU_INFO_T)
- QUEUE_GET_HEAD(&prQM->arTxQueue[ucQueArrayIdx]);
- prMsduInfoListTail = (P_MSDU_INFO_T)
- QUEUE_GET_TAIL(&prQM->arTxQueue[ucQueArrayIdx]);
- } else {
- /* Concatenate the MSDU_INFO list with the existing list */
- QM_TX_SET_NEXT_MSDU_INFO(prMsduInfoListTail, QUEUE_GET_HEAD(&prQM->arTxQueue[ucQueArrayIdx]));
- prMsduInfoListTail = (P_MSDU_INFO_T)
- QUEUE_GET_TAIL(&prQM->arTxQueue[ucQueArrayIdx]);
- }
- QUEUE_INITIALIZE(&prQM->arTxQueue[ucQueArrayIdx]);
- }
- if (prMsduInfoListTail) {
- /* Terminate the MSDU_INFO list with a NULL pointer */
- QM_TX_SET_NEXT_MSDU_INFO(prMsduInfoListTail, NULL);
- }
- return prMsduInfoListHead;
- }
- /*----------------------------------------------------------------------------*/
- /*!
- * \brief Flush TX packets for a particular STA
- *
- * \param[in] u4StaRecIdx STA_REC index
- *
- * \return The flushed packets (in a list of MSDU_INFOs)
- */
- /*----------------------------------------------------------------------------*/
- P_MSDU_INFO_T qmFlushStaTxQueues(IN P_ADAPTER_T prAdapter, IN UINT_32 u4StaRecIdx)
- {
- UINT_8 ucQueArrayIdx;
- P_MSDU_INFO_T prMsduInfoListHead;
- P_MSDU_INFO_T prMsduInfoListTail;
- P_STA_RECORD_T prStaRec;
- /* To reduce printk for IOT sta to connect all the time, */
- /* DBGLOG(QM, TRACE, ("QM: Enter qmFlushStaTxQueues(%ld)\n", u4StaRecIdx)); */
- ASSERT(u4StaRecIdx < CFG_NUM_OF_STA_RECORD);
- prMsduInfoListHead = NULL;
- prMsduInfoListTail = NULL;
- prStaRec = &prAdapter->arStaRec[u4StaRecIdx];
- ASSERT(prStaRec);
- /* No matter whether this is an activated STA_REC, do flush */
- #if 0
- if (!prStaRec->fgIsValid)
- return NULL;
- #endif
- /* Concatenate all MSDU_INFOs in TX queues of this STA_REC */
- for (ucQueArrayIdx = 0; ucQueArrayIdx < NUM_OF_PER_STA_TX_QUEUES; ucQueArrayIdx++) {
- if (QUEUE_IS_EMPTY(&(prStaRec->arTxQueue[ucQueArrayIdx])))
- continue;
- if (!prMsduInfoListHead) {
- /* The first MSDU_INFO is found */
- prMsduInfoListHead = (P_MSDU_INFO_T)
- QUEUE_GET_HEAD(&prStaRec->arTxQueue[ucQueArrayIdx]);
- prMsduInfoListTail = (P_MSDU_INFO_T)
- QUEUE_GET_TAIL(&prStaRec->arTxQueue[ucQueArrayIdx]);
- } else {
- /* Concatenate the MSDU_INFO list with the existing list */
- QM_TX_SET_NEXT_MSDU_INFO(prMsduInfoListTail,
- QUEUE_GET_HEAD(&prStaRec->arTxQueue[ucQueArrayIdx]));
- prMsduInfoListTail = (P_MSDU_INFO_T) QUEUE_GET_TAIL(&prStaRec->arTxQueue[ucQueArrayIdx]);
- }
- QUEUE_INITIALIZE(&prStaRec->arTxQueue[ucQueArrayIdx]);
- }
- #if 0
- if (prMsduInfoListTail) {
- /* Terminate the MSDU_INFO list with a NULL pointer */
- QM_TX_SET_NEXT_MSDU_INFO(prMsduInfoListTail, nicGetPendingStaMMPDU(prAdapter, (UINT_8) u4StaRecIdx));
- } else {
- prMsduInfoListHead = nicGetPendingStaMMPDU(prAdapter, (UINT_8) u4StaRecIdx);
- }
- #endif
- return prMsduInfoListHead;
- }
- /*----------------------------------------------------------------------------*/
- /*!
- * \brief Flush RX packets
- *
- * \param[in] (none)
- *
- * \return The flushed packets (in a list of SW_RFBs)
- */
- /*----------------------------------------------------------------------------*/
- P_SW_RFB_T qmFlushRxQueues(IN P_ADAPTER_T prAdapter)
- {
- UINT_32 i;
- P_SW_RFB_T prSwRfbListHead;
- P_SW_RFB_T prSwRfbListTail;
- P_QUE_MGT_T prQM = &prAdapter->rQM;
- prSwRfbListHead = prSwRfbListTail = NULL;
- DBGLOG(QM, TRACE, "QM: Enter qmFlushRxQueues()\n");
- for (i = 0; i < CFG_NUM_OF_RX_BA_AGREEMENTS; i++) {
- if (QUEUE_IS_NOT_EMPTY(&(prQM->arRxBaTable[i].rReOrderQue))) {
- if (!prSwRfbListHead) {
- /* The first MSDU_INFO is found */
- prSwRfbListHead = (P_SW_RFB_T)
- QUEUE_GET_HEAD(&(prQM->arRxBaTable[i].rReOrderQue));
- prSwRfbListTail = (P_SW_RFB_T)
- QUEUE_GET_TAIL(&(prQM->arRxBaTable[i].rReOrderQue));
- } else {
- /* Concatenate the MSDU_INFO list with the existing list */
- QM_TX_SET_NEXT_MSDU_INFO(prSwRfbListTail,
- QUEUE_GET_HEAD(&(prQM->arRxBaTable[i].rReOrderQue)));
- prSwRfbListTail = (P_SW_RFB_T)
- QUEUE_GET_TAIL(&(prQM->arRxBaTable[i].rReOrderQue));
- }
- QUEUE_INITIALIZE(&(prQM->arRxBaTable[i].rReOrderQue));
- } else {
- continue;
- }
- }
- if (prSwRfbListTail) {
- /* Terminate the MSDU_INFO list with a NULL pointer */
- QM_TX_SET_NEXT_SW_RFB(prSwRfbListTail, NULL);
- }
- return prSwRfbListHead;
- }
- /*----------------------------------------------------------------------------*/
- /*!
- * \brief Flush RX packets with respect to a particular STA
- *
- * \param[in] u4StaRecIdx STA_REC index
- * \param[in] u4Tid TID
- *
- * \return The flushed packets (in a list of SW_RFBs)
- */
- /*----------------------------------------------------------------------------*/
- P_SW_RFB_T qmFlushStaRxQueue(IN P_ADAPTER_T prAdapter, IN UINT_32 u4StaRecIdx, IN UINT_32 u4Tid)
- {
- /* UINT_32 i; */
- P_SW_RFB_T prSwRfbListHead;
- P_SW_RFB_T prSwRfbListTail;
- P_RX_BA_ENTRY_T prReorderQueParm;
- P_STA_RECORD_T prStaRec;
- DBGLOG(QM, TRACE, "QM: Enter qmFlushStaRxQueues(%u)\n", u4StaRecIdx);
- prSwRfbListHead = prSwRfbListTail = NULL;
- prStaRec = &prAdapter->arStaRec[u4StaRecIdx];
- ASSERT(prStaRec);
- /* No matter whether this is an activated STA_REC, do flush */
- #if 0
- if (!prStaRec->fgIsValid)
- return NULL;
- #endif
- /* Obtain the RX BA Entry pointer */
- prReorderQueParm = ((prStaRec->aprRxReorderParamRefTbl)[u4Tid]);
- /* Note: For each queued packet, prCurrSwRfb->eDst equals RX_PKT_DESTINATION_HOST */
- if (prReorderQueParm) {
- if (QUEUE_IS_NOT_EMPTY(&(prReorderQueParm->rReOrderQue))) {
- prSwRfbListHead = (P_SW_RFB_T)
- QUEUE_GET_HEAD(&(prReorderQueParm->rReOrderQue));
- prSwRfbListTail = (P_SW_RFB_T)
- QUEUE_GET_TAIL(&(prReorderQueParm->rReOrderQue));
- QUEUE_INITIALIZE(&(prReorderQueParm->rReOrderQue));
- }
- }
- if (prSwRfbListTail) {
- /* Terminate the MSDU_INFO list with a NULL pointer */
- QM_TX_SET_NEXT_SW_RFB(prSwRfbListTail, NULL);
- }
- return prSwRfbListHead;
- }
- /*----------------------------------------------------------------------------*/
- /*!
- * \brief Enqueue TX packets
- *
- * \param[in] prMsduInfoListHead Pointer to the list of TX packets
- *
- * \return The freed packets, which are not enqueued
- */
- /*----------------------------------------------------------------------------*/
- P_MSDU_INFO_T qmEnqueueTxPackets(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfoListHead)
- {
- P_MSDU_INFO_T prMsduInfoReleaseList;
- P_MSDU_INFO_T prCurrentMsduInfo;
- P_MSDU_INFO_T prNextMsduInfo;
- P_STA_RECORD_T prStaRec;
- QUE_T rNotEnqueuedQue;
- P_QUE_T prTxQue = &rNotEnqueuedQue;
- UINT_8 ucPacketType;
- UINT_8 ucTC;
- P_QUE_MGT_T prQM = &prAdapter->rQM;
- UINT_8 aucNextUP[WMM_AC_INDEX_NUM] = { 1 /* BEtoBK */ , 1 /*na */ , 0 /*VItoBE */ , 4 /*VOtoVI */ };
- DBGLOG(QM, LOUD, "Enter qmEnqueueTxPackets\n");
- ASSERT(prMsduInfoListHead);
- #if QM_ADAPTIVE_TC_RESOURCE_CTRL
- {
- /* UINT_32 i; */
- /* 4 <0> Update TC resource control related variables */
- /* Keep track of the queue length */
- if (--prQM->u4TimeToUpdateQueLen == 0) { /* -- only here */
- prQM->u4TimeToUpdateQueLen = QM_INIT_TIME_TO_UPDATE_QUE_LEN;
- qmUpdateAverageTxQueLen(prAdapter);
- }
- }
- #endif
- /* Push TX packets into STA_REC (for UNICAST) or prAdapter->rQM (for BMCAST) */
- prStaRec = NULL;
- prMsduInfoReleaseList = NULL;
- prCurrentMsduInfo = NULL;
- QUEUE_INITIALIZE(&rNotEnqueuedQue);
- prNextMsduInfo = prMsduInfoListHead;
- do {
- P_BSS_INFO_T prBssInfo;
- BOOLEAN fgCheckACMAgain;
- ENUM_WMM_ACI_T eAci = WMM_AC_BE_INDEX;
- prCurrentMsduInfo = prNextMsduInfo;
- prNextMsduInfo = QM_TX_GET_NEXT_MSDU_INFO(prCurrentMsduInfo);
- ucTC = TC1_INDEX;
- /* 4 <1> Lookup the STA_REC index */
- /* The ucStaRecIndex will be set in this function */
- qmDetermineStaRecIndex(prAdapter, prCurrentMsduInfo);
- ucPacketType = HIF_TX_PACKET_TYPE_DATA;
- STATS_ENV_REPORT_DETECT(prAdapter, prCurrentMsduInfo->ucStaRecIndex);
- DBGLOG(QM, LOUD, "***** ucStaRecIndex = %d *****\n", prCurrentMsduInfo->ucStaRecIndex);
- prBssInfo = &(prAdapter->rWifiVar.arBssInfo[prCurrentMsduInfo->ucNetworkType]);
- #if (CONF_HIF_LOOPBACK_AUTO == 0)
- if (IS_NET_ACTIVE(prAdapter, prCurrentMsduInfo->ucNetworkType)) {
- #else
- /* force to send the loopback test packet */
- if (1) {
- SET_NET_ACTIVE(prAdapter, prCurrentMsduInfo->ucNetworkType);
- prCurrentMsduInfo->ucStaRecIndex = STA_REC_INDEX_BMCAST;
- ucPacketType = HIF_TX_PKT_TYPE_HIF_LOOPBACK;
- #endif /* End of CONF_HIF_LOOPBACK_AUTO */
- switch (prCurrentMsduInfo->ucStaRecIndex) {
- case STA_REC_INDEX_BMCAST:
- prTxQue = &prQM->arTxQueue[TX_QUEUE_INDEX_BMCAST];
- ucTC = TC5_INDEX;
- #if 0
- if (prCurrentMsduInfo->ucNetworkType == NETWORK_TYPE_P2P_INDEX
- && prCurrentMsduInfo->eSrc != TX_PACKET_MGMT) {
- if (LINK_IS_EMPTY
- (&prAdapter->rWifiVar.
- arBssInfo[NETWORK_TYPE_P2P_INDEX].rStaRecOfClientList)) {
- prTxQue = &rNotEnqueuedQue;
- TX_INC_CNT(&prAdapter->rTxCtrl, TX_AP_BORADCAST_DROP);
- }
- }
- #endif
- QM_DBG_CNT_INC(prQM, QM_DBG_CNT_23);
- break;
- case STA_REC_INDEX_NOT_FOUND:
- ucTC = TC5_INDEX;
- if (prCurrentMsduInfo->eSrc == TX_PACKET_FORWARDING) {
- /* if the packet is the forward type. the packet should be freed */
- DBGLOG(QM, TRACE, "Forwarding packet but Sta is STA_REC_INDEX_NOT_FOUND\n");
- /* prTxQue = &rNotEnqueuedQue; */
- }
- prTxQue = &prQM->arTxQueue[TX_QUEUE_INDEX_NO_STA_REC];
- QM_DBG_CNT_INC(prQM, QM_DBG_CNT_24);
- break;
- default:
- prStaRec = QM_GET_STA_REC_PTR_FROM_INDEX(prAdapter, prCurrentMsduInfo->ucStaRecIndex);
- if (!prStaRec) {
- DBGLOG(QM, ERROR, "prStaRec is NULL\n");
- break;
- }
- ASSERT(prStaRec->fgIsValid);
- if (prCurrentMsduInfo->ucUserPriority < 8) {
- QM_DBG_CNT_INC(prQM, prCurrentMsduInfo->ucUserPriority + 15);
- /* QM_DBG_CNT_15 *//* QM_DBG_CNT_16 *//* QM_DBG_CNT_17 *//* QM_DBG_CNT_18 */
- /* QM_DBG_CNT_19 *//* QM_DBG_CNT_20 *//* QM_DBG_CNT_21 *//* QM_DBG_CNT_22 */
- }
- eAci = WMM_AC_BE_INDEX;
- do {
- fgCheckACMAgain = FALSE;
- if (!prStaRec->fgIsQoS) {
- prTxQue = &prStaRec->arTxQueue[TX_QUEUE_INDEX_AC1];
- ucTC = TC1_INDEX;
- break;
- }
- switch (prCurrentMsduInfo->ucUserPriority) {
- case 1:
- case 2:
- prTxQue = &prStaRec->arTxQueue[TX_QUEUE_INDEX_AC0];
- ucTC = TC0_INDEX;
- eAci = WMM_AC_BK_INDEX;
- break;
- case 0:
- case 3:
- prTxQue = &prStaRec->arTxQueue[TX_QUEUE_INDEX_AC1];
- ucTC = TC1_INDEX;
- eAci = WMM_AC_BE_INDEX;
- break;
- case 4:
- case 5:
- prTxQue = &prStaRec->arTxQueue[TX_QUEUE_INDEX_AC2];
- ucTC = TC2_INDEX;
- eAci = WMM_AC_VI_INDEX;
- #if QM_ADAPTIVE_TC_RESOURCE_CTRL
- prQM->u4TxNumOfVi++;
- #endif
- break;
- case 6:
- case 7:
- prTxQue = &prStaRec->arTxQueue[TX_QUEUE_INDEX_AC3];
- ucTC = TC3_INDEX;
- eAci = WMM_AC_VO_INDEX;
- #if QM_ADAPTIVE_TC_RESOURCE_CTRL
- prQM->u4TxNumOfVo++;
- #endif
- break;
- default:
- prTxQue = &prStaRec->arTxQueue[TX_QUEUE_INDEX_AC1];
- ucTC = TC1_INDEX;
- eAci = WMM_AC_BE_INDEX;
- ASSERT(0);
- break;
- }
- if (prBssInfo->arACQueParms[eAci].fgIsACMSet && eAci
- != WMM_AC_BK_INDEX) {
- prCurrentMsduInfo->ucUserPriority = aucNextUP[eAci];
- fgCheckACMAgain = TRUE;
- }
- } while (fgCheckACMAgain);
- /* LOG_FUNC ("QoS %u UP %u TC %u", */
- /* prStaRec->fgIsQoS,prCurrentMsduInfo->ucUserPriority, ucTC); */
- #if QM_ADAPTIVE_TC_RESOURCE_CTRL
- /*
- In TDLS or AP mode, peer maybe enter "sleep mode".
- If QM_INIT_TIME_TO_UPDATE_QUE_LEN = 60 when peer is in sleep mode,
- we need to wait 60 * u4TimeToAdjustTcResource = 180 packets
- u4TimeToAdjustTcResource = 3,
- then we will adjust TC resouce for VI or VO.
- But in TDLS test case, the throughput is very low, only 0.8Mbps in 5.7,
- we will to wait about 12 seconds to collect 180 packets.
- but the test time is only 20 seconds.
- */
- if ((prQM->u4TxNumOfVi == 10) || (prQM->u4TxNumOfVo == 10)) {
- /* force to do TC resouce update */
- prQM->u4TimeToUpdateQueLen = QM_INIT_TIME_TO_UPDATE_QUE_LEN_MIN;
- prQM->u4TimeToAdjustTcResource = 1;
- }
- #endif
- #if ARP_MONITER_ENABLE
- if (IS_STA_IN_AIS(prStaRec) && prCurrentMsduInfo->eSrc == TX_PACKET_OS)
- qmDetectArpNoResponse(prAdapter, prCurrentMsduInfo);
- #endif
- break; /*default */
- } /* switch (prCurrentMsduInfo->ucStaRecIndex) */
- if (prCurrentMsduInfo->eSrc == TX_PACKET_FORWARDING) {
- if (prTxQue->u4NumElem > 32) {
- DBGLOG(QM, WARN,
- "Drop the Packet for full Tx queue (forwarding) Bss %u\n",
- prCurrentMsduInfo->ucNetworkType);
- prTxQue = &rNotEnqueuedQue;
- TX_INC_CNT(&prAdapter->rTxCtrl, TX_FORWARD_OVERFLOW_DROP);
- }
- }
- } else {
- DBGLOG(QM, WARN, "Drop the Packet for inactive Bss %u\n", prCurrentMsduInfo->ucNetworkType);
- QM_DBG_CNT_INC(prQM, QM_DBG_CNT_31);
- prTxQue = &rNotEnqueuedQue;
- TX_INC_CNT(&prAdapter->rTxCtrl, TX_INACTIVE_BSS_DROP);
- }
- /* 4 <3> Fill the MSDU_INFO for constructing HIF TX header */
- /* TODO: Fill MSDU_INFO according to the network type,
- * EtherType, and STA status (for PS forwarding control).
- */
- /* Note that the Network Type Index and STA_REC index are determined in
- * qmDetermineStaRecIndex(prCurrentMsduInfo).
- */
- QM_TX_SET_MSDU_INFO_FOR_DATA_PACKET(prCurrentMsduInfo, /* MSDU_INFO ptr */
- ucTC, /* TC tag */
- ucPacketType, /* Packet Type */
- 0, /* Format ID */
- prCurrentMsduInfo->fgIs802_1x, /* Flag 802.1x */
- prCurrentMsduInfo->fgIs802_11, /* Flag 802.11 */
- 0, /* PAL LLH */
- 0, /* ACL SN */
- PS_FORWARDING_TYPE_NON_PS, /* PS Forwarding Type */
- 0 /* PS Session ID */
- );
- /* 4 <4> Enqueue the packet to different AC queue (max 5 AC queues) */
- QUEUE_INSERT_TAIL(prTxQue, (P_QUE_ENTRY_T) prCurrentMsduInfo);
- #if QM_TC_RESOURCE_EMPTY_COUNTER
- {
- P_TX_CTRL_T prTxCtrl = &prAdapter->rTxCtrl;
- if (prTxCtrl->rTc.aucFreeBufferCount[ucTC] == 0) {
- prQM->au4QmTcResourceEmptyCounter[prCurrentMsduInfo->ucNetworkType][ucTC]++;
- /*
- DBGLOG(QM, TRACE, ("TC%d Q Empty Count: [%d]%ld\n",
- ucTC,
- prCurrentMsduInfo->ucNetworkType,
- prQM->au4QmTcResourceEmptyCounter[prCurrentMsduInfo->ucNetworkType][ucTC]));
- */
- }
- }
- #endif
- #if QM_TEST_MODE
- if (++prQM->u4PktCount == QM_TEST_TRIGGER_TX_COUNT) {
- prQM->u4PktCount = 0;
- qmTestCases(prAdapter);
- }
- #endif
- DBGLOG(QM, LOUD, "Current queue length = %u\n", prTxQue->u4NumElem);
- } while (prNextMsduInfo);
- if (QUEUE_IS_NOT_EMPTY(&rNotEnqueuedQue)) {
- QM_TX_SET_NEXT_MSDU_INFO((P_MSDU_INFO_T) QUEUE_GET_TAIL(&rNotEnqueuedQue), NULL);
- prMsduInfoReleaseList = (P_MSDU_INFO_T) QUEUE_GET_HEAD(&rNotEnqueuedQue);
- }
- return prMsduInfoReleaseList;
- }
- /*----------------------------------------------------------------------------*/
- /*!
- * \brief Determine the STA_REC index for a packet
- *
- * \param[in] prMsduInfo Pointer to the packet
- *
- * \return (none)
- */
- /*----------------------------------------------------------------------------*/
- static VOID qmDetermineStaRecIndex(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo)
- {
- UINT_32 i;
- P_STA_RECORD_T prTempStaRec;
- /* P_QUE_MGT_T prQM = &prAdapter->rQM; */
- prTempStaRec = NULL;
- ASSERT(prMsduInfo);
- /* 4 <1> DA = BMCAST */
- if (IS_BMCAST_MAC_ADDR(prMsduInfo->aucEthDestAddr)) {
- /* For intrastructure mode and P2P (playing as a GC), BMCAST frames shall be sent to the AP.
- * FW shall take care of this. The host driver is not able to distinguish these cases. */
- prMsduInfo->ucStaRecIndex = STA_REC_INDEX_BMCAST;
- DBGLOG(QM, LOUD, "TX with DA = BMCAST\n");
- return;
- }
- #if (CFG_SUPPORT_TDLS == 1)
- /* Check if the peer is TDLS one */
- if (TdlsexStaRecIdxGet(prAdapter, prMsduInfo) == TDLS_STATUS_SUCCESS)
- return; /* find a TDLS record */
- #endif /* CFG_SUPPORT_TDLS */
- /* 4 <2> Check if an AP STA is present */
- for (i = 0; i < CFG_NUM_OF_STA_RECORD; i++) {
- prTempStaRec = &(prAdapter->arStaRec[i]);
- if ((prTempStaRec->ucNetTypeIndex == prMsduInfo->ucNetworkType)
- && (prTempStaRec->fgIsAp)
- && (prTempStaRec->fgIsValid)) {
- prMsduInfo->ucStaRecIndex = prTempStaRec->ucIndex;
- return;
- }
- }
- /* 4 <3> Not BMCAST, No AP --> Compare DA (i.e., to see whether this is a unicast frame to a client) */
- for (i = 0; i < CFG_NUM_OF_STA_RECORD; i++) {
- prTempStaRec = &(prAdapter->arStaRec[i]);
- if (prTempStaRec->fgIsValid) {
- if (EQUAL_MAC_ADDR(prTempStaRec->aucMacAddr, prMsduInfo->aucEthDestAddr)) {
- prMsduInfo->ucStaRecIndex = prTempStaRec->ucIndex;
- return;
- }
- }
- }
- /* 4 <4> No STA found, Not BMCAST --> Indicate NOT_FOUND to FW */
- prMsduInfo->ucStaRecIndex = STA_REC_INDEX_NOT_FOUND;
- DBGLOG(QM, LOUD, "QM: TX with STA_REC_INDEX_NOT_FOUND\n");
- #if (QM_TEST_MODE && QM_TEST_FAIR_FORWARDING)
- prMsduInfo->ucStaRecIndex = (UINT_8) prQM->u4CurrentStaRecIndexToEnqueue;
- #endif
- }
- /*----------------------------------------------------------------------------*/
- /*!
- * \brief Dequeue TX packets from a STA_REC for a particular TC
- *
- * \param[out] prQue The queue to put the dequeued packets
- * \param[in] ucTC The TC index (TC0_INDEX to TC5_INDEX)
- * \param[in] ucMaxNum The maximum amount of dequeued packets
- *
- * \return (none)
- */
- /*----------------------------------------------------------------------------*/
- static VOID
- qmDequeueTxPacketsFromPerStaQueues(IN P_ADAPTER_T prAdapter,
- OUT P_QUE_T prQue, IN UINT_8 ucTC, IN UINT_8 ucCurrentQuota, IN UINT_8 ucTotalQuota)
- {
- #if QM_FORWARDING_FAIRNESS
- UINT_32 i; /* Loop for */
- PUINT_32 pu4HeadStaRecIndex; /* The Head STA index */
- PUINT_32 pu4HeadStaRecForwardCount; /* The total forwarded packets for the head STA */
- P_STA_RECORD_T prStaRec; /* The current focused STA */
- P_BSS_INFO_T prBssInfo; /* The Bss for current focused STA */
- P_QUE_T prCurrQueue; /* The current TX queue to dequeue */
- P_MSDU_INFO_T prDequeuedPkt; /* The dequeued packet */
- UINT_32 u4ForwardCount; /* To remember the total forwarded packets for a STA */
- UINT_32 u4MaxForwardCount; /* The maximum number of packets a STA can forward */
- UINT_32 u4Resource; /* The TX resource amount */
- BOOLEAN fgChangeHeadSta; /* Whether a new head STA shall be determined at the end of the function */
- P_QUE_MGT_T prQM = &prAdapter->rQM;
- PUINT_8 pucFreeQuota = NULL;
- #if CFG_ENABLE_WIFI_DIRECT
- P_P2P_CHNL_REQ_INFO_T prChnlReqInfo = &prAdapter->rWifiVar.prP2pFsmInfo->rChnlReqInfo;
- /*NFC Beam + Indication */
- #endif
- DBGLOG(QM, LOUD, "Enter qmDequeueTxPacketsFromPerStaQueues (TC = %u)\n", ucTC);
- ASSERT(ucTC == TC0_INDEX || ucTC == TC1_INDEX || ucTC == TC2_INDEX || ucTC == TC3_INDEX || ucTC == TC4_INDEX);
- if (!ucCurrentQuota) {
- DBGLOG(TX, LOUD, "@@@@@ TC = %u ucCurrentQuota = %u @@@@@\n", ucTC, ucCurrentQuota);
- return;
- }
- u4Resource = ucCurrentQuota;
- /* 4 <1> Determine the head STA */
- /* The head STA shall be an active STA */
- pu4HeadStaRecIndex = &(prQM->au4HeadStaRecIndex[ucTC]);
- pu4HeadStaRecForwardCount = &(prQM->au4ForwardCount[ucTC]);
- DBGLOG(QM, LOUD, "(Fairness) TID = %u Init Head STA = %u Resource = %u\n",
- ucTC, *pu4HeadStaRecIndex, u4Resource);
- /* From STA[x] to STA[x+1] to STA[x+2] to ... to STA[x] */
- for (i = 0; i < CFG_NUM_OF_STA_RECORD + 1; i++) {
- prStaRec = &prAdapter->arStaRec[(*pu4HeadStaRecIndex)];
- ASSERT(prStaRec);
- /* Only Data frame (1x was not included) will be queued in */
- if (prStaRec->fgIsValid) {
- prBssInfo = &(prAdapter->rWifiVar.arBssInfo[prStaRec->ucNetTypeIndex]);
- ASSERT(prBssInfo->ucNetTypeIndex == prStaRec->ucNetTypeIndex);
- /* Determine how many packets the head STA is allowed to send in a round */
- QM_DBG_CNT_INC(prQM, QM_DBG_CNT_25);
- u4MaxForwardCount = ucTotalQuota;
- #if CFG_ENABLE_WIFI_DIRECT
- pucFreeQuota = NULL;
- if (prStaRec->fgIsInPS && (ucTC != TC4_INDEX)) {
- /* TODO: Change the threshold in coorperation with the PS forwarding mechanism */
- /* u4MaxForwardCount = ucTotalQuota; */
- /* Per STA flow control when STA in PS mode */
- /* The PHASE 1: only update from ucFreeQuota (now) */
- /* XXX The PHASE 2: Decide by ucFreeQuota and ucBmpDeliveryAC (per queue ) */
- /* aucFreeQuotaPerQueue[] */
- /* NOTE: other method to set u4Resource */
- if (prStaRec->fgIsQoS && prStaRec->fgIsUapsdSupported
- /* && prAdapter->rWifiVar.fgSupportQoS
- && prAdapter->rWifiVar.fgSupportUAPSD */) {
- if (prStaRec->ucBmpTriggerAC & BIT(ucTC)) {
- u4MaxForwardCount = prStaRec->ucFreeQuotaForDelivery;
- pucFreeQuota = &prStaRec->ucFreeQuotaForDelivery;
- } else {
- u4MaxForwardCount = prStaRec->ucFreeQuotaForNonDelivery;
- pucFreeQuota = &prStaRec->ucFreeQuotaForNonDelivery;
- }
- } else {
- ASSERT(prStaRec->ucFreeQuotaForDelivery == 0);
- u4MaxForwardCount = prStaRec->ucFreeQuotaForNonDelivery;
- pucFreeQuota = &prStaRec->ucFreeQuotaForNonDelivery;
- }
- } /* fgIsInPS */
- #endif /* CFG_ENABLE_WIFI_DIRECT */
- #if CFG_ENABLE_WIFI_DIRECT
- /*NFC Beam + Indication */
- if (prBssInfo->fgIsNetAbsent && (ucTC != TC4_INDEX)) {
- if (prBssInfo->eCurrentOPMode == OP_MODE_ACCESS_POINT) {
- if ((prChnlReqInfo->NFC_BEAM != 1) &&
- (u4MaxForwardCount > prBssInfo->ucBssFreeQuota))
- u4MaxForwardCount = prBssInfo->ucBssFreeQuota;
- } else {
- if (u4MaxForwardCount > prBssInfo->ucBssFreeQuota)
- u4MaxForwardCount = prBssInfo->ucBssFreeQuota;
- }
- }
- #endif /* CFG_ENABLE_WIFI_DIRECT */
- /* Determine whether the head STA can continue to forward packets in this round */
- if ((*pu4HeadStaRecForwardCount) < u4MaxForwardCount)
- break;
- } /* prStaRec->fgIsValid */
- else {
- /* The current Head STA has been deactivated, so search for a new head STA */
- prStaRec = NULL;
- prBssInfo = NULL;
- (*pu4HeadStaRecIndex)++;
- (*pu4HeadStaRecIndex) %= CFG_NUM_OF_STA_RECORD;
- /* Reset the forwarding count before searching (since this is for a new selected STA) */
- (*pu4HeadStaRecForwardCount) = 0;
- }
- } /* i < CFG_NUM_OF_STA_RECORD + 1 */
- /* All STA_RECs are inactive, so exit */
- if (!prStaRec) {
- /* Under concurrent, it is possible that there is no candidcated STA. */
- /* DBGLOG(TX, EVENT, ("All STA_RECs are inactive\n")); */
- return;
- }
- DBGLOG(QM, LOUD, "(Fairness) TID = %u Round Head STA = %u\n", ucTC, *pu4HeadStaRecIndex);
- /* 4 <2> Dequeue packets from the head STA */
- prCurrQueue = &prStaRec->arTxQueue[ucTC];
- prDequeuedPkt = NULL;
- fgChangeHeadSta = FALSE;
- #if (CFG_SUPPORT_TDLS == 1)
- if (pucFreeQuota != NULL)
- TdlsexTxQuotaCheck(prAdapter->prGlueInfo, prStaRec, *pucFreeQuota);
- #endif /* CFG_SUPPORT_TDLS */
- while (prCurrQueue) {
- #if QM_DEBUG_COUNTER
- if (ucTC <= TC4_INDEX) {
- if (QUEUE_IS_EMPTY(prCurrQueue)) {
- QM_DBG_CNT_INC(prQM, ucTC);
- /* QM_DBG_CNT_00 *//* QM_DBG_CNT_01 *//* QM_DBG_CNT_02 */
- /* QM_DBG_CNT_03 *//* QM_DBG_CNT_04 */
- }
- if (u4Resource == 0) {
- QM_DBG_CNT_INC(prQM, ucTC + 5);
- /* QM_DBG_CNT_05 *//* QM_DBG_CNT_06 *//* QM_DBG_CNT_07 */
- /* QM_DBG_CNT_08 *//* QM_DBG_CNT_09 */
- }
- if (((*pu4HeadStaRecForwardCount) >= u4MaxForwardCount)) {
- QM_DBG_CNT_INC(prQM, ucTC + 10);
- /* QM_DBG_CNT_10 *//* QM_DBG_CNT_11 *//* QM_DBG_CNT_12 */
- /* QM_DBG_CNT_13 *//* QM_DBG_CNT_14 */
- }
- }
- #endif
- /* Three cases to break: (1) No resource (2) No packets (3) Fairness */
- if (QUEUE_IS_EMPTY(prCurrQueue) || ((*pu4HeadStaRecForwardCount) >= u4MaxForwardCount)) {
- fgChangeHeadSta = TRUE;
- break;
- } else if (u4Resource == 0) {
- #if (CFG_SUPPORT_STATISTICS == 1)
- prStaRec->u4NumOfNoTxQuota++;
- #endif /* CFG_SUPPORT_STATISTICS */
- break;
- }
- QUEUE_REMOVE_HEAD(prCurrQueue, prDequeuedPkt, P_MSDU_INFO_T);
- #if (CFG_SUPPORT_TDLS_DBG == 1)
- if (prDequeuedPkt != NULL) {
- struct sk_buff *prSkb = (struct sk_buff *)prDequeuedPkt->prPacket;
- UINT8 *pkt = prSkb->data;
- UINT16 u2Identifier;
- if ((*(pkt + 12) == 0x08) && (*(pkt + 13) == 0x00)) {
- /* ip */
- u2Identifier = ((*(pkt + 18)) << 8) | (*(pkt + 19));
- DBGLOG(QM, LOUD, "<d> %d\n", u2Identifier);
- }
- }
- #endif
- #if DBG && 0
- LOG_FUNC("Deq0 TC %d queued %u net %u mac len %u len %u Type %u 1x %u 11 %u\n",
- prDequeuedPkt->ucTC,
- prCurrQueue->u4NumElem,
- prDequeuedPkt->ucNetworkType,
- prDequeuedPkt->ucMacHeaderLength,
- prDequeuedPkt->u2FrameLength,
- prDequeuedPkt->ucPacketType, prDequeuedPkt->fgIs802_1x, prDequeuedPkt->fgIs802_11);
- LOG_FUNC("Dest Mac: %pM\n", prDequeuedPkt->aucEthDestAddr);
- #if LINUX
- {
- struct sk_buff *prSkb = (struct sk_buff *)prDequeuedPkt->prPacket;
- dumpMemory8((PUINT_8) prSkb->data, prSkb->len);
- }
- #endif
- #endif
- ASSERT(prDequeuedPkt->ucTC == ucTC);
- if (!QUEUE_IS_EMPTY(prCurrQueue)) {
- /* XXX: check all queues for STA */
- prDequeuedPkt->ucPsForwardingType = PS_FORWARDING_MORE_DATA_ENABLED;
- }
- QUEUE_INSERT_TAIL(prQue, (P_QUE_ENTRY_T) prDequeuedPkt);
- u4Resource--;
- (*pu4HeadStaRecForwardCount)++;
- #if CFG_ENABLE_WIFI_DIRECT
- /* XXX The PHASE 2: decrease from aucFreeQuotaPerQueue[] */
- if (prStaRec->fgIsInPS && (ucTC != TC4_INDEX)) {
- if ((pucFreeQuota) && (*pucFreeQuota > 0))
- *pucFreeQuota = *pucFreeQuota - 1;
- }
- #endif /* CFG_ENABLE_WIFI_DIRECT */
- #if CFG_ENABLE_WIFI_DIRECT
- if (prBssInfo->fgIsNetAbsent && (ucTC != TC4_INDEX)) {
- if (prBssInfo->ucBssFreeQuota > 0)
- prBssInfo->ucBssFreeQuota--;
- }
- #endif /* CFG_ENABLE_WIFI_DIRECT */
- }
- if (*pu4HeadStaRecForwardCount) {
- DBGLOG(QM, LOUD,
- "TC = %u Round Head STA = %u, u4HeadStaRecForwardCount = %u\n", ucTC, *pu4HeadStaRecIndex,
- (*pu4HeadStaRecForwardCount));
- }
- #if QM_BURST_END_INFO_ENABLED
- /* Let FW know which packet is the last one dequeued from the STA */
- if (prDequeuedPkt)
- prDequeuedPkt->fgIsBurstEnd = TRUE;
- #endif
- /* 4 <3> Dequeue from the other STAs if there is residual TX resource */
- /* Check all of the STAs to continue forwarding packets (including the head STA) */
- for (i = 0; i < CFG_NUM_OF_STA_RECORD; i++) {
- /* Break in case no reasource is available */
- if (u4Resource == 0)
- break;
- /* The current head STA will be examined when i = CFG_NUM_OF_STA_RECORD-1 */
- prStaRec = &prAdapter->arStaRec[((*pu4HeadStaRecIndex) + i + 1) % CFG_NUM_OF_STA_RECORD];
- ASSERT(prStaRec);
- if (prStaRec->fgIsValid) {
- prBssInfo = &(prAdapter->rWifiVar.arBssInfo[prStaRec->ucNetTypeIndex]);
- ASSERT(prBssInfo->ucNetTypeIndex == prStaRec->ucNetTypeIndex);
- DBGLOG(QM, LOUD, "(Fairness) TID = %u Sharing STA = %u Resource = %u\n",
- ucTC, prStaRec->ucIndex, u4Resource);
- prCurrQueue = &prStaRec->arTxQueue[ucTC];
- u4ForwardCount = 0;
- u4MaxForwardCount = ucTotalQuota;
- #if CFG_ENABLE_WIFI_DIRECT
- pucFreeQuota = NULL;
- if (prStaRec->fgIsInPS && (ucTC != TC4_INDEX)) {
- /* TODO: Change the threshold in coorperation with the PS forwarding mechanism */
- /* u4MaxForwardCount = ucTotalQuota; */
- /* Per STA flow control when STA in PS mode */
- /* The PHASE 1: only update from ucFreeQuota (now) */
- /* XXX The PHASE 2: Decide by ucFreeQuota and ucBmpDeliveryAC (per queue ) */
- /* aucFreeQuotaPerQueue[] */
- /* NOTE: other method to set u4Resource */
- if (prStaRec->fgIsQoS && prStaRec->fgIsUapsdSupported
- /* && prAdapter->rWifiVar.fgSupportQoS
- && prAdapter->rWifiVar.fgSupportUAPSD */) {
- if (prStaRec->ucBmpTriggerAC & BIT(ucTC)) {
- u4MaxForwardCount = prStaRec->ucFreeQuotaForDelivery;
- pucFreeQuota = &prStaRec->ucFreeQuotaForDelivery;
- } else {
- u4MaxForwardCount = prStaRec->ucFreeQuotaForNonDelivery;
- pucFreeQuota = &prStaRec->ucFreeQuotaForNonDelivery;
- }
- } else {
- ASSERT(prStaRec->ucFreeQuotaForDelivery == 0);
- u4MaxForwardCount = prStaRec->ucFreeQuotaForNonDelivery;
- pucFreeQuota = &prStaRec->ucFreeQuotaForNonDelivery;
- }
- }
- #endif /* CFG_ENABLE_WIFI_DIRECT */
- #if CFG_ENABLE_WIFI_DIRECT
- if (prBssInfo->fgIsNetAbsent && (ucTC != TC4_INDEX)) {
- if (u4MaxForwardCount > prBssInfo->ucBssFreeQuota)
- u4MaxForwardCount = prBssInfo->ucBssFreeQuota;
- }
- #endif /* CFG_ENABLE_WIFI_DIRECT */
- } /* prStaRec->fgIsValid */
- else {
- prBssInfo = NULL;
- /* Invalid STA, so check the next STA */
- continue;
- }
- while (prCurrQueue) {
- /* Three cases to break: (1) No resource (2) No packets (3) Fairness */
- if ((u4Resource == 0) || QUEUE_IS_EMPTY(prCurrQueue) || (u4ForwardCount >= u4MaxForwardCount))
- break;
- QUEUE_REMOVE_HEAD(prCurrQueue, prDequeuedPkt, P_MSDU_INFO_T);
- #if DBG && 0
- DBGLOG(QM, LOUD, "Deq0 TC %d queued %u net %u mac len %u len %u Type %u 1x %u 11 %u\n",
- prDequeuedPkt->ucTC,
- prCurrQueue->u4NumElem,
- prDequeuedPkt->ucNetworkType,
- prDequeuedPkt->ucMacHeaderLength,
- prDequeuedPkt->u2FrameLength,
- prDequeuedPkt->ucPacketType,
- prDequeuedPkt->fgIs802_1x, prDequeuedPkt->fgIs802_11));
- DBGLOG(QM, LOUD, "Dest Mac: %pM\n", prDequeuedPkt->aucEthDestAddr);
- #if LINUX
- {
- struct sk_buff *prSkb = (struct sk_buff *)prDequeuedPkt->prPacket;
- dumpMemory8((PUINT_8) prSkb->data, prSkb->len);
- }
- #endif
- #endif
- ASSERT(prDequeuedPkt->ucTC == ucTC);
- if (!QUEUE_IS_EMPTY(prCurrQueue))
- /* more data field ? */
- prDequeuedPkt->ucPsForwardingType = PS_FORWARDING_MORE_DATA_ENABLED;
- QUEUE_INSERT_TAIL(prQue, (P_QUE_ENTRY_T) prDequeuedPkt);
- u4Resource--;
- u4ForwardCount++;
- #if CFG_ENABLE_WIFI_DIRECT
- /* XXX The PHASE 2: decrease from aucFreeQuotaPerQueue[] */
- if (prStaRec->fgIsInPS && (ucTC != TC4_INDEX)) {
- ASSERT(pucFreeQuota);
- ASSERT(*pucFreeQuota > 0);
- if (*pucFreeQuota > 0)
- *pucFreeQuota = *pucFreeQuota - 1;
- }
- #endif /* CFG_ENABLE_WIFI_DIRECT */
- #if CFG_ENABLE_WIFI_DIRECT
- ASSERT(prBssInfo->ucNetTypeIndex == prStaRec->ucNetTypeIndex);
- if (prBssInfo->fgIsNetAbsent && (ucTC != TC4_INDEX)) {
- if (prBssInfo->ucBssFreeQuota > 0)
- prBssInfo->ucBssFreeQuota--;
- }
- #endif /* CFG_ENABLE_WIFI_DIRECT */
- }
- #if QM_BURST_END_INFO_ENABLED
- /* Let FW know which packet is the last one dequeued from the STA */
- if (u4ForwardCount)
- prDequeuedPkt->fgIsBurstEnd = TRUE;
- #endif
- }
- if (fgChangeHeadSta) {
- (*pu4HeadStaRecIndex)++;
- (*pu4HeadStaRecIndex) %= CFG_NUM_OF_STA_RECORD;
- (*pu4HeadStaRecForwardCount) = 0;
- DBGLOG(QM, LOUD, "(Fairness) TID = %u Scheduled Head STA = %u Left Resource = %u\n",
- ucTC, (*pu4HeadStaRecIndex), u4Resource);
- }
- /***************************************************************************************/
- #else
- UINT_8 ucStaRecIndex;
- P_STA_RECORD_T prStaRec;
- P_QUE_T prCurrQueue;
- UINT_8 ucPktCount;
- P_MSDU_INFO_T prDequeuedPkt;
- DBGLOG(QM, LOUD, "Enter qmDequeueTxPacketsFromPerStaQueues (TC = %u)\n", ucTC);
- if (ucCurrentQuota == 0)
- return;
- /* 4 <1> Determine the queue index and the head STA */
- /* The head STA */
- ucStaRecIndex = 0; /* TODO: Get the current head STA */
- prStaRec = QM_GET_STA_REC_PTR_FROM_INDEX(prAdapter, ucStaRecIndex);
- ASSERT(prStaRec);
- if (prStaRec == NULL)
- return;
- /* The queue to pull out packets */
- ASSERT(ucTC == TC0_INDEX || ucTC == TC1_INDEX || ucTC == TC2_INDEX || ucTC == TC3_INDEX || ucTC == TC4_INDEX);
- prCurrQueue = &prStaRec->arTxQueue[ucTC];
- ucPktCount = ucCurrentQuota;
- prDequeuedPkt = NULL;
- /* 4 <2> Dequeue packets for the head STA */
- while (TRUE) {
- if (!(prStaRec->fgIsValid) || ucPktCount == 0 || QUEUE_IS_EMPTY(prCurrQueue)) {
- break;
- } else {
- QUEUE_REMOVE_HEAD(prCurrQueue, prDequeuedPkt, P_MSDU_INFO_T);
- /* DbgPrint("QM: Remove Queue Head, TC= %d\n", prDequeuedPkt->ucTC); */
- ASSERT(prDequeuedPkt->ucTC == ucTC);
- QUEUE_INSERT_TAIL(prQue, (P_QUE_ENTRY_T) prDequeuedPkt);
- ucPktCount--;
- }
- }
- /* DbgPrint("QM: Remaining number of queued packets = %d\n", prCurrQueue->u4NumElem); */
- #if QM_BURST_END_INFO_ENABLED
- if (prDequeuedPkt)
- prDequeuedPkt->fgIsBurstEnd = TRUE;
- #endif
- /* 4 <3> Update scheduling info */
- /* TODO */
- /* 4 <4> Utilize the remainaing TX opportunities for non-head STAs */
- /* TODO */
- #endif
- }
- /*----------------------------------------------------------------------------*/
- /*!
- * \brief Dequeue TX packets from a per-Type-based Queue for a particular TC
- *
- * \param[out] prQue The queue to put the dequeued packets
- * \param[in] ucTC The TC index (Shall always be TC5_INDEX)
- * \param[in] ucMaxNum The maximum amount of dequeued packets
- *
- * \return (none)
- */
- /*----------------------------------------------------------------------------*/
- static VOID
- qmDequeueTxPacketsFromPerTypeQueues(IN P_ADAPTER_T prAdapter, OUT P_QUE_T prQue, IN UINT_8 ucTC, IN UINT_8 ucMaxNum)
- {
- /* UINT_8 ucQueIndex; */
- /* UINT_8 ucStaRecIndex; */
- P_BSS_INFO_T prBssInfo;
- P_BSS_INFO_T parBssInfo;
- P_QUE_T prCurrQueue;
- UINT_8 ucPktCount;
- P_MSDU_INFO_T prDequeuedPkt;
- P_MSDU_INFO_T prBurstEndPkt;
- QUE_T rMergeQue;
- P_QUE_T prMergeQue;
- P_QUE_MGT_T prQM;
- DBGLOG(QM, LOUD, "Enter qmDequeueTxPacketsFromPerTypeQueues (TC = %d, Max = %d)\n", ucTC, ucMaxNum);
- /* TC5: Broadcast/Multicast data packets */
- ASSERT(ucTC == TC5_INDEX);
- if (ucMaxNum == 0)
- return;
- prQM = &prAdapter->rQM;
- /* 4 <1> Determine the queue */
- prCurrQueue = &prQM->arTxQueue[TX_QUEUE_INDEX_BMCAST];
- ucPktCount = ucMaxNum;
- prDequeuedPkt = NULL;
- prBurstEndPkt = NULL;
- parBssInfo = prAdapter->rWifiVar.arBssInfo;
- QUEUE_INITIALIZE(&rMergeQue);
- prMergeQue = &rMergeQue;
- /* 4 <2> Dequeue packets */
- while (TRUE) {
- if (ucPktCount == 0 || QUEUE_IS_EMPTY(prCurrQueue))
- break;
- QUEUE_REMOVE_HEAD(prCurrQueue, prDequeuedPkt, P_MSDU_INFO_T);
- ASSERT(prDequeuedPkt->ucTC == ucTC);
- ASSERT(prDequeuedPkt->ucNetworkType < NETWORK_TYPE_INDEX_NUM);
- prBssInfo = &parBssInfo[prDequeuedPkt->ucNetworkType];
- if (IS_BSS_ACTIVE(prBssInfo)) {
- if (!prBssInfo->fgIsNetAbsent) {
- QUEUE_INSERT_TAIL(prQue, (P_QUE_ENTRY_T) prDequeuedPkt);
- prBurstEndPkt = prDequeuedPkt;
- ucPktCount--;
- QM_DBG_CNT_INC(prQM, QM_DBG_CNT_26);
- #if DBG && 0
- LOG_FUNC
- ("DeqType TC %d queued %u net %u mac len %u len %u Type %u 1x %u 11 %u\n",
- prDequeuedPkt->ucTC, prCurrQueue->u4NumElem, prDequeuedPkt->ucNetworkType,
- prDequeuedPkt->ucMacHeaderLength, prDequeuedPkt->u2FrameLength,
- prDequeuedPkt->ucPacketType, prDequeuedPkt->fgIs802_1x,
- prDequeuedPkt->fgIs802_11);
- LOG_FUNC("Dest Mac: %pM\n", prDequeuedPkt->aucEthDestAddr);
- #if LINUX
- {
- struct sk_buff *prSkb = (struct sk_buff *)prDequeuedPkt->prPacket;
- dumpMemory8((PUINT_8) prSkb->data, prSkb->len);
- }
- #endif
- #endif
- } else {
- QUEUE_INSERT_TAIL(prMergeQue, (P_QUE_ENTRY_T) prDequeuedPkt);
- }
- } else {
- QM_TX_SET_NEXT_MSDU_INFO(prDequeuedPkt, NULL);
- wlanProcessQueuedMsduInfo(prAdapter, prDequeuedPkt);
- }
- }
- if (QUEUE_IS_NOT_EMPTY(prMergeQue)) {
- QUEUE_CONCATENATE_QUEUES(prMergeQue, prCurrQueue);
- QUEUE_MOVE_ALL(prCurrQueue, prMergeQue);
- if (QUEUE_GET_TAIL(prCurrQueue))
- QM_TX_SET_NEXT_MSDU_INFO((P_MSDU_INFO_T) QUEUE_GET_TAIL(prCurrQueue), NULL);
- }
- #if QM_BURST_END_INFO_ENABLED
- if (prBurstEndPkt)
- prBurstEndPkt->fgIsBurstEnd = TRUE;
- #endif
- } /* qmDequeueTxPacketsFromPerTypeQueues */
- /*----------------------------------------------------------------------------*/
- /*!
- * \brief Dequeue TX packets to send to HIF TX
- *
- * \param[in] prTcqStatus Info about the maximum amount of dequeued packets
- *
- * \return The list of dequeued TX packets
- */
- /*----------------------------------------------------------------------------*/
- P_MSDU_INFO_T qmDequeueTxPackets(IN P_ADAPTER_T prAdapter, IN P_TX_TCQ_STATUS_T prTcqStatus)
- {
- INT32 i;
- P_MSDU_INFO_T prReturnedPacketListHead;
- QUE_T rReturnedQue;
- DBGLOG(QM, LOUD, "Enter qmDequeueTxPackets\n");
- QUEUE_INITIALIZE(&rReturnedQue);
- prReturnedPacketListHead = NULL;
- /* dequeue packets from different AC queue based on available aucFreeBufferCount */
- /* TC0 to TC4: AC0~AC3, 802.1x (commands packets are not handled by QM) */
- for (i = TC4_INDEX; i >= TC0_INDEX; i--) {
- DBGLOG(QM, LOUD, "Dequeue packets from Per-STA queue[%d]\n", i);
- /*
- in the function, we will re-calculate the ucFreeQuota.
- If any packet with any priority for the station will be sent, ucFreeQuota --
- Note1: ucFreeQuota will be decrease only when station is in power save mode.
- In active mode, we will sent the packet to the air directly.
- if(prStaRec->fgIsInPS && (ucTC!=TC4_INDEX)) {
- ASSERT(pucFreeQuota);
- ASSERT(*pucFreeQuota>0);
- if ((pucFreeQuota) && (*pucFreeQuota>0)) {
- *pucFreeQuota = *pucFreeQuota - 1;
- }
- }
- Note2: maximum queued number for a station is 10, TXM_MAX_BUFFER_PER_STA_DEF in fw
- i.e. default prStaRec->ucFreeQuota = 10
- Note3: In qmUpdateFreeQuota(), we will adjust
- ucFreeQuotaForNonDelivery = ucFreeQuota>>1;
- ucFreeQuotaForDelivery = ucFreeQuota - ucFreeQuotaForNonDelivery;
- */
- qmDequeueTxPacketsFromPerStaQueues(prAdapter,
- &rReturnedQue,
- (UINT_8) i,
- prTcqStatus->aucFreeBufferCount[i], /* maximum dequeue number */
- prTcqStatus->aucMaxNumOfBuffer[i]);
- /* The aggregate number of dequeued packets */
- DBGLOG(QM, LOUD, "DQA)[%u](%u)\n", i, rReturnedQue.u4NumElem);
- }
- /* TC5 (BMCAST or STA-NOT-FOUND packets) */
- qmDequeueTxPacketsFromPerTypeQueues(prAdapter,
- &rReturnedQue, TC5_INDEX, prTcqStatus->aucFreeBufferCount[TC5_INDEX]
- );
- DBGLOG(QM, LOUD, "Current total number of dequeued packets = %u\n", rReturnedQue.u4NumElem);
- if (QUEUE_IS_NOT_EMPTY(&rReturnedQue)) {
- prReturnedPacketListHead = (P_MSDU_INFO_T) QUEUE_GET_HEAD(&rReturnedQue);
- QM_TX_SET_NEXT_MSDU_INFO((P_MSDU_INFO_T) QUEUE_GET_TAIL(&rReturnedQue), NULL);
- }
- return prReturnedPacketListHead;
- }
- /*----------------------------------------------------------------------------*/
- /*!
- * \brief Adjust the TC quotas according to traffic demands
- *
- * \param[out] prTcqAdjust The resulting adjustment
- * \param[in] prTcqStatus Info about the current TC quotas and counters
- *
- * \return (none)
- */
- /*----------------------------------------------------------------------------*/
- VOID qmAdjustTcQuotas(IN P_ADAPTER_T prAdapter, OUT P_TX_TCQ_ADJUST_T prTcqAdjust, IN P_TX_TCQ_STATUS_T prTcqStatus)
- {
- #if QM_ADAPTIVE_TC_RESOURCE_CTRL
- UINT_32 i;
- P_QUE_MGT_T prQM = &prAdapter->rQM;
- /* Must reset */
- for (i = 0; i < TC_NUM; i++)
- prTcqAdjust->acVariation[i] = 0;
- /* 4 <1> If TC resource is not just adjusted, exit directly */
- if (!prQM->fgTcResourcePostAnnealing)
- return;
- /* 4 <2> Adjust TcqStatus according to the updated prQM->au4CurrentTcResource */
- else {
- INT_32 i4TotalExtraQuota = 0;
- INT_32 ai4ExtraQuota[TC_NUM];
- BOOLEAN fgResourceRedistributed = TRUE;
- /* Obtain the free-to-distribute resource */
- for (i = 0; i < TC_NUM; i++) {
- ai4ExtraQuota[i] =
- (INT_32) prTcqStatus->aucMaxNumOfBuffer[i] - (INT_32) prQM->au4CurrentTcResource[i];
- if (ai4ExtraQuota[i] > 0) { /* The resource shall be reallocated to other TCs */
- if (ai4ExtraQuota[i] > prTcqStatus->aucFreeBufferCount[i]) {
- /*
- we have residunt TC resources for the TC:
- EX: aucMaxNumOfBuffer[] = 20, au4CurrentTcResource[] = 5
- ai4ExtraQuota[] = 15, aucFreeBufferCount[] = 10
- so ai4ExtraQuota[] = aucFreeBufferCount[] = 10
- because we available TC resources actually is 10, not 20
- */
- ai4ExtraQuota[i] = prTcqStatus->aucFreeBufferCount[i];
- /*
- FALSE means we can re-do TC resource adjustment in tx done
- at next time, maybe more tx done is finished
- */
- fgResourceRedistributed = FALSE;
- }
- /* accumulate current all available TC resources */
- i4TotalExtraQuota += ai4ExtraQuota[i];
- /* deduce unused TC resources for the TC */
- prTcqAdjust->acVariation[i] = (INT_8) (-ai4ExtraQuota[i]);
- }
- }
- /* Distribute quotas to TCs which need extra resource according to prQM->au4CurrentTcResource */
- for (i = 0; i < TC_NUM; i++) {
- if (ai4ExtraQuota[i] < 0) {
- /* The TC needs extra resources */
- if ((-ai4ExtraQuota[i]) > i4TotalExtraQuota) {
- /* the number of needed extra resources is larger than total available */
- ai4ExtraQuota[i] = (-i4TotalExtraQuota);
- /* wait for next tx done to do adjustment */
- fgResourceRedistributed = FALSE;
- }
- /* decrease the total available */
- i4TotalExtraQuota += ai4ExtraQuota[i];
- /* mark to increase TC resources for the TC */
- prTcqAdjust->acVariation[i] = (INT_8) (-ai4ExtraQuota[i]);
- }
- }
- /* In case some TC is waiting for TX Done, continue to adjust TC quotas upon TX Done */
- /*
- if fgResourceRedistributed == TRUE, it means we will adjust at this time so
- we need to re-adjust TC resources (fgTcResourcePostAnnealing = FALSE).
- */
- prQM->fgTcResourcePostAnnealing = (!fgResourceRedistributed);
- #if QM_PRINT_TC_RESOURCE_CTRL
- DBGLOG(QM, LOUD, "QM: Curr Quota [0]=%u [1]=%u [2]=%u [3]=%u [4]=%u [5]=%u\n",
- prTcqStatus->aucFreeBufferCount[0],
- prTcqStatus->aucFreeBufferCount[1],
- prTcqStatus->aucFreeBufferCount[2],
- prTcqStatus->aucFreeBufferCount[3],
- prTcqStatus->aucFreeBufferCount[4], prTcqStatus->aucFreeBufferCount[5]
- ));
- #endif
- }
- #else
- UINT_32 i;
- for (i = 0; i < TC_NUM; i++)
- prTcqAdjust->acVariation[i] = 0;
- #endif
- }
- #if QM_ADAPTIVE_TC_RESOURCE_CTRL
- /*----------------------------------------------------------------------------*/
- /*!
- * \brief Update the average TX queue length for the TC resource control mechanism
- *
- * \param (none)
- *
- * \return (none)
- */
- /*----------------------------------------------------------------------------*/
- VOID qmUpdateAverageTxQueLen(IN P_ADAPTER_T prAdapter)
- {
- INT_32 u4CurrQueLen, i, k;
- P_STA_RECORD_T prStaRec;
- P_QUE_MGT_T prQM = &prAdapter->rQM;
- /* 4 <1> Update the queue lengths for TC0 to TC3 (skip TC4) and TC5 */
- /* use moving average algorithm to calculate au4AverageQueLen for every TC queue */
- for (i = 0; i < NUM_OF_PER_STA_TX_QUEUES - 1; i++) {
- u4CurrQueLen = 0;
- for (k = 0; k < CFG_NUM_OF_STA_RECORD; k++) {
- prStaRec = &prAdapter->arStaRec[k];
- ASSERT(prStaRec);
- /* If the STA is activated, get the queue length */
- if (prStaRec->fgIsValid &&
- (!prAdapter->rWifiVar.arBssInfo[prStaRec->ucNetTypeIndex].fgIsNetAbsent)
- ) {
- u4CurrQueLen += (prStaRec->arTxQueue[i].u4NumElem);
- }
- }
- if (prQM->au4AverageQueLen[i] == 0) {
- prQM->au4AverageQueLen[i] = (u4CurrQueLen << QM_QUE_LEN_MOVING_AVE_FACTOR); /* *8 */
- } else {
- /* len => len - len/8 = 7/8 * len + new len */
- prQM->au4AverageQueLen[i] -= (prQM->au4AverageQueLen[i] >> QM_QUE_LEN_MOVING_AVE_FACTOR);
- prQM->au4AverageQueLen[i] += (u4CurrQueLen);
- }
- }
- /* Update the queue length for TC5 (BMCAST) */
- u4CurrQueLen = prQM->arTxQueue[TX_QUEUE_INDEX_BMCAST].u4NumElem;
- if (prQM->au4AverageQueLen[TC_NUM - 1] == 0) {
- prQM->au4AverageQueLen[TC_NUM - 1] = (u4CurrQueLen << QM_QUE_LEN_MOVING_AVE_FACTOR);
- } else {
- prQM->au4AverageQueLen[TC_NUM - 1] -=
- (prQM->au4AverageQueLen[TC_NUM - 1] >> QM_QUE_LEN_MOVING_AVE_FACTOR);
- prQM->au4AverageQueLen[TC_NUM - 1] += (u4CurrQueLen);
- }
- /* 4 <2> Adjust TC resource assignment every 3 times */
- /* Check whether it is time to adjust the TC resource assignment */
- if (--prQM->u4TimeToAdjustTcResource == 0) { /* u4TimeToAdjustTcResource = 3 */
- /* The last assignment has not been completely applied */
- if (prQM->fgTcResourcePostAnnealing) {
- /* Upon the next qmUpdateAverageTxQueLen function call, do this check again */
- /* wait for next time to do qmReassignTcResource */
- prQM->u4TimeToAdjustTcResource = 1;
- } else { /* The last assignment has been applied */
- prQM->u4TimeToAdjustTcResource = QM_INIT_TIME_TO_ADJUST_TC_RSC;
- qmReassignTcResource(prAdapter);
- }
- }
- /* Debug */
- #if QM_PRINT_TC_RESOURCE_CTRL
- for (i = 0; i < TC_NUM; i++) {
- if (QM_GET_TX_QUEUE_LEN(prAdapter, i) >= 100) {
- DBGLOG(QM, LOUD, "QM: QueLen [%u %u %u %u %u %u]\n",
- QM_GET_TX_QUEUE_LEN(prAdapter, 0),
- QM_GET_TX_QUEUE_LEN(prAdapter, 1),
- QM_GET_TX_QUEUE_LEN(prAdapter, 2),
- QM_GET_TX_QUEUE_LEN(prAdapter, 3),
- QM_GET_TX_QUEUE_LEN(prAdapter, 4), QM_GET_TX_QUEUE_LEN(prAdapter, 5)
- ));
- break;
- }
- }
- #endif
- }
- /*----------------------------------------------------------------------------*/
- /*!
- * \brief Assign TX resource for each TC according to TX queue length and current assignment
- *
- * \param (none)
- *
- * \return (none)
- */
- /*----------------------------------------------------------------------------*/
- VOID qmReassignTcResource(IN P_ADAPTER_T prAdapter)
- {
- INT_32 i4TotalResourceDemand = 0;
- UINT_32 u4ResidualResource = 0;
- UINT_32 i;
- INT_32 ai4PerTcResourceDemand[TC_NUM];
- UINT_32 u4ShareCount = 0;
- UINT_32 u4Share = 0;
- P_QUE_MGT_T prQM = &prAdapter->rQM;
- /* Note: After the new assignment is obtained, set prQM->fgTcResourcePostAnnealing to TRUE to
- * start the TC-quota adjusting procedure, which will be invoked upon every TX Done
- */
- /* tx done -> nicProcessTxInterrupt() -> nicTxAdjustTcq()
- * -> qmAdjustTcQuotas() -> check fgTcResourcePostAnnealing */
- /* 4 <1> Determine the demands */
- /* Determine the amount of extra resource to fulfill all of the demands */
- for (i = 0; i < TC_NUM; i++) {
- /* Skip TC4, which is not adjustable */
- if (i == TC4_INDEX)
- continue;
- /*
- Define: extra_demand = average que_length (includes all station records) +
- min_reserved_quota -
- current available TC resources
- extra_demand means we need extra TC resources to transmit; other TCs can
- borrow their resources to us?
- */
- ai4PerTcResourceDemand[i] =
- ((UINT_32) (QM_GET_TX_QUEUE_LEN(prAdapter, i)) +
- prQM->au4MinReservedTcResource[i] - prQM->au4CurrentTcResource[i]);
- /* If there are queued packets, allocate extra resource for the TC (for TCP consideration) */
- if (QM_GET_TX_QUEUE_LEN(prAdapter, i))
- ai4PerTcResourceDemand[i] += QM_EXTRA_RESERVED_RESOURCE_WHEN_BUSY; /* 0 */
- /*
- accumulate all needed extra TC resources
- maybe someone need + resource, maybe someone need - resource
- */
- i4TotalResourceDemand += ai4PerTcResourceDemand[i];
- }
- /* 4 <2> Case 1: Demand <= Total Resource */
- if (i4TotalResourceDemand <= 0) {
- /* 4 <2.1> Satisfy every TC */
- /* total TC resources are enough, no extra TC resources is needed */
- /* adjust used TC resources to average TC resources + min reserve TC resources */
- for (i = 0; i < TC_NUM; i++) {
- /* Skip TC4 (not adjustable) */
- if (i == TC4_INDEX)
- continue;
- /*
- the number of resources that one TC releases can be used for
- other TCs
- EX: TC0 au4CurrentTcResource[0] = 10 ai4PerTcResourceDemand[0] = -5
- TC1 au4CurrentTcResource[1] = 5 ai4PerTcResourceDemand[0] = +5
- => TC0 au4CurrentTcResource[0] = 10 + (-5) = 5
- TC1 au4CurrentTcResource[1] = 5 + (+5) = 10
- */
- prQM->au4CurrentTcResource[i] += ai4PerTcResourceDemand[i];
- }
- /* 4 <2.2> Share the residual resource evenly */
- u4ShareCount = (TC_NUM - 1); /* 5, excluding TC4 */
- /*
- EX: i4TotalResourceDemand = -10
- means we have 10 available resources can be used.
- */
- u4ResidualResource = (UINT_32) (-i4TotalResourceDemand);
- u4Share = (u4ResidualResource / u4ShareCount);
- /* share available TC resources to all TCs averagely */
- for (i = 0; i < TC_NUM; i++) {
- /* Skip TC4 (not adjustable) */
- if (i == TC4_INDEX)
- continue;
- /* allocate residual average resources to the TC */
- prQM->au4CurrentTcResource[i] += u4Share;
- /* Every TC is fully satisfied so no need extra resources */
- ai4PerTcResourceDemand[i] = 0;
- /* decrease the allocated resources */
- u4ResidualResource -= u4Share;
- }
- /* if still have available resources, we decide to give them to VO (TC3) queue */
- /* 4 <2.3> Allocate the left resource to TC3 (VO) */
- prQM->au4CurrentTcResource[TC3_INDEX] += (u4ResidualResource);
- }
- /* 4 <3> Case 2: Demand > Total Resource --> Guarantee a minimum amount of resource for each TC */
- else {
- /*
- u4ResidualResource means we at least need to keep
- QM_INITIAL_RESIDUAL_TC_RESOURCE available TC resources
- in 6628, u4ResidualResource = 26, max 28
- */
- u4ResidualResource = QM_INITIAL_RESIDUAL_TC_RESOURCE;
- /* 4 <3.1> Allocated resource amount = minimum of (guaranteed, total demand) */
- for (i = 0; i < TC_NUM; i++) {
- if (i == TC4_INDEX)
- continue; /* Skip TC4 (not adjustable) */
- /* The demand can be fulfilled with the guaranteed resource amount 4 4 6 6 2 4 */
- /*
- ai4PerTcResourceDemand[i] =
- ((UINT_32)(QM_GET_TX_QUEUE_LEN(prAdapter, i)) +
- prQM->au4MinReservedTcResource[i] -
- prQM->au4CurrentTcResource[i]);
- so au4CurrentTcResource + ai4PerTcResourceDemand =
- ((UINT_32)(QM_GET_TX_QUEUE_LEN(prAdapter, i)) +
- prQM->au4MinReservedTcResource[i] =
- current average queue len + min TC resources
- */
- if (prQM->au4CurrentTcResource[i] + ai4PerTcResourceDemand[i] <
- prQM->au4GuaranteedTcResource[i]) {
- /* avg queue len + min reserve still smaller than guarantee so enough */
- prQM->au4CurrentTcResource[i] += ai4PerTcResourceDemand[i];
- /* accumulate available TC resources from the TC */
- u4ResidualResource +=
- (prQM->au4GuaranteedTcResource[i] - prQM->au4CurrentTcResource[i]);
- ai4PerTcResourceDemand[i] = 0;
- }
- /* The demand can not be fulfilled with the guaranteed resource amount */
- else {
- /* means even we use all guarantee resources for the TC is still not enough */
- /*
- guarantee number is always for the TC so extra resource number cannot
- include the guarantee number.
- EX: au4GuaranteedTcResource = 10, au4CurrentTcResource = 5
- ai4PerTcResourceDemand = 6
- ai4PerTcResourceDemand -= (10 - 5) ==> 1
- only need extra 1 TC resouce is enough.
- */
- ai4PerTcResourceDemand[i] -=
- (prQM->au4GuaranteedTcResource[i] - prQM->au4CurrentTcResource[i]);
- /* update current avg TC resource to guarantee number */
- prQM->au4CurrentTcResource[i] = prQM->au4GuaranteedTcResource[i];
- /* count how many TC queues need to get extra resources */
- u4ShareCount++;
- }
- }
- /* 4 <3.2> Allocate the residual resource */
- do {
- /* If there is no resource left, exit directly */
- if (u4ResidualResource == 0)
- break;
- /* This shall not happen */
- if (u4ShareCount == 0) {
- prQM->au4CurrentTcResource[TC1_INDEX] += u4ResidualResource;
- DBGLOG(QM, ERROR, "QM: (Error) u4ShareCount = 0\n");
- break;
- }
- /* Share the residual resource evenly */
- u4Share = (u4ResidualResource / u4ShareCount);
- if (u4Share) {
- for (i = 0; i < TC_NUM; i++) {
- /* Skip TC4 (not adjustable) */
- if (i == TC4_INDEX)
- continue;
- if (ai4PerTcResourceDemand[i] == 0)
- continue;
- if (ai4PerTcResourceDemand[i] - u4Share) {
- /* still not enough but we just can give it u4Share resources */
- prQM->au4CurrentTcResource[i] += u4Share;
- u4ResidualResource -= u4Share;
- ai4PerTcResourceDemand[i] -= u4Share;
- } else {
- /* enough */
- prQM->au4CurrentTcResource[i] += ai4PerTcResourceDemand[i];
- u4ResidualResource -= ai4PerTcResourceDemand[i];
- ai4PerTcResourceDemand[i] = 0;
- }
- }
- }
- if (u4ResidualResource == 0)
- break;
- /* By priority, allocate the left resource that is not divisible by u4Share */
- if (ai4PerTcResourceDemand[TC3_INDEX]) { /* VO */
- prQM->au4CurrentTcResource[TC3_INDEX]++;
- if (--u4ResidualResource == 0)
- break;
- }
- if (ai4PerTcResourceDemand[TC2_INDEX]) { /* VI */
- prQM->au4CurrentTcResource[TC2_INDEX]++;
- if (--u4ResidualResource == 0)
- break;
- }
- if (ai4PerTcResourceDemand[TC5_INDEX]) { /* BMCAST */
- prQM->au4CurrentTcResource[TC5_INDEX]++;
- if (--u4ResidualResource == 0)
- break;
- }
- if (ai4PerTcResourceDemand[TC1_INDEX]) { /* BE */
- prQM->au4CurrentTcResource[TC1_INDEX]++;
- if (--u4ResidualResource == 0)
- break;
- }
- if (ai4PerTcResourceDemand[TC0_INDEX]) { /* BK */
- prQM->au4CurrentTcResource[TC0_INDEX]++;
- if (--u4ResidualResource == 0)
- break;
- }
- /* Allocate the left resource */
- prQM->au4CurrentTcResource[TC3_INDEX] += u4ResidualResource;
- } while (FALSE);
- }
- /* mark the flag that we can start to do TC resource adjustment after TX done handle */
- prQM->fgTcResourcePostAnnealing = TRUE;
- #if QM_PRINT_TC_RESOURCE_CTRL
- /* Debug print */
- DBGLOG(QM, LOUD, "QM: TC Rsc %u %u %u %u %u %u\n",
- prQM->au4CurrentTcResource[0],
- prQM->au4CurrentTcResource[1],
- prQM->au4CurrentTcResource[2],
- prQM->au4CurrentTcResource[3], prQM->au4CurrentTcResource[4], prQM->au4CurrentTcResource[5]
- ));
- #endif
- }
- #endif
- /*----------------------------------------------------------------------------*/
- /* RX-Related Queue Management */
- /*----------------------------------------------------------------------------*/
- /*----------------------------------------------------------------------------*/
- /*!
- * \brief Init Queue Management for RX
- *
- * \param[in] (none)
- *
- * \return (none)
- */
- /*----------------------------------------------------------------------------*/
- VOID qmInitRxQueues(IN P_ADAPTER_T prAdapter)
- {
- /* DbgPrint("QM: Enter qmInitRxQueues()\n"); */
- /* TODO */
- }
- /*----------------------------------------------------------------------------*/
- /*!
- * \brief Handle RX packets (buffer reordering)
- *
- * \param[in] prSwRfbListHead The list of RX packets
- *
- * \return The list of packets which are not buffered for reordering
- */
- /*----------------------------------------------------------------------------*/
- P_SW_RFB_T qmHandleRxPackets(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfbListHead)
- {
- #if CFG_RX_REORDERING_ENABLED
- /* UINT_32 i; */
- P_SW_RFB_T prCurrSwRfb;
- P_SW_RFB_T prNextSwRfb;
- P_HIF_RX_HEADER_T prHifRxHdr;
- QUE_T rReturnedQue;
- PUINT_8 pucEthDestAddr;
- BOOLEAN fgIsBMC;
- /* DbgPrint("QM: Enter qmHandleRxPackets()\n"); */
- DEBUGFUNC("qmHandleRxPackets");
- ASSERT(prSwRfbListHead);
- QUEUE_INITIALIZE(&rReturnedQue);
- prNextSwRfb = prSwRfbListHead;
- do {
- prCurrSwRfb = prNextSwRfb;
- prNextSwRfb = QM_RX_GET_NEXT_SW_RFB(prCurrSwRfb);
- prHifRxHdr = prCurrSwRfb->prHifRxHdr; /* TODO: (Tehuang) Use macro to obtain the pointer */
- /* TODO: (Tehuang) Check if relaying */
- prCurrSwRfb->eDst = RX_PKT_DESTINATION_HOST;
- /* Decide the Destination */
- #if CFG_RX_PKTS_DUMP
- if (prAdapter->rRxCtrl.u4RxPktsDumpTypeMask & BIT(HIF_RX_PKT_TYPE_DATA)) {
- DBGLOG(SW4, INFO, "QM RX DATA: net %u sta idx %u wlan idx %u ssn %u tid %u ptype %u 11 %u\n",
- (UINT_32) HIF_RX_HDR_GET_NETWORK_IDX(prHifRxHdr),
- prHifRxHdr->ucStaRecIdx, prCurrSwRfb->ucWlanIdx,
- (UINT_32) HIF_RX_HDR_GET_SN(prHifRxHdr), /* The new SN of the frame */
- (UINT_32) HIF_RX_HDR_GET_TID(prHifRxHdr),
- prCurrSwRfb->ucPacketType,
- (UINT_32) HIF_RX_HDR_GET_80211_FLAG(prHifRxHdr));
- DBGLOG_MEM8(SW4, TRACE, (PUINT_8) prCurrSwRfb->pvHeader, prCurrSwRfb->u2PacketLen);
- }
- #endif
- fgIsBMC = FALSE;
- if (!HIF_RX_HDR_GET_80211_FLAG(prHifRxHdr)) {
- UINT_8 ucNetTypeIdx;
- P_BSS_INFO_T prBssInfo;
- pucEthDestAddr = prCurrSwRfb->pvHeader;
- ucNetTypeIdx = HIF_RX_HDR_GET_NETWORK_IDX(prHifRxHdr);
- prBssInfo = &(prAdapter->rWifiVar.arBssInfo[ucNetTypeIdx]);
- /* DBGLOG_MEM8(QM, TRACE,prCurrSwRfb->pvHeader, 16); */
- /* */
- if (IS_BMCAST_MAC_ADDR(pucEthDestAddr) && (OP_MODE_ACCESS_POINT != prBssInfo->eCurrentOPMode))
- fgIsBMC = TRUE;
- if (prAdapter->rRxCtrl.rFreeSwRfbList.u4NumElem >
- (CFG_RX_MAX_PKT_NUM - CFG_NUM_OF_QM_RX_PKT_NUM)) {
- if (!IS_BSS_ACTIVE(prBssInfo)) {
- DBGLOG(QM, WARN, "Mark NULL the Packet for inactive Bss %u\n", ucNetTypeIdx);
- prCurrSwRfb->eDst = RX_PKT_DESTINATION_NULL;
- QUEUE_INSERT_TAIL(&rReturnedQue, (P_QUE_ENTRY_T) prCurrSwRfb);
- continue;
- }
- if (OP_MODE_ACCESS_POINT == prBssInfo->eCurrentOPMode) {
- if (IS_BMCAST_MAC_ADDR(pucEthDestAddr))
- prCurrSwRfb->eDst = RX_PKT_DESTINATION_HOST_WITH_FORWARD;
- else if (UNEQUAL_MAC_ADDR(prBssInfo->aucOwnMacAddr, pucEthDestAddr) &&
- bssGetClientByAddress(prBssInfo, pucEthDestAddr))
- prCurrSwRfb->eDst = RX_PKT_DESTINATION_FORWARD;
- /* TODO : need to check the dst mac is valid */
- /* If src mac is invalid, the packet will be freed in fw */
- } /* OP_MODE_ACCESS_POINT */
- #if CFG_SUPPORT_HOTSPOT_2_0
- else if (hs20IsFrameFilterEnabled(prAdapter, prBssInfo) &&
- hs20IsUnsecuredFrame(prAdapter, prBssInfo, prCurrSwRfb)) {
- DBGLOG(QM, WARN,
- "Mark NULL the Packet for Dropped Packet %u\n", ucNetTypeIdx);
- prCurrSwRfb->eDst = RX_PKT_DESTINATION_NULL;
- QUEUE_INSERT_TAIL(&rReturnedQue, (P_QUE_ENTRY_T) prCurrSwRfb);
- continue;
- }
- #endif
- } else {
- /* Dont not occupy other SW RFB */
- DBGLOG(QM, WARN, "Mark NULL the Packet for less Free Sw Rfb\n");
- prCurrSwRfb->eDst = RX_PKT_DESTINATION_NULL;
- QUEUE_INSERT_TAIL(&rReturnedQue, (P_QUE_ENTRY_T) prCurrSwRfb);
- continue;
- }
- }
- #if CFG_SUPPORT_WAPI
- if (prCurrSwRfb->u2PacketLen > ETHER_HEADER_LEN) {
- PUINT_8 pc = (PUINT_8) prCurrSwRfb->pvHeader;
- UINT_16 u2Etype = 0;
- u2Etype = (pc[ETH_TYPE_LEN_OFFSET] << 8) | (pc[ETH_TYPE_LEN_OFFSET + 1]);
- /* for wapi integrity test. WPI_1x packet should be always in non-encrypted mode.
- if we received any WPI(0x88b4) packet that is encrypted, drop here. */
- if (u2Etype == ETH_WPI_1X && HIF_RX_HDR_GET_SEC_MODE(prHifRxHdr) != 0) {
- DBGLOG(QM, INFO, "drop wpi packet with sec mode\n");
- prCurrSwRfb->eDst = RX_PKT_DESTINATION_NULL;
- QUEUE_INSERT_TAIL(&rReturnedQue, (P_QUE_ENTRY_T) prCurrSwRfb);
- continue;
- }
- }
- #endif
- /* BAR frame */
- if (HIF_RX_HDR_GET_BAR_FLAG(prHifRxHdr)) {
- prCurrSwRfb->eDst = RX_PKT_DESTINATION_NULL;
- qmProcessBarFrame(prAdapter, prCurrSwRfb, &rReturnedQue);
- }
- /* Reordering is not required for this packet, return it without buffering */
- else if (!HIF_RX_HDR_GET_REORDER_FLAG(prHifRxHdr) || fgIsBMC) {
- #if 0
- if (!HIF_RX_HDR_GET_80211_FLAG(prHifRxHdr)) {
- UINT_8 ucNetTypeIdx;
- P_BSS_INFO_T prBssInfo;
- pucEthDestAddr = prCurrSwRfb->pvHeader;
- ucNetTypeIdx = HIF_RX_HDR_GET_NETWORK_IDX(prHifRxHdr);
- prBssInfo = &(prAdapter->rWifiVar.arBssInfo[ucNetTypeIdx]);
- if (IS_BMCAST_MAC_ADDR(pucEthDestAddr)
- && (OP_MODE_ACCESS_POINT == prBssInfo->eCurrentOPMode)) {
- prCurrSwRfb->eDst = RX_PKT_DESTINATION_HOST_WITH_FORWARD;
- }
- }
- #endif
- QUEUE_INSERT_TAIL(&rReturnedQue, (P_QUE_ENTRY_T) prCurrSwRfb);
- }
- /* Reordering is required for this packet */
- else {
- /* If this packet should dropped or indicated to the host immediately,
- * it should be enqueued into the rReturnedQue with specific flags. If
- * this packet should be buffered for reordering, it should be enqueued
- * into the reordering queue in the STA_REC rather than into the
- * rReturnedQue.
- */
- qmProcessPktWithReordering(prAdapter, prCurrSwRfb, &rReturnedQue);
- }
- } while (prNextSwRfb);
- /* RX_PKT_DESTINATION_HOST_WITH_FORWARD or RX_PKT_DESTINATION_FORWARD */
- /* The returned list of SW_RFBs must end with a NULL pointer */
- if (QUEUE_IS_NOT_EMPTY(&rReturnedQue))
- QM_TX_SET_NEXT_MSDU_INFO((P_SW_RFB_T) QUEUE_GET_TAIL(&rReturnedQue), NULL);
- return (P_SW_RFB_T) QUEUE_GET_HEAD(&rReturnedQue);
- #else
- /* DbgPrint("QM: Enter qmHandleRxPackets()\n"); */
- return prSwRfbListHead;
- #endif
- }
- /*----------------------------------------------------------------------------*/
- /*!
- * \brief Reorder the received packet
- *
- * \param[in] prSwRfb The RX packet to process
- * \param[out] prReturnedQue The queue for indicating packets
- *
- * \return (none)
- */
- /*----------------------------------------------------------------------------*/
- VOID qmProcessPktWithReordering(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb, OUT P_QUE_T prReturnedQue)
- {
- P_STA_RECORD_T prStaRec;
- P_HIF_RX_HEADER_T prHifRxHdr;
- P_RX_BA_ENTRY_T prReorderQueParm;
- UINT_32 u4SeqNo;
- UINT_32 u4WinStart;
- UINT_32 u4WinEnd;
- P_QUE_T prReorderQue;
- /* P_SW_RFB_T prReorderedSwRfb; */
- BOOLEAN fgIsBaTimeout;
- DEBUGFUNC("qmProcessPktWithReordering");
- if ((prSwRfb == NULL) || (prReturnedQue == NULL) || (prSwRfb->prHifRxHdr == NULL)) {
- ASSERT(FALSE);
- return;
- }
- prHifRxHdr = prSwRfb->prHifRxHdr;
- prSwRfb->ucStaRecIdx = prHifRxHdr->ucStaRecIdx;
- prSwRfb->u2SSN = HIF_RX_HDR_GET_SN(prHifRxHdr); /* The new SN of the frame */
- prSwRfb->ucTid = (UINT_8) (HIF_RX_HDR_GET_TID(prHifRxHdr));
- /* prSwRfb->eDst = RX_PKT_DESTINATION_HOST; */
- /* Incorrect STA_REC index */
- if (prSwRfb->ucStaRecIdx >= CFG_NUM_OF_STA_RECORD) {
- prSwRfb->eDst = RX_PKT_DESTINATION_NULL;
- QUEUE_INSERT_TAIL(prReturnedQue, (P_QUE_ENTRY_T) prSwRfb);
- DBGLOG(QM, WARN, "Reordering for a NULL STA_REC, ucStaRecIdx = %d\n", prSwRfb->ucStaRecIdx);
- /* ASSERT(0); */
- return;
- }
- /* Check whether the STA_REC is activated */
- prStaRec = &(prAdapter->arStaRec[prSwRfb->ucStaRecIdx]);
- ASSERT(prStaRec);
- #if 0
- if (!(prStaRec->fgIsValid)) {
- /* TODO: (Tehuang) Handle the Host-FW sync issue. */
- prSwRfb->eDst = RX_PKT_DESTINATION_NULL;
- QUEUE_INSERT_TAIL(prReturnedQue, (P_QUE_ENTRY_T) prSwRfb);
- DBGLOG(QM, WARN, "Reordering for an invalid STA_REC\n");
- /* ASSERT(0); */
- return;
- }
- #endif
- /* Check whether the BA agreement exists */
- prReorderQueParm = ((prStaRec->aprRxReorderParamRefTbl)[prSwRfb->ucTid]);
- if (!prReorderQueParm) {
- /* TODO: (Tehuang) Handle the Host-FW sync issue. */
- prSwRfb->eDst = RX_PKT_DESTINATION_NULL;
- QUEUE_INSERT_TAIL(prReturnedQue, (P_QUE_ENTRY_T) prSwRfb);
- DBGLOG(QM, WARN, "Reordering for a NULL ReorderQueParm\n");
- /* ASSERT(0); */
- return;
- }
- /* Start to reorder packets */
- u4SeqNo = (UINT_32) (prSwRfb->u2SSN);
- prReorderQue = &(prReorderQueParm->rReOrderQue);
- u4WinStart = (UINT_32) (prReorderQueParm->u2WinStart);
- u4WinEnd = (UINT_32) (prReorderQueParm->u2WinEnd);
- /* Debug */
- /* DbgPrint("QM:(R)[%d](%ld){%ld,%ld}\n", prSwRfb->ucTid, u4SeqNo, u4WinStart, u4WinEnd); */
- /* Case 1: Fall within */
- if /* 0 - start - sn - end - 4095 */
- (((u4WinStart <= u4SeqNo) && (u4SeqNo <= u4WinEnd))
- /* 0 - end - start - sn - 4095 */
- || ((u4WinEnd < u4WinStart) && (u4WinStart <= u4SeqNo))
- /* 0 - sn - end - start - 4095 */
- || ((u4SeqNo <= u4WinEnd) && (u4WinEnd < u4WinStart))) {
- qmInsertFallWithinReorderPkt(prSwRfb, prReorderQueParm, prReturnedQue);
- #if QM_RX_WIN_SSN_AUTO_ADVANCING
- if (prReorderQueParm->fgIsWaitingForPktWithSsn) {
- /* Let the first received packet pass the reorder check */
- DBGLOG(QM, LOUD, "QM:(A)[%d](%u){%u,%u}\n", prSwRfb->ucTid, u4SeqNo, u4WinStart, u4WinEnd);
- prReorderQueParm->u2WinStart = (UINT_16) u4SeqNo;
- prReorderQueParm->u2WinEnd =
- ((prReorderQueParm->u2WinStart) + (prReorderQueParm->u2WinSize) - 1) % MAX_SEQ_NO_COUNT;
- prReorderQueParm->fgIsWaitingForPktWithSsn = FALSE;
- }
- #endif
- if (qmPopOutDueToFallWithin(prAdapter, prReorderQueParm, prReturnedQue, &fgIsBaTimeout) == FALSE)
- STATS_RX_REORDER_HOLE_INC(prStaRec); /* record hole count */
- STATS_RX_REORDER_HOLE_TIMEOUT_INC(prStaRec, fgIsBaTimeout);
- }
- /* Case 2: Fall ahead */
- else if
- /* 0 - start - end - sn - (start+2048) - 4095 */
- (((u4WinStart < u4WinEnd)
- && (u4WinEnd < u4SeqNo)
- && (u4SeqNo < (u4WinStart + HALF_SEQ_NO_COUNT)))
- /* 0 - sn - (start+2048) - start - end - 4095 */
- || ((u4SeqNo < u4WinStart)
- && (u4WinStart < u4WinEnd)
- && ((u4SeqNo + MAX_SEQ_NO_COUNT) < (u4WinStart + HALF_SEQ_NO_COUNT)))
- /* 0 - end - sn - (start+2048) - start - 4095 */
- || ((u4WinEnd < u4SeqNo)
- && (u4SeqNo < u4WinStart)
- && ((u4SeqNo + MAX_SEQ_NO_COUNT) < (u4WinStart + HALF_SEQ_NO_COUNT)))) {
- #if QM_RX_WIN_SSN_AUTO_ADVANCING
- if (prReorderQueParm->fgIsWaitingForPktWithSsn)
- prReorderQueParm->fgIsWaitingForPktWithSsn = FALSE;
- #endif
- qmInsertFallAheadReorderPkt(prSwRfb, prReorderQueParm, prReturnedQue);
- /* Advance the window after inserting a new tail */
- prReorderQueParm->u2WinEnd = (UINT_16) u4SeqNo;
- prReorderQueParm->u2WinStart =
- (((prReorderQueParm->u2WinEnd) - (prReorderQueParm->u2WinSize) + MAX_SEQ_NO_COUNT + 1)
- % MAX_SEQ_NO_COUNT);
- qmPopOutDueToFallAhead(prAdapter, prReorderQueParm, prReturnedQue);
- STATS_RX_REORDER_FALL_AHEAD_INC(prStaRec);
- }
- /* Case 3: Fall behind */
- else {
- #if QM_RX_WIN_SSN_AUTO_ADVANCING
- #if QM_RX_INIT_FALL_BEHIND_PASS
- if (prReorderQueParm->fgIsWaitingForPktWithSsn) {
- /* ?? prSwRfb->eDst = RX_PKT_DESTINATION_HOST; */
- QUEUE_INSERT_TAIL(prReturnedQue, (P_QUE_ENTRY_T) prSwRfb);
- /* DbgPrint("QM:(P)[%d](%ld){%ld,%ld}\n", prSwRfb->ucTid, u4SeqNo, u4WinStart, u4WinEnd); */
- return;
- }
- #endif
- #endif
- STATS_RX_REORDER_FALL_BEHIND_INC(prStaRec);
- /* An erroneous packet */
- prSwRfb->eDst = RX_PKT_DESTINATION_NULL;
- QUEUE_INSERT_TAIL(prReturnedQue, (P_QUE_ENTRY_T) prSwRfb);
- /* DbgPrint("QM:(D)[%d](%ld){%ld,%ld}\n", prSwRfb->ucTid, u4SeqNo, u4WinStart, u4WinEnd); */
- return;
- }
- return;
- }
- VOID qmProcessBarFrame(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb, OUT P_QUE_T prReturnedQue)
- {
- P_STA_RECORD_T prStaRec;
- P_HIF_RX_HEADER_T prHifRxHdr;
- P_RX_BA_ENTRY_T prReorderQueParm;
- UINT_32 u4SSN;
- UINT_32 u4WinStart;
- UINT_32 u4WinEnd;
- P_QUE_T prReorderQue;
- /* P_SW_RFB_T prReorderedSwRfb; */
- if ((prSwRfb == NULL) || (prReturnedQue == NULL) || (prSwRfb->prHifRxHdr == NULL)) {
- ASSERT(FALSE);
- return;
- }
- prHifRxHdr = prSwRfb->prHifRxHdr;
- prSwRfb->ucStaRecIdx = prHifRxHdr->ucStaRecIdx;
- prSwRfb->u2SSN = HIF_RX_HDR_GET_SN(prHifRxHdr); /* The new SSN */
- prSwRfb->ucTid = (UINT_8) (HIF_RX_HDR_GET_TID(prHifRxHdr));
- prSwRfb->eDst = RX_PKT_DESTINATION_NULL;
- QUEUE_INSERT_TAIL(prReturnedQue, (P_QUE_ENTRY_T) prSwRfb);
- /* Incorrect STA_REC index */
- if (prSwRfb->ucStaRecIdx >= CFG_NUM_OF_STA_RECORD) {
- DBGLOG(QM, WARN, "QM: (Warning) BAR for a NULL STA_REC, ucStaRecIdx = %d\n", prSwRfb->ucStaRecIdx);
- /* ASSERT(0); */
- return;
- }
- /* Check whether the STA_REC is activated */
- prStaRec = &(prAdapter->arStaRec[prSwRfb->ucStaRecIdx]);
- ASSERT(prStaRec);
- #if 0
- if (!(prStaRec->fgIsValid)) {
- /* TODO: (Tehuang) Handle the Host-FW sync issue. */
- DbgPrint("QM: (Warning) BAR for an invalid STA_REC\n");
- /* ASSERT(0); */
- return;
- }
- #endif
- /* Check whether the BA agreement exists */
- prReorderQueParm = ((prStaRec->aprRxReorderParamRefTbl)[prSwRfb->ucTid]);
- if (!prReorderQueParm) {
- /* TODO: (Tehuang) Handle the Host-FW sync issue. */
- DBGLOG(QM, WARN, "QM: (Warning) BAR for a NULL ReorderQueParm\n");
- /* ASSERT(0); */
- return;
- }
- u4SSN = (UINT_32) (prSwRfb->u2SSN);
- prReorderQue = &(prReorderQueParm->rReOrderQue);
- u4WinStart = (UINT_32) (prReorderQueParm->u2WinStart);
- u4WinEnd = (UINT_32) (prReorderQueParm->u2WinEnd);
- if (qmCompareSnIsLessThan(u4WinStart, u4SSN)) {
- prReorderQueParm->u2WinStart = (UINT_16) u4SSN;
- prReorderQueParm->u2WinEnd =
- ((prReorderQueParm->u2WinStart) + (prReorderQueParm->u2WinSize) - 1) % MAX_SEQ_NO_COUNT;
- DBGLOG(QM, TRACE,
- "QM:(BAR)[%d](%u){%d,%d}\n", prSwRfb->ucTid, u4SSN, prReorderQueParm->u2WinStart,
- prReorderQueParm->u2WinEnd);
- qmPopOutDueToFallAhead(prAdapter, prReorderQueParm, prReturnedQue);
- } else {
- DBGLOG(QM, TRACE, "QM:(BAR)(%d)(%u){%u,%u}\n", prSwRfb->ucTid, u4SSN, u4WinStart, u4WinEnd);
- }
- }
- VOID qmInsertFallWithinReorderPkt(IN P_SW_RFB_T prSwRfb, IN P_RX_BA_ENTRY_T prReorderQueParm, OUT P_QUE_T prReturnedQue)
- {
- P_SW_RFB_T prExaminedQueuedSwRfb;
- P_QUE_T prReorderQue;
- ASSERT(prSwRfb);
- ASSERT(prReorderQueParm);
- ASSERT(prReturnedQue);
- prReorderQue = &(prReorderQueParm->rReOrderQue);
- prExaminedQueuedSwRfb = (P_SW_RFB_T) QUEUE_GET_HEAD(prReorderQue);
- /* There are no packets queued in the Reorder Queue */
- if (prExaminedQueuedSwRfb == NULL) {
- ((P_QUE_ENTRY_T) prSwRfb)->prPrev = NULL;
- ((P_QUE_ENTRY_T) prSwRfb)->prNext = NULL;
- prReorderQue->prHead = (P_QUE_ENTRY_T) prSwRfb;
- prReorderQue->prTail = (P_QUE_ENTRY_T) prSwRfb;
- prReorderQue->u4NumElem++;
- }
- /* Determine the insert position */
- else {
- do {
- /* Case 1: Terminate. A duplicate packet */
- if (((prExaminedQueuedSwRfb->u2SSN) == (prSwRfb->u2SSN))) {
- prSwRfb->eDst = RX_PKT_DESTINATION_NULL;
- QUEUE_INSERT_TAIL(prReturnedQue, (P_QUE_ENTRY_T) prSwRfb);
- return;
- }
- /* Case 2: Terminate. The insert point is found */
- else if (qmCompareSnIsLessThan((prSwRfb->u2SSN), (prExaminedQueuedSwRfb->u2SSN)))
- break;
- /* Case 3: Insert point not found. Check the next SW_RFB in the Reorder Queue */
- else
- prExaminedQueuedSwRfb = (P_SW_RFB_T) (((P_QUE_ENTRY_T) prExaminedQueuedSwRfb)->prNext);
- } while (prExaminedQueuedSwRfb);
- /* Update the Reorder Queue Parameters according to the found insert position */
- if (prExaminedQueuedSwRfb == NULL) {
- /* The received packet shall be placed at the tail */
- ((P_QUE_ENTRY_T) prSwRfb)->prPrev = prReorderQue->prTail;
- ((P_QUE_ENTRY_T) prSwRfb)->prNext = NULL;
- (prReorderQue->prTail)->prNext = (P_QUE_ENTRY_T) (prSwRfb);
- prReorderQue->prTail = (P_QUE_ENTRY_T) (prSwRfb);
- } else {
- ((P_QUE_ENTRY_T) prSwRfb)->prPrev = ((P_QUE_ENTRY_T) prExaminedQueuedSwRfb)->prPrev;
- ((P_QUE_ENTRY_T) prSwRfb)->prNext = (P_QUE_ENTRY_T) prExaminedQueuedSwRfb;
- if (((P_QUE_ENTRY_T) prExaminedQueuedSwRfb) == (prReorderQue->prHead)) {
- /* The received packet will become the head */
- prReorderQue->prHead = (P_QUE_ENTRY_T) prSwRfb;
- } else {
- (((P_QUE_ENTRY_T) prExaminedQueuedSwRfb)->prPrev)->prNext = (P_QUE_ENTRY_T) prSwRfb;
- }
- ((P_QUE_ENTRY_T) prExaminedQueuedSwRfb)->prPrev = (P_QUE_ENTRY_T) prSwRfb;
- }
- prReorderQue->u4NumElem++;
- }
- }
- VOID qmInsertFallAheadReorderPkt(IN P_SW_RFB_T prSwRfb, IN P_RX_BA_ENTRY_T prReorderQueParm, OUT P_QUE_T prReturnedQue)
- {
- P_QUE_T prReorderQue;
- ASSERT(prSwRfb);
- ASSERT(prReorderQueParm);
- ASSERT(prReturnedQue);
- prReorderQue = &(prReorderQueParm->rReOrderQue);
- /* There are no packets queued in the Reorder Queue */
- if (QUEUE_IS_EMPTY(prReorderQue)) {
- ((P_QUE_ENTRY_T) prSwRfb)->prPrev = NULL;
- ((P_QUE_ENTRY_T) prSwRfb)->prNext = NULL;
- prReorderQue->prHead = (P_QUE_ENTRY_T) prSwRfb;
- } else {
- ((P_QUE_ENTRY_T) prSwRfb)->prPrev = prReorderQue->prTail;
- ((P_QUE_ENTRY_T) prSwRfb)->prNext = NULL;
- (prReorderQue->prTail)->prNext = (P_QUE_ENTRY_T) (prSwRfb);
- }
- prReorderQue->prTail = (P_QUE_ENTRY_T) prSwRfb;
- prReorderQue->u4NumElem++;
- }
- BOOLEAN
- qmPopOutDueToFallWithin(P_ADAPTER_T prAdapter, IN P_RX_BA_ENTRY_T prReorderQueParm,
- OUT P_QUE_T prReturnedQue, OUT BOOLEAN *fgIsTimeout)
- {
- P_SW_RFB_T prReorderedSwRfb;
- P_QUE_T prReorderQue;
- BOOLEAN fgDequeuHead, fgMissing;
- OS_SYSTIME rCurrentTime, *prMissTimeout;
- prReorderQue = &(prReorderQueParm->rReOrderQue);
- *fgIsTimeout = FALSE;
- fgMissing = FALSE;
- rCurrentTime = 0;
- prMissTimeout = &(g_arMissTimeout[prReorderQueParm->ucStaRecIdx][prReorderQueParm->ucTid]);
- if ((*prMissTimeout)) {
- fgMissing = TRUE;
- GET_CURRENT_SYSTIME(&rCurrentTime);
- }
- /* Check whether any packet can be indicated to the higher layer */
- while (TRUE) {
- if (QUEUE_IS_EMPTY(prReorderQue))
- break;
- /* Always examine the head packet */
- prReorderedSwRfb = (P_SW_RFB_T) QUEUE_GET_HEAD(prReorderQue);
- fgDequeuHead = FALSE;
- /* SN == WinStart, so the head packet shall be indicated (advance the window) */
- if ((prReorderedSwRfb->u2SSN) == (prReorderQueParm->u2WinStart)) {
- fgDequeuHead = TRUE;
- prReorderQueParm->u2WinStart = (((prReorderedSwRfb->u2SSN) + 1) % MAX_SEQ_NO_COUNT);
- }
- /* SN > WinStart, break to update WinEnd */
- else {
- /* Start bubble timer */
- if (!prReorderQueParm->fgHasBubble) {
- cnmTimerStartTimer(prAdapter,
- &(prReorderQueParm->rReorderBubbleTimer),
- QM_RX_BA_ENTRY_MISS_TIMEOUT_MS);
- prReorderQueParm->fgHasBubble = TRUE;
- prReorderQueParm->u2FirstBubbleSn = prReorderQueParm->u2WinStart;
- DBGLOG(QM, TRACE,
- "QM:Bub Timer STA[%u] TID[%u] BubSN[%u] Win{%d, %d}\n",
- prReorderQueParm->ucStaRecIdx, prReorderedSwRfb->ucTid,
- prReorderQueParm->u2FirstBubbleSn,
- prReorderQueParm->u2WinStart, prReorderQueParm->u2WinEnd);
- }
- if ((fgMissing == TRUE) &&
- CHECK_FOR_TIMEOUT(rCurrentTime, (*prMissTimeout),
- MSEC_TO_SYSTIME(QM_RX_BA_ENTRY_MISS_TIMEOUT_MS))) {
- DBGLOG(QM, TRACE,
- "QM:RX BA Timout Next Tid %d SSN %d\n", prReorderQueParm->ucTid,
- prReorderedSwRfb->u2SSN);
- fgDequeuHead = TRUE;
- prReorderQueParm->u2WinStart = (((prReorderedSwRfb->u2SSN) + 1) % MAX_SEQ_NO_COUNT);
- fgMissing = FALSE;
- *fgIsTimeout = TRUE;
- } else
- break;
- }
- /* Dequeue the head packet */
- if (fgDequeuHead) {
- if (((P_QUE_ENTRY_T) prReorderedSwRfb)->prNext == NULL) {
- prReorderQue->prHead = NULL;
- prReorderQue->prTail = NULL;
- } else {
- prReorderQue->prHead = ((P_QUE_ENTRY_T) prReorderedSwRfb)->prNext;
- (((P_QUE_ENTRY_T) prReorderedSwRfb)->prNext)->prPrev = NULL;
- }
- prReorderQue->u4NumElem--;
- /* DbgPrint("QM: [%d] %d (%d)\n",
- prReorderQueParm->ucTid,
- prReorderedSwRfb->u2PacketLen,
- prReorderedSwRfb->u2SSN); */
- QUEUE_INSERT_TAIL(prReturnedQue, (P_QUE_ENTRY_T) prReorderedSwRfb);
- }
- }
- if (QUEUE_IS_EMPTY(prReorderQue))
- *prMissTimeout = 0;
- else {
- if (fgMissing == FALSE)
- GET_CURRENT_SYSTIME(prMissTimeout);
- }
- /* After WinStart has been determined, update the WinEnd */
- prReorderQueParm->u2WinEnd =
- (((prReorderQueParm->u2WinStart) + (prReorderQueParm->u2WinSize) - 1) % MAX_SEQ_NO_COUNT);
- return QUEUE_IS_EMPTY(prReorderQue);
- }
- VOID qmPopOutDueToFallAhead(P_ADAPTER_T prAdapter, IN P_RX_BA_ENTRY_T prReorderQueParm, OUT P_QUE_T prReturnedQue)
- {
- P_SW_RFB_T prReorderedSwRfb;
- P_QUE_T prReorderQue;
- BOOLEAN fgDequeuHead;
- prReorderQue = &(prReorderQueParm->rReOrderQue);
- /* Check whether any packet can be indicated to the higher layer */
- while (TRUE) {
- if (QUEUE_IS_EMPTY(prReorderQue))
- break;
- /* Always examine the head packet */
- prReorderedSwRfb = (P_SW_RFB_T) QUEUE_GET_HEAD(prReorderQue);
- fgDequeuHead = FALSE;
- /* SN == WinStart, so the head packet shall be indicated (advance the window) */
- if ((prReorderedSwRfb->u2SSN) == (prReorderQueParm->u2WinStart)) {
- fgDequeuHead = TRUE;
- prReorderQueParm->u2WinStart = (((prReorderedSwRfb->u2SSN) + 1) % MAX_SEQ_NO_COUNT);
- }
- /* SN < WinStart, so the head packet shall be indicated (do not advance the window) */
- else if (qmCompareSnIsLessThan((UINT_32) (prReorderedSwRfb->u2SSN),
- (UINT_32) (prReorderQueParm->u2WinStart)))
- fgDequeuHead = TRUE;
- /* SN > WinStart, break to update WinEnd */
- else {
- /* Start bubble timer */
- if (!prReorderQueParm->fgHasBubble) {
- cnmTimerStartTimer(prAdapter,
- &(prReorderQueParm->rReorderBubbleTimer),
- QM_RX_BA_ENTRY_MISS_TIMEOUT_MS);
- prReorderQueParm->fgHasBubble = TRUE;
- prReorderQueParm->u2FirstBubbleSn = prReorderQueParm->u2WinStart;
- DBGLOG(QM, TRACE,
- "QM:(Bub Timer) STA[%u] TID[%u] BubSN[%u] Win{%d, %d}\n",
- prReorderQueParm->ucStaRecIdx, prReorderedSwRfb->ucTid,
- prReorderQueParm->u2FirstBubbleSn,
- prReorderQueParm->u2WinStart, prReorderQueParm->u2WinEnd);
- }
- break;
- }
- /* Dequeue the head packet */
- if (fgDequeuHead) {
- if (((P_QUE_ENTRY_T) prReorderedSwRfb)->prNext == NULL) {
- prReorderQue->prHead = NULL;
- prReorderQue->prTail = NULL;
- } else {
- prReorderQue->prHead = ((P_QUE_ENTRY_T) prReorderedSwRfb)->prNext;
- (((P_QUE_ENTRY_T) prReorderedSwRfb)->prNext)->prPrev = NULL;
- }
- prReorderQue->u4NumElem--;
- /* DbgPrint("QM: [%d] %d (%d)\n", */
- /* prReorderQueParm->ucTid, prReorderedSwRfb->u2PacketLen, prReorderedSwRfb->u2SSN); */
- QUEUE_INSERT_TAIL(prReturnedQue, (P_QUE_ENTRY_T) prReorderedSwRfb);
- }
- }
- /* After WinStart has been determined, update the WinEnd */
- prReorderQueParm->u2WinEnd =
- (((prReorderQueParm->u2WinStart) + (prReorderQueParm->u2WinSize) - 1) % MAX_SEQ_NO_COUNT);
- }
- BOOLEAN qmCompareSnIsLessThan(IN UINT_32 u4SnLess, IN UINT_32 u4SnGreater)
- {
- /* 0 <---> SnLess <--(gap>2048)--> SnGreater : SnLess > SnGreater */
- if ((u4SnLess + HALF_SEQ_NO_COUNT) <= u4SnGreater) /* Shall be <= */
- return FALSE;
- /* 0 <---> SnGreater <--(gap>2048)--> SnLess : SnLess < SnGreater */
- else if ((u4SnGreater + HALF_SEQ_NO_COUNT) < u4SnLess)
- return TRUE;
- /* 0 <---> SnGreater <--(gap<2048)--> SnLess : SnLess > SnGreater */
- /* 0 <---> SnLess <--(gap<2048)--> SnGreater : SnLess < SnGreater */
- else if (u4SnLess < u4SnGreater)
- return TRUE;
- else
- return FALSE;
- }
- /*----------------------------------------------------------------------------*/
- /*!
- * \brief Handle Mailbox RX messages
- *
- * \param[in] prMailboxRxMsg The received Mailbox message from the FW
- *
- * \return (none)
- */
- /*----------------------------------------------------------------------------*/
- VOID qmHandleMailboxRxMessage(IN MAILBOX_MSG_T prMailboxRxMsg)
- {
- /* DbgPrint("QM: Enter qmHandleMailboxRxMessage()\n"); */
- /* TODO */
- }
- /*----------------------------------------------------------------------------*/
- /*!
- * \brief Handle ADD RX BA Event from the FW
- *
- * \param[in] prAdapter Adapter pointer
- * \param[in] prEvent The event packet from the FW
- *
- * \return (none)
- */
- /*----------------------------------------------------------------------------*/
- VOID qmHandleEventRxAddBa(IN P_ADAPTER_T prAdapter, IN P_WIFI_EVENT_T prEvent)
- {
- P_EVENT_RX_ADDBA_T prEventRxAddBa;
- P_STA_RECORD_T prStaRec;
- UINT_32 u4Tid;
- UINT_32 u4WinSize;
- DBGLOG(QM, INFO, "QM:Event +RxBa\n");
- prEventRxAddBa = (P_EVENT_RX_ADDBA_T) prEvent;
- prStaRec = QM_GET_STA_REC_PTR_FROM_INDEX(prAdapter, prEventRxAddBa->ucStaRecIdx);
- if (!prStaRec) {
- /* Invalid STA_REC index, discard the event packet */
- /* ASSERT(0); */
- DBGLOG(QM, WARN, "QM: (Warning) RX ADDBA Event for a NULL STA_REC\n");
- return;
- }
- #if 0
- if (!(prStaRec->fgIsValid)) {
- /* TODO: (Tehuang) Handle the Host-FW synchronization issue */
- DBGLOG(QM, WARN, "QM: (Warning) RX ADDBA Event for an invalid STA_REC\n");
- /* ASSERT(0); */
- /* return; */
- }
- #endif
- u4Tid = (((prEventRxAddBa->u2BAParameterSet) & BA_PARAM_SET_TID_MASK)
- >> BA_PARAM_SET_TID_MASK_OFFSET);
- u4WinSize = (((prEventRxAddBa->u2BAParameterSet) & BA_PARAM_SET_BUFFER_SIZE_MASK)
- >> BA_PARAM_SET_BUFFER_SIZE_MASK_OFFSET);
- if (!qmAddRxBaEntry(prAdapter,
- prStaRec->ucIndex,
- (UINT_8) u4Tid,
- (prEventRxAddBa->u2BAStartSeqCtrl >> OFFSET_BAR_SSC_SN), (UINT_16) u4WinSize)) {
- /* FW shall ensure the availabiilty of the free-to-use BA entry */
- DBGLOG(QM, ERROR, "QM: (Error) qmAddRxBaEntry() failure\n");
- ASSERT(0);
- }
- }
- /*----------------------------------------------------------------------------*/
- /*!
- * \brief Handle DEL RX BA Event from the FW
- *
- * \param[in] prAdapter Adapter pointer
- * \param[in] prEvent The event packet from the FW
- *
- * \return (none)
- */
- /*----------------------------------------------------------------------------*/
- VOID qmHandleEventRxDelBa(IN P_ADAPTER_T prAdapter, IN P_WIFI_EVENT_T prEvent)
- {
- P_EVENT_RX_DELBA_T prEventRxDelBa;
- P_STA_RECORD_T prStaRec;
- /* DbgPrint("QM:Event -RxBa\n"); */
- prEventRxDelBa = (P_EVENT_RX_DELBA_T) prEvent;
- prStaRec = QM_GET_STA_REC_PTR_FROM_INDEX(prAdapter, prEventRxDelBa->ucStaRecIdx);
- if (!prStaRec)
- /* Invalid STA_REC index, discard the event packet */
- /* ASSERT(0); */
- return;
- #if 0
- if (!(prStaRec->fgIsValid))
- /* TODO: (Tehuang) Handle the Host-FW synchronization issue */
- /* ASSERT(0); */
- return;
- #endif
- qmDelRxBaEntry(prAdapter, prStaRec->ucIndex, prEventRxDelBa->ucTid, TRUE);
- }
- P_RX_BA_ENTRY_T qmLookupRxBaEntry(IN P_ADAPTER_T prAdapter, UINT_8 ucStaRecIdx, UINT_8 ucTid)
- {
- int i;
- P_QUE_MGT_T prQM = &prAdapter->rQM;
- /* DbgPrint("QM: Enter qmLookupRxBaEntry()\n"); */
- for (i = 0; i < CFG_NUM_OF_RX_BA_AGREEMENTS; i++) {
- if (prQM->arRxBaTable[i].fgIsValid) {
- if ((prQM->arRxBaTable[i].ucStaRecIdx == ucStaRecIdx) && (prQM->arRxBaTable[i].ucTid == ucTid))
- return &prQM->arRxBaTable[i];
- }
- }
- return NULL;
- }
- BOOLEAN
- qmAddRxBaEntry(IN P_ADAPTER_T prAdapter,
- IN UINT_8 ucStaRecIdx, IN UINT_8 ucTid, IN UINT_16 u2WinStart, IN UINT_16 u2WinSize)
- {
- int i;
- P_RX_BA_ENTRY_T prRxBaEntry = NULL;
- P_STA_RECORD_T prStaRec;
- P_QUE_MGT_T prQM = &prAdapter->rQM;
- ASSERT(ucStaRecIdx < CFG_NUM_OF_STA_RECORD);
- if (ucStaRecIdx >= CFG_NUM_OF_STA_RECORD) {
- /* Invalid STA_REC index, discard the event packet */
- DBGLOG(QM, WARN, "QM: (WARNING) RX ADDBA Event for a invalid ucStaRecIdx = %d\n", ucStaRecIdx);
- return FALSE;
- }
- prStaRec = &prAdapter->arStaRec[ucStaRecIdx];
- ASSERT(prStaRec);
- /* if(!(prStaRec->fgIsValid)){ */
- /* DbgPrint("QM: (WARNING) Invalid STA when adding an RX BA\n"); */
- /* return FALSE; */
- /* } */
- /* 4 <1> Delete before adding */
- /* Remove the BA entry for the same (STA, TID) tuple if it exists */
- if (qmLookupRxBaEntry(prAdapter, ucStaRecIdx, ucTid))
- qmDelRxBaEntry(prAdapter, ucStaRecIdx, ucTid, TRUE); /* prQM->ucRxBaCount-- */
- /* 4 <2> Add a new BA entry */
- /* No available entry to store the BA agreement info. Retrun FALSE. */
- if (prQM->ucRxBaCount >= CFG_NUM_OF_RX_BA_AGREEMENTS) {
- DBGLOG(QM, ERROR, "QM: **failure** (limited resource, ucRxBaCount=%d)\n", prQM->ucRxBaCount);
- return FALSE;
- }
- /* Find the free-to-use BA entry */
- for (i = 0; i < CFG_NUM_OF_RX_BA_AGREEMENTS; i++) {
- if (!prQM->arRxBaTable[i].fgIsValid) {
- prRxBaEntry = &(prQM->arRxBaTable[i]);
- prQM->ucRxBaCount++;
- DBGLOG(QM, LOUD, "QM: ucRxBaCount=%d\n", prQM->ucRxBaCount);
- break;
- }
- }
- /* If a free-to-use entry is found, configure it and associate it with the STA_REC */
- u2WinSize += CFG_RX_BA_INC_SIZE;
- if (prRxBaEntry) {
- prRxBaEntry->ucStaRecIdx = ucStaRecIdx;
- prRxBaEntry->ucTid = ucTid;
- prRxBaEntry->u2WinStart = u2WinStart;
- prRxBaEntry->u2WinSize = u2WinSize;
- prRxBaEntry->u2WinEnd = ((u2WinStart + u2WinSize - 1) % MAX_SEQ_NO_COUNT);
- prRxBaEntry->fgIsValid = TRUE;
- prRxBaEntry->fgIsWaitingForPktWithSsn = TRUE;
- prRxBaEntry->fgHasBubble = FALSE;
- g_arMissTimeout[ucStaRecIdx][ucTid] = 0;
- DBGLOG(QM, INFO, "QM: +RxBA(STA=%d TID=%d WinStart=%d WinEnd=%d WinSize=%d)\n",
- ucStaRecIdx, ucTid,
- prRxBaEntry->u2WinStart, prRxBaEntry->u2WinEnd, prRxBaEntry->u2WinSize);
- /* Update the BA entry reference table for per-packet lookup */
- prStaRec->aprRxReorderParamRefTbl[ucTid] = prRxBaEntry;
- } else {
- /* This shall not happen because FW should keep track of the usage of RX BA entries */
- DBGLOG(QM, ERROR, "QM: **AddBA Error** (ucRxBaCount=%d)\n", prQM->ucRxBaCount);
- return FALSE;
- }
- return TRUE;
- }
- VOID qmDelRxBaEntry(IN P_ADAPTER_T prAdapter, IN UINT_8 ucStaRecIdx, IN UINT_8 ucTid, IN BOOLEAN fgFlushToHost)
- {
- P_RX_BA_ENTRY_T prRxBaEntry;
- P_STA_RECORD_T prStaRec;
- P_SW_RFB_T prFlushedPacketList = NULL;
- P_QUE_MGT_T prQM = &prAdapter->rQM;
- ASSERT(ucStaRecIdx < CFG_NUM_OF_STA_RECORD);
- prStaRec = &prAdapter->arStaRec[ucStaRecIdx];
- ASSERT(prStaRec);
- #if 0
- if (!(prStaRec->fgIsValid)) {
- DbgPrint("QM: (WARNING) Invalid STA when deleting an RX BA\n");
- return;
- }
- #endif
- /* Remove the BA entry for the same (STA, TID) tuple if it exists */
- prRxBaEntry = prStaRec->aprRxReorderParamRefTbl[ucTid];
- if (prRxBaEntry) {
- prFlushedPacketList = qmFlushStaRxQueue(prAdapter, ucStaRecIdx, ucTid);
- if (prFlushedPacketList) {
- if (fgFlushToHost) {
- wlanProcessQueuedSwRfb(prAdapter, prFlushedPacketList);
- } else {
- P_SW_RFB_T prSwRfb;
- P_SW_RFB_T prNextSwRfb;
- prSwRfb = prFlushedPacketList;
- do {
- prNextSwRfb = (P_SW_RFB_T) QUEUE_GET_NEXT_ENTRY((P_QUE_ENTRY_T) prSwRfb);
- nicRxReturnRFB(prAdapter, prSwRfb);
- prSwRfb = prNextSwRfb;
- } while (prSwRfb);
- }
- }
- if (prRxBaEntry->fgHasBubble) {
- DBGLOG(QM, TRACE, "QM:(Bub Check Cancel) STA[%u] TID[%u], DELBA\n",
- prRxBaEntry->ucStaRecIdx, prRxBaEntry->ucTid);
- cnmTimerStopTimer(prAdapter, &prRxBaEntry->rReorderBubbleTimer);
- prRxBaEntry->fgHasBubble = FALSE;
- }
- #if ((QM_TEST_MODE == 0) && (QM_TEST_STA_REC_DEACTIVATION == 0))
- /* Update RX BA entry state. Note that RX queue flush is not done here */
- prRxBaEntry->fgIsValid = FALSE;
- prQM->ucRxBaCount--;
- /* Debug */
- #if 0
- DbgPrint("QM: ucRxBaCount=%d\n", prQM->ucRxBaCount);
- #endif
- /* Update STA RX BA table */
- prStaRec->aprRxReorderParamRefTbl[ucTid] = NULL;
- #endif
- DBGLOG(QM, INFO, "QM: -RxBA(STA=%d,TID=%d)\n", ucStaRecIdx, ucTid);
- }
- /* Debug */
- #if CFG_HIF_RX_STARVATION_WARNING
- {
- P_RX_CTRL_T prRxCtrl;
- prRxCtrl = &prAdapter->rRxCtrl;
- DBGLOG(QM, TRACE,
- "QM: (RX DEBUG) Enqueued: %d / Dequeued: %d\n", prRxCtrl->u4QueuedCnt,
- prRxCtrl->u4DequeuedCnt);
- }
- #endif
- }
- /*----------------------------------------------------------------------------*/
- /*!
- * \brief To process WMM related IEs in ASSOC_RSP
- *
- * \param[in] prAdapter Adapter pointer
- * \param[in] prSwRfb The received frame
- * \param[in] pucIE The pointer to the first IE in the frame
- * \param[in] u2IELength The total length of IEs in the frame
- *
- * \return none
- */
- /*----------------------------------------------------------------------------*/
- VOID mqmProcessAssocReq(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb, IN PUINT_8 pucIE, IN UINT_16 u2IELength)
- {
- P_STA_RECORD_T prStaRec;
- UINT_16 u2Offset;
- PUINT_8 pucIEStart;
- UINT_8 aucWfaOui[] = VENDOR_OUI_WFA;
- P_IE_WMM_INFO_T prIeWmmInfo;
- UINT_8 ucQosInfo;
- UINT_8 ucQosInfoAC;
- UINT_8 ucBmpAC;
- DEBUGFUNC("mqmProcessAssocReq");
- ASSERT(prSwRfb);
- ASSERT(pucIE);
- prStaRec = cnmGetStaRecByIndex(prAdapter, prSwRfb->ucStaRecIdx);
- ASSERT(prStaRec);
- if (prStaRec == NULL)
- return;
- prStaRec->fgIsQoS = FALSE;
- prStaRec->fgIsWmmSupported = prStaRec->fgIsUapsdSupported = FALSE;
- pucIEStart = pucIE;
- /* If the device does not support QoS or if WMM is not supported by the peer, exit. */
- if (!prAdapter->rWifiVar.fgSupportQoS)
- return;
- /* Determine whether QoS is enabled with the association */
- IE_FOR_EACH(pucIE, u2IELength, u2Offset) {
- switch (IE_ID(pucIE)) {
- case ELEM_ID_WMM:
- if ((WMM_IE_OUI_TYPE(pucIE) == VENDOR_OUI_TYPE_WMM) &&
- (!kalMemCmp(WMM_IE_OUI(pucIE), aucWfaOui, 3))) {
- switch (WMM_IE_OUI_SUBTYPE(pucIE)) {
- case VENDOR_OUI_SUBTYPE_WMM_INFO:
- if (IE_LEN(pucIE) != 7)
- break; /* WMM Info IE with a wrong length */
- prStaRec->fgIsQoS = TRUE;
- prStaRec->fgIsWmmSupported = TRUE;
- prIeWmmInfo = (P_IE_WMM_INFO_T) pucIE;
- ucQosInfo = prIeWmmInfo->ucQosInfo;
- ucQosInfoAC = ucQosInfo & BITS(0, 3);
- prStaRec->fgIsUapsdSupported = ((ucQosInfoAC) ? TRUE : FALSE) &
- prAdapter->rWifiVar.fgSupportUAPSD;
- ucBmpAC = 0;
- if (ucQosInfoAC & WMM_QOS_INFO_VO_UAPSD)
- ucBmpAC |= BIT(ACI_VO);
- if (ucQosInfoAC & WMM_QOS_INFO_VI_UAPSD)
- ucBmpAC |= BIT(ACI_VI);
- if (ucQosInfoAC & WMM_QOS_INFO_BE_UAPSD)
- ucBmpAC |= BIT(ACI_BE);
- if (ucQosInfoAC & WMM_QOS_INFO_BK_UAPSD)
- ucBmpAC |= BIT(ACI_BK);
- prStaRec->ucBmpTriggerAC = prStaRec->ucBmpDeliveryAC = ucBmpAC;
- prStaRec->ucUapsdSp =
- (ucQosInfo & WMM_QOS_INFO_MAX_SP_LEN_MASK) >> 5;
- break;
- default:
- /* Other WMM QoS IEs. Ignore any */
- break;
- }
- }
- /* else: VENDOR_OUI_TYPE_WPA, VENDOR_OUI_TYPE_WPS */
- break;
- case ELEM_ID_HT_CAP:
- /* Some client won't put the WMM IE if client is 802.11n */
- if (IE_LEN(pucIE) == (sizeof(IE_HT_CAP_T) - 2))
- prStaRec->fgIsQoS = TRUE;
- break;
- default:
- break;
- }
- }
- DBGLOG(QM, TRACE, "MQM: Assoc_Req Parsing (QoS Enabled=%d)\n", prStaRec->fgIsQoS);
- }
- /*----------------------------------------------------------------------------*/
- /*!
- * \brief To process WMM related IEs in ASSOC_RSP
- *
- * \param[in] prAdapter Adapter pointer
- * \param[in] prSwRfb The received frame
- * \param[in] pucIE The pointer to the first IE in the frame
- * \param[in] u2IELength The total length of IEs in the frame
- *
- * \return none
- */
- /*----------------------------------------------------------------------------*/
- VOID mqmProcessAssocRsp(IN P_ADAPTER_T prAdapter, IN P_SW_RFB_T prSwRfb, IN PUINT_8 pucIE, IN UINT_16 u2IELength)
- {
- P_STA_RECORD_T prStaRec;
- UINT_16 u2Offset;
- PUINT_8 pucIEStart;
- UINT_8 aucWfaOui[] = VENDOR_OUI_WFA;
- DEBUGFUNC("mqmProcessAssocRsp");
- ASSERT(prSwRfb);
- ASSERT(pucIE);
- prStaRec = cnmGetStaRecByIndex(prAdapter, prSwRfb->ucStaRecIdx);
- ASSERT(prStaRec);
- if (prStaRec == NULL)
- return;
- prStaRec->fgIsQoS = FALSE;
- pucIEStart = pucIE;
- DBGLOG(QM, TRACE, "QM: (fgIsWmmSupported=%d, fgSupportQoS=%d)\n",
- prStaRec->fgIsWmmSupported, prAdapter->rWifiVar.fgSupportQoS);
- /* If the device does not support QoS or if WMM is not supported by the peer, exit. */
- /* if((!prAdapter->rWifiVar.fgSupportQoS) || (!prStaRec->fgIsWmmSupported)) */
- if ((!prAdapter->rWifiVar.fgSupportQoS))
- return;
- /* Determine whether QoS is enabled with the association */
- IE_FOR_EACH(pucIE, u2IELength, u2Offset) {
- switch (IE_ID(pucIE)) {
- case ELEM_ID_WMM:
- if ((WMM_IE_OUI_TYPE(pucIE) == VENDOR_OUI_TYPE_WMM) &&
- (!kalMemCmp(WMM_IE_OUI(pucIE), aucWfaOui, 3))) {
- switch (WMM_IE_OUI_SUBTYPE(pucIE)) {
- case VENDOR_OUI_SUBTYPE_WMM_PARAM:
- if (IE_LEN(pucIE) != 24)
- break; /* WMM Info IE with a wrong length */
- prStaRec->fgIsQoS = TRUE;
- break;
- case VENDOR_OUI_SUBTYPE_WMM_INFO:
- if (IE_LEN(pucIE) != 7)
- break; /* WMM Info IE with a wrong length */
- prStaRec->fgIsQoS = TRUE;
- break;
- default:
- /* Other WMM QoS IEs. Ignore any */
- break;
- }
- }
- /* else: VENDOR_OUI_TYPE_WPA, VENDOR_OUI_TYPE_WPS */
- break;
- case ELEM_ID_HT_CAP:
- /* Some AP won't put the WMM IE if client is 802.11n */
- if (IE_LEN(pucIE) == (sizeof(IE_HT_CAP_T) - 2))
- prStaRec->fgIsQoS = TRUE;
- break;
- default:
- break;
- }
- }
- /* Parse AC parameters and write to HW CRs */
- if ((prStaRec->fgIsQoS) && (prStaRec->eStaType == STA_TYPE_LEGACY_AP)) {
- mqmParseEdcaParameters(prAdapter, prSwRfb, pucIEStart, u2IELength, TRUE);
- #if ARP_MONITER_ENABLE
- qmResetArpDetect();
- #endif
- }
- DBGLOG(QM, TRACE, "MQM: Assoc_Rsp Parsing (QoS Enabled=%d)\n", prStaRec->fgIsQoS);
- if (prStaRec->fgIsWmmSupported)
- nicQmUpdateWmmParms(prAdapter, prStaRec->ucNetTypeIndex);
- }
- /*----------------------------------------------------------------------------*/
- /*!
- * \brief To parse WMM Parameter IE (in BCN or Assoc_Rsp)
- *
- * \param[in] prAdapter Adapter pointer
- * \param[in] prSwRfb The received frame
- * \param[in] pucIE The pointer to the first IE in the frame
- * \param[in] u2IELength The total length of IEs in the frame
- * \param[in] fgForceOverride TRUE: If EDCA parameters are found, always set to HW CRs.
- *
- * \return none
- */
- /*----------------------------------------------------------------------------*/
- VOID
- mqmParseEdcaParameters(IN P_ADAPTER_T prAdapter,
- IN P_SW_RFB_T prSwRfb, IN PUINT_8 pucIE, IN UINT_16 u2IELength, IN BOOLEAN fgForceOverride)
- {
- P_STA_RECORD_T prStaRec;
- UINT_16 u2Offset;
- UINT_8 aucWfaOui[] = VENDOR_OUI_WFA;
- P_BSS_INFO_T prBssInfo;
- P_AC_QUE_PARMS_T prAcQueParams;
- P_IE_WMM_PARAM_T prIeWmmParam;
- ENUM_WMM_ACI_T eAci;
- PUINT_8 pucWmmParamSetCount;
- DEBUGFUNC("mqmParseEdcaParameters");
- ASSERT(prSwRfb);
- ASSERT(pucIE);
- prStaRec = cnmGetStaRecByIndex(prAdapter, prSwRfb->ucStaRecIdx);
- ASSERT(prStaRec);
- if (prStaRec == NULL)
- return;
- DBGLOG(QM, TRACE, "QM: (fgIsWmmSupported=%d, fgIsQoS=%d)\n", prStaRec->fgIsWmmSupported, prStaRec->fgIsQoS);
- if ((!prAdapter->rWifiVar.fgSupportQoS) || (!prStaRec->fgIsWmmSupported) || (!prStaRec->fgIsQoS))
- return;
- prBssInfo = &(prAdapter->rWifiVar.arBssInfo[prStaRec->ucNetTypeIndex]);
- /* Goal: Obtain the EDCA parameters */
- IE_FOR_EACH(pucIE, u2IELength, u2Offset) {
- switch (IE_ID(pucIE)) {
- case ELEM_ID_WMM:
- if ((WMM_IE_OUI_TYPE(pucIE) != VENDOR_OUI_TYPE_WMM) ||
- (kalMemCmp(WMM_IE_OUI(pucIE), aucWfaOui, 3)))
- break;
- switch (WMM_IE_OUI_SUBTYPE(pucIE)) {
- case VENDOR_OUI_SUBTYPE_WMM_PARAM:
- if (IE_LEN(pucIE) != 24)
- break; /* WMM Param IE with a wrong length */
- pucWmmParamSetCount = &(prBssInfo->ucWmmParamSetCount);
- prIeWmmParam = (P_IE_WMM_PARAM_T) pucIE;
- /* Check the Parameter Set Count to determine whether EDCA parameters */
- /* have been changed */
- if (!fgForceOverride && (*pucWmmParamSetCount
- == (prIeWmmParam->ucQosInfo & WMM_QOS_INFO_PARAM_SET_CNT)))
- break; /* Ignore the IE without updating HW CRs */
- /* Update Parameter Set Count */
- *pucWmmParamSetCount =
- (prIeWmmParam->ucQosInfo & WMM_QOS_INFO_PARAM_SET_CNT);
- /* Update EDCA parameters */
- for (eAci = 0; eAci < WMM_AC_INDEX_NUM; eAci++) {
- prAcQueParams = &prBssInfo->arACQueParms[eAci];
- mqmFillAcQueParam(prIeWmmParam, eAci, prAcQueParams);
- prAcQueParams->fgIsACMSet =
- (prAcQueParams->u2Aifsn & WMM_ACIAIFSN_ACM) ? TRUE : FALSE;
- prAcQueParams->u2Aifsn &= WMM_ACIAIFSN_AIFSN;
- DBGLOG(QM, LOUD,
- "eAci:%d, ACM:%d, Aifsn:%d, CWmin:%d, CWmax:%d, TxopLmt:%d\n",
- eAci, prAcQueParams->fgIsACMSet, prAcQueParams->u2Aifsn,
- prAcQueParams->u2CWmin, prAcQueParams->u2CWmax,
- prAcQueParams->u2TxopLimit);
- }
- break;
- default:
- /* Other WMM QoS IEs. Ignore */
- break;
- }
- /* else: VENDOR_OUI_TYPE_WPA, VENDOR_OUI_TYPE_WPS, ... (not cared) */
- break;
- default:
- break;
- }
- }
- }
- /*----------------------------------------------------------------------------*/
- /*!
- * \brief This function is used for parsing EDCA parameters specified in the WMM Parameter IE
- *
- * \param[in] prAdapter Adapter pointer
- * \param[in] prIeWmmParam The pointer to the WMM Parameter IE
- * \param[in] u4AcOffset The offset specifying the AC queue for parsing
- * \param[in] prHwAcParams The parameter structure used to configure the HW CRs
- *
- * \return none
- */
- /*----------------------------------------------------------------------------*/
- VOID mqmFillAcQueParam(IN P_IE_WMM_PARAM_T prIeWmmParam, IN UINT_32 u4AcOffset, OUT P_AC_QUE_PARMS_T prAcQueParams)
- {
- prAcQueParams->u2Aifsn = *((PUINT_8) (&(prIeWmmParam->ucAciAifsn_BE)) + (u4AcOffset * 4));
- prAcQueParams->u2CWmax = BIT(((*((PUINT_8) (&(prIeWmmParam->ucEcw_BE)) + (u4AcOffset * 4))) & WMM_ECW_WMAX_MASK)
- >> WMM_ECW_WMAX_OFFSET) - 1;
- prAcQueParams->u2CWmin =
- BIT((*((PUINT_8) (&(prIeWmmParam->ucEcw_BE)) + (u4AcOffset * 4))) & WMM_ECW_WMIN_MASK) - 1;
- WLAN_GET_FIELD_16(((PUINT_8) (&(prIeWmmParam->aucTxopLimit_BE)) + (u4AcOffset * 4)),
- &(prAcQueParams->u2TxopLimit));
- prAcQueParams->ucGuradTime = TXM_DEFAULT_FLUSH_QUEUE_GUARD_TIME;
- }
- /*----------------------------------------------------------------------------*/
- /*!
- * \brief To parse WMM/11n related IEs in scan results (only for AP peers)
- *
- * \param[in] prAdapter Adapter pointer
- * \param[in] prScanResult The scan result which shall be parsed to obtain needed info
- * \param[out] prStaRec The obtained info is stored in the STA_REC
- *
- * \return none
- */
- /*----------------------------------------------------------------------------*/
- #if (CFG_SUPPORT_TDLS == 1) /* for test purpose */
- BOOLEAN flgTdlsTestExtCapElm = FALSE;
- UINT8 aucTdlsTestExtCapElm[7];
- #endif /* CFG_SUPPORT_TDLS */
- VOID mqmProcessScanResult(IN P_ADAPTER_T prAdapter, IN P_BSS_DESC_T prScanResult, OUT P_STA_RECORD_T prStaRec)
- {
- PUINT_8 pucIE;
- UINT_16 u2IELength;
- UINT_16 u2Offset;
- UINT_8 aucWfaOui[] = VENDOR_OUI_WFA;
- DEBUGFUNC("mqmProcessScanResult");
- ASSERT(prScanResult);
- ASSERT(prStaRec);
- /* Reset the flag before parsing */
- prStaRec->fgIsWmmSupported = prStaRec->fgIsUapsdSupported = FALSE;
- if (!prAdapter->rWifiVar.fgSupportQoS)
- return;
- u2IELength = prScanResult->u2IELength;
- pucIE = prScanResult->aucIEBuf;
- #if (CFG_SUPPORT_TDLS == 1)
- /* TDLS test purpose */
- if (flgTdlsTestExtCapElm == TRUE)
- TdlsexBssExtCapParse(prStaRec, aucTdlsTestExtCapElm);
- #endif /* CFG_SUPPORT_TDLS */
- /* Goal: Determine whether the peer supports WMM/QoS and UAPSDU */
- IE_FOR_EACH(pucIE, u2IELength, u2Offset) {
- switch (IE_ID(pucIE)) {
- case ELEM_ID_EXTENDED_CAP:
- #if (CFG_SUPPORT_TDLS == 1)
- TdlsexBssExtCapParse(prStaRec, pucIE);
- #endif /* CFG_SUPPORT_TDLS */
- break;
- case ELEM_ID_WMM:
- if ((WMM_IE_OUI_TYPE(pucIE) == VENDOR_OUI_TYPE_WMM) &&
- (!kalMemCmp(WMM_IE_OUI(pucIE), aucWfaOui, 3))) {
- switch (WMM_IE_OUI_SUBTYPE(pucIE)) {
- case VENDOR_OUI_SUBTYPE_WMM_PARAM:
- if (IE_LEN(pucIE) != 24)
- break; /* WMM Param IE with a wrong length */
- prStaRec->fgIsWmmSupported = TRUE;
- prStaRec->fgIsUapsdSupported =
- (((((P_IE_WMM_PARAM_T) pucIE)->ucQosInfo) & WMM_QOS_INFO_UAPSD) ?
- TRUE : FALSE);
- break;
- case VENDOR_OUI_SUBTYPE_WMM_INFO:
- if (IE_LEN(pucIE) != 7)
- break; /* WMM Info IE with a wrong length */
- prStaRec->fgIsWmmSupported = TRUE;
- prStaRec->fgIsUapsdSupported =
- (((((P_IE_WMM_INFO_T) pucIE)->ucQosInfo) & WMM_QOS_INFO_UAPSD) ?
- TRUE : FALSE);
- break;
- default:
- /* A WMM QoS IE that doesn't matter. Ignore it. */
- break;
- }
- }
- /* else: VENDOR_OUI_TYPE_WPA, VENDOR_OUI_TYPE_WPS, ... (not cared) */
- break;
- default:
- /* A WMM IE that doesn't matter. Ignore it. */
- break;
- }
- }
- DBGLOG(QM, LOUD, "MQM: Scan Result Parsing (WMM=%d, UAPSD=%d)\n",
- prStaRec->fgIsWmmSupported, prStaRec->fgIsUapsdSupported);
- }
- UINT_8 qmGetStaRecIdx(IN P_ADAPTER_T prAdapter, IN PUINT_8 pucEthDestAddr, IN ENUM_NETWORK_TYPE_INDEX_T eNetworkType)
- {
- UINT_32 i;
- P_STA_RECORD_T prTempStaRec;
- prTempStaRec = NULL;
- ASSERT(prAdapter);
- /* 4 <1> DA = BMCAST */
- if (IS_BMCAST_MAC_ADDR(pucEthDestAddr))
- return STA_REC_INDEX_BMCAST;
- /* 4 <2> Check if an AP STA is present */
- for (i = 0; i < CFG_NUM_OF_STA_RECORD; i++) {
- prTempStaRec = &(prAdapter->arStaRec[i]);
- if ((prTempStaRec->ucNetTypeIndex == eNetworkType)
- && (prTempStaRec->fgIsAp)
- && (prTempStaRec->fgIsValid)) {
- return prTempStaRec->ucIndex;
- }
- }
- /* 4 <3> Not BMCAST, No AP --> Compare DA (i.e., to see whether this is a unicast frame to a client) */
- for (i = 0; i < CFG_NUM_OF_STA_RECORD; i++) {
- prTempStaRec = &(prAdapter->arStaRec[i]);
- if (prTempStaRec->fgIsValid) {
- if (EQUAL_MAC_ADDR(prTempStaRec->aucMacAddr, pucEthDestAddr))
- return prTempStaRec->ucIndex;
- }
- }
- /* 4 <4> No STA found, Not BMCAST --> Indicate NOT_FOUND to FW */
- return STA_REC_INDEX_NOT_FOUND;
- }
- UINT_32
- mqmGenerateWmmInfoIEByParam(BOOLEAN fgSupportUAPSD,
- UINT_8 ucBmpDeliveryAC, UINT_8 ucBmpTriggerAC, UINT_8 ucUapsdSp, UINT_8 *pOutBuf)
- {
- P_IE_WMM_INFO_T prIeWmmInfo;
- UINT_32 ucUapsd[] = {
- WMM_QOS_INFO_BE_UAPSD,
- WMM_QOS_INFO_BK_UAPSD,
- WMM_QOS_INFO_VI_UAPSD,
- WMM_QOS_INFO_VO_UAPSD
- };
- UINT_8 aucWfaOui[] = VENDOR_OUI_WFA;
- ASSERT(pOutBuf);
- prIeWmmInfo = (P_IE_WMM_INFO_T) pOutBuf;
- prIeWmmInfo->ucId = ELEM_ID_WMM;
- prIeWmmInfo->ucLength = ELEM_MAX_LEN_WMM_INFO;
- /* WMM-2.2.1 WMM Information Element Field Values */
- prIeWmmInfo->aucOui[0] = aucWfaOui[0];
- prIeWmmInfo->aucOui[1] = aucWfaOui[1];
- prIeWmmInfo->aucOui[2] = aucWfaOui[2];
- prIeWmmInfo->ucOuiType = VENDOR_OUI_TYPE_WMM;
- prIeWmmInfo->ucOuiSubtype = VENDOR_OUI_SUBTYPE_WMM_INFO;
- prIeWmmInfo->ucVersion = VERSION_WMM;
- prIeWmmInfo->ucQosInfo = 0;
- /* UAPSD initial queue configurations (delivery and trigger enabled) */
- if (fgSupportUAPSD) {
- UINT_8 ucQosInfo = 0;
- UINT_8 i;
- /* Static U-APSD setting */
- for (i = ACI_BE; i <= ACI_VO; i++) {
- if (ucBmpDeliveryAC & ucBmpTriggerAC & BIT(i))
- ucQosInfo |= (UINT_8) ucUapsd[i];
- }
- if (ucBmpDeliveryAC & ucBmpTriggerAC) {
- switch (ucUapsdSp) {
- case WMM_MAX_SP_LENGTH_ALL:
- ucQosInfo |= WMM_QOS_INFO_MAX_SP_ALL;
- break;
- case WMM_MAX_SP_LENGTH_2:
- ucQosInfo |= WMM_QOS_INFO_MAX_SP_2;
- break;
- case WMM_MAX_SP_LENGTH_4:
- ucQosInfo |= WMM_QOS_INFO_MAX_SP_4;
- break;
- case WMM_MAX_SP_LENGTH_6:
- ucQosInfo |= WMM_QOS_INFO_MAX_SP_6;
- break;
- default:
- DBGLOG(QM, WARN, "MQM: Incorrect SP length\n");
- ucQosInfo |= WMM_QOS_INFO_MAX_SP_2;
- break;
- }
- }
- prIeWmmInfo->ucQosInfo = ucQosInfo;
- }
- /* Increment the total IE length for the Element ID and Length fields. */
- return IE_SIZE(prIeWmmInfo);
- }
- /*----------------------------------------------------------------------------*/
- /*!
- * @brief Generate the WMM Info IE
- *
- * \param[in] prAdapter Adapter pointer
- * @param prMsduInfo The TX MMPDU
- *
- * @return (none)
- */
- /*----------------------------------------------------------------------------*/
- VOID mqmGenerateWmmInfoIE(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo)
- {
- P_IE_WMM_INFO_T prIeWmmInfo;
- P_PM_PROFILE_SETUP_INFO_T prPmProfSetupInfo;
- P_BSS_INFO_T prBssInfo;
- P_STA_RECORD_T prStaRec;
- DEBUGFUNC("mqmGenerateWmmInfoIE");
- ASSERT(prMsduInfo);
- /* In case QoS is not turned off, exit directly */
- if (!prAdapter->rWifiVar.fgSupportQoS)
- return;
- prStaRec = cnmGetStaRecByIndex(prAdapter, prMsduInfo->ucStaRecIndex);
- ASSERT(prStaRec);
- if (prStaRec == NULL)
- return;
- if (!prStaRec->fgIsWmmSupported)
- return;
- prBssInfo = &(prAdapter->rWifiVar.arBssInfo[prStaRec->ucNetTypeIndex]);
- prPmProfSetupInfo = &prBssInfo->rPmProfSetupInfo;
- prIeWmmInfo = (P_IE_WMM_INFO_T)
- ((PUINT_8) prMsduInfo->prPacket + prMsduInfo->u2FrameLength);
- #if 0
- prIeWmmInfo->ucId = ELEM_ID_WMM;
- prIeWmmInfo->ucLength = ELEM_MAX_LEN_WMM_INFO;
- /* WMM-2.2.1 WMM Information Element Field Values */
- prIeWmmInfo->aucOui[0] = aucWfaOui[0];
- prIeWmmInfo->aucOui[1] = aucWfaOui[1];
- prIeWmmInfo->aucOui[2] = aucWfaOui[2];
- prIeWmmInfo->ucOuiType = VENDOR_OUI_TYPE_WMM;
- prIeWmmInfo->ucOuiSubtype = VENDOR_OUI_SUBTYPE_WMM_INFO;
- prIeWmmInfo->ucVersion = VERSION_WMM;
- prIeWmmInfo->ucQosInfo = 0;
- /* UAPSD initial queue configurations (delivery and trigger enabled) */
- /* if(prAdapter->rWifiVar.fgSupportUAPSD){ */
- if (prAdapter->rWifiVar.fgSupportUAPSD && prStaRec->fgIsUapsdSupported) {
- UINT_8 ucQosInfo = 0;
- UINT_8 i;
- /* Static U-APSD setting */
- for (i = ACI_BE; i <= ACI_VO; i++) {
- if (prPmProfSetupInfo->ucBmpDeliveryAC & prPmProfSetupInfo->ucBmpTriggerAC & BIT(i))
- ucQosInfo |= (UINT_8) ucUapsd[i];
- }
- if (prPmProfSetupInfo->ucBmpDeliveryAC & prPmProfSetupInfo->ucBmpTriggerAC) {
- switch (prPmProfSetupInfo->ucUapsdSp) {
- case WMM_MAX_SP_LENGTH_ALL:
- ucQosInfo |= WMM_QOS_INFO_MAX_SP_ALL;
- break;
- case WMM_MAX_SP_LENGTH_2:
- ucQosInfo |= WMM_QOS_INFO_MAX_SP_2;
- break;
- case WMM_MAX_SP_LENGTH_4:
- ucQosInfo |= WMM_QOS_INFO_MAX_SP_4;
- break;
- case WMM_MAX_SP_LENGTH_6:
- ucQosInfo |= WMM_QOS_INFO_MAX_SP_6;
- break;
- default:
- DBGLOG(QM, INFO, "MQM: Incorrect SP length\n");
- ucQosInfo |= WMM_QOS_INFO_MAX_SP_2;
- break;
- }
- }
- prIeWmmInfo->ucQosInfo = ucQosInfo;
- }
- /* Increment the total IE length for the Element ID and Length fields. */
- prMsduInfo->u2FrameLength += IE_SIZE(prIeWmmInfo);
- #else
- prMsduInfo->u2FrameLength += mqmGenerateWmmInfoIEByParam((prAdapter->rWifiVar.fgSupportUAPSD
- && prStaRec->fgIsUapsdSupported),
- prPmProfSetupInfo->ucBmpDeliveryAC,
- prPmProfSetupInfo->ucBmpTriggerAC,
- prPmProfSetupInfo->ucUapsdSp, (UINT_8 *) prIeWmmInfo);
- #endif
- }
- #if 0
- /*----------------------------------------------------------------------------*/
- /*!
- * @brief log2 calculation for CW
- *
- * @param[in] val value
- *
- * @return log2(val)
- */
- /*----------------------------------------------------------------------------*/
- UINT_32 cwlog2(UINT_32 val)
- {
- UINT_32 n;
- n = 0;
- while (val >= 512) {
- n += 9;
- val = val >> 9;
- }
- while (val >= 16) {
- n += 4;
- val >>= 4;
- }
- while (val >= 2) {
- n += 1;
- val >>= 1;
- }
- return n;
- }
- #endif
- UINT_32 mqmGenerateWmmParamIEByParam(P_ADAPTER_T prAdapter,
- P_BSS_INFO_T prBssInfo, UINT_8 *pOutBuf, ENUM_OP_MODE_T ucOpMode)
- {
- P_IE_WMM_PARAM_T prIeWmmParam;
- UINT_8 aucWfaOui[] = VENDOR_OUI_WFA;
- UINT_8 aucACI[] = {
- WMM_ACI_AC_BE,
- WMM_ACI_AC_BK,
- WMM_ACI_AC_VI,
- WMM_ACI_AC_VO
- };
- ENUM_WMM_ACI_T eAci;
- UCHAR *pucAciAifsn, *pucEcw, *pucTxopLimit;
- ASSERT(pOutBuf);
- prIeWmmParam = (P_IE_WMM_PARAM_T) pOutBuf;
- prIeWmmParam->ucId = ELEM_ID_WMM;
- prIeWmmParam->ucLength = ELEM_MAX_LEN_WMM_PARAM;
- /* WMM-2.2.1 WMM Information Element Field Values */
- prIeWmmParam->aucOui[0] = aucWfaOui[0];
- prIeWmmParam->aucOui[1] = aucWfaOui[1];
- prIeWmmParam->aucOui[2] = aucWfaOui[2];
- prIeWmmParam->ucOuiType = VENDOR_OUI_TYPE_WMM;
- prIeWmmParam->ucOuiSubtype = VENDOR_OUI_SUBTYPE_WMM_PARAM;
- prIeWmmParam->ucVersion = VERSION_WMM;
- prIeWmmParam->ucQosInfo = (prBssInfo->ucWmmParamSetCount & WMM_QOS_INFO_PARAM_SET_CNT);
- /* UAPSD initial queue configurations (delivery and trigger enabled) */
- if (prAdapter->rWifiVar.fgSupportUAPSD) {
- if (ucOpMode == OP_MODE_INFRASTRUCTURE)
- prIeWmmParam->ucQosInfo = 0xf;
- else
- prIeWmmParam->ucQosInfo |= WMM_QOS_INFO_UAPSD;
- }
- /* EDCA parameter */
- for (eAci = 0; eAci < WMM_AC_INDEX_NUM; eAci++) {
- /* DBGLOG(QM, LOUD, */
- /* ("MQM: eAci = %d, ACM = %d, Aifsn = %d, CWmin = %d, CWmax = %d, TxopLimit = %d\n", */
- /* eAci,prBssInfo->arACQueParmsForBcast[eAci].fgIsACMSet , */
- /* prBssInfo->arACQueParmsForBcast[eAci].u2Aifsn, */
- /* prBssInfo->arACQueParmsForBcast[eAci].u2CWmin, */
- /* prBssInfo->arACQueParmsForBcast[eAci].u2CWmax, */
- /* prBssInfo->arACQueParmsForBcast[eAci].u2TxopLimit)); */
- #if 0
- *(((PUINT_8) (&prIeWmmParam->ucAciAifsn_BE)) + (eAci << 2)) = (UINT_8) (aucACI[eAci]
- |
- (prBssInfo->arACQueParmsForBcast
- [eAci].fgIsACMSet ?
- WMM_ACIAIFSN_ACM : 0)
- |
- (prBssInfo->arACQueParmsForBcast
- [eAci].u2Aifsn &
- (WMM_ACIAIFSN_AIFSN)));
- #else
- /* avoid compile warnings in Klockwork tool */
- if (eAci == WMM_AC_BE_INDEX) {
- pucAciAifsn = &prIeWmmParam->ucAciAifsn_BE;
- pucEcw = &prIeWmmParam->ucEcw_BE;
- pucTxopLimit = prIeWmmParam->aucTxopLimit_BE;
- } else if (eAci == WMM_AC_BK_INDEX) {
- pucAciAifsn = &prIeWmmParam->ucAciAifsn_BG;
- pucEcw = &prIeWmmParam->ucEcw_BG;
- pucTxopLimit = prIeWmmParam->aucTxopLimit_BG;
- } else if (eAci == WMM_AC_VI_INDEX) {
- pucAciAifsn = &prIeWmmParam->ucAciAifsn_VI;
- pucEcw = &prIeWmmParam->ucEcw_VI;
- pucTxopLimit = prIeWmmParam->aucTxopLimit_VI;
- } else if (eAci == WMM_AC_VO_INDEX) {
- pucAciAifsn = &prIeWmmParam->ucAciAifsn_VO;
- pucEcw = &prIeWmmParam->ucEcw_VO;
- pucTxopLimit = prIeWmmParam->aucTxopLimit_VO;
- }
- *pucAciAifsn = (UINT_8) (aucACI[eAci]
- | (prBssInfo->arACQueParmsForBcast[eAci].fgIsACMSet ? WMM_ACIAIFSN_ACM : 0)
- | (prBssInfo->arACQueParmsForBcast[eAci].u2Aifsn & (WMM_ACIAIFSN_AIFSN)));
- #endif
- #if 1
- /* *( ((PUINT_8)(&prIeWmmParam->ucEcw_BE)) + (eAci <<2) ) = (UINT_8) (0 */
- *pucEcw = (UINT_8) (0 | (((prBssInfo->aucCWminLog2ForBcast[eAci])) & WMM_ECW_WMIN_MASK)
- | ((((prBssInfo->aucCWmaxLog2ForBcast[eAci])) << WMM_ECW_WMAX_OFFSET) &
- WMM_ECW_WMAX_MASK)
- );
- #else
- *(((PUINT_8) (&prIeWmmParam->ucEcw_BE)) + (eAci << 2)) = (UINT_8) (0
- |
- (cwlog2
- ((prBssInfo->arACQueParmsForBcast
- [eAci].u2CWmin +
- 1)) & WMM_ECW_WMIN_MASK)
- |
- ((cwlog2
- ((prBssInfo->arACQueParmsForBcast
- [eAci].u2CWmax +
- 1)) << WMM_ECW_WMAX_OFFSET) &
- WMM_ECW_WMAX_MASK)
- );
- #endif
- #if 0
- WLAN_SET_FIELD_16(((PUINT_8) (prIeWmmParam->aucTxopLimit_BE)) + (eAci << 2)
- , prBssInfo->arACQueParmsForBcast[eAci].u2TxopLimit);
- #else
- WLAN_SET_FIELD_16(pucTxopLimit, prBssInfo->arACQueParmsForBcast[eAci].u2TxopLimit);
- #endif
- }
- /* Increment the total IE length for the Element ID and Length fields. */
- return IE_SIZE(prIeWmmParam);
- }
- /*----------------------------------------------------------------------------*/
- /*!
- * @brief Generate the WMM Param IE
- *
- * \param[in] prAdapter Adapter pointer
- * @param prMsduInfo The TX MMPDU
- *
- * @return (none)
- */
- /*----------------------------------------------------------------------------*/
- VOID mqmGenerateWmmParamIE(IN P_ADAPTER_T prAdapter, IN P_MSDU_INFO_T prMsduInfo)
- {
- P_IE_WMM_PARAM_T prIeWmmParam;
- #if 0
- UINT_8 aucWfaOui[] = VENDOR_OUI_WFA;
- UINT_8 aucACI[] = {
- WMM_ACI_AC_BE,
- WMM_ACI_AC_BK,
- WMM_ACI_AC_VI,
- WMM_ACI_AC_VO
- };
- ENUM_WMM_ACI_T eAci;
- #endif
- P_BSS_INFO_T prBssInfo;
- P_STA_RECORD_T prStaRec;
- DEBUGFUNC("mqmGenerateWmmParamIE");
- DBGLOG(QM, LOUD, "\n");
- ASSERT(prMsduInfo);
- /* In case QoS is not turned off, exit directly */
- if (!prAdapter->rWifiVar.fgSupportQoS)
- return;
- prStaRec = cnmGetStaRecByIndex(prAdapter, prMsduInfo->ucStaRecIndex);
- if (prStaRec) {
- if (!prStaRec->fgIsQoS)
- return;
- }
- prBssInfo = &(prAdapter->rWifiVar.arBssInfo[prMsduInfo->ucNetworkType]);
- if (!prBssInfo->fgIsQBSS)
- return;
- /* 20120220 frog: update beacon content & change OP mode is a separate event for P2P network. */
- #if 0
- if (prBssInfo->eCurrentOPMode != OP_MODE_ACCESS_POINT && prBssInfo->eCurrentOPMode != OP_MODE_BOW)
- return;
- #endif
- prIeWmmParam = (P_IE_WMM_PARAM_T)
- ((PUINT_8) prMsduInfo->prPacket + prMsduInfo->u2FrameLength);
- #if 0
- prIeWmmParam->ucId = ELEM_ID_WMM;
- prIeWmmParam->ucLength = ELEM_MAX_LEN_WMM_PARAM;
- /* WMM-2.2.1 WMM Information Element Field Values */
- prIeWmmParam->aucOui[0] = aucWfaOui[0];
- prIeWmmParam->aucOui[1] = aucWfaOui[1];
- prIeWmmParam->aucOui[2] = aucWfaOui[2];
- prIeWmmParam->ucOuiType = VENDOR_OUI_TYPE_WMM;
- prIeWmmParam->ucOuiSubtype = VENDOR_OUI_SUBTYPE_WMM_PARAM;
- prIeWmmParam->ucVersion = VERSION_WMM;
- prIeWmmParam->ucQosInfo = (prBssInfo->ucWmmParamSetCount & WMM_QOS_INFO_PARAM_SET_CNT);
- /* UAPSD initial queue configurations (delivery and trigger enabled) */
- if (prAdapter->rWifiVar.fgSupportUAPSD)
- prIeWmmParam->ucQosInfo |= WMM_QOS_INFO_UAPSD;
- /* EDCA parameter */
- for (eAci = 0; eAci < WMM_AC_INDEX_NUM; eAci++) {
- /* DBGLOG(QM, LOUD, */
- /* ("MQM: eAci = %d, ACM = %d, Aifsn = %d, CWmin = %d, CWmax = %d, TxopLimit = %d\n", */
- /* eAci,prBssInfo->arACQueParmsForBcast[eAci].fgIsACMSet , */
- /* prBssInfo->arACQueParmsForBcast[eAci].u2Aifsn, */
- /* prBssInfo->arACQueParmsForBcast[eAci].u2CWmin, */
- /* prBssInfo->arACQueParmsForBcast[eAci].u2CWmax, */
- /* prBssInfo->arACQueParmsForBcast[eAci].u2TxopLimit)); */
- *(((PUINT_8) (&prIeWmmParam->ucAciAifsn_BE)) + (eAci << 2)) = (UINT_8) (aucACI[eAci]
- |
- (prBssInfo->arACQueParmsForBcast
- [eAci].fgIsACMSet ?
- WMM_ACIAIFSN_ACM : 0)
- |
- (prBssInfo->arACQueParmsForBcast
- [eAci].u2Aifsn &
- (WMM_ACIAIFSN_AIFSN)));
- #if 1
- *(((PUINT_8) (&prIeWmmParam->ucEcw_BE)) + (eAci << 2)) = (UINT_8) (0
- |
- (((prBssInfo->aucCWminLog2ForBcast
- [eAci])) & WMM_ECW_WMIN_MASK)
- |
- ((((prBssInfo->aucCWmaxLog2ForBcast
- [eAci])) << WMM_ECW_WMAX_OFFSET)
- & WMM_ECW_WMAX_MASK)
- );
- #else
- *(((PUINT_8) (&prIeWmmParam->ucEcw_BE)) + (eAci << 2)) = (UINT_8) (0
- |
- (cwlog2
- ((prBssInfo->arACQueParmsForBcast
- [eAci].u2CWmin +
- 1)) & WMM_ECW_WMIN_MASK)
- |
- ((cwlog2
- ((prBssInfo->arACQueParmsForBcast
- [eAci].u2CWmax +
- 1)) << WMM_ECW_WMAX_OFFSET) &
- WMM_ECW_WMAX_MASK)
- );
- #endif
- WLAN_SET_FIELD_16(((PUINT_8) (prIeWmmParam->aucTxopLimit_BE)) + (eAci << 2)
- , prBssInfo->arACQueParmsForBcast[eAci].u2TxopLimit);
- }
- /* Increment the total IE length for the Element ID and Length fields. */
- prMsduInfo->u2FrameLength += IE_SIZE(prIeWmmParam);
- #else
- prMsduInfo->u2FrameLength += mqmGenerateWmmParamIEByParam(prAdapter,
- prBssInfo, (UINT_8 *) prIeWmmParam, OP_MODE_ACCESS_POINT);
- #endif
- }
- ENUM_FRAME_ACTION_T
- qmGetFrameAction(IN P_ADAPTER_T prAdapter,
- IN ENUM_NETWORK_TYPE_INDEX_T eNetworkType,
- IN UINT_8 ucStaRecIdx, IN P_MSDU_INFO_T prMsduInfo, IN ENUM_FRAME_TYPE_IN_CMD_Q_T eFrameType)
- {
- P_BSS_INFO_T prBssInfo;
- P_STA_RECORD_T prStaRec;
- P_WLAN_MAC_HEADER_T prWlanFrame;
- UINT_16 u2TxFrameCtrl;
- DEBUGFUNC("qmGetFrameAction");
- #if (NIC_TX_BUFF_COUNT_TC4 > 2)
- #define QM_MGMT_QUUEUD_THRESHOLD 2
- #else
- #define QM_MGMT_QUUEUD_THRESHOLD 1
- #endif
- DATA_STRUCT_INSPECTING_ASSERT(QM_MGMT_QUUEUD_THRESHOLD <= (NIC_TX_BUFF_COUNT_TC4));
- DATA_STRUCT_INSPECTING_ASSERT(QM_MGMT_QUUEUD_THRESHOLD > 0);
- prBssInfo = &(prAdapter->rWifiVar.arBssInfo[eNetworkType]);
- prStaRec = QM_GET_STA_REC_PTR_FROM_INDEX(prAdapter, ucStaRecIdx);
- /* XXX Check BOW P2P AIS time ot set active */
- if (!IS_BSS_ACTIVE(prBssInfo)) {
- if (eFrameType == FRAME_TYPE_MMPDU) {
- prWlanFrame = (P_WLAN_MAC_HEADER_T) prMsduInfo->prPacket;
- u2TxFrameCtrl = (prWlanFrame->u2FrameCtrl) & MASK_FRAME_TYPE; /* Optimized for ARM */
- if (((u2TxFrameCtrl == MAC_FRAME_DEAUTH)
- && (prMsduInfo->pfTxDoneHandler == NULL))
- || (u2TxFrameCtrl == MAC_FRAME_ACTION)) /* whsu */
- return FRAME_ACTION_TX_PKT;
- }
- DBGLOG(QM, WARN, "Drop packets Action, eFrameType: %d (Bss Index %u).\n",
- eFrameType, prBssInfo->ucNetTypeIndex);
- TX_INC_CNT(&prAdapter->rTxCtrl, TX_INACTIVE_BSS_DROP);
- return FRAME_ACTION_DROP_PKT;
- }
- /* TODO Handle disconnect issue */
- /* P2P probe Request frame */
- do {
- if (eFrameType == FRAME_TYPE_MMPDU) {
- prWlanFrame = (P_WLAN_MAC_HEADER_T) prMsduInfo->prPacket;
- u2TxFrameCtrl = (prWlanFrame->u2FrameCtrl) & MASK_FRAME_TYPE; /* Optimized for ARM */
- if (u2TxFrameCtrl == MAC_FRAME_BEACON) {
- if (prBssInfo->fgIsNetAbsent)
- return FRAME_ACTION_DROP_PKT;
- } else if (u2TxFrameCtrl == MAC_FRAME_PROBE_RSP) {
- if (prBssInfo->fgIsNetAbsent)
- return FRAME_ACTION_DROP_PKT;
- } else if (u2TxFrameCtrl == MAC_FRAME_DEAUTH) {
- if (prBssInfo->fgIsNetAbsent)
- break;
- DBGLOG(P2P, LOUD, "Sending DEAUTH Frame\n");
- return FRAME_ACTION_TX_PKT;
- }
- /* MMPDU with prStaRec && fgIsInUse not check fgIsNetActive */
- else if (u2TxFrameCtrl == MAC_FRAME_ASSOC_REQ
- || u2TxFrameCtrl == MAC_FRAME_AUTH
- || u2TxFrameCtrl == MAC_FRAME_REASSOC_REQ
- || u2TxFrameCtrl == MAC_FRAME_PROBE_REQ || u2TxFrameCtrl == MAC_FRAME_ACTION) {
- if ((prStaRec) && (prStaRec->fgIsInPS)) {
- if (nicTxGetResource(prAdapter, TC4_INDEX) >= QM_MGMT_QUUEUD_THRESHOLD)
- return FRAME_ACTION_TX_PKT;
- else
- return FRAME_ACTION_QUEUE_PKT;
- }
- return FRAME_ACTION_TX_PKT;
- }
- if (!prStaRec)
- return FRAME_ACTION_TX_PKT;
- if (!prStaRec->fgIsInUse)
- return FRAME_ACTION_DROP_PKT;
- } /* FRAME_TYPE_MMPDU */
- else if (eFrameType == FRAME_TYPE_802_1X) {
- if (!prStaRec)
- return FRAME_ACTION_TX_PKT;
- if (!prStaRec->fgIsInUse)
- return FRAME_ACTION_DROP_PKT;
- if (prStaRec->fgIsInPS) {
- if (nicTxGetResource(prAdapter, TC4_INDEX) >= QM_MGMT_QUUEUD_THRESHOLD)
- return FRAME_ACTION_TX_PKT;
- else
- return FRAME_ACTION_QUEUE_PKT;
- }
- } /* FRAME_TYPE_802_1X */
- else if ((!IS_BSS_ACTIVE(prBssInfo))
- || (!prStaRec)
- || (!prStaRec->fgIsInUse)) {
- return FRAME_ACTION_DROP_PKT;
- }
- } while (0);
- if (prBssInfo->fgIsNetAbsent) {
- DBGLOG(QM, LOUD, "Queue packets (Absent %u).\n", prBssInfo->ucNetTypeIndex);
- return FRAME_ACTION_QUEUE_PKT;
- }
- if (prStaRec && prStaRec->fgIsInPS) {
- DBGLOG(QM, LOUD, "Queue packets (PS %u).\n", prStaRec->fgIsInPS);
- return FRAME_ACTION_QUEUE_PKT;
- }
- switch (eFrameType) {
- case FRAME_TYPE_802_1X:
- if (!prStaRec->fgIsValid)
- return FRAME_ACTION_QUEUE_PKT;
- break;
- case FRAME_TYPE_MMPDU:
- break;
- default:
- ASSERT(0);
- }
- return FRAME_ACTION_TX_PKT;
- }
- /*----------------------------------------------------------------------------*/
- /*!
- * \brief Handle BSS change operation Event from the FW
- *
- * \param[in] prAdapter Adapter pointer
- * \param[in] prEvent The event packet from the FW
- *
- * \return (none)
- */
- /*----------------------------------------------------------------------------*/
- VOID qmHandleEventBssAbsencePresence(IN P_ADAPTER_T prAdapter, IN P_WIFI_EVENT_T prEvent)
- {
- P_EVENT_BSS_ABSENCE_PRESENCE_T prEventBssStatus;
- P_BSS_INFO_T prBssInfo;
- BOOLEAN fgIsNetAbsentOld;
- prEventBssStatus = (P_EVENT_BSS_ABSENCE_PRESENCE_T) prEvent;
- prBssInfo = &(prAdapter->rWifiVar.arBssInfo[prEventBssStatus->ucNetTypeIdx]);
- fgIsNetAbsentOld = prBssInfo->fgIsNetAbsent;
- prBssInfo->fgIsNetAbsent = prEventBssStatus->fgIsAbsent;
- prBssInfo->ucBssFreeQuota = prEventBssStatus->ucBssFreeQuota;
- /* DBGLOG(QM, TRACE, ("qmHandleEventBssAbsencePresence (ucNetTypeIdx=%d, fgIsAbsent=%d, FreeQuota=%d)\n", */
- /* prEventBssStatus->ucNetTypeIdx, prBssInfo->fgIsNetAbsent, prBssInfo->ucBssFreeQuota)); */
- DBGLOG(QM, INFO, "NAF=%d,%d,%d\n",
- prEventBssStatus->ucNetTypeIdx, prBssInfo->fgIsNetAbsent, prBssInfo->ucBssFreeQuota);
- if (!prBssInfo->fgIsNetAbsent) {
- /* QM_DBG_CNT_27 */
- QM_DBG_CNT_INC(&(prAdapter->rQM), QM_DBG_CNT_27);
- } else {
- /* QM_DBG_CNT_28 */
- QM_DBG_CNT_INC(&(prAdapter->rQM), QM_DBG_CNT_28);
- }
- /* From Absent to Present */
- if ((fgIsNetAbsentOld) && (!prBssInfo->fgIsNetAbsent))
- kalSetEvent(prAdapter->prGlueInfo);
- }
- /*----------------------------------------------------------------------------*/
- /*!
- * \brief Handle STA change PS mode Event from the FW
- *
- * \param[in] prAdapter Adapter pointer
- * \param[in] prEvent The event packet from the FW
- *
- * \return (none)
- */
- /*----------------------------------------------------------------------------*/
- VOID qmHandleEventStaChangePsMode(IN P_ADAPTER_T prAdapter, IN P_WIFI_EVENT_T prEvent)
- {
- P_EVENT_STA_CHANGE_PS_MODE_T prEventStaChangePsMode;
- P_STA_RECORD_T prStaRec;
- BOOLEAN fgIsInPSOld;
- /* DbgPrint("QM:Event -RxBa\n"); */
- prEventStaChangePsMode = (P_EVENT_STA_CHANGE_PS_MODE_T) prEvent;
- prStaRec = QM_GET_STA_REC_PTR_FROM_INDEX(prAdapter, prEventStaChangePsMode->ucStaRecIdx);
- ASSERT(prStaRec);
- if (prStaRec) {
- fgIsInPSOld = prStaRec->fgIsInPS;
- prStaRec->fgIsInPS = prEventStaChangePsMode->fgIsInPs;
- qmUpdateFreeQuota(prAdapter,
- prStaRec,
- prEventStaChangePsMode->ucUpdateMode, prEventStaChangePsMode->ucFreeQuota, 0);
- /* DBGLOG(QM, TRACE, ("qmHandleEventStaChangePsMode (ucStaRecIdx=%d, fgIsInPs=%d)\n", */
- /* prEventStaChangePsMode->ucStaRecIdx, prStaRec->fgIsInPS)); */
- DBGLOG(QM, TRACE, "PS=%d,%d\n", prEventStaChangePsMode->ucStaRecIdx, prStaRec->fgIsInPS);
- /* From PS to Awake */
- if ((fgIsInPSOld) && (!prStaRec->fgIsInPS))
- kalSetEvent(prAdapter->prGlueInfo);
- }
- }
- /*----------------------------------------------------------------------------*/
- /*!
- * \brief Update STA free quota Event from FW
- *
- * \param[in] prAdapter Adapter pointer
- * \param[in] prEvent The event packet from the FW
- *
- * \return (none)
- */
- /*----------------------------------------------------------------------------*/
- VOID qmHandleEventStaUpdateFreeQuota(IN P_ADAPTER_T prAdapter, IN P_WIFI_EVENT_T prEvent)
- {
- P_EVENT_STA_UPDATE_FREE_QUOTA_T prEventStaUpdateFreeQuota;
- P_STA_RECORD_T prStaRec;
- prEventStaUpdateFreeQuota = (P_EVENT_STA_UPDATE_FREE_QUOTA_T) prEvent;
- prStaRec = QM_GET_STA_REC_PTR_FROM_INDEX(prAdapter, prEventStaUpdateFreeQuota->ucStaRecIdx);
- ASSERT(prStaRec);
- if (prStaRec) {
- if (prStaRec->fgIsInPS) {
- qmUpdateFreeQuota(prAdapter,
- prStaRec,
- prEventStaUpdateFreeQuota->ucUpdateMode,
- prEventStaUpdateFreeQuota->ucFreeQuota,
- prEventStaUpdateFreeQuota->aucReserved[0]);
- kalSetEvent(prAdapter->prGlueInfo);
- }
- #if 0
- DBGLOG(QM, TRACE,
- "qmHandleEventStaUpdateFreeQuota (ucStaRecIdx=%d, ucUpdateMode=%d, ucFreeQuota=%d)\n",
- prEventStaUpdateFreeQuota->ucStaRecIdx, prEventStaUpdateFreeQuota->ucUpdateMode,
- prEventStaUpdateFreeQuota->ucFreeQuota);
- #endif
- DBGLOG(QM, TRACE, "UFQ=%d,%d,%d\n",
- prEventStaUpdateFreeQuota->ucStaRecIdx,
- prEventStaUpdateFreeQuota->ucUpdateMode, prEventStaUpdateFreeQuota->ucFreeQuota);
- }
- }
- /*----------------------------------------------------------------------------*/
- /*!
- * \brief Update STA free quota
- *
- * \param[in] prStaRec the STA
- * \param[in] ucUpdateMode the method to update free quota
- * \param[in] ucFreeQuota the value for update
- *
- * \return (none)
- */
- /*----------------------------------------------------------------------------*/
- VOID
- qmUpdateFreeQuota(IN P_ADAPTER_T prAdapter,
- IN P_STA_RECORD_T prStaRec, IN UINT_8 ucUpdateMode, IN UINT_8 ucFreeQuota, IN UINT_8 ucNumOfTxDone)
- {
- UINT_8 ucFreeQuotaForNonDelivery;
- UINT_8 ucFreeQuotaForDelivery;
- BOOLEAN flgIsUpdateForcedToDelivery;
- ASSERT(prStaRec);
- DBGLOG(QM, LOUD, "qmUpdateFreeQuota orig ucFreeQuota=%d Mode %u New %u\n",
- prStaRec->ucFreeQuota, ucUpdateMode, ucFreeQuota);
- if (!prStaRec->fgIsInPS)
- return;
- flgIsUpdateForcedToDelivery = FALSE;
- if (ucNumOfTxDone > 0) {
- /*
- update free quota by
- num of tx done + resident free quota (delivery + non-delivery)
- */
- UINT_8 ucAvailQuota;
- ucAvailQuota = ucNumOfTxDone + prStaRec->ucFreeQuotaForDelivery + prStaRec->ucFreeQuotaForNonDelivery;
- if (ucAvailQuota > ucFreeQuota) /* sanity check */
- ucAvailQuota = ucFreeQuota;
- /* update current free quota */
- ucFreeQuota = ucAvailQuota;
- /* check if the update is from last packet */
- if (ucFreeQuota == (prStaRec->ucFreeQuota + 1)) {
- /* just add the extra quota to delivery queue */
- /*
- EX:
- 1. TDLS peer enters power save
- 2. When the last 2 VI packets are tx done, we will receive 2 update events
- 3. 1st update event: ucFreeQuota = 9
- 4. We will correct new quota for delivey and non-delivery to 7:2
- 5. 2rd update event: ucFreeQuota = 10
- 6. We will re-correct new quota for delivery and non-delivery to 5:5
- But non-delivery queue is not busy.
- So in the case, we will have wrong decision, i.e. higher queue always quota 5
- Solution: skip the 2rd update event and just add the extra quota to delivery.
- */
- flgIsUpdateForcedToDelivery = TRUE;
- }
- }
- switch (ucUpdateMode) {
- case FREE_QUOTA_UPDATE_MODE_INIT:
- case FREE_QUOTA_UPDATE_MODE_OVERWRITE:
- prStaRec->ucFreeQuota = ucFreeQuota;
- break;
- case FREE_QUOTA_UPDATE_MODE_INCREASE:
- prStaRec->ucFreeQuota += ucFreeQuota;
- break;
- case FREE_QUOTA_UPDATE_MODE_DECREASE:
- prStaRec->ucFreeQuota -= ucFreeQuota;
- break;
- default:
- ASSERT(0);
- }
- DBGLOG(QM, LOUD, "qmUpdateFreeQuota new ucFreeQuota=%d)\n", prStaRec->ucFreeQuota);
- ucFreeQuota = prStaRec->ucFreeQuota;
- ucFreeQuotaForNonDelivery = 0;
- ucFreeQuotaForDelivery = 0;
- if (ucFreeQuota > 0) {
- if (prStaRec->fgIsQoS && prStaRec->fgIsUapsdSupported
- /* && prAdapter->rWifiVar.fgSupportQoS
- && prAdapter->rWifiVar.fgSupportUAPSD */) {
- /* XXX We should assign quota to aucFreeQuotaPerQueue[NUM_OF_PER_STA_TX_QUEUES] */
- if (flgIsUpdateForcedToDelivery == FALSE) {
- if (prStaRec->ucFreeQuotaForNonDelivery > 0 && prStaRec->ucFreeQuotaForDelivery > 0) {
- ucFreeQuotaForNonDelivery = ucFreeQuota >> 1;
- ucFreeQuotaForDelivery = ucFreeQuota - ucFreeQuotaForNonDelivery;
- } else if (prStaRec->ucFreeQuotaForNonDelivery == 0
- && prStaRec->ucFreeQuotaForDelivery == 0) {
- ucFreeQuotaForNonDelivery = ucFreeQuota >> 1;
- ucFreeQuotaForDelivery = ucFreeQuota - ucFreeQuotaForNonDelivery;
- } else if (prStaRec->ucFreeQuotaForNonDelivery > 0) {
- /* NonDelivery is not busy */
- if (ucFreeQuota >= 3) {
- ucFreeQuotaForNonDelivery = 2;
- ucFreeQuotaForDelivery = ucFreeQuota - ucFreeQuotaForNonDelivery;
- } else {
- ucFreeQuotaForDelivery = ucFreeQuota;
- ucFreeQuotaForNonDelivery = 0;
- }
- } else if (prStaRec->ucFreeQuotaForDelivery > 0) {
- /* Delivery is not busy */
- if (ucFreeQuota >= 3) {
- ucFreeQuotaForDelivery = 2;
- ucFreeQuotaForNonDelivery = ucFreeQuota - ucFreeQuotaForDelivery;
- } else {
- ucFreeQuotaForNonDelivery = ucFreeQuota;
- ucFreeQuotaForDelivery = 0;
- }
- }
- } else {
- ucFreeQuotaForNonDelivery = 2;
- ucFreeQuotaForDelivery = ucFreeQuota - ucFreeQuotaForNonDelivery;
- }
- } else {
- /* no use ? */
- /* !prStaRec->fgIsUapsdSupported */
- ucFreeQuotaForNonDelivery = ucFreeQuota;
- ucFreeQuotaForDelivery = 0;
- }
- }
- /* ucFreeQuota > 0 */
- prStaRec->ucFreeQuotaForDelivery = ucFreeQuotaForDelivery;
- prStaRec->ucFreeQuotaForNonDelivery = ucFreeQuotaForNonDelivery;
- #if (CFG_SUPPORT_TDLS_DBG == 1)
- if (IS_TDLS_STA(prStaRec))
- DBGLOG(QM, LOUD, "<tx> quota %d %d %d\n",
- ucFreeQuota, ucFreeQuotaForDelivery, ucFreeQuotaForNonDelivery);
- #endif
- DBGLOG(QM, LOUD, "new QuotaForDelivery = %d QuotaForNonDelivery = %d\n",
- prStaRec->ucFreeQuotaForDelivery, prStaRec->ucFreeQuotaForNonDelivery);
- }
- /*----------------------------------------------------------------------------*/
- /*!
- * \brief Return the reorder queued RX packets
- *
- * \param[in] (none)
- *
- * \return The number of queued RX packets
- */
- /*----------------------------------------------------------------------------*/
- UINT_32 qmGetRxReorderQueuedBufferCount(IN P_ADAPTER_T prAdapter)
- {
- UINT_32 i, u4Total;
- P_QUE_MGT_T prQM = &prAdapter->rQM;
- u4Total = 0;
- /* XXX The summation may impact the performance */
- for (i = 0; i < CFG_NUM_OF_RX_BA_AGREEMENTS; i++) {
- u4Total += prQM->arRxBaTable[i].rReOrderQue.u4NumElem;
- #if DBG && 0
- if (QUEUE_IS_EMPTY(&(prQM->arRxBaTable[i].rReOrderQue)))
- ASSERT(prQM->arRxBaTable[i].rReOrderQue == 0);
- #endif
- }
- ASSERT(u4Total <= (CFG_NUM_OF_QM_RX_PKT_NUM * 2));
- return u4Total;
- }
- #if ARP_MONITER_ENABLE
- VOID qmDetectArpNoResponse(P_ADAPTER_T prAdapter, P_MSDU_INFO_T prMsduInfo)
- {
- struct sk_buff *prSkb = NULL;
- PUINT_8 pucData = NULL;
- UINT_16 u2EtherType = 0;
- int arpOpCode = 0;
- prSkb = (struct sk_buff *)prMsduInfo->prPacket;
- if (!prSkb || (prSkb->len <= ETHER_HEADER_LEN))
- return;
- pucData = prSkb->data;
- if (!pucData)
- return;
- u2EtherType = (pucData[ETH_TYPE_LEN_OFFSET] << 8) | (pucData[ETH_TYPE_LEN_OFFSET + 1]);
- if (u2EtherType != ETH_P_ARP || (apIp[0] | apIp[1] | apIp[2] | apIp[3]) == 0)
- return;
- if (kalMemCmp(apIp, &pucData[ETH_TYPE_LEN_OFFSET + 26], sizeof(apIp))) /* dest ip address */
- return;
- arpOpCode = (pucData[ETH_TYPE_LEN_OFFSET + 8] << 8) | (pucData[ETH_TYPE_LEN_OFFSET + 8 + 1]);
- if (arpOpCode == ARP_PRO_REQ) {
- arpMoniter++;
- if (arpMoniter > 20) {
- DBGLOG(INIT, WARN, "IOT Critical issue, arp no resp, check AP!\n");
- aisBssBeaconTimeout(prAdapter);
- arpMoniter = 0;
- kalMemZero(apIp, sizeof(apIp));
- }
- }
- }
- VOID qmHandleRxArpPackets(P_ADAPTER_T prAdapter, P_SW_RFB_T prSwRfb)
- {
- PUINT_8 pucData = NULL;
- UINT_16 u2EtherType = 0;
- int arpOpCode = 0;
- P_BSS_INFO_T prBssInfo = NULL;
- if (prSwRfb->u2PacketLen <= ETHER_HEADER_LEN)
- return;
- pucData = (PUINT_8)prSwRfb->pvHeader;
- if (!pucData)
- return;
- u2EtherType = (pucData[ETH_TYPE_LEN_OFFSET] << 8) | (pucData[ETH_TYPE_LEN_OFFSET + 1]);
- if (u2EtherType != ETH_P_ARP)
- return;
- arpOpCode = (pucData[ETH_TYPE_LEN_OFFSET + 8] << 8) | (pucData[ETH_TYPE_LEN_OFFSET + 8 + 1]);
- prBssInfo = &(prAdapter->rWifiVar.arBssInfo[NETWORK_TYPE_AIS_INDEX]);
- if (arpOpCode == ARP_PRO_RSP) {
- arpMoniter = 0;
- if (prBssInfo && prBssInfo->prStaRecOfAP && prBssInfo->prStaRecOfAP->aucMacAddr) {
- if (EQUAL_MAC_ADDR(&(pucData[ETH_TYPE_LEN_OFFSET + 10]), /* source hardware address */
- prBssInfo->prStaRecOfAP->aucMacAddr)) {
- kalMemCopy(apIp, &(pucData[ETH_TYPE_LEN_OFFSET + 16]), sizeof(apIp));
- DBGLOG(INIT, TRACE, "get arp response from AP %d.%d.%d.%d\n",
- apIp[0], apIp[1], apIp[2], apIp[3]);
- }
- }
- }
- }
- VOID qmResetArpDetect(VOID)
- {
- arpMoniter = 0;
- kalMemZero(apIp, sizeof(apIp));
- }
- #endif
- VOID qmHandleReorderBubbleTimeout(IN P_ADAPTER_T prAdapter, IN ULONG ulParamPtr)
- {
- P_RX_BA_ENTRY_T prReorderQueParm = (P_RX_BA_ENTRY_T) ulParamPtr;
- P_SW_RFB_T prSwRfb = (P_SW_RFB_T) NULL;
- P_EVENT_CHECK_REORDER_BUBBLE_T prCheckReorderEvent;
- if (!prReorderQueParm->fgIsValid) {
- DBGLOG(QM, TRACE, "QM:Bub Check Cancel STA[%u] TID[%u], No Rx BA entry\n",
- prReorderQueParm->ucStaRecIdx, prReorderQueParm->ucTid);
- return;
- }
- if (!prReorderQueParm->fgHasBubble) {
- DBGLOG(QM, TRACE,
- "QM:Bub Check Cancel STA[%u] TID[%u], Bubble has been filled\n",
- prReorderQueParm->ucStaRecIdx, prReorderQueParm->ucTid);
- return;
- }
- DBGLOG(QM, TRACE, "QM:Bub Timeout STA[%u] TID[%u] BubSN[%u]\n",
- prReorderQueParm->ucStaRecIdx, prReorderQueParm->ucTid, prReorderQueParm->u2FirstBubbleSn);
- /* Generate a self-inited event to Rx path */
- QUEUE_REMOVE_HEAD(&prAdapter->rRxCtrl.rFreeSwRfbList, prSwRfb, P_SW_RFB_T);
- if (prSwRfb) {
- prCheckReorderEvent = (P_EVENT_CHECK_REORDER_BUBBLE_T) prSwRfb->pucRecvBuff;
- prSwRfb->ucPacketType = HIF_RX_PKT_TYPE_EVENT;
- prCheckReorderEvent->ucEID = EVENT_ID_CHECK_REORDER_BUBBLE;
- prCheckReorderEvent->ucSeqNum = 0;
- prCheckReorderEvent->ucStaRecIdx = prReorderQueParm->ucStaRecIdx;
- prCheckReorderEvent->ucTid = prReorderQueParm->ucTid;
- prCheckReorderEvent->u2Length = sizeof(EVENT_CHECK_REORDER_BUBBLE_T);
- QUEUE_INSERT_TAIL(&prAdapter->rRxCtrl.rReceivedRfbList, &prSwRfb->rQueEntry);
- RX_INC_CNT(&prAdapter->rRxCtrl, RX_MPDU_TOTAL_COUNT);
- DBGLOG(QM, LOUD, "QM:Bub Check Event Sent STA[%u] TID[%u]\n",
- prReorderQueParm->ucStaRecIdx, prReorderQueParm->ucTid);
- nicRxProcessRFBs(prAdapter);
- DBGLOG(QM, LOUD, "QM:Bub Check Event Handled STA[%u] TID[%u]\n",
- prReorderQueParm->ucStaRecIdx, prReorderQueParm->ucTid);
- } else {
- DBGLOG(QM, TRACE,
- "QM:Bub Check Cancel STA[%u] TID[%u], Bub check event alloc failed\n",
- prReorderQueParm->ucStaRecIdx, prReorderQueParm->ucTid);
- cnmTimerStartTimer(prAdapter, &(prReorderQueParm->rReorderBubbleTimer), QM_RX_BA_ENTRY_MISS_TIMEOUT_MS);
- DBGLOG(QM, TRACE, "QM:Bub Timer Restart STA[%u] TID[%u] BubSN[%u] Win{%d, %d}\n",
- prReorderQueParm->ucStaRecIdx,
- prReorderQueParm->ucTid,
- prReorderQueParm->u2FirstBubbleSn,
- prReorderQueParm->u2WinStart, prReorderQueParm->u2WinEnd);
- }
- }
- VOID qmHandleEventCheckReorderBubble(IN P_ADAPTER_T prAdapter, IN P_WIFI_EVENT_T prEvent)
- {
- P_EVENT_CHECK_REORDER_BUBBLE_T prCheckReorderEvent = (P_EVENT_CHECK_REORDER_BUBBLE_T) prEvent;
- P_RX_BA_ENTRY_T prReorderQueParm;
- P_QUE_T prReorderQue;
- QUE_T rReturnedQue;
- P_QUE_T prReturnedQue = &rReturnedQue;
- P_SW_RFB_T prReorderedSwRfb, prSwRfb;
- QUEUE_INITIALIZE(prReturnedQue);
- /* Get target Rx BA entry */
- prReorderQueParm = qmLookupRxBaEntry(prAdapter, prCheckReorderEvent->ucStaRecIdx, prCheckReorderEvent->ucTid);
- /* Sanity Check */
- if (!prReorderQueParm || !prReorderQueParm->fgIsValid || !prReorderQueParm->fgHasBubble) {
- DBGLOG(QM, WARN, "QM:Bub Check Cancel STA[%u] TID[%u]. QueParm %p valid %d has bubble %d\n",
- prCheckReorderEvent->ucStaRecIdx, prCheckReorderEvent->ucTid, prReorderQueParm,
- prReorderQueParm->fgIsValid, prReorderQueParm->fgHasBubble);
- return;
- }
- prReorderQue = &(prReorderQueParm->rReOrderQue);
- if (QUEUE_IS_EMPTY(prReorderQue)) {
- prReorderQueParm->fgHasBubble = FALSE;
- DBGLOG(QM, WARN,
- "QM:Bub Check Cancel STA[%u] TID[%u], Bubble has been filled\n",
- prReorderQueParm->ucStaRecIdx, prReorderQueParm->ucTid);
- return;
- }
- DBGLOG(QM, TRACE, "QM:Bub Check Event Got STA[%u] TID[%u]\n",
- prReorderQueParm->ucStaRecIdx, prReorderQueParm->ucTid);
- /* Expected bubble timeout => pop out packets before win_end */
- if (prReorderQueParm->u2FirstBubbleSn == prReorderQueParm->u2WinStart) {
- prReorderedSwRfb = (P_SW_RFB_T) QUEUE_GET_TAIL(prReorderQue);
- prReorderQueParm->u2WinStart = prReorderedSwRfb->u2SSN + 1;
- prReorderQueParm->u2WinEnd =
- ((prReorderQueParm->u2WinStart) + (prReorderQueParm->u2WinSize) - 1) % MAX_SEQ_NO_COUNT;
- qmPopOutDueToFallAhead(prAdapter, prReorderQueParm, prReturnedQue);
- DBGLOG(QM, TRACE, "QM:Bub Flush) STA[%u] TID[%u] BubSN[%u] Win{%d, %d}\n",
- prReorderQueParm->ucStaRecIdx,
- prReorderQueParm->ucTid,
- prReorderQueParm->u2FirstBubbleSn,
- prReorderQueParm->u2WinStart, prReorderQueParm->u2WinEnd);
- if (QUEUE_IS_NOT_EMPTY(prReturnedQue)) {
- QM_TX_SET_NEXT_MSDU_INFO((P_SW_RFB_T) QUEUE_GET_TAIL(prReturnedQue), NULL);
- prSwRfb = (P_SW_RFB_T) QUEUE_GET_HEAD(prReturnedQue);
- while (prSwRfb) {
- DBGLOG(QM, TRACE,
- "QM:Bub Flush STA[%u] TID[%u] Pop Out SN[%u]\n",
- prReorderQueParm->ucStaRecIdx, prReorderQueParm->ucTid, prSwRfb->u2SSN);
- prSwRfb = (P_SW_RFB_T) QUEUE_GET_NEXT_ENTRY((P_QUE_ENTRY_T) prSwRfb);
- }
- wlanProcessQueuedSwRfb(prAdapter, (P_SW_RFB_T) QUEUE_GET_HEAD(prReturnedQue));
- } else {
- DBGLOG(QM, TRACE, "QM:Bub Flush STA[%u] TID[%u] Pop Out 0 packet\n",
- prReorderQueParm->ucStaRecIdx, prReorderQueParm->ucTid);
- }
- prReorderQueParm->fgHasBubble = FALSE;
- }
- /* First bubble has been filled but others exist */
- else {
- prReorderQueParm->u2FirstBubbleSn = prReorderQueParm->u2WinStart;
- cnmTimerStartTimer(prAdapter, &(prReorderQueParm->rReorderBubbleTimer), QM_RX_BA_ENTRY_MISS_TIMEOUT_MS);
- DBGLOG(QM, TRACE, "QM:Bub Timer STA[%u] TID[%u] BubSN[%u] Win{%d, %d}\n",
- prReorderQueParm->ucStaRecIdx,
- prReorderQueParm->ucTid,
- prReorderQueParm->u2FirstBubbleSn,
- prReorderQueParm->u2WinStart, prReorderQueParm->u2WinEnd);
- }
- }
|