0010-mwlwifi.patch 545 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209421042114212421342144215421642174218421942204221422242234224422542264227422842294230423142324233423442354236423742384239424042414242424342444245424642474248424942504251425242534254425542564257425842594260426142624263426442654266426742684269427042714272427342744275427642774278427942804281428242834284428542864287428842894290429142924293429442954296429742984299430043014302430343044305430643074308430943104311431243134314431543164317431843194320432143224323432443254326432743284329433043314332433343344335433643374338433943404341434243434344434543464347434843494350435143524353435443554356435743584359436043614362436343644365436643674368436943704371437243734374437543764377437843794380438143824383438443854386438743884389439043914392439343944395439643974398439944004401440244034404440544064407440844094410441144124413441444154416441744184419442044214422442344244425442644274428442944304431443244334434443544364437443844394440444144424443444444454446444744484449445044514452445344544455445644574458445944604461446244634464446544664467446844694470447144724473447444754476447744784479448044814482448344844485448644874488448944904491449244934494449544964497449844994500450145024503450445054506450745084509451045114512451345144515451645174518451945204521452245234524452545264527452845294530453145324533453445354536453745384539454045414542454345444545454645474548454945504551455245534554455545564557455845594560456145624563456445654566456745684569457045714572457345744575457645774578457945804581458245834584458545864587458845894590459145924593459445954596459745984599460046014602460346044605460646074608460946104611461246134614461546164617461846194620462146224623462446254626462746284629463046314632463346344635463646374638463946404641464246434644464546464647464846494650465146524653465446554656465746584659466046614662466346644665466646674668466946704671467246734674467546764677467846794680468146824683468446854686468746884689469046914692469346944695469646974698469947004701470247034704470547064707470847094710471147124713471447154716471747184719472047214722472347244725472647274728472947304731473247334734473547364737473847394740474147424743474447454746474747484749475047514752475347544755475647574758475947604761476247634764476547664767476847694770477147724773477447754776477747784779478047814782478347844785478647874788478947904791479247934794479547964797479847994800480148024803480448054806480748084809481048114812481348144815481648174818481948204821482248234824482548264827482848294830483148324833483448354836483748384839484048414842484348444845484648474848484948504851485248534854485548564857485848594860486148624863486448654866486748684869487048714872487348744875487648774878487948804881488248834884488548864887488848894890489148924893489448954896489748984899490049014902490349044905490649074908490949104911491249134914491549164917491849194920492149224923492449254926492749284929493049314932493349344935493649374938493949404941494249434944494549464947494849494950495149524953495449554956495749584959496049614962496349644965496649674968496949704971497249734974497549764977497849794980498149824983498449854986498749884989499049914992499349944995499649974998499950005001500250035004500550065007500850095010501150125013501450155016501750185019502050215022502350245025502650275028502950305031503250335034503550365037503850395040504150425043504450455046504750485049505050515052505350545055505650575058505950605061506250635064506550665067506850695070507150725073507450755076507750785079508050815082508350845085508650875088508950905091509250935094509550965097509850995100510151025103510451055106510751085109511051115112511351145115511651175118511951205121512251235124512551265127512851295130513151325133513451355136513751385139514051415142514351445145514651475148514951505151515251535154515551565157515851595160516151625163516451655166516751685169517051715172517351745175517651775178517951805181518251835184518551865187518851895190519151925193519451955196519751985199520052015202520352045205520652075208520952105211521252135214521552165217521852195220522152225223522452255226522752285229523052315232523352345235523652375238523952405241524252435244524552465247524852495250525152525253525452555256525752585259526052615262526352645265526652675268526952705271527252735274527552765277527852795280528152825283528452855286528752885289529052915292529352945295529652975298529953005301530253035304530553065307530853095310531153125313531453155316531753185319532053215322532353245325532653275328532953305331533253335334533553365337533853395340534153425343534453455346534753485349535053515352535353545355535653575358535953605361536253635364536553665367536853695370537153725373537453755376537753785379538053815382538353845385538653875388538953905391539253935394539553965397539853995400540154025403540454055406540754085409541054115412541354145415541654175418541954205421542254235424542554265427542854295430543154325433543454355436543754385439544054415442544354445445544654475448544954505451545254535454545554565457545854595460546154625463546454655466546754685469547054715472547354745475547654775478547954805481548254835484548554865487548854895490549154925493549454955496549754985499550055015502550355045505550655075508550955105511551255135514551555165517551855195520552155225523552455255526552755285529553055315532553355345535553655375538553955405541554255435544554555465547554855495550555155525553555455555556555755585559556055615562556355645565556655675568556955705571557255735574557555765577557855795580558155825583558455855586558755885589559055915592559355945595559655975598559956005601560256035604560556065607560856095610561156125613561456155616561756185619562056215622562356245625562656275628562956305631563256335634563556365637563856395640564156425643564456455646564756485649565056515652565356545655565656575658565956605661566256635664566556665667566856695670567156725673567456755676567756785679568056815682568356845685568656875688568956905691569256935694569556965697569856995700570157025703570457055706570757085709571057115712571357145715571657175718571957205721572257235724572557265727572857295730573157325733573457355736573757385739574057415742574357445745574657475748574957505751575257535754575557565757575857595760576157625763576457655766576757685769577057715772577357745775577657775778577957805781578257835784578557865787578857895790579157925793579457955796579757985799580058015802580358045805580658075808580958105811581258135814581558165817581858195820582158225823582458255826582758285829583058315832583358345835583658375838583958405841584258435844584558465847584858495850585158525853585458555856585758585859586058615862586358645865586658675868586958705871587258735874587558765877587858795880588158825883588458855886588758885889589058915892589358945895589658975898589959005901590259035904590559065907590859095910591159125913591459155916591759185919592059215922592359245925592659275928592959305931593259335934593559365937593859395940594159425943594459455946594759485949595059515952595359545955595659575958595959605961596259635964596559665967596859695970597159725973597459755976597759785979598059815982598359845985598659875988598959905991599259935994599559965997599859996000600160026003600460056006600760086009601060116012601360146015601660176018601960206021602260236024602560266027602860296030603160326033603460356036603760386039604060416042604360446045604660476048604960506051605260536054605560566057605860596060606160626063606460656066606760686069607060716072607360746075607660776078607960806081608260836084608560866087608860896090609160926093609460956096609760986099610061016102610361046105610661076108610961106111611261136114611561166117611861196120612161226123612461256126612761286129613061316132613361346135613661376138613961406141614261436144614561466147614861496150615161526153615461556156615761586159616061616162616361646165616661676168616961706171617261736174617561766177617861796180618161826183618461856186618761886189619061916192619361946195619661976198619962006201620262036204620562066207620862096210621162126213621462156216621762186219622062216222622362246225622662276228622962306231623262336234623562366237623862396240624162426243624462456246624762486249625062516252625362546255625662576258625962606261626262636264626562666267626862696270627162726273627462756276627762786279628062816282628362846285628662876288628962906291629262936294629562966297629862996300630163026303630463056306630763086309631063116312631363146315631663176318631963206321632263236324632563266327632863296330633163326333633463356336633763386339634063416342634363446345634663476348634963506351635263536354635563566357635863596360636163626363636463656366636763686369637063716372637363746375637663776378637963806381638263836384638563866387638863896390639163926393639463956396639763986399640064016402640364046405640664076408640964106411641264136414641564166417641864196420642164226423642464256426642764286429643064316432643364346435643664376438643964406441644264436444644564466447644864496450645164526453645464556456645764586459646064616462646364646465646664676468646964706471647264736474647564766477647864796480648164826483648464856486648764886489649064916492649364946495649664976498649965006501650265036504650565066507650865096510651165126513651465156516651765186519652065216522652365246525652665276528652965306531653265336534653565366537653865396540654165426543654465456546654765486549655065516552655365546555655665576558655965606561656265636564656565666567656865696570657165726573657465756576657765786579658065816582658365846585658665876588658965906591659265936594659565966597659865996600660166026603660466056606660766086609661066116612661366146615661666176618661966206621662266236624662566266627662866296630663166326633663466356636663766386639664066416642664366446645664666476648664966506651665266536654665566566657665866596660666166626663666466656666666766686669667066716672667366746675667666776678667966806681668266836684668566866687668866896690669166926693669466956696669766986699670067016702670367046705670667076708670967106711671267136714671567166717671867196720672167226723672467256726672767286729673067316732673367346735673667376738673967406741674267436744674567466747674867496750675167526753675467556756675767586759676067616762676367646765676667676768676967706771677267736774677567766777677867796780678167826783678467856786678767886789679067916792679367946795679667976798679968006801680268036804680568066807680868096810681168126813681468156816681768186819682068216822682368246825682668276828682968306831683268336834683568366837683868396840684168426843684468456846684768486849685068516852685368546855685668576858685968606861686268636864686568666867686868696870687168726873687468756876687768786879688068816882688368846885688668876888688968906891689268936894689568966897689868996900690169026903690469056906690769086909691069116912691369146915691669176918691969206921692269236924692569266927692869296930693169326933693469356936693769386939694069416942694369446945694669476948694969506951695269536954695569566957695869596960696169626963696469656966696769686969697069716972697369746975697669776978697969806981698269836984698569866987698869896990699169926993699469956996699769986999700070017002700370047005700670077008700970107011701270137014701570167017701870197020702170227023702470257026702770287029703070317032703370347035703670377038703970407041704270437044704570467047704870497050705170527053705470557056705770587059706070617062706370647065706670677068706970707071707270737074707570767077707870797080708170827083708470857086708770887089709070917092709370947095709670977098709971007101710271037104710571067107710871097110711171127113711471157116711771187119712071217122712371247125712671277128712971307131713271337134713571367137713871397140714171427143714471457146714771487149715071517152715371547155715671577158715971607161716271637164716571667167716871697170717171727173717471757176717771787179718071817182718371847185718671877188718971907191719271937194719571967197719871997200720172027203720472057206720772087209721072117212721372147215721672177218721972207221722272237224722572267227722872297230723172327233723472357236723772387239724072417242724372447245724672477248724972507251725272537254725572567257725872597260726172627263726472657266726772687269727072717272727372747275727672777278727972807281728272837284728572867287728872897290729172927293729472957296729772987299730073017302730373047305730673077308730973107311731273137314731573167317731873197320732173227323732473257326732773287329733073317332733373347335733673377338733973407341734273437344734573467347734873497350735173527353735473557356735773587359736073617362736373647365736673677368736973707371737273737374737573767377737873797380738173827383738473857386738773887389739073917392739373947395739673977398739974007401740274037404740574067407740874097410741174127413741474157416741774187419742074217422742374247425742674277428742974307431743274337434743574367437743874397440744174427443744474457446744774487449745074517452745374547455745674577458745974607461746274637464746574667467746874697470747174727473747474757476747774787479748074817482748374847485748674877488748974907491749274937494749574967497749874997500750175027503750475057506750775087509751075117512751375147515751675177518751975207521752275237524752575267527752875297530753175327533753475357536753775387539754075417542754375447545754675477548754975507551755275537554755575567557755875597560756175627563756475657566756775687569757075717572757375747575757675777578757975807581758275837584758575867587758875897590759175927593759475957596759775987599760076017602760376047605760676077608760976107611761276137614761576167617761876197620762176227623762476257626762776287629763076317632763376347635763676377638763976407641764276437644764576467647764876497650765176527653765476557656765776587659766076617662766376647665766676677668766976707671767276737674767576767677767876797680768176827683768476857686768776887689769076917692769376947695769676977698769977007701770277037704770577067707770877097710771177127713771477157716771777187719772077217722772377247725772677277728772977307731773277337734773577367737773877397740774177427743774477457746774777487749775077517752775377547755775677577758775977607761776277637764776577667767776877697770777177727773777477757776777777787779778077817782778377847785778677877788778977907791779277937794779577967797779877997800780178027803780478057806780778087809781078117812781378147815781678177818781978207821782278237824782578267827782878297830783178327833783478357836783778387839784078417842784378447845784678477848784978507851785278537854785578567857785878597860786178627863786478657866786778687869787078717872787378747875787678777878787978807881788278837884788578867887788878897890789178927893789478957896789778987899790079017902790379047905790679077908790979107911791279137914791579167917791879197920792179227923792479257926792779287929793079317932793379347935793679377938793979407941794279437944794579467947794879497950795179527953795479557956795779587959796079617962796379647965796679677968796979707971797279737974797579767977797879797980798179827983798479857986798779887989799079917992799379947995799679977998799980008001800280038004800580068007800880098010801180128013801480158016801780188019802080218022802380248025802680278028802980308031803280338034803580368037803880398040804180428043804480458046804780488049805080518052805380548055805680578058805980608061806280638064806580668067806880698070807180728073807480758076807780788079808080818082808380848085808680878088808980908091809280938094809580968097809880998100810181028103810481058106810781088109811081118112811381148115811681178118811981208121812281238124812581268127812881298130813181328133813481358136813781388139814081418142814381448145814681478148814981508151815281538154815581568157815881598160816181628163816481658166816781688169817081718172817381748175817681778178817981808181818281838184818581868187818881898190819181928193819481958196819781988199820082018202820382048205820682078208820982108211821282138214821582168217821882198220822182228223822482258226822782288229823082318232823382348235823682378238823982408241824282438244824582468247824882498250825182528253825482558256825782588259826082618262826382648265826682678268826982708271827282738274827582768277827882798280828182828283828482858286828782888289829082918292829382948295829682978298829983008301830283038304830583068307830883098310831183128313831483158316831783188319832083218322832383248325832683278328832983308331833283338334833583368337833883398340834183428343834483458346834783488349835083518352835383548355835683578358835983608361836283638364836583668367836883698370837183728373837483758376837783788379838083818382838383848385838683878388838983908391839283938394839583968397839883998400840184028403840484058406840784088409841084118412841384148415841684178418841984208421842284238424842584268427842884298430843184328433843484358436843784388439844084418442844384448445844684478448844984508451845284538454845584568457845884598460846184628463846484658466846784688469847084718472847384748475847684778478847984808481848284838484848584868487848884898490849184928493849484958496849784988499850085018502850385048505850685078508850985108511851285138514851585168517851885198520852185228523852485258526852785288529853085318532853385348535853685378538853985408541854285438544854585468547854885498550855185528553855485558556855785588559856085618562856385648565856685678568856985708571857285738574857585768577857885798580858185828583858485858586858785888589859085918592859385948595859685978598859986008601860286038604860586068607860886098610861186128613861486158616861786188619862086218622862386248625862686278628862986308631863286338634863586368637863886398640864186428643864486458646864786488649865086518652865386548655865686578658865986608661866286638664866586668667866886698670867186728673867486758676867786788679868086818682868386848685868686878688868986908691869286938694869586968697869886998700870187028703870487058706870787088709871087118712871387148715871687178718871987208721872287238724872587268727872887298730873187328733873487358736873787388739874087418742874387448745874687478748874987508751875287538754875587568757875887598760876187628763876487658766876787688769877087718772877387748775877687778778877987808781878287838784878587868787878887898790879187928793879487958796879787988799880088018802880388048805880688078808880988108811881288138814881588168817881888198820882188228823882488258826882788288829883088318832883388348835883688378838883988408841884288438844884588468847884888498850885188528853885488558856885788588859886088618862886388648865886688678868886988708871887288738874887588768877887888798880888188828883888488858886888788888889889088918892889388948895889688978898889989008901890289038904890589068907890889098910891189128913891489158916891789188919892089218922892389248925892689278928892989308931893289338934893589368937893889398940894189428943894489458946894789488949895089518952895389548955895689578958895989608961896289638964896589668967896889698970897189728973897489758976897789788979898089818982898389848985898689878988898989908991899289938994899589968997899889999000900190029003900490059006900790089009901090119012901390149015901690179018901990209021902290239024902590269027902890299030903190329033903490359036903790389039904090419042904390449045904690479048904990509051905290539054905590569057905890599060906190629063906490659066906790689069907090719072907390749075907690779078907990809081908290839084908590869087908890899090909190929093909490959096909790989099910091019102910391049105910691079108910991109111911291139114911591169117911891199120912191229123912491259126912791289129913091319132913391349135913691379138913991409141914291439144914591469147914891499150915191529153915491559156915791589159916091619162916391649165916691679168916991709171917291739174917591769177917891799180918191829183918491859186918791889189919091919192919391949195919691979198919992009201920292039204920592069207920892099210921192129213921492159216921792189219922092219222922392249225922692279228922992309231923292339234923592369237923892399240924192429243924492459246924792489249925092519252925392549255925692579258925992609261926292639264926592669267926892699270927192729273927492759276927792789279928092819282928392849285928692879288928992909291929292939294929592969297929892999300930193029303930493059306930793089309931093119312931393149315931693179318931993209321932293239324932593269327932893299330933193329333933493359336933793389339934093419342934393449345934693479348934993509351935293539354935593569357935893599360936193629363936493659366936793689369937093719372937393749375937693779378937993809381938293839384938593869387938893899390939193929393939493959396939793989399940094019402940394049405940694079408940994109411941294139414941594169417941894199420942194229423942494259426942794289429943094319432943394349435943694379438943994409441944294439444944594469447944894499450945194529453945494559456945794589459946094619462946394649465946694679468946994709471947294739474947594769477947894799480948194829483948494859486948794889489949094919492949394949495949694979498949995009501950295039504950595069507950895099510951195129513951495159516951795189519952095219522952395249525952695279528952995309531953295339534953595369537953895399540954195429543954495459546954795489549955095519552955395549555955695579558955995609561956295639564956595669567956895699570957195729573957495759576957795789579958095819582958395849585958695879588958995909591959295939594959595969597959895999600960196029603960496059606960796089609961096119612961396149615961696179618961996209621962296239624962596269627962896299630963196329633963496359636963796389639964096419642964396449645964696479648964996509651965296539654965596569657965896599660966196629663966496659666966796689669967096719672967396749675967696779678967996809681968296839684968596869687968896899690969196929693969496959696969796989699970097019702970397049705970697079708970997109711971297139714971597169717971897199720972197229723972497259726972797289729973097319732973397349735973697379738973997409741974297439744974597469747974897499750975197529753975497559756975797589759976097619762976397649765976697679768976997709771977297739774977597769777977897799780978197829783978497859786978797889789979097919792979397949795979697979798979998009801980298039804980598069807980898099810981198129813981498159816981798189819982098219822982398249825982698279828982998309831983298339834983598369837983898399840984198429843984498459846984798489849985098519852985398549855985698579858985998609861986298639864986598669867986898699870987198729873987498759876987798789879988098819882988398849885988698879888988998909891989298939894989598969897989898999900990199029903990499059906990799089909991099119912991399149915991699179918991999209921992299239924992599269927992899299930993199329933993499359936993799389939994099419942994399449945994699479948994999509951995299539954995599569957995899599960996199629963996499659966996799689969997099719972997399749975997699779978997999809981998299839984998599869987998899899990999199929993999499959996999799989999100001000110002100031000410005100061000710008100091001010011100121001310014100151001610017100181001910020100211002210023100241002510026100271002810029100301003110032100331003410035100361003710038100391004010041100421004310044100451004610047100481004910050100511005210053100541005510056100571005810059100601006110062100631006410065100661006710068100691007010071100721007310074100751007610077100781007910080100811008210083100841008510086100871008810089100901009110092100931009410095100961009710098100991010010101101021010310104101051010610107101081010910110101111011210113101141011510116101171011810119101201012110122101231012410125101261012710128101291013010131101321013310134101351013610137101381013910140101411014210143101441014510146101471014810149101501015110152101531015410155101561015710158101591016010161101621016310164101651016610167101681016910170101711017210173101741017510176101771017810179101801018110182101831018410185101861018710188101891019010191101921019310194101951019610197101981019910200102011020210203102041020510206102071020810209102101021110212102131021410215102161021710218102191022010221102221022310224102251022610227102281022910230102311023210233102341023510236102371023810239102401024110242102431024410245102461024710248102491025010251102521025310254102551025610257102581025910260102611026210263102641026510266102671026810269102701027110272102731027410275102761027710278102791028010281102821028310284102851028610287102881028910290102911029210293102941029510296102971029810299103001030110302103031030410305103061030710308103091031010311103121031310314103151031610317103181031910320103211032210323103241032510326103271032810329103301033110332103331033410335103361033710338103391034010341103421034310344103451034610347103481034910350103511035210353103541035510356103571035810359103601036110362103631036410365103661036710368103691037010371103721037310374103751037610377103781037910380103811038210383103841038510386103871038810389103901039110392103931039410395103961039710398103991040010401104021040310404104051040610407104081040910410104111041210413104141041510416104171041810419104201042110422104231042410425104261042710428104291043010431104321043310434104351043610437104381043910440104411044210443104441044510446104471044810449104501045110452104531045410455104561045710458104591046010461104621046310464104651046610467104681046910470104711047210473104741047510476104771047810479104801048110482104831048410485104861048710488104891049010491104921049310494104951049610497104981049910500105011050210503105041050510506105071050810509105101051110512105131051410515105161051710518105191052010521105221052310524105251052610527105281052910530105311053210533105341053510536105371053810539105401054110542105431054410545105461054710548105491055010551105521055310554105551055610557105581055910560105611056210563105641056510566105671056810569105701057110572105731057410575105761057710578105791058010581105821058310584105851058610587105881058910590105911059210593105941059510596105971059810599106001060110602106031060410605106061060710608106091061010611106121061310614106151061610617106181061910620106211062210623106241062510626106271062810629106301063110632106331063410635106361063710638106391064010641106421064310644106451064610647106481064910650106511065210653106541065510656106571065810659106601066110662106631066410665106661066710668106691067010671106721067310674106751067610677106781067910680106811068210683106841068510686106871068810689106901069110692106931069410695106961069710698106991070010701107021070310704107051070610707107081070910710107111071210713107141071510716107171071810719107201072110722107231072410725107261072710728107291073010731107321073310734107351073610737107381073910740107411074210743107441074510746107471074810749107501075110752107531075410755107561075710758107591076010761107621076310764107651076610767107681076910770107711077210773107741077510776107771077810779107801078110782107831078410785107861078710788107891079010791107921079310794107951079610797107981079910800108011080210803108041080510806108071080810809108101081110812108131081410815108161081710818108191082010821108221082310824108251082610827108281082910830108311083210833108341083510836108371083810839108401084110842108431084410845108461084710848108491085010851108521085310854108551085610857108581085910860108611086210863108641086510866108671086810869108701087110872108731087410875108761087710878108791088010881108821088310884108851088610887108881088910890108911089210893108941089510896108971089810899109001090110902109031090410905109061090710908109091091010911109121091310914109151091610917109181091910920109211092210923109241092510926109271092810929109301093110932109331093410935109361093710938109391094010941109421094310944109451094610947109481094910950109511095210953109541095510956109571095810959109601096110962109631096410965109661096710968109691097010971109721097310974109751097610977109781097910980109811098210983109841098510986109871098810989109901099110992109931099410995109961099710998109991100011001110021100311004110051100611007110081100911010110111101211013110141101511016110171101811019110201102111022110231102411025110261102711028110291103011031110321103311034110351103611037110381103911040110411104211043110441104511046110471104811049110501105111052110531105411055110561105711058110591106011061110621106311064110651106611067110681106911070110711107211073110741107511076110771107811079110801108111082110831108411085110861108711088110891109011091110921109311094110951109611097110981109911100111011110211103111041110511106111071110811109111101111111112111131111411115111161111711118111191112011121111221112311124111251112611127111281112911130111311113211133111341113511136111371113811139111401114111142111431114411145111461114711148111491115011151111521115311154111551115611157111581115911160111611116211163111641116511166111671116811169111701117111172111731117411175111761117711178111791118011181111821118311184111851118611187111881118911190111911119211193111941119511196111971119811199112001120111202112031120411205112061120711208112091121011211112121121311214112151121611217112181121911220112211122211223112241122511226112271122811229112301123111232112331123411235112361123711238112391124011241112421124311244112451124611247112481124911250112511125211253112541125511256112571125811259112601126111262112631126411265112661126711268112691127011271112721127311274112751127611277112781127911280112811128211283112841128511286112871128811289112901129111292112931129411295112961129711298112991130011301113021130311304113051130611307113081130911310113111131211313113141131511316113171131811319113201132111322113231132411325113261132711328113291133011331113321133311334113351133611337113381133911340113411134211343113441134511346113471134811349113501135111352113531135411355113561135711358113591136011361113621136311364113651136611367113681136911370113711137211373113741137511376113771137811379113801138111382113831138411385113861138711388113891139011391113921139311394113951139611397113981139911400114011140211403114041140511406114071140811409114101141111412114131141411415114161141711418114191142011421114221142311424114251142611427114281142911430114311143211433114341143511436114371143811439114401144111442114431144411445114461144711448114491145011451114521145311454114551145611457114581145911460114611146211463114641146511466114671146811469114701147111472114731147411475114761147711478114791148011481114821148311484114851148611487114881148911490114911149211493114941149511496114971149811499115001150111502115031150411505115061150711508115091151011511115121151311514115151151611517115181151911520115211152211523115241152511526115271152811529115301153111532115331153411535115361153711538115391154011541115421154311544115451154611547115481154911550115511155211553115541155511556115571155811559115601156111562115631156411565115661156711568115691157011571115721157311574115751157611577115781157911580115811158211583115841158511586115871158811589115901159111592115931159411595115961159711598115991160011601116021160311604116051160611607116081160911610116111161211613116141161511616116171161811619116201162111622116231162411625116261162711628116291163011631116321163311634116351163611637116381163911640116411164211643116441164511646116471164811649116501165111652116531165411655116561165711658116591166011661116621166311664116651166611667116681166911670116711167211673116741167511676116771167811679116801168111682116831168411685116861168711688116891169011691116921169311694116951169611697116981169911700117011170211703117041170511706117071170811709117101171111712117131171411715117161171711718117191172011721117221172311724117251172611727117281172911730117311173211733117341173511736117371173811739117401174111742117431174411745117461174711748117491175011751117521175311754117551175611757117581175911760117611176211763117641176511766117671176811769117701177111772117731177411775117761177711778117791178011781117821178311784117851178611787117881178911790117911179211793117941179511796117971179811799118001180111802118031180411805118061180711808118091181011811118121181311814118151181611817118181181911820118211182211823118241182511826118271182811829118301183111832118331183411835118361183711838118391184011841118421184311844118451184611847118481184911850118511185211853118541185511856118571185811859118601186111862118631186411865118661186711868118691187011871118721187311874118751187611877118781187911880118811188211883118841188511886118871188811889118901189111892118931189411895118961189711898118991190011901119021190311904119051190611907119081190911910119111191211913119141191511916119171191811919119201192111922119231192411925119261192711928119291193011931119321193311934119351193611937119381193911940119411194211943119441194511946119471194811949119501195111952119531195411955119561195711958119591196011961119621196311964119651196611967119681196911970119711197211973119741197511976119771197811979119801198111982119831198411985119861198711988119891199011991119921199311994119951199611997119981199912000120011200212003120041200512006120071200812009120101201112012120131201412015120161201712018120191202012021120221202312024120251202612027120281202912030120311203212033120341203512036120371203812039120401204112042120431204412045120461204712048120491205012051120521205312054120551205612057120581205912060120611206212063120641206512066120671206812069120701207112072120731207412075120761207712078120791208012081120821208312084120851208612087120881208912090120911209212093120941209512096120971209812099121001210112102121031210412105121061210712108121091211012111121121211312114121151211612117121181211912120121211212212123121241212512126121271212812129121301213112132121331213412135121361213712138121391214012141121421214312144121451214612147121481214912150121511215212153121541215512156121571215812159121601216112162121631216412165121661216712168121691217012171121721217312174121751217612177121781217912180121811218212183121841218512186121871218812189121901219112192121931219412195121961219712198121991220012201122021220312204122051220612207122081220912210122111221212213122141221512216122171221812219122201222112222122231222412225122261222712228122291223012231122321223312234122351223612237122381223912240122411224212243122441224512246122471224812249122501225112252122531225412255122561225712258122591226012261122621226312264122651226612267122681226912270122711227212273122741227512276122771227812279122801228112282122831228412285122861228712288122891229012291122921229312294122951229612297122981229912300123011230212303123041230512306123071230812309123101231112312123131231412315123161231712318123191232012321123221232312324123251232612327123281232912330123311233212333123341233512336123371233812339123401234112342123431234412345123461234712348123491235012351123521235312354123551235612357123581235912360123611236212363123641236512366123671236812369123701237112372123731237412375123761237712378123791238012381123821238312384123851238612387123881238912390123911239212393123941239512396123971239812399124001240112402124031240412405124061240712408124091241012411124121241312414124151241612417124181241912420124211242212423124241242512426124271242812429124301243112432124331243412435124361243712438124391244012441124421244312444124451244612447124481244912450124511245212453124541245512456124571245812459124601246112462124631246412465124661246712468124691247012471124721247312474124751247612477124781247912480124811248212483124841248512486124871248812489124901249112492124931249412495124961249712498124991250012501125021250312504125051250612507125081250912510125111251212513125141251512516125171251812519125201252112522125231252412525125261252712528125291253012531125321253312534125351253612537125381253912540125411254212543125441254512546125471254812549125501255112552125531255412555125561255712558125591256012561125621256312564125651256612567125681256912570125711257212573125741257512576125771257812579125801258112582125831258412585125861258712588125891259012591125921259312594125951259612597125981259912600126011260212603126041260512606126071260812609126101261112612126131261412615126161261712618126191262012621126221262312624126251262612627126281262912630126311263212633126341263512636126371263812639126401264112642126431264412645126461264712648126491265012651126521265312654126551265612657126581265912660126611266212663126641266512666126671266812669126701267112672126731267412675126761267712678126791268012681126821268312684126851268612687126881268912690126911269212693126941269512696126971269812699127001270112702127031270412705127061270712708127091271012711127121271312714127151271612717127181271912720127211272212723127241272512726127271272812729127301273112732127331273412735127361273712738127391274012741127421274312744127451274612747127481274912750127511275212753127541275512756127571275812759127601276112762127631276412765127661276712768127691277012771127721277312774127751277612777127781277912780127811278212783127841278512786127871278812789127901279112792127931279412795127961279712798127991280012801128021280312804128051280612807128081280912810128111281212813128141281512816128171281812819128201282112822128231282412825128261282712828128291283012831128321283312834128351283612837128381283912840128411284212843128441284512846128471284812849128501285112852128531285412855128561285712858128591286012861128621286312864128651286612867128681286912870128711287212873128741287512876128771287812879128801288112882128831288412885128861288712888128891289012891128921289312894128951289612897128981289912900129011290212903129041290512906129071290812909129101291112912129131291412915129161291712918129191292012921129221292312924129251292612927129281292912930129311293212933129341293512936129371293812939129401294112942129431294412945129461294712948129491295012951129521295312954129551295612957129581295912960129611296212963129641296512966129671296812969129701297112972129731297412975129761297712978129791298012981129821298312984129851298612987129881298912990129911299212993129941299512996129971299812999130001300113002130031300413005130061300713008130091301013011130121301313014130151301613017130181301913020130211302213023130241302513026130271302813029130301303113032130331303413035130361303713038130391304013041130421304313044130451304613047130481304913050130511305213053130541305513056130571305813059130601306113062130631306413065130661306713068130691307013071130721307313074130751307613077130781307913080130811308213083130841308513086130871308813089130901309113092130931309413095130961309713098130991310013101131021310313104131051310613107131081310913110131111311213113131141311513116131171311813119131201312113122131231312413125131261312713128131291313013131131321313313134131351313613137131381313913140131411314213143131441314513146131471314813149131501315113152131531315413155131561315713158131591316013161131621316313164131651316613167131681316913170131711317213173131741317513176131771317813179131801318113182131831318413185131861318713188131891319013191131921319313194131951319613197131981319913200132011320213203132041320513206132071320813209132101321113212132131321413215132161321713218132191322013221132221322313224132251322613227132281322913230132311323213233132341323513236132371323813239132401324113242132431324413245132461324713248132491325013251132521325313254132551325613257132581325913260132611326213263132641326513266132671326813269132701327113272132731327413275132761327713278132791328013281132821328313284132851328613287132881328913290132911329213293132941329513296132971329813299133001330113302133031330413305133061330713308133091331013311133121331313314133151331613317133181331913320133211332213323133241332513326133271332813329133301333113332133331333413335133361333713338133391334013341133421334313344133451334613347133481334913350133511335213353133541335513356133571335813359133601336113362133631336413365133661336713368133691337013371133721337313374133751337613377133781337913380133811338213383133841338513386133871338813389133901339113392133931339413395133961339713398133991340013401134021340313404134051340613407134081340913410134111341213413134141341513416134171341813419134201342113422134231342413425134261342713428134291343013431134321343313434134351343613437134381343913440134411344213443134441344513446134471344813449134501345113452134531345413455134561345713458134591346013461134621346313464134651346613467134681346913470134711347213473134741347513476134771347813479134801348113482134831348413485134861348713488134891349013491134921349313494134951349613497134981349913500135011350213503135041350513506135071350813509135101351113512135131351413515135161351713518135191352013521135221352313524135251352613527135281352913530135311353213533135341353513536135371353813539135401354113542135431354413545135461354713548135491355013551135521355313554135551355613557135581355913560135611356213563135641356513566135671356813569135701357113572135731357413575135761357713578135791358013581135821358313584135851358613587135881358913590135911359213593135941359513596135971359813599136001360113602136031360413605136061360713608136091361013611136121361313614136151361613617136181361913620136211362213623136241362513626136271362813629136301363113632136331363413635136361363713638136391364013641136421364313644136451364613647136481364913650136511365213653136541365513656136571365813659136601366113662136631366413665136661366713668136691367013671136721367313674136751367613677136781367913680136811368213683136841368513686136871368813689136901369113692136931369413695136961369713698136991370013701137021370313704137051370613707137081370913710137111371213713137141371513716137171371813719137201372113722137231372413725137261372713728137291373013731137321373313734137351373613737137381373913740137411374213743137441374513746137471374813749137501375113752137531375413755137561375713758137591376013761137621376313764137651376613767137681376913770137711377213773137741377513776137771377813779137801378113782137831378413785137861378713788137891379013791137921379313794137951379613797137981379913800138011380213803138041380513806138071380813809138101381113812138131381413815138161381713818138191382013821138221382313824138251382613827138281382913830138311383213833138341383513836138371383813839138401384113842138431384413845138461384713848138491385013851138521385313854138551385613857138581385913860138611386213863138641386513866138671386813869138701387113872138731387413875138761387713878138791388013881138821388313884138851388613887138881388913890138911389213893138941389513896138971389813899139001390113902139031390413905139061390713908139091391013911139121391313914139151391613917139181391913920139211392213923139241392513926139271392813929139301393113932139331393413935139361393713938139391394013941139421394313944139451394613947139481394913950139511395213953139541395513956139571395813959139601396113962139631396413965139661396713968139691397013971139721397313974139751397613977139781397913980139811398213983139841398513986139871398813989139901399113992139931399413995139961399713998139991400014001140021400314004140051400614007140081400914010140111401214013140141401514016140171401814019140201402114022140231402414025140261402714028140291403014031140321403314034140351403614037140381403914040140411404214043140441404514046140471404814049140501405114052140531405414055140561405714058140591406014061140621406314064140651406614067140681406914070140711407214073140741407514076140771407814079140801408114082140831408414085140861408714088140891409014091140921409314094140951409614097140981409914100141011410214103141041410514106141071410814109141101411114112141131411414115141161411714118141191412014121141221412314124141251412614127141281412914130141311413214133141341413514136141371413814139141401414114142141431414414145141461414714148141491415014151141521415314154141551415614157141581415914160141611416214163141641416514166141671416814169141701417114172141731417414175141761417714178141791418014181141821418314184141851418614187141881418914190141911419214193141941419514196141971419814199142001420114202142031420414205142061420714208142091421014211142121421314214142151421614217142181421914220142211422214223142241422514226142271422814229142301423114232142331423414235142361423714238142391424014241142421424314244142451424614247142481424914250142511425214253142541425514256142571425814259142601426114262142631426414265142661426714268142691427014271142721427314274142751427614277142781427914280142811428214283142841428514286142871428814289142901429114292142931429414295142961429714298142991430014301143021430314304143051430614307143081430914310143111431214313143141431514316143171431814319143201432114322143231432414325143261432714328143291433014331143321433314334143351433614337143381433914340143411434214343143441434514346143471434814349143501435114352143531435414355143561435714358143591436014361143621436314364143651436614367143681436914370143711437214373143741437514376143771437814379143801438114382143831438414385143861438714388143891439014391143921439314394143951439614397143981439914400144011440214403144041440514406144071440814409144101441114412144131441414415144161441714418144191442014421144221442314424144251442614427144281442914430144311443214433144341443514436144371443814439144401444114442144431444414445144461444714448144491445014451144521445314454144551445614457144581445914460144611446214463144641446514466144671446814469144701447114472144731447414475144761447714478144791448014481144821448314484144851448614487144881448914490144911449214493144941449514496144971449814499145001450114502145031450414505145061450714508145091451014511145121451314514145151451614517145181451914520145211452214523145241452514526145271452814529145301453114532145331453414535145361453714538145391454014541145421454314544145451454614547145481454914550145511455214553145541455514556145571455814559145601456114562145631456414565145661456714568145691457014571145721457314574145751457614577145781457914580145811458214583145841458514586145871458814589145901459114592145931459414595145961459714598145991460014601146021460314604146051460614607146081460914610146111461214613146141461514616146171461814619146201462114622146231462414625146261462714628146291463014631146321463314634146351463614637146381463914640146411464214643146441464514646146471464814649146501465114652146531465414655146561465714658146591466014661146621466314664146651466614667146681466914670146711467214673146741467514676146771467814679146801468114682146831468414685146861468714688146891469014691146921469314694146951469614697146981469914700147011470214703147041470514706147071470814709147101471114712147131471414715147161471714718147191472014721147221472314724147251472614727147281472914730147311473214733147341473514736147371473814739147401474114742147431474414745147461474714748147491475014751147521475314754147551475614757147581475914760147611476214763147641476514766147671476814769147701477114772147731477414775147761477714778147791478014781147821478314784147851478614787147881478914790147911479214793147941479514796147971479814799148001480114802148031480414805148061480714808148091481014811148121481314814148151481614817148181481914820148211482214823148241482514826148271482814829148301483114832148331483414835148361483714838148391484014841148421484314844148451484614847148481484914850148511485214853148541485514856148571485814859148601486114862148631486414865148661486714868148691487014871148721487314874148751487614877148781487914880148811488214883148841488514886148871488814889148901489114892148931489414895148961489714898148991490014901149021490314904149051490614907149081490914910149111491214913149141491514916149171491814919149201492114922149231492414925149261492714928149291493014931149321493314934149351493614937149381493914940149411494214943149441494514946149471494814949149501495114952149531495414955149561495714958149591496014961149621496314964149651496614967149681496914970149711497214973149741497514976149771497814979149801498114982149831498414985149861498714988149891499014991149921499314994149951499614997149981499915000150011500215003150041500515006150071500815009150101501115012150131501415015150161501715018150191502015021150221502315024150251502615027150281502915030150311503215033150341503515036150371503815039150401504115042150431504415045150461504715048150491505015051150521505315054150551505615057150581505915060150611506215063150641506515066150671506815069150701507115072150731507415075150761507715078150791508015081150821508315084150851508615087150881508915090150911509215093150941509515096150971509815099151001510115102151031510415105151061510715108151091511015111151121511315114151151511615117151181511915120151211512215123151241512515126151271512815129151301513115132151331513415135151361513715138151391514015141151421514315144151451514615147151481514915150151511515215153151541515515156151571515815159151601516115162151631516415165151661516715168151691517015171151721517315174151751517615177151781517915180151811518215183151841518515186151871518815189151901519115192151931519415195151961519715198151991520015201152021520315204152051520615207152081520915210152111521215213152141521515216152171521815219152201522115222152231522415225152261522715228152291523015231152321523315234152351523615237152381523915240152411524215243152441524515246152471524815249152501525115252152531525415255152561525715258152591526015261152621526315264152651526615267152681526915270152711527215273152741527515276152771527815279152801528115282152831528415285152861528715288152891529015291152921529315294152951529615297152981529915300153011530215303153041530515306153071530815309153101531115312153131531415315153161531715318153191532015321153221532315324153251532615327153281532915330153311533215333153341533515336153371533815339153401534115342153431534415345153461534715348153491535015351153521535315354153551535615357153581535915360153611536215363153641536515366153671536815369153701537115372153731537415375153761537715378153791538015381153821538315384153851538615387153881538915390153911539215393153941539515396153971539815399154001540115402154031540415405154061540715408154091541015411154121541315414154151541615417154181541915420154211542215423154241542515426154271542815429154301543115432154331543415435154361543715438154391544015441154421544315444154451544615447154481544915450154511545215453154541545515456154571545815459154601546115462154631546415465154661546715468154691547015471154721547315474154751547615477154781547915480154811548215483154841548515486154871548815489154901549115492154931549415495154961549715498154991550015501155021550315504155051550615507155081550915510155111551215513155141551515516155171551815519155201552115522155231552415525155261552715528155291553015531155321553315534155351553615537155381553915540155411554215543155441554515546155471554815549155501555115552155531555415555155561555715558155591556015561155621556315564155651556615567155681556915570155711557215573155741557515576155771557815579155801558115582155831558415585155861558715588155891559015591155921559315594155951559615597155981559915600156011560215603156041560515606156071560815609156101561115612156131561415615156161561715618156191562015621156221562315624156251562615627156281562915630156311563215633156341563515636156371563815639156401564115642156431564415645156461564715648156491565015651156521565315654156551565615657156581565915660156611566215663156641566515666156671566815669156701567115672156731567415675156761567715678156791568015681156821568315684156851568615687156881568915690156911569215693156941569515696156971569815699157001570115702157031570415705157061570715708157091571015711157121571315714157151571615717157181571915720157211572215723157241572515726157271572815729157301573115732157331573415735157361573715738157391574015741157421574315744157451574615747157481574915750157511575215753157541575515756157571575815759157601576115762157631576415765157661576715768157691577015771157721577315774157751577615777157781577915780157811578215783157841578515786157871578815789157901579115792157931579415795157961579715798157991580015801158021580315804158051580615807158081580915810158111581215813158141581515816158171581815819158201582115822158231582415825158261582715828158291583015831158321583315834158351583615837158381583915840158411584215843158441584515846158471584815849158501585115852158531585415855158561585715858158591586015861158621586315864158651586615867158681586915870158711587215873158741587515876158771587815879158801588115882158831588415885158861588715888158891589015891158921589315894158951589615897158981589915900159011590215903159041590515906159071590815909159101591115912159131591415915159161591715918159191592015921159221592315924159251592615927159281592915930159311593215933159341593515936159371593815939159401594115942159431594415945159461594715948159491595015951159521595315954159551595615957159581595915960159611596215963159641596515966159671596815969159701597115972159731597415975159761597715978159791598015981159821598315984159851598615987159881598915990159911599215993159941599515996159971599815999160001600116002160031600416005160061600716008160091601016011160121601316014160151601616017160181601916020160211602216023160241602516026160271602816029160301603116032160331603416035160361603716038160391604016041160421604316044160451604616047160481604916050160511605216053160541605516056160571605816059160601606116062160631606416065160661606716068160691607016071160721607316074160751607616077160781607916080160811608216083160841608516086160871608816089160901609116092160931609416095160961609716098160991610016101161021610316104161051610616107161081610916110161111611216113161141611516116161171611816119161201612116122161231612416125161261612716128161291613016131161321613316134161351613616137161381613916140161411614216143161441614516146161471614816149161501615116152161531615416155161561615716158161591616016161161621616316164161651616616167161681616916170161711617216173161741617516176161771617816179161801618116182161831618416185161861618716188161891619016191161921619316194161951619616197161981619916200162011620216203162041620516206162071620816209162101621116212162131621416215162161621716218162191622016221162221622316224162251622616227162281622916230162311623216233162341623516236162371623816239162401624116242162431624416245162461624716248162491625016251162521625316254162551625616257162581625916260162611626216263162641626516266162671626816269162701627116272162731627416275162761627716278162791628016281162821628316284162851628616287162881628916290162911629216293162941629516296162971629816299163001630116302163031630416305163061630716308163091631016311163121631316314163151631616317163181631916320163211632216323163241632516326163271632816329163301633116332163331633416335163361633716338163391634016341163421634316344163451634616347163481634916350163511635216353163541635516356163571635816359163601636116362163631636416365163661636716368163691637016371163721637316374163751637616377163781637916380163811638216383163841638516386163871638816389163901639116392163931639416395163961639716398163991640016401164021640316404164051640616407164081640916410164111641216413164141641516416164171641816419164201642116422164231642416425164261642716428164291643016431164321643316434164351643616437164381643916440164411644216443164441644516446164471644816449164501645116452164531645416455164561645716458164591646016461164621646316464164651646616467164681646916470164711647216473164741647516476164771647816479164801648116482164831648416485164861648716488164891649016491164921649316494164951649616497164981649916500165011650216503165041650516506165071650816509165101651116512165131651416515165161651716518165191652016521165221652316524165251652616527165281652916530165311653216533165341653516536165371653816539165401654116542165431654416545165461654716548165491655016551165521655316554165551655616557165581655916560165611656216563165641656516566165671656816569165701657116572165731657416575165761657716578165791658016581165821658316584165851658616587165881658916590165911659216593165941659516596165971659816599166001660116602166031660416605166061660716608166091661016611166121661316614166151661616617166181661916620166211662216623166241662516626166271662816629166301663116632166331663416635166361663716638166391664016641166421664316644166451664616647166481664916650166511665216653166541665516656166571665816659166601666116662166631666416665166661666716668166691667016671166721667316674166751667616677166781667916680166811668216683166841668516686166871668816689166901669116692166931669416695166961669716698166991670016701167021670316704167051670616707167081670916710167111671216713167141671516716167171671816719167201672116722167231672416725167261672716728167291673016731167321673316734167351673616737167381673916740167411674216743167441674516746167471674816749167501675116752167531675416755167561675716758167591676016761167621676316764167651676616767167681676916770167711677216773167741677516776167771677816779167801678116782167831678416785167861678716788167891679016791167921679316794167951679616797167981679916800168011680216803168041680516806168071680816809168101681116812168131681416815168161681716818168191682016821168221682316824168251682616827168281682916830168311683216833168341683516836168371683816839168401684116842168431684416845168461684716848168491685016851168521685316854168551685616857168581685916860168611686216863168641686516866168671686816869168701687116872168731687416875168761687716878168791688016881168821688316884168851688616887168881688916890168911689216893168941689516896168971689816899169001690116902169031690416905169061690716908169091691016911169121691316914169151691616917169181691916920169211692216923169241692516926169271692816929169301693116932169331693416935169361693716938169391694016941169421694316944169451694616947169481694916950169511695216953169541695516956169571695816959169601696116962169631696416965169661696716968169691697016971169721697316974169751697616977169781697916980169811698216983169841698516986169871698816989169901699116992169931699416995169961699716998169991700017001170021700317004170051700617007170081700917010170111701217013170141701517016170171701817019170201702117022170231702417025170261702717028170291703017031170321703317034170351703617037170381703917040170411704217043170441704517046170471704817049170501705117052170531705417055170561705717058170591706017061170621706317064170651706617067170681706917070170711707217073170741707517076170771707817079170801708117082170831708417085170861708717088170891709017091170921709317094170951709617097170981709917100171011710217103171041710517106171071710817109171101711117112171131711417115171161711717118171191712017121171221712317124171251712617127171281712917130171311713217133171341713517136171371713817139171401714117142171431714417145171461714717148171491715017151171521715317154171551715617157171581715917160171611716217163171641716517166171671716817169171701717117172171731717417175171761717717178171791718017181171821718317184171851718617187171881718917190171911719217193171941719517196171971719817199172001720117202172031720417205172061720717208172091721017211172121721317214172151721617217172181721917220172211722217223172241722517226172271722817229172301723117232172331723417235172361723717238172391724017241172421724317244172451724617247172481724917250172511725217253172541725517256172571725817259172601726117262172631726417265172661726717268172691727017271172721727317274172751727617277172781727917280172811728217283172841728517286172871728817289172901729117292172931729417295172961729717298172991730017301173021730317304173051730617307173081730917310173111731217313173141731517316173171731817319173201732117322173231732417325173261732717328173291733017331173321733317334173351733617337173381733917340173411734217343173441734517346173471734817349173501735117352173531735417355173561735717358173591736017361173621736317364173651736617367173681736917370173711737217373173741737517376173771737817379173801738117382173831738417385173861738717388173891739017391173921739317394173951739617397173981739917400174011740217403174041740517406174071740817409174101741117412174131741417415174161741717418174191742017421174221742317424174251742617427174281742917430174311743217433174341743517436174371743817439174401744117442174431744417445174461744717448174491745017451174521745317454174551745617457174581745917460174611746217463174641746517466174671746817469174701747117472174731747417475174761747717478174791748017481174821748317484174851748617487174881748917490174911749217493174941749517496174971749817499175001750117502175031750417505175061750717508175091751017511175121751317514175151751617517175181751917520175211752217523175241752517526175271752817529175301753117532175331753417535175361753717538175391754017541175421754317544175451754617547175481754917550175511755217553175541755517556175571755817559175601756117562175631756417565175661756717568175691757017571175721757317574175751757617577175781757917580175811758217583175841758517586175871758817589175901759117592175931759417595175961759717598175991760017601176021760317604176051760617607176081760917610176111761217613176141761517616176171761817619176201762117622176231762417625176261762717628176291763017631176321763317634176351763617637176381763917640176411764217643176441764517646176471764817649176501765117652176531765417655176561765717658176591766017661176621766317664176651766617667176681766917670176711767217673176741767517676176771767817679176801768117682176831768417685176861768717688176891769017691176921769317694176951769617697176981769917700177011770217703177041770517706177071770817709177101771117712177131771417715177161771717718177191772017721177221772317724177251772617727177281772917730177311773217733177341773517736177371773817739177401774117742177431774417745177461774717748177491775017751177521775317754177551775617757177581775917760177611776217763177641776517766177671776817769177701777117772177731777417775177761777717778177791778017781177821778317784177851778617787177881778917790177911779217793177941779517796177971779817799178001780117802178031780417805178061780717808178091781017811178121781317814178151781617817178181781917820178211782217823178241782517826178271782817829178301783117832178331783417835178361783717838178391784017841178421784317844178451784617847178481784917850178511785217853178541785517856178571785817859178601786117862178631786417865178661786717868178691787017871178721787317874178751787617877178781787917880178811788217883178841788517886178871788817889178901789117892178931789417895178961789717898178991790017901179021790317904179051790617907179081790917910179111791217913179141791517916179171791817919179201792117922179231792417925179261792717928179291793017931179321793317934179351793617937179381793917940179411794217943179441794517946179471794817949179501795117952179531795417955179561795717958179591796017961179621796317964179651796617967179681796917970179711797217973179741797517976179771797817979179801798117982179831798417985179861798717988179891799017991179921799317994179951799617997179981799918000180011800218003180041800518006180071800818009180101801118012180131801418015180161801718018180191802018021180221802318024180251802618027180281802918030180311803218033180341803518036180371803818039180401804118042180431804418045180461804718048180491805018051180521805318054180551805618057180581805918060180611806218063180641806518066180671806818069180701807118072180731807418075180761807718078180791808018081180821808318084180851808618087180881808918090180911809218093180941809518096180971809818099181001810118102181031810418105181061810718108181091811018111181121811318114181151811618117181181811918120181211812218123181241812518126181271812818129181301813118132181331813418135181361813718138181391814018141181421814318144181451814618147181481814918150181511815218153181541815518156181571815818159181601816118162181631816418165181661816718168181691817018171181721817318174181751817618177181781817918180181811818218183181841818518186181871818818189181901819118192181931819418195181961819718198181991820018201182021820318204182051820618207182081820918210182111821218213182141821518216182171821818219182201822118222182231822418225182261822718228182291823018231182321823318234182351823618237182381823918240182411824218243182441824518246182471824818249182501825118252182531825418255182561825718258182591826018261182621826318264182651826618267182681826918270182711827218273182741827518276182771827818279182801828118282182831828418285182861828718288182891829018291182921829318294182951829618297182981829918300183011830218303183041830518306183071830818309183101831118312183131831418315183161831718318183191832018321183221832318324183251832618327183281832918330183311833218333183341833518336183371833818339183401834118342183431834418345183461834718348183491835018351183521835318354183551835618357183581835918360183611836218363183641836518366183671836818369183701837118372183731837418375183761837718378183791838018381183821838318384183851838618387183881838918390183911839218393183941839518396183971839818399184001840118402184031840418405184061840718408184091841018411184121841318414184151841618417184181841918420184211842218423184241842518426184271842818429184301843118432184331843418435184361843718438184391844018441184421844318444184451844618447184481844918450184511845218453184541845518456184571845818459184601846118462184631846418465184661846718468184691847018471184721847318474184751847618477184781847918480184811848218483184841848518486184871848818489184901849118492184931849418495184961849718498184991850018501185021850318504185051850618507185081850918510185111851218513185141851518516185171851818519185201852118522185231852418525185261852718528185291853018531185321853318534185351853618537185381853918540185411854218543185441854518546185471854818549185501855118552185531855418555185561855718558185591856018561185621856318564185651856618567185681856918570185711857218573185741857518576185771857818579185801858118582185831858418585185861858718588185891859018591185921859318594185951859618597185981859918600186011860218603186041860518606186071860818609186101861118612186131861418615186161861718618186191862018621186221862318624186251862618627186281862918630186311863218633186341863518636186371863818639186401864118642186431864418645186461864718648186491865018651186521865318654186551865618657186581865918660186611866218663186641866518666186671866818669186701867118672186731867418675186761867718678186791868018681186821868318684186851868618687186881868918690186911869218693186941869518696186971869818699187001870118702187031870418705187061870718708187091871018711187121871318714187151871618717187181871918720187211872218723187241872518726187271872818729187301873118732187331873418735187361873718738187391874018741187421874318744187451874618747187481874918750187511875218753187541875518756187571875818759187601876118762187631876418765187661876718768187691877018771187721877318774187751877618777187781877918780187811878218783187841878518786187871878818789187901879118792187931879418795187961879718798187991880018801188021880318804188051880618807188081880918810188111881218813188141881518816188171881818819188201882118822188231882418825188261882718828188291883018831188321883318834188351883618837188381883918840188411884218843188441884518846188471884818849188501885118852188531885418855188561885718858188591886018861188621886318864188651886618867188681886918870188711887218873188741887518876188771887818879188801888118882188831888418885188861888718888188891889018891188921889318894188951889618897188981889918900189011890218903189041890518906189071890818909189101891118912189131891418915189161891718918189191892018921189221892318924189251892618927189281892918930189311893218933189341893518936189371893818939189401894118942189431894418945189461894718948189491895018951189521895318954189551895618957189581895918960189611896218963189641896518966189671896818969189701897118972189731897418975189761897718978189791898018981189821898318984189851898618987189881898918990189911899218993189941899518996189971899818999190001900119002190031900419005190061900719008190091901019011190121901319014190151901619017190181901919020190211902219023190241902519026190271902819029190301903119032190331903419035190361903719038190391904019041190421904319044190451904619047190481904919050190511905219053190541905519056190571905819059190601906119062190631906419065190661906719068190691907019071190721907319074190751907619077190781907919080190811908219083190841908519086190871908819089190901909119092190931909419095190961909719098190991910019101191021910319104191051910619107191081910919110191111911219113191141911519116191171911819119191201912119122191231912419125191261912719128191291913019131191321913319134191351913619137191381913919140191411914219143191441914519146191471914819149191501915119152191531915419155191561915719158191591916019161191621916319164191651916619167191681916919170191711917219173191741917519176191771917819179191801918119182191831918419185191861918719188191891919019191191921919319194191951919619197191981919919200192011920219203192041920519206192071920819209192101921119212192131921419215192161921719218192191922019221192221922319224192251922619227192281922919230192311923219233192341923519236192371923819239192401924119242192431924419245192461924719248192491925019251192521925319254192551925619257192581925919260192611926219263192641926519266192671926819269192701927119272192731927419275192761927719278192791928019281192821928319284192851928619287192881928919290192911929219293192941929519296192971929819299193001930119302193031930419305193061930719308193091931019311193121931319314193151931619317193181931919320193211932219323193241932519326193271932819329193301933119332193331933419335193361933719338193391934019341193421934319344193451934619347193481934919350193511935219353193541935519356193571935819359193601936119362193631936419365193661936719368193691937019371193721937319374193751937619377193781937919380193811938219383193841938519386193871938819389193901939119392193931939419395193961939719398193991940019401194021940319404194051940619407194081940919410194111941219413194141941519416194171941819419194201942119422194231942419425194261942719428194291943019431194321943319434194351943619437194381943919440194411944219443194441944519446194471944819449194501945119452194531945419455194561945719458194591946019461194621946319464194651946619467194681946919470194711947219473194741947519476194771947819479194801948119482194831948419485194861948719488194891949019491194921949319494194951949619497194981949919500195011950219503195041950519506195071950819509195101951119512195131951419515195161951719518195191952019521195221952319524195251952619527195281952919530195311953219533195341953519536195371953819539195401954119542195431954419545195461954719548195491955019551195521955319554195551955619557195581955919560195611956219563195641956519566195671956819569195701957119572195731957419575195761957719578195791958019581195821958319584195851958619587195881958919590195911959219593195941959519596195971959819599196001960119602196031960419605196061960719608196091961019611196121961319614196151961619617196181961919620196211962219623196241962519626196271962819629196301963119632196331963419635196361963719638196391964019641196421964319644196451964619647196481964919650196511965219653196541965519656196571965819659196601966119662196631966419665196661966719668196691967019671196721967319674196751967619677196781967919680196811968219683196841968519686196871968819689196901969119692196931969419695196961969719698196991970019701197021970319704197051970619707197081970919710197111971219713197141971519716197171971819719197201972119722197231972419725197261972719728197291973019731197321973319734197351973619737197381973919740197411974219743197441974519746197471974819749197501975119752197531975419755
  1. From 7f9b63420584b1d54d6289639a5ffac2e67e3e5c Mon Sep 17 00:00:00 2001
  2. From: Maximilian Luz <luzmaximilian@gmail.com>
  3. Date: Fri, 26 Jul 2019 04:47:02 +0200
  4. Subject: [PATCH 10/12] mwlwifi
  5. ---
  6. drivers/net/wireless/marvell/Kconfig | 1 +
  7. drivers/net/wireless/marvell/Makefile | 1 +
  8. drivers/net/wireless/marvell/mwlwifi/Kconfig | 23 +
  9. drivers/net/wireless/marvell/mwlwifi/Makefile | 19 +
  10. .../wireless/marvell/mwlwifi/Makefile.module | 28 +
  11. .../net/wireless/marvell/mwlwifi/README.md | 142 +
  12. drivers/net/wireless/marvell/mwlwifi/core.c | 1086 +++++
  13. drivers/net/wireless/marvell/mwlwifi/core.h | 517 +++
  14. .../net/wireless/marvell/mwlwifi/debugfs.c | 2201 ++++++++++
  15. .../net/wireless/marvell/mwlwifi/debugfs.h | 24 +
  16. .../net/wireless/marvell/mwlwifi/hif/fwcmd.c | 3852 +++++++++++++++++
  17. .../net/wireless/marvell/mwlwifi/hif/fwcmd.h | 285 ++
  18. .../wireless/marvell/mwlwifi/hif/hif-ops.h | 297 ++
  19. .../net/wireless/marvell/mwlwifi/hif/hif.h | 81 +
  20. .../wireless/marvell/mwlwifi/hif/hostcmd.h | 1285 ++++++
  21. .../wireless/marvell/mwlwifi/hif/pcie/dev.h | 1032 +++++
  22. .../wireless/marvell/mwlwifi/hif/pcie/fwdl.c | 274 ++
  23. .../wireless/marvell/mwlwifi/hif/pcie/fwdl.h | 24 +
  24. .../wireless/marvell/mwlwifi/hif/pcie/pcie.c | 1645 +++++++
  25. .../wireless/marvell/mwlwifi/hif/pcie/rx.c | 540 +++
  26. .../wireless/marvell/mwlwifi/hif/pcie/rx.h | 25 +
  27. .../marvell/mwlwifi/hif/pcie/rx_ndp.c | 612 +++
  28. .../marvell/mwlwifi/hif/pcie/rx_ndp.h | 26 +
  29. .../marvell/mwlwifi/hif/pcie/sc4_ddr.h | 965 +++++
  30. .../wireless/marvell/mwlwifi/hif/pcie/tx.c | 1396 ++++++
  31. .../wireless/marvell/mwlwifi/hif/pcie/tx.h | 38 +
  32. .../marvell/mwlwifi/hif/pcie/tx_ndp.c | 693 +++
  33. .../marvell/mwlwifi/hif/pcie/tx_ndp.h | 30 +
  34. ...-workaround-for-80+80-and-160-MHz-channels | 32 +
  35. .../wireless/marvell/mwlwifi/hostapd/README | 26 +
  36. .../net/wireless/marvell/mwlwifi/mac80211.c | 933 ++++
  37. .../net/wireless/marvell/mwlwifi/mu_mimo.c | 21 +
  38. .../net/wireless/marvell/mwlwifi/mu_mimo.h | 23 +
  39. .../net/wireless/marvell/mwlwifi/sysadpt.h | 86 +
  40. .../net/wireless/marvell/mwlwifi/thermal.c | 182 +
  41. .../net/wireless/marvell/mwlwifi/thermal.h | 42 +
  42. drivers/net/wireless/marvell/mwlwifi/utils.c | 576 +++
  43. drivers/net/wireless/marvell/mwlwifi/utils.h | 158 +
  44. .../net/wireless/marvell/mwlwifi/vendor_cmd.c | 136 +
  45. .../net/wireless/marvell/mwlwifi/vendor_cmd.h | 60 +
  46. 40 files changed, 19417 insertions(+)
  47. create mode 100644 drivers/net/wireless/marvell/mwlwifi/Kconfig
  48. create mode 100644 drivers/net/wireless/marvell/mwlwifi/Makefile
  49. create mode 100644 drivers/net/wireless/marvell/mwlwifi/Makefile.module
  50. create mode 100644 drivers/net/wireless/marvell/mwlwifi/README.md
  51. create mode 100644 drivers/net/wireless/marvell/mwlwifi/core.c
  52. create mode 100644 drivers/net/wireless/marvell/mwlwifi/core.h
  53. create mode 100644 drivers/net/wireless/marvell/mwlwifi/debugfs.c
  54. create mode 100644 drivers/net/wireless/marvell/mwlwifi/debugfs.h
  55. create mode 100644 drivers/net/wireless/marvell/mwlwifi/hif/fwcmd.c
  56. create mode 100644 drivers/net/wireless/marvell/mwlwifi/hif/fwcmd.h
  57. create mode 100644 drivers/net/wireless/marvell/mwlwifi/hif/hif-ops.h
  58. create mode 100644 drivers/net/wireless/marvell/mwlwifi/hif/hif.h
  59. create mode 100644 drivers/net/wireless/marvell/mwlwifi/hif/hostcmd.h
  60. create mode 100644 drivers/net/wireless/marvell/mwlwifi/hif/pcie/dev.h
  61. create mode 100644 drivers/net/wireless/marvell/mwlwifi/hif/pcie/fwdl.c
  62. create mode 100644 drivers/net/wireless/marvell/mwlwifi/hif/pcie/fwdl.h
  63. create mode 100644 drivers/net/wireless/marvell/mwlwifi/hif/pcie/pcie.c
  64. create mode 100644 drivers/net/wireless/marvell/mwlwifi/hif/pcie/rx.c
  65. create mode 100644 drivers/net/wireless/marvell/mwlwifi/hif/pcie/rx.h
  66. create mode 100644 drivers/net/wireless/marvell/mwlwifi/hif/pcie/rx_ndp.c
  67. create mode 100644 drivers/net/wireless/marvell/mwlwifi/hif/pcie/rx_ndp.h
  68. create mode 100644 drivers/net/wireless/marvell/mwlwifi/hif/pcie/sc4_ddr.h
  69. create mode 100644 drivers/net/wireless/marvell/mwlwifi/hif/pcie/tx.c
  70. create mode 100644 drivers/net/wireless/marvell/mwlwifi/hif/pcie/tx.h
  71. create mode 100644 drivers/net/wireless/marvell/mwlwifi/hif/pcie/tx_ndp.c
  72. create mode 100644 drivers/net/wireless/marvell/mwlwifi/hif/pcie/tx_ndp.h
  73. create mode 100644 drivers/net/wireless/marvell/mwlwifi/hostapd/700-interoperability-workaround-for-80+80-and-160-MHz-channels
  74. create mode 100644 drivers/net/wireless/marvell/mwlwifi/hostapd/README
  75. create mode 100644 drivers/net/wireless/marvell/mwlwifi/mac80211.c
  76. create mode 100644 drivers/net/wireless/marvell/mwlwifi/mu_mimo.c
  77. create mode 100644 drivers/net/wireless/marvell/mwlwifi/mu_mimo.h
  78. create mode 100644 drivers/net/wireless/marvell/mwlwifi/sysadpt.h
  79. create mode 100644 drivers/net/wireless/marvell/mwlwifi/thermal.c
  80. create mode 100644 drivers/net/wireless/marvell/mwlwifi/thermal.h
  81. create mode 100644 drivers/net/wireless/marvell/mwlwifi/utils.c
  82. create mode 100644 drivers/net/wireless/marvell/mwlwifi/utils.h
  83. create mode 100644 drivers/net/wireless/marvell/mwlwifi/vendor_cmd.c
  84. create mode 100644 drivers/net/wireless/marvell/mwlwifi/vendor_cmd.h
  85. diff --git a/drivers/net/wireless/marvell/Kconfig b/drivers/net/wireless/marvell/Kconfig
  86. index dff82fdbea78..c0790dbd52c0 100644
  87. --- a/drivers/net/wireless/marvell/Kconfig
  88. +++ b/drivers/net/wireless/marvell/Kconfig
  89. @@ -15,6 +15,7 @@ if WLAN_VENDOR_MARVELL
  90. source "drivers/net/wireless/marvell/libertas/Kconfig"
  91. source "drivers/net/wireless/marvell/libertas_tf/Kconfig"
  92. source "drivers/net/wireless/marvell/mwifiex/Kconfig"
  93. +source "drivers/net/wireless/marvell/mwlwifi/Kconfig"
  94. config MWL8K
  95. tristate "Marvell 88W8xxx PCI/PCIe Wireless support"
  96. diff --git a/drivers/net/wireless/marvell/Makefile b/drivers/net/wireless/marvell/Makefile
  97. index 25f6d5d2fa0c..00fccce28cdd 100644
  98. --- a/drivers/net/wireless/marvell/Makefile
  99. +++ b/drivers/net/wireless/marvell/Makefile
  100. @@ -3,5 +3,6 @@ obj-$(CONFIG_LIBERTAS) += libertas/
  101. obj-$(CONFIG_LIBERTAS_THINFIRM) += libertas_tf/
  102. obj-$(CONFIG_MWIFIEX) += mwifiex/
  103. +obj-$(CONFIG_MWLWIFI) += mwlwifi/
  104. obj-$(CONFIG_MWL8K) += mwl8k.o
  105. diff --git a/drivers/net/wireless/marvell/mwlwifi/Kconfig b/drivers/net/wireless/marvell/mwlwifi/Kconfig
  106. new file mode 100644
  107. index 000000000000..a9bcb9cd4100
  108. --- /dev/null
  109. +++ b/drivers/net/wireless/marvell/mwlwifi/Kconfig
  110. @@ -0,0 +1,23 @@
  111. +config MWLWIFI
  112. + tristate "Marvell Avastar 88W8864/88W8897 PCIe driver (mac80211 compatible)"
  113. + depends on PCI && MAC80211
  114. + select FW_LOADER
  115. + ---help---
  116. + Select to build the driver supporting the:
  117. +
  118. + Marvell Wireless Wi-Fi 88W8864 modules
  119. + Marvell Wireless Wi-Fi 88W8897 modules
  120. +
  121. + This driver uses the kernel's mac80211 subsystem.
  122. +
  123. + If you want to compile the driver as a module (= code which can be
  124. + inserted in and removed from the running kernel whenever you want),
  125. + say M here and read <file:Documentation/kbuild/modules.txt>. The
  126. + module will be called mwlwifi.
  127. +
  128. + NOTE: Selecting this driver may cause conflict with MWIFIEX driver
  129. + that also operates on the same part number 88W8897. Users should
  130. + select either MWIFIEX or MWLWIFI, not both. MWIFIEX is fullmac,
  131. + supporting more comprehensive client functions for laptops/embedded
  132. + devices. MWLWIFI is mac80211-based for full AP/Wireless Bridge.
  133. +
  134. diff --git a/drivers/net/wireless/marvell/mwlwifi/Makefile b/drivers/net/wireless/marvell/mwlwifi/Makefile
  135. new file mode 100644
  136. index 000000000000..061833703c7f
  137. --- /dev/null
  138. +++ b/drivers/net/wireless/marvell/mwlwifi/Makefile
  139. @@ -0,0 +1,19 @@
  140. +obj-$(CONFIG_MWLWIFI) += mwlwifi.o
  141. +
  142. +mwlwifi-objs += core.o
  143. +mwlwifi-objs += mac80211.o
  144. +mwlwifi-objs += mu_mimo.o
  145. +mwlwifi-objs += vendor_cmd.o
  146. +mwlwifi-objs += utils.o
  147. +mwlwifi-$(CONFIG_THERMAL) += thermal.o
  148. +mwlwifi-$(CONFIG_DEBUG_FS) += debugfs.o
  149. +mwlwifi-objs += hif/fwcmd.o
  150. +mwlwifi-objs += hif/pcie/pcie.o
  151. +mwlwifi-objs += hif/pcie/fwdl.o
  152. +mwlwifi-objs += hif/pcie/tx.o
  153. +mwlwifi-objs += hif/pcie/rx.o
  154. +mwlwifi-objs += hif/pcie/tx_ndp.o
  155. +mwlwifi-objs += hif/pcie/rx_ndp.o
  156. +
  157. +ccflags-y += -I$(src)
  158. +ccflags-y += -D__CHECK_ENDIAN__
  159. diff --git a/drivers/net/wireless/marvell/mwlwifi/Makefile.module b/drivers/net/wireless/marvell/mwlwifi/Makefile.module
  160. new file mode 100644
  161. index 000000000000..d11a1b88cab6
  162. --- /dev/null
  163. +++ b/drivers/net/wireless/marvell/mwlwifi/Makefile.module
  164. @@ -0,0 +1,28 @@
  165. +obj-m += mwlwifi.o
  166. +
  167. +mwlwifi-objs += core.o
  168. +mwlwifi-objs += mac80211.o
  169. +mwlwifi-objs += mu_mimo.o
  170. +mwlwifi-objs += vendor_cmd.o
  171. +mwlwifi-objs += utils.o
  172. +mwlwifi-$(CONFIG_THERMAL) += thermal.o
  173. +mwlwifi-$(CONFIG_DEBUG_FS) += debugfs.o
  174. +mwlwifi-objs += hif/fwcmd.o
  175. +mwlwifi-objs += hif/pcie/pcie.o
  176. +mwlwifi-objs += hif/pcie/fwdl.o
  177. +mwlwifi-objs += hif/pcie/tx.o
  178. +mwlwifi-objs += hif/pcie/rx.o
  179. +mwlwifi-objs += hif/pcie/tx_ndp.o
  180. +mwlwifi-objs += hif/pcie/rx_ndp.o
  181. +
  182. +ccflags-y += -I$(src)
  183. +ccflags-y += -O2 -funroll-loops -D__CHECK_ENDIAN__
  184. +
  185. +all:
  186. + $(MAKE) -C $(KDIR) M=$(PWD)
  187. +
  188. +clean:
  189. + rm -f *.a *.s *.ko *.ko.cmd *.mod.* .mwlwifi.* modules.order Module.symvers
  190. + rm -rf .tmp_versions
  191. + find . -name ".*.o.cmd" -exec rm -f {} \;
  192. + find . -name "*.o" -exec rm -f {} \;
  193. diff --git a/drivers/net/wireless/marvell/mwlwifi/README.md b/drivers/net/wireless/marvell/mwlwifi/README.md
  194. new file mode 100644
  195. index 000000000000..788c5d4dc80d
  196. --- /dev/null
  197. +++ b/drivers/net/wireless/marvell/mwlwifi/README.md
  198. @@ -0,0 +1,142 @@
  199. +# mwlwifi
  200. +mac80211 driver for the Marvell 88W8x64 802.11ac chip
  201. +
  202. +## Building mwlwifi With OpenWrt/LEDE
  203. +1. Modify `package/kernel/mwlwifi/Makefile`:
  204. + ```
  205. + PKG_VERSION:=10.3.0.17-20160601
  206. + PKG_SOURCE_VERSION:=4bb95ba1aeccce506a95499b49b9b844ecfae8a1
  207. + ```
  208. +
  209. +2. Rename `package/kernel/mwlwifi/patches` to `package/kernel/mwlwifi/patches.tmp`.
  210. +3. Run the following commands:
  211. + ```sh
  212. + make package/kernel/mwlwifi/clean
  213. + make V=s (-jx)
  214. + ```
  215. +
  216. +### Special Considerations
  217. +* After driver 10.3.0.17-20160603, [MAX-MPDU-7991] should be removed from vht_capab command of hostapd.
  218. +
  219. +* Hostpad must include the following commit for 160 MHz operation:
  220. + ```
  221. + commit 03a72eacda5d9a1837a74387081596a0d5466ec1
  222. + Author: Jouni Malinen <jouni@qca.qualcomm.com>
  223. + Date: Thu Dec 17 18:39:19 2015 +0200
  224. +
  225. + VHT: Add an interoperability workaround for 80+80 and 160 MHz channels
  226. +
  227. + Number of deployed 80 MHz capable VHT stations that do not support 80+80
  228. + and 160 MHz bandwidths seem to misbehave when trying to connect to an AP
  229. + that advertises 80+80 or 160 MHz channel bandwidth in the VHT Operation
  230. + element. To avoid such issues with deployed devices, modify the design
  231. + based on newly proposed IEEE 802.11 standard changes.
  232. +
  233. + This allows poorly implemented VHT 80 MHz stations to connect with the
  234. + AP in 80 MHz mode. 80+80 and 160 MHz capable stations need to support
  235. + the new workaround mechanism to allow full bandwidth to be used.
  236. + However, there are more or less no impacted station with 80+80/160
  237. + capability deployed.
  238. +
  239. + Signed-off-by: Jouni Malinen jouni@qca.qualcomm.com
  240. +
  241. + Note: After hostapd package 2016-06-15, this commit is already included.
  242. + ```
  243. +
  244. +* In order to let STA mode to support 160 MHz operation, mac80211 package should be 2016-10-08 or later.
  245. +
  246. +* WiFi device does not use HT rates when using TKIP as the encryption cipher. If you want to have good performance, please use AES only.
  247. +
  248. +* DTS parameters for mwlwifi driver (pcie@X,0):
  249. + ```sh
  250. + #Disable 2g band
  251. + marvell,2ghz = <0>;
  252. +
  253. + #Disable 5g band
  254. + marvell,5ghz = <0>;
  255. +
  256. + #Specify antenna number, default is 4x4. For WRT1200AC, you must set these values to 2x2.
  257. + marvell,chainmask = <4 4>;
  258. +
  259. + #Specify external power table. If your device needs external power table, you must provide the power table via this parameter, otherwise the Tx power will be pretty low.
  260. + marvell,powertable
  261. + ```
  262. +
  263. + To see if your device needs/accepts an external power table or not, run the following:
  264. + ```sh
  265. + cat /sys/kernel/debug/ieee80211/phy0/mwlwifi/info
  266. + ```
  267. +
  268. + You should see a line in the results which looks like the following:
  269. + ```sh
  270. + power table loaded from dts: no
  271. + ```
  272. +
  273. + If it is "no", it does not allow you to load external power table (for newer devices due to FCC regulations). If it is "yes", you must provide power table in DTS file (for older devices).
  274. +
  275. +* Changing interrupt to different CPU cores:
  276. + ```sh
  277. + #Use CPU0:
  278. + echo 1 > /proc/irq/irq number of phy0 or phy1/smp_affinity
  279. +
  280. + #Use CPU1:
  281. + echo 2 > /proc/irq/irq number of phy0 or phy1/smp_affinity
  282. + ```
  283. +
  284. +* Note for DFS of WRT3200ACM (88W8964):
  285. +
  286. + All WRT3200ACM devices are programmed with device power table. Mwlwifi driver will base on region code to set country code for your device and it will not allow you to change country code. There are another wifi (phy2) on WRT3200ACM which is not mwlwifi. It will allow you to change country code. Under this case, country code setting will be conflicted and it will let DFS can't work.
  287. +
  288. + There are two ways to resolve this problem:
  289. + * Please don't change country code and let mwlwifi set it for you.
  290. + * Remove phy2. Under this case, even though you change country code, mwlwifi will reject it. Because phy2 is not existed, country code setting won't be conflicted. To do this, run the following commands (for OpenWrt/LEDE):
  291. +
  292. + ```sh
  293. + opkg remove kmod-mwifiex-sdio
  294. + opkg remove mwifiex-sdio-firmware
  295. + reboot
  296. + ```
  297. +
  298. + The better way is let mwlwifi set country code for you.
  299. +
  300. +## Replacing mwlwifi on a Current OpenWrt/LEDE Build
  301. +
  302. +1. Establish a symbolic link to your working mwlwifi directory with current mwlwifi package name under directory "dl":
  303. + ```sh
  304. + ls -l mwlwifi*
  305. + ```
  306. +
  307. + You should see something like the following:
  308. + ```sh
  309. + lrwxrwxrwx 1 dlin dlin 48 mwlwifi-10.3.2.0-20170110 -> /home/dlin/home2/projects/github/mwlwifi
  310. +
  311. + -rw-r--r-- 1 dlin dlin 4175136 mwlwifi-10.3.2.0-20170110.tar.xz
  312. + ```
  313. +
  314. +2. Back up original mwlwifi package and tar your working mwlwifi to replace original mwlwifi package:
  315. +
  316. + ```sh
  317. + tar Jcvf mwlwifi-10.3.2.0-20170110.tar.xz mwlwifi-10.3.2.0-20170110/.
  318. + ```
  319. +
  320. +3. You can use `make V=s` to build the whole image or `make V=s package/kernel/mwlwifi/compile` to build mwlwifi package. The generated whole image or mwlwifi package can be found under directory "bin".
  321. +
  322. +Due to package version being the same as previous one, you need to add option `--force-reinstall` when you use `opkg` to update mwlwifi package on your device.
  323. +
  324. +## Monitor interface for debug
  325. +
  326. +1. Create moinitor interface mon0:
  327. + ```sh
  328. + iw wlan0/wlan1 interface add mon0 type monitor
  329. + ifconfig mon0 up
  330. + ```
  331. +
  332. +2. Use tcpdump to dump dhcp packets:
  333. + ```sh
  334. + tcpdump -vvvi mon0 -n port 67 and port 68
  335. + ```
  336. +
  337. +3. Use tcpdump to dump icmp packets:
  338. + ```sh
  339. + tcpdump -vvvi mon0 icmp
  340. + ```
  341. diff --git a/drivers/net/wireless/marvell/mwlwifi/core.c b/drivers/net/wireless/marvell/mwlwifi/core.c
  342. new file mode 100644
  343. index 000000000000..9d2b5511607e
  344. --- /dev/null
  345. +++ b/drivers/net/wireless/marvell/mwlwifi/core.c
  346. @@ -0,0 +1,1086 @@
  347. +/*
  348. + * Copyright (C) 2006-2018, Marvell International Ltd.
  349. + *
  350. + * This software file (the "File") is distributed by Marvell International
  351. + * Ltd. under the terms of the GNU General Public License Version 2, June 1991
  352. + * (the "License"). You may use, redistribute and/or modify this File in
  353. + * accordance with the terms and conditions of the License, a copy of which
  354. + * is available by writing to the Free Software Foundation, Inc.
  355. + *
  356. + * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
  357. + * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
  358. + * ARE EXPRESSLY DISCLAIMED. The License provides additional details about
  359. + * this warranty disclaimer.
  360. + */
  361. +
  362. +/* Description: This file implements core layer related functions. */
  363. +
  364. +#include <linux/etherdevice.h>
  365. +
  366. +#include "sysadpt.h"
  367. +#include "core.h"
  368. +#include "vendor_cmd.h"
  369. +#include "thermal.h"
  370. +#include "debugfs.h"
  371. +#include "hif/fwcmd.h"
  372. +#include "hif/hif-ops.h"
  373. +
  374. +#define CMD_BUF_SIZE 0x4000
  375. +#define INVALID_WATCHDOG 0xAA
  376. +
  377. +static const struct ieee80211_channel mwl_channels_24[] = {
  378. + { .band = NL80211_BAND_2GHZ, .center_freq = 2412, .hw_value = 1, },
  379. + { .band = NL80211_BAND_2GHZ, .center_freq = 2417, .hw_value = 2, },
  380. + { .band = NL80211_BAND_2GHZ, .center_freq = 2422, .hw_value = 3, },
  381. + { .band = NL80211_BAND_2GHZ, .center_freq = 2427, .hw_value = 4, },
  382. + { .band = NL80211_BAND_2GHZ, .center_freq = 2432, .hw_value = 5, },
  383. + { .band = NL80211_BAND_2GHZ, .center_freq = 2437, .hw_value = 6, },
  384. + { .band = NL80211_BAND_2GHZ, .center_freq = 2442, .hw_value = 7, },
  385. + { .band = NL80211_BAND_2GHZ, .center_freq = 2447, .hw_value = 8, },
  386. + { .band = NL80211_BAND_2GHZ, .center_freq = 2452, .hw_value = 9, },
  387. + { .band = NL80211_BAND_2GHZ, .center_freq = 2457, .hw_value = 10, },
  388. + { .band = NL80211_BAND_2GHZ, .center_freq = 2462, .hw_value = 11, },
  389. + { .band = NL80211_BAND_2GHZ, .center_freq = 2467, .hw_value = 12, },
  390. + { .band = NL80211_BAND_2GHZ, .center_freq = 2472, .hw_value = 13, },
  391. + { .band = NL80211_BAND_2GHZ, .center_freq = 2484, .hw_value = 14, },
  392. +};
  393. +
  394. +static const struct ieee80211_rate mwl_rates_24[] = {
  395. + { .bitrate = 10, .hw_value = 2, },
  396. + { .bitrate = 20, .hw_value = 4, },
  397. + { .bitrate = 55, .hw_value = 11, },
  398. + { .bitrate = 110, .hw_value = 22, },
  399. + { .bitrate = 220, .hw_value = 44, },
  400. + { .bitrate = 60, .hw_value = 12, },
  401. + { .bitrate = 90, .hw_value = 18, },
  402. + { .bitrate = 120, .hw_value = 24, },
  403. + { .bitrate = 180, .hw_value = 36, },
  404. + { .bitrate = 240, .hw_value = 48, },
  405. + { .bitrate = 360, .hw_value = 72, },
  406. + { .bitrate = 480, .hw_value = 96, },
  407. + { .bitrate = 540, .hw_value = 108, },
  408. +};
  409. +
  410. +static const struct ieee80211_channel mwl_channels_50[] = {
  411. + { .band = NL80211_BAND_5GHZ, .center_freq = 5180, .hw_value = 36, },
  412. + { .band = NL80211_BAND_5GHZ, .center_freq = 5200, .hw_value = 40, },
  413. + { .band = NL80211_BAND_5GHZ, .center_freq = 5220, .hw_value = 44, },
  414. + { .band = NL80211_BAND_5GHZ, .center_freq = 5240, .hw_value = 48, },
  415. + { .band = NL80211_BAND_5GHZ, .center_freq = 5260, .hw_value = 52, },
  416. + { .band = NL80211_BAND_5GHZ, .center_freq = 5280, .hw_value = 56, },
  417. + { .band = NL80211_BAND_5GHZ, .center_freq = 5300, .hw_value = 60, },
  418. + { .band = NL80211_BAND_5GHZ, .center_freq = 5320, .hw_value = 64, },
  419. + { .band = NL80211_BAND_5GHZ, .center_freq = 5500, .hw_value = 100, },
  420. + { .band = NL80211_BAND_5GHZ, .center_freq = 5520, .hw_value = 104, },
  421. + { .band = NL80211_BAND_5GHZ, .center_freq = 5540, .hw_value = 108, },
  422. + { .band = NL80211_BAND_5GHZ, .center_freq = 5560, .hw_value = 112, },
  423. + { .band = NL80211_BAND_5GHZ, .center_freq = 5580, .hw_value = 116, },
  424. + { .band = NL80211_BAND_5GHZ, .center_freq = 5600, .hw_value = 120, },
  425. + { .band = NL80211_BAND_5GHZ, .center_freq = 5620, .hw_value = 124, },
  426. + { .band = NL80211_BAND_5GHZ, .center_freq = 5640, .hw_value = 128, },
  427. + { .band = NL80211_BAND_5GHZ, .center_freq = 5660, .hw_value = 132, },
  428. + { .band = NL80211_BAND_5GHZ, .center_freq = 5680, .hw_value = 136, },
  429. + { .band = NL80211_BAND_5GHZ, .center_freq = 5700, .hw_value = 140, },
  430. + { .band = NL80211_BAND_5GHZ, .center_freq = 5720, .hw_value = 144, },
  431. + { .band = NL80211_BAND_5GHZ, .center_freq = 5745, .hw_value = 149, },
  432. + { .band = NL80211_BAND_5GHZ, .center_freq = 5765, .hw_value = 153, },
  433. + { .band = NL80211_BAND_5GHZ, .center_freq = 5785, .hw_value = 157, },
  434. + { .band = NL80211_BAND_5GHZ, .center_freq = 5805, .hw_value = 161, },
  435. +};
  436. +
  437. +static const struct ieee80211_rate mwl_rates_50[] = {
  438. + { .bitrate = 60, .hw_value = 12, },
  439. + { .bitrate = 90, .hw_value = 18, },
  440. + { .bitrate = 120, .hw_value = 24, },
  441. + { .bitrate = 180, .hw_value = 36, },
  442. + { .bitrate = 240, .hw_value = 48, },
  443. + { .bitrate = 360, .hw_value = 72, },
  444. + { .bitrate = 480, .hw_value = 96, },
  445. + { .bitrate = 540, .hw_value = 108, },
  446. +};
  447. +
  448. +static const struct ieee80211_iface_limit ap_if_limits[] = {
  449. + { .max = SYSADPT_NUM_OF_AP, .types = BIT(NL80211_IFTYPE_AP) },
  450. +#if defined(CPTCFG_MAC80211_MESH) || defined(CONFIG_MAC80211_MESH)
  451. + { .max = SYSADPT_NUM_OF_MESH, .types = BIT(NL80211_IFTYPE_MESH_POINT) },
  452. +#endif
  453. + { .max = SYSADPT_NUM_OF_CLIENT, .types = BIT(NL80211_IFTYPE_STATION) },
  454. +};
  455. +
  456. +static const struct ieee80211_iface_combination ap_if_comb = {
  457. + .limits = ap_if_limits,
  458. + .n_limits = ARRAY_SIZE(ap_if_limits),
  459. + .max_interfaces = SYSADPT_NUM_OF_AP,
  460. + .num_different_channels = 1,
  461. + .radar_detect_widths = BIT(NL80211_CHAN_WIDTH_20_NOHT) |
  462. + BIT(NL80211_CHAN_WIDTH_20) |
  463. + BIT(NL80211_CHAN_WIDTH_40) |
  464. + BIT(NL80211_CHAN_WIDTH_80) |
  465. + BIT(NL80211_CHAN_WIDTH_160),
  466. +};
  467. +
  468. +struct region_code_mapping {
  469. + const char *alpha2;
  470. + u32 region_code;
  471. +};
  472. +
  473. +static const struct region_code_mapping regmap[] = {
  474. + {"US", 0x10}, /* US FCC */
  475. + {"CA", 0x20}, /* Canada */
  476. + {"FR", 0x30}, /* France */
  477. + {"ES", 0x31}, /* Spain */
  478. + {"FR", 0x32}, /* France */
  479. + {"JP", 0x40}, /* Japan */
  480. + {"TW", 0x80}, /* Taiwan */
  481. + {"AU", 0x81}, /* Australia */
  482. + {"CN", 0x90}, /* China (Asia) */
  483. +};
  484. +
  485. +static int mwl_prepare_cmd_buf(struct mwl_priv *priv)
  486. +{
  487. + priv->pcmd_buf =
  488. + (unsigned short *)dmam_alloc_coherent(priv->dev,
  489. + CMD_BUF_SIZE,
  490. + &priv->pphys_cmd_buf,
  491. + GFP_KERNEL);
  492. + if (!priv->pcmd_buf) {
  493. + wiphy_err(priv->hw->wiphy,
  494. + "cannot alloc memory for command buffer\n");
  495. + goto err;
  496. + }
  497. + wiphy_debug(priv->hw->wiphy,
  498. + "priv->pcmd_buf = %p priv->pphys_cmd_buf = %p\n",
  499. + priv->pcmd_buf,
  500. + (void *)priv->pphys_cmd_buf);
  501. + memset(priv->pcmd_buf, 0x00, CMD_BUF_SIZE);
  502. +
  503. + return 0;
  504. +
  505. +err:
  506. + wiphy_err(priv->hw->wiphy, "command buffer alloc fail\n");
  507. +
  508. + return -EIO;
  509. +}
  510. +
  511. +static int mwl_init_firmware(struct mwl_priv *priv, const char *fw_name,
  512. + const char *cal_name, const char *txpwrlmt_name)
  513. +{
  514. + int rc = 0;
  515. +
  516. + rc = request_firmware((const struct firmware **)&priv->fw_ucode,
  517. + fw_name, priv->dev);
  518. +
  519. + if (rc) {
  520. + wiphy_err(priv->hw->wiphy,
  521. + "cannot find firmware image <%s>\n", fw_name);
  522. + goto err_load_fw;
  523. + }
  524. +
  525. + rc = mwl_hif_download_firmware(priv->hw);
  526. + if (rc) {
  527. + wiphy_err(priv->hw->wiphy,
  528. + "cannot download firmware image <%s>\n", fw_name);
  529. + goto err_download_fw;
  530. + }
  531. +
  532. + if (cal_name) {
  533. + if ((request_firmware((const struct firmware **)&priv->cal_data,
  534. + cal_name, priv->dev)) < 0)
  535. + wiphy_debug(priv->hw->wiphy,
  536. + "cannot find calibtration data\n");
  537. + }
  538. +
  539. + if (txpwrlmt_name) {
  540. + if ((request_firmware(
  541. + (const struct firmware **)&priv->txpwrlmt_file,
  542. + txpwrlmt_name, priv->dev)) < 0)
  543. + wiphy_debug(priv->hw->wiphy,
  544. + "cannot find tx power limit data\n");
  545. + }
  546. +
  547. + return rc;
  548. +
  549. +err_download_fw:
  550. +
  551. + release_firmware(priv->fw_ucode);
  552. +
  553. +err_load_fw:
  554. +
  555. + wiphy_err(priv->hw->wiphy, "firmware init fail\n");
  556. +
  557. + return rc;
  558. +}
  559. +
  560. +static void mwl_process_of_dts(struct mwl_priv *priv)
  561. +{
  562. +#ifdef CONFIG_OF
  563. + struct property *prop;
  564. + u32 prop_value;
  565. +
  566. + priv->dt_node =
  567. + of_find_node_by_name(mwl_hif_device_node(priv->hw),
  568. + "mwlwifi");
  569. + if (!priv->dt_node)
  570. + return;
  571. +
  572. + /* look for all matching property names */
  573. + for_each_property_of_node(priv->dt_node, prop) {
  574. + if (strcmp(prop->name, "marvell,2ghz") == 0)
  575. + priv->disable_2g = true;
  576. + if (strcmp(prop->name, "marvell,5ghz") == 0)
  577. + priv->disable_5g = true;
  578. + if (strcmp(prop->name, "marvell,chainmask") == 0) {
  579. + prop_value = be32_to_cpu(*((__be32 *)prop->value));
  580. + if (prop_value == 2)
  581. + priv->antenna_tx = ANTENNA_TX_2;
  582. + else if (prop_value == 3)
  583. + priv->antenna_tx = ANTENNA_TX_3;
  584. +
  585. + prop_value = be32_to_cpu(*((__be32 *)
  586. + (prop->value + 4)));
  587. + if (prop_value == 2)
  588. + priv->antenna_rx = ANTENNA_RX_2;
  589. + else if (prop_value == 3)
  590. + priv->antenna_rx = ANTENNA_RX_3;
  591. + }
  592. + }
  593. +
  594. + priv->pwr_node = of_find_node_by_name(priv->dt_node,
  595. + "marvell,powertable");
  596. +#endif
  597. +}
  598. +
  599. +static void mwl_reg_notifier(struct wiphy *wiphy,
  600. + struct regulatory_request *request)
  601. +{
  602. + struct ieee80211_hw *hw;
  603. + struct mwl_priv *priv;
  604. +#ifdef CONFIG_OF
  605. + struct property *prop;
  606. + struct property *fcc_prop = NULL;
  607. + struct property *etsi_prop = NULL;
  608. + struct property *specific_prop = NULL;
  609. + u32 prop_value;
  610. + int i, j, k;
  611. +#endif
  612. +
  613. + hw = wiphy_to_ieee80211_hw(wiphy);
  614. + priv = hw->priv;
  615. +
  616. + if (priv->forbidden_setting) {
  617. + if (!priv->regulatory_set) {
  618. + regulatory_hint(wiphy, priv->fw_alpha2);
  619. + priv->regulatory_set = true;
  620. + } else {
  621. + if (memcmp(priv->fw_alpha2, request->alpha2, 2))
  622. + regulatory_hint(wiphy, priv->fw_alpha2);
  623. + }
  624. + return;
  625. + }
  626. +
  627. + priv->dfs_region = request->dfs_region;
  628. +
  629. +#ifdef CONFIG_OF
  630. + if ((priv->chip_type != MWL8997) && (priv->pwr_node)) {
  631. + for_each_property_of_node(priv->pwr_node, prop) {
  632. + if (strcmp(prop->name, "FCC") == 0)
  633. + fcc_prop = prop;
  634. + if (strcmp(prop->name, "ETSI") == 0)
  635. + etsi_prop = prop;
  636. + if ((prop->name[0] == request->alpha2[0]) &&
  637. + (prop->name[1] == request->alpha2[1]))
  638. + specific_prop = prop;
  639. + }
  640. +
  641. + prop = NULL;
  642. +
  643. + if (specific_prop) {
  644. + prop = specific_prop;
  645. + } else {
  646. + if (priv->dfs_region == NL80211_DFS_ETSI)
  647. + prop = etsi_prop;
  648. + else
  649. + prop = fcc_prop;
  650. + }
  651. +
  652. + if (prop) {
  653. + /* Reset the whole table */
  654. + for (i = 0; i < SYSADPT_MAX_NUM_CHANNELS; i++)
  655. + memset(&priv->tx_pwr_tbl[i], 0,
  656. + sizeof(struct mwl_tx_pwr_tbl));
  657. +
  658. + /* Load related power table */
  659. + i = 0;
  660. + j = 0;
  661. + while (i < prop->length) {
  662. + prop_value =
  663. + be32_to_cpu(*(__be32 *)
  664. + (prop->value + i));
  665. + priv->tx_pwr_tbl[j].channel = prop_value;
  666. + i += 4;
  667. + prop_value =
  668. + be32_to_cpu(*(__be32 *)
  669. + (prop->value + i));
  670. + priv->tx_pwr_tbl[j].setcap = prop_value;
  671. + i += 4;
  672. + for (k = 0; k < SYSADPT_TX_POWER_LEVEL_TOTAL;
  673. + k++) {
  674. + prop_value =
  675. + be32_to_cpu(*(__be32 *)
  676. + (prop->value + i));
  677. + priv->tx_pwr_tbl[j].tx_power[k] =
  678. + prop_value;
  679. + i += 4;
  680. + }
  681. + prop_value =
  682. + be32_to_cpu(*(__be32 *)
  683. + (prop->value + i));
  684. + priv->tx_pwr_tbl[j].cdd =
  685. + (prop_value == 0) ? false : true;
  686. + i += 4;
  687. + prop_value =
  688. + be32_to_cpu(*(__be32 *)
  689. + (prop->value + i));
  690. + priv->tx_pwr_tbl[j].txantenna2 = prop_value;
  691. + i += 4;
  692. + j++;
  693. + }
  694. +
  695. + /* Dump loaded power tabel */
  696. + wiphy_debug(hw->wiphy, "regdomain: %s\n", prop->name);
  697. + for (i = 0; i < SYSADPT_MAX_NUM_CHANNELS; i++) {
  698. + struct mwl_tx_pwr_tbl *pwr_tbl;
  699. + char disp_buf[64];
  700. + char *disp_ptr;
  701. +
  702. + pwr_tbl = &priv->tx_pwr_tbl[i];
  703. + if (pwr_tbl->channel == 0)
  704. + break;
  705. + wiphy_debug(hw->wiphy,
  706. + "Channel: %d: 0x%x 0x%x 0x%x\n",
  707. + pwr_tbl->channel,
  708. + pwr_tbl->setcap,
  709. + pwr_tbl->cdd,
  710. + pwr_tbl->txantenna2);
  711. + disp_ptr = disp_buf;
  712. + for (j = 0; j < SYSADPT_TX_POWER_LEVEL_TOTAL;
  713. + j++) {
  714. + disp_ptr +=
  715. + sprintf(disp_ptr, "%x ",
  716. + pwr_tbl->tx_power[j]);
  717. + }
  718. + wiphy_debug(hw->wiphy, "%s\n", disp_buf);
  719. + }
  720. + }
  721. + }
  722. +#endif
  723. +}
  724. +
  725. +static void mwl_regd_init(struct mwl_priv *priv)
  726. +{
  727. + u8 region_code;
  728. + int rc;
  729. + int i;
  730. +
  731. + /* hook regulatory domain change notification */
  732. + priv->hw->wiphy->reg_notifier = mwl_reg_notifier;
  733. +
  734. + if (priv->chip_type == MWL8964)
  735. + rc = mwl_fwcmd_get_pwr_tbl_sc4(priv->hw,
  736. + &priv->device_pwr_tbl[0],
  737. + &region_code,
  738. + &priv->number_of_channels,
  739. + 0);
  740. + else
  741. + rc = mwl_fwcmd_get_device_pwr_tbl(priv->hw,
  742. + &priv->device_pwr_tbl[0],
  743. + &region_code,
  744. + &priv->number_of_channels,
  745. + 0);
  746. + if (rc)
  747. + return;
  748. +
  749. + priv->forbidden_setting = true;
  750. +
  751. + for (i = 1; i < priv->number_of_channels; i++) {
  752. + if (priv->chip_type == MWL8964)
  753. + mwl_fwcmd_get_pwr_tbl_sc4(priv->hw,
  754. + &priv->device_pwr_tbl[i],
  755. + &region_code,
  756. + &priv->number_of_channels,
  757. + i);
  758. + else
  759. + mwl_fwcmd_get_device_pwr_tbl(priv->hw,
  760. + &priv->device_pwr_tbl[i],
  761. + &region_code,
  762. + &priv->number_of_channels,
  763. + i);
  764. + }
  765. +
  766. + for (i = 0; i < ARRAY_SIZE(regmap); i++)
  767. + if (regmap[i].region_code == priv->fw_region_code) {
  768. + memcpy(priv->fw_alpha2, regmap[i].alpha2, 2);
  769. + break;
  770. + }
  771. +}
  772. +
  773. +static void mwl_set_ht_caps(struct mwl_priv *priv,
  774. + struct ieee80211_supported_band *band)
  775. +{
  776. + struct ieee80211_hw *hw;
  777. + const u8 ant_rx_no[ANTENNA_RX_MAX] = { 3, 1, 2, 3};
  778. + int i;
  779. +
  780. + hw = priv->hw;
  781. +
  782. + band->ht_cap.ht_supported = 1;
  783. + if (priv->chip_type == MWL8964)
  784. + band->ht_cap.cap |= IEEE80211_HT_CAP_MAX_AMSDU;
  785. + band->ht_cap.cap |= IEEE80211_HT_CAP_LDPC_CODING;
  786. + band->ht_cap.cap |= IEEE80211_HT_CAP_SUP_WIDTH_20_40;
  787. + band->ht_cap.cap |= IEEE80211_HT_CAP_SM_PS;
  788. + band->ht_cap.cap |= IEEE80211_HT_CAP_SGI_20;
  789. + band->ht_cap.cap |= IEEE80211_HT_CAP_SGI_40;
  790. + band->ht_cap.cap |= IEEE80211_HT_CAP_DSSSCCK40;
  791. +
  792. + if ((priv->chip_type == MWL8997) &&
  793. + (priv->antenna_tx != ANTENNA_TX_1)) {
  794. + band->ht_cap.cap |= IEEE80211_HT_CAP_TX_STBC;
  795. + band->ht_cap.cap |= (1 << IEEE80211_HT_CAP_RX_STBC_SHIFT);
  796. + }
  797. +
  798. + ieee80211_hw_set(hw, AMPDU_AGGREGATION);
  799. + ieee80211_hw_set(hw, SUPPORTS_AMSDU_IN_AMPDU);
  800. + band->ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K;
  801. + band->ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_4;
  802. +
  803. + for (i = 0; i < ant_rx_no[priv->antenna_rx]; i++)
  804. + band->ht_cap.mcs.rx_mask[i] = 0xff;
  805. + band->ht_cap.mcs.rx_mask[4] = 0x01;
  806. +
  807. + band->ht_cap.mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED;
  808. +}
  809. +
  810. +static void mwl_set_vht_caps(struct mwl_priv *priv,
  811. + struct ieee80211_supported_band *band)
  812. +{
  813. + u32 antenna_num = 4;
  814. +
  815. + band->vht_cap.vht_supported = 1;
  816. +
  817. + if (priv->chip_type == MWL8964) {
  818. + band->vht_cap.cap |= IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_11454;
  819. + band->vht_cap.cap |= IEEE80211_VHT_CAP_SHORT_GI_160;
  820. + band->vht_cap.cap |= IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ;
  821. + } else
  822. + band->vht_cap.cap |= IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_3895;
  823. + band->vht_cap.cap |= IEEE80211_VHT_CAP_RXLDPC;
  824. + band->vht_cap.cap |= IEEE80211_VHT_CAP_SHORT_GI_80;
  825. + band->vht_cap.cap |= IEEE80211_VHT_CAP_RXSTBC_1;
  826. + if (priv->antenna_tx != ANTENNA_TX_1) {
  827. + band->vht_cap.cap |= IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE;
  828. + if (priv->chip_type == MWL8964)
  829. + band->vht_cap.cap |=
  830. + IEEE80211_VHT_CAP_MU_BEAMFORMER_CAPABLE;
  831. + }
  832. + band->vht_cap.cap |= IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE;
  833. + if (priv->chip_type == MWL8964)
  834. + band->vht_cap.cap |= IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE;
  835. + band->vht_cap.cap |= IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK;
  836. + band->vht_cap.cap |= IEEE80211_VHT_CAP_RX_ANTENNA_PATTERN;
  837. + band->vht_cap.cap |= IEEE80211_VHT_CAP_TX_ANTENNA_PATTERN;
  838. + if (priv->chip_type == MWL8997) {
  839. + if (priv->antenna_tx != ANTENNA_TX_1)
  840. + band->vht_cap.cap |= IEEE80211_VHT_CAP_TXSTBC;
  841. + }
  842. +
  843. + if (priv->antenna_rx == ANTENNA_RX_1)
  844. + band->vht_cap.vht_mcs.rx_mcs_map = cpu_to_le16(0xfffe);
  845. + else if (priv->antenna_rx == ANTENNA_RX_2)
  846. + band->vht_cap.vht_mcs.rx_mcs_map = cpu_to_le16(0xfffa);
  847. + else
  848. + band->vht_cap.vht_mcs.rx_mcs_map = cpu_to_le16(0xffea);
  849. +
  850. + if (priv->antenna_tx == ANTENNA_TX_1) {
  851. + band->vht_cap.vht_mcs.tx_mcs_map = cpu_to_le16(0xfffe);
  852. + antenna_num = 1;
  853. + } else if (priv->antenna_tx == ANTENNA_TX_2) {
  854. + band->vht_cap.vht_mcs.tx_mcs_map = cpu_to_le16(0xfffa);
  855. + antenna_num = 2;
  856. + } else
  857. + band->vht_cap.vht_mcs.tx_mcs_map = cpu_to_le16(0xffea);
  858. +
  859. + if (band->vht_cap.cap & (IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE |
  860. + IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE)) {
  861. + band->vht_cap.cap |=
  862. + ((antenna_num - 1) <<
  863. + IEEE80211_VHT_CAP_BEAMFORMEE_STS_SHIFT) &
  864. + IEEE80211_VHT_CAP_BEAMFORMEE_STS_MASK;
  865. + }
  866. +
  867. + if (band->vht_cap.cap & (IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE |
  868. + IEEE80211_VHT_CAP_MU_BEAMFORMER_CAPABLE)) {
  869. + band->vht_cap.cap |=
  870. + ((antenna_num - 1) <<
  871. + IEEE80211_VHT_CAP_SOUNDING_DIMENSIONS_SHIFT) &
  872. + IEEE80211_VHT_CAP_SOUNDING_DIMENSIONS_MASK;
  873. + }
  874. +}
  875. +
  876. +static void mwl_set_caps(struct mwl_priv *priv)
  877. +{
  878. + struct ieee80211_hw *hw;
  879. +
  880. + hw = priv->hw;
  881. +
  882. + /* set up band information for 2.4G */
  883. + if (!priv->disable_2g) {
  884. + BUILD_BUG_ON(sizeof(priv->channels_24) !=
  885. + sizeof(mwl_channels_24));
  886. + memcpy(priv->channels_24, mwl_channels_24,
  887. + sizeof(mwl_channels_24));
  888. +
  889. + BUILD_BUG_ON(sizeof(priv->rates_24) != sizeof(mwl_rates_24));
  890. + memcpy(priv->rates_24, mwl_rates_24, sizeof(mwl_rates_24));
  891. +
  892. + priv->band_24.band = NL80211_BAND_2GHZ;
  893. + priv->band_24.channels = priv->channels_24;
  894. + priv->band_24.n_channels = ARRAY_SIZE(mwl_channels_24);
  895. + priv->band_24.bitrates = priv->rates_24;
  896. + priv->band_24.n_bitrates = ARRAY_SIZE(mwl_rates_24);
  897. +
  898. + mwl_set_ht_caps(priv, &priv->band_24);
  899. + mwl_set_vht_caps(priv, &priv->band_24);
  900. +
  901. + hw->wiphy->bands[NL80211_BAND_2GHZ] = &priv->band_24;
  902. + }
  903. +
  904. + /* set up band information for 5G */
  905. + if (!priv->disable_5g) {
  906. + BUILD_BUG_ON(sizeof(priv->channels_50) !=
  907. + sizeof(mwl_channels_50));
  908. + memcpy(priv->channels_50, mwl_channels_50,
  909. + sizeof(mwl_channels_50));
  910. +
  911. + BUILD_BUG_ON(sizeof(priv->rates_50) != sizeof(mwl_rates_50));
  912. + memcpy(priv->rates_50, mwl_rates_50, sizeof(mwl_rates_50));
  913. +
  914. + priv->band_50.band = NL80211_BAND_5GHZ;
  915. + priv->band_50.channels = priv->channels_50;
  916. + priv->band_50.n_channels = ARRAY_SIZE(mwl_channels_50);
  917. + priv->band_50.bitrates = priv->rates_50;
  918. + priv->band_50.n_bitrates = ARRAY_SIZE(mwl_rates_50);
  919. +
  920. + mwl_set_ht_caps(priv, &priv->band_50);
  921. + mwl_set_vht_caps(priv, &priv->band_50);
  922. +
  923. + hw->wiphy->bands[NL80211_BAND_5GHZ] = &priv->band_50;
  924. + }
  925. +}
  926. +
  927. +static void mwl_heartbeat_handle(struct work_struct *work)
  928. +{
  929. + struct mwl_priv *priv =
  930. + container_of(work, struct mwl_priv, heartbeat_handle);
  931. + u32 val;
  932. +
  933. + mwl_fwcmd_get_addr_value(priv->hw, 0, 1, &val, 0);
  934. + priv->heartbeating = false;
  935. +}
  936. +
  937. +static void mwl_watchdog_ba_events(struct work_struct *work)
  938. +{
  939. + int rc;
  940. + u8 bitmap = 0, stream_index;
  941. + struct mwl_ampdu_stream *streams;
  942. + struct mwl_priv *priv =
  943. + container_of(work, struct mwl_priv, watchdog_ba_handle);
  944. +
  945. + rc = mwl_fwcmd_get_watchdog_bitmap(priv->hw, &bitmap);
  946. +
  947. + if (rc)
  948. + return;
  949. +
  950. + spin_lock_bh(&priv->stream_lock);
  951. +
  952. + /* the bitmap is the hw queue number. Map it to the ampdu queue. */
  953. + if (bitmap != INVALID_WATCHDOG) {
  954. + if (bitmap == priv->ampdu_num)
  955. + stream_index = 0;
  956. + else if (bitmap > priv->ampdu_num)
  957. + stream_index = bitmap - priv->ampdu_num;
  958. + else
  959. + stream_index = bitmap + 3; /** queue 0 is stream 3*/
  960. +
  961. + if (bitmap != 0xFF) {
  962. + /* Check if the stream is in use before disabling it */
  963. + streams = &priv->ampdu[stream_index];
  964. +
  965. + if (streams->state == AMPDU_STREAM_ACTIVE)
  966. + ieee80211_stop_tx_ba_session(streams->sta,
  967. + streams->tid);
  968. + } else {
  969. + for (stream_index = 0;
  970. + stream_index < priv->ampdu_num;
  971. + stream_index++) {
  972. + streams = &priv->ampdu[stream_index];
  973. +
  974. + if (streams->state != AMPDU_STREAM_ACTIVE)
  975. + continue;
  976. +
  977. + ieee80211_stop_tx_ba_session(streams->sta,
  978. + streams->tid);
  979. + }
  980. + }
  981. + }
  982. +
  983. + spin_unlock_bh(&priv->stream_lock);
  984. +}
  985. +
  986. +static void mwl_account_handle(struct work_struct *work)
  987. +{
  988. + struct mwl_priv *priv =
  989. + container_of(work, struct mwl_priv, account_handle);
  990. +
  991. + mwl_hif_process_account(priv->hw);
  992. +}
  993. +
  994. +static void mwl_wds_check_handle(struct work_struct *work)
  995. +{
  996. + struct mwl_priv *priv =
  997. + container_of(work, struct mwl_priv, wds_check_handle);
  998. + struct mwl_sta *sta_info;
  999. + struct ieee80211_sta *sta;
  1000. + bool wds_sta = false;
  1001. +
  1002. + spin_lock_bh(&priv->sta_lock);
  1003. + list_for_each_entry(sta_info, &priv->sta_list, list) {
  1004. + if (sta_info->wds)
  1005. + continue;
  1006. + sta = container_of((void *)sta_info, struct ieee80211_sta,
  1007. + drv_priv);
  1008. + if (ether_addr_equal(sta->addr, priv->wds_check_sta)) {
  1009. + wds_sta = true;
  1010. + break;
  1011. + }
  1012. + }
  1013. + spin_unlock_bh(&priv->sta_lock);
  1014. +
  1015. + if (wds_sta) {
  1016. + mwl_fwcmd_set_new_stn_wds_sc4(priv->hw, sta->addr);
  1017. + sta_info->wds = true;
  1018. + }
  1019. +
  1020. + priv->wds_check = false;
  1021. +}
  1022. +
  1023. +static void mwl_chnl_switch_event(struct work_struct *work)
  1024. +{
  1025. + struct mwl_priv *priv =
  1026. + container_of(work, struct mwl_priv, chnl_switch_handle);
  1027. + struct mwl_vif *mwl_vif;
  1028. + struct ieee80211_vif *vif;
  1029. +
  1030. + if (!priv->csa_active) {
  1031. + wiphy_err(priv->hw->wiphy,
  1032. + "csa is not active (got channel switch event)\n");
  1033. + return;
  1034. + }
  1035. +
  1036. + spin_lock_bh(&priv->vif_lock);
  1037. + list_for_each_entry(mwl_vif, &priv->vif_list, list) {
  1038. + vif = container_of((void *)mwl_vif, struct ieee80211_vif,
  1039. + drv_priv);
  1040. +
  1041. + if (vif->csa_active)
  1042. + ieee80211_csa_finish(vif);
  1043. + }
  1044. + spin_unlock_bh(&priv->vif_lock);
  1045. +
  1046. + wiphy_info(priv->hw->wiphy, "channel switch is done\n");
  1047. +
  1048. + priv->csa_active = false;
  1049. +}
  1050. +
  1051. +static irqreturn_t mwl_isr(int irq, void *dev_id)
  1052. +{
  1053. + struct ieee80211_hw *hw = dev_id;
  1054. +
  1055. + return mwl_hif_irq_handler(hw);
  1056. +}
  1057. +
  1058. +#ifdef timer_setup
  1059. +static void timer_routine(struct timer_list *t)
  1060. +{
  1061. + struct mwl_priv *priv = from_timer(priv, t, period_timer);
  1062. + struct ieee80211_hw *hw = priv->hw;
  1063. +#else
  1064. +static void timer_routine(unsigned long data)
  1065. +{
  1066. + struct ieee80211_hw *hw = (struct ieee80211_hw *)data;
  1067. + struct mwl_priv *priv = hw->priv;
  1068. +#endif
  1069. + if (priv->heartbeat) {
  1070. + if ((jiffies - priv->pre_jiffies) >=
  1071. + msecs_to_jiffies(priv->heartbeat * 1000)) {
  1072. + if (!priv->heartbeating) {
  1073. + priv->heartbeating = true;
  1074. + ieee80211_queue_work(hw,
  1075. + &priv->heartbeat_handle);
  1076. + }
  1077. + priv->pre_jiffies = jiffies;
  1078. + }
  1079. + }
  1080. +
  1081. + mwl_hif_timer_routine(hw);
  1082. +
  1083. + mod_timer(&priv->period_timer, jiffies +
  1084. + msecs_to_jiffies(SYSADPT_TIMER_WAKEUP_TIME));
  1085. +}
  1086. +
  1087. +static int mwl_wl_init(struct mwl_priv *priv)
  1088. +{
  1089. + struct ieee80211_hw *hw = priv->hw;
  1090. + int rc;
  1091. + u16 addr_num;
  1092. + struct mac_address *mac_addr;
  1093. + u8 last_nibble;
  1094. +
  1095. + hw->extra_tx_headroom = mwl_hif_get_tx_head_room(hw);
  1096. + hw->queues = SYSADPT_TX_WMM_QUEUES;
  1097. +
  1098. + /* Set rssi values to dBm */
  1099. + ieee80211_hw_set(hw, SIGNAL_DBM);
  1100. + ieee80211_hw_set(hw, HAS_RATE_CONTROL);
  1101. +
  1102. + /* Ask mac80211 not to trigger PS mode
  1103. + * based on PM bit of incoming frames.
  1104. + */
  1105. + ieee80211_hw_set(hw, AP_LINK_PS);
  1106. +
  1107. + ieee80211_hw_set(hw, SUPPORTS_PER_STA_GTK);
  1108. + ieee80211_hw_set(hw, MFP_CAPABLE);
  1109. +
  1110. + hw->wiphy->flags |= WIPHY_FLAG_IBSS_RSN;
  1111. + hw->wiphy->flags |= WIPHY_FLAG_HAS_CHANNEL_SWITCH;
  1112. + hw->wiphy->flags |= WIPHY_FLAG_SUPPORTS_TDLS;
  1113. + hw->wiphy->flags |= WIPHY_FLAG_AP_UAPSD;
  1114. +
  1115. + hw->vif_data_size = sizeof(struct mwl_vif);
  1116. + hw->sta_data_size = sizeof(struct mwl_sta);
  1117. +
  1118. + priv->ap_macids_supported = 0x0000ffff;
  1119. + priv->sta_macids_supported = 0x00010000;
  1120. + priv->macids_used = 0;
  1121. + INIT_LIST_HEAD(&priv->vif_list);
  1122. + INIT_LIST_HEAD(&priv->sta_list);
  1123. +
  1124. + /* Set default radio state, preamble and wmm */
  1125. + priv->noise = -104;
  1126. + priv->radio_on = false;
  1127. + priv->radio_short_preamble = false;
  1128. + priv->wmm_enabled = false;
  1129. + priv->powinited = 0;
  1130. + priv->wds_check = false;
  1131. + if (priv->chip_type == MWL8997)
  1132. + priv->pwr_level = SYSADPT_TX_GRP_PWR_LEVEL_TOTAL;
  1133. + else
  1134. + priv->pwr_level = SYSADPT_TX_POWER_LEVEL_TOTAL;
  1135. + priv->dfs_test = false;
  1136. + priv->csa_active = false;
  1137. + priv->dfs_chirp_count_min = 5;
  1138. + priv->dfs_chirp_time_interval = 1000;
  1139. + priv->dfs_pw_filter = 0;
  1140. + priv->dfs_min_num_radar = 5;
  1141. + priv->dfs_min_pri_count = 4;
  1142. + priv->bf_type = TXBF_MODE_AUTO;
  1143. +
  1144. + /* Handle watchdog ba events */
  1145. + INIT_WORK(&priv->heartbeat_handle, mwl_heartbeat_handle);
  1146. + INIT_WORK(&priv->watchdog_ba_handle, mwl_watchdog_ba_events);
  1147. + INIT_WORK(&priv->account_handle, mwl_account_handle);
  1148. + INIT_WORK(&priv->wds_check_handle, mwl_wds_check_handle);
  1149. + INIT_WORK(&priv->chnl_switch_handle, mwl_chnl_switch_event);
  1150. +
  1151. + mutex_init(&priv->fwcmd_mutex);
  1152. + spin_lock_init(&priv->vif_lock);
  1153. + spin_lock_init(&priv->sta_lock);
  1154. + spin_lock_init(&priv->stream_lock);
  1155. + spin_lock_init(&priv->stnid_lock);
  1156. +
  1157. + rc = mwl_thermal_register(priv);
  1158. + if (rc) {
  1159. + wiphy_err(hw->wiphy, "fail to register thermal framework\n");
  1160. + goto err_thermal_register;
  1161. + }
  1162. +
  1163. + rc = mwl_hif_init(hw);
  1164. + if (rc) {
  1165. + wiphy_err(hw->wiphy, "fail to initialize host interface\n");
  1166. + goto err_hif_init;
  1167. + }
  1168. +
  1169. + SET_IEEE80211_PERM_ADDR(hw, priv->hw_data.mac_addr);
  1170. +
  1171. + if (priv->chip_type == MWL8964) {
  1172. + addr_num = SYSADPT_NUM_OF_AP + SYSADPT_NUM_OF_CLIENT;
  1173. + hw->wiphy->n_addresses = addr_num;
  1174. + hw->wiphy->addresses =
  1175. + kzalloc(addr_num * sizeof(*mac_addr), GFP_KERNEL);
  1176. +
  1177. + mac_addr = &hw->wiphy->addresses[0];
  1178. + ether_addr_copy(mac_addr->addr, priv->hw_data.mac_addr);
  1179. + last_nibble = mac_addr->addr[5] & 0x0F;
  1180. + for (addr_num = 0; addr_num < SYSADPT_NUM_OF_AP; addr_num++) {
  1181. + mac_addr = &hw->wiphy->addresses[addr_num + 1];
  1182. + ether_addr_copy(mac_addr->addr, priv->hw_data.mac_addr);
  1183. + if (!strcmp(wiphy_name(hw->wiphy), "phy0")) {
  1184. + last_nibble++;
  1185. + if (last_nibble == 0x10)
  1186. + last_nibble = 0;
  1187. + } else {
  1188. + last_nibble--;
  1189. + if (last_nibble == 0xFF)
  1190. + last_nibble = 0x0F;
  1191. + }
  1192. + mac_addr->addr[5] =
  1193. + (mac_addr->addr[5] & 0xF0) | last_nibble;
  1194. + mac_addr->addr[0] |= 0x2;
  1195. + }
  1196. + }
  1197. +
  1198. + wiphy_info(hw->wiphy,
  1199. + "firmware version: 0x%x\n", priv->hw_data.fw_release_num);
  1200. +
  1201. + if (priv->chip_type == MWL8997) {
  1202. + mwl_fwcmd_set_cfg_data(hw, 2);
  1203. + mwl_fwcmd_set_txpwrlmt_cfg_data(hw);
  1204. + mwl_fwcmd_get_txpwrlmt_cfg_data(hw);
  1205. + }
  1206. +
  1207. + if (priv->chip_type == MWL8964)
  1208. + rc = mwl_fwcmd_get_fw_region_code_sc4(hw,
  1209. + &priv->fw_region_code);
  1210. + else
  1211. + rc = mwl_fwcmd_get_fw_region_code(hw, &priv->fw_region_code);
  1212. + if (!rc) {
  1213. + priv->fw_device_pwrtbl = true;
  1214. + mwl_regd_init(priv);
  1215. + wiphy_info(hw->wiphy,
  1216. + "firmware region code: %x\n", priv->fw_region_code);
  1217. + }
  1218. +
  1219. + if (priv->chip_type == MWL8997)
  1220. + mwl_fwcmd_dump_otp_data(hw);
  1221. +
  1222. + mwl_fwcmd_radio_disable(hw);
  1223. + mwl_fwcmd_rf_antenna(hw, WL_ANTENNATYPE_TX, priv->antenna_tx);
  1224. + mwl_fwcmd_rf_antenna(hw, WL_ANTENNATYPE_RX, priv->antenna_rx);
  1225. +
  1226. + hw->wiphy->interface_modes = 0;
  1227. + hw->wiphy->interface_modes |= BIT(NL80211_IFTYPE_AP);
  1228. +#if defined(CPTCFG_MAC80211_MESH) || defined(CONFIG_MAC80211_MESH)
  1229. + hw->wiphy->interface_modes |= BIT(NL80211_IFTYPE_MESH_POINT);
  1230. +#endif
  1231. + hw->wiphy->interface_modes |= BIT(NL80211_IFTYPE_STATION);
  1232. + hw->wiphy->iface_combinations = &ap_if_comb;
  1233. + hw->wiphy->n_iface_combinations = 1;
  1234. +
  1235. + mwl_set_caps(priv);
  1236. +
  1237. + priv->led_blink_enable = 1;
  1238. + priv->led_blink_rate = LED_BLINK_RATE_MID;
  1239. + mwl_fwcmd_led_ctrl(hw, priv->led_blink_enable, priv->led_blink_rate);
  1240. +
  1241. + vendor_cmd_register(hw->wiphy);
  1242. +
  1243. + rc = ieee80211_register_hw(hw);
  1244. + if (rc) {
  1245. + wiphy_err(hw->wiphy, "fail to register device\n");
  1246. + goto err_register_hw;
  1247. + }
  1248. +
  1249. + priv->irq = mwl_hif_get_irq_num(hw);
  1250. + rc = request_irq(priv->irq, mwl_isr, IRQF_SHARED,
  1251. + mwl_hif_get_driver_name(hw), hw);
  1252. + if (rc) {
  1253. + priv->irq = -1;
  1254. + wiphy_err(hw->wiphy, "fail to register IRQ handler\n");
  1255. + goto err_register_irq;
  1256. + }
  1257. +#ifdef timer_setup
  1258. + timer_setup(&priv->period_timer, timer_routine, 0);
  1259. +#else
  1260. + setup_timer(&priv->period_timer, timer_routine, (unsigned long)hw);
  1261. +#endif
  1262. + mod_timer(&priv->period_timer, jiffies +
  1263. + msecs_to_jiffies(SYSADPT_TIMER_WAKEUP_TIME));
  1264. +
  1265. + return rc;
  1266. +
  1267. +err_register_hw:
  1268. +err_register_irq:
  1269. + mwl_hif_deinit(hw);
  1270. +
  1271. +err_hif_init:
  1272. +err_thermal_register:
  1273. +
  1274. + wiphy_err(hw->wiphy, "init fail\n");
  1275. +
  1276. + return rc;
  1277. +}
  1278. +
  1279. +static void mwl_wl_deinit(struct mwl_priv *priv)
  1280. +{
  1281. + struct ieee80211_hw *hw = priv->hw;
  1282. +
  1283. + del_timer_sync(&priv->period_timer);
  1284. +
  1285. + if (priv->irq != -1) {
  1286. + free_irq(priv->irq, hw);
  1287. + priv->irq = -1;
  1288. + }
  1289. +
  1290. + if (priv->chip_type == MWL8964)
  1291. + kfree(hw->wiphy->addresses);
  1292. + ieee80211_unregister_hw(hw);
  1293. + mwl_thermal_unregister(priv);
  1294. + cancel_work_sync(&priv->chnl_switch_handle);
  1295. + cancel_work_sync(&priv->account_handle);
  1296. + cancel_work_sync(&priv->wds_check_handle);
  1297. + cancel_work_sync(&priv->watchdog_ba_handle);
  1298. + cancel_work_sync(&priv->heartbeat_handle);
  1299. + mwl_hif_deinit(hw);
  1300. +}
  1301. +
  1302. +struct ieee80211_hw *mwl_alloc_hw(int bus_type,
  1303. + int chip_type,
  1304. + struct device *dev,
  1305. + const struct mwl_hif_ops *ops,
  1306. + size_t hif_data_len)
  1307. +{
  1308. + struct ieee80211_hw *hw;
  1309. + struct mwl_priv *priv;
  1310. + int priv_size;
  1311. +
  1312. + priv_size = ALIGN(sizeof(*priv), NETDEV_ALIGN) + hif_data_len;
  1313. +
  1314. + hw = ieee80211_alloc_hw(priv_size, &mwl_mac80211_ops);
  1315. + if (!hw) {
  1316. + pr_err("ieee80211 alloc hw failed\n");
  1317. + return NULL;
  1318. + }
  1319. +
  1320. + priv = hw->priv;
  1321. + priv->hw = hw;
  1322. + priv->dev = dev;
  1323. + priv->chip_type = chip_type;
  1324. + priv->fw_device_pwrtbl = false;
  1325. + priv->forbidden_setting = false;
  1326. + priv->regulatory_set = false;
  1327. + priv->use_short_slot = false;
  1328. + priv->use_short_preamble = false;
  1329. + priv->disable_2g = false;
  1330. + priv->disable_5g = false;
  1331. + priv->tx_amsdu = true;
  1332. + priv->hif.bus = bus_type;
  1333. + priv->hif.ops = ops;
  1334. + priv->hif.priv = (char *)priv + ALIGN(sizeof(*priv), NETDEV_ALIGN);
  1335. + priv->ampdu_num = mwl_hif_get_ampdu_num(hw);
  1336. + priv->ampdu =
  1337. + kzalloc(priv->ampdu_num * sizeof(*priv->ampdu), GFP_KERNEL);
  1338. + if (!priv->ampdu) {
  1339. + ieee80211_free_hw(hw);
  1340. + pr_err("alloc ampdu stream failed\n");
  1341. + return NULL;
  1342. + }
  1343. +
  1344. + if (chip_type == MWL8964)
  1345. + priv->stnid_num = SYSADPT_MAX_STA_SC4;
  1346. + else
  1347. + priv->stnid_num = SYSADPT_MAX_STA;
  1348. + priv->stnid =
  1349. + kzalloc(priv->stnid_num * sizeof(struct mwl_stnid), GFP_KERNEL);
  1350. + if (!priv->stnid) {
  1351. + kfree(priv->ampdu);
  1352. + ieee80211_free_hw(hw);
  1353. + pr_err("alloc stnid failed\n");
  1354. + return NULL;
  1355. + }
  1356. + priv->available_stnid = 0;
  1357. +
  1358. + SET_IEEE80211_DEV(hw, dev);
  1359. +
  1360. + return hw;
  1361. +}
  1362. +
  1363. +void mwl_free_hw(struct ieee80211_hw *hw)
  1364. +{
  1365. + struct mwl_priv *priv = hw->priv;
  1366. +
  1367. + kfree(priv->stnid);
  1368. + kfree(priv->ampdu);
  1369. + ieee80211_free_hw(hw);
  1370. +}
  1371. +
  1372. +int mwl_init_hw(struct ieee80211_hw *hw, const char *fw_name,
  1373. + const char *cal_name, const char *txpwrlmt_name)
  1374. +{
  1375. + struct mwl_priv *priv = hw->priv;
  1376. + int rc;
  1377. + int tx_num = 4, rx_num = 4;
  1378. +
  1379. +
  1380. + rc = mwl_prepare_cmd_buf(priv);
  1381. + if (rc) {
  1382. + wiphy_err(hw->wiphy, "fail to prepare command buffer\n");
  1383. + return -ENOMEM;
  1384. + }
  1385. +
  1386. + rc = mwl_init_firmware(priv, fw_name, cal_name, txpwrlmt_name);
  1387. + if (rc) {
  1388. + wiphy_err(hw->wiphy, "fail to initialize firmware\n");
  1389. + return -EIO;
  1390. + }
  1391. +
  1392. + /* firmware is loaded to H/W, it can be released now */
  1393. + release_firmware(priv->fw_ucode);
  1394. +
  1395. + mwl_process_of_dts(priv);
  1396. +
  1397. + rc = mwl_wl_init(priv);
  1398. + if (rc) {
  1399. + wiphy_err(hw->wiphy, "fail to initialize wireless lan\n");
  1400. + return -EIO;
  1401. + }
  1402. +
  1403. + wiphy_info(priv->hw->wiphy, "2G %s, 5G %s\n",
  1404. + priv->disable_2g ? "disabled" : "enabled",
  1405. + priv->disable_5g ? "disabled" : "enabled");
  1406. +
  1407. + if (priv->antenna_tx == ANTENNA_TX_2)
  1408. + tx_num = 2;
  1409. + else if (priv->antenna_tx == ANTENNA_TX_3)
  1410. + tx_num = 3;
  1411. + if (priv->antenna_rx == ANTENNA_RX_2)
  1412. + rx_num = 2;
  1413. + else if (priv->antenna_rx == ANTENNA_RX_3)
  1414. + rx_num = 3;
  1415. + wiphy_info(priv->hw->wiphy, "%d TX antennas, %d RX antennas\n",
  1416. + tx_num, rx_num);
  1417. +
  1418. +#ifdef CONFIG_DEBUG_FS
  1419. + mwl_debugfs_init(hw);
  1420. +#endif
  1421. +
  1422. + return 0;
  1423. +}
  1424. +
  1425. +void mwl_deinit_hw(struct ieee80211_hw *hw)
  1426. +{
  1427. +#ifdef CONFIG_DEBUG_FS
  1428. + mwl_debugfs_remove(hw);
  1429. +#endif
  1430. +
  1431. + mwl_wl_deinit(hw->priv);
  1432. +}
  1433. diff --git a/drivers/net/wireless/marvell/mwlwifi/core.h b/drivers/net/wireless/marvell/mwlwifi/core.h
  1434. new file mode 100644
  1435. index 000000000000..00069c4f0b44
  1436. --- /dev/null
  1437. +++ b/drivers/net/wireless/marvell/mwlwifi/core.h
  1438. @@ -0,0 +1,517 @@
  1439. +/*
  1440. + * Copyright (C) 2006-2018, Marvell International Ltd.
  1441. + *
  1442. + * This software file (the "File") is distributed by Marvell International
  1443. + * Ltd. under the terms of the GNU General Public License Version 2, June 1991
  1444. + * (the "License"). You may use, redistribute and/or modify this File in
  1445. + * accordance with the terms and conditions of the License, a copy of which
  1446. + * is available by writing to the Free Software Foundation, Inc.
  1447. + *
  1448. + * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
  1449. + * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
  1450. + * ARE EXPRESSLY DISCLAIMED. The License provides additional details about
  1451. + * this warranty disclaimer.
  1452. + */
  1453. +
  1454. +/* Description: This file defines core layer related functions. */
  1455. +
  1456. +#ifndef _CORE_H_
  1457. +#define _CORE_H_
  1458. +
  1459. +#include <linux/interrupt.h>
  1460. +#include <linux/firmware.h>
  1461. +#include <linux/of.h>
  1462. +#include <net/mac80211.h>
  1463. +
  1464. +#include "hif/hif.h"
  1465. +
  1466. +/* antenna control */
  1467. +#define ANTENNA_TX_4_AUTO 0
  1468. +#define ANTENNA_TX_1 1
  1469. +#define ANTENNA_TX_2 3
  1470. +#define ANTENNA_TX_3 7
  1471. +#define ANTENNA_RX_4_AUTO 0
  1472. +#define ANTENNA_RX_1 1
  1473. +#define ANTENNA_RX_2 2
  1474. +#define ANTENNA_RX_3 3
  1475. +#define ANTENNA_RX_MAX 4
  1476. +
  1477. +/* band related constants */
  1478. +#define BAND_24_CHANNEL_NUM 14
  1479. +#define BAND_24_RATE_NUM 13
  1480. +#define BAND_50_CHANNEL_NUM 24
  1481. +#define BAND_50_RATE_NUM 8
  1482. +
  1483. +#define NUM_WEP_KEYS 4
  1484. +#define MWL_MAX_TID 8
  1485. +#define MWL_AMSDU_SIZE_4K 1
  1486. +#define MWL_AMSDU_SIZE_8K 2
  1487. +#define MWL_AMSDU_SIZE_11K 3
  1488. +
  1489. +/* power init */
  1490. +#define MWL_POWER_INIT_1 1
  1491. +#define MWL_POWER_INIT_2 2
  1492. +
  1493. +/* tx rate information constants */
  1494. +#define TX_RATE_FORMAT_LEGACY 0
  1495. +#define TX_RATE_FORMAT_11N 1
  1496. +#define TX_RATE_FORMAT_11AC 2
  1497. +
  1498. +#define TX_RATE_BANDWIDTH_20 0
  1499. +#define TX_RATE_BANDWIDTH_40 1
  1500. +#define TX_RATE_BANDWIDTH_80 2
  1501. +#define TX_RATE_BANDWIDTH_160 3
  1502. +
  1503. +#define TX_RATE_INFO_STD_GI 0
  1504. +#define TX_RATE_INFO_SHORT_GI 1
  1505. +
  1506. +/* tx rate information */
  1507. +/* 0: legacy format 1: 11n format 2: 11ac format */
  1508. +#define MWL_TX_RATE_FORMAT_MASK 0x00000003
  1509. +#define MWL_TX_RATE_STBC_MASK 0x00000004
  1510. +#define MWL_TX_RATE_STBC_SHIFT 2
  1511. +/* 0: 20 MHz 1: 40 MHz 2: 80 MHz 3: 160 MHz */
  1512. +#define MWL_TX_RATE_BANDWIDTH_MASK 0x00000030
  1513. +#define MWL_TX_RATE_BANDWIDTH_SHIFT 4
  1514. +/* 0: normal 1: short */
  1515. +#define MWL_TX_RATE_SHORTGI_MASK 0x00000040
  1516. +#define MWL_TX_RATE_SHORTGI_SHIFT 6
  1517. +#define MWL_TX_RATE_RATEIDMCS_MASK 0x00007F00
  1518. +#define MWL_TX_RATE_RATEIDMCS_SHIFT 8
  1519. +/* 0: long 1: short */
  1520. +#define MWL_TX_RATE_PREAMBLE_MASK 0x00008000
  1521. +#define MWL_TX_RATE_PREAMBLE_SHIFT 15
  1522. +#define MWL_TX_RATE_POWERID_MASK 0x003F0000
  1523. +#define MWL_TX_RATE_POWERID_SHIFT 16
  1524. +#define MWL_TX_RATE_ADVCODING_MASK 0x00400000
  1525. +#define MWL_TX_RATE_ADVCODING_SHIFT 22
  1526. +/* 0: beam forming off 1: beam forming on */
  1527. +#define MWL_TX_RATE_BF_MASK 0x00800000
  1528. +#define MWL_TX_RATE_BF_SHIFT 23
  1529. +#define MWL_TX_RATE_ANTSELECT_MASK 0xFF000000
  1530. +#define MWL_TX_RATE_ANTSELECT_SHIFT 24
  1531. +
  1532. +#define ACNT_BA_SIZE 1000
  1533. +
  1534. +/* Q stats */
  1535. +#define QS_MAX_DATA_RATES_G 14
  1536. +#define QS_NUM_SUPPORTED_11N_BW 2
  1537. +#define QS_NUM_SUPPORTED_GI 2
  1538. +#define QS_NUM_SUPPORTED_MCS 24
  1539. +#define QS_NUM_SUPPORTED_11AC_NSS 3
  1540. +#define QS_NUM_SUPPORTED_11AC_BW 4
  1541. +#define QS_NUM_SUPPORTED_11AC_MCS 10
  1542. +#define TX_RATE_HISTO_CUSTOM_CNT 1
  1543. +#define TX_RATE_HISTO_PER_CNT 5
  1544. +#define MAX_DATA_RATES_G 14
  1545. +#define MAX_SUPPORTED_MCS 24
  1546. +#define MAX_SUPPORTED_11AC_RATES 20
  1547. +/* MAX_DATA_RATES_G + MAX_SUPPORTED_MCS + MAX_SUPPORTED_11AC_RATES */
  1548. +#define MAX_SUPPORTED_RATES 58
  1549. +#define SU_MIMO 0
  1550. +#define MU_MIMO 1
  1551. +#define SU_MU_TYPE_CNT 2 /* traffic type, SU and MU */
  1552. +
  1553. +/* BF operation mode */
  1554. +#define TXBF_MODE_OFF 0x05
  1555. +#define TXBF_MODE_AUTO 0x06
  1556. +#define TXBF_MODE_BFMER_AUTO 0x07
  1557. +
  1558. +static const u8 TX_HISTO_PER_THRES[TX_RATE_HISTO_PER_CNT - 1] = {6, 12, 20, 30};
  1559. +
  1560. +enum {
  1561. + MWL8864 = 0,
  1562. + MWL8897,
  1563. + MWL8964,
  1564. + MWL8997,
  1565. + MWLUNKNOWN,
  1566. +};
  1567. +
  1568. +enum mwl_bus {
  1569. + MWL_BUS_PCIE,
  1570. + MWL_BUS_SDIO,
  1571. +};
  1572. +
  1573. +enum {
  1574. + AP_MODE_11AC = 0x10, /* generic 11ac indication mode */
  1575. + AP_MODE_2_4GHZ_11AC_MIXED = 0x17,
  1576. +};
  1577. +
  1578. +enum {
  1579. + AMPDU_NO_STREAM = 0,
  1580. + AMPDU_STREAM_NEW,
  1581. + AMPDU_STREAM_IN_PROGRESS,
  1582. + AMPDU_STREAM_ACTIVE,
  1583. +};
  1584. +
  1585. +enum {
  1586. + LED_BLINK_RATE_LOW = 0x1,
  1587. + LED_BLINK_RATE_MID,
  1588. + LED_BLINK_RATE_HIGH,
  1589. +};
  1590. +
  1591. +struct mwl_chip_info {
  1592. + const char *part_name;
  1593. + const char *fw_image;
  1594. + const char *cal_file;
  1595. + const char *txpwrlmt_file;
  1596. + int antenna_tx;
  1597. + int antenna_rx;
  1598. +};
  1599. +
  1600. +struct mwl_device_pwr_tbl {
  1601. + u8 channel;
  1602. + u8 tx_pwr[SYSADPT_TX_PWR_LEVEL_TOTAL_SC4];
  1603. + u8 dfs_capable;
  1604. + u8 ax_ant;
  1605. + u8 cdd;
  1606. +};
  1607. +
  1608. +struct mwl_tx_pwr_tbl {
  1609. + u8 channel;
  1610. + u8 setcap;
  1611. + u16 txantenna2;
  1612. + u16 tx_power[SYSADPT_TX_POWER_LEVEL_TOTAL];
  1613. + bool cdd;
  1614. +};
  1615. +
  1616. +struct mwl_hw_data {
  1617. + u32 fw_release_num; /* MajNbr:MinNbr:SubMin:PatchLevel */
  1618. + u8 hw_version; /* plain number indicating version */
  1619. + unsigned char mac_addr[ETH_ALEN]; /* well known -> AA:BB:CC:DD:EE:FF */
  1620. +};
  1621. +
  1622. +struct mwl_ampdu_stream {
  1623. + struct ieee80211_sta *sta;
  1624. + u8 tid;
  1625. + u8 state;
  1626. + int idx;
  1627. +};
  1628. +
  1629. +struct mwl_stnid {
  1630. + int macid; /* keep macid for related stnid */
  1631. + u16 aid; /* keep aid for related stnid */
  1632. +};
  1633. +
  1634. +struct otp_data {
  1635. + u8 buf[SYSADPT_OTP_BUF_SIZE];
  1636. + u32 len; /* Actual size of data in buf[] */
  1637. +};
  1638. +
  1639. +struct txpwrlmt_cfg_data {
  1640. + u8 buf[SYSADPT_TXPWRLMT_CFG_BUF_SIZE];
  1641. + u32 len; /* Actual size of data in buf[] */
  1642. +};
  1643. +
  1644. +struct mwl_priv {
  1645. + struct ieee80211_hw *hw;
  1646. + struct device *dev;
  1647. + struct firmware *fw_ucode;
  1648. + struct firmware *cal_data;
  1649. + struct firmware *txpwrlmt_file;
  1650. + struct otp_data otp_data;
  1651. + struct txpwrlmt_cfg_data txpwrlmt_data;
  1652. + bool fw_device_pwrtbl;
  1653. + bool forbidden_setting;
  1654. + bool regulatory_set;
  1655. + u32 fw_region_code;
  1656. + char fw_alpha2[2];
  1657. + u8 number_of_channels;
  1658. + struct mwl_device_pwr_tbl device_pwr_tbl[SYSADPT_MAX_NUM_CHANNELS];
  1659. + int chip_type;
  1660. +
  1661. + bool use_short_slot;
  1662. + bool use_short_preamble;
  1663. +
  1664. + struct {
  1665. + enum mwl_bus bus;
  1666. + const struct mwl_hif_ops *ops;
  1667. + void *priv;
  1668. + } hif;
  1669. +
  1670. + struct device_node *dt_node;
  1671. + struct device_node *pwr_node;
  1672. + bool disable_2g;
  1673. + bool disable_5g;
  1674. + int antenna_tx;
  1675. + int antenna_rx;
  1676. + bool tx_amsdu;
  1677. + bool dump_hostcmd;
  1678. + bool dump_probe;
  1679. +
  1680. + struct mwl_tx_pwr_tbl tx_pwr_tbl[SYSADPT_MAX_NUM_CHANNELS];
  1681. + bool cdd;
  1682. + u16 txantenna2;
  1683. + u8 powinited;
  1684. + u8 pwr_level;
  1685. + u16 max_tx_pow[SYSADPT_TX_GRP_PWR_LEVEL_TOTAL]; /* max tx power (dBm) */
  1686. + u16 target_powers[SYSADPT_TX_GRP_PWR_LEVEL_TOTAL]; /* target powers */
  1687. +
  1688. + struct mutex fwcmd_mutex; /* for firmware command */
  1689. + unsigned short *pcmd_buf; /* pointer to CmdBuf (virtual) */
  1690. + dma_addr_t pphys_cmd_buf; /* pointer to CmdBuf (physical) */
  1691. + bool in_send_cmd;
  1692. + bool cmd_timeout;
  1693. + bool rmmod;
  1694. + int heartbeat;
  1695. + u32 pre_jiffies;
  1696. + bool heartbeating;
  1697. + struct work_struct heartbeat_handle;
  1698. +
  1699. + int irq;
  1700. + struct mwl_hw_data hw_data; /* Adapter HW specific info */
  1701. +
  1702. + struct timer_list period_timer;
  1703. +
  1704. + /* keep survey information */
  1705. + bool sw_scanning;
  1706. + int survey_info_idx;
  1707. + struct mwl_survey_info survey_info[SYSADPT_MAX_NUM_CHANNELS];
  1708. + struct mwl_survey_info cur_survey_info;
  1709. +
  1710. + s8 noise; /* Most recently reported noise in dBm */
  1711. +
  1712. + struct ieee80211_supported_band band_24;
  1713. + struct ieee80211_channel channels_24[BAND_24_CHANNEL_NUM];
  1714. + struct ieee80211_rate rates_24[BAND_24_RATE_NUM];
  1715. + struct ieee80211_supported_band band_50;
  1716. + struct ieee80211_channel channels_50[BAND_50_CHANNEL_NUM];
  1717. + struct ieee80211_rate rates_50[BAND_50_RATE_NUM];
  1718. +
  1719. + u32 ap_macids_supported;
  1720. + u32 sta_macids_supported;
  1721. + u32 macids_used;
  1722. + u32 running_bsses; /* bitmap of running BSSes */
  1723. +
  1724. + struct {
  1725. + spinlock_t vif_lock; /* for private interface info */
  1726. + struct list_head vif_list; /* List of interfaces. */
  1727. + } ____cacheline_aligned_in_smp;
  1728. +
  1729. + struct {
  1730. + spinlock_t sta_lock; /* for private sta info */
  1731. + struct list_head sta_list; /* List of stations */
  1732. + } ____cacheline_aligned_in_smp;
  1733. +
  1734. + /* ampdu stream information */
  1735. + /* for ampdu stream */
  1736. + int ampdu_num;
  1737. + struct {
  1738. + spinlock_t stream_lock; /* for BA stream */
  1739. + struct mwl_ampdu_stream *ampdu;
  1740. + } ____cacheline_aligned_in_smp;
  1741. + struct work_struct watchdog_ba_handle;
  1742. +
  1743. + /* station id */
  1744. + int stnid_num;
  1745. + struct {
  1746. + spinlock_t stnid_lock; /* for station id */
  1747. + struct mwl_stnid *stnid;
  1748. + u16 available_stnid;
  1749. + } ____cacheline_aligned_in_smp;
  1750. +
  1751. + bool radio_on;
  1752. + bool radio_short_preamble;
  1753. + bool wmm_enabled;
  1754. + struct ieee80211_tx_queue_params wmm_params[SYSADPT_TX_WMM_QUEUES];
  1755. +
  1756. + struct work_struct account_handle;
  1757. +
  1758. + bool wds_check;
  1759. + struct work_struct wds_check_handle;
  1760. + u8 wds_check_sta[ETH_ALEN];
  1761. +
  1762. + bool dfs_test;
  1763. + bool csa_active;
  1764. + struct work_struct chnl_switch_handle;
  1765. + enum nl80211_dfs_regions dfs_region;
  1766. + u16 dfs_chirp_count_min;
  1767. + u16 dfs_chirp_time_interval;
  1768. + u16 dfs_pw_filter;
  1769. + u16 dfs_min_num_radar;
  1770. + u16 dfs_min_pri_count;
  1771. +
  1772. + u8 bf_type;
  1773. +
  1774. + struct thermal_cooling_device *cdev;
  1775. + u32 throttle_state;
  1776. + u32 quiet_period;
  1777. + int temperature;
  1778. +
  1779. + u8 led_blink_enable;
  1780. + u8 led_blink_rate;
  1781. +
  1782. + struct dentry *debugfs_phy;
  1783. + u32 reg_type;
  1784. + u32 reg_offset;
  1785. + u32 reg_value;
  1786. + int ra_aid;
  1787. + int ba_aid;
  1788. + int fixed_rate;
  1789. + bool coredump_text;
  1790. + u32 ra_tx_attempt[2][6];
  1791. +};
  1792. +
  1793. +struct beacon_info {
  1794. + bool valid;
  1795. + u16 cap_info;
  1796. + u8 power_constraint;
  1797. + u8 b_rate_set[SYSADPT_MAX_DATA_RATES_G];
  1798. + u8 op_rate_set[SYSADPT_MAX_DATA_RATES_G];
  1799. + u8 ie_list_ht[148];
  1800. + u8 ie_list_vht[24];
  1801. + u8 *ie_wmm_ptr;
  1802. + u8 *ie_wsc_ptr;
  1803. + u8 *ie_rsn_ptr;
  1804. + u8 *ie_rsn48_ptr;
  1805. + u8 *ie_mde_ptr;
  1806. + u8 *ie_ht_ptr;
  1807. + u8 *ie_vht_ptr;
  1808. + u8 *ie_country_ptr;
  1809. + u8 *ie_meshid_ptr;
  1810. + u8 *ie_meshcfg_ptr;
  1811. + u8 *ie_meshchsw_ptr;
  1812. + u8 ie_wmm_len;
  1813. + u8 ie_wsc_len;
  1814. + u8 ie_rsn_len;
  1815. + u8 ie_rsn48_len;
  1816. + u8 ie_mde_len;
  1817. + u8 ie_ht_len;
  1818. + u8 ie_vht_len;
  1819. + u8 ie_country_len;
  1820. + u8 ie_meshid_len;
  1821. + u8 ie_meshcfg_len;
  1822. + u8 ie_meshchsw_len;
  1823. +};
  1824. +
  1825. +struct mwl_vif {
  1826. + struct list_head list;
  1827. + enum nl80211_iftype type;
  1828. + int macid; /* Firmware macid for this vif. */
  1829. + u16 seqno; /* Non AMPDU sequence number assigned by driver. */
  1830. + struct { /* Saved WEP keys */
  1831. + u8 enabled;
  1832. + u8 key[sizeof(struct ieee80211_key_conf) + WLAN_KEY_LEN_WEP104];
  1833. + } wep_key_conf[NUM_WEP_KEYS];
  1834. + u8 bssid[ETH_ALEN]; /* BSSID */
  1835. + u8 sta_mac[ETH_ALEN]; /* Station mac address */
  1836. + /* A flag to indicate is HW crypto is enabled for this bssid */
  1837. + bool is_hw_crypto_enabled;
  1838. + /* Indicate if this is station mode */
  1839. + struct beacon_info beacon_info;
  1840. + bool set_beacon;
  1841. + int basic_rate_idx;
  1842. + u8 broadcast_ssid;
  1843. + u16 iv16;
  1844. + u32 iv32;
  1845. + s8 keyidx;
  1846. +};
  1847. +
  1848. +struct mwl_tx_info {
  1849. + unsigned long start_time;
  1850. + u32 pkts;
  1851. +};
  1852. +
  1853. +struct mwl_amsdu_frag {
  1854. + struct sk_buff *skb;
  1855. + u8 *cur_pos;
  1856. + unsigned long jiffies;
  1857. + u8 pad;
  1858. + u8 num;
  1859. +};
  1860. +
  1861. +struct mwl_amsdu_ctrl {
  1862. + struct mwl_amsdu_frag frag[SYSADPT_TX_WMM_QUEUES];
  1863. + u8 cap;
  1864. +};
  1865. +
  1866. +struct mwl_tx_ba_stats {
  1867. + u8 ba_hole; /* Total pkt not acked in a BA bitmap */
  1868. + u8 ba_expected; /* Total Tx pkt expected to be acked */
  1869. + u8 no_ba; /* No BA is received */
  1870. + u8 pad; /* Unused */
  1871. +};
  1872. +
  1873. +struct mwl_tx_ba_hist {
  1874. + u16 index; /* Current buffer index */
  1875. + u8 type; /* 0:SU, 1: MU */
  1876. + bool enable;
  1877. + struct mwl_tx_ba_stats *ba_stats;
  1878. +};
  1879. +
  1880. +struct mwl_tx_hist_data {
  1881. + u32 rateinfo;
  1882. + u32 cnt;
  1883. + /* store according to TX_HISTO_PER_THRES threshold */
  1884. + u32 per[TX_RATE_HISTO_PER_CNT];
  1885. +};
  1886. +
  1887. +struct mwl_tx_hist {
  1888. + struct mwl_tx_hist_data su_rate[MAX_SUPPORTED_RATES];
  1889. + struct mwl_tx_hist_data mu_rate
  1890. + [QS_NUM_SUPPORTED_11AC_NSS - 1][QS_NUM_SUPPORTED_11AC_BW]
  1891. + [QS_NUM_SUPPORTED_GI][QS_NUM_SUPPORTED_11AC_MCS];
  1892. + struct mwl_tx_hist_data custom_rate[TX_RATE_HISTO_CUSTOM_CNT];
  1893. + /* Current rate for 0:SU, 1:MU */
  1894. + u32 cur_rate_info[SU_MU_TYPE_CNT];
  1895. + /* Total tx attempt cnt for 0:SU, 1:MU */
  1896. + u32 total_tx_cnt[SU_MU_TYPE_CNT];
  1897. +};
  1898. +
  1899. +struct mwl_sta {
  1900. + struct list_head list;
  1901. + struct mwl_vif *mwl_vif;
  1902. + u16 stnid;
  1903. + u16 sta_stnid;
  1904. + bool wds;
  1905. + bool is_mesh_node;
  1906. + bool is_ampdu_allowed;
  1907. + struct mwl_tx_info tx_stats[MWL_MAX_TID];
  1908. + u32 check_ba_failed[MWL_MAX_TID];
  1909. + struct mwl_tx_ba_hist ba_hist;
  1910. + bool is_amsdu_allowed;
  1911. + bool is_key_set;
  1912. + /* for amsdu aggregation */
  1913. + struct {
  1914. + spinlock_t amsdu_lock; /* for amsdu */
  1915. + struct mwl_amsdu_ctrl amsdu_ctrl;
  1916. + } ____cacheline_aligned_in_smp;
  1917. + struct mwl_tx_hist tx_hist;
  1918. + u32 tx_rate_info;
  1919. + u16 rx_format;
  1920. + u16 rx_nss;
  1921. + u16 rx_bw;
  1922. + u16 rx_gi;
  1923. + u16 rx_rate_mcs;
  1924. + u8 rx_signal;
  1925. + u16 iv16;
  1926. + u32 iv32;
  1927. +};
  1928. +
  1929. +static inline struct mwl_vif *mwl_dev_get_vif(const struct ieee80211_vif *vif)
  1930. +{
  1931. + return (struct mwl_vif *)&vif->drv_priv;
  1932. +}
  1933. +
  1934. +static inline struct mwl_sta *mwl_dev_get_sta(const struct ieee80211_sta *sta)
  1935. +{
  1936. + return (struct mwl_sta *)&sta->drv_priv;
  1937. +}
  1938. +
  1939. +struct ieee80211_hw *mwl_alloc_hw(int bus_type,
  1940. + int chip_type,
  1941. + struct device *dev,
  1942. + const struct mwl_hif_ops *ops,
  1943. + size_t hif_data_len);
  1944. +
  1945. +void mwl_free_hw(struct ieee80211_hw *hw);
  1946. +
  1947. +int mwl_init_hw(struct ieee80211_hw *hw, const char *fw_name,
  1948. + const char *cal_name, const char *txpwrlmt_name);
  1949. +
  1950. +void mwl_deinit_hw(struct ieee80211_hw *hw);
  1951. +
  1952. +/* Defined in mac80211.c. */
  1953. +extern const struct ieee80211_ops mwl_mac80211_ops;
  1954. +
  1955. +#endif /* _CORE_H_ */
  1956. diff --git a/drivers/net/wireless/marvell/mwlwifi/debugfs.c b/drivers/net/wireless/marvell/mwlwifi/debugfs.c
  1957. new file mode 100644
  1958. index 000000000000..e375806a7111
  1959. --- /dev/null
  1960. +++ b/drivers/net/wireless/marvell/mwlwifi/debugfs.c
  1961. @@ -0,0 +1,2201 @@
  1962. +/*
  1963. + * Copyright (C) 2006-2018, Marvell International Ltd.
  1964. + *
  1965. + * This software file (the "File") is distributed by Marvell International
  1966. + * Ltd. under the terms of the GNU General Public License Version 2, June 1991
  1967. + * (the "License"). You may use, redistribute and/or modify this File in
  1968. + * accordance with the terms and conditions of the License, a copy of which
  1969. + * is available by writing to the Free Software Foundation, Inc.
  1970. + *
  1971. + * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
  1972. + * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
  1973. + * ARE EXPRESSLY DISCLAIMED. The License provides additional details about
  1974. + * this warranty disclaimer.
  1975. + */
  1976. +
  1977. +/* Description: This file implements debug fs related functions. */
  1978. +
  1979. +#include <linux/debugfs.h>
  1980. +#include <linux/etherdevice.h>
  1981. +
  1982. +#include "sysadpt.h"
  1983. +#include "core.h"
  1984. +#include "utils.h"
  1985. +#include "thermal.h"
  1986. +#include "hif/fwcmd.h"
  1987. +#include "hif/hif-ops.h"
  1988. +#include "debugfs.h"
  1989. +
  1990. +#define MWLWIFI_DEBUGFS_ADD_FILE(name) do { \
  1991. + if (!debugfs_create_file(#name, 0644, priv->debugfs_phy, \
  1992. + priv, &mwl_debugfs_##name##_fops)) \
  1993. + return; \
  1994. +} while (0)
  1995. +
  1996. +#define MWLWIFI_DEBUGFS_FILE_OPS(name) \
  1997. +static const struct file_operations mwl_debugfs_##name##_fops = { \
  1998. + .read = mwl_debugfs_##name##_read, \
  1999. + .write = mwl_debugfs_##name##_write, \
  2000. + .open = simple_open, \
  2001. +}
  2002. +
  2003. +#define MWLWIFI_DEBUGFS_FILE_READ_OPS(name) \
  2004. +static const struct file_operations mwl_debugfs_##name##_fops = { \
  2005. + .read = mwl_debugfs_##name##_read, \
  2006. + .open = simple_open, \
  2007. +}
  2008. +
  2009. +#define MWLWIFI_DEBUGFS_FILE_WRITE_OPS(name) \
  2010. +static const struct file_operations mwl_debugfs_##name##_fops = { \
  2011. + .write = mwl_debugfs_##name##_write, \
  2012. + .open = simple_open, \
  2013. +}
  2014. +
  2015. +static const char chipname[MWLUNKNOWN][8] = {
  2016. + "88W8864",
  2017. + "88W8897",
  2018. + "88W8964",
  2019. + "88W8997"
  2020. +};
  2021. +
  2022. +static void dump_data(char *p, int size, int *len, u8 *data,
  2023. + int data_len, char *title)
  2024. +{
  2025. + int cur_byte = 0;
  2026. + int i;
  2027. +
  2028. + *len += scnprintf(p + *len, size - *len, "%s\n", title);
  2029. +
  2030. + for (cur_byte = 0; cur_byte < data_len; cur_byte += 8) {
  2031. + if ((cur_byte + 8) < data_len) {
  2032. + for (i = 0; i < 8; i++)
  2033. + *len += scnprintf(p + *len, size - *len,
  2034. + "0x%02x ",
  2035. + *(data + cur_byte + i));
  2036. + *len += scnprintf(p + *len, size - *len, "\n");
  2037. + } else {
  2038. + for (i = 0; i < (data_len - cur_byte); i++)
  2039. + *len += scnprintf(p + *len, size - *len,
  2040. + "0x%02x ",
  2041. + *(data + cur_byte + i));
  2042. + *len += scnprintf(p + *len, size - *len, "\n");
  2043. + break;
  2044. + }
  2045. + }
  2046. +}
  2047. +
  2048. +static void _dump_tx_hist_mu(char *p, int size, int *len, bool *printed,
  2049. + u32 *total, u8 nss, u8 bw, u8 mcs, u8 sgi,
  2050. + struct mwl_sta *sta_info)
  2051. +{
  2052. + char *bw_str[4] = {"ht20", "ht40", "ht80", "ht160"};
  2053. + char *sgi_str[2] = {"lgi", "sgi"};
  2054. + struct mwl_tx_hist_data *tx_hist_data;
  2055. + u32 cnt, rateinfo, per0, per1, per2, per3, per4, ratemask;
  2056. +
  2057. + tx_hist_data = &sta_info->tx_hist.mu_rate[nss][bw][sgi][mcs];
  2058. + cnt = le32_to_cpu(tx_hist_data->cnt);
  2059. + rateinfo = le32_to_cpu(tx_hist_data->rateinfo);
  2060. + if (cnt && (rateinfo > 0)) {
  2061. + *total += cnt;
  2062. + per4 = le32_to_cpu(tx_hist_data->per[4]);
  2063. + per3 = le32_to_cpu(tx_hist_data->per[3]);
  2064. + per2 = le32_to_cpu(tx_hist_data->per[2]);
  2065. + per1 = le32_to_cpu(tx_hist_data->per[1]);
  2066. + per0 = le32_to_cpu(tx_hist_data->per[0]);
  2067. + if (!*printed) {
  2068. + *len += scnprintf(p + *len, size - *len,
  2069. + "%s %26s <%2d %8s%2d%8s%2d%8s%2d%8s%2d\n",
  2070. + "MU_MIMO rate", " PER%", TX_HISTO_PER_THRES[0],
  2071. + ">=", TX_HISTO_PER_THRES[0],
  2072. + ">=", TX_HISTO_PER_THRES[1],
  2073. + ">=", TX_HISTO_PER_THRES[2],
  2074. + ">=", TX_HISTO_PER_THRES[3]);
  2075. + *len += scnprintf(p + *len, size - *len,
  2076. + "TOTAL MPDU tx pkt: %d\n",
  2077. + sta_info->tx_hist.total_tx_cnt[MU_MIMO]);
  2078. + *printed = true;
  2079. + }
  2080. + if ((rateinfo & 0x3) == 0)
  2081. + ratemask = 0xfff;
  2082. + else
  2083. + ratemask = 0xffff;
  2084. + if ((sta_info->tx_hist.cur_rate_info[MU_MIMO] & ratemask) ==
  2085. + (rateinfo & ratemask))
  2086. + /* mark as current rate */
  2087. + *len += scnprintf(p + *len, size - *len, "*");
  2088. + else
  2089. + *len += scnprintf(p + *len, size - *len, " ");
  2090. + *len += scnprintf(p + *len, size - *len,
  2091. + "%5s_%3s_%1dSS_MCS%2d: %10u, %9d, %9d, %9d, %9d, %9d\n",
  2092. + bw_str[bw], sgi_str[sgi], (nss + 1), mcs, cnt, per0,
  2093. + per1, per2, per3, per4);
  2094. + }
  2095. +}
  2096. +
  2097. +static void dump_tx_hist_mu(char *p, int size, int *len, bool *printed,
  2098. + u32 *total, struct mwl_sta *sta_info)
  2099. +{
  2100. + u8 nss, bw, mcs, sgi;
  2101. +
  2102. + for (nss = 0; nss < (QS_NUM_SUPPORTED_11AC_NSS - 1); nss++) {
  2103. + for (bw = 0; bw < QS_NUM_SUPPORTED_11AC_BW; bw++) {
  2104. + for (mcs = 0; mcs < QS_NUM_SUPPORTED_11AC_MCS; mcs++) {
  2105. + for (sgi = 0; sgi < QS_NUM_SUPPORTED_GI;
  2106. + sgi++) {
  2107. + _dump_tx_hist_mu(p, size, len, printed,
  2108. + total, nss, bw, mcs,
  2109. + sgi, sta_info);
  2110. + }
  2111. + }
  2112. + }
  2113. + }
  2114. +}
  2115. +
  2116. +
  2117. +static void dump_tx_hist_su(char *p, int size, int *len, bool su, bool *printed,
  2118. + u32 *total, struct mwl_sta *sta_info)
  2119. +{
  2120. + int g_rate[14] = {1, 2, 5, 11, 22, 6, 9, 12, 18, 24, 36, 48, 54, 72};
  2121. + char *bw_str[4] = {"ht20", "ht40", "ht80", "ht160"};
  2122. + char *sgi_str[2] = {"lgi", "sgi"};
  2123. + char title_str[32];
  2124. + struct mwl_tx_hist *tx_hist;
  2125. + struct mwl_tx_hist_data *tx_hist_data;
  2126. + u32 j, loopcnt;
  2127. + u32 cnt, rateinfo, per0, per1, per2, per3, per4, ratemask;
  2128. + u8 format, bw, sgi, mcs, nss;
  2129. +
  2130. + tx_hist = &sta_info->tx_hist;
  2131. + if (su) {
  2132. + loopcnt = MAX_SUPPORTED_RATES;
  2133. + tx_hist_data = &tx_hist->su_rate[0];
  2134. + } else {
  2135. + loopcnt = TX_RATE_HISTO_CUSTOM_CNT;
  2136. + tx_hist_data = &tx_hist->custom_rate[0];
  2137. + }
  2138. +
  2139. + for (j = 0; j < loopcnt; j++) {
  2140. + cnt = le32_to_cpu(tx_hist_data[j].cnt);
  2141. + rateinfo = le32_to_cpu(tx_hist_data[j].rateinfo);
  2142. + if (cnt && (rateinfo > 0)) {
  2143. + *total += cnt;
  2144. + per4 = le32_to_cpu(tx_hist_data[j].per[4]);
  2145. + per3 = le32_to_cpu(tx_hist_data[j].per[3]);
  2146. + per2 = le32_to_cpu(tx_hist_data[j].per[2]);
  2147. + per1 = le32_to_cpu(tx_hist_data[j].per[1]);
  2148. + per0 = le32_to_cpu(tx_hist_data[j].per[0]);
  2149. + if (!*printed) {
  2150. + *len += scnprintf(p + *len, size - *len,
  2151. + "%s %26s <%2d %8s%2d%8s%2d%8s%2d%8s%2d\n",
  2152. + su ? "SU_MIMO rate" : " Custom rate",
  2153. + " PER%", TX_HISTO_PER_THRES[0],
  2154. + ">=", TX_HISTO_PER_THRES[0],
  2155. + ">=", TX_HISTO_PER_THRES[1],
  2156. + ">=", TX_HISTO_PER_THRES[2],
  2157. + ">=", TX_HISTO_PER_THRES[3]);
  2158. + *len += scnprintf(p + *len, size - *len,
  2159. + "TOTAL MPDU tx pkt: %d\n",
  2160. + tx_hist->total_tx_cnt[SU_MIMO]);
  2161. + *printed = true;
  2162. + }
  2163. + format = rateinfo & MWL_TX_RATE_FORMAT_MASK;
  2164. + bw = (rateinfo & MWL_TX_RATE_BANDWIDTH_MASK) >>
  2165. + MWL_TX_RATE_BANDWIDTH_SHIFT;
  2166. + sgi = (rateinfo & MWL_TX_RATE_SHORTGI_MASK) >>
  2167. + MWL_TX_RATE_SHORTGI_SHIFT;
  2168. + mcs = (rateinfo & MWL_TX_RATE_RATEIDMCS_MASK) >>
  2169. + MWL_TX_RATE_RATEIDMCS_SHIFT;
  2170. + if (format == TX_RATE_FORMAT_LEGACY)
  2171. + ratemask = 0xfff;
  2172. + else
  2173. + ratemask = 0xffff;
  2174. + if ((tx_hist->cur_rate_info[SU_MIMO] & ratemask) ==
  2175. + (rateinfo & ratemask))
  2176. + /* mark as current rate */
  2177. + *len += scnprintf(p + *len, size - *len, "*");
  2178. + else
  2179. + *len += scnprintf(p + *len, size - *len, " ");
  2180. + if (format == TX_RATE_FORMAT_LEGACY) {
  2181. + if (mcs == 2) {
  2182. + *len += scnprintf(p + *len, size - *len,
  2183. + "%s %10u, %9d, %9d, %9d, %9d, %9d\n",
  2184. + "5.5Mbps :", cnt, per0,
  2185. + per1, per2, per3, per4);
  2186. + } else {
  2187. + sprintf(title_str,
  2188. + "%-3dMbps :",
  2189. + g_rate[mcs]);
  2190. + *len += scnprintf(p + *len, size - *len,
  2191. + "%s %10u, %9d, %9d, %9d, %9d, %9d\n",
  2192. + title_str, cnt, per0, per1, per2, per3,
  2193. + per4);
  2194. + }
  2195. + } else if (format == TX_RATE_FORMAT_11N) {
  2196. + sprintf(title_str, "%4s_%3s_MCS%2d :",
  2197. + bw_str[bw], sgi_str[sgi], mcs);
  2198. + *len += scnprintf(p + *len, size - *len,
  2199. + "%s %10u, %9d, %9d, %9d, %9d, %9d\n",
  2200. + title_str, cnt, per0, per1, per2, per3,
  2201. + per4);
  2202. + } else {
  2203. + nss = (mcs >> 4);
  2204. + sprintf(title_str, "%5s_%3s_%1dSS_MCS%2d :",
  2205. + bw_str[bw], sgi_str[sgi], (nss+1),
  2206. + (mcs & 0xf));
  2207. + *len += scnprintf(p + *len, size - *len,
  2208. + "%s %10u, %9d, %9d, %9d, %9d, %9d\n",
  2209. + title_str, cnt, per0, per1, per2, per3,
  2210. + per4);
  2211. + }
  2212. + }
  2213. + }
  2214. +}
  2215. +
  2216. +static void dump_tx_hist(char *p, int size, int *len, struct mwl_sta *sta_info)
  2217. +{
  2218. + int type;
  2219. + bool printed, su;
  2220. + u32 total;
  2221. +
  2222. + for (type = 0; type <= SU_MU_TYPE_CNT; type++) {
  2223. + printed = false;
  2224. + total = 0;
  2225. + if (type == MU_MIMO) {
  2226. + dump_tx_hist_mu(p, size, len, &printed,
  2227. + &total, sta_info);
  2228. + } else {
  2229. + su = (type == SU_MIMO) ? true : false;
  2230. + dump_tx_hist_su(p, size, len, su, &printed,
  2231. + &total, sta_info);
  2232. + }
  2233. + if (printed)
  2234. + *len += scnprintf(p + *len, size - *len,
  2235. + " TOTAL : %10u\n\n",
  2236. + total);
  2237. + }
  2238. +}
  2239. +
  2240. +static void core_dump_file(u8 *valbuf, u32 length, u32 region, u32 address,
  2241. + u32 append, u32 totallen, bool textmode)
  2242. +{
  2243. + struct file *filp_core = NULL;
  2244. + char file_name[40];
  2245. + u8 *buf = kmalloc(length * 3, GFP_KERNEL);
  2246. + u8 *data_p = buf;
  2247. + u32 i, j = 0;
  2248. +
  2249. + if (!buf)
  2250. + return;
  2251. +
  2252. + memset(file_name, 0, sizeof(file_name));
  2253. + sprintf(file_name, "/dev/shm/coredump-%x-%x",
  2254. + region, (region + totallen));
  2255. +
  2256. + if (append)
  2257. + filp_core = filp_open(file_name, O_RDWR | O_APPEND, 0);
  2258. + else
  2259. + filp_core = filp_open(file_name, O_RDWR | O_CREAT | O_TRUNC, 0);
  2260. +
  2261. + if (!IS_ERR(filp_core)) {
  2262. + if (textmode) {
  2263. + for (i = 0; i < length; i += 4) {
  2264. + u32 val = 0;
  2265. +
  2266. + val = le32_to_cpu(*(__le32 *)(&valbuf[i]));
  2267. +
  2268. + if (i % 16 == 0) {
  2269. + sprintf(buf + j, "\n0x%08x",
  2270. + (int)(address + i));
  2271. + j = strlen(buf);
  2272. + }
  2273. + sprintf(buf + j, " %08x", val);
  2274. + j = strlen(buf);
  2275. + }
  2276. + data_p = buf + j;
  2277. + data_p += sprintf(data_p, "\n");
  2278. + __kernel_write(filp_core, buf, strlen(buf),
  2279. + &filp_core->f_pos);
  2280. + } else
  2281. + __kernel_write(filp_core, valbuf, length,
  2282. + &filp_core->f_pos);
  2283. +
  2284. + filp_close(filp_core, current->files);
  2285. + }
  2286. +
  2287. + kfree(buf);
  2288. +}
  2289. +
  2290. +static ssize_t mwl_debugfs_info_read(struct file *file, char __user *ubuf,
  2291. + size_t count, loff_t *ppos)
  2292. +{
  2293. + struct mwl_priv *priv = (struct mwl_priv *)file->private_data;
  2294. + unsigned long page = get_zeroed_page(GFP_KERNEL);
  2295. + int tx_num = 4, rx_num = 4;
  2296. + char *p = (char *)page;
  2297. + int len = 0, size = PAGE_SIZE;
  2298. + ssize_t ret;
  2299. +
  2300. + if (!p)
  2301. + return -ENOMEM;
  2302. +
  2303. + len += scnprintf(p + len, size - len, "\n");
  2304. + len += scnprintf(p + len, size - len,
  2305. + "driver name: %s\n",
  2306. + mwl_hif_get_driver_name(priv->hw));
  2307. + len += scnprintf(p + len, size - len, "chip type: %s\n",
  2308. + chipname[priv->chip_type]);
  2309. + len += scnprintf(p + len, size - len,
  2310. + "hw version: %X\n", priv->hw_data.hw_version);
  2311. + len += scnprintf(p + len, size - len,
  2312. + "driver version: %s\n",
  2313. + mwl_hif_get_driver_version(priv->hw));
  2314. + len += scnprintf(p + len, size - len, "firmware version: 0x%08x\n",
  2315. + priv->hw_data.fw_release_num);
  2316. + len += scnprintf(p + len, size - len,
  2317. + "power table loaded from dts: %s\n",
  2318. + priv->forbidden_setting ? "no" : "yes");
  2319. + len += scnprintf(p + len, size - len, "firmware region code: 0x%x\n",
  2320. + priv->fw_region_code);
  2321. + len += scnprintf(p + len, size - len,
  2322. + "mac address: %pM\n", priv->hw_data.mac_addr);
  2323. + len += scnprintf(p + len, size - len,
  2324. + "2g: %s\n", priv->disable_2g ? "disable" : "enable");
  2325. + len += scnprintf(p + len, size - len,
  2326. + "5g: %s\n", priv->disable_5g ? "disable" : "enable");
  2327. + if (priv->antenna_tx == ANTENNA_TX_2)
  2328. + tx_num = 2;
  2329. + else if (priv->antenna_tx == ANTENNA_TX_3)
  2330. + tx_num = 3;
  2331. + if (priv->antenna_rx == ANTENNA_RX_2)
  2332. + rx_num = 2;
  2333. + else if (priv->antenna_rx == ANTENNA_RX_3)
  2334. + rx_num = 3;
  2335. + len += scnprintf(p + len, size - len, "antenna: %d %d\n",
  2336. + tx_num, rx_num);
  2337. + len += scnprintf(p + len, size - len, "irq number: %d\n", priv->irq);
  2338. + len += scnprintf(p + len, size - len, "ap macid support: %08x\n",
  2339. + priv->ap_macids_supported);
  2340. + len += scnprintf(p + len, size - len, "sta macid support: %08x\n",
  2341. + priv->sta_macids_supported);
  2342. + len += scnprintf(p + len, size - len,
  2343. + "macid used: %08x\n", priv->macids_used);
  2344. + len += scnprintf(p + len, size - len,
  2345. + "radio: %s\n", priv->radio_on ? "enable" : "disable");
  2346. + len += mwl_hif_get_info(priv->hw, p + len, size - len);
  2347. + len += scnprintf(p + len, size - len, "\n");
  2348. +
  2349. + ret = simple_read_from_buffer(ubuf, count, ppos, p, len);
  2350. + free_page(page);
  2351. +
  2352. + return ret;
  2353. +}
  2354. +
  2355. +static ssize_t mwl_debugfs_tx_status_read(struct file *file, char __user *ubuf,
  2356. + size_t count, loff_t *ppos)
  2357. +{
  2358. + struct mwl_priv *priv = (struct mwl_priv *)file->private_data;
  2359. + unsigned long page = get_zeroed_page(GFP_KERNEL);
  2360. + char *p = (char *)page;
  2361. + int len = 0, size = PAGE_SIZE;
  2362. + ssize_t ret;
  2363. +
  2364. + if (!p)
  2365. + return -ENOMEM;
  2366. +
  2367. + len += scnprintf(p + len, size - len, "\n");
  2368. + len += mwl_hif_get_tx_status(priv->hw, p + len, size - len);
  2369. + len += scnprintf(p + len, size - len, "\n");
  2370. +
  2371. + ret = simple_read_from_buffer(ubuf, count, ppos, p, len);
  2372. + free_page(page);
  2373. +
  2374. + return ret;
  2375. +}
  2376. +
  2377. +static ssize_t mwl_debugfs_rx_status_read(struct file *file, char __user *ubuf,
  2378. + size_t count, loff_t *ppos)
  2379. +{
  2380. + struct mwl_priv *priv = (struct mwl_priv *)file->private_data;
  2381. + unsigned long page = get_zeroed_page(GFP_KERNEL);
  2382. + char *p = (char *)page;
  2383. + int len = 0, size = PAGE_SIZE;
  2384. + ssize_t ret;
  2385. +
  2386. + if (!p)
  2387. + return -ENOMEM;
  2388. +
  2389. + len += scnprintf(p + len, size - len, "\n");
  2390. + len += mwl_hif_get_rx_status(priv->hw, p + len, size - len);
  2391. + len += scnprintf(p + len, size - len, "\n");
  2392. +
  2393. + ret = simple_read_from_buffer(ubuf, count, ppos, p, len);
  2394. + free_page(page);
  2395. +
  2396. + return ret;
  2397. +}
  2398. +
  2399. +static ssize_t mwl_debugfs_vif_read(struct file *file, char __user *ubuf,
  2400. + size_t count, loff_t *ppos)
  2401. +{
  2402. + struct mwl_priv *priv = (struct mwl_priv *)file->private_data;
  2403. + unsigned long page = get_zeroed_page(GFP_KERNEL);
  2404. + char *p = (char *)page;
  2405. + int len = 0, size = PAGE_SIZE;
  2406. + struct mwl_vif *mwl_vif;
  2407. + struct ieee80211_vif *vif;
  2408. + char ssid[IEEE80211_MAX_SSID_LEN + 1];
  2409. + struct cfg80211_chan_def *chan_def;
  2410. + struct beacon_info *beacon_info;
  2411. + ssize_t ret;
  2412. +
  2413. + if (!p)
  2414. + return -ENOMEM;
  2415. +
  2416. + len += scnprintf(p + len, size - len, "\n");
  2417. + spin_lock_bh(&priv->vif_lock);
  2418. + list_for_each_entry(mwl_vif, &priv->vif_list, list) {
  2419. + vif = container_of((void *)mwl_vif, struct ieee80211_vif,
  2420. + drv_priv);
  2421. + len += scnprintf(p + len, size - len,
  2422. + "macid: %d\n", mwl_vif->macid);
  2423. + switch (vif->type) {
  2424. + case NL80211_IFTYPE_AP:
  2425. + len += scnprintf(p + len, size - len, "type: ap\n");
  2426. + memcpy(ssid, vif->bss_conf.ssid,
  2427. + vif->bss_conf.ssid_len);
  2428. + ssid[vif->bss_conf.ssid_len] = 0;
  2429. + len += scnprintf(p + len, size - len,
  2430. + "ssid: %s\n", ssid);
  2431. + len += scnprintf(p + len, size - len,
  2432. + "mac address: %pM\n", mwl_vif->bssid);
  2433. + break;
  2434. + case NL80211_IFTYPE_MESH_POINT:
  2435. + len += scnprintf(p + len, size - len, "type: mesh\n");
  2436. + len += scnprintf(p + len, size - len,
  2437. + "mac address: %pM\n", mwl_vif->bssid);
  2438. + break;
  2439. + case NL80211_IFTYPE_STATION:
  2440. + len += scnprintf(p + len, size - len, "type: sta\n");
  2441. + len += scnprintf(p + len, size - len,
  2442. + "mac address: %pM\n",
  2443. + mwl_vif->sta_mac);
  2444. + break;
  2445. + default:
  2446. + len += scnprintf(p + len, size - len,
  2447. + "type: unknown\n");
  2448. + break;
  2449. + }
  2450. + if (vif->chanctx_conf) {
  2451. + chan_def = &vif->chanctx_conf->def;
  2452. + len += scnprintf(p + len, size - len,
  2453. + "channel: %d: width: %d\n",
  2454. + chan_def->chan->hw_value,
  2455. + chan_def->width);
  2456. + len += scnprintf(p + len, size - len,
  2457. + "freq: %d freq1: %d freq2: %d\n",
  2458. + chan_def->chan->center_freq,
  2459. + chan_def->center_freq1,
  2460. + chan_def->center_freq2);
  2461. + }
  2462. + len += scnprintf(p + len, size - len, "hw_crypto_enabled: %s\n",
  2463. + mwl_vif->is_hw_crypto_enabled ?
  2464. + "true" : "false");
  2465. + len += scnprintf(p + len, size - len,
  2466. + "key idx: %d\n", mwl_vif->keyidx);
  2467. + len += scnprintf(p + len, size - len,
  2468. + "IV: %08x%04x\n", mwl_vif->iv32,
  2469. + mwl_vif->iv16);
  2470. + beacon_info = &mwl_vif->beacon_info;
  2471. + dump_data(p, size, &len, beacon_info->ie_wmm_ptr,
  2472. + beacon_info->ie_wmm_len, "WMM:");
  2473. + dump_data(p, size, &len, beacon_info->ie_rsn_ptr,
  2474. + beacon_info->ie_rsn_len, "RSN:");
  2475. + dump_data(p, size, &len, beacon_info->ie_rsn48_ptr,
  2476. + beacon_info->ie_rsn48_len, "RSN48:");
  2477. + dump_data(p, size, &len, beacon_info->ie_mde_ptr,
  2478. + beacon_info->ie_mde_len, "MDE:");
  2479. + dump_data(p, size, &len, beacon_info->ie_ht_ptr,
  2480. + beacon_info->ie_ht_len, "HT:");
  2481. + dump_data(p, size, &len, beacon_info->ie_vht_ptr,
  2482. + beacon_info->ie_vht_len, "VHT:");
  2483. + if (vif->type == NL80211_IFTYPE_MESH_POINT) {
  2484. + dump_data(p, size, &len, beacon_info->ie_meshid_ptr,
  2485. + beacon_info->ie_meshid_len, "MESHID:");
  2486. + dump_data(p, size, &len, beacon_info->ie_meshcfg_ptr,
  2487. + beacon_info->ie_meshcfg_len, "MESHCFG:");
  2488. + dump_data(p, size, &len, beacon_info->ie_meshchsw_ptr,
  2489. + beacon_info->ie_meshchsw_len, "MESHCHSW:");
  2490. + }
  2491. + len += scnprintf(p + len, size - len, "\n");
  2492. + }
  2493. + spin_unlock_bh(&priv->vif_lock);
  2494. +
  2495. + ret = simple_read_from_buffer(ubuf, count, ppos, p, len);
  2496. + free_page(page);
  2497. +
  2498. + return ret;
  2499. +}
  2500. +
  2501. +static ssize_t mwl_debugfs_sta_read(struct file *file, char __user *ubuf,
  2502. + size_t count, loff_t *ppos)
  2503. +{
  2504. + struct mwl_priv *priv = (struct mwl_priv *)file->private_data;
  2505. + unsigned long page = get_zeroed_page(GFP_KERNEL);
  2506. + char *p = (char *)page;
  2507. + int len = 0, size = PAGE_SIZE;
  2508. + struct mwl_sta *sta_info;
  2509. + struct ieee80211_sta *sta;
  2510. + ssize_t ret;
  2511. +
  2512. + if (!p)
  2513. + return -ENOMEM;
  2514. +
  2515. + len += scnprintf(p + len, size - len, "\n");
  2516. + spin_lock_bh(&priv->sta_lock);
  2517. + list_for_each_entry(sta_info, &priv->sta_list, list) {
  2518. + sta = container_of((void *)sta_info, struct ieee80211_sta,
  2519. + drv_priv);
  2520. + len += scnprintf(p + len, size - len,
  2521. + "mac address: %pM\n", sta->addr);
  2522. + len += scnprintf(p + len, size - len, "aid: %u\n", sta->aid);
  2523. + len += scnprintf(p + len, size - len, "ampdu: %s\n",
  2524. + sta_info->is_ampdu_allowed ? "true" : "false");
  2525. + len += scnprintf(p + len, size - len, "amsdu: %s\n",
  2526. + sta_info->is_amsdu_allowed ? "true" : "false");
  2527. + len += scnprintf(p + len, size - len, "wds: %s\n",
  2528. + sta_info->wds ? "true" : "false");
  2529. + len += scnprintf(p + len, size - len, "ba_hist: %s\n",
  2530. + sta_info->ba_hist.enable ?
  2531. + "enable" : "disable");
  2532. + if (sta_info->is_amsdu_allowed) {
  2533. + len += scnprintf(p + len, size - len,
  2534. + "amsdu cap: 0x%02x\n",
  2535. + sta_info->amsdu_ctrl.cap);
  2536. + }
  2537. + if (sta->ht_cap.ht_supported) {
  2538. + len += scnprintf(p + len, size - len,
  2539. + "ht_cap: 0x%04x, ampdu: %02x, %02x\n",
  2540. + sta->ht_cap.cap,
  2541. + sta->ht_cap.ampdu_factor,
  2542. + sta->ht_cap.ampdu_density);
  2543. + len += scnprintf(p + len, size - len,
  2544. + "rx_mask: 0x%02x, %02x, %02x, %02x\n",
  2545. + sta->ht_cap.mcs.rx_mask[0],
  2546. + sta->ht_cap.mcs.rx_mask[1],
  2547. + sta->ht_cap.mcs.rx_mask[2],
  2548. + sta->ht_cap.mcs.rx_mask[3]);
  2549. + }
  2550. + if (sta->vht_cap.vht_supported) {
  2551. + len += scnprintf(p + len, size - len,
  2552. + "vht_cap: 0x%08x, mcs: %02x, %02x\n",
  2553. + sta->vht_cap.cap,
  2554. + sta->vht_cap.vht_mcs.rx_mcs_map,
  2555. + sta->vht_cap.vht_mcs.tx_mcs_map);
  2556. + }
  2557. + len += scnprintf(p + len, size - len, "rx_bw: %d, rx_nss: %d\n",
  2558. + sta->bandwidth, sta->rx_nss);
  2559. + len += scnprintf(p + len, size - len,
  2560. + "tdls: %d, tdls_init: %d\n",
  2561. + sta->tdls, sta->tdls_initiator);
  2562. + len += scnprintf(p + len, size - len, "wme: %d, mfp: %d\n",
  2563. + sta->wme, sta->mfp);
  2564. + len += scnprintf(p + len, size - len, "IV: %08x%04x\n",
  2565. + sta_info->iv32, sta_info->iv16);
  2566. + len += scnprintf(p + len, size - len, "\n");
  2567. + }
  2568. + spin_unlock_bh(&priv->sta_lock);
  2569. +
  2570. + ret = simple_read_from_buffer(ubuf, count, ppos, p, len);
  2571. + free_page(page);
  2572. +
  2573. + return ret;
  2574. +}
  2575. +
  2576. +static ssize_t mwl_debugfs_ampdu_read(struct file *file, char __user *ubuf,
  2577. + size_t count, loff_t *ppos)
  2578. +{
  2579. + struct mwl_priv *priv = (struct mwl_priv *)file->private_data;
  2580. + unsigned long page = get_zeroed_page(GFP_KERNEL);
  2581. + char *p = (char *)page;
  2582. + int len = 0, size = PAGE_SIZE;
  2583. + struct mwl_ampdu_stream *stream;
  2584. + int i;
  2585. + struct mwl_sta *sta_info;
  2586. + struct ieee80211_sta *sta;
  2587. + ssize_t ret;
  2588. +
  2589. + if (!p)
  2590. + return -ENOMEM;
  2591. +
  2592. + len += scnprintf(p + len, size - len, "\n");
  2593. + spin_lock_bh(&priv->stream_lock);
  2594. + for (i = 0; i < priv->ampdu_num; i++) {
  2595. + stream = &priv->ampdu[i];
  2596. + if (!stream->state)
  2597. + continue;
  2598. + len += scnprintf(p + len, size - len, "stream: %d\n", i);
  2599. + len += scnprintf(p + len, size - len, "idx: %u\n", stream->idx);
  2600. + len += scnprintf(p + len, size - len,
  2601. + "state: %u\n", stream->state);
  2602. + if (stream->sta) {
  2603. + len += scnprintf(p + len, size - len,
  2604. + "mac address: %pM\n",
  2605. + stream->sta->addr);
  2606. + len += scnprintf(p + len, size - len,
  2607. + "tid: %u\n", stream->tid);
  2608. + }
  2609. + }
  2610. + spin_unlock_bh(&priv->stream_lock);
  2611. + spin_lock_bh(&priv->sta_lock);
  2612. + list_for_each_entry(sta_info, &priv->sta_list, list) {
  2613. + for (i = 0; i < MWL_MAX_TID; i++) {
  2614. + if (sta_info->check_ba_failed[i]) {
  2615. + sta = container_of((void *)sta_info,
  2616. + struct ieee80211_sta,
  2617. + drv_priv);
  2618. + len += scnprintf(p + len, size - len,
  2619. + "%pM(%d): %d\n",
  2620. + sta->addr, i,
  2621. + sta_info->check_ba_failed[i]);
  2622. + }
  2623. + }
  2624. + }
  2625. + spin_unlock_bh(&priv->sta_lock);
  2626. + len += scnprintf(p + len, size - len, "\n");
  2627. +
  2628. + ret = simple_read_from_buffer(ubuf, count, ppos, p, len);
  2629. + free_page(page);
  2630. +
  2631. + return ret;
  2632. +}
  2633. +
  2634. +static ssize_t mwl_debugfs_stnid_read(struct file *file, char __user *ubuf,
  2635. + size_t count, loff_t *ppos)
  2636. +{
  2637. + struct mwl_priv *priv = (struct mwl_priv *)file->private_data;
  2638. + unsigned long page = get_zeroed_page(GFP_KERNEL);
  2639. + char *p = (char *)page;
  2640. + int len = 0, size = PAGE_SIZE;
  2641. + struct mwl_stnid *stnid;
  2642. + int i;
  2643. + ssize_t ret;
  2644. +
  2645. + if (!p)
  2646. + return -ENOMEM;
  2647. +
  2648. + len += scnprintf(p + len, size - len, "\n");
  2649. + spin_lock_bh(&priv->stnid_lock);
  2650. + for (i = 0; i < priv->stnid_num; i++) {
  2651. + stnid = &priv->stnid[i];
  2652. + if (!stnid->aid)
  2653. + continue;
  2654. + len += scnprintf(p + len, size - len,
  2655. + "stnid: %d macid: %d aid: %d\n",
  2656. + i + 1, stnid->macid, stnid->aid);
  2657. + }
  2658. + spin_unlock_bh(&priv->stnid_lock);
  2659. + len += scnprintf(p + len, size - len, "\n");
  2660. +
  2661. + ret = simple_read_from_buffer(ubuf, count, ppos, p, len);
  2662. + free_page(page);
  2663. +
  2664. + return ret;
  2665. +}
  2666. +
  2667. +static ssize_t mwl_debugfs_device_pwrtbl_read(struct file *file,
  2668. + char __user *ubuf,
  2669. + size_t count, loff_t *ppos)
  2670. +{
  2671. + struct mwl_priv *priv = (struct mwl_priv *)file->private_data;
  2672. + unsigned long page = get_zeroed_page(GFP_KERNEL);
  2673. + char *p = (char *)page;
  2674. + int len = 0, size = PAGE_SIZE;
  2675. + int i, j;
  2676. + ssize_t ret;
  2677. +
  2678. + if (!p)
  2679. + return -ENOMEM;
  2680. +
  2681. + len += scnprintf(p + len, size - len, "\n");
  2682. + len += scnprintf(p + len, size - len,
  2683. + "power table loaded from dts: %s\n",
  2684. + priv->forbidden_setting ? "no" : "yes");
  2685. + len += scnprintf(p + len, size - len, "firmware region code: 0x%x\n",
  2686. + priv->fw_region_code);
  2687. + len += scnprintf(p + len, size - len, "number of channel: %d\n",
  2688. + priv->number_of_channels);
  2689. + for (i = 0; i < priv->number_of_channels; i++) {
  2690. + len += scnprintf(p + len, size - len, "%3d ",
  2691. + priv->device_pwr_tbl[i].channel);
  2692. + for (j = 0; j < SYSADPT_TX_POWER_LEVEL_TOTAL; j++)
  2693. + len += scnprintf(p + len, size - len, "%3d ",
  2694. + priv->device_pwr_tbl[i].tx_pwr[j]);
  2695. + len += scnprintf(p + len, size - len, "%3d ",
  2696. + priv->device_pwr_tbl[i].dfs_capable);
  2697. + len += scnprintf(p + len, size - len, "%3d ",
  2698. + priv->device_pwr_tbl[i].ax_ant);
  2699. + len += scnprintf(p + len, size - len, "%3d\n",
  2700. + priv->device_pwr_tbl[i].cdd);
  2701. + }
  2702. + len += scnprintf(p + len, size - len, "\n");
  2703. +
  2704. + ret = simple_read_from_buffer(ubuf, count, ppos, p, len);
  2705. + free_page(page);
  2706. +
  2707. + return ret;
  2708. +}
  2709. +
  2710. +static ssize_t mwl_debugfs_txpwrlmt_read(struct file *file,
  2711. + char __user *ubuf,
  2712. + size_t count, loff_t *ppos)
  2713. +{
  2714. + struct mwl_priv *priv = (struct mwl_priv *)file->private_data;
  2715. +
  2716. + return simple_read_from_buffer(ubuf, count, ppos,
  2717. + priv->txpwrlmt_data.buf,
  2718. + priv->txpwrlmt_data.len);
  2719. +}
  2720. +
  2721. +static ssize_t mwl_debugfs_tx_amsdu_read(struct file *file,
  2722. + char __user *ubuf,
  2723. + size_t count, loff_t *ppos)
  2724. +{
  2725. + struct mwl_priv *priv = (struct mwl_priv *)file->private_data;
  2726. + unsigned long page = get_zeroed_page(GFP_KERNEL);
  2727. + char *p = (char *)page;
  2728. + int len = 0, size = PAGE_SIZE;
  2729. + ssize_t ret;
  2730. +
  2731. + if (!p)
  2732. + return -ENOMEM;
  2733. +
  2734. + len += scnprintf(p + len, size - len, "\n");
  2735. + len += scnprintf(p + len, size - len, "tx amsdu: %s\n",
  2736. + priv->tx_amsdu ? "enable" : "disable");
  2737. + len += scnprintf(p + len, size - len, "\n");
  2738. +
  2739. + ret = simple_read_from_buffer(ubuf, count, ppos, p, len);
  2740. + free_page(page);
  2741. +
  2742. + return ret;
  2743. +}
  2744. +
  2745. +static ssize_t mwl_debugfs_tx_amsdu_write(struct file *file,
  2746. + const char __user *ubuf,
  2747. + size_t count, loff_t *ppos)
  2748. +{
  2749. + struct mwl_priv *priv = (struct mwl_priv *)file->private_data;
  2750. + unsigned long addr = get_zeroed_page(GFP_KERNEL);
  2751. + char *buf = (char *)addr;
  2752. + size_t buf_size = min_t(size_t, count, PAGE_SIZE - 1);
  2753. + int value;
  2754. + ssize_t ret;
  2755. +
  2756. + if (!buf)
  2757. + return -ENOMEM;
  2758. +
  2759. + if (copy_from_user(buf, ubuf, buf_size)) {
  2760. + ret = -EFAULT;
  2761. + goto err;
  2762. + }
  2763. +
  2764. + if (kstrtoint(buf, 0, &value)) {
  2765. + ret = -EINVAL;
  2766. + goto err;
  2767. + }
  2768. +
  2769. + priv->tx_amsdu = value ? true : false;
  2770. +
  2771. + ret = count;
  2772. +
  2773. +err:
  2774. + free_page(addr);
  2775. + return ret;
  2776. +}
  2777. +
  2778. +static ssize_t mwl_debugfs_dump_hostcmd_read(struct file *file,
  2779. + char __user *ubuf,
  2780. + size_t count, loff_t *ppos)
  2781. +{
  2782. + struct mwl_priv *priv = (struct mwl_priv *)file->private_data;
  2783. + unsigned long page = get_zeroed_page(GFP_KERNEL);
  2784. + char *p = (char *)page;
  2785. + int len = 0, size = PAGE_SIZE;
  2786. + ssize_t ret;
  2787. +
  2788. + if (!p)
  2789. + return -ENOMEM;
  2790. +
  2791. + len += scnprintf(p + len, size - len, "\n");
  2792. + len += scnprintf(p + len, size - len, "dump_hostcmd: %s\n",
  2793. + priv->dump_hostcmd ? "enable" : "disable");
  2794. + len += scnprintf(p + len, size - len, "\n");
  2795. +
  2796. + ret = simple_read_from_buffer(ubuf, count, ppos, p, len);
  2797. + free_page(page);
  2798. +
  2799. + return ret;
  2800. +}
  2801. +
  2802. +static ssize_t mwl_debugfs_dump_hostcmd_write(struct file *file,
  2803. + const char __user *ubuf,
  2804. + size_t count, loff_t *ppos)
  2805. +{
  2806. + struct mwl_priv *priv = (struct mwl_priv *)file->private_data;
  2807. + unsigned long addr = get_zeroed_page(GFP_KERNEL);
  2808. + char *buf = (char *)addr;
  2809. + size_t buf_size = min_t(size_t, count, PAGE_SIZE - 1);
  2810. + int value;
  2811. + ssize_t ret;
  2812. +
  2813. + if (!buf)
  2814. + return -ENOMEM;
  2815. +
  2816. + if (copy_from_user(buf, ubuf, buf_size)) {
  2817. + ret = -EFAULT;
  2818. + goto err;
  2819. + }
  2820. +
  2821. + if (kstrtoint(buf, 0, &value)) {
  2822. + ret = -EINVAL;
  2823. + goto err;
  2824. + }
  2825. +
  2826. + priv->dump_hostcmd = value ? true : false;
  2827. +
  2828. + ret = count;
  2829. +
  2830. +err:
  2831. + free_page(addr);
  2832. + return ret;
  2833. +}
  2834. +
  2835. +static ssize_t mwl_debugfs_dump_probe_read(struct file *file,
  2836. + char __user *ubuf,
  2837. + size_t count, loff_t *ppos)
  2838. +{
  2839. + struct mwl_priv *priv = (struct mwl_priv *)file->private_data;
  2840. + unsigned long page = get_zeroed_page(GFP_KERNEL);
  2841. + char *p = (char *)page;
  2842. + int len = 0, size = PAGE_SIZE;
  2843. + ssize_t ret;
  2844. +
  2845. + if (!p)
  2846. + return -ENOMEM;
  2847. +
  2848. + len += scnprintf(p + len, size - len, "\n");
  2849. + len += scnprintf(p + len, size - len, "dump_probe: %s\n",
  2850. + priv->dump_probe ? "enable" : "disable");
  2851. + len += scnprintf(p + len, size - len, "\n");
  2852. +
  2853. + ret = simple_read_from_buffer(ubuf, count, ppos, p, len);
  2854. + free_page(page);
  2855. +
  2856. + return ret;
  2857. +}
  2858. +
  2859. +static ssize_t mwl_debugfs_dump_probe_write(struct file *file,
  2860. + const char __user *ubuf,
  2861. + size_t count, loff_t *ppos)
  2862. +{
  2863. + struct mwl_priv *priv = (struct mwl_priv *)file->private_data;
  2864. + unsigned long addr = get_zeroed_page(GFP_KERNEL);
  2865. + char *buf = (char *)addr;
  2866. + size_t buf_size = min_t(size_t, count, PAGE_SIZE - 1);
  2867. + int value;
  2868. + ssize_t ret;
  2869. +
  2870. + if (!buf)
  2871. + return -ENOMEM;
  2872. +
  2873. + if (copy_from_user(buf, ubuf, buf_size)) {
  2874. + ret = -EFAULT;
  2875. + goto err;
  2876. + }
  2877. +
  2878. + if (kstrtoint(buf, 0, &value)) {
  2879. + ret = -EINVAL;
  2880. + goto err;
  2881. + }
  2882. +
  2883. + priv->dump_probe = value ? true : false;
  2884. +
  2885. + ret = count;
  2886. +
  2887. +err:
  2888. + free_page(addr);
  2889. + return ret;
  2890. +}
  2891. +
  2892. +static ssize_t mwl_debugfs_heartbeat_read(struct file *file,
  2893. + char __user *ubuf,
  2894. + size_t count, loff_t *ppos)
  2895. +{
  2896. + struct mwl_priv *priv = (struct mwl_priv *)file->private_data;
  2897. + unsigned long page = get_zeroed_page(GFP_KERNEL);
  2898. + char *p = (char *)page;
  2899. + int len = 0, size = PAGE_SIZE;
  2900. + ssize_t ret;
  2901. +
  2902. + if (!p)
  2903. + return -ENOMEM;
  2904. +
  2905. + len += scnprintf(p + len, size - len, "\n");
  2906. + len += scnprintf(p + len, size - len, "heartbeat: %d\n",
  2907. + priv->heartbeat);
  2908. + len += scnprintf(p + len, size - len, "\n");
  2909. +
  2910. + ret = simple_read_from_buffer(ubuf, count, ppos, p, len);
  2911. + free_page(page);
  2912. +
  2913. + return ret;
  2914. +}
  2915. +
  2916. +static ssize_t mwl_debugfs_heartbeat_write(struct file *file,
  2917. + const char __user *ubuf,
  2918. + size_t count, loff_t *ppos)
  2919. +{
  2920. + struct mwl_priv *priv = (struct mwl_priv *)file->private_data;
  2921. + unsigned long addr = get_zeroed_page(GFP_KERNEL);
  2922. + char *buf = (char *)addr;
  2923. + size_t buf_size = min_t(size_t, count, PAGE_SIZE - 1);
  2924. + ssize_t ret;
  2925. +
  2926. + if (!buf)
  2927. + return -ENOMEM;
  2928. +
  2929. + if (copy_from_user(buf, ubuf, buf_size)) {
  2930. + ret = -EFAULT;
  2931. + goto err;
  2932. + }
  2933. +
  2934. + if (kstrtoint(buf, 0, &priv->heartbeat)) {
  2935. + ret = -EINVAL;
  2936. + goto err;
  2937. + }
  2938. + priv->pre_jiffies = jiffies;
  2939. +
  2940. + ret = count;
  2941. +
  2942. +err:
  2943. + free_page(addr);
  2944. + return ret;
  2945. +}
  2946. +
  2947. +static ssize_t mwl_debugfs_dfs_test_read(struct file *file,
  2948. + char __user *ubuf,
  2949. + size_t count, loff_t *ppos)
  2950. +{
  2951. + struct mwl_priv *priv = (struct mwl_priv *)file->private_data;
  2952. + unsigned long page = get_zeroed_page(GFP_KERNEL);
  2953. + char *p = (char *)page;
  2954. + int len = 0, size = PAGE_SIZE;
  2955. + ssize_t ret;
  2956. +
  2957. + if (!p)
  2958. + return -ENOMEM;
  2959. +
  2960. + len += scnprintf(p + len, size - len, "\n");
  2961. + len += scnprintf(p + len, size - len, "dfs_test: %s\n",
  2962. + priv->dfs_test ? "enable" : "disable");
  2963. + len += scnprintf(p + len, size - len, "\n");
  2964. +
  2965. + ret = simple_read_from_buffer(ubuf, count, ppos, p, len);
  2966. + free_page(page);
  2967. +
  2968. + return ret;
  2969. +}
  2970. +
  2971. +static ssize_t mwl_debugfs_dfs_test_write(struct file *file,
  2972. + const char __user *ubuf,
  2973. + size_t count, loff_t *ppos)
  2974. +{
  2975. + struct mwl_priv *priv = (struct mwl_priv *)file->private_data;
  2976. + unsigned long addr = get_zeroed_page(GFP_KERNEL);
  2977. + char *buf = (char *)addr;
  2978. + size_t buf_size = min_t(size_t, count, PAGE_SIZE - 1);
  2979. + int value;
  2980. + ssize_t ret;
  2981. +
  2982. + if (!buf)
  2983. + return -ENOMEM;
  2984. +
  2985. + if (copy_from_user(buf, ubuf, buf_size)) {
  2986. + ret = -EFAULT;
  2987. + goto err;
  2988. + }
  2989. +
  2990. + if (kstrtoint(buf, 0, &value)) {
  2991. + ret = -EINVAL;
  2992. + goto err;
  2993. + }
  2994. +
  2995. + priv->dfs_test = value ? true : false;
  2996. +
  2997. + ret = count;
  2998. +
  2999. +err:
  3000. + free_page(addr);
  3001. + return ret;
  3002. +}
  3003. +
  3004. +static ssize_t mwl_debugfs_dfs_channel_read(struct file *file,
  3005. + char __user *ubuf,
  3006. + size_t count, loff_t *ppos)
  3007. +{
  3008. + struct mwl_priv *priv = (struct mwl_priv *)file->private_data;
  3009. + unsigned long page = get_zeroed_page(GFP_KERNEL);
  3010. + char *p = (char *)page;
  3011. + int len = 0, size = PAGE_SIZE;
  3012. + struct ieee80211_supported_band *sband;
  3013. + struct ieee80211_channel *channel;
  3014. + int i;
  3015. + ssize_t ret;
  3016. +
  3017. + if (!p)
  3018. + return -ENOMEM;
  3019. +
  3020. + sband = priv->hw->wiphy->bands[NL80211_BAND_5GHZ];
  3021. + if (!sband) {
  3022. + ret = -EINVAL;
  3023. + goto err;
  3024. + }
  3025. +
  3026. + len += scnprintf(p + len, size - len, "\n");
  3027. + for (i = 0; i < sband->n_channels; i++) {
  3028. + channel = &sband->channels[i];
  3029. + if (channel->flags & IEEE80211_CHAN_RADAR) {
  3030. + len += scnprintf(p + len, size - len,
  3031. + "%d(%d): flags: %08x dfs_state: %d\n",
  3032. + channel->hw_value,
  3033. + channel->center_freq,
  3034. + channel->flags, channel->dfs_state);
  3035. + len += scnprintf(p + len, size - len,
  3036. + "cac timer: %d ms\n",
  3037. + channel->dfs_cac_ms);
  3038. + }
  3039. + }
  3040. + len += scnprintf(p + len, size - len, "\n");
  3041. +
  3042. + ret = simple_read_from_buffer(ubuf, count, ppos, p, len);
  3043. +
  3044. +err:
  3045. + free_page(page);
  3046. + return ret;
  3047. +}
  3048. +
  3049. +static ssize_t mwl_debugfs_dfs_channel_write(struct file *file,
  3050. + const char __user *ubuf,
  3051. + size_t count, loff_t *ppos)
  3052. +{
  3053. + struct mwl_priv *priv = (struct mwl_priv *)file->private_data;
  3054. + struct ieee80211_supported_band *sband;
  3055. + unsigned long addr = get_zeroed_page(GFP_KERNEL);
  3056. + char *buf = (char *)addr;
  3057. + size_t buf_size = min_t(size_t, count, PAGE_SIZE - 1);
  3058. + int dfs_state = 0;
  3059. + int cac_time = -1;
  3060. + struct ieee80211_channel *channel;
  3061. + int i;
  3062. + ssize_t ret;
  3063. +
  3064. + if (!buf)
  3065. + return -ENOMEM;
  3066. +
  3067. + sband = priv->hw->wiphy->bands[NL80211_BAND_5GHZ];
  3068. + if (!sband) {
  3069. + ret = -EINVAL;
  3070. + goto err;
  3071. + }
  3072. +
  3073. + if (copy_from_user(buf, ubuf, buf_size)) {
  3074. + ret = -EFAULT;
  3075. + goto err;
  3076. + }
  3077. +
  3078. + ret = sscanf(buf, "%d %d", &dfs_state, &cac_time);
  3079. +
  3080. + if ((ret < 1) || (ret > 2)) {
  3081. + ret = -EINVAL;
  3082. + goto err;
  3083. + }
  3084. +
  3085. + for (i = 0; i < sband->n_channels; i++) {
  3086. + channel = &sband->channels[i];
  3087. + if (channel->flags & IEEE80211_CHAN_RADAR) {
  3088. + channel->dfs_state = dfs_state;
  3089. + if (cac_time != -1)
  3090. + channel->dfs_cac_ms = cac_time * 1000;
  3091. + }
  3092. + }
  3093. + ret = count;
  3094. +
  3095. +err:
  3096. + free_page(addr);
  3097. + return ret;
  3098. +}
  3099. +
  3100. +static ssize_t mwl_debugfs_dfs_radar_read(struct file *file, char __user *ubuf,
  3101. + size_t count, loff_t *ppos)
  3102. +{
  3103. + struct mwl_priv *priv = (struct mwl_priv *)file->private_data;
  3104. + unsigned long page = get_zeroed_page(GFP_KERNEL);
  3105. + char *p = (char *)page;
  3106. + int len = 0, size = PAGE_SIZE;
  3107. + ssize_t ret;
  3108. +
  3109. + if (!p)
  3110. + return -ENOMEM;
  3111. +
  3112. + len += scnprintf(p + len, size - len, "\n");
  3113. + len += scnprintf(p + len, size - len,
  3114. + "csa_active: %d\n", priv->csa_active);
  3115. + len += scnprintf(p + len, size - len,
  3116. + "dfs_region: %d\n", priv->dfs_region);
  3117. + len += scnprintf(p + len, size - len,
  3118. + "chirp_count_min: %d\n", priv->dfs_chirp_count_min);
  3119. + len += scnprintf(p + len, size - len, "chirp_time_interval: %d\n",
  3120. + priv->dfs_chirp_time_interval);
  3121. + len += scnprintf(p + len, size - len,
  3122. + "pw_filter: %d\n", priv->dfs_pw_filter);
  3123. + len += scnprintf(p + len, size - len,
  3124. + "min_num_radar: %d\n", priv->dfs_min_num_radar);
  3125. + len += scnprintf(p + len, size - len,
  3126. + "min_pri_count: %d\n", priv->dfs_min_pri_count);
  3127. + len += scnprintf(p + len, size - len, "\n");
  3128. +
  3129. + ret = simple_read_from_buffer(ubuf, count, ppos, p, len);
  3130. + free_page(page);
  3131. +
  3132. + return ret;
  3133. +}
  3134. +
  3135. +static ssize_t mwl_debugfs_dfs_radar_write(struct file *file,
  3136. + const char __user *ubuf,
  3137. + size_t count, loff_t *ppos)
  3138. +{
  3139. + struct mwl_priv *priv = (struct mwl_priv *)file->private_data;
  3140. +
  3141. + wiphy_info(priv->hw->wiphy, "simulate radar detected\n");
  3142. + ieee80211_radar_detected(priv->hw);
  3143. +
  3144. + return count;
  3145. +}
  3146. +
  3147. +static ssize_t mwl_debugfs_thermal_read(struct file *file,
  3148. + char __user *ubuf,
  3149. + size_t count, loff_t *ppos)
  3150. +{
  3151. + struct mwl_priv *priv = (struct mwl_priv *)file->private_data;
  3152. + unsigned long page = get_zeroed_page(GFP_KERNEL);
  3153. + char *p = (char *)page;
  3154. + int len = 0, size = PAGE_SIZE;
  3155. + ssize_t ret;
  3156. +
  3157. + if (!p)
  3158. + return -ENOMEM;
  3159. +
  3160. + mwl_fwcmd_get_temp(priv->hw, &priv->temperature);
  3161. +
  3162. + len += scnprintf(p + len, size - len, "\n");
  3163. + len += scnprintf(p + len, size - len, "quiet period: %d\n",
  3164. + priv->quiet_period);
  3165. + len += scnprintf(p + len, size - len, "throttle state: %d\n",
  3166. + priv->throttle_state);
  3167. + len += scnprintf(p + len, size - len, "temperature: %d\n",
  3168. + priv->temperature);
  3169. + len += scnprintf(p + len, size - len, "\n");
  3170. +
  3171. + ret = simple_read_from_buffer(ubuf, count, ppos, p, len);
  3172. + free_page(page);
  3173. +
  3174. + return ret;
  3175. +}
  3176. +
  3177. +static ssize_t mwl_debugfs_thermal_write(struct file *file,
  3178. + const char __user *ubuf,
  3179. + size_t count, loff_t *ppos)
  3180. +{
  3181. + struct mwl_priv *priv = (struct mwl_priv *)file->private_data;
  3182. + unsigned long addr = get_zeroed_page(GFP_KERNEL);
  3183. + char *buf = (char *)addr;
  3184. + size_t buf_size = min_t(size_t, count, PAGE_SIZE - 1);
  3185. + int throttle_state;
  3186. + ssize_t ret;
  3187. +
  3188. + if (!buf)
  3189. + return -ENOMEM;
  3190. +
  3191. + if (copy_from_user(buf, ubuf, buf_size)) {
  3192. + ret = -EFAULT;
  3193. + goto err;
  3194. + }
  3195. +
  3196. + if (kstrtoint(buf, 0, &throttle_state)) {
  3197. + ret = -EINVAL;
  3198. + goto err;
  3199. + }
  3200. +
  3201. + if (throttle_state > SYSADPT_THERMAL_THROTTLE_MAX) {
  3202. + wiphy_warn(priv->hw->wiphy,
  3203. + "throttle state %d is exceeding the limit %d\n",
  3204. + throttle_state, SYSADPT_THERMAL_THROTTLE_MAX);
  3205. + ret = -EINVAL;
  3206. + goto err;
  3207. + }
  3208. +
  3209. + priv->throttle_state = throttle_state;
  3210. + mwl_thermal_set_throttling(priv);
  3211. + ret = count;
  3212. +
  3213. +err:
  3214. + free_page(addr);
  3215. + return ret;
  3216. +}
  3217. +
  3218. +static ssize_t mwl_debugfs_led_ctrl_read(struct file *file,
  3219. + char __user *ubuf,
  3220. + size_t count, loff_t *ppos)
  3221. +{
  3222. + struct mwl_priv *priv = (struct mwl_priv *)file->private_data;
  3223. + unsigned long page = get_zeroed_page(GFP_KERNEL);
  3224. + char *p = (char *)page;
  3225. + int len = 0, size = PAGE_SIZE;
  3226. + ssize_t ret;
  3227. +
  3228. + if (!p)
  3229. + return -ENOMEM;
  3230. +
  3231. + len += scnprintf(p + len, size - len, "\n");
  3232. + len += scnprintf(p + len, size - len, "led blink %s\n",
  3233. + priv->led_blink_enable ? "enable" : "disable");
  3234. + len += scnprintf(p + len, size - len, "led blink rate: %d\n",
  3235. + priv->led_blink_rate);
  3236. + len += scnprintf(p + len, size - len, "\n");
  3237. +
  3238. + ret = simple_read_from_buffer(ubuf, count, ppos, p, len);
  3239. + free_page(page);
  3240. +
  3241. + return ret;
  3242. +}
  3243. +
  3244. +static ssize_t mwl_debugfs_led_ctrl_write(struct file *file,
  3245. + const char __user *ubuf,
  3246. + size_t count, loff_t *ppos)
  3247. +{
  3248. + struct mwl_priv *priv = (struct mwl_priv *)file->private_data;
  3249. + unsigned long addr = get_zeroed_page(GFP_KERNEL);
  3250. + char *buf = (char *)addr;
  3251. + size_t buf_size = min_t(size_t, count, PAGE_SIZE - 1);
  3252. + int enable, rate;
  3253. + ssize_t ret;
  3254. +
  3255. + if (!buf)
  3256. + return -ENOMEM;
  3257. +
  3258. + if (copy_from_user(buf, ubuf, buf_size)) {
  3259. + ret = -EFAULT;
  3260. + goto err;
  3261. + }
  3262. +
  3263. + ret = sscanf(buf, "%x %x", &enable, &rate);
  3264. +
  3265. + if ((ret != 1) && (ret != 2)) {
  3266. + ret = -EINVAL;
  3267. + goto err;
  3268. + }
  3269. +
  3270. + if (enable && (ret != 2)) {
  3271. + ret = -EINVAL;
  3272. + goto err;
  3273. + }
  3274. +
  3275. + ret = mwl_fwcmd_led_ctrl(priv->hw, enable, rate);
  3276. +
  3277. + if (ret)
  3278. + goto err;
  3279. +
  3280. + priv->led_blink_enable = enable;
  3281. + if (enable)
  3282. + priv->led_blink_rate = rate;
  3283. + else
  3284. + priv->led_blink_rate = 0;
  3285. +
  3286. + ret = count;
  3287. +
  3288. +err:
  3289. + free_page(addr);
  3290. + return ret;
  3291. +}
  3292. +
  3293. +static ssize_t mwl_debugfs_regrdwr_read(struct file *file, char __user *ubuf,
  3294. + size_t count, loff_t *ppos)
  3295. +{
  3296. + struct mwl_priv *priv = (struct mwl_priv *)file->private_data;
  3297. + unsigned long page = get_zeroed_page(GFP_KERNEL);
  3298. + char *p = (char *)page;
  3299. + int len = 0, size = PAGE_SIZE;
  3300. + ssize_t ret;
  3301. +
  3302. + if (*ppos)
  3303. + return len;
  3304. +
  3305. + if (!p)
  3306. + return -ENOMEM;
  3307. +
  3308. + if (!priv->reg_type) {
  3309. + /* No command has been given */
  3310. + len += scnprintf(p + len, size - len, "0");
  3311. + ret = -EINVAL;
  3312. + goto none;
  3313. + }
  3314. +
  3315. + /* Set command has been given */
  3316. + if (priv->reg_value != UINT_MAX) {
  3317. + ret = mwl_hif_reg_access(priv->hw, true);
  3318. + goto done;
  3319. + }
  3320. + /* Get command has been given */
  3321. + ret = mwl_hif_reg_access(priv->hw, false);
  3322. +
  3323. +done:
  3324. + if (!ret)
  3325. + len += scnprintf(p + len, size - len, "%u 0x%08x 0x%08x\n",
  3326. + priv->reg_type, priv->reg_offset,
  3327. + priv->reg_value);
  3328. + else
  3329. + len += scnprintf(p + len, size - len,
  3330. + "error: %d(%u 0x%08x 0x%08x)\n",
  3331. + ret, priv->reg_type, priv->reg_offset,
  3332. + priv->reg_value);
  3333. +
  3334. + ret = simple_read_from_buffer(ubuf, count, ppos, p, len);
  3335. +
  3336. +none:
  3337. + free_page(page);
  3338. + return ret;
  3339. +}
  3340. +
  3341. +static ssize_t mwl_debugfs_regrdwr_write(struct file *file,
  3342. + const char __user *ubuf,
  3343. + size_t count, loff_t *ppos)
  3344. +{
  3345. + struct mwl_priv *priv = (struct mwl_priv *)file->private_data;
  3346. + unsigned long addr = get_zeroed_page(GFP_KERNEL);
  3347. + char *buf = (char *)addr;
  3348. + size_t buf_size = min_t(size_t, count, PAGE_SIZE - 1);
  3349. + ssize_t ret;
  3350. + u32 reg_type = 0, reg_offset = 0, reg_value = UINT_MAX;
  3351. +
  3352. + if (!buf)
  3353. + return -ENOMEM;
  3354. +
  3355. + if (copy_from_user(buf, ubuf, buf_size)) {
  3356. + ret = -EFAULT;
  3357. + goto err;
  3358. + }
  3359. +
  3360. + ret = sscanf(buf, "%u %x %x", &reg_type, &reg_offset, &reg_value);
  3361. +
  3362. + if (!reg_type) {
  3363. + ret = -EINVAL;
  3364. + goto err;
  3365. + } else {
  3366. + priv->reg_type = reg_type;
  3367. + priv->reg_offset = reg_offset;
  3368. + priv->reg_value = reg_value;
  3369. + ret = count;
  3370. + }
  3371. +
  3372. +err:
  3373. + free_page(addr);
  3374. + return ret;
  3375. +}
  3376. +
  3377. +static ssize_t mwl_debugfs_ratetable_read(struct file *file, char __user *ubuf,
  3378. + size_t count, loff_t *ppos)
  3379. +{
  3380. + struct mwl_priv *priv = (struct mwl_priv *)file->private_data;
  3381. + unsigned long page = get_zeroed_page(GFP_KERNEL);
  3382. + char *p = (char *)page;
  3383. + int len = 0, size = PAGE_SIZE;
  3384. + struct mwl_sta *sta_info;
  3385. + struct ieee80211_sta *sta;
  3386. + u8 addr[ETH_ALEN];
  3387. + int table_size = (sizeof(__le32) * 2 * SYSADPT_MAX_RATE_ADAPT_RATES);
  3388. + u8 *rate_table, *rate_idx;
  3389. + u32 rate_info;
  3390. + u8 fmt, stbc, bw, sgi, mcs, preamble_gf, power_id, ldpc, bf, ant;
  3391. + int idx, rate, nss;
  3392. + ssize_t ret;
  3393. +
  3394. + if (!p)
  3395. + return -ENOMEM;
  3396. +
  3397. + if (!priv->ra_aid) {
  3398. + ret = -EINVAL;
  3399. + goto err;
  3400. + }
  3401. +
  3402. + spin_lock_bh(&priv->sta_lock);
  3403. + list_for_each_entry(sta_info, &priv->sta_list, list) {
  3404. + sta = container_of((void *)sta_info, struct ieee80211_sta,
  3405. + drv_priv);
  3406. + if (priv->ra_aid == sta->aid) {
  3407. + ether_addr_copy(addr, sta->addr);
  3408. + break;
  3409. + }
  3410. + }
  3411. + spin_unlock_bh(&priv->sta_lock);
  3412. +
  3413. + rate_table = kzalloc(size, GFP_KERNEL);
  3414. + if (!rate_table) {
  3415. + ret = -ENOMEM;
  3416. + goto err;
  3417. + }
  3418. +
  3419. + ret = mwl_fwcmd_get_ratetable(priv->hw, addr, rate_table,
  3420. + table_size, 0);
  3421. + if (ret) {
  3422. + kfree(rate_table);
  3423. + goto err;
  3424. + }
  3425. +
  3426. + len += scnprintf(p + len, size - len, "\n");
  3427. + len += scnprintf(p + len, size - len,
  3428. + "%3s %6s %5s %5s %5s %5s %5s %4s %2s %5s %4s %5s %5s\n",
  3429. + "Num", "Fmt", "STBC", "BW", "SGI", "Nss", "RateId",
  3430. + "GF/Pre", "PId", "LDPC", "BF", "TxAnt", "Rate");
  3431. + idx = 0;
  3432. + rate_idx = rate_table;
  3433. + rate_info = le32_to_cpu(*(__le32 *)rate_idx);
  3434. + while (rate_info) {
  3435. + fmt = rate_info & MWL_TX_RATE_FORMAT_MASK;
  3436. + stbc = (rate_info & MWL_TX_RATE_STBC_MASK) >>
  3437. + MWL_TX_RATE_STBC_SHIFT;
  3438. + bw = (rate_info & MWL_TX_RATE_BANDWIDTH_MASK) >>
  3439. + MWL_TX_RATE_BANDWIDTH_SHIFT;
  3440. + sgi = (rate_info & MWL_TX_RATE_SHORTGI_MASK) >>
  3441. + MWL_TX_RATE_SHORTGI_SHIFT;
  3442. + mcs = (rate_info & MWL_TX_RATE_RATEIDMCS_MASK) >>
  3443. + MWL_TX_RATE_RATEIDMCS_SHIFT;
  3444. + preamble_gf = (rate_info & MWL_TX_RATE_PREAMBLE_MASK) >>
  3445. + MWL_TX_RATE_PREAMBLE_SHIFT;
  3446. + power_id = (rate_info & MWL_TX_RATE_POWERID_MASK) >>
  3447. + MWL_TX_RATE_POWERID_SHIFT;
  3448. + ldpc = (rate_info & MWL_TX_RATE_ADVCODING_MASK) >>
  3449. + MWL_TX_RATE_ADVCODING_SHIFT;
  3450. + bf = (rate_info & MWL_TX_RATE_BF_MASK) >>
  3451. + MWL_TX_RATE_BF_SHIFT;
  3452. + ant = (rate_info & MWL_TX_RATE_ANTSELECT_MASK) >>
  3453. + MWL_TX_RATE_ANTSELECT_SHIFT;
  3454. +
  3455. + if (fmt == TX_RATE_FORMAT_11AC) {
  3456. + rate = mcs & 0xf; /* 11ac, mcs[3:0]: rate */
  3457. + nss = mcs >> 4; /* 11ac, mcs[6:4] = nss code */
  3458. + nss++; /* ddd 1 to correct Nss representation */
  3459. + } else {
  3460. + rate = mcs;
  3461. + nss = 0;
  3462. + if (fmt == TX_RATE_FORMAT_11N) {
  3463. + if ((mcs >= 0) && (mcs < 8))
  3464. + nss = 1;
  3465. + else if ((mcs >= 8) && (mcs < 16))
  3466. + nss = 2;
  3467. + else if ((mcs >= 16) && (mcs < 24))
  3468. + nss = 3;
  3469. + }
  3470. + }
  3471. +
  3472. + len += scnprintf(p + len, size - len,
  3473. + "%3d %5d %5d %5d %5d %5d %5d %5d %5d %5d %5d %5d %5d\n",
  3474. + idx, (int)fmt, (int)stbc, (int)bw, (int)sgi, nss, rate,
  3475. + (int)preamble_gf, (int)power_id, (int)ldpc, (int)bf,
  3476. + (int)ant,
  3477. + utils_get_phy_rate(fmt, bw, sgi, mcs));
  3478. +
  3479. + idx++;
  3480. + rate_idx += (2 * sizeof(__le32));
  3481. + rate_info = le32_to_cpu(*(__le32 *)rate_idx);
  3482. + }
  3483. + len += scnprintf(p + len, size - len, "\n");
  3484. +
  3485. + kfree(rate_table);
  3486. + ret = simple_read_from_buffer(ubuf, count, ppos, p, len);
  3487. +
  3488. +err:
  3489. + free_page(page);
  3490. + return ret;
  3491. +}
  3492. +
  3493. +static ssize_t mwl_debugfs_ratetable_write(struct file *file,
  3494. + const char __user *ubuf,
  3495. + size_t count, loff_t *ppos)
  3496. +{
  3497. + struct mwl_priv *priv = (struct mwl_priv *)file->private_data;
  3498. + unsigned long addr = get_zeroed_page(GFP_KERNEL);
  3499. + char *buf = (char *)addr;
  3500. + size_t buf_size = min_t(size_t, count, PAGE_SIZE - 1);
  3501. + int sta_aid;
  3502. + ssize_t ret;
  3503. +
  3504. + if (!buf)
  3505. + return -ENOMEM;
  3506. +
  3507. + if (copy_from_user(buf, ubuf, buf_size)) {
  3508. + ret = -EFAULT;
  3509. + goto err;
  3510. + }
  3511. +
  3512. + if (kstrtoint(buf, 0, &sta_aid)) {
  3513. + ret = -EINVAL;
  3514. + goto err;
  3515. + }
  3516. +
  3517. + if ((sta_aid <= 0) || (sta_aid > SYSADPT_MAX_STA_SC4)) {
  3518. + wiphy_warn(priv->hw->wiphy,
  3519. + "station aid is exceeding the limit %d\n", sta_aid);
  3520. + ret = -EINVAL;
  3521. + goto err;
  3522. + }
  3523. +
  3524. + priv->ra_aid = sta_aid;
  3525. + ret = count;
  3526. +
  3527. +err:
  3528. + free_page(addr);
  3529. + return ret;
  3530. +}
  3531. +
  3532. +static ssize_t mwl_debugfs_tx_hist_read(struct file *file, char __user *ubuf,
  3533. + size_t count, loff_t *ppos)
  3534. +{
  3535. + struct mwl_priv *priv = (struct mwl_priv *)file->private_data;
  3536. + unsigned long page = get_zeroed_page(GFP_KERNEL);
  3537. + char *p = (char *)page;
  3538. + int len = 0, size = PAGE_SIZE;
  3539. + struct ieee80211_sta *sta;
  3540. + struct mwl_sta *sta_info;
  3541. + ssize_t ret;
  3542. +
  3543. + if (priv->chip_type != MWL8964)
  3544. + return -EPERM;
  3545. +
  3546. + if (!p)
  3547. + return -ENOMEM;
  3548. +
  3549. + len += scnprintf(p + len, size - len, "\n");
  3550. + len += scnprintf(p + len, size - len,
  3551. + "SU: <4:%d >=4:%d >=15:%d >=50:%d >=100:%d >=250:%d\n",
  3552. + priv->ra_tx_attempt[SU_MIMO][0],
  3553. + priv->ra_tx_attempt[SU_MIMO][1],
  3554. + priv->ra_tx_attempt[SU_MIMO][2],
  3555. + priv->ra_tx_attempt[SU_MIMO][3],
  3556. + priv->ra_tx_attempt[SU_MIMO][4],
  3557. + priv->ra_tx_attempt[SU_MIMO][5]);
  3558. + len += scnprintf(p + len, size - len,
  3559. + "MU: <4:%d >=4:%d >=15:%d >=50:%d >=100:%d >=250:%d\n",
  3560. + priv->ra_tx_attempt[MU_MIMO][0],
  3561. + priv->ra_tx_attempt[MU_MIMO][1],
  3562. + priv->ra_tx_attempt[MU_MIMO][2],
  3563. + priv->ra_tx_attempt[MU_MIMO][3],
  3564. + priv->ra_tx_attempt[MU_MIMO][4],
  3565. + priv->ra_tx_attempt[MU_MIMO][5]);
  3566. + spin_lock_bh(&priv->sta_lock);
  3567. + list_for_each_entry(sta_info, &priv->sta_list, list) {
  3568. + sta = container_of((void *)sta_info, struct ieee80211_sta,
  3569. + drv_priv);
  3570. + len += scnprintf(p + len, size - len, "\nSTA %pM\n", sta->addr);
  3571. + len += scnprintf(p + len, size - len,
  3572. + "============================\n");
  3573. + dump_tx_hist(p, size, &len, sta_info);
  3574. + len += scnprintf(p + len, size - len,
  3575. + "============================\n");
  3576. + }
  3577. + spin_unlock_bh(&priv->sta_lock);
  3578. +
  3579. + ret = simple_read_from_buffer(ubuf, count, ppos, p, len);
  3580. + free_page(page);
  3581. + return ret;
  3582. +}
  3583. +
  3584. +static ssize_t mwl_debugfs_tx_hist_write(struct file *file,
  3585. + const char __user *ubuf,
  3586. + size_t count, loff_t *ppos)
  3587. +{
  3588. + struct mwl_priv *priv = (struct mwl_priv *)file->private_data;
  3589. + unsigned long addr = get_zeroed_page(GFP_KERNEL);
  3590. + char *buf = (char *)addr;
  3591. + size_t buf_size = min_t(size_t, count, PAGE_SIZE - 1);
  3592. + int reset;
  3593. + struct mwl_sta *sta_info;
  3594. + ssize_t ret;
  3595. +
  3596. + if (!buf)
  3597. + return -ENOMEM;
  3598. +
  3599. + if (copy_from_user(buf, ubuf, buf_size)) {
  3600. + ret = -EFAULT;
  3601. + goto err;
  3602. + }
  3603. +
  3604. + if (kstrtoint(buf, 0, &reset)) {
  3605. + ret = -EINVAL;
  3606. + goto err;
  3607. + }
  3608. +
  3609. + if (!reset) {
  3610. + memset(&priv->ra_tx_attempt, 0, 2 * 6 * sizeof(u32));
  3611. + spin_lock_bh(&priv->sta_lock);
  3612. + list_for_each_entry(sta_info, &priv->sta_list, list) {
  3613. + memset(&sta_info->tx_hist, 0,
  3614. + sizeof(sta_info->tx_hist));
  3615. + }
  3616. + spin_unlock_bh(&priv->sta_lock);
  3617. + }
  3618. +
  3619. + ret = count;
  3620. +
  3621. +err:
  3622. + free_page(addr);
  3623. + return ret;
  3624. +}
  3625. +
  3626. +static ssize_t mwl_debugfs_ba_hist_read(struct file *file, char __user *ubuf,
  3627. + size_t count, loff_t *ppos)
  3628. +{
  3629. + struct mwl_priv *priv = (struct mwl_priv *)file->private_data;
  3630. + unsigned long page = get_zeroed_page(GFP_KERNEL);
  3631. + char *p = (char *)page;
  3632. + int len = 0, size = PAGE_SIZE;
  3633. + struct mwl_sta *sta_info;
  3634. + struct mwl_tx_ba_stats *ba_stats;
  3635. + u32 i, data;
  3636. + u32 baholecnt, baexpcnt, bmap0cnt, nobacnt;
  3637. + u8 bmap0flag, nobaflag;
  3638. + char buff[500], file_location[20];
  3639. + struct file *filp_bahisto;
  3640. + u8 *data_p = buff;
  3641. + ssize_t ret;
  3642. +
  3643. + if (!p)
  3644. + return -ENOMEM;
  3645. +
  3646. + if (!priv->ba_aid) {
  3647. + ret = -EINVAL;
  3648. + goto err;
  3649. + }
  3650. +
  3651. + memset(buff, 0, sizeof(buff));
  3652. + memset(file_location, 0, sizeof(file_location));
  3653. + sprintf(file_location, "/tmp/ba_histo-%d", priv->ba_aid);
  3654. +
  3655. + filp_bahisto = filp_open(file_location,
  3656. + O_RDWR | O_CREAT | O_TRUNC, 0);
  3657. +
  3658. + if (IS_ERR(filp_bahisto)) {
  3659. + ret = -EIO;
  3660. + goto err;
  3661. + }
  3662. +
  3663. + sta_info = utils_find_sta_by_aid(priv, priv->ba_aid);
  3664. + if (sta_info && sta_info->ba_hist.enable &&
  3665. + sta_info->ba_hist.ba_stats) {
  3666. + ba_stats = sta_info->ba_hist.ba_stats;
  3667. + len += scnprintf(p + len, size - len,
  3668. + "BA histogram aid: %d, stnid: %d type: %s\n",
  3669. + priv->ba_aid, sta_info->stnid,
  3670. + sta_info->ba_hist.type ? "MU" : "SU");
  3671. + data_p += sprintf(data_p,
  3672. + "BA histogram aid: %d, stnid: %d type: %s\n",
  3673. + priv->ba_aid, sta_info->stnid,
  3674. + sta_info->ba_hist.type ? "MU" : "SU");
  3675. + data_p += sprintf(data_p, "%8s,%8s,%8s,%8s\n",
  3676. + "BAhole", "Expect", "Bmap0", "NoBA");
  3677. + data = *(u32 *)&ba_stats[0];
  3678. + baholecnt = 0;
  3679. + baexpcnt = 0;
  3680. + bmap0cnt = 0;
  3681. + nobacnt = 0;
  3682. + for (i = 0; i < ACNT_BA_SIZE && data; i++) {
  3683. + data = *(u32 *)&ba_stats[i];
  3684. + if (data == 0)
  3685. + break;
  3686. +
  3687. + /* If no BA event does not happen, check BA hole and BA
  3688. + * expected to mark BA bitmap all 0 event
  3689. + */
  3690. + if (!ba_stats[i].no_ba)
  3691. + bmap0flag = (ba_stats[i].ba_hole ==
  3692. + ba_stats[i].ba_expected) ? 1 : 0;
  3693. + else
  3694. + bmap0flag = 0;
  3695. + nobaflag = ba_stats[i].no_ba;
  3696. +
  3697. + /* Buffer is full. Write to file and reset buf */
  3698. + if ((strlen(buff) + 36) >= 500) {
  3699. + __kernel_write(filp_bahisto, buff, strlen(buff),
  3700. + &filp_bahisto->f_pos);
  3701. + mdelay(2);
  3702. + memset(buff, 0, sizeof(buff));
  3703. + data_p = buff;
  3704. + }
  3705. +
  3706. + data_p += sprintf(data_p, "%8d,%8d,",
  3707. + ba_stats[i].ba_hole,
  3708. + ba_stats[i].ba_expected);
  3709. +
  3710. + baholecnt += ba_stats[i].ba_hole;
  3711. + baexpcnt += ba_stats[i].ba_expected;
  3712. + if (bmap0flag) {
  3713. + data_p += sprintf(data_p, " #,");
  3714. + bmap0cnt++;
  3715. + } else
  3716. + data_p += sprintf(data_p, "%8d,", bmap0flag);
  3717. + if (nobaflag) {
  3718. + data_p += sprintf(data_p, " *\n");
  3719. + nobacnt++;
  3720. + } else
  3721. + data_p += sprintf(data_p, "%8d\n", nobaflag);
  3722. + }
  3723. +
  3724. + __kernel_write(filp_bahisto, buff, strlen(buff),
  3725. + &filp_bahisto->f_pos);
  3726. + len += scnprintf(p + len, size - len,
  3727. + "hole: %d, expect: %d, bmap0: %d, noba: %d\n",
  3728. + baholecnt, baexpcnt, bmap0cnt, nobacnt);
  3729. + len += scnprintf(p + len, size - len,
  3730. + "BA histogram data written to %s\n",
  3731. + file_location);
  3732. + } else
  3733. + len += scnprintf(p + len, size - len,
  3734. + "No BA histogram for sta aid: %d\n",
  3735. + priv->ba_aid);
  3736. +
  3737. + filp_close(filp_bahisto, current->files);
  3738. +
  3739. + ret = simple_read_from_buffer(ubuf, count, ppos, p, len);
  3740. +
  3741. +err:
  3742. + free_page(page);
  3743. + return ret;
  3744. +}
  3745. +
  3746. +static ssize_t mwl_debugfs_ba_hist_write(struct file *file,
  3747. + const char __user *ubuf,
  3748. + size_t count, loff_t *ppos)
  3749. +{
  3750. + struct mwl_priv *priv = (struct mwl_priv *)file->private_data;
  3751. + unsigned long addr = get_zeroed_page(GFP_KERNEL);
  3752. + char *buf = (char *)addr;
  3753. + size_t buf_size = min_t(size_t, count, PAGE_SIZE - 1);
  3754. + int sta_aid;
  3755. + struct mwl_sta *sta_info;
  3756. + int size;
  3757. + ssize_t ret;
  3758. +
  3759. + if (!buf)
  3760. + return -ENOMEM;
  3761. +
  3762. + if (copy_from_user(buf, ubuf, buf_size)) {
  3763. + ret = -EFAULT;
  3764. + goto err;
  3765. + }
  3766. +
  3767. + if (kstrtoint(buf, 0, &sta_aid)) {
  3768. + ret = -EINVAL;
  3769. + goto err;
  3770. + }
  3771. +
  3772. + if ((sta_aid <= 0) || (sta_aid > SYSADPT_MAX_STA_SC4)) {
  3773. + wiphy_warn(priv->hw->wiphy,
  3774. + "station aid is exceeding the limit %d\n", sta_aid);
  3775. + ret = -EINVAL;
  3776. + goto err;
  3777. + }
  3778. +
  3779. + if (priv->ba_aid) {
  3780. + sta_info = utils_find_sta_by_aid(priv, priv->ba_aid);
  3781. + if (sta_info) {
  3782. + sta_info->ba_hist.enable = false;
  3783. + kfree(sta_info->ba_hist.ba_stats);
  3784. + }
  3785. + }
  3786. + priv->ba_aid = 0;
  3787. + sta_info = utils_find_sta_by_aid(priv, sta_aid);
  3788. + if (sta_info) {
  3789. + sta_info->ba_hist.enable = true;
  3790. + sta_info->ba_hist.index = 0;
  3791. + size = sizeof(struct mwl_tx_ba_stats) * ACNT_BA_SIZE;
  3792. + sta_info->ba_hist.ba_stats = kmalloc(size, GFP_KERNEL);
  3793. + if (sta_info->ba_hist.ba_stats) {
  3794. + memset(sta_info->ba_hist.ba_stats, 0, size);
  3795. + priv->ba_aid = sta_aid;
  3796. + }
  3797. + ret = count;
  3798. + } else
  3799. + ret = -EINVAL;
  3800. +
  3801. +err:
  3802. + free_page(addr);
  3803. + return ret;
  3804. +}
  3805. +
  3806. +static ssize_t mwl_debugfs_fixed_rate_read(struct file *file, char __user *ubuf,
  3807. + size_t count, loff_t *ppos)
  3808. +{
  3809. + struct mwl_priv *priv = (struct mwl_priv *)file->private_data;
  3810. + unsigned long page = get_zeroed_page(GFP_KERNEL);
  3811. + char *p = (char *)page;
  3812. + int len = 0, size = PAGE_SIZE;
  3813. + ssize_t ret;
  3814. +
  3815. + if (!p)
  3816. + return -ENOMEM;
  3817. +
  3818. + len += scnprintf(p + len, size - len, "\n");
  3819. + len += scnprintf(p + len, size - len, "fixed rate: 0x%08x\n",
  3820. + priv->fixed_rate);
  3821. + len += scnprintf(p + len, size - len, "\n");
  3822. +
  3823. + ret = simple_read_from_buffer(ubuf, count, ppos, p, len);
  3824. + free_page(page);
  3825. + return ret;
  3826. +}
  3827. +
  3828. +static ssize_t mwl_debugfs_fixed_rate_write(struct file *file,
  3829. + const char __user *ubuf,
  3830. + size_t count, loff_t *ppos)
  3831. +{
  3832. + struct mwl_priv *priv = (struct mwl_priv *)file->private_data;
  3833. + unsigned long addr = get_zeroed_page(GFP_KERNEL);
  3834. + char *buf = (char *)addr;
  3835. + size_t buf_size = min_t(size_t, count, PAGE_SIZE - 1);
  3836. + ssize_t ret;
  3837. + int fixed_rate = 0, fwcmd_ret;
  3838. +
  3839. + if (!buf)
  3840. + return -ENOMEM;
  3841. +
  3842. + if (copy_from_user(buf, ubuf, buf_size)) {
  3843. + ret = -EFAULT;
  3844. + goto err;
  3845. + }
  3846. +
  3847. + ret = sscanf(buf, "%08x", &fixed_rate);
  3848. + if (!ret) {
  3849. + ret = -EIO;
  3850. + goto err;
  3851. + }
  3852. +
  3853. + priv->fixed_rate = fixed_rate;
  3854. +
  3855. + if (fixed_rate != 0)
  3856. + fwcmd_ret = mwl_fwcmd_set_rate_drop(priv->hw, 3,
  3857. + priv->fixed_rate, 0);
  3858. + else
  3859. + fwcmd_ret = mwl_fwcmd_set_rate_drop(priv->hw, 1,
  3860. + priv->fixed_rate, 0);
  3861. + if (fwcmd_ret)
  3862. + ret = -EIO;
  3863. + else
  3864. + ret = count;
  3865. +
  3866. +err:
  3867. + free_page(addr);
  3868. + return ret;
  3869. +}
  3870. +
  3871. +static ssize_t mwl_debugfs_core_dump_read(struct file *file, char __user *ubuf,
  3872. + size_t count, loff_t *ppos)
  3873. +{
  3874. + struct mwl_priv *priv = (struct mwl_priv *)file->private_data;
  3875. + unsigned long page = get_zeroed_page(GFP_KERNEL);
  3876. + char *p = (char *)page;
  3877. + int len = 0, size = PAGE_SIZE;
  3878. + struct coredump_cmd *core_dump = NULL;
  3879. + struct coredump *cd = NULL;
  3880. + char *buff = NULL;
  3881. + u32 i, offset;
  3882. + u32 address, length;
  3883. + ssize_t ret;
  3884. +
  3885. + if (priv->chip_type != MWL8964)
  3886. + return -EPERM;
  3887. +
  3888. + if (*ppos)
  3889. + return len;
  3890. +
  3891. + if (!p)
  3892. + return -ENOMEM;
  3893. +
  3894. + core_dump = kmalloc(sizeof(*core_dump), GFP_ATOMIC);
  3895. + if (!core_dump) {
  3896. + ret = -ENOMEM;
  3897. + goto err;
  3898. + }
  3899. +
  3900. + buff = kmalloc(MAX_CORE_DUMP_BUFFER, GFP_ATOMIC);
  3901. + if (!buff) {
  3902. + ret = -ENOMEM;
  3903. + goto err;
  3904. + }
  3905. + memset((char *)buff, 0, MAX_CORE_DUMP_BUFFER);
  3906. +
  3907. + cd = kmalloc(sizeof(*cd), GFP_ATOMIC);
  3908. + if (!cd) {
  3909. + ret = -ENOMEM;
  3910. + goto err;
  3911. + }
  3912. +
  3913. + core_dump->context = 0;
  3914. + core_dump->flags = 0;
  3915. + core_dump->size_kb = 0;
  3916. + if (mwl_fwcmd_get_fw_core_dump(priv->hw, core_dump, buff)) {
  3917. + ret = -EIO;
  3918. + goto err;
  3919. + }
  3920. + memcpy(cd, buff, sizeof(*cd));
  3921. +
  3922. + len += scnprintf(p + len, size - len, "\n");
  3923. + len += scnprintf(p + len, size - len, "Major Version : %d\n",
  3924. + cd->version_major);
  3925. + len += scnprintf(p + len, size - len, "Minor Version : %d\n",
  3926. + cd->version_minor);
  3927. + len += scnprintf(p + len, size - len, "Patch Version : %d\n",
  3928. + cd->version_patch);
  3929. + len += scnprintf(p + len, size - len, "Num of Regions: %d\n",
  3930. + cd->num_regions);
  3931. + len += scnprintf(p + len, size - len, "Num of Symbols: %d\n",
  3932. + cd->num_symbols);
  3933. +
  3934. + for (i = 0; i < cd->num_regions; i++) {
  3935. + address = le32_to_cpu(cd->region[i].address);
  3936. + length = le32_to_cpu(cd->region[i].length);
  3937. + len += scnprintf(p + len, size - len,
  3938. + "\ncd.region[%d]: address=%x, length=%x\n",
  3939. + i, address, length);
  3940. +
  3941. + for (offset = 0; offset < length;
  3942. + offset += MAX_CORE_DUMP_BUFFER) {
  3943. + core_dump->context = cpu_to_le32((i << 28) | offset);
  3944. + core_dump->flags = 0;
  3945. + core_dump->size_kb = 0;
  3946. + if (mwl_fwcmd_get_fw_core_dump(priv->hw,
  3947. + core_dump, buff)) {
  3948. + wiphy_info(priv->hw->wiphy,
  3949. + "region:%d offset:%x\n", i, offset);
  3950. + break;
  3951. + }
  3952. + core_dump_file(buff, MAX_CORE_DUMP_BUFFER,
  3953. + address, address + offset,
  3954. + offset, length, priv->coredump_text);
  3955. + }
  3956. + }
  3957. + len += scnprintf(p + len, size - len, "\n");
  3958. +
  3959. + ret = simple_read_from_buffer(ubuf, count, ppos, p, len);
  3960. +
  3961. +err:
  3962. + kfree(core_dump);
  3963. + kfree(buff);
  3964. + kfree(cd);
  3965. + free_page(page);
  3966. + return ret;
  3967. +}
  3968. +
  3969. +static ssize_t mwl_debugfs_core_dump_write(struct file *file,
  3970. + const char __user *ubuf,
  3971. + size_t count, loff_t *ppos)
  3972. +{
  3973. + struct mwl_priv *priv = (struct mwl_priv *)file->private_data;
  3974. + unsigned long addr = get_zeroed_page(GFP_KERNEL);
  3975. + char *buf = (char *)addr;
  3976. + size_t buf_size = min_t(size_t, count, PAGE_SIZE - 1);
  3977. + int text_mode;
  3978. + ssize_t ret;
  3979. +
  3980. + if (priv->chip_type != MWL8964)
  3981. + return -EPERM;
  3982. +
  3983. + if (!buf)
  3984. + return -ENOMEM;
  3985. +
  3986. + if (copy_from_user(buf, ubuf, buf_size)) {
  3987. + ret = -EFAULT;
  3988. + goto err;
  3989. + }
  3990. +
  3991. + if (kstrtoint(buf, 0, &text_mode)) {
  3992. + ret = -EINVAL;
  3993. + goto err;
  3994. + }
  3995. +
  3996. + if ((text_mode < 0) || (text_mode > 1)) {
  3997. + wiphy_warn(priv->hw->wiphy,
  3998. + "text mode should be 0 (false) or 1 (true): %d\n",
  3999. + text_mode);
  4000. + ret = -EINVAL;
  4001. + goto err;
  4002. + }
  4003. +
  4004. + mwl_fwcmd_core_dump_diag_mode(priv->hw, 1);
  4005. + priv->coredump_text = text_mode ? true : false;
  4006. + ret = count;
  4007. +
  4008. +err:
  4009. + free_page(addr);
  4010. + return ret;
  4011. +}
  4012. +
  4013. +static ssize_t mwl_debugfs_mcast_cts_write(struct file *file,
  4014. + const char __user *ubuf,
  4015. + size_t count, loff_t *ppos)
  4016. +{
  4017. + struct mwl_priv *priv = (struct mwl_priv *)file->private_data;
  4018. + unsigned long addr = get_zeroed_page(GFP_KERNEL);
  4019. + char *buf = (char *)addr;
  4020. + size_t buf_size = min_t(size_t, count, PAGE_SIZE - 1);
  4021. + int cts_enable = 0;
  4022. + ssize_t ret;
  4023. +
  4024. + if (!buf)
  4025. + return -ENOMEM;
  4026. +
  4027. + if (copy_from_user(buf, ubuf, buf_size)) {
  4028. + ret = -EFAULT;
  4029. + goto err;
  4030. + }
  4031. +
  4032. + if (kstrtoint(buf, 0, &cts_enable)) {
  4033. + ret = -EINVAL;
  4034. + goto err;
  4035. + }
  4036. +
  4037. + ret = mwl_hif_mcast_cts(priv->hw, cts_enable ? true : false);
  4038. + if (ret)
  4039. + goto err;
  4040. +
  4041. + ret = count;
  4042. +
  4043. +err:
  4044. + free_page(addr);
  4045. + return ret;
  4046. +}
  4047. +
  4048. +static ssize_t mwl_debugfs_wmmedcaap_write(struct file *file,
  4049. + const char __user *ubuf,
  4050. + size_t count, loff_t *ppos)
  4051. +{
  4052. + struct mwl_priv *priv = (struct mwl_priv *)file->private_data;
  4053. + unsigned long addr = get_zeroed_page(GFP_KERNEL);
  4054. + char *buf = (char *)addr;
  4055. + size_t buf_size = min_t(size_t, count, PAGE_SIZE - 1);
  4056. + u32 index = 0, cw_min = 0, cw_max = 0, aifsn = 0, txop = 0;
  4057. + ssize_t ret;
  4058. +
  4059. + if (!buf)
  4060. + return -ENOMEM;
  4061. +
  4062. + if (copy_from_user(buf, ubuf, buf_size)) {
  4063. + ret = -EFAULT;
  4064. + goto err;
  4065. + }
  4066. +
  4067. + ret = sscanf(buf, "%u %x %x %u %x", &index, &cw_min,
  4068. + &cw_max, &aifsn, &txop);
  4069. + if (ret != 5) {
  4070. + ret = -EINVAL;
  4071. + goto err;
  4072. + }
  4073. + wiphy_info(priv->hw->wiphy, "set TCQ%d wmm edca with:\n", index);
  4074. + wiphy_info(priv->hw->wiphy,
  4075. + "cw_min=0x%x, cw_max=0x%x, aifs_num=%d, txop=0x%x\n",
  4076. + cw_min, cw_max, aifsn, txop);
  4077. +
  4078. + ret = mwl_fwcmd_set_edca_params(priv->hw, index,
  4079. + cw_min, cw_max, aifsn, txop);
  4080. + if (ret)
  4081. + goto err;
  4082. +
  4083. + ret = count;
  4084. +
  4085. +err:
  4086. + free_page(addr);
  4087. + return ret;
  4088. +}
  4089. +
  4090. +MWLWIFI_DEBUGFS_FILE_READ_OPS(info);
  4091. +MWLWIFI_DEBUGFS_FILE_READ_OPS(tx_status);
  4092. +MWLWIFI_DEBUGFS_FILE_READ_OPS(rx_status);
  4093. +MWLWIFI_DEBUGFS_FILE_READ_OPS(vif);
  4094. +MWLWIFI_DEBUGFS_FILE_READ_OPS(sta);
  4095. +MWLWIFI_DEBUGFS_FILE_READ_OPS(ampdu);
  4096. +MWLWIFI_DEBUGFS_FILE_READ_OPS(stnid);
  4097. +MWLWIFI_DEBUGFS_FILE_READ_OPS(device_pwrtbl);
  4098. +MWLWIFI_DEBUGFS_FILE_READ_OPS(txpwrlmt);
  4099. +MWLWIFI_DEBUGFS_FILE_OPS(tx_amsdu);
  4100. +MWLWIFI_DEBUGFS_FILE_OPS(dump_hostcmd);
  4101. +MWLWIFI_DEBUGFS_FILE_OPS(dump_probe);
  4102. +MWLWIFI_DEBUGFS_FILE_OPS(heartbeat);
  4103. +MWLWIFI_DEBUGFS_FILE_OPS(dfs_test);
  4104. +MWLWIFI_DEBUGFS_FILE_OPS(dfs_channel);
  4105. +MWLWIFI_DEBUGFS_FILE_OPS(dfs_radar);
  4106. +MWLWIFI_DEBUGFS_FILE_OPS(thermal);
  4107. +MWLWIFI_DEBUGFS_FILE_OPS(led_ctrl);
  4108. +MWLWIFI_DEBUGFS_FILE_OPS(regrdwr);
  4109. +MWLWIFI_DEBUGFS_FILE_OPS(ratetable);
  4110. +MWLWIFI_DEBUGFS_FILE_OPS(tx_hist);
  4111. +MWLWIFI_DEBUGFS_FILE_OPS(ba_hist);
  4112. +MWLWIFI_DEBUGFS_FILE_OPS(fixed_rate);
  4113. +MWLWIFI_DEBUGFS_FILE_OPS(core_dump);
  4114. +MWLWIFI_DEBUGFS_FILE_WRITE_OPS(mcast_cts);
  4115. +MWLWIFI_DEBUGFS_FILE_WRITE_OPS(wmmedcaap);
  4116. +
  4117. +void mwl_debugfs_init(struct ieee80211_hw *hw)
  4118. +{
  4119. + struct mwl_priv *priv = hw->priv;
  4120. +
  4121. + if (!priv->debugfs_phy)
  4122. + priv->debugfs_phy = debugfs_create_dir("mwlwifi",
  4123. + hw->wiphy->debugfsdir);
  4124. +
  4125. + if (!priv->debugfs_phy)
  4126. + return;
  4127. +
  4128. + MWLWIFI_DEBUGFS_ADD_FILE(info);
  4129. + MWLWIFI_DEBUGFS_ADD_FILE(tx_status);
  4130. + MWLWIFI_DEBUGFS_ADD_FILE(rx_status);
  4131. + MWLWIFI_DEBUGFS_ADD_FILE(vif);
  4132. + MWLWIFI_DEBUGFS_ADD_FILE(sta);
  4133. + MWLWIFI_DEBUGFS_ADD_FILE(ampdu);
  4134. + MWLWIFI_DEBUGFS_ADD_FILE(stnid);
  4135. + MWLWIFI_DEBUGFS_ADD_FILE(device_pwrtbl);
  4136. + MWLWIFI_DEBUGFS_ADD_FILE(txpwrlmt);
  4137. + MWLWIFI_DEBUGFS_ADD_FILE(tx_amsdu);
  4138. + MWLWIFI_DEBUGFS_ADD_FILE(dump_hostcmd);
  4139. + MWLWIFI_DEBUGFS_ADD_FILE(dump_probe);
  4140. + MWLWIFI_DEBUGFS_ADD_FILE(heartbeat);
  4141. + MWLWIFI_DEBUGFS_ADD_FILE(dfs_test);
  4142. + MWLWIFI_DEBUGFS_ADD_FILE(dfs_channel);
  4143. + MWLWIFI_DEBUGFS_ADD_FILE(dfs_radar);
  4144. + MWLWIFI_DEBUGFS_ADD_FILE(thermal);
  4145. + MWLWIFI_DEBUGFS_ADD_FILE(led_ctrl);
  4146. + MWLWIFI_DEBUGFS_ADD_FILE(regrdwr);
  4147. + MWLWIFI_DEBUGFS_ADD_FILE(ratetable);
  4148. + MWLWIFI_DEBUGFS_ADD_FILE(tx_hist);
  4149. + MWLWIFI_DEBUGFS_ADD_FILE(ba_hist);
  4150. + MWLWIFI_DEBUGFS_ADD_FILE(fixed_rate);
  4151. + MWLWIFI_DEBUGFS_ADD_FILE(core_dump);
  4152. + MWLWIFI_DEBUGFS_ADD_FILE(mcast_cts);
  4153. + MWLWIFI_DEBUGFS_ADD_FILE(wmmedcaap);
  4154. +}
  4155. +
  4156. +void mwl_debugfs_remove(struct ieee80211_hw *hw)
  4157. +{
  4158. + struct mwl_priv *priv = hw->priv;
  4159. +
  4160. + debugfs_remove(priv->debugfs_phy);
  4161. + priv->debugfs_phy = NULL;
  4162. +}
  4163. diff --git a/drivers/net/wireless/marvell/mwlwifi/debugfs.h b/drivers/net/wireless/marvell/mwlwifi/debugfs.h
  4164. new file mode 100644
  4165. index 000000000000..e7595f563348
  4166. --- /dev/null
  4167. +++ b/drivers/net/wireless/marvell/mwlwifi/debugfs.h
  4168. @@ -0,0 +1,24 @@
  4169. +/*
  4170. + * Copyright (C) 2006-2018, Marvell International Ltd.
  4171. + *
  4172. + * This software file (the "File") is distributed by Marvell International
  4173. + * Ltd. under the terms of the GNU General Public License Version 2, June 1991
  4174. + * (the "License"). You may use, redistribute and/or modify this File in
  4175. + * accordance with the terms and conditions of the License, a copy of which
  4176. + * is available by writing to the Free Software Foundation, Inc.
  4177. + *
  4178. + * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
  4179. + * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
  4180. + * ARE EXPRESSLY DISCLAIMED. The License provides additional details about
  4181. + * this warranty disclaimer.
  4182. + */
  4183. +
  4184. +/* Description: This file defines debug fs related functions. */
  4185. +
  4186. +#ifndef _MWL_DEBUGFS_H_
  4187. +#define _MWL_DEBUGFS_H_
  4188. +
  4189. +void mwl_debugfs_init(struct ieee80211_hw *hw);
  4190. +void mwl_debugfs_remove(struct ieee80211_hw *hw);
  4191. +
  4192. +#endif /* _MWL_DEBUGFS_H_ */
  4193. diff --git a/drivers/net/wireless/marvell/mwlwifi/hif/fwcmd.c b/drivers/net/wireless/marvell/mwlwifi/hif/fwcmd.c
  4194. new file mode 100644
  4195. index 000000000000..ff943d6fe447
  4196. --- /dev/null
  4197. +++ b/drivers/net/wireless/marvell/mwlwifi/hif/fwcmd.c
  4198. @@ -0,0 +1,3852 @@
  4199. +/*
  4200. + * Copyright (C) 2006-2018, Marvell International Ltd.
  4201. + *
  4202. + * This software file (the "File") is distributed by Marvell International
  4203. + * Ltd. under the terms of the GNU General Public License Version 2, June 1991
  4204. + * (the "License"). You may use, redistribute and/or modify this File in
  4205. + * accordance with the terms and conditions of the License, a copy of which
  4206. + * is available by writing to the Free Software Foundation, Inc.
  4207. + *
  4208. + * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
  4209. + * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
  4210. + * ARE EXPRESSLY DISCLAIMED. The License provides additional details about
  4211. + * this warranty disclaimer.
  4212. + */
  4213. +
  4214. +/* Description: This file implements firmware host command related
  4215. + * functions.
  4216. + */
  4217. +
  4218. +#include <linux/etherdevice.h>
  4219. +#include <linux/ctype.h>
  4220. +
  4221. +#include "sysadpt.h"
  4222. +#include "core.h"
  4223. +#include "utils.h"
  4224. +#include "hif/fwcmd.h"
  4225. +#include "hif/hif-ops.h"
  4226. +
  4227. +#define MAX_WAIT_GET_HW_SPECS_ITERATONS 3
  4228. +
  4229. +struct cmd_header {
  4230. + __le16 command;
  4231. + __le16 len;
  4232. +} __packed;
  4233. +
  4234. +char *mwl_fwcmd_get_cmd_string(unsigned short cmd)
  4235. +{
  4236. + int max_entries = 0;
  4237. + int curr_cmd = 0;
  4238. +
  4239. + static const struct {
  4240. + u16 cmd;
  4241. + char *cmd_string;
  4242. + } cmds[] = {
  4243. + { HOSTCMD_CMD_GET_HW_SPEC, "GetHwSpecifications" },
  4244. + { HOSTCMD_CMD_SET_HW_SPEC, "SetHwSepcifications" },
  4245. + { HOSTCMD_CMD_802_11_GET_STAT, "80211GetStat" },
  4246. + { HOSTCMD_CMD_BBP_REG_ACCESS, "BBPRegAccess" },
  4247. + { HOSTCMD_CMD_RF_REG_ACCESS, "RFRegAccess" },
  4248. + { HOSTCMD_CMD_802_11_RADIO_CONTROL, "80211RadioControl" },
  4249. + { HOSTCMD_CMD_MEM_ADDR_ACCESS, "MEMAddrAccess" },
  4250. + { HOSTCMD_CMD_802_11_TX_POWER, "80211TxPower" },
  4251. + { HOSTCMD_CMD_802_11_RF_ANTENNA, "80211RfAntenna" },
  4252. + { HOSTCMD_CMD_BROADCAST_SSID_ENABLE, "BroadcastSsidEnable" },
  4253. + { HOSTCMD_CMD_SET_CFG, "SetCfg" },
  4254. + { HOSTCMD_CMD_SET_RF_CHANNEL, "SetRfChannel" },
  4255. + { HOSTCMD_CMD_SET_AID, "SetAid" },
  4256. + { HOSTCMD_CMD_SET_INFRA_MODE, "SetInfraMode" },
  4257. + { HOSTCMD_CMD_802_11_RTS_THSD, "80211RtsThreshold" },
  4258. + { HOSTCMD_CMD_SET_EDCA_PARAMS, "SetEDCAParams" },
  4259. + { HOSTCMD_CMD_802_11H_DETECT_RADAR, "80211hDetectRadar" },
  4260. + { HOSTCMD_CMD_SET_WMM_MODE, "SetWMMMode" },
  4261. + { HOSTCMD_CMD_HT_GUARD_INTERVAL, "HtGuardInterval" },
  4262. + { HOSTCMD_CMD_SET_FIXED_RATE, "SetFixedRate" },
  4263. + { HOSTCMD_CMD_SET_IES, "SetInformationElements" },
  4264. + { HOSTCMD_CMD_SET_LINKADAPT_CS_MODE, "LinkAdaptCsMode" },
  4265. + { HOSTCMD_CMD_DUMP_OTP_DATA, "DumpOtpData" },
  4266. + { HOSTCMD_CMD_SET_MAC_ADDR, "SetMacAddr" },
  4267. + { HOSTCMD_CMD_SET_RATE_ADAPT_MODE, "SetRateAdaptationMode" },
  4268. + { HOSTCMD_CMD_GET_WATCHDOG_BITMAP, "GetWatchdogBitMap" },
  4269. + { HOSTCMD_CMD_DEL_MAC_ADDR, "DelMacAddr" },
  4270. + { HOSTCMD_CMD_BSS_START, "BssStart" },
  4271. + { HOSTCMD_CMD_AP_BEACON, "SetApBeacon" },
  4272. + { HOSTCMD_CMD_SET_NEW_STN, "SetNewStation" },
  4273. + { HOSTCMD_CMD_SET_APMODE, "SetApMode" },
  4274. + { HOSTCMD_CMD_SET_SWITCH_CHANNEL, "SetSwitchChannel" },
  4275. + { HOSTCMD_CMD_UPDATE_ENCRYPTION, "UpdateEncryption" },
  4276. + { HOSTCMD_CMD_BASTREAM, "BAStream" },
  4277. + { HOSTCMD_CMD_SET_SPECTRUM_MGMT, "SetSpectrumMgmt" },
  4278. + { HOSTCMD_CMD_SET_POWER_CONSTRAINT, "SetPowerConstraint" },
  4279. + { HOSTCMD_CMD_SET_COUNTRY_CODE, "SetCountryCode" },
  4280. + { HOSTCMD_CMD_SET_OPTIMIZATION_LEVEL, "SetOptimizationLevel" },
  4281. + { HOSTCMD_CMD_SET_WSC_IE, "SetWscIE" },
  4282. + { HOSTCMD_CMD_GET_RATETABLE, "GetRateTable" },
  4283. + { HOSTCMD_CMD_GET_SEQNO, "GetSeqno" },
  4284. + { HOSTCMD_CMD_DWDS_ENABLE, "DwdsEnable" },
  4285. + { HOSTCMD_CMD_FW_FLUSH_TIMER, "FwFlushTimer" },
  4286. + { HOSTCMD_CMD_SET_CDD, "SetCDD" },
  4287. + { HOSTCMD_CMD_SET_BFTYPE, "SetBFType" },
  4288. + { HOSTCMD_CMD_CAU_REG_ACCESS, "CAURegAccess" },
  4289. + { HOSTCMD_CMD_GET_TEMP, "GetTemp" },
  4290. + { HOSTCMD_CMD_LED_CTRL, "LedCtrl" },
  4291. + { HOSTCMD_CMD_GET_FW_REGION_CODE, "GetFwRegionCode" },
  4292. + { HOSTCMD_CMD_GET_DEVICE_PWR_TBL, "GetDevicePwrTbl" },
  4293. + { HOSTCMD_CMD_SET_RATE_DROP, "SetRateDrop" },
  4294. + { HOSTCMD_CMD_NEWDP_DMATHREAD_START, "NewdpDMAThreadStart" },
  4295. + { HOSTCMD_CMD_GET_FW_REGION_CODE_SC4, "GetFwRegionCodeSC4" },
  4296. + { HOSTCMD_CMD_GET_DEVICE_PWR_TBL_SC4, "GetDevicePwrTblSC4" },
  4297. + { HOSTCMD_CMD_QUIET_MODE, "QuietMode" },
  4298. + { HOSTCMD_CMD_CORE_DUMP_DIAG_MODE, "CoreDumpDiagMode" },
  4299. + { HOSTCMD_CMD_802_11_SLOT_TIME, "80211SlotTime" },
  4300. + { HOSTCMD_CMD_GET_FW_CORE_DUMP, "GetFwCoreDump" },
  4301. + { HOSTCMD_CMD_EDMAC_CTRL, "EDMACCtrl" },
  4302. + { HOSTCMD_CMD_TXPWRLMT_CFG, "TxpwrlmtCfg" },
  4303. + { HOSTCMD_CMD_MCAST_CTS, "McastCts" },
  4304. + };
  4305. +
  4306. + max_entries = ARRAY_SIZE(cmds);
  4307. +
  4308. + for (curr_cmd = 0; curr_cmd < max_entries; curr_cmd++)
  4309. + if ((cmd & 0x7fff) == cmds[curr_cmd].cmd)
  4310. + return cmds[curr_cmd].cmd_string;
  4311. +
  4312. + return "unknown";
  4313. +}
  4314. +
  4315. +static int mwl_fwcmd_802_11_radio_control(struct mwl_priv *priv,
  4316. + bool enable, bool force)
  4317. +{
  4318. + struct hostcmd_cmd_802_11_radio_control *pcmd;
  4319. +
  4320. + if (enable == priv->radio_on && !force)
  4321. + return 0;
  4322. +
  4323. + pcmd = (struct hostcmd_cmd_802_11_radio_control *)&priv->pcmd_buf[0];
  4324. +
  4325. + mutex_lock(&priv->fwcmd_mutex);
  4326. +
  4327. + memset(pcmd, 0x00, sizeof(*pcmd));
  4328. + pcmd->cmd_hdr.cmd = cpu_to_le16(HOSTCMD_CMD_802_11_RADIO_CONTROL);
  4329. + pcmd->cmd_hdr.len = cpu_to_le16(sizeof(*pcmd));
  4330. + pcmd->action = cpu_to_le16(WL_SET);
  4331. + pcmd->control = cpu_to_le16(priv->radio_short_preamble ?
  4332. + WL_AUTO_PREAMBLE : WL_LONG_PREAMBLE);
  4333. + pcmd->radio_on = cpu_to_le16(enable ? WL_ENABLE : WL_DISABLE);
  4334. +
  4335. + if (mwl_hif_exec_cmd(priv->hw, HOSTCMD_CMD_802_11_RADIO_CONTROL)) {
  4336. + mutex_unlock(&priv->fwcmd_mutex);
  4337. + return -EIO;
  4338. + }
  4339. +
  4340. + priv->radio_on = enable;
  4341. +
  4342. + mutex_unlock(&priv->fwcmd_mutex);
  4343. +
  4344. + return 0;
  4345. +}
  4346. +
  4347. +static int mwl_fwcmd_get_tx_powers(struct mwl_priv *priv, u16 *powlist,
  4348. + u8 action, u16 ch, u16 band,
  4349. + u16 width, u16 sub_ch)
  4350. +{
  4351. + struct hostcmd_cmd_802_11_tx_power *pcmd;
  4352. + int i;
  4353. +
  4354. + pcmd = (struct hostcmd_cmd_802_11_tx_power *)&priv->pcmd_buf[0];
  4355. +
  4356. + mutex_lock(&priv->fwcmd_mutex);
  4357. +
  4358. + if (priv->chip_type == MWL8997) {
  4359. + memset(pcmd, 0x00,
  4360. + sizeof(struct hostcmd_cmd_802_11_tx_power_kf2));
  4361. + pcmd->cmd_hdr.len = cpu_to_le16(
  4362. + sizeof(struct hostcmd_cmd_802_11_tx_power_kf2));
  4363. + } else {
  4364. + memset(pcmd, 0x00, sizeof(*pcmd));
  4365. + pcmd->cmd_hdr.len = cpu_to_le16(sizeof(*pcmd));
  4366. + }
  4367. + pcmd->cmd_hdr.cmd = cpu_to_le16(HOSTCMD_CMD_802_11_TX_POWER);
  4368. + pcmd->action = cpu_to_le16(action);
  4369. + pcmd->ch = cpu_to_le16(ch);
  4370. + pcmd->bw = cpu_to_le16(width);
  4371. + pcmd->band = cpu_to_le16(band);
  4372. + pcmd->sub_ch = cpu_to_le16(sub_ch);
  4373. +
  4374. + if (mwl_hif_exec_cmd(priv->hw, HOSTCMD_CMD_802_11_TX_POWER)) {
  4375. + mutex_unlock(&priv->fwcmd_mutex);
  4376. + return -EIO;
  4377. + }
  4378. +
  4379. + for (i = 0; i < priv->pwr_level; i++)
  4380. + powlist[i] = le16_to_cpu(pcmd->power_level_list[i]);
  4381. +
  4382. + mutex_unlock(&priv->fwcmd_mutex);
  4383. +
  4384. + return 0;
  4385. +}
  4386. +
  4387. +static int mwl_fwcmd_set_tx_powers(struct mwl_priv *priv, u16 txpow[],
  4388. + u8 action, u16 ch, u16 band,
  4389. + u16 width, u16 sub_ch)
  4390. +{
  4391. + struct hostcmd_cmd_802_11_tx_power *pcmd;
  4392. + int i;
  4393. +
  4394. + pcmd = (struct hostcmd_cmd_802_11_tx_power *)&priv->pcmd_buf[0];
  4395. +
  4396. + mutex_lock(&priv->fwcmd_mutex);
  4397. +
  4398. + if (priv->chip_type == MWL8997) {
  4399. + memset(pcmd, 0x00,
  4400. + sizeof(struct hostcmd_cmd_802_11_tx_power_kf2));
  4401. + pcmd->cmd_hdr.len = cpu_to_le16(
  4402. + sizeof(struct hostcmd_cmd_802_11_tx_power_kf2));
  4403. + } else {
  4404. + memset(pcmd, 0x00, sizeof(*pcmd));
  4405. + pcmd->cmd_hdr.len = cpu_to_le16(sizeof(*pcmd));
  4406. + }
  4407. + pcmd->cmd_hdr.cmd = cpu_to_le16(HOSTCMD_CMD_802_11_TX_POWER);
  4408. + pcmd->action = cpu_to_le16(action);
  4409. + pcmd->ch = cpu_to_le16(ch);
  4410. + pcmd->bw = cpu_to_le16(width);
  4411. + pcmd->band = cpu_to_le16(band);
  4412. + pcmd->sub_ch = cpu_to_le16(sub_ch);
  4413. +
  4414. + for (i = 0; i < priv->pwr_level; i++)
  4415. + pcmd->power_level_list[i] = cpu_to_le16(txpow[i]);
  4416. +
  4417. + if (mwl_hif_exec_cmd(priv->hw, HOSTCMD_CMD_802_11_TX_POWER)) {
  4418. + mutex_unlock(&priv->fwcmd_mutex);
  4419. + return -EIO;
  4420. + }
  4421. +
  4422. + mutex_unlock(&priv->fwcmd_mutex);
  4423. +
  4424. + return 0;
  4425. +}
  4426. +
  4427. +static u8 mwl_fwcmd_get_80m_pri_chnl(u8 channel)
  4428. +{
  4429. + u8 act_primary = ACT_PRIMARY_CHAN_0;
  4430. +
  4431. + switch (channel) {
  4432. + case 36:
  4433. + act_primary = ACT_PRIMARY_CHAN_0;
  4434. + break;
  4435. + case 40:
  4436. + act_primary = ACT_PRIMARY_CHAN_1;
  4437. + break;
  4438. + case 44:
  4439. + act_primary = ACT_PRIMARY_CHAN_2;
  4440. + break;
  4441. + case 48:
  4442. + act_primary = ACT_PRIMARY_CHAN_3;
  4443. + break;
  4444. + case 52:
  4445. + act_primary = ACT_PRIMARY_CHAN_0;
  4446. + break;
  4447. + case 56:
  4448. + act_primary = ACT_PRIMARY_CHAN_1;
  4449. + break;
  4450. + case 60:
  4451. + act_primary = ACT_PRIMARY_CHAN_2;
  4452. + break;
  4453. + case 64:
  4454. + act_primary = ACT_PRIMARY_CHAN_3;
  4455. + break;
  4456. + case 100:
  4457. + act_primary = ACT_PRIMARY_CHAN_0;
  4458. + break;
  4459. + case 104:
  4460. + act_primary = ACT_PRIMARY_CHAN_1;
  4461. + break;
  4462. + case 108:
  4463. + act_primary = ACT_PRIMARY_CHAN_2;
  4464. + break;
  4465. + case 112:
  4466. + act_primary = ACT_PRIMARY_CHAN_3;
  4467. + break;
  4468. + case 116:
  4469. + act_primary = ACT_PRIMARY_CHAN_0;
  4470. + break;
  4471. + case 120:
  4472. + act_primary = ACT_PRIMARY_CHAN_1;
  4473. + break;
  4474. + case 124:
  4475. + act_primary = ACT_PRIMARY_CHAN_2;
  4476. + break;
  4477. + case 128:
  4478. + act_primary = ACT_PRIMARY_CHAN_3;
  4479. + break;
  4480. + case 132:
  4481. + act_primary = ACT_PRIMARY_CHAN_0;
  4482. + break;
  4483. + case 136:
  4484. + act_primary = ACT_PRIMARY_CHAN_1;
  4485. + break;
  4486. + case 140:
  4487. + act_primary = ACT_PRIMARY_CHAN_2;
  4488. + break;
  4489. + case 144:
  4490. + act_primary = ACT_PRIMARY_CHAN_3;
  4491. + break;
  4492. + case 149:
  4493. + act_primary = ACT_PRIMARY_CHAN_0;
  4494. + break;
  4495. + case 153:
  4496. + act_primary = ACT_PRIMARY_CHAN_1;
  4497. + break;
  4498. + case 157:
  4499. + act_primary = ACT_PRIMARY_CHAN_2;
  4500. + break;
  4501. + case 161:
  4502. + act_primary = ACT_PRIMARY_CHAN_3;
  4503. + break;
  4504. + }
  4505. +
  4506. + return act_primary;
  4507. +}
  4508. +
  4509. +static u8 mwl_fwcmd_get_160m_pri_chnl(u8 channel)
  4510. +{
  4511. + u8 act_primary = ACT_PRIMARY_CHAN_0;
  4512. +
  4513. + switch (channel) {
  4514. + case 36:
  4515. + act_primary = ACT_PRIMARY_CHAN_0;
  4516. + break;
  4517. + case 40:
  4518. + act_primary = ACT_PRIMARY_CHAN_1;
  4519. + break;
  4520. + case 44:
  4521. + act_primary = ACT_PRIMARY_CHAN_2;
  4522. + break;
  4523. + case 48:
  4524. + act_primary = ACT_PRIMARY_CHAN_3;
  4525. + break;
  4526. + case 52:
  4527. + act_primary = ACT_PRIMARY_CHAN_4;
  4528. + break;
  4529. + case 56:
  4530. + act_primary = ACT_PRIMARY_CHAN_5;
  4531. + break;
  4532. + case 60:
  4533. + act_primary = ACT_PRIMARY_CHAN_6;
  4534. + break;
  4535. + case 64:
  4536. + act_primary = ACT_PRIMARY_CHAN_7;
  4537. + break;
  4538. + case 100:
  4539. + act_primary = ACT_PRIMARY_CHAN_0;
  4540. + break;
  4541. + case 104:
  4542. + act_primary = ACT_PRIMARY_CHAN_1;
  4543. + break;
  4544. + case 108:
  4545. + act_primary = ACT_PRIMARY_CHAN_2;
  4546. + break;
  4547. + case 112:
  4548. + act_primary = ACT_PRIMARY_CHAN_3;
  4549. + break;
  4550. + case 116:
  4551. + act_primary = ACT_PRIMARY_CHAN_4;
  4552. + break;
  4553. + case 120:
  4554. + act_primary = ACT_PRIMARY_CHAN_5;
  4555. + break;
  4556. + case 124:
  4557. + act_primary = ACT_PRIMARY_CHAN_6;
  4558. + break;
  4559. + case 128:
  4560. + act_primary = ACT_PRIMARY_CHAN_7;
  4561. + break;
  4562. + case 149:
  4563. + act_primary = ACT_PRIMARY_CHAN_0;
  4564. + break;
  4565. + case 153:
  4566. + act_primary = ACT_PRIMARY_CHAN_1;
  4567. + break;
  4568. + case 157:
  4569. + act_primary = ACT_PRIMARY_CHAN_2;
  4570. + break;
  4571. + case 161:
  4572. + act_primary = ACT_PRIMARY_CHAN_3;
  4573. + break;
  4574. + case 165:
  4575. + act_primary = ACT_PRIMARY_CHAN_4;
  4576. + break;
  4577. + case 169:
  4578. + act_primary = ACT_PRIMARY_CHAN_5;
  4579. + break;
  4580. + case 173:
  4581. + act_primary = ACT_PRIMARY_CHAN_6;
  4582. + break;
  4583. + case 177:
  4584. + act_primary = ACT_PRIMARY_CHAN_7;
  4585. + break;
  4586. + }
  4587. +
  4588. + return act_primary;
  4589. +}
  4590. +
  4591. +static void mwl_fwcmd_parse_beacon(struct mwl_priv *priv,
  4592. + struct mwl_vif *vif, u8 *beacon, int len)
  4593. +{
  4594. + struct ieee80211_mgmt *mgmt;
  4595. + struct beacon_info *beacon_info;
  4596. + int baselen;
  4597. + u8 *pos;
  4598. + size_t left;
  4599. + bool elem_parse_failed;
  4600. +
  4601. + mgmt = (struct ieee80211_mgmt *)beacon;
  4602. +
  4603. + baselen = (u8 *)mgmt->u.beacon.variable - (u8 *)mgmt;
  4604. + if (baselen > len)
  4605. + return;
  4606. +
  4607. + beacon_info = &vif->beacon_info;
  4608. + memset(beacon_info, 0, sizeof(struct beacon_info));
  4609. + beacon_info->valid = false;
  4610. + beacon_info->ie_ht_ptr = &beacon_info->ie_list_ht[0];
  4611. + beacon_info->ie_vht_ptr = &beacon_info->ie_list_vht[0];
  4612. +
  4613. + beacon_info->cap_info = le16_to_cpu(mgmt->u.beacon.capab_info);
  4614. + beacon_info->power_constraint = 0;
  4615. +
  4616. + pos = (u8 *)mgmt->u.beacon.variable;
  4617. + left = len - baselen;
  4618. +
  4619. + elem_parse_failed = false;
  4620. +
  4621. + while (left >= 2) {
  4622. + u8 id, elen;
  4623. +
  4624. + id = *pos++;
  4625. + elen = *pos++;
  4626. + left -= 2;
  4627. +
  4628. + if (elen > left) {
  4629. + elem_parse_failed = true;
  4630. + break;
  4631. + }
  4632. +
  4633. + switch (id) {
  4634. + case WLAN_EID_COUNTRY:
  4635. + beacon_info->ie_country_len = (elen + 2);
  4636. + beacon_info->ie_country_ptr = (pos - 2);
  4637. + break;
  4638. + case WLAN_EID_SUPP_RATES:
  4639. + case WLAN_EID_EXT_SUPP_RATES:
  4640. + {
  4641. + int idx, bi, oi;
  4642. + u8 rate;
  4643. +
  4644. + for (bi = 0; bi < SYSADPT_MAX_DATA_RATES_G;
  4645. + bi++) {
  4646. + if (beacon_info->b_rate_set[bi] == 0)
  4647. + break;
  4648. + }
  4649. +
  4650. + for (oi = 0; oi < SYSADPT_MAX_DATA_RATES_G;
  4651. + oi++) {
  4652. + if (beacon_info->op_rate_set[oi] == 0)
  4653. + break;
  4654. + }
  4655. +
  4656. + for (idx = 0; idx < elen; idx++) {
  4657. + rate = pos[idx];
  4658. + if ((rate & 0x80) != 0) {
  4659. + if (bi < SYSADPT_MAX_DATA_RATES_G)
  4660. + beacon_info->b_rate_set[bi++]
  4661. + = rate & 0x7f;
  4662. + else {
  4663. + elem_parse_failed = true;
  4664. + break;
  4665. + }
  4666. + }
  4667. + if (oi < SYSADPT_MAX_DATA_RATES_G)
  4668. + beacon_info->op_rate_set[oi++] =
  4669. + rate & 0x7f;
  4670. + else {
  4671. + elem_parse_failed = true;
  4672. + break;
  4673. + }
  4674. + }
  4675. + }
  4676. + break;
  4677. + case WLAN_EID_PWR_CONSTRAINT:
  4678. + if (elen == 1)
  4679. + beacon_info->power_constraint = *pos;
  4680. + break;
  4681. + case WLAN_EID_RSN:
  4682. + beacon_info->ie_rsn48_len = (elen + 2);
  4683. + beacon_info->ie_rsn48_ptr = (pos - 2);
  4684. + break;
  4685. + case WLAN_EID_MOBILITY_DOMAIN:
  4686. + beacon_info->ie_mde_len = (elen + 2);
  4687. + beacon_info->ie_mde_ptr = (pos - 2);
  4688. + break;
  4689. + case WLAN_EID_HT_CAPABILITY:
  4690. + case WLAN_EID_HT_OPERATION:
  4691. + case WLAN_EID_OVERLAP_BSS_SCAN_PARAM:
  4692. + case WLAN_EID_EXT_CAPABILITY:
  4693. + beacon_info->ie_ht_len += (elen + 2);
  4694. + if (beacon_info->ie_ht_len >
  4695. + sizeof(beacon_info->ie_list_ht)) {
  4696. + elem_parse_failed = true;
  4697. + } else {
  4698. + *beacon_info->ie_ht_ptr++ = id;
  4699. + *beacon_info->ie_ht_ptr++ = elen;
  4700. + memcpy(beacon_info->ie_ht_ptr, pos, elen);
  4701. + beacon_info->ie_ht_ptr += elen;
  4702. + }
  4703. + break;
  4704. + case WLAN_EID_MESH_CONFIG:
  4705. + beacon_info->ie_meshcfg_len = (elen + 2);
  4706. + beacon_info->ie_meshcfg_ptr = (pos - 2);
  4707. + break;
  4708. + case WLAN_EID_MESH_ID:
  4709. + beacon_info->ie_meshid_len = (elen + 2);
  4710. + beacon_info->ie_meshid_ptr = (pos - 2);
  4711. + break;
  4712. + case WLAN_EID_CHAN_SWITCH_PARAM:
  4713. + beacon_info->ie_meshchsw_len = (elen + 2);
  4714. + beacon_info->ie_meshchsw_ptr = (pos - 2);
  4715. + break;
  4716. + case WLAN_EID_VHT_CAPABILITY:
  4717. + case WLAN_EID_VHT_OPERATION:
  4718. + case WLAN_EID_OPMODE_NOTIF:
  4719. + beacon_info->ie_vht_len += (elen + 2);
  4720. + if (beacon_info->ie_vht_len >
  4721. + sizeof(beacon_info->ie_list_vht)) {
  4722. + elem_parse_failed = true;
  4723. + } else {
  4724. + *beacon_info->ie_vht_ptr++ = id;
  4725. + *beacon_info->ie_vht_ptr++ = elen;
  4726. + memcpy(beacon_info->ie_vht_ptr, pos, elen);
  4727. + beacon_info->ie_vht_ptr += elen;
  4728. + }
  4729. + break;
  4730. + case WLAN_EID_VENDOR_SPECIFIC:
  4731. + if ((pos[0] == 0x00) && (pos[1] == 0x50) &&
  4732. + (pos[2] == 0xf2)) {
  4733. + if (pos[3] == 0x01) {
  4734. + beacon_info->ie_rsn_len = (elen + 2);
  4735. + beacon_info->ie_rsn_ptr = (pos - 2);
  4736. + }
  4737. +
  4738. + if (pos[3] == 0x02) {
  4739. + beacon_info->ie_wmm_len = (elen + 2);
  4740. + beacon_info->ie_wmm_ptr = (pos - 2);
  4741. + }
  4742. +
  4743. + if (pos[3] == 0x04) {
  4744. + beacon_info->ie_wsc_len = (elen + 2);
  4745. + beacon_info->ie_wsc_ptr = (pos - 2);
  4746. + }
  4747. + }
  4748. + break;
  4749. + default:
  4750. + break;
  4751. + }
  4752. +
  4753. + left -= elen;
  4754. + pos += elen;
  4755. + }
  4756. +
  4757. + if (!elem_parse_failed) {
  4758. + beacon_info->ie_ht_ptr = &beacon_info->ie_list_ht[0];
  4759. + beacon_info->ie_vht_ptr = &beacon_info->ie_list_vht[0];
  4760. + beacon_info->valid = true;
  4761. + }
  4762. +}
  4763. +
  4764. +static int mwl_fwcmd_set_ies(struct mwl_priv *priv, struct mwl_vif *mwl_vif)
  4765. +{
  4766. + struct hostcmd_cmd_set_ies *pcmd;
  4767. + struct beacon_info *beacon = &mwl_vif->beacon_info;
  4768. + u16 ie_list_len_proprietary = 0;
  4769. +
  4770. + if (beacon->ie_ht_len > sizeof(pcmd->ie_list_ht))
  4771. + goto einval;
  4772. +
  4773. + if (beacon->ie_vht_len > sizeof(pcmd->ie_list_vht))
  4774. + goto einval;
  4775. +
  4776. + pcmd = (struct hostcmd_cmd_set_ies *)&priv->pcmd_buf[0];
  4777. +
  4778. + mutex_lock(&priv->fwcmd_mutex);
  4779. +
  4780. + memset(pcmd, 0x00, sizeof(*pcmd));
  4781. + pcmd->cmd_hdr.cmd = cpu_to_le16(HOSTCMD_CMD_SET_IES);
  4782. + pcmd->cmd_hdr.len = cpu_to_le16(sizeof(*pcmd));
  4783. + pcmd->cmd_hdr.macid = mwl_vif->macid;
  4784. +
  4785. + pcmd->action = cpu_to_le16(HOSTCMD_ACT_GEN_SET);
  4786. +
  4787. + memcpy(pcmd->ie_list_ht, beacon->ie_ht_ptr, beacon->ie_ht_len);
  4788. + pcmd->ie_list_len_ht = cpu_to_le16(beacon->ie_ht_len);
  4789. +
  4790. + memcpy(pcmd->ie_list_vht, beacon->ie_vht_ptr, beacon->ie_vht_len);
  4791. + pcmd->ie_list_len_vht = cpu_to_le16(beacon->ie_vht_len);
  4792. +
  4793. + memcpy(pcmd->ie_list_proprietary, beacon->ie_meshid_ptr,
  4794. + beacon->ie_meshid_len);
  4795. + ie_list_len_proprietary = beacon->ie_meshid_len;
  4796. +
  4797. + memcpy(pcmd->ie_list_proprietary + ie_list_len_proprietary,
  4798. + beacon->ie_meshcfg_ptr, beacon->ie_meshcfg_len);
  4799. + ie_list_len_proprietary += beacon->ie_meshcfg_len;
  4800. +
  4801. + memcpy(pcmd->ie_list_proprietary + ie_list_len_proprietary,
  4802. + beacon->ie_meshchsw_ptr, beacon->ie_meshchsw_len);
  4803. + ie_list_len_proprietary += beacon->ie_meshchsw_len;
  4804. +
  4805. + if (priv->chip_type == MWL8897) {
  4806. + memcpy(pcmd->ie_list_proprietary + ie_list_len_proprietary,
  4807. + beacon->ie_wmm_ptr, beacon->ie_wmm_len);
  4808. + ie_list_len_proprietary += mwl_vif->beacon_info.ie_wmm_len;
  4809. + }
  4810. +
  4811. + memcpy(pcmd->ie_list_proprietary + ie_list_len_proprietary,
  4812. + beacon->ie_mde_ptr, beacon->ie_mde_len);
  4813. + ie_list_len_proprietary += mwl_vif->beacon_info.ie_mde_len;
  4814. +
  4815. + pcmd->ie_list_len_proprietary = cpu_to_le16(ie_list_len_proprietary);
  4816. +
  4817. + if (mwl_hif_exec_cmd(priv->hw, HOSTCMD_CMD_SET_IES)) {
  4818. + mutex_unlock(&priv->fwcmd_mutex);
  4819. + return -EIO;
  4820. + }
  4821. +
  4822. + mutex_unlock(&priv->fwcmd_mutex);
  4823. +
  4824. + return 0;
  4825. +
  4826. +einval:
  4827. +
  4828. + wiphy_err(priv->hw->wiphy, "length of IE is too long\n");
  4829. +
  4830. + return -EINVAL;
  4831. +}
  4832. +
  4833. +static int mwl_fwcmd_set_ap_beacon(struct mwl_priv *priv,
  4834. + struct mwl_vif *mwl_vif,
  4835. + struct ieee80211_bss_conf *bss_conf)
  4836. +{
  4837. + struct hostcmd_cmd_ap_beacon *pcmd;
  4838. + struct ds_params *phy_ds_param_set;
  4839. +
  4840. + /* wmm structure of start command is defined less one byte,
  4841. + * due to following field country is not used, add byte one
  4842. + * to bypass the check.
  4843. + */
  4844. + if (mwl_vif->beacon_info.ie_wmm_len >
  4845. + (sizeof(pcmd->start_cmd.wmm_param) + 1))
  4846. + goto ielenerr;
  4847. +
  4848. + if (mwl_vif->beacon_info.ie_rsn_len > sizeof(pcmd->start_cmd.rsn_ie))
  4849. + goto ielenerr;
  4850. +
  4851. + if (mwl_vif->beacon_info.ie_rsn48_len >
  4852. + sizeof(pcmd->start_cmd.rsn48_ie))
  4853. + goto ielenerr;
  4854. +
  4855. + pcmd = (struct hostcmd_cmd_ap_beacon *)&priv->pcmd_buf[0];
  4856. +
  4857. + mutex_lock(&priv->fwcmd_mutex);
  4858. +
  4859. + memset(pcmd, 0x00, sizeof(*pcmd));
  4860. + pcmd->cmd_hdr.cmd = cpu_to_le16(HOSTCMD_CMD_AP_BEACON);
  4861. + pcmd->cmd_hdr.len = cpu_to_le16(sizeof(*pcmd));
  4862. + pcmd->cmd_hdr.macid = mwl_vif->macid;
  4863. +
  4864. + ether_addr_copy(pcmd->start_cmd.sta_mac_addr, mwl_vif->bssid);
  4865. + memcpy(pcmd->start_cmd.ssid, bss_conf->ssid, bss_conf->ssid_len);
  4866. + if (priv->chip_type == MWL8997)
  4867. + ether_addr_copy(pcmd->start_cmd.bssid, mwl_vif->bssid);
  4868. + pcmd->start_cmd.bss_type = 1;
  4869. + pcmd->start_cmd.bcn_period = cpu_to_le16(bss_conf->beacon_int);
  4870. + pcmd->start_cmd.dtim_period = bss_conf->dtim_period; /* 8bit */
  4871. +
  4872. + phy_ds_param_set = &pcmd->start_cmd.phy_param_set.ds_param_set;
  4873. + phy_ds_param_set->elem_id = WLAN_EID_DS_PARAMS;
  4874. + phy_ds_param_set->len = sizeof(phy_ds_param_set->current_chnl);
  4875. + phy_ds_param_set->current_chnl = bss_conf->chandef.chan->hw_value;
  4876. +
  4877. + pcmd->start_cmd.probe_delay = cpu_to_le16(10);
  4878. + pcmd->start_cmd.cap_info = cpu_to_le16(mwl_vif->beacon_info.cap_info);
  4879. +
  4880. + memcpy(&pcmd->start_cmd.wmm_param, mwl_vif->beacon_info.ie_wmm_ptr,
  4881. + mwl_vif->beacon_info.ie_wmm_len);
  4882. +
  4883. + memcpy(&pcmd->start_cmd.rsn_ie, mwl_vif->beacon_info.ie_rsn_ptr,
  4884. + mwl_vif->beacon_info.ie_rsn_len);
  4885. +
  4886. + memcpy(&pcmd->start_cmd.rsn48_ie, mwl_vif->beacon_info.ie_rsn48_ptr,
  4887. + mwl_vif->beacon_info.ie_rsn48_len);
  4888. +
  4889. + memcpy(pcmd->start_cmd.b_rate_set, mwl_vif->beacon_info.b_rate_set,
  4890. + SYSADPT_MAX_DATA_RATES_G);
  4891. +
  4892. + memcpy(pcmd->start_cmd.op_rate_set, mwl_vif->beacon_info.op_rate_set,
  4893. + SYSADPT_MAX_DATA_RATES_G);
  4894. +
  4895. + if (mwl_hif_exec_cmd(priv->hw, HOSTCMD_CMD_AP_BEACON)) {
  4896. + mutex_unlock(&priv->fwcmd_mutex);
  4897. + return -EIO;
  4898. + }
  4899. +
  4900. + mutex_unlock(&priv->fwcmd_mutex);
  4901. +
  4902. + return 0;
  4903. +
  4904. +ielenerr:
  4905. +
  4906. + wiphy_err(priv->hw->wiphy, "length of IE is too long\n");
  4907. +
  4908. + return -EINVAL;
  4909. +}
  4910. +
  4911. +static int mwl_fwcmd_set_spectrum_mgmt(struct mwl_priv *priv, bool enable)
  4912. +{
  4913. + struct hostcmd_cmd_set_spectrum_mgmt *pcmd;
  4914. +
  4915. + pcmd = (struct hostcmd_cmd_set_spectrum_mgmt *)&priv->pcmd_buf[0];
  4916. +
  4917. + mutex_lock(&priv->fwcmd_mutex);
  4918. +
  4919. + memset(pcmd, 0x00, sizeof(*pcmd));
  4920. + pcmd->cmd_hdr.cmd = cpu_to_le16(HOSTCMD_CMD_SET_SPECTRUM_MGMT);
  4921. + pcmd->cmd_hdr.len = cpu_to_le16(sizeof(*pcmd));
  4922. + pcmd->spectrum_mgmt = cpu_to_le32(enable);
  4923. +
  4924. + if (mwl_hif_exec_cmd(priv->hw, HOSTCMD_CMD_SET_SPECTRUM_MGMT)) {
  4925. + mutex_unlock(&priv->fwcmd_mutex);
  4926. + return -EIO;
  4927. + }
  4928. +
  4929. + mutex_unlock(&priv->fwcmd_mutex);
  4930. +
  4931. + return 0;
  4932. +}
  4933. +
  4934. +static int mwl_fwcmd_set_power_constraint(struct mwl_priv *priv,
  4935. + u32 power_constraint)
  4936. +{
  4937. + struct hostcmd_cmd_set_power_constraint *pcmd;
  4938. +
  4939. + pcmd = (struct hostcmd_cmd_set_power_constraint *)&priv->pcmd_buf[0];
  4940. +
  4941. + mutex_lock(&priv->fwcmd_mutex);
  4942. +
  4943. + memset(pcmd, 0x00, sizeof(*pcmd));
  4944. + pcmd->cmd_hdr.cmd = cpu_to_le16(HOSTCMD_CMD_SET_POWER_CONSTRAINT);
  4945. + pcmd->cmd_hdr.len = cpu_to_le16(sizeof(*pcmd));
  4946. + pcmd->power_constraint = cpu_to_le32(power_constraint);
  4947. +
  4948. + if (mwl_hif_exec_cmd(priv->hw, HOSTCMD_CMD_SET_POWER_CONSTRAINT)) {
  4949. + mutex_unlock(&priv->fwcmd_mutex);
  4950. + return -EIO;
  4951. + }
  4952. +
  4953. + mutex_unlock(&priv->fwcmd_mutex);
  4954. +
  4955. + return 0;
  4956. +}
  4957. +
  4958. +static int mwl_fwcmd_set_country_code(struct mwl_priv *priv,
  4959. + struct mwl_vif *mwl_vif,
  4960. + struct ieee80211_bss_conf *bss_conf)
  4961. +{
  4962. + struct hostcmd_cmd_set_country_code *pcmd;
  4963. + struct beacon_info *b_inf = &mwl_vif->beacon_info;
  4964. + u8 chnl_len;
  4965. + bool a_band;
  4966. + bool enable = false;
  4967. +
  4968. + if (b_inf->ie_country_ptr) {
  4969. + if (bss_conf->chandef.chan->band == NL80211_BAND_2GHZ)
  4970. + a_band = false;
  4971. + else if (bss_conf->chandef.chan->band == NL80211_BAND_5GHZ)
  4972. + a_band = true;
  4973. + else
  4974. + return -EINVAL;
  4975. +
  4976. + chnl_len = b_inf->ie_country_len - 5;
  4977. + if (a_band) {
  4978. + if (chnl_len > sizeof(pcmd->domain_info.domain_entry_a))
  4979. + return -EINVAL;
  4980. + } else {
  4981. + if (chnl_len > sizeof(pcmd->domain_info.domain_entry_g))
  4982. + return -EINVAL;
  4983. + }
  4984. +
  4985. + enable = true;
  4986. + }
  4987. +
  4988. + pcmd = (struct hostcmd_cmd_set_country_code *)&priv->pcmd_buf[0];
  4989. +
  4990. + mutex_lock(&priv->fwcmd_mutex);
  4991. +
  4992. + memset(pcmd, 0x00, sizeof(*pcmd));
  4993. + pcmd->cmd_hdr.cmd = cpu_to_le16(HOSTCMD_CMD_SET_COUNTRY_CODE);
  4994. + pcmd->cmd_hdr.len = cpu_to_le16(sizeof(*pcmd));
  4995. + pcmd->action = cpu_to_le32(enable);
  4996. + if (enable) {
  4997. + memcpy(pcmd->domain_info.country_string,
  4998. + b_inf->ie_country_ptr + 2, 3);
  4999. + if (a_band) {
  5000. + pcmd->domain_info.g_chnl_len = 0;
  5001. + pcmd->domain_info.a_chnl_len = chnl_len;
  5002. + memcpy(pcmd->domain_info.domain_entry_a,
  5003. + b_inf->ie_country_ptr + 5, chnl_len);
  5004. + } else {
  5005. + pcmd->domain_info.a_chnl_len = 0;
  5006. + pcmd->domain_info.g_chnl_len = chnl_len;
  5007. + memcpy(pcmd->domain_info.domain_entry_g,
  5008. + b_inf->ie_country_ptr + 5, chnl_len);
  5009. + }
  5010. + }
  5011. +
  5012. + if (mwl_hif_exec_cmd(priv->hw, HOSTCMD_CMD_SET_COUNTRY_CODE)) {
  5013. + mutex_unlock(&priv->fwcmd_mutex);
  5014. + return -EIO;
  5015. + }
  5016. +
  5017. + mutex_unlock(&priv->fwcmd_mutex);
  5018. +
  5019. + return 0;
  5020. +}
  5021. +
  5022. +static int mwl_fwcmd_encryption_set_cmd_info(struct hostcmd_cmd_set_key *cmd,
  5023. + u8 *addr,
  5024. + struct ieee80211_key_conf *key)
  5025. +{
  5026. + cmd->cmd_hdr.cmd = cpu_to_le16(HOSTCMD_CMD_UPDATE_ENCRYPTION);
  5027. + cmd->cmd_hdr.len = cpu_to_le16(sizeof(*cmd));
  5028. + cmd->key_param.length = cpu_to_le16(sizeof(*cmd) -
  5029. + offsetof(struct hostcmd_cmd_set_key, key_param));
  5030. + cmd->key_param.key_index = cpu_to_le32(key->keyidx);
  5031. + cmd->key_param.key_len = cpu_to_le16(key->keylen);
  5032. + ether_addr_copy(cmd->key_param.mac_addr, addr);
  5033. +
  5034. + switch (key->cipher) {
  5035. + case WLAN_CIPHER_SUITE_WEP40:
  5036. + case WLAN_CIPHER_SUITE_WEP104:
  5037. + cmd->key_param.key_type_id = cpu_to_le16(KEY_TYPE_ID_WEP);
  5038. + if (key->keyidx == 0)
  5039. + cmd->key_param.key_info =
  5040. + cpu_to_le32(ENCR_KEY_FLAG_WEP_TXKEY);
  5041. + break;
  5042. + case WLAN_CIPHER_SUITE_TKIP:
  5043. + cmd->key_param.key_type_id = cpu_to_le16(KEY_TYPE_ID_TKIP);
  5044. + cmd->key_param.key_info =
  5045. + (key->flags & IEEE80211_KEY_FLAG_PAIRWISE) ?
  5046. + cpu_to_le32(ENCR_KEY_FLAG_PAIRWISE) :
  5047. + cpu_to_le32(ENCR_KEY_FLAG_TXGROUPKEY);
  5048. + cmd->key_param.key_info |=
  5049. + cpu_to_le32(ENCR_KEY_FLAG_MICKEY_VALID |
  5050. + ENCR_KEY_FLAG_TSC_VALID);
  5051. + break;
  5052. + case WLAN_CIPHER_SUITE_CCMP:
  5053. + cmd->key_param.key_type_id = cpu_to_le16(KEY_TYPE_ID_AES);
  5054. + cmd->key_param.key_info =
  5055. + (key->flags & IEEE80211_KEY_FLAG_PAIRWISE) ?
  5056. + cpu_to_le32(ENCR_KEY_FLAG_PAIRWISE) :
  5057. + cpu_to_le32(ENCR_KEY_FLAG_TXGROUPKEY);
  5058. + break;
  5059. + case WLAN_CIPHER_SUITE_AES_CMAC:
  5060. + return 1;
  5061. + default:
  5062. + return -ENOTSUPP;
  5063. + }
  5064. +
  5065. + return 0;
  5066. +}
  5067. +
  5068. +static __le16 mwl_fwcmd_parse_cal_cfg(const u8 *src, size_t len, u8 *dst)
  5069. +{
  5070. + const u8 *ptr;
  5071. + u8 *dptr;
  5072. + char byte_str[3];
  5073. + long res;
  5074. +
  5075. + ptr = src;
  5076. + dptr = dst;
  5077. + byte_str[2] = '\0';
  5078. +
  5079. + while (ptr - src < len) {
  5080. + if (*ptr && (isspace(*ptr) || iscntrl(*ptr))) {
  5081. + ptr++;
  5082. + continue;
  5083. + }
  5084. +
  5085. + if (isxdigit(*ptr)) {
  5086. + byte_str[0] = *ptr++;
  5087. + byte_str[1] = *ptr++;
  5088. + kstrtol(byte_str, 16, &res);
  5089. + *dptr++ = res;
  5090. + } else {
  5091. + ptr++;
  5092. + }
  5093. + }
  5094. +
  5095. + return cpu_to_le16(dptr - dst);
  5096. +}
  5097. +
  5098. +static u16 mwl_fwcmd_parse_txpwrlmt_cfg(const u8 *src, size_t len,
  5099. + u16 parse_len, u8 *dst)
  5100. +{
  5101. + const u8 *ptr;
  5102. + u8 *dptr;
  5103. + char byte_str[3];
  5104. + long res;
  5105. +
  5106. + ptr = src;
  5107. + dptr = dst;
  5108. + byte_str[2] = '\0';
  5109. +
  5110. + while ((ptr - src < len) && (dptr - dst < parse_len)) {
  5111. + if (*ptr && (isspace(*ptr) || iscntrl(*ptr))) {
  5112. + ptr++;
  5113. + continue;
  5114. + }
  5115. +
  5116. + if (isxdigit(*ptr)) {
  5117. + byte_str[0] = *ptr++;
  5118. + byte_str[1] = *ptr++;
  5119. + kstrtol(byte_str, 16, &res);
  5120. + *dptr++ = res;
  5121. + } else {
  5122. + ptr++;
  5123. + }
  5124. + }
  5125. +
  5126. + return (ptr - src);
  5127. +}
  5128. +
  5129. +const struct hostcmd_get_hw_spec
  5130. +*mwl_fwcmd_get_hw_specs(struct ieee80211_hw *hw)
  5131. +{
  5132. + struct mwl_priv *priv = hw->priv;
  5133. + struct hostcmd_cmd_get_hw_spec *pcmd;
  5134. + int retry;
  5135. +
  5136. + pcmd = (struct hostcmd_cmd_get_hw_spec *)&priv->pcmd_buf[0];
  5137. +
  5138. + mutex_lock(&priv->fwcmd_mutex);
  5139. +
  5140. + wiphy_debug(hw->wiphy, "pcmd = %p\n", pcmd);
  5141. + memset(pcmd, 0x00, sizeof(*pcmd));
  5142. + eth_broadcast_addr(pcmd->hw_spec.permanent_addr);
  5143. + pcmd->cmd_hdr.cmd = cpu_to_le16(HOSTCMD_CMD_GET_HW_SPEC);
  5144. + pcmd->cmd_hdr.len = cpu_to_le16(sizeof(*pcmd));
  5145. + pcmd->hw_spec.fw_awake_cookie = cpu_to_le32(priv->pphys_cmd_buf + 2048);
  5146. +
  5147. + retry = 0;
  5148. + while (mwl_hif_exec_cmd(hw, HOSTCMD_CMD_GET_HW_SPEC)) {
  5149. + if (retry++ > MAX_WAIT_GET_HW_SPECS_ITERATONS) {
  5150. + wiphy_err(hw->wiphy, "can't get hw specs\n");
  5151. + mutex_unlock(&priv->fwcmd_mutex);
  5152. + return NULL;
  5153. + }
  5154. +
  5155. + msleep(1000);
  5156. + wiphy_debug(hw->wiphy,
  5157. + "repeat command = %p\n", pcmd);
  5158. + }
  5159. +
  5160. + mutex_unlock(&priv->fwcmd_mutex);
  5161. +
  5162. + return &pcmd->hw_spec;
  5163. +}
  5164. +
  5165. +int mwl_fwcmd_set_hw_specs(struct ieee80211_hw *hw,
  5166. + struct hostcmd_set_hw_spec *spec)
  5167. +{
  5168. + struct mwl_priv *priv = hw->priv;
  5169. + struct hostcmd_cmd_set_hw_spec *pcmd;
  5170. +
  5171. + pcmd = (struct hostcmd_cmd_set_hw_spec *)&priv->pcmd_buf[0];
  5172. +
  5173. + mutex_lock(&priv->fwcmd_mutex);
  5174. +
  5175. + memset(pcmd, 0x00, sizeof(*pcmd));
  5176. + pcmd->cmd_hdr.cmd = cpu_to_le16(HOSTCMD_CMD_SET_HW_SPEC);
  5177. + pcmd->cmd_hdr.len = cpu_to_le16(sizeof(*pcmd));
  5178. + memcpy(&pcmd->hw_spec, spec, sizeof(*spec));
  5179. +
  5180. + if (mwl_hif_exec_cmd(hw, HOSTCMD_CMD_SET_HW_SPEC)) {
  5181. + mutex_unlock(&priv->fwcmd_mutex);
  5182. + return -EIO;
  5183. + }
  5184. +
  5185. + mutex_unlock(&priv->fwcmd_mutex);
  5186. +
  5187. + return 0;
  5188. +}
  5189. +
  5190. +int mwl_fwcmd_get_stat(struct ieee80211_hw *hw,
  5191. + struct ieee80211_low_level_stats *stats)
  5192. +{
  5193. + struct mwl_priv *priv = hw->priv;
  5194. + struct hostcmd_cmd_802_11_get_stat *pcmd;
  5195. +
  5196. + pcmd = (struct hostcmd_cmd_802_11_get_stat *)&priv->pcmd_buf[0];
  5197. +
  5198. + mutex_lock(&priv->fwcmd_mutex);
  5199. +
  5200. + memset(pcmd, 0x00, sizeof(*pcmd));
  5201. + pcmd->cmd_hdr.cmd = cpu_to_le16(HOSTCMD_CMD_802_11_GET_STAT);
  5202. + pcmd->cmd_hdr.len = cpu_to_le16(sizeof(*pcmd));
  5203. +
  5204. + if (mwl_hif_exec_cmd(hw, HOSTCMD_CMD_802_11_GET_STAT)) {
  5205. + mutex_unlock(&priv->fwcmd_mutex);
  5206. + return -EIO;
  5207. + }
  5208. +
  5209. + stats->dot11ACKFailureCount =
  5210. + le32_to_cpu(pcmd->ack_failures);
  5211. + stats->dot11RTSFailureCount =
  5212. + le32_to_cpu(pcmd->rts_failures);
  5213. + stats->dot11FCSErrorCount =
  5214. + le32_to_cpu(pcmd->rx_fcs_errors);
  5215. + stats->dot11RTSSuccessCount =
  5216. + le32_to_cpu(pcmd->rts_successes);
  5217. +
  5218. + mutex_unlock(&priv->fwcmd_mutex);
  5219. +
  5220. + return 0;
  5221. +}
  5222. +
  5223. +int mwl_fwcmd_reg_bb(struct ieee80211_hw *hw, u8 flag, u32 reg, u32 *val)
  5224. +{
  5225. + struct mwl_priv *priv = hw->priv;
  5226. + struct hostcmd_cmd_bbp_reg_access *pcmd;
  5227. +
  5228. + pcmd = (struct hostcmd_cmd_bbp_reg_access *)&priv->pcmd_buf[0];
  5229. +
  5230. + mutex_lock(&priv->fwcmd_mutex);
  5231. +
  5232. + memset(pcmd, 0x00, sizeof(*pcmd));
  5233. + pcmd->cmd_hdr.cmd = cpu_to_le16(HOSTCMD_CMD_BBP_REG_ACCESS);
  5234. + pcmd->cmd_hdr.len = cpu_to_le16(sizeof(*pcmd));
  5235. + pcmd->offset = cpu_to_le16(reg);
  5236. + pcmd->action = cpu_to_le16(flag);
  5237. + pcmd->value = *val;
  5238. +
  5239. + if (mwl_hif_exec_cmd(hw, HOSTCMD_CMD_BBP_REG_ACCESS)) {
  5240. + mutex_unlock(&priv->fwcmd_mutex);
  5241. + return -EIO;
  5242. + }
  5243. +
  5244. + *val = pcmd->value;
  5245. + mutex_unlock(&priv->fwcmd_mutex);
  5246. +
  5247. + return 0;
  5248. +}
  5249. +
  5250. +int mwl_fwcmd_reg_rf(struct ieee80211_hw *hw, u8 flag, u32 reg, u32 *val)
  5251. +{
  5252. + struct mwl_priv *priv = hw->priv;
  5253. + struct hostcmd_cmd_rf_reg_access *pcmd;
  5254. +
  5255. + pcmd = (struct hostcmd_cmd_rf_reg_access *)&priv->pcmd_buf[0];
  5256. +
  5257. + mutex_lock(&priv->fwcmd_mutex);
  5258. +
  5259. + memset(pcmd, 0x00, sizeof(*pcmd));
  5260. + pcmd->cmd_hdr.cmd = cpu_to_le16(HOSTCMD_CMD_RF_REG_ACCESS);
  5261. + pcmd->cmd_hdr.len = cpu_to_le16(sizeof(*pcmd));
  5262. + pcmd->offset = cpu_to_le16(reg);
  5263. + pcmd->action = cpu_to_le16(flag);
  5264. + pcmd->value = *val;
  5265. +
  5266. + if (mwl_hif_exec_cmd(hw, HOSTCMD_CMD_RF_REG_ACCESS)) {
  5267. + mutex_unlock(&priv->fwcmd_mutex);
  5268. + return -EIO;
  5269. + }
  5270. +
  5271. + *val = pcmd->value;
  5272. +
  5273. + mutex_unlock(&priv->fwcmd_mutex);
  5274. +
  5275. + return 0;
  5276. +}
  5277. +
  5278. +int mwl_fwcmd_radio_enable(struct ieee80211_hw *hw)
  5279. +{
  5280. + return mwl_fwcmd_802_11_radio_control(hw->priv, true, false);
  5281. +}
  5282. +
  5283. +int mwl_fwcmd_radio_disable(struct ieee80211_hw *hw)
  5284. +{
  5285. + return mwl_fwcmd_802_11_radio_control(hw->priv, false, false);
  5286. +}
  5287. +
  5288. +int mwl_fwcmd_set_radio_preamble(struct ieee80211_hw *hw, bool short_preamble)
  5289. +{
  5290. + struct mwl_priv *priv = hw->priv;
  5291. + int rc;
  5292. +
  5293. + priv->radio_short_preamble = short_preamble;
  5294. + rc = mwl_fwcmd_802_11_radio_control(priv, true, true);
  5295. +
  5296. + return rc;
  5297. +}
  5298. +
  5299. +int mwl_fwcmd_get_addr_value(struct ieee80211_hw *hw, u32 addr, u32 len,
  5300. + u32 *val, u16 set)
  5301. +{
  5302. + struct mwl_priv *priv = hw->priv;
  5303. + struct hostcmd_cmd_mem_addr_access *pcmd;
  5304. + int i;
  5305. +
  5306. + pcmd = (struct hostcmd_cmd_mem_addr_access *)&priv->pcmd_buf[0];
  5307. +
  5308. + mutex_lock(&priv->fwcmd_mutex);
  5309. +
  5310. + memset(pcmd, 0x00, sizeof(*pcmd));
  5311. + pcmd->cmd_hdr.cmd = cpu_to_le16(HOSTCMD_CMD_MEM_ADDR_ACCESS);
  5312. + pcmd->cmd_hdr.len = cpu_to_le16(sizeof(*pcmd));
  5313. + pcmd->address = cpu_to_le32(addr);
  5314. + pcmd->length = cpu_to_le16(len);
  5315. + pcmd->value[0] = cpu_to_le32(*val);
  5316. + pcmd->reserved = cpu_to_le16(set);
  5317. +
  5318. + if (mwl_hif_exec_cmd(hw, HOSTCMD_CMD_MEM_ADDR_ACCESS)) {
  5319. + mutex_unlock(&priv->fwcmd_mutex);
  5320. + return -EIO;
  5321. + }
  5322. +
  5323. + for (i = 0; i < len; i++)
  5324. + val[i] = le32_to_cpu(pcmd->value[i]);
  5325. +
  5326. + mutex_unlock(&priv->fwcmd_mutex);
  5327. +
  5328. + return 0;
  5329. +}
  5330. +
  5331. +int mwl_fwcmd_max_tx_power(struct ieee80211_hw *hw,
  5332. + struct ieee80211_conf *conf, u8 fraction)
  5333. +{
  5334. + struct ieee80211_channel *channel = conf->chandef.chan;
  5335. + struct mwl_priv *priv = hw->priv;
  5336. + int reduce_val = 0;
  5337. + u16 band = 0, width = 0, sub_ch = 0;
  5338. + u16 maxtxpow[SYSADPT_TX_GRP_PWR_LEVEL_TOTAL];
  5339. + int i, tmp;
  5340. + int rc = 0;
  5341. +
  5342. + if ((priv->chip_type != MWL8997) && (priv->forbidden_setting))
  5343. + return rc;
  5344. +
  5345. + switch (fraction) {
  5346. + case 0:
  5347. + reduce_val = 0; /* Max */
  5348. + break;
  5349. + case 1:
  5350. + reduce_val = 2; /* 75% -1.25db */
  5351. + break;
  5352. + case 2:
  5353. + reduce_val = 3; /* 50% -3db */
  5354. + break;
  5355. + case 3:
  5356. + reduce_val = 6; /* 25% -6db */
  5357. + break;
  5358. + default:
  5359. + /* larger than case 3, pCmd->MaxPowerLevel is min */
  5360. + reduce_val = 0xff;
  5361. + break;
  5362. + }
  5363. +
  5364. + if (channel->band == NL80211_BAND_2GHZ)
  5365. + band = FREQ_BAND_2DOT4GHZ;
  5366. + else if (channel->band == NL80211_BAND_5GHZ)
  5367. + band = FREQ_BAND_5GHZ;
  5368. +
  5369. + switch (conf->chandef.width) {
  5370. + case NL80211_CHAN_WIDTH_20_NOHT:
  5371. + case NL80211_CHAN_WIDTH_20:
  5372. + width = CH_20_MHZ_WIDTH;
  5373. + sub_ch = NO_EXT_CHANNEL;
  5374. + break;
  5375. + case NL80211_CHAN_WIDTH_40:
  5376. + width = CH_40_MHZ_WIDTH;
  5377. + if (conf->chandef.center_freq1 > channel->center_freq)
  5378. + sub_ch = EXT_CH_ABOVE_CTRL_CH;
  5379. + else
  5380. + sub_ch = EXT_CH_BELOW_CTRL_CH;
  5381. + break;
  5382. + case NL80211_CHAN_WIDTH_80:
  5383. + width = CH_80_MHZ_WIDTH;
  5384. + if (conf->chandef.center_freq1 > channel->center_freq)
  5385. + sub_ch = EXT_CH_ABOVE_CTRL_CH;
  5386. + else
  5387. + sub_ch = EXT_CH_BELOW_CTRL_CH;
  5388. + break;
  5389. + default:
  5390. + return -EINVAL;
  5391. + }
  5392. +
  5393. + if (priv->chip_type == MWL8997) {
  5394. + mwl_fwcmd_get_tx_powers(priv, priv->max_tx_pow,
  5395. + HOSTCMD_ACT_GET_MAX_TX_PWR,
  5396. + channel->hw_value, band, width, sub_ch);
  5397. +
  5398. + for (i = 0; i < priv->pwr_level; i++) {
  5399. + tmp = priv->max_tx_pow[i];
  5400. + maxtxpow[i] = ((tmp - reduce_val) > 0) ?
  5401. + (tmp - reduce_val) : 0;
  5402. + }
  5403. +
  5404. + rc = mwl_fwcmd_set_tx_powers(priv, maxtxpow,
  5405. + HOSTCMD_ACT_SET_MAX_TX_PWR,
  5406. + channel->hw_value, band,
  5407. + width, sub_ch);
  5408. + return rc;
  5409. + }
  5410. +
  5411. + if ((priv->powinited & MWL_POWER_INIT_2) == 0) {
  5412. + mwl_fwcmd_get_tx_powers(priv, priv->max_tx_pow,
  5413. + HOSTCMD_ACT_GEN_GET_LIST,
  5414. + channel->hw_value, band, width, sub_ch);
  5415. + priv->powinited |= MWL_POWER_INIT_2;
  5416. + }
  5417. +
  5418. + if ((priv->powinited & MWL_POWER_INIT_1) == 0) {
  5419. + mwl_fwcmd_get_tx_powers(priv, priv->target_powers,
  5420. + HOSTCMD_ACT_GEN_GET_LIST,
  5421. + channel->hw_value, band, width, sub_ch);
  5422. + priv->powinited |= MWL_POWER_INIT_1;
  5423. + }
  5424. +
  5425. + for (i = 0; i < priv->pwr_level; i++) {
  5426. + if (priv->target_powers[i] > priv->max_tx_pow[i])
  5427. + tmp = priv->max_tx_pow[i];
  5428. + else
  5429. + tmp = priv->target_powers[i];
  5430. + maxtxpow[i] = ((tmp - reduce_val) > 0) ? (tmp - reduce_val) : 0;
  5431. + }
  5432. +
  5433. + rc = mwl_fwcmd_set_tx_powers(priv, maxtxpow, HOSTCMD_ACT_GEN_SET,
  5434. + channel->hw_value, band, width, sub_ch);
  5435. +
  5436. + return rc;
  5437. +}
  5438. +
  5439. +int mwl_fwcmd_tx_power(struct ieee80211_hw *hw,
  5440. + struct ieee80211_conf *conf, u8 fraction)
  5441. +{
  5442. + struct ieee80211_channel *channel = conf->chandef.chan;
  5443. + struct mwl_priv *priv = hw->priv;
  5444. + int reduce_val = 0;
  5445. + u16 band = 0, width = 0, sub_ch = 0;
  5446. + u16 txpow[SYSADPT_TX_GRP_PWR_LEVEL_TOTAL];
  5447. + int index, found = 0;
  5448. + int i, tmp;
  5449. + int rc = 0;
  5450. +
  5451. + if ((priv->chip_type != MWL8997) && (priv->forbidden_setting))
  5452. + return rc;
  5453. +
  5454. + switch (fraction) {
  5455. + case 0:
  5456. + reduce_val = 0; /* Max */
  5457. + break;
  5458. + case 1:
  5459. + reduce_val = 2; /* 75% -1.25db */
  5460. + break;
  5461. + case 2:
  5462. + reduce_val = 3; /* 50% -3db */
  5463. + break;
  5464. + case 3:
  5465. + reduce_val = 6; /* 25% -6db */
  5466. + break;
  5467. + default:
  5468. + /* larger than case 3, pCmd->MaxPowerLevel is min */
  5469. + reduce_val = 0xff;
  5470. + break;
  5471. + }
  5472. +
  5473. + if (channel->band == NL80211_BAND_2GHZ)
  5474. + band = FREQ_BAND_2DOT4GHZ;
  5475. + else if (channel->band == NL80211_BAND_5GHZ)
  5476. + band = FREQ_BAND_5GHZ;
  5477. +
  5478. + switch (conf->chandef.width) {
  5479. + case NL80211_CHAN_WIDTH_20_NOHT:
  5480. + case NL80211_CHAN_WIDTH_20:
  5481. + width = CH_20_MHZ_WIDTH;
  5482. + sub_ch = NO_EXT_CHANNEL;
  5483. + break;
  5484. + case NL80211_CHAN_WIDTH_40:
  5485. + width = CH_40_MHZ_WIDTH;
  5486. + if (conf->chandef.center_freq1 > channel->center_freq)
  5487. + sub_ch = EXT_CH_ABOVE_CTRL_CH;
  5488. + else
  5489. + sub_ch = EXT_CH_BELOW_CTRL_CH;
  5490. + break;
  5491. + case NL80211_CHAN_WIDTH_80:
  5492. + width = CH_80_MHZ_WIDTH;
  5493. + if (conf->chandef.center_freq1 > channel->center_freq)
  5494. + sub_ch = EXT_CH_ABOVE_CTRL_CH;
  5495. + else
  5496. + sub_ch = EXT_CH_BELOW_CTRL_CH;
  5497. + break;
  5498. + default:
  5499. + return -EINVAL;
  5500. + }
  5501. +
  5502. + if (priv->chip_type == MWL8997) {
  5503. + mwl_fwcmd_get_tx_powers(priv, priv->target_powers,
  5504. + HOSTCMD_ACT_GET_TARGET_TX_PWR,
  5505. + channel->hw_value, band, width, sub_ch);
  5506. +
  5507. + for (i = 0; i < priv->pwr_level; i++) {
  5508. + tmp = priv->target_powers[i];
  5509. + txpow[i] = ((tmp - reduce_val) > 0) ?
  5510. + (tmp - reduce_val) : 0;
  5511. + }
  5512. +
  5513. + rc = mwl_fwcmd_set_tx_powers(priv, txpow,
  5514. + HOSTCMD_ACT_SET_TARGET_TX_PWR,
  5515. + channel->hw_value, band,
  5516. + width, sub_ch);
  5517. +
  5518. + return rc;
  5519. + }
  5520. +
  5521. + /* search tx power table if exist */
  5522. + for (index = 0; index < SYSADPT_MAX_NUM_CHANNELS; index++) {
  5523. + struct mwl_tx_pwr_tbl *tx_pwr;
  5524. +
  5525. + tx_pwr = &priv->tx_pwr_tbl[index];
  5526. +
  5527. + /* do nothing if table is not loaded */
  5528. + if (tx_pwr->channel == 0)
  5529. + break;
  5530. +
  5531. + if (tx_pwr->channel == channel->hw_value) {
  5532. + priv->cdd = tx_pwr->cdd;
  5533. + priv->txantenna2 = tx_pwr->txantenna2;
  5534. +
  5535. + if (tx_pwr->setcap)
  5536. + priv->powinited = MWL_POWER_INIT_1;
  5537. + else
  5538. + priv->powinited = MWL_POWER_INIT_2;
  5539. +
  5540. + for (i = 0; i < priv->pwr_level; i++) {
  5541. + if (tx_pwr->setcap)
  5542. + priv->max_tx_pow[i] =
  5543. + tx_pwr->tx_power[i];
  5544. + else
  5545. + priv->target_powers[i] =
  5546. + tx_pwr->tx_power[i];
  5547. + }
  5548. +
  5549. + found = 1;
  5550. + break;
  5551. + }
  5552. + }
  5553. +
  5554. + if ((priv->powinited & MWL_POWER_INIT_2) == 0) {
  5555. + mwl_fwcmd_get_tx_powers(priv, priv->max_tx_pow,
  5556. + HOSTCMD_ACT_GEN_GET_LIST,
  5557. + channel->hw_value, band, width, sub_ch);
  5558. +
  5559. + priv->powinited |= MWL_POWER_INIT_2;
  5560. + }
  5561. +
  5562. + if ((priv->powinited & MWL_POWER_INIT_1) == 0) {
  5563. + mwl_fwcmd_get_tx_powers(priv, priv->target_powers,
  5564. + HOSTCMD_ACT_GEN_GET_LIST,
  5565. + channel->hw_value, band, width, sub_ch);
  5566. +
  5567. + priv->powinited |= MWL_POWER_INIT_1;
  5568. + }
  5569. +
  5570. + for (i = 0; i < priv->pwr_level; i++) {
  5571. + if (found) {
  5572. + if ((priv->tx_pwr_tbl[index].setcap) &&
  5573. + (priv->tx_pwr_tbl[index].tx_power[i] >
  5574. + priv->max_tx_pow[i]))
  5575. + tmp = priv->max_tx_pow[i];
  5576. + else
  5577. + tmp = priv->tx_pwr_tbl[index].tx_power[i];
  5578. + } else {
  5579. + if (priv->target_powers[i] > priv->max_tx_pow[i])
  5580. + tmp = priv->max_tx_pow[i];
  5581. + else
  5582. + tmp = priv->target_powers[i];
  5583. + }
  5584. +
  5585. + txpow[i] = ((tmp - reduce_val) > 0) ? (tmp - reduce_val) : 0;
  5586. + }
  5587. +
  5588. + rc = mwl_fwcmd_set_tx_powers(priv, txpow, HOSTCMD_ACT_GEN_SET_LIST,
  5589. + channel->hw_value, band, width, sub_ch);
  5590. +
  5591. + return rc;
  5592. +}
  5593. +
  5594. +int mwl_fwcmd_rf_antenna(struct ieee80211_hw *hw, int dir, int antenna)
  5595. +{
  5596. + struct mwl_priv *priv = hw->priv;
  5597. + struct hostcmd_cmd_802_11_rf_antenna *pcmd;
  5598. +
  5599. + pcmd = (struct hostcmd_cmd_802_11_rf_antenna *)&priv->pcmd_buf[0];
  5600. +
  5601. + mutex_lock(&priv->fwcmd_mutex);
  5602. +
  5603. + memset(pcmd, 0x00, sizeof(*pcmd));
  5604. + pcmd->cmd_hdr.cmd = cpu_to_le16(HOSTCMD_CMD_802_11_RF_ANTENNA);
  5605. + pcmd->cmd_hdr.len = cpu_to_le16(sizeof(*pcmd));
  5606. +
  5607. + pcmd->action = cpu_to_le16(dir);
  5608. +
  5609. + if (dir == WL_ANTENNATYPE_RX) {
  5610. + u8 rx_antenna;
  5611. +
  5612. + if (priv->chip_type == MWL8964) {
  5613. + if (antenna == ANTENNA_RX_4_AUTO)
  5614. + rx_antenna = 0xf;
  5615. + else if (antenna == ANTENNA_RX_3)
  5616. + rx_antenna = 7;
  5617. + else if (antenna == ANTENNA_RX_2)
  5618. + rx_antenna = 4;
  5619. + else
  5620. + rx_antenna = 1;
  5621. +
  5622. + pcmd->antenna_mode = cpu_to_le16(rx_antenna);
  5623. + } else {
  5624. + rx_antenna = 4;
  5625. +
  5626. + if (antenna != 0)
  5627. + pcmd->antenna_mode = cpu_to_le16(antenna);
  5628. + else
  5629. + pcmd->antenna_mode = cpu_to_le16(rx_antenna);
  5630. + }
  5631. + } else {
  5632. + u8 tx_antenna = 0xf;
  5633. +
  5634. + if (antenna != 0)
  5635. + pcmd->antenna_mode = cpu_to_le16(antenna);
  5636. + else
  5637. + pcmd->antenna_mode = cpu_to_le16(tx_antenna);
  5638. + }
  5639. +
  5640. + if (mwl_hif_exec_cmd(hw, HOSTCMD_CMD_802_11_RF_ANTENNA)) {
  5641. + mutex_unlock(&priv->fwcmd_mutex);
  5642. + return -EIO;
  5643. + }
  5644. +
  5645. + mutex_unlock(&priv->fwcmd_mutex);
  5646. +
  5647. + return 0;
  5648. +}
  5649. +
  5650. +int mwl_fwcmd_broadcast_ssid_enable(struct ieee80211_hw *hw,
  5651. + struct ieee80211_vif *vif, bool enable)
  5652. +{
  5653. + struct mwl_priv *priv = hw->priv;
  5654. + struct mwl_vif *mwl_vif;
  5655. + struct hostcmd_cmd_broadcast_ssid_enable *pcmd;
  5656. +
  5657. + mwl_vif = mwl_dev_get_vif(vif);
  5658. +
  5659. + pcmd = (struct hostcmd_cmd_broadcast_ssid_enable *)&priv->pcmd_buf[0];
  5660. +
  5661. + mutex_lock(&priv->fwcmd_mutex);
  5662. +
  5663. + memset(pcmd, 0x00, sizeof(*pcmd));
  5664. + pcmd->cmd_hdr.cmd = cpu_to_le16(HOSTCMD_CMD_BROADCAST_SSID_ENABLE);
  5665. + pcmd->cmd_hdr.len = cpu_to_le16(sizeof(*pcmd));
  5666. + pcmd->cmd_hdr.macid = mwl_vif->macid;
  5667. + pcmd->enable = cpu_to_le32(enable);
  5668. + if (priv->chip_type == MWL8997)
  5669. + pcmd->hidden_ssid_info = enable ? 0 : 2;
  5670. +
  5671. + if (mwl_hif_exec_cmd(hw, HOSTCMD_CMD_BROADCAST_SSID_ENABLE)) {
  5672. + mutex_unlock(&priv->fwcmd_mutex);
  5673. + return -EIO;
  5674. + }
  5675. +
  5676. + mutex_unlock(&priv->fwcmd_mutex);
  5677. +
  5678. + return 0;
  5679. +}
  5680. +
  5681. +int mwl_fwcmd_set_cfg_data(struct ieee80211_hw *hw, u16 type)
  5682. +{
  5683. + struct mwl_priv *priv = hw->priv;
  5684. + struct hostcmd_cmd_set_cfg *pcmd;
  5685. +
  5686. + if (!priv->cal_data)
  5687. + return 0;
  5688. +
  5689. + pcmd = (struct hostcmd_cmd_set_cfg *)&priv->pcmd_buf[0];
  5690. +
  5691. + mutex_lock(&priv->fwcmd_mutex);
  5692. +
  5693. + memset(pcmd, 0x00, sizeof(*pcmd));
  5694. + pcmd->data_len = mwl_fwcmd_parse_cal_cfg(priv->cal_data->data,
  5695. + priv->cal_data->size,
  5696. + pcmd->data);
  5697. + pcmd->cmd_hdr.cmd = cpu_to_le16(HOSTCMD_CMD_SET_CFG);
  5698. + pcmd->cmd_hdr.len = cpu_to_le16(sizeof(*pcmd) +
  5699. + le16_to_cpu(pcmd->data_len) - sizeof(pcmd->data));
  5700. + pcmd->action = cpu_to_le16(HOSTCMD_ACT_GEN_SET);
  5701. + pcmd->type = cpu_to_le16(type);
  5702. +
  5703. + utils_dump_data_debug("CalData:", pcmd->data,
  5704. + le16_to_cpu(pcmd->data_len));
  5705. +
  5706. + if (mwl_hif_exec_cmd(hw, HOSTCMD_CMD_SET_CFG)) {
  5707. + mutex_unlock(&priv->fwcmd_mutex);
  5708. + release_firmware(priv->cal_data);
  5709. + priv->cal_data = NULL;
  5710. + return -EIO;
  5711. + }
  5712. +
  5713. + mutex_unlock(&priv->fwcmd_mutex);
  5714. +
  5715. + release_firmware(priv->cal_data);
  5716. + priv->cal_data = NULL;
  5717. +
  5718. + return 0;
  5719. +}
  5720. +
  5721. +int mwl_fwcmd_set_rf_channel(struct ieee80211_hw *hw,
  5722. + struct ieee80211_conf *conf)
  5723. +{
  5724. + struct ieee80211_channel *channel = conf->chandef.chan;
  5725. + struct mwl_priv *priv = hw->priv;
  5726. + struct hostcmd_cmd_set_rf_channel *pcmd;
  5727. + u32 chnl_flags, freq_band, chnl_width, act_primary;
  5728. +
  5729. + pcmd = (struct hostcmd_cmd_set_rf_channel *)&priv->pcmd_buf[0];
  5730. +
  5731. + mutex_lock(&priv->fwcmd_mutex);
  5732. +
  5733. + if (priv->chip_type == MWL8997) {
  5734. + memset(pcmd, 0x00,
  5735. + sizeof(struct hostcmd_cmd_set_rf_channel_kf2));
  5736. + pcmd->cmd_hdr.len = cpu_to_le16(
  5737. + sizeof(struct hostcmd_cmd_set_rf_channel_kf2));
  5738. + } else {
  5739. + memset(pcmd, 0x00, sizeof(*pcmd));
  5740. + pcmd->cmd_hdr.len = cpu_to_le16(sizeof(*pcmd));
  5741. + }
  5742. + pcmd->cmd_hdr.cmd = cpu_to_le16(HOSTCMD_CMD_SET_RF_CHANNEL);
  5743. + pcmd->action = cpu_to_le16(WL_SET);
  5744. + pcmd->curr_chnl = channel->hw_value;
  5745. +
  5746. + if (channel->band == NL80211_BAND_2GHZ) {
  5747. + freq_band = FREQ_BAND_2DOT4GHZ;
  5748. + } else if (channel->band == NL80211_BAND_5GHZ) {
  5749. + freq_band = FREQ_BAND_5GHZ;
  5750. + } else {
  5751. + mutex_unlock(&priv->fwcmd_mutex);
  5752. + return -EINVAL;
  5753. + }
  5754. +
  5755. + switch (conf->chandef.width) {
  5756. + case NL80211_CHAN_WIDTH_20_NOHT:
  5757. + case NL80211_CHAN_WIDTH_20:
  5758. + chnl_width = CH_20_MHZ_WIDTH;
  5759. + act_primary = ACT_PRIMARY_CHAN_0;
  5760. + break;
  5761. + case NL80211_CHAN_WIDTH_40:
  5762. + chnl_width = CH_40_MHZ_WIDTH;
  5763. + if (conf->chandef.center_freq1 > channel->center_freq)
  5764. + act_primary = ACT_PRIMARY_CHAN_0;
  5765. + else
  5766. + act_primary = ACT_PRIMARY_CHAN_1;
  5767. + break;
  5768. + case NL80211_CHAN_WIDTH_80:
  5769. + chnl_width = CH_80_MHZ_WIDTH;
  5770. + act_primary =
  5771. + mwl_fwcmd_get_80m_pri_chnl(pcmd->curr_chnl);
  5772. + break;
  5773. + case NL80211_CHAN_WIDTH_160:
  5774. + chnl_width = CH_160_MHZ_WIDTH;
  5775. + act_primary =
  5776. + mwl_fwcmd_get_160m_pri_chnl(pcmd->curr_chnl);
  5777. + break;
  5778. + default:
  5779. + mutex_unlock(&priv->fwcmd_mutex);
  5780. + return -EINVAL;
  5781. + }
  5782. +
  5783. + chnl_flags = (freq_band & FREQ_BAND_MASK) |
  5784. + ((chnl_width << CHNL_WIDTH_SHIFT) & CHNL_WIDTH_MASK) |
  5785. + ((act_primary << ACT_PRIMARY_SHIFT) & ACT_PRIMARY_MASK);
  5786. +
  5787. + pcmd->chnl_flags = cpu_to_le32(chnl_flags);
  5788. +
  5789. + if (mwl_hif_exec_cmd(hw, HOSTCMD_CMD_SET_RF_CHANNEL)) {
  5790. + mutex_unlock(&priv->fwcmd_mutex);
  5791. + return -EIO;
  5792. + }
  5793. +
  5794. + if (pcmd->cmd_hdr.result != 0) {
  5795. + mutex_unlock(&priv->fwcmd_mutex);
  5796. + return -EINVAL;
  5797. + }
  5798. +
  5799. + mutex_unlock(&priv->fwcmd_mutex);
  5800. +
  5801. + if (priv->sw_scanning) {
  5802. + priv->survey_info_idx++;
  5803. + mwl_fwcmd_get_survey(hw, priv->survey_info_idx);
  5804. + } else {
  5805. + mwl_fwcmd_get_survey(hw, 0);
  5806. + memset(&priv->cur_survey_info, 0,
  5807. + sizeof(struct mwl_survey_info));
  5808. + }
  5809. +
  5810. + return 0;
  5811. +}
  5812. +
  5813. +int mwl_fwcmd_set_aid(struct ieee80211_hw *hw,
  5814. + struct ieee80211_vif *vif, u8 *bssid, u16 aid)
  5815. +{
  5816. + struct mwl_priv *priv = hw->priv;
  5817. + struct mwl_vif *mwl_vif;
  5818. + struct hostcmd_cmd_set_aid *pcmd;
  5819. +
  5820. + mwl_vif = mwl_dev_get_vif(vif);
  5821. +
  5822. + pcmd = (struct hostcmd_cmd_set_aid *)&priv->pcmd_buf[0];
  5823. +
  5824. + mutex_lock(&priv->fwcmd_mutex);
  5825. +
  5826. + memset(pcmd, 0x00, sizeof(*pcmd));
  5827. + pcmd->cmd_hdr.cmd = cpu_to_le16(HOSTCMD_CMD_SET_AID);
  5828. + pcmd->cmd_hdr.len = cpu_to_le16(sizeof(*pcmd));
  5829. + pcmd->cmd_hdr.macid = mwl_vif->macid;
  5830. + pcmd->aid = cpu_to_le16(aid);
  5831. + ether_addr_copy(pcmd->mac_addr, bssid);
  5832. +
  5833. + if (mwl_hif_exec_cmd(hw, HOSTCMD_CMD_SET_AID)) {
  5834. + mutex_unlock(&priv->fwcmd_mutex);
  5835. + return -EIO;
  5836. + }
  5837. +
  5838. + mutex_unlock(&priv->fwcmd_mutex);
  5839. +
  5840. + return 0;
  5841. +}
  5842. +
  5843. +int mwl_fwcmd_set_infra_mode(struct ieee80211_hw *hw,
  5844. + struct ieee80211_vif *vif)
  5845. +{
  5846. + struct mwl_priv *priv = hw->priv;
  5847. + struct mwl_vif *mwl_vif;
  5848. + struct hostcmd_cmd_set_infra_mode *pcmd;
  5849. +
  5850. + mwl_vif = mwl_dev_get_vif(vif);
  5851. +
  5852. + pcmd = (struct hostcmd_cmd_set_infra_mode *)&priv->pcmd_buf[0];
  5853. +
  5854. + mutex_lock(&priv->fwcmd_mutex);
  5855. +
  5856. + memset(pcmd, 0x00, sizeof(*pcmd));
  5857. + pcmd->cmd_hdr.cmd = cpu_to_le16(HOSTCMD_CMD_SET_INFRA_MODE);
  5858. + pcmd->cmd_hdr.len = cpu_to_le16(sizeof(*pcmd));
  5859. + pcmd->cmd_hdr.macid = mwl_vif->macid;
  5860. +
  5861. + if (mwl_hif_exec_cmd(hw, HOSTCMD_CMD_SET_INFRA_MODE)) {
  5862. + mutex_unlock(&priv->fwcmd_mutex);
  5863. + return -EIO;
  5864. + }
  5865. +
  5866. + mutex_unlock(&priv->fwcmd_mutex);
  5867. +
  5868. + return 0;
  5869. +}
  5870. +
  5871. +int mwl_fwcmd_set_rts_threshold(struct ieee80211_hw *hw, int threshold)
  5872. +{
  5873. + struct mwl_priv *priv = hw->priv;
  5874. + struct hostcmd_cmd_802_11_rts_thsd *pcmd;
  5875. +
  5876. + pcmd = (struct hostcmd_cmd_802_11_rts_thsd *)&priv->pcmd_buf[0];
  5877. +
  5878. + mutex_lock(&priv->fwcmd_mutex);
  5879. +
  5880. + memset(pcmd, 0x00, sizeof(*pcmd));
  5881. + pcmd->cmd_hdr.cmd = cpu_to_le16(HOSTCMD_CMD_802_11_RTS_THSD);
  5882. + pcmd->cmd_hdr.len = cpu_to_le16(sizeof(*pcmd));
  5883. + pcmd->action = cpu_to_le16(WL_SET);
  5884. + pcmd->threshold = cpu_to_le16(threshold);
  5885. +
  5886. + if (mwl_hif_exec_cmd(hw, HOSTCMD_CMD_802_11_RTS_THSD)) {
  5887. + mutex_unlock(&priv->fwcmd_mutex);
  5888. + return -EIO;
  5889. + }
  5890. +
  5891. + mutex_unlock(&priv->fwcmd_mutex);
  5892. +
  5893. + return 0;
  5894. +}
  5895. +
  5896. +int mwl_fwcmd_set_edca_params(struct ieee80211_hw *hw, u8 index,
  5897. + u16 cw_min, u16 cw_max, u8 aifs, u16 txop)
  5898. +{
  5899. + struct mwl_priv *priv = hw->priv;
  5900. + struct hostcmd_cmd_set_edca_params *pcmd;
  5901. +
  5902. + pcmd = (struct hostcmd_cmd_set_edca_params *)&priv->pcmd_buf[0];
  5903. +
  5904. + mutex_lock(&priv->fwcmd_mutex);
  5905. +
  5906. + memset(pcmd, 0x00, sizeof(*pcmd));
  5907. + pcmd->cmd_hdr.cmd = cpu_to_le16(HOSTCMD_CMD_SET_EDCA_PARAMS);
  5908. + pcmd->cmd_hdr.len = cpu_to_le16(sizeof(*pcmd));
  5909. +
  5910. + pcmd->action = cpu_to_le16(0xffff);
  5911. + pcmd->txop = cpu_to_le16(txop);
  5912. + pcmd->cw_max = cpu_to_le32(cw_max);
  5913. + pcmd->cw_min = cpu_to_le32(cw_min);
  5914. + pcmd->aifsn = aifs;
  5915. + pcmd->txq_num = index;
  5916. +
  5917. + if (mwl_hif_exec_cmd(hw, HOSTCMD_CMD_SET_EDCA_PARAMS)) {
  5918. + mutex_unlock(&priv->fwcmd_mutex);
  5919. + return -EIO;
  5920. + }
  5921. +
  5922. + mutex_unlock(&priv->fwcmd_mutex);
  5923. +
  5924. + return 0;
  5925. +}
  5926. +
  5927. +int mwl_fwcmd_set_radar_detect(struct ieee80211_hw *hw, u16 action)
  5928. +{
  5929. + struct mwl_priv *priv = hw->priv;
  5930. + struct hostcmd_cmd_802_11h_detect_radar *pcmd;
  5931. + u16 radar_type = RADAR_TYPE_CODE_0;
  5932. + u8 channel = hw->conf.chandef.chan->hw_value;
  5933. +
  5934. + pcmd = (struct hostcmd_cmd_802_11h_detect_radar *)&priv->pcmd_buf[0];
  5935. +
  5936. + if (priv->dfs_region == NL80211_DFS_JP) {
  5937. + if (channel >= 52 && channel <= 64)
  5938. + radar_type = RADAR_TYPE_CODE_53;
  5939. + else if (channel >= 100 && channel <= 140)
  5940. + radar_type = RADAR_TYPE_CODE_56;
  5941. + else
  5942. + radar_type = RADAR_TYPE_CODE_0;
  5943. + } else if (priv->dfs_region == NL80211_DFS_ETSI) {
  5944. + radar_type = RADAR_TYPE_CODE_ETSI;
  5945. + }
  5946. +
  5947. + mutex_lock(&priv->fwcmd_mutex);
  5948. +
  5949. + memset(pcmd, 0x00, sizeof(*pcmd));
  5950. + pcmd->cmd_hdr.cmd = cpu_to_le16(HOSTCMD_CMD_802_11H_DETECT_RADAR);
  5951. + pcmd->cmd_hdr.len = cpu_to_le16(sizeof(*pcmd));
  5952. + pcmd->action = cpu_to_le16(action);
  5953. + pcmd->radar_type_code = cpu_to_le16(radar_type);
  5954. + pcmd->min_chirp_cnt = cpu_to_le16(priv->dfs_chirp_count_min);
  5955. + pcmd->chirp_time_intvl = cpu_to_le16(priv->dfs_chirp_time_interval);
  5956. + pcmd->pw_filter = cpu_to_le16(priv->dfs_pw_filter);
  5957. + pcmd->min_num_radar = cpu_to_le16(priv->dfs_min_num_radar);
  5958. + pcmd->pri_min_num = cpu_to_le16(priv->dfs_min_pri_count);
  5959. +
  5960. + if (mwl_hif_exec_cmd(hw, HOSTCMD_CMD_802_11H_DETECT_RADAR)) {
  5961. + mutex_unlock(&priv->fwcmd_mutex);
  5962. + return -EIO;
  5963. + }
  5964. +
  5965. + mutex_unlock(&priv->fwcmd_mutex);
  5966. +
  5967. + return 0;
  5968. +}
  5969. +
  5970. +int mwl_fwcmd_set_wmm_mode(struct ieee80211_hw *hw, bool enable)
  5971. +{
  5972. + struct mwl_priv *priv = hw->priv;
  5973. + struct hostcmd_cmd_set_wmm_mode *pcmd;
  5974. +
  5975. + pcmd = (struct hostcmd_cmd_set_wmm_mode *)&priv->pcmd_buf[0];
  5976. +
  5977. + mutex_lock(&priv->fwcmd_mutex);
  5978. +
  5979. + memset(pcmd, 0x00, sizeof(*pcmd));
  5980. + pcmd->cmd_hdr.cmd = cpu_to_le16(HOSTCMD_CMD_SET_WMM_MODE);
  5981. + pcmd->cmd_hdr.len = cpu_to_le16(sizeof(*pcmd));
  5982. + pcmd->action = cpu_to_le16(enable ? WL_ENABLE : WL_DISABLE);
  5983. +
  5984. + if (mwl_hif_exec_cmd(hw, HOSTCMD_CMD_SET_WMM_MODE)) {
  5985. + mutex_unlock(&priv->fwcmd_mutex);
  5986. + return -EIO;
  5987. + }
  5988. +
  5989. + mutex_unlock(&priv->fwcmd_mutex);
  5990. +
  5991. + return 0;
  5992. +}
  5993. +
  5994. +int mwl_fwcmd_ht_guard_interval(struct ieee80211_hw *hw, u32 gi_type)
  5995. +{
  5996. + struct mwl_priv *priv = hw->priv;
  5997. + struct hostcmd_cmd_ht_guard_interval *pcmd;
  5998. +
  5999. + pcmd = (struct hostcmd_cmd_ht_guard_interval *)&priv->pcmd_buf[0];
  6000. +
  6001. + mutex_lock(&priv->fwcmd_mutex);
  6002. +
  6003. + memset(pcmd, 0x00, sizeof(*pcmd));
  6004. + pcmd->cmd_hdr.cmd = cpu_to_le16(HOSTCMD_CMD_HT_GUARD_INTERVAL);
  6005. + pcmd->cmd_hdr.len = cpu_to_le16(sizeof(*pcmd));
  6006. + pcmd->action = cpu_to_le32(WL_SET);
  6007. + pcmd->gi_type = cpu_to_le32(gi_type);
  6008. +
  6009. + if (mwl_hif_exec_cmd(hw, HOSTCMD_CMD_HT_GUARD_INTERVAL)) {
  6010. + mutex_unlock(&priv->fwcmd_mutex);
  6011. + return -EIO;
  6012. + }
  6013. +
  6014. + mutex_unlock(&priv->fwcmd_mutex);
  6015. +
  6016. + return 0;
  6017. +}
  6018. +
  6019. +int mwl_fwcmd_use_fixed_rate(struct ieee80211_hw *hw, int mcast, int mgmt)
  6020. +{
  6021. + struct mwl_priv *priv = hw->priv;
  6022. + struct hostcmd_cmd_set_fixed_rate *pcmd;
  6023. +
  6024. + pcmd = (struct hostcmd_cmd_set_fixed_rate *)&priv->pcmd_buf[0];
  6025. +
  6026. + mutex_lock(&priv->fwcmd_mutex);
  6027. +
  6028. + memset(pcmd, 0x00, sizeof(*pcmd));
  6029. + pcmd->cmd_hdr.cmd = cpu_to_le16(HOSTCMD_CMD_SET_FIXED_RATE);
  6030. + pcmd->cmd_hdr.len = cpu_to_le16(sizeof(*pcmd));
  6031. +
  6032. + pcmd->action = cpu_to_le32(HOSTCMD_ACT_NOT_USE_FIXED_RATE);
  6033. + pcmd->multicast_rate = mcast;
  6034. + pcmd->management_rate = mgmt;
  6035. +
  6036. + if (mwl_hif_exec_cmd(hw, HOSTCMD_CMD_SET_FIXED_RATE)) {
  6037. + mutex_unlock(&priv->fwcmd_mutex);
  6038. + return -EIO;
  6039. + }
  6040. +
  6041. + mutex_unlock(&priv->fwcmd_mutex);
  6042. +
  6043. + return 0;
  6044. +}
  6045. +
  6046. +int mwl_fwcmd_set_linkadapt_cs_mode(struct ieee80211_hw *hw, u16 cs_mode)
  6047. +{
  6048. + struct mwl_priv *priv = hw->priv;
  6049. + struct hostcmd_cmd_set_linkadapt_cs_mode *pcmd;
  6050. +
  6051. + pcmd = (struct hostcmd_cmd_set_linkadapt_cs_mode *)&priv->pcmd_buf[0];
  6052. +
  6053. + mutex_lock(&priv->fwcmd_mutex);
  6054. +
  6055. + memset(pcmd, 0x00, sizeof(*pcmd));
  6056. + pcmd->cmd_hdr.cmd = cpu_to_le16(HOSTCMD_CMD_SET_LINKADAPT_CS_MODE);
  6057. + pcmd->cmd_hdr.len = cpu_to_le16(sizeof(*pcmd));
  6058. + pcmd->action = cpu_to_le16(HOSTCMD_ACT_GEN_SET);
  6059. + pcmd->cs_mode = cpu_to_le16(cs_mode);
  6060. +
  6061. + if (mwl_hif_exec_cmd(hw, HOSTCMD_CMD_SET_LINKADAPT_CS_MODE)) {
  6062. + mutex_unlock(&priv->fwcmd_mutex);
  6063. + return -EIO;
  6064. + }
  6065. +
  6066. + mutex_unlock(&priv->fwcmd_mutex);
  6067. +
  6068. + return 0;
  6069. +}
  6070. +
  6071. +int mwl_fwcmd_dump_otp_data(struct ieee80211_hw *hw)
  6072. +{
  6073. + int otp_data_len;
  6074. + struct mwl_priv *priv = hw->priv;
  6075. + struct hostcmd_cmd_dump_otp_data *pcmd;
  6076. +
  6077. + pcmd = (struct hostcmd_cmd_dump_otp_data *)&priv->pcmd_buf[0];
  6078. +
  6079. + mutex_lock(&priv->fwcmd_mutex);
  6080. +
  6081. + memset(pcmd, 0x00, sizeof(*pcmd));
  6082. + pcmd->cmd_hdr.cmd = cpu_to_le16(HOSTCMD_CMD_DUMP_OTP_DATA);
  6083. + pcmd->cmd_hdr.len = cpu_to_le16(sizeof(*pcmd));
  6084. +
  6085. + if (mwl_hif_exec_cmd(hw, HOSTCMD_CMD_DUMP_OTP_DATA)) {
  6086. + mutex_unlock(&priv->fwcmd_mutex);
  6087. + return -EIO;
  6088. + }
  6089. +
  6090. + otp_data_len = pcmd->cmd_hdr.len - cpu_to_le16(sizeof(*pcmd));
  6091. +
  6092. + if (otp_data_len <= SYSADPT_OTP_BUF_SIZE) {
  6093. + wiphy_info(hw->wiphy, "OTP data len = %d\n", otp_data_len);
  6094. + priv->otp_data.len = otp_data_len;
  6095. + memcpy(priv->otp_data.buf, pcmd->pload, otp_data_len);
  6096. + } else {
  6097. + wiphy_err(hw->wiphy, "Driver OTP buf size is less\n");
  6098. + }
  6099. +
  6100. + mutex_unlock(&priv->fwcmd_mutex);
  6101. +
  6102. + return 0;
  6103. +}
  6104. +
  6105. +int mwl_fwcmd_set_rate_adapt_mode(struct ieee80211_hw *hw, u16 mode)
  6106. +{
  6107. + struct mwl_priv *priv = hw->priv;
  6108. + struct hostcmd_cmd_set_rate_adapt_mode *pcmd;
  6109. +
  6110. + pcmd = (struct hostcmd_cmd_set_rate_adapt_mode *)&priv->pcmd_buf[0];
  6111. +
  6112. + mutex_lock(&priv->fwcmd_mutex);
  6113. +
  6114. + memset(pcmd, 0x00, sizeof(*pcmd));
  6115. + pcmd->cmd_hdr.cmd = cpu_to_le16(HOSTCMD_CMD_SET_RATE_ADAPT_MODE);
  6116. + pcmd->cmd_hdr.len = cpu_to_le16(sizeof(*pcmd));
  6117. + pcmd->action = cpu_to_le16(WL_SET);
  6118. + pcmd->rate_adapt_mode = cpu_to_le16(mode);
  6119. +
  6120. + if (mwl_hif_exec_cmd(hw, HOSTCMD_CMD_SET_RATE_ADAPT_MODE)) {
  6121. + mutex_unlock(&priv->fwcmd_mutex);
  6122. + return -EIO;
  6123. + }
  6124. +
  6125. + mutex_unlock(&priv->fwcmd_mutex);
  6126. +
  6127. + return 0;
  6128. +}
  6129. +
  6130. +int mwl_fwcmd_set_mac_addr_client(struct ieee80211_hw *hw,
  6131. + struct ieee80211_vif *vif, u8 *mac_addr)
  6132. +{
  6133. + struct mwl_priv *priv = hw->priv;
  6134. + struct mwl_vif *mwl_vif;
  6135. + struct hostcmd_cmd_set_mac_addr *pcmd;
  6136. +
  6137. + mwl_vif = mwl_dev_get_vif(vif);
  6138. +
  6139. + pcmd = (struct hostcmd_cmd_set_mac_addr *)&priv->pcmd_buf[0];
  6140. +
  6141. + mutex_lock(&priv->fwcmd_mutex);
  6142. +
  6143. + memset(pcmd, 0x00, sizeof(*pcmd));
  6144. + pcmd->cmd_hdr.cmd = cpu_to_le16(HOSTCMD_CMD_SET_MAC_ADDR);
  6145. + pcmd->cmd_hdr.len = cpu_to_le16(sizeof(*pcmd));
  6146. + pcmd->cmd_hdr.macid = mwl_vif->macid;
  6147. + pcmd->mac_type = cpu_to_le16(WL_MAC_TYPE_SECONDARY_CLIENT);
  6148. + ether_addr_copy(pcmd->mac_addr, mac_addr);
  6149. +
  6150. + if (mwl_hif_exec_cmd(hw, HOSTCMD_CMD_SET_MAC_ADDR)) {
  6151. + mutex_unlock(&priv->fwcmd_mutex);
  6152. + return -EIO;
  6153. + }
  6154. +
  6155. + mutex_unlock(&priv->fwcmd_mutex);
  6156. +
  6157. + return 0;
  6158. +}
  6159. +
  6160. +int mwl_fwcmd_get_watchdog_bitmap(struct ieee80211_hw *hw, u8 *bitmap)
  6161. +{
  6162. + struct mwl_priv *priv = hw->priv;
  6163. + struct hostcmd_cmd_get_watchdog_bitmap *pcmd;
  6164. +
  6165. + pcmd = (struct hostcmd_cmd_get_watchdog_bitmap *)&priv->pcmd_buf[0];
  6166. +
  6167. + mutex_lock(&priv->fwcmd_mutex);
  6168. +
  6169. + memset(pcmd, 0x00, sizeof(*pcmd));
  6170. + pcmd->cmd_hdr.cmd = cpu_to_le16(HOSTCMD_CMD_GET_WATCHDOG_BITMAP);
  6171. + pcmd->cmd_hdr.len = cpu_to_le16(sizeof(*pcmd));
  6172. +
  6173. + if (mwl_hif_exec_cmd(hw, HOSTCMD_CMD_GET_WATCHDOG_BITMAP)) {
  6174. + mutex_unlock(&priv->fwcmd_mutex);
  6175. + return -EIO;
  6176. + }
  6177. +
  6178. + *bitmap = pcmd->watchdog_bitmap;
  6179. +
  6180. + mutex_unlock(&priv->fwcmd_mutex);
  6181. +
  6182. + return 0;
  6183. +}
  6184. +
  6185. +int mwl_fwcmd_remove_mac_addr(struct ieee80211_hw *hw,
  6186. + struct ieee80211_vif *vif, u8 *mac_addr)
  6187. +{
  6188. + struct mwl_priv *priv = hw->priv;
  6189. + struct mwl_vif *mwl_vif;
  6190. + struct hostcmd_cmd_set_mac_addr *pcmd;
  6191. +
  6192. + mwl_vif = mwl_dev_get_vif(vif);
  6193. +
  6194. + pcmd = (struct hostcmd_cmd_set_mac_addr *)&priv->pcmd_buf[0];
  6195. +
  6196. + mutex_lock(&priv->fwcmd_mutex);
  6197. +
  6198. + memset(pcmd, 0x00, sizeof(*pcmd));
  6199. + pcmd->cmd_hdr.cmd = cpu_to_le16(HOSTCMD_CMD_DEL_MAC_ADDR);
  6200. + pcmd->cmd_hdr.len = cpu_to_le16(sizeof(*pcmd));
  6201. + pcmd->cmd_hdr.macid = mwl_vif->macid;
  6202. + ether_addr_copy(pcmd->mac_addr, mac_addr);
  6203. +
  6204. + if (mwl_hif_exec_cmd(hw, HOSTCMD_CMD_DEL_MAC_ADDR)) {
  6205. + mutex_unlock(&priv->fwcmd_mutex);
  6206. + return -EIO;
  6207. + }
  6208. +
  6209. + mutex_unlock(&priv->fwcmd_mutex);
  6210. +
  6211. + return 0;
  6212. +}
  6213. +
  6214. +int mwl_fwcmd_bss_start(struct ieee80211_hw *hw,
  6215. + struct ieee80211_vif *vif, bool enable)
  6216. +{
  6217. + struct mwl_priv *priv = hw->priv;
  6218. + struct mwl_vif *mwl_vif;
  6219. + struct hostcmd_cmd_bss_start *pcmd;
  6220. +
  6221. + mwl_vif = mwl_dev_get_vif(vif);
  6222. +
  6223. + if (enable && (priv->running_bsses & (1 << mwl_vif->macid)))
  6224. + return 0;
  6225. +
  6226. + if (!enable && !(priv->running_bsses & (1 << mwl_vif->macid)))
  6227. + return 0;
  6228. +
  6229. + pcmd = (struct hostcmd_cmd_bss_start *)&priv->pcmd_buf[0];
  6230. +
  6231. + mutex_lock(&priv->fwcmd_mutex);
  6232. +
  6233. + memset(pcmd, 0x00, sizeof(*pcmd));
  6234. + pcmd->cmd_hdr.cmd = cpu_to_le16(HOSTCMD_CMD_BSS_START);
  6235. + pcmd->cmd_hdr.len = cpu_to_le16(sizeof(*pcmd));
  6236. + pcmd->cmd_hdr.macid = mwl_vif->macid;
  6237. +
  6238. + if (enable) {
  6239. + pcmd->enable = cpu_to_le32(WL_ENABLE);
  6240. + } else {
  6241. + if (mwl_vif->macid == 0)
  6242. + pcmd->enable = cpu_to_le32(WL_DISABLE);
  6243. + else
  6244. + pcmd->enable = cpu_to_le32(WL_DISABLE_VMAC);
  6245. + }
  6246. + if (priv->chip_type == MWL8964)
  6247. + pcmd->amsdu = MWL_AMSDU_SIZE_11K;
  6248. +
  6249. + if (mwl_hif_exec_cmd(hw, HOSTCMD_CMD_BSS_START)) {
  6250. + mutex_unlock(&priv->fwcmd_mutex);
  6251. + return -EIO;
  6252. + }
  6253. +
  6254. + if (enable)
  6255. + priv->running_bsses |= (1 << mwl_vif->macid);
  6256. + else
  6257. + priv->running_bsses &= ~(1 << mwl_vif->macid);
  6258. +
  6259. + mutex_unlock(&priv->fwcmd_mutex);
  6260. +
  6261. + return 0;
  6262. +}
  6263. +
  6264. +int mwl_fwcmd_set_beacon(struct ieee80211_hw *hw,
  6265. + struct ieee80211_vif *vif, u8 *beacon, int len)
  6266. +{
  6267. + struct mwl_priv *priv = hw->priv;
  6268. + struct mwl_vif *mwl_vif;
  6269. + struct beacon_info *b_inf;
  6270. + int rc;
  6271. +
  6272. + mwl_vif = mwl_dev_get_vif(vif);
  6273. + b_inf = &mwl_vif->beacon_info;
  6274. +
  6275. + mwl_fwcmd_parse_beacon(priv, mwl_vif, beacon, len);
  6276. +
  6277. + if (!b_inf->valid)
  6278. + goto err;
  6279. +
  6280. + if (mwl_fwcmd_set_ies(priv, mwl_vif))
  6281. + goto err;
  6282. +
  6283. + if (mwl_fwcmd_set_wsc_ie(hw, b_inf->ie_wsc_len, b_inf->ie_wsc_ptr))
  6284. + goto err;
  6285. +
  6286. + if (mwl_fwcmd_set_ap_beacon(priv, mwl_vif, &vif->bss_conf))
  6287. + goto err;
  6288. +
  6289. + if (b_inf->cap_info & WLAN_CAPABILITY_SPECTRUM_MGMT)
  6290. + rc = mwl_fwcmd_set_spectrum_mgmt(priv, true);
  6291. + else
  6292. + rc = mwl_fwcmd_set_spectrum_mgmt(priv, false);
  6293. + if (rc)
  6294. + goto err;
  6295. +
  6296. + if (b_inf->power_constraint)
  6297. + rc = mwl_fwcmd_set_power_constraint(priv,
  6298. + b_inf->power_constraint);
  6299. + if (rc)
  6300. + goto err;
  6301. +
  6302. + if (mwl_fwcmd_set_country_code(priv, mwl_vif, &vif->bss_conf))
  6303. + goto err;
  6304. +
  6305. + b_inf->valid = false;
  6306. +
  6307. + return 0;
  6308. +
  6309. +err:
  6310. +
  6311. + b_inf->valid = false;
  6312. +
  6313. + return -EIO;
  6314. +}
  6315. +
  6316. +int mwl_fwcmd_set_new_stn_add(struct ieee80211_hw *hw,
  6317. + struct ieee80211_vif *vif,
  6318. + struct ieee80211_sta *sta)
  6319. +{
  6320. + struct mwl_priv *priv = hw->priv;
  6321. + struct mwl_vif *mwl_vif;
  6322. + struct mwl_sta *sta_info;
  6323. + struct hostcmd_cmd_set_new_stn *pcmd;
  6324. + u32 rates;
  6325. +
  6326. + mwl_vif = mwl_dev_get_vif(vif);
  6327. + sta_info = mwl_dev_get_sta(sta);
  6328. +
  6329. + pcmd = (struct hostcmd_cmd_set_new_stn *)&priv->pcmd_buf[0];
  6330. +
  6331. + mutex_lock(&priv->fwcmd_mutex);
  6332. +
  6333. + memset(pcmd, 0x00, sizeof(*pcmd));
  6334. + pcmd->cmd_hdr.cmd = cpu_to_le16(HOSTCMD_CMD_SET_NEW_STN);
  6335. + pcmd->cmd_hdr.len = cpu_to_le16(sizeof(*pcmd));
  6336. + pcmd->cmd_hdr.macid = mwl_vif->macid;
  6337. +
  6338. + pcmd->action = cpu_to_le16(HOSTCMD_ACT_STA_ACTION_ADD);
  6339. + pcmd->aid = cpu_to_le16(sta->aid);
  6340. + pcmd->stn_id = cpu_to_le16(sta_info->stnid);
  6341. + if (priv->chip_type == MWL8997)
  6342. + pcmd->if_type = cpu_to_le16(vif->type);
  6343. + else
  6344. + pcmd->if_type = cpu_to_le16(1);
  6345. + ether_addr_copy(pcmd->mac_addr, sta->addr);
  6346. +
  6347. + if (hw->conf.chandef.chan->band == NL80211_BAND_2GHZ)
  6348. + rates = sta->supp_rates[NL80211_BAND_2GHZ];
  6349. + else
  6350. + rates = sta->supp_rates[NL80211_BAND_5GHZ] << 5;
  6351. + pcmd->peer_info.legacy_rate_bitmap = cpu_to_le32(rates);
  6352. +
  6353. + if (sta->ht_cap.ht_supported) {
  6354. + int i;
  6355. +
  6356. + for (i = 0; i < 4; i++) {
  6357. + if (i < sta->rx_nss) {
  6358. + pcmd->peer_info.ht_rates[i] =
  6359. + sta->ht_cap.mcs.rx_mask[i];
  6360. + } else {
  6361. + pcmd->peer_info.ht_rates[i] = 0;
  6362. + }
  6363. + }
  6364. + pcmd->peer_info.ht_cap_info = cpu_to_le16(sta->ht_cap.cap);
  6365. + pcmd->peer_info.mac_ht_param_info =
  6366. + (sta->ht_cap.ampdu_factor & 3) |
  6367. + ((sta->ht_cap.ampdu_density & 7) << 2);
  6368. + }
  6369. +
  6370. + if (sta->vht_cap.vht_supported) {
  6371. + u32 rx_mcs_map_mask = 0;
  6372. +
  6373. + rx_mcs_map_mask = ((0x0000FFFF) >> (sta->rx_nss * 2))
  6374. + << (sta->rx_nss * 2);
  6375. + pcmd->peer_info.vht_max_rx_mcs =
  6376. + cpu_to_le32((*((u32 *)
  6377. + &sta->vht_cap.vht_mcs.rx_mcs_map)) | rx_mcs_map_mask);
  6378. + pcmd->peer_info.vht_cap = cpu_to_le32(sta->vht_cap.cap);
  6379. + pcmd->peer_info.vht_rx_channel_width = sta->bandwidth;
  6380. + }
  6381. +
  6382. + pcmd->is_qos_sta = sta->wme;
  6383. + pcmd->qos_info = ((sta->uapsd_queues << 4) | (sta->max_sp << 1));
  6384. +
  6385. + if (mwl_hif_exec_cmd(hw, HOSTCMD_CMD_SET_NEW_STN)) {
  6386. + mutex_unlock(&priv->fwcmd_mutex);
  6387. + return -EIO;
  6388. + }
  6389. +
  6390. + if (vif->type == NL80211_IFTYPE_STATION) {
  6391. + ether_addr_copy(pcmd->mac_addr, mwl_vif->sta_mac);
  6392. + pcmd->aid = cpu_to_le16(sta->aid + 1);
  6393. + pcmd->stn_id = cpu_to_le16(sta_info->sta_stnid);
  6394. + pcmd->if_type = cpu_to_le16(0);
  6395. + if (mwl_hif_exec_cmd(hw, HOSTCMD_CMD_SET_NEW_STN)) {
  6396. + mutex_unlock(&priv->fwcmd_mutex);
  6397. + return -EIO;
  6398. + }
  6399. + }
  6400. +
  6401. + mutex_unlock(&priv->fwcmd_mutex);
  6402. +
  6403. + return 0;
  6404. +}
  6405. +
  6406. +int mwl_fwcmd_set_new_stn_add_sc4(struct ieee80211_hw *hw,
  6407. + struct ieee80211_vif *vif,
  6408. + struct ieee80211_sta *sta,
  6409. + u32 wds)
  6410. +{
  6411. + struct mwl_priv *priv = hw->priv;
  6412. + struct mwl_vif *mwl_vif;
  6413. + struct mwl_sta *sta_info;
  6414. + struct hostcmd_cmd_set_new_stn_sc4 *pcmd;
  6415. + u32 rates;
  6416. +
  6417. + mwl_vif = mwl_dev_get_vif(vif);
  6418. + sta_info = mwl_dev_get_sta(sta);
  6419. +
  6420. + pcmd = (struct hostcmd_cmd_set_new_stn_sc4 *)&priv->pcmd_buf[0];
  6421. +
  6422. + mutex_lock(&priv->fwcmd_mutex);
  6423. +
  6424. + memset(pcmd, 0x00, sizeof(*pcmd));
  6425. + pcmd->cmd_hdr.cmd = cpu_to_le16(HOSTCMD_CMD_SET_NEW_STN);
  6426. + pcmd->cmd_hdr.len = cpu_to_le16(sizeof(*pcmd));
  6427. + pcmd->cmd_hdr.macid = mwl_vif->macid;
  6428. +
  6429. + pcmd->action = cpu_to_le16(HOSTCMD_ACT_STA_ACTION_ADD);
  6430. + pcmd->aid = cpu_to_le16(sta->aid);
  6431. + pcmd->stn_id = cpu_to_le16(sta_info->stnid);
  6432. + ether_addr_copy(pcmd->mac_addr, sta->addr);
  6433. +
  6434. + if (hw->conf.chandef.chan->band == NL80211_BAND_2GHZ)
  6435. + rates = sta->supp_rates[NL80211_BAND_2GHZ];
  6436. + else
  6437. + rates = sta->supp_rates[NL80211_BAND_5GHZ] << 5;
  6438. + pcmd->peer_info.legacy_rate_bitmap = cpu_to_le32(rates);
  6439. +
  6440. + if (sta->ht_cap.ht_supported) {
  6441. + int i;
  6442. +
  6443. + for (i = 0; i < 4; i++) {
  6444. + if (i < sta->rx_nss) {
  6445. + pcmd->peer_info.ht_rates[i] =
  6446. + sta->ht_cap.mcs.rx_mask[i];
  6447. + } else {
  6448. + pcmd->peer_info.ht_rates[i] = 0;
  6449. + }
  6450. + }
  6451. + pcmd->peer_info.ht_cap_info = cpu_to_le16(sta->ht_cap.cap);
  6452. + pcmd->peer_info.mac_ht_param_info =
  6453. + (sta->ht_cap.ampdu_factor & 3) |
  6454. + ((sta->ht_cap.ampdu_density & 7) << 2);
  6455. + }
  6456. +
  6457. + if (sta->vht_cap.vht_supported) {
  6458. + u32 rx_mcs_map_mask = 0;
  6459. +
  6460. + rx_mcs_map_mask = ((0x0000FFFF) >> (sta->rx_nss * 2))
  6461. + << (sta->rx_nss * 2);
  6462. + pcmd->peer_info.vht_max_rx_mcs =
  6463. + cpu_to_le32((*((u32 *)
  6464. + &sta->vht_cap.vht_mcs.rx_mcs_map)) | rx_mcs_map_mask);
  6465. + pcmd->peer_info.vht_cap = cpu_to_le32(sta->vht_cap.cap);
  6466. + pcmd->peer_info.vht_rx_channel_width = sta->bandwidth;
  6467. + }
  6468. +
  6469. + pcmd->is_qos_sta = sta->wme;
  6470. + pcmd->qos_info = ((sta->uapsd_queues << 4) | (sta->max_sp << 1));
  6471. + pcmd->wds = cpu_to_le32(wds);
  6472. +
  6473. + if (mwl_hif_exec_cmd(hw, HOSTCMD_CMD_SET_NEW_STN)) {
  6474. + mutex_unlock(&priv->fwcmd_mutex);
  6475. + return -EIO;
  6476. + }
  6477. +
  6478. + if (vif->type == NL80211_IFTYPE_STATION) {
  6479. + ether_addr_copy(pcmd->mac_addr, mwl_vif->sta_mac);
  6480. + pcmd->aid = cpu_to_le16(sta->aid + 1);
  6481. + pcmd->stn_id = cpu_to_le16(sta_info->sta_stnid);
  6482. + if (mwl_hif_exec_cmd(hw, HOSTCMD_CMD_SET_NEW_STN)) {
  6483. + mutex_unlock(&priv->fwcmd_mutex);
  6484. + return -EIO;
  6485. + }
  6486. + }
  6487. +
  6488. + mutex_unlock(&priv->fwcmd_mutex);
  6489. +
  6490. + return 0;
  6491. +}
  6492. +
  6493. +int mwl_fwcmd_set_new_stn_wds_sc4(struct ieee80211_hw *hw, u8 *addr)
  6494. +{
  6495. + struct mwl_priv *priv = hw->priv;
  6496. + struct hostcmd_cmd_set_new_stn_sc4 *pcmd;
  6497. +
  6498. + pcmd = (struct hostcmd_cmd_set_new_stn_sc4 *)&priv->pcmd_buf[0];
  6499. +
  6500. + mutex_lock(&priv->fwcmd_mutex);
  6501. +
  6502. + memset(pcmd, 0x00, sizeof(*pcmd));
  6503. + pcmd->cmd_hdr.cmd = cpu_to_le16(HOSTCMD_CMD_SET_NEW_STN);
  6504. + pcmd->cmd_hdr.len = cpu_to_le16(sizeof(*pcmd));
  6505. +
  6506. + pcmd->action = cpu_to_le16(HOSTCMD_ACT_STA_ACTION_MODIFY);
  6507. + ether_addr_copy(pcmd->mac_addr, addr);
  6508. + pcmd->wds = cpu_to_le32(WDS_MODE);
  6509. +
  6510. + if (mwl_hif_exec_cmd(hw, HOSTCMD_CMD_SET_NEW_STN)) {
  6511. + mutex_unlock(&priv->fwcmd_mutex);
  6512. + return -EIO;
  6513. + }
  6514. +
  6515. + mutex_unlock(&priv->fwcmd_mutex);
  6516. +
  6517. + return 0;
  6518. +}
  6519. +
  6520. +int mwl_fwcmd_set_new_stn_add_self(struct ieee80211_hw *hw,
  6521. + struct ieee80211_vif *vif)
  6522. +{
  6523. + struct mwl_priv *priv = hw->priv;
  6524. + struct mwl_vif *mwl_vif;
  6525. + struct hostcmd_cmd_set_new_stn *pcmd;
  6526. +
  6527. + mwl_vif = mwl_dev_get_vif(vif);
  6528. +
  6529. + pcmd = (struct hostcmd_cmd_set_new_stn *)&priv->pcmd_buf[0];
  6530. +
  6531. + mutex_lock(&priv->fwcmd_mutex);
  6532. +
  6533. + if (priv->chip_type == MWL8964) {
  6534. + memset(pcmd, 0x00, sizeof(struct hostcmd_cmd_set_new_stn_sc4));
  6535. + pcmd->cmd_hdr.len =
  6536. + cpu_to_le16(sizeof(struct hostcmd_cmd_set_new_stn_sc4));
  6537. + } else {
  6538. + memset(pcmd, 0x00, sizeof(*pcmd));
  6539. + pcmd->cmd_hdr.len = cpu_to_le16(sizeof(*pcmd));
  6540. + }
  6541. + pcmd->cmd_hdr.cmd = cpu_to_le16(HOSTCMD_CMD_SET_NEW_STN);
  6542. + pcmd->cmd_hdr.macid = mwl_vif->macid;
  6543. +
  6544. + pcmd->action = cpu_to_le16(HOSTCMD_ACT_STA_ACTION_ADD);
  6545. + ether_addr_copy(pcmd->mac_addr, vif->addr);
  6546. +
  6547. + if (mwl_hif_exec_cmd(hw, HOSTCMD_CMD_SET_NEW_STN)) {
  6548. + mutex_unlock(&priv->fwcmd_mutex);
  6549. + return -EIO;
  6550. + }
  6551. +
  6552. + mutex_unlock(&priv->fwcmd_mutex);
  6553. +
  6554. + return 0;
  6555. +}
  6556. +
  6557. +int mwl_fwcmd_set_new_stn_del(struct ieee80211_hw *hw,
  6558. + struct ieee80211_vif *vif, u8 *addr)
  6559. +{
  6560. + struct mwl_priv *priv = hw->priv;
  6561. + struct mwl_vif *mwl_vif;
  6562. + struct hostcmd_cmd_set_new_stn *pcmd;
  6563. +
  6564. + mwl_vif = mwl_dev_get_vif(vif);
  6565. +
  6566. + pcmd = (struct hostcmd_cmd_set_new_stn *)&priv->pcmd_buf[0];
  6567. +
  6568. + mutex_lock(&priv->fwcmd_mutex);
  6569. +
  6570. + if (priv->chip_type == MWL8964) {
  6571. + memset(pcmd, 0x00, sizeof(struct hostcmd_cmd_set_new_stn_sc4));
  6572. + pcmd->cmd_hdr.len =
  6573. + cpu_to_le16(sizeof(struct hostcmd_cmd_set_new_stn_sc4));
  6574. + } else {
  6575. + memset(pcmd, 0x00, sizeof(*pcmd));
  6576. + pcmd->cmd_hdr.len = cpu_to_le16(sizeof(*pcmd));
  6577. + }
  6578. + pcmd->cmd_hdr.cmd = cpu_to_le16(HOSTCMD_CMD_SET_NEW_STN);
  6579. + pcmd->cmd_hdr.macid = mwl_vif->macid;
  6580. +
  6581. + pcmd->action = cpu_to_le16(HOSTCMD_ACT_STA_ACTION_REMOVE);
  6582. + ether_addr_copy(pcmd->mac_addr, addr);
  6583. +
  6584. + if (mwl_hif_exec_cmd(hw, HOSTCMD_CMD_SET_NEW_STN)) {
  6585. + mutex_unlock(&priv->fwcmd_mutex);
  6586. + return -EIO;
  6587. + }
  6588. +
  6589. + if (vif->type == NL80211_IFTYPE_STATION) {
  6590. + ether_addr_copy(pcmd->mac_addr, mwl_vif->sta_mac);
  6591. +
  6592. + if (mwl_hif_exec_cmd(hw, HOSTCMD_CMD_SET_NEW_STN)) {
  6593. + mutex_unlock(&priv->fwcmd_mutex);
  6594. + return -EIO;
  6595. + }
  6596. + }
  6597. +
  6598. + mutex_unlock(&priv->fwcmd_mutex);
  6599. +
  6600. + return 0;
  6601. +}
  6602. +
  6603. +int mwl_fwcmd_set_apmode(struct ieee80211_hw *hw, u8 apmode)
  6604. +{
  6605. + struct mwl_priv *priv = hw->priv;
  6606. + struct hostcmd_cmd_set_apmode *pcmd;
  6607. +
  6608. + pcmd = (struct hostcmd_cmd_set_apmode *)&priv->pcmd_buf[0];
  6609. +
  6610. + mutex_lock(&priv->fwcmd_mutex);
  6611. +
  6612. + memset(pcmd, 0x00, sizeof(*pcmd));
  6613. + pcmd->cmd_hdr.cmd = cpu_to_le16(HOSTCMD_CMD_SET_APMODE);
  6614. + pcmd->cmd_hdr.len = cpu_to_le16(sizeof(*pcmd));
  6615. + pcmd->apmode = apmode;
  6616. +
  6617. + if (mwl_hif_exec_cmd(hw, HOSTCMD_CMD_SET_APMODE)) {
  6618. + mutex_unlock(&priv->fwcmd_mutex);
  6619. + return -EIO;
  6620. + }
  6621. +
  6622. + mutex_unlock(&priv->fwcmd_mutex);
  6623. +
  6624. + return 0;
  6625. +}
  6626. +
  6627. +int mwl_fwcmd_set_switch_channel(struct ieee80211_hw *hw,
  6628. + struct ieee80211_channel_switch *ch_switch)
  6629. +{
  6630. + struct mwl_priv *priv = hw->priv;
  6631. + struct hostcmd_cmd_set_switch_channel *pcmd;
  6632. + struct cfg80211_chan_def *chandef = &ch_switch->chandef;
  6633. + struct ieee80211_channel *channel = chandef->chan;
  6634. + u32 chnl_flags, freq_band, chnl_width, act_primary, sec_chnl_offset;
  6635. +
  6636. + if (priv->csa_active)
  6637. + return 0;
  6638. +
  6639. + if (channel->band == NL80211_BAND_2GHZ)
  6640. + freq_band = FREQ_BAND_2DOT4GHZ;
  6641. + else if (channel->band == NL80211_BAND_5GHZ)
  6642. + freq_band = FREQ_BAND_5GHZ;
  6643. + else
  6644. + return -EINVAL;
  6645. +
  6646. + switch (chandef->width) {
  6647. + case NL80211_CHAN_WIDTH_20_NOHT:
  6648. + case NL80211_CHAN_WIDTH_20:
  6649. + chnl_width = CH_20_MHZ_WIDTH;
  6650. + act_primary = ACT_PRIMARY_CHAN_0;
  6651. + sec_chnl_offset = IEEE80211_HT_PARAM_CHA_SEC_NONE;
  6652. + break;
  6653. + case NL80211_CHAN_WIDTH_40:
  6654. + chnl_width = CH_40_MHZ_WIDTH;
  6655. + if (chandef->center_freq1 > channel->center_freq) {
  6656. + act_primary = ACT_PRIMARY_CHAN_0;
  6657. + sec_chnl_offset = IEEE80211_HT_PARAM_CHA_SEC_ABOVE;
  6658. + } else {
  6659. + act_primary = ACT_PRIMARY_CHAN_1;
  6660. + sec_chnl_offset = IEEE80211_HT_PARAM_CHA_SEC_BELOW;
  6661. + }
  6662. + break;
  6663. + case NL80211_CHAN_WIDTH_80:
  6664. + chnl_width = CH_80_MHZ_WIDTH;
  6665. + act_primary =
  6666. + mwl_fwcmd_get_80m_pri_chnl(channel->hw_value);
  6667. + if ((act_primary == ACT_PRIMARY_CHAN_0) ||
  6668. + (act_primary == ACT_PRIMARY_CHAN_2))
  6669. + sec_chnl_offset = IEEE80211_HT_PARAM_CHA_SEC_ABOVE;
  6670. + else
  6671. + sec_chnl_offset = IEEE80211_HT_PARAM_CHA_SEC_BELOW;
  6672. + break;
  6673. + default:
  6674. + return -EINVAL;
  6675. + }
  6676. +
  6677. + chnl_flags = (freq_band & FREQ_BAND_MASK) |
  6678. + ((chnl_width << CHNL_WIDTH_SHIFT) & CHNL_WIDTH_MASK) |
  6679. + ((act_primary << ACT_PRIMARY_SHIFT) & ACT_PRIMARY_MASK);
  6680. +
  6681. + pcmd = (struct hostcmd_cmd_set_switch_channel *)&priv->pcmd_buf[0];
  6682. +
  6683. + mutex_lock(&priv->fwcmd_mutex);
  6684. +
  6685. + memset(pcmd, 0x00, sizeof(*pcmd));
  6686. + pcmd->cmd_hdr.cmd = cpu_to_le16(HOSTCMD_CMD_SET_SWITCH_CHANNEL);
  6687. + pcmd->cmd_hdr.len = cpu_to_le16(sizeof(*pcmd));
  6688. + pcmd->next_11h_chnl = cpu_to_le32(channel->hw_value);
  6689. + pcmd->mode = cpu_to_le32(ch_switch->block_tx);
  6690. + pcmd->init_count = cpu_to_le32(ch_switch->count + 1);
  6691. + pcmd->chnl_flags = cpu_to_le32(chnl_flags);
  6692. + pcmd->next_ht_extchnl_offset = cpu_to_le32(sec_chnl_offset);
  6693. + pcmd->dfs_test_mode = cpu_to_le32(priv->dfs_test);
  6694. +
  6695. + if (mwl_hif_exec_cmd(hw, HOSTCMD_CMD_SET_SWITCH_CHANNEL)) {
  6696. + mutex_unlock(&priv->fwcmd_mutex);
  6697. + return -EIO;
  6698. + }
  6699. +
  6700. + priv->csa_active = true;
  6701. +
  6702. + mutex_unlock(&priv->fwcmd_mutex);
  6703. +
  6704. + return 0;
  6705. +}
  6706. +
  6707. +int mwl_fwcmd_update_encryption_enable(struct ieee80211_hw *hw,
  6708. + struct ieee80211_vif *vif,
  6709. + u8 *addr, u8 encr_type)
  6710. +{
  6711. + struct mwl_priv *priv = hw->priv;
  6712. + struct mwl_vif *mwl_vif;
  6713. + struct hostcmd_cmd_update_encryption *pcmd;
  6714. +
  6715. + mwl_vif = mwl_dev_get_vif(vif);
  6716. +
  6717. + pcmd = (struct hostcmd_cmd_update_encryption *)&priv->pcmd_buf[0];
  6718. +
  6719. + mutex_lock(&priv->fwcmd_mutex);
  6720. +
  6721. + memset(pcmd, 0x00, sizeof(*pcmd));
  6722. + pcmd->cmd_hdr.cmd = cpu_to_le16(HOSTCMD_CMD_UPDATE_ENCRYPTION);
  6723. + pcmd->cmd_hdr.len = cpu_to_le16(sizeof(*pcmd));
  6724. + pcmd->cmd_hdr.macid = mwl_vif->macid;
  6725. +
  6726. + pcmd->action_type = cpu_to_le32(ENCR_ACTION_ENABLE_HW_ENCR);
  6727. + ether_addr_copy(pcmd->mac_addr, addr);
  6728. + pcmd->action_data[0] = encr_type;
  6729. +
  6730. + if (mwl_hif_exec_cmd(hw, HOSTCMD_CMD_UPDATE_ENCRYPTION)) {
  6731. + mutex_unlock(&priv->fwcmd_mutex);
  6732. + return -EIO;
  6733. + }
  6734. +
  6735. + if ((vif->type == NL80211_IFTYPE_STATION) &&
  6736. + (priv->chip_type != MWL8964)) {
  6737. + if (ether_addr_equal(mwl_vif->bssid, addr))
  6738. + ether_addr_copy(pcmd->mac_addr, mwl_vif->sta_mac);
  6739. + else
  6740. + ether_addr_copy(pcmd->mac_addr, mwl_vif->bssid);
  6741. +
  6742. + if (mwl_hif_exec_cmd(hw, HOSTCMD_CMD_UPDATE_ENCRYPTION)) {
  6743. + mutex_unlock(&priv->fwcmd_mutex);
  6744. + return -EIO;
  6745. + }
  6746. + }
  6747. +
  6748. + mutex_unlock(&priv->fwcmd_mutex);
  6749. +
  6750. + return 0;
  6751. +}
  6752. +
  6753. +int mwl_fwcmd_encryption_set_key(struct ieee80211_hw *hw,
  6754. + struct ieee80211_vif *vif, u8 *addr,
  6755. + struct ieee80211_key_conf *key)
  6756. +{
  6757. + struct mwl_priv *priv = hw->priv;
  6758. + struct mwl_vif *mwl_vif;
  6759. + struct hostcmd_cmd_set_key *pcmd;
  6760. + int rc;
  6761. + int keymlen;
  6762. + u32 action;
  6763. + u8 idx;
  6764. +
  6765. + mwl_vif = mwl_dev_get_vif(vif);
  6766. +
  6767. + pcmd = (struct hostcmd_cmd_set_key *)&priv->pcmd_buf[0];
  6768. +
  6769. + mutex_lock(&priv->fwcmd_mutex);
  6770. +
  6771. + memset(pcmd, 0x00, sizeof(*pcmd));
  6772. + pcmd->cmd_hdr.cmd = cpu_to_le16(HOSTCMD_CMD_UPDATE_ENCRYPTION);
  6773. + pcmd->cmd_hdr.len = cpu_to_le16(sizeof(*pcmd));
  6774. + pcmd->cmd_hdr.macid = mwl_vif->macid;
  6775. +
  6776. + rc = mwl_fwcmd_encryption_set_cmd_info(pcmd, addr, key);
  6777. + if (rc) {
  6778. + mutex_unlock(&priv->fwcmd_mutex);
  6779. + if (rc != 1)
  6780. + wiphy_err(hw->wiphy, "encryption not support\n");
  6781. + return rc;
  6782. + }
  6783. +
  6784. + idx = key->keyidx;
  6785. +
  6786. + if (key->flags & IEEE80211_KEY_FLAG_PAIRWISE)
  6787. + action = ENCR_ACTION_TYPE_SET_KEY;
  6788. + else {
  6789. + action = ENCR_ACTION_TYPE_SET_GROUP_KEY;
  6790. + if (vif->type == NL80211_IFTYPE_MESH_POINT &&
  6791. + !ether_addr_equal(mwl_vif->bssid, addr))
  6792. + pcmd->key_param.key_info |=
  6793. + cpu_to_le32(ENCR_KEY_FLAG_RXGROUPKEY);
  6794. + }
  6795. +
  6796. + switch (key->cipher) {
  6797. + case WLAN_CIPHER_SUITE_WEP40:
  6798. + case WLAN_CIPHER_SUITE_WEP104:
  6799. + if (!mwl_vif->wep_key_conf[idx].enabled) {
  6800. + memcpy(mwl_vif->wep_key_conf[idx].key, key,
  6801. + sizeof(*key) + key->keylen);
  6802. + mwl_vif->wep_key_conf[idx].enabled = 1;
  6803. + }
  6804. +
  6805. + keymlen = key->keylen;
  6806. + action = ENCR_ACTION_TYPE_SET_KEY;
  6807. + break;
  6808. + case WLAN_CIPHER_SUITE_TKIP:
  6809. + keymlen = MAX_ENCR_KEY_LENGTH + 2 * MIC_KEY_LENGTH;
  6810. + break;
  6811. + case WLAN_CIPHER_SUITE_CCMP:
  6812. + keymlen = key->keylen;
  6813. + break;
  6814. + default:
  6815. + mutex_unlock(&priv->fwcmd_mutex);
  6816. + wiphy_err(hw->wiphy, "encryption not support\n");
  6817. + return -ENOTSUPP;
  6818. + }
  6819. +
  6820. + memcpy((void *)&pcmd->key_param.key, key->key, keymlen);
  6821. + pcmd->action_type = cpu_to_le32(action);
  6822. +
  6823. + if (mwl_hif_exec_cmd(hw, HOSTCMD_CMD_UPDATE_ENCRYPTION)) {
  6824. + mutex_unlock(&priv->fwcmd_mutex);
  6825. + return -EIO;
  6826. + }
  6827. +
  6828. + if (vif->type == NL80211_IFTYPE_STATION) {
  6829. + if (ether_addr_equal(mwl_vif->bssid, addr))
  6830. + ether_addr_copy(pcmd->key_param.mac_addr,
  6831. + mwl_vif->sta_mac);
  6832. + else
  6833. + ether_addr_copy(pcmd->key_param.mac_addr,
  6834. + mwl_vif->bssid);
  6835. +
  6836. + if (mwl_hif_exec_cmd(hw, HOSTCMD_CMD_UPDATE_ENCRYPTION)) {
  6837. + mutex_unlock(&priv->fwcmd_mutex);
  6838. + return -EIO;
  6839. + }
  6840. + }
  6841. +
  6842. + mutex_unlock(&priv->fwcmd_mutex);
  6843. +
  6844. + return 0;
  6845. +}
  6846. +
  6847. +int mwl_fwcmd_encryption_remove_key(struct ieee80211_hw *hw,
  6848. + struct ieee80211_vif *vif, u8 *addr,
  6849. + struct ieee80211_key_conf *key)
  6850. +{
  6851. + struct mwl_priv *priv = hw->priv;
  6852. + struct mwl_vif *mwl_vif;
  6853. + struct hostcmd_cmd_set_key *pcmd;
  6854. + int rc;
  6855. +
  6856. + mwl_vif = mwl_dev_get_vif(vif);
  6857. +
  6858. + pcmd = (struct hostcmd_cmd_set_key *)&priv->pcmd_buf[0];
  6859. +
  6860. + mutex_lock(&priv->fwcmd_mutex);
  6861. +
  6862. + memset(pcmd, 0x00, sizeof(*pcmd));
  6863. + pcmd->cmd_hdr.cmd = cpu_to_le16(HOSTCMD_CMD_UPDATE_ENCRYPTION);
  6864. + pcmd->cmd_hdr.len = cpu_to_le16(sizeof(*pcmd));
  6865. + pcmd->cmd_hdr.macid = mwl_vif->macid;
  6866. +
  6867. + rc = mwl_fwcmd_encryption_set_cmd_info(pcmd, addr, key);
  6868. + if (rc) {
  6869. + mutex_unlock(&priv->fwcmd_mutex);
  6870. + if (rc != 1)
  6871. + wiphy_err(hw->wiphy, "encryption not support\n");
  6872. + return rc;
  6873. + }
  6874. +
  6875. + pcmd->action_type = cpu_to_le32(ENCR_ACTION_TYPE_REMOVE_KEY);
  6876. +
  6877. + if (key->cipher == WLAN_CIPHER_SUITE_WEP40 ||
  6878. + key->cipher == WLAN_CIPHER_SUITE_WEP104)
  6879. + mwl_vif->wep_key_conf[key->keyidx].enabled = 0;
  6880. +
  6881. + if (mwl_hif_exec_cmd(hw, HOSTCMD_CMD_UPDATE_ENCRYPTION)) {
  6882. + mutex_unlock(&priv->fwcmd_mutex);
  6883. + return -EIO;
  6884. + }
  6885. +
  6886. + mutex_unlock(&priv->fwcmd_mutex);
  6887. +
  6888. + return 0;
  6889. +}
  6890. +
  6891. +int mwl_fwcmd_check_ba(struct ieee80211_hw *hw,
  6892. + struct mwl_ampdu_stream *stream,
  6893. + struct ieee80211_vif *vif,
  6894. + u32 direction)
  6895. +{
  6896. + struct mwl_priv *priv = hw->priv;
  6897. + struct mwl_vif *mwl_vif;
  6898. + struct hostcmd_cmd_bastream *pcmd;
  6899. + u32 ba_flags, ba_type, ba_direction;
  6900. +
  6901. + mwl_vif = mwl_dev_get_vif(vif);
  6902. +
  6903. + pcmd = (struct hostcmd_cmd_bastream *)&priv->pcmd_buf[0];
  6904. +
  6905. + mutex_lock(&priv->fwcmd_mutex);
  6906. +
  6907. + memset(pcmd, 0x00, sizeof(*pcmd));
  6908. + pcmd->cmd_hdr.cmd = cpu_to_le16(HOSTCMD_CMD_BASTREAM);
  6909. + pcmd->cmd_hdr.len = cpu_to_le16(sizeof(*pcmd));
  6910. + pcmd->cmd_hdr.macid = mwl_vif->macid;
  6911. + pcmd->cmd_hdr.result = cpu_to_le16(0xffff);
  6912. +
  6913. + pcmd->action_type = cpu_to_le32(BA_CHECK_STREAM);
  6914. + ether_addr_copy(&pcmd->ba_info.create_params.peer_mac_addr[0],
  6915. + stream->sta->addr);
  6916. + pcmd->ba_info.create_params.tid = stream->tid;
  6917. + ba_type = BA_FLAG_IMMEDIATE_TYPE;
  6918. + ba_direction = direction;
  6919. + ba_flags = (ba_type & BA_TYPE_MASK) |
  6920. + ((ba_direction << BA_DIRECTION_SHIFT) & BA_DIRECTION_MASK);
  6921. + pcmd->ba_info.create_params.flags = cpu_to_le32(ba_flags);
  6922. + pcmd->ba_info.create_params.queue_id = stream->idx;
  6923. +
  6924. + if (mwl_hif_exec_cmd(hw, HOSTCMD_CMD_BASTREAM)) {
  6925. + mutex_unlock(&priv->fwcmd_mutex);
  6926. + return -EIO;
  6927. + }
  6928. +
  6929. + if (pcmd->cmd_hdr.result != 0) {
  6930. + mutex_unlock(&priv->fwcmd_mutex);
  6931. + return -EINVAL;
  6932. + }
  6933. +
  6934. + mutex_unlock(&priv->fwcmd_mutex);
  6935. +
  6936. + return 0;
  6937. +}
  6938. +
  6939. +int mwl_fwcmd_create_ba(struct ieee80211_hw *hw,
  6940. + struct mwl_ampdu_stream *stream,
  6941. + struct ieee80211_vif *vif,
  6942. + u32 direction, u8 buf_size, u16 seqno, bool amsdu)
  6943. +{
  6944. + struct mwl_priv *priv = hw->priv;
  6945. + struct mwl_vif *mwl_vif;
  6946. + struct hostcmd_cmd_bastream *pcmd;
  6947. + u32 ba_flags, ba_type, ba_direction;
  6948. +
  6949. + mwl_vif = mwl_dev_get_vif(vif);
  6950. +
  6951. + pcmd = (struct hostcmd_cmd_bastream *)&priv->pcmd_buf[0];
  6952. +
  6953. + mutex_lock(&priv->fwcmd_mutex);
  6954. +
  6955. + memset(pcmd, 0x00, sizeof(*pcmd));
  6956. + pcmd->cmd_hdr.cmd = cpu_to_le16(HOSTCMD_CMD_BASTREAM);
  6957. + pcmd->cmd_hdr.len = cpu_to_le16(sizeof(*pcmd));
  6958. + pcmd->cmd_hdr.macid = mwl_vif->macid;
  6959. + pcmd->cmd_hdr.result = cpu_to_le16(0xffff);
  6960. +
  6961. + pcmd->action_type = cpu_to_le32(BA_CREATE_STREAM);
  6962. + pcmd->ba_info.create_params.bar_thrs = cpu_to_le32(buf_size);
  6963. + pcmd->ba_info.create_params.window_size = cpu_to_le32(buf_size);
  6964. + pcmd->ba_info.create_params.idle_thrs = cpu_to_le32(0x22000);
  6965. + ether_addr_copy(&pcmd->ba_info.create_params.peer_mac_addr[0],
  6966. + stream->sta->addr);
  6967. + pcmd->ba_info.create_params.tid = stream->tid;
  6968. + ba_direction = direction;
  6969. + if (priv->chip_type == MWL8964) {
  6970. + ba_type = amsdu ? MWL_AMSDU_SIZE_11K : 0;
  6971. + ba_flags = (ba_type & BA_TYPE_MASK_NDP) |
  6972. + ((ba_direction << BA_DIRECTION_SHIFT_NDP) &
  6973. + BA_DIRECTION_MASK_NDP);
  6974. + } else {
  6975. + ba_type = BA_FLAG_IMMEDIATE_TYPE;
  6976. + ba_flags = (ba_type & BA_TYPE_MASK) |
  6977. + ((ba_direction << BA_DIRECTION_SHIFT) &
  6978. + BA_DIRECTION_MASK);
  6979. + }
  6980. + pcmd->ba_info.create_params.flags = cpu_to_le32(ba_flags);
  6981. + pcmd->ba_info.create_params.queue_id = stream->idx;
  6982. + pcmd->ba_info.create_params.param_info =
  6983. + (stream->sta->ht_cap.ampdu_factor &
  6984. + IEEE80211_HT_AMPDU_PARM_FACTOR) |
  6985. + ((stream->sta->ht_cap.ampdu_density << 2) &
  6986. + IEEE80211_HT_AMPDU_PARM_DENSITY);
  6987. + if (direction == BA_FLAG_DIRECTION_UP) {
  6988. + pcmd->ba_info.create_params.reset_seq_no = 0;
  6989. + pcmd->ba_info.create_params.current_seq = cpu_to_le16(seqno);
  6990. + } else {
  6991. + pcmd->ba_info.create_params.reset_seq_no = 1;
  6992. + pcmd->ba_info.create_params.current_seq = cpu_to_le16(0);
  6993. + }
  6994. + if (priv->chip_type == MWL8964 &&
  6995. + stream->sta->vht_cap.vht_supported) {
  6996. + pcmd->ba_info.create_params.vht_rx_factor =
  6997. + cpu_to_le32((stream->sta->vht_cap.cap &
  6998. + IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK) >>
  6999. + IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_SHIFT);
  7000. + }
  7001. +
  7002. + if (mwl_hif_exec_cmd(hw, HOSTCMD_CMD_BASTREAM)) {
  7003. + mutex_unlock(&priv->fwcmd_mutex);
  7004. + return -EIO;
  7005. + }
  7006. +
  7007. + if (pcmd->cmd_hdr.result != 0) {
  7008. + mutex_unlock(&priv->fwcmd_mutex);
  7009. + wiphy_err(hw->wiphy, "create ba result error %d\n",
  7010. + le16_to_cpu(pcmd->cmd_hdr.result));
  7011. + return -EINVAL;
  7012. + }
  7013. +
  7014. + mutex_unlock(&priv->fwcmd_mutex);
  7015. +
  7016. + return 0;
  7017. +}
  7018. +
  7019. +int mwl_fwcmd_destroy_ba(struct ieee80211_hw *hw,
  7020. + struct mwl_ampdu_stream *stream,
  7021. + u32 direction)
  7022. +{
  7023. + struct mwl_priv *priv = hw->priv;
  7024. + struct hostcmd_cmd_bastream *pcmd;
  7025. + u32 ba_flags, ba_type, ba_direction;
  7026. +
  7027. + pcmd = (struct hostcmd_cmd_bastream *)&priv->pcmd_buf[0];
  7028. +
  7029. + mutex_lock(&priv->fwcmd_mutex);
  7030. +
  7031. + memset(pcmd, 0x00, sizeof(*pcmd));
  7032. + pcmd->cmd_hdr.cmd = cpu_to_le16(HOSTCMD_CMD_BASTREAM);
  7033. + pcmd->cmd_hdr.len = cpu_to_le16(sizeof(*pcmd));
  7034. +
  7035. + pcmd->action_type = cpu_to_le32(BA_DESTROY_STREAM);
  7036. + ba_type = 0;
  7037. + ba_direction = direction;
  7038. + if (priv->chip_type == MWL8964)
  7039. + ba_flags = (ba_type & BA_TYPE_MASK_NDP) |
  7040. + ((ba_direction << BA_DIRECTION_SHIFT_NDP) &
  7041. + BA_DIRECTION_MASK_NDP);
  7042. + else
  7043. + ba_flags = (ba_type & BA_TYPE_MASK) |
  7044. + ((ba_direction << BA_DIRECTION_SHIFT) &
  7045. + BA_DIRECTION_MASK);
  7046. + pcmd->ba_info.destroy_params.flags = cpu_to_le32(ba_flags);
  7047. + pcmd->ba_info.destroy_params.fw_ba_context.context =
  7048. + cpu_to_le32(stream->idx);
  7049. + pcmd->ba_info.destroy_params.tid = stream->tid;
  7050. + ether_addr_copy(&pcmd->ba_info.destroy_params.peer_mac_addr[0],
  7051. + stream->sta->addr);
  7052. +
  7053. + if (mwl_hif_exec_cmd(hw, HOSTCMD_CMD_BASTREAM)) {
  7054. + mutex_unlock(&priv->fwcmd_mutex);
  7055. + return -EIO;
  7056. + }
  7057. +
  7058. + mutex_unlock(&priv->fwcmd_mutex);
  7059. +
  7060. + return 0;
  7061. +}
  7062. +
  7063. +/* caller must hold priv->stream_lock when calling the stream functions */
  7064. +struct mwl_ampdu_stream *mwl_fwcmd_add_stream(struct ieee80211_hw *hw,
  7065. + struct ieee80211_sta *sta,
  7066. + u8 tid)
  7067. +{
  7068. + struct mwl_priv *priv = hw->priv;
  7069. + struct mwl_ampdu_stream *stream;
  7070. + struct mwl_sta *sta_info = mwl_dev_get_sta(sta);
  7071. + int idx;
  7072. +
  7073. + if (priv->chip_type == MWL8964) {
  7074. + idx = ((sta_info->stnid - 1) * SYSADPT_MAX_TID) + tid;
  7075. +
  7076. + if (idx < priv->ampdu_num) {
  7077. + stream = &priv->ampdu[idx];
  7078. + stream->sta = sta;
  7079. + stream->state = AMPDU_STREAM_NEW;
  7080. + stream->tid = tid;
  7081. + stream->idx = idx;
  7082. + return stream;
  7083. + }
  7084. + } else {
  7085. + for (idx = 0; idx < priv->ampdu_num; idx++) {
  7086. + stream = &priv->ampdu[idx];
  7087. +
  7088. + if (stream->state == AMPDU_NO_STREAM) {
  7089. + stream->sta = sta;
  7090. + stream->state = AMPDU_STREAM_NEW;
  7091. + stream->tid = tid;
  7092. + stream->idx = idx;
  7093. + return stream;
  7094. + }
  7095. + }
  7096. + }
  7097. +
  7098. + return NULL;
  7099. +}
  7100. +
  7101. +void mwl_fwcmd_del_sta_streams(struct ieee80211_hw *hw,
  7102. + struct ieee80211_sta *sta)
  7103. +{
  7104. + struct mwl_priv *priv = hw->priv;
  7105. + struct mwl_ampdu_stream *stream;
  7106. + struct mwl_sta *sta_info = mwl_dev_get_sta(sta);
  7107. + int i, idx;
  7108. +
  7109. + spin_lock_bh(&priv->stream_lock);
  7110. + if (priv->chip_type == MWL8964) {
  7111. + idx = (sta_info->stnid - 1) * SYSADPT_MAX_TID;
  7112. + for (i = 0; i < SYSADPT_MAX_TID; i++) {
  7113. + stream = &priv->ampdu[idx + i];
  7114. +
  7115. + if (stream->sta == sta) {
  7116. + spin_unlock_bh(&priv->stream_lock);
  7117. + mwl_fwcmd_destroy_ba(hw, stream,
  7118. + BA_FLAG_DIRECTION_UP);
  7119. + spin_lock_bh(&priv->stream_lock);
  7120. + mwl_fwcmd_remove_stream(hw, stream);
  7121. + }
  7122. + }
  7123. + } else {
  7124. + for (idx = 0; idx < priv->ampdu_num; idx++) {
  7125. + stream = &priv->ampdu[idx];
  7126. +
  7127. + if (stream->sta == sta) {
  7128. + spin_unlock_bh(&priv->stream_lock);
  7129. + mwl_fwcmd_destroy_ba(hw, stream,
  7130. + BA_FLAG_DIRECTION_UP);
  7131. + spin_lock_bh(&priv->stream_lock);
  7132. + mwl_fwcmd_remove_stream(hw, stream);
  7133. + }
  7134. + }
  7135. + }
  7136. + spin_unlock_bh(&priv->stream_lock);
  7137. +}
  7138. +
  7139. +int mwl_fwcmd_start_stream(struct ieee80211_hw *hw,
  7140. + struct mwl_ampdu_stream *stream)
  7141. +{
  7142. + /* if the stream has already been started, don't start it again */
  7143. + if (stream->state != AMPDU_STREAM_NEW)
  7144. + return 0;
  7145. +
  7146. + return ieee80211_start_tx_ba_session(stream->sta, stream->tid, 0);
  7147. +}
  7148. +
  7149. +void mwl_fwcmd_remove_stream(struct ieee80211_hw *hw,
  7150. + struct mwl_ampdu_stream *stream)
  7151. +{
  7152. + memset(stream, 0, sizeof(*stream));
  7153. +}
  7154. +
  7155. +struct mwl_ampdu_stream *mwl_fwcmd_lookup_stream(struct ieee80211_hw *hw,
  7156. + struct ieee80211_sta *sta,
  7157. + u8 tid)
  7158. +{
  7159. + struct mwl_priv *priv = hw->priv;
  7160. + struct mwl_ampdu_stream *stream;
  7161. + struct mwl_sta *sta_info = mwl_dev_get_sta(sta);
  7162. + int idx;
  7163. +
  7164. + if (priv->chip_type == MWL8964) {
  7165. + idx = ((sta_info->stnid - 1) * SYSADPT_MAX_TID) + tid;
  7166. + if (idx < priv->ampdu_num)
  7167. + return &priv->ampdu[idx];
  7168. + } else {
  7169. + for (idx = 0; idx < priv->ampdu_num; idx++) {
  7170. + stream = &priv->ampdu[idx];
  7171. + if (stream->state == AMPDU_NO_STREAM)
  7172. + continue;
  7173. +
  7174. + if ((stream->sta == sta) && (stream->tid == tid))
  7175. + return stream;
  7176. + }
  7177. + }
  7178. +
  7179. + return NULL;
  7180. +}
  7181. +
  7182. +bool mwl_fwcmd_ampdu_allowed(struct ieee80211_sta *sta, u8 tid)
  7183. +{
  7184. + struct mwl_sta *sta_info;
  7185. + struct mwl_tx_info *tx_stats;
  7186. +
  7187. + if (WARN_ON(tid >= SYSADPT_MAX_TID))
  7188. + return false;
  7189. +
  7190. + sta_info = mwl_dev_get_sta(sta);
  7191. +
  7192. + tx_stats = &sta_info->tx_stats[tid];
  7193. +
  7194. + return (sta_info->is_ampdu_allowed &&
  7195. + tx_stats->pkts > SYSADPT_AMPDU_PACKET_THRESHOLD);
  7196. +}
  7197. +
  7198. +int mwl_fwcmd_set_optimization_level(struct ieee80211_hw *hw, u8 opt_level)
  7199. +{
  7200. + struct mwl_priv *priv = hw->priv;
  7201. + struct hostcmd_cmd_set_optimization_level *pcmd;
  7202. +
  7203. + pcmd = (struct hostcmd_cmd_set_optimization_level *)&priv->pcmd_buf[0];
  7204. +
  7205. + mutex_lock(&priv->fwcmd_mutex);
  7206. +
  7207. + memset(pcmd, 0x00, sizeof(*pcmd));
  7208. + pcmd->cmd_hdr.cmd = cpu_to_le16(HOSTCMD_CMD_SET_OPTIMIZATION_LEVEL);
  7209. + pcmd->cmd_hdr.len = cpu_to_le16(sizeof(*pcmd));
  7210. + pcmd->opt_level = opt_level;
  7211. +
  7212. + if (mwl_hif_exec_cmd(hw, HOSTCMD_CMD_SET_OPTIMIZATION_LEVEL)) {
  7213. + mutex_unlock(&priv->fwcmd_mutex);
  7214. + return -EIO;
  7215. + }
  7216. +
  7217. + mutex_unlock(&priv->fwcmd_mutex);
  7218. +
  7219. + return 0;
  7220. +}
  7221. +
  7222. +int mwl_fwcmd_set_wsc_ie(struct ieee80211_hw *hw, u8 len, u8 *data)
  7223. +{
  7224. + struct mwl_priv *priv = hw->priv;
  7225. + struct hostcmd_cmd_set_wsc_ie *pcmd;
  7226. +
  7227. + pcmd = (struct hostcmd_cmd_set_wsc_ie *)&priv->pcmd_buf[0];
  7228. +
  7229. + mutex_lock(&priv->fwcmd_mutex);
  7230. +
  7231. + memset(pcmd, 0x00, sizeof(*pcmd));
  7232. + pcmd->cmd_hdr.cmd = cpu_to_le16(HOSTCMD_CMD_SET_WSC_IE);
  7233. + pcmd->cmd_hdr.len = cpu_to_le16(sizeof(*pcmd));
  7234. + pcmd->len = cpu_to_le16(len);
  7235. + memcpy(pcmd->data, data, len);
  7236. +
  7237. + if (mwl_hif_exec_cmd(hw, HOSTCMD_CMD_SET_WSC_IE)) {
  7238. + mutex_unlock(&priv->fwcmd_mutex);
  7239. + return -EIO;
  7240. + }
  7241. +
  7242. + pcmd->ie_type = cpu_to_le16(WSC_IE_SET_PROBE_RESPONSE);
  7243. +
  7244. + if (mwl_hif_exec_cmd(hw, HOSTCMD_CMD_SET_WSC_IE)) {
  7245. + mutex_unlock(&priv->fwcmd_mutex);
  7246. + return -EIO;
  7247. + }
  7248. +
  7249. + mutex_unlock(&priv->fwcmd_mutex);
  7250. +
  7251. + return 0;
  7252. +}
  7253. +
  7254. +int mwl_fwcmd_get_ratetable(struct ieee80211_hw *hw, u8 *addr, u8 *rate_table,
  7255. + u32 size, u8 type)
  7256. +{
  7257. + struct mwl_priv *priv = hw->priv;
  7258. + struct hostcmd_cmd_get_ratetable *pcmd;
  7259. +
  7260. + pcmd = (struct hostcmd_cmd_get_ratetable *)&priv->pcmd_buf[0];
  7261. +
  7262. + mutex_lock(&priv->fwcmd_mutex);
  7263. +
  7264. + memset(pcmd, 0x00, sizeof(*pcmd));
  7265. + pcmd->cmd_hdr.cmd = cpu_to_le16(HOSTCMD_CMD_GET_RATETABLE);
  7266. + pcmd->cmd_hdr.len = cpu_to_le16(sizeof(*pcmd));
  7267. + pcmd->type = type;
  7268. + ether_addr_copy(pcmd->addr, addr);
  7269. + memset(rate_table, 0x00, size);
  7270. +
  7271. + if (mwl_hif_exec_cmd(hw, HOSTCMD_CMD_GET_RATETABLE)) {
  7272. + mutex_unlock(&priv->fwcmd_mutex);
  7273. + return -EIO;
  7274. + }
  7275. +
  7276. + memcpy(rate_table, &pcmd->sorted_rates_idx_map, size);
  7277. +
  7278. + mutex_unlock(&priv->fwcmd_mutex);
  7279. +
  7280. + return 0;
  7281. +}
  7282. +
  7283. +int mwl_fwcmd_get_seqno(struct ieee80211_hw *hw,
  7284. + struct mwl_ampdu_stream *stream, u16 *start_seqno)
  7285. +{
  7286. + struct mwl_priv *priv = hw->priv;
  7287. + struct hostcmd_cmd_get_seqno *pcmd;
  7288. +
  7289. + pcmd = (struct hostcmd_cmd_get_seqno *)&priv->pcmd_buf[0];
  7290. +
  7291. + mutex_lock(&priv->fwcmd_mutex);
  7292. +
  7293. + memset(pcmd, 0x00, sizeof(*pcmd));
  7294. + pcmd->cmd_hdr.cmd = cpu_to_le16(HOSTCMD_CMD_GET_SEQNO);
  7295. + pcmd->cmd_hdr.len = cpu_to_le16(sizeof(*pcmd));
  7296. + ether_addr_copy(pcmd->mac_addr, stream->sta->addr);
  7297. + pcmd->tid = stream->tid;
  7298. +
  7299. + if (mwl_hif_exec_cmd(hw, HOSTCMD_CMD_GET_SEQNO)) {
  7300. + mutex_unlock(&priv->fwcmd_mutex);
  7301. + return -EIO;
  7302. + }
  7303. +
  7304. + *start_seqno = le16_to_cpu(pcmd->seq_no);
  7305. +
  7306. + mutex_unlock(&priv->fwcmd_mutex);
  7307. +
  7308. + return 0;
  7309. +}
  7310. +
  7311. +int mwl_fwcmd_set_dwds_stamode(struct ieee80211_hw *hw, bool enable)
  7312. +{
  7313. + struct mwl_priv *priv = hw->priv;
  7314. + struct hostcmd_cmd_dwds_enable *pcmd;
  7315. +
  7316. + pcmd = (struct hostcmd_cmd_dwds_enable *)&priv->pcmd_buf[0];
  7317. +
  7318. + mutex_lock(&priv->fwcmd_mutex);
  7319. +
  7320. + memset(pcmd, 0x00, sizeof(*pcmd));
  7321. + pcmd->cmd_hdr.cmd = cpu_to_le16(HOSTCMD_CMD_DWDS_ENABLE);
  7322. + pcmd->cmd_hdr.len = cpu_to_le16(sizeof(*pcmd));
  7323. + pcmd->enable = cpu_to_le32(enable);
  7324. +
  7325. + if (mwl_hif_exec_cmd(hw, HOSTCMD_CMD_DWDS_ENABLE)) {
  7326. + mutex_unlock(&priv->fwcmd_mutex);
  7327. + return -EIO;
  7328. + }
  7329. +
  7330. + mutex_unlock(&priv->fwcmd_mutex);
  7331. +
  7332. + return 0;
  7333. +}
  7334. +
  7335. +int mwl_fwcmd_set_fw_flush_timer(struct ieee80211_hw *hw, u32 value)
  7336. +{
  7337. + struct mwl_priv *priv = hw->priv;
  7338. + struct hostcmd_cmd_fw_flush_timer *pcmd;
  7339. +
  7340. + pcmd = (struct hostcmd_cmd_fw_flush_timer *)&priv->pcmd_buf[0];
  7341. +
  7342. + mutex_lock(&priv->fwcmd_mutex);
  7343. +
  7344. + memset(pcmd, 0x00, sizeof(*pcmd));
  7345. + pcmd->cmd_hdr.cmd = cpu_to_le16(HOSTCMD_CMD_FW_FLUSH_TIMER);
  7346. + pcmd->cmd_hdr.len = cpu_to_le16(sizeof(*pcmd));
  7347. + pcmd->value = cpu_to_le32(value);
  7348. +
  7349. + if (mwl_hif_exec_cmd(hw, HOSTCMD_CMD_FW_FLUSH_TIMER)) {
  7350. + mutex_unlock(&priv->fwcmd_mutex);
  7351. + return -EIO;
  7352. + }
  7353. +
  7354. + mutex_unlock(&priv->fwcmd_mutex);
  7355. +
  7356. + return 0;
  7357. +}
  7358. +
  7359. +int mwl_fwcmd_set_cdd(struct ieee80211_hw *hw)
  7360. +{
  7361. + struct mwl_priv *priv = hw->priv;
  7362. + struct hostcmd_cmd_set_cdd *pcmd;
  7363. +
  7364. + pcmd = (struct hostcmd_cmd_set_cdd *)&priv->pcmd_buf[0];
  7365. +
  7366. + mutex_lock(&priv->fwcmd_mutex);
  7367. +
  7368. + memset(pcmd, 0x00, sizeof(*pcmd));
  7369. + pcmd->cmd_hdr.cmd = cpu_to_le16(HOSTCMD_CMD_SET_CDD);
  7370. + pcmd->cmd_hdr.len = cpu_to_le16(sizeof(*pcmd));
  7371. + pcmd->enable = cpu_to_le32(priv->cdd);
  7372. +
  7373. + if (mwl_hif_exec_cmd(hw, HOSTCMD_CMD_SET_CDD)) {
  7374. + mutex_unlock(&priv->fwcmd_mutex);
  7375. + return -EIO;
  7376. + }
  7377. +
  7378. + mutex_unlock(&priv->fwcmd_mutex);
  7379. +
  7380. + return 0;
  7381. +}
  7382. +
  7383. +int mwl_fwcmd_set_bftype(struct ieee80211_hw *hw, int mode)
  7384. +{
  7385. + struct mwl_priv *priv = hw->priv;
  7386. + struct hostcmd_cmd_set_bftype *pcmd;
  7387. +
  7388. + pcmd = (struct hostcmd_cmd_set_bftype *)&priv->pcmd_buf[0];
  7389. +
  7390. + mutex_lock(&priv->fwcmd_mutex);
  7391. +
  7392. + memset(pcmd, 0x00, sizeof(*pcmd));
  7393. + pcmd->cmd_hdr.cmd = cpu_to_le16(HOSTCMD_CMD_SET_BFTYPE);
  7394. + pcmd->cmd_hdr.len = cpu_to_le16(sizeof(*pcmd));
  7395. + pcmd->action = cpu_to_le32(WL_SET);
  7396. + pcmd->mode = cpu_to_le32(mode);
  7397. +
  7398. + if (mwl_hif_exec_cmd(hw, HOSTCMD_CMD_SET_BFTYPE)) {
  7399. + mutex_unlock(&priv->fwcmd_mutex);
  7400. + return -EIO;
  7401. + }
  7402. +
  7403. + mutex_unlock(&priv->fwcmd_mutex);
  7404. +
  7405. + return 0;
  7406. +}
  7407. +
  7408. +int mwl_fwcmd_reg_cau(struct ieee80211_hw *hw, u8 flag, u32 reg, u32 *val)
  7409. +{
  7410. + struct mwl_priv *priv = hw->priv;
  7411. + struct hostcmd_cmd_bbp_reg_access *pcmd;
  7412. +
  7413. + pcmd = (struct hostcmd_cmd_bbp_reg_access *)&priv->pcmd_buf[0];
  7414. +
  7415. + mutex_lock(&priv->fwcmd_mutex);
  7416. +
  7417. + memset(pcmd, 0x00, sizeof(*pcmd));
  7418. + pcmd->cmd_hdr.cmd = cpu_to_le16(HOSTCMD_CMD_CAU_REG_ACCESS);
  7419. + pcmd->cmd_hdr.len = cpu_to_le16(sizeof(*pcmd));
  7420. + pcmd->offset = cpu_to_le16(reg);
  7421. + pcmd->action = cpu_to_le16(flag);
  7422. + pcmd->value = *val;
  7423. +
  7424. + if (mwl_hif_exec_cmd(hw, HOSTCMD_CMD_CAU_REG_ACCESS)) {
  7425. + mutex_unlock(&priv->fwcmd_mutex);
  7426. + return -EIO;
  7427. + }
  7428. +
  7429. + *val = pcmd->value;
  7430. +
  7431. + mutex_unlock(&priv->fwcmd_mutex);
  7432. +
  7433. + return 0;
  7434. +}
  7435. +
  7436. +int mwl_fwcmd_get_temp(struct ieee80211_hw *hw, u32 *temp)
  7437. +{
  7438. + struct mwl_priv *priv = hw->priv;
  7439. + struct hostcmd_cmd_get_temp *pcmd;
  7440. +
  7441. + pcmd = (struct hostcmd_cmd_get_temp *)&priv->pcmd_buf[0];
  7442. +
  7443. + mutex_lock(&priv->fwcmd_mutex);
  7444. +
  7445. + memset(pcmd, 0x00, sizeof(*pcmd));
  7446. + pcmd->cmd_hdr.cmd = cpu_to_le16(HOSTCMD_CMD_GET_TEMP);
  7447. + pcmd->cmd_hdr.len = cpu_to_le16(sizeof(*pcmd));
  7448. +
  7449. + if (mwl_hif_exec_cmd(hw, HOSTCMD_CMD_GET_TEMP)) {
  7450. + mutex_unlock(&priv->fwcmd_mutex);
  7451. + return -EIO;
  7452. + }
  7453. +
  7454. + *temp = le32_to_cpu(pcmd->celcius);
  7455. +
  7456. + mutex_unlock(&priv->fwcmd_mutex);
  7457. +
  7458. + return 0;
  7459. +}
  7460. +
  7461. +int mwl_fwcmd_led_ctrl(struct ieee80211_hw *hw, u8 enable, u8 rate)
  7462. +{
  7463. + struct hostcmd_cmd_led_ctrl *pcmd;
  7464. + struct mwl_priv *priv = hw->priv;
  7465. +
  7466. + pcmd = (struct hostcmd_cmd_led_ctrl *)&priv->pcmd_buf[0];
  7467. +
  7468. + mutex_lock(&priv->fwcmd_mutex);
  7469. +
  7470. + memset(pcmd, 0x00, sizeof(*pcmd));
  7471. + pcmd->cmd_hdr.cmd = cpu_to_le16(HOSTCMD_CMD_LED_CTRL);
  7472. + pcmd->cmd_hdr.len = cpu_to_le16(sizeof(*pcmd));
  7473. + pcmd->action = 1; /* 1: set */
  7474. + pcmd->led_enable = enable;
  7475. + pcmd->led_control = 1; /* 1: SW */
  7476. +
  7477. + switch (rate) {
  7478. + case LED_BLINK_RATE_LOW:
  7479. + case LED_BLINK_RATE_MID:
  7480. + case LED_BLINK_RATE_HIGH:
  7481. + pcmd->led_blink_rate = rate;
  7482. + break;
  7483. + default:
  7484. + if (enable) {
  7485. + mutex_unlock(&priv->fwcmd_mutex);
  7486. + return -EINVAL;
  7487. + }
  7488. + break;
  7489. + }
  7490. + if (mwl_hif_exec_cmd(hw, HOSTCMD_CMD_LED_CTRL)) {
  7491. + mutex_unlock(&priv->fwcmd_mutex);
  7492. + return -EIO;
  7493. + }
  7494. +
  7495. + mutex_unlock(&priv->fwcmd_mutex);
  7496. +
  7497. + return 0;
  7498. +}
  7499. +
  7500. +int mwl_fwcmd_get_fw_region_code(struct ieee80211_hw *hw,
  7501. + u32 *fw_region_code)
  7502. +{
  7503. + struct mwl_priv *priv = hw->priv;
  7504. + struct hostcmd_cmd_get_fw_region_code *pcmd;
  7505. + u16 cmd;
  7506. + int status;
  7507. +
  7508. + pcmd = (struct hostcmd_cmd_get_fw_region_code *)&priv->pcmd_buf[0];
  7509. +
  7510. + mutex_lock(&priv->fwcmd_mutex);
  7511. +
  7512. + memset(pcmd, 0x00, sizeof(*pcmd));
  7513. + cmd = HOSTCMD_CMD_GET_FW_REGION_CODE;
  7514. + pcmd->cmd_hdr.cmd = cpu_to_le16(cmd);
  7515. + pcmd->cmd_hdr.len = cpu_to_le16(sizeof(*pcmd));
  7516. +
  7517. + if (mwl_hif_exec_cmd(hw, cmd)) {
  7518. + mutex_unlock(&priv->fwcmd_mutex);
  7519. + return -EIO;
  7520. + }
  7521. +
  7522. + if (pcmd->cmd_hdr.result != 0) {
  7523. + mutex_unlock(&priv->fwcmd_mutex);
  7524. + return -EINVAL;
  7525. + }
  7526. +
  7527. + status = le32_to_cpu(pcmd->status);
  7528. +
  7529. + if (!status)
  7530. + *fw_region_code = le32_to_cpu(pcmd->fw_region_code);
  7531. +
  7532. + mutex_unlock(&priv->fwcmd_mutex);
  7533. +
  7534. + return 0;
  7535. +}
  7536. +
  7537. +int mwl_fwcmd_get_device_pwr_tbl(struct ieee80211_hw *hw,
  7538. + struct mwl_device_pwr_tbl *device_ch_pwrtbl,
  7539. + u8 *region_code,
  7540. + u8 *number_of_channels,
  7541. + u32 channel_index)
  7542. +{
  7543. + struct mwl_priv *priv = hw->priv;
  7544. + struct hostcmd_cmd_get_device_pwr_tbl *pcmd;
  7545. + int status;
  7546. + u16 cmd;
  7547. +
  7548. + pcmd = (struct hostcmd_cmd_get_device_pwr_tbl *)&priv->pcmd_buf[0];
  7549. +
  7550. + mutex_lock(&priv->fwcmd_mutex);
  7551. +
  7552. + memset(pcmd, 0x00, sizeof(*pcmd));
  7553. + cmd = HOSTCMD_CMD_GET_DEVICE_PWR_TBL;
  7554. + pcmd->cmd_hdr.cmd = cpu_to_le16(cmd);
  7555. + pcmd->cmd_hdr.len = cpu_to_le16(sizeof(*pcmd));
  7556. + pcmd->status = cpu_to_le16(cmd);
  7557. + pcmd->current_channel_index = cpu_to_le32(channel_index);
  7558. +
  7559. + if (mwl_hif_exec_cmd(hw, cmd)) {
  7560. + mutex_unlock(&priv->fwcmd_mutex);
  7561. + return -EIO;
  7562. + }
  7563. +
  7564. + device_ch_pwrtbl->channel = pcmd->channel_pwr_tbl.channel;
  7565. + memcpy(device_ch_pwrtbl->tx_pwr, pcmd->channel_pwr_tbl.tx_pwr,
  7566. + priv->pwr_level);
  7567. + device_ch_pwrtbl->dfs_capable = pcmd->channel_pwr_tbl.dfs_capable;
  7568. + device_ch_pwrtbl->ax_ant = pcmd->channel_pwr_tbl.ax_ant;
  7569. + device_ch_pwrtbl->cdd = pcmd->channel_pwr_tbl.cdd;
  7570. + *region_code = pcmd->region_code;
  7571. + *number_of_channels = pcmd->number_of_channels;
  7572. + status = le16_to_cpu(pcmd->status);
  7573. +
  7574. + mutex_unlock(&priv->fwcmd_mutex);
  7575. +
  7576. + return status;
  7577. +}
  7578. +
  7579. +int mwl_fwcmd_set_rate_drop(struct ieee80211_hw *hw, int enable,
  7580. + int value, int staid)
  7581. +{
  7582. + struct mwl_priv *priv = hw->priv;
  7583. + struct hostcmd_cmd_set_rate_drop *pcmd;
  7584. +
  7585. + pcmd = (struct hostcmd_cmd_set_rate_drop *)&priv->pcmd_buf[0];
  7586. +
  7587. + mutex_lock(&priv->fwcmd_mutex);
  7588. +
  7589. + memset(pcmd, 0x00, sizeof(*pcmd));
  7590. + pcmd->cmd_hdr.cmd = cpu_to_le16(HOSTCMD_CMD_SET_RATE_DROP);
  7591. + pcmd->cmd_hdr.len = cpu_to_le16(sizeof(*pcmd));
  7592. + pcmd->enable = cpu_to_le32(enable);
  7593. + pcmd->rate_index = cpu_to_le32(value);
  7594. + pcmd->sta_index = cpu_to_le32(staid);
  7595. +
  7596. + if (mwl_hif_exec_cmd(hw, HOSTCMD_CMD_SET_RATE_DROP)) {
  7597. + mutex_unlock(&priv->fwcmd_mutex);
  7598. + return -EIO;
  7599. + }
  7600. +
  7601. + mutex_unlock(&priv->fwcmd_mutex);
  7602. +
  7603. + return 0;
  7604. +}
  7605. +
  7606. +int mwl_fwcmd_newdp_dmathread_start(struct ieee80211_hw *hw)
  7607. +{
  7608. + struct mwl_priv *priv = hw->priv;
  7609. + struct hostcmd_cmd_newdp_dmathread_start *pcmd;
  7610. + u16 cmd;
  7611. +
  7612. + pcmd = (struct hostcmd_cmd_newdp_dmathread_start *)&priv->pcmd_buf[0];
  7613. +
  7614. + mutex_lock(&priv->fwcmd_mutex);
  7615. +
  7616. + memset(pcmd, 0x00, sizeof(*pcmd));
  7617. + cmd = HOSTCMD_CMD_NEWDP_DMATHREAD_START;
  7618. + pcmd->cmd_hdr.cmd = cpu_to_le16(cmd);
  7619. + pcmd->cmd_hdr.len = cpu_to_le16(sizeof(*pcmd));
  7620. +
  7621. + if (mwl_hif_exec_cmd(hw, cmd)) {
  7622. + mutex_unlock(&priv->fwcmd_mutex);
  7623. + return -EIO;
  7624. + }
  7625. +
  7626. + mutex_unlock(&priv->fwcmd_mutex);
  7627. +
  7628. + return 0;
  7629. +}
  7630. +
  7631. +
  7632. +int mwl_fwcmd_get_fw_region_code_sc4(struct ieee80211_hw *hw,
  7633. + u32 *fw_region_code)
  7634. +{
  7635. + struct mwl_priv *priv = hw->priv;
  7636. + struct hostcmd_cmd_get_fw_region_code_sc4 *pcmd;
  7637. + u16 cmd;
  7638. +
  7639. + pcmd = (struct hostcmd_cmd_get_fw_region_code_sc4 *)&priv->pcmd_buf[0];
  7640. +
  7641. + mutex_lock(&priv->fwcmd_mutex);
  7642. +
  7643. + memset(pcmd, 0x00, sizeof(*pcmd));
  7644. + cmd = HOSTCMD_CMD_GET_FW_REGION_CODE_SC4;
  7645. + pcmd->cmd_hdr.cmd = cpu_to_le16(cmd);
  7646. + pcmd->cmd_hdr.len = cpu_to_le16(sizeof(*pcmd));
  7647. +
  7648. + if (mwl_hif_exec_cmd(hw, cmd)) {
  7649. + mutex_unlock(&priv->fwcmd_mutex);
  7650. + return -EIO;
  7651. + }
  7652. +
  7653. + if (pcmd->cmd_hdr.result != 0) {
  7654. + mutex_unlock(&priv->fwcmd_mutex);
  7655. + return -EINVAL;
  7656. + }
  7657. +
  7658. + if (pcmd->status)
  7659. + *fw_region_code = (pcmd->status == 1) ? 0 : pcmd->status;
  7660. + else
  7661. + *fw_region_code = le32_to_cpu(pcmd->fw_region_code);
  7662. +
  7663. + mutex_unlock(&priv->fwcmd_mutex);
  7664. +
  7665. + return 0;
  7666. +}
  7667. +
  7668. +int mwl_fwcmd_get_pwr_tbl_sc4(struct ieee80211_hw *hw,
  7669. + struct mwl_device_pwr_tbl *device_ch_pwrtbl,
  7670. + u8 *region_code,
  7671. + u8 *number_of_channels,
  7672. + u32 channel_index)
  7673. +{
  7674. + struct mwl_priv *priv = hw->priv;
  7675. + struct hostcmd_cmd_get_device_pwr_tbl_sc4 *pcmd;
  7676. + int status;
  7677. + u16 cmd;
  7678. +
  7679. + pcmd = (struct hostcmd_cmd_get_device_pwr_tbl_sc4 *)&priv->pcmd_buf[0];
  7680. +
  7681. + mutex_lock(&priv->fwcmd_mutex);
  7682. +
  7683. + memset(pcmd, 0x00, sizeof(*pcmd));
  7684. + cmd = HOSTCMD_CMD_GET_DEVICE_PWR_TBL_SC4;
  7685. + pcmd->cmd_hdr.cmd = cpu_to_le16(cmd);
  7686. + pcmd->cmd_hdr.len = cpu_to_le16(sizeof(*pcmd));
  7687. + pcmd->status = cpu_to_le16(cmd);
  7688. + pcmd->current_channel_index = cpu_to_le32(channel_index);
  7689. +
  7690. + if (mwl_hif_exec_cmd(hw, cmd)) {
  7691. + mutex_unlock(&priv->fwcmd_mutex);
  7692. + return -EIO;
  7693. + }
  7694. +
  7695. + device_ch_pwrtbl->channel = pcmd->channel_pwr_tbl.channel;
  7696. + memcpy(device_ch_pwrtbl->tx_pwr, pcmd->channel_pwr_tbl.tx_pwr,
  7697. + SYSADPT_TX_PWR_LEVEL_TOTAL_SC4);
  7698. + device_ch_pwrtbl->dfs_capable = pcmd->channel_pwr_tbl.dfs_capable;
  7699. + device_ch_pwrtbl->ax_ant = pcmd->channel_pwr_tbl.ax_ant;
  7700. + device_ch_pwrtbl->cdd = pcmd->channel_pwr_tbl.cdd;
  7701. + *region_code = pcmd->region_code;
  7702. + *number_of_channels = pcmd->number_of_channels;
  7703. + status = le16_to_cpu(pcmd->status);
  7704. +
  7705. + mutex_unlock(&priv->fwcmd_mutex);
  7706. +
  7707. + return status;
  7708. +}
  7709. +
  7710. +int mwl_fwcmd_quiet_mode(struct ieee80211_hw *hw, bool enable, u32 period,
  7711. + u32 duration, u32 next_offset)
  7712. +{
  7713. + struct mwl_priv *priv = hw->priv;
  7714. + struct hostcmd_cmd_quiet_mode *pcmd;
  7715. +
  7716. + pcmd = (struct hostcmd_cmd_quiet_mode *)&priv->pcmd_buf[0];
  7717. +
  7718. + mutex_lock(&priv->fwcmd_mutex);
  7719. +
  7720. + memset(pcmd, 0x00, sizeof(*pcmd));
  7721. + pcmd->cmd_hdr.cmd = cpu_to_le16(HOSTCMD_CMD_QUIET_MODE);
  7722. + pcmd->cmd_hdr.len = cpu_to_le16(sizeof(*pcmd));
  7723. + pcmd->action = cpu_to_le16(WL_SET);
  7724. + pcmd->enable = cpu_to_le32(enable);
  7725. + if (enable) {
  7726. + pcmd->period = cpu_to_le32(period);
  7727. + pcmd->duration = cpu_to_le32(duration);
  7728. + pcmd->next_offset = cpu_to_le32(next_offset);
  7729. + }
  7730. +
  7731. + if (mwl_hif_exec_cmd(hw, HOSTCMD_CMD_QUIET_MODE)) {
  7732. + mutex_unlock(&priv->fwcmd_mutex);
  7733. + return -EIO;
  7734. + }
  7735. +
  7736. + mutex_unlock(&priv->fwcmd_mutex);
  7737. +
  7738. + return 0;
  7739. +}
  7740. +
  7741. +int mwl_fwcmd_core_dump_diag_mode(struct ieee80211_hw *hw, u16 status)
  7742. +{
  7743. + struct mwl_priv *priv = hw->priv;
  7744. + struct hostcmd_cmd_core_dump_diag_mode *pcmd;
  7745. +
  7746. + pcmd = (struct hostcmd_cmd_core_dump_diag_mode *)&priv->pcmd_buf[0];
  7747. +
  7748. + mutex_lock(&priv->fwcmd_mutex);
  7749. +
  7750. + memset(pcmd, 0x00, sizeof(*pcmd));
  7751. + pcmd->cmd_hdr.cmd = cpu_to_le16(HOSTCMD_CMD_CORE_DUMP_DIAG_MODE);
  7752. + pcmd->cmd_hdr.len = cpu_to_le16(sizeof(*pcmd));
  7753. + pcmd->status = cpu_to_le16(status);
  7754. +
  7755. + if (mwl_hif_exec_cmd(hw, HOSTCMD_CMD_CORE_DUMP_DIAG_MODE)) {
  7756. + mutex_unlock(&priv->fwcmd_mutex);
  7757. + return -EIO;
  7758. + }
  7759. +
  7760. + mutex_unlock(&priv->fwcmd_mutex);
  7761. +
  7762. + return 0;
  7763. +}
  7764. +
  7765. +int mwl_fwcmd_get_fw_core_dump(struct ieee80211_hw *hw,
  7766. + struct coredump_cmd *core_dump, char *buff)
  7767. +{
  7768. + struct mwl_priv *priv = hw->priv;
  7769. + struct hostcmd_cmd_get_fw_core_dump *pcmd;
  7770. +
  7771. + if (priv->chip_type != MWL8964)
  7772. + return -EPERM;
  7773. +
  7774. + pcmd = (struct hostcmd_cmd_get_fw_core_dump *)&priv->pcmd_buf[0];
  7775. +
  7776. + mutex_lock(&priv->fwcmd_mutex);
  7777. +
  7778. + memset(pcmd, 0x00, sizeof(*pcmd));
  7779. + pcmd->cmd_hdr.cmd = cpu_to_le16(HOSTCMD_CMD_GET_FW_CORE_DUMP);
  7780. + pcmd->cmd_hdr.len = cpu_to_le16(sizeof(*pcmd));
  7781. + pcmd->cmd_data.coredump.context = core_dump->context;
  7782. + pcmd->cmd_data.coredump.buffer = cpu_to_le32(priv->pphys_cmd_buf +
  7783. + sizeof(struct hostcmd_cmd_get_fw_core_dump) -
  7784. + sizeof(struct hostcmd_cmd_get_fw_core_dump_));
  7785. + pcmd->cmd_data.coredump.buffer_len = cpu_to_le32(MAX_CORE_DUMP_BUFFER);
  7786. + pcmd->cmd_data.coredump.size_kb = core_dump->size_kb;
  7787. + pcmd->cmd_data.coredump.flags = core_dump->flags;
  7788. +
  7789. + if (mwl_hif_exec_cmd(hw, HOSTCMD_CMD_GET_FW_CORE_DUMP)) {
  7790. + mutex_unlock(&priv->fwcmd_mutex);
  7791. + return -EIO;
  7792. + }
  7793. +
  7794. + /* update core dump buffer */
  7795. + core_dump->context = pcmd->cmd_data.coredump.context;
  7796. + core_dump->size_kb = pcmd->cmd_data.coredump.size_kb;
  7797. + core_dump->flags = pcmd->cmd_data.coredump.flags;
  7798. + memcpy(buff,
  7799. + (const void *)((u32)pcmd +
  7800. + sizeof(struct hostcmd_cmd_get_fw_core_dump) -
  7801. + sizeof(struct hostcmd_cmd_get_fw_core_dump_)),
  7802. + MAX_CORE_DUMP_BUFFER);
  7803. +
  7804. + mutex_unlock(&priv->fwcmd_mutex);
  7805. +
  7806. + return 0;
  7807. +}
  7808. +
  7809. +int mwl_fwcmd_set_slot_time(struct ieee80211_hw *hw, bool short_slot)
  7810. +{
  7811. + struct mwl_priv *priv = hw->priv;
  7812. + struct hostcmd_cmd_802_11_slot_time *pcmd;
  7813. +
  7814. + wiphy_debug(priv->hw->wiphy, "%s(): short_slot_time=%d\n",
  7815. + __func__, short_slot);
  7816. +
  7817. + pcmd = (struct hostcmd_cmd_802_11_slot_time *)&priv->pcmd_buf[0];
  7818. +
  7819. + mutex_lock(&priv->fwcmd_mutex);
  7820. +
  7821. + memset(pcmd, 0x00, sizeof(*pcmd));
  7822. + pcmd->cmd_hdr.cmd = cpu_to_le16(HOSTCMD_CMD_802_11_SLOT_TIME);
  7823. + pcmd->cmd_hdr.len = cpu_to_le16(sizeof(*pcmd));
  7824. + pcmd->action = cpu_to_le16(WL_SET);
  7825. + pcmd->short_slot = cpu_to_le16(short_slot ? 1 : 0);
  7826. +
  7827. + if (mwl_hif_exec_cmd(hw, HOSTCMD_CMD_802_11_SLOT_TIME)) {
  7828. + mutex_unlock(&priv->fwcmd_mutex);
  7829. + return -EIO;
  7830. + }
  7831. +
  7832. + mutex_unlock(&priv->fwcmd_mutex);
  7833. +
  7834. + return 0;
  7835. +}
  7836. +
  7837. +int mwl_fwcmd_config_EDMACCtrl(struct ieee80211_hw *hw, int EDMAC_Ctrl)
  7838. +{
  7839. + struct hostcmd_cmd_edmac_ctrl *pcmd;
  7840. + struct mwl_priv *priv = hw->priv;
  7841. +
  7842. + pcmd = (struct hostcmd_cmd_edmac_ctrl *)&priv->pcmd_buf[0];
  7843. +
  7844. + mutex_lock(&priv->fwcmd_mutex);
  7845. +
  7846. + memset(pcmd, 0x00, sizeof(*pcmd));
  7847. + pcmd->cmd_hdr.cmd = cpu_to_le16(HOSTCMD_CMD_EDMAC_CTRL);
  7848. + pcmd->cmd_hdr.len = cpu_to_le16(sizeof(*pcmd));
  7849. + pcmd->action = cpu_to_le16(WL_SET);
  7850. + pcmd->ed_ctrl_2g = cpu_to_le16((EDMAC_Ctrl & EDMAC_2G_ENABLE_MASK)
  7851. + >> EDMAC_2G_ENABLE_SHIFT);
  7852. + pcmd->ed_ctrl_5g = cpu_to_le16((EDMAC_Ctrl & EDMAC_5G_ENABLE_MASK)
  7853. + >> EDMAC_5G_ENABLE_SHIFT);
  7854. + pcmd->ed_offset_2g = cpu_to_le16((EDMAC_Ctrl &
  7855. + EDMAC_2G_THRESHOLD_OFFSET_MASK)
  7856. + >> EDMAC_2G_THRESHOLD_OFFSET_SHIFT);
  7857. + pcmd->ed_offset_5g = cpu_to_le16((EDMAC_Ctrl &
  7858. + EDMAC_5G_THRESHOLD_OFFSET_MASK)
  7859. + >> EDMAC_5G_THRESHOLD_OFFSET_SHIFT);
  7860. + pcmd->ed_bitmap_txq_lock = cpu_to_le16((EDMAC_Ctrl &
  7861. + EDMAC_QLOCK_BITMAP_MASK)
  7862. + >> EDMAC_QLOCK_BITMAP_SHIFT);
  7863. +
  7864. + if (mwl_hif_exec_cmd(hw, HOSTCMD_CMD_EDMAC_CTRL)) {
  7865. + mutex_unlock(&priv->fwcmd_mutex);
  7866. + return -EIO;
  7867. + }
  7868. +
  7869. + mutex_unlock(&priv->fwcmd_mutex);
  7870. +
  7871. + return 0;
  7872. +}
  7873. +
  7874. +int mwl_fwcmd_set_txpwrlmt_cfg_data(struct ieee80211_hw *hw)
  7875. +{
  7876. + struct mwl_priv *priv = hw->priv;
  7877. + struct hostcmd_cmd_txpwrlmt_cfg *pcmd;
  7878. + struct mwl_txpwrlmt_cfg_entry_hdr hdr;
  7879. + u16 id, parsed_len, size;
  7880. + __le32 txpwr_cfg_sig;
  7881. + u8 version[TXPWRLMT_CFG_VERSION_INFO_LEN];
  7882. + const u8 *ptr;
  7883. +
  7884. + if (!priv->txpwrlmt_file)
  7885. + return 0;
  7886. +
  7887. + ptr = priv->txpwrlmt_file->data;
  7888. + size = priv->txpwrlmt_file->size;
  7889. +
  7890. + /* Parsing TxPwrLmit Conf file Signature */
  7891. + parsed_len = mwl_fwcmd_parse_txpwrlmt_cfg(ptr, size,
  7892. + TXPWRLMT_CFG_SIG_LEN,
  7893. + (u8 *)&txpwr_cfg_sig);
  7894. + ptr += parsed_len;
  7895. + size -= parsed_len;
  7896. +
  7897. + if (le32_to_cpu(txpwr_cfg_sig) != TXPWRLMT_CFG_SIGNATURE) {
  7898. + wiphy_err(hw->wiphy,
  7899. + "txpwrlmt config signature mismatch\n");
  7900. + release_firmware(priv->txpwrlmt_file);
  7901. + priv->txpwrlmt_file = NULL;
  7902. + return 0;
  7903. + }
  7904. +
  7905. + /* Parsing TxPwrLmit Conf file Version */
  7906. + parsed_len = mwl_fwcmd_parse_txpwrlmt_cfg(ptr, size,
  7907. + TXPWRLMT_CFG_VERSION_INFO_LEN,
  7908. + version);
  7909. + ptr += parsed_len;
  7910. + size -= parsed_len;
  7911. +
  7912. + for (id = 0; id < TXPWRLMT_CFG_MAX_SUBBAND_INFO; id++) {
  7913. + u16 data_len;
  7914. +
  7915. + /*Parsing tx pwr cfg subband header info*/
  7916. + parsed_len = sizeof(struct mwl_txpwrlmt_cfg_entry_hdr);
  7917. + parsed_len = mwl_fwcmd_parse_txpwrlmt_cfg(ptr, size,
  7918. + parsed_len,
  7919. + (u8 *)&hdr);
  7920. + ptr += parsed_len;
  7921. + size -= parsed_len;
  7922. + data_len = le16_to_cpu(hdr.len) -
  7923. + sizeof(struct mwl_txpwrlmt_cfg_entry_hdr);
  7924. +
  7925. + pcmd = (struct hostcmd_cmd_txpwrlmt_cfg *)&priv->pcmd_buf[0];
  7926. +
  7927. + mutex_lock(&priv->fwcmd_mutex);
  7928. +
  7929. + memset(pcmd, 0x00, sizeof(*pcmd));
  7930. + pcmd->action = cpu_to_le16(HOSTCMD_ACT_GEN_SET);
  7931. + pcmd->subband_id = hdr.id;
  7932. + pcmd->data_len = cpu_to_le16(data_len);
  7933. + pcmd->num_entries = hdr.num_entries;
  7934. +
  7935. + /* Parsing tx pwr cfg subband header info */
  7936. + parsed_len = mwl_fwcmd_parse_txpwrlmt_cfg(ptr, size,
  7937. + data_len, pcmd->data);
  7938. + ptr += parsed_len;
  7939. + size -= parsed_len;
  7940. +
  7941. + pcmd->cmd_hdr.cmd = cpu_to_le16(HOSTCMD_CMD_TXPWRLMT_CFG);
  7942. + pcmd->cmd_hdr.len = cpu_to_le16(sizeof(*pcmd) +
  7943. + data_len - sizeof(pcmd->data));
  7944. +
  7945. + if (size < sizeof(struct mwl_txpwrlmt_cfg_entry_hdr))
  7946. + pcmd->cfgComplete = 1;
  7947. +
  7948. + if (mwl_hif_exec_cmd(hw, HOSTCMD_CMD_TXPWRLMT_CFG)) {
  7949. + mutex_unlock(&priv->fwcmd_mutex);
  7950. + release_firmware(priv->txpwrlmt_file);
  7951. + priv->txpwrlmt_file = NULL;
  7952. + return -EIO;
  7953. + }
  7954. +
  7955. + mutex_unlock(&priv->fwcmd_mutex);
  7956. + }
  7957. +
  7958. + release_firmware(priv->txpwrlmt_file);
  7959. + priv->txpwrlmt_file = NULL;
  7960. +
  7961. + return 0;
  7962. +}
  7963. +
  7964. +int mwl_fwcmd_get_txpwrlmt_cfg_data(struct ieee80211_hw *hw)
  7965. +{
  7966. + struct mwl_priv *priv = hw->priv;
  7967. + struct hostcmd_cmd_txpwrlmt_cfg *pcmd;
  7968. + u16 subband_len, total_len = 0;
  7969. + u8 id;
  7970. +
  7971. + for (id = 0; id < TXPWRLMT_CFG_MAX_SUBBAND_INFO; id++) {
  7972. + pcmd = (struct hostcmd_cmd_txpwrlmt_cfg *)&priv->pcmd_buf[0];
  7973. +
  7974. + mutex_lock(&priv->fwcmd_mutex);
  7975. +
  7976. + memset(pcmd, 0x00, sizeof(*pcmd));
  7977. + pcmd->action = 0;
  7978. + pcmd->subband_id = id;
  7979. + pcmd->data_len = 0;
  7980. + pcmd->num_entries = 0;
  7981. +
  7982. + pcmd->cmd_hdr.cmd = cpu_to_le16(HOSTCMD_CMD_TXPWRLMT_CFG);
  7983. + pcmd->cmd_hdr.len = cpu_to_le16(sizeof(*pcmd));
  7984. +
  7985. + if (mwl_hif_exec_cmd(hw, HOSTCMD_CMD_TXPWRLMT_CFG)) {
  7986. + mutex_unlock(&priv->fwcmd_mutex);
  7987. + return -EIO;
  7988. + }
  7989. +
  7990. + mutex_unlock(&priv->fwcmd_mutex);
  7991. +
  7992. + subband_len = le16_to_cpu(pcmd->cmd_hdr.len) -
  7993. + sizeof(struct hostcmd_header) - 2;
  7994. + if (total_len <= SYSADPT_TXPWRLMT_CFG_BUF_SIZE) {
  7995. + wiphy_debug(hw->wiphy, "Subband len = %d\n",
  7996. + subband_len);
  7997. + memcpy(priv->txpwrlmt_data.buf + total_len,
  7998. + &pcmd->subband_id, subband_len);
  7999. + total_len += subband_len;
  8000. + priv->txpwrlmt_data.buf[total_len] = '\n';
  8001. + total_len++;
  8002. + priv->txpwrlmt_data.len = total_len;
  8003. + } else {
  8004. + wiphy_err(hw->wiphy,
  8005. + "TxPwrLmt cfg buf size is not enough\n");
  8006. + }
  8007. + }
  8008. +
  8009. + return 0;
  8010. +}
  8011. +
  8012. +int mwl_fwcmd_mcast_cts(struct ieee80211_hw *hw, u8 enable)
  8013. +{
  8014. + struct mwl_priv *priv = hw->priv;
  8015. + struct hostcmd_cmd_mcast_cts *pcmd;
  8016. +
  8017. + pcmd = (struct hostcmd_cmd_mcast_cts *)&priv->pcmd_buf[0];
  8018. +
  8019. + mutex_lock(&priv->fwcmd_mutex);
  8020. +
  8021. + memset(pcmd, 0x00, sizeof(*pcmd));
  8022. + pcmd->cmd_hdr.cmd = cpu_to_le16(HOSTCMD_CMD_MCAST_CTS);
  8023. + pcmd->cmd_hdr.len = cpu_to_le16(sizeof(*pcmd));
  8024. + pcmd->enable = enable;
  8025. +
  8026. + if (mwl_hif_exec_cmd(hw, HOSTCMD_CMD_MCAST_CTS)) {
  8027. + mutex_unlock(&priv->fwcmd_mutex);
  8028. + return -EIO;
  8029. + }
  8030. +
  8031. + mutex_unlock(&priv->fwcmd_mutex);
  8032. +
  8033. + return 0;
  8034. +}
  8035. +
  8036. +void mwl_fwcmd_get_survey(struct ieee80211_hw *hw, int idx)
  8037. +{
  8038. + struct mwl_priv *priv = hw->priv;
  8039. + struct ieee80211_conf *conf = &hw->conf;
  8040. + struct mwl_survey_info *survey_info;
  8041. +
  8042. + if (idx)
  8043. + survey_info = &priv->survey_info[idx - 1];
  8044. + else
  8045. + survey_info = &priv->cur_survey_info;
  8046. +
  8047. + memcpy(&survey_info->channel, conf->chandef.chan,
  8048. + sizeof(struct ieee80211_channel));
  8049. + mwl_hif_get_survey(hw, survey_info);
  8050. +}
  8051. diff --git a/drivers/net/wireless/marvell/mwlwifi/hif/fwcmd.h b/drivers/net/wireless/marvell/mwlwifi/hif/fwcmd.h
  8052. new file mode 100644
  8053. index 000000000000..9565cc447dc6
  8054. --- /dev/null
  8055. +++ b/drivers/net/wireless/marvell/mwlwifi/hif/fwcmd.h
  8056. @@ -0,0 +1,285 @@
  8057. +/*
  8058. + * Copyright (C) 2006-2018, Marvell International Ltd.
  8059. + *
  8060. + * This software file (the "File") is distributed by Marvell International
  8061. + * Ltd. under the terms of the GNU General Public License Version 2, June 1991
  8062. + * (the "License"). You may use, redistribute and/or modify this File in
  8063. + * accordance with the terms and conditions of the License, a copy of which
  8064. + * is available by writing to the Free Software Foundation, Inc.
  8065. + *
  8066. + * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
  8067. + * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
  8068. + * ARE EXPRESSLY DISCLAIMED. The License provides additional details about
  8069. + * this warranty disclaimer.
  8070. + */
  8071. +
  8072. +/* Description: This file defines firmware host command related
  8073. + * functions.
  8074. + */
  8075. +
  8076. +#ifndef _FWCMD_H_
  8077. +#define _FWCMD_H_
  8078. +
  8079. +#include "hif/hostcmd.h"
  8080. +
  8081. +/* Define OpMode for SoftAP/Station mode
  8082. + *
  8083. + * The following mode signature has to be written to PCI scratch register#0
  8084. + * right after successfully downloading the last block of firmware and
  8085. + * before waiting for firmware ready signature
  8086. + */
  8087. +
  8088. +#define HOSTCMD_STA_MODE 0x5A
  8089. +#define HOSTCMD_SOFTAP_MODE 0xA5
  8090. +
  8091. +#define HOSTCMD_STA_FWRDY_SIGNATURE 0xF0F1F2F4
  8092. +#define HOSTCMD_SOFTAP_FWRDY_SIGNATURE 0xF1F2F4A5
  8093. +
  8094. +#define GUARD_INTERVAL_STANDARD 1
  8095. +#define GUARD_INTERVAL_SHORT 2
  8096. +#define GUARD_INTERVAL_AUTO 3
  8097. +
  8098. +#define LINK_CS_STATE_CONSERV 0
  8099. +#define LINK_CS_STATE_AGGR 1
  8100. +#define LINK_CS_STATE_AUTO 2
  8101. +#define LINK_CS_STATE_AUTO_DISABLED 3
  8102. +
  8103. +#define STOP_DETECT_RADAR 0
  8104. +#define CAC_START 1
  8105. +#define MONITOR_START 3
  8106. +
  8107. +#define WDS_MODE 4
  8108. +
  8109. +enum {
  8110. + WL_ANTENNATYPE_RX = 1,
  8111. + WL_ANTENNATYPE_TX = 2,
  8112. +};
  8113. +
  8114. +enum encr_type {
  8115. + ENCR_TYPE_WEP = 0,
  8116. + ENCR_TYPE_DISABLE = 1,
  8117. + ENCR_TYPE_TKIP = 4,
  8118. + ENCR_TYPE_AES = 6,
  8119. + ENCR_TYPE_MIX = 7,
  8120. +};
  8121. +
  8122. +char *mwl_fwcmd_get_cmd_string(unsigned short cmd);
  8123. +
  8124. +const struct hostcmd_get_hw_spec
  8125. +*mwl_fwcmd_get_hw_specs(struct ieee80211_hw *hw);
  8126. +
  8127. +int mwl_fwcmd_set_hw_specs(struct ieee80211_hw *hw,
  8128. + struct hostcmd_set_hw_spec *spec);
  8129. +
  8130. +int mwl_fwcmd_get_stat(struct ieee80211_hw *hw,
  8131. + struct ieee80211_low_level_stats *stats);
  8132. +
  8133. +int mwl_fwcmd_reg_bb(struct ieee80211_hw *hw, u8 flag, u32 reg, u32 *val);
  8134. +
  8135. +int mwl_fwcmd_reg_rf(struct ieee80211_hw *hw, u8 flag, u32 reg, u32 *val);
  8136. +
  8137. +int mwl_fwcmd_radio_enable(struct ieee80211_hw *hw);
  8138. +
  8139. +int mwl_fwcmd_radio_disable(struct ieee80211_hw *hw);
  8140. +
  8141. +int mwl_fwcmd_set_radio_preamble(struct ieee80211_hw *hw,
  8142. + bool short_preamble);
  8143. +
  8144. +int mwl_fwcmd_get_addr_value(struct ieee80211_hw *hw, u32 addr, u32 len,
  8145. + u32 *val, u16 set);
  8146. +
  8147. +int mwl_fwcmd_max_tx_power(struct ieee80211_hw *hw,
  8148. + struct ieee80211_conf *conf, u8 fraction);
  8149. +
  8150. +int mwl_fwcmd_tx_power(struct ieee80211_hw *hw,
  8151. + struct ieee80211_conf *conf, u8 fraction);
  8152. +
  8153. +int mwl_fwcmd_rf_antenna(struct ieee80211_hw *hw, int dir, int antenna);
  8154. +
  8155. +int mwl_fwcmd_broadcast_ssid_enable(struct ieee80211_hw *hw,
  8156. + struct ieee80211_vif *vif, bool enable);
  8157. +
  8158. +int mwl_fwcmd_set_cfg_data(struct ieee80211_hw *hw, u16 type);
  8159. +
  8160. +int mwl_fwcmd_set_rf_channel(struct ieee80211_hw *hw,
  8161. + struct ieee80211_conf *conf);
  8162. +
  8163. +int mwl_fwcmd_set_aid(struct ieee80211_hw *hw,
  8164. + struct ieee80211_vif *vif, u8 *bssid, u16 aid);
  8165. +
  8166. +int mwl_fwcmd_set_infra_mode(struct ieee80211_hw *hw,
  8167. + struct ieee80211_vif *vif);
  8168. +
  8169. +int mwl_fwcmd_set_rts_threshold(struct ieee80211_hw *hw,
  8170. + int threshold);
  8171. +
  8172. +int mwl_fwcmd_set_edca_params(struct ieee80211_hw *hw, u8 index,
  8173. + u16 cw_min, u16 cw_max, u8 aifs, u16 txop);
  8174. +
  8175. +int mwl_fwcmd_set_radar_detect(struct ieee80211_hw *hw, u16 action);
  8176. +
  8177. +int mwl_fwcmd_set_wmm_mode(struct ieee80211_hw *hw, bool enable);
  8178. +
  8179. +int mwl_fwcmd_ht_guard_interval(struct ieee80211_hw *hw, u32 gi_type);
  8180. +
  8181. +int mwl_fwcmd_use_fixed_rate(struct ieee80211_hw *hw,
  8182. + int mcast, int mgmt);
  8183. +
  8184. +int mwl_fwcmd_set_linkadapt_cs_mode(struct ieee80211_hw *hw,
  8185. + u16 cs_mode);
  8186. +
  8187. +int mwl_fwcmd_dump_otp_data(struct ieee80211_hw *hw);
  8188. +
  8189. +int mwl_fwcmd_set_rate_adapt_mode(struct ieee80211_hw *hw,
  8190. + u16 mode);
  8191. +
  8192. +int mwl_fwcmd_set_mac_addr_client(struct ieee80211_hw *hw,
  8193. + struct ieee80211_vif *vif, u8 *mac_addr);
  8194. +
  8195. +int mwl_fwcmd_get_watchdog_bitmap(struct ieee80211_hw *hw,
  8196. + u8 *bitmap);
  8197. +
  8198. +int mwl_fwcmd_remove_mac_addr(struct ieee80211_hw *hw,
  8199. + struct ieee80211_vif *vif, u8 *mac_addr);
  8200. +
  8201. +int mwl_fwcmd_bss_start(struct ieee80211_hw *hw,
  8202. + struct ieee80211_vif *vif, bool enable);
  8203. +
  8204. +int mwl_fwcmd_set_beacon(struct ieee80211_hw *hw,
  8205. + struct ieee80211_vif *vif, u8 *beacon, int len);
  8206. +
  8207. +int mwl_fwcmd_set_new_stn_add(struct ieee80211_hw *hw,
  8208. + struct ieee80211_vif *vif,
  8209. + struct ieee80211_sta *sta);
  8210. +
  8211. +int mwl_fwcmd_set_new_stn_add_sc4(struct ieee80211_hw *hw,
  8212. + struct ieee80211_vif *vif,
  8213. + struct ieee80211_sta *sta,
  8214. + u32 wds);
  8215. +
  8216. +int mwl_fwcmd_set_new_stn_wds_sc4(struct ieee80211_hw *hw, u8 *addr);
  8217. +
  8218. +int mwl_fwcmd_set_new_stn_add_self(struct ieee80211_hw *hw,
  8219. + struct ieee80211_vif *vif);
  8220. +
  8221. +int mwl_fwcmd_set_new_stn_del(struct ieee80211_hw *hw,
  8222. + struct ieee80211_vif *vif, u8 *addr);
  8223. +
  8224. +int mwl_fwcmd_set_apmode(struct ieee80211_hw *hw, u8 apmode);
  8225. +
  8226. +int mwl_fwcmd_set_switch_channel(struct ieee80211_hw *hw,
  8227. + struct ieee80211_channel_switch *ch_switch);
  8228. +
  8229. +int mwl_fwcmd_update_encryption_enable(struct ieee80211_hw *hw,
  8230. + struct ieee80211_vif *vif,
  8231. + u8 *addr, u8 encr_type);
  8232. +
  8233. +int mwl_fwcmd_encryption_set_key(struct ieee80211_hw *hw,
  8234. + struct ieee80211_vif *vif, u8 *addr,
  8235. + struct ieee80211_key_conf *key);
  8236. +
  8237. +int mwl_fwcmd_encryption_remove_key(struct ieee80211_hw *hw,
  8238. + struct ieee80211_vif *vif, u8 *addr,
  8239. + struct ieee80211_key_conf *key);
  8240. +
  8241. +int mwl_fwcmd_check_ba(struct ieee80211_hw *hw,
  8242. + struct mwl_ampdu_stream *stream,
  8243. + struct ieee80211_vif *vif,
  8244. + u32 direction);
  8245. +
  8246. +int mwl_fwcmd_create_ba(struct ieee80211_hw *hw,
  8247. + struct mwl_ampdu_stream *stream,
  8248. + struct ieee80211_vif *vif,
  8249. + u32 direction, u8 buf_size, u16 seqno, bool amsdu);
  8250. +
  8251. +int mwl_fwcmd_destroy_ba(struct ieee80211_hw *hw,
  8252. + struct mwl_ampdu_stream *stream,
  8253. + u32 direction);
  8254. +
  8255. +struct mwl_ampdu_stream *mwl_fwcmd_add_stream(struct ieee80211_hw *hw,
  8256. + struct ieee80211_sta *sta,
  8257. + u8 tid);
  8258. +
  8259. +void mwl_fwcmd_del_sta_streams(struct ieee80211_hw *hw,
  8260. + struct ieee80211_sta *sta);
  8261. +
  8262. +int mwl_fwcmd_start_stream(struct ieee80211_hw *hw,
  8263. + struct mwl_ampdu_stream *stream);
  8264. +
  8265. +void mwl_fwcmd_remove_stream(struct ieee80211_hw *hw,
  8266. + struct mwl_ampdu_stream *stream);
  8267. +
  8268. +struct mwl_ampdu_stream *mwl_fwcmd_lookup_stream(struct ieee80211_hw *hw,
  8269. + struct ieee80211_sta *sta,
  8270. + u8 tid);
  8271. +
  8272. +bool mwl_fwcmd_ampdu_allowed(struct ieee80211_sta *sta, u8 tid);
  8273. +
  8274. +int mwl_fwcmd_set_optimization_level(struct ieee80211_hw *hw, u8 opt_level);
  8275. +
  8276. +int mwl_fwcmd_set_wsc_ie(struct ieee80211_hw *hw, u8 len, u8 *data);
  8277. +
  8278. +int mwl_fwcmd_get_ratetable(struct ieee80211_hw *hw, u8 *addr, u8 *rate_table,
  8279. + u32 size, u8 type);
  8280. +
  8281. +int mwl_fwcmd_get_seqno(struct ieee80211_hw *hw,
  8282. + struct mwl_ampdu_stream *stream, u16 *start_seqno);
  8283. +
  8284. +int mwl_fwcmd_set_dwds_stamode(struct ieee80211_hw *hw, bool enable);
  8285. +
  8286. +int mwl_fwcmd_set_fw_flush_timer(struct ieee80211_hw *hw, u32 value);
  8287. +
  8288. +int mwl_fwcmd_set_cdd(struct ieee80211_hw *hw);
  8289. +
  8290. +int mwl_fwcmd_set_bftype(struct ieee80211_hw *hw, int mode);
  8291. +
  8292. +int mwl_fwcmd_reg_cau(struct ieee80211_hw *hw, u8 flag, u32 reg, u32 *val);
  8293. +
  8294. +int mwl_fwcmd_get_temp(struct ieee80211_hw *hw, u32 *temp);
  8295. +
  8296. +int mwl_fwcmd_led_ctrl(struct ieee80211_hw *hw, u8 enable, u8 rate);
  8297. +
  8298. +int mwl_fwcmd_get_fw_region_code(struct ieee80211_hw *hw,
  8299. + u32 *fw_region_code);
  8300. +
  8301. +int mwl_fwcmd_get_device_pwr_tbl(struct ieee80211_hw *hw,
  8302. + struct mwl_device_pwr_tbl *device_ch_pwrtbl,
  8303. + u8 *region_code,
  8304. + u8 *number_of_channels,
  8305. + u32 channel_index);
  8306. +
  8307. +int mwl_fwcmd_set_rate_drop(struct ieee80211_hw *hw, int enable,
  8308. + int value, int staid);
  8309. +
  8310. +int mwl_fwcmd_newdp_dmathread_start(struct ieee80211_hw *hw);
  8311. +
  8312. +int mwl_fwcmd_get_fw_region_code_sc4(struct ieee80211_hw *hw,
  8313. + u32 *fw_region_code);
  8314. +
  8315. +int mwl_fwcmd_get_pwr_tbl_sc4(struct ieee80211_hw *hw,
  8316. + struct mwl_device_pwr_tbl *device_ch_pwrtbl,
  8317. + u8 *region_code,
  8318. + u8 *number_of_channels,
  8319. + u32 channel_index);
  8320. +
  8321. +int mwl_fwcmd_quiet_mode(struct ieee80211_hw *hw, bool enable, u32 period,
  8322. + u32 duration, u32 next_offset);
  8323. +
  8324. +int mwl_fwcmd_core_dump_diag_mode(struct ieee80211_hw *hw, u16 status);
  8325. +
  8326. +int mwl_fwcmd_get_fw_core_dump(struct ieee80211_hw *hw,
  8327. + struct coredump_cmd *core_dump, char *buff);
  8328. +
  8329. +int mwl_fwcmd_set_slot_time(struct ieee80211_hw *hw, bool short_slot);
  8330. +
  8331. +int mwl_fwcmd_config_EDMACCtrl(struct ieee80211_hw *hw, int EDMAC_Ctrl);
  8332. +
  8333. +int mwl_fwcmd_set_txpwrlmt_cfg_data(struct ieee80211_hw *hw);
  8334. +
  8335. +int mwl_fwcmd_get_txpwrlmt_cfg_data(struct ieee80211_hw *hw);
  8336. +
  8337. +int mwl_fwcmd_mcast_cts(struct ieee80211_hw *hw, u8 enable);
  8338. +
  8339. +void mwl_fwcmd_get_survey(struct ieee80211_hw *hw, int idx);
  8340. +
  8341. +#endif /* _FWCMD_H_ */
  8342. diff --git a/drivers/net/wireless/marvell/mwlwifi/hif/hif-ops.h b/drivers/net/wireless/marvell/mwlwifi/hif/hif-ops.h
  8343. new file mode 100644
  8344. index 000000000000..f5c7144b3c1b
  8345. --- /dev/null
  8346. +++ b/drivers/net/wireless/marvell/mwlwifi/hif/hif-ops.h
  8347. @@ -0,0 +1,297 @@
  8348. +/*
  8349. + * Copyright (C) 2006-2018, Marvell International Ltd.
  8350. + *
  8351. + * This software file (the "File") is distributed by Marvell International
  8352. + * Ltd. under the terms of the GNU General Public License Version 2, June 1991
  8353. + * (the "License"). You may use, redistribute and/or modify this File in
  8354. + * accordance with the terms and conditions of the License, a copy of which
  8355. + * is available by writing to the Free Software Foundation, Inc.
  8356. + *
  8357. + * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
  8358. + * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
  8359. + * ARE EXPRESSLY DISCLAIMED. The License provides additional details about
  8360. + * this warranty disclaimer.
  8361. + */
  8362. +
  8363. +/* Description: This file defines host interface related operations. */
  8364. +
  8365. +#ifndef _HIF_OPS_H_
  8366. +#define _HIF_OPS_H_
  8367. +static inline const char *mwl_hif_get_driver_name(struct ieee80211_hw *hw)
  8368. +{
  8369. + struct mwl_priv *priv = hw->priv;
  8370. +
  8371. + return priv->hif.ops->driver_name;
  8372. +}
  8373. +
  8374. +static inline const char *mwl_hif_get_driver_version(struct ieee80211_hw *hw)
  8375. +{
  8376. + struct mwl_priv *priv = hw->priv;
  8377. +
  8378. + return priv->hif.ops->driver_version;
  8379. +}
  8380. +
  8381. +static inline unsigned int mwl_hif_get_tx_head_room(struct ieee80211_hw *hw)
  8382. +{
  8383. + struct mwl_priv *priv = hw->priv;
  8384. +
  8385. + return priv->hif.ops->tx_head_room;
  8386. +}
  8387. +
  8388. +static inline unsigned int mwl_hif_get_ampdu_num(struct ieee80211_hw *hw)
  8389. +{
  8390. + struct mwl_priv *priv = hw->priv;
  8391. +
  8392. + return priv->hif.ops->ampdu_num;
  8393. +}
  8394. +
  8395. +static inline void mwl_hif_reset(struct ieee80211_hw *hw)
  8396. +{
  8397. + struct mwl_priv *priv = hw->priv;
  8398. +
  8399. + if (priv->hif.ops->reset)
  8400. + priv->hif.ops->reset(hw);
  8401. +}
  8402. +
  8403. +static inline int mwl_hif_init(struct ieee80211_hw *hw)
  8404. +{
  8405. + struct mwl_priv *priv = hw->priv;
  8406. +
  8407. + if (priv->hif.ops->init)
  8408. + return priv->hif.ops->init(hw);
  8409. + else
  8410. + return -ENOTSUPP;
  8411. +}
  8412. +
  8413. +static inline void mwl_hif_deinit(struct ieee80211_hw *hw)
  8414. +{
  8415. + struct mwl_priv *priv = hw->priv;
  8416. +
  8417. + if (priv->hif.ops->deinit)
  8418. + priv->hif.ops->deinit(hw);
  8419. +}
  8420. +
  8421. +static inline int mwl_hif_get_info(struct ieee80211_hw *hw,
  8422. + char *buf, size_t size)
  8423. +{
  8424. + struct mwl_priv *priv = hw->priv;
  8425. +
  8426. + if (priv->hif.ops->get_info)
  8427. + return priv->hif.ops->get_info(hw, buf, size);
  8428. + else
  8429. + return 0;
  8430. +}
  8431. +
  8432. +static inline int mwl_hif_get_tx_status(struct ieee80211_hw *hw,
  8433. + char *buf, size_t size)
  8434. +{
  8435. + struct mwl_priv *priv = hw->priv;
  8436. +
  8437. + if (priv->hif.ops->get_tx_status)
  8438. + return priv->hif.ops->get_tx_status(hw, buf, size);
  8439. + else
  8440. + return 0;
  8441. +}
  8442. +
  8443. +static inline int mwl_hif_get_rx_status(struct ieee80211_hw *hw,
  8444. + char *buf, size_t size)
  8445. +{
  8446. + struct mwl_priv *priv = hw->priv;
  8447. +
  8448. + if (priv->hif.ops->get_rx_status)
  8449. + return priv->hif.ops->get_rx_status(hw, buf, size);
  8450. + else
  8451. + return 0;
  8452. +}
  8453. +
  8454. +static inline void mwl_hif_enable_data_tasks(struct ieee80211_hw *hw)
  8455. +{
  8456. + struct mwl_priv *priv = hw->priv;
  8457. +
  8458. + if (priv->hif.ops->enable_data_tasks)
  8459. + priv->hif.ops->enable_data_tasks(hw);
  8460. +}
  8461. +
  8462. +static inline void mwl_hif_disable_data_tasks(struct ieee80211_hw *hw)
  8463. +{
  8464. + struct mwl_priv *priv = hw->priv;
  8465. +
  8466. + if (priv->hif.ops->disable_data_tasks)
  8467. + priv->hif.ops->disable_data_tasks(hw);
  8468. +}
  8469. +
  8470. +static inline int mwl_hif_exec_cmd(struct ieee80211_hw *hw, unsigned short cmd)
  8471. +{
  8472. + struct mwl_priv *priv = hw->priv;
  8473. +
  8474. + if (priv->hif.ops->exec_cmd)
  8475. + return priv->hif.ops->exec_cmd(hw, cmd);
  8476. + else
  8477. + return -ENOTSUPP;
  8478. +}
  8479. +
  8480. +static inline int mwl_hif_get_irq_num(struct ieee80211_hw *hw)
  8481. +{
  8482. + struct mwl_priv *priv = hw->priv;
  8483. +
  8484. + if (priv->hif.ops->get_irq_num)
  8485. + return priv->hif.ops->get_irq_num(hw);
  8486. + else
  8487. + return -ENOTSUPP;
  8488. +}
  8489. +
  8490. +static inline irqreturn_t mwl_hif_irq_handler(struct ieee80211_hw *hw)
  8491. +{
  8492. + struct mwl_priv *priv = hw->priv;
  8493. +
  8494. + if (priv->hif.ops->irq_handler)
  8495. + return priv->hif.ops->irq_handler(hw);
  8496. + else
  8497. + return -ENOTSUPP;
  8498. +}
  8499. +
  8500. +static inline void mwl_hif_irq_enable(struct ieee80211_hw *hw)
  8501. +{
  8502. + struct mwl_priv *priv = hw->priv;
  8503. +
  8504. + if (priv->hif.ops->irq_enable)
  8505. + priv->hif.ops->irq_enable(hw);
  8506. +}
  8507. +
  8508. +static inline void mwl_hif_irq_disable(struct ieee80211_hw *hw)
  8509. +{
  8510. + struct mwl_priv *priv = hw->priv;
  8511. +
  8512. + if (priv->hif.ops->irq_disable)
  8513. + priv->hif.ops->irq_disable(hw);
  8514. +}
  8515. +
  8516. +static inline int mwl_hif_download_firmware(struct ieee80211_hw *hw)
  8517. +{
  8518. + struct mwl_priv *priv = hw->priv;
  8519. +
  8520. + if (priv->hif.ops->download_firmware)
  8521. + return priv->hif.ops->download_firmware(hw);
  8522. + else
  8523. + return -ENOTSUPP;
  8524. +}
  8525. +
  8526. +static inline void mwl_hif_timer_routine(struct ieee80211_hw *hw)
  8527. +{
  8528. + struct mwl_priv *priv = hw->priv;
  8529. +
  8530. + if (priv->hif.ops->timer_routine)
  8531. + priv->hif.ops->timer_routine(hw);
  8532. +}
  8533. +
  8534. +static inline void mwl_hif_tx_xmit(struct ieee80211_hw *hw,
  8535. + struct ieee80211_tx_control *control,
  8536. + struct sk_buff *skb)
  8537. +{
  8538. + struct mwl_priv *priv = hw->priv;
  8539. +
  8540. + if (priv->hif.ops->tx_xmit)
  8541. + priv->hif.ops->tx_xmit(hw, control, skb);
  8542. +}
  8543. +
  8544. +static inline void mwl_hif_tx_del_pkts_via_vif(struct ieee80211_hw *hw,
  8545. + struct ieee80211_vif *vif)
  8546. +{
  8547. + struct mwl_priv *priv = hw->priv;
  8548. +
  8549. + if (priv->hif.ops->tx_del_pkts_via_vif)
  8550. + priv->hif.ops->tx_del_pkts_via_vif(hw, vif);
  8551. +}
  8552. +
  8553. +static inline void mwl_hif_tx_del_pkts_via_sta(struct ieee80211_hw *hw,
  8554. + struct ieee80211_sta *sta)
  8555. +{
  8556. + struct mwl_priv *priv = hw->priv;
  8557. +
  8558. + if (priv->hif.ops->tx_del_pkts_via_sta)
  8559. + priv->hif.ops->tx_del_pkts_via_sta(hw, sta);
  8560. +}
  8561. +
  8562. +static inline void mwl_hif_tx_del_ampdu_pkts(struct ieee80211_hw *hw,
  8563. + struct ieee80211_sta *sta, u8 tid)
  8564. +{
  8565. + struct mwl_priv *priv = hw->priv;
  8566. +
  8567. + if (priv->hif.ops->tx_del_ampdu_pkts)
  8568. + priv->hif.ops->tx_del_ampdu_pkts(hw, sta, tid);
  8569. +}
  8570. +
  8571. +static inline void mwl_hif_tx_del_sta_amsdu_pkts(struct ieee80211_hw *hw,
  8572. + struct ieee80211_sta *sta)
  8573. +{
  8574. + struct mwl_priv *priv = hw->priv;
  8575. +
  8576. + if (priv->hif.ops->tx_del_sta_amsdu_pkts)
  8577. + priv->hif.ops->tx_del_sta_amsdu_pkts(hw, sta);
  8578. +}
  8579. +
  8580. +static inline void mwl_hif_tx_return_pkts(struct ieee80211_hw *hw)
  8581. +{
  8582. + struct mwl_priv *priv = hw->priv;
  8583. +
  8584. + if (priv->hif.ops->tx_return_pkts)
  8585. + priv->hif.ops->tx_return_pkts(hw);
  8586. +}
  8587. +
  8588. +static inline struct device_node *mwl_hif_device_node(struct ieee80211_hw *hw)
  8589. +{
  8590. + struct mwl_priv *priv = hw->priv;
  8591. +
  8592. + if (priv->hif.ops->get_device_node)
  8593. + return priv->hif.ops->get_device_node(hw);
  8594. + else
  8595. + return NULL;
  8596. +}
  8597. +
  8598. +static inline void mwl_hif_get_survey(struct ieee80211_hw *hw,
  8599. + struct mwl_survey_info *survey_info)
  8600. +{
  8601. + struct mwl_priv *priv = hw->priv;
  8602. +
  8603. + if (priv->hif.ops->get_survey)
  8604. + priv->hif.ops->get_survey(hw, survey_info);
  8605. +}
  8606. +
  8607. +static inline int mwl_hif_reg_access(struct ieee80211_hw *hw, bool write)
  8608. +{
  8609. + struct mwl_priv *priv = hw->priv;
  8610. +
  8611. + if (priv->hif.ops->reg_access)
  8612. + return priv->hif.ops->reg_access(hw, write);
  8613. + else
  8614. + return -ENOTSUPP;
  8615. +}
  8616. +
  8617. +static inline void mwl_hif_set_sta_id(struct ieee80211_hw *hw,
  8618. + struct ieee80211_sta *sta,
  8619. + bool sta_mode, bool set)
  8620. +{
  8621. + struct mwl_priv *priv = hw->priv;
  8622. +
  8623. + if (priv->hif.ops->set_sta_id)
  8624. + priv->hif.ops->set_sta_id(hw, sta, sta_mode, set);
  8625. +}
  8626. +
  8627. +static inline void mwl_hif_process_account(struct ieee80211_hw *hw)
  8628. +{
  8629. + struct mwl_priv *priv = hw->priv;
  8630. +
  8631. + if (priv->hif.ops->process_account)
  8632. + priv->hif.ops->process_account(hw);
  8633. +}
  8634. +
  8635. +static inline int mwl_hif_mcast_cts(struct ieee80211_hw *hw, bool enable)
  8636. +{
  8637. + struct mwl_priv *priv = hw->priv;
  8638. +
  8639. + if (priv->hif.ops->mcast_cts)
  8640. + return priv->hif.ops->mcast_cts(hw, enable);
  8641. + else
  8642. + return -ENOTSUPP;
  8643. +}
  8644. +#endif /* _HIF_OPS_H_ */
  8645. diff --git a/drivers/net/wireless/marvell/mwlwifi/hif/hif.h b/drivers/net/wireless/marvell/mwlwifi/hif/hif.h
  8646. new file mode 100644
  8647. index 000000000000..6ea6192ac5e0
  8648. --- /dev/null
  8649. +++ b/drivers/net/wireless/marvell/mwlwifi/hif/hif.h
  8650. @@ -0,0 +1,81 @@
  8651. +/*
  8652. + * Copyright (C) 2006-2018, Marvell International Ltd.
  8653. + *
  8654. + * This software file (the "File") is distributed by Marvell International
  8655. + * Ltd. under the terms of the GNU General Public License Version 2, June 1991
  8656. + * (the "License"). You may use, redistribute and/or modify this File in
  8657. + * accordance with the terms and conditions of the License, a copy of which
  8658. + * is available by writing to the Free Software Foundation, Inc.
  8659. + *
  8660. + * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
  8661. + * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
  8662. + * ARE EXPRESSLY DISCLAIMED. The License provides additional details about
  8663. + * this warranty disclaimer.
  8664. + */
  8665. +
  8666. +/* Description: This file defines host interface data structure. */
  8667. +
  8668. +#ifndef _HIF_H_
  8669. +#define _HIF_H_
  8670. +
  8671. +/* memory/register access */
  8672. +#define MWL_ACCESS_MAC 1
  8673. +#define MWL_ACCESS_RF 2
  8674. +#define MWL_ACCESS_BBP 3
  8675. +#define MWL_ACCESS_CAU 4
  8676. +#define MWL_ACCESS_ADDR0 5
  8677. +#define MWL_ACCESS_ADDR1 6
  8678. +#define MWL_ACCESS_ADDR 7
  8679. +
  8680. +struct mwl_survey_info {
  8681. + struct ieee80211_channel channel;
  8682. + u32 filled;
  8683. + u32 time_period;
  8684. + u32 time_busy;
  8685. + u32 time_tx;
  8686. + s8 noise;
  8687. +};
  8688. +
  8689. +struct mwl_hif_ops {
  8690. + const char *driver_name;
  8691. + const char *driver_version;
  8692. + unsigned int tx_head_room;
  8693. + int ampdu_num;
  8694. + void (*reset)(struct ieee80211_hw *hw);
  8695. + int (*init)(struct ieee80211_hw *hw);
  8696. + void (*deinit)(struct ieee80211_hw *hw);
  8697. + int (*get_info)(struct ieee80211_hw *hw, char *buf, size_t size);
  8698. + int (*get_tx_status)(struct ieee80211_hw *hw, char *buf, size_t size);
  8699. + int (*get_rx_status)(struct ieee80211_hw *hw, char *buf, size_t size);
  8700. + void (*enable_data_tasks)(struct ieee80211_hw *hw);
  8701. + void (*disable_data_tasks)(struct ieee80211_hw *hw);
  8702. + int (*exec_cmd)(struct ieee80211_hw *hw, unsigned short cmd);
  8703. + int (*get_irq_num)(struct ieee80211_hw *hw);
  8704. + irqreturn_t (*irq_handler)(struct ieee80211_hw *hw);
  8705. + void (*irq_enable)(struct ieee80211_hw *hw);
  8706. + void (*irq_disable)(struct ieee80211_hw *hw);
  8707. + int (*download_firmware)(struct ieee80211_hw *hw);
  8708. + void (*timer_routine)(struct ieee80211_hw *hw);
  8709. + void (*tx_xmit)(struct ieee80211_hw *hw,
  8710. + struct ieee80211_tx_control *control,
  8711. + struct sk_buff *skb);
  8712. + void (*tx_del_pkts_via_vif)(struct ieee80211_hw *hw,
  8713. + struct ieee80211_vif *vif);
  8714. + void (*tx_del_pkts_via_sta)(struct ieee80211_hw *hw,
  8715. + struct ieee80211_sta *sta);
  8716. + void (*tx_del_ampdu_pkts)(struct ieee80211_hw *hw,
  8717. + struct ieee80211_sta *sta, u8 tid);
  8718. + void (*tx_del_sta_amsdu_pkts)(struct ieee80211_hw *hw,
  8719. + struct ieee80211_sta *sta);
  8720. + void (*tx_return_pkts)(struct ieee80211_hw *hw);
  8721. + struct device_node *(*get_device_node)(struct ieee80211_hw *hw);
  8722. + void (*get_survey)(struct ieee80211_hw *hw,
  8723. + struct mwl_survey_info *survey_info);
  8724. + int (*reg_access)(struct ieee80211_hw *hw, bool write);
  8725. + void (*set_sta_id)(struct ieee80211_hw *hw,
  8726. + struct ieee80211_sta *sta,
  8727. + bool sta_mode, bool set);
  8728. + void (*process_account)(struct ieee80211_hw *hw);
  8729. + int (*mcast_cts)(struct ieee80211_hw *hw, bool enable);
  8730. +};
  8731. +#endif /* _HIF_H_ */
  8732. diff --git a/drivers/net/wireless/marvell/mwlwifi/hif/hostcmd.h b/drivers/net/wireless/marvell/mwlwifi/hif/hostcmd.h
  8733. new file mode 100644
  8734. index 000000000000..b14f161f1410
  8735. --- /dev/null
  8736. +++ b/drivers/net/wireless/marvell/mwlwifi/hif/hostcmd.h
  8737. @@ -0,0 +1,1285 @@
  8738. +/*
  8739. + * Copyright (C) 2006-2018, Marvell International Ltd.
  8740. + *
  8741. + * This software file (the "File") is distributed by Marvell International
  8742. + * Ltd. under the terms of the GNU General Public License Version 2, June 1991
  8743. + * (the "License"). You may use, redistribute and/or modify this File in
  8744. + * accordance with the terms and conditions of the License, a copy of which
  8745. + * is available by writing to the Free Software Foundation, Inc.
  8746. + *
  8747. + * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
  8748. + * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
  8749. + * ARE EXPRESSLY DISCLAIMED. The License provides additional details about
  8750. + * this warranty disclaimer.
  8751. + */
  8752. +
  8753. +/* Description: This file defines firmware host command related
  8754. + * structure.
  8755. + */
  8756. +
  8757. +#ifndef _HOSTCMD_H_
  8758. +#define _HOSTCMD_H_
  8759. +
  8760. +/* 16 bit host command code */
  8761. +#define HOSTCMD_CMD_GET_HW_SPEC 0x0003
  8762. +#define HOSTCMD_CMD_SET_HW_SPEC 0x0004
  8763. +#define HOSTCMD_CMD_802_11_GET_STAT 0x0014
  8764. +#define HOSTCMD_CMD_BBP_REG_ACCESS 0x001a
  8765. +#define HOSTCMD_CMD_RF_REG_ACCESS 0x001b
  8766. +#define HOSTCMD_CMD_802_11_RADIO_CONTROL 0x001c
  8767. +#define HOSTCMD_CMD_MEM_ADDR_ACCESS 0x001d
  8768. +#define HOSTCMD_CMD_802_11_TX_POWER 0x001f
  8769. +#define HOSTCMD_CMD_802_11_RF_ANTENNA 0x0020
  8770. +#define HOSTCMD_CMD_BROADCAST_SSID_ENABLE 0x0050 /* per-vif */
  8771. +#define HOSTCMD_CMD_SET_CFG 0x008f
  8772. +#define HOSTCMD_CMD_SET_RF_CHANNEL 0x010a
  8773. +#define HOSTCMD_CMD_SET_AID 0x010d /* per-vif */
  8774. +#define HOSTCMD_CMD_SET_INFRA_MODE 0x010e /* per-vif */
  8775. +#define HOSTCMD_CMD_802_11_RTS_THSD 0x0113
  8776. +#define HOSTCMD_CMD_SET_EDCA_PARAMS 0x0115
  8777. +#define HOSTCMD_CMD_802_11H_DETECT_RADAR 0x0120
  8778. +#define HOSTCMD_CMD_SET_WMM_MODE 0x0123
  8779. +#define HOSTCMD_CMD_HT_GUARD_INTERVAL 0x0124
  8780. +#define HOSTCMD_CMD_SET_FIXED_RATE 0x0126
  8781. +#define HOSTCMD_CMD_SET_IES 0x0127
  8782. +#define HOSTCMD_CMD_SET_LINKADAPT_CS_MODE 0x0129
  8783. +#define HOSTCMD_CMD_DUMP_OTP_DATA 0x0142
  8784. +#define HOSTCMD_CMD_SET_MAC_ADDR 0x0202 /* per-vif */
  8785. +#define HOSTCMD_CMD_SET_RATE_ADAPT_MODE 0x0203
  8786. +#define HOSTCMD_CMD_GET_WATCHDOG_BITMAP 0x0205
  8787. +#define HOSTCMD_CMD_DEL_MAC_ADDR 0x0206 /* per-vif */
  8788. +#define HOSTCMD_CMD_BSS_START 0x1100 /* per-vif */
  8789. +#define HOSTCMD_CMD_AP_BEACON 0x1101 /* per-vif */
  8790. +#define HOSTCMD_CMD_SET_NEW_STN 0x1111 /* per-vif */
  8791. +#define HOSTCMD_CMD_SET_APMODE 0x1114
  8792. +#define HOSTCMD_CMD_SET_SWITCH_CHANNEL 0x1121
  8793. +#define HOSTCMD_CMD_UPDATE_ENCRYPTION 0x1122 /* per-vif */
  8794. +#define HOSTCMD_CMD_BASTREAM 0x1125
  8795. +#define HOSTCMD_CMD_SET_SPECTRUM_MGMT 0x1128
  8796. +#define HOSTCMD_CMD_SET_POWER_CONSTRAINT 0x1129
  8797. +#define HOSTCMD_CMD_SET_COUNTRY_CODE 0x1130
  8798. +#define HOSTCMD_CMD_SET_OPTIMIZATION_LEVEL 0x1133
  8799. +#define HOSTCMD_CMD_SET_WSC_IE 0x1136 /* per-vif */
  8800. +#define HOSTCMD_CMD_GET_RATETABLE 0x1137
  8801. +#define HOSTCMD_CMD_GET_SEQNO 0x1143
  8802. +#define HOSTCMD_CMD_DWDS_ENABLE 0x1144
  8803. +#define HOSTCMD_CMD_FW_FLUSH_TIMER 0x1148
  8804. +#define HOSTCMD_CMD_SET_CDD 0x1150
  8805. +#define HOSTCMD_CMD_SET_BFTYPE 0x1155
  8806. +#define HOSTCMD_CMD_CAU_REG_ACCESS 0x1157
  8807. +#define HOSTCMD_CMD_GET_TEMP 0x1159
  8808. +#define HOSTCMD_CMD_LED_CTRL 0x1169
  8809. +#define HOSTCMD_CMD_GET_FW_REGION_CODE 0x116A
  8810. +#define HOSTCMD_CMD_GET_DEVICE_PWR_TBL 0x116B
  8811. +#define HOSTCMD_CMD_SET_RATE_DROP 0x1172
  8812. +#define HOSTCMD_CMD_NEWDP_DMATHREAD_START 0x1189
  8813. +#define HOSTCMD_CMD_GET_FW_REGION_CODE_SC4 0x118A
  8814. +#define HOSTCMD_CMD_GET_DEVICE_PWR_TBL_SC4 0x118B
  8815. +#define HOSTCMD_CMD_QUIET_MODE 0x1201
  8816. +#define HOSTCMD_CMD_CORE_DUMP_DIAG_MODE 0x1202
  8817. +#define HOSTCMD_CMD_802_11_SLOT_TIME 0x1203
  8818. +#define HOSTCMD_CMD_GET_FW_CORE_DUMP 0x1203
  8819. +#define HOSTCMD_CMD_EDMAC_CTRL 0x1204
  8820. +#define HOSTCMD_CMD_TXPWRLMT_CFG 0x1211
  8821. +#define HOSTCMD_CMD_MCAST_CTS 0x4001
  8822. +
  8823. +/* Define general result code for each command */
  8824. +#define HOSTCMD_RESULT_OK 0x0000
  8825. +/* General error */
  8826. +#define HOSTCMD_RESULT_ERROR 0x0001
  8827. +/* Command is not valid */
  8828. +#define HOSTCMD_RESULT_NOT_SUPPORT 0x0002
  8829. +/* Command is pending (will be processed) */
  8830. +#define HOSTCMD_RESULT_PENDING 0x0003
  8831. +/* System is busy (command ignored) */
  8832. +#define HOSTCMD_RESULT_BUSY 0x0004
  8833. +/* Data buffer is not big enough */
  8834. +#define HOSTCMD_RESULT_PARTIAL_DATA 0x0005
  8835. +
  8836. +/* Define channel related constants */
  8837. +#define FREQ_BAND_2DOT4GHZ 0x1
  8838. +#define FREQ_BAND_4DOT9GHZ 0x2
  8839. +#define FREQ_BAND_5GHZ 0x4
  8840. +#define FREQ_BAND_5DOT2GHZ 0x8
  8841. +#define CH_AUTO_WIDTH 0
  8842. +#define CH_10_MHZ_WIDTH 0x1
  8843. +#define CH_20_MHZ_WIDTH 0x2
  8844. +#define CH_40_MHZ_WIDTH 0x4
  8845. +#define CH_80_MHZ_WIDTH 0x5
  8846. +#define CH_160_MHZ_WIDTH 0x6
  8847. +#define EXT_CH_ABOVE_CTRL_CH 0x1
  8848. +#define EXT_CH_AUTO 0x2
  8849. +#define EXT_CH_BELOW_CTRL_CH 0x3
  8850. +#define NO_EXT_CHANNEL 0x0
  8851. +
  8852. +#define ACT_PRIMARY_CHAN_0 0
  8853. +#define ACT_PRIMARY_CHAN_1 1
  8854. +#define ACT_PRIMARY_CHAN_2 2
  8855. +#define ACT_PRIMARY_CHAN_3 3
  8856. +#define ACT_PRIMARY_CHAN_4 4
  8857. +#define ACT_PRIMARY_CHAN_5 5
  8858. +#define ACT_PRIMARY_CHAN_6 6
  8859. +#define ACT_PRIMARY_CHAN_7 7
  8860. +
  8861. +/* Define rate related constants */
  8862. +#define HOSTCMD_ACT_NOT_USE_FIXED_RATE 0x0002
  8863. +
  8864. +/* Define station related constants */
  8865. +#define HOSTCMD_ACT_STA_ACTION_ADD 0
  8866. +#define HOSTCMD_ACT_STA_ACTION_MODIFY 1
  8867. +#define HOSTCMD_ACT_STA_ACTION_REMOVE 2
  8868. +
  8869. +/* Define key related constants */
  8870. +#define MAX_ENCR_KEY_LENGTH 16
  8871. +#define MIC_KEY_LENGTH 8
  8872. +
  8873. +#define KEY_TYPE_ID_WEP 0x00
  8874. +#define KEY_TYPE_ID_TKIP 0x01
  8875. +#define KEY_TYPE_ID_AES 0x02
  8876. +
  8877. +/* Group key for RX only */
  8878. +#define ENCR_KEY_FLAG_RXGROUPKEY 0x00000002
  8879. +#define ENCR_KEY_FLAG_TXGROUPKEY 0x00000004
  8880. +#define ENCR_KEY_FLAG_PAIRWISE 0x00000008
  8881. +#define ENCR_KEY_FLAG_TSC_VALID 0x00000040
  8882. +#define ENCR_KEY_FLAG_WEP_TXKEY 0x01000000
  8883. +#define ENCR_KEY_FLAG_MICKEY_VALID 0x02000000
  8884. +
  8885. +/* Define block ack related constants */
  8886. +#define BA_FLAG_IMMEDIATE_TYPE 1
  8887. +#define BA_FLAG_DIRECTION_UP 0
  8888. +#define BA_FLAG_DIRECTION_DOWN 1
  8889. +
  8890. +/* Define general purpose action */
  8891. +#define HOSTCMD_ACT_GEN_SET 0x0001
  8892. +#define HOSTCMD_ACT_GEN_SET_LIST 0x0002
  8893. +#define HOSTCMD_ACT_GEN_GET_LIST 0x0003
  8894. +
  8895. +/* Define TXPower control action*/
  8896. +#define HOSTCMD_ACT_GET_TARGET_TX_PWR 0x0000
  8897. +#define HOSTCMD_ACT_GET_MAX_TX_PWR 0x0001
  8898. +#define HOSTCMD_ACT_SET_TARGET_TX_PWR 0x0002
  8899. +#define HOSTCMD_ACT_SET_MAX_TX_PWR 0x0003
  8900. +
  8901. +/* Misc */
  8902. +#define WSC_IE_MAX_LENGTH 251
  8903. +#define WSC_IE_SET_BEACON 0
  8904. +#define WSC_IE_SET_PROBE_RESPONSE 1
  8905. +
  8906. +#define HW_SET_PARMS_FEATURES_HOST_PROBE_RESP 0x00000020
  8907. +
  8908. +#define EDMAC_2G_ENABLE_MASK 0x00000001
  8909. +#define EDMAC_2G_ENABLE_SHIFT 0x0
  8910. +#define EDMAC_5G_ENABLE_MASK 0x00000002
  8911. +#define EDMAC_5G_ENABLE_SHIFT 0x1
  8912. +#define EDMAC_2G_THRESHOLD_OFFSET_MASK 0x00000FF0
  8913. +#define EDMAC_2G_THRESHOLD_OFFSET_SHIFT 0x4
  8914. +#define EDMAC_5G_THRESHOLD_OFFSET_MASK 0x000FF000
  8915. +#define EDMAC_5G_THRESHOLD_OFFSET_SHIFT 0xC
  8916. +#define EDMAC_QLOCK_BITMAP_MASK 0x0FF00000
  8917. +#define EDMAC_QLOCK_BITMAP_SHIFT 0x14
  8918. +
  8919. +enum {
  8920. + WL_DISABLE = 0,
  8921. + WL_ENABLE = 1,
  8922. + WL_DISABLE_VMAC = 0x80,
  8923. +};
  8924. +
  8925. +enum {
  8926. + WL_GET = 0,
  8927. + WL_SET = 1,
  8928. + WL_RESET = 2,
  8929. +};
  8930. +
  8931. +enum {
  8932. + WL_LONG_PREAMBLE = 1,
  8933. + WL_SHORT_PREAMBLE = 3,
  8934. + WL_AUTO_PREAMBLE = 5,
  8935. +};
  8936. +
  8937. +enum encr_action_type {
  8938. + /* request to enable/disable HW encryption */
  8939. + ENCR_ACTION_ENABLE_HW_ENCR,
  8940. + /* request to set encryption key */
  8941. + ENCR_ACTION_TYPE_SET_KEY,
  8942. + /* request to remove one or more keys */
  8943. + ENCR_ACTION_TYPE_REMOVE_KEY,
  8944. + ENCR_ACTION_TYPE_SET_GROUP_KEY,
  8945. +};
  8946. +
  8947. +enum ba_action_type {
  8948. + BA_CREATE_STREAM,
  8949. + BA_UPDATE_STREAM,
  8950. + BA_DESTROY_STREAM,
  8951. + BA_FLUSH_STREAM,
  8952. + BA_CHECK_STREAM,
  8953. +};
  8954. +
  8955. +enum mac_type {
  8956. + WL_MAC_TYPE_PRIMARY_CLIENT,
  8957. + WL_MAC_TYPE_SECONDARY_CLIENT,
  8958. + WL_MAC_TYPE_PRIMARY_AP,
  8959. + WL_MAC_TYPE_SECONDARY_AP,
  8960. +};
  8961. +
  8962. +/* General host command header */
  8963. +struct hostcmd_header {
  8964. + __le16 cmd;
  8965. + __le16 len;
  8966. + u8 seq_num;
  8967. + u8 macid;
  8968. + __le16 result;
  8969. +} __packed;
  8970. +
  8971. +/* HOSTCMD_CMD_GET_HW_SPEC */
  8972. +struct hostcmd_get_hw_spec {
  8973. + u8 version; /* version of the HW */
  8974. + u8 host_if; /* host interface */
  8975. + __le16 num_wcb; /* Max. number of WCB FW can handle */
  8976. + __le16 num_mcast_addr; /* MaxNbr of MC addresses FW can handle */
  8977. + u8 permanent_addr[ETH_ALEN]; /* MAC address programmed in HW */
  8978. + __le16 region_code;
  8979. + __le16 num_antenna; /* Number of antenna used */
  8980. + __le32 fw_release_num; /* 4 byte of FW release number */
  8981. + __le32 wcb_base0;
  8982. + __le32 rxpd_wr_ptr;
  8983. + __le32 rxpd_rd_ptr;
  8984. + __le32 fw_awake_cookie;
  8985. + __le32 wcb_base[SYSADPT_TOTAL_TX_QUEUES - 1];
  8986. +} __packed;
  8987. +
  8988. +struct hostcmd_cmd_get_hw_spec {
  8989. + struct hostcmd_header cmd_hdr;
  8990. + struct hostcmd_get_hw_spec hw_spec;
  8991. +} __packed;
  8992. +
  8993. +/* HOSTCMD_CMD_SET_HW_SPEC */
  8994. +struct hostcmd_set_hw_spec {
  8995. + /* HW revision */
  8996. + u8 version;
  8997. + /* Host interface */
  8998. + u8 host_if;
  8999. + /* Max. number of Multicast address FW can handle */
  9000. + __le16 num_mcast_addr;
  9001. + /* MAC address */
  9002. + u8 permanent_addr[ETH_ALEN];
  9003. + /* Region Code */
  9004. + __le16 region_code;
  9005. + /* 4 byte of FW release number, example 0x1234=1.2.3.4 */
  9006. + __le32 fw_release_num;
  9007. + /* Firmware awake cookie - used to ensure that the device
  9008. + * is not in sleep mode
  9009. + */
  9010. + __le32 fw_awake_cookie;
  9011. + /* Device capabilities (see above) */
  9012. + __le32 device_caps;
  9013. + /* Rx shared memory queue */
  9014. + __le32 rxpd_wr_ptr;
  9015. + /* Actual number of TX queues in WcbBase array */
  9016. + __le32 num_tx_queues;
  9017. + /* TX WCB Rings */
  9018. + __le32 wcb_base[4 + SYSADPT_NUM_OF_AP];
  9019. + /* Max AMSDU size (00 - AMSDU Disabled,
  9020. + * 01 - 4K, 10 - 8K, 11 - not defined)
  9021. + */
  9022. + __le32 features;
  9023. + __le32 tx_wcb_num_per_queue;
  9024. + __le32 total_rx_wcb;
  9025. + __le32 acnt_buf_size;
  9026. + __le32 acnt_base_addr;
  9027. +} __packed;
  9028. +
  9029. +struct hostcmd_cmd_set_hw_spec {
  9030. + struct hostcmd_header cmd_hdr;
  9031. + struct hostcmd_set_hw_spec hw_spec;
  9032. +} __packed;
  9033. +
  9034. +/* HOSTCMD_CMD_802_11_GET_STAT */
  9035. +struct hostcmd_cmd_802_11_get_stat {
  9036. + struct hostcmd_header cmd_hdr;
  9037. + __le32 tx_retry_successes;
  9038. + __le32 tx_multiple_retry_successes;
  9039. + __le32 tx_failures;
  9040. + __le32 rts_successes;
  9041. + __le32 rts_failures;
  9042. + __le32 ack_failures;
  9043. + __le32 rx_duplicate_frames;
  9044. + __le32 rx_fcs_errors;
  9045. + __le32 tx_watchdog_timeouts;
  9046. + __le32 rx_overflows;
  9047. + __le32 rx_frag_errors;
  9048. + __le32 rx_mem_errors;
  9049. + __le32 pointer_errors;
  9050. + __le32 tx_underflows;
  9051. + __le32 tx_done;
  9052. + __le32 tx_done_buf_try_put;
  9053. + __le32 tx_done_buf_put;
  9054. + /* Put size of requested buffer in here */
  9055. + __le32 wait_for_tx_buf;
  9056. + __le32 tx_attempts;
  9057. + __le32 tx_successes;
  9058. + __le32 tx_fragments;
  9059. + __le32 tx_multicasts;
  9060. + __le32 rx_non_ctl_pkts;
  9061. + __le32 rx_multicasts;
  9062. + __le32 rx_undecryptable_frames;
  9063. + __le32 rx_icv_errors;
  9064. + __le32 rx_excluded_frames;
  9065. + __le32 rx_weak_iv_count;
  9066. + __le32 rx_unicasts;
  9067. + __le32 rx_bytes;
  9068. + __le32 rx_errors;
  9069. + __le32 rx_rts_count;
  9070. + __le32 tx_cts_count;
  9071. +} __packed;
  9072. +
  9073. +/* HOSTCMD_CMD_BBP_REG_ACCESS */
  9074. +struct hostcmd_cmd_bbp_reg_access {
  9075. + struct hostcmd_header cmd_hdr;
  9076. + __le16 action;
  9077. + __le16 offset;
  9078. + u8 value;
  9079. + u8 reserverd[3];
  9080. +} __packed;
  9081. +
  9082. +/* HOSTCMD_CMD_RF_REG_ACCESS */
  9083. +struct hostcmd_cmd_rf_reg_access {
  9084. + struct hostcmd_header cmd_hdr;
  9085. + __le16 action;
  9086. + __le16 offset;
  9087. + u8 value;
  9088. + u8 reserverd[3];
  9089. +} __packed;
  9090. +
  9091. +/* HOSTCMD_CMD_802_11_RADIO_CONTROL */
  9092. +struct hostcmd_cmd_802_11_radio_control {
  9093. + struct hostcmd_header cmd_hdr;
  9094. + __le16 action;
  9095. + /* @bit0: 1/0,on/off, @bit1: 1/0, long/short @bit2: 1/0,auto/fix */
  9096. + __le16 control;
  9097. + __le16 radio_on;
  9098. +} __packed;
  9099. +
  9100. +/* HOSTCMD_CMD_MEM_ADDR_ACCESS */
  9101. +struct hostcmd_cmd_mem_addr_access {
  9102. + struct hostcmd_header cmd_hdr;
  9103. + __le32 address;
  9104. + __le16 length;
  9105. + __le16 reserved;
  9106. + __le32 value[64];
  9107. +} __packed;
  9108. +
  9109. +/* HOSTCMD_CMD_802_11_TX_POWER */
  9110. +struct hostcmd_cmd_802_11_tx_power {
  9111. + struct hostcmd_header cmd_hdr;
  9112. + __le16 action;
  9113. + __le16 band;
  9114. + __le16 ch;
  9115. + __le16 bw;
  9116. + __le16 sub_ch;
  9117. + __le16 power_level_list[SYSADPT_TX_POWER_LEVEL_TOTAL];
  9118. +} __packed;
  9119. +
  9120. +struct hostcmd_cmd_802_11_tx_power_kf2 {
  9121. + struct hostcmd_header cmd_hdr;
  9122. + __le16 action;
  9123. + __le16 band;
  9124. + __le16 ch;
  9125. + __le16 bw;
  9126. + __le16 sub_ch;
  9127. + __le16 power_level_list[SYSADPT_TX_GRP_PWR_LEVEL_TOTAL];
  9128. +} __packed;
  9129. +
  9130. +/* HOSTCMD_CMD_802_11_RF_ANTENNA */
  9131. +struct hostcmd_cmd_802_11_rf_antenna {
  9132. + struct hostcmd_header cmd_hdr;
  9133. + __le16 action;
  9134. + __le16 antenna_mode; /* Number of antennas or 0xffff(diversity) */
  9135. +} __packed;
  9136. +
  9137. +/* HOSTCMD_CMD_BROADCAST_SSID_ENABLE */
  9138. +struct hostcmd_cmd_broadcast_ssid_enable {
  9139. + struct hostcmd_header cmd_hdr;
  9140. + __le32 enable;
  9141. + __le32 hidden_ssid_info;
  9142. +} __packed;
  9143. +
  9144. +/* HOSTCMD_CMD_SET_CFG */
  9145. +struct hostcmd_cmd_set_cfg {
  9146. + struct hostcmd_header cmd_hdr;
  9147. + /* Action */
  9148. + __le16 action;
  9149. + /* Type */
  9150. + __le16 type;
  9151. + /* Data length */
  9152. + __le16 data_len;
  9153. + /* Data */
  9154. + u8 data[1];
  9155. +} __packed;
  9156. +
  9157. +/* HOSTCMD_CMD_SET_RF_CHANNEL */
  9158. +#define FREQ_BAND_MASK 0x0000003f
  9159. +#define CHNL_WIDTH_MASK 0x000007c0
  9160. +#define CHNL_WIDTH_SHIFT 6
  9161. +#define ACT_PRIMARY_MASK 0x00003800
  9162. +#define ACT_PRIMARY_SHIFT 11
  9163. +
  9164. +struct hostcmd_cmd_set_rf_channel {
  9165. + struct hostcmd_header cmd_hdr;
  9166. + __le16 action;
  9167. + u8 curr_chnl;
  9168. + __le32 chnl_flags;
  9169. +} __packed;
  9170. +
  9171. +struct hostcmd_cmd_set_rf_channel_kf2 {
  9172. + struct hostcmd_header cmd_hdr;
  9173. + __le16 action;
  9174. + u8 curr_chnl;
  9175. + __le32 chnl_flags;
  9176. + u8 remain_on_chan;
  9177. +} __packed;
  9178. +
  9179. +/* HOSTCMD_CMD_SET_AID */
  9180. +struct hostcmd_cmd_set_aid {
  9181. + struct hostcmd_header cmd_hdr;
  9182. + __le16 aid;
  9183. + u8 mac_addr[ETH_ALEN]; /* AP's Mac Address(BSSID) */
  9184. + __le32 gprotect;
  9185. + u8 ap_rates[SYSADPT_MAX_DATA_RATES_G];
  9186. +} __packed;
  9187. +
  9188. +/* HOSTCMD_CMD_SET_INFRA_MODE */
  9189. +struct hostcmd_cmd_set_infra_mode {
  9190. + struct hostcmd_header cmd_hdr;
  9191. +} __packed;
  9192. +
  9193. +/* HOSTCMD_CMD_802_11_RTS_THSD */
  9194. +struct hostcmd_cmd_802_11_rts_thsd {
  9195. + struct hostcmd_header cmd_hdr;
  9196. + __le16 action;
  9197. + __le16 threshold;
  9198. +} __packed;
  9199. +
  9200. +/* HOSTCMD_CMD_SET_EDCA_PARAMS */
  9201. +struct hostcmd_cmd_set_edca_params {
  9202. + struct hostcmd_header cmd_hdr;
  9203. + /* 0 = get all, 0x1 =set CWMin/Max, 0x2 = set TXOP , 0x4 =set AIFSN */
  9204. + __le16 action;
  9205. + __le16 txop; /* in unit of 32 us */
  9206. + __le32 cw_max; /* 0~15 */
  9207. + __le32 cw_min; /* 0~15 */
  9208. + u8 aifsn;
  9209. + u8 txq_num; /* Tx Queue number. */
  9210. +} __packed;
  9211. +
  9212. +/* HOSTCMD_CMD_802_11H_DETECT_RADAR */
  9213. +#define RADAR_TYPE_CODE_0 0
  9214. +#define RADAR_TYPE_CODE_53 53
  9215. +#define RADAR_TYPE_CODE_56 56
  9216. +#define RADAR_TYPE_CODE_ETSI 151
  9217. +
  9218. +struct hostcmd_cmd_802_11h_detect_radar {
  9219. + struct hostcmd_header cmd_hdr;
  9220. + __le16 action;
  9221. + __le16 radar_type_code;
  9222. + __le16 min_chirp_cnt;
  9223. + __le16 chirp_time_intvl;
  9224. + __le16 pw_filter;
  9225. + __le16 min_num_radar;
  9226. + __le16 pri_min_num;
  9227. +} __packed;
  9228. +
  9229. +/* HOSTCMD_CMD_SET_WMM_MODE */
  9230. +struct hostcmd_cmd_set_wmm_mode {
  9231. + struct hostcmd_header cmd_hdr;
  9232. + __le16 action; /* 0->unset, 1->set */
  9233. +} __packed;
  9234. +
  9235. +/* HOSTCMD_CMD_HT_GUARD_INTERVAL */
  9236. +struct hostcmd_cmd_ht_guard_interval {
  9237. + struct hostcmd_header cmd_hdr;
  9238. + __le32 action;
  9239. + __le32 gi_type;
  9240. +} __packed;
  9241. +
  9242. +/* HOSTCMD_CMD_SET_FIXED_RATE */
  9243. +struct fix_rate_flag { /* lower rate after the retry count */
  9244. + /* 0: legacy, 1: HT */
  9245. + __le32 fix_rate_type;
  9246. + /* 0: retry count is not valid, 1: use retry count specified */
  9247. + __le32 retry_count_valid;
  9248. +} __packed;
  9249. +
  9250. +struct fix_rate_entry {
  9251. + struct fix_rate_flag fix_rate_type_flags;
  9252. + /* depending on the flags above, this can be either a legacy
  9253. + * rate(not index) or an MCS code.
  9254. + */
  9255. + __le32 fixed_rate;
  9256. + __le32 retry_count;
  9257. +} __packed;
  9258. +
  9259. +struct hostcmd_cmd_set_fixed_rate {
  9260. + struct hostcmd_header cmd_hdr;
  9261. + /* HOSTCMD_ACT_NOT_USE_FIXED_RATE 0x0002 */
  9262. + __le32 action;
  9263. + /* use fixed rate specified but firmware can drop to */
  9264. + __le32 allow_rate_drop;
  9265. + __le32 entry_count;
  9266. + struct fix_rate_entry fixed_rate_table[4];
  9267. + u8 multicast_rate;
  9268. + u8 multi_rate_tx_type;
  9269. + u8 management_rate;
  9270. +} __packed;
  9271. +
  9272. +/* HOSTCMD_CMD_SET_IES */
  9273. +struct hostcmd_cmd_set_ies {
  9274. + struct hostcmd_header cmd_hdr;
  9275. + __le16 action; /* 0->unset, 1->set */
  9276. + __le16 ie_list_len_ht;
  9277. + __le16 ie_list_len_vht;
  9278. + __le16 ie_list_len_proprietary;
  9279. + /*Buffer size same as Generic_Beacon*/
  9280. + u8 ie_list_ht[148];
  9281. + u8 ie_list_vht[24];
  9282. + u8 ie_list_proprietary[112];
  9283. +} __packed;
  9284. +
  9285. +/* HOSTCMD_CMD_SET_LINKADAPT_CS_MODE */
  9286. +struct hostcmd_cmd_set_linkadapt_cs_mode {
  9287. + struct hostcmd_header cmd_hdr;
  9288. + __le16 action;
  9289. + __le16 cs_mode;
  9290. +} __packed;
  9291. +
  9292. +/* HOSTCMD_CMD_DUMP_OTP_DATA */
  9293. +struct hostcmd_cmd_dump_otp_data {
  9294. + struct hostcmd_header cmd_hdr;
  9295. + u8 pload[0];
  9296. +} __packed;
  9297. +
  9298. +/* HOSTCMD_CMD_SET_MAC_ADDR, HOSTCMD_CMD_DEL_MAC_ADDR */
  9299. +struct hostcmd_cmd_set_mac_addr {
  9300. + struct hostcmd_header cmd_hdr;
  9301. + __le16 mac_type;
  9302. + u8 mac_addr[ETH_ALEN];
  9303. +} __packed;
  9304. +
  9305. +/* HOSTCMD_CMD_SET_RATE_ADAPT_MODE */
  9306. +struct hostcmd_cmd_set_rate_adapt_mode {
  9307. + struct hostcmd_header cmd_hdr;
  9308. + __le16 action;
  9309. + __le16 rate_adapt_mode; /* 0:Indoor, 1:Outdoor */
  9310. +} __packed;
  9311. +
  9312. +/* HOSTCMD_CMD_GET_WATCHDOG_BITMAP */
  9313. +struct hostcmd_cmd_get_watchdog_bitmap {
  9314. + struct hostcmd_header cmd_hdr;
  9315. + u8 watchdog_bitmap; /* for SW/BA */
  9316. +} __packed;
  9317. +
  9318. +/* HOSTCMD_CMD_BSS_START */
  9319. +struct hostcmd_cmd_bss_start {
  9320. + struct hostcmd_header cmd_hdr;
  9321. + __le32 enable; /* FALSE: Disable or TRUE: Enable */
  9322. + u8 amsdu;
  9323. +} __packed;
  9324. +
  9325. +/* HOSTCMD_CMD_AP_BEACON */
  9326. +struct cf_params {
  9327. + u8 elem_id;
  9328. + u8 len;
  9329. + u8 cfp_cnt;
  9330. + u8 cfp_period;
  9331. + __le16 cfp_max_duration;
  9332. + __le16 cfp_duration_remaining;
  9333. +} __packed;
  9334. +
  9335. +struct ibss_params {
  9336. + u8 elem_id;
  9337. + u8 len;
  9338. + __le16 atim_window;
  9339. +} __packed;
  9340. +
  9341. +union ss_params {
  9342. + struct cf_params cf_param_set;
  9343. + struct ibss_params ibss_param_set;
  9344. +} __packed;
  9345. +
  9346. +struct fh_params {
  9347. + u8 elem_id;
  9348. + u8 len;
  9349. + __le16 dwell_time;
  9350. + u8 hop_set;
  9351. + u8 hop_pattern;
  9352. + u8 hop_index;
  9353. +} __packed;
  9354. +
  9355. +struct ds_params {
  9356. + u8 elem_id;
  9357. + u8 len;
  9358. + u8 current_chnl;
  9359. +} __packed;
  9360. +
  9361. +union phy_params {
  9362. + struct fh_params fh_param_set;
  9363. + struct ds_params ds_param_set;
  9364. +} __packed;
  9365. +
  9366. +struct rsn_ie {
  9367. + u8 elem_id;
  9368. + u8 len;
  9369. + u8 oui_type[4]; /* 00:50:f2:01 */
  9370. + u8 ver[2];
  9371. + u8 grp_key_cipher[4];
  9372. + u8 pws_key_cnt[2];
  9373. + u8 pws_key_cipher_list[4];
  9374. + u8 auth_key_cnt[2];
  9375. + u8 auth_key_list[4];
  9376. +} __packed;
  9377. +
  9378. +struct rsn48_ie {
  9379. + u8 elem_id;
  9380. + u8 len;
  9381. + u8 ver[2];
  9382. + u8 grp_key_cipher[4];
  9383. + u8 pws_key_cnt[2];
  9384. + u8 pws_key_cipher_list[4];
  9385. + u8 auth_key_cnt[2];
  9386. + u8 auth_key_list[4];
  9387. + u8 rsn_cap[2];
  9388. + u8 pmk_id_cnt[2];
  9389. + u8 pmk_id_list[16]; /* Should modify to 16 * S */
  9390. + u8 reserved[8];
  9391. +} __packed;
  9392. +
  9393. +struct ac_param_rcd {
  9394. + u8 aci_aifsn;
  9395. + u8 ecw_min_max;
  9396. + __le16 txop_lim;
  9397. +} __packed;
  9398. +
  9399. +struct wmm_param_elem {
  9400. + u8 elem_id;
  9401. + u8 len;
  9402. + u8 oui[3];
  9403. + u8 type;
  9404. + u8 sub_type;
  9405. + u8 version;
  9406. + u8 qos_info;
  9407. + u8 rsvd;
  9408. + struct ac_param_rcd ac_be;
  9409. + struct ac_param_rcd ac_bk;
  9410. + struct ac_param_rcd ac_vi;
  9411. + struct ac_param_rcd ac_vo;
  9412. +} __packed;
  9413. +
  9414. +struct channel_info {
  9415. + u8 first_channel_num;
  9416. + u8 num_channels;
  9417. + u8 max_tx_pwr_level;
  9418. +} __packed;
  9419. +
  9420. +struct country {
  9421. + u8 elem_id;
  9422. + u8 len;
  9423. + u8 country_str[3];
  9424. + struct channel_info channel_info[40];
  9425. +} __packed;
  9426. +
  9427. +struct start_cmd {
  9428. + u8 sta_mac_addr[ETH_ALEN];
  9429. + u8 ssid[IEEE80211_MAX_SSID_LEN];
  9430. + u8 bss_type;
  9431. + __le16 bcn_period;
  9432. + u8 dtim_period;
  9433. + union ss_params ss_param_set;
  9434. + union phy_params phy_param_set;
  9435. + __le16 probe_delay;
  9436. + __le16 cap_info;
  9437. + u8 b_rate_set[SYSADPT_MAX_DATA_RATES_G];
  9438. + u8 op_rate_set[SYSADPT_MAX_DATA_RATES_G];
  9439. + struct rsn_ie rsn_ie;
  9440. + struct rsn48_ie rsn48_ie;
  9441. + struct wmm_param_elem wmm_param;
  9442. + struct country country;
  9443. + __le32 ap_rf_type; /* 0->B, 1->G, 2->Mixed, 3->A, 4->11J */
  9444. + u8 rsvd[3];
  9445. + u8 bssid[ETH_ALEN]; /* only for 88W8997 */
  9446. +} __packed;
  9447. +
  9448. +struct hostcmd_cmd_ap_beacon {
  9449. + struct hostcmd_header cmd_hdr;
  9450. + struct start_cmd start_cmd;
  9451. +} __packed;
  9452. +
  9453. +/* HOSTCMD_CMD_SET_NEW_STN */
  9454. +struct add_ht_info {
  9455. + u8 control_chnl;
  9456. + u8 add_chnl;
  9457. + __le16 op_mode;
  9458. + __le16 stbc;
  9459. +} __packed;
  9460. +
  9461. +struct peer_info {
  9462. + __le32 legacy_rate_bitmap;
  9463. + u8 ht_rates[4];
  9464. + __le16 cap_info;
  9465. + __le16 ht_cap_info;
  9466. + u8 mac_ht_param_info;
  9467. + u8 mrvl_sta;
  9468. + struct add_ht_info add_ht_info;
  9469. + __le32 tx_bf_capabilities; /* EXBF_SUPPORT */
  9470. + __le32 vht_max_rx_mcs;
  9471. + __le32 vht_cap;
  9472. + /* 0:20Mhz, 1:40Mhz, 2:80Mhz, 3:160 or 80+80Mhz */
  9473. + u8 vht_rx_channel_width;
  9474. +} __packed;
  9475. +
  9476. +struct hostcmd_cmd_set_new_stn {
  9477. + struct hostcmd_header cmd_hdr;
  9478. + __le16 aid;
  9479. + u8 mac_addr[ETH_ALEN];
  9480. + __le16 stn_id;
  9481. + __le16 action;
  9482. + __le16 if_type;
  9483. + struct peer_info peer_info;
  9484. + /* UAPSD_SUPPORT */
  9485. + u8 qos_info;
  9486. + u8 is_qos_sta;
  9487. + __le32 fw_sta_ptr;
  9488. +} __packed;
  9489. +
  9490. +struct retry_cnt_qos {
  9491. + u8 retry_cfg_enable;
  9492. + u8 retry_cnt_BK;
  9493. + u8 retry_cnt_BE;
  9494. + u8 retry_cnt_VI;
  9495. + u8 retry_cnt_VO;
  9496. +} __packed;
  9497. +
  9498. +struct peer_info_sc4 {
  9499. + __le32 legacy_rate_bitmap;
  9500. + u8 ht_rates[4];
  9501. + __le16 cap_info;
  9502. + __le16 ht_cap_info;
  9503. + u8 mac_ht_param_info;
  9504. + u8 mrvl_sta;
  9505. + struct add_ht_info add_ht_info;
  9506. + __le32 tx_bf_capabilities; /* EXBF_SUPPORT */
  9507. + __le32 vht_max_rx_mcs;
  9508. + __le32 vht_cap;
  9509. + /* 0:20Mhz, 1:40Mhz, 2:80Mhz, 3:160 or 80+80Mhz */
  9510. + u8 vht_rx_channel_width;
  9511. + struct retry_cnt_qos retry_cnt_qos;
  9512. + u8 assoc_rssi;
  9513. +} __packed;
  9514. +
  9515. +struct hostcmd_cmd_set_new_stn_sc4 {
  9516. + struct hostcmd_header cmd_hdr;
  9517. + __le16 aid;
  9518. + u8 mac_addr[ETH_ALEN];
  9519. + __le16 stn_id;
  9520. + __le16 action;
  9521. + __le16 reserved;
  9522. + struct peer_info_sc4 peer_info;
  9523. + /* UAPSD_SUPPORT */
  9524. + u8 qos_info;
  9525. + u8 is_qos_sta;
  9526. + __le32 fw_sta_ptr;
  9527. + __le32 wds;
  9528. +} __packed;
  9529. +
  9530. +/* HOSTCMD_CMD_SET_APMODE */
  9531. +struct hostcmd_cmd_set_apmode {
  9532. + struct hostcmd_header cmd_hdr;
  9533. + u8 apmode;
  9534. +} __packed;
  9535. +
  9536. +/* HOSTCMD_CMD_SET_SWITCH_CHANNEL */
  9537. +struct hostcmd_cmd_set_switch_channel {
  9538. + struct hostcmd_header cmd_hdr;
  9539. + __le32 next_11h_chnl;
  9540. + __le32 mode;
  9541. + __le32 init_count;
  9542. + __le32 chnl_flags;
  9543. + __le32 next_ht_extchnl_offset;
  9544. + __le32 dfs_test_mode;
  9545. +} __packed;
  9546. +
  9547. +/* HOSTCMD_CMD_UPDATE_ENCRYPTION */
  9548. +struct hostcmd_cmd_update_encryption {
  9549. + struct hostcmd_header cmd_hdr;
  9550. + /* Action type - see encr_action_type */
  9551. + __le32 action_type; /* encr_action_type */
  9552. + /* size of the data buffer attached. */
  9553. + __le32 data_length;
  9554. + u8 mac_addr[ETH_ALEN];
  9555. + u8 action_data[1];
  9556. +} __packed;
  9557. +
  9558. +struct wep_type_key {
  9559. + /* WEP key material (max 128bit) */
  9560. + u8 key_material[MAX_ENCR_KEY_LENGTH];
  9561. +} __packed;
  9562. +
  9563. +struct encr_tkip_seqcnt {
  9564. + __le16 low;
  9565. + __le32 high;
  9566. +} __packed;
  9567. +
  9568. +struct tkip_type_key {
  9569. + /* TKIP Key material. Key type (group or pairwise key) is
  9570. + * determined by flags
  9571. + */
  9572. + /* in KEY_PARAM_SET structure. */
  9573. + u8 key_material[MAX_ENCR_KEY_LENGTH];
  9574. + /* MIC keys */
  9575. + u8 tkip_tx_mic_key[MIC_KEY_LENGTH];
  9576. + u8 tkip_rx_mic_key[MIC_KEY_LENGTH];
  9577. + struct encr_tkip_seqcnt tkip_rsc;
  9578. + struct encr_tkip_seqcnt tkip_tsc;
  9579. +} __packed;
  9580. +
  9581. +struct aes_type_key {
  9582. + /* AES Key material */
  9583. + u8 key_material[MAX_ENCR_KEY_LENGTH];
  9584. +} __packed;
  9585. +
  9586. +union mwl_key_type {
  9587. + struct wep_type_key wep_key;
  9588. + struct tkip_type_key tkip_key;
  9589. + struct aes_type_key aes_key;
  9590. +} __packed;
  9591. +
  9592. +struct key_param_set {
  9593. + /* Total length of this structure (Key is variable size array) */
  9594. + __le16 length;
  9595. + /* Key type - WEP, TKIP or AES-CCMP. */
  9596. + /* See definitions above */
  9597. + __le16 key_type_id;
  9598. + /* key flags (ENCR_KEY_FLAG_XXX_ */
  9599. + __le32 key_info;
  9600. + /* For WEP only - actual key index */
  9601. + __le32 key_index;
  9602. + /* Size of the key */
  9603. + __le16 key_len;
  9604. + /* Key material (variable size array) */
  9605. + union mwl_key_type key;
  9606. + u8 mac_addr[ETH_ALEN];
  9607. +} __packed;
  9608. +
  9609. +struct hostcmd_cmd_set_key {
  9610. + struct hostcmd_header cmd_hdr;
  9611. + /* Action type - see encr_action_type */
  9612. + __le32 action_type; /* encr_action_type */
  9613. + /* size of the data buffer attached. */
  9614. + __le32 data_length;
  9615. + /* data buffer - maps to one KEY_PARAM_SET structure */
  9616. + struct key_param_set key_param;
  9617. +} __packed;
  9618. +
  9619. +/* HOSTCMD_CMD_BASTREAM */
  9620. +#define BA_TYPE_MASK 0x00000001
  9621. +#define BA_DIRECTION_MASK 0x0000000e
  9622. +#define BA_DIRECTION_SHIFT 1
  9623. +
  9624. +#define BA_TYPE_MASK_NDP 0x00000003
  9625. +#define BA_DIRECTION_MASK_NDP 0x0000001c
  9626. +#define BA_DIRECTION_SHIFT_NDP 2
  9627. +
  9628. +struct ba_context {
  9629. + __le32 context;
  9630. +} __packed;
  9631. +
  9632. +/* parameters for block ack creation */
  9633. +struct create_ba_params {
  9634. + /* BA Creation flags - see above */
  9635. + __le32 flags;
  9636. + /* idle threshold */
  9637. + __le32 idle_thrs;
  9638. + /* block ack transmit threshold (after how many pkts should we
  9639. + * send BAR?)
  9640. + */
  9641. + __le32 bar_thrs;
  9642. + /* receiver window size */
  9643. + __le32 window_size;
  9644. + /* MAC Address of the BA partner */
  9645. + u8 peer_mac_addr[ETH_ALEN];
  9646. + /* Dialog Token */
  9647. + u8 dialog_token;
  9648. + /* TID for the traffic stream in this BA */
  9649. + u8 tid;
  9650. + /* shared memory queue ID (not sure if this is required) */
  9651. + u8 queue_id;
  9652. + u8 param_info;
  9653. + /* returned by firmware - firmware context pointer. */
  9654. + /* this context pointer will be passed to firmware for all
  9655. + * future commands.
  9656. + */
  9657. + struct ba_context fw_ba_context;
  9658. + u8 reset_seq_no; /** 0 or 1**/
  9659. + __le16 current_seq;
  9660. + __le32 vht_rx_factor;
  9661. + /* This is for virtual station in Sta proxy mode for V6FW */
  9662. + u8 sta_src_mac_addr[ETH_ALEN];
  9663. +} __packed;
  9664. +
  9665. +/* new transmit sequence number information */
  9666. +struct ba_update_seq_num {
  9667. + /* BA flags - see above */
  9668. + __le32 flags;
  9669. + /* returned by firmware in the create ba stream response */
  9670. + struct ba_context fw_ba_context;
  9671. + /* new sequence number for this block ack stream */
  9672. + __le16 ba_seq_num;
  9673. +} __packed;
  9674. +
  9675. +struct ba_stream_context {
  9676. + /* BA Stream flags */
  9677. + __le32 flags;
  9678. + /* returned by firmware in the create ba stream response */
  9679. + struct ba_context fw_ba_context;
  9680. + u8 tid;
  9681. + u8 peer_mac_addr[ETH_ALEN];
  9682. +} __packed;
  9683. +
  9684. +union ba_info {
  9685. + /* information required to create BA Stream... */
  9686. + struct create_ba_params create_params;
  9687. + /* update starting/new sequence number etc. */
  9688. + struct ba_update_seq_num updt_seq_num;
  9689. + /* destroy an existing stream... */
  9690. + struct ba_stream_context destroy_params;
  9691. + /* destroy an existing stream... */
  9692. + struct ba_stream_context flush_params;
  9693. +} __packed;
  9694. +
  9695. +struct hostcmd_cmd_bastream {
  9696. + struct hostcmd_header cmd_hdr;
  9697. + __le32 action_type;
  9698. + union ba_info ba_info;
  9699. +} __packed;
  9700. +
  9701. +/* HOSTCMD_CMD_SET_SPECTRUM_MGMT */
  9702. +struct hostcmd_cmd_set_spectrum_mgmt {
  9703. + struct hostcmd_header cmd_hdr;
  9704. + __le32 spectrum_mgmt;
  9705. +} __packed;
  9706. +
  9707. +/* HOSTCMD_CMD_SET_POWER_CONSTRAINT */
  9708. +struct hostcmd_cmd_set_power_constraint {
  9709. + struct hostcmd_header cmd_hdr;
  9710. + __le32 power_constraint;
  9711. +} __packed;
  9712. +
  9713. +/* HOSTCMD_CMD_SET_COUNTRY_CODE */
  9714. +struct domain_chnl_entry {
  9715. + u8 first_chnl_num;
  9716. + u8 chnl_num;
  9717. + u8 max_transmit_pw;
  9718. +} __packed;
  9719. +
  9720. +struct domain_country_info {
  9721. + u8 country_string[3];
  9722. + u8 g_chnl_len;
  9723. + struct domain_chnl_entry domain_entry_g[1];
  9724. + u8 a_chnl_len;
  9725. + struct domain_chnl_entry domain_entry_a[20];
  9726. +} __packed;
  9727. +
  9728. +struct hostcmd_cmd_set_country_code {
  9729. + struct hostcmd_header cmd_hdr;
  9730. + __le32 action ; /* 0 -> unset, 1 ->set */
  9731. + struct domain_country_info domain_info;
  9732. +} __packed;
  9733. +
  9734. +/* HOSTCMD_CMD_SET_OPTIMIZATION_LEVEL */
  9735. +struct hostcmd_cmd_set_optimization_level {
  9736. + struct hostcmd_header cmd_hdr;
  9737. + u8 opt_level;
  9738. +} __packed;
  9739. +
  9740. +/* HOSTCMD_CMD_SET_WSC_IE */
  9741. +struct hostcmd_cmd_set_wsc_ie {
  9742. + struct hostcmd_header cmd_hdr;
  9743. + __le16 ie_type; /* 0 -- beacon. or 1 -- probe response. */
  9744. + __le16 len;
  9745. + u8 data[WSC_IE_MAX_LENGTH];
  9746. +} __packed;
  9747. +
  9748. +/* HOSTCMD_CMD_GET_RATETABLE */
  9749. +struct hostcmd_cmd_get_ratetable {
  9750. + struct hostcmd_header cmd_hdr;
  9751. + u8 addr[ETH_ALEN];
  9752. + u8 type; /* 0: SU, 1: MU */
  9753. + /* multiply 2 because 2 DWORD in rate info */
  9754. + __le32 sorted_rates_idx_map[2 * SYSADPT_MAX_RATE_ADAPT_RATES];
  9755. +} __packed;
  9756. +
  9757. +/* HOSTCMD_CMD_GET_SEQNO */
  9758. +struct hostcmd_cmd_get_seqno {
  9759. + struct hostcmd_header cmd_hdr;
  9760. + u8 mac_addr[ETH_ALEN];
  9761. + u8 tid;
  9762. + __le16 seq_no;
  9763. + u8 reserved;
  9764. +} __packed;
  9765. +
  9766. +/* HOSTCMD_CMD_DWDS_ENABLE */
  9767. +struct hostcmd_cmd_dwds_enable {
  9768. + struct hostcmd_header cmd_hdr;
  9769. + __le32 enable; /* 0 -- Disable. or 1 -- Enable. */
  9770. +} __packed;
  9771. +
  9772. +/* HOSTCMD_CMD_FW_FLUSH_TIMER */
  9773. +struct hostcmd_cmd_fw_flush_timer {
  9774. + struct hostcmd_header cmd_hdr;
  9775. + /* 0 -- Disable. > 0 -- holds time value in usecs. */
  9776. + __le32 value;
  9777. +} __packed;
  9778. +
  9779. +/* HOSTCMD_CMD_SET_CDD */
  9780. +struct hostcmd_cmd_set_cdd {
  9781. + struct hostcmd_header cmd_hdr;
  9782. + __le32 enable;
  9783. +} __packed;
  9784. +
  9785. +/* HOSTCMD_CMD_SET_BFTYPE */
  9786. +struct hostcmd_cmd_set_bftype {
  9787. + struct hostcmd_header cmd_hdr;
  9788. + __le32 action;
  9789. + __le32 mode;
  9790. +} __packed;
  9791. +
  9792. +/* HOSTCMD_CMD_GET_TEMP */
  9793. +struct hostcmd_cmd_get_temp {
  9794. + struct hostcmd_header cmd_hdr;
  9795. + __le32 celcius;
  9796. + __le32 raw_data;
  9797. +} __packed;
  9798. +
  9799. +/* HOSTCMD_CMD_LED_CTRL */
  9800. +struct hostcmd_cmd_led_ctrl {
  9801. + struct hostcmd_header cmd_hdr;
  9802. + __le16 action; /* 0: GET, 1: SET (only SET is supported) */
  9803. + u8 led_enable; /* 0: Disable, 1: Enable */
  9804. + u8 led_control; /* 0: HW 1: SW (only SW is supported) */
  9805. + u8 led_blink_rate; /* 1: Slow, 2: Medium, 3: Fast blink */
  9806. + u8 reserved;
  9807. +} __packed;
  9808. +
  9809. +/* HOSTCMD_CMD_GET_FW_REGION_CODE */
  9810. +struct hostcmd_cmd_get_fw_region_code {
  9811. + struct hostcmd_header cmd_hdr;
  9812. + __le32 status; /* 0 = Found, 1 = Error */
  9813. + __le32 fw_region_code;
  9814. +} __packed;
  9815. +
  9816. +/* HOSTCMD_CMD_GET_DEVICE_PWR_TBL */
  9817. +#define HAL_TRPC_ID_MAX 16
  9818. +
  9819. +struct channel_power_tbl {
  9820. + u8 channel;
  9821. + u8 tx_pwr[HAL_TRPC_ID_MAX];
  9822. + u8 dfs_capable;
  9823. + u8 ax_ant;
  9824. + u8 cdd;
  9825. +} __packed;
  9826. +
  9827. +struct hostcmd_cmd_get_device_pwr_tbl {
  9828. + struct hostcmd_header cmd_hdr;
  9829. + __le16 status; /* 0 = Found, 1 = Error */
  9830. + u8 region_code;
  9831. + u8 number_of_channels;
  9832. + __le32 current_channel_index;
  9833. + /* Only for 1 channel, so, 1 channel at a time */
  9834. + struct channel_power_tbl channel_pwr_tbl;
  9835. +} __packed;
  9836. +
  9837. +/* HOSTCMD_CMD_SET_RATE_DROP */
  9838. +struct hostcmd_cmd_set_rate_drop {
  9839. + struct hostcmd_header cmd_hdr;
  9840. + __le32 enable;
  9841. + __le32 rate_index;
  9842. + __le32 sta_index;
  9843. +} __packed;
  9844. +
  9845. +/* HOSTCMD_CMD_NEWDP_DMATHREAD_START */
  9846. +struct hostcmd_cmd_newdp_dmathread_start {
  9847. + struct hostcmd_header cmd_hdr;
  9848. +} __packed;
  9849. +
  9850. +/* HOSTCMD_CMD_GET_FW_REGION_CODE_SC4 */
  9851. +struct hostcmd_cmd_get_fw_region_code_sc4 {
  9852. + struct hostcmd_header cmd_hdr;
  9853. + __le32 status; /* 0 = Found, 1 = Error */
  9854. + __le32 fw_region_code;
  9855. +} __packed;
  9856. +
  9857. +/* HOSTCMD_CMD_GET_DEVICE_PWR_TBL_SC4 */
  9858. +#define HAL_TRPC_ID_MAX_SC4 32
  9859. +#define MAX_GROUP_PER_CHANNEL_5G 39
  9860. +#define MAX_GROUP_PER_CHANNEL_2G 21
  9861. +#define MAX(a, b) (((a) > (b)) ? (a) : (b))
  9862. +#define MAX_GROUP_PER_CHANNEL_RATE \
  9863. + MAX(MAX_GROUP_PER_CHANNEL_5G, MAX_GROUP_PER_CHANNEL_2G)
  9864. +
  9865. +struct channel_power_tbl_sc4 {
  9866. + u8 channel;
  9867. + u8 grp_pwr[MAX_GROUP_PER_CHANNEL_RATE];
  9868. + u8 tx_pwr[HAL_TRPC_ID_MAX_SC4];
  9869. + u8 dfs_capable;
  9870. + u8 ax_ant;
  9871. + u8 cdd;
  9872. + u8 rsvd;
  9873. +} __packed;
  9874. +
  9875. +struct hostcmd_cmd_get_device_pwr_tbl_sc4 {
  9876. + struct hostcmd_header cmd_hdr;
  9877. + __le16 status; /* 0 = Found, 1 = Error */
  9878. + u8 region_code;
  9879. + u8 number_of_channels;
  9880. + __le32 current_channel_index;
  9881. + /* Only for 1 channel, so, 1 channel at a time */
  9882. + struct channel_power_tbl_sc4 channel_pwr_tbl;
  9883. +} __packed;
  9884. +
  9885. +/* HOSTCMD_CMD_QUIET_MODE */
  9886. +struct hostcmd_cmd_quiet_mode {
  9887. + struct hostcmd_header cmd_hdr;
  9888. + __le16 action;
  9889. + __le32 enable;
  9890. + __le32 period;
  9891. + __le32 duration;
  9892. + __le32 next_offset;
  9893. +} __packed;
  9894. +
  9895. +/* HOSTCMD_CMD_CORE_DUMP_DIAG_MODE */
  9896. +struct hostcmd_cmd_core_dump_diag_mode {
  9897. + struct hostcmd_header cmd_hdr;
  9898. + __le16 status;
  9899. +} __packed;
  9900. +
  9901. +/* HOSTCMD_CMD_GET_FW_CORE_DUMP */
  9902. +#define MAX_CORE_REGIONS 20
  9903. +#define MAX_CORE_SYMBOLS 30
  9904. +#define MVL_COREDUMP_DIAG_MODE 0x00000001
  9905. +#define MVL_COREDUMP_INCL_EXT 0x00000002
  9906. +#define MAX_CORE_DUMP_BUFFER 2048
  9907. +
  9908. +struct core_region {
  9909. + __le32 address;
  9910. + __le32 length;
  9911. +} __packed;
  9912. +
  9913. +struct core_symbol {
  9914. + u8 name[16];
  9915. + __le32 address;
  9916. + __le32 length;
  9917. + __le16 entries;
  9918. +} __packed;
  9919. +
  9920. +struct coredump {
  9921. + u8 version_major;
  9922. + u8 version_minor;
  9923. + u8 version_patch;
  9924. + u8 hdr_version;
  9925. + u8 num_regions;
  9926. + u8 num_symbols;
  9927. + u8 fill[2];
  9928. + struct core_region region[MAX_CORE_REGIONS];
  9929. + struct core_symbol symbol[MAX_CORE_SYMBOLS];
  9930. + __le32 fill_end[40];
  9931. +} __packed;
  9932. +
  9933. +struct coredump_cmd {
  9934. + __le32 context;
  9935. + __le32 buffer;
  9936. + __le32 buffer_len;
  9937. + __le16 size_kb;
  9938. + __le16 flags;
  9939. +} __packed;
  9940. +
  9941. +struct debug_mem_cmd {
  9942. + __le32 set;
  9943. + __le32 type;
  9944. + __le32 addr;
  9945. + __le32 val;
  9946. +} __packed;
  9947. +
  9948. +struct hostcmd_cmd_get_fw_core_dump {
  9949. + struct hostcmd_header cmd_hdr;
  9950. + union {
  9951. + struct coredump_cmd coredump;
  9952. + struct debug_mem_cmd debug_mem;
  9953. + } cmd_data;
  9954. + /*Buffer where F/W Copies the Core Dump*/
  9955. + char buffer[MAX_CORE_DUMP_BUFFER];
  9956. +} __packed;
  9957. +
  9958. +struct hostcmd_cmd_get_fw_core_dump_ {
  9959. + struct hostcmd_header cmd_hdr;
  9960. + union {
  9961. + struct coredump_cmd coredump;
  9962. + struct debug_mem_cmd debug_mem;
  9963. + } cmd_data;
  9964. +} __packed;
  9965. +
  9966. +/* HOSTCMD_CMD_802_11_SLOT_TIME */
  9967. +struct hostcmd_cmd_802_11_slot_time {
  9968. + struct hostcmd_header cmd_hdr;
  9969. + __le16 action;
  9970. + /* 0:long slot; 1:short slot */
  9971. + __le16 short_slot;
  9972. +} __packed;
  9973. +
  9974. +/* HOSTCMD_CMD_EDMAC_CTRL */
  9975. +struct hostcmd_cmd_edmac_ctrl {
  9976. + struct hostcmd_header cmd_hdr;
  9977. + __le16 action;
  9978. + __le16 ed_ctrl_2g;
  9979. + __le16 ed_offset_2g;
  9980. + __le16 ed_ctrl_5g;
  9981. + __le16 ed_offset_5g;
  9982. + __le16 ed_bitmap_txq_lock;
  9983. +} __packed;
  9984. +
  9985. +/* HOSTCMD_CMD_TXPWRLMT_CFG */
  9986. +#define TXPWRLMT_CFG_VERSION_INFO_LEN 0x4
  9987. +#define TXPWRLMT_CFG_MAX_SUBBAND_INFO 0x5
  9988. +#define TXPWRLMT_CFG_SIG_LEN 0x4
  9989. +#define TXPWRLMT_CFG_SIGNATURE 0xA1240E01
  9990. +
  9991. +struct hostcmd_cmd_txpwrlmt_cfg {
  9992. + struct hostcmd_header cmd_hdr;
  9993. + /* Action */
  9994. + __le16 action;
  9995. + /*Sub band id*/
  9996. + u8 subband_id;
  9997. + /* Cfg Complete Info*/
  9998. + u8 cfgComplete;
  9999. + /* Data length */
  10000. + __le16 data_len;
  10001. + /*number of entries*/
  10002. + __le16 num_entries;
  10003. + /* Data */
  10004. + u8 data[1];
  10005. +} __packed;
  10006. +
  10007. +struct mwl_txpwrlmt_cfg_entry_hdr {
  10008. + /* subband id */
  10009. + __le16 id;
  10010. + /* length */
  10011. + __le16 len;
  10012. + /* number of entries */
  10013. + __le16 num_entries;
  10014. +} __packed;
  10015. +
  10016. +/* HOSTCMD_CMD_MCAST_CTS */
  10017. +struct hostcmd_cmd_mcast_cts {
  10018. + struct hostcmd_header cmd_hdr;
  10019. + u8 enable; /* 1:enable, 0:disable */
  10020. +} __packed;
  10021. +
  10022. +#endif /* _HOSTCMD_H_ */
  10023. diff --git a/drivers/net/wireless/marvell/mwlwifi/hif/pcie/dev.h b/drivers/net/wireless/marvell/mwlwifi/hif/pcie/dev.h
  10024. new file mode 100644
  10025. index 000000000000..2c26bff80683
  10026. --- /dev/null
  10027. +++ b/drivers/net/wireless/marvell/mwlwifi/hif/pcie/dev.h
  10028. @@ -0,0 +1,1032 @@
  10029. +/*
  10030. + * Copyright (C) 2006-2018, Marvell International Ltd.
  10031. + *
  10032. + * This software file (the "File") is distributed by Marvell International
  10033. + * Ltd. under the terms of the GNU General Public License Version 2, June 1991
  10034. + * (the "License"). You may use, redistribute and/or modify this File in
  10035. + * accordance with the terms and conditions of the License, a copy of which
  10036. + * is available by writing to the Free Software Foundation, Inc.
  10037. + *
  10038. + * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
  10039. + * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
  10040. + * ARE EXPRESSLY DISCLAIMED. The License provides additional details about
  10041. + * this warranty disclaimer.
  10042. + */
  10043. +
  10044. +/* Description: This file defines device related information. */
  10045. +
  10046. +#ifndef _DEV_H_
  10047. +#define _DEV_H_
  10048. +
  10049. +#include <linux/version.h>
  10050. +#include <linux/interrupt.h>
  10051. +#include <linux/pci.h>
  10052. +#include <linux/firmware.h>
  10053. +#include <linux/delay.h>
  10054. +#include <linux/bitops.h>
  10055. +#include <net/mac80211.h>
  10056. +
  10057. +#define PCIE_DRV_NAME KBUILD_MODNAME
  10058. +#define PCIE_DRV_VERSION "10.3.8.0-20181210"
  10059. +
  10060. +#define PCIE_MIN_BYTES_HEADROOM 64
  10061. +#define PCIE_MIN_TX_HEADROOM_KF2 96
  10062. +#define PCIE_NUM_OF_DESC_DATA SYSADPT_TOTAL_TX_QUEUES
  10063. +#define PCIE_AMPDU_QUEUES 4
  10064. +#define PCIE_MAX_NUM_TX_DESC 256
  10065. +#define PCIE_TX_QUEUE_LIMIT (3 * PCIE_MAX_NUM_TX_DESC)
  10066. +#define PCIE_TX_WAKE_Q_THRESHOLD (2 * PCIE_MAX_NUM_TX_DESC)
  10067. +#define PCIE_DELAY_FREE_Q_LIMIT PCIE_MAX_NUM_TX_DESC
  10068. +#define PCIE_MAX_NUM_RX_DESC 256
  10069. +#define PCIE_RECEIVE_LIMIT 64
  10070. +
  10071. +enum {
  10072. + IEEE_TYPE_MANAGEMENT = 0,
  10073. + IEEE_TYPE_CONTROL,
  10074. + IEEE_TYPE_DATA
  10075. +};
  10076. +
  10077. +#define MAC_REG_ADDR(offset) (offset)
  10078. +#define MAC_REG_ADDR_PCI(offset) ((pcie_priv->iobase1 + 0xA000) + offset)
  10079. +
  10080. +#define MCU_CCA_CNT MAC_REG_ADDR(0x06A0)
  10081. +#define MCU_TXPE_CNT MAC_REG_ADDR(0x06A4)
  10082. +#define MCU_LAST_READ MAC_REG_ADDR(0x06A8)
  10083. +
  10084. +/* Map to 0x80000000 (Bus control) on BAR0 */
  10085. +#define MACREG_REG_H2A_INTERRUPT_EVENTS 0x00000C18 /* (From host to ARM) */
  10086. +#define MACREG_REG_H2A_INTERRUPT_CAUSE 0x00000C1C /* (From host to ARM) */
  10087. +#define MACREG_REG_H2A_INTERRUPT_MASK 0x00000C20 /* (From host to ARM) */
  10088. +#define MACREG_REG_H2A_INTERRUPT_CLEAR_SEL 0x00000C24 /* (From host to ARM) */
  10089. +#define MACREG_REG_H2A_INTERRUPT_STATUS_MASK 0x00000C28 /* (From host to ARM) */
  10090. +
  10091. +#define MACREG_REG_A2H_INTERRUPT_EVENTS 0x00000C2C /* (From ARM to host) */
  10092. +#define MACREG_REG_A2H_INTERRUPT_CAUSE 0x00000C30 /* (From ARM to host) */
  10093. +#define MACREG_REG_A2H_INTERRUPT_MASK 0x00000C34 /* (From ARM to host) */
  10094. +#define MACREG_REG_A2H_INTERRUPT_CLEAR_SEL 0x00000C38 /* (From ARM to host) */
  10095. +#define MACREG_REG_A2H_INTERRUPT_STATUS_MASK 0x00000C3C /* (From ARM to host) */
  10096. +
  10097. +/* Map to 0x80000000 on BAR1 */
  10098. +#define MACREG_REG_GEN_PTR 0x00000C10
  10099. +#define MACREG_REG_INT_CODE 0x00000C14
  10100. +
  10101. +/* Bit definition for MACREG_REG_A2H_INTERRUPT_CAUSE (A2HRIC) */
  10102. +#define MACREG_A2HRIC_BIT_TX_DONE BIT(0)
  10103. +#define MACREG_A2HRIC_BIT_RX_RDY BIT(1)
  10104. +#define MACREG_A2HRIC_BIT_OPC_DONE BIT(2)
  10105. +#define MACREG_A2HRIC_BIT_MAC_EVENT BIT(3)
  10106. +#define MACREG_A2HRIC_BIT_RX_PROBLEM BIT(4)
  10107. +#define MACREG_A2HRIC_BIT_RADIO_OFF BIT(5)
  10108. +#define MACREG_A2HRIC_BIT_RADIO_ON BIT(6)
  10109. +#define MACREG_A2HRIC_BIT_RADAR_DETECT BIT(7)
  10110. +#define MACREG_A2HRIC_BIT_ICV_ERROR BIT(8)
  10111. +#define MACREG_A2HRIC_BIT_WEAKIV_ERROR BIT(9)
  10112. +#define MACREG_A2HRIC_BIT_QUE_EMPTY BIT(10)
  10113. +#define MACREG_A2HRIC_BIT_QUE_FULL BIT(11)
  10114. +#define MACREG_A2HRIC_BIT_CHAN_SWITCH BIT(12)
  10115. +#define MACREG_A2HRIC_BIT_TX_WATCHDOG BIT(13)
  10116. +#define MACREG_A2HRIC_BA_WATCHDOG BIT(14)
  10117. +/* 15 taken by ISR_TXACK */
  10118. +#define MACREG_A2HRIC_BIT_SSU_DONE BIT(16)
  10119. +#define MACREG_A2HRIC_CONSEC_TXFAIL BIT(17)
  10120. +
  10121. +#define ISR_SRC_BITS (MACREG_A2HRIC_BIT_RX_RDY | \
  10122. + MACREG_A2HRIC_BIT_TX_DONE | \
  10123. + MACREG_A2HRIC_BIT_OPC_DONE | \
  10124. + MACREG_A2HRIC_BIT_MAC_EVENT | \
  10125. + MACREG_A2HRIC_BIT_WEAKIV_ERROR | \
  10126. + MACREG_A2HRIC_BIT_ICV_ERROR | \
  10127. + MACREG_A2HRIC_BIT_SSU_DONE | \
  10128. + MACREG_A2HRIC_BIT_RADAR_DETECT | \
  10129. + MACREG_A2HRIC_BIT_CHAN_SWITCH | \
  10130. + MACREG_A2HRIC_BIT_TX_WATCHDOG | \
  10131. + MACREG_A2HRIC_BIT_QUE_EMPTY | \
  10132. + MACREG_A2HRIC_BA_WATCHDOG | \
  10133. + MACREG_A2HRIC_CONSEC_TXFAIL)
  10134. +
  10135. +#define MACREG_A2HRIC_BIT_MASK ISR_SRC_BITS
  10136. +
  10137. +/* Bit definition for MACREG_REG_H2A_INTERRUPT_CAUSE (H2ARIC) */
  10138. +#define MACREG_H2ARIC_BIT_PPA_READY BIT(0)
  10139. +#define MACREG_H2ARIC_BIT_DOOR_BELL BIT(1)
  10140. +#define MACREG_H2ARIC_BIT_PS BIT(2)
  10141. +#define MACREG_H2ARIC_BIT_PSPOLL BIT(3)
  10142. +#define ISR_RESET BIT(15)
  10143. +#define ISR_RESET_AP33 BIT(26)
  10144. +
  10145. +/* Data descriptor related constants */
  10146. +#define EAGLE_RXD_CTRL_DRIVER_OWN 0x00
  10147. +#define EAGLE_RXD_CTRL_DMA_OWN 0x80
  10148. +
  10149. +#define EAGLE_RXD_STATUS_OK 0x01
  10150. +
  10151. +#define EAGLE_TXD_STATUS_IDLE 0x00000000
  10152. +#define EAGLE_TXD_STATUS_OK 0x00000001
  10153. +#define EAGLE_TXD_STATUS_FW_OWNED 0x80000000
  10154. +
  10155. +struct pcie_tx_desc {
  10156. + u8 data_rate;
  10157. + u8 tx_priority;
  10158. + __le16 qos_ctrl;
  10159. + __le32 pkt_ptr;
  10160. + __le16 pkt_len;
  10161. + u8 dest_addr[ETH_ALEN];
  10162. + __le32 pphys_next;
  10163. + __le32 sap_pkt_info;
  10164. + __le32 rate_info;
  10165. + u8 type;
  10166. + u8 xmit_control; /* bit 0: use rateinfo, bit 1: disable ampdu */
  10167. + __le16 reserved;
  10168. + __le32 tcpack_sn;
  10169. + __le32 tcpack_src_dst;
  10170. + __le32 reserved1;
  10171. + __le32 reserved2;
  10172. + u8 reserved3[2];
  10173. + u8 packet_info;
  10174. + u8 packet_id;
  10175. + __le16 packet_len_and_retry;
  10176. + __le16 packet_rate_info;
  10177. + __le32 flags;
  10178. + __le32 status;
  10179. +} __packed;
  10180. +
  10181. +struct pcie_tx_hndl {
  10182. + struct sk_buff *psk_buff;
  10183. + struct pcie_tx_desc *pdesc;
  10184. + struct pcie_tx_hndl *pnext;
  10185. +};
  10186. +
  10187. +/* Receive rate information constants */
  10188. +#define RX_RATE_INFO_FORMAT_11A 0
  10189. +#define RX_RATE_INFO_FORMAT_11B 1
  10190. +#define RX_RATE_INFO_FORMAT_11N 2
  10191. +#define RX_RATE_INFO_FORMAT_11AC 4
  10192. +
  10193. +#define RX_RATE_INFO_HT20 0
  10194. +#define RX_RATE_INFO_HT40 1
  10195. +#define RX_RATE_INFO_HT80 2
  10196. +#define RX_RATE_INFO_HT160 3
  10197. +
  10198. +#define RX_RATE_INFO_LONG_INTERVAL 0
  10199. +#define RX_RATE_INFO_SHORT_INTERVAL 1
  10200. +
  10201. +#define MWL_RX_RATE_FORMAT_MASK 0x0007
  10202. +#define MWL_RX_RATE_NSS_MASK 0x0018
  10203. +#define MWL_RX_RATE_NSS_SHIFT 3
  10204. +#define MWL_RX_RATE_BW_MASK 0x0060
  10205. +#define MWL_RX_RATE_BW_SHIFT 5
  10206. +#define MWL_RX_RATE_GI_MASK 0x0080
  10207. +#define MWL_RX_RATE_GI_SHIFT 7
  10208. +#define MWL_RX_RATE_RT_MASK 0xFF00
  10209. +#define MWL_RX_RATE_RT_SHIFT 8
  10210. +
  10211. +struct pcie_rx_desc {
  10212. + __le16 pkt_len; /* total length of received data */
  10213. + __le16 rate; /* receive rate information */
  10214. + __le32 pphys_buff_data; /* physical address of payload data */
  10215. + __le32 pphys_next; /* physical address of next RX desc */
  10216. + __le16 qos_ctrl; /* received QosCtrl field variable */
  10217. + __le16 ht_sig2; /* like name states */
  10218. + __le32 hw_rssi_info;
  10219. + __le32 hw_noise_floor_info;
  10220. + u8 noise_floor;
  10221. + u8 reserved[3];
  10222. + u8 rssi; /* received signal strengt indication */
  10223. + u8 status; /* status field containing USED bit */
  10224. + u8 channel; /* channel this pkt was received on */
  10225. + u8 rx_control; /* the control element of the desc */
  10226. + __le32 reserved1[3];
  10227. +} __packed;
  10228. +
  10229. +struct pcie_rx_hndl {
  10230. + struct sk_buff *psk_buff; /* associated sk_buff for Linux */
  10231. + struct pcie_rx_desc *pdesc;
  10232. + struct pcie_rx_hndl *pnext;
  10233. +};
  10234. +
  10235. +struct pcie_desc_data {
  10236. + dma_addr_t pphys_tx_ring; /* ptr to first TX desc (phys.) */
  10237. + struct pcie_tx_desc *ptx_ring; /* ptr to first TX desc (virt.) */
  10238. + struct pcie_tx_hndl *tx_hndl;
  10239. + struct pcie_tx_hndl *pnext_tx_hndl;/* next TX handle that can be used */
  10240. + struct pcie_tx_hndl *pstale_tx_hndl;/* the staled TX handle */
  10241. + dma_addr_t pphys_rx_ring; /* ptr to first RX desc (phys.) */
  10242. + struct pcie_rx_desc *prx_ring; /* ptr to first RX desc (virt.) */
  10243. + struct pcie_rx_hndl *rx_hndl;
  10244. + struct pcie_rx_hndl *pnext_rx_hndl;/* next RX handle that can be used */
  10245. + u32 wcb_base; /* FW base offset for registers */
  10246. + u32 rx_desc_write; /* FW descriptor write position */
  10247. + u32 rx_desc_read; /* FW descriptor read position */
  10248. + u32 rx_buf_size; /* length of the RX buffers */
  10249. +};
  10250. +
  10251. +/* DMA header used by firmware and hardware. */
  10252. +struct pcie_dma_data {
  10253. + __le16 fwlen;
  10254. + struct ieee80211_hdr wh;
  10255. + char data[0];
  10256. +} __packed;
  10257. +
  10258. +/* New Data Path */
  10259. +#define MACREG_REG_SCRATCH3 0x00000C44
  10260. +#define MACREG_REG_TXSENDHEAD 0x00000CD0
  10261. +#define MACREG_REG_TXSEDNTAIL 0x00000CD4
  10262. +#define MACREG_REG_TXDONEHEAD 0x00000CD8
  10263. +#define MACREG_REG_TXDONETAIL 0x00000CDC
  10264. +#define MACREG_REG_RXDESCHEAD 0x00000CE0
  10265. +#define MACREG_REG_RXDESCTAIL 0x00000CE4
  10266. +#define MACREG_REG_RXDONEHEAD 0x00000CE8
  10267. +#define MACREG_REG_RXDONETAIL 0x00000CEC
  10268. +#define MACREG_REG_ACNTHEAD 0x00000CF0
  10269. +#define MACREG_REG_ACNTTAIL 0x00000CF4
  10270. +
  10271. +/* Buff removed from Tx Send Ring */
  10272. +#define MACREG_A2HRIC_TX_DESC_TAIL_RDY (1<<9)
  10273. +/* Buff added to Tx Done Ring */
  10274. +#define MACREG_A2HRIC_TX_DONE_HEAD_RDY (1<<10)
  10275. +/* Records added to Accounting Ring */
  10276. +#define MACREG_A2HRIC_ACNT_HEAD_RDY (1<<12)
  10277. +/* Buff removed from Rx Desc Ring */
  10278. +#define MACREG_A2HRIC_RX_DESC_TAIL_RDY (1<<17)
  10279. +/* Buff added to Rx Done Ring */
  10280. +#define MACREG_A2HRIC_RX_DONE_HEAD_RDY (1<<18)
  10281. +#define MACREG_A2HRIC_NEWDP_DFS (1<<19)
  10282. +#define MACREG_A2HRIC_NEWDP_CHANNEL_SWITCH (1<<20)
  10283. +
  10284. +#define ISR_SRC_BITS_NDP ((MACREG_A2HRIC_ACNT_HEAD_RDY) | \
  10285. + (MACREG_A2HRIC_RX_DONE_HEAD_RDY) | \
  10286. + (MACREG_A2HRIC_NEWDP_DFS) | \
  10287. + (MACREG_A2HRIC_NEWDP_CHANNEL_SWITCH))
  10288. +
  10289. +#define MACREG_A2HRIC_BIT_MASK_NDP ISR_SRC_BITS_NDP
  10290. +
  10291. +#define MIN_BYTES_RX_HEADROOM (64 + 2)
  10292. +#define AMPDU_QUEUES_NDP (SYSADPT_MAX_STA_SC4 * \
  10293. + SYSADPT_MAX_TID)
  10294. +#define MAX_NUM_TX_DESC 1024
  10295. +#define MAX_NUM_RX_DESC (1024 * 16)
  10296. +#define MAX_TX_RING_SEND_SIZE (4 * MAX_NUM_TX_DESC)
  10297. +#define MAX_TX_RING_DONE_SIZE MAX_NUM_TX_DESC
  10298. +#define MAX_RX_RING_SEND_SIZE MAX_NUM_RX_DESC
  10299. +#define MAX_RX_RING_DONE_SIZE MAX_NUM_RX_DESC
  10300. +#define DEFAULT_ACNT_RING_SIZE 0x10000
  10301. +#define MAX_AGGR_SIZE 1900
  10302. +#define TX_QUEUE_LIMIT MAX_NUM_TX_DESC
  10303. +#define TX_WAKE_Q_THRESHOLD (MAX_NUM_TX_DESC - 256)
  10304. +
  10305. +/* RateCode usage notes:
  10306. + * * General
  10307. + * * No error checking is provided on RateCodes, so usage of invalid values
  10308. + * or rates not supported by HW can result in undefined operation.
  10309. + * * Some values are not allowed by Std, but are included to sanitize the
  10310. + * table;
  10311. + * * MaxPwr should only be used for rates that can be sent using Max Power,
  10312. + * such as for TxEVM limits or regulatory. It is only valid for Host
  10313. + * Generated frames, and not for DRA, etc.
  10314. + * * VHT
  10315. + * * Need to reconsile MU.
  10316. + * * HT
  10317. + * * MCS and SS are made to mimic 11ac, so MCS=mcs[2:0] and SS=mcs[4:3];
  10318. + * * MCS32 is selected by providing MCS=10;
  10319. + * * Legacy
  10320. + * * MCS0..7 = 6/9/12/18/24/36/48/54;
  10321. + * * MCS8..15 = 1S/1L/2S/2L/5.5S/5.5L/11S/11L;
  10322. + * * BW is used to request legacy duplicate modes;
  10323. + */
  10324. +#define RATECODE_DEFAULT 0xFFFF /* Don't override the Rate */
  10325. +#define RATECODE_TYPE_MASK 0xC000 /* Mask to extract Type */
  10326. +#define RATECODE_TYPE_SHIFT 14 /* Shift to extract Type */
  10327. +#define RATECODE_TYPE_VHT 0x8000 /* Use VHT rates */
  10328. +#define RATECODE_TYPE_HT 0x4000 /* Use HT rates */
  10329. +#define RATECODE_TYPE_LEGACY 0x0000 /* Use Legacy (a/b/g) rates */
  10330. +#define RATECODE_MAXPWR 0x2000 /* Send at Max Power / Off Channel */
  10331. +#define RATECODE_RSVD 0x1000 /* Unused */
  10332. +#define RATECODE_STBC 0x0800 /* Use Space Time Block Codes */
  10333. +#define RATECODE_BFMR 0x0400 /* Use Beamforming */
  10334. +#define RATECODE_SS_MASK 0x0300 /* Mask to extract nSS-1 */
  10335. +#define RATECODE_SS_SHIFT 8 /* Shift to extract nSS-1 */
  10336. +#define RATECODE_MCS_MASK 0x00F0 /* Mask to extract MCS rate */
  10337. +#define RATECODE_MCS_SHIFT 4 /* Shift to extract MCS rate */
  10338. +#define RATECODE_BW_MASK 0x000C /* Mask to extract Channel BW */
  10339. +#define RATECODE_BW_SHIFT 2 /* Shift to extract Channel BW */
  10340. +#define RATECODE_BW_160MHZ 0x000C /* Send 160M wide packet (or 80+80) */
  10341. +#define RATECODE_BW_80MHZ 0x0008 /* Send 80M wide packet */
  10342. +#define RATECODE_BW_40MHZ 0x0004 /* Send 40M wide packet */
  10343. +#define RATECODE_BW_20MHZ 0x0000 /* Send 20M wide packet */
  10344. +#define RATECODE_LDPC 0x0002 /* Use Low Density Parity Codes */
  10345. +#define RATECODE_SGI 0x0001 /* Use Short Guard Interval */
  10346. +
  10347. +#define TXRING_CTRL_LEN_SHIFT 0 /* PCIe Payload size (Starts w/ SNAP) */
  10348. +#define TXRING_CTRL_LEN_MASK 0x3FFF /* PCIe Payload size (Starts w/ SNAP) */
  10349. +#define TXRING_CTRL_QID_SHIFT 14 /* Queue ID (STA*UP, Mcast, MC2UC, etc)*/
  10350. +#define TXRING_CTRL_QID_MASK 0xFFF /* Queue ID (STA*UP, Mcast, MC2UC, etc)*/
  10351. +#define TXRING_CTRL_TAG_SHIFT 26 /* Tags for special Processing */
  10352. +#define TXRING_CTRL_TAG_MASK 0x3F /* Tags for special Processing */
  10353. +#define TXRING_CTRL_TAG_MGMT 0x01 /* Has Host generated dot11 Header */
  10354. +#define TXRING_CTRL_TAG_EAP 0x02 /* Tag for EAPOL frames */
  10355. +#define TXRING_CTRL_TAG_TCP_ACK 0x4
  10356. +#define TXRING_CTRL_TAG_RSVD 0x3C /* Unused */
  10357. +
  10358. +struct tx_info { /* Tx INFO used by MAC HW */
  10359. + __le32 reserved0[10];
  10360. + __le32 rate_info;
  10361. + __le32 reserved1[14];
  10362. +} __packed;
  10363. +
  10364. +struct pcie_tx_desc_ndp {
  10365. + union { /* Union for Tx DA/SA or Mgmt Overrides */
  10366. + struct { /* Fields for Data frames */
  10367. + u8 da[ETH_ALEN]; /* L2 Destination Address */
  10368. + u8 sa[ETH_ALEN]; /* L2 Source Address */
  10369. + };
  10370. + struct { /* Fields when marked as Mgmt */
  10371. + __le16 rate_code; /* Rate Code: Table + Index */
  10372. + u8 max_retry;
  10373. + u8 pad[5]; /* Unused */
  10374. + __le32 call_back; /* Used for Packet returned to FW */
  10375. + };
  10376. + } u;
  10377. + __le32 ctrl; /* Bit fields (TXRING_CTRL_*) */
  10378. + __le32 data; /* PCIe Payload Pointer (Starts w/ SNAP) */
  10379. + __le32 user; /* Value returned to Host when done */
  10380. + __le32 tcp_dst_src;
  10381. + __le32 tcp_sn;
  10382. +} __packed;
  10383. +
  10384. +struct tx_ring_done {
  10385. + __le32 user;
  10386. +} __packed;
  10387. +
  10388. +#define RXRING_CTRL_CASE_SHIFT 0 /* What is in the buffer(RXRING_CASE_*) */
  10389. +#define RXRING_CTRL_CASE_MASK 0x1F /* What is in the buffer(RXRING_CASE_*) */
  10390. +#define RXRING_CTRL_STA_SHIFT 5 /* STA information (or Mcast group) */
  10391. +#define RXRING_CTRL_STA_MASK 0x1FF /* STA information (or Mcast group) */
  10392. +#define RXRING_CTRL_STA_UNKNOWN 0x1FF /* STA Idx for packets from Unknown STA */
  10393. +#define RXRING_CTRL_STA_FROMDS 0x1FE /* STA Idx for packets from DS */
  10394. +#define RXRING_CTRL_TID_SHIFT 14 /* TID/UP for QoS Data frames */
  10395. +#define RXRING_CTRL_TID_MASK 0xF /* TID/UP for QoS Data frames */
  10396. +#define RXRING_CTRL_KEY_SHIFT 18 /* Key Type used (KEY_TYPE_*) */
  10397. +#define RXRING_CTRL_KEY_MASK 0xF /* Key Type used (KEY_TYPE_*) */
  10398. +#define RXRING_CTRL_TRUNC (1UL<<31) /* Packet Truncated */
  10399. +
  10400. +/* Rx Buffer Formats
  10401. + * Each Case listed above will indicate the format used, and each format will
  10402. + * carry their length in the packet buffer. Should the packet be too big for
  10403. + * the buffer, it will be truncated, but the full length will still be
  10404. + * indicated. Currently only a single, fixed size Rx Pool is envisioned.
  10405. + *
  10406. + * Fmt0 is used for Slow path, when some processing of dot11 headers may still
  10407. + * be required, or for promiscuous mode captures. It is in the HW RxINFO
  10408. + * (rx_info_t) format including dot11_t followed by Payload. The Length field in
  10409. + * the dot11_t is updated to only include Payload bytes, and is in Little Endian
  10410. + * format. If the frame is too big, it is truncated to the buffer size, and
  10411. + * promiscuous packets may also be configured for truncation to reduce load. The
  10412. + * mark field is replaced with software status, and the RSSI will be updated to
  10413. + * apply Rx calibration.
  10414. + *
  10415. + * Fmt1 is used for fast path Data packets in the run state, where all rx
  10416. + * processing of dot11 headers is performed from radio FW. It has an AMSDU
  10417. + * centric format of DA/SA/Len followed by SNAP, with the Length in Big Endian
  10418. + * Format. In most cases conversion to Ethernet format is accomplished by
  10419. + * copying 12 bytes to drop 8 bytes in the middle.
  10420. + *
  10421. + * Fmt2 is used for fast path AMSDU packets that are malformed. They just
  10422. + * contain the dot11 header (dot11_t) containing the residual Len (Little
  10423. + * Endian) after any valid MSDU have been extracted. The header is followed by
  10424. + * the first invalid MSDU which will be truncated to 64 bytes.
  10425. + */
  10426. +enum { /* What is in Rx Buffer and why it was delivered */
  10427. + /* Data for Assoc Clients in Run State on Channel [Fmt1] */
  10428. + RXRING_CASE_FAST_DATA,
  10429. + RXRING_CASE_FAST_BAD_AMSDU, /* Fast Data with bad AMSDU Header [Fmt2] */
  10430. + /* Data for Assoc Clients using unconfigured queue [Fmt0] */
  10431. + RXRING_CASE_SLOW_NOQUEUE,
  10432. + /* Data for Assoc Clients not matching Run State [Fmt0] */
  10433. + RXRING_CASE_SLOW_NORUN,
  10434. + /* Data for filtered Multicast groups [Fmt0] */
  10435. + RXRING_CASE_SLOW_MCAST,
  10436. + RXRING_CASE_SLOW_BAD_STA, /* Data for Unassoc Clients [Fmt0] */
  10437. + RXRING_CASE_SLOW_BAD_MIC, /* Decrypt failure [Fmt0] */
  10438. + RXRING_CASE_SLOW_BAD_PN, /* Decrypt PN replay [Fmt0] */
  10439. + RXRING_CASE_SLOW_MGMT, /* Mgmt traffic to this AP or Bcast [Fmt0]*/
  10440. + RXRING_CASE_SLOW_PROMISC, /* Packets captured promiscuously [Fmt0] */
  10441. + RXRING_CASE_SLOW_DEL_DONE, /* Client has been deleted [N/A] */
  10442. + RXRING_CASE_DROP, /* Buffer returned to Host [N/A] */
  10443. +};
  10444. +
  10445. +enum { /* Type of Key */
  10446. + KEY_TYPE_NONE, /* Bypass (never stored in real keys) */
  10447. + KEY_TYPE_WEP40, /* WEP with 40 bit key + 24 bit IV = 64 */
  10448. + KEY_TYPE_WEP104, /* WEP with 104 bit key + 24 bit IV = 128 */
  10449. + KEY_TYPE_TKIP, /* TKIP */
  10450. + KEY_TYPE_CCMP128, /* CCMP with 128 bit Key */
  10451. + KEY_TYPE_CCMP256, /* CCMP with 256 bit Key + 16 byte MIC */
  10452. + KEY_TYPE_WAPI, /* WAPI */
  10453. + KEY_TYPE_UNKNOWN, /* Not known what key was used (Rx Only) */
  10454. + KEY_TYPE_GCMP128, /* GCMP with 128 bit Key */
  10455. + KEY_TYPE_GCMP256, /* GCMP with 256 bit Key + 16 byte MIC */
  10456. +};
  10457. +
  10458. +#define RXINFO_RSSI_X_SHIFT 24
  10459. +#define RXINFO_RSSI_X_MASK 0xFF
  10460. +#define RXINFO_HT_SIG1_SHIFT 0
  10461. +#define RXINFO_HT_SIG1_MASK 0xFFFFFF
  10462. +#define RXINFO_HT_SIG2_SHIFT 0
  10463. +#define RXINFO_HT_SIG2_MASK 0x3FFFF
  10464. +#define RXINFO_RATE_SHIFT 24
  10465. +#define RXINFO_RATE_MASK 0xFF
  10466. +#define RXINFO_NF_A_SHIFT 12
  10467. +#define RXINFO_NF_A_MASK 0xFFF
  10468. +#define RXINFO_NF_B_SHIFT 0
  10469. +#define RXINFO_NF_B_MASK 0xFFF
  10470. +#define RXINFO_NF_C_SHIFT 12
  10471. +#define RXINFO_NF_C_MASK 0xFFF
  10472. +#define RXINFO_NF_D_SHIFT 0
  10473. +#define RXINFO_NF_D_MASK 0xFFF
  10474. +#define RXINFO_PARAM_SHIFT 0
  10475. +#define RXINFO_PARAM_MASK 0xFFFFFF
  10476. +
  10477. +struct rx_info { /* HW Rx buffer */
  10478. + __le32 reserved0[2];
  10479. + __le32 rssi_x;
  10480. + __le32 reserved1[2];
  10481. + __le32 ht_sig1;
  10482. + __le32 ht_sig2_rate;
  10483. + __le32 reserved2[6];
  10484. + __le32 nf_a_b;
  10485. + __le32 nf_c_d;
  10486. + __le32 reserved3[6];
  10487. + __le32 param;
  10488. + __le32 reserved4[2];
  10489. + __le32 hdr[0]; /* Len from HW includes rx_info w/ hdr */
  10490. +} __packed;
  10491. +
  10492. +struct pcie_rx_desc_ndp { /* ToNIC Rx Empty Buffer Ring Entry */
  10493. + __le32 data; /* PCIe Payload Pointer */
  10494. + __le32 user; /* Value returned to Host when done */
  10495. +} __packed;
  10496. +
  10497. +struct rx_ring_done { /* FromNIC Rx Done Ring Entry */
  10498. + __le32 user; /* Value returned to Host when done */
  10499. + __le32 tsf; /* Rx Radio Timestamp from MAC */
  10500. + __le32 ctrl; /* Bit fields (RXRING_CTRL_*) */
  10501. +} __packed;
  10502. +
  10503. +struct pcie_desc_data_ndp {
  10504. + dma_addr_t pphys_tx_ring; /* ptr to first TX desc (phys.) */
  10505. + struct pcie_tx_desc_ndp *ptx_ring;/* ptr to first TX desc (virt.) */
  10506. + dma_addr_t pphys_rx_ring; /* ptr to first RX desc (phys.) */
  10507. + struct pcie_rx_desc_ndp *prx_ring;/* ptr to first RX desc (virt.) */
  10508. + u32 wcb_base; /* FW base offset for registers */
  10509. + u32 rx_buf_size; /* length of the RX buffers */
  10510. + u32 tx_sent_tail; /* index to the TX desc FW used */
  10511. + u32 tx_sent_head; /* index to next TX desc to be used*/
  10512. + u32 tx_done_tail; /* index to Tx Done queue tail */
  10513. + /* keept the skb owned by fw */
  10514. + dma_addr_t pphys_tx_buflist[MAX_TX_RING_SEND_SIZE];
  10515. + struct sk_buff *tx_vbuflist[MAX_TX_RING_SEND_SIZE];
  10516. + u32 tx_vbuflist_idx; /* idx to empty slot in tx_vbuflist*/
  10517. + struct sk_buff *rx_vbuflist[MAX_NUM_RX_DESC];
  10518. + struct tx_ring_done *ptx_ring_done;
  10519. + dma_addr_t pphys_tx_ring_done; /* ptr to first TX done desc (phys.) */
  10520. + struct rx_ring_done *prx_ring_done;
  10521. + dma_addr_t pphys_rx_ring_done; /* ptr to first RX done desc (phys.) */
  10522. + dma_addr_t pphys_acnt_ring; /* ptr to first account record (phys.)*/
  10523. + u8 *pacnt_ring; /* ptr to first accounting record */
  10524. + u32 tx_desc_busy_cnt;
  10525. + u8 *pacnt_buf;
  10526. + u32 acnt_ring_size;
  10527. +};
  10528. +
  10529. +struct ndp_rx_counter {
  10530. + u32 fast_data_cnt;
  10531. + u32 fast_bad_amsdu_cnt;
  10532. + u32 slow_noqueue_cnt;
  10533. + u32 slow_norun_cnt;
  10534. + u32 slow_mcast_cnt;
  10535. + u32 slow_bad_sta_cnt;
  10536. + u32 slow_bad_mic_cnt;
  10537. + u32 slow_bad_pn_cnt;
  10538. + u32 slow_mgmt_cnt;
  10539. + u32 slow_promisc_cnt;
  10540. + u32 drop_cnt;
  10541. + u32 offch_promisc_cnt;
  10542. + u32 mu_pkt_cnt;
  10543. +};
  10544. +
  10545. +/* KF2 - 88W8997 */
  10546. +#define PCIE_MAX_TXRX_BD 0x20
  10547. +/* PCIE read data pointer for queue 0 and 1 */
  10548. +#define PCIE_RD_DATA_PTR_Q0_Q1 0xC1A4 /* 0x8000C1A4 */
  10549. +/* PCIE read data pointer for queue 2 and 3 */
  10550. +#define PCIE_RD_DATA_PTR_Q2_Q3 0xC1A8 /* 0x8000C1A8 */
  10551. +/* PCIE write data pointer for queue 0 and 1 */
  10552. +#define PCIE_WR_DATA_PTR_Q0_Q1 0xC174 /* 0x8000C174 */
  10553. +/* PCIE write data pointer for queue 2 and 3 */
  10554. +#define PCIE_WR_DATA_PTR_Q2_Q3 0xC178 /* 0x8000C178 */
  10555. +
  10556. +/* TX buffer description read pointer */
  10557. +#define REG_TXBD_RDPTR PCIE_RD_DATA_PTR_Q0_Q1
  10558. +/* TX buffer description write pointer */
  10559. +#define REG_TXBD_WRPTR PCIE_WR_DATA_PTR_Q0_Q1
  10560. +
  10561. +#define PCIE_TX_START_PTR 16
  10562. +
  10563. +#define PCIE_TXBD_MASK 0x0FFF0000
  10564. +#define PCIE_TXBD_WRAP_MASK 0x1FFF0000
  10565. +
  10566. +#define PCIE_BD_FLAG_RX_ROLLOVER_IND BIT(12)
  10567. +#define PCIE_BD_FLAG_TX_START_PTR BIT(16)
  10568. +#define PCIE_BD_FLAG_TX_ROLLOVER_IND BIT(28)
  10569. +#define PCIE_BD_FLAG_TX2_START_PTR BIT(0)
  10570. +#define PCIE_BD_FLAG_TX2_ROLLOVER_IND BIT(12)
  10571. +
  10572. +#define PCIE_BD_FLAG_FIRST_DESC BIT(0)
  10573. +#define PCIE_BD_FLAG_LAST_DESC BIT(1)
  10574. +
  10575. +#define PCIE_TX_WCB_FLAGS_DONT_ENCRYPT 0x00000001
  10576. +#define PCIE_TX_WCB_FLAGS_NO_CCK_RATE 0x00000002
  10577. +
  10578. +#define PCIE_TXBD_NOT_FULL(wrptr, rdptr) \
  10579. + (((wrptr & PCIE_TXBD_MASK) != (rdptr & PCIE_TXBD_MASK)) \
  10580. + || ((wrptr & PCIE_BD_FLAG_TX_ROLLOVER_IND) == \
  10581. + (rdptr & PCIE_BD_FLAG_TX_ROLLOVER_IND)))
  10582. +
  10583. +struct pcie_data_buf {
  10584. + /* Buffer descriptor flags */
  10585. + __le16 flags;
  10586. + /* Offset of fragment/pkt to start of ip header */
  10587. + __le16 offset;
  10588. + /* Fragment length of the buffer */
  10589. + __le16 frag_len;
  10590. + /* Length of the buffer */
  10591. + __le16 len;
  10592. + /* Physical address of the buffer */
  10593. + __le64 paddr;
  10594. + /* Reserved */
  10595. + __le32 reserved;
  10596. +} __packed;
  10597. +
  10598. +struct pcie_pfu_dma_data {
  10599. + struct pcie_tx_desc tx_desc;
  10600. + struct pcie_dma_data dma_data;
  10601. +} __packed;
  10602. +
  10603. +struct pcie_priv {
  10604. + struct mwl_priv *mwl_priv;
  10605. + struct pci_dev *pdev;
  10606. + void __iomem *iobase0; /* MEM Base Address Register 0 */
  10607. + void __iomem *iobase1; /* MEM Base Address Register 1 */
  10608. + u32 next_bar_num;
  10609. +
  10610. + struct sk_buff_head txq[PCIE_NUM_OF_DESC_DATA];
  10611. +
  10612. + spinlock_t int_mask_lock ____cacheline_aligned_in_smp;
  10613. + struct tasklet_struct tx_task;
  10614. + struct tasklet_struct tx_done_task;
  10615. + struct tasklet_struct rx_task;
  10616. + struct tasklet_struct qe_task;
  10617. + unsigned int tx_head_room;
  10618. + int txq_limit;
  10619. + int txq_wake_threshold;
  10620. + bool is_tx_schedule;
  10621. + bool is_tx_done_schedule;
  10622. + int recv_limit;
  10623. + bool is_rx_schedule;
  10624. + bool is_qe_schedule;
  10625. + u32 qe_trig_num;
  10626. + unsigned long qe_trig_time;
  10627. +
  10628. + /* various descriptor data */
  10629. + /* for tx descriptor data */
  10630. + spinlock_t tx_desc_lock ____cacheline_aligned_in_smp;
  10631. + struct pcie_desc_data desc_data[PCIE_NUM_OF_DESC_DATA];
  10632. + int delay_q_idx;
  10633. + struct sk_buff *delay_q[PCIE_DELAY_FREE_Q_LIMIT];
  10634. + /* number of descriptors owned by fw at any one time */
  10635. + int fw_desc_cnt[PCIE_NUM_OF_DESC_DATA];
  10636. +
  10637. + /* new data path */
  10638. + struct pcie_desc_data_ndp desc_data_ndp;
  10639. + int tx_done_cnt;
  10640. + struct ieee80211_sta *sta_link[SYSADPT_MAX_STA_SC4 + 1];
  10641. + struct sk_buff_head rx_skb_trace;
  10642. + struct ndp_rx_counter rx_cnts;
  10643. + u32 rx_skb_unlink_err;
  10644. + u32 signature_err;
  10645. + u32 recheck_rxringdone;
  10646. + u32 acnt_busy;
  10647. + u32 acnt_wrap;
  10648. + u32 acnt_drop;
  10649. +
  10650. + /* KF2 - 88W8997 */
  10651. + struct firmware *cal_data;
  10652. + /* Write pointer for TXBD ring */
  10653. + u32 txbd_wrptr;
  10654. + /* Shadow copy of TXBD read pointer */
  10655. + u32 txbd_rdptr;
  10656. + /* TXBD ring size */
  10657. + u32 txbd_ring_size;
  10658. + /* Virtual base address of txbd_ring */
  10659. + u8 *txbd_ring_vbase;
  10660. + /* Physical base address of txbd_ring */
  10661. + dma_addr_t txbd_ring_pbase;
  10662. + /* Ring of buffer descriptors for TX */
  10663. + struct pcie_data_buf *txbd_ring[PCIE_MAX_TXRX_BD];
  10664. + struct sk_buff *tx_buf_list[PCIE_MAX_TXRX_BD];
  10665. +};
  10666. +
  10667. +enum { /* Definition of accounting record codes */
  10668. + ACNT_CODE_BUSY = 0, /* Marked busy until filled in */
  10669. + ACNT_CODE_WRAP, /* Used to pad when wrapping */
  10670. + ACNT_CODE_DROP, /* Count of dropped records */
  10671. + ACNT_CODE_TX_ENQUEUE, /* TXINFO when added to TCQ (acnt_tx_s) */
  10672. + ACNT_CODE_RX_PPDU, /* RXINFO for each PPDu (acnt_rx_s) */
  10673. + ACNT_CODE_TX_FLUSH, /* Flush Tx Queue */
  10674. + ACNT_CODE_RX_RESET, /* Channel Change / Rx Reset */
  10675. + ACNT_CODE_TX_RESET, /* TCQ reset */
  10676. + ACNT_CODE_QUOTE_LEVEL,/* Quota Level changes */
  10677. + ACNT_CODE_TX_DONE, /* Tx status when done */
  10678. + ACNT_CODE_RA_STATS, /* rateinfo PER (acnt_ra_s) */
  10679. + ACNT_CODE_BA_STATS, /* BA stats (acnt_ba_s) */
  10680. + ACNT_CODE_BF_MIMO_CTRL,/* BF Mimo Ctrl Field Log (acnt_bf_mimo_ctrl_s)*/
  10681. +};
  10682. +
  10683. +struct acnt_s { /* Baseline Accounting Record format */
  10684. + __le16 code; /* Unique code for each type */
  10685. + u8 len; /* Length in DWORDS, including header */
  10686. + u8 pad; /* Alignment for generic, but specific can reuse*/
  10687. + __le32 tsf; /* Timestamp for Entry (when len>1) */
  10688. +} __packed;
  10689. +
  10690. +struct acnt_tx_s { /* Accounting Record For Tx (at Enqueue time) */
  10691. + __le16 code; /* Unique code for each type */
  10692. + u8 len; /* Length in DWORDS, including header */
  10693. + u8 tcq; /* Which TCQ was used */
  10694. + __le32 tsf; /* Timestamp for Entry (when len>1) */
  10695. + __le64 bitmap; /* Map of SeqNr when AMPDU */
  10696. + __le16 air_time; /* Air Time used by PPDU */
  10697. + __le16 npkts; /* Number of Descriptors sent (AMPDU&AMSDU) */
  10698. + __le16 qid; /* Transmit Queue ID */
  10699. + __le16 latency; /* Latency of oldest frame in AMPDU (128us) */
  10700. + __le16 rate1; /* Rate Code for sending data */
  10701. + __le16 rate2; /* Rate Code for sending RTS/CTS protection */
  10702. + u8 rate_tbl_index; /* Rate table index for this TxInfo rate */
  10703. + u8 type; /* SU:0 or MU:1 */
  10704. + u8 pad[1]; /* Unused */
  10705. + u8 retries; /* Number of retries of oldest frame in AMPDU */
  10706. + __le32 tx_cnt; /* No. of pkt sent */
  10707. + struct tx_info tx_info;/* Transmit parameters used for 1st MPDU/AMPDU */
  10708. + struct pcie_dma_data hdr;/* Dot11 header used for 1st MPDU in AMPDU */
  10709. + u8 payload[0]; /* Variable Payload by use case */
  10710. +} __packed;
  10711. +
  10712. +struct acnt_rx_s { /* Accounting Record for Rx PPDU */
  10713. + __le16 code; /* Unique code for each type */
  10714. + u8 len; /* Length in DWORDS, including header */
  10715. + u8 flags; /* Flags (ACNTRX_*) */
  10716. + __le32 tsf; /* Timestamp for Entry (when len>1) */
  10717. + __le64 bitmap; /* Map of SeqNr when AMPDU */
  10718. + __le16 air_time; /* Air Time used by PPDU (no CSMA overhead) */
  10719. + __le16 rate; /* Rate Code for receiving data */
  10720. + struct rx_info rx_info;/* Receive parameters from 1st valid MPDU/AMPDU*/
  10721. +} __packed;
  10722. +
  10723. +struct acnt_ra_s { /* Accounting Record w/ rateinfo PER */
  10724. + __le16 code; /* Unique code for each type */
  10725. + u8 len; /* Length in DWORDS, including header */
  10726. + u8 per; /* PER for this rateinfo */
  10727. + __le32 tsf; /* Timestamp for Entry (when len>1) */
  10728. + __le16 stn_id; /* sta index this rateinfo is tied to */
  10729. + u8 type; /* SU:0 or MU:1 */
  10730. + u8 rate_tbl_index; /* ratetbl index */
  10731. + __le32 rate_info; /* rateinfo for this ratetbl index */
  10732. + __le32 tx_attempt_cnt;/* Total tx pkt during rate adapt interval */
  10733. +} __packed;
  10734. +
  10735. +struct acnt_ba_s { /* Accounting Record w/ rateinfo PER */
  10736. + __le16 code; /* Unique code for each type */
  10737. + u8 len; /* Length in DWORDS, including header */
  10738. + u8 ba_hole; /* Total missing pkt in a BA */
  10739. + __le32 tsf; /* Timestamp for Entry (when len>1) */
  10740. + __le16 stnid; /* sta index for this BA */
  10741. + u8 no_ba; /* No BA received */
  10742. + u8 ba_expected; /* Total expected pkt to be BA'd */
  10743. + u8 type; /* SU:0 or MU:1 */
  10744. + u8 pad[3]; /* Unused */
  10745. +} __packed;
  10746. +
  10747. +struct acnt_bf_mimo_ctrl_s {/* Accounting Record w/ BF MIMO Control Field Data*/
  10748. + __le16 code; /* Unique code for each type */
  10749. + u8 len; /* Length in DWORDS, including header */
  10750. + u8 type; /* SU:0, MU:1 */
  10751. + __le32 tsf; /* Timestamp for Entry (when len>1) */
  10752. + u8 rec_mac[6]; /* Received Packet Source MAC Address */
  10753. + __le16 pad; /* Padding */
  10754. + __le32 mimo_ctrl; /* BF MIMO Control Field Data */
  10755. + __le64 comp_bf_rep; /* First 8 bytes of Compressed BF Report */
  10756. +} __packed;
  10757. +
  10758. +static inline void pcie_tx_add_dma_header(struct mwl_priv *priv,
  10759. + struct sk_buff *skb,
  10760. + int head_pad,
  10761. + int tail_pad)
  10762. +{
  10763. + struct ieee80211_hdr *wh;
  10764. + int dma_hdrlen;
  10765. + int hdrlen;
  10766. + int reqd_hdrlen;
  10767. + int needed_room;
  10768. + struct pcie_dma_data *dma_data;
  10769. +
  10770. + dma_hdrlen = (priv->chip_type == MWL8997) ?
  10771. + sizeof(struct pcie_pfu_dma_data) :
  10772. + sizeof(struct pcie_dma_data);
  10773. +
  10774. + /* Add a firmware DMA header; the firmware requires that we
  10775. + * present a 2-byte payload length followed by a 4-address
  10776. + * header (without QoS field), followed (optionally) by any
  10777. + * WEP/ExtIV header (but only filled in for CCMP).
  10778. + */
  10779. + wh = (struct ieee80211_hdr *)skb->data;
  10780. +
  10781. + hdrlen = ieee80211_hdrlen(wh->frame_control);
  10782. +
  10783. + reqd_hdrlen = dma_hdrlen + head_pad;
  10784. +
  10785. + if (hdrlen != reqd_hdrlen) {
  10786. + needed_room = reqd_hdrlen - hdrlen;
  10787. + if (skb_headroom(skb) < needed_room) {
  10788. + wiphy_debug(priv->hw->wiphy, "headroom is short: %d %d",
  10789. + skb_headroom(skb), needed_room);
  10790. + skb_cow(skb, needed_room);
  10791. + }
  10792. + skb_push(skb, needed_room);
  10793. + }
  10794. +
  10795. + if (ieee80211_is_data_qos(wh->frame_control))
  10796. + hdrlen -= IEEE80211_QOS_CTL_LEN;
  10797. +
  10798. + if (priv->chip_type == MWL8997)
  10799. + dma_data = &((struct pcie_pfu_dma_data *)skb->data)->dma_data;
  10800. + else
  10801. + dma_data = (struct pcie_dma_data *)skb->data;
  10802. +
  10803. + if (wh != &dma_data->wh)
  10804. + memmove(&dma_data->wh, wh, hdrlen);
  10805. +
  10806. + if (hdrlen != sizeof(dma_data->wh))
  10807. + memset(((void *)&dma_data->wh) + hdrlen, 0,
  10808. + sizeof(dma_data->wh) - hdrlen);
  10809. +
  10810. + /* Firmware length is the length of the fully formed "802.11
  10811. + * payload". That is, everything except for the 802.11 header.
  10812. + * This includes all crypto material including the MIC.
  10813. + */
  10814. + dma_data->fwlen =
  10815. + cpu_to_le16(skb->len - dma_hdrlen + tail_pad);
  10816. +}
  10817. +
  10818. +static inline void pcie_tx_encapsulate_frame(struct mwl_priv *priv,
  10819. + struct sk_buff *skb,
  10820. + struct ieee80211_key_conf *k_conf,
  10821. + bool *ccmp)
  10822. +{
  10823. + int head_pad = 0;
  10824. + int data_pad = 0;
  10825. +
  10826. + /* Make sure the packet header is in the DMA header format (4-address
  10827. + * without QoS), and add head & tail padding when HW crypto is enabled.
  10828. + *
  10829. + * We have the following trailer padding requirements:
  10830. + * - WEP: 4 trailer bytes (ICV)
  10831. + * - TKIP: 12 trailer bytes (8 MIC + 4 ICV)
  10832. + * - CCMP: 8 trailer bytes (MIC)
  10833. + */
  10834. +
  10835. + if (k_conf) {
  10836. + head_pad = k_conf->iv_len;
  10837. +
  10838. + switch (k_conf->cipher) {
  10839. + case WLAN_CIPHER_SUITE_WEP40:
  10840. + case WLAN_CIPHER_SUITE_WEP104:
  10841. + data_pad = 4;
  10842. + break;
  10843. + case WLAN_CIPHER_SUITE_TKIP:
  10844. + data_pad = 12;
  10845. + break;
  10846. + case WLAN_CIPHER_SUITE_CCMP:
  10847. + data_pad = 8;
  10848. + if (ccmp)
  10849. + *ccmp = true;
  10850. + break;
  10851. + }
  10852. + }
  10853. +
  10854. + pcie_tx_add_dma_header(priv, skb, head_pad, data_pad);
  10855. +}
  10856. +
  10857. +static inline void pcie_tx_prepare_info(struct mwl_priv *priv, u32 rate,
  10858. + struct ieee80211_tx_info *info)
  10859. +{
  10860. + u32 format, bandwidth, short_gi, rate_id;
  10861. +
  10862. + ieee80211_tx_info_clear_status(info);
  10863. +
  10864. + info->status.rates[0].idx = -1;
  10865. + info->status.rates[0].count = 0;
  10866. + info->status.rates[0].flags = 0;
  10867. + info->flags &= ~IEEE80211_TX_CTL_AMPDU;
  10868. + info->flags |= IEEE80211_TX_STAT_ACK;
  10869. +
  10870. + if (rate) {
  10871. + /* Prepare rate information */
  10872. + format = rate & MWL_TX_RATE_FORMAT_MASK;
  10873. + bandwidth =
  10874. + (rate & MWL_TX_RATE_BANDWIDTH_MASK) >>
  10875. + MWL_TX_RATE_BANDWIDTH_SHIFT;
  10876. + short_gi = (rate & MWL_TX_RATE_SHORTGI_MASK) >>
  10877. + MWL_TX_RATE_SHORTGI_SHIFT;
  10878. + rate_id = (rate & MWL_TX_RATE_RATEIDMCS_MASK) >>
  10879. + MWL_TX_RATE_RATEIDMCS_SHIFT;
  10880. +
  10881. + info->status.rates[0].idx = rate_id;
  10882. + if (format == TX_RATE_FORMAT_LEGACY) {
  10883. + if (priv->hw->conf.chandef.chan->hw_value >
  10884. + BAND_24_CHANNEL_NUM) {
  10885. + info->status.rates[0].idx -= 5;
  10886. + }
  10887. + }
  10888. + if (format == TX_RATE_FORMAT_11N)
  10889. + info->status.rates[0].flags |=
  10890. + IEEE80211_TX_RC_MCS;
  10891. + if (format == TX_RATE_FORMAT_11AC)
  10892. + info->status.rates[0].flags |=
  10893. + IEEE80211_TX_RC_VHT_MCS;
  10894. + if (bandwidth == TX_RATE_BANDWIDTH_40)
  10895. + info->status.rates[0].flags |=
  10896. + IEEE80211_TX_RC_40_MHZ_WIDTH;
  10897. + if (bandwidth == TX_RATE_BANDWIDTH_80)
  10898. + info->status.rates[0].flags |=
  10899. + IEEE80211_TX_RC_80_MHZ_WIDTH;
  10900. + if (bandwidth == TX_RATE_BANDWIDTH_160)
  10901. + info->status.rates[0].flags |=
  10902. + IEEE80211_TX_RC_160_MHZ_WIDTH;
  10903. + if (short_gi == TX_RATE_INFO_SHORT_GI)
  10904. + info->status.rates[0].flags |=
  10905. + IEEE80211_TX_RC_SHORT_GI;
  10906. + info->status.rates[0].count = 1;
  10907. + info->status.rates[1].idx = -1;
  10908. + }
  10909. +}
  10910. +
  10911. +static inline void pcie_tx_count_packet(struct ieee80211_sta *sta, u8 tid)
  10912. +{
  10913. + struct mwl_sta *sta_info;
  10914. + struct mwl_tx_info *tx_stats;
  10915. +
  10916. + if (WARN_ON(tid >= SYSADPT_MAX_TID))
  10917. + return;
  10918. +
  10919. + sta_info = mwl_dev_get_sta(sta);
  10920. +
  10921. + tx_stats = &sta_info->tx_stats[tid];
  10922. +
  10923. + if (tx_stats->start_time == 0)
  10924. + tx_stats->start_time = jiffies;
  10925. +
  10926. + /* reset the packet count after each second elapses. If the number of
  10927. + * packets ever exceeds the ampdu_min_traffic threshold, we will allow
  10928. + * an ampdu stream to be started.
  10929. + */
  10930. + if (jiffies - tx_stats->start_time > HZ) {
  10931. + tx_stats->pkts = 0;
  10932. + tx_stats->start_time = jiffies;
  10933. + } else {
  10934. + tx_stats->pkts++;
  10935. + }
  10936. +}
  10937. +
  10938. +static inline void pcie_rx_prepare_status(struct mwl_priv *priv, u16 format,
  10939. + u16 nss, u16 bw, u16 gi, u16 rate,
  10940. + struct ieee80211_rx_status *status)
  10941. +{
  10942. +#ifdef RX_ENC_FLAG_STBC_SHIFT
  10943. + switch (format) {
  10944. + case RX_RATE_INFO_FORMAT_11N:
  10945. + status->encoding = RX_ENC_HT;
  10946. + status->bw = RATE_INFO_BW_20;
  10947. + if (bw == RX_RATE_INFO_HT40)
  10948. + status->bw = RATE_INFO_BW_40;
  10949. + if (gi == RX_RATE_INFO_SHORT_INTERVAL)
  10950. + status->enc_flags |= RX_ENC_FLAG_SHORT_GI;
  10951. + break;
  10952. + case RX_RATE_INFO_FORMAT_11AC:
  10953. + status->encoding = RX_ENC_VHT;
  10954. + status->bw = RATE_INFO_BW_20;
  10955. + if (bw == RX_RATE_INFO_HT40)
  10956. + status->bw = RATE_INFO_BW_40;
  10957. + if (bw == RX_RATE_INFO_HT80)
  10958. + status->bw = RATE_INFO_BW_80;
  10959. + if (bw == RX_RATE_INFO_HT160)
  10960. + status->bw = RATE_INFO_BW_160;
  10961. + if (gi == RX_RATE_INFO_SHORT_INTERVAL)
  10962. + status->enc_flags |= RX_ENC_FLAG_SHORT_GI;
  10963. + status->nss = (nss + 1);
  10964. + break;
  10965. + }
  10966. +#else
  10967. + switch (format) {
  10968. + case RX_RATE_INFO_FORMAT_11N:
  10969. + status->flag |= RX_FLAG_HT;
  10970. + if (bw == RX_RATE_INFO_HT40)
  10971. + status->flag |= RX_FLAG_40MHZ;
  10972. + if (gi == RX_RATE_INFO_SHORT_INTERVAL)
  10973. + status->flag |= RX_FLAG_SHORT_GI;
  10974. + break;
  10975. + case RX_RATE_INFO_FORMAT_11AC:
  10976. + status->flag |= RX_FLAG_VHT;
  10977. + if (bw == RX_RATE_INFO_HT40)
  10978. + status->flag |= RX_FLAG_40MHZ;
  10979. + if (bw == RX_RATE_INFO_HT80)
  10980. + status->vht_flag |= RX_VHT_FLAG_80MHZ;
  10981. + if (bw == RX_RATE_INFO_HT160)
  10982. + status->vht_flag |= RX_VHT_FLAG_160MHZ;
  10983. + if (gi == RX_RATE_INFO_SHORT_INTERVAL)
  10984. + status->flag |= RX_FLAG_SHORT_GI;
  10985. + status->vht_nss = (nss + 1);
  10986. + break;
  10987. + }
  10988. +#endif
  10989. + status->rate_idx = rate;
  10990. +
  10991. + if (priv->hw->conf.chandef.chan->hw_value >
  10992. + BAND_24_CHANNEL_NUM) {
  10993. + status->band = NL80211_BAND_5GHZ;
  10994. +#ifdef RX_ENC_FLAG_STBC_SHIFT
  10995. + if ((!(status->encoding == RX_ENC_HT)) &&
  10996. + (!(status->encoding == RX_ENC_VHT))) {
  10997. +#else
  10998. + if ((!(status->flag & RX_FLAG_HT)) &&
  10999. + (!(status->flag & RX_FLAG_VHT))) {
  11000. +#endif
  11001. + status->rate_idx -= 5;
  11002. + if (status->rate_idx >= BAND_50_RATE_NUM)
  11003. + status->rate_idx = BAND_50_RATE_NUM - 1;
  11004. + }
  11005. + } else {
  11006. + status->band = NL80211_BAND_2GHZ;
  11007. +#ifdef RX_ENC_FLAG_STBC_SHIFT
  11008. + if ((!(status->encoding == RX_ENC_HT)) &&
  11009. + (!(status->encoding == RX_ENC_VHT))) {
  11010. +#else
  11011. + if ((!(status->flag & RX_FLAG_HT)) &&
  11012. + (!(status->flag & RX_FLAG_VHT))) {
  11013. +#endif
  11014. + if (status->rate_idx >= BAND_24_RATE_NUM)
  11015. + status->rate_idx = BAND_24_RATE_NUM - 1;
  11016. + }
  11017. + }
  11018. +}
  11019. +
  11020. +static inline void pcie_rx_remove_dma_header(struct sk_buff *skb, __le16 qos)
  11021. +{
  11022. + struct pcie_dma_data *dma_data;
  11023. + int hdrlen;
  11024. +
  11025. + dma_data = (struct pcie_dma_data *)skb->data;
  11026. + hdrlen = ieee80211_hdrlen(dma_data->wh.frame_control);
  11027. +
  11028. + if (hdrlen != sizeof(dma_data->wh)) {
  11029. + if (ieee80211_is_data_qos(dma_data->wh.frame_control)) {
  11030. + memmove(dma_data->data - hdrlen,
  11031. + &dma_data->wh, hdrlen - 2);
  11032. + *((__le16 *)(dma_data->data - 2)) = qos;
  11033. + } else {
  11034. + memmove(dma_data->data - hdrlen, &dma_data->wh, hdrlen);
  11035. + }
  11036. + }
  11037. +
  11038. + if (hdrlen != sizeof(*dma_data))
  11039. + skb_pull(skb, sizeof(*dma_data) - hdrlen);
  11040. +}
  11041. +
  11042. +static inline void pcie_mask_int(struct pcie_priv *pcie_priv,
  11043. + u32 mask_bit, bool set)
  11044. +{
  11045. + unsigned long flags;
  11046. + void __iomem *int_status_mask;
  11047. + u32 status;
  11048. +
  11049. + spin_lock_irqsave(&pcie_priv->int_mask_lock, flags);
  11050. + int_status_mask = pcie_priv->iobase1 +
  11051. + MACREG_REG_A2H_INTERRUPT_STATUS_MASK;
  11052. + status = readl(int_status_mask);
  11053. + if (set)
  11054. + writel((status | mask_bit), int_status_mask);
  11055. + else
  11056. + writel((status & ~mask_bit), int_status_mask);
  11057. + spin_unlock_irqrestore(&pcie_priv->int_mask_lock, flags);
  11058. +}
  11059. +
  11060. +#endif /* _DEV_H_ */
  11061. diff --git a/drivers/net/wireless/marvell/mwlwifi/hif/pcie/fwdl.c b/drivers/net/wireless/marvell/mwlwifi/hif/pcie/fwdl.c
  11062. new file mode 100644
  11063. index 000000000000..939ed54133c7
  11064. --- /dev/null
  11065. +++ b/drivers/net/wireless/marvell/mwlwifi/hif/pcie/fwdl.c
  11066. @@ -0,0 +1,274 @@
  11067. +/*
  11068. + * Copyright (C) 2006-2018, Marvell International Ltd.
  11069. + *
  11070. + * This software file (the "File") is distributed by Marvell International
  11071. + * Ltd. under the terms of the GNU General Public License Version 2, June 1991
  11072. + * (the "License"). You may use, redistribute and/or modify this File in
  11073. + * accordance with the terms and conditions of the License, a copy of which
  11074. + * is available by writing to the Free Software Foundation, Inc.
  11075. + *
  11076. + * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
  11077. + * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
  11078. + * ARE EXPRESSLY DISCLAIMED. The License provides additional details about
  11079. + * this warranty disclaimer.
  11080. + */
  11081. +
  11082. +/* Description: This file implements firmware download related
  11083. + * functions.
  11084. + */
  11085. +
  11086. +#include <linux/io.h>
  11087. +
  11088. +#include "sysadpt.h"
  11089. +#include "core.h"
  11090. +#include "hif/fwcmd.h"
  11091. +#include "hif/pcie/dev.h"
  11092. +#include "hif/pcie/sc4_ddr.h"
  11093. +#include "hif/pcie/fwdl.h"
  11094. +
  11095. +#define FW_DOWNLOAD_BLOCK_SIZE 256
  11096. +#define FW_CHECK_MSECS 3
  11097. +
  11098. +#define FW_MAX_NUM_CHECKS 0xffff
  11099. +
  11100. +static void pcie_trigger_pcicmd_bootcode(struct pcie_priv *pcie_priv)
  11101. +{
  11102. + writel(pcie_priv->mwl_priv->pphys_cmd_buf,
  11103. + pcie_priv->iobase1 + MACREG_REG_GEN_PTR);
  11104. + writel(0x00, pcie_priv->iobase1 + MACREG_REG_INT_CODE);
  11105. + writel(MACREG_H2ARIC_BIT_DOOR_BELL,
  11106. + pcie_priv->iobase1 + MACREG_REG_H2A_INTERRUPT_EVENTS);
  11107. +}
  11108. +
  11109. +static bool pcie_download_ddr_init(struct mwl_priv *priv)
  11110. +{
  11111. + struct pcie_priv *pcie_priv = (struct pcie_priv *)priv->hif.priv;
  11112. + u32 size_ddr_init = sizeof(sc4_ddr_init);
  11113. + u8 *p = (u8 *)&sc4_ddr_init[0];
  11114. + u32 curr_iteration = 0;
  11115. + u32 size_ddr_init_downloaded = 0;
  11116. + u32 int_code = 0;
  11117. + u32 len = 0;
  11118. +
  11119. + /* download ddr init code */
  11120. + wiphy_debug(priv->hw->wiphy, "ddr init: download start\n");
  11121. +
  11122. + while (size_ddr_init_downloaded < size_ddr_init) {
  11123. + len = readl(pcie_priv->iobase1 + 0xc40);
  11124. +
  11125. + if (!len)
  11126. + break;
  11127. +
  11128. + /* this copies the next chunk of fw binary to be delivered */
  11129. + memcpy((char *)&priv->pcmd_buf[0], p, len);
  11130. + /* this is arbitrary per your platform; we use 0xffff */
  11131. + curr_iteration = (FW_MAX_NUM_CHECKS * 500);
  11132. + /* this function writes pdata to c10, then write 2 to c18 */
  11133. + pcie_trigger_pcicmd_bootcode(pcie_priv);
  11134. +
  11135. + /* NOTE: the following back to back checks on C1C is time
  11136. + * sensitive, hence may need to be tweaked dependent on host
  11137. + * processor. Time for SC2 to go from the write of event 2 to
  11138. + * C1C == 2 is ~1300 nSec. Hence the checkings on host has to
  11139. + * consider how efficient your code can be to meet this timing,
  11140. + * or you can alternatively tweak this routines to fit your
  11141. + * platform
  11142. + */
  11143. + do {
  11144. + int_code = readl(pcie_priv->iobase1 + 0xc1c);
  11145. + if (int_code != 0)
  11146. + break;
  11147. + cond_resched();
  11148. + curr_iteration--;
  11149. + } while (curr_iteration);
  11150. +
  11151. + do {
  11152. + int_code = readl(pcie_priv->iobase1 + 0xc1c);
  11153. + if ((int_code & MACREG_H2ARIC_BIT_DOOR_BELL) !=
  11154. + MACREG_H2ARIC_BIT_DOOR_BELL)
  11155. + break;
  11156. + cond_resched();
  11157. + curr_iteration--;
  11158. + } while (curr_iteration);
  11159. +
  11160. + if (curr_iteration == 0) {
  11161. + /* This limited loop check allows you to exit gracefully
  11162. + * without locking up your entire system just because fw
  11163. + * download failed
  11164. + */
  11165. + wiphy_err(priv->hw->wiphy,
  11166. + "Exhausted curr_iteration during download\n");
  11167. + return false;
  11168. + }
  11169. +
  11170. + p += len;
  11171. + size_ddr_init_downloaded += len;
  11172. + }
  11173. +
  11174. + wiphy_debug(priv->hw->wiphy, "ddr init: download complete\n");
  11175. +
  11176. + return true;
  11177. +}
  11178. +
  11179. +void pcie_reset(struct ieee80211_hw *hw)
  11180. +{
  11181. + struct mwl_priv *priv = hw->priv;
  11182. + struct pcie_priv *pcie_priv = priv->hif.priv;
  11183. + u32 regval;
  11184. +
  11185. + regval = readl(pcie_priv->iobase1 + MACREG_REG_INT_CODE);
  11186. + if (regval == 0xffffffff) {
  11187. + wiphy_err(priv->hw->wiphy, "adapter does not exist\n");
  11188. + return;
  11189. + }
  11190. +
  11191. + writel(ISR_RESET, pcie_priv->iobase1 + MACREG_REG_H2A_INTERRUPT_EVENTS);
  11192. +}
  11193. +
  11194. +int pcie_download_firmware(struct ieee80211_hw *hw)
  11195. +{
  11196. + struct mwl_priv *priv = hw->priv;
  11197. + struct pcie_priv *pcie_priv = priv->hif.priv;
  11198. + const struct firmware *fw = priv->fw_ucode;
  11199. + u32 curr_iteration = 0;
  11200. + u32 size_fw_downloaded = 0;
  11201. + u32 int_code = 0;
  11202. + u32 len = 0;
  11203. + u32 fwreadysignature = HOSTCMD_SOFTAP_FWRDY_SIGNATURE;
  11204. +
  11205. + pcie_reset(hw);
  11206. +
  11207. + /* FW before jumping to boot rom, it will enable PCIe transaction retry,
  11208. + * wait for boot code to stop it.
  11209. + */
  11210. + usleep_range(FW_CHECK_MSECS * 1000, FW_CHECK_MSECS * 2000);
  11211. +
  11212. + if (priv->chip_type == MWL8964) {
  11213. + writel(MACREG_A2HRIC_BIT_MASK_NDP,
  11214. + pcie_priv->iobase1 + MACREG_REG_A2H_INTERRUPT_CLEAR_SEL);
  11215. + } else {
  11216. + writel(MACREG_A2HRIC_BIT_MASK,
  11217. + pcie_priv->iobase1 + MACREG_REG_A2H_INTERRUPT_CLEAR_SEL);
  11218. + }
  11219. + writel(0x00, pcie_priv->iobase1 + MACREG_REG_A2H_INTERRUPT_CAUSE);
  11220. + writel(0x00, pcie_priv->iobase1 + MACREG_REG_A2H_INTERRUPT_MASK);
  11221. + if (priv->chip_type == MWL8964) {
  11222. + writel(MACREG_A2HRIC_BIT_MASK_NDP,
  11223. + pcie_priv->iobase1 +
  11224. + MACREG_REG_A2H_INTERRUPT_STATUS_MASK);
  11225. + } else {
  11226. + writel(MACREG_A2HRIC_BIT_MASK,
  11227. + pcie_priv->iobase1 +
  11228. + MACREG_REG_A2H_INTERRUPT_STATUS_MASK);
  11229. + }
  11230. +
  11231. + /* this routine interacts with SC2 bootrom to download firmware binary
  11232. + * to the device. After DMA'd to SC2, the firmware could be deflated to
  11233. + * reside on its respective blocks such as ITCM, DTCM, SQRAM,
  11234. + * (or even DDR, AFTER DDR is init'd before fw download
  11235. + */
  11236. + wiphy_debug(hw->wiphy, "fw download start\n");
  11237. +
  11238. + if (priv->chip_type != MWL8997)
  11239. + /* Disable PFU before FWDL */
  11240. + writel(0x100, pcie_priv->iobase1 + 0xE0E4);
  11241. +
  11242. + /* make sure SCRATCH2 C40 is clear, in case we are too quick */
  11243. + while (readl(pcie_priv->iobase1 + 0xc40) == 0)
  11244. + cond_resched();
  11245. +
  11246. + if (priv->chip_type == MWL8964) {
  11247. + if (!pcie_download_ddr_init(priv)) {
  11248. + wiphy_err(hw->wiphy,
  11249. + "ddr init: code download failed\n");
  11250. + goto err_download;
  11251. + }
  11252. + }
  11253. +
  11254. + while (size_fw_downloaded < fw->size) {
  11255. + len = readl(pcie_priv->iobase1 + 0xc40);
  11256. +
  11257. + if (!len)
  11258. + break;
  11259. +
  11260. + /* this copies the next chunk of fw binary to be delivered */
  11261. + memcpy((char *)&priv->pcmd_buf[0],
  11262. + (fw->data + size_fw_downloaded), len);
  11263. +
  11264. + /* this function writes pdata to c10, then write 2 to c18 */
  11265. + pcie_trigger_pcicmd_bootcode(pcie_priv);
  11266. +
  11267. + /* this is arbitrary per your platform; we use 0xffff */
  11268. + curr_iteration = FW_MAX_NUM_CHECKS;
  11269. +
  11270. + /* NOTE: the following back to back checks on C1C is time
  11271. + * sensitive, hence may need to be tweaked dependent on host
  11272. + * processor. Time for SC2 to go from the write of event 2 to
  11273. + * C1C == 2 is ~1300 nSec. Hence the checkings on host has to
  11274. + * consider how efficient your code can be to meet this timing,
  11275. + * or you can alternatively tweak this routines to fit your
  11276. + * platform
  11277. + */
  11278. + do {
  11279. + int_code = readl(pcie_priv->iobase1 + 0xc1c);
  11280. + if ((int_code & MACREG_H2ARIC_BIT_DOOR_BELL) !=
  11281. + MACREG_H2ARIC_BIT_DOOR_BELL)
  11282. + break;
  11283. + cond_resched();
  11284. + curr_iteration--;
  11285. + } while (curr_iteration);
  11286. +
  11287. + if (curr_iteration == 0) {
  11288. + /* This limited loop check allows you to exit gracefully
  11289. + * without locking up your entire system just because fw
  11290. + * download failed
  11291. + */
  11292. + wiphy_err(hw->wiphy,
  11293. + "Exhausted curr_iteration for fw download\n");
  11294. + goto err_download;
  11295. + }
  11296. +
  11297. + size_fw_downloaded += len;
  11298. + }
  11299. +
  11300. + wiphy_debug(hw->wiphy,
  11301. + "FwSize = %d downloaded Size = %d curr_iteration %d\n",
  11302. + (int)fw->size, size_fw_downloaded, curr_iteration);
  11303. +
  11304. + /* Now firware is downloaded successfully, so this part is to check
  11305. + * whether fw can properly execute to an extent that write back
  11306. + * signature to indicate its readiness to the host. NOTE: if your
  11307. + * downloaded fw crashes, this signature checking will fail. This
  11308. + * part is similar as SC1
  11309. + */
  11310. + *((u32 *)&priv->pcmd_buf[1]) = 0;
  11311. + pcie_trigger_pcicmd_bootcode(pcie_priv);
  11312. + curr_iteration = FW_MAX_NUM_CHECKS;
  11313. + do {
  11314. + curr_iteration--;
  11315. + writel(HOSTCMD_SOFTAP_MODE,
  11316. + pcie_priv->iobase1 + MACREG_REG_GEN_PTR);
  11317. + usleep_range(FW_CHECK_MSECS * 1000, FW_CHECK_MSECS * 2000);
  11318. + int_code = readl(pcie_priv->iobase1 + MACREG_REG_INT_CODE);
  11319. + if (!(curr_iteration % 0xff) && (int_code != 0))
  11320. + wiphy_err(hw->wiphy, "%x;", int_code);
  11321. + } while ((curr_iteration) &&
  11322. + (int_code != fwreadysignature));
  11323. +
  11324. + if (curr_iteration == 0) {
  11325. + wiphy_err(hw->wiphy,
  11326. + "Exhausted curr_iteration for fw signature\n");
  11327. + goto err_download;
  11328. + }
  11329. +
  11330. + wiphy_debug(hw->wiphy, "fw download complete\n");
  11331. + writel(0x00, pcie_priv->iobase1 + MACREG_REG_INT_CODE);
  11332. +
  11333. + return 0;
  11334. +
  11335. +err_download:
  11336. +
  11337. + pcie_reset(hw);
  11338. +
  11339. + return -EIO;
  11340. +}
  11341. diff --git a/drivers/net/wireless/marvell/mwlwifi/hif/pcie/fwdl.h b/drivers/net/wireless/marvell/mwlwifi/hif/pcie/fwdl.h
  11342. new file mode 100644
  11343. index 000000000000..36a3311aa678
  11344. --- /dev/null
  11345. +++ b/drivers/net/wireless/marvell/mwlwifi/hif/pcie/fwdl.h
  11346. @@ -0,0 +1,24 @@
  11347. +/*
  11348. + * Copyright (C) 2006-2018, Marvell International Ltd.
  11349. + *
  11350. + * This software file (the "File") is distributed by Marvell International
  11351. + * Ltd. under the terms of the GNU General Public License Version 2, June 1991
  11352. + * (the "License"). You may use, redistribute and/or modify this File in
  11353. + * accordance with the terms and conditions of the License, a copy of which
  11354. + * is available by writing to the Free Software Foundation, Inc.
  11355. + *
  11356. + * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
  11357. + * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
  11358. + * ARE EXPRESSLY DISCLAIMED. The License provides additional details about
  11359. + * this warranty disclaimer.
  11360. + */
  11361. +
  11362. +/* Description: This file defines firmware download related functions. */
  11363. +
  11364. +#ifndef _FWDL_H_
  11365. +#define _FWDL_H_
  11366. +
  11367. +void pcie_reset(struct ieee80211_hw *hw);
  11368. +int pcie_download_firmware(struct ieee80211_hw *hw);
  11369. +
  11370. +#endif /* _FWDL_H_ */
  11371. diff --git a/drivers/net/wireless/marvell/mwlwifi/hif/pcie/pcie.c b/drivers/net/wireless/marvell/mwlwifi/hif/pcie/pcie.c
  11372. new file mode 100644
  11373. index 000000000000..da55913c0570
  11374. --- /dev/null
  11375. +++ b/drivers/net/wireless/marvell/mwlwifi/hif/pcie/pcie.c
  11376. @@ -0,0 +1,1645 @@
  11377. +/*
  11378. + * Copyright (C) 2006-2018, Marvell International Ltd.
  11379. + *
  11380. + * This software file (the "File") is distributed by Marvell International
  11381. + * Ltd. under the terms of the GNU General Public License Version 2, June 1991
  11382. + * (the "License"). You may use, redistribute and/or modify this File in
  11383. + * accordance with the terms and conditions of the License, a copy of which
  11384. + * is available by writing to the Free Software Foundation, Inc.
  11385. + *
  11386. + * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
  11387. + * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
  11388. + * ARE EXPRESSLY DISCLAIMED. The License provides additional details about
  11389. + * this warranty disclaimer.
  11390. + */
  11391. +
  11392. +/* Description: This file implements functions needed for PCIe module. */
  11393. +
  11394. +#include <linux/module.h>
  11395. +#include <linux/etherdevice.h>
  11396. +
  11397. +#include "sysadpt.h"
  11398. +#include "core.h"
  11399. +#include "utils.h"
  11400. +#include "vendor_cmd.h"
  11401. +#include "hif/fwcmd.h"
  11402. +#include "hif/pcie/dev.h"
  11403. +#include "hif/pcie/fwdl.h"
  11404. +#include "hif/pcie/tx.h"
  11405. +#include "hif/pcie/rx.h"
  11406. +#include "hif/pcie/tx_ndp.h"
  11407. +#include "hif/pcie/rx_ndp.h"
  11408. +
  11409. +#define PCIE_DRV_DESC "Marvell Mac80211 Wireless PCIE Network Driver"
  11410. +#define PCIE_DEV_NAME "Marvell 802.11ac PCIE Adapter"
  11411. +
  11412. +#define MAX_WAIT_FW_COMPLETE_ITERATIONS 2000
  11413. +#define CHECK_BA_TRAFFIC_TIME 300 /* msec */
  11414. +#define CHECK_TX_DONE_TIME 50 /* msec */
  11415. +
  11416. +static struct pci_device_id pcie_id_tbl[] = {
  11417. + { PCI_VDEVICE(MARVELL, 0x2a55), .driver_data = MWL8864, },
  11418. + { PCI_VDEVICE(MARVELL, 0x2b38), .driver_data = MWL8897, },
  11419. + { PCI_VDEVICE(MARVELL, 0x2b40), .driver_data = MWL8964, },
  11420. + { PCI_VDEVICE(MARVELL_EXT, 0x2b42), .driver_data = MWL8997, },
  11421. + { },
  11422. +};
  11423. +
  11424. +static struct mwl_chip_info pcie_chip_tbl[] = {
  11425. + [MWL8864] = {
  11426. + .part_name = "88W8864",
  11427. + .fw_image = "mwlwifi/88W8864.bin",
  11428. + .cal_file = NULL,
  11429. + .txpwrlmt_file = NULL,
  11430. + .antenna_tx = ANTENNA_TX_4_AUTO,
  11431. + .antenna_rx = ANTENNA_RX_4_AUTO,
  11432. + },
  11433. + [MWL8897] = {
  11434. + .part_name = "88W8897",
  11435. + .fw_image = "mwlwifi/88W8897.bin",
  11436. + .cal_file = NULL,
  11437. + .txpwrlmt_file = NULL,
  11438. + .antenna_tx = ANTENNA_TX_2,
  11439. + .antenna_rx = ANTENNA_RX_2,
  11440. + },
  11441. + [MWL8964] = {
  11442. + .part_name = "88W8964",
  11443. + .fw_image = "mwlwifi/88W8964.bin",
  11444. + .cal_file = NULL,
  11445. + .txpwrlmt_file = NULL,
  11446. + .antenna_tx = ANTENNA_TX_4_AUTO,
  11447. + .antenna_rx = ANTENNA_RX_4_AUTO,
  11448. + },
  11449. + [MWL8997] = {
  11450. + .part_name = "88W8997",
  11451. + .fw_image = "mwlwifi/88W8997.bin",
  11452. + .cal_file = "mwlwifi/WlanCalData_ext.conf",
  11453. + .txpwrlmt_file = "mwlwifi/txpwrlmt_cfg.conf",
  11454. + .antenna_tx = ANTENNA_TX_2,
  11455. + .antenna_rx = ANTENNA_RX_2,
  11456. + },
  11457. +};
  11458. +
  11459. +static int pcie_alloc_resource(struct pcie_priv *pcie_priv)
  11460. +{
  11461. + struct pci_dev *pdev = pcie_priv->pdev;
  11462. + struct device *dev = &pdev->dev;
  11463. + void __iomem *addr;
  11464. +
  11465. + pcie_priv->next_bar_num = 1; /* 32-bit */
  11466. + if (pci_resource_flags(pdev, 0) & 0x04)
  11467. + pcie_priv->next_bar_num = 2; /* 64-bit */
  11468. +
  11469. + addr = devm_ioremap_resource(dev, &pdev->resource[0]);
  11470. + if (IS_ERR(addr)) {
  11471. + pr_err("%s: cannot reserve PCI memory region 0\n",
  11472. + PCIE_DRV_NAME);
  11473. + goto err;
  11474. + }
  11475. + pcie_priv->iobase0 = addr;
  11476. + pr_debug("iobase0 = %p\n", pcie_priv->iobase0);
  11477. +
  11478. + addr = devm_ioremap_resource(dev,
  11479. + &pdev->resource[pcie_priv->next_bar_num]);
  11480. + if (IS_ERR(addr)) {
  11481. + pr_err("%s: cannot reserve PCI memory region 1\n",
  11482. + PCIE_DRV_NAME);
  11483. + goto err;
  11484. + }
  11485. + pcie_priv->iobase1 = addr;
  11486. + pr_debug("iobase1 = %p\n", pcie_priv->iobase1);
  11487. +
  11488. + return 0;
  11489. +
  11490. +err:
  11491. + pr_err("pci alloc fail\n");
  11492. +
  11493. + return -EIO;
  11494. +}
  11495. +
  11496. +static u32 pcie_read_mac_reg(struct pcie_priv *pcie_priv, u32 offset)
  11497. +{
  11498. + struct mwl_priv *priv = pcie_priv->mwl_priv;
  11499. +
  11500. + if (priv->chip_type == MWL8964) {
  11501. + u32 *addr_val = kmalloc(64 * sizeof(u32), GFP_ATOMIC);
  11502. + u32 val;
  11503. +
  11504. + if (addr_val) {
  11505. + mwl_fwcmd_get_addr_value(priv->hw,
  11506. + 0x8000a000 + offset, 4,
  11507. + addr_val, 0);
  11508. + val = addr_val[0];
  11509. + kfree(addr_val);
  11510. + return val;
  11511. + }
  11512. + return 0;
  11513. + } else
  11514. + return le32_to_cpu(*(__le32 *)
  11515. + (MAC_REG_ADDR_PCI(offset)));
  11516. +}
  11517. +
  11518. +static bool pcie_chk_adapter(struct pcie_priv *pcie_priv)
  11519. +{
  11520. + struct mwl_priv *priv = pcie_priv->mwl_priv;
  11521. + u32 regval;
  11522. +
  11523. + regval = readl(pcie_priv->iobase1 + MACREG_REG_INT_CODE);
  11524. +
  11525. + if (regval == 0xffffffff) {
  11526. + wiphy_err(priv->hw->wiphy, "adapter does not exist\n");
  11527. + return false;
  11528. + }
  11529. +
  11530. + if (priv->cmd_timeout)
  11531. + wiphy_debug(priv->hw->wiphy, "MACREG_REG_INT_CODE: 0x%04x\n",
  11532. + regval);
  11533. +
  11534. + return true;
  11535. +}
  11536. +
  11537. +static void pcie_send_cmd(struct pcie_priv *pcie_priv)
  11538. +{
  11539. + writel(pcie_priv->mwl_priv->pphys_cmd_buf,
  11540. + pcie_priv->iobase1 + MACREG_REG_GEN_PTR);
  11541. + writel(MACREG_H2ARIC_BIT_DOOR_BELL,
  11542. + pcie_priv->iobase1 + MACREG_REG_H2A_INTERRUPT_EVENTS);
  11543. +}
  11544. +
  11545. +static int pcie_wait_complete(struct mwl_priv *priv, unsigned short cmd)
  11546. +{
  11547. + unsigned int curr_iteration = MAX_WAIT_FW_COMPLETE_ITERATIONS;
  11548. + unsigned short int_code = 0;
  11549. +
  11550. + do {
  11551. + int_code = le16_to_cpu(*((__le16 *)&priv->pcmd_buf[0]));
  11552. + usleep_range(1000, 2000);
  11553. + } while ((int_code != cmd) && (--curr_iteration) && !priv->rmmod);
  11554. +
  11555. + if (curr_iteration == 0) {
  11556. + wiphy_err(priv->hw->wiphy, "cmd 0x%04x=%s timed out\n",
  11557. + cmd, mwl_fwcmd_get_cmd_string(cmd));
  11558. + wiphy_err(priv->hw->wiphy, "return code: 0x%04x\n", int_code);
  11559. + return -EIO;
  11560. + }
  11561. +
  11562. + if (priv->chip_type != MWL8997)
  11563. + usleep_range(3000, 5000);
  11564. +
  11565. + return 0;
  11566. +}
  11567. +
  11568. +static int pcie_init(struct ieee80211_hw *hw)
  11569. +{
  11570. + struct mwl_priv *priv = hw->priv;
  11571. + struct pcie_priv *pcie_priv = priv->hif.priv;
  11572. + const struct hostcmd_get_hw_spec *get_hw_spec;
  11573. + struct hostcmd_set_hw_spec set_hw_spec;
  11574. + int rc, i;
  11575. +
  11576. + spin_lock_init(&pcie_priv->int_mask_lock);
  11577. + tasklet_init(&pcie_priv->tx_task,
  11578. + (void *)pcie_tx_skbs, (unsigned long)hw);
  11579. + tasklet_disable(&pcie_priv->tx_task);
  11580. + tasklet_init(&pcie_priv->tx_done_task,
  11581. + (void *)pcie_tx_done, (unsigned long)hw);
  11582. + tasklet_disable(&pcie_priv->tx_done_task);
  11583. + spin_lock_init(&pcie_priv->tx_desc_lock);
  11584. + tasklet_init(&pcie_priv->rx_task,
  11585. + (void *)pcie_rx_recv, (unsigned long)hw);
  11586. + tasklet_disable(&pcie_priv->rx_task);
  11587. + tasklet_init(&pcie_priv->qe_task,
  11588. + (void *)pcie_tx_flush_amsdu, (unsigned long)hw);
  11589. + tasklet_disable(&pcie_priv->qe_task);
  11590. + pcie_priv->txq_limit = PCIE_TX_QUEUE_LIMIT;
  11591. + pcie_priv->txq_wake_threshold = PCIE_TX_WAKE_Q_THRESHOLD;
  11592. + pcie_priv->is_tx_done_schedule = false;
  11593. + pcie_priv->recv_limit = PCIE_RECEIVE_LIMIT;
  11594. + pcie_priv->is_rx_schedule = false;
  11595. + pcie_priv->is_qe_schedule = false;
  11596. + pcie_priv->qe_trig_num = 0;
  11597. + pcie_priv->qe_trig_time = jiffies;
  11598. +
  11599. + rc = pcie_tx_init(hw);
  11600. + if (rc) {
  11601. + wiphy_err(hw->wiphy, "%s: fail to initialize TX\n",
  11602. + PCIE_DRV_NAME);
  11603. + goto err_mwl_tx_init;
  11604. + }
  11605. +
  11606. + rc = pcie_rx_init(hw);
  11607. + if (rc) {
  11608. + wiphy_err(hw->wiphy, "%s: fail to initialize RX\n",
  11609. + PCIE_DRV_NAME);
  11610. + goto err_mwl_rx_init;
  11611. + }
  11612. +
  11613. + /* get and prepare HW specifications */
  11614. + get_hw_spec = mwl_fwcmd_get_hw_specs(hw);
  11615. + if (!get_hw_spec) {
  11616. + wiphy_err(hw->wiphy, "%s: fail to get HW specifications\n",
  11617. + PCIE_DRV_NAME);
  11618. + goto err_get_hw_specs;
  11619. + }
  11620. + ether_addr_copy(&priv->hw_data.mac_addr[0],
  11621. + get_hw_spec->permanent_addr);
  11622. + pcie_priv->desc_data[0].wcb_base =
  11623. + le32_to_cpu(get_hw_spec->wcb_base0) & 0x0000ffff;
  11624. + for (i = 1; i < SYSADPT_TOTAL_TX_QUEUES; i++)
  11625. + pcie_priv->desc_data[i].wcb_base =
  11626. + le32_to_cpu(get_hw_spec->wcb_base[i - 1]) & 0x0000ffff;
  11627. + pcie_priv->desc_data[0].rx_desc_read =
  11628. + le32_to_cpu(get_hw_spec->rxpd_rd_ptr) & 0x0000ffff;
  11629. + pcie_priv->desc_data[0].rx_desc_write =
  11630. + le32_to_cpu(get_hw_spec->rxpd_wr_ptr) & 0x0000ffff;
  11631. + priv->hw_data.fw_release_num = le32_to_cpu(get_hw_spec->fw_release_num);
  11632. + priv->hw_data.hw_version = get_hw_spec->version;
  11633. + if (priv->chip_type != MWL8997) {
  11634. + writel(pcie_priv->desc_data[0].pphys_tx_ring,
  11635. + pcie_priv->iobase0 + pcie_priv->desc_data[0].wcb_base);
  11636. + for (i = 1; i < SYSADPT_TOTAL_TX_QUEUES; i++)
  11637. + writel(pcie_priv->desc_data[i].pphys_tx_ring,
  11638. + pcie_priv->iobase0 +
  11639. + pcie_priv->desc_data[i].wcb_base);
  11640. + }
  11641. + writel(pcie_priv->desc_data[0].pphys_rx_ring,
  11642. + pcie_priv->iobase0 + pcie_priv->desc_data[0].rx_desc_read);
  11643. + writel(pcie_priv->desc_data[0].pphys_rx_ring,
  11644. + pcie_priv->iobase0 + pcie_priv->desc_data[0].rx_desc_write);
  11645. +
  11646. + /* prepare and set HW specifications */
  11647. + memset(&set_hw_spec, 0, sizeof(set_hw_spec));
  11648. + if (priv->chip_type == MWL8997) {
  11649. + set_hw_spec.wcb_base[0] =
  11650. + cpu_to_le32(pcie_priv->txbd_ring_pbase);
  11651. + set_hw_spec.tx_wcb_num_per_queue =
  11652. + cpu_to_le32(PCIE_MAX_TXRX_BD);
  11653. + set_hw_spec.num_tx_queues = cpu_to_le32(1);
  11654. + set_hw_spec.features |= HW_SET_PARMS_FEATURES_HOST_PROBE_RESP;
  11655. + } else {
  11656. + set_hw_spec.wcb_base[0] =
  11657. + cpu_to_le32(pcie_priv->desc_data[0].pphys_tx_ring);
  11658. + for (i = 1; i < SYSADPT_TOTAL_TX_QUEUES; i++)
  11659. + set_hw_spec.wcb_base[i] = cpu_to_le32(
  11660. + pcie_priv->desc_data[i].pphys_tx_ring);
  11661. + set_hw_spec.tx_wcb_num_per_queue =
  11662. + cpu_to_le32(PCIE_MAX_NUM_TX_DESC);
  11663. + set_hw_spec.num_tx_queues = cpu_to_le32(PCIE_NUM_OF_DESC_DATA);
  11664. + }
  11665. + set_hw_spec.total_rx_wcb = cpu_to_le32(PCIE_MAX_NUM_RX_DESC);
  11666. + set_hw_spec.rxpd_wr_ptr =
  11667. + cpu_to_le32(pcie_priv->desc_data[0].pphys_rx_ring);
  11668. + rc = mwl_fwcmd_set_hw_specs(hw, &set_hw_spec);
  11669. + if (rc) {
  11670. + wiphy_err(hw->wiphy, "%s: fail to set HW specifications\n",
  11671. + PCIE_DRV_NAME);
  11672. + goto err_set_hw_specs;
  11673. + }
  11674. +
  11675. + return rc;
  11676. +
  11677. +err_set_hw_specs:
  11678. +err_get_hw_specs:
  11679. +
  11680. + pcie_rx_deinit(hw);
  11681. +
  11682. +err_mwl_rx_init:
  11683. +
  11684. + pcie_tx_deinit(hw);
  11685. +
  11686. +err_mwl_tx_init:
  11687. +
  11688. + wiphy_err(hw->wiphy, "%s: init fail\n", PCIE_DRV_NAME);
  11689. +
  11690. + return rc;
  11691. +}
  11692. +
  11693. +static void pcie_deinit(struct ieee80211_hw *hw)
  11694. +{
  11695. + struct mwl_priv *priv = hw->priv;
  11696. + struct pcie_priv *pcie_priv = priv->hif.priv;
  11697. +
  11698. + pcie_rx_deinit(hw);
  11699. + pcie_tx_deinit(hw);
  11700. + tasklet_kill(&pcie_priv->qe_task);
  11701. + tasklet_kill(&pcie_priv->rx_task);
  11702. + tasklet_kill(&pcie_priv->tx_done_task);
  11703. + tasklet_kill(&pcie_priv->tx_task);
  11704. + pcie_reset(hw);
  11705. +}
  11706. +
  11707. +static int pcie_get_info(struct ieee80211_hw *hw, char *buf, size_t size)
  11708. +{
  11709. + struct mwl_priv *priv = hw->priv;
  11710. + struct pcie_priv *pcie_priv = priv->hif.priv;
  11711. + char *p = buf;
  11712. + int len = 0;
  11713. +
  11714. + len += scnprintf(p + len, size - len, "iobase0: %p\n",
  11715. + pcie_priv->iobase0);
  11716. + len += scnprintf(p + len, size - len, "iobase1: %p\n",
  11717. + pcie_priv->iobase1);
  11718. + len += scnprintf(p + len, size - len,
  11719. + "tx limit: %d\n", pcie_priv->txq_limit);
  11720. + len += scnprintf(p + len, size - len,
  11721. + "rx limit: %d\n", pcie_priv->recv_limit);
  11722. + len += scnprintf(p + len, size - len,
  11723. + "qe trigger number: %d\n", pcie_priv->qe_trig_num);
  11724. + return len;
  11725. +}
  11726. +
  11727. +static void pcie_enable_data_tasks(struct ieee80211_hw *hw)
  11728. +{
  11729. + struct mwl_priv *priv = hw->priv;
  11730. + struct pcie_priv *pcie_priv = priv->hif.priv;
  11731. +
  11732. + tasklet_enable(&pcie_priv->tx_task);
  11733. + tasklet_enable(&pcie_priv->tx_done_task);
  11734. + tasklet_enable(&pcie_priv->rx_task);
  11735. + tasklet_enable(&pcie_priv->qe_task);
  11736. +}
  11737. +
  11738. +static void pcie_disable_data_tasks(struct ieee80211_hw *hw)
  11739. +{
  11740. + struct mwl_priv *priv = hw->priv;
  11741. + struct pcie_priv *pcie_priv = priv->hif.priv;
  11742. +
  11743. + tasklet_disable(&pcie_priv->tx_task);
  11744. + tasklet_disable(&pcie_priv->tx_done_task);
  11745. + tasklet_disable(&pcie_priv->rx_task);
  11746. + tasklet_disable(&pcie_priv->qe_task);
  11747. +}
  11748. +
  11749. +static int pcie_exec_cmd(struct ieee80211_hw *hw, unsigned short cmd)
  11750. +{
  11751. + struct mwl_priv *priv = hw->priv;
  11752. + struct pcie_priv *pcie_priv = priv->hif.priv;
  11753. + bool busy = false;
  11754. +
  11755. + might_sleep();
  11756. +
  11757. + if (!pcie_chk_adapter(pcie_priv)) {
  11758. + wiphy_err(priv->hw->wiphy, "adapter does not exist\n");
  11759. + priv->in_send_cmd = false;
  11760. + return -EIO;
  11761. + }
  11762. +
  11763. + if (!priv->in_send_cmd && !priv->rmmod) {
  11764. + priv->in_send_cmd = true;
  11765. + if (priv->dump_hostcmd)
  11766. + wiphy_debug(priv->hw->wiphy, "send cmd 0x%04x=%s\n",
  11767. + cmd, mwl_fwcmd_get_cmd_string(cmd));
  11768. + pcie_send_cmd(pcie_priv);
  11769. + if (pcie_wait_complete(priv, 0x8000 | cmd)) {
  11770. + wiphy_err(priv->hw->wiphy, "timeout: 0x%04x\n", cmd);
  11771. + priv->in_send_cmd = false;
  11772. + priv->cmd_timeout = true;
  11773. + if (priv->heartbeat)
  11774. + vendor_cmd_basic_event(
  11775. + hw->wiphy,
  11776. + MWL_VENDOR_EVENT_CMD_TIMEOUT);
  11777. + return -EIO;
  11778. + }
  11779. + } else {
  11780. + wiphy_warn(priv->hw->wiphy,
  11781. + "previous command is running or module removed\n");
  11782. + busy = true;
  11783. + }
  11784. +
  11785. + if (!busy)
  11786. + priv->in_send_cmd = false;
  11787. +
  11788. + return 0;
  11789. +}
  11790. +
  11791. +static int pcie_get_irq_num(struct ieee80211_hw *hw)
  11792. +{
  11793. + struct mwl_priv *priv = hw->priv;
  11794. + struct pcie_priv *pcie_priv = priv->hif.priv;
  11795. +
  11796. + return pcie_priv->pdev->irq;
  11797. +}
  11798. +
  11799. +static irqreturn_t pcie_isr(struct ieee80211_hw *hw)
  11800. +{
  11801. + struct mwl_priv *priv = hw->priv;
  11802. + struct pcie_priv *pcie_priv = priv->hif.priv;
  11803. + u32 int_status;
  11804. +
  11805. + int_status = readl(pcie_priv->iobase1 + MACREG_REG_A2H_INTERRUPT_CAUSE);
  11806. +
  11807. + if (int_status == 0x00000000)
  11808. + return IRQ_NONE;
  11809. +
  11810. + if (int_status == 0xffffffff) {
  11811. + wiphy_warn(hw->wiphy, "card unplugged?\n");
  11812. + } else {
  11813. + writel(~int_status,
  11814. + pcie_priv->iobase1 + MACREG_REG_A2H_INTERRUPT_CAUSE);
  11815. +
  11816. + if (int_status & MACREG_A2HRIC_BIT_TX_DONE) {
  11817. + if (!pcie_priv->is_tx_done_schedule) {
  11818. + pcie_mask_int(pcie_priv,
  11819. + MACREG_A2HRIC_BIT_TX_DONE, false);
  11820. + tasklet_schedule(&pcie_priv->tx_done_task);
  11821. + pcie_priv->is_tx_done_schedule = true;
  11822. + }
  11823. + }
  11824. +
  11825. + if (int_status & MACREG_A2HRIC_BIT_RX_RDY) {
  11826. + if (!pcie_priv->is_rx_schedule) {
  11827. + pcie_mask_int(pcie_priv,
  11828. + MACREG_A2HRIC_BIT_RX_RDY, false);
  11829. + tasklet_schedule(&pcie_priv->rx_task);
  11830. + pcie_priv->is_rx_schedule = true;
  11831. + }
  11832. + }
  11833. +
  11834. + if (int_status & MACREG_A2HRIC_BIT_RADAR_DETECT) {
  11835. + wiphy_info(hw->wiphy, "radar detected by firmware\n");
  11836. + ieee80211_radar_detected(hw);
  11837. + }
  11838. +
  11839. + if (int_status & MACREG_A2HRIC_BIT_QUE_EMPTY) {
  11840. + if (!pcie_priv->is_qe_schedule) {
  11841. + if (time_after(jiffies,
  11842. + (pcie_priv->qe_trig_time + 1))) {
  11843. + pcie_mask_int(pcie_priv,
  11844. + MACREG_A2HRIC_BIT_QUE_EMPTY,
  11845. + false);
  11846. + tasklet_schedule(&pcie_priv->qe_task);
  11847. + pcie_priv->qe_trig_num++;
  11848. + pcie_priv->is_qe_schedule = true;
  11849. + pcie_priv->qe_trig_time = jiffies;
  11850. + }
  11851. + }
  11852. + }
  11853. +
  11854. + if (int_status & MACREG_A2HRIC_BIT_CHAN_SWITCH)
  11855. + ieee80211_queue_work(hw, &priv->chnl_switch_handle);
  11856. +
  11857. + if (int_status & MACREG_A2HRIC_BA_WATCHDOG)
  11858. + ieee80211_queue_work(hw, &priv->watchdog_ba_handle);
  11859. + }
  11860. +
  11861. + return IRQ_HANDLED;
  11862. +}
  11863. +
  11864. +static void pcie_irq_enable(struct ieee80211_hw *hw)
  11865. +{
  11866. + struct mwl_priv *priv = hw->priv;
  11867. + struct pcie_priv *pcie_priv = priv->hif.priv;
  11868. +
  11869. + if (pcie_chk_adapter(pcie_priv)) {
  11870. + writel(0x00,
  11871. + pcie_priv->iobase1 + MACREG_REG_A2H_INTERRUPT_MASK);
  11872. + writel(MACREG_A2HRIC_BIT_MASK,
  11873. + pcie_priv->iobase1 + MACREG_REG_A2H_INTERRUPT_MASK);
  11874. + }
  11875. +}
  11876. +
  11877. +static void pcie_irq_disable(struct ieee80211_hw *hw)
  11878. +{
  11879. + struct mwl_priv *priv = hw->priv;
  11880. + struct pcie_priv *pcie_priv = priv->hif.priv;
  11881. +
  11882. + if (pcie_chk_adapter(pcie_priv))
  11883. + writel(0x00,
  11884. + pcie_priv->iobase1 + MACREG_REG_A2H_INTERRUPT_MASK);
  11885. +}
  11886. +
  11887. +static void pcie_timer_routine(struct ieee80211_hw *hw)
  11888. +{
  11889. + struct mwl_priv *priv = hw->priv;
  11890. + static int cnt;
  11891. + struct mwl_ampdu_stream *stream;
  11892. + struct mwl_sta *sta_info;
  11893. + struct mwl_tx_info *tx_stats;
  11894. + struct mwl_ampdu_stream *rm_stream = NULL;
  11895. + u32 rm_pkts = 0;
  11896. + bool ba_full = true;
  11897. + int i;
  11898. +
  11899. + if ((++cnt * SYSADPT_TIMER_WAKEUP_TIME) < CHECK_BA_TRAFFIC_TIME)
  11900. + return;
  11901. + cnt = 0;
  11902. + spin_lock_bh(&priv->stream_lock);
  11903. + for (i = 0; i < priv->ampdu_num; i++) {
  11904. + stream = &priv->ampdu[i];
  11905. +
  11906. + if (stream->state == AMPDU_STREAM_ACTIVE) {
  11907. + sta_info = mwl_dev_get_sta(stream->sta);
  11908. + tx_stats = &sta_info->tx_stats[stream->tid];
  11909. +
  11910. + if ((jiffies - tx_stats->start_time > HZ) &&
  11911. + (tx_stats->pkts < SYSADPT_AMPDU_PACKET_THRESHOLD)) {
  11912. + if (rm_pkts) {
  11913. + if (tx_stats->pkts < rm_pkts) {
  11914. + rm_stream = stream;
  11915. + rm_pkts = tx_stats->pkts;
  11916. + }
  11917. + } else {
  11918. + rm_stream = stream;
  11919. + rm_pkts = tx_stats->pkts;
  11920. + }
  11921. + }
  11922. +
  11923. + if (jiffies - tx_stats->start_time > HZ) {
  11924. + tx_stats->pkts = 0;
  11925. + tx_stats->start_time = jiffies;
  11926. + }
  11927. + } else
  11928. + ba_full = false;
  11929. + }
  11930. + if (ba_full && rm_stream) {
  11931. + ieee80211_stop_tx_ba_session(rm_stream->sta,
  11932. + rm_stream->tid);
  11933. + wiphy_debug(hw->wiphy, "Stop BA %pM\n", rm_stream->sta->addr);
  11934. + }
  11935. + spin_unlock_bh(&priv->stream_lock);
  11936. +}
  11937. +
  11938. +static void pcie_tx_return_pkts(struct ieee80211_hw *hw)
  11939. +{
  11940. + pcie_tx_done((unsigned long)hw);
  11941. +}
  11942. +
  11943. +static struct device_node *pcie_get_device_node(struct ieee80211_hw *hw)
  11944. +{
  11945. + struct mwl_priv *priv = hw->priv;
  11946. + struct pcie_priv *pcie_priv = priv->hif.priv;
  11947. + struct device_node *dev_node;
  11948. +
  11949. + dev_node = pci_bus_to_OF_node(pcie_priv->pdev->bus);
  11950. + wiphy_info(priv->hw->wiphy, "device node: %s\n", dev_node->full_name);
  11951. +
  11952. + return dev_node;
  11953. +}
  11954. +
  11955. +static void pcie_get_survey(struct ieee80211_hw *hw,
  11956. + struct mwl_survey_info *survey_info)
  11957. +{
  11958. + struct mwl_priv *priv = hw->priv;
  11959. + struct pcie_priv *pcie_priv = priv->hif.priv;
  11960. +
  11961. + survey_info->filled = SURVEY_INFO_TIME |
  11962. + SURVEY_INFO_TIME_BUSY |
  11963. + SURVEY_INFO_TIME_TX |
  11964. + SURVEY_INFO_NOISE_DBM;
  11965. + survey_info->time_period += pcie_read_mac_reg(pcie_priv, MCU_LAST_READ);
  11966. + survey_info->time_busy += pcie_read_mac_reg(pcie_priv, MCU_CCA_CNT);
  11967. + survey_info->time_tx += pcie_read_mac_reg(pcie_priv, MCU_TXPE_CNT);
  11968. + survey_info->noise = priv->noise;
  11969. +}
  11970. +
  11971. +static int pcie_reg_access(struct ieee80211_hw *hw, bool write)
  11972. +{
  11973. + struct mwl_priv *priv = hw->priv;
  11974. + struct pcie_priv *pcie_priv = priv->hif.priv;
  11975. + u8 set;
  11976. + u32 *addr_val;
  11977. + int ret = 0;
  11978. +
  11979. + set = write ? WL_SET : WL_GET;
  11980. +
  11981. + switch (priv->reg_type) {
  11982. + case MWL_ACCESS_RF:
  11983. + ret = mwl_fwcmd_reg_rf(hw, set, priv->reg_offset,
  11984. + &priv->reg_value);
  11985. + break;
  11986. + case MWL_ACCESS_BBP:
  11987. + ret = mwl_fwcmd_reg_bb(hw, set, priv->reg_offset,
  11988. + &priv->reg_value);
  11989. + break;
  11990. + case MWL_ACCESS_CAU:
  11991. + ret = mwl_fwcmd_reg_cau(hw, set, priv->reg_offset,
  11992. + &priv->reg_value);
  11993. + break;
  11994. + case MWL_ACCESS_ADDR0:
  11995. + if (set == WL_GET)
  11996. + priv->reg_value =
  11997. + readl(pcie_priv->iobase0 + priv->reg_offset);
  11998. + else
  11999. + writel(priv->reg_value,
  12000. + pcie_priv->iobase0 + priv->reg_offset);
  12001. + break;
  12002. + case MWL_ACCESS_ADDR1:
  12003. + if (set == WL_GET)
  12004. + priv->reg_value =
  12005. + readl(pcie_priv->iobase1 + priv->reg_offset);
  12006. + else
  12007. + writel(priv->reg_value,
  12008. + pcie_priv->iobase1 + priv->reg_offset);
  12009. + break;
  12010. + case MWL_ACCESS_ADDR:
  12011. + addr_val = kzalloc(64 * sizeof(u32), GFP_KERNEL);
  12012. + if (addr_val) {
  12013. + addr_val[0] = priv->reg_value;
  12014. + ret = mwl_fwcmd_get_addr_value(hw, priv->reg_offset,
  12015. + 4, addr_val, set);
  12016. + if ((!ret) && (set == WL_GET))
  12017. + priv->reg_value = addr_val[0];
  12018. + kfree(addr_val);
  12019. + } else {
  12020. + ret = -ENOMEM;
  12021. + }
  12022. + break;
  12023. + default:
  12024. + ret = -EINVAL;
  12025. + break;
  12026. + }
  12027. +
  12028. + return ret;
  12029. +}
  12030. +
  12031. +static struct mwl_hif_ops pcie_hif_ops = {
  12032. + .driver_name = PCIE_DRV_NAME,
  12033. + .driver_version = PCIE_DRV_VERSION,
  12034. + .tx_head_room = PCIE_MIN_BYTES_HEADROOM,
  12035. + .ampdu_num = PCIE_AMPDU_QUEUES,
  12036. + .reset = pcie_reset,
  12037. + .init = pcie_init,
  12038. + .deinit = pcie_deinit,
  12039. + .get_info = pcie_get_info,
  12040. + .enable_data_tasks = pcie_enable_data_tasks,
  12041. + .disable_data_tasks = pcie_disable_data_tasks,
  12042. + .exec_cmd = pcie_exec_cmd,
  12043. + .get_irq_num = pcie_get_irq_num,
  12044. + .irq_handler = pcie_isr,
  12045. + .irq_enable = pcie_irq_enable,
  12046. + .irq_disable = pcie_irq_disable,
  12047. + .download_firmware = pcie_download_firmware,
  12048. + .timer_routine = pcie_timer_routine,
  12049. + .tx_xmit = pcie_tx_xmit,
  12050. + .tx_del_pkts_via_vif = pcie_tx_del_pkts_via_vif,
  12051. + .tx_del_pkts_via_sta = pcie_tx_del_pkts_via_sta,
  12052. + .tx_del_ampdu_pkts = pcie_tx_del_ampdu_pkts,
  12053. + .tx_del_sta_amsdu_pkts = pcie_tx_del_sta_amsdu_pkts,
  12054. + .tx_return_pkts = pcie_tx_return_pkts,
  12055. + .get_device_node = pcie_get_device_node,
  12056. + .get_survey = pcie_get_survey,
  12057. + .reg_access = pcie_reg_access,
  12058. +};
  12059. +
  12060. +static int pcie_init_ndp(struct ieee80211_hw *hw)
  12061. +{
  12062. + struct mwl_priv *priv = hw->priv;
  12063. + struct pcie_priv *pcie_priv = priv->hif.priv;
  12064. + const struct hostcmd_get_hw_spec *get_hw_spec;
  12065. + struct hostcmd_set_hw_spec set_hw_spec;
  12066. + int rc;
  12067. +
  12068. + spin_lock_init(&pcie_priv->int_mask_lock);
  12069. + tasklet_init(&pcie_priv->tx_task,
  12070. + (void *)pcie_tx_skbs_ndp, (unsigned long)hw);
  12071. + tasklet_disable(&pcie_priv->tx_task);
  12072. + spin_lock_init(&pcie_priv->tx_desc_lock);
  12073. + tasklet_init(&pcie_priv->rx_task,
  12074. + (void *)pcie_rx_recv_ndp, (unsigned long)hw);
  12075. + tasklet_disable(&pcie_priv->rx_task);
  12076. + pcie_priv->txq_limit = TX_QUEUE_LIMIT;
  12077. + pcie_priv->txq_wake_threshold = TX_WAKE_Q_THRESHOLD;
  12078. + pcie_priv->is_tx_schedule = false;
  12079. + pcie_priv->recv_limit = MAX_NUM_RX_DESC;
  12080. + pcie_priv->is_rx_schedule = false;
  12081. +
  12082. + rc = pcie_tx_init_ndp(hw);
  12083. + if (rc) {
  12084. + wiphy_err(hw->wiphy, "%s: fail to initialize TX\n",
  12085. + PCIE_DRV_NAME);
  12086. + goto err_mwl_tx_init;
  12087. + }
  12088. +
  12089. + rc = pcie_rx_init_ndp(hw);
  12090. + if (rc) {
  12091. + wiphy_err(hw->wiphy, "%s: fail to initialize RX\n",
  12092. + PCIE_DRV_NAME);
  12093. + goto err_mwl_rx_init;
  12094. + }
  12095. +
  12096. + /* get and prepare HW specifications */
  12097. + get_hw_spec = mwl_fwcmd_get_hw_specs(hw);
  12098. + if (!get_hw_spec) {
  12099. + wiphy_err(hw->wiphy, "%s: fail to get HW specifications\n",
  12100. + PCIE_DRV_NAME);
  12101. + goto err_get_hw_specs;
  12102. + }
  12103. + ether_addr_copy(&priv->hw_data.mac_addr[0],
  12104. + get_hw_spec->permanent_addr);
  12105. + priv->hw_data.fw_release_num = le32_to_cpu(get_hw_spec->fw_release_num);
  12106. + priv->hw_data.hw_version = get_hw_spec->version;
  12107. +
  12108. + /* prepare and set HW specifications */
  12109. + memset(&set_hw_spec, 0, sizeof(set_hw_spec));
  12110. + set_hw_spec.wcb_base[0] =
  12111. + cpu_to_le32(pcie_priv->desc_data_ndp.pphys_tx_ring);
  12112. + set_hw_spec.wcb_base[1] =
  12113. + cpu_to_le32(pcie_priv->desc_data_ndp.pphys_tx_ring_done);
  12114. + set_hw_spec.wcb_base[2] =
  12115. + cpu_to_le32(pcie_priv->desc_data_ndp.pphys_rx_ring);
  12116. + set_hw_spec.wcb_base[3] =
  12117. + cpu_to_le32(pcie_priv->desc_data_ndp.pphys_rx_ring_done);
  12118. + set_hw_spec.acnt_base_addr =
  12119. + cpu_to_le32(pcie_priv->desc_data_ndp.pphys_acnt_ring);
  12120. + set_hw_spec.acnt_buf_size =
  12121. + cpu_to_le32(pcie_priv->desc_data_ndp.acnt_ring_size);
  12122. + rc = mwl_fwcmd_set_hw_specs(hw, &set_hw_spec);
  12123. + if (rc) {
  12124. + wiphy_err(hw->wiphy, "%s: fail to set HW specifications\n",
  12125. + PCIE_DRV_NAME);
  12126. + goto err_set_hw_specs;
  12127. + }
  12128. +
  12129. + return rc;
  12130. +
  12131. +err_set_hw_specs:
  12132. +err_get_hw_specs:
  12133. +
  12134. + pcie_rx_deinit_ndp(hw);
  12135. +
  12136. +err_mwl_rx_init:
  12137. +
  12138. + pcie_tx_deinit_ndp(hw);
  12139. +
  12140. +err_mwl_tx_init:
  12141. +
  12142. + wiphy_err(hw->wiphy, "%s: init fail\n", PCIE_DRV_NAME);
  12143. +
  12144. + return rc;
  12145. +}
  12146. +
  12147. +static void pcie_deinit_ndp(struct ieee80211_hw *hw)
  12148. +{
  12149. + struct mwl_priv *priv = hw->priv;
  12150. + struct pcie_priv *pcie_priv = priv->hif.priv;
  12151. +
  12152. + pcie_rx_deinit_ndp(hw);
  12153. + pcie_tx_deinit_ndp(hw);
  12154. + tasklet_kill(&pcie_priv->rx_task);
  12155. + tasklet_kill(&pcie_priv->tx_task);
  12156. + pcie_reset(hw);
  12157. +}
  12158. +
  12159. +static int pcie_get_info_ndp(struct ieee80211_hw *hw, char *buf, size_t size)
  12160. +{
  12161. + struct mwl_priv *priv = hw->priv;
  12162. + struct pcie_priv *pcie_priv = priv->hif.priv;
  12163. + char *p = buf;
  12164. + int len = 0;
  12165. +
  12166. + len += scnprintf(p + len, size - len, "iobase0: %p\n",
  12167. + pcie_priv->iobase0);
  12168. + len += scnprintf(p + len, size - len, "iobase1: %p\n",
  12169. + pcie_priv->iobase1);
  12170. + len += scnprintf(p + len, size - len,
  12171. + "tx limit: %d\n", pcie_priv->txq_limit);
  12172. + len += scnprintf(p + len, size - len,
  12173. + "rx limit: %d\n", pcie_priv->recv_limit);
  12174. + return len;
  12175. +}
  12176. +
  12177. +static int pcie_get_tx_status_ndp(struct ieee80211_hw *hw, char *buf,
  12178. + size_t size)
  12179. +{
  12180. + struct mwl_priv *priv = hw->priv;
  12181. + struct pcie_priv *pcie_priv = priv->hif.priv;
  12182. + char *p = buf;
  12183. + int len = 0;
  12184. +
  12185. + len += scnprintf(p + len, size - len, "tx_done_cnt: %d\n",
  12186. + pcie_priv->tx_done_cnt);
  12187. + len += scnprintf(p + len, size - len, "tx_desc_busy_cnt: %d\n",
  12188. + pcie_priv->desc_data_ndp.tx_desc_busy_cnt);
  12189. + len += scnprintf(p + len, size - len, "tx_sent_head: %d\n",
  12190. + pcie_priv->desc_data_ndp.tx_sent_head);
  12191. + len += scnprintf(p + len, size - len, "tx_sent_tail: %d\n",
  12192. + pcie_priv->desc_data_ndp.tx_sent_tail);
  12193. + len += scnprintf(p + len, size - len, "tx_done_head: %d\n",
  12194. + readl(pcie_priv->iobase1 + MACREG_REG_TXDONEHEAD));
  12195. + len += scnprintf(p + len, size - len, "tx_done_tail: %d\n",
  12196. + pcie_priv->desc_data_ndp.tx_done_tail);
  12197. + len += scnprintf(p + len, size - len, "tx_vbuflist_idx: %d\n",
  12198. + pcie_priv->desc_data_ndp.tx_vbuflist_idx);
  12199. + return len;
  12200. +}
  12201. +
  12202. +static int pcie_get_rx_status_ndp(struct ieee80211_hw *hw, char *buf,
  12203. + size_t size)
  12204. +{
  12205. + struct mwl_priv *priv = hw->priv;
  12206. + struct pcie_priv *pcie_priv = priv->hif.priv;
  12207. + char *p = buf;
  12208. + int len = 0;
  12209. +
  12210. + len += scnprintf(p + len, size - len, "rx_done_head: %d\n",
  12211. + readl(pcie_priv->iobase1 + MACREG_REG_RXDONEHEAD));
  12212. + len += scnprintf(p + len, size - len, "rx_done_tail: %d\n",
  12213. + readl(pcie_priv->iobase1 + MACREG_REG_RXDONETAIL));
  12214. + len += scnprintf(p + len, size - len, "rx_desc_head: %d\n",
  12215. + readl(pcie_priv->iobase1 + MACREG_REG_RXDESCHEAD));
  12216. + len += scnprintf(p + len, size - len, "rx_skb_trace: %d\n",
  12217. + skb_queue_len(&pcie_priv->rx_skb_trace));
  12218. + len += scnprintf(p + len, size - len, "rx_skb_unlink_err: %d\n",
  12219. + pcie_priv->rx_skb_unlink_err);
  12220. + len += scnprintf(p + len, size - len, "signature_err: %d\n",
  12221. + pcie_priv->signature_err);
  12222. + len += scnprintf(p + len, size - len, "recheck_rxringdone: %d\n",
  12223. + pcie_priv->recheck_rxringdone);
  12224. + len += scnprintf(p + len, size - len, "fast_data_cnt: %d\n",
  12225. + pcie_priv->rx_cnts.fast_data_cnt);
  12226. + len += scnprintf(p + len, size - len, "fast_bad_amsdu_cnt: %d\n",
  12227. + pcie_priv->rx_cnts.fast_bad_amsdu_cnt);
  12228. + len += scnprintf(p + len, size - len, "slow_noqueue_cnt: %d\n",
  12229. + pcie_priv->rx_cnts.slow_noqueue_cnt);
  12230. + len += scnprintf(p + len, size - len, "slow_norun_cnt: %d\n",
  12231. + pcie_priv->rx_cnts.slow_norun_cnt);
  12232. + len += scnprintf(p + len, size - len, "slow_mcast_cnt: %d\n",
  12233. + pcie_priv->rx_cnts.slow_mcast_cnt);
  12234. + len += scnprintf(p + len, size - len, "slow_bad_sta_cnt: %d\n",
  12235. + pcie_priv->rx_cnts.slow_bad_sta_cnt);
  12236. + len += scnprintf(p + len, size - len, "slow_bad_mic_cnt: %d\n",
  12237. + pcie_priv->rx_cnts.slow_bad_mic_cnt);
  12238. + len += scnprintf(p + len, size - len, "slow_bad_pn_cnt: %d\n",
  12239. + pcie_priv->rx_cnts.slow_bad_pn_cnt);
  12240. + len += scnprintf(p + len, size - len, "slow_mgmt_cnt: %d\n",
  12241. + pcie_priv->rx_cnts.slow_mgmt_cnt);
  12242. + len += scnprintf(p + len, size - len, "slow_promisc_cnt: %d\n",
  12243. + pcie_priv->rx_cnts.slow_promisc_cnt);
  12244. + len += scnprintf(p + len, size - len, "drop_cnt: %d\n",
  12245. + pcie_priv->rx_cnts.drop_cnt);
  12246. + len += scnprintf(p + len, size - len, "offch_promisc_cnt: %d\n",
  12247. + pcie_priv->rx_cnts.offch_promisc_cnt);
  12248. + len += scnprintf(p + len, size - len, "mu_pkt_cnt: %d\n",
  12249. + pcie_priv->rx_cnts.mu_pkt_cnt);
  12250. + return len;
  12251. +}
  12252. +
  12253. +static void pcie_enable_data_tasks_ndp(struct ieee80211_hw *hw)
  12254. +{
  12255. + struct mwl_priv *priv = hw->priv;
  12256. + struct pcie_priv *pcie_priv = priv->hif.priv;
  12257. +
  12258. + tasklet_enable(&pcie_priv->tx_task);
  12259. + tasklet_enable(&pcie_priv->rx_task);
  12260. +}
  12261. +
  12262. +static void pcie_disable_data_tasks_ndp(struct ieee80211_hw *hw)
  12263. +{
  12264. + struct mwl_priv *priv = hw->priv;
  12265. + struct pcie_priv *pcie_priv = priv->hif.priv;
  12266. +
  12267. + tasklet_disable(&pcie_priv->tx_task);
  12268. + tasklet_disable(&pcie_priv->rx_task);
  12269. +}
  12270. +
  12271. +static irqreturn_t pcie_isr_ndp(struct ieee80211_hw *hw)
  12272. +{
  12273. + struct mwl_priv *priv = hw->priv;
  12274. + struct pcie_priv *pcie_priv = priv->hif.priv;
  12275. + u32 int_status;
  12276. +
  12277. + int_status = readl(pcie_priv->iobase1 + MACREG_REG_A2H_INTERRUPT_CAUSE);
  12278. +
  12279. + if (int_status == 0x00000000)
  12280. + return IRQ_NONE;
  12281. +
  12282. + if (int_status == 0xffffffff) {
  12283. + wiphy_warn(hw->wiphy, "card unplugged?\n");
  12284. + } else {
  12285. + writel(~int_status,
  12286. + pcie_priv->iobase1 + MACREG_REG_A2H_INTERRUPT_CAUSE);
  12287. +
  12288. + if (int_status & MACREG_A2HRIC_ACNT_HEAD_RDY)
  12289. + ieee80211_queue_work(hw, &priv->account_handle);
  12290. +
  12291. + if (int_status & MACREG_A2HRIC_RX_DONE_HEAD_RDY) {
  12292. + if (!pcie_priv->is_rx_schedule) {
  12293. + pcie_mask_int(pcie_priv,
  12294. + MACREG_A2HRIC_RX_DONE_HEAD_RDY,
  12295. + false);
  12296. + tasklet_schedule(&pcie_priv->rx_task);
  12297. + pcie_priv->is_rx_schedule = true;
  12298. + }
  12299. + }
  12300. +
  12301. + if (int_status & MACREG_A2HRIC_NEWDP_DFS) {
  12302. + wiphy_info(hw->wiphy, "radar detected by firmware\n");
  12303. + ieee80211_radar_detected(hw);
  12304. + }
  12305. +
  12306. + if (int_status & MACREG_A2HRIC_NEWDP_CHANNEL_SWITCH)
  12307. + ieee80211_queue_work(hw, &priv->chnl_switch_handle);
  12308. + }
  12309. +
  12310. + return IRQ_HANDLED;
  12311. +}
  12312. +
  12313. +static void pcie_irq_enable_ndp(struct ieee80211_hw *hw)
  12314. +{
  12315. + struct mwl_priv *priv = hw->priv;
  12316. + struct pcie_priv *pcie_priv = priv->hif.priv;
  12317. +
  12318. + if (pcie_chk_adapter(pcie_priv)) {
  12319. + writel(0x00,
  12320. + pcie_priv->iobase1 + MACREG_REG_A2H_INTERRUPT_MASK);
  12321. + writel(MACREG_A2HRIC_BIT_MASK_NDP,
  12322. + pcie_priv->iobase1 + MACREG_REG_A2H_INTERRUPT_MASK);
  12323. + }
  12324. +}
  12325. +
  12326. +static void pcie_timer_routine_ndp(struct ieee80211_hw *hw)
  12327. +{
  12328. + struct mwl_priv *priv = hw->priv;
  12329. + struct pcie_priv *pcie_priv = priv->hif.priv;
  12330. + int num = SYSADPT_TX_WMM_QUEUES;
  12331. + static int cnt;
  12332. +
  12333. + if (!pcie_priv->is_tx_schedule) {
  12334. + while (num--) {
  12335. + if (skb_queue_len(&pcie_priv->txq[num]) > 0) {
  12336. + tasklet_schedule(&pcie_priv->tx_task);
  12337. + pcie_priv->is_tx_schedule = true;
  12338. + break;
  12339. + }
  12340. + }
  12341. + }
  12342. +
  12343. + if ((++cnt * SYSADPT_TIMER_WAKEUP_TIME) >= CHECK_TX_DONE_TIME) {
  12344. + pcie_tx_done_ndp(hw);
  12345. + cnt = 0;
  12346. + }
  12347. +}
  12348. +
  12349. +static void pcie_tx_return_pkts_ndp(struct ieee80211_hw *hw)
  12350. +{
  12351. + pcie_tx_done_ndp(hw);
  12352. +}
  12353. +
  12354. +static void pcie_set_sta_id(struct ieee80211_hw *hw,
  12355. + struct ieee80211_sta *sta,
  12356. + bool sta_mode, bool set)
  12357. +{
  12358. + struct mwl_priv *priv = hw->priv;
  12359. + struct pcie_priv *pcie_priv = priv->hif.priv;
  12360. + struct mwl_sta *sta_info;
  12361. + u16 stnid;
  12362. +
  12363. + sta_info = mwl_dev_get_sta(sta);
  12364. + stnid = sta_mode ? 0 : sta_info->stnid;
  12365. + pcie_priv->sta_link[stnid] = set ? sta : NULL;
  12366. +}
  12367. +
  12368. +static void pcie_tx_account(struct mwl_priv *priv,
  12369. + struct mwl_sta *sta_info,
  12370. + struct acnt_tx_s *acnt_tx)
  12371. +{
  12372. + u32 rate_info, tx_cnt;
  12373. + u8 index, type, rate_ac, format, bw, gi, mcs, nss;
  12374. + u16 ratemask;
  12375. + u8 i, found;
  12376. + struct mwl_tx_hist *tx_hist;
  12377. + struct mwl_tx_hist_data *tx_hist_data;
  12378. +
  12379. + rate_info = le32_to_cpu(acnt_tx->tx_info.rate_info);
  12380. + tx_cnt = le32_to_cpu(acnt_tx->tx_cnt);
  12381. + index = acnt_tx->rate_tbl_index;
  12382. + type = acnt_tx->type;
  12383. +
  12384. + if (!rate_info)
  12385. + return;
  12386. + sta_info->tx_rate_info = rate_info;
  12387. +
  12388. + tx_hist = &sta_info->tx_hist;
  12389. + if (!tx_hist || (type >= SU_MU_TYPE_CNT))
  12390. + return;
  12391. +
  12392. + format = rate_info & MWL_TX_RATE_FORMAT_MASK;
  12393. + bw = (rate_info & MWL_TX_RATE_BANDWIDTH_MASK) >>
  12394. + MWL_TX_RATE_BANDWIDTH_SHIFT;
  12395. + gi = (rate_info & MWL_TX_RATE_SHORTGI_MASK) >>
  12396. + MWL_TX_RATE_SHORTGI_SHIFT;
  12397. + mcs = (rate_info & MWL_TX_RATE_RATEIDMCS_MASK) >>
  12398. + MWL_TX_RATE_RATEIDMCS_SHIFT;
  12399. +
  12400. + tx_hist->cur_rate_info[type] = rate_info;
  12401. +
  12402. + /* Rate table index is valid */
  12403. + if (index != 0xff) {
  12404. + if (type == MU_MIMO) {
  12405. + rate_ac = mcs & 0xf;
  12406. + nss = mcs >> 4;
  12407. + if (nss < (QS_NUM_SUPPORTED_11AC_NSS - 1)) {
  12408. + tx_hist_data =
  12409. + &tx_hist->mu_rate[nss][bw][gi][rate_ac];
  12410. + tx_hist_data->rateinfo = rate_info;
  12411. + tx_hist_data->cnt++;
  12412. + tx_hist->total_tx_cnt[type] += tx_cnt;
  12413. + }
  12414. + } else {
  12415. + /* If legacy, skip legacy preamble bit 15 */
  12416. + if (format == TX_RATE_FORMAT_LEGACY)
  12417. + ratemask = 0xfff;
  12418. + else
  12419. + ratemask = 0xffff;
  12420. + tx_hist_data = &tx_hist->su_rate[0];
  12421. + if ((tx_hist_data[index].rateinfo & ratemask) ==
  12422. + (rate_info & ratemask)) {
  12423. + tx_hist_data[index].cnt++;
  12424. + tx_hist->total_tx_cnt[type] += tx_cnt;
  12425. + }
  12426. + }
  12427. + } else {
  12428. + if (type == MU_MIMO) {
  12429. + rate_ac = mcs & 0xf;
  12430. + nss = mcs >> 4;
  12431. + if (nss < (QS_NUM_SUPPORTED_11AC_NSS - 1)) {
  12432. + tx_hist_data =
  12433. + &tx_hist->mu_rate[nss][bw][gi][rate_ac];
  12434. + tx_hist_data->rateinfo = rate_info;
  12435. + tx_hist_data->cnt++;
  12436. + tx_hist->total_tx_cnt[type] += tx_cnt;
  12437. + }
  12438. + } else {
  12439. + /* If legacy, skip legacy preamble bit 15 */
  12440. + if (format == TX_RATE_FORMAT_LEGACY)
  12441. + ratemask = 0xfff;
  12442. + else
  12443. + ratemask = 0xffff;
  12444. + tx_hist_data = &tx_hist->custom_rate[0];
  12445. + /* Go through non rate table buffer to see if any has
  12446. + * been used. If all used up, recycle by using index 0
  12447. + */
  12448. + for (i = 0; i < TX_RATE_HISTO_CUSTOM_CNT; i++) {
  12449. + if (!tx_hist_data[i].rateinfo ||
  12450. + ((tx_hist_data[i].rateinfo & ratemask) ==
  12451. + (rate_info & ratemask))) {
  12452. + found = 1;
  12453. + break;
  12454. + }
  12455. + }
  12456. + if (found)
  12457. + index = i;
  12458. + else
  12459. + index = 0; /* reuse index 0 buffer */
  12460. + tx_hist_data[index].rateinfo = rate_info;
  12461. + tx_hist_data[index].cnt++;
  12462. + tx_hist->total_tx_cnt[type] += tx_cnt;
  12463. + }
  12464. + }
  12465. +}
  12466. +
  12467. +static void pcie_rx_account(struct mwl_priv *priv,
  12468. + struct mwl_sta *sta_info,
  12469. + struct acnt_rx_s *acnt_rx)
  12470. +{
  12471. + u32 sig1, sig2, rate, param;
  12472. + u16 format, nss, bw, gi, rate_mcs;
  12473. +
  12474. + sig1 = (le32_to_cpu(acnt_rx->rx_info.ht_sig1) >>
  12475. + RXINFO_HT_SIG1_SHIFT) & RXINFO_HT_SIG1_MASK;
  12476. + sig2 = (le32_to_cpu(acnt_rx->rx_info.ht_sig2_rate) >>
  12477. + RXINFO_HT_SIG2_SHIFT) & RXINFO_HT_SIG2_MASK;
  12478. + rate = (le32_to_cpu(acnt_rx->rx_info.ht_sig2_rate) >>
  12479. + RXINFO_RATE_SHIFT) & RXINFO_RATE_MASK;
  12480. + param = (le32_to_cpu(acnt_rx->rx_info.param) >>
  12481. + RXINFO_PARAM_SHIFT) & RXINFO_PARAM_MASK;
  12482. +
  12483. + format = (param >> 3) & 0x7;
  12484. + nss = 0;
  12485. + bw = RX_RATE_INFO_HT20;
  12486. + switch (format) {
  12487. + case RX_RATE_INFO_FORMAT_11A:
  12488. + rate_mcs = rate & 0xF;
  12489. + if (rate_mcs == 10)
  12490. + rate_mcs = 7; /* 12 Mbps */
  12491. + else
  12492. + rate_mcs = utils_get_rate_id(rate_mcs);
  12493. + gi = RX_RATE_INFO_SHORT_INTERVAL;
  12494. + if ((rate_mcs == 5) || (rate_mcs == 7) || (rate_mcs == 9))
  12495. + return;
  12496. + break;
  12497. + case RX_RATE_INFO_FORMAT_11B:
  12498. + rate_mcs = utils_get_rate_id(rate & 0xF);
  12499. + gi = RX_RATE_INFO_LONG_INTERVAL;
  12500. + if ((rate_mcs == 0) || (rate_mcs == 1))
  12501. + return;
  12502. + break;
  12503. + case RX_RATE_INFO_FORMAT_11N:
  12504. + if ((sig1 & 0x3f) >= 16)
  12505. + return;
  12506. + bw = (sig1 >> 7) & 0x1;
  12507. + gi = (sig2 >> 7) & 0x1;
  12508. + rate_mcs = sig1 & 0x3F;
  12509. + if (rate_mcs > 76)
  12510. + return;
  12511. + break;
  12512. + case RX_RATE_INFO_FORMAT_11AC:
  12513. + if (((sig2 >> 4) & 0xf) >= 10)
  12514. + return;
  12515. + nss = (sig1 >> 10) & 0x3;
  12516. + if (!nss)
  12517. + return;
  12518. + bw = sig1 & 0x3;
  12519. + gi = sig2 & 0x1;
  12520. + rate_mcs = (sig2 >> 4) & 0xF;
  12521. + if (rate_mcs > 9)
  12522. + return;
  12523. + break;
  12524. + default:
  12525. + return;
  12526. + }
  12527. +
  12528. + sta_info->rx_format = format;
  12529. + sta_info->rx_nss = nss;
  12530. + sta_info->rx_bw = bw;
  12531. + sta_info->rx_gi = gi;
  12532. + sta_info->rx_rate_mcs = rate_mcs;
  12533. + sta_info->rx_signal = ((le32_to_cpu(acnt_rx->rx_info.rssi_x) >>
  12534. + RXINFO_RSSI_X_SHIFT) & RXINFO_RSSI_X_MASK);
  12535. +}
  12536. +
  12537. +static void pcie_tx_per(struct mwl_priv *priv, struct mwl_sta *sta_info,
  12538. + struct acnt_ra_s *acnt_ra)
  12539. +{
  12540. + u32 rate_info;
  12541. + u8 index, per, type, rate_ac, per_index, format, bw, gi, mcs, nss;
  12542. + u16 ratemask;
  12543. + u8 i, found;
  12544. + struct mwl_tx_hist *tx_hist;
  12545. + struct mwl_tx_hist_data *tx_hist_data;
  12546. +
  12547. + rate_info = le32_to_cpu(acnt_ra->rate_info);
  12548. + index = acnt_ra->rate_tbl_index;
  12549. + per = acnt_ra->per;
  12550. + type = acnt_ra->type;
  12551. +
  12552. + tx_hist = &sta_info->tx_hist;
  12553. +
  12554. + if (!tx_hist || !rate_info || (type >= SU_MU_TYPE_CNT))
  12555. + return;
  12556. +
  12557. + if ((type == SU_MIMO) && (index >= MAX_SUPPORTED_RATES) &&
  12558. + (index != 0xFF))
  12559. + return;
  12560. +
  12561. + if (per >= TX_HISTO_PER_THRES[3])
  12562. + per_index = 4;
  12563. + else if (per >= TX_HISTO_PER_THRES[2])
  12564. + per_index = 3;
  12565. + else if (per >= TX_HISTO_PER_THRES[1])
  12566. + per_index = 2;
  12567. + else if (per >= TX_HISTO_PER_THRES[0])
  12568. + per_index = 1;
  12569. + else
  12570. + per_index = 0;
  12571. +
  12572. + format = rate_info & MWL_TX_RATE_FORMAT_MASK;
  12573. + bw = (rate_info & MWL_TX_RATE_BANDWIDTH_MASK) >>
  12574. + MWL_TX_RATE_BANDWIDTH_SHIFT;
  12575. + gi = (rate_info & MWL_TX_RATE_SHORTGI_MASK) >>
  12576. + MWL_TX_RATE_SHORTGI_SHIFT;
  12577. + mcs = (rate_info & MWL_TX_RATE_RATEIDMCS_MASK) >>
  12578. + MWL_TX_RATE_RATEIDMCS_SHIFT;
  12579. +
  12580. + /* Rate table index is valid */
  12581. + if (index != 0xff) {
  12582. + if (type == MU_MIMO) {
  12583. + rate_ac = mcs & 0xf;
  12584. + nss = mcs >> 4;
  12585. + if (nss < (QS_NUM_SUPPORTED_11AC_NSS - 1)) {
  12586. + tx_hist_data =
  12587. + &tx_hist->mu_rate[nss][bw][gi][rate_ac];
  12588. + tx_hist_data->rateinfo = rate_info;
  12589. + tx_hist_data->per[per_index]++;
  12590. + }
  12591. + } else {
  12592. + /* If legacy, skip legacy preamble bit 15 */
  12593. + if (format == TX_RATE_FORMAT_LEGACY)
  12594. + ratemask = 0xfff;
  12595. + else
  12596. + ratemask = 0xffff;
  12597. + tx_hist_data = &tx_hist->su_rate[0];
  12598. + if ((tx_hist_data[index].rateinfo & ratemask) ==
  12599. + (rate_info & ratemask))
  12600. + tx_hist_data[index].per[per_index]++;
  12601. + }
  12602. + } else {
  12603. + if (type == MU_MIMO) {
  12604. + rate_ac = mcs & 0xf;
  12605. + nss = mcs >> 4;
  12606. + if (nss < (QS_NUM_SUPPORTED_11AC_NSS - 1)) {
  12607. + tx_hist_data =
  12608. + &tx_hist->mu_rate[nss][bw][gi][rate_ac];
  12609. + tx_hist_data->rateinfo = rate_info;
  12610. + tx_hist_data->per[per_index]++;
  12611. + }
  12612. + } else {
  12613. + /* If legacy, skip legacy preamble bit 15 */
  12614. + if (format == TX_RATE_FORMAT_LEGACY)
  12615. + ratemask = 0xfff;
  12616. + else
  12617. + ratemask = 0xffff;
  12618. + tx_hist_data = &tx_hist->custom_rate[0];
  12619. + /* Go through non rate table buffer to see if any has
  12620. + * been used. If all used up, recycle by using index 0
  12621. + */
  12622. + for (i = 0; i < TX_RATE_HISTO_CUSTOM_CNT; i++) {
  12623. + if (!tx_hist_data[i].rateinfo ||
  12624. + ((tx_hist_data[i].rateinfo & ratemask) ==
  12625. + (rate_info & ratemask))) {
  12626. + found = 1;
  12627. + break;
  12628. + }
  12629. + }
  12630. + if (found)
  12631. + index = i;
  12632. + else
  12633. + index = 0; /* reuse index 0 buffer */
  12634. + tx_hist_data[index].rateinfo = rate_info;
  12635. + tx_hist_data[index].per[per_index]++;
  12636. + }
  12637. + }
  12638. +}
  12639. +
  12640. +static void pcie_ba_account(struct mwl_priv *priv,
  12641. + struct mwl_sta *sta_info,
  12642. + struct acnt_ba_s *acnt_ba)
  12643. +{
  12644. + struct mwl_tx_ba_hist *ba_hist = &sta_info->ba_hist;
  12645. +
  12646. + if (sta_info->stnid != le16_to_cpu(acnt_ba->stnid))
  12647. + return;
  12648. +
  12649. + if (ba_hist->enable && ba_hist->ba_stats &&
  12650. + (ba_hist->index < ACNT_BA_SIZE)) {
  12651. + ba_hist->type = acnt_ba->type;
  12652. + ba_hist->ba_stats[ba_hist->index].ba_hole = acnt_ba->ba_hole;
  12653. + ba_hist->ba_stats[ba_hist->index].ba_expected =
  12654. + acnt_ba->ba_expected;
  12655. + ba_hist->ba_stats[ba_hist->index].no_ba = acnt_ba->no_ba;
  12656. + ba_hist->index++;
  12657. + if (ba_hist->index == ACNT_BA_SIZE)
  12658. + wiphy_info(priv->hw->wiphy,
  12659. + "Aid:%d BA histo collection done\n",
  12660. + priv->ba_aid);
  12661. + }
  12662. +}
  12663. +
  12664. +static void pcie_bf_mimo_ctrl_decode(struct mwl_priv *priv,
  12665. + struct acnt_bf_mimo_ctrl_s *bf_mimo_ctrl)
  12666. +{
  12667. + struct file *fp_data = NULL;
  12668. + const char filename[] = "/tmp/BF_MIMO_Ctrl_Field_Output.txt";
  12669. + char str_buf[256];
  12670. + char *buf = &str_buf[0];
  12671. + mm_segment_t oldfs;
  12672. +
  12673. + oldfs = get_fs();
  12674. + set_fs(KERNEL_DS);
  12675. +
  12676. + buf += sprintf(buf, "\nMAC: %pM\n", bf_mimo_ctrl->rec_mac);
  12677. + buf += sprintf(buf, "SU_0_MU_1: %d\n", bf_mimo_ctrl->type);
  12678. + buf += sprintf(buf, "MIMO_Ctrl_Field: 0x%x\n",
  12679. + le32_to_cpu(bf_mimo_ctrl->mimo_ctrl));
  12680. + buf += sprintf(buf, "Comp_BF_Report_First_8Bytes: 0x%llx\n",
  12681. + le64_to_cpu(bf_mimo_ctrl->comp_bf_rep));
  12682. +
  12683. + fp_data = filp_open(filename, O_RDWR | O_CREAT | O_TRUNC, 0);
  12684. +
  12685. + if (!IS_ERR(fp_data)) {
  12686. + __kernel_write(fp_data, str_buf, strlen(str_buf),
  12687. + &fp_data->f_pos);
  12688. + filp_close(fp_data, current->files);
  12689. + } else {
  12690. + wiphy_err(priv->hw->wiphy, "Error opening %s! %x\n",
  12691. + filename, (unsigned int)fp_data);
  12692. + }
  12693. +
  12694. + set_fs(oldfs);
  12695. +}
  12696. +
  12697. +static void pcie_process_account(struct ieee80211_hw *hw)
  12698. +{
  12699. + struct mwl_priv *priv = hw->priv;
  12700. + struct pcie_priv *pcie_priv = priv->hif.priv;
  12701. + struct pcie_desc_data_ndp *desc = &pcie_priv->desc_data_ndp;
  12702. + u32 acnt_head, acnt_tail;
  12703. + u32 read_size;
  12704. + u8 *acnt_recds;
  12705. + u8 *pstart, *pend;
  12706. + struct acnt_s *acnt;
  12707. + struct acnt_tx_s *acnt_tx;
  12708. + struct acnt_rx_s *acnt_rx;
  12709. + struct acnt_ra_s *acnt_ra;
  12710. + struct acnt_ba_s *acnt_ba;
  12711. + struct acnt_bf_mimo_ctrl_s *acnt_bf_mimo_ctrl;
  12712. + struct pcie_dma_data *dma_data;
  12713. + struct mwl_sta *sta_info;
  12714. + u16 nf_a, nf_b, nf_c, nf_d;
  12715. + u16 stnid;
  12716. + u8 type;
  12717. +
  12718. + acnt_head = readl(pcie_priv->iobase1 + MACREG_REG_ACNTHEAD);
  12719. + acnt_tail = readl(pcie_priv->iobase1 + MACREG_REG_ACNTTAIL);
  12720. +
  12721. + if (acnt_tail == acnt_head)
  12722. + return;
  12723. +
  12724. + if (acnt_tail > acnt_head) {
  12725. + read_size = desc->acnt_ring_size - acnt_tail + acnt_head;
  12726. + if (read_size > desc->acnt_ring_size) {
  12727. + wiphy_err(hw->wiphy,
  12728. + "account size overflow (%d %d %d)\n",
  12729. + acnt_head, acnt_tail, read_size);
  12730. + goto process_next;
  12731. + }
  12732. + memset(desc->pacnt_buf, 0, desc->acnt_ring_size);
  12733. + memcpy(desc->pacnt_buf, desc->pacnt_ring + acnt_tail,
  12734. + desc->acnt_ring_size - acnt_tail);
  12735. + memcpy(desc->pacnt_buf + desc->acnt_ring_size - acnt_tail,
  12736. + desc->pacnt_ring, acnt_head);
  12737. + acnt_recds = desc->pacnt_buf;
  12738. + } else {
  12739. + read_size = acnt_head - acnt_tail;
  12740. + if (read_size > desc->acnt_ring_size) {
  12741. + wiphy_err(hw->wiphy,
  12742. + "account size overflow (%d %d %d)\n",
  12743. + acnt_head, acnt_tail, read_size);
  12744. + goto process_next;
  12745. + }
  12746. + acnt_recds = desc->pacnt_ring + acnt_tail;
  12747. + }
  12748. +
  12749. + pstart = acnt_recds;
  12750. + pend = pstart + read_size;
  12751. + while (pstart < pend) {
  12752. + acnt = (struct acnt_s *)pstart;
  12753. +
  12754. + switch (le16_to_cpu(acnt->code)) {
  12755. + case ACNT_CODE_BUSY:
  12756. + pcie_priv->acnt_busy++;
  12757. + break;
  12758. + case ACNT_CODE_WRAP:
  12759. + pcie_priv->acnt_wrap++;
  12760. + break;
  12761. + case ACNT_CODE_DROP:
  12762. + pcie_priv->acnt_drop++;
  12763. + break;
  12764. + case ACNT_CODE_TX_ENQUEUE:
  12765. + acnt_tx = (struct acnt_tx_s *)pstart;
  12766. + sta_info = utils_find_sta(priv, acnt_tx->hdr.wh.addr1);
  12767. + if (sta_info) {
  12768. + spin_lock_bh(&priv->sta_lock);
  12769. + pcie_tx_account(priv, sta_info, acnt_tx);
  12770. + spin_unlock_bh(&priv->sta_lock);
  12771. + }
  12772. + break;
  12773. + case ACNT_CODE_RX_PPDU:
  12774. + acnt_rx = (struct acnt_rx_s *)pstart;
  12775. + nf_a = (le32_to_cpu(acnt_rx->rx_info.nf_a_b) >>
  12776. + RXINFO_NF_A_SHIFT) & RXINFO_NF_A_MASK;
  12777. + nf_b = (le32_to_cpu(acnt_rx->rx_info.nf_a_b) >>
  12778. + RXINFO_NF_B_SHIFT) & RXINFO_NF_B_MASK;
  12779. + nf_c = (le32_to_cpu(acnt_rx->rx_info.nf_c_d) >>
  12780. + RXINFO_NF_C_SHIFT) & RXINFO_NF_C_MASK;
  12781. + nf_d = (le32_to_cpu(acnt_rx->rx_info.nf_c_d) >>
  12782. + RXINFO_NF_D_SHIFT) & RXINFO_NF_D_MASK;
  12783. + if ((nf_a >= 2048) && (nf_b >= 2048) &&
  12784. + (nf_c >= 2048) && (nf_d >= 2048)) {
  12785. + nf_a = ((4096 - nf_a) >> 4);
  12786. + nf_b = ((4096 - nf_b) >> 4);
  12787. + nf_c = ((4096 - nf_c) >> 4);
  12788. + nf_d = ((4096 - nf_d) >> 4);
  12789. + priv->noise =
  12790. + -((nf_a + nf_b + nf_c + nf_d) / 4);
  12791. + }
  12792. + dma_data = (struct pcie_dma_data *)
  12793. + &acnt_rx->rx_info.hdr[0];
  12794. + sta_info = utils_find_sta(priv, dma_data->wh.addr2);
  12795. + if (sta_info) {
  12796. + spin_lock_bh(&priv->sta_lock);
  12797. + pcie_rx_account(priv, sta_info, acnt_rx);
  12798. + spin_unlock_bh(&priv->sta_lock);
  12799. + }
  12800. + break;
  12801. + case ACNT_CODE_RA_STATS:
  12802. + acnt_ra = (struct acnt_ra_s *)pstart;
  12803. + stnid = le16_to_cpu(acnt_ra->stn_id);
  12804. + if ((stnid > 0) && (stnid <= priv->stnid_num)) {
  12805. + type = acnt_ra->type;
  12806. + if (type < 2) {
  12807. + if (acnt_ra->tx_attempt_cnt >= 250)
  12808. + priv->ra_tx_attempt[type][5]++;
  12809. + else if (acnt_ra->tx_attempt_cnt >= 100)
  12810. + priv->ra_tx_attempt[type][4]++;
  12811. + else if (acnt_ra->tx_attempt_cnt >= 50)
  12812. + priv->ra_tx_attempt[type][3]++;
  12813. + else if (acnt_ra->tx_attempt_cnt >= 15)
  12814. + priv->ra_tx_attempt[type][2]++;
  12815. + else if (acnt_ra->tx_attempt_cnt >= 4)
  12816. + priv->ra_tx_attempt[type][1]++;
  12817. + else
  12818. + priv->ra_tx_attempt[type][0]++;
  12819. + }
  12820. + sta_info = utils_find_sta_by_id(priv, stnid);
  12821. + if (sta_info) {
  12822. + spin_lock_bh(&priv->sta_lock);
  12823. + pcie_tx_per(priv, sta_info, acnt_ra);
  12824. + spin_unlock_bh(&priv->sta_lock);
  12825. + }
  12826. + }
  12827. + break;
  12828. + case ACNT_CODE_BA_STATS:
  12829. + acnt_ba = (struct acnt_ba_s *)pstart;
  12830. + if (priv->ba_aid) {
  12831. + sta_info = utils_find_sta_by_aid(priv,
  12832. + priv->ba_aid);
  12833. + if (sta_info) {
  12834. + spin_lock_bh(&priv->sta_lock);
  12835. + pcie_ba_account(priv, sta_info,
  12836. + acnt_ba);
  12837. + spin_unlock_bh(&priv->sta_lock);
  12838. + }
  12839. + }
  12840. + break;
  12841. + case ACNT_CODE_BF_MIMO_CTRL:
  12842. + acnt_bf_mimo_ctrl =
  12843. + (struct acnt_bf_mimo_ctrl_s *)pstart;
  12844. + pcie_bf_mimo_ctrl_decode(priv, acnt_bf_mimo_ctrl);
  12845. + break;
  12846. + default:
  12847. + break;
  12848. + }
  12849. +
  12850. + if (acnt->len)
  12851. + pstart += acnt->len * 4;
  12852. + else
  12853. + goto process_next;
  12854. + }
  12855. +process_next:
  12856. + acnt_tail = acnt_head;
  12857. + writel(acnt_tail, pcie_priv->iobase1 + MACREG_REG_ACNTTAIL);
  12858. +}
  12859. +
  12860. +static int pcie_mcast_cts(struct ieee80211_hw *hw, bool enable)
  12861. +{
  12862. + return mwl_fwcmd_mcast_cts(hw, enable ? 1 : 0);
  12863. +}
  12864. +
  12865. +static const struct mwl_hif_ops pcie_hif_ops_ndp = {
  12866. + .driver_name = PCIE_DRV_NAME,
  12867. + .driver_version = PCIE_DRV_VERSION,
  12868. + .tx_head_room = PCIE_MIN_BYTES_HEADROOM,
  12869. + .ampdu_num = AMPDU_QUEUES_NDP,
  12870. + .reset = pcie_reset,
  12871. + .init = pcie_init_ndp,
  12872. + .deinit = pcie_deinit_ndp,
  12873. + .get_info = pcie_get_info_ndp,
  12874. + .get_tx_status = pcie_get_tx_status_ndp,
  12875. + .get_rx_status = pcie_get_rx_status_ndp,
  12876. + .enable_data_tasks = pcie_enable_data_tasks_ndp,
  12877. + .disable_data_tasks = pcie_disable_data_tasks_ndp,
  12878. + .exec_cmd = pcie_exec_cmd,
  12879. + .get_irq_num = pcie_get_irq_num,
  12880. + .irq_handler = pcie_isr_ndp,
  12881. + .irq_enable = pcie_irq_enable_ndp,
  12882. + .irq_disable = pcie_irq_disable,
  12883. + .download_firmware = pcie_download_firmware,
  12884. + .timer_routine = pcie_timer_routine_ndp,
  12885. + .tx_xmit = pcie_tx_xmit_ndp,
  12886. + .tx_return_pkts = pcie_tx_return_pkts_ndp,
  12887. + .get_device_node = pcie_get_device_node,
  12888. + .get_survey = pcie_get_survey,
  12889. + .reg_access = pcie_reg_access,
  12890. + .set_sta_id = pcie_set_sta_id,
  12891. + .process_account = pcie_process_account,
  12892. + .mcast_cts = pcie_mcast_cts,
  12893. +};
  12894. +
  12895. +static int pcie_probe(struct pci_dev *pdev, const struct pci_device_id *id)
  12896. +{
  12897. + static bool printed_version;
  12898. + struct ieee80211_hw *hw;
  12899. + struct mwl_priv *priv;
  12900. + struct pcie_priv *pcie_priv;
  12901. + const struct mwl_hif_ops *hif_ops;
  12902. + int rc = 0;
  12903. +
  12904. + if (id->driver_data >= MWLUNKNOWN)
  12905. + return -ENODEV;
  12906. +
  12907. + if (!printed_version) {
  12908. + pr_info("<<%s version %s>>\n",
  12909. + PCIE_DRV_DESC, PCIE_DRV_VERSION);
  12910. + printed_version = true;
  12911. + }
  12912. +
  12913. + rc = pci_enable_device(pdev);
  12914. + if (rc) {
  12915. + pr_err("%s: cannot enable new PCI device\n",
  12916. + PCIE_DRV_NAME);
  12917. + return rc;
  12918. + }
  12919. +
  12920. + rc = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
  12921. + if (rc) {
  12922. + pr_err("%s: 32-bit PCI DMA not supported\n",
  12923. + PCIE_DRV_NAME);
  12924. + goto err_pci_disable_device;
  12925. + }
  12926. +
  12927. + pci_set_master(pdev);
  12928. +
  12929. + if (id->driver_data == MWL8964)
  12930. + hif_ops = &pcie_hif_ops_ndp;
  12931. + else
  12932. + hif_ops = &pcie_hif_ops;
  12933. + hw = mwl_alloc_hw(MWL_BUS_PCIE, id->driver_data, &pdev->dev,
  12934. + hif_ops, sizeof(*pcie_priv));
  12935. + if (!hw) {
  12936. + pr_err("%s: mwlwifi hw alloc failed\n",
  12937. + PCIE_DRV_NAME);
  12938. + rc = -ENOMEM;
  12939. + goto err_pci_disable_device;
  12940. + }
  12941. +
  12942. + pci_set_drvdata(pdev, hw);
  12943. +
  12944. + priv = hw->priv;
  12945. + priv->antenna_tx = pcie_chip_tbl[priv->chip_type].antenna_tx;
  12946. + priv->antenna_rx = pcie_chip_tbl[priv->chip_type].antenna_rx;
  12947. + pcie_priv = priv->hif.priv;
  12948. + pcie_priv->mwl_priv = priv;
  12949. + pcie_priv->pdev = pdev;
  12950. + if (id->driver_data != MWL8964) {
  12951. + pcie_priv->tx_head_room = PCIE_MIN_BYTES_HEADROOM;
  12952. + if (id->driver_data == MWL8997) {
  12953. + if (NET_SKB_PAD < PCIE_MIN_TX_HEADROOM_KF2) {
  12954. + pcie_priv->tx_head_room =
  12955. + PCIE_MIN_TX_HEADROOM_KF2;
  12956. + pcie_hif_ops.tx_head_room =
  12957. + PCIE_MIN_TX_HEADROOM_KF2;
  12958. + }
  12959. + }
  12960. + }
  12961. +
  12962. + rc = pcie_alloc_resource(pcie_priv);
  12963. + if (rc)
  12964. + goto err_alloc_pci_resource;
  12965. +
  12966. + rc = mwl_init_hw(hw, pcie_chip_tbl[priv->chip_type].fw_image,
  12967. + pcie_chip_tbl[priv->chip_type].cal_file,
  12968. + pcie_chip_tbl[priv->chip_type].txpwrlmt_file);
  12969. + if (rc)
  12970. + goto err_wl_init;
  12971. +
  12972. + vendor_cmd_basic_event(hw->wiphy, MWL_VENDOR_EVENT_DRIVER_READY);
  12973. +
  12974. + return rc;
  12975. +
  12976. +err_wl_init:
  12977. +
  12978. + pcie_reset(hw);
  12979. +
  12980. +err_alloc_pci_resource:
  12981. +
  12982. + pci_set_drvdata(pdev, NULL);
  12983. + mwl_free_hw(hw);
  12984. +
  12985. +err_pci_disable_device:
  12986. +
  12987. + pci_disable_device(pdev);
  12988. +
  12989. + return rc;
  12990. +}
  12991. +
  12992. +static void pcie_remove(struct pci_dev *pdev)
  12993. +{
  12994. + struct ieee80211_hw *hw = pci_get_drvdata(pdev);
  12995. + struct mwl_priv *priv = hw->priv;
  12996. +
  12997. + priv->rmmod = true;
  12998. + while (priv->in_send_cmd)
  12999. + usleep_range(1000, 2000);
  13000. + vendor_cmd_basic_event(hw->wiphy, MWL_VENDOR_EVENT_DRIVER_START_REMOVE);
  13001. + mwl_deinit_hw(hw);
  13002. + pci_set_drvdata(pdev, NULL);
  13003. + mwl_free_hw(hw);
  13004. + pci_disable_device(pdev);
  13005. +}
  13006. +
  13007. +static struct pci_driver mwl_pcie_driver = {
  13008. + .name = PCIE_DRV_NAME,
  13009. + .id_table = pcie_id_tbl,
  13010. + .probe = pcie_probe,
  13011. + .remove = pcie_remove
  13012. +};
  13013. +
  13014. +module_pci_driver(mwl_pcie_driver);
  13015. +
  13016. +MODULE_DESCRIPTION(PCIE_DRV_DESC);
  13017. +MODULE_VERSION(PCIE_DRV_VERSION);
  13018. +MODULE_AUTHOR("Marvell Semiconductor, Inc.");
  13019. +MODULE_LICENSE("GPL v2");
  13020. +MODULE_SUPPORTED_DEVICE(PCIE_DEV_NAME);
  13021. +MODULE_DEVICE_TABLE(pci, pcie_id_tbl);
  13022. diff --git a/drivers/net/wireless/marvell/mwlwifi/hif/pcie/rx.c b/drivers/net/wireless/marvell/mwlwifi/hif/pcie/rx.c
  13023. new file mode 100644
  13024. index 000000000000..25076c6d66df
  13025. --- /dev/null
  13026. +++ b/drivers/net/wireless/marvell/mwlwifi/hif/pcie/rx.c
  13027. @@ -0,0 +1,540 @@
  13028. +/*
  13029. + * Copyright (C) 2006-2018, Marvell International Ltd.
  13030. + *
  13031. + * This software file (the "File") is distributed by Marvell International
  13032. + * Ltd. under the terms of the GNU General Public License Version 2, June 1991
  13033. + * (the "License"). You may use, redistribute and/or modify this File in
  13034. + * accordance with the terms and conditions of the License, a copy of which
  13035. + * is available by writing to the Free Software Foundation, Inc.
  13036. + *
  13037. + * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
  13038. + * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
  13039. + * ARE EXPRESSLY DISCLAIMED. The License provides additional details about
  13040. + * this warranty disclaimer.
  13041. + */
  13042. +
  13043. +/* Description: This file implements receive related functions. */
  13044. +
  13045. +#include <linux/etherdevice.h>
  13046. +#include <linux/skbuff.h>
  13047. +
  13048. +#include "sysadpt.h"
  13049. +#include "core.h"
  13050. +#include "utils.h"
  13051. +#include "hif/pcie/dev.h"
  13052. +#include "hif/pcie/rx.h"
  13053. +
  13054. +#define MAX_NUM_RX_RING_BYTES (PCIE_MAX_NUM_RX_DESC * \
  13055. + sizeof(struct pcie_rx_desc))
  13056. +
  13057. +#define MAX_NUM_RX_HNDL_BYTES (PCIE_MAX_NUM_RX_DESC * \
  13058. + sizeof(struct pcie_rx_hndl))
  13059. +
  13060. +#define DECRYPT_ERR_MASK 0x80
  13061. +#define GENERAL_DECRYPT_ERR 0xFF
  13062. +#define TKIP_DECRYPT_MIC_ERR 0x02
  13063. +#define WEP_DECRYPT_ICV_ERR 0x04
  13064. +#define TKIP_DECRYPT_ICV_ERR 0x08
  13065. +
  13066. +#define W836X_RSSI_OFFSET 8
  13067. +
  13068. +static int pcie_rx_ring_alloc(struct mwl_priv *priv)
  13069. +{
  13070. + struct pcie_priv *pcie_priv = priv->hif.priv;
  13071. + struct pcie_desc_data *desc;
  13072. +
  13073. + desc = &pcie_priv->desc_data[0];
  13074. +
  13075. + desc->prx_ring = (struct pcie_rx_desc *)
  13076. + dma_alloc_coherent(priv->dev,
  13077. + MAX_NUM_RX_RING_BYTES,
  13078. + &desc->pphys_rx_ring,
  13079. + GFP_KERNEL);
  13080. +
  13081. + if (!desc->prx_ring) {
  13082. + wiphy_err(priv->hw->wiphy, "cannot alloc mem\n");
  13083. + return -ENOMEM;
  13084. + }
  13085. +
  13086. + memset(desc->prx_ring, 0x00, MAX_NUM_RX_RING_BYTES);
  13087. +
  13088. + desc->rx_hndl = kzalloc(MAX_NUM_RX_HNDL_BYTES, GFP_KERNEL);
  13089. +
  13090. + if (!desc->rx_hndl) {
  13091. + dma_free_coherent(priv->dev,
  13092. + MAX_NUM_RX_RING_BYTES,
  13093. + desc->prx_ring,
  13094. + desc->pphys_rx_ring);
  13095. + return -ENOMEM;
  13096. + }
  13097. +
  13098. + return 0;
  13099. +}
  13100. +
  13101. +static int pcie_rx_ring_init(struct mwl_priv *priv)
  13102. +{
  13103. + struct pcie_priv *pcie_priv = priv->hif.priv;
  13104. + struct pcie_desc_data *desc;
  13105. + int i;
  13106. + struct pcie_rx_hndl *rx_hndl;
  13107. + dma_addr_t dma;
  13108. + u32 val;
  13109. +
  13110. + desc = &pcie_priv->desc_data[0];
  13111. +
  13112. + if (desc->prx_ring) {
  13113. + desc->rx_buf_size = SYSADPT_MAX_AGGR_SIZE;
  13114. +
  13115. + for (i = 0; i < PCIE_MAX_NUM_RX_DESC; i++) {
  13116. + rx_hndl = &desc->rx_hndl[i];
  13117. + rx_hndl->psk_buff =
  13118. + dev_alloc_skb(desc->rx_buf_size);
  13119. +
  13120. + if (!rx_hndl->psk_buff) {
  13121. + wiphy_err(priv->hw->wiphy,
  13122. + "rxdesc %i: no skbuff available\n",
  13123. + i);
  13124. + return -ENOMEM;
  13125. + }
  13126. +
  13127. + skb_reserve(rx_hndl->psk_buff,
  13128. + PCIE_MIN_BYTES_HEADROOM);
  13129. + desc->prx_ring[i].rx_control =
  13130. + EAGLE_RXD_CTRL_DRIVER_OWN;
  13131. + desc->prx_ring[i].status = EAGLE_RXD_STATUS_OK;
  13132. + desc->prx_ring[i].qos_ctrl = 0x0000;
  13133. + desc->prx_ring[i].channel = 0x00;
  13134. + desc->prx_ring[i].rssi = 0x00;
  13135. + desc->prx_ring[i].pkt_len =
  13136. + cpu_to_le16(SYSADPT_MAX_AGGR_SIZE);
  13137. + dma = pci_map_single(pcie_priv->pdev,
  13138. + rx_hndl->psk_buff->data,
  13139. + desc->rx_buf_size,
  13140. + PCI_DMA_FROMDEVICE);
  13141. + if (pci_dma_mapping_error(pcie_priv->pdev, dma)) {
  13142. + wiphy_err(priv->hw->wiphy,
  13143. + "failed to map pci memory!\n");
  13144. + return -ENOMEM;
  13145. + }
  13146. + desc->prx_ring[i].pphys_buff_data = cpu_to_le32(dma);
  13147. + val = (u32)desc->pphys_rx_ring +
  13148. + ((i + 1) * sizeof(struct pcie_rx_desc));
  13149. + desc->prx_ring[i].pphys_next = cpu_to_le32(val);
  13150. + rx_hndl->pdesc = &desc->prx_ring[i];
  13151. + if (i < (PCIE_MAX_NUM_RX_DESC - 1))
  13152. + rx_hndl->pnext = &desc->rx_hndl[i + 1];
  13153. + }
  13154. + desc->prx_ring[PCIE_MAX_NUM_RX_DESC - 1].pphys_next =
  13155. + cpu_to_le32((u32)desc->pphys_rx_ring);
  13156. + desc->rx_hndl[PCIE_MAX_NUM_RX_DESC - 1].pnext =
  13157. + &desc->rx_hndl[0];
  13158. + desc->pnext_rx_hndl = &desc->rx_hndl[0];
  13159. +
  13160. + return 0;
  13161. + }
  13162. +
  13163. + wiphy_err(priv->hw->wiphy, "no valid RX mem\n");
  13164. +
  13165. + return -ENOMEM;
  13166. +}
  13167. +
  13168. +static void pcie_rx_ring_cleanup(struct mwl_priv *priv)
  13169. +{
  13170. + struct pcie_priv *pcie_priv = priv->hif.priv;
  13171. + struct pcie_desc_data *desc;
  13172. + int i;
  13173. + struct pcie_rx_hndl *rx_hndl;
  13174. +
  13175. + desc = &pcie_priv->desc_data[0];
  13176. +
  13177. + if (desc->prx_ring) {
  13178. + for (i = 0; i < PCIE_MAX_NUM_RX_DESC; i++) {
  13179. + rx_hndl = &desc->rx_hndl[i];
  13180. + if (!rx_hndl->psk_buff)
  13181. + continue;
  13182. +
  13183. + pci_unmap_single(pcie_priv->pdev,
  13184. + le32_to_cpu
  13185. + (rx_hndl->pdesc->pphys_buff_data),
  13186. + desc->rx_buf_size,
  13187. + PCI_DMA_FROMDEVICE);
  13188. +
  13189. + dev_kfree_skb_any(rx_hndl->psk_buff);
  13190. +
  13191. + wiphy_debug(priv->hw->wiphy,
  13192. + "unmapped+free'd %i 0x%p 0x%x %i\n",
  13193. + i, rx_hndl->psk_buff->data,
  13194. + le32_to_cpu(
  13195. + rx_hndl->pdesc->pphys_buff_data),
  13196. + desc->rx_buf_size);
  13197. +
  13198. + rx_hndl->psk_buff = NULL;
  13199. + }
  13200. + }
  13201. +}
  13202. +
  13203. +static void pcie_rx_ring_free(struct mwl_priv *priv)
  13204. +{
  13205. + struct pcie_priv *pcie_priv = priv->hif.priv;
  13206. + struct pcie_desc_data *desc;
  13207. +
  13208. + desc = &pcie_priv->desc_data[0];
  13209. +
  13210. + if (desc->prx_ring) {
  13211. + pcie_rx_ring_cleanup(priv);
  13212. +
  13213. + dma_free_coherent(priv->dev,
  13214. + MAX_NUM_RX_RING_BYTES,
  13215. + desc->prx_ring,
  13216. + desc->pphys_rx_ring);
  13217. +
  13218. + desc->prx_ring = NULL;
  13219. + }
  13220. +
  13221. + kfree(desc->rx_hndl);
  13222. +
  13223. + desc->pnext_rx_hndl = NULL;
  13224. +}
  13225. +
  13226. +static inline void pcie_rx_status(struct mwl_priv *priv,
  13227. + struct pcie_rx_desc *pdesc,
  13228. + struct ieee80211_rx_status *status)
  13229. +{
  13230. + u16 rx_rate;
  13231. +
  13232. + memset(status, 0, sizeof(*status));
  13233. +
  13234. + if (priv->chip_type == MWL8997)
  13235. + status->signal = (s8)pdesc->rssi;
  13236. + else
  13237. + status->signal = -(pdesc->rssi + W836X_RSSI_OFFSET);
  13238. +
  13239. + rx_rate = le16_to_cpu(pdesc->rate);
  13240. + pcie_rx_prepare_status(priv,
  13241. + rx_rate & MWL_RX_RATE_FORMAT_MASK,
  13242. + (rx_rate & MWL_RX_RATE_NSS_MASK) >>
  13243. + MWL_RX_RATE_NSS_SHIFT,
  13244. + (rx_rate & MWL_RX_RATE_BW_MASK) >>
  13245. + MWL_RX_RATE_BW_SHIFT,
  13246. + (rx_rate & MWL_RX_RATE_GI_MASK) >>
  13247. + MWL_RX_RATE_GI_SHIFT,
  13248. + (rx_rate & MWL_RX_RATE_RT_MASK) >>
  13249. + MWL_RX_RATE_RT_SHIFT,
  13250. + status);
  13251. +
  13252. + status->freq = ieee80211_channel_to_frequency(pdesc->channel,
  13253. + status->band);
  13254. +
  13255. + /* check if status has a specific error bit (bit 7) set or indicates
  13256. + * a general decrypt error
  13257. + */
  13258. + if ((pdesc->status == GENERAL_DECRYPT_ERR) ||
  13259. + (pdesc->status & DECRYPT_ERR_MASK)) {
  13260. + /* check if status is not equal to 0xFF
  13261. + * the 0xFF check is for backward compatibility
  13262. + */
  13263. + if (pdesc->status != GENERAL_DECRYPT_ERR) {
  13264. + if (((pdesc->status & (~DECRYPT_ERR_MASK)) &
  13265. + TKIP_DECRYPT_MIC_ERR) && !((pdesc->status &
  13266. + (WEP_DECRYPT_ICV_ERR | TKIP_DECRYPT_ICV_ERR)))) {
  13267. + status->flag |= RX_FLAG_MMIC_ERROR;
  13268. + }
  13269. + }
  13270. + }
  13271. +}
  13272. +
  13273. +static inline bool pcie_rx_process_mesh_amsdu(struct mwl_priv *priv,
  13274. + struct sk_buff *skb,
  13275. + struct ieee80211_rx_status *status)
  13276. +{
  13277. + struct ieee80211_hdr *wh;
  13278. + struct mwl_sta *sta_info;
  13279. + struct ieee80211_sta *sta;
  13280. + u8 *qc;
  13281. + int wh_len;
  13282. + int len;
  13283. + u8 pad;
  13284. + u8 *data;
  13285. + u16 frame_len;
  13286. + struct sk_buff *newskb;
  13287. +
  13288. + wh = (struct ieee80211_hdr *)skb->data;
  13289. +
  13290. + spin_lock_bh(&priv->sta_lock);
  13291. + list_for_each_entry(sta_info, &priv->sta_list, list) {
  13292. + sta = container_of((void *)sta_info, struct ieee80211_sta,
  13293. + drv_priv[0]);
  13294. + if (ether_addr_equal(sta->addr, wh->addr2)) {
  13295. + if (!sta_info->is_mesh_node) {
  13296. + spin_unlock_bh(&priv->sta_lock);
  13297. + return false;
  13298. + }
  13299. + }
  13300. + }
  13301. + spin_unlock_bh(&priv->sta_lock);
  13302. +
  13303. + qc = ieee80211_get_qos_ctl(wh);
  13304. + *qc &= ~IEEE80211_QOS_CTL_A_MSDU_PRESENT;
  13305. +
  13306. + wh_len = ieee80211_hdrlen(wh->frame_control);
  13307. + len = wh_len;
  13308. + data = skb->data;
  13309. +
  13310. + while (len < skb->len) {
  13311. + frame_len = *(u8 *)(data + len + ETH_HLEN - 1) |
  13312. + (*(u8 *)(data + len + ETH_HLEN - 2) << 8);
  13313. +
  13314. + if ((len + ETH_HLEN + frame_len) > skb->len)
  13315. + break;
  13316. +
  13317. + newskb = dev_alloc_skb(wh_len + frame_len);
  13318. + if (!newskb)
  13319. + break;
  13320. +
  13321. + ether_addr_copy(wh->addr3, data + len);
  13322. + ether_addr_copy(wh->addr4, data + len + ETH_ALEN);
  13323. + memcpy(newskb->data, wh, wh_len);
  13324. + memcpy(newskb->data + wh_len, data + len + ETH_HLEN, frame_len);
  13325. + skb_put(newskb, wh_len + frame_len);
  13326. +
  13327. + pad = ((ETH_HLEN + frame_len) % 4) ?
  13328. + (4 - (ETH_HLEN + frame_len) % 4) : 0;
  13329. + len += (ETH_HLEN + frame_len + pad);
  13330. + if (len < skb->len)
  13331. + status->flag |= RX_FLAG_AMSDU_MORE;
  13332. + else
  13333. + status->flag &= ~RX_FLAG_AMSDU_MORE;
  13334. + memcpy(IEEE80211_SKB_RXCB(newskb), status, sizeof(*status));
  13335. + ieee80211_rx(priv->hw, newskb);
  13336. + }
  13337. +
  13338. + dev_kfree_skb_any(skb);
  13339. +
  13340. + return true;
  13341. +}
  13342. +
  13343. +static inline int pcie_rx_refill(struct mwl_priv *priv,
  13344. + struct pcie_rx_hndl *rx_hndl)
  13345. +{
  13346. + struct pcie_priv *pcie_priv = priv->hif.priv;
  13347. + struct pcie_desc_data *desc;
  13348. + dma_addr_t dma;
  13349. +
  13350. + desc = &pcie_priv->desc_data[0];
  13351. +
  13352. + rx_hndl->psk_buff = dev_alloc_skb(desc->rx_buf_size);
  13353. +
  13354. + if (!rx_hndl->psk_buff)
  13355. + return -ENOMEM;
  13356. +
  13357. + skb_reserve(rx_hndl->psk_buff, PCIE_MIN_BYTES_HEADROOM);
  13358. +
  13359. + rx_hndl->pdesc->status = EAGLE_RXD_STATUS_OK;
  13360. + rx_hndl->pdesc->qos_ctrl = 0x0000;
  13361. + rx_hndl->pdesc->channel = 0x00;
  13362. + rx_hndl->pdesc->rssi = 0x00;
  13363. + rx_hndl->pdesc->pkt_len = cpu_to_le16(desc->rx_buf_size);
  13364. +
  13365. + dma = pci_map_single(pcie_priv->pdev,
  13366. + rx_hndl->psk_buff->data,
  13367. + desc->rx_buf_size,
  13368. + PCI_DMA_FROMDEVICE);
  13369. + if (pci_dma_mapping_error(pcie_priv->pdev, dma)) {
  13370. + dev_kfree_skb_any(rx_hndl->psk_buff);
  13371. + wiphy_err(priv->hw->wiphy,
  13372. + "failed to map pci memory!\n");
  13373. + return -ENOMEM;
  13374. + }
  13375. +
  13376. + rx_hndl->pdesc->pphys_buff_data = cpu_to_le32(dma);
  13377. +
  13378. + return 0;
  13379. +}
  13380. +
  13381. +int pcie_rx_init(struct ieee80211_hw *hw)
  13382. +{
  13383. + struct mwl_priv *priv = hw->priv;
  13384. + int rc;
  13385. +
  13386. + rc = pcie_rx_ring_alloc(priv);
  13387. + if (rc) {
  13388. + wiphy_err(hw->wiphy, "allocating RX ring failed\n");
  13389. + return rc;
  13390. + }
  13391. +
  13392. + rc = pcie_rx_ring_init(priv);
  13393. + if (rc) {
  13394. + pcie_rx_ring_free(priv);
  13395. + wiphy_err(hw->wiphy,
  13396. + "initializing RX ring failed\n");
  13397. + return rc;
  13398. + }
  13399. +
  13400. + return 0;
  13401. +}
  13402. +
  13403. +void pcie_rx_deinit(struct ieee80211_hw *hw)
  13404. +{
  13405. + struct mwl_priv *priv = hw->priv;
  13406. +
  13407. + pcie_rx_ring_cleanup(priv);
  13408. + pcie_rx_ring_free(priv);
  13409. +}
  13410. +
  13411. +void pcie_rx_recv(unsigned long data)
  13412. +{
  13413. + struct ieee80211_hw *hw = (struct ieee80211_hw *)data;
  13414. + struct mwl_priv *priv = hw->priv;
  13415. + struct pcie_priv *pcie_priv = priv->hif.priv;
  13416. + struct pcie_desc_data *desc;
  13417. + struct pcie_rx_hndl *curr_hndl;
  13418. + int work_done = 0;
  13419. + struct sk_buff *prx_skb = NULL;
  13420. + int pkt_len;
  13421. + struct ieee80211_rx_status *status;
  13422. + struct mwl_vif *mwl_vif = NULL;
  13423. + struct ieee80211_hdr *wh;
  13424. +
  13425. + desc = &pcie_priv->desc_data[0];
  13426. + curr_hndl = desc->pnext_rx_hndl;
  13427. +
  13428. + if (!curr_hndl) {
  13429. + pcie_mask_int(pcie_priv, MACREG_A2HRIC_BIT_RX_RDY, true);
  13430. + pcie_priv->is_rx_schedule = false;
  13431. + wiphy_warn(hw->wiphy, "busy or no receiving packets\n");
  13432. + return;
  13433. + }
  13434. +
  13435. + while ((curr_hndl->pdesc->rx_control == EAGLE_RXD_CTRL_DMA_OWN) &&
  13436. + (work_done < pcie_priv->recv_limit)) {
  13437. + prx_skb = curr_hndl->psk_buff;
  13438. + if (!prx_skb)
  13439. + goto out;
  13440. + pci_unmap_single(pcie_priv->pdev,
  13441. + le32_to_cpu(curr_hndl->pdesc->pphys_buff_data),
  13442. + desc->rx_buf_size,
  13443. + PCI_DMA_FROMDEVICE);
  13444. + pkt_len = le16_to_cpu(curr_hndl->pdesc->pkt_len);
  13445. +
  13446. + if (skb_tailroom(prx_skb) < pkt_len) {
  13447. + dev_kfree_skb_any(prx_skb);
  13448. + goto out;
  13449. + }
  13450. +
  13451. + if (curr_hndl->pdesc->channel !=
  13452. + hw->conf.chandef.chan->hw_value) {
  13453. + dev_kfree_skb_any(prx_skb);
  13454. + goto out;
  13455. + }
  13456. +
  13457. + status = IEEE80211_SKB_RXCB(prx_skb);
  13458. + pcie_rx_status(priv, curr_hndl->pdesc, status);
  13459. +
  13460. + if (priv->chip_type == MWL8997) {
  13461. + priv->noise = (s8)curr_hndl->pdesc->noise_floor;
  13462. + if (priv->noise > 0)
  13463. + priv->noise = -priv->noise;
  13464. + } else
  13465. + priv->noise = -curr_hndl->pdesc->noise_floor;
  13466. +
  13467. + wh = &((struct pcie_dma_data *)prx_skb->data)->wh;
  13468. +
  13469. + if (ieee80211_has_protected(wh->frame_control)) {
  13470. + /* Check if hw crypto has been enabled for
  13471. + * this bss. If yes, set the status flags
  13472. + * accordingly
  13473. + */
  13474. + if (ieee80211_has_tods(wh->frame_control)) {
  13475. + mwl_vif = utils_find_vif_bss(priv, wh->addr1);
  13476. + if (!mwl_vif &&
  13477. + ieee80211_has_a4(wh->frame_control))
  13478. + mwl_vif =
  13479. + utils_find_vif_bss(priv,
  13480. + wh->addr2);
  13481. + } else {
  13482. + mwl_vif = utils_find_vif_bss(priv, wh->addr2);
  13483. + }
  13484. +
  13485. + if ((mwl_vif && mwl_vif->is_hw_crypto_enabled) ||
  13486. + is_multicast_ether_addr(wh->addr1) ||
  13487. + (ieee80211_is_mgmt(wh->frame_control) &&
  13488. + !is_multicast_ether_addr(wh->addr1))) {
  13489. + /* When MMIC ERROR is encountered
  13490. + * by the firmware, payload is
  13491. + * dropped and only 32 bytes of
  13492. + * mwlwifi Firmware header is sent
  13493. + * to the host.
  13494. + *
  13495. + * We need to add four bytes of
  13496. + * key information. In it
  13497. + * MAC80211 expects keyidx set to
  13498. + * 0 for triggering Counter
  13499. + * Measure of MMIC failure.
  13500. + */
  13501. + if (status->flag & RX_FLAG_MMIC_ERROR) {
  13502. + struct pcie_dma_data *dma_data;
  13503. +
  13504. + dma_data = (struct pcie_dma_data *)
  13505. + prx_skb->data;
  13506. + memset((void *)&dma_data->data, 0, 4);
  13507. + pkt_len += 4;
  13508. + }
  13509. +
  13510. + if (!ieee80211_is_auth(wh->frame_control)) {
  13511. + if (priv->chip_type != MWL8997)
  13512. + status->flag |=
  13513. + RX_FLAG_IV_STRIPPED |
  13514. + RX_FLAG_DECRYPTED |
  13515. + RX_FLAG_MMIC_STRIPPED;
  13516. + else
  13517. + status->flag |=
  13518. + RX_FLAG_DECRYPTED |
  13519. + RX_FLAG_MMIC_STRIPPED;
  13520. + }
  13521. + }
  13522. + }
  13523. +
  13524. + skb_put(prx_skb, pkt_len);
  13525. + pcie_rx_remove_dma_header(prx_skb, curr_hndl->pdesc->qos_ctrl);
  13526. +
  13527. + wh = (struct ieee80211_hdr *)prx_skb->data;
  13528. +
  13529. + if (ieee80211_is_data_qos(wh->frame_control)) {
  13530. + const u8 eapol[] = {0x88, 0x8e};
  13531. + u8 *qc = ieee80211_get_qos_ctl(wh);
  13532. + u8 *data;
  13533. +
  13534. + data = prx_skb->data +
  13535. + ieee80211_hdrlen(wh->frame_control) + 6;
  13536. +
  13537. + if (!memcmp(data, eapol, sizeof(eapol)))
  13538. + *qc |= 7;
  13539. + }
  13540. +
  13541. + if (ieee80211_is_data_qos(wh->frame_control) &&
  13542. + ieee80211_has_a4(wh->frame_control)) {
  13543. + u8 *qc = ieee80211_get_qos_ctl(wh);
  13544. +
  13545. + if (*qc & IEEE80211_QOS_CTL_A_MSDU_PRESENT)
  13546. + if (pcie_rx_process_mesh_amsdu(priv, prx_skb,
  13547. + status))
  13548. + goto out;
  13549. + }
  13550. +
  13551. + if (ieee80211_is_probe_req(wh->frame_control) &&
  13552. + priv->dump_probe)
  13553. + wiphy_info(hw->wiphy, "Probe Req: %pM\n", wh->addr2);
  13554. +
  13555. + ieee80211_rx(hw, prx_skb);
  13556. +out:
  13557. + pcie_rx_refill(priv, curr_hndl);
  13558. + curr_hndl->pdesc->rx_control = EAGLE_RXD_CTRL_DRIVER_OWN;
  13559. + curr_hndl->pdesc->qos_ctrl = 0;
  13560. + curr_hndl = curr_hndl->pnext;
  13561. + work_done++;
  13562. + }
  13563. +
  13564. + desc->pnext_rx_hndl = curr_hndl;
  13565. + pcie_mask_int(pcie_priv, MACREG_A2HRIC_BIT_RX_RDY, true);
  13566. + pcie_priv->is_rx_schedule = false;
  13567. +}
  13568. diff --git a/drivers/net/wireless/marvell/mwlwifi/hif/pcie/rx.h b/drivers/net/wireless/marvell/mwlwifi/hif/pcie/rx.h
  13569. new file mode 100644
  13570. index 000000000000..d2b580fceb0a
  13571. --- /dev/null
  13572. +++ b/drivers/net/wireless/marvell/mwlwifi/hif/pcie/rx.h
  13573. @@ -0,0 +1,25 @@
  13574. +/*
  13575. + * Copyright (C) 2006-2018, Marvell International Ltd.
  13576. + *
  13577. + * This software file (the "File") is distributed by Marvell International
  13578. + * Ltd. under the terms of the GNU General Public License Version 2, June 1991
  13579. + * (the "License"). You may use, redistribute and/or modify this File in
  13580. + * accordance with the terms and conditions of the License, a copy of which
  13581. + * is available by writing to the Free Software Foundation, Inc.
  13582. + *
  13583. + * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
  13584. + * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
  13585. + * ARE EXPRESSLY DISCLAIMED. The License provides additional details about
  13586. + * this warranty disclaimer.
  13587. + */
  13588. +
  13589. +/* Description: This file defines receive related functions. */
  13590. +
  13591. +#ifndef _RX_H_
  13592. +#define _RX_H_
  13593. +
  13594. +int pcie_rx_init(struct ieee80211_hw *hw);
  13595. +void pcie_rx_deinit(struct ieee80211_hw *hw);
  13596. +void pcie_rx_recv(unsigned long data);
  13597. +
  13598. +#endif /* _RX_H_ */
  13599. diff --git a/drivers/net/wireless/marvell/mwlwifi/hif/pcie/rx_ndp.c b/drivers/net/wireless/marvell/mwlwifi/hif/pcie/rx_ndp.c
  13600. new file mode 100644
  13601. index 000000000000..d1ede588b4c1
  13602. --- /dev/null
  13603. +++ b/drivers/net/wireless/marvell/mwlwifi/hif/pcie/rx_ndp.c
  13604. @@ -0,0 +1,612 @@
  13605. +/*
  13606. + * Copyright (C) 2006-2018, Marvell International Ltd.
  13607. + *
  13608. + * This software file (the "File") is distributed by Marvell International
  13609. + * Ltd. under the terms of the GNU General Public License Version 2, June 1991
  13610. + * (the "License"). You may use, redistribute and/or modify this File in
  13611. + * accordance with the terms and conditions of the License, a copy of which
  13612. + * is available by writing to the Free Software Foundation, Inc.
  13613. + *
  13614. + * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
  13615. + * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
  13616. + * ARE EXPRESSLY DISCLAIMED. The License provides additional details about
  13617. + * this warranty disclaimer.
  13618. + */
  13619. +
  13620. +/* Description: This file implements receive related functions for new data
  13621. + * path.
  13622. + */
  13623. +
  13624. +#include <linux/etherdevice.h>
  13625. +#include <linux/skbuff.h>
  13626. +
  13627. +#include "sysadpt.h"
  13628. +#include "core.h"
  13629. +#include "utils.h"
  13630. +#include "hif/pcie/dev.h"
  13631. +#include "hif/pcie/rx_ndp.h"
  13632. +
  13633. +#define MAX_NUM_RX_RING_BYTES (MAX_NUM_RX_DESC * \
  13634. + sizeof(struct pcie_rx_desc_ndp))
  13635. +#define MAX_NUM_RX_RING_DONE_BYTES (MAX_NUM_RX_DESC * \
  13636. + sizeof(struct rx_ring_done))
  13637. +
  13638. +static int pcie_rx_ring_alloc_ndp(struct mwl_priv *priv)
  13639. +{
  13640. + struct pcie_priv *pcie_priv = priv->hif.priv;
  13641. + struct pcie_desc_data_ndp *desc = &pcie_priv->desc_data_ndp;
  13642. +
  13643. + desc->prx_ring = (struct pcie_rx_desc_ndp *)
  13644. + dma_alloc_coherent(priv->dev,
  13645. + MAX_NUM_RX_RING_BYTES,
  13646. + &desc->pphys_rx_ring,
  13647. + GFP_KERNEL);
  13648. + if (!desc->prx_ring)
  13649. + goto err_no_mem;
  13650. + memset(desc->prx_ring, 0x00, MAX_NUM_RX_RING_BYTES);
  13651. +
  13652. + desc->prx_ring_done = (struct rx_ring_done *)
  13653. + dma_alloc_coherent(priv->dev,
  13654. + MAX_NUM_RX_RING_DONE_BYTES,
  13655. + &desc->pphys_rx_ring_done,
  13656. + GFP_KERNEL);
  13657. + if (!desc->prx_ring_done)
  13658. + goto err_no_mem;
  13659. + memset(desc->prx_ring_done, 0x00, MAX_NUM_RX_RING_DONE_BYTES);
  13660. + return 0;
  13661. +
  13662. +err_no_mem:
  13663. +
  13664. + wiphy_err(priv->hw->wiphy, "cannot alloc mem\n");
  13665. + return -ENOMEM;
  13666. +}
  13667. +
  13668. +static int pcie_rx_ring_init_ndp(struct mwl_priv *priv)
  13669. +{
  13670. + struct pcie_priv *pcie_priv = priv->hif.priv;
  13671. + struct pcie_desc_data_ndp *desc = &pcie_priv->desc_data_ndp;
  13672. + int i;
  13673. + struct sk_buff *psk_buff;
  13674. + dma_addr_t dma;
  13675. +
  13676. + skb_queue_head_init(&pcie_priv->rx_skb_trace);
  13677. + if (desc->prx_ring) {
  13678. + desc->rx_buf_size = MAX_AGGR_SIZE;
  13679. +
  13680. + for (i = 0; i < MAX_NUM_RX_DESC; i++) {
  13681. + psk_buff = __alloc_skb(desc->rx_buf_size + NET_SKB_PAD,
  13682. + GFP_ATOMIC, SKB_ALLOC_RX,
  13683. + NUMA_NO_NODE);
  13684. + skb_reserve(psk_buff, NET_SKB_PAD);
  13685. + if (!psk_buff) {
  13686. + wiphy_err(priv->hw->wiphy,
  13687. + "rxdesc %i: no skbuff available\n",
  13688. + i);
  13689. + return -ENOMEM;
  13690. + }
  13691. + skb_reserve(psk_buff, MIN_BYTES_RX_HEADROOM);
  13692. +
  13693. + dma = pci_map_single(pcie_priv->pdev,
  13694. + psk_buff->data,
  13695. + desc->rx_buf_size,
  13696. + PCI_DMA_FROMDEVICE);
  13697. + if (pci_dma_mapping_error(pcie_priv->pdev, dma)) {
  13698. + wiphy_err(priv->hw->wiphy,
  13699. + "failed to map pci memory!\n");
  13700. + return -ENOMEM;
  13701. + }
  13702. +
  13703. + desc->rx_vbuflist[i] = psk_buff;
  13704. + desc->prx_ring[i].user = cpu_to_le32(i);
  13705. + desc->prx_ring[i].data = cpu_to_le32(dma);
  13706. + *((u32 *)&psk_buff->cb[16]) = 0xdeadbeef;
  13707. + skb_queue_tail(&pcie_priv->rx_skb_trace, psk_buff);
  13708. + }
  13709. +
  13710. + writel(1023, pcie_priv->iobase1 + MACREG_REG_RXDESCHEAD);
  13711. + return 0;
  13712. + }
  13713. +
  13714. + wiphy_err(priv->hw->wiphy, "no valid RX mem\n");
  13715. + return -ENOMEM;
  13716. +}
  13717. +
  13718. +static void pcie_rx_ring_cleanup_ndp(struct mwl_priv *priv)
  13719. +{
  13720. + struct pcie_priv *pcie_priv = priv->hif.priv;
  13721. + struct pcie_desc_data_ndp *desc = &pcie_priv->desc_data_ndp;
  13722. + int i;
  13723. +
  13724. + if (desc->prx_ring) {
  13725. + for (i = 0; i < MAX_NUM_RX_DESC; i++) {
  13726. + if (desc->rx_vbuflist[i]) {
  13727. + pci_unmap_single(pcie_priv->pdev,
  13728. + le32_to_cpu(
  13729. + desc->prx_ring[i].data),
  13730. + desc->rx_buf_size,
  13731. + PCI_DMA_FROMDEVICE);
  13732. + desc->rx_vbuflist[i] = NULL;
  13733. + }
  13734. + }
  13735. + skb_queue_purge(&pcie_priv->rx_skb_trace);
  13736. + }
  13737. +}
  13738. +
  13739. +static void pcie_rx_ring_free_ndp(struct mwl_priv *priv)
  13740. +{
  13741. + struct pcie_priv *pcie_priv = priv->hif.priv;
  13742. + struct pcie_desc_data_ndp *desc = &pcie_priv->desc_data_ndp;
  13743. +
  13744. + if (desc->prx_ring) {
  13745. + pcie_rx_ring_cleanup_ndp(priv);
  13746. + dma_free_coherent(priv->dev,
  13747. + MAX_NUM_RX_RING_BYTES,
  13748. + desc->prx_ring,
  13749. + desc->pphys_rx_ring);
  13750. + desc->prx_ring = NULL;
  13751. + }
  13752. +
  13753. + if (desc->prx_ring_done) {
  13754. + dma_free_coherent(priv->dev,
  13755. + MAX_NUM_RX_RING_DONE_BYTES,
  13756. + desc->prx_ring_done,
  13757. + desc->pphys_rx_ring_done);
  13758. + desc->prx_ring_done = NULL;
  13759. + }
  13760. +}
  13761. +
  13762. +static inline void pcie_rx_update_ndp_cnts(struct mwl_priv *priv, u32 ctrl)
  13763. +{
  13764. + struct pcie_priv *pcie_priv = priv->hif.priv;
  13765. +
  13766. + switch (ctrl) {
  13767. + case RXRING_CASE_DROP:
  13768. + pcie_priv->rx_cnts.drop_cnt++;
  13769. + break;
  13770. + case RXRING_CASE_FAST_BAD_AMSDU:
  13771. + pcie_priv->rx_cnts.fast_bad_amsdu_cnt++;
  13772. + break;
  13773. + case RXRING_CASE_FAST_DATA:
  13774. + pcie_priv->rx_cnts.fast_data_cnt++;
  13775. + break;
  13776. + case RXRING_CASE_SLOW_BAD_MIC:
  13777. + pcie_priv->rx_cnts.slow_bad_mic_cnt++;
  13778. + break;
  13779. + case RXRING_CASE_SLOW_BAD_PN:
  13780. + pcie_priv->rx_cnts.slow_bad_pn_cnt++;
  13781. + break;
  13782. + case RXRING_CASE_SLOW_BAD_STA:
  13783. + pcie_priv->rx_cnts.slow_bad_sta_cnt++;
  13784. + break;
  13785. + case RXRING_CASE_SLOW_MCAST:
  13786. + pcie_priv->rx_cnts.slow_mcast_cnt++;
  13787. + break;
  13788. + case RXRING_CASE_SLOW_MGMT:
  13789. + pcie_priv->rx_cnts.slow_mgmt_cnt++;
  13790. + break;
  13791. + case RXRING_CASE_SLOW_NOQUEUE:
  13792. + pcie_priv->rx_cnts.slow_noqueue_cnt++;
  13793. + break;
  13794. + case RXRING_CASE_SLOW_NORUN:
  13795. + pcie_priv->rx_cnts.slow_norun_cnt++;
  13796. + break;
  13797. + case RXRING_CASE_SLOW_PROMISC:
  13798. + pcie_priv->rx_cnts.slow_promisc_cnt++;
  13799. + break;
  13800. + }
  13801. +}
  13802. +
  13803. +static void pcie_rx_status_ndp(struct mwl_priv *priv,
  13804. + struct mwl_sta *sta_info,
  13805. + struct ieee80211_rx_status *status)
  13806. +{
  13807. + memset(status, 0, sizeof(*status));
  13808. + pcie_rx_prepare_status(priv,
  13809. + sta_info->rx_format,
  13810. + sta_info->rx_nss,
  13811. + sta_info->rx_bw,
  13812. + sta_info->rx_gi,
  13813. + sta_info->rx_rate_mcs,
  13814. + status);
  13815. + status->signal = -sta_info->rx_signal;
  13816. + status->band = priv->hw->conf.chandef.chan->band;
  13817. + status->freq = ieee80211_channel_to_frequency(
  13818. + priv->hw->conf.chandef.chan->hw_value, status->band);
  13819. +}
  13820. +
  13821. +static inline void pcie_rx_process_fast_data(struct mwl_priv *priv,
  13822. + struct sk_buff *skb,
  13823. + u16 stnid)
  13824. +{
  13825. + struct pcie_priv *pcie_priv = priv->hif.priv;
  13826. + struct ieee80211_sta *sta;
  13827. + struct mwl_sta *sta_info;
  13828. + struct mwl_vif *mwl_vif;
  13829. + struct ieee80211_hdr hdr;
  13830. + u16 hdrlen, ethertype;
  13831. + __le16 fc;
  13832. + struct ieee80211_rx_status *status;
  13833. +
  13834. + if (stnid == RXRING_CTRL_STA_FROMDS)
  13835. + stnid = 0;
  13836. +
  13837. + if (stnid > SYSADPT_MAX_STA_SC4)
  13838. + goto drop_packet;
  13839. +
  13840. + sta = pcie_priv->sta_link[stnid];
  13841. + if (!sta)
  13842. + goto drop_packet;
  13843. +
  13844. + sta_info = mwl_dev_get_sta(sta);
  13845. + mwl_vif = sta_info->mwl_vif;
  13846. + if (!mwl_vif)
  13847. + goto drop_packet;
  13848. +
  13849. + ethertype = (skb->data[20] << 8) | skb->data[21];
  13850. + fc = cpu_to_le16(IEEE80211_FTYPE_DATA | IEEE80211_STYPE_DATA);
  13851. +
  13852. + memset(&hdr, 0, sizeof(hdr));
  13853. + switch (mwl_vif->type) {
  13854. + case NL80211_IFTYPE_AP:
  13855. + if (sta_info->wds) {
  13856. + fc |= (cpu_to_le16(IEEE80211_FCTL_TODS) |
  13857. + cpu_to_le16(IEEE80211_FCTL_FROMDS));
  13858. + /* RA TA DA SA */
  13859. + ether_addr_copy(hdr.addr1, mwl_vif->bssid);
  13860. + ether_addr_copy(hdr.addr2, sta->addr);
  13861. + ether_addr_copy(hdr.addr3, skb->data);
  13862. + ether_addr_copy(hdr.addr4, skb->data + ETH_ALEN);
  13863. + hdrlen = 30;
  13864. + } else {
  13865. + fc |= cpu_to_le16(IEEE80211_FCTL_TODS);
  13866. + /* BSSID SA DA */
  13867. + ether_addr_copy(hdr.addr1, mwl_vif->bssid);
  13868. + ether_addr_copy(hdr.addr2, skb->data + ETH_ALEN);
  13869. + ether_addr_copy(hdr.addr3, skb->data);
  13870. + hdrlen = 24;
  13871. + }
  13872. + break;
  13873. + case NL80211_IFTYPE_STATION:
  13874. + if (sta_info->wds) {
  13875. + fc |= (cpu_to_le16(IEEE80211_FCTL_TODS) |
  13876. + cpu_to_le16(IEEE80211_FCTL_FROMDS));
  13877. + /* RA TA DA SA */
  13878. + ether_addr_copy(hdr.addr1, mwl_vif->sta_mac);
  13879. + ether_addr_copy(hdr.addr2, mwl_vif->bssid);
  13880. + ether_addr_copy(hdr.addr3, skb->data);
  13881. + ether_addr_copy(hdr.addr4, skb->data + ETH_ALEN);
  13882. + hdrlen = 30;
  13883. + } else {
  13884. + fc |= cpu_to_le16(IEEE80211_FCTL_FROMDS);
  13885. + /* DA BSSID SA */
  13886. + ether_addr_copy(hdr.addr1, skb->data);
  13887. + ether_addr_copy(hdr.addr2, mwl_vif->bssid);
  13888. + ether_addr_copy(hdr.addr3, skb->data + ETH_ALEN);
  13889. + hdrlen = 24;
  13890. + }
  13891. + break;
  13892. + default:
  13893. + goto drop_packet;
  13894. + }
  13895. +
  13896. + if (sta->wme) {
  13897. + fc |= cpu_to_le16(IEEE80211_STYPE_QOS_DATA);
  13898. + hdrlen += 2;
  13899. + }
  13900. +
  13901. + status = IEEE80211_SKB_RXCB(skb);
  13902. + pcie_rx_status_ndp(priv, sta_info, status);
  13903. + if (mwl_vif->is_hw_crypto_enabled) {
  13904. + fc |= cpu_to_le16(IEEE80211_FCTL_PROTECTED);
  13905. + status->flag |= RX_FLAG_IV_STRIPPED |
  13906. + RX_FLAG_DECRYPTED |
  13907. + RX_FLAG_MMIC_STRIPPED;
  13908. + }
  13909. +
  13910. + hdr.frame_control = fc;
  13911. + hdr.duration_id = 0;
  13912. +
  13913. + skb_pull(skb, ETH_HLEN);
  13914. +
  13915. + if (ieee80211_is_data_qos(fc)) {
  13916. + __le16 *qos_control;
  13917. +
  13918. + qos_control = (__le16 *)skb_push(skb, 2);
  13919. + memcpy(skb_push(skb, hdrlen - 2), &hdr, hdrlen - 2);
  13920. + if (ethertype == ETH_P_PAE)
  13921. + *qos_control = cpu_to_le16(
  13922. + IEEE80211_QOS_CTL_ACK_POLICY_NOACK | 7);
  13923. + else
  13924. + *qos_control = cpu_to_le16(
  13925. + IEEE80211_QOS_CTL_ACK_POLICY_NOACK);
  13926. + } else
  13927. + memcpy(skb_push(skb, hdrlen), &hdr, hdrlen);
  13928. +
  13929. + status->flag |= RX_FLAG_DUP_VALIDATED;
  13930. + ieee80211_rx(priv->hw, skb);
  13931. +
  13932. + return;
  13933. +drop_packet:
  13934. +
  13935. + dev_kfree_skb_any(skb);
  13936. +}
  13937. +
  13938. +static inline void pcie_rx_process_slow_data(struct mwl_priv *priv,
  13939. + struct sk_buff *skb,
  13940. + bool bad_mic, u8 signal)
  13941. +{
  13942. + struct ieee80211_rx_status *status;
  13943. + struct ieee80211_hdr *wh;
  13944. + struct mwl_vif *mwl_vif = NULL;
  13945. +
  13946. + pcie_rx_remove_dma_header(skb, 0);
  13947. + status = IEEE80211_SKB_RXCB(skb);
  13948. + memset(status, 0, sizeof(*status));
  13949. + status->signal = -signal;
  13950. + status->band = priv->hw->conf.chandef.chan->band;
  13951. + status->freq = ieee80211_channel_to_frequency(
  13952. + priv->hw->conf.chandef.chan->hw_value, status->band);
  13953. +
  13954. + if (bad_mic)
  13955. + status->flag |= RX_FLAG_MMIC_ERROR;
  13956. + else {
  13957. + wh = (struct ieee80211_hdr *)skb->data;
  13958. +
  13959. + if (ieee80211_has_protected(wh->frame_control)) {
  13960. + if (ieee80211_has_tods(wh->frame_control)) {
  13961. + mwl_vif = utils_find_vif_bss(priv, wh->addr1);
  13962. + if (!mwl_vif &&
  13963. + ieee80211_has_a4(wh->frame_control))
  13964. + mwl_vif =
  13965. + utils_find_vif_bss(priv,
  13966. + wh->addr2);
  13967. + } else {
  13968. + mwl_vif = utils_find_vif_bss(priv, wh->addr2);
  13969. + }
  13970. +
  13971. + if ((mwl_vif && mwl_vif->is_hw_crypto_enabled) ||
  13972. + is_multicast_ether_addr(wh->addr1) ||
  13973. + (ieee80211_is_mgmt(wh->frame_control) &&
  13974. + !is_multicast_ether_addr(wh->addr1))) {
  13975. + if (!ieee80211_is_auth(wh->frame_control))
  13976. + status->flag |= RX_FLAG_IV_STRIPPED |
  13977. + RX_FLAG_DECRYPTED |
  13978. + RX_FLAG_MMIC_STRIPPED;
  13979. + }
  13980. + }
  13981. +
  13982. + if (ieee80211_has_a4(wh->frame_control) && !priv->wds_check) {
  13983. + ether_addr_copy(priv->wds_check_sta, wh->addr2);
  13984. + ieee80211_queue_work(priv->hw, &priv->wds_check_handle);
  13985. + priv->wds_check = true;
  13986. + }
  13987. + }
  13988. +
  13989. + status->flag |= RX_FLAG_DUP_VALIDATED;
  13990. + ieee80211_rx(priv->hw, skb);
  13991. +}
  13992. +
  13993. +static inline int pcie_rx_refill_ndp(struct mwl_priv *priv, u32 buf_idx)
  13994. +{
  13995. + struct pcie_priv *pcie_priv = priv->hif.priv;
  13996. + struct pcie_desc_data_ndp *desc = &pcie_priv->desc_data_ndp;
  13997. + struct sk_buff *psk_buff;
  13998. + dma_addr_t dma;
  13999. +
  14000. + psk_buff = __alloc_skb(desc->rx_buf_size + NET_SKB_PAD, GFP_ATOMIC,
  14001. + SKB_ALLOC_RX, NUMA_NO_NODE);
  14002. + skb_reserve(psk_buff, NET_SKB_PAD);
  14003. + if (!psk_buff)
  14004. + return -ENOMEM;
  14005. + skb_reserve(psk_buff, MIN_BYTES_RX_HEADROOM);
  14006. +
  14007. + dma = pci_map_single(pcie_priv->pdev,
  14008. + psk_buff->data,
  14009. + desc->rx_buf_size,
  14010. + PCI_DMA_FROMDEVICE);
  14011. + if (pci_dma_mapping_error(pcie_priv->pdev, dma)) {
  14012. + wiphy_err(priv->hw->wiphy,
  14013. + "refill: failed to map pci memory!\n");
  14014. + return -ENOMEM;
  14015. + }
  14016. +
  14017. + desc->rx_vbuflist[buf_idx] = psk_buff;
  14018. + desc->prx_ring[buf_idx].data = cpu_to_le32(dma);
  14019. + *((u32 *)&psk_buff->cb[16]) = 0xdeadbeef;
  14020. + skb_queue_tail(&pcie_priv->rx_skb_trace, psk_buff);
  14021. +
  14022. + return 0;
  14023. +}
  14024. +
  14025. +int pcie_rx_init_ndp(struct ieee80211_hw *hw)
  14026. +{
  14027. + struct mwl_priv *priv = hw->priv;
  14028. + int rc;
  14029. +
  14030. + rc = pcie_rx_ring_alloc_ndp(priv);
  14031. + if (rc) {
  14032. + pcie_rx_ring_free_ndp(priv);
  14033. + wiphy_err(hw->wiphy, "allocating RX ring failed\n");
  14034. + return rc;
  14035. + }
  14036. +
  14037. + rc = pcie_rx_ring_init_ndp(priv);
  14038. + if (rc) {
  14039. + pcie_rx_ring_free_ndp(priv);
  14040. + wiphy_err(hw->wiphy,
  14041. + "initializing RX ring failed\n");
  14042. + return rc;
  14043. + }
  14044. +
  14045. + return 0;
  14046. +}
  14047. +
  14048. +void pcie_rx_deinit_ndp(struct ieee80211_hw *hw)
  14049. +{
  14050. + struct mwl_priv *priv = hw->priv;
  14051. +
  14052. + pcie_rx_ring_cleanup_ndp(priv);
  14053. + pcie_rx_ring_free_ndp(priv);
  14054. +}
  14055. +
  14056. +void pcie_rx_recv_ndp(unsigned long data)
  14057. +{
  14058. + struct ieee80211_hw *hw = (struct ieee80211_hw *)data;
  14059. + struct mwl_priv *priv = hw->priv;
  14060. + struct pcie_priv *pcie_priv = priv->hif.priv;
  14061. + struct pcie_desc_data_ndp *desc = &pcie_priv->desc_data_ndp;
  14062. + struct rx_ring_done *prx_ring_done;
  14063. + struct pcie_rx_desc_ndp *prx_desc;
  14064. + u32 rx_done_head;
  14065. + u32 rx_done_tail;
  14066. + u32 rx_desc_head;
  14067. + struct sk_buff *psk_buff;
  14068. + u32 buf_idx;
  14069. + u32 rx_cnt;
  14070. + u32 ctrl, ctrl_case;
  14071. + bool bad_mic;
  14072. + u16 stnid;
  14073. + u16 pktlen;
  14074. + struct rx_info *rx_info;
  14075. + struct pcie_dma_data *dma_data;
  14076. + u8 signal;
  14077. +
  14078. + rx_done_head = readl(pcie_priv->iobase1 + MACREG_REG_RXDONEHEAD);
  14079. + rx_done_tail = readl(pcie_priv->iobase1 + MACREG_REG_RXDONETAIL);
  14080. + rx_desc_head = readl(pcie_priv->iobase1 + MACREG_REG_RXDESCHEAD);
  14081. + rx_cnt = 0;
  14082. +
  14083. + while ((rx_done_tail != rx_done_head) &&
  14084. + (rx_cnt < pcie_priv->recv_limit)) {
  14085. +recheck:
  14086. + prx_ring_done = &desc->prx_ring_done[rx_done_tail];
  14087. + wmb(); /*Data Memory Barrier*/
  14088. + if (le32_to_cpu(prx_ring_done->user) == 0xdeadbeef) {
  14089. + pcie_priv->recheck_rxringdone++;
  14090. + udelay(1);
  14091. + goto recheck;
  14092. + }
  14093. + buf_idx = le32_to_cpu(prx_ring_done->user) & 0x3fff;
  14094. + prx_ring_done->user = cpu_to_le32(0xdeadbeef);
  14095. + rx_done_tail++;
  14096. + prx_desc = &desc->prx_ring[buf_idx];
  14097. + if (!prx_desc->data)
  14098. + wiphy_err(hw->wiphy, "RX desc data is NULL\n");
  14099. + psk_buff = desc->rx_vbuflist[buf_idx];
  14100. + if (!psk_buff) {
  14101. + wiphy_err(hw->wiphy, "RX socket buffer is NULL\n");
  14102. + goto out;
  14103. + }
  14104. + if (*((u32 *)&psk_buff->cb[16]) != 0xdeadbeef) {
  14105. + pcie_priv->signature_err++;
  14106. + break;
  14107. + }
  14108. + if (psk_buff->next && psk_buff->prev) {
  14109. + skb_unlink(psk_buff, &pcie_priv->rx_skb_trace);
  14110. + *((u32 *)&psk_buff->cb[16]) = 0xbeefdead;
  14111. + } else {
  14112. + pcie_priv->rx_skb_unlink_err++;
  14113. + break;
  14114. + }
  14115. +
  14116. + pci_unmap_single(pcie_priv->pdev,
  14117. + le32_to_cpu(prx_desc->data),
  14118. + desc->rx_buf_size,
  14119. + PCI_DMA_FROMDEVICE);
  14120. +
  14121. + bad_mic = false;
  14122. + ctrl = le32_to_cpu(prx_ring_done->ctrl);
  14123. + ctrl_case = ctrl & RXRING_CTRL_CASE_MASK;
  14124. + stnid = (ctrl >> RXRING_CTRL_STA_SHIFT) & RXRING_CTRL_STA_MASK;
  14125. + pcie_rx_update_ndp_cnts(priv, ctrl_case);
  14126. +
  14127. + switch (ctrl_case) {
  14128. + case RXRING_CASE_FAST_DATA:
  14129. + if (stnid == RXRING_CTRL_STA_UNKNOWN) {
  14130. + dev_kfree_skb_any(psk_buff);
  14131. + break;
  14132. + }
  14133. + pktlen = psk_buff->data[12] << 8 | psk_buff->data[13];
  14134. + pktlen += ETH_HLEN;
  14135. +
  14136. + if (skb_tailroom(psk_buff) >= pktlen) {
  14137. + skb_put(psk_buff, pktlen);
  14138. + pcie_rx_process_fast_data(priv, psk_buff,
  14139. + stnid);
  14140. + } else {
  14141. + wiphy_err(hw->wiphy,
  14142. + "fast: space %d(%d) is not enough\n",
  14143. + skb_tailroom(psk_buff), pktlen);
  14144. + dev_kfree_skb_any(psk_buff);
  14145. + }
  14146. + break;
  14147. + case RXRING_CASE_FAST_BAD_AMSDU:
  14148. + case RXRING_CASE_SLOW_BAD_STA:
  14149. + case RXRING_CASE_SLOW_DEL_DONE:
  14150. + case RXRING_CASE_DROP:
  14151. + case RXRING_CASE_SLOW_BAD_PN:
  14152. + if (ctrl_case == RXRING_CASE_SLOW_DEL_DONE) {
  14153. + wiphy_debug(hw->wiphy,
  14154. + "staid %d deleted\n",
  14155. + stnid);
  14156. + utils_free_stnid(priv, stnid);
  14157. + }
  14158. + dev_kfree_skb_any(psk_buff);
  14159. + break;
  14160. + case RXRING_CASE_SLOW_BAD_MIC:
  14161. + bad_mic = true;
  14162. + case RXRING_CASE_SLOW_NOQUEUE:
  14163. + case RXRING_CASE_SLOW_NORUN:
  14164. + case RXRING_CASE_SLOW_MGMT:
  14165. + case RXRING_CASE_SLOW_MCAST:
  14166. + case RXRING_CASE_SLOW_PROMISC:
  14167. + rx_info = (struct rx_info *)psk_buff->data;
  14168. + dma_data = (struct pcie_dma_data *)&rx_info->hdr[0];
  14169. + pktlen = le16_to_cpu(dma_data->fwlen);
  14170. + pktlen += sizeof(*rx_info);
  14171. + pktlen += sizeof(struct pcie_dma_data);
  14172. + if (bad_mic) {
  14173. + memset((void *)&dma_data->data, 0, 4);
  14174. + pktlen += 4;
  14175. + }
  14176. + if (skb_tailroom(psk_buff) >= pktlen) {
  14177. + skb_put(psk_buff, pktlen);
  14178. + skb_pull(psk_buff, sizeof(*rx_info));
  14179. + signal = ((le32_to_cpu(rx_info->rssi_x) >>
  14180. + RXINFO_RSSI_X_SHIFT) &
  14181. + RXINFO_RSSI_X_MASK);
  14182. + pcie_rx_process_slow_data(priv, psk_buff,
  14183. + bad_mic, signal);
  14184. + } else {
  14185. + wiphy_err(hw->wiphy,
  14186. + "slow: space %d(%d) is not enough\n",
  14187. + skb_tailroom(psk_buff), pktlen);
  14188. + dev_kfree_skb_any(psk_buff);
  14189. + }
  14190. + break;
  14191. + default:
  14192. + wiphy_err(hw->wiphy, "unknown control case: %d\n",
  14193. + ctrl_case);
  14194. + dev_kfree_skb_any(psk_buff);
  14195. + break;
  14196. + }
  14197. +out:
  14198. + pcie_rx_refill_ndp(priv, buf_idx);
  14199. +
  14200. + if (rx_done_tail >= MAX_RX_RING_DONE_SIZE)
  14201. + rx_done_tail = 0;
  14202. +
  14203. + rx_done_head =
  14204. + readl(pcie_priv->iobase1 + MACREG_REG_RXDONEHEAD);
  14205. + rx_cnt++;
  14206. + }
  14207. +
  14208. + rx_desc_head += rx_cnt;
  14209. + if (rx_desc_head >= MAX_RX_RING_SEND_SIZE)
  14210. + rx_desc_head = rx_desc_head - MAX_RX_RING_SEND_SIZE;
  14211. + writel(rx_done_tail, pcie_priv->iobase1 + MACREG_REG_RXDONETAIL);
  14212. + writel(rx_desc_head, pcie_priv->iobase1 + MACREG_REG_RXDESCHEAD);
  14213. +
  14214. + pcie_mask_int(pcie_priv, MACREG_A2HRIC_RX_DONE_HEAD_RDY, true);
  14215. + pcie_priv->is_rx_schedule = false;
  14216. +}
  14217. diff --git a/drivers/net/wireless/marvell/mwlwifi/hif/pcie/rx_ndp.h b/drivers/net/wireless/marvell/mwlwifi/hif/pcie/rx_ndp.h
  14218. new file mode 100644
  14219. index 000000000000..7e83cedf4351
  14220. --- /dev/null
  14221. +++ b/drivers/net/wireless/marvell/mwlwifi/hif/pcie/rx_ndp.h
  14222. @@ -0,0 +1,26 @@
  14223. +/*
  14224. + * Copyright (C) 2006-2018, Marvell International Ltd.
  14225. + *
  14226. + * This software file (the "File") is distributed by Marvell International
  14227. + * Ltd. under the terms of the GNU General Public License Version 2, June 1991
  14228. + * (the "License"). You may use, redistribute and/or modify this File in
  14229. + * accordance with the terms and conditions of the License, a copy of which
  14230. + * is available by writing to the Free Software Foundation, Inc.
  14231. + *
  14232. + * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
  14233. + * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
  14234. + * ARE EXPRESSLY DISCLAIMED. The License provides additional details about
  14235. + * this warranty disclaimer.
  14236. + */
  14237. +
  14238. +/* Description: This file defines receive related functions for new data path.
  14239. + */
  14240. +
  14241. +#ifndef _RX_NDP_H_
  14242. +#define _RX_NDP_H_
  14243. +
  14244. +int pcie_rx_init_ndp(struct ieee80211_hw *hw);
  14245. +void pcie_rx_deinit_ndp(struct ieee80211_hw *hw);
  14246. +void pcie_rx_recv_ndp(unsigned long data);
  14247. +
  14248. +#endif /* _RX_NDP_H_ */
  14249. diff --git a/drivers/net/wireless/marvell/mwlwifi/hif/pcie/sc4_ddr.h b/drivers/net/wireless/marvell/mwlwifi/hif/pcie/sc4_ddr.h
  14250. new file mode 100644
  14251. index 000000000000..2da0257accba
  14252. --- /dev/null
  14253. +++ b/drivers/net/wireless/marvell/mwlwifi/hif/pcie/sc4_ddr.h
  14254. @@ -0,0 +1,965 @@
  14255. +/*
  14256. + * Copyright (C) 2006-2018, Marvell International Ltd.
  14257. + *
  14258. + * This software file (the "File") is distributed by Marvell International
  14259. + * Ltd. under the terms of the GNU General Public License Version 2, June 1991
  14260. + * (the "License"). You may use, redistribute and/or modify this File in
  14261. + * accordance with the terms and conditions of the License, a copy of which
  14262. + * is available by writing to the Free Software Foundation, Inc.
  14263. + *
  14264. + * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
  14265. + * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
  14266. + * ARE EXPRESSLY DISCLAIMED. The License provides additional details about
  14267. + * this warranty disclaimer.
  14268. + */
  14269. +
  14270. +static unsigned char sc4_ddr_init[] = {
  14271. +0x05,
  14272. +0x00,
  14273. +0x00,
  14274. +0x00,
  14275. +0x00,
  14276. +0x00,
  14277. +0x00,
  14278. +0x00,
  14279. +0xa4,
  14280. +0x03,
  14281. +0x00,
  14282. +0x00,
  14283. +0x2a,
  14284. +0xbe,
  14285. +0xad,
  14286. +0x7e,
  14287. +0x00,
  14288. +0x00,
  14289. +0x00,
  14290. +0xa8,
  14291. +0x01,
  14292. +0x00,
  14293. +0x00,
  14294. +0x00,
  14295. +0x00,
  14296. +0x00,
  14297. +0x00,
  14298. +0x00,
  14299. +0x5c,
  14300. +0x48,
  14301. +0x5b,
  14302. +0x49,
  14303. +0x04,
  14304. +0x00,
  14305. +0x00,
  14306. +0x00,
  14307. +0x10,
  14308. +0xb5,
  14309. +0xc0,
  14310. +0xf8,
  14311. +0x08,
  14312. +0x00,
  14313. +0x00,
  14314. +0x00,
  14315. +0xe0,
  14316. +0x12,
  14317. +0xef,
  14318. +0x21,
  14319. +0x0c,
  14320. +0x00,
  14321. +0x00,
  14322. +0x00,
  14323. +0xc0,
  14324. +0xf8,
  14325. +0x20,
  14326. +0x13,
  14327. +0x10,
  14328. +0x00,
  14329. +0x00,
  14330. +0x00,
  14331. +0x02,
  14332. +0x21,
  14333. +0xc0,
  14334. +0xf8,
  14335. +0x14,
  14336. +0x00,
  14337. +0x00,
  14338. +0x00,
  14339. +0x24,
  14340. +0x13,
  14341. +0x02,
  14342. +0x01,
  14343. +0x18,
  14344. +0x00,
  14345. +0x00,
  14346. +0x00,
  14347. +0x57,
  14348. +0x49,
  14349. +0x0a,
  14350. +0x60,
  14351. +0x1c,
  14352. +0x00,
  14353. +0x00,
  14354. +0x00,
  14355. +0x00,
  14356. +0x21,
  14357. +0x56,
  14358. +0x4b,
  14359. +0x20,
  14360. +0x00,
  14361. +0x00,
  14362. +0x00,
  14363. +0xc0,
  14364. +0x3b,
  14365. +0x19,
  14366. +0x60,
  14367. +0x24,
  14368. +0x00,
  14369. +0x00,
  14370. +0x00,
  14371. +0x54,
  14372. +0x4b,
  14373. +0x1b,
  14374. +0x1d,
  14375. +0x28,
  14376. +0x00,
  14377. +0x00,
  14378. +0x00,
  14379. +0x1a,
  14380. +0x60,
  14381. +0x53,
  14382. +0x4b,
  14383. +0x2c,
  14384. +0x00,
  14385. +0x00,
  14386. +0x00,
  14387. +0xbc,
  14388. +0x3b,
  14389. +0x19,
  14390. +0x60,
  14391. +0x30,
  14392. +0x00,
  14393. +0x00,
  14394. +0x00,
  14395. +0x51,
  14396. +0x4b,
  14397. +0x08,
  14398. +0x33,
  14399. +0x34,
  14400. +0x00,
  14401. +0x00,
  14402. +0x00,
  14403. +0x1a,
  14404. +0x60,
  14405. +0x50,
  14406. +0x4b,
  14407. +0x38,
  14408. +0x00,
  14409. +0x00,
  14410. +0x00,
  14411. +0xb8,
  14412. +0x3b,
  14413. +0x19,
  14414. +0x60,
  14415. +0x3c,
  14416. +0x00,
  14417. +0x00,
  14418. +0x00,
  14419. +0x4e,
  14420. +0x4b,
  14421. +0x0c,
  14422. +0x33,
  14423. +0x40,
  14424. +0x00,
  14425. +0x00,
  14426. +0x00,
  14427. +0x1a,
  14428. +0x60,
  14429. +0x4d,
  14430. +0x4b,
  14431. +0x44,
  14432. +0x00,
  14433. +0x00,
  14434. +0x00,
  14435. +0xb4,
  14436. +0x3b,
  14437. +0x19,
  14438. +0x60,
  14439. +0x48,
  14440. +0x00,
  14441. +0x00,
  14442. +0x00,
  14443. +0x4b,
  14444. +0x4b,
  14445. +0x10,
  14446. +0x33,
  14447. +0x4c,
  14448. +0x00,
  14449. +0x00,
  14450. +0x00,
  14451. +0x1a,
  14452. +0x60,
  14453. +0x4a,
  14454. +0x4b,
  14455. +0x50,
  14456. +0x00,
  14457. +0x00,
  14458. +0x00,
  14459. +0xb0,
  14460. +0x3b,
  14461. +0x19,
  14462. +0x60,
  14463. +0x54,
  14464. +0x00,
  14465. +0x00,
  14466. +0x00,
  14467. +0x48,
  14468. +0x4b,
  14469. +0x80,
  14470. +0x33,
  14471. +0x58,
  14472. +0x00,
  14473. +0x00,
  14474. +0x00,
  14475. +0x1a,
  14476. +0x60,
  14477. +0x47,
  14478. +0x4b,
  14479. +0x5c,
  14480. +0x00,
  14481. +0x00,
  14482. +0x00,
  14483. +0x40,
  14484. +0x3b,
  14485. +0x19,
  14486. +0x60,
  14487. +0x60,
  14488. +0x00,
  14489. +0x00,
  14490. +0x00,
  14491. +0x47,
  14492. +0x4c,
  14493. +0x46,
  14494. +0x4b,
  14495. +0x64,
  14496. +0x00,
  14497. +0x00,
  14498. +0x00,
  14499. +0x23,
  14500. +0x60,
  14501. +0x24,
  14502. +0x1d,
  14503. +0x68,
  14504. +0x00,
  14505. +0x00,
  14506. +0x00,
  14507. +0x23,
  14508. +0x60,
  14509. +0x24,
  14510. +0x1d,
  14511. +0x6c,
  14512. +0x00,
  14513. +0x00,
  14514. +0x00,
  14515. +0x23,
  14516. +0x60,
  14517. +0x44,
  14518. +0x4b,
  14519. +0x70,
  14520. +0x00,
  14521. +0x00,
  14522. +0x00,
  14523. +0x40,
  14524. +0x33,
  14525. +0x19,
  14526. +0x60,
  14527. +0x74,
  14528. +0x00,
  14529. +0x00,
  14530. +0x00,
  14531. +0x1b,
  14532. +0x1d,
  14533. +0x19,
  14534. +0x60,
  14535. +0x78,
  14536. +0x00,
  14537. +0x00,
  14538. +0x00,
  14539. +0x1b,
  14540. +0x1d,
  14541. +0x19,
  14542. +0x60,
  14543. +0x7c,
  14544. +0x00,
  14545. +0x00,
  14546. +0x00,
  14547. +0x41,
  14548. +0x4b,
  14549. +0xc0,
  14550. +0xf8,
  14551. +0x80,
  14552. +0x00,
  14553. +0x00,
  14554. +0x00,
  14555. +0xe0,
  14556. +0x31,
  14557. +0x41,
  14558. +0x4b,
  14559. +0x84,
  14560. +0x00,
  14561. +0x00,
  14562. +0x00,
  14563. +0xc0,
  14564. +0xf8,
  14565. +0xf0,
  14566. +0x31,
  14567. +0x88,
  14568. +0x00,
  14569. +0x00,
  14570. +0x00,
  14571. +0x03,
  14572. +0x04,
  14573. +0xc0,
  14574. +0xf8,
  14575. +0x8c,
  14576. +0x00,
  14577. +0x00,
  14578. +0x00,
  14579. +0xf0,
  14580. +0x32,
  14581. +0x40,
  14582. +0xf2,
  14583. +0x90,
  14584. +0x00,
  14585. +0x00,
  14586. +0x00,
  14587. +0x55,
  14588. +0x13,
  14589. +0xc0,
  14590. +0xf8,
  14591. +0x94,
  14592. +0x00,
  14593. +0x00,
  14594. +0x00,
  14595. +0x60,
  14596. +0x33,
  14597. +0x3d,
  14598. +0x4b,
  14599. +0x98,
  14600. +0x00,
  14601. +0x00,
  14602. +0x00,
  14603. +0xc0,
  14604. +0xf8,
  14605. +0x64,
  14606. +0x33,
  14607. +0x9c,
  14608. +0x00,
  14609. +0x00,
  14610. +0x00,
  14611. +0x13,
  14612. +0x1d,
  14613. +0xc0,
  14614. +0xf8,
  14615. +0xa0,
  14616. +0x00,
  14617. +0x00,
  14618. +0x00,
  14619. +0x68,
  14620. +0x33,
  14621. +0x3b,
  14622. +0x4b,
  14623. +0xa4,
  14624. +0x00,
  14625. +0x00,
  14626. +0x00,
  14627. +0xc0,
  14628. +0xf8,
  14629. +0x6c,
  14630. +0x33,
  14631. +0xa8,
  14632. +0x00,
  14633. +0x00,
  14634. +0x00,
  14635. +0x3a,
  14636. +0x4b,
  14637. +0xc0,
  14638. +0xf8,
  14639. +0xac,
  14640. +0x00,
  14641. +0x00,
  14642. +0x00,
  14643. +0x70,
  14644. +0x33,
  14645. +0x3a,
  14646. +0x4b,
  14647. +0xb0,
  14648. +0x00,
  14649. +0x00,
  14650. +0x00,
  14651. +0xc0,
  14652. +0xf8,
  14653. +0x74,
  14654. +0x33,
  14655. +0xb4,
  14656. +0x00,
  14657. +0x00,
  14658. +0x00,
  14659. +0x39,
  14660. +0x4b,
  14661. +0xc0,
  14662. +0xf8,
  14663. +0xb8,
  14664. +0x00,
  14665. +0x00,
  14666. +0x00,
  14667. +0x78,
  14668. +0x33,
  14669. +0xc4,
  14670. +0x23,
  14671. +0xbc,
  14672. +0x00,
  14673. +0x00,
  14674. +0x00,
  14675. +0xc0,
  14676. +0xf8,
  14677. +0x7c,
  14678. +0x33,
  14679. +0xc0,
  14680. +0x00,
  14681. +0x00,
  14682. +0x00,
  14683. +0x37,
  14684. +0x4b,
  14685. +0xc0,
  14686. +0xf8,
  14687. +0xc4,
  14688. +0x00,
  14689. +0x00,
  14690. +0x00,
  14691. +0x80,
  14692. +0x33,
  14693. +0x37,
  14694. +0x4b,
  14695. +0xc8,
  14696. +0x00,
  14697. +0x00,
  14698. +0x00,
  14699. +0xc0,
  14700. +0xf8,
  14701. +0x84,
  14702. +0x33,
  14703. +0xcc,
  14704. +0x00,
  14705. +0x00,
  14706. +0x00,
  14707. +0x36,
  14708. +0x4b,
  14709. +0xc0,
  14710. +0xf8,
  14711. +0xd0,
  14712. +0x00,
  14713. +0x00,
  14714. +0x00,
  14715. +0x88,
  14716. +0x33,
  14717. +0x42,
  14718. +0xf2,
  14719. +0xd4,
  14720. +0x00,
  14721. +0x00,
  14722. +0x00,
  14723. +0x44,
  14724. +0x23,
  14725. +0xc0,
  14726. +0xf8,
  14727. +0xd8,
  14728. +0x00,
  14729. +0x00,
  14730. +0x00,
  14731. +0x8c,
  14732. +0x33,
  14733. +0xc0,
  14734. +0xf8,
  14735. +0xdc,
  14736. +0x00,
  14737. +0x00,
  14738. +0x00,
  14739. +0x90,
  14740. +0x13,
  14741. +0x4f,
  14742. +0xf4,
  14743. +0xe0,
  14744. +0x00,
  14745. +0x00,
  14746. +0x00,
  14747. +0x60,
  14748. +0x43,
  14749. +0xc0,
  14750. +0xf8,
  14751. +0xe4,
  14752. +0x00,
  14753. +0x00,
  14754. +0x00,
  14755. +0xa0,
  14756. +0x32,
  14757. +0xc0,
  14758. +0xf8,
  14759. +0xe8,
  14760. +0x00,
  14761. +0x00,
  14762. +0x00,
  14763. +0xa4,
  14764. +0x22,
  14765. +0xc0,
  14766. +0xf8,
  14767. +0xec,
  14768. +0x00,
  14769. +0x00,
  14770. +0x00,
  14771. +0xa8,
  14772. +0x12,
  14773. +0x44,
  14774. +0xf2,
  14775. +0xf0,
  14776. +0x00,
  14777. +0x00,
  14778. +0x00,
  14779. +0x40,
  14780. +0x02,
  14781. +0x2e,
  14782. +0x4b,
  14783. +0xf4,
  14784. +0x00,
  14785. +0x00,
  14786. +0x00,
  14787. +0x1a,
  14788. +0x60,
  14789. +0x1b,
  14790. +0x1d,
  14791. +0xf8,
  14792. +0x00,
  14793. +0x00,
  14794. +0x00,
  14795. +0x2d,
  14796. +0x4a,
  14797. +0x1a,
  14798. +0x60,
  14799. +0xfc,
  14800. +0x00,
  14801. +0x00,
  14802. +0x00,
  14803. +0x1b,
  14804. +0x1d,
  14805. +0x2d,
  14806. +0x4a,
  14807. +0x00,
  14808. +0x01,
  14809. +0x00,
  14810. +0x00,
  14811. +0x1a,
  14812. +0x60,
  14813. +0x1b,
  14814. +0x1d,
  14815. +0x04,
  14816. +0x01,
  14817. +0x00,
  14818. +0x00,
  14819. +0x2c,
  14820. +0x4a,
  14821. +0x1a,
  14822. +0x60,
  14823. +0x08,
  14824. +0x01,
  14825. +0x00,
  14826. +0x00,
  14827. +0x1b,
  14828. +0x1d,
  14829. +0x2c,
  14830. +0x4a,
  14831. +0x0c,
  14832. +0x01,
  14833. +0x00,
  14834. +0x00,
  14835. +0x1a,
  14836. +0x60,
  14837. +0x1b,
  14838. +0x1d,
  14839. +0x10,
  14840. +0x01,
  14841. +0x00,
  14842. +0x00,
  14843. +0x4f,
  14844. +0xf4,
  14845. +0x60,
  14846. +0x12,
  14847. +0x14,
  14848. +0x01,
  14849. +0x00,
  14850. +0x00,
  14851. +0x1a,
  14852. +0x60,
  14853. +0x25,
  14854. +0x4a,
  14855. +0x18,
  14856. +0x01,
  14857. +0x00,
  14858. +0x00,
  14859. +0x28,
  14860. +0x32,
  14861. +0x11,
  14862. +0x60,
  14863. +0x1c,
  14864. +0x01,
  14865. +0x00,
  14866. +0x00,
  14867. +0x23,
  14868. +0x4a,
  14869. +0x30,
  14870. +0x32,
  14871. +0x20,
  14872. +0x01,
  14873. +0x00,
  14874. +0x00,
  14875. +0x11,
  14876. +0x60,
  14877. +0x12,
  14878. +0x1d,
  14879. +0x24,
  14880. +0x01,
  14881. +0x00,
  14882. +0x00,
  14883. +0x11,
  14884. +0x60,
  14885. +0x03,
  14886. +0x22,
  14887. +0x28,
  14888. +0x01,
  14889. +0x00,
  14890. +0x00,
  14891. +0x20,
  14892. +0x4b,
  14893. +0x38,
  14894. +0x33,
  14895. +0x2c,
  14896. +0x01,
  14897. +0x00,
  14898. +0x00,
  14899. +0x1a,
  14900. +0x60,
  14901. +0x20,
  14902. +0x22,
  14903. +0x30,
  14904. +0x01,
  14905. +0x00,
  14906. +0x00,
  14907. +0x1b,
  14908. +0x1d,
  14909. +0x1a,
  14910. +0x60,
  14911. +0x34,
  14912. +0x01,
  14913. +0x00,
  14914. +0x00,
  14915. +0x1b,
  14916. +0x1d,
  14917. +0x4f,
  14918. +0xf0,
  14919. +0x38,
  14920. +0x01,
  14921. +0x00,
  14922. +0x00,
  14923. +0x04,
  14924. +0x22,
  14925. +0x1a,
  14926. +0x60,
  14927. +0x3c,
  14928. +0x01,
  14929. +0x00,
  14930. +0x00,
  14931. +0x03,
  14932. +0x06,
  14933. +0x1b,
  14934. +0x4a,
  14935. +0x40,
  14936. +0x01,
  14937. +0x00,
  14938. +0x00,
  14939. +0x20,
  14940. +0x32,
  14941. +0x13,
  14942. +0x60,
  14943. +0x44,
  14944. +0x01,
  14945. +0x00,
  14946. +0x00,
  14947. +0x43,
  14948. +0x06,
  14949. +0x13,
  14950. +0x60,
  14951. +0x48,
  14952. +0x01,
  14953. +0x00,
  14954. +0x00,
  14955. +0x83,
  14956. +0x06,
  14957. +0x13,
  14958. +0x60,
  14959. +0x4c,
  14960. +0x01,
  14961. +0x00,
  14962. +0x00,
  14963. +0x0c,
  14964. +0x4b,
  14965. +0x1c,
  14966. +0x4a,
  14967. +0x50,
  14968. +0x01,
  14969. +0x00,
  14970. +0x00,
  14971. +0x70,
  14972. +0x33,
  14973. +0x1a,
  14974. +0x60,
  14975. +0x54,
  14976. +0x01,
  14977. +0x00,
  14978. +0x00,
  14979. +0x41,
  14980. +0x62,
  14981. +0x4f,
  14982. +0xf4,
  14983. +0x58,
  14984. +0x01,
  14985. +0x00,
  14986. +0x00,
  14987. +0x7f,
  14988. +0x22,
  14989. +0x82,
  14990. +0x62,
  14991. +0x5c,
  14992. +0x01,
  14993. +0x00,
  14994. +0x00,
  14995. +0x19,
  14996. +0x4a,
  14997. +0x82,
  14998. +0x66,
  14999. +0x60,
  15000. +0x01,
  15001. +0x00,
  15002. +0x00,
  15003. +0xc1,
  15004. +0x66,
  15005. +0x40,
  15006. +0xf2,
  15007. +0x64,
  15008. +0x01,
  15009. +0x00,
  15010. +0x00,
  15011. +0x63,
  15012. +0x42,
  15013. +0x42,
  15014. +0x63,
  15015. +0x68,
  15016. +0x01,
  15017. +0x00,
  15018. +0x00,
  15019. +0x01,
  15020. +0x64,
  15021. +0x17,
  15022. +0x49,
  15023. +0x6c,
  15024. +0x01,
  15025. +0x00,
  15026. +0x00,
  15027. +0x01,
  15028. +0x60,
  15029. +0x10,
  15030. +0xbd,
  15031. +0x70,
  15032. +0x01,
  15033. +0x00,
  15034. +0x00,
  15035. +0x22,
  15036. +0x76,
  15037. +0x30,
  15038. +0x00,
  15039. +0x74,
  15040. +0x01,
  15041. +0x00,
  15042. +0x00,
  15043. +0x20,
  15044. +0x00,
  15045. +0x00,
  15046. +0xf0,
  15047. +0x78,
  15048. +0x01,
  15049. +0x00,
  15050. +0x00,
  15051. +0x40,
  15052. +0x06,
  15053. +0x00,
  15054. +0xf0,
  15055. +0x7c,
  15056. +0x01,
  15057. +0x00,
  15058. +0x00,
  15059. +0x04,
  15060. +0x00,
  15061. +0x15,
  15062. +0x15,
  15063. +0x80,
  15064. +0x01,
  15065. +0x00,
  15066. +0x00,
  15067. +0x00,
  15068. +0x05,
  15069. +0x00,
  15070. +0xf0,
  15071. +0x84,
  15072. +0x01,
  15073. +0x00,
  15074. +0x00,
  15075. +0x01,
  15076. +0x00,
  15077. +0x0d,
  15078. +0x00,
  15079. +0x88,
  15080. +0x01,
  15081. +0x00,
  15082. +0x00,
  15083. +0x32,
  15084. +0x05,
  15085. +0x00,
  15086. +0x04,
  15087. +0x8c,
  15088. +0x01,
  15089. +0x00,
  15090. +0x00,
  15091. +0xa9,
  15092. +0x02,
  15093. +0xb8,
  15094. +0x00,
  15095. +0x90,
  15096. +0x01,
  15097. +0x00,
  15098. +0x00,
  15099. +0x00,
  15100. +0x01,
  15101. +0x40,
  15102. +0x00,
  15103. +0x94,
  15104. +0x01,
  15105. +0x00,
  15106. +0x00,
  15107. +0xeb,
  15108. +0x06,
  15109. +0x77,
  15110. +0x00,
  15111. +0x98,
  15112. +0x01,
  15113. +0x00,
  15114. +0x00,
  15115. +0x00,
  15116. +0x52,
  15117. +0x7b,
  15118. +0x50,
  15119. +0x9c,
  15120. +0x01,
  15121. +0x00,
  15122. +0x00,
  15123. +0x0b,
  15124. +0x06,
  15125. +0x04,
  15126. +0x10,
  15127. +0xa0,
  15128. +0x01,
  15129. +0x00,
  15130. +0x00,
  15131. +0x10,
  15132. +0x07,
  15133. +0x17,
  15134. +0x13,
  15135. +0xa4,
  15136. +0x01,
  15137. +0x00,
  15138. +0x00,
  15139. +0x07,
  15140. +0x74,
  15141. +0x70,
  15142. +0x00,
  15143. +0xa8,
  15144. +0x01,
  15145. +0x00,
  15146. +0x00,
  15147. +0x40,
  15148. +0x00,
  15149. +0x70,
  15150. +0x50,
  15151. +0xac,
  15152. +0x01,
  15153. +0x00,
  15154. +0x00,
  15155. +0x00,
  15156. +0x04,
  15157. +0x00,
  15158. +0xf0,
  15159. +0xb0,
  15160. +0x01,
  15161. +0x00,
  15162. +0x00,
  15163. +0x79,
  15164. +0x07,
  15165. +0x70,
  15166. +0x17,
  15167. +0xb4,
  15168. +0x01,
  15169. +0x00,
  15170. +0x00,
  15171. +0x70,
  15172. +0x07,
  15173. +0xf0,
  15174. +0x0f,
  15175. +0xb8,
  15176. +0x01,
  15177. +0x00,
  15178. +0x00,
  15179. +0x77,
  15180. +0xfc,
  15181. +0x03,
  15182. +0x3f,
  15183. +0xbc,
  15184. +0x01,
  15185. +0x00,
  15186. +0x00,
  15187. +0x00,
  15188. +0x31,
  15189. +0x10,
  15190. +0x00,
  15191. +0xc0,
  15192. +0x01,
  15193. +0x00,
  15194. +0x00,
  15195. +0x01,
  15196. +0x00,
  15197. +0x00,
  15198. +0xc0,
  15199. +0xc4,
  15200. +0x01,
  15201. +0x00,
  15202. +0x00,
  15203. +0x66,
  15204. +0x66,
  15205. +0x66,
  15206. +0x00,
  15207. +0xc8,
  15208. +0x01,
  15209. +0x00,
  15210. +0x00,
  15211. +0x01,
  15212. +0x00,
  15213. +0x00,
  15214. +0x11,
  15215. +0x37,
  15216. +0x3e,
  15217. +0xfc,
  15218. +0xdc,
  15219. +};
  15220. diff --git a/drivers/net/wireless/marvell/mwlwifi/hif/pcie/tx.c b/drivers/net/wireless/marvell/mwlwifi/hif/pcie/tx.c
  15221. new file mode 100644
  15222. index 000000000000..dd77589ef5a6
  15223. --- /dev/null
  15224. +++ b/drivers/net/wireless/marvell/mwlwifi/hif/pcie/tx.c
  15225. @@ -0,0 +1,1396 @@
  15226. +/*
  15227. + * Copyright (C) 2006-2018, Marvell International Ltd.
  15228. + *
  15229. + * This software file (the "File") is distributed by Marvell International
  15230. + * Ltd. under the terms of the GNU General Public License Version 2, June 1991
  15231. + * (the "License"). You may use, redistribute and/or modify this File in
  15232. + * accordance with the terms and conditions of the License, a copy of which
  15233. + * is available by writing to the Free Software Foundation, Inc.
  15234. + *
  15235. + * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
  15236. + * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
  15237. + * ARE EXPRESSLY DISCLAIMED. The License provides additional details about
  15238. + * this warranty disclaimer.
  15239. + */
  15240. +
  15241. +/* Description: This file implements transmit related functions. */
  15242. +
  15243. +#include <linux/etherdevice.h>
  15244. +#include <linux/skbuff.h>
  15245. +
  15246. +#include "sysadpt.h"
  15247. +#include "core.h"
  15248. +#include "utils.h"
  15249. +#include "hif/fwcmd.h"
  15250. +#include "hif/pcie/dev.h"
  15251. +#include "hif/pcie/tx.h"
  15252. +
  15253. +#define MAX_NUM_TX_RING_BYTES (PCIE_MAX_NUM_TX_DESC * \
  15254. + sizeof(struct pcie_tx_desc))
  15255. +
  15256. +#define MAX_NUM_TX_HNDL_BYTES (PCIE_MAX_NUM_TX_DESC * \
  15257. + sizeof(struct pcie_tx_hndl))
  15258. +
  15259. +#define TOTAL_HW_QUEUES (SYSADPT_TX_WMM_QUEUES + \
  15260. + PCIE_AMPDU_QUEUES)
  15261. +
  15262. +#define EAGLE_TXD_XMITCTRL_USE_MC_RATE 0x8 /* Use multicast data rate */
  15263. +
  15264. +#define MWL_QOS_ACK_POLICY_MASK 0x0060
  15265. +#define MWL_QOS_ACK_POLICY_NORMAL 0x0000
  15266. +#define MWL_QOS_ACK_POLICY_BLOCKACK 0x0060
  15267. +
  15268. +#define EXT_IV 0x20
  15269. +#define INCREASE_IV(iv16, iv32) \
  15270. +{ \
  15271. + (iv16)++; \
  15272. + if ((iv16) == 0) \
  15273. + (iv32)++; \
  15274. +}
  15275. +
  15276. +/* Transmission information to transmit a socket buffer. */
  15277. +struct pcie_tx_ctrl {
  15278. + void *vif;
  15279. + void *sta;
  15280. + void *k_conf;
  15281. + void *amsdu_pkts;
  15282. + u8 tx_priority;
  15283. + u8 type;
  15284. + u16 qos_ctrl;
  15285. + u8 xmit_control;
  15286. +};
  15287. +
  15288. +struct ccmp_hdr {
  15289. + __le16 iv16;
  15290. + u8 rsvd;
  15291. + u8 key_id;
  15292. + __le32 iv32;
  15293. +} __packed;
  15294. +
  15295. +static int pcie_tx_ring_alloc(struct mwl_priv *priv)
  15296. +{
  15297. + struct pcie_priv *pcie_priv = priv->hif.priv;
  15298. + struct pcie_desc_data *desc;
  15299. + int num;
  15300. + u8 *mem;
  15301. +
  15302. + desc = &pcie_priv->desc_data[0];
  15303. +
  15304. + mem = dma_alloc_coherent(priv->dev,
  15305. + MAX_NUM_TX_RING_BYTES *
  15306. + PCIE_NUM_OF_DESC_DATA,
  15307. + &desc->pphys_tx_ring,
  15308. + GFP_KERNEL);
  15309. +
  15310. + if (!mem) {
  15311. + wiphy_err(priv->hw->wiphy, "cannot alloc mem\n");
  15312. + return -ENOMEM;
  15313. + }
  15314. +
  15315. + for (num = 0; num < PCIE_NUM_OF_DESC_DATA; num++) {
  15316. + desc = &pcie_priv->desc_data[num];
  15317. +
  15318. + desc->ptx_ring = (struct pcie_tx_desc *)
  15319. + (mem + num * MAX_NUM_TX_RING_BYTES);
  15320. +
  15321. + desc->pphys_tx_ring = (dma_addr_t)
  15322. + ((u32)pcie_priv->desc_data[0].pphys_tx_ring +
  15323. + num * MAX_NUM_TX_RING_BYTES);
  15324. +
  15325. + memset(desc->ptx_ring, 0x00,
  15326. + MAX_NUM_TX_RING_BYTES);
  15327. + }
  15328. +
  15329. + mem = kzalloc(MAX_NUM_TX_HNDL_BYTES * PCIE_NUM_OF_DESC_DATA,
  15330. + GFP_KERNEL);
  15331. +
  15332. + if (!mem) {
  15333. + wiphy_err(priv->hw->wiphy, "cannot alloc mem\n");
  15334. + dma_free_coherent(priv->dev,
  15335. + MAX_NUM_TX_RING_BYTES *
  15336. + PCIE_NUM_OF_DESC_DATA,
  15337. + pcie_priv->desc_data[0].ptx_ring,
  15338. + pcie_priv->desc_data[0].pphys_tx_ring);
  15339. + return -ENOMEM;
  15340. + }
  15341. +
  15342. + for (num = 0; num < PCIE_NUM_OF_DESC_DATA; num++) {
  15343. + desc = &pcie_priv->desc_data[num];
  15344. +
  15345. + desc->tx_hndl = (struct pcie_tx_hndl *)
  15346. + (mem + num * MAX_NUM_TX_HNDL_BYTES);
  15347. + }
  15348. +
  15349. + return 0;
  15350. +}
  15351. +
  15352. +static int pcie_txbd_ring_create(struct mwl_priv *priv)
  15353. +{
  15354. + struct pcie_priv *pcie_priv = priv->hif.priv;
  15355. + int num;
  15356. + u8 *mem;
  15357. +
  15358. + /* driver maintaines the write pointer and firmware maintaines the read
  15359. + * pointer.
  15360. + */
  15361. + pcie_priv->txbd_wrptr = 0;
  15362. + pcie_priv->txbd_rdptr = 0;
  15363. +
  15364. + /* allocate shared memory for the BD ring and divide the same in to
  15365. + * several descriptors
  15366. + */
  15367. + pcie_priv->txbd_ring_size =
  15368. + sizeof(struct pcie_data_buf) * PCIE_MAX_TXRX_BD;
  15369. + wiphy_info(priv->hw->wiphy, "TX ring: allocating %d bytes\n",
  15370. + pcie_priv->txbd_ring_size);
  15371. +
  15372. + mem = dma_alloc_coherent(priv->dev,
  15373. + pcie_priv->txbd_ring_size,
  15374. + &pcie_priv->txbd_ring_pbase,
  15375. + GFP_KERNEL);
  15376. +
  15377. + if (!mem) {
  15378. + wiphy_err(priv->hw->wiphy, "cannot alloc mem\n");
  15379. + return -ENOMEM;
  15380. + }
  15381. + pcie_priv->txbd_ring_vbase = mem;
  15382. + wiphy_info(priv->hw->wiphy,
  15383. + "TX ring: - base: %p, pbase: 0x%x, len: %d\n",
  15384. + pcie_priv->txbd_ring_vbase,
  15385. + pcie_priv->txbd_ring_pbase,
  15386. + pcie_priv->txbd_ring_size);
  15387. +
  15388. + for (num = 0; num < PCIE_MAX_TXRX_BD; num++) {
  15389. + pcie_priv->txbd_ring[num] =
  15390. + (struct pcie_data_buf *)(pcie_priv->txbd_ring_vbase +
  15391. + (sizeof(struct pcie_data_buf) * num));
  15392. + pcie_priv->txbd_ring[num]->flags = 0;
  15393. + pcie_priv->txbd_ring[num]->offset = 0;
  15394. + pcie_priv->txbd_ring[num]->frag_len = 0;
  15395. + pcie_priv->txbd_ring[num]->len = 0;
  15396. + pcie_priv->txbd_ring[num]->paddr = 0;
  15397. + pcie_priv->tx_buf_list[num] = NULL;
  15398. + }
  15399. +
  15400. + return 0;
  15401. +}
  15402. +
  15403. +static int pcie_tx_ring_init(struct mwl_priv *priv)
  15404. +{
  15405. + struct pcie_priv *pcie_priv = priv->hif.priv;
  15406. + int num, i;
  15407. + struct pcie_desc_data *desc;
  15408. +
  15409. + for (num = 0; num < PCIE_NUM_OF_DESC_DATA; num++) {
  15410. + skb_queue_head_init(&pcie_priv->txq[num]);
  15411. + pcie_priv->fw_desc_cnt[num] = 0;
  15412. +
  15413. + if (priv->chip_type == MWL8997)
  15414. + continue;
  15415. +
  15416. + desc = &pcie_priv->desc_data[num];
  15417. +
  15418. + if (desc->ptx_ring) {
  15419. + for (i = 0; i < PCIE_MAX_NUM_TX_DESC; i++) {
  15420. + desc->ptx_ring[i].status =
  15421. + cpu_to_le32(EAGLE_TXD_STATUS_IDLE);
  15422. + desc->ptx_ring[i].pphys_next =
  15423. + cpu_to_le32((u32)desc->pphys_tx_ring +
  15424. + ((i + 1) *
  15425. + sizeof(struct pcie_tx_desc)));
  15426. + desc->tx_hndl[i].pdesc =
  15427. + &desc->ptx_ring[i];
  15428. + if (i < PCIE_MAX_NUM_TX_DESC - 1)
  15429. + desc->tx_hndl[i].pnext =
  15430. + &desc->tx_hndl[i + 1];
  15431. + }
  15432. + desc->ptx_ring[PCIE_MAX_NUM_TX_DESC - 1].pphys_next =
  15433. + cpu_to_le32((u32)desc->pphys_tx_ring);
  15434. + desc->tx_hndl[PCIE_MAX_NUM_TX_DESC - 1].pnext =
  15435. + &desc->tx_hndl[0];
  15436. +
  15437. + desc->pstale_tx_hndl = &desc->tx_hndl[0];
  15438. + desc->pnext_tx_hndl = &desc->tx_hndl[0];
  15439. + } else {
  15440. + wiphy_err(priv->hw->wiphy, "no valid TX mem\n");
  15441. + return -ENOMEM;
  15442. + }
  15443. + }
  15444. +
  15445. + return 0;
  15446. +}
  15447. +
  15448. +static void pcie_tx_ring_cleanup(struct mwl_priv *priv)
  15449. +{
  15450. + struct pcie_priv *pcie_priv = priv->hif.priv;
  15451. + int cleaned_tx_desc = 0;
  15452. + int num, i;
  15453. + struct pcie_desc_data *desc;
  15454. +
  15455. + for (num = 0; num < PCIE_NUM_OF_DESC_DATA; num++) {
  15456. + skb_queue_purge(&pcie_priv->txq[num]);
  15457. + pcie_priv->fw_desc_cnt[num] = 0;
  15458. +
  15459. + if (priv->chip_type == MWL8997)
  15460. + continue;
  15461. +
  15462. + desc = &pcie_priv->desc_data[num];
  15463. +
  15464. + if (desc->ptx_ring) {
  15465. + for (i = 0; i < PCIE_MAX_NUM_TX_DESC; i++) {
  15466. + if (!desc->tx_hndl[i].psk_buff)
  15467. + continue;
  15468. +
  15469. + wiphy_debug(priv->hw->wiphy,
  15470. + "unmapped and free'd %i %p %x\n",
  15471. + i,
  15472. + desc->tx_hndl[i].psk_buff->data,
  15473. + le32_to_cpu(
  15474. + desc->ptx_ring[i].pkt_ptr));
  15475. + pci_unmap_single(pcie_priv->pdev,
  15476. + le32_to_cpu(
  15477. + desc->ptx_ring[i].pkt_ptr),
  15478. + desc->tx_hndl[i].psk_buff->len,
  15479. + PCI_DMA_TODEVICE);
  15480. + dev_kfree_skb_any(desc->tx_hndl[i].psk_buff);
  15481. + desc->ptx_ring[i].status =
  15482. + cpu_to_le32(EAGLE_TXD_STATUS_IDLE);
  15483. + desc->ptx_ring[i].pkt_ptr = 0;
  15484. + desc->ptx_ring[i].pkt_len = 0;
  15485. + desc->tx_hndl[i].psk_buff = NULL;
  15486. + cleaned_tx_desc++;
  15487. + }
  15488. + }
  15489. + }
  15490. +
  15491. + wiphy_info(priv->hw->wiphy, "cleaned %i TX descr\n", cleaned_tx_desc);
  15492. +}
  15493. +
  15494. +static void pcie_tx_ring_free(struct mwl_priv *priv)
  15495. +{
  15496. + struct pcie_priv *pcie_priv = priv->hif.priv;
  15497. + int num;
  15498. +
  15499. + if (pcie_priv->desc_data[0].ptx_ring) {
  15500. + dma_free_coherent(priv->dev,
  15501. + MAX_NUM_TX_RING_BYTES *
  15502. + PCIE_NUM_OF_DESC_DATA,
  15503. + pcie_priv->desc_data[0].ptx_ring,
  15504. + pcie_priv->desc_data[0].pphys_tx_ring);
  15505. + }
  15506. +
  15507. + for (num = 0; num < PCIE_NUM_OF_DESC_DATA; num++) {
  15508. + if (pcie_priv->desc_data[num].ptx_ring)
  15509. + pcie_priv->desc_data[num].ptx_ring = NULL;
  15510. + pcie_priv->desc_data[num].pstale_tx_hndl = NULL;
  15511. + pcie_priv->desc_data[num].pnext_tx_hndl = NULL;
  15512. + }
  15513. +
  15514. + kfree(pcie_priv->desc_data[0].tx_hndl);
  15515. +}
  15516. +
  15517. +static void pcie_txbd_ring_delete(struct mwl_priv *priv)
  15518. +{
  15519. + struct pcie_priv *pcie_priv = priv->hif.priv;
  15520. + struct sk_buff *skb;
  15521. + struct pcie_tx_desc *tx_desc;
  15522. + int num;
  15523. +
  15524. + if (pcie_priv->txbd_ring_vbase) {
  15525. + dma_free_coherent(priv->dev,
  15526. + pcie_priv->txbd_ring_size,
  15527. + pcie_priv->txbd_ring_vbase,
  15528. + pcie_priv->txbd_ring_pbase);
  15529. + }
  15530. +
  15531. + for (num = 0; num < PCIE_MAX_TXRX_BD; num++) {
  15532. + pcie_priv->txbd_ring[num] = NULL;
  15533. + if (pcie_priv->tx_buf_list[num]) {
  15534. + skb = pcie_priv->tx_buf_list[num];
  15535. + tx_desc = (struct pcie_tx_desc *)skb->data;
  15536. +
  15537. + pci_unmap_single(pcie_priv->pdev,
  15538. + le32_to_cpu(tx_desc->pkt_ptr),
  15539. + skb->len,
  15540. + PCI_DMA_TODEVICE);
  15541. + dev_kfree_skb_any(skb);
  15542. + }
  15543. + pcie_priv->tx_buf_list[num] = NULL;
  15544. + }
  15545. +
  15546. + pcie_priv->txbd_wrptr = 0;
  15547. + pcie_priv->txbd_rdptr = 0;
  15548. + pcie_priv->txbd_ring_size = 0;
  15549. + pcie_priv->txbd_ring_vbase = NULL;
  15550. + pcie_priv->txbd_ring_pbase = 0;
  15551. +}
  15552. +
  15553. +static inline void pcie_tx_add_ccmp_hdr(u8 *pccmp_hdr,
  15554. + u8 key_id, u16 iv16, u32 iv32)
  15555. +{
  15556. + struct ccmp_hdr *ccmp_h = (struct ccmp_hdr *)pccmp_hdr;
  15557. +
  15558. + ccmp_h->iv16 = cpu_to_le16(iv16);
  15559. + ccmp_h->rsvd = 0;
  15560. + ccmp_h->key_id = EXT_IV | (key_id << 6);
  15561. + ccmp_h->iv32 = cpu_to_le32(iv32);
  15562. +}
  15563. +
  15564. +static inline bool pcie_tx_available(struct mwl_priv *priv, int desc_num)
  15565. +{
  15566. + struct pcie_priv *pcie_priv = priv->hif.priv;
  15567. + struct pcie_tx_hndl *tx_hndl;
  15568. +
  15569. + if (priv->chip_type == MWL8997)
  15570. + return PCIE_TXBD_NOT_FULL(pcie_priv->txbd_wrptr,
  15571. + pcie_priv->txbd_rdptr);
  15572. +
  15573. + tx_hndl = pcie_priv->desc_data[desc_num].pnext_tx_hndl;
  15574. +
  15575. + if (!tx_hndl->pdesc)
  15576. + return false;
  15577. +
  15578. + if (tx_hndl->pdesc->status != EAGLE_TXD_STATUS_IDLE) {
  15579. + /* Interrupt F/W anyway */
  15580. + if (tx_hndl->pdesc->status &
  15581. + cpu_to_le32(EAGLE_TXD_STATUS_FW_OWNED))
  15582. + writel(MACREG_H2ARIC_BIT_PPA_READY,
  15583. + pcie_priv->iobase1 +
  15584. + MACREG_REG_H2A_INTERRUPT_EVENTS);
  15585. + return false;
  15586. + }
  15587. +
  15588. + return true;
  15589. +}
  15590. +
  15591. +static inline void pcie_tx_skb(struct mwl_priv *priv, int desc_num,
  15592. + struct sk_buff *tx_skb)
  15593. +{
  15594. + struct pcie_priv *pcie_priv = priv->hif.priv;
  15595. + struct ieee80211_tx_info *tx_info;
  15596. + struct pcie_tx_ctrl *tx_ctrl;
  15597. + struct pcie_tx_hndl *tx_hndl = NULL;
  15598. + struct pcie_tx_desc *tx_desc;
  15599. + struct ieee80211_sta *sta;
  15600. + struct ieee80211_vif *vif;
  15601. + struct mwl_vif *mwl_vif;
  15602. + struct ieee80211_key_conf *k_conf;
  15603. + bool ccmp = false;
  15604. + struct pcie_pfu_dma_data *pfu_dma_data;
  15605. + struct pcie_dma_data *dma_data;
  15606. + struct ieee80211_hdr *wh;
  15607. + dma_addr_t dma;
  15608. +
  15609. + if (WARN_ON(!tx_skb))
  15610. + return;
  15611. +
  15612. + tx_info = IEEE80211_SKB_CB(tx_skb);
  15613. + tx_ctrl = (struct pcie_tx_ctrl *)&tx_info->status;
  15614. + sta = (struct ieee80211_sta *)tx_ctrl->sta;
  15615. + vif = (struct ieee80211_vif *)tx_ctrl->vif;
  15616. + mwl_vif = mwl_dev_get_vif(vif);
  15617. + k_conf = (struct ieee80211_key_conf *)tx_ctrl->k_conf;
  15618. +
  15619. + pcie_tx_encapsulate_frame(priv, tx_skb, k_conf, &ccmp);
  15620. +
  15621. + if (priv->chip_type == MWL8997) {
  15622. + pfu_dma_data = (struct pcie_pfu_dma_data *)tx_skb->data;
  15623. + tx_desc = &pfu_dma_data->tx_desc;
  15624. + dma_data = &pfu_dma_data->dma_data;
  15625. + } else {
  15626. + tx_hndl = pcie_priv->desc_data[desc_num].pnext_tx_hndl;
  15627. + tx_hndl->psk_buff = tx_skb;
  15628. + tx_desc = tx_hndl->pdesc;
  15629. + dma_data = (struct pcie_dma_data *)tx_skb->data;
  15630. + }
  15631. + wh = &dma_data->wh;
  15632. +
  15633. + if (ieee80211_is_probe_resp(wh->frame_control) &&
  15634. + priv->dump_probe)
  15635. + wiphy_info(priv->hw->wiphy,
  15636. + "Probe Resp: %pM\n", wh->addr1);
  15637. +
  15638. + if (ieee80211_is_data(wh->frame_control) ||
  15639. + (ieee80211_is_mgmt(wh->frame_control) &&
  15640. + ieee80211_has_protected(wh->frame_control) &&
  15641. + !is_multicast_ether_addr(wh->addr1))) {
  15642. + if (is_multicast_ether_addr(wh->addr1)) {
  15643. + if (ccmp) {
  15644. + pcie_tx_add_ccmp_hdr(dma_data->data,
  15645. + mwl_vif->keyidx,
  15646. + mwl_vif->iv16,
  15647. + mwl_vif->iv32);
  15648. + INCREASE_IV(mwl_vif->iv16, mwl_vif->iv32);
  15649. + }
  15650. + } else {
  15651. + if (ccmp) {
  15652. + if (vif->type == NL80211_IFTYPE_STATION) {
  15653. + pcie_tx_add_ccmp_hdr(dma_data->data,
  15654. + mwl_vif->keyidx,
  15655. + mwl_vif->iv16,
  15656. + mwl_vif->iv32);
  15657. + INCREASE_IV(mwl_vif->iv16,
  15658. + mwl_vif->iv32);
  15659. + } else {
  15660. + struct mwl_sta *sta_info;
  15661. +
  15662. + sta_info = mwl_dev_get_sta(sta);
  15663. +
  15664. + pcie_tx_add_ccmp_hdr(dma_data->data,
  15665. + 0,
  15666. + sta_info->iv16,
  15667. + sta_info->iv32);
  15668. + INCREASE_IV(sta_info->iv16,
  15669. + sta_info->iv32);
  15670. + }
  15671. + }
  15672. + }
  15673. + }
  15674. +
  15675. + if (tx_info->flags & IEEE80211_TX_INTFL_DONT_ENCRYPT)
  15676. + tx_desc->flags |= PCIE_TX_WCB_FLAGS_DONT_ENCRYPT;
  15677. + if (tx_info->flags & IEEE80211_TX_CTL_NO_CCK_RATE)
  15678. + tx_desc->flags |= PCIE_TX_WCB_FLAGS_NO_CCK_RATE;
  15679. + tx_desc->tx_priority = tx_ctrl->tx_priority;
  15680. + tx_desc->qos_ctrl = cpu_to_le16(tx_ctrl->qos_ctrl);
  15681. + tx_desc->pkt_len = cpu_to_le16(tx_skb->len);
  15682. + tx_desc->packet_info = 0;
  15683. + tx_desc->data_rate = 0;
  15684. + tx_desc->type = tx_ctrl->type;
  15685. + tx_desc->xmit_control = tx_ctrl->xmit_control;
  15686. + tx_desc->sap_pkt_info = 0;
  15687. + dma = pci_map_single(pcie_priv->pdev, tx_skb->data,
  15688. + tx_skb->len, PCI_DMA_TODEVICE);
  15689. + if (pci_dma_mapping_error(pcie_priv->pdev, dma)) {
  15690. + dev_kfree_skb_any(tx_skb);
  15691. + wiphy_err(priv->hw->wiphy,
  15692. + "failed to map pci memory!\n");
  15693. + return;
  15694. + }
  15695. + if (priv->chip_type == MWL8997)
  15696. + tx_desc->pkt_ptr = cpu_to_le32(sizeof(struct pcie_tx_desc));
  15697. + else
  15698. + tx_desc->pkt_ptr = cpu_to_le32(dma);
  15699. + tx_desc->status = cpu_to_le32(EAGLE_TXD_STATUS_FW_OWNED);
  15700. + /* make sure all the memory transactions done by cpu were completed */
  15701. + wmb(); /*Data Memory Barrier*/
  15702. +
  15703. + if (priv->chip_type == MWL8997) {
  15704. + u32 wrindx;
  15705. + struct pcie_data_buf *data_buf;
  15706. + const u32 num_tx_buffs = PCIE_MAX_TXRX_BD << PCIE_TX_START_PTR;
  15707. +
  15708. + wrindx = (pcie_priv->txbd_wrptr & PCIE_TXBD_MASK) >>
  15709. + PCIE_TX_START_PTR;
  15710. + pcie_priv->tx_buf_list[wrindx] = tx_skb;
  15711. + data_buf = pcie_priv->txbd_ring[wrindx];
  15712. + data_buf->paddr = cpu_to_le64(dma);
  15713. + data_buf->len = cpu_to_le16(tx_skb->len);
  15714. + data_buf->flags = cpu_to_le16(PCIE_BD_FLAG_FIRST_DESC |
  15715. + PCIE_BD_FLAG_LAST_DESC);
  15716. + data_buf->frag_len = cpu_to_le16(tx_skb->len);
  15717. + data_buf->offset = 0;
  15718. + pcie_priv->txbd_wrptr += PCIE_BD_FLAG_TX_START_PTR;
  15719. +
  15720. + if ((pcie_priv->txbd_wrptr & PCIE_TXBD_MASK) == num_tx_buffs)
  15721. + pcie_priv->txbd_wrptr = ((pcie_priv->txbd_wrptr &
  15722. + PCIE_BD_FLAG_TX_ROLLOVER_IND) ^
  15723. + PCIE_BD_FLAG_TX_ROLLOVER_IND);
  15724. +
  15725. + /* Write the TX ring write pointer in to REG_TXBD_WRPTR */
  15726. + writel(pcie_priv->txbd_wrptr,
  15727. + pcie_priv->iobase1 + REG_TXBD_WRPTR);
  15728. + } else {
  15729. + writel(MACREG_H2ARIC_BIT_PPA_READY,
  15730. + pcie_priv->iobase1 + MACREG_REG_H2A_INTERRUPT_EVENTS);
  15731. + pcie_priv->desc_data[desc_num].pnext_tx_hndl = tx_hndl->pnext;
  15732. + pcie_priv->fw_desc_cnt[desc_num]++;
  15733. + }
  15734. +}
  15735. +
  15736. +static inline
  15737. +struct sk_buff *pcie_tx_do_amsdu(struct mwl_priv *priv,
  15738. + int desc_num,
  15739. + struct sk_buff *tx_skb,
  15740. + struct ieee80211_tx_info *tx_info)
  15741. +{
  15742. + struct pcie_priv *pcie_priv = priv->hif.priv;
  15743. + struct ieee80211_sta *sta;
  15744. + struct mwl_sta *sta_info;
  15745. + struct pcie_tx_ctrl *tx_ctrl = (struct pcie_tx_ctrl *)&tx_info->status;
  15746. + struct ieee80211_tx_info *amsdu_info;
  15747. + struct sk_buff_head *amsdu_pkts;
  15748. + struct mwl_amsdu_frag *amsdu;
  15749. + int amsdu_allow_size;
  15750. + struct ieee80211_hdr *wh;
  15751. + int wh_len;
  15752. + u16 len;
  15753. + u8 *data;
  15754. +
  15755. + sta = (struct ieee80211_sta *)tx_ctrl->sta;
  15756. + sta_info = mwl_dev_get_sta(sta);
  15757. +
  15758. + if (!sta_info->is_amsdu_allowed)
  15759. + return tx_skb;
  15760. +
  15761. + wh = (struct ieee80211_hdr *)tx_skb->data;
  15762. + if (sta_info->is_mesh_node && is_multicast_ether_addr(wh->addr3))
  15763. + return tx_skb;
  15764. +
  15765. + if (ieee80211_is_qos_nullfunc(wh->frame_control))
  15766. + return tx_skb;
  15767. +
  15768. + if (sta_info->amsdu_ctrl.cap == MWL_AMSDU_SIZE_4K)
  15769. + amsdu_allow_size = SYSADPT_AMSDU_4K_MAX_SIZE;
  15770. + else if (sta_info->amsdu_ctrl.cap == MWL_AMSDU_SIZE_8K)
  15771. + amsdu_allow_size = SYSADPT_AMSDU_8K_MAX_SIZE;
  15772. + else
  15773. + return tx_skb;
  15774. +
  15775. + spin_lock_bh(&sta_info->amsdu_lock);
  15776. + amsdu = &sta_info->amsdu_ctrl.frag[desc_num];
  15777. +
  15778. + if ((tx_skb->len > SYSADPT_AMSDU_ALLOW_SIZE) ||
  15779. + utils_is_non_amsdu_packet(tx_skb->data, true)) {
  15780. + if (amsdu->num) {
  15781. + pcie_tx_skb(priv, desc_num, amsdu->skb);
  15782. + amsdu->num = 0;
  15783. + amsdu->cur_pos = NULL;
  15784. + }
  15785. + spin_unlock_bh(&sta_info->amsdu_lock);
  15786. + return tx_skb;
  15787. + }
  15788. +
  15789. + /* potential amsdu size, should add amsdu header 14 bytes +
  15790. + * maximum padding 3.
  15791. + */
  15792. + wh_len = ieee80211_hdrlen(wh->frame_control);
  15793. + len = tx_skb->len - wh_len + 17;
  15794. +
  15795. + if (amsdu->num) {
  15796. + if ((amsdu->skb->len + len) > amsdu_allow_size) {
  15797. + pcie_tx_skb(priv, desc_num, amsdu->skb);
  15798. + amsdu->num = 0;
  15799. + amsdu->cur_pos = NULL;
  15800. + }
  15801. + }
  15802. +
  15803. + amsdu->jiffies = jiffies;
  15804. + len = tx_skb->len - wh_len;
  15805. +
  15806. + if (amsdu->num == 0) {
  15807. + struct sk_buff *newskb;
  15808. + int headroom;
  15809. +
  15810. + amsdu_pkts = (struct sk_buff_head *)
  15811. + kmalloc(sizeof(*amsdu_pkts), GFP_ATOMIC);
  15812. + if (!amsdu_pkts) {
  15813. + spin_unlock_bh(&sta_info->amsdu_lock);
  15814. + return tx_skb;
  15815. + }
  15816. + newskb = dev_alloc_skb(amsdu_allow_size +
  15817. + pcie_priv->tx_head_room);
  15818. + if (!newskb) {
  15819. + spin_unlock_bh(&sta_info->amsdu_lock);
  15820. + kfree(amsdu_pkts);
  15821. + return tx_skb;
  15822. + }
  15823. +
  15824. + headroom = skb_headroom(newskb);
  15825. + if (headroom < pcie_priv->tx_head_room)
  15826. + skb_reserve(newskb,
  15827. + (pcie_priv->tx_head_room - headroom));
  15828. +
  15829. + data = newskb->data;
  15830. + memcpy(data, tx_skb->data, wh_len);
  15831. + if (sta_info->is_mesh_node) {
  15832. + ether_addr_copy(data + wh_len, wh->addr3);
  15833. + ether_addr_copy(data + wh_len + ETH_ALEN, wh->addr4);
  15834. + } else {
  15835. + ether_addr_copy(data + wh_len,
  15836. + ieee80211_get_DA(wh));
  15837. + ether_addr_copy(data + wh_len + ETH_ALEN,
  15838. + ieee80211_get_SA(wh));
  15839. + }
  15840. + *(u8 *)(data + wh_len + ETH_HLEN - 1) = len & 0xff;
  15841. + *(u8 *)(data + wh_len + ETH_HLEN - 2) = (len >> 8) & 0xff;
  15842. + memcpy(data + wh_len + ETH_HLEN, tx_skb->data + wh_len, len);
  15843. +
  15844. + skb_put(newskb, tx_skb->len + ETH_HLEN);
  15845. + tx_ctrl->qos_ctrl |= IEEE80211_QOS_CTL_A_MSDU_PRESENT;
  15846. + amsdu_info = IEEE80211_SKB_CB(newskb);
  15847. + memcpy(amsdu_info, tx_info, sizeof(*tx_info));
  15848. + skb_queue_head_init(amsdu_pkts);
  15849. + ((struct pcie_tx_ctrl *)&amsdu_info->status)->amsdu_pkts =
  15850. + (void *)amsdu_pkts;
  15851. + amsdu->skb = newskb;
  15852. + } else {
  15853. + amsdu->cur_pos += amsdu->pad;
  15854. + data = amsdu->cur_pos;
  15855. +
  15856. + if (sta_info->is_mesh_node) {
  15857. + ether_addr_copy(data, wh->addr3);
  15858. + ether_addr_copy(data + ETH_ALEN, wh->addr4);
  15859. + } else {
  15860. + ether_addr_copy(data, ieee80211_get_DA(wh));
  15861. + ether_addr_copy(data + ETH_ALEN, ieee80211_get_SA(wh));
  15862. + }
  15863. + *(u8 *)(data + ETH_HLEN - 1) = len & 0xff;
  15864. + *(u8 *)(data + ETH_HLEN - 2) = (len >> 8) & 0xff;
  15865. + memcpy(data + ETH_HLEN, tx_skb->data + wh_len, len);
  15866. +
  15867. + skb_put(amsdu->skb, len + ETH_HLEN + amsdu->pad);
  15868. + amsdu_info = IEEE80211_SKB_CB(amsdu->skb);
  15869. + amsdu_pkts = (struct sk_buff_head *)
  15870. + ((struct pcie_tx_ctrl *)
  15871. + &amsdu_info->status)->amsdu_pkts;
  15872. + }
  15873. +
  15874. + amsdu->num++;
  15875. + amsdu->pad = ((len + ETH_HLEN) % 4) ? (4 - (len + ETH_HLEN) % 4) : 0;
  15876. + amsdu->cur_pos = amsdu->skb->data + amsdu->skb->len;
  15877. + skb_queue_tail(amsdu_pkts, tx_skb);
  15878. +
  15879. + if (amsdu->num > SYSADPT_AMSDU_PACKET_THRESHOLD) {
  15880. + amsdu->num = 0;
  15881. + amsdu->cur_pos = NULL;
  15882. + spin_unlock_bh(&sta_info->amsdu_lock);
  15883. + return amsdu->skb;
  15884. + }
  15885. +
  15886. + spin_unlock_bh(&sta_info->amsdu_lock);
  15887. + return NULL;
  15888. +}
  15889. +
  15890. +static inline void pcie_tx_ack_amsdu_pkts(struct ieee80211_hw *hw, u32 rate,
  15891. + struct sk_buff_head *amsdu_pkts)
  15892. +{
  15893. + struct sk_buff *amsdu_pkt;
  15894. + struct ieee80211_tx_info *info;
  15895. +
  15896. + while (skb_queue_len(amsdu_pkts) > 0) {
  15897. + amsdu_pkt = skb_dequeue(amsdu_pkts);
  15898. + info = IEEE80211_SKB_CB(amsdu_pkt);
  15899. + pcie_tx_prepare_info(hw->priv, rate, info);
  15900. + ieee80211_tx_status(hw, amsdu_pkt);
  15901. + }
  15902. +
  15903. + kfree(amsdu_pkts);
  15904. +}
  15905. +
  15906. +static void pcie_pfu_tx_done(struct mwl_priv *priv)
  15907. +{
  15908. + struct pcie_priv *pcie_priv = priv->hif.priv;
  15909. + u32 wrdoneidx, rdptr;
  15910. + const u32 num_tx_buffs = PCIE_MAX_TXRX_BD << PCIE_TX_START_PTR;
  15911. + struct pcie_data_buf *data_buf;
  15912. + struct sk_buff *done_skb;
  15913. + struct pcie_pfu_dma_data *pfu_dma;
  15914. + struct pcie_tx_desc *tx_desc;
  15915. + struct pcie_dma_data *dma_data;
  15916. + struct ieee80211_hdr *wh;
  15917. + struct ieee80211_tx_info *info;
  15918. + struct pcie_tx_ctrl *tx_ctrl;
  15919. + struct ieee80211_sta *sta;
  15920. + struct mwl_sta *sta_info;
  15921. + u32 rate = 0;
  15922. + struct sk_buff_head *amsdu_pkts;
  15923. + int hdrlen;
  15924. +
  15925. + spin_lock_bh(&pcie_priv->tx_desc_lock);
  15926. + /* Read the TX ring read pointer set by firmware */
  15927. + rdptr = readl(pcie_priv->iobase1 + REG_TXBD_RDPTR);
  15928. + /* free from previous txbd_rdptr to current txbd_rdptr */
  15929. + while (((pcie_priv->txbd_rdptr & PCIE_TXBD_MASK) !=
  15930. + (rdptr & PCIE_TXBD_MASK)) ||
  15931. + ((pcie_priv->txbd_rdptr & PCIE_BD_FLAG_TX_ROLLOVER_IND) !=
  15932. + (rdptr & PCIE_BD_FLAG_TX_ROLLOVER_IND))) {
  15933. + wrdoneidx = pcie_priv->txbd_rdptr & PCIE_TXBD_MASK;
  15934. + wrdoneidx >>= PCIE_TX_START_PTR;
  15935. +
  15936. + data_buf = pcie_priv->txbd_ring[wrdoneidx];
  15937. + done_skb = pcie_priv->tx_buf_list[wrdoneidx];
  15938. + if (done_skb) {
  15939. + pfu_dma = (struct pcie_pfu_dma_data *)done_skb->data;
  15940. + tx_desc = &pfu_dma->tx_desc;
  15941. + dma_data = &pfu_dma->dma_data;
  15942. + pci_unmap_single(pcie_priv->pdev,
  15943. + le32_to_cpu(data_buf->paddr),
  15944. + le16_to_cpu(data_buf->len),
  15945. + PCI_DMA_TODEVICE);
  15946. + tx_desc->pkt_ptr = 0;
  15947. + tx_desc->pkt_len = 0;
  15948. + tx_desc->status = cpu_to_le32(EAGLE_TXD_STATUS_IDLE);
  15949. + wmb(); /* memory barrier */
  15950. +
  15951. + wh = &dma_data->wh;
  15952. + if (ieee80211_is_nullfunc(wh->frame_control) ||
  15953. + ieee80211_is_qos_nullfunc(wh->frame_control)) {
  15954. + dev_kfree_skb_any(done_skb);
  15955. + done_skb = NULL;
  15956. + goto next;
  15957. + }
  15958. +
  15959. + info = IEEE80211_SKB_CB(done_skb);
  15960. + tx_ctrl = (struct pcie_tx_ctrl *)&info->status;
  15961. + sta = (struct ieee80211_sta *)tx_ctrl->sta;
  15962. + if (sta) {
  15963. + sta_info = mwl_dev_get_sta(sta);
  15964. + rate = sta_info->tx_rate_info;
  15965. + }
  15966. +
  15967. + if (ieee80211_is_data(wh->frame_control) ||
  15968. + ieee80211_is_data_qos(wh->frame_control)) {
  15969. + amsdu_pkts = (struct sk_buff_head *)
  15970. + tx_ctrl->amsdu_pkts;
  15971. + if (amsdu_pkts) {
  15972. + pcie_tx_ack_amsdu_pkts(priv->hw, rate,
  15973. + amsdu_pkts);
  15974. + dev_kfree_skb_any(done_skb);
  15975. + done_skb = NULL;
  15976. + } else {
  15977. + pcie_tx_prepare_info(priv, rate, info);
  15978. + }
  15979. + } else {
  15980. + pcie_tx_prepare_info(priv, 0, info);
  15981. + }
  15982. +
  15983. + if (done_skb) {
  15984. + /* Remove H/W dma header */
  15985. + hdrlen = ieee80211_hdrlen(
  15986. + dma_data->wh.frame_control);
  15987. + memmove(dma_data->data - hdrlen,
  15988. + &dma_data->wh, hdrlen);
  15989. + skb_pull(done_skb, sizeof(*pfu_dma) - hdrlen);
  15990. + ieee80211_tx_status(priv->hw, done_skb);
  15991. + }
  15992. + }
  15993. +next:
  15994. + memset(data_buf, 0, sizeof(*data_buf));
  15995. + pcie_priv->tx_buf_list[wrdoneidx] = NULL;
  15996. +
  15997. + pcie_priv->txbd_rdptr += PCIE_BD_FLAG_TX_START_PTR;
  15998. + if ((pcie_priv->txbd_rdptr & PCIE_TXBD_MASK) == num_tx_buffs)
  15999. + pcie_priv->txbd_rdptr = ((pcie_priv->txbd_rdptr &
  16000. + PCIE_BD_FLAG_TX_ROLLOVER_IND) ^
  16001. + PCIE_BD_FLAG_TX_ROLLOVER_IND);
  16002. + }
  16003. + spin_unlock_bh(&pcie_priv->tx_desc_lock);
  16004. +
  16005. + if (pcie_priv->is_tx_done_schedule) {
  16006. + pcie_mask_int(pcie_priv, MACREG_A2HRIC_BIT_TX_DONE, true);
  16007. + tasklet_schedule(&pcie_priv->tx_task);
  16008. + pcie_priv->is_tx_done_schedule = false;
  16009. + }
  16010. +}
  16011. +
  16012. +static void pcie_non_pfu_tx_done(struct mwl_priv *priv)
  16013. +{
  16014. + struct pcie_priv *pcie_priv = priv->hif.priv;
  16015. + int num;
  16016. + struct pcie_desc_data *desc;
  16017. + struct pcie_tx_hndl *tx_hndl;
  16018. + struct pcie_tx_desc *tx_desc;
  16019. + struct sk_buff *done_skb;
  16020. + int idx;
  16021. + u32 rate;
  16022. + struct pcie_dma_data *dma_data;
  16023. + struct ieee80211_hdr *wh;
  16024. + struct ieee80211_tx_info *info;
  16025. + struct pcie_tx_ctrl *tx_ctrl;
  16026. + struct sk_buff_head *amsdu_pkts;
  16027. + int hdrlen;
  16028. +
  16029. + spin_lock_bh(&pcie_priv->tx_desc_lock);
  16030. + for (num = 0; num < SYSADPT_TX_WMM_QUEUES; num++) {
  16031. + desc = &pcie_priv->desc_data[num];
  16032. + tx_hndl = desc->pstale_tx_hndl;
  16033. + tx_desc = tx_hndl->pdesc;
  16034. +
  16035. + if ((tx_desc->status &
  16036. + cpu_to_le32(EAGLE_TXD_STATUS_FW_OWNED)) &&
  16037. + (tx_hndl->pnext->pdesc->status &
  16038. + cpu_to_le32(EAGLE_TXD_STATUS_OK)))
  16039. + tx_desc->status = cpu_to_le32(EAGLE_TXD_STATUS_OK);
  16040. +
  16041. + while (tx_hndl &&
  16042. + (tx_desc->status & cpu_to_le32(EAGLE_TXD_STATUS_OK)) &&
  16043. + (!(tx_desc->status &
  16044. + cpu_to_le32(EAGLE_TXD_STATUS_FW_OWNED)))) {
  16045. + pci_unmap_single(pcie_priv->pdev,
  16046. + le32_to_cpu(tx_desc->pkt_ptr),
  16047. + le16_to_cpu(tx_desc->pkt_len),
  16048. + PCI_DMA_TODEVICE);
  16049. + done_skb = tx_hndl->psk_buff;
  16050. + rate = le32_to_cpu(tx_desc->rate_info);
  16051. + tx_desc->pkt_ptr = 0;
  16052. + tx_desc->pkt_len = 0;
  16053. + tx_desc->status =
  16054. + cpu_to_le32(EAGLE_TXD_STATUS_IDLE);
  16055. + tx_hndl->psk_buff = NULL;
  16056. + wmb(); /*Data Memory Barrier*/
  16057. +
  16058. + skb_get(done_skb);
  16059. + idx = pcie_priv->delay_q_idx;
  16060. + if (pcie_priv->delay_q[idx])
  16061. + dev_kfree_skb_any(pcie_priv->delay_q[idx]);
  16062. + pcie_priv->delay_q[idx] = done_skb;
  16063. + idx++;
  16064. + if (idx >= PCIE_DELAY_FREE_Q_LIMIT)
  16065. + idx = 0;
  16066. + pcie_priv->delay_q_idx = idx;
  16067. +
  16068. + dma_data = (struct pcie_dma_data *)done_skb->data;
  16069. + wh = &dma_data->wh;
  16070. + if (ieee80211_is_nullfunc(wh->frame_control) ||
  16071. + ieee80211_is_qos_nullfunc(wh->frame_control)) {
  16072. + dev_kfree_skb_any(done_skb);
  16073. + done_skb = NULL;
  16074. + goto next;
  16075. + }
  16076. +
  16077. + info = IEEE80211_SKB_CB(done_skb);
  16078. + if (ieee80211_is_data(wh->frame_control) ||
  16079. + ieee80211_is_data_qos(wh->frame_control)) {
  16080. + tx_ctrl = (struct pcie_tx_ctrl *)&info->status;
  16081. + amsdu_pkts = (struct sk_buff_head *)
  16082. + tx_ctrl->amsdu_pkts;
  16083. + if (amsdu_pkts) {
  16084. + pcie_tx_ack_amsdu_pkts(priv->hw, rate,
  16085. + amsdu_pkts);
  16086. + dev_kfree_skb_any(done_skb);
  16087. + done_skb = NULL;
  16088. + } else {
  16089. + pcie_tx_prepare_info(priv, rate, info);
  16090. + }
  16091. + } else {
  16092. + pcie_tx_prepare_info(priv, 0, info);
  16093. + }
  16094. +
  16095. + if (done_skb) {
  16096. + /* Remove H/W dma header */
  16097. + hdrlen = ieee80211_hdrlen(
  16098. + dma_data->wh.frame_control);
  16099. + memmove(dma_data->data - hdrlen,
  16100. + &dma_data->wh, hdrlen);
  16101. + skb_pull(done_skb, sizeof(*dma_data) - hdrlen);
  16102. + ieee80211_tx_status(priv->hw, done_skb);
  16103. + }
  16104. +next:
  16105. + tx_hndl = tx_hndl->pnext;
  16106. + tx_desc = tx_hndl->pdesc;
  16107. + pcie_priv->fw_desc_cnt[num]--;
  16108. + }
  16109. +
  16110. + desc->pstale_tx_hndl = tx_hndl;
  16111. + }
  16112. + spin_unlock_bh(&pcie_priv->tx_desc_lock);
  16113. +
  16114. + if (pcie_priv->is_tx_done_schedule) {
  16115. + pcie_mask_int(pcie_priv, MACREG_A2HRIC_BIT_TX_DONE, true);
  16116. + tasklet_schedule(&pcie_priv->tx_task);
  16117. + pcie_priv->is_tx_done_schedule = false;
  16118. + }
  16119. +}
  16120. +
  16121. +int pcie_tx_init(struct ieee80211_hw *hw)
  16122. +{
  16123. + struct mwl_priv *priv = hw->priv;
  16124. + struct pcie_priv *pcie_priv = priv->hif.priv;
  16125. + int rc;
  16126. + int i;
  16127. +
  16128. + if (priv->chip_type == MWL8997)
  16129. + rc = pcie_txbd_ring_create(priv);
  16130. + else
  16131. + rc = pcie_tx_ring_alloc(priv);
  16132. +
  16133. + if (rc) {
  16134. + wiphy_err(hw->wiphy, "allocating TX ring failed\n");
  16135. + return rc;
  16136. + }
  16137. +
  16138. + rc = pcie_tx_ring_init(priv);
  16139. + if (rc) {
  16140. + pcie_tx_ring_free(priv);
  16141. + wiphy_err(hw->wiphy, "initializing TX ring failed\n");
  16142. + return rc;
  16143. + }
  16144. +
  16145. + pcie_priv->delay_q_idx = 0;
  16146. + for (i = 0; i < PCIE_DELAY_FREE_Q_LIMIT; i++)
  16147. + pcie_priv->delay_q[i] = NULL;
  16148. +
  16149. + return 0;
  16150. +}
  16151. +
  16152. +void pcie_tx_deinit(struct ieee80211_hw *hw)
  16153. +{
  16154. + struct mwl_priv *priv = hw->priv;
  16155. + struct pcie_priv *pcie_priv = priv->hif.priv;
  16156. + int i;
  16157. +
  16158. + for (i = 0; i < PCIE_DELAY_FREE_Q_LIMIT; i++)
  16159. + if (pcie_priv->delay_q[i])
  16160. + dev_kfree_skb_any(pcie_priv->delay_q[i]);
  16161. +
  16162. + pcie_tx_ring_cleanup(priv);
  16163. +
  16164. + if (priv->chip_type == MWL8997)
  16165. + pcie_txbd_ring_delete(priv);
  16166. + else
  16167. + pcie_tx_ring_free(priv);
  16168. +}
  16169. +
  16170. +void pcie_tx_skbs(unsigned long data)
  16171. +{
  16172. + struct ieee80211_hw *hw = (struct ieee80211_hw *)data;
  16173. + struct mwl_priv *priv = hw->priv;
  16174. + struct pcie_priv *pcie_priv = priv->hif.priv;
  16175. + int num = SYSADPT_TX_WMM_QUEUES;
  16176. + struct sk_buff *tx_skb;
  16177. +
  16178. + spin_lock_bh(&pcie_priv->tx_desc_lock);
  16179. + while (num--) {
  16180. + while (skb_queue_len(&pcie_priv->txq[num]) > 0) {
  16181. + struct ieee80211_tx_info *tx_info;
  16182. + struct pcie_tx_ctrl *tx_ctrl;
  16183. +
  16184. + if (!pcie_tx_available(priv, num))
  16185. + break;
  16186. +
  16187. + tx_skb = skb_dequeue(&pcie_priv->txq[num]);
  16188. + if (!tx_skb)
  16189. + continue;
  16190. + tx_info = IEEE80211_SKB_CB(tx_skb);
  16191. + tx_ctrl = (struct pcie_tx_ctrl *)&tx_info->status;
  16192. +
  16193. + if (tx_ctrl->tx_priority >= SYSADPT_TX_WMM_QUEUES)
  16194. + tx_skb = pcie_tx_do_amsdu(priv, num,
  16195. + tx_skb, tx_info);
  16196. +
  16197. + if (tx_skb) {
  16198. + if (pcie_tx_available(priv, num))
  16199. + pcie_tx_skb(priv, num, tx_skb);
  16200. + else
  16201. + skb_queue_head(&pcie_priv->txq[num],
  16202. + tx_skb);
  16203. + }
  16204. + }
  16205. +
  16206. + if (skb_queue_len(&pcie_priv->txq[num]) <
  16207. + pcie_priv->txq_wake_threshold) {
  16208. + int queue;
  16209. +
  16210. + queue = SYSADPT_TX_WMM_QUEUES - num - 1;
  16211. + if (ieee80211_queue_stopped(hw, queue))
  16212. + ieee80211_wake_queue(hw, queue);
  16213. + }
  16214. + }
  16215. + spin_unlock_bh(&pcie_priv->tx_desc_lock);
  16216. +}
  16217. +
  16218. +void pcie_tx_flush_amsdu(unsigned long data)
  16219. +{
  16220. + struct ieee80211_hw *hw = (struct ieee80211_hw *)data;
  16221. + struct mwl_priv *priv = hw->priv;
  16222. + struct pcie_priv *pcie_priv = priv->hif.priv;
  16223. + struct mwl_sta *sta_info;
  16224. + int i;
  16225. + struct mwl_amsdu_frag *amsdu_frag;
  16226. +
  16227. + spin_lock(&priv->sta_lock);
  16228. + list_for_each_entry(sta_info, &priv->sta_list, list) {
  16229. + spin_lock(&pcie_priv->tx_desc_lock);
  16230. + spin_lock(&sta_info->amsdu_lock);
  16231. + for (i = 0; i < SYSADPT_TX_WMM_QUEUES; i++) {
  16232. + amsdu_frag = &sta_info->amsdu_ctrl.frag[i];
  16233. + if (amsdu_frag->num) {
  16234. + if (time_after(jiffies,
  16235. + (amsdu_frag->jiffies + 1))) {
  16236. + if (pcie_tx_available(priv, i)) {
  16237. + pcie_tx_skb(priv, i,
  16238. + amsdu_frag->skb);
  16239. + amsdu_frag->num = 0;
  16240. + amsdu_frag->cur_pos = NULL;
  16241. + }
  16242. + }
  16243. + }
  16244. + }
  16245. + spin_unlock(&sta_info->amsdu_lock);
  16246. + spin_unlock(&pcie_priv->tx_desc_lock);
  16247. + }
  16248. + spin_unlock(&priv->sta_lock);
  16249. +
  16250. + pcie_mask_int(pcie_priv, MACREG_A2HRIC_BIT_QUE_EMPTY, true);
  16251. + pcie_priv->is_qe_schedule = false;
  16252. +}
  16253. +
  16254. +void pcie_tx_done(unsigned long data)
  16255. +{
  16256. + struct ieee80211_hw *hw = (struct ieee80211_hw *)data;
  16257. + struct mwl_priv *priv = hw->priv;
  16258. +
  16259. + if (priv->chip_type == MWL8997)
  16260. + pcie_pfu_tx_done(priv);
  16261. + else
  16262. + pcie_non_pfu_tx_done(priv);
  16263. +}
  16264. +
  16265. +void pcie_tx_xmit(struct ieee80211_hw *hw,
  16266. + struct ieee80211_tx_control *control,
  16267. + struct sk_buff *skb)
  16268. +{
  16269. + struct mwl_priv *priv = hw->priv;
  16270. + struct pcie_priv *pcie_priv = priv->hif.priv;
  16271. + int index;
  16272. + struct ieee80211_sta *sta;
  16273. + struct ieee80211_tx_info *tx_info;
  16274. + struct mwl_vif *mwl_vif;
  16275. + struct ieee80211_hdr *wh;
  16276. + u8 xmitcontrol;
  16277. + u16 qos;
  16278. + int txpriority;
  16279. + u8 tid = 0;
  16280. + struct mwl_ampdu_stream *stream = NULL;
  16281. + bool start_ba_session = false;
  16282. + bool mgmtframe = false;
  16283. + struct ieee80211_mgmt *mgmt;
  16284. + bool eapol_frame = false;
  16285. + struct pcie_tx_ctrl *tx_ctrl;
  16286. + struct ieee80211_key_conf *k_conf = NULL;
  16287. + int rc;
  16288. +
  16289. + index = skb_get_queue_mapping(skb);
  16290. + sta = control->sta;
  16291. +
  16292. + wh = (struct ieee80211_hdr *)skb->data;
  16293. + tx_info = IEEE80211_SKB_CB(skb);
  16294. + mwl_vif = mwl_dev_get_vif(tx_info->control.vif);
  16295. +
  16296. + if (ieee80211_is_data_qos(wh->frame_control))
  16297. + qos = le16_to_cpu(*((__le16 *)ieee80211_get_qos_ctl(wh)));
  16298. + else
  16299. + qos = 0;
  16300. +
  16301. + if (ieee80211_is_mgmt(wh->frame_control)) {
  16302. + mgmtframe = true;
  16303. + mgmt = (struct ieee80211_mgmt *)skb->data;
  16304. + } else {
  16305. + u16 pkt_type;
  16306. + struct mwl_sta *sta_info;
  16307. +
  16308. + pkt_type = be16_to_cpu(*((__be16 *)
  16309. + &skb->data[ieee80211_hdrlen(wh->frame_control) + 6]));
  16310. + if (pkt_type == ETH_P_PAE) {
  16311. + index = IEEE80211_AC_VO;
  16312. + eapol_frame = true;
  16313. + }
  16314. + if (sta) {
  16315. + if (mwl_vif->is_hw_crypto_enabled) {
  16316. + sta_info = mwl_dev_get_sta(sta);
  16317. + if (!sta_info->is_key_set && !eapol_frame) {
  16318. + dev_kfree_skb_any(skb);
  16319. + return;
  16320. + }
  16321. + }
  16322. + }
  16323. + }
  16324. +
  16325. + if (tx_info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) {
  16326. + wh->seq_ctrl &= cpu_to_le16(IEEE80211_SCTL_FRAG);
  16327. + wh->seq_ctrl |= cpu_to_le16(mwl_vif->seqno);
  16328. + mwl_vif->seqno += 0x10;
  16329. + }
  16330. +
  16331. + /* Setup firmware control bit fields for each frame type. */
  16332. + xmitcontrol = 0;
  16333. +
  16334. + if (mgmtframe || ieee80211_is_ctl(wh->frame_control)) {
  16335. + qos = 0;
  16336. + } else if (ieee80211_is_data(wh->frame_control)) {
  16337. + qos &= ~MWL_QOS_ACK_POLICY_MASK;
  16338. +
  16339. + if (tx_info->flags & IEEE80211_TX_CTL_AMPDU) {
  16340. + xmitcontrol &= 0xfb;
  16341. + qos |= MWL_QOS_ACK_POLICY_BLOCKACK;
  16342. + } else {
  16343. + xmitcontrol |= 0x4;
  16344. + qos |= MWL_QOS_ACK_POLICY_NORMAL;
  16345. + }
  16346. +
  16347. + if (is_multicast_ether_addr(wh->addr1) || eapol_frame)
  16348. + xmitcontrol |= EAGLE_TXD_XMITCTRL_USE_MC_RATE;
  16349. + }
  16350. +
  16351. + k_conf = tx_info->control.hw_key;
  16352. +
  16353. + /* Queue ADDBA request in the respective data queue. While setting up
  16354. + * the ampdu stream, mac80211 queues further packets for that
  16355. + * particular ra/tid pair. However, packets piled up in the hardware
  16356. + * for that ra/tid pair will still go out. ADDBA request and the
  16357. + * related data packets going out from different queues asynchronously
  16358. + * will cause a shift in the receiver window which might result in
  16359. + * ampdu packets getting dropped at the receiver after the stream has
  16360. + * been setup.
  16361. + */
  16362. + if (mgmtframe) {
  16363. + u16 capab;
  16364. +
  16365. + if (unlikely(ieee80211_is_action(wh->frame_control) &&
  16366. + mgmt->u.action.category == WLAN_CATEGORY_BACK &&
  16367. + mgmt->u.action.u.addba_req.action_code ==
  16368. + WLAN_ACTION_ADDBA_REQ)) {
  16369. + capab = le16_to_cpu(mgmt->u.action.u.addba_req.capab);
  16370. + tid = (capab & IEEE80211_ADDBA_PARAM_TID_MASK) >> 2;
  16371. + index = utils_tid_to_ac(tid);
  16372. + }
  16373. +
  16374. + if (unlikely(ieee80211_is_assoc_req(wh->frame_control)))
  16375. + utils_add_basic_rates(hw->conf.chandef.chan->band, skb);
  16376. + }
  16377. +
  16378. + index = SYSADPT_TX_WMM_QUEUES - index - 1;
  16379. + txpriority = index;
  16380. +
  16381. + if (sta && sta->ht_cap.ht_supported && !eapol_frame &&
  16382. + ieee80211_is_data_qos(wh->frame_control)) {
  16383. + tid = qos & 0xf;
  16384. + pcie_tx_count_packet(sta, tid);
  16385. +
  16386. + spin_lock_bh(&priv->stream_lock);
  16387. + stream = mwl_fwcmd_lookup_stream(hw, sta, tid);
  16388. +
  16389. + if (stream) {
  16390. + if (stream->state == AMPDU_STREAM_ACTIVE) {
  16391. + if (WARN_ON(!(qos &
  16392. + MWL_QOS_ACK_POLICY_BLOCKACK))) {
  16393. + spin_unlock_bh(&priv->stream_lock);
  16394. + dev_kfree_skb_any(skb);
  16395. + return;
  16396. + }
  16397. +
  16398. + txpriority =
  16399. + (SYSADPT_TX_WMM_QUEUES + stream->idx) %
  16400. + TOTAL_HW_QUEUES;
  16401. + } else if (stream->state == AMPDU_STREAM_NEW) {
  16402. + /* We get here if the driver sends us packets
  16403. + * after we've initiated a stream, but before
  16404. + * our ampdu_action routine has been called
  16405. + * with IEEE80211_AMPDU_TX_START to get the SSN
  16406. + * for the ADDBA request. So this packet can
  16407. + * go out with no risk of sequence number
  16408. + * mismatch. No special handling is required.
  16409. + */
  16410. + } else {
  16411. + /* Drop packets that would go out after the
  16412. + * ADDBA request was sent but before the ADDBA
  16413. + * response is received. If we don't do this,
  16414. + * the recipient would probably receive it
  16415. + * after the ADDBA request with SSN 0. This
  16416. + * will cause the recipient's BA receive window
  16417. + * to shift, which would cause the subsequent
  16418. + * packets in the BA stream to be discarded.
  16419. + * mac80211 queues our packets for us in this
  16420. + * case, so this is really just a safety check.
  16421. + */
  16422. + wiphy_warn(hw->wiphy,
  16423. + "can't send packet during ADDBA\n");
  16424. + spin_unlock_bh(&priv->stream_lock);
  16425. + dev_kfree_skb_any(skb);
  16426. + return;
  16427. + }
  16428. + } else {
  16429. + if (mwl_fwcmd_ampdu_allowed(sta, tid)) {
  16430. + stream = mwl_fwcmd_add_stream(hw, sta, tid);
  16431. +
  16432. + if (stream)
  16433. + start_ba_session = true;
  16434. + }
  16435. + }
  16436. +
  16437. + spin_unlock_bh(&priv->stream_lock);
  16438. + } else {
  16439. + qos &= ~MWL_QOS_ACK_POLICY_MASK;
  16440. + qos |= MWL_QOS_ACK_POLICY_NORMAL;
  16441. + }
  16442. +
  16443. + tx_ctrl = (struct pcie_tx_ctrl *)&tx_info->status;
  16444. + tx_ctrl->vif = (void *)tx_info->control.vif;
  16445. + tx_ctrl->sta = (void *)sta;
  16446. + tx_ctrl->k_conf = (void *)k_conf;
  16447. + tx_ctrl->amsdu_pkts = NULL;
  16448. + tx_ctrl->tx_priority = txpriority;
  16449. + tx_ctrl->type = (mgmtframe ? IEEE_TYPE_MANAGEMENT : IEEE_TYPE_DATA);
  16450. + tx_ctrl->qos_ctrl = qos;
  16451. + tx_ctrl->xmit_control = xmitcontrol;
  16452. +
  16453. + if (skb_queue_len(&pcie_priv->txq[index]) > pcie_priv->txq_limit)
  16454. + ieee80211_stop_queue(hw, SYSADPT_TX_WMM_QUEUES - index - 1);
  16455. +
  16456. + skb_queue_tail(&pcie_priv->txq[index], skb);
  16457. +
  16458. + tasklet_schedule(&pcie_priv->tx_task);
  16459. +
  16460. + /* Initiate the ampdu session here */
  16461. + if (start_ba_session) {
  16462. + spin_lock_bh(&priv->stream_lock);
  16463. + rc = mwl_fwcmd_start_stream(hw, stream);
  16464. + if (rc)
  16465. + mwl_fwcmd_remove_stream(hw, stream);
  16466. + else
  16467. + wiphy_debug(hw->wiphy, "Mac80211 start BA %pM\n",
  16468. + stream->sta->addr);
  16469. + spin_unlock_bh(&priv->stream_lock);
  16470. + }
  16471. +}
  16472. +
  16473. +void pcie_tx_del_pkts_via_vif(struct ieee80211_hw *hw,
  16474. + struct ieee80211_vif *vif)
  16475. +{
  16476. + struct mwl_priv *priv = hw->priv;
  16477. + struct pcie_priv *pcie_priv = priv->hif.priv;
  16478. + int num;
  16479. + struct sk_buff *skb, *tmp;
  16480. + struct ieee80211_tx_info *tx_info;
  16481. + struct pcie_tx_ctrl *tx_ctrl;
  16482. + struct sk_buff_head *amsdu_pkts;
  16483. + unsigned long flags;
  16484. +
  16485. + for (num = 1; num < PCIE_NUM_OF_DESC_DATA; num++) {
  16486. + spin_lock_irqsave(&pcie_priv->txq[num].lock, flags);
  16487. + skb_queue_walk_safe(&pcie_priv->txq[num], skb, tmp) {
  16488. + tx_info = IEEE80211_SKB_CB(skb);
  16489. + tx_ctrl = (struct pcie_tx_ctrl *)&tx_info->status;
  16490. + if (tx_ctrl->vif == vif) {
  16491. + amsdu_pkts = (struct sk_buff_head *)
  16492. + tx_ctrl->amsdu_pkts;
  16493. + if (amsdu_pkts) {
  16494. + skb_queue_purge(amsdu_pkts);
  16495. + kfree(amsdu_pkts);
  16496. + }
  16497. + __skb_unlink(skb, &pcie_priv->txq[num]);
  16498. + dev_kfree_skb_any(skb);
  16499. + }
  16500. + }
  16501. + spin_unlock_irqrestore(&pcie_priv->txq[num].lock, flags);
  16502. + }
  16503. +}
  16504. +
  16505. +void pcie_tx_del_pkts_via_sta(struct ieee80211_hw *hw,
  16506. + struct ieee80211_sta *sta)
  16507. +{
  16508. + struct mwl_priv *priv = hw->priv;
  16509. + struct pcie_priv *pcie_priv = priv->hif.priv;
  16510. + int num;
  16511. + struct sk_buff *skb, *tmp;
  16512. + struct ieee80211_tx_info *tx_info;
  16513. + struct pcie_tx_ctrl *tx_ctrl;
  16514. + struct sk_buff_head *amsdu_pkts;
  16515. + unsigned long flags;
  16516. +
  16517. + for (num = 1; num < PCIE_NUM_OF_DESC_DATA; num++) {
  16518. + spin_lock_irqsave(&pcie_priv->txq[num].lock, flags);
  16519. + skb_queue_walk_safe(&pcie_priv->txq[num], skb, tmp) {
  16520. + tx_info = IEEE80211_SKB_CB(skb);
  16521. + tx_ctrl = (struct pcie_tx_ctrl *)&tx_info->status;
  16522. + if (tx_ctrl->sta == sta) {
  16523. + amsdu_pkts = (struct sk_buff_head *)
  16524. + tx_ctrl->amsdu_pkts;
  16525. + if (amsdu_pkts) {
  16526. + skb_queue_purge(amsdu_pkts);
  16527. + kfree(amsdu_pkts);
  16528. + }
  16529. + __skb_unlink(skb, &pcie_priv->txq[num]);
  16530. + dev_kfree_skb_any(skb);
  16531. + }
  16532. + }
  16533. + spin_unlock_irqrestore(&pcie_priv->txq[num].lock, flags);
  16534. + }
  16535. +}
  16536. +
  16537. +void pcie_tx_del_ampdu_pkts(struct ieee80211_hw *hw,
  16538. + struct ieee80211_sta *sta, u8 tid)
  16539. +{
  16540. + struct mwl_priv *priv = hw->priv;
  16541. + struct pcie_priv *pcie_priv = priv->hif.priv;
  16542. + struct mwl_sta *sta_info = mwl_dev_get_sta(sta);
  16543. + int ac, desc_num;
  16544. + struct mwl_amsdu_frag *amsdu_frag;
  16545. + struct sk_buff *skb, *tmp;
  16546. + struct ieee80211_tx_info *tx_info;
  16547. + struct pcie_tx_ctrl *tx_ctrl;
  16548. + struct sk_buff_head *amsdu_pkts;
  16549. + unsigned long flags;
  16550. +
  16551. + ac = utils_tid_to_ac(tid);
  16552. + desc_num = SYSADPT_TX_WMM_QUEUES - ac - 1;
  16553. + spin_lock_irqsave(&pcie_priv->txq[desc_num].lock, flags);
  16554. + skb_queue_walk_safe(&pcie_priv->txq[desc_num], skb, tmp) {
  16555. + tx_info = IEEE80211_SKB_CB(skb);
  16556. + tx_ctrl = (struct pcie_tx_ctrl *)&tx_info->status;
  16557. + if (tx_ctrl->sta == sta) {
  16558. + amsdu_pkts = (struct sk_buff_head *)
  16559. + tx_ctrl->amsdu_pkts;
  16560. + if (amsdu_pkts) {
  16561. + skb_queue_purge(amsdu_pkts);
  16562. + kfree(amsdu_pkts);
  16563. + }
  16564. + __skb_unlink(skb, &pcie_priv->txq[desc_num]);
  16565. + dev_kfree_skb_any(skb);
  16566. + }
  16567. + }
  16568. + spin_unlock_irqrestore(&pcie_priv->txq[desc_num].lock, flags);
  16569. +
  16570. + spin_lock_bh(&sta_info->amsdu_lock);
  16571. + amsdu_frag = &sta_info->amsdu_ctrl.frag[desc_num];
  16572. + if (amsdu_frag->num) {
  16573. + amsdu_frag->num = 0;
  16574. + amsdu_frag->cur_pos = NULL;
  16575. + if (amsdu_frag->skb) {
  16576. + tx_info = IEEE80211_SKB_CB(amsdu_frag->skb);
  16577. + tx_ctrl = (struct pcie_tx_ctrl *)&tx_info->status;
  16578. + amsdu_pkts = (struct sk_buff_head *)
  16579. + tx_ctrl->amsdu_pkts;
  16580. + if (amsdu_pkts) {
  16581. + skb_queue_purge(amsdu_pkts);
  16582. + kfree(amsdu_pkts);
  16583. + }
  16584. + dev_kfree_skb_any(amsdu_frag->skb);
  16585. + }
  16586. + }
  16587. + spin_unlock_bh(&sta_info->amsdu_lock);
  16588. +}
  16589. +
  16590. +void pcie_tx_del_sta_amsdu_pkts(struct ieee80211_hw *hw,
  16591. + struct ieee80211_sta *sta)
  16592. +{
  16593. + struct mwl_sta *sta_info = mwl_dev_get_sta(sta);
  16594. + int num;
  16595. + struct mwl_amsdu_frag *amsdu_frag;
  16596. + struct ieee80211_tx_info *tx_info;
  16597. + struct pcie_tx_ctrl *tx_ctrl;
  16598. + struct sk_buff_head *amsdu_pkts;
  16599. +
  16600. + spin_lock_bh(&sta_info->amsdu_lock);
  16601. + for (num = 0; num < SYSADPT_TX_WMM_QUEUES; num++) {
  16602. + amsdu_frag = &sta_info->amsdu_ctrl.frag[num];
  16603. + if (amsdu_frag->num) {
  16604. + amsdu_frag->num = 0;
  16605. + amsdu_frag->cur_pos = NULL;
  16606. + if (amsdu_frag->skb) {
  16607. + tx_info = IEEE80211_SKB_CB(amsdu_frag->skb);
  16608. + tx_ctrl = (struct pcie_tx_ctrl *)
  16609. + &tx_info->status;
  16610. + amsdu_pkts = (struct sk_buff_head *)
  16611. + tx_ctrl->amsdu_pkts;
  16612. + if (amsdu_pkts) {
  16613. + skb_queue_purge(amsdu_pkts);
  16614. + kfree(amsdu_pkts);
  16615. + }
  16616. + dev_kfree_skb_any(amsdu_frag->skb);
  16617. + }
  16618. + }
  16619. + }
  16620. + spin_unlock_bh(&sta_info->amsdu_lock);
  16621. +}
  16622. diff --git a/drivers/net/wireless/marvell/mwlwifi/hif/pcie/tx.h b/drivers/net/wireless/marvell/mwlwifi/hif/pcie/tx.h
  16623. new file mode 100644
  16624. index 000000000000..c233ba1aaa9d
  16625. --- /dev/null
  16626. +++ b/drivers/net/wireless/marvell/mwlwifi/hif/pcie/tx.h
  16627. @@ -0,0 +1,38 @@
  16628. +/*
  16629. + * Copyright (C) 2006-2018, Marvell International Ltd.
  16630. + *
  16631. + * This software file (the "File") is distributed by Marvell International
  16632. + * Ltd. under the terms of the GNU General Public License Version 2, June 1991
  16633. + * (the "License"). You may use, redistribute and/or modify this File in
  16634. + * accordance with the terms and conditions of the License, a copy of which
  16635. + * is available by writing to the Free Software Foundation, Inc.
  16636. + *
  16637. + * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
  16638. + * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
  16639. + * ARE EXPRESSLY DISCLAIMED. The License provides additional details about
  16640. + * this warranty disclaimer.
  16641. + */
  16642. +
  16643. +/* Description: This file defines transmit related functions. */
  16644. +
  16645. +#ifndef _TX_H_
  16646. +#define _TX_H_
  16647. +
  16648. +int pcie_tx_init(struct ieee80211_hw *hw);
  16649. +void pcie_tx_deinit(struct ieee80211_hw *hw);
  16650. +void pcie_tx_skbs(unsigned long data);
  16651. +void pcie_tx_done(unsigned long data);
  16652. +void pcie_tx_flush_amsdu(unsigned long data);
  16653. +void pcie_tx_xmit(struct ieee80211_hw *hw,
  16654. + struct ieee80211_tx_control *control,
  16655. + struct sk_buff *skb);
  16656. +void pcie_tx_del_pkts_via_vif(struct ieee80211_hw *hw,
  16657. + struct ieee80211_vif *vif);
  16658. +void pcie_tx_del_pkts_via_sta(struct ieee80211_hw *hw,
  16659. + struct ieee80211_sta *sta);
  16660. +void pcie_tx_del_ampdu_pkts(struct ieee80211_hw *hw,
  16661. + struct ieee80211_sta *sta, u8 tid);
  16662. +void pcie_tx_del_sta_amsdu_pkts(struct ieee80211_hw *hw,
  16663. + struct ieee80211_sta *sta);
  16664. +
  16665. +#endif /* _TX_H_ */
  16666. diff --git a/drivers/net/wireless/marvell/mwlwifi/hif/pcie/tx_ndp.c b/drivers/net/wireless/marvell/mwlwifi/hif/pcie/tx_ndp.c
  16667. new file mode 100644
  16668. index 000000000000..6758cde363c6
  16669. --- /dev/null
  16670. +++ b/drivers/net/wireless/marvell/mwlwifi/hif/pcie/tx_ndp.c
  16671. @@ -0,0 +1,693 @@
  16672. +/*
  16673. + * Copyright (C) 2006-2018, Marvell International Ltd.
  16674. + *
  16675. + * This software file (the "File") is distributed by Marvell International
  16676. + * Ltd. under the terms of the GNU General Public License Version 2, June 1991
  16677. + * (the "License"). You may use, redistribute and/or modify this File in
  16678. + * accordance with the terms and conditions of the License, a copy of which
  16679. + * is available by writing to the Free Software Foundation, Inc.
  16680. + *
  16681. + * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
  16682. + * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
  16683. + * ARE EXPRESSLY DISCLAIMED. The License provides additional details about
  16684. + * this warranty disclaimer.
  16685. + */
  16686. +
  16687. +/* Description: This file implements transmit related functions for new data
  16688. + * path.
  16689. + */
  16690. +
  16691. +#include <linux/etherdevice.h>
  16692. +#include <linux/skbuff.h>
  16693. +
  16694. +#include "sysadpt.h"
  16695. +#include "core.h"
  16696. +#include "utils.h"
  16697. +#include "hif/fwcmd.h"
  16698. +#include "hif/pcie/dev.h"
  16699. +#include "hif/pcie/tx_ndp.h"
  16700. +
  16701. +#define MAX_NUM_TX_RING_BYTES (MAX_NUM_TX_DESC * \
  16702. + sizeof(struct pcie_tx_desc_ndp))
  16703. +#define MAX_NUM_TX_RING_DONE_BYTES (MAX_NUM_TX_DESC * \
  16704. + sizeof(struct tx_ring_done))
  16705. +#define QUEUE_STAOFFSET ((SYSADPT_NUM_OF_AP - 1) + \
  16706. + SYSADPT_NUM_OF_CLIENT)
  16707. +#define PROBE_RESPONSE_TXQNUM ((SYSADPT_MAX_STA_SC4 + SYSADPT_NUM_OF_AP + \
  16708. + SYSADPT_NUM_OF_CLIENT) * SYSADPT_MAX_TID)
  16709. +#define MGMT_TXQNUM ((PROBE_RESPONSE_TXQNUM + 1))
  16710. +#define TXDONE_THRESHOLD 4
  16711. +
  16712. +#define TX_CTRL_TYPE_DATA BIT(0)
  16713. +#define TX_CTRL_EAPOL BIT(1)
  16714. +#define TX_CTRL_TCP_ACK BIT(2)
  16715. +
  16716. +/* Transmission information to transmit a socket buffer.
  16717. + */
  16718. +struct pcie_tx_ctrl_ndp {
  16719. + u16 tx_que_priority;
  16720. + u8 hdrlen;
  16721. + u8 flags;
  16722. + u32 rate;
  16723. + u32 tcp_dst_src;
  16724. + u32 tcp_sn;
  16725. +} __packed;
  16726. +
  16727. +static int pcie_tx_ring_alloc_ndp(struct mwl_priv *priv)
  16728. +{
  16729. + struct pcie_priv *pcie_priv = priv->hif.priv;
  16730. + struct pcie_desc_data_ndp *desc = &pcie_priv->desc_data_ndp;
  16731. + u8 *mem;
  16732. +
  16733. + mem = dma_alloc_coherent(priv->dev,
  16734. + MAX_NUM_TX_RING_BYTES,
  16735. + &desc->pphys_tx_ring,
  16736. + GFP_KERNEL);
  16737. + if (!mem)
  16738. + goto err_no_mem;
  16739. + desc->ptx_ring = (struct pcie_tx_desc_ndp *)mem;
  16740. + memset(desc->ptx_ring, 0x00, MAX_NUM_TX_RING_BYTES);
  16741. +
  16742. + mem = dma_alloc_coherent(priv->dev,
  16743. + MAX_NUM_TX_RING_DONE_BYTES,
  16744. + &desc->pphys_tx_ring_done,
  16745. + GFP_KERNEL);
  16746. + if (!mem)
  16747. + goto err_no_mem;
  16748. + desc->ptx_ring_done = (struct tx_ring_done *)mem;
  16749. + memset(desc->ptx_ring_done, 0x00, MAX_NUM_TX_RING_DONE_BYTES);
  16750. +
  16751. + mem = dma_alloc_coherent(priv->dev,
  16752. + DEFAULT_ACNT_RING_SIZE,
  16753. + &desc->pphys_acnt_ring,
  16754. + GFP_KERNEL);
  16755. + if (!mem)
  16756. + goto err_no_mem;
  16757. + desc->pacnt_ring = (u8 *)mem;
  16758. + memset(desc->pacnt_ring, 0x00, DEFAULT_ACNT_RING_SIZE);
  16759. +
  16760. + desc->pacnt_buf = kzalloc(DEFAULT_ACNT_RING_SIZE, GFP_KERNEL);
  16761. + if (!desc->pacnt_buf)
  16762. + goto err_no_mem;
  16763. + desc->acnt_ring_size = DEFAULT_ACNT_RING_SIZE;
  16764. +
  16765. + return 0;
  16766. +
  16767. +err_no_mem:
  16768. +
  16769. + wiphy_err(priv->hw->wiphy, "cannot alloc mem\n");
  16770. +
  16771. + return -ENOMEM;
  16772. +}
  16773. +
  16774. +static int pcie_tx_ring_init_ndp(struct mwl_priv *priv)
  16775. +{
  16776. + struct pcie_priv *pcie_priv = priv->hif.priv;
  16777. + struct pcie_desc_data_ndp *desc = &pcie_priv->desc_data_ndp;
  16778. + int i;
  16779. +
  16780. + for (i = 0; i < PCIE_NUM_OF_DESC_DATA; i++)
  16781. + skb_queue_head_init(&pcie_priv->txq[i]);
  16782. +
  16783. + if (!desc->ptx_ring) {
  16784. + for (i = 0; i < MAX_NUM_TX_DESC; i++)
  16785. + desc->ptx_ring[i].user = cpu_to_le32(i);
  16786. + desc->tx_desc_busy_cnt = 0;
  16787. + }
  16788. +
  16789. + return 0;
  16790. +}
  16791. +
  16792. +static void pcie_tx_ring_cleanup_ndp(struct mwl_priv *priv)
  16793. +{
  16794. + struct pcie_priv *pcie_priv = priv->hif.priv;
  16795. + struct pcie_desc_data_ndp *desc = &pcie_priv->desc_data_ndp;
  16796. + struct sk_buff *tx_skb;
  16797. + int i;
  16798. +
  16799. + for (i = 0; i < PCIE_NUM_OF_DESC_DATA; i++)
  16800. + skb_queue_purge(&pcie_priv->txq[i]);
  16801. +
  16802. + for (i = 0; i < MAX_TX_RING_SEND_SIZE; i++) {
  16803. + tx_skb = desc->tx_vbuflist[i];
  16804. + if (tx_skb) {
  16805. + pci_unmap_single(pcie_priv->pdev,
  16806. + desc->pphys_tx_buflist[i],
  16807. + tx_skb->len,
  16808. + PCI_DMA_TODEVICE);
  16809. + dev_kfree_skb_any(tx_skb);
  16810. + desc->pphys_tx_buflist[i] = 0;
  16811. + desc->tx_vbuflist[i] = NULL;
  16812. + }
  16813. + }
  16814. + desc->tx_sent_tail = 0;
  16815. + desc->tx_sent_head = 0;
  16816. + desc->tx_done_tail = 0;
  16817. + desc->tx_vbuflist_idx = 0;
  16818. + desc->tx_desc_busy_cnt = 0;
  16819. +}
  16820. +
  16821. +static void pcie_tx_ring_free_ndp(struct mwl_priv *priv)
  16822. +{
  16823. + struct pcie_priv *pcie_priv = priv->hif.priv;
  16824. + struct pcie_desc_data_ndp *desc = &pcie_priv->desc_data_ndp;
  16825. +
  16826. + if (desc->ptx_ring) {
  16827. + dma_free_coherent(priv->dev,
  16828. + MAX_NUM_TX_RING_BYTES,
  16829. + desc->ptx_ring,
  16830. + desc->pphys_tx_ring);
  16831. + desc->ptx_ring = NULL;
  16832. + }
  16833. +
  16834. + if (desc->ptx_ring_done) {
  16835. + dma_free_coherent(priv->dev,
  16836. + MAX_NUM_TX_RING_DONE_BYTES,
  16837. + desc->ptx_ring_done,
  16838. + desc->pphys_tx_ring_done);
  16839. + desc->prx_ring_done = NULL;
  16840. + }
  16841. +
  16842. + if (desc->pacnt_ring) {
  16843. + dma_free_coherent(priv->dev,
  16844. + DEFAULT_ACNT_RING_SIZE,
  16845. + desc->pacnt_ring,
  16846. + desc->pphys_acnt_ring);
  16847. + desc->pacnt_ring = NULL;
  16848. + }
  16849. +
  16850. + kfree(desc->pacnt_buf);
  16851. +}
  16852. +
  16853. +static inline u32 pcie_tx_set_skb(struct mwl_priv *priv, struct sk_buff *skb,
  16854. + dma_addr_t dma)
  16855. +{
  16856. + struct pcie_priv *pcie_priv = priv->hif.priv;
  16857. + struct pcie_desc_data_ndp *desc = &pcie_priv->desc_data_ndp;
  16858. + u32 index = desc->tx_vbuflist_idx;
  16859. +
  16860. + while (desc->tx_vbuflist[index])
  16861. + index = (index + 1) % MAX_TX_RING_SEND_SIZE;
  16862. +
  16863. + desc->tx_vbuflist_idx = (index + 1) % MAX_TX_RING_SEND_SIZE;
  16864. + desc->pphys_tx_buflist[index] = dma;
  16865. + desc->tx_vbuflist[index] = skb;
  16866. +
  16867. + return index;
  16868. +}
  16869. +
  16870. +static inline int pcie_tx_skb_ndp(struct mwl_priv *priv,
  16871. + struct sk_buff *tx_skb)
  16872. +{
  16873. + struct pcie_priv *pcie_priv = priv->hif.priv;
  16874. + struct pcie_desc_data_ndp *desc = &pcie_priv->desc_data_ndp;
  16875. + u32 tx_send_tail;
  16876. + u32 tx_send_head_new;
  16877. + struct ieee80211_tx_info *tx_info;
  16878. + struct pcie_tx_ctrl_ndp *tx_ctrl;
  16879. + struct pcie_tx_desc_ndp *pnext_tx_desc;
  16880. + struct ieee80211_hdr *wh;
  16881. + u32 ctrl = 0;
  16882. + dma_addr_t dma;
  16883. +
  16884. + spin_lock_bh(&pcie_priv->tx_desc_lock);
  16885. +
  16886. + tx_send_tail = desc->tx_sent_tail;
  16887. + tx_send_head_new = desc->tx_sent_head;
  16888. +
  16889. + if (((tx_send_head_new + 1) & (MAX_NUM_TX_DESC-1)) == tx_send_tail) {
  16890. + /* Update the tx_send_tail */
  16891. + tx_send_tail = readl(pcie_priv->iobase1 +
  16892. + MACREG_REG_TXSEDNTAIL);
  16893. + desc->tx_sent_tail = tx_send_tail;
  16894. +
  16895. + if (((tx_send_head_new + 1) & (MAX_NUM_TX_DESC-1)) ==
  16896. + tx_send_tail) {
  16897. + spin_unlock_bh(&pcie_priv->tx_desc_lock);
  16898. + return -EAGAIN;
  16899. + }
  16900. + }
  16901. +
  16902. + tx_info = IEEE80211_SKB_CB(tx_skb);
  16903. + tx_ctrl = (struct pcie_tx_ctrl_ndp *)tx_info->status.status_driver_data;
  16904. + pnext_tx_desc = &desc->ptx_ring[tx_send_head_new];
  16905. +
  16906. + if (tx_ctrl->flags & TX_CTRL_TYPE_DATA) {
  16907. + wh = (struct ieee80211_hdr *)tx_skb->data;
  16908. +
  16909. + skb_pull(tx_skb, tx_ctrl->hdrlen);
  16910. + ether_addr_copy(pnext_tx_desc->u.sa,
  16911. + ieee80211_get_SA(wh));
  16912. + ether_addr_copy(pnext_tx_desc->u.da,
  16913. + ieee80211_get_DA(wh));
  16914. +
  16915. + if (tx_ctrl->flags & TX_CTRL_EAPOL)
  16916. + ctrl = TXRING_CTRL_TAG_EAP << TXRING_CTRL_TAG_SHIFT;
  16917. + if (tx_ctrl->flags & TX_CTRL_TCP_ACK) {
  16918. + pnext_tx_desc->tcp_dst_src =
  16919. + cpu_to_le32(tx_ctrl->tcp_dst_src);
  16920. + pnext_tx_desc->tcp_sn = cpu_to_le32(tx_ctrl->tcp_sn);
  16921. + ctrl = TXRING_CTRL_TAG_TCP_ACK << TXRING_CTRL_TAG_SHIFT;
  16922. + }
  16923. + ctrl |= (((tx_ctrl->tx_que_priority & TXRING_CTRL_QID_MASK) <<
  16924. + TXRING_CTRL_QID_SHIFT) |
  16925. + ((tx_skb->len & TXRING_CTRL_LEN_MASK) <<
  16926. + TXRING_CTRL_LEN_SHIFT));
  16927. + } else {
  16928. + /* Assigning rate code; use legacy 6mbps rate. */
  16929. + pnext_tx_desc->u.rate_code = cpu_to_le16(RATECODE_TYPE_LEGACY +
  16930. + (0 << RATECODE_MCS_SHIFT) + RATECODE_BW_20MHZ);
  16931. + pnext_tx_desc->u.max_retry = 5;
  16932. +
  16933. + ctrl = (((tx_ctrl->tx_que_priority & TXRING_CTRL_QID_MASK) <<
  16934. + TXRING_CTRL_QID_SHIFT) |
  16935. + (((tx_skb->len - sizeof(struct pcie_dma_data)) &
  16936. + TXRING_CTRL_LEN_MASK) << TXRING_CTRL_LEN_SHIFT) |
  16937. + (TXRING_CTRL_TAG_MGMT << TXRING_CTRL_TAG_SHIFT));
  16938. + }
  16939. +
  16940. + dma = pci_map_single(pcie_priv->pdev, tx_skb->data,
  16941. + tx_skb->len, PCI_DMA_TODEVICE);
  16942. + if (pci_dma_mapping_error(pcie_priv->pdev, dma)) {
  16943. + dev_kfree_skb_any(tx_skb);
  16944. + wiphy_err(priv->hw->wiphy,
  16945. + "failed to map pci memory!\n");
  16946. + spin_unlock_bh(&pcie_priv->tx_desc_lock);
  16947. + return -EIO;
  16948. + }
  16949. +
  16950. + pnext_tx_desc->data = cpu_to_le32(dma);
  16951. + pnext_tx_desc->ctrl = cpu_to_le32(ctrl);
  16952. + pnext_tx_desc->user = cpu_to_le32(pcie_tx_set_skb(priv, tx_skb, dma));
  16953. +
  16954. + if ((tx_ctrl->flags & TX_CTRL_TYPE_DATA) &&
  16955. + (tx_ctrl->rate != 0)) {
  16956. + skb_push(tx_skb, tx_ctrl->hdrlen);
  16957. + skb_get(tx_skb);
  16958. + pcie_tx_prepare_info(priv, tx_ctrl->rate, tx_info);
  16959. + tx_ctrl->flags |= TX_CTRL_TYPE_DATA;
  16960. + ieee80211_tx_status(priv->hw, tx_skb);
  16961. + }
  16962. +
  16963. + if (++tx_send_head_new >= MAX_NUM_TX_DESC)
  16964. + tx_send_head_new = 0;
  16965. + desc->tx_sent_head = tx_send_head_new;
  16966. + wmb(); /*Data Memory Barrier*/
  16967. + writel(tx_send_head_new, pcie_priv->iobase1 + MACREG_REG_TXSENDHEAD);
  16968. + desc->tx_desc_busy_cnt++;
  16969. +
  16970. + spin_unlock_bh(&pcie_priv->tx_desc_lock);
  16971. +
  16972. + return 0;
  16973. +}
  16974. +
  16975. +static inline void pcie_tx_check_tcp_ack(struct sk_buff *tx_skb,
  16976. + struct pcie_tx_ctrl_ndp *tx_ctrl)
  16977. +{
  16978. + struct iphdr *iph;
  16979. + struct tcphdr *tcph;
  16980. +
  16981. + if (tx_ctrl->flags & TX_CTRL_TYPE_DATA) {
  16982. + iph = (struct iphdr *)(tx_skb->data + tx_ctrl->hdrlen + 8);
  16983. + tcph = (struct tcphdr *)((u8 *)iph + (iph->ihl * 4));
  16984. + if ((iph->protocol == IPPROTO_TCP) &&
  16985. + (tx_skb->protocol == htons(ETH_P_IP))) {
  16986. + if ((tcph->ack == 1) && (ntohs(iph->tot_len) ==
  16987. + (iph->ihl * 4 + tcph->doff * 4))) {
  16988. + if (tcph->syn || tcph->fin)
  16989. + return;
  16990. +
  16991. + tx_ctrl->flags |= TX_CTRL_TCP_ACK;
  16992. + tx_ctrl->tcp_dst_src = ntohs(tcph->source) |
  16993. + (ntohs(tcph->dest) << 16);
  16994. + tx_ctrl->tcp_sn = ntohl(tcph->ack_seq);
  16995. + }
  16996. + }
  16997. + }
  16998. +}
  16999. +
  17000. +int pcie_tx_init_ndp(struct ieee80211_hw *hw)
  17001. +{
  17002. + struct mwl_priv *priv = hw->priv;
  17003. + struct sk_buff skb;
  17004. + struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(&skb);
  17005. + int rc;
  17006. +
  17007. + if (sizeof(struct pcie_tx_ctrl_ndp) >
  17008. + sizeof(tx_info->status.status_driver_data)) {
  17009. + wiphy_err(hw->wiphy, "driver data is not enough: %d (%d)\n",
  17010. + sizeof(struct pcie_tx_ctrl_ndp),
  17011. + sizeof(tx_info->status.status_driver_data));
  17012. + return -ENOMEM;
  17013. + }
  17014. +
  17015. + rc = pcie_tx_ring_alloc_ndp(priv);
  17016. + if (rc) {
  17017. + pcie_tx_ring_free_ndp(priv);
  17018. + wiphy_err(hw->wiphy, "allocating TX ring failed\n");
  17019. + return rc;
  17020. + }
  17021. +
  17022. + rc = pcie_tx_ring_init_ndp(priv);
  17023. + if (rc) {
  17024. + pcie_tx_ring_free_ndp(priv);
  17025. + wiphy_err(hw->wiphy, "initializing TX ring failed\n");
  17026. + return rc;
  17027. + }
  17028. +
  17029. + return 0;
  17030. +}
  17031. +
  17032. +void pcie_tx_deinit_ndp(struct ieee80211_hw *hw)
  17033. +{
  17034. + struct mwl_priv *priv = hw->priv;
  17035. +
  17036. + pcie_tx_ring_cleanup_ndp(priv);
  17037. + pcie_tx_ring_free_ndp(priv);
  17038. +}
  17039. +
  17040. +void pcie_tx_skbs_ndp(unsigned long data)
  17041. +{
  17042. + struct ieee80211_hw *hw = (struct ieee80211_hw *)data;
  17043. + struct mwl_priv *priv = hw->priv;
  17044. + struct pcie_priv *pcie_priv = priv->hif.priv;
  17045. + int num = SYSADPT_TX_WMM_QUEUES;
  17046. + struct sk_buff *tx_skb;
  17047. + int rc;
  17048. +
  17049. + while (num--) {
  17050. + while (skb_queue_len(&pcie_priv->txq[num]) > 0) {
  17051. + if (pcie_priv->desc_data_ndp.tx_desc_busy_cnt >=
  17052. + (MAX_TX_RING_SEND_SIZE - 1)) {
  17053. + pcie_tx_done_ndp(hw);
  17054. + break;
  17055. + }
  17056. +
  17057. + tx_skb = skb_dequeue(&pcie_priv->txq[num]);
  17058. +
  17059. + rc = pcie_tx_skb_ndp(priv, tx_skb);
  17060. + if (rc) {
  17061. + pcie_tx_done_ndp(hw);
  17062. + if (rc == -EAGAIN)
  17063. + skb_queue_head(&pcie_priv->txq[num],
  17064. + tx_skb);
  17065. + break;
  17066. + }
  17067. +
  17068. + if (++pcie_priv->tx_done_cnt > TXDONE_THRESHOLD) {
  17069. + pcie_tx_done_ndp(hw);
  17070. + pcie_priv->tx_done_cnt = 0;
  17071. + }
  17072. + }
  17073. +
  17074. + if (skb_queue_len(&pcie_priv->txq[num]) <
  17075. + pcie_priv->txq_wake_threshold) {
  17076. + int queue;
  17077. +
  17078. + queue = SYSADPT_TX_WMM_QUEUES - num - 1;
  17079. + if (ieee80211_queue_stopped(hw, queue))
  17080. + ieee80211_wake_queue(hw, queue);
  17081. + }
  17082. + }
  17083. +
  17084. + pcie_priv->is_tx_schedule = false;
  17085. +}
  17086. +
  17087. +void pcie_tx_done_ndp(struct ieee80211_hw *hw)
  17088. +{
  17089. + struct mwl_priv *priv = hw->priv;
  17090. + struct pcie_priv *pcie_priv = priv->hif.priv;
  17091. + struct pcie_desc_data_ndp *desc = &pcie_priv->desc_data_ndp;
  17092. + u32 tx_done_head, tx_done_tail;
  17093. + struct tx_ring_done *ptx_ring_done;
  17094. + u32 index;
  17095. + struct sk_buff *skb;
  17096. + struct ieee80211_tx_info *tx_info;
  17097. + struct pcie_tx_ctrl_ndp *tx_ctrl;
  17098. + struct pcie_dma_data *dma_data;
  17099. + u16 hdrlen;
  17100. +
  17101. + spin_lock_bh(&pcie_priv->tx_desc_lock);
  17102. +
  17103. + tx_done_head = readl(pcie_priv->iobase1 +
  17104. + MACREG_REG_TXDONEHEAD);
  17105. + tx_done_tail = desc->tx_done_tail & (MAX_TX_RING_DONE_SIZE - 1);
  17106. + tx_done_head &= (MAX_TX_RING_DONE_SIZE - 1);
  17107. +
  17108. + while (tx_done_head != tx_done_tail) {
  17109. + ptx_ring_done = &desc->ptx_ring_done[tx_done_tail];
  17110. +
  17111. + index = le32_to_cpu(ptx_ring_done->user);
  17112. + ptx_ring_done->user = 0;
  17113. + if (index >= MAX_TX_RING_SEND_SIZE) {
  17114. + wiphy_err(hw->wiphy,
  17115. + "corruption for index of buffer\n");
  17116. + break;
  17117. + }
  17118. + skb = desc->tx_vbuflist[index];
  17119. + if (!skb) {
  17120. + wiphy_err(hw->wiphy,
  17121. + "buffer is NULL for tx done ring\n");
  17122. + break;
  17123. + }
  17124. + pci_unmap_single(pcie_priv->pdev,
  17125. + desc->pphys_tx_buflist[index],
  17126. + skb->len,
  17127. + PCI_DMA_TODEVICE);
  17128. + desc->pphys_tx_buflist[index] = 0;
  17129. + desc->tx_vbuflist[index] = NULL;
  17130. +
  17131. + tx_info = IEEE80211_SKB_CB(skb);
  17132. + tx_ctrl = (struct pcie_tx_ctrl_ndp *)
  17133. + tx_info->status.status_driver_data;
  17134. +
  17135. + if (tx_ctrl->flags & TX_CTRL_TYPE_DATA) {
  17136. + dev_kfree_skb_any(skb);
  17137. + goto bypass_ack;
  17138. + } else {
  17139. + /* Remove H/W dma header */
  17140. + dma_data = (struct pcie_dma_data *)skb->data;
  17141. +
  17142. + if (ieee80211_is_assoc_resp(
  17143. + dma_data->wh.frame_control) ||
  17144. + ieee80211_is_reassoc_resp(
  17145. + dma_data->wh.frame_control)) {
  17146. + dev_kfree_skb_any(skb);
  17147. + goto bypass_ack;
  17148. + }
  17149. + hdrlen = ieee80211_hdrlen(
  17150. + dma_data->wh.frame_control);
  17151. + memmove(dma_data->data - hdrlen,
  17152. + &dma_data->wh, hdrlen);
  17153. + skb_pull(skb, sizeof(*dma_data) - hdrlen);
  17154. + }
  17155. +
  17156. + pcie_tx_prepare_info(priv, 0, tx_info);
  17157. + ieee80211_tx_status(hw, skb);
  17158. +
  17159. +bypass_ack:
  17160. + if (++tx_done_tail >= MAX_TX_RING_DONE_SIZE)
  17161. + tx_done_tail = 0;
  17162. + desc->tx_desc_busy_cnt--;
  17163. + }
  17164. +
  17165. + writel(tx_done_tail, pcie_priv->iobase1 +
  17166. + MACREG_REG_TXDONETAIL);
  17167. + desc->tx_done_tail = tx_done_tail;
  17168. +
  17169. + spin_unlock_bh(&pcie_priv->tx_desc_lock);
  17170. +}
  17171. +
  17172. +void pcie_tx_xmit_ndp(struct ieee80211_hw *hw,
  17173. + struct ieee80211_tx_control *control,
  17174. + struct sk_buff *skb)
  17175. +{
  17176. + struct mwl_priv *priv = hw->priv;
  17177. + struct pcie_priv *pcie_priv = priv->hif.priv;
  17178. + struct ieee80211_tx_info *tx_info;
  17179. + struct ieee80211_key_conf *k_conf;
  17180. + struct mwl_vif *mwl_vif;
  17181. + int index;
  17182. + struct ieee80211_sta *sta;
  17183. + struct mwl_sta *sta_info;
  17184. + struct ieee80211_hdr *wh;
  17185. + u8 *da;
  17186. + u16 qos;
  17187. + u8 tid = 0;
  17188. + struct mwl_ampdu_stream *stream = NULL;
  17189. + u16 tx_que_priority;
  17190. + bool mgmtframe = false;
  17191. + struct ieee80211_mgmt *mgmt;
  17192. + bool eapol_frame = false;
  17193. + bool start_ba_session = false;
  17194. + struct pcie_tx_ctrl_ndp *tx_ctrl;
  17195. +
  17196. + tx_info = IEEE80211_SKB_CB(skb);
  17197. + k_conf = tx_info->control.hw_key;
  17198. + mwl_vif = mwl_dev_get_vif(tx_info->control.vif);
  17199. + index = skb_get_queue_mapping(skb);
  17200. + sta = control->sta;
  17201. + sta_info = sta ? mwl_dev_get_sta(sta) : NULL;
  17202. +
  17203. + wh = (struct ieee80211_hdr *)skb->data;
  17204. +
  17205. + if (ieee80211_is_data_qos(wh->frame_control))
  17206. + qos = le16_to_cpu(*((__le16 *)ieee80211_get_qos_ctl(wh)));
  17207. + else
  17208. + qos = 0xFFFF;
  17209. +
  17210. + if (skb->protocol == cpu_to_be16(ETH_P_PAE)) {
  17211. + index = IEEE80211_AC_VO;
  17212. + eapol_frame = true;
  17213. + }
  17214. +
  17215. + if (ieee80211_is_mgmt(wh->frame_control)) {
  17216. + mgmtframe = true;
  17217. + mgmt = (struct ieee80211_mgmt *)skb->data;
  17218. + }
  17219. +
  17220. + if (mgmtframe) {
  17221. + u16 capab;
  17222. +
  17223. + if (unlikely(ieee80211_is_action(wh->frame_control) &&
  17224. + mgmt->u.action.category == WLAN_CATEGORY_BACK &&
  17225. + mgmt->u.action.u.addba_req.action_code ==
  17226. + WLAN_ACTION_ADDBA_REQ)) {
  17227. + capab = le16_to_cpu(mgmt->u.action.u.addba_req.capab);
  17228. + tid = (capab & IEEE80211_ADDBA_PARAM_TID_MASK) >> 2;
  17229. + index = utils_tid_to_ac(tid);
  17230. + }
  17231. +
  17232. + if (unlikely(ieee80211_is_assoc_req(wh->frame_control)))
  17233. + utils_add_basic_rates(hw->conf.chandef.chan->band, skb);
  17234. +
  17235. + if (ieee80211_is_probe_req(wh->frame_control) ||
  17236. + ieee80211_is_probe_resp(wh->frame_control))
  17237. + tx_que_priority = PROBE_RESPONSE_TXQNUM;
  17238. + else {
  17239. + if ((
  17240. + (mwl_vif->macid == SYSADPT_NUM_OF_AP) &&
  17241. + (!ieee80211_has_protected(wh->frame_control) ||
  17242. + (ieee80211_has_protected(wh->frame_control) &&
  17243. + ieee80211_is_auth(wh->frame_control)))
  17244. + ) ||
  17245. + !sta ||
  17246. + ieee80211_is_auth(wh->frame_control) ||
  17247. + ieee80211_is_assoc_req(wh->frame_control) ||
  17248. + ieee80211_is_assoc_resp(wh->frame_control))
  17249. + tx_que_priority = MGMT_TXQNUM;
  17250. + else {
  17251. + if (is_multicast_ether_addr(wh->addr1) &&
  17252. + (mwl_vif->macid != SYSADPT_NUM_OF_AP))
  17253. + tx_que_priority = mwl_vif->macid *
  17254. + SYSADPT_MAX_TID;
  17255. + else
  17256. + tx_que_priority = SYSADPT_MAX_TID *
  17257. + (sta_info->stnid +
  17258. + QUEUE_STAOFFSET) + 6;
  17259. + }
  17260. + }
  17261. +
  17262. + if (ieee80211_is_assoc_resp(wh->frame_control) ||
  17263. + ieee80211_is_reassoc_resp(wh->frame_control)) {
  17264. + struct sk_buff *ack_skb;
  17265. + struct ieee80211_tx_info *ack_info;
  17266. +
  17267. + ack_skb = skb_copy(skb, GFP_ATOMIC);
  17268. + ack_info = IEEE80211_SKB_CB(ack_skb);
  17269. + pcie_tx_prepare_info(priv, 0, ack_info);
  17270. + ieee80211_tx_status(hw, ack_skb);
  17271. + }
  17272. +
  17273. + pcie_tx_encapsulate_frame(priv, skb, k_conf, NULL);
  17274. + } else {
  17275. + tid = qos & 0x7;
  17276. + if (sta && sta->ht_cap.ht_supported && !eapol_frame &&
  17277. + qos != 0xFFFF) {
  17278. + pcie_tx_count_packet(sta, tid);
  17279. + spin_lock_bh(&priv->stream_lock);
  17280. + stream = mwl_fwcmd_lookup_stream(hw, sta, tid);
  17281. + if (!stream ||
  17282. + stream->state == AMPDU_STREAM_IN_PROGRESS) {
  17283. + wiphy_warn(hw->wiphy,
  17284. + "can't send packet during ADDBA\n");
  17285. + spin_unlock_bh(&priv->stream_lock);
  17286. + dev_kfree_skb_any(skb);
  17287. + return;
  17288. + }
  17289. + if ((stream->state == AMPDU_NO_STREAM) &&
  17290. + mwl_fwcmd_ampdu_allowed(sta, tid)) {
  17291. + stream = mwl_fwcmd_add_stream(hw, sta, tid);
  17292. + if (stream)
  17293. + start_ba_session = true;
  17294. + }
  17295. + spin_unlock_bh(&priv->stream_lock);
  17296. + }
  17297. +
  17298. + da = ieee80211_get_DA(wh);
  17299. +
  17300. + if (is_multicast_ether_addr(da)
  17301. + && (mwl_vif->macid != SYSADPT_NUM_OF_AP)) {
  17302. +
  17303. + tx_que_priority = mwl_vif->macid * SYSADPT_MAX_TID;
  17304. +
  17305. + if (da[ETH_ALEN - 1] == 0xff)
  17306. + tx_que_priority += 7;
  17307. +
  17308. + if (ieee80211_has_a4(wh->frame_control)) {
  17309. + if (sta && sta_info->wds)
  17310. + tx_que_priority = SYSADPT_MAX_TID *
  17311. + (sta_info->stnid +
  17312. + QUEUE_STAOFFSET) + 6;
  17313. + }
  17314. + } else {
  17315. + if (sta) {
  17316. + if (!eapol_frame)
  17317. + tx_que_priority = SYSADPT_MAX_TID *
  17318. + (sta_info->stnid +
  17319. + QUEUE_STAOFFSET) +
  17320. + ((qos == 0xFFFF) ? 0 : tid);
  17321. + else
  17322. + tx_que_priority = SYSADPT_MAX_TID *
  17323. + (sta_info->stnid +
  17324. + QUEUE_STAOFFSET) +
  17325. + ((qos == 0xFFFF) ? 0 : 6);
  17326. + } else
  17327. + tx_que_priority = 0;
  17328. + }
  17329. + }
  17330. +
  17331. + index = SYSADPT_TX_WMM_QUEUES - index - 1;
  17332. +
  17333. + tx_ctrl = (struct pcie_tx_ctrl_ndp *)tx_info->status.status_driver_data;
  17334. + tx_ctrl->tx_que_priority = tx_que_priority;
  17335. + tx_ctrl->hdrlen = ieee80211_hdrlen(wh->frame_control);
  17336. + tx_ctrl->flags = 0;
  17337. + if (!mgmtframe)
  17338. + tx_ctrl->flags |= TX_CTRL_TYPE_DATA;
  17339. + if (eapol_frame)
  17340. + tx_ctrl->flags |= TX_CTRL_EAPOL;
  17341. + tx_ctrl->rate = sta ? sta_info->tx_rate_info : 0;
  17342. + if (ieee80211_is_nullfunc(wh->frame_control) ||
  17343. + ieee80211_is_qos_nullfunc(wh->frame_control))
  17344. + tx_ctrl->rate = 0;
  17345. + pcie_tx_check_tcp_ack(skb, tx_ctrl);
  17346. +
  17347. + if (skb_queue_len(&pcie_priv->txq[index]) > pcie_priv->txq_limit)
  17348. + ieee80211_stop_queue(hw, SYSADPT_TX_WMM_QUEUES - index - 1);
  17349. +
  17350. + skb_queue_tail(&pcie_priv->txq[index], skb);
  17351. +
  17352. + if (!pcie_priv->is_tx_schedule) {
  17353. + tasklet_schedule(&pcie_priv->tx_task);
  17354. + pcie_priv->is_tx_schedule = true;
  17355. + }
  17356. +
  17357. + /* Initiate the ampdu session here */
  17358. + if (start_ba_session) {
  17359. + spin_lock_bh(&priv->stream_lock);
  17360. + if (mwl_fwcmd_start_stream(hw, stream))
  17361. + mwl_fwcmd_remove_stream(hw, stream);
  17362. + spin_unlock_bh(&priv->stream_lock);
  17363. + }
  17364. +}
  17365. diff --git a/drivers/net/wireless/marvell/mwlwifi/hif/pcie/tx_ndp.h b/drivers/net/wireless/marvell/mwlwifi/hif/pcie/tx_ndp.h
  17366. new file mode 100644
  17367. index 000000000000..2ad5f381b9ee
  17368. --- /dev/null
  17369. +++ b/drivers/net/wireless/marvell/mwlwifi/hif/pcie/tx_ndp.h
  17370. @@ -0,0 +1,30 @@
  17371. +/*
  17372. + * Copyright (C) 2006-2018, Marvell International Ltd.
  17373. + *
  17374. + * This software file (the "File") is distributed by Marvell International
  17375. + * Ltd. under the terms of the GNU General Public License Version 2, June 1991
  17376. + * (the "License"). You may use, redistribute and/or modify this File in
  17377. + * accordance with the terms and conditions of the License, a copy of which
  17378. + * is available by writing to the Free Software Foundation, Inc.
  17379. + *
  17380. + * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
  17381. + * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
  17382. + * ARE EXPRESSLY DISCLAIMED. The License provides additional details about
  17383. + * this warranty disclaimer.
  17384. + */
  17385. +
  17386. +/* Description: This file defines transmit related functions for new data path.
  17387. + */
  17388. +
  17389. +#ifndef _TX_NDP_H_
  17390. +#define _TX_NDP_H_
  17391. +
  17392. +int pcie_tx_init_ndp(struct ieee80211_hw *hw);
  17393. +void pcie_tx_deinit_ndp(struct ieee80211_hw *hw);
  17394. +void pcie_tx_skbs_ndp(unsigned long data);
  17395. +void pcie_tx_done_ndp(struct ieee80211_hw *hw);
  17396. +void pcie_tx_xmit_ndp(struct ieee80211_hw *hw,
  17397. + struct ieee80211_tx_control *control,
  17398. + struct sk_buff *skb);
  17399. +
  17400. +#endif /* _TX_NDP_H_ */
  17401. diff --git a/drivers/net/wireless/marvell/mwlwifi/hostapd/700-interoperability-workaround-for-80+80-and-160-MHz-channels b/drivers/net/wireless/marvell/mwlwifi/hostapd/700-interoperability-workaround-for-80+80-and-160-MHz-channels
  17402. new file mode 100644
  17403. index 000000000000..adadd2e4d8d4
  17404. --- /dev/null
  17405. +++ b/drivers/net/wireless/marvell/mwlwifi/hostapd/700-interoperability-workaround-for-80+80-and-160-MHz-channels
  17406. @@ -0,0 +1,32 @@
  17407. +diff --git a/src/ap/ieee802_11_vht.c b/src/ap/ieee802_11_vht.c
  17408. +index 3236016..e923094 100644
  17409. +--- a/src/ap/ieee802_11_vht.c
  17410. ++++ b/src/ap/ieee802_11_vht.c
  17411. +@@ -82,6 +82,27 @@ u8 * hostapd_eid_vht_operation(struct hostapd_data *hapd, u8 *eid)
  17412. +
  17413. + oper->vht_op_info_chwidth = hapd->iconf->vht_oper_chwidth;
  17414. +
  17415. ++ if (hapd->iconf->vht_oper_chwidth == 2) {
  17416. ++ /*
  17417. ++ * Convert 160 MHz channel width to new style as interop
  17418. ++ * workaround.
  17419. ++ */
  17420. ++ oper->vht_op_info_chwidth = 1;
  17421. ++ oper->vht_op_info_chan_center_freq_seg1_idx =
  17422. ++ oper->vht_op_info_chan_center_freq_seg0_idx;
  17423. ++ if (hapd->iconf->channel <
  17424. ++ hapd->iconf->vht_oper_centr_freq_seg0_idx)
  17425. ++ oper->vht_op_info_chan_center_freq_seg0_idx -= 8;
  17426. ++ else
  17427. ++ oper->vht_op_info_chan_center_freq_seg0_idx += 8;
  17428. ++ } else if (hapd->iconf->vht_oper_chwidth == 3) {
  17429. ++ /*
  17430. ++ * Convert 80+80 MHz channel width to new style as interop
  17431. ++ * workaround.
  17432. ++ */
  17433. ++ oper->vht_op_info_chwidth = 1;
  17434. ++ }
  17435. ++
  17436. + /* VHT Basic MCS set comes from hw */
  17437. + /* Hard code 1 stream, MCS0-7 is a min Basic VHT MCS rates */
  17438. + oper->vht_basic_mcs_set = host_to_le16(0xfffc);
  17439. diff --git a/drivers/net/wireless/marvell/mwlwifi/hostapd/README b/drivers/net/wireless/marvell/mwlwifi/hostapd/README
  17440. new file mode 100644
  17441. index 000000000000..a5fb2b68d3d3
  17442. --- /dev/null
  17443. +++ b/drivers/net/wireless/marvell/mwlwifi/hostapd/README
  17444. @@ -0,0 +1,26 @@
  17445. +700-interoperability-workaround-for-80+80-and-160-MHz-channels:
  17446. +
  17447. +patch for OpenWrt hostapd package 2016-01-15 for following commit
  17448. +(move it to package/network/services/hostapd/patches).
  17449. +
  17450. +Note: After hostapd package 2016-06-15, this commit is already included.
  17451. +
  17452. +commit 03a72eacda5d9a1837a74387081596a0d5466ec1
  17453. +Author: Jouni Malinen <jouni@qca.qualcomm.com>
  17454. +Date: Thu Dec 17 18:39:19 2015 +0200
  17455. +
  17456. + VHT: Add an interoperability workaround for 80+80 and 160 MHz channels
  17457. +
  17458. + Number of deployed 80 MHz capable VHT stations that do not support 80+80
  17459. + and 160 MHz bandwidths seem to misbehave when trying to connect to an AP
  17460. + that advertises 80+80 or 160 MHz channel bandwidth in the VHT Operation
  17461. + element. To avoid such issues with deployed devices, modify the design
  17462. + based on newly proposed IEEE 802.11 standard changes.
  17463. +
  17464. + This allows poorly implemented VHT 80 MHz stations to connect with the
  17465. + AP in 80 MHz mode. 80+80 and 160 MHz capable stations need to support
  17466. + the new workaround mechanism to allow full bandwidth to be used.
  17467. + However, there are more or less no impacted station with 80+80/160
  17468. + capability deployed.
  17469. +
  17470. + Signed-off-by: Jouni Malinen jouni@qca.qualcomm.com
  17471. diff --git a/drivers/net/wireless/marvell/mwlwifi/mac80211.c b/drivers/net/wireless/marvell/mwlwifi/mac80211.c
  17472. new file mode 100644
  17473. index 000000000000..725dec0f604b
  17474. --- /dev/null
  17475. +++ b/drivers/net/wireless/marvell/mwlwifi/mac80211.c
  17476. @@ -0,0 +1,933 @@
  17477. +/*
  17478. + * Copyright (C) 2006-2018, Marvell International Ltd.
  17479. + *
  17480. + * This software file (the "File") is distributed by Marvell International
  17481. + * Ltd. under the terms of the GNU General Public License Version 2, June 1991
  17482. + * (the "License"). You may use, redistribute and/or modify this File in
  17483. + * accordance with the terms and conditions of the License, a copy of which
  17484. + * is available by writing to the Free Software Foundation, Inc.
  17485. + *
  17486. + * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
  17487. + * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
  17488. + * ARE EXPRESSLY DISCLAIMED. The License provides additional details about
  17489. + * this warranty disclaimer.
  17490. + */
  17491. +
  17492. +/* Description: This file implements mac80211 related functions. */
  17493. +
  17494. +#include <linux/etherdevice.h>
  17495. +
  17496. +#include "sysadpt.h"
  17497. +#include "core.h"
  17498. +#include "utils.h"
  17499. +#include "hif/fwcmd.h"
  17500. +#include "hif/hif-ops.h"
  17501. +
  17502. +#define MAX_AMPDU_ATTEMPTS 5
  17503. +
  17504. +static const struct ieee80211_rate mwl_rates_24[] = {
  17505. + { .bitrate = 10, .hw_value = 2, },
  17506. + { .bitrate = 20, .hw_value = 4, },
  17507. + { .bitrate = 55, .hw_value = 11, },
  17508. + { .bitrate = 110, .hw_value = 22, },
  17509. + { .bitrate = 220, .hw_value = 44, },
  17510. + { .bitrate = 60, .hw_value = 12, },
  17511. + { .bitrate = 90, .hw_value = 18, },
  17512. + { .bitrate = 120, .hw_value = 24, },
  17513. + { .bitrate = 180, .hw_value = 36, },
  17514. + { .bitrate = 240, .hw_value = 48, },
  17515. + { .bitrate = 360, .hw_value = 72, },
  17516. + { .bitrate = 480, .hw_value = 96, },
  17517. + { .bitrate = 540, .hw_value = 108, },
  17518. +};
  17519. +
  17520. +static const struct ieee80211_rate mwl_rates_50[] = {
  17521. + { .bitrate = 60, .hw_value = 12, },
  17522. + { .bitrate = 90, .hw_value = 18, },
  17523. + { .bitrate = 120, .hw_value = 24, },
  17524. + { .bitrate = 180, .hw_value = 36, },
  17525. + { .bitrate = 240, .hw_value = 48, },
  17526. + { .bitrate = 360, .hw_value = 72, },
  17527. + { .bitrate = 480, .hw_value = 96, },
  17528. + { .bitrate = 540, .hw_value = 108, },
  17529. +};
  17530. +
  17531. +static void mwl_get_rateinfo(struct mwl_priv *priv, u8 *addr,
  17532. + struct mwl_sta *sta_info)
  17533. +{
  17534. + int table_size = (sizeof(__le32) * 2 * SYSADPT_MAX_RATE_ADAPT_RATES);
  17535. + u8 *rate_table, *rate_idx;
  17536. + u32 rate_info;
  17537. + struct mwl_tx_hist_data *tx_hist_data;
  17538. + int ret, idx;
  17539. +
  17540. + rate_table = kzalloc(table_size, GFP_KERNEL);
  17541. + if (!rate_table)
  17542. + return;
  17543. +
  17544. + ret = mwl_fwcmd_get_ratetable(priv->hw, addr, rate_table,
  17545. + table_size, 0);
  17546. + if (ret) {
  17547. + kfree(rate_table);
  17548. + return;
  17549. + }
  17550. +
  17551. + idx = 0;
  17552. + rate_idx = rate_table;
  17553. + rate_info = le32_to_cpu(*(__le32 *)rate_idx);
  17554. + tx_hist_data = &sta_info->tx_hist.su_rate[0];
  17555. + while (rate_info) {
  17556. + if (idx < SYSADPT_MAX_RATE_ADAPT_RATES)
  17557. + tx_hist_data[idx].rateinfo = rate_info;
  17558. + idx++;
  17559. + rate_idx += (2 * sizeof(__le32));
  17560. + rate_info = le32_to_cpu(*(__le32 *)rate_idx);
  17561. + }
  17562. +
  17563. + kfree(rate_table);
  17564. +}
  17565. +
  17566. +static void mwl_mac80211_tx(struct ieee80211_hw *hw,
  17567. + struct ieee80211_tx_control *control,
  17568. + struct sk_buff *skb)
  17569. +{
  17570. + struct mwl_priv *priv = hw->priv;
  17571. +
  17572. + if (!priv->radio_on) {
  17573. + wiphy_warn(hw->wiphy,
  17574. + "dropped TX frame since radio is disabled\n");
  17575. + dev_kfree_skb_any(skb);
  17576. + return;
  17577. + }
  17578. +
  17579. + mwl_hif_tx_xmit(hw, control, skb);
  17580. +}
  17581. +
  17582. +static int mwl_mac80211_start(struct ieee80211_hw *hw)
  17583. +{
  17584. + struct mwl_priv *priv = hw->priv;
  17585. + int rc;
  17586. +
  17587. + /* Enable TX and RX tasklets. */
  17588. + mwl_hif_enable_data_tasks(hw);
  17589. +
  17590. + /* Enable interrupts */
  17591. + mwl_hif_irq_enable(hw);
  17592. +
  17593. + rc = mwl_fwcmd_radio_enable(hw);
  17594. + if (rc)
  17595. + goto fwcmd_fail;
  17596. + rc = mwl_fwcmd_set_rate_adapt_mode(hw, 0);
  17597. + if (rc)
  17598. + goto fwcmd_fail;
  17599. + rc = mwl_fwcmd_set_wmm_mode(hw, true);
  17600. + if (rc)
  17601. + goto fwcmd_fail;
  17602. + rc = mwl_fwcmd_ht_guard_interval(hw, GUARD_INTERVAL_AUTO);
  17603. + if (rc)
  17604. + goto fwcmd_fail;
  17605. + rc = mwl_fwcmd_set_dwds_stamode(hw, true);
  17606. + if (rc)
  17607. + goto fwcmd_fail;
  17608. + rc = mwl_fwcmd_set_fw_flush_timer(hw, SYSADPT_AMSDU_FLUSH_TIME);
  17609. + if (rc)
  17610. + goto fwcmd_fail;
  17611. + rc = mwl_fwcmd_set_optimization_level(hw, 1);
  17612. + if (rc)
  17613. + goto fwcmd_fail;
  17614. + if (priv->chip_type == MWL8997) {
  17615. + rc = mwl_fwcmd_config_EDMACCtrl(hw, 0);
  17616. + if (rc)
  17617. + goto fwcmd_fail;
  17618. + }
  17619. + if (priv->chip_type == MWL8964) {
  17620. + rc = mwl_fwcmd_newdp_dmathread_start(hw);
  17621. + if (rc)
  17622. + goto fwcmd_fail;
  17623. + rc = mwl_fwcmd_set_bftype(hw, priv->bf_type);
  17624. + if (rc)
  17625. + goto fwcmd_fail;
  17626. + }
  17627. +
  17628. + ieee80211_wake_queues(hw);
  17629. + return 0;
  17630. +
  17631. +fwcmd_fail:
  17632. + mwl_hif_irq_disable(hw);
  17633. + mwl_hif_disable_data_tasks(hw);
  17634. +
  17635. + return rc;
  17636. +}
  17637. +
  17638. +static void mwl_mac80211_stop(struct ieee80211_hw *hw)
  17639. +{
  17640. + mwl_fwcmd_radio_disable(hw);
  17641. +
  17642. + ieee80211_stop_queues(hw);
  17643. +
  17644. + /* Disable interrupts */
  17645. + mwl_hif_irq_disable(hw);
  17646. +
  17647. + /* Disable TX and RX tasklets. */
  17648. + mwl_hif_disable_data_tasks(hw);
  17649. +
  17650. + /* Return all skbs to mac80211 */
  17651. + mwl_hif_tx_return_pkts(hw);
  17652. +}
  17653. +
  17654. +static int mwl_mac80211_add_interface(struct ieee80211_hw *hw,
  17655. + struct ieee80211_vif *vif)
  17656. +{
  17657. + struct mwl_priv *priv = hw->priv;
  17658. + struct mwl_vif *mwl_vif;
  17659. + u32 macids_supported;
  17660. + int macid;
  17661. +
  17662. + switch (vif->type) {
  17663. + case NL80211_IFTYPE_AP:
  17664. + case NL80211_IFTYPE_MESH_POINT:
  17665. + if (vif->type == NL80211_IFTYPE_MESH_POINT)
  17666. + if (priv->chip_type != MWL8997)
  17667. + return -EPERM;
  17668. + macids_supported = priv->ap_macids_supported;
  17669. + break;
  17670. + case NL80211_IFTYPE_STATION:
  17671. + macids_supported = priv->sta_macids_supported;
  17672. + break;
  17673. + default:
  17674. + return -EINVAL;
  17675. + }
  17676. +
  17677. + macid = ffs(macids_supported & ~priv->macids_used);
  17678. +
  17679. + if (!macid) {
  17680. + wiphy_warn(hw->wiphy, "no macid can be allocated\n");
  17681. + return -EBUSY;
  17682. + }
  17683. + macid--;
  17684. +
  17685. + /* Setup driver private area. */
  17686. + mwl_vif = mwl_dev_get_vif(vif);
  17687. + memset(mwl_vif, 0, sizeof(*mwl_vif));
  17688. + mwl_vif->type = vif->type;
  17689. + mwl_vif->macid = macid;
  17690. + mwl_vif->seqno = 0;
  17691. + mwl_vif->is_hw_crypto_enabled = false;
  17692. + mwl_vif->beacon_info.valid = false;
  17693. + mwl_vif->set_beacon = false;
  17694. + mwl_vif->basic_rate_idx = 0;
  17695. + mwl_vif->broadcast_ssid = 0xFF;
  17696. + mwl_vif->iv16 = 1;
  17697. + mwl_vif->iv32 = 0;
  17698. + mwl_vif->keyidx = 0;
  17699. +
  17700. + switch (vif->type) {
  17701. + case NL80211_IFTYPE_AP:
  17702. + ether_addr_copy(mwl_vif->bssid, vif->addr);
  17703. + mwl_fwcmd_set_new_stn_add_self(hw, vif);
  17704. + if (priv->chip_type == MWL8964) {
  17705. + /* allow firmware to really set channel */
  17706. + mwl_fwcmd_bss_start(hw, vif, true);
  17707. + mwl_fwcmd_bss_start(hw, vif, false);
  17708. + }
  17709. + break;
  17710. + case NL80211_IFTYPE_MESH_POINT:
  17711. + ether_addr_copy(mwl_vif->bssid, vif->addr);
  17712. + mwl_fwcmd_set_new_stn_add_self(hw, vif);
  17713. + break;
  17714. + case NL80211_IFTYPE_STATION:
  17715. + ether_addr_copy(mwl_vif->sta_mac, vif->addr);
  17716. + mwl_fwcmd_bss_start(hw, vif, true);
  17717. + mwl_fwcmd_set_infra_mode(hw, vif);
  17718. + mwl_fwcmd_set_mac_addr_client(hw, vif, vif->addr);
  17719. + break;
  17720. + default:
  17721. + return -EINVAL;
  17722. + }
  17723. +
  17724. + priv->macids_used |= 1 << mwl_vif->macid;
  17725. + spin_lock_bh(&priv->vif_lock);
  17726. + list_add_tail(&mwl_vif->list, &priv->vif_list);
  17727. + spin_unlock_bh(&priv->vif_lock);
  17728. +
  17729. + return 0;
  17730. +}
  17731. +
  17732. +static void mwl_mac80211_remove_vif(struct mwl_priv *priv,
  17733. + struct ieee80211_vif *vif)
  17734. +{
  17735. + struct mwl_vif *mwl_vif = mwl_dev_get_vif(vif);
  17736. +
  17737. + if (!priv->macids_used)
  17738. + return;
  17739. +
  17740. + mwl_hif_tx_del_pkts_via_vif(priv->hw, vif);
  17741. +
  17742. + priv->macids_used &= ~(1 << mwl_vif->macid);
  17743. + spin_lock_bh(&priv->vif_lock);
  17744. + list_del(&mwl_vif->list);
  17745. + spin_unlock_bh(&priv->vif_lock);
  17746. +}
  17747. +
  17748. +static void mwl_mac80211_remove_interface(struct ieee80211_hw *hw,
  17749. + struct ieee80211_vif *vif)
  17750. +{
  17751. + struct mwl_priv *priv = hw->priv;
  17752. +
  17753. + switch (vif->type) {
  17754. + case NL80211_IFTYPE_AP:
  17755. + case NL80211_IFTYPE_MESH_POINT:
  17756. + mwl_fwcmd_set_new_stn_del(hw, vif, vif->addr);
  17757. + break;
  17758. + case NL80211_IFTYPE_STATION:
  17759. + mwl_fwcmd_remove_mac_addr(hw, vif, vif->addr);
  17760. + break;
  17761. + default:
  17762. + break;
  17763. + }
  17764. +
  17765. + mwl_mac80211_remove_vif(priv, vif);
  17766. +}
  17767. +
  17768. +static int mwl_mac80211_config(struct ieee80211_hw *hw,
  17769. + u32 changed)
  17770. +{
  17771. + struct ieee80211_conf *conf = &hw->conf;
  17772. + int rc;
  17773. +
  17774. + wiphy_debug(hw->wiphy, "change: 0x%x\n", changed);
  17775. +
  17776. + if (conf->flags & IEEE80211_CONF_IDLE)
  17777. + rc = mwl_fwcmd_radio_disable(hw);
  17778. + else
  17779. + rc = mwl_fwcmd_radio_enable(hw);
  17780. +
  17781. + if (rc)
  17782. + goto out;
  17783. +
  17784. + if (changed & IEEE80211_CONF_CHANGE_CHANNEL) {
  17785. + int rate = 0;
  17786. +
  17787. + if (conf->chandef.chan->band == NL80211_BAND_2GHZ) {
  17788. + mwl_fwcmd_set_apmode(hw, AP_MODE_2_4GHZ_11AC_MIXED);
  17789. + mwl_fwcmd_set_linkadapt_cs_mode(hw,
  17790. + LINK_CS_STATE_CONSERV);
  17791. + rate = mwl_rates_24[0].hw_value;
  17792. + } else if (conf->chandef.chan->band == NL80211_BAND_5GHZ) {
  17793. + mwl_fwcmd_set_apmode(hw, AP_MODE_11AC);
  17794. + mwl_fwcmd_set_linkadapt_cs_mode(hw,
  17795. + LINK_CS_STATE_AUTO);
  17796. + rate = mwl_rates_50[0].hw_value;
  17797. +
  17798. + if (conf->radar_enabled)
  17799. + mwl_fwcmd_set_radar_detect(hw, MONITOR_START);
  17800. + else
  17801. + mwl_fwcmd_set_radar_detect(hw,
  17802. + STOP_DETECT_RADAR);
  17803. + }
  17804. +
  17805. + rc = mwl_fwcmd_set_rf_channel(hw, conf);
  17806. + if (rc)
  17807. + goto out;
  17808. + rc = mwl_fwcmd_use_fixed_rate(hw, rate, rate);
  17809. + if (rc)
  17810. + goto out;
  17811. + rc = mwl_fwcmd_max_tx_power(hw, conf, 0);
  17812. + if (rc)
  17813. + goto out;
  17814. + rc = mwl_fwcmd_tx_power(hw, conf, 0);
  17815. + if (rc)
  17816. + goto out;
  17817. + rc = mwl_fwcmd_set_cdd(hw);
  17818. + }
  17819. +
  17820. +out:
  17821. +
  17822. + return rc;
  17823. +}
  17824. +
  17825. +static void mwl_mac80211_bss_info_changed_sta(struct ieee80211_hw *hw,
  17826. + struct ieee80211_vif *vif,
  17827. + struct ieee80211_bss_conf *info,
  17828. + u32 changed)
  17829. +{
  17830. + struct mwl_priv *priv = hw->priv;
  17831. +
  17832. + if ((changed & BSS_CHANGED_ERP_SLOT) && (priv->chip_type == MWL8997)) {
  17833. + if (priv->use_short_slot != vif->bss_conf.use_short_slot) {
  17834. + mwl_fwcmd_set_slot_time(hw,
  17835. + vif->bss_conf.use_short_slot);
  17836. + priv->use_short_slot = vif->bss_conf.use_short_slot;
  17837. + }
  17838. + }
  17839. +
  17840. + if (changed & BSS_CHANGED_ERP_PREAMBLE) {
  17841. + if (priv->use_short_preamble !=
  17842. + vif->bss_conf.use_short_preamble) {
  17843. + mwl_fwcmd_set_radio_preamble(
  17844. + hw, vif->bss_conf.use_short_preamble);
  17845. + priv->use_short_preamble =
  17846. + vif->bss_conf.use_short_preamble;
  17847. + }
  17848. + }
  17849. +
  17850. + if ((changed & BSS_CHANGED_ASSOC) && vif->bss_conf.assoc)
  17851. + mwl_fwcmd_set_aid(hw, vif, (u8 *)vif->bss_conf.bssid,
  17852. + vif->bss_conf.aid);
  17853. +}
  17854. +
  17855. +static void mwl_mac80211_bss_info_changed_ap(struct ieee80211_hw *hw,
  17856. + struct ieee80211_vif *vif,
  17857. + struct ieee80211_bss_conf *info,
  17858. + u32 changed)
  17859. +{
  17860. + struct mwl_priv *priv = hw->priv;
  17861. + struct mwl_vif *mwl_vif;
  17862. +
  17863. + mwl_vif = mwl_dev_get_vif(vif);
  17864. +
  17865. + if ((changed & BSS_CHANGED_ERP_SLOT) && (priv->chip_type == MWL8997)) {
  17866. + if (priv->use_short_slot != vif->bss_conf.use_short_slot) {
  17867. + mwl_fwcmd_set_slot_time(hw,
  17868. + vif->bss_conf.use_short_slot);
  17869. + priv->use_short_slot = vif->bss_conf.use_short_slot;
  17870. + }
  17871. + }
  17872. +
  17873. + if (changed & BSS_CHANGED_ERP_PREAMBLE) {
  17874. + if (priv->use_short_preamble !=
  17875. + vif->bss_conf.use_short_preamble) {
  17876. + mwl_fwcmd_set_radio_preamble(
  17877. + hw, vif->bss_conf.use_short_preamble);
  17878. + priv->use_short_preamble =
  17879. + vif->bss_conf.use_short_preamble;
  17880. + }
  17881. + }
  17882. +
  17883. + if (changed & BSS_CHANGED_BASIC_RATES) {
  17884. + int idx;
  17885. + int rate;
  17886. +
  17887. + /* Use lowest supported basic rate for multicasts
  17888. + * and management frames (such as probe responses --
  17889. + * beacons will always go out at 1 Mb/s).
  17890. + */
  17891. + idx = ffs(vif->bss_conf.basic_rates);
  17892. + if (idx)
  17893. + idx--;
  17894. + if (mwl_vif->basic_rate_idx != idx) {
  17895. + if (hw->conf.chandef.chan->band == NL80211_BAND_2GHZ)
  17896. + rate = mwl_rates_24[idx].hw_value;
  17897. + else
  17898. + rate = mwl_rates_50[idx].hw_value;
  17899. +
  17900. + mwl_fwcmd_use_fixed_rate(hw, rate, rate);
  17901. + mwl_vif->basic_rate_idx = idx;
  17902. + }
  17903. + }
  17904. +
  17905. + if (changed & (BSS_CHANGED_BEACON_INT | BSS_CHANGED_BEACON)) {
  17906. + struct sk_buff *skb;
  17907. +
  17908. + if ((info->ssid[0] != '\0') &&
  17909. + (info->ssid_len != 0) &&
  17910. + (!info->hidden_ssid)) {
  17911. + if (mwl_vif->broadcast_ssid != true) {
  17912. + mwl_fwcmd_broadcast_ssid_enable(hw, vif, true);
  17913. + mwl_vif->broadcast_ssid = true;
  17914. + }
  17915. + } else {
  17916. + if (mwl_vif->broadcast_ssid != false) {
  17917. + mwl_fwcmd_broadcast_ssid_enable(hw, vif, false);
  17918. + mwl_vif->broadcast_ssid = false;
  17919. + }
  17920. + }
  17921. +
  17922. + if (!mwl_vif->set_beacon) {
  17923. + skb = ieee80211_beacon_get(hw, vif);
  17924. +
  17925. + if (skb) {
  17926. + mwl_fwcmd_set_beacon(hw, vif, skb->data, skb->len);
  17927. + dev_kfree_skb_any(skb);
  17928. + }
  17929. + mwl_vif->set_beacon = true;
  17930. + }
  17931. + }
  17932. +
  17933. + if (changed & BSS_CHANGED_BEACON_ENABLED)
  17934. + mwl_fwcmd_bss_start(hw, vif, info->enable_beacon);
  17935. +}
  17936. +
  17937. +static void mwl_mac80211_bss_info_changed(struct ieee80211_hw *hw,
  17938. + struct ieee80211_vif *vif,
  17939. + struct ieee80211_bss_conf *info,
  17940. + u32 changed)
  17941. +{
  17942. + switch (vif->type) {
  17943. + case NL80211_IFTYPE_AP:
  17944. + case NL80211_IFTYPE_MESH_POINT:
  17945. + mwl_mac80211_bss_info_changed_ap(hw, vif, info, changed);
  17946. + break;
  17947. + case NL80211_IFTYPE_STATION:
  17948. + mwl_mac80211_bss_info_changed_sta(hw, vif, info, changed);
  17949. + break;
  17950. + default:
  17951. + break;
  17952. + }
  17953. +}
  17954. +
  17955. +static void mwl_mac80211_configure_filter(struct ieee80211_hw *hw,
  17956. + unsigned int changed_flags,
  17957. + unsigned int *total_flags,
  17958. + u64 multicast)
  17959. +{
  17960. + /* AP firmware doesn't allow fine-grained control over
  17961. + * the receive filter.
  17962. + */
  17963. + *total_flags &= FIF_ALLMULTI | FIF_BCN_PRBRESP_PROMISC;
  17964. +}
  17965. +
  17966. +static int mwl_mac80211_set_key(struct ieee80211_hw *hw,
  17967. + enum set_key_cmd cmd_param,
  17968. + struct ieee80211_vif *vif,
  17969. + struct ieee80211_sta *sta,
  17970. + struct ieee80211_key_conf *key)
  17971. +{
  17972. + struct mwl_vif *mwl_vif;
  17973. + struct mwl_sta *sta_info;
  17974. + int rc = 0;
  17975. + u8 encr_type;
  17976. + u8 *addr;
  17977. +
  17978. + mwl_vif = mwl_dev_get_vif(vif);
  17979. + addr = sta ? sta->addr : vif->addr;
  17980. +
  17981. + if (cmd_param == SET_KEY) {
  17982. + if ((key->cipher == WLAN_CIPHER_SUITE_WEP40) ||
  17983. + (key->cipher == WLAN_CIPHER_SUITE_WEP104)) {
  17984. + encr_type = ENCR_TYPE_WEP;
  17985. + } else if (key->cipher == WLAN_CIPHER_SUITE_CCMP) {
  17986. + encr_type = ENCR_TYPE_AES;
  17987. + if ((key->flags & IEEE80211_KEY_FLAG_PAIRWISE) == 0) {
  17988. + if (vif->type != NL80211_IFTYPE_STATION)
  17989. + mwl_vif->keyidx = key->keyidx;
  17990. + }
  17991. + } else if (key->cipher == WLAN_CIPHER_SUITE_TKIP) {
  17992. + encr_type = ENCR_TYPE_TKIP;
  17993. + } else {
  17994. + encr_type = ENCR_TYPE_DISABLE;
  17995. + }
  17996. +
  17997. + rc = mwl_fwcmd_update_encryption_enable(hw, vif, addr,
  17998. + encr_type);
  17999. + if (rc)
  18000. + goto out;
  18001. + rc = mwl_fwcmd_encryption_set_key(hw, vif, addr, key);
  18002. + if (rc)
  18003. + goto out;
  18004. +
  18005. + mwl_vif->is_hw_crypto_enabled = true;
  18006. + if (sta) {
  18007. + sta_info = mwl_dev_get_sta(sta);
  18008. + sta_info->is_key_set = true;
  18009. + }
  18010. + } else {
  18011. + rc = mwl_fwcmd_encryption_remove_key(hw, vif, addr, key);
  18012. + if (rc)
  18013. + goto out;
  18014. + }
  18015. +
  18016. +out:
  18017. +
  18018. + return rc;
  18019. +}
  18020. +
  18021. +static int mwl_mac80211_set_rts_threshold(struct ieee80211_hw *hw,
  18022. + u32 value)
  18023. +{
  18024. + return mwl_fwcmd_set_rts_threshold(hw, value);
  18025. +}
  18026. +
  18027. +static int mwl_mac80211_sta_add(struct ieee80211_hw *hw,
  18028. + struct ieee80211_vif *vif,
  18029. + struct ieee80211_sta *sta)
  18030. +{
  18031. + struct mwl_priv *priv = hw->priv;
  18032. + u16 stnid, sta_stnid = 0;
  18033. + struct mwl_vif *mwl_vif;
  18034. + struct wireless_dev *wdev = ieee80211_vif_to_wdev(vif);
  18035. + bool use_4addr = wdev->use_4addr;
  18036. + struct mwl_sta *sta_info;
  18037. + struct ieee80211_key_conf *key;
  18038. + int rc;
  18039. + int i;
  18040. +
  18041. + if (vif->type == NL80211_IFTYPE_STATION)
  18042. + sta->aid = 1;
  18043. + mwl_vif = mwl_dev_get_vif(vif);
  18044. + stnid = utils_assign_stnid(priv, mwl_vif->macid, sta->aid);
  18045. + if (!stnid)
  18046. + return -EPERM;
  18047. + if (vif->type == NL80211_IFTYPE_STATION) {
  18048. + sta_stnid = utils_assign_stnid(priv, mwl_vif->macid,
  18049. + sta->aid + 1);
  18050. + if (!sta_stnid) {
  18051. + utils_free_stnid(priv, stnid);
  18052. + return -EPERM;
  18053. + }
  18054. + ether_addr_copy(mwl_vif->bssid, sta->addr);
  18055. + }
  18056. + sta_info = mwl_dev_get_sta(sta);
  18057. + memset(sta_info, 0, sizeof(*sta_info));
  18058. +
  18059. + if (vif->type == NL80211_IFTYPE_MESH_POINT)
  18060. + sta_info->is_mesh_node = true;
  18061. +
  18062. + if (sta->ht_cap.ht_supported) {
  18063. + sta_info->is_ampdu_allowed = true;
  18064. + sta_info->is_amsdu_allowed = false;
  18065. + if (sta->ht_cap.cap & IEEE80211_HT_CAP_MAX_AMSDU)
  18066. + sta_info->amsdu_ctrl.cap = MWL_AMSDU_SIZE_8K;
  18067. + else
  18068. + sta_info->amsdu_ctrl.cap = MWL_AMSDU_SIZE_4K;
  18069. + if ((sta->tdls) && (!sta->wme))
  18070. + sta->wme = true;
  18071. + }
  18072. + sta_info->mwl_vif = mwl_vif;
  18073. + sta_info->stnid = stnid;
  18074. + if (vif->type == NL80211_IFTYPE_STATION)
  18075. + sta_info->sta_stnid = sta_stnid;
  18076. + sta_info->tx_rate_info = utils_get_init_tx_rate(priv, &hw->conf, sta);
  18077. + sta_info->iv16 = 1;
  18078. + sta_info->iv32 = 0;
  18079. + spin_lock_init(&sta_info->amsdu_lock);
  18080. + spin_lock_bh(&priv->sta_lock);
  18081. + list_add_tail(&sta_info->list, &priv->sta_list);
  18082. + spin_unlock_bh(&priv->sta_lock);
  18083. +
  18084. + if (vif->type == NL80211_IFTYPE_STATION)
  18085. + mwl_fwcmd_set_new_stn_del(hw, vif, sta->addr);
  18086. +
  18087. + if (priv->chip_type == MWL8964) {
  18088. + if (use_4addr) {
  18089. + sta_info->wds = true;
  18090. + rc = mwl_fwcmd_set_new_stn_add_sc4(hw, vif, sta,
  18091. + WDS_MODE);
  18092. + } else
  18093. + rc = mwl_fwcmd_set_new_stn_add_sc4(hw, vif, sta, 0);
  18094. + } else
  18095. + rc = mwl_fwcmd_set_new_stn_add(hw, vif, sta);
  18096. +
  18097. + if ((vif->type == NL80211_IFTYPE_STATION) && !use_4addr)
  18098. + mwl_hif_set_sta_id(hw, sta, true, true);
  18099. + else
  18100. + mwl_hif_set_sta_id(hw, sta, false, true);
  18101. +
  18102. + for (i = 0; i < NUM_WEP_KEYS; i++) {
  18103. + key = (struct ieee80211_key_conf *)mwl_vif->wep_key_conf[i].key;
  18104. +
  18105. + if (mwl_vif->wep_key_conf[i].enabled)
  18106. + mwl_mac80211_set_key(hw, SET_KEY, vif, sta, key);
  18107. + }
  18108. +
  18109. + mwl_get_rateinfo(priv, sta->addr, sta_info);
  18110. +
  18111. + return rc;
  18112. +}
  18113. +
  18114. +static int mwl_mac80211_sta_remove(struct ieee80211_hw *hw,
  18115. + struct ieee80211_vif *vif,
  18116. + struct ieee80211_sta *sta)
  18117. +{
  18118. + struct mwl_priv *priv = hw->priv;
  18119. + int rc;
  18120. + struct mwl_sta *sta_info = mwl_dev_get_sta(sta);
  18121. +
  18122. + mwl_hif_tx_del_sta_amsdu_pkts(hw, sta);
  18123. + mwl_fwcmd_del_sta_streams(hw, sta);
  18124. + mwl_hif_tx_del_pkts_via_sta(hw, sta);
  18125. +
  18126. + rc = mwl_fwcmd_set_new_stn_del(hw, vif, sta->addr);
  18127. +
  18128. + if (vif->type == NL80211_IFTYPE_STATION)
  18129. + mwl_hif_set_sta_id(hw, sta, true, false);
  18130. + else
  18131. + mwl_hif_set_sta_id(hw, sta, false, false);
  18132. +
  18133. + if (priv->chip_type != MWL8964)
  18134. + utils_free_stnid(priv, sta_info->stnid);
  18135. + if (vif->type == NL80211_IFTYPE_STATION)
  18136. + utils_free_stnid(priv, sta_info->sta_stnid);
  18137. +
  18138. + spin_lock_bh(&priv->sta_lock);
  18139. + list_del(&sta_info->list);
  18140. + spin_unlock_bh(&priv->sta_lock);
  18141. +
  18142. + return rc;
  18143. +}
  18144. +
  18145. +static int mwl_mac80211_conf_tx(struct ieee80211_hw *hw,
  18146. + struct ieee80211_vif *vif,
  18147. + u16 queue,
  18148. + const struct ieee80211_tx_queue_params *params)
  18149. +{
  18150. + struct mwl_priv *priv = hw->priv;
  18151. + int rc = 0;
  18152. +
  18153. + if (WARN_ON(queue > SYSADPT_TX_WMM_QUEUES - 1))
  18154. + return -EINVAL;
  18155. +
  18156. + memcpy(&priv->wmm_params[queue], params, sizeof(*params));
  18157. +
  18158. + if (!priv->wmm_enabled) {
  18159. + rc = mwl_fwcmd_set_wmm_mode(hw, true);
  18160. + priv->wmm_enabled = true;
  18161. + }
  18162. +
  18163. + if (!rc) {
  18164. + int q = SYSADPT_TX_WMM_QUEUES - 1 - queue;
  18165. +
  18166. + rc = mwl_fwcmd_set_edca_params(hw, q,
  18167. + params->cw_min, params->cw_max,
  18168. + params->aifs, params->txop);
  18169. + }
  18170. +
  18171. + return rc;
  18172. +}
  18173. +
  18174. +static int mwl_mac80211_get_stats(struct ieee80211_hw *hw,
  18175. + struct ieee80211_low_level_stats *stats)
  18176. +{
  18177. + return mwl_fwcmd_get_stat(hw, stats);
  18178. +}
  18179. +
  18180. +static int mwl_mac80211_get_survey(struct ieee80211_hw *hw,
  18181. + int idx,
  18182. + struct survey_info *survey)
  18183. +{
  18184. + struct mwl_priv *priv = hw->priv;
  18185. + struct mwl_survey_info *survey_info;
  18186. +
  18187. + if (priv->survey_info_idx) {
  18188. + if (idx >= priv->survey_info_idx) {
  18189. + priv->survey_info_idx = 0;
  18190. + return -ENOENT;
  18191. + }
  18192. + survey_info = &priv->survey_info[idx];
  18193. + } else {
  18194. + if (idx != 0)
  18195. + return -ENOENT;
  18196. + mwl_fwcmd_get_survey(hw, 0);
  18197. + survey_info = &priv->cur_survey_info;
  18198. + if (!(hw->conf.flags & IEEE80211_CONF_OFFCHANNEL))
  18199. + survey->filled |= SURVEY_INFO_IN_USE;
  18200. + }
  18201. +
  18202. + survey->channel = &survey_info->channel;
  18203. + survey->filled |= survey_info->filled;
  18204. + survey->time = survey_info->time_period / 1000;
  18205. + survey->time_busy = survey_info->time_busy / 1000;
  18206. + survey->time_tx = survey_info->time_tx / 1000;
  18207. + survey->noise = survey_info->noise;
  18208. +
  18209. + return 0;
  18210. +}
  18211. +
  18212. +static int mwl_mac80211_ampdu_action(struct ieee80211_hw *hw,
  18213. + struct ieee80211_vif *vif,
  18214. + struct ieee80211_ampdu_params *params)
  18215. +{
  18216. + int rc = 0;
  18217. + struct mwl_priv *priv = hw->priv;
  18218. + struct mwl_ampdu_stream *stream;
  18219. + enum ieee80211_ampdu_mlme_action action = params->action;
  18220. + struct ieee80211_sta *sta = params->sta;
  18221. + u16 tid = params->tid;
  18222. + u8 buf_size = params->buf_size;
  18223. + u8 *addr = sta->addr;
  18224. + struct mwl_sta *sta_info;
  18225. +
  18226. + sta_info = mwl_dev_get_sta(sta);
  18227. +
  18228. + spin_lock_bh(&priv->stream_lock);
  18229. +
  18230. + stream = mwl_fwcmd_lookup_stream(hw, sta, tid);
  18231. +
  18232. + switch (action) {
  18233. + case IEEE80211_AMPDU_RX_START:
  18234. + if (priv->chip_type == MWL8964) {
  18235. + struct mwl_ampdu_stream tmp;
  18236. +
  18237. + tmp.sta = sta;
  18238. + tmp.tid = tid;
  18239. + spin_unlock_bh(&priv->stream_lock);
  18240. + mwl_fwcmd_create_ba(hw, &tmp, vif,
  18241. + BA_FLAG_DIRECTION_DOWN,
  18242. + buf_size, params->ssn,
  18243. + params->amsdu);
  18244. + spin_lock_bh(&priv->stream_lock);
  18245. + break;
  18246. + }
  18247. + case IEEE80211_AMPDU_RX_STOP:
  18248. + if (priv->chip_type == MWL8964) {
  18249. + struct mwl_ampdu_stream tmp;
  18250. +
  18251. + tmp.sta = sta;
  18252. + tmp.tid = tid;
  18253. + spin_unlock_bh(&priv->stream_lock);
  18254. + mwl_fwcmd_destroy_ba(hw, &tmp,
  18255. + BA_FLAG_DIRECTION_DOWN);
  18256. + spin_lock_bh(&priv->stream_lock);
  18257. + }
  18258. + break;
  18259. + case IEEE80211_AMPDU_TX_START:
  18260. + if (!sta_info->is_ampdu_allowed) {
  18261. + wiphy_warn(hw->wiphy, "ampdu not allowed\n");
  18262. + rc = -EPERM;
  18263. + break;
  18264. + }
  18265. +
  18266. + if (!stream) {
  18267. + stream = mwl_fwcmd_add_stream(hw, sta, tid);
  18268. + if (!stream) {
  18269. + wiphy_warn(hw->wiphy, "no stream found\n");
  18270. + rc = -EPERM;
  18271. + break;
  18272. + }
  18273. + }
  18274. +
  18275. + if (priv->chip_type != MWL8964) {
  18276. + spin_unlock_bh(&priv->stream_lock);
  18277. + rc = mwl_fwcmd_check_ba(hw, stream, vif,
  18278. + BA_FLAG_DIRECTION_UP);
  18279. + spin_lock_bh(&priv->stream_lock);
  18280. + if (rc) {
  18281. + mwl_fwcmd_remove_stream(hw, stream);
  18282. + sta_info->check_ba_failed[tid]++;
  18283. + break;
  18284. + }
  18285. + }
  18286. + stream->state = AMPDU_STREAM_IN_PROGRESS;
  18287. + spin_unlock_bh(&priv->stream_lock);
  18288. + rc = mwl_fwcmd_get_seqno(hw, stream, &params->ssn);
  18289. + spin_lock_bh(&priv->stream_lock);
  18290. + if (rc)
  18291. + break;
  18292. + ieee80211_start_tx_ba_cb_irqsafe(vif, addr, tid);
  18293. + break;
  18294. + case IEEE80211_AMPDU_TX_STOP_CONT:
  18295. + case IEEE80211_AMPDU_TX_STOP_FLUSH:
  18296. + case IEEE80211_AMPDU_TX_STOP_FLUSH_CONT:
  18297. + if (stream) {
  18298. + if (stream->state == AMPDU_STREAM_ACTIVE) {
  18299. + stream->state = AMPDU_STREAM_IN_PROGRESS;
  18300. + mwl_hif_tx_del_ampdu_pkts(hw, sta, tid);
  18301. + spin_unlock_bh(&priv->stream_lock);
  18302. + mwl_fwcmd_destroy_ba(hw, stream,
  18303. + BA_FLAG_DIRECTION_UP);
  18304. + spin_lock_bh(&priv->stream_lock);
  18305. + sta_info->is_amsdu_allowed = false;
  18306. + }
  18307. +
  18308. + mwl_fwcmd_remove_stream(hw, stream);
  18309. + ieee80211_stop_tx_ba_cb_irqsafe(vif, addr, tid);
  18310. + } else {
  18311. + rc = -EPERM;
  18312. + }
  18313. + break;
  18314. + case IEEE80211_AMPDU_TX_OPERATIONAL:
  18315. + if (stream) {
  18316. + if (WARN_ON(stream->state !=
  18317. + AMPDU_STREAM_IN_PROGRESS)) {
  18318. + rc = -EPERM;
  18319. + break;
  18320. + }
  18321. + spin_unlock_bh(&priv->stream_lock);
  18322. + rc = mwl_fwcmd_create_ba(hw, stream, vif,
  18323. + BA_FLAG_DIRECTION_UP,
  18324. + buf_size, params->ssn,
  18325. + params->amsdu);
  18326. + spin_lock_bh(&priv->stream_lock);
  18327. +
  18328. + if (!rc) {
  18329. + stream->state = AMPDU_STREAM_ACTIVE;
  18330. + sta_info->check_ba_failed[tid] = 0;
  18331. + if (priv->tx_amsdu)
  18332. + sta_info->is_amsdu_allowed =
  18333. + params->amsdu;
  18334. + else
  18335. + sta_info->is_amsdu_allowed = false;
  18336. + } else {
  18337. + spin_unlock_bh(&priv->stream_lock);
  18338. + mwl_fwcmd_destroy_ba(hw, stream,
  18339. + BA_FLAG_DIRECTION_UP);
  18340. + spin_lock_bh(&priv->stream_lock);
  18341. + mwl_fwcmd_remove_stream(hw, stream);
  18342. + wiphy_err(hw->wiphy,
  18343. + "ampdu operation error code: %d\n",
  18344. + rc);
  18345. + }
  18346. + } else {
  18347. + rc = -EPERM;
  18348. + }
  18349. + break;
  18350. + default:
  18351. + rc = -ENOTSUPP;
  18352. + break;
  18353. + }
  18354. +
  18355. + spin_unlock_bh(&priv->stream_lock);
  18356. +
  18357. + return rc;
  18358. +}
  18359. +
  18360. +static int mwl_mac80211_chnl_switch(struct ieee80211_hw *hw,
  18361. + struct ieee80211_vif *vif,
  18362. + struct ieee80211_channel_switch *ch_switch)
  18363. +{
  18364. + int rc = 0;
  18365. +
  18366. + rc = mwl_fwcmd_set_switch_channel(hw, ch_switch);
  18367. +
  18368. + return rc;
  18369. +}
  18370. +
  18371. +static void mwl_mac80211_sw_scan_start(struct ieee80211_hw *hw,
  18372. + struct ieee80211_vif *vif,
  18373. + const u8 *mac_addr)
  18374. +{
  18375. + struct mwl_priv *priv = hw->priv;
  18376. +
  18377. + priv->sw_scanning = true;
  18378. + priv->survey_info_idx = 0;
  18379. +}
  18380. +
  18381. +static void mwl_mac80211_sw_scan_complete(struct ieee80211_hw *hw,
  18382. + struct ieee80211_vif *vif)
  18383. +{
  18384. + struct mwl_priv *priv = hw->priv;
  18385. +
  18386. + priv->sw_scanning = false;
  18387. +}
  18388. +
  18389. +const struct ieee80211_ops mwl_mac80211_ops = {
  18390. + .tx = mwl_mac80211_tx,
  18391. + .start = mwl_mac80211_start,
  18392. + .stop = mwl_mac80211_stop,
  18393. + .add_interface = mwl_mac80211_add_interface,
  18394. + .remove_interface = mwl_mac80211_remove_interface,
  18395. + .config = mwl_mac80211_config,
  18396. + .bss_info_changed = mwl_mac80211_bss_info_changed,
  18397. + .configure_filter = mwl_mac80211_configure_filter,
  18398. + .set_key = mwl_mac80211_set_key,
  18399. + .set_rts_threshold = mwl_mac80211_set_rts_threshold,
  18400. + .sta_add = mwl_mac80211_sta_add,
  18401. + .sta_remove = mwl_mac80211_sta_remove,
  18402. + .conf_tx = mwl_mac80211_conf_tx,
  18403. + .get_stats = mwl_mac80211_get_stats,
  18404. + .get_survey = mwl_mac80211_get_survey,
  18405. + .ampdu_action = mwl_mac80211_ampdu_action,
  18406. + .pre_channel_switch = mwl_mac80211_chnl_switch,
  18407. + .sw_scan_start = mwl_mac80211_sw_scan_start,
  18408. + .sw_scan_complete = mwl_mac80211_sw_scan_complete,
  18409. +};
  18410. diff --git a/drivers/net/wireless/marvell/mwlwifi/mu_mimo.c b/drivers/net/wireless/marvell/mwlwifi/mu_mimo.c
  18411. new file mode 100644
  18412. index 000000000000..74ab054f947e
  18413. --- /dev/null
  18414. +++ b/drivers/net/wireless/marvell/mwlwifi/mu_mimo.c
  18415. @@ -0,0 +1,21 @@
  18416. +/*
  18417. + * Copyright (C) 2006-2018, Marvell International Ltd.
  18418. + *
  18419. + * This software file (the "File") is distributed by Marvell International
  18420. + * Ltd. under the terms of the GNU General Public License Version 2, June 1991
  18421. + * (the "License"). You may use, redistribute and/or modify this File in
  18422. + * accordance with the terms and conditions of the License, a copy of which
  18423. + * is available by writing to the Free Software Foundation, Inc.
  18424. + *
  18425. + * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
  18426. + * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
  18427. + * ARE EXPRESSLY DISCLAIMED. The License provides additional details about
  18428. + * this warranty disclaimer.
  18429. + */
  18430. +
  18431. +/* Description: This file implements MU-MIMO functions. */
  18432. +
  18433. +#include "sysadpt.h"
  18434. +#include "core.h"
  18435. +#include "mu_mimo.h"
  18436. +
  18437. diff --git a/drivers/net/wireless/marvell/mwlwifi/mu_mimo.h b/drivers/net/wireless/marvell/mwlwifi/mu_mimo.h
  18438. new file mode 100644
  18439. index 000000000000..24179f404774
  18440. --- /dev/null
  18441. +++ b/drivers/net/wireless/marvell/mwlwifi/mu_mimo.h
  18442. @@ -0,0 +1,23 @@
  18443. +/*
  18444. + * Copyright (C) 2006-2018, Marvell International Ltd.
  18445. + *
  18446. + * This software file (the "File") is distributed by Marvell International
  18447. + * Ltd. under the terms of the GNU General Public License Version 2, June 1991
  18448. + * (the "License"). You may use, redistribute and/or modify this File in
  18449. + * accordance with the terms and conditions of the License, a copy of which
  18450. + * is available by writing to the Free Software Foundation, Inc.
  18451. + *
  18452. + * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
  18453. + * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
  18454. + * ARE EXPRESSLY DISCLAIMED. The License provides additional details about
  18455. + * this warranty disclaimer.
  18456. + */
  18457. +
  18458. +/* Description: This file defines MU-MIMO functions. */
  18459. +
  18460. +#ifndef _MU_MIMO_H_
  18461. +#define _MU_MIMO_H_
  18462. +
  18463. +
  18464. +
  18465. +#endif /* _MU_MIMO_H_ */
  18466. diff --git a/drivers/net/wireless/marvell/mwlwifi/sysadpt.h b/drivers/net/wireless/marvell/mwlwifi/sysadpt.h
  18467. new file mode 100644
  18468. index 000000000000..1194e5271870
  18469. --- /dev/null
  18470. +++ b/drivers/net/wireless/marvell/mwlwifi/sysadpt.h
  18471. @@ -0,0 +1,86 @@
  18472. +/*
  18473. + * Copyright (C) 2006-2018, Marvell International Ltd.
  18474. + *
  18475. + * This software file (the "File") is distributed by Marvell International
  18476. + * Ltd. under the terms of the GNU General Public License Version 2, June 1991
  18477. + * (the "License"). You may use, redistribute and/or modify this File in
  18478. + * accordance with the terms and conditions of the License, a copy of which
  18479. + * is available by writing to the Free Software Foundation, Inc.
  18480. + *
  18481. + * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
  18482. + * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
  18483. + * ARE EXPRESSLY DISCLAIMED. The License provides additional details about
  18484. + * this warranty disclaimer.
  18485. + */
  18486. +
  18487. +/* Description: This file defines system adaptation related information. */
  18488. +
  18489. +#ifndef _SYSADPT_H_
  18490. +#define _SYSADPT_H_
  18491. +
  18492. +#define SYSADPT_MAX_STA 64
  18493. +
  18494. +#define SYSADPT_MAX_STA_SC4 300
  18495. +
  18496. +#define SYSADPT_MAX_NUM_CHANNELS 64
  18497. +
  18498. +#define SYSADPT_MAX_DATA_RATES_G 14
  18499. +
  18500. +#define SYSADPT_MAX_MCS_RATES 24
  18501. +
  18502. +#define SYSADPT_MAX_11AC_RATES 20
  18503. +
  18504. +#define SYSADPT_MAX_RATE_ADAPT_RATES (SYSADPT_MAX_DATA_RATES_G + \
  18505. + SYSADPT_MAX_MCS_RATES + \
  18506. + SYSADPT_MAX_11AC_RATES)
  18507. +
  18508. +#define SYSADPT_TX_POWER_LEVEL_TOTAL 16 /* SC3 */
  18509. +
  18510. +#define SYSADPT_TX_GRP_PWR_LEVEL_TOTAL 28 /* KF2 */
  18511. +
  18512. +#define SYSADPT_TX_PWR_LEVEL_TOTAL_SC4 32 /* SC4 */
  18513. +
  18514. +#define SYSADPT_TX_WMM_QUEUES 4
  18515. +
  18516. +#define SYSADPT_NUM_OF_CLIENT 1
  18517. +
  18518. +#define SYSADPT_NUM_OF_AP 16
  18519. +
  18520. +#define SYSADPT_NUM_OF_MESH 1
  18521. +
  18522. +#define SYSADPT_TOTAL_TX_QUEUES (SYSADPT_TX_WMM_QUEUES + \
  18523. + SYSADPT_NUM_OF_AP)
  18524. +
  18525. +#define SYSADPT_MAX_AGGR_SIZE 4096
  18526. +
  18527. +#define SYSADPT_AMPDU_PACKET_THRESHOLD 64
  18528. +
  18529. +#define SYSADPT_AMSDU_FW_MAX_SIZE 3300
  18530. +
  18531. +#define SYSADPT_AMSDU_4K_MAX_SIZE SYSADPT_AMSDU_FW_MAX_SIZE
  18532. +
  18533. +#define SYSADPT_AMSDU_8K_MAX_SIZE SYSADPT_AMSDU_FW_MAX_SIZE
  18534. +
  18535. +#define SYSADPT_AMSDU_ALLOW_SIZE 1600
  18536. +
  18537. +#define SYSADPT_AMSDU_FLUSH_TIME 500
  18538. +
  18539. +#define SYSADPT_AMSDU_PACKET_THRESHOLD 10
  18540. +
  18541. +#define SYSADPT_MAX_TID 8
  18542. +
  18543. +#define SYSADPT_QUIET_PERIOD_DEFAULT 100
  18544. +
  18545. +#define SYSADPT_QUIET_PERIOD_MIN 25
  18546. +
  18547. +#define SYSADPT_QUIET_START_OFFSET 10
  18548. +
  18549. +#define SYSADPT_THERMAL_THROTTLE_MAX 100
  18550. +
  18551. +#define SYSADPT_TIMER_WAKEUP_TIME 10 /* ms */
  18552. +
  18553. +#define SYSADPT_OTP_BUF_SIZE (256*8) /* 258 lines * 8 bytes */
  18554. +
  18555. +#define SYSADPT_TXPWRLMT_CFG_BUF_SIZE (3650)
  18556. +
  18557. +#endif /* _SYSADPT_H_ */
  18558. diff --git a/drivers/net/wireless/marvell/mwlwifi/thermal.c b/drivers/net/wireless/marvell/mwlwifi/thermal.c
  18559. new file mode 100644
  18560. index 000000000000..7c59def51e7f
  18561. --- /dev/null
  18562. +++ b/drivers/net/wireless/marvell/mwlwifi/thermal.c
  18563. @@ -0,0 +1,182 @@
  18564. +/*
  18565. + * Copyright (C) 2006-2018, Marvell International Ltd.
  18566. + *
  18567. + * This software file (the "File") is distributed by Marvell International
  18568. + * Ltd. under the terms of the GNU General Public License Version 2, June 1991
  18569. + * (the "License"). You may use, redistribute and/or modify this File in
  18570. + * accordance with the terms and conditions of the License, a copy of which
  18571. + * is available by writing to the Free Software Foundation, Inc.
  18572. + *
  18573. + * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
  18574. + * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
  18575. + * ARE EXPRESSLY DISCLAIMED. The License provides additional details about
  18576. + * this warranty disclaimer.
  18577. + */
  18578. +
  18579. +/* Description: This file implements thermal framework related functions. */
  18580. +
  18581. +#include <linux/device.h>
  18582. +#include <linux/sysfs.h>
  18583. +#include <linux/thermal.h>
  18584. +#include <linux/hwmon.h>
  18585. +#include <linux/hwmon-sysfs.h>
  18586. +
  18587. +#include "sysadpt.h"
  18588. +#include "core.h"
  18589. +#include "hif/fwcmd.h"
  18590. +#include "thermal.h"
  18591. +
  18592. +static int
  18593. +mwl_thermal_get_max_throttle_state(struct thermal_cooling_device *cdev,
  18594. + unsigned long *state)
  18595. +{
  18596. + *state = SYSADPT_THERMAL_THROTTLE_MAX;
  18597. +
  18598. + return 0;
  18599. +}
  18600. +
  18601. +static int
  18602. +mwl_thermal_get_cur_throttle_state(struct thermal_cooling_device *cdev,
  18603. + unsigned long *state)
  18604. +{
  18605. + struct mwl_priv *priv = cdev->devdata;
  18606. +
  18607. + *state = priv->throttle_state;
  18608. +
  18609. + return 0;
  18610. +}
  18611. +
  18612. +static int
  18613. +mwl_thermal_set_cur_throttle_state(struct thermal_cooling_device *cdev,
  18614. + unsigned long throttle_state)
  18615. +{
  18616. + struct mwl_priv *priv = cdev->devdata;
  18617. +
  18618. + if (throttle_state > SYSADPT_THERMAL_THROTTLE_MAX) {
  18619. + wiphy_warn(priv->hw->wiphy,
  18620. + "throttle state %ld is exceeding the limit %d\n",
  18621. + throttle_state, SYSADPT_THERMAL_THROTTLE_MAX);
  18622. + return -EINVAL;
  18623. + }
  18624. + priv->throttle_state = throttle_state;
  18625. + mwl_thermal_set_throttling(priv);
  18626. +
  18627. + return 0;
  18628. +}
  18629. +
  18630. +static struct thermal_cooling_device_ops mwl_thermal_ops = {
  18631. + .get_max_state = mwl_thermal_get_max_throttle_state,
  18632. + .get_cur_state = mwl_thermal_get_cur_throttle_state,
  18633. + .set_cur_state = mwl_thermal_set_cur_throttle_state,
  18634. +};
  18635. +
  18636. +static ssize_t mwl_thermal_show_temp(struct device *dev,
  18637. + struct device_attribute *attr,
  18638. + char *buf)
  18639. +{
  18640. + struct mwl_priv *priv = dev_get_drvdata(dev);
  18641. + int ret, temperature;
  18642. +
  18643. + ret = mwl_fwcmd_get_temp(priv->hw, &priv->temperature);
  18644. + if (ret) {
  18645. + wiphy_warn(priv->hw->wiphy, "failed: can't get temperature\n");
  18646. + goto out;
  18647. + }
  18648. +
  18649. + temperature = priv->temperature;
  18650. +
  18651. + /* display in millidegree celcius */
  18652. + ret = snprintf(buf, PAGE_SIZE, "%d\n", temperature * 1000);
  18653. +out:
  18654. + return ret;
  18655. +}
  18656. +
  18657. +static SENSOR_DEVICE_ATTR(temp1_input, 0444, mwl_thermal_show_temp,
  18658. + NULL, 0);
  18659. +
  18660. +static struct attribute *mwl_hwmon_attrs[] = {
  18661. + &sensor_dev_attr_temp1_input.dev_attr.attr,
  18662. + NULL,
  18663. +};
  18664. +ATTRIBUTE_GROUPS(mwl_hwmon);
  18665. +
  18666. +void mwl_thermal_set_throttling(struct mwl_priv *priv)
  18667. +{
  18668. + u32 period, duration, enabled;
  18669. + int ret;
  18670. +
  18671. + period = priv->quiet_period;
  18672. + duration = (period * priv->throttle_state) / 100;
  18673. + enabled = duration ? 1 : 0;
  18674. +
  18675. + ret = mwl_fwcmd_quiet_mode(priv->hw, enabled, period,
  18676. + duration, SYSADPT_QUIET_START_OFFSET);
  18677. + if (ret) {
  18678. + wiphy_warn(priv->hw->wiphy,
  18679. + "failed: period %u duarion %u enabled %u ret %d\n",
  18680. + period, duration, enabled, ret);
  18681. + }
  18682. +}
  18683. +
  18684. +int mwl_thermal_register(struct mwl_priv *priv)
  18685. +{
  18686. + struct thermal_cooling_device *cdev;
  18687. + struct device *hwmon_dev;
  18688. + int ret;
  18689. +
  18690. + if (priv->chip_type != MWL8897)
  18691. + return 0;
  18692. +
  18693. + cdev = thermal_cooling_device_register("mwlwifi_thermal", priv,
  18694. + &mwl_thermal_ops);
  18695. + if (IS_ERR(cdev)) {
  18696. + wiphy_err(priv->hw->wiphy,
  18697. + "failed to setup thermal device result: %ld\n",
  18698. + PTR_ERR(cdev));
  18699. + return -EINVAL;
  18700. + }
  18701. +
  18702. + ret = sysfs_create_link(&priv->dev->kobj, &cdev->device.kobj,
  18703. + "cooling_device");
  18704. + if (ret) {
  18705. + wiphy_err(priv->hw->wiphy,
  18706. + "failed to create cooling device symlink\n");
  18707. + goto err_cooling_destroy;
  18708. + }
  18709. +
  18710. + priv->cdev = cdev;
  18711. + priv->quiet_period = SYSADPT_QUIET_PERIOD_DEFAULT;
  18712. +
  18713. + if (!IS_ENABLED(CONFIG_HWMON))
  18714. + return 0;
  18715. +
  18716. + hwmon_dev =
  18717. + devm_hwmon_device_register_with_groups(priv->dev,
  18718. + "mwlwifi_hwmon", priv,
  18719. + mwl_hwmon_groups);
  18720. + if (IS_ERR(hwmon_dev)) {
  18721. + wiphy_err(priv->hw->wiphy,
  18722. + "failed to register hwmon device: %ld\n",
  18723. + PTR_ERR(hwmon_dev));
  18724. + ret = -EINVAL;
  18725. + goto err_remove_link;
  18726. + }
  18727. +
  18728. + return 0;
  18729. +
  18730. +err_remove_link:
  18731. + sysfs_remove_link(&priv->dev->kobj, "cooling_device");
  18732. +err_cooling_destroy:
  18733. + thermal_cooling_device_unregister(cdev);
  18734. +
  18735. + return ret;
  18736. +}
  18737. +
  18738. +void mwl_thermal_unregister(struct mwl_priv *priv)
  18739. +{
  18740. + if (priv->chip_type != MWL8897)
  18741. + return;
  18742. +
  18743. + sysfs_remove_link(&priv->dev->kobj, "cooling_device");
  18744. + thermal_cooling_device_unregister(priv->cdev);
  18745. +}
  18746. diff --git a/drivers/net/wireless/marvell/mwlwifi/thermal.h b/drivers/net/wireless/marvell/mwlwifi/thermal.h
  18747. new file mode 100644
  18748. index 000000000000..c7f0ad2b87eb
  18749. --- /dev/null
  18750. +++ b/drivers/net/wireless/marvell/mwlwifi/thermal.h
  18751. @@ -0,0 +1,42 @@
  18752. +/*
  18753. + * Copyright (C) 2006-2018, Marvell International Ltd.
  18754. + *
  18755. + * This software file (the "File") is distributed by Marvell International
  18756. + * Ltd. under the terms of the GNU General Public License Version 2, June 1991
  18757. + * (the "License"). You may use, redistribute and/or modify this File in
  18758. + * accordance with the terms and conditions of the License, a copy of which
  18759. + * is available by writing to the Free Software Foundation, Inc.
  18760. + *
  18761. + * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
  18762. + * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
  18763. + * ARE EXPRESSLY DISCLAIMED. The License provides additional details about
  18764. + * this warranty disclaimer.
  18765. + */
  18766. +
  18767. +/* Description: This file defines Linux thermal framework related functions. */
  18768. +
  18769. +#ifndef _THERMAL_H_
  18770. +#define _THERMAL_H_
  18771. +
  18772. +#include <linux/kconfig.h>
  18773. +
  18774. +#if IS_ENABLED(CONFIG_THERMAL)
  18775. +int mwl_thermal_register(struct mwl_priv *priv);
  18776. +void mwl_thermal_unregister(struct mwl_priv *priv);
  18777. +void mwl_thermal_set_throttling(struct mwl_priv *priv);
  18778. +#else
  18779. +static inline int mwl_thermal_register(struct mwl_priv *priv)
  18780. +{
  18781. + return 0;
  18782. +}
  18783. +
  18784. +static inline void mwl_thermal_unregister(struct mwl_priv *priv)
  18785. +{
  18786. +}
  18787. +
  18788. +static inline void mwl_thermal_set_throttling(struct mwl_priv *priv)
  18789. +{
  18790. +}
  18791. +#endif
  18792. +
  18793. +#endif /* _THERMAL_H_ */
  18794. diff --git a/drivers/net/wireless/marvell/mwlwifi/utils.c b/drivers/net/wireless/marvell/mwlwifi/utils.c
  18795. new file mode 100644
  18796. index 000000000000..b73054a3f55e
  18797. --- /dev/null
  18798. +++ b/drivers/net/wireless/marvell/mwlwifi/utils.c
  18799. @@ -0,0 +1,576 @@
  18800. +/*
  18801. + * Copyright (C) 2006-2018, Marvell International Ltd.
  18802. + *
  18803. + * This software file (the "File") is distributed by Marvell International
  18804. + * Ltd. under the terms of the GNU General Public License Version 2, June 1991
  18805. + * (the "License"). You may use, redistribute and/or modify this File in
  18806. + * accordance with the terms and conditions of the License, a copy of which
  18807. + * is available by writing to the Free Software Foundation, Inc.
  18808. + *
  18809. + * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
  18810. + * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
  18811. + * ARE EXPRESSLY DISCLAIMED. The License provides additional details about
  18812. + * this warranty disclaimer.
  18813. + */
  18814. +
  18815. +/* Description: This file implements common utility functions. */
  18816. +
  18817. +#include <linux/etherdevice.h>
  18818. +
  18819. +#include "sysadpt.h"
  18820. +#include "core.h"
  18821. +#include "utils.h"
  18822. +
  18823. +static unsigned short phy_rate[][5] = {
  18824. + {2, 13, 15, 27, 30}, /* 0 */
  18825. + {4, 26, 29, 54, 60}, /* 1 */
  18826. + {11, 39, 43, 81, 90}, /* 2 */
  18827. + {22, 52, 58, 108, 120}, /* 3 */
  18828. + {44, 78, 87, 162, 180}, /* 4 */
  18829. + {12, 104, 115, 216, 240}, /* 5 */
  18830. + {18, 117, 130, 243, 270}, /* 6 */
  18831. + {24, 130, 144, 270, 300}, /* 7 */
  18832. + {36, 26, 29, 54, 60}, /* 8 */
  18833. + {48, 52, 58, 108, 120}, /* 9 */
  18834. + {72, 78, 87, 162, 180}, /* 10 */
  18835. + {96, 104, 116, 216, 240}, /* 11 */
  18836. + {108, 156, 173, 324, 360}, /* 12 */
  18837. + {0, 208, 231, 432, 480}, /* 13 */
  18838. + {0, 234, 260, 486, 540}, /* 14 */
  18839. + {0, 260, 289, 540, 600}, /* 15 */
  18840. + {0, 39, 43, 81, 90}, /* 16 */
  18841. + {0, 78, 87, 162, 180}, /* 17 */
  18842. + {0, 117, 130, 243, 270}, /* 18 */
  18843. + {0, 156, 173, 324, 360}, /* 19 */
  18844. + {0, 234, 260, 486, 540}, /* 20 */
  18845. + {0, 312, 347, 648, 720}, /* 21 */
  18846. + {0, 351, 390, 729, 810}, /* 22 */
  18847. + {0, 390, 433, 810, 900}, /* 23 */
  18848. +};
  18849. +
  18850. +/* 20Mhz: Nss1_LGI, Nss1_SGI, Nss2_LGI, Nss2_SGI, Nss3_LGI, Nss3_SGI */
  18851. +static unsigned short phy_rate_11ac20M[][6] = {
  18852. + {13, 15, 26, 29, 39, 44}, /* 0 */
  18853. + {26, 29, 52, 58, 78, 87}, /* 1 */
  18854. + {39, 44, 78, 87, 117, 130}, /* 2 */
  18855. + {52, 58, 104, 116, 156, 174}, /* 3 */
  18856. + {78, 87, 156, 174, 234, 260}, /* 4 */
  18857. + {104, 116, 208, 231, 312, 347}, /* 5 */
  18858. + {117, 130, 234, 260, 351, 390}, /* 6 */
  18859. + {130, 145, 260, 289, 390, 434}, /* 7 */
  18860. + {156, 174, 312, 347, 468, 520}, /* 8 */
  18861. + /* Nss 1 and Nss 2 mcs9 not valid */
  18862. + {2, 2, 2, 2, 520, 578}, /* 9 */
  18863. +};
  18864. +
  18865. +/* 40Mhz: Nss1_LGI, Nss1_SGI, Nss2_LGI, Nss2_SGI, Nss3_LGI, Nss3_SGI */
  18866. +static unsigned short phy_rate_11ac40M[][6] = {
  18867. + {27, 30, 54, 60, 81, 90}, /* 0 */
  18868. + {54, 60, 108, 120, 162, 180}, /* 1 */
  18869. + {81, 90, 162, 180, 243, 270}, /* 2 */
  18870. + {108, 120, 216, 240, 324, 360}, /* 3 */
  18871. + {162, 180, 324, 360, 486, 540}, /* 4 */
  18872. + {216, 240, 432, 480, 648, 720}, /* 5 */
  18873. + {243, 270, 486, 540, 729, 810}, /* 6 */
  18874. + {270, 300, 540, 600, 810, 900}, /* 7 */
  18875. + {324, 360, 648, 720, 972, 1080}, /* 8 */
  18876. + {360, 400, 720, 800, 1080, 1200}, /* 9 */
  18877. +};
  18878. +
  18879. +/* 80Mhz: Nss1_LGI, Nss1_SGI, Nss2_LGI, Nss2_SGI, Nss3_LGI, Nss3_SGI */
  18880. +static unsigned short phy_rate_11ac80M[][6] = {
  18881. + {59, 65, 117, 130, 175, 195}, /* 0 */
  18882. + {117, 130, 234, 260, 351, 390}, /* 1 */
  18883. + {175, 195, 351, 390, 527, 585}, /* 2 */
  18884. + {234, 260, 468, 520, 702, 780}, /* 3 */
  18885. + {351, 390, 702, 780, 1053, 1170}, /* 4 */
  18886. + {468, 520, 936, 1040, 1404, 1560}, /* 5 */
  18887. + {527, 585, 1053, 1170, 2, 2}, /* 6, Nss 3 mcs6 not valid */
  18888. + {585, 650, 1170, 1300, 1755, 1950}, /* 7 */
  18889. + {702, 780, 1404, 1560, 2106, 2340}, /* 8 */
  18890. + {780, 867, 1560, 1733, 2340, 2600}, /* 9 */
  18891. +};
  18892. +
  18893. +/* 160Mhz: Nss1_LGI, Nss1_SGI, Nss2_LGI, Nss2_SGI, Nss3_LGI, Nss3_SGI */
  18894. +static unsigned short phy_rate_11ac160M[][6] = {
  18895. + {117, 130, 234, 260, 351, 390}, /* 0 */
  18896. + {234, 260, 468, 520, 702, 780}, /* 1 */
  18897. + {351, 390, 702, 780, 1053, 1170}, /* 2 */
  18898. + {468, 520, 936, 1040, 1404, 1560}, /* 3 */
  18899. + {702, 780, 1404, 1560, 2106, 2340}, /* 4 */
  18900. + {936, 1040, 1872, 2080, 2808, 3120}, /* 5 */
  18901. + {1053, 1170, 2106, 2340, 3159, 3510}, /* 6 */
  18902. + {1170, 1300, 2340, 2600, 3510, 3900}, /* 7 */
  18903. + {1404, 1560, 2808, 3120, 4212, 4680}, /* 8 */
  18904. + {1560, 1733, 2130, 3467, 4680, 5200}, /* 9 */
  18905. +};
  18906. +
  18907. +int utils_get_phy_rate(u8 format, u8 bandwidth, u8 short_gi, u8 mcs_id)
  18908. +{
  18909. + u8 index = 0;
  18910. + u8 nss_11ac = 0;
  18911. + u8 rate_11ac = 0;
  18912. +
  18913. + if (format == TX_RATE_FORMAT_11N) {
  18914. + index = (bandwidth << 1) | short_gi;
  18915. + index++;
  18916. + } else if (format == TX_RATE_FORMAT_11AC) {
  18917. + rate_11ac = mcs_id & 0xf; /* 11ac, mcs_id[3:0]: rate */
  18918. + nss_11ac = mcs_id >> 4; /* 11ac, mcs_id[6:4]: nss code */
  18919. + index = (nss_11ac << 1) | short_gi;
  18920. + }
  18921. +
  18922. + if (format != TX_RATE_FORMAT_11AC)
  18923. + return (phy_rate[mcs_id][index] / 2);
  18924. +
  18925. + if (bandwidth == TX_RATE_BANDWIDTH_20)
  18926. + return (phy_rate_11ac20M[rate_11ac][index] / 2);
  18927. + else if (bandwidth == TX_RATE_BANDWIDTH_40)
  18928. + return (phy_rate_11ac40M[rate_11ac][index] / 2);
  18929. + else if (bandwidth == TX_RATE_BANDWIDTH_80)
  18930. + return (phy_rate_11ac80M[rate_11ac][index] / 2);
  18931. + else
  18932. + return (phy_rate_11ac160M[rate_11ac][index] / 2);
  18933. +}
  18934. +
  18935. +u8 utils_get_rate_id(u8 rate)
  18936. +{
  18937. + switch (rate) {
  18938. + case 10: /* 1 Mbit/s or 12 Mbit/s */
  18939. + return 0;
  18940. + case 20: /* 2 Mbit/s */
  18941. + return 1;
  18942. + case 55: /* 5.5 Mbit/s */
  18943. + return 2;
  18944. + case 110: /* 11 Mbit/s */
  18945. + return 3;
  18946. + case 220: /* 22 Mbit/s */
  18947. + return 4;
  18948. + case 0xb: /* 6 Mbit/s */
  18949. + return 5;
  18950. + case 0xf: /* 9 Mbit/s */
  18951. + return 6;
  18952. + case 0xe: /* 18 Mbit/s */
  18953. + return 8;
  18954. + case 0x9: /* 24 Mbit/s */
  18955. + return 9;
  18956. + case 0xd: /* 36 Mbit/s */
  18957. + return 10;
  18958. + case 0x8: /* 48 Mbit/s */
  18959. + return 11;
  18960. + case 0xc: /* 54 Mbit/s */
  18961. + return 12;
  18962. + case 0x7: /* 72 Mbit/s */
  18963. + return 13;
  18964. + }
  18965. +
  18966. + return 0;
  18967. +}
  18968. +
  18969. +u32 utils_get_init_tx_rate(struct mwl_priv *priv, struct ieee80211_conf *conf,
  18970. + struct ieee80211_sta *sta)
  18971. +{
  18972. + u32 tx_rate;
  18973. + u16 format, nss, bw, rate_mcs;
  18974. +
  18975. + if (sta->vht_cap.vht_supported)
  18976. + format = TX_RATE_FORMAT_11AC;
  18977. + else if (sta->ht_cap.ht_supported)
  18978. + format = TX_RATE_FORMAT_11N;
  18979. + else
  18980. + format = TX_RATE_FORMAT_LEGACY;
  18981. +
  18982. + switch (priv->antenna_tx) {
  18983. + case ANTENNA_TX_1:
  18984. + nss = 1;
  18985. + break;
  18986. + case ANTENNA_TX_2:
  18987. + nss = 2;
  18988. + break;
  18989. + case ANTENNA_TX_3:
  18990. + case ANTENNA_TX_4_AUTO:
  18991. + nss = 3;
  18992. + break;
  18993. + default:
  18994. + nss = sta->rx_nss;
  18995. + break;
  18996. + }
  18997. + if (nss > sta->rx_nss)
  18998. + nss = sta->rx_nss;
  18999. +
  19000. + switch (conf->chandef.width) {
  19001. + case NL80211_CHAN_WIDTH_20_NOHT:
  19002. + case NL80211_CHAN_WIDTH_20:
  19003. + bw = TX_RATE_BANDWIDTH_20;
  19004. + break;
  19005. + case NL80211_CHAN_WIDTH_40:
  19006. + bw = TX_RATE_BANDWIDTH_40;
  19007. + break;
  19008. + case NL80211_CHAN_WIDTH_80:
  19009. + bw = TX_RATE_BANDWIDTH_80;
  19010. + break;
  19011. + case NL80211_CHAN_WIDTH_160:
  19012. + bw = TX_RATE_BANDWIDTH_160;
  19013. + break;
  19014. + default:
  19015. + bw = sta->bandwidth;
  19016. + break;
  19017. + }
  19018. + if (bw > sta->bandwidth)
  19019. + bw = sta->bandwidth;
  19020. +
  19021. + switch (format) {
  19022. + case TX_RATE_FORMAT_LEGACY:
  19023. + rate_mcs = 12; /* ignore 11b */
  19024. + break;
  19025. + case TX_RATE_FORMAT_11N:
  19026. + rate_mcs = (nss * 8) - 1;
  19027. + break;
  19028. + default:
  19029. + rate_mcs = ((nss - 1) << 4) | 8;
  19030. + break;
  19031. + }
  19032. +
  19033. + tx_rate = (format | (bw << MWL_TX_RATE_BANDWIDTH_SHIFT) |
  19034. + (TX_RATE_INFO_SHORT_GI << MWL_TX_RATE_SHORTGI_SHIFT) |
  19035. + (rate_mcs << MWL_TX_RATE_RATEIDMCS_SHIFT));
  19036. +
  19037. + return tx_rate;
  19038. +}
  19039. +
  19040. +struct mwl_vif *utils_find_vif_bss(struct mwl_priv *priv, u8 *bssid)
  19041. +{
  19042. + struct mwl_vif *mwl_vif;
  19043. +
  19044. + spin_lock_bh(&priv->vif_lock);
  19045. + list_for_each_entry(mwl_vif, &priv->vif_list, list) {
  19046. + if (ether_addr_equal(bssid, mwl_vif->bssid)) {
  19047. + spin_unlock_bh(&priv->vif_lock);
  19048. + return mwl_vif;
  19049. + }
  19050. + }
  19051. + spin_unlock_bh(&priv->vif_lock);
  19052. +
  19053. + return NULL;
  19054. +}
  19055. +
  19056. +struct mwl_sta *utils_find_sta(struct mwl_priv *priv, u8 *addr)
  19057. +{
  19058. + struct mwl_sta *sta_info;
  19059. + struct ieee80211_sta *sta;
  19060. +
  19061. + spin_lock_bh(&priv->sta_lock);
  19062. + list_for_each_entry(sta_info, &priv->sta_list, list) {
  19063. + sta = container_of((void *)sta_info, struct ieee80211_sta,
  19064. + drv_priv);
  19065. + if (ether_addr_equal(addr, sta->addr)) {
  19066. + spin_unlock_bh(&priv->sta_lock);
  19067. + return sta_info;
  19068. + }
  19069. + }
  19070. + spin_unlock_bh(&priv->sta_lock);
  19071. +
  19072. + return NULL;
  19073. +}
  19074. +
  19075. +struct mwl_sta *utils_find_sta_by_aid(struct mwl_priv *priv, u16 aid)
  19076. +{
  19077. + struct mwl_sta *sta_info;
  19078. + struct ieee80211_sta *sta;
  19079. +
  19080. + spin_lock_bh(&priv->sta_lock);
  19081. + list_for_each_entry(sta_info, &priv->sta_list, list) {
  19082. + sta = container_of((void *)sta_info, struct ieee80211_sta,
  19083. + drv_priv);
  19084. + if (sta->aid == aid) {
  19085. + spin_unlock_bh(&priv->sta_lock);
  19086. + return sta_info;
  19087. + }
  19088. + }
  19089. + spin_unlock_bh(&priv->sta_lock);
  19090. +
  19091. + return NULL;
  19092. +}
  19093. +
  19094. +struct mwl_sta *utils_find_sta_by_id(struct mwl_priv *priv, u16 stnid)
  19095. +{
  19096. + struct mwl_sta *sta_info;
  19097. +
  19098. + spin_lock_bh(&priv->sta_lock);
  19099. + list_for_each_entry(sta_info, &priv->sta_list, list) {
  19100. + if (sta_info->stnid == stnid) {
  19101. + spin_unlock_bh(&priv->sta_lock);
  19102. + return sta_info;
  19103. + }
  19104. + }
  19105. + spin_unlock_bh(&priv->sta_lock);
  19106. +
  19107. + return NULL;
  19108. +}
  19109. +
  19110. +void utils_dump_data_info(const char *prefix_str, const void *buf, size_t len)
  19111. +{
  19112. + print_hex_dump(KERN_INFO, prefix_str, DUMP_PREFIX_OFFSET,
  19113. + 16, 1, buf, len, true);
  19114. +}
  19115. +
  19116. +void utils_dump_data_debug(const char *prefix_str, const void *buf, size_t len)
  19117. +{
  19118. + print_hex_dump(KERN_DEBUG, prefix_str, DUMP_PREFIX_OFFSET,
  19119. + 16, 1, buf, len, true);
  19120. +}
  19121. +
  19122. +bool utils_is_non_amsdu_packet(const void *packet, bool mac80211)
  19123. +{
  19124. + const u8 *data = packet;
  19125. + struct ieee80211_hdr *wh;
  19126. + __be16 *protocol;
  19127. + struct iphdr *iph;
  19128. + struct udphdr *udph;
  19129. +
  19130. + if (mac80211) {
  19131. + /* mac80211 packet */
  19132. + wh = (struct ieee80211_hdr *)data;
  19133. + data += ieee80211_hdrlen(wh->frame_control) + 6;
  19134. + protocol = (__be16 *)data;
  19135. + } else {
  19136. + /* mac802.3 packet */
  19137. + data += (2 * ETH_ALEN);
  19138. + protocol = (__be16 *)data;
  19139. + }
  19140. +
  19141. + if (*protocol == cpu_to_be16(ETH_P_PAE))
  19142. + return true;
  19143. +
  19144. + if (*protocol == htons(ETH_P_ARP))
  19145. + return true;
  19146. +
  19147. + if (*protocol == htons(ETH_P_IP)) {
  19148. + data += sizeof(__be16);
  19149. + iph = (struct iphdr *)data;
  19150. + if (iph->protocol == IPPROTO_ICMP)
  19151. + return true;
  19152. + if (iph->protocol == IPPROTO_UDP) {
  19153. + data += (iph->ihl * 4);
  19154. + udph = (struct udphdr *)data;
  19155. + if (((udph->source == htons(68)) &&
  19156. + (udph->dest == htons(67))) ||
  19157. + ((udph->source == htons(67)) &&
  19158. + (udph->dest == htons(68))))
  19159. + return true;
  19160. + }
  19161. + }
  19162. +
  19163. + return false;
  19164. +}
  19165. +
  19166. +bool utils_is_arp(const void *packet, bool mac80211, u16 *arp_op)
  19167. +{
  19168. + const u8 *data = packet;
  19169. + struct ieee80211_hdr *wh;
  19170. + __be16 *protocol;
  19171. + struct arphdr *arph;
  19172. +
  19173. + if (mac80211) {
  19174. + /* mac80211 packet */
  19175. + wh = (struct ieee80211_hdr *)data;
  19176. + data += ieee80211_hdrlen(wh->frame_control) + 6;
  19177. + protocol = (__be16 *)data;
  19178. + } else {
  19179. + /* mac802.3 packet */
  19180. + data += (2 * ETH_ALEN);
  19181. + protocol = (__be16 *)data;
  19182. + }
  19183. +
  19184. + if (*protocol == htons(ETH_P_ARP)) {
  19185. + data += sizeof(__be16);
  19186. + arph = (struct arphdr *)data;
  19187. + *arp_op = ntohs(arph->ar_op);
  19188. + return true;
  19189. + }
  19190. +
  19191. + return false;
  19192. +}
  19193. +
  19194. +bool utils_is_icmp_echo(const void *packet, bool mac80211, u8 *type)
  19195. +{
  19196. + const u8 *data = packet;
  19197. + struct ieee80211_hdr *wh;
  19198. + __be16 *protocol;
  19199. + struct iphdr *iph;
  19200. + struct icmphdr *icmph;
  19201. +
  19202. + if (mac80211) {
  19203. + /* mac80211 packet */
  19204. + wh = (struct ieee80211_hdr *)data;
  19205. + data += ieee80211_hdrlen(wh->frame_control) + 6;
  19206. + protocol = (__be16 *)data;
  19207. + } else {
  19208. + /* mac802.3 packet */
  19209. + data += (2 * ETH_ALEN);
  19210. + protocol = (__be16 *)data;
  19211. + }
  19212. +
  19213. + if (*protocol == htons(ETH_P_IP)) {
  19214. + data += sizeof(__be16);
  19215. + iph = (struct iphdr *)data;
  19216. + if (iph->protocol == IPPROTO_ICMP) {
  19217. + data += (iph->ihl * 4);
  19218. + icmph = (struct icmphdr *)data;
  19219. + *type = icmph->type;
  19220. + return true;
  19221. + }
  19222. + }
  19223. +
  19224. + return false;
  19225. +}
  19226. +
  19227. +bool utils_is_dhcp(const void *packet, bool mac80211, u8 *op, u8 *dhcp_client)
  19228. +{
  19229. + const u8 *data = packet;
  19230. + struct ieee80211_hdr *wh;
  19231. + __be16 *protocol;
  19232. + struct iphdr *iph;
  19233. + struct udphdr *udph;
  19234. +
  19235. + if (mac80211) {
  19236. + /* mac80211 packet */
  19237. + wh = (struct ieee80211_hdr *)data;
  19238. + data += ieee80211_hdrlen(wh->frame_control) + 6;
  19239. + protocol = (__be16 *)data;
  19240. + } else {
  19241. + /* mac802.3 packet */
  19242. + data += (2 * ETH_ALEN);
  19243. + protocol = (__be16 *)data;
  19244. + }
  19245. +
  19246. + if (*protocol == htons(ETH_P_IP)) {
  19247. + data += sizeof(__be16);
  19248. + iph = (struct iphdr *)data;
  19249. + if (iph->protocol == IPPROTO_UDP) {
  19250. + data += (iph->ihl * 4);
  19251. + udph = (struct udphdr *)data;
  19252. + if (((udph->source == htons(68)) &&
  19253. + (udph->dest == htons(67))) ||
  19254. + ((udph->source == htons(67)) &&
  19255. + (udph->dest == htons(68)))) {
  19256. + data += sizeof(struct udphdr);
  19257. + *op = *data;
  19258. + ether_addr_copy(dhcp_client, data + 28);
  19259. + return true;
  19260. + }
  19261. + }
  19262. + }
  19263. +
  19264. + return false;
  19265. +}
  19266. +
  19267. +void utils_dump_arp(const void *packet, bool mac80211, size_t len)
  19268. +{
  19269. + const u8 *data = packet;
  19270. + struct ieee80211_hdr *wh;
  19271. + __be16 *protocol;
  19272. + struct arphdr *arph;
  19273. +
  19274. + if (mac80211) {
  19275. + /* mac80211 packet */
  19276. + wh = (struct ieee80211_hdr *)data;
  19277. + data += ieee80211_hdrlen(wh->frame_control) + 6;
  19278. + protocol = (__be16 *)data;
  19279. + } else {
  19280. + /* mac802.3 packet */
  19281. + data += (2 * ETH_ALEN);
  19282. + protocol = (__be16 *)data;
  19283. + }
  19284. +
  19285. + if (*protocol == htons(ETH_P_ARP)) {
  19286. + data += sizeof(__be16);
  19287. + arph = (struct arphdr *)data;
  19288. + if (arph->ar_op == htons(ARPOP_REQUEST))
  19289. + utils_dump_data_info("ARP REQUEST: ", packet, len);
  19290. + else if (arph->ar_op == htons(ARPOP_REPLY))
  19291. + utils_dump_data_info("ARP REPLY: ", packet, len);
  19292. + }
  19293. +}
  19294. +
  19295. +void utils_dump_icmp_echo(const void *packet, bool mac80211, size_t len)
  19296. +{
  19297. + const u8 *data = packet;
  19298. + struct ieee80211_hdr *wh;
  19299. + __be16 *protocol;
  19300. + struct iphdr *iph;
  19301. + struct icmphdr *icmph;
  19302. +
  19303. + if (mac80211) {
  19304. + /* mac80211 packet */
  19305. + wh = (struct ieee80211_hdr *)data;
  19306. + data += ieee80211_hdrlen(wh->frame_control) + 6;
  19307. + protocol = (__be16 *)data;
  19308. + } else {
  19309. + /* mac802.3 packet */
  19310. + data += (2 * ETH_ALEN);
  19311. + protocol = (__be16 *)data;
  19312. + }
  19313. +
  19314. + if (*protocol == htons(ETH_P_IP)) {
  19315. + data += sizeof(__be16);
  19316. + iph = (struct iphdr *)data;
  19317. + if (iph->protocol == IPPROTO_ICMP) {
  19318. + data += (iph->ihl * 4);
  19319. + icmph = (struct icmphdr *)data;
  19320. + if (icmph->type == ICMP_ECHO)
  19321. + utils_dump_data_info("ECHO REQUEST: ",
  19322. + packet, len);
  19323. + else if (icmph->type == ICMP_ECHOREPLY)
  19324. + utils_dump_data_info("ECHO REPLY: ",
  19325. + packet, len);
  19326. + }
  19327. + }
  19328. +}
  19329. +
  19330. +void utils_dump_dhcp(const void *packet, bool mac80211, size_t len)
  19331. +{
  19332. + const u8 *data = packet;
  19333. + struct ieee80211_hdr *wh;
  19334. + __be16 *protocol;
  19335. + struct iphdr *iph;
  19336. + struct udphdr *udph;
  19337. + const char *dhcp_op[8] = {
  19338. + "DHCPDISCOVER",
  19339. + "DHCPOFFER",
  19340. + "DHCPREQUEST",
  19341. + "DHCPDECLINE",
  19342. + "DHCPACK",
  19343. + "DHCPNAK",
  19344. + "DHCPRELEASE",
  19345. + "DHCPINFORM"
  19346. + };
  19347. +
  19348. + if (mac80211) {
  19349. + /* mac80211 packet */
  19350. + wh = (struct ieee80211_hdr *)data;
  19351. + data += ieee80211_hdrlen(wh->frame_control) + 6;
  19352. + protocol = (__be16 *)data;
  19353. + } else {
  19354. + /* mac802.3 packet */
  19355. + data += (2 * ETH_ALEN);
  19356. + protocol = (__be16 *)data;
  19357. + }
  19358. +
  19359. + if (*protocol == htons(ETH_P_IP)) {
  19360. + data += sizeof(__be16);
  19361. + iph = (struct iphdr *)data;
  19362. + if (iph->protocol == IPPROTO_UDP) {
  19363. + data += (iph->ihl * 4);
  19364. + udph = (struct udphdr *)data;
  19365. + if (((udph->source == htons(68)) &&
  19366. + (udph->dest == htons(67))) ||
  19367. + ((udph->source == htons(67)) &&
  19368. + (udph->dest == htons(68)))) {
  19369. + data += sizeof(struct udphdr);
  19370. + utils_dump_data_info(dhcp_op[*data - 1],
  19371. + packet, len);
  19372. + }
  19373. + }
  19374. + }
  19375. +}
  19376. diff --git a/drivers/net/wireless/marvell/mwlwifi/utils.h b/drivers/net/wireless/marvell/mwlwifi/utils.h
  19377. new file mode 100644
  19378. index 000000000000..4a292e990412
  19379. --- /dev/null
  19380. +++ b/drivers/net/wireless/marvell/mwlwifi/utils.h
  19381. @@ -0,0 +1,158 @@
  19382. +/*
  19383. + * Copyright (C) 2006-2018, Marvell International Ltd.
  19384. + *
  19385. + * This software file (the "File") is distributed by Marvell International
  19386. + * Ltd. under the terms of the GNU General Public License Version 2, June 1991
  19387. + * (the "License"). You may use, redistribute and/or modify this File in
  19388. + * accordance with the terms and conditions of the License, a copy of which
  19389. + * is available by writing to the Free Software Foundation, Inc.
  19390. + *
  19391. + * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
  19392. + * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
  19393. + * ARE EXPRESSLY DISCLAIMED. The License provides additional details about
  19394. + * this warranty disclaimer.
  19395. + */
  19396. +
  19397. +/* Description: This file defines common utility functions. */
  19398. +
  19399. +#ifndef _UTILS_H_
  19400. +#define _UTILS_H_
  19401. +
  19402. +#include <net/arp.h>
  19403. +#include <net/ip.h>
  19404. +#include <net/udp.h>
  19405. +#include <net/icmp.h>
  19406. +
  19407. +/* DHCP message types */
  19408. +#define DHCPDISCOVER 1
  19409. +#define DHCPOFFER 2
  19410. +#define DHCPREQUEST 3
  19411. +#define DHCPDECLINE 4
  19412. +#define DHCPACK 5
  19413. +#define DHCPNAK 6
  19414. +#define DHCPRELEASE 7
  19415. +#define DHCPINFORM 8
  19416. +
  19417. +static inline int utils_tid_to_ac(u8 tid)
  19418. +{
  19419. + switch (tid) {
  19420. + case 0:
  19421. + case 3:
  19422. + return IEEE80211_AC_BE;
  19423. + case 1:
  19424. + case 2:
  19425. + return IEEE80211_AC_BK;
  19426. + case 4:
  19427. + case 5:
  19428. + return IEEE80211_AC_VI;
  19429. + case 6:
  19430. + case 7:
  19431. + return IEEE80211_AC_VO;
  19432. + default:
  19433. + break;
  19434. + }
  19435. +
  19436. + return -1;
  19437. +}
  19438. +
  19439. +static inline void utils_add_basic_rates(int band, struct sk_buff *skb)
  19440. +{
  19441. + struct ieee80211_mgmt *mgmt;
  19442. + int len;
  19443. + u8 *pos;
  19444. +
  19445. + mgmt = (struct ieee80211_mgmt *)skb->data;
  19446. + len = skb->len - ieee80211_hdrlen(mgmt->frame_control);
  19447. + len -= 4;
  19448. + pos = (u8 *)cfg80211_find_ie(WLAN_EID_SUPP_RATES,
  19449. + mgmt->u.assoc_req.variable,
  19450. + len);
  19451. + if (pos) {
  19452. + pos++;
  19453. + len = *pos++;
  19454. + while (len) {
  19455. + if (band == NL80211_BAND_2GHZ) {
  19456. + if ((*pos == 2) || (*pos == 4) ||
  19457. + (*pos == 11) || (*pos == 22))
  19458. + *pos |= 0x80;
  19459. + } else {
  19460. + if ((*pos == 12) || (*pos == 24) ||
  19461. + (*pos == 48))
  19462. + *pos |= 0x80;
  19463. + }
  19464. + pos++;
  19465. + len--;
  19466. + }
  19467. + }
  19468. +}
  19469. +
  19470. +static inline int utils_assign_stnid(struct mwl_priv *priv, int macid, u16 aid)
  19471. +{
  19472. + int stnid;
  19473. + int i;
  19474. +
  19475. + spin_lock_bh(&priv->stnid_lock);
  19476. + stnid = priv->available_stnid;
  19477. + if (stnid >= priv->stnid_num) {
  19478. + spin_unlock_bh(&priv->stnid_lock);
  19479. + return 0;
  19480. + }
  19481. + priv->stnid[stnid].macid = macid;
  19482. + priv->stnid[stnid].aid = aid;
  19483. + stnid++;
  19484. + for (i = stnid; i < priv->stnid_num; i++) {
  19485. + if (!priv->stnid[i].aid)
  19486. + break;
  19487. + }
  19488. + priv->available_stnid = i;
  19489. + spin_unlock_bh(&priv->stnid_lock);
  19490. + return stnid;
  19491. +}
  19492. +
  19493. +static inline void utils_free_stnid(struct mwl_priv *priv, u16 stnid)
  19494. +{
  19495. + spin_lock_bh(&priv->stnid_lock);
  19496. + if (stnid && (stnid <= priv->stnid_num)) {
  19497. + stnid--;
  19498. + priv->stnid[stnid].macid = 0;
  19499. + priv->stnid[stnid].aid = 0;
  19500. + if (priv->available_stnid > stnid)
  19501. + priv->available_stnid = stnid;
  19502. + }
  19503. + spin_unlock_bh(&priv->stnid_lock);
  19504. +}
  19505. +
  19506. +int utils_get_phy_rate(u8 format, u8 bandwidth, u8 short_gi, u8 mcs_id);
  19507. +
  19508. +u8 utils_get_rate_id(u8 rate);
  19509. +
  19510. +u32 utils_get_init_tx_rate(struct mwl_priv *priv, struct ieee80211_conf *conf,
  19511. + struct ieee80211_sta *sta);
  19512. +
  19513. +struct mwl_vif *utils_find_vif_bss(struct mwl_priv *priv, u8 *bssid);
  19514. +
  19515. +struct mwl_sta *utils_find_sta(struct mwl_priv *priv, u8 *addr);
  19516. +
  19517. +struct mwl_sta *utils_find_sta_by_aid(struct mwl_priv *priv, u16 aid);
  19518. +
  19519. +struct mwl_sta *utils_find_sta_by_id(struct mwl_priv *priv, u16 stnid);
  19520. +
  19521. +void utils_dump_data_info(const char *prefix_str, const void *buf, size_t len);
  19522. +
  19523. +void utils_dump_data_debug(const char *prefix_str, const void *buf, size_t len);
  19524. +
  19525. +bool utils_is_non_amsdu_packet(const void *packet, bool mac80211);
  19526. +
  19527. +bool utils_is_arp(const void *packet, bool mac80211, u16 *arp_op);
  19528. +
  19529. +bool utils_is_icmp_echo(const void *packet, bool mac80211, u8 *type);
  19530. +
  19531. +bool utils_is_dhcp(const void *packet, bool mac80211, u8 *op, u8 *dhcp_client);
  19532. +
  19533. +void utils_dump_arp(const void *packet, bool mac80211, size_t len);
  19534. +
  19535. +void utils_dump_icmp_echo(const void *packet, bool mac80211, size_t len);
  19536. +
  19537. +void utils_dump_dhcp(const void *packet, bool mac80211, size_t len);
  19538. +
  19539. +#endif /* _UTILS_H_ */
  19540. diff --git a/drivers/net/wireless/marvell/mwlwifi/vendor_cmd.c b/drivers/net/wireless/marvell/mwlwifi/vendor_cmd.c
  19541. new file mode 100644
  19542. index 000000000000..3e26fc42c225
  19543. --- /dev/null
  19544. +++ b/drivers/net/wireless/marvell/mwlwifi/vendor_cmd.c
  19545. @@ -0,0 +1,136 @@
  19546. +/*
  19547. + * Copyright (C) 2006-2018, Marvell International Ltd.
  19548. + *
  19549. + * This software file (the "File") is distributed by Marvell International
  19550. + * Ltd. under the terms of the GNU General Public License Version 2, June 1991
  19551. + * (the "License"). You may use, redistribute and/or modify this File in
  19552. + * accordance with the terms and conditions of the License, a copy of which
  19553. + * is available by writing to the Free Software Foundation, Inc.
  19554. + *
  19555. + * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
  19556. + * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
  19557. + * ARE EXPRESSLY DISCLAIMED. The License provides additional details about
  19558. + * this warranty disclaimer.
  19559. + */
  19560. +
  19561. +/* Description: This file implements vendor spcific functions. */
  19562. +
  19563. +#include <net/mac80211.h>
  19564. +#include <net/netlink.h>
  19565. +#include <linux/version.h>
  19566. +
  19567. +#include "sysadpt.h"
  19568. +#include "core.h"
  19569. +#include "utils.h"
  19570. +#include "hif/fwcmd.h"
  19571. +#include "vendor_cmd.h"
  19572. +
  19573. +static const struct nla_policy mwl_vendor_attr_policy[NUM_MWL_VENDOR_ATTR] = {
  19574. + [MWL_VENDOR_ATTR_BF_TYPE] = { .type = NLA_U8 },
  19575. +};
  19576. +
  19577. +static int mwl_vendor_cmd_set_bf_type(struct wiphy *wiphy,
  19578. + struct wireless_dev *wdev,
  19579. + const void *data, int data_len)
  19580. +{
  19581. + struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy);
  19582. + struct mwl_priv *priv = hw->priv;
  19583. + struct nlattr *tb[NUM_MWL_VENDOR_ATTR];
  19584. + int rc;
  19585. + u8 val;
  19586. +
  19587. + if (priv->chip_type != MWL8964)
  19588. + return -EPERM;
  19589. +
  19590. + rc = nla_parse(tb, MWL_VENDOR_ATTR_MAX, data, data_len,
  19591. + mwl_vendor_attr_policy
  19592. +#if (defined(LINUX_BACKPORT) || (LINUX_VERSION_CODE >=KERNEL_VERSION(4,12,0)))
  19593. + , NULL
  19594. +#endif
  19595. + );
  19596. + if (rc)
  19597. + return rc;
  19598. +
  19599. + if (!tb[MWL_VENDOR_ATTR_BF_TYPE])
  19600. + return -EINVAL;
  19601. +
  19602. + val = nla_get_u8(tb[MWL_VENDOR_ATTR_BF_TYPE]);
  19603. + if ((val < TXBF_MODE_OFF) || (val > TXBF_MODE_BFMER_AUTO))
  19604. + return -EINVAL;
  19605. + wiphy_debug(wiphy, "set bf_type: 0x%x\n", val);
  19606. +
  19607. + rc = mwl_fwcmd_set_bftype(hw, val);
  19608. + if (!rc)
  19609. + priv->bf_type = val;
  19610. +
  19611. + return rc;
  19612. +}
  19613. +
  19614. +static int mwl_vendor_cmd_get_bf_type(struct wiphy *wiphy,
  19615. + struct wireless_dev *wdev,
  19616. + const void *data, int data_len)
  19617. +{
  19618. + struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy);
  19619. + struct mwl_priv *priv = hw->priv;
  19620. + struct sk_buff *skb;
  19621. +
  19622. + if (priv->chip_type != MWL8964)
  19623. + return -EPERM;
  19624. +
  19625. + skb = cfg80211_vendor_cmd_alloc_reply_skb(wiphy, 8);
  19626. + if (!skb)
  19627. + return -ENOMEM;
  19628. +
  19629. + nla_put_u8(skb, MWL_VENDOR_ATTR_BF_TYPE, priv->bf_type);
  19630. +
  19631. + return cfg80211_vendor_cmd_reply(skb);
  19632. +}
  19633. +
  19634. +static const struct wiphy_vendor_command mwl_vendor_commands[] = {
  19635. + {
  19636. + .info = { .vendor_id = MRVL_OUI,
  19637. + .subcmd = MWL_VENDOR_CMD_SET_BF_TYPE},
  19638. + .flags = WIPHY_VENDOR_CMD_NEED_NETDEV,
  19639. + .doit = mwl_vendor_cmd_set_bf_type,
  19640. + },
  19641. + {
  19642. + .info = { .vendor_id = MRVL_OUI,
  19643. + .subcmd = MWL_VENDOR_CMD_GET_BF_TYPE},
  19644. + .flags = WIPHY_VENDOR_CMD_NEED_NETDEV,
  19645. + .doit = mwl_vendor_cmd_get_bf_type,
  19646. + }
  19647. +};
  19648. +
  19649. +static const struct nl80211_vendor_cmd_info mwl_vendor_events[] = {
  19650. + {
  19651. + .vendor_id = MRVL_OUI,
  19652. + .subcmd = MWL_VENDOR_EVENT_DRIVER_READY,
  19653. + },
  19654. + {
  19655. + .vendor_id = MRVL_OUI,
  19656. + .subcmd = MWL_VENDOR_EVENT_DRIVER_START_REMOVE,
  19657. + },
  19658. + {
  19659. + .vendor_id = MRVL_OUI,
  19660. + .subcmd = MWL_VENDOR_EVENT_CMD_TIMEOUT,
  19661. + }
  19662. +};
  19663. +
  19664. +void vendor_cmd_register(struct wiphy *wiphy)
  19665. +{
  19666. + wiphy->vendor_commands = mwl_vendor_commands;
  19667. + wiphy->n_vendor_commands = ARRAY_SIZE(mwl_vendor_commands);
  19668. + wiphy->vendor_events = mwl_vendor_events;
  19669. + wiphy->n_vendor_events = ARRAY_SIZE(mwl_vendor_events);
  19670. +}
  19671. +
  19672. +void vendor_cmd_basic_event(struct wiphy *wiphy, int event_idx)
  19673. +{
  19674. + struct sk_buff *skb;
  19675. +
  19676. + skb = cfg80211_vendor_event_alloc(wiphy, NULL, 0,
  19677. + event_idx, GFP_KERNEL);
  19678. +
  19679. + if (skb)
  19680. + cfg80211_vendor_event(skb, GFP_KERNEL);
  19681. +}
  19682. diff --git a/drivers/net/wireless/marvell/mwlwifi/vendor_cmd.h b/drivers/net/wireless/marvell/mwlwifi/vendor_cmd.h
  19683. new file mode 100644
  19684. index 000000000000..b6fdf70c22fb
  19685. --- /dev/null
  19686. +++ b/drivers/net/wireless/marvell/mwlwifi/vendor_cmd.h
  19687. @@ -0,0 +1,60 @@
  19688. +/*
  19689. + * Copyright (C) 2006-2018, Marvell International Ltd.
  19690. + *
  19691. + * This software file (the "File") is distributed by Marvell International
  19692. + * Ltd. under the terms of the GNU General Public License Version 2, June 1991
  19693. + * (the "License"). You may use, redistribute and/or modify this File in
  19694. + * accordance with the terms and conditions of the License, a copy of which
  19695. + * is available by writing to the Free Software Foundation, Inc.
  19696. + *
  19697. + * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
  19698. + * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
  19699. + * ARE EXPRESSLY DISCLAIMED. The License provides additional details about
  19700. + * this warranty disclaimer.
  19701. + */
  19702. +
  19703. +/* Description: This file defines vendor constants and register function. */
  19704. +
  19705. +#ifndef _VENDOR_CMD_H_
  19706. +#define _VENDOR_CMD_H_
  19707. +
  19708. +#ifdef __KERNEL__
  19709. +void vendor_cmd_register(struct wiphy *wiphy);
  19710. +void vendor_cmd_basic_event(struct wiphy *wiphy, int event_idx);
  19711. +#endif
  19712. +
  19713. +#define MRVL_OUI 0x005043
  19714. +
  19715. +enum mwl_vendor_commands {
  19716. + MWL_VENDOR_CMD_SET_BF_TYPE,
  19717. + MWL_VENDOR_CMD_GET_BF_TYPE,
  19718. +
  19719. + /* add commands here, update the command in vendor_cmd.c */
  19720. +
  19721. + __MWL_VENDOR_CMD_AFTER_LAST,
  19722. + NUM_MWL_VENDOR_CMD = __MWL_VENDOR_CMD_AFTER_LAST,
  19723. + MWL_VENDOR_CMD_MAX = __MWL_VENDOR_CMD_AFTER_LAST - 1
  19724. +};
  19725. +
  19726. +enum mwl_vendor_attributes {
  19727. + MWL_VENDOR_ATTR_NOT_USE,
  19728. + MWL_VENDOR_ATTR_BF_TYPE,
  19729. +
  19730. + /* add attributes here, update the policy in vendor_cmd.c */
  19731. +
  19732. + __MWL_VENDOR_ATTR_AFTER_LAST,
  19733. + NUM_MWL_VENDOR_ATTR = __MWL_VENDOR_ATTR_AFTER_LAST,
  19734. + MWL_VENDOR_ATTR_MAX = __MWL_VENDOR_ATTR_AFTER_LAST - 1
  19735. +};
  19736. +
  19737. +enum mwl_vendor_events {
  19738. + MWL_VENDOR_EVENT_DRIVER_READY,
  19739. + MWL_VENDOR_EVENT_DRIVER_START_REMOVE,
  19740. + MWL_VENDOR_EVENT_CMD_TIMEOUT,
  19741. +
  19742. + __MWL_VENDOR_EVENT_AFTER_LAST,
  19743. + NUM_MWL_VENDOR_EVENT = __MWL_VENDOR_EVENT_AFTER_LAST,
  19744. + MWL_VENDOR_EVENT_MAX = __MWL_VENDOR_EVENT_AFTER_LAST - 1
  19745. +};
  19746. +
  19747. +#endif /* _VENDOR_CMD_H_ */
  19748. --
  19749. 2.23.0