wl_cfg80211.c 734 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832383338343835383638373838383938403841384238433844384538463847384838493850385138523853385438553856385738583859386038613862386338643865386638673868386938703871387238733874387538763877387838793880388138823883388438853886388738883889389038913892389338943895389638973898389939003901390239033904390539063907390839093910391139123913391439153916391739183919392039213922392339243925392639273928392939303931393239333934393539363937393839393940394139423943394439453946394739483949395039513952395339543955395639573958395939603961396239633964396539663967396839693970397139723973397439753976397739783979398039813982398339843985398639873988398939903991399239933994399539963997399839994000400140024003400440054006400740084009401040114012401340144015401640174018401940204021402240234024402540264027402840294030403140324033403440354036403740384039404040414042404340444045404640474048404940504051405240534054405540564057405840594060406140624063406440654066406740684069407040714072407340744075407640774078407940804081408240834084408540864087408840894090409140924093409440954096409740984099410041014102410341044105410641074108410941104111411241134114411541164117411841194120412141224123412441254126412741284129413041314132413341344135413641374138413941404141414241434144414541464147414841494150415141524153415441554156415741584159416041614162416341644165416641674168416941704171417241734174417541764177417841794180418141824183418441854186418741884189419041914192419341944195419641974198419942004201420242034204420542064207420842094210421142124213421442154216421742184219422042214222422342244225422642274228422942304231423242334234423542364237423842394240424142424243424442454246424742484249425042514252425342544255425642574258425942604261426242634264426542664267426842694270427142724273427442754276427742784279428042814282428342844285428642874288428942904291429242934294429542964297429842994300430143024303430443054306430743084309431043114312431343144315431643174318431943204321432243234324432543264327432843294330433143324333433443354336433743384339434043414342434343444345434643474348434943504351435243534354435543564357435843594360436143624363436443654366436743684369437043714372437343744375437643774378437943804381438243834384438543864387438843894390439143924393439443954396439743984399440044014402440344044405440644074408440944104411441244134414441544164417441844194420442144224423442444254426442744284429443044314432443344344435443644374438443944404441444244434444444544464447444844494450445144524453445444554456445744584459446044614462446344644465446644674468446944704471447244734474447544764477447844794480448144824483448444854486448744884489449044914492449344944495449644974498449945004501450245034504450545064507450845094510451145124513451445154516451745184519452045214522452345244525452645274528452945304531453245334534453545364537453845394540454145424543454445454546454745484549455045514552455345544555455645574558455945604561456245634564456545664567456845694570457145724573457445754576457745784579458045814582458345844585458645874588458945904591459245934594459545964597459845994600460146024603460446054606460746084609461046114612461346144615461646174618461946204621462246234624462546264627462846294630463146324633463446354636463746384639464046414642464346444645464646474648464946504651465246534654465546564657465846594660466146624663466446654666466746684669467046714672467346744675467646774678467946804681468246834684468546864687468846894690469146924693469446954696469746984699470047014702470347044705470647074708470947104711471247134714471547164717471847194720472147224723472447254726472747284729473047314732473347344735473647374738473947404741474247434744474547464747474847494750475147524753475447554756475747584759476047614762476347644765476647674768476947704771477247734774477547764777477847794780478147824783478447854786478747884789479047914792479347944795479647974798479948004801480248034804480548064807480848094810481148124813481448154816481748184819482048214822482348244825482648274828482948304831483248334834483548364837483848394840484148424843484448454846484748484849485048514852485348544855485648574858485948604861486248634864486548664867486848694870487148724873487448754876487748784879488048814882488348844885488648874888488948904891489248934894489548964897489848994900490149024903490449054906490749084909491049114912491349144915491649174918491949204921492249234924492549264927492849294930493149324933493449354936493749384939494049414942494349444945494649474948494949504951495249534954495549564957495849594960496149624963496449654966496749684969497049714972497349744975497649774978497949804981498249834984498549864987498849894990499149924993499449954996499749984999500050015002500350045005500650075008500950105011501250135014501550165017501850195020502150225023502450255026502750285029503050315032503350345035503650375038503950405041504250435044504550465047504850495050505150525053505450555056505750585059506050615062506350645065506650675068506950705071507250735074507550765077507850795080508150825083508450855086508750885089509050915092509350945095509650975098509951005101510251035104510551065107510851095110511151125113511451155116511751185119512051215122512351245125512651275128512951305131513251335134513551365137513851395140514151425143514451455146514751485149515051515152515351545155515651575158515951605161516251635164516551665167516851695170517151725173517451755176517751785179518051815182518351845185518651875188518951905191519251935194519551965197519851995200520152025203520452055206520752085209521052115212521352145215521652175218521952205221522252235224522552265227522852295230523152325233523452355236523752385239524052415242524352445245524652475248524952505251525252535254525552565257525852595260526152625263526452655266526752685269527052715272527352745275527652775278527952805281528252835284528552865287528852895290529152925293529452955296529752985299530053015302530353045305530653075308530953105311531253135314531553165317531853195320532153225323532453255326532753285329533053315332533353345335533653375338533953405341534253435344534553465347534853495350535153525353535453555356535753585359536053615362536353645365536653675368536953705371537253735374537553765377537853795380538153825383538453855386538753885389539053915392539353945395539653975398539954005401540254035404540554065407540854095410541154125413541454155416541754185419542054215422542354245425542654275428542954305431543254335434543554365437543854395440544154425443544454455446544754485449545054515452545354545455545654575458545954605461546254635464546554665467546854695470547154725473547454755476547754785479548054815482548354845485548654875488548954905491549254935494549554965497549854995500550155025503550455055506550755085509551055115512551355145515551655175518551955205521552255235524552555265527552855295530553155325533553455355536553755385539554055415542554355445545554655475548554955505551555255535554555555565557555855595560556155625563556455655566556755685569557055715572557355745575557655775578557955805581558255835584558555865587558855895590559155925593559455955596559755985599560056015602560356045605560656075608560956105611561256135614561556165617561856195620562156225623562456255626562756285629563056315632563356345635563656375638563956405641564256435644564556465647564856495650565156525653565456555656565756585659566056615662566356645665566656675668566956705671567256735674567556765677567856795680568156825683568456855686568756885689569056915692569356945695569656975698569957005701570257035704570557065707570857095710571157125713571457155716571757185719572057215722572357245725572657275728572957305731573257335734573557365737573857395740574157425743574457455746574757485749575057515752575357545755575657575758575957605761576257635764576557665767576857695770577157725773577457755776577757785779578057815782578357845785578657875788578957905791579257935794579557965797579857995800580158025803580458055806580758085809581058115812581358145815581658175818581958205821582258235824582558265827582858295830583158325833583458355836583758385839584058415842584358445845584658475848584958505851585258535854585558565857585858595860586158625863586458655866586758685869587058715872587358745875587658775878587958805881588258835884588558865887588858895890589158925893589458955896589758985899590059015902590359045905590659075908590959105911591259135914591559165917591859195920592159225923592459255926592759285929593059315932593359345935593659375938593959405941594259435944594559465947594859495950595159525953595459555956595759585959596059615962596359645965596659675968596959705971597259735974597559765977597859795980598159825983598459855986598759885989599059915992599359945995599659975998599960006001600260036004600560066007600860096010601160126013601460156016601760186019602060216022602360246025602660276028602960306031603260336034603560366037603860396040604160426043604460456046604760486049605060516052605360546055605660576058605960606061606260636064606560666067606860696070607160726073607460756076607760786079608060816082608360846085608660876088608960906091609260936094609560966097609860996100610161026103610461056106610761086109611061116112611361146115611661176118611961206121612261236124612561266127612861296130613161326133613461356136613761386139614061416142614361446145614661476148614961506151615261536154615561566157615861596160616161626163616461656166616761686169617061716172617361746175617661776178617961806181618261836184618561866187618861896190619161926193619461956196619761986199620062016202620362046205620662076208620962106211621262136214621562166217621862196220622162226223622462256226622762286229623062316232623362346235623662376238623962406241624262436244624562466247624862496250625162526253625462556256625762586259626062616262626362646265626662676268626962706271627262736274627562766277627862796280628162826283628462856286628762886289629062916292629362946295629662976298629963006301630263036304630563066307630863096310631163126313631463156316631763186319632063216322632363246325632663276328632963306331633263336334633563366337633863396340634163426343634463456346634763486349635063516352635363546355635663576358635963606361636263636364636563666367636863696370637163726373637463756376637763786379638063816382638363846385638663876388638963906391639263936394639563966397639863996400640164026403640464056406640764086409641064116412641364146415641664176418641964206421642264236424642564266427642864296430643164326433643464356436643764386439644064416442644364446445644664476448644964506451645264536454645564566457645864596460646164626463646464656466646764686469647064716472647364746475647664776478647964806481648264836484648564866487648864896490649164926493649464956496649764986499650065016502650365046505650665076508650965106511651265136514651565166517651865196520652165226523652465256526652765286529653065316532653365346535653665376538653965406541654265436544654565466547654865496550655165526553655465556556655765586559656065616562656365646565656665676568656965706571657265736574657565766577657865796580658165826583658465856586658765886589659065916592659365946595659665976598659966006601660266036604660566066607660866096610661166126613661466156616661766186619662066216622662366246625662666276628662966306631663266336634663566366637663866396640664166426643664466456646664766486649665066516652665366546655665666576658665966606661666266636664666566666667666866696670667166726673667466756676667766786679668066816682668366846685668666876688668966906691669266936694669566966697669866996700670167026703670467056706670767086709671067116712671367146715671667176718671967206721672267236724672567266727672867296730673167326733673467356736673767386739674067416742674367446745674667476748674967506751675267536754675567566757675867596760676167626763676467656766676767686769677067716772677367746775677667776778677967806781678267836784678567866787678867896790679167926793679467956796679767986799680068016802680368046805680668076808680968106811681268136814681568166817681868196820682168226823682468256826682768286829683068316832683368346835683668376838683968406841684268436844684568466847684868496850685168526853685468556856685768586859686068616862686368646865686668676868686968706871687268736874687568766877687868796880688168826883688468856886688768886889689068916892689368946895689668976898689969006901690269036904690569066907690869096910691169126913691469156916691769186919692069216922692369246925692669276928692969306931693269336934693569366937693869396940694169426943694469456946694769486949695069516952695369546955695669576958695969606961696269636964696569666967696869696970697169726973697469756976697769786979698069816982698369846985698669876988698969906991699269936994699569966997699869997000700170027003700470057006700770087009701070117012701370147015701670177018701970207021702270237024702570267027702870297030703170327033703470357036703770387039704070417042704370447045704670477048704970507051705270537054705570567057705870597060706170627063706470657066706770687069707070717072707370747075707670777078707970807081708270837084708570867087708870897090709170927093709470957096709770987099710071017102710371047105710671077108710971107111711271137114711571167117711871197120712171227123712471257126712771287129713071317132713371347135713671377138713971407141714271437144714571467147714871497150715171527153715471557156715771587159716071617162716371647165716671677168716971707171717271737174717571767177717871797180718171827183718471857186718771887189719071917192719371947195719671977198719972007201720272037204720572067207720872097210721172127213721472157216721772187219722072217222722372247225722672277228722972307231723272337234723572367237723872397240724172427243724472457246724772487249725072517252725372547255725672577258725972607261726272637264726572667267726872697270727172727273727472757276727772787279728072817282728372847285728672877288728972907291729272937294729572967297729872997300730173027303730473057306730773087309731073117312731373147315731673177318731973207321732273237324732573267327732873297330733173327333733473357336733773387339734073417342734373447345734673477348734973507351735273537354735573567357735873597360736173627363736473657366736773687369737073717372737373747375737673777378737973807381738273837384738573867387738873897390739173927393739473957396739773987399740074017402740374047405740674077408740974107411741274137414741574167417741874197420742174227423742474257426742774287429743074317432743374347435743674377438743974407441744274437444744574467447744874497450745174527453745474557456745774587459746074617462746374647465746674677468746974707471747274737474747574767477747874797480748174827483748474857486748774887489749074917492749374947495749674977498749975007501750275037504750575067507750875097510751175127513751475157516751775187519752075217522752375247525752675277528752975307531753275337534753575367537753875397540754175427543754475457546754775487549755075517552755375547555755675577558755975607561756275637564756575667567756875697570757175727573757475757576757775787579758075817582758375847585758675877588758975907591759275937594759575967597759875997600760176027603760476057606760776087609761076117612761376147615761676177618761976207621762276237624762576267627762876297630763176327633763476357636763776387639764076417642764376447645764676477648764976507651765276537654765576567657765876597660766176627663766476657666766776687669767076717672767376747675767676777678767976807681768276837684768576867687768876897690769176927693769476957696769776987699770077017702770377047705770677077708770977107711771277137714771577167717771877197720772177227723772477257726772777287729773077317732773377347735773677377738773977407741774277437744774577467747774877497750775177527753775477557756775777587759776077617762776377647765776677677768776977707771777277737774777577767777777877797780778177827783778477857786778777887789779077917792779377947795779677977798779978007801780278037804780578067807780878097810781178127813781478157816781778187819782078217822782378247825782678277828782978307831783278337834783578367837783878397840784178427843784478457846784778487849785078517852785378547855785678577858785978607861786278637864786578667867786878697870787178727873787478757876787778787879788078817882788378847885788678877888788978907891789278937894789578967897789878997900790179027903790479057906790779087909791079117912791379147915791679177918791979207921792279237924792579267927792879297930793179327933793479357936793779387939794079417942794379447945794679477948794979507951795279537954795579567957795879597960796179627963796479657966796779687969797079717972797379747975797679777978797979807981798279837984798579867987798879897990799179927993799479957996799779987999800080018002800380048005800680078008800980108011801280138014801580168017801880198020802180228023802480258026802780288029803080318032803380348035803680378038803980408041804280438044804580468047804880498050805180528053805480558056805780588059806080618062806380648065806680678068806980708071807280738074807580768077807880798080808180828083808480858086808780888089809080918092809380948095809680978098809981008101810281038104810581068107810881098110811181128113811481158116811781188119812081218122812381248125812681278128812981308131813281338134813581368137813881398140814181428143814481458146814781488149815081518152815381548155815681578158815981608161816281638164816581668167816881698170817181728173817481758176817781788179818081818182818381848185818681878188818981908191819281938194819581968197819881998200820182028203820482058206820782088209821082118212821382148215821682178218821982208221822282238224822582268227822882298230823182328233823482358236823782388239824082418242824382448245824682478248824982508251825282538254825582568257825882598260826182628263826482658266826782688269827082718272827382748275827682778278827982808281828282838284828582868287828882898290829182928293829482958296829782988299830083018302830383048305830683078308830983108311831283138314831583168317831883198320832183228323832483258326832783288329833083318332833383348335833683378338833983408341834283438344834583468347834883498350835183528353835483558356835783588359836083618362836383648365836683678368836983708371837283738374837583768377837883798380838183828383838483858386838783888389839083918392839383948395839683978398839984008401840284038404840584068407840884098410841184128413841484158416841784188419842084218422842384248425842684278428842984308431843284338434843584368437843884398440844184428443844484458446844784488449845084518452845384548455845684578458845984608461846284638464846584668467846884698470847184728473847484758476847784788479848084818482848384848485848684878488848984908491849284938494849584968497849884998500850185028503850485058506850785088509851085118512851385148515851685178518851985208521852285238524852585268527852885298530853185328533853485358536853785388539854085418542854385448545854685478548854985508551855285538554855585568557855885598560856185628563856485658566856785688569857085718572857385748575857685778578857985808581858285838584858585868587858885898590859185928593859485958596859785988599860086018602860386048605860686078608860986108611861286138614861586168617861886198620862186228623862486258626862786288629863086318632863386348635863686378638863986408641864286438644864586468647864886498650865186528653865486558656865786588659866086618662866386648665866686678668866986708671867286738674867586768677867886798680868186828683868486858686868786888689869086918692869386948695869686978698869987008701870287038704870587068707870887098710871187128713871487158716871787188719872087218722872387248725872687278728872987308731873287338734873587368737873887398740874187428743874487458746874787488749875087518752875387548755875687578758875987608761876287638764876587668767876887698770877187728773877487758776877787788779878087818782878387848785878687878788878987908791879287938794879587968797879887998800880188028803880488058806880788088809881088118812881388148815881688178818881988208821882288238824882588268827882888298830883188328833883488358836883788388839884088418842884388448845884688478848884988508851885288538854885588568857885888598860886188628863886488658866886788688869887088718872887388748875887688778878887988808881888288838884888588868887888888898890889188928893889488958896889788988899890089018902890389048905890689078908890989108911891289138914891589168917891889198920892189228923892489258926892789288929893089318932893389348935893689378938893989408941894289438944894589468947894889498950895189528953895489558956895789588959896089618962896389648965896689678968896989708971897289738974897589768977897889798980898189828983898489858986898789888989899089918992899389948995899689978998899990009001900290039004900590069007900890099010901190129013901490159016901790189019902090219022902390249025902690279028902990309031903290339034903590369037903890399040904190429043904490459046904790489049905090519052905390549055905690579058905990609061906290639064906590669067906890699070907190729073907490759076907790789079908090819082908390849085908690879088908990909091909290939094909590969097909890999100910191029103910491059106910791089109911091119112911391149115911691179118911991209121912291239124912591269127912891299130913191329133913491359136913791389139914091419142914391449145914691479148914991509151915291539154915591569157915891599160916191629163916491659166916791689169917091719172917391749175917691779178917991809181918291839184918591869187918891899190919191929193919491959196919791989199920092019202920392049205920692079208920992109211921292139214921592169217921892199220922192229223922492259226922792289229923092319232923392349235923692379238923992409241924292439244924592469247924892499250925192529253925492559256925792589259926092619262926392649265926692679268926992709271927292739274927592769277927892799280928192829283928492859286928792889289929092919292929392949295929692979298929993009301930293039304930593069307930893099310931193129313931493159316931793189319932093219322932393249325932693279328932993309331933293339334933593369337933893399340934193429343934493459346934793489349935093519352935393549355935693579358935993609361936293639364936593669367936893699370937193729373937493759376937793789379938093819382938393849385938693879388938993909391939293939394939593969397939893999400940194029403940494059406940794089409941094119412941394149415941694179418941994209421942294239424942594269427942894299430943194329433943494359436943794389439944094419442944394449445944694479448944994509451945294539454945594569457945894599460946194629463946494659466946794689469947094719472947394749475947694779478947994809481948294839484948594869487948894899490949194929493949494959496949794989499950095019502950395049505950695079508950995109511951295139514951595169517951895199520952195229523952495259526952795289529953095319532953395349535953695379538953995409541954295439544954595469547954895499550955195529553955495559556955795589559956095619562956395649565956695679568956995709571957295739574957595769577957895799580958195829583958495859586958795889589959095919592959395949595959695979598959996009601960296039604960596069607960896099610961196129613961496159616961796189619962096219622962396249625962696279628962996309631963296339634963596369637963896399640964196429643964496459646964796489649965096519652965396549655965696579658965996609661966296639664966596669667966896699670967196729673967496759676967796789679968096819682968396849685968696879688968996909691969296939694969596969697969896999700970197029703970497059706970797089709971097119712971397149715971697179718971997209721972297239724972597269727972897299730973197329733973497359736973797389739974097419742974397449745974697479748974997509751975297539754975597569757975897599760976197629763976497659766976797689769977097719772977397749775977697779778977997809781978297839784978597869787978897899790979197929793979497959796979797989799980098019802980398049805980698079808980998109811981298139814981598169817981898199820982198229823982498259826982798289829983098319832983398349835983698379838983998409841984298439844984598469847984898499850985198529853985498559856985798589859986098619862986398649865986698679868986998709871987298739874987598769877987898799880988198829883988498859886988798889889989098919892989398949895989698979898989999009901990299039904990599069907990899099910991199129913991499159916991799189919992099219922992399249925992699279928992999309931993299339934993599369937993899399940994199429943994499459946994799489949995099519952995399549955995699579958995999609961996299639964996599669967996899699970997199729973997499759976997799789979998099819982998399849985998699879988998999909991999299939994999599969997999899991000010001100021000310004100051000610007100081000910010100111001210013100141001510016100171001810019100201002110022100231002410025100261002710028100291003010031100321003310034100351003610037100381003910040100411004210043100441004510046100471004810049100501005110052100531005410055100561005710058100591006010061100621006310064100651006610067100681006910070100711007210073100741007510076100771007810079100801008110082100831008410085100861008710088100891009010091100921009310094100951009610097100981009910100101011010210103101041010510106101071010810109101101011110112101131011410115101161011710118101191012010121101221012310124101251012610127101281012910130101311013210133101341013510136101371013810139101401014110142101431014410145101461014710148101491015010151101521015310154101551015610157101581015910160101611016210163101641016510166101671016810169101701017110172101731017410175101761017710178101791018010181101821018310184101851018610187101881018910190101911019210193101941019510196101971019810199102001020110202102031020410205102061020710208102091021010211102121021310214102151021610217102181021910220102211022210223102241022510226102271022810229102301023110232102331023410235102361023710238102391024010241102421024310244102451024610247102481024910250102511025210253102541025510256102571025810259102601026110262102631026410265102661026710268102691027010271102721027310274102751027610277102781027910280102811028210283102841028510286102871028810289102901029110292102931029410295102961029710298102991030010301103021030310304103051030610307103081030910310103111031210313103141031510316103171031810319103201032110322103231032410325103261032710328103291033010331103321033310334103351033610337103381033910340103411034210343103441034510346103471034810349103501035110352103531035410355103561035710358103591036010361103621036310364103651036610367103681036910370103711037210373103741037510376103771037810379103801038110382103831038410385103861038710388103891039010391103921039310394103951039610397103981039910400104011040210403104041040510406104071040810409104101041110412104131041410415104161041710418104191042010421104221042310424104251042610427104281042910430104311043210433104341043510436104371043810439104401044110442104431044410445104461044710448104491045010451104521045310454104551045610457104581045910460104611046210463104641046510466104671046810469104701047110472104731047410475104761047710478104791048010481104821048310484104851048610487104881048910490104911049210493104941049510496104971049810499105001050110502105031050410505105061050710508105091051010511105121051310514105151051610517105181051910520105211052210523105241052510526105271052810529105301053110532105331053410535105361053710538105391054010541105421054310544105451054610547105481054910550105511055210553105541055510556105571055810559105601056110562105631056410565105661056710568105691057010571105721057310574105751057610577105781057910580105811058210583105841058510586105871058810589105901059110592105931059410595105961059710598105991060010601106021060310604106051060610607106081060910610106111061210613106141061510616106171061810619106201062110622106231062410625106261062710628106291063010631106321063310634106351063610637106381063910640106411064210643106441064510646106471064810649106501065110652106531065410655106561065710658106591066010661106621066310664106651066610667106681066910670106711067210673106741067510676106771067810679106801068110682106831068410685106861068710688106891069010691106921069310694106951069610697106981069910700107011070210703107041070510706107071070810709107101071110712107131071410715107161071710718107191072010721107221072310724107251072610727107281072910730107311073210733107341073510736107371073810739107401074110742107431074410745107461074710748107491075010751107521075310754107551075610757107581075910760107611076210763107641076510766107671076810769107701077110772107731077410775107761077710778107791078010781107821078310784107851078610787107881078910790107911079210793107941079510796107971079810799108001080110802108031080410805108061080710808108091081010811108121081310814108151081610817108181081910820108211082210823108241082510826108271082810829108301083110832108331083410835108361083710838108391084010841108421084310844108451084610847108481084910850108511085210853108541085510856108571085810859108601086110862108631086410865108661086710868108691087010871108721087310874108751087610877108781087910880108811088210883108841088510886108871088810889108901089110892108931089410895108961089710898108991090010901109021090310904109051090610907109081090910910109111091210913109141091510916109171091810919109201092110922109231092410925109261092710928109291093010931109321093310934109351093610937109381093910940109411094210943109441094510946109471094810949109501095110952109531095410955109561095710958109591096010961109621096310964109651096610967109681096910970109711097210973109741097510976109771097810979109801098110982109831098410985109861098710988109891099010991109921099310994109951099610997109981099911000110011100211003110041100511006110071100811009110101101111012110131101411015110161101711018110191102011021110221102311024110251102611027110281102911030110311103211033110341103511036110371103811039110401104111042110431104411045110461104711048110491105011051110521105311054110551105611057110581105911060110611106211063110641106511066110671106811069110701107111072110731107411075110761107711078110791108011081110821108311084110851108611087110881108911090110911109211093110941109511096110971109811099111001110111102111031110411105111061110711108111091111011111111121111311114111151111611117111181111911120111211112211123111241112511126111271112811129111301113111132111331113411135111361113711138111391114011141111421114311144111451114611147111481114911150111511115211153111541115511156111571115811159111601116111162111631116411165111661116711168111691117011171111721117311174111751117611177111781117911180111811118211183111841118511186111871118811189111901119111192111931119411195111961119711198111991120011201112021120311204112051120611207112081120911210112111121211213112141121511216112171121811219112201122111222112231122411225112261122711228112291123011231112321123311234112351123611237112381123911240112411124211243112441124511246112471124811249112501125111252112531125411255112561125711258112591126011261112621126311264112651126611267112681126911270112711127211273112741127511276112771127811279112801128111282112831128411285112861128711288112891129011291112921129311294112951129611297112981129911300113011130211303113041130511306113071130811309113101131111312113131131411315113161131711318113191132011321113221132311324113251132611327113281132911330113311133211333113341133511336113371133811339113401134111342113431134411345113461134711348113491135011351113521135311354113551135611357113581135911360113611136211363113641136511366113671136811369113701137111372113731137411375113761137711378113791138011381113821138311384113851138611387113881138911390113911139211393113941139511396113971139811399114001140111402114031140411405114061140711408114091141011411114121141311414114151141611417114181141911420114211142211423114241142511426114271142811429114301143111432114331143411435114361143711438114391144011441114421144311444114451144611447114481144911450114511145211453114541145511456114571145811459114601146111462114631146411465114661146711468114691147011471114721147311474114751147611477114781147911480114811148211483114841148511486114871148811489114901149111492114931149411495114961149711498114991150011501115021150311504115051150611507115081150911510115111151211513115141151511516115171151811519115201152111522115231152411525115261152711528115291153011531115321153311534115351153611537115381153911540115411154211543115441154511546115471154811549115501155111552115531155411555115561155711558115591156011561115621156311564115651156611567115681156911570115711157211573115741157511576115771157811579115801158111582115831158411585115861158711588115891159011591115921159311594115951159611597115981159911600116011160211603116041160511606116071160811609116101161111612116131161411615116161161711618116191162011621116221162311624116251162611627116281162911630116311163211633116341163511636116371163811639116401164111642116431164411645116461164711648116491165011651116521165311654116551165611657116581165911660116611166211663116641166511666116671166811669116701167111672116731167411675116761167711678116791168011681116821168311684116851168611687116881168911690116911169211693116941169511696116971169811699117001170111702117031170411705117061170711708117091171011711117121171311714117151171611717117181171911720117211172211723117241172511726117271172811729117301173111732117331173411735117361173711738117391174011741117421174311744117451174611747117481174911750117511175211753117541175511756117571175811759117601176111762117631176411765117661176711768117691177011771117721177311774117751177611777117781177911780117811178211783117841178511786117871178811789117901179111792117931179411795117961179711798117991180011801118021180311804118051180611807118081180911810118111181211813118141181511816118171181811819118201182111822118231182411825118261182711828118291183011831118321183311834118351183611837118381183911840118411184211843118441184511846118471184811849118501185111852118531185411855118561185711858118591186011861118621186311864118651186611867118681186911870118711187211873118741187511876118771187811879118801188111882118831188411885118861188711888118891189011891118921189311894118951189611897118981189911900119011190211903119041190511906119071190811909119101191111912119131191411915119161191711918119191192011921119221192311924119251192611927119281192911930119311193211933119341193511936119371193811939119401194111942119431194411945119461194711948119491195011951119521195311954119551195611957119581195911960119611196211963119641196511966119671196811969119701197111972119731197411975119761197711978119791198011981119821198311984119851198611987119881198911990119911199211993119941199511996119971199811999120001200112002120031200412005120061200712008120091201012011120121201312014120151201612017120181201912020120211202212023120241202512026120271202812029120301203112032120331203412035120361203712038120391204012041120421204312044120451204612047120481204912050120511205212053120541205512056120571205812059120601206112062120631206412065120661206712068120691207012071120721207312074120751207612077120781207912080120811208212083120841208512086120871208812089120901209112092120931209412095120961209712098120991210012101121021210312104121051210612107121081210912110121111211212113121141211512116121171211812119121201212112122121231212412125121261212712128121291213012131121321213312134121351213612137121381213912140121411214212143121441214512146121471214812149121501215112152121531215412155121561215712158121591216012161121621216312164121651216612167121681216912170121711217212173121741217512176121771217812179121801218112182121831218412185121861218712188121891219012191121921219312194121951219612197121981219912200122011220212203122041220512206122071220812209122101221112212122131221412215122161221712218122191222012221122221222312224122251222612227122281222912230122311223212233122341223512236122371223812239122401224112242122431224412245122461224712248122491225012251122521225312254122551225612257122581225912260122611226212263122641226512266122671226812269122701227112272122731227412275122761227712278122791228012281122821228312284122851228612287122881228912290122911229212293122941229512296122971229812299123001230112302123031230412305123061230712308123091231012311123121231312314123151231612317123181231912320123211232212323123241232512326123271232812329123301233112332123331233412335123361233712338123391234012341123421234312344123451234612347123481234912350123511235212353123541235512356123571235812359123601236112362123631236412365123661236712368123691237012371123721237312374123751237612377123781237912380123811238212383123841238512386123871238812389123901239112392123931239412395123961239712398123991240012401124021240312404124051240612407124081240912410124111241212413124141241512416124171241812419124201242112422124231242412425124261242712428124291243012431124321243312434124351243612437124381243912440124411244212443124441244512446124471244812449124501245112452124531245412455124561245712458124591246012461124621246312464124651246612467124681246912470124711247212473124741247512476124771247812479124801248112482124831248412485124861248712488124891249012491124921249312494124951249612497124981249912500125011250212503125041250512506125071250812509125101251112512125131251412515125161251712518125191252012521125221252312524125251252612527125281252912530125311253212533125341253512536125371253812539125401254112542125431254412545125461254712548125491255012551125521255312554125551255612557125581255912560125611256212563125641256512566125671256812569125701257112572125731257412575125761257712578125791258012581125821258312584125851258612587125881258912590125911259212593125941259512596125971259812599126001260112602126031260412605126061260712608126091261012611126121261312614126151261612617126181261912620126211262212623126241262512626126271262812629126301263112632126331263412635126361263712638126391264012641126421264312644126451264612647126481264912650126511265212653126541265512656126571265812659126601266112662126631266412665126661266712668126691267012671126721267312674126751267612677126781267912680126811268212683126841268512686126871268812689126901269112692126931269412695126961269712698126991270012701127021270312704127051270612707127081270912710127111271212713127141271512716127171271812719127201272112722127231272412725127261272712728127291273012731127321273312734127351273612737127381273912740127411274212743127441274512746127471274812749127501275112752127531275412755127561275712758127591276012761127621276312764127651276612767127681276912770127711277212773127741277512776127771277812779127801278112782127831278412785127861278712788127891279012791127921279312794127951279612797127981279912800128011280212803128041280512806128071280812809128101281112812128131281412815128161281712818128191282012821128221282312824128251282612827128281282912830128311283212833128341283512836128371283812839128401284112842128431284412845128461284712848128491285012851128521285312854128551285612857128581285912860128611286212863128641286512866128671286812869128701287112872128731287412875128761287712878128791288012881128821288312884128851288612887128881288912890128911289212893128941289512896128971289812899129001290112902129031290412905129061290712908129091291012911129121291312914129151291612917129181291912920129211292212923129241292512926129271292812929129301293112932129331293412935129361293712938129391294012941129421294312944129451294612947129481294912950129511295212953129541295512956129571295812959129601296112962129631296412965129661296712968129691297012971129721297312974129751297612977129781297912980129811298212983129841298512986129871298812989129901299112992129931299412995129961299712998129991300013001130021300313004130051300613007130081300913010130111301213013130141301513016130171301813019130201302113022130231302413025130261302713028130291303013031130321303313034130351303613037130381303913040130411304213043130441304513046130471304813049130501305113052130531305413055130561305713058130591306013061130621306313064130651306613067130681306913070130711307213073130741307513076130771307813079130801308113082130831308413085130861308713088130891309013091130921309313094130951309613097130981309913100131011310213103131041310513106131071310813109131101311113112131131311413115131161311713118131191312013121131221312313124131251312613127131281312913130131311313213133131341313513136131371313813139131401314113142131431314413145131461314713148131491315013151131521315313154131551315613157131581315913160131611316213163131641316513166131671316813169131701317113172131731317413175131761317713178131791318013181131821318313184131851318613187131881318913190131911319213193131941319513196131971319813199132001320113202132031320413205132061320713208132091321013211132121321313214132151321613217132181321913220132211322213223132241322513226132271322813229132301323113232132331323413235132361323713238132391324013241132421324313244132451324613247132481324913250132511325213253132541325513256132571325813259132601326113262132631326413265132661326713268132691327013271132721327313274132751327613277132781327913280132811328213283132841328513286132871328813289132901329113292132931329413295132961329713298132991330013301133021330313304133051330613307133081330913310133111331213313133141331513316133171331813319133201332113322133231332413325133261332713328133291333013331133321333313334133351333613337133381333913340133411334213343133441334513346133471334813349133501335113352133531335413355133561335713358133591336013361133621336313364133651336613367133681336913370133711337213373133741337513376133771337813379133801338113382133831338413385133861338713388133891339013391133921339313394133951339613397133981339913400134011340213403134041340513406134071340813409134101341113412134131341413415134161341713418134191342013421134221342313424134251342613427134281342913430134311343213433134341343513436134371343813439134401344113442134431344413445134461344713448134491345013451134521345313454134551345613457134581345913460134611346213463134641346513466134671346813469134701347113472134731347413475134761347713478134791348013481134821348313484134851348613487134881348913490134911349213493134941349513496134971349813499135001350113502135031350413505135061350713508135091351013511135121351313514135151351613517135181351913520135211352213523135241352513526135271352813529135301353113532135331353413535135361353713538135391354013541135421354313544135451354613547135481354913550135511355213553135541355513556135571355813559135601356113562135631356413565135661356713568135691357013571135721357313574135751357613577135781357913580135811358213583135841358513586135871358813589135901359113592135931359413595135961359713598135991360013601136021360313604136051360613607136081360913610136111361213613136141361513616136171361813619136201362113622136231362413625136261362713628136291363013631136321363313634136351363613637136381363913640136411364213643136441364513646136471364813649136501365113652136531365413655136561365713658136591366013661136621366313664136651366613667136681366913670136711367213673136741367513676136771367813679136801368113682136831368413685136861368713688136891369013691136921369313694136951369613697136981369913700137011370213703137041370513706137071370813709137101371113712137131371413715137161371713718137191372013721137221372313724137251372613727137281372913730137311373213733137341373513736137371373813739137401374113742137431374413745137461374713748137491375013751137521375313754137551375613757137581375913760137611376213763137641376513766137671376813769137701377113772137731377413775137761377713778137791378013781137821378313784137851378613787137881378913790137911379213793137941379513796137971379813799138001380113802138031380413805138061380713808138091381013811138121381313814138151381613817138181381913820138211382213823138241382513826138271382813829138301383113832138331383413835138361383713838138391384013841138421384313844138451384613847138481384913850138511385213853138541385513856138571385813859138601386113862138631386413865138661386713868138691387013871138721387313874138751387613877138781387913880138811388213883138841388513886138871388813889138901389113892138931389413895138961389713898138991390013901139021390313904139051390613907139081390913910139111391213913139141391513916139171391813919139201392113922139231392413925139261392713928139291393013931139321393313934139351393613937139381393913940139411394213943139441394513946139471394813949139501395113952139531395413955139561395713958139591396013961139621396313964139651396613967139681396913970139711397213973139741397513976139771397813979139801398113982139831398413985139861398713988139891399013991139921399313994139951399613997139981399914000140011400214003140041400514006140071400814009140101401114012140131401414015140161401714018140191402014021140221402314024140251402614027140281402914030140311403214033140341403514036140371403814039140401404114042140431404414045140461404714048140491405014051140521405314054140551405614057140581405914060140611406214063140641406514066140671406814069140701407114072140731407414075140761407714078140791408014081140821408314084140851408614087140881408914090140911409214093140941409514096140971409814099141001410114102141031410414105141061410714108141091411014111141121411314114141151411614117141181411914120141211412214123141241412514126141271412814129141301413114132141331413414135141361413714138141391414014141141421414314144141451414614147141481414914150141511415214153141541415514156141571415814159141601416114162141631416414165141661416714168141691417014171141721417314174141751417614177141781417914180141811418214183141841418514186141871418814189141901419114192141931419414195141961419714198141991420014201142021420314204142051420614207142081420914210142111421214213142141421514216142171421814219142201422114222142231422414225142261422714228142291423014231142321423314234142351423614237142381423914240142411424214243142441424514246142471424814249142501425114252142531425414255142561425714258142591426014261142621426314264142651426614267142681426914270142711427214273142741427514276142771427814279142801428114282142831428414285142861428714288142891429014291142921429314294142951429614297142981429914300143011430214303143041430514306143071430814309143101431114312143131431414315143161431714318143191432014321143221432314324143251432614327143281432914330143311433214333143341433514336143371433814339143401434114342143431434414345143461434714348143491435014351143521435314354143551435614357143581435914360143611436214363143641436514366143671436814369143701437114372143731437414375143761437714378143791438014381143821438314384143851438614387143881438914390143911439214393143941439514396143971439814399144001440114402144031440414405144061440714408144091441014411144121441314414144151441614417144181441914420144211442214423144241442514426144271442814429144301443114432144331443414435144361443714438144391444014441144421444314444144451444614447144481444914450144511445214453144541445514456144571445814459144601446114462144631446414465144661446714468144691447014471144721447314474144751447614477144781447914480144811448214483144841448514486144871448814489144901449114492144931449414495144961449714498144991450014501145021450314504145051450614507145081450914510145111451214513145141451514516145171451814519145201452114522145231452414525145261452714528145291453014531145321453314534145351453614537145381453914540145411454214543145441454514546145471454814549145501455114552145531455414555145561455714558145591456014561145621456314564145651456614567145681456914570145711457214573145741457514576145771457814579145801458114582145831458414585145861458714588145891459014591145921459314594145951459614597145981459914600146011460214603146041460514606146071460814609146101461114612146131461414615146161461714618146191462014621146221462314624146251462614627146281462914630146311463214633146341463514636146371463814639146401464114642146431464414645146461464714648146491465014651146521465314654146551465614657146581465914660146611466214663146641466514666146671466814669146701467114672146731467414675146761467714678146791468014681146821468314684146851468614687146881468914690146911469214693146941469514696146971469814699147001470114702147031470414705147061470714708147091471014711147121471314714147151471614717147181471914720147211472214723147241472514726147271472814729147301473114732147331473414735147361473714738147391474014741147421474314744147451474614747147481474914750147511475214753147541475514756147571475814759147601476114762147631476414765147661476714768147691477014771147721477314774147751477614777147781477914780147811478214783147841478514786147871478814789147901479114792147931479414795147961479714798147991480014801148021480314804148051480614807148081480914810148111481214813148141481514816148171481814819148201482114822148231482414825148261482714828148291483014831148321483314834148351483614837148381483914840148411484214843148441484514846148471484814849148501485114852148531485414855148561485714858148591486014861148621486314864148651486614867148681486914870148711487214873148741487514876148771487814879148801488114882148831488414885148861488714888148891489014891148921489314894148951489614897148981489914900149011490214903149041490514906149071490814909149101491114912149131491414915149161491714918149191492014921149221492314924149251492614927149281492914930149311493214933149341493514936149371493814939149401494114942149431494414945149461494714948149491495014951149521495314954149551495614957149581495914960149611496214963149641496514966149671496814969149701497114972149731497414975149761497714978149791498014981149821498314984149851498614987149881498914990149911499214993149941499514996149971499814999150001500115002150031500415005150061500715008150091501015011150121501315014150151501615017150181501915020150211502215023150241502515026150271502815029150301503115032150331503415035150361503715038150391504015041150421504315044150451504615047150481504915050150511505215053150541505515056150571505815059150601506115062150631506415065150661506715068150691507015071150721507315074150751507615077150781507915080150811508215083150841508515086150871508815089150901509115092150931509415095150961509715098150991510015101151021510315104151051510615107151081510915110151111511215113151141511515116151171511815119151201512115122151231512415125151261512715128151291513015131151321513315134151351513615137151381513915140151411514215143151441514515146151471514815149151501515115152151531515415155151561515715158151591516015161151621516315164151651516615167151681516915170151711517215173151741517515176151771517815179151801518115182151831518415185151861518715188151891519015191151921519315194151951519615197151981519915200152011520215203152041520515206152071520815209152101521115212152131521415215152161521715218152191522015221152221522315224152251522615227152281522915230152311523215233152341523515236152371523815239152401524115242152431524415245152461524715248152491525015251152521525315254152551525615257152581525915260152611526215263152641526515266152671526815269152701527115272152731527415275152761527715278152791528015281152821528315284152851528615287152881528915290152911529215293152941529515296152971529815299153001530115302153031530415305153061530715308153091531015311153121531315314153151531615317153181531915320153211532215323153241532515326153271532815329153301533115332153331533415335153361533715338153391534015341153421534315344153451534615347153481534915350153511535215353153541535515356153571535815359153601536115362153631536415365153661536715368153691537015371153721537315374153751537615377153781537915380153811538215383153841538515386153871538815389153901539115392153931539415395153961539715398153991540015401154021540315404154051540615407154081540915410154111541215413154141541515416154171541815419154201542115422154231542415425154261542715428154291543015431154321543315434154351543615437154381543915440154411544215443154441544515446154471544815449154501545115452154531545415455154561545715458154591546015461154621546315464154651546615467154681546915470154711547215473154741547515476154771547815479154801548115482154831548415485154861548715488154891549015491154921549315494154951549615497154981549915500155011550215503155041550515506155071550815509155101551115512155131551415515155161551715518155191552015521155221552315524155251552615527155281552915530155311553215533155341553515536155371553815539155401554115542155431554415545155461554715548155491555015551155521555315554155551555615557155581555915560155611556215563155641556515566155671556815569155701557115572155731557415575155761557715578155791558015581155821558315584155851558615587155881558915590155911559215593155941559515596155971559815599156001560115602156031560415605156061560715608156091561015611156121561315614156151561615617156181561915620156211562215623156241562515626156271562815629156301563115632156331563415635156361563715638156391564015641156421564315644156451564615647156481564915650156511565215653156541565515656156571565815659156601566115662156631566415665156661566715668156691567015671156721567315674156751567615677156781567915680156811568215683156841568515686156871568815689156901569115692156931569415695156961569715698156991570015701157021570315704157051570615707157081570915710157111571215713157141571515716157171571815719157201572115722157231572415725157261572715728157291573015731157321573315734157351573615737157381573915740157411574215743157441574515746157471574815749157501575115752157531575415755157561575715758157591576015761157621576315764157651576615767157681576915770157711577215773157741577515776157771577815779157801578115782157831578415785157861578715788157891579015791157921579315794157951579615797157981579915800158011580215803158041580515806158071580815809158101581115812158131581415815158161581715818158191582015821158221582315824158251582615827158281582915830158311583215833158341583515836158371583815839158401584115842158431584415845158461584715848158491585015851158521585315854158551585615857158581585915860158611586215863158641586515866158671586815869158701587115872158731587415875158761587715878158791588015881158821588315884158851588615887158881588915890158911589215893158941589515896158971589815899159001590115902159031590415905159061590715908159091591015911159121591315914159151591615917159181591915920159211592215923159241592515926159271592815929159301593115932159331593415935159361593715938159391594015941159421594315944159451594615947159481594915950159511595215953159541595515956159571595815959159601596115962159631596415965159661596715968159691597015971159721597315974159751597615977159781597915980159811598215983159841598515986159871598815989159901599115992159931599415995159961599715998159991600016001160021600316004160051600616007160081600916010160111601216013160141601516016160171601816019160201602116022160231602416025160261602716028160291603016031160321603316034160351603616037160381603916040160411604216043160441604516046160471604816049160501605116052160531605416055160561605716058160591606016061160621606316064160651606616067160681606916070160711607216073160741607516076160771607816079160801608116082160831608416085160861608716088160891609016091160921609316094160951609616097160981609916100161011610216103161041610516106161071610816109161101611116112161131611416115161161611716118161191612016121161221612316124161251612616127161281612916130161311613216133161341613516136161371613816139161401614116142161431614416145161461614716148161491615016151161521615316154161551615616157161581615916160161611616216163161641616516166161671616816169161701617116172161731617416175161761617716178161791618016181161821618316184161851618616187161881618916190161911619216193161941619516196161971619816199162001620116202162031620416205162061620716208162091621016211162121621316214162151621616217162181621916220162211622216223162241622516226162271622816229162301623116232162331623416235162361623716238162391624016241162421624316244162451624616247162481624916250162511625216253162541625516256162571625816259162601626116262162631626416265162661626716268162691627016271162721627316274162751627616277162781627916280162811628216283162841628516286162871628816289162901629116292162931629416295162961629716298162991630016301163021630316304163051630616307163081630916310163111631216313163141631516316163171631816319163201632116322163231632416325163261632716328163291633016331163321633316334163351633616337163381633916340163411634216343163441634516346163471634816349163501635116352163531635416355163561635716358163591636016361163621636316364163651636616367163681636916370163711637216373163741637516376163771637816379163801638116382163831638416385163861638716388163891639016391163921639316394163951639616397163981639916400164011640216403164041640516406164071640816409164101641116412164131641416415164161641716418164191642016421164221642316424164251642616427164281642916430164311643216433164341643516436164371643816439164401644116442164431644416445164461644716448164491645016451164521645316454164551645616457164581645916460164611646216463164641646516466164671646816469164701647116472164731647416475164761647716478164791648016481164821648316484164851648616487164881648916490164911649216493164941649516496164971649816499165001650116502165031650416505165061650716508165091651016511165121651316514165151651616517165181651916520165211652216523165241652516526165271652816529165301653116532165331653416535165361653716538165391654016541165421654316544165451654616547165481654916550165511655216553165541655516556165571655816559165601656116562165631656416565165661656716568165691657016571165721657316574165751657616577165781657916580165811658216583165841658516586165871658816589165901659116592165931659416595165961659716598165991660016601166021660316604166051660616607166081660916610166111661216613166141661516616166171661816619166201662116622166231662416625166261662716628166291663016631166321663316634166351663616637166381663916640166411664216643166441664516646166471664816649166501665116652166531665416655166561665716658166591666016661166621666316664166651666616667166681666916670166711667216673166741667516676166771667816679166801668116682166831668416685166861668716688166891669016691166921669316694166951669616697166981669916700167011670216703167041670516706167071670816709167101671116712167131671416715167161671716718167191672016721167221672316724167251672616727167281672916730167311673216733167341673516736167371673816739167401674116742167431674416745167461674716748167491675016751167521675316754167551675616757167581675916760167611676216763167641676516766167671676816769167701677116772167731677416775167761677716778167791678016781167821678316784167851678616787167881678916790167911679216793167941679516796167971679816799168001680116802168031680416805168061680716808168091681016811168121681316814168151681616817168181681916820168211682216823168241682516826168271682816829168301683116832168331683416835168361683716838168391684016841168421684316844168451684616847168481684916850168511685216853168541685516856168571685816859168601686116862168631686416865168661686716868168691687016871168721687316874168751687616877168781687916880168811688216883168841688516886168871688816889168901689116892168931689416895168961689716898168991690016901169021690316904169051690616907169081690916910169111691216913169141691516916169171691816919169201692116922169231692416925169261692716928169291693016931169321693316934169351693616937169381693916940169411694216943169441694516946169471694816949169501695116952169531695416955169561695716958169591696016961169621696316964169651696616967169681696916970169711697216973169741697516976169771697816979169801698116982169831698416985169861698716988169891699016991169921699316994169951699616997169981699917000170011700217003170041700517006170071700817009170101701117012170131701417015170161701717018170191702017021170221702317024170251702617027170281702917030170311703217033170341703517036170371703817039170401704117042170431704417045170461704717048170491705017051170521705317054170551705617057170581705917060170611706217063170641706517066170671706817069170701707117072170731707417075170761707717078170791708017081170821708317084170851708617087170881708917090170911709217093170941709517096170971709817099171001710117102171031710417105171061710717108171091711017111171121711317114171151711617117171181711917120171211712217123171241712517126171271712817129171301713117132171331713417135171361713717138171391714017141171421714317144171451714617147171481714917150171511715217153171541715517156171571715817159171601716117162171631716417165171661716717168171691717017171171721717317174171751717617177171781717917180171811718217183171841718517186171871718817189171901719117192171931719417195171961719717198171991720017201172021720317204172051720617207172081720917210172111721217213172141721517216172171721817219172201722117222172231722417225172261722717228172291723017231172321723317234172351723617237172381723917240172411724217243172441724517246172471724817249172501725117252172531725417255172561725717258172591726017261172621726317264172651726617267172681726917270172711727217273172741727517276172771727817279172801728117282172831728417285172861728717288172891729017291172921729317294172951729617297172981729917300173011730217303173041730517306173071730817309173101731117312173131731417315173161731717318173191732017321173221732317324173251732617327173281732917330173311733217333173341733517336173371733817339173401734117342173431734417345173461734717348173491735017351173521735317354173551735617357173581735917360173611736217363173641736517366173671736817369173701737117372173731737417375173761737717378173791738017381173821738317384173851738617387173881738917390173911739217393173941739517396173971739817399174001740117402174031740417405174061740717408174091741017411174121741317414174151741617417174181741917420174211742217423174241742517426174271742817429174301743117432174331743417435174361743717438174391744017441174421744317444174451744617447174481744917450174511745217453174541745517456174571745817459174601746117462174631746417465174661746717468174691747017471174721747317474174751747617477174781747917480174811748217483174841748517486174871748817489174901749117492174931749417495174961749717498174991750017501175021750317504175051750617507175081750917510175111751217513175141751517516175171751817519175201752117522175231752417525175261752717528175291753017531175321753317534175351753617537175381753917540175411754217543175441754517546175471754817549175501755117552175531755417555175561755717558175591756017561175621756317564175651756617567175681756917570175711757217573175741757517576175771757817579175801758117582175831758417585175861758717588175891759017591175921759317594175951759617597175981759917600176011760217603176041760517606176071760817609176101761117612176131761417615176161761717618176191762017621176221762317624176251762617627176281762917630176311763217633176341763517636176371763817639176401764117642176431764417645176461764717648176491765017651176521765317654176551765617657176581765917660176611766217663176641766517666176671766817669176701767117672176731767417675176761767717678176791768017681176821768317684176851768617687176881768917690176911769217693176941769517696176971769817699177001770117702177031770417705177061770717708177091771017711177121771317714177151771617717177181771917720177211772217723177241772517726177271772817729177301773117732177331773417735177361773717738177391774017741177421774317744177451774617747177481774917750177511775217753177541775517756177571775817759177601776117762177631776417765177661776717768177691777017771177721777317774177751777617777177781777917780177811778217783177841778517786177871778817789177901779117792177931779417795177961779717798177991780017801178021780317804178051780617807178081780917810178111781217813178141781517816178171781817819178201782117822178231782417825178261782717828178291783017831178321783317834178351783617837178381783917840178411784217843178441784517846178471784817849178501785117852178531785417855178561785717858178591786017861178621786317864178651786617867178681786917870178711787217873178741787517876178771787817879178801788117882178831788417885178861788717888178891789017891178921789317894178951789617897178981789917900179011790217903179041790517906179071790817909179101791117912179131791417915179161791717918179191792017921179221792317924179251792617927179281792917930179311793217933179341793517936179371793817939179401794117942179431794417945179461794717948179491795017951179521795317954179551795617957179581795917960179611796217963179641796517966179671796817969179701797117972179731797417975179761797717978179791798017981179821798317984179851798617987179881798917990179911799217993179941799517996179971799817999180001800118002180031800418005180061800718008180091801018011180121801318014180151801618017180181801918020180211802218023180241802518026180271802818029180301803118032180331803418035180361803718038180391804018041180421804318044180451804618047180481804918050180511805218053180541805518056180571805818059180601806118062180631806418065180661806718068180691807018071180721807318074180751807618077180781807918080180811808218083180841808518086180871808818089180901809118092180931809418095180961809718098180991810018101181021810318104181051810618107181081810918110181111811218113181141811518116181171811818119181201812118122181231812418125181261812718128181291813018131181321813318134181351813618137181381813918140181411814218143181441814518146181471814818149181501815118152181531815418155181561815718158181591816018161181621816318164181651816618167181681816918170181711817218173181741817518176181771817818179181801818118182181831818418185181861818718188181891819018191181921819318194181951819618197181981819918200182011820218203182041820518206182071820818209182101821118212182131821418215182161821718218182191822018221182221822318224182251822618227182281822918230182311823218233182341823518236182371823818239182401824118242182431824418245182461824718248182491825018251182521825318254182551825618257182581825918260182611826218263182641826518266182671826818269182701827118272182731827418275182761827718278182791828018281182821828318284182851828618287182881828918290182911829218293182941829518296182971829818299183001830118302183031830418305183061830718308183091831018311183121831318314183151831618317183181831918320183211832218323183241832518326183271832818329183301833118332183331833418335183361833718338183391834018341183421834318344183451834618347183481834918350183511835218353183541835518356183571835818359183601836118362183631836418365183661836718368183691837018371183721837318374183751837618377183781837918380183811838218383183841838518386183871838818389183901839118392183931839418395183961839718398183991840018401184021840318404184051840618407184081840918410184111841218413184141841518416184171841818419184201842118422184231842418425184261842718428184291843018431184321843318434184351843618437184381843918440184411844218443184441844518446184471844818449184501845118452184531845418455184561845718458184591846018461184621846318464184651846618467184681846918470184711847218473184741847518476184771847818479184801848118482184831848418485184861848718488184891849018491184921849318494184951849618497184981849918500185011850218503185041850518506185071850818509185101851118512185131851418515185161851718518185191852018521185221852318524185251852618527185281852918530185311853218533185341853518536185371853818539185401854118542185431854418545185461854718548185491855018551185521855318554185551855618557185581855918560185611856218563185641856518566185671856818569185701857118572185731857418575185761857718578185791858018581185821858318584185851858618587185881858918590185911859218593185941859518596185971859818599186001860118602186031860418605186061860718608186091861018611186121861318614186151861618617186181861918620186211862218623186241862518626186271862818629186301863118632186331863418635186361863718638186391864018641186421864318644186451864618647186481864918650186511865218653186541865518656186571865818659186601866118662186631866418665186661866718668186691867018671186721867318674186751867618677186781867918680186811868218683186841868518686186871868818689186901869118692186931869418695186961869718698186991870018701187021870318704187051870618707187081870918710187111871218713187141871518716187171871818719187201872118722187231872418725187261872718728187291873018731187321873318734187351873618737187381873918740187411874218743187441874518746187471874818749187501875118752187531875418755187561875718758187591876018761187621876318764187651876618767187681876918770187711877218773187741877518776187771877818779187801878118782187831878418785187861878718788187891879018791187921879318794187951879618797187981879918800188011880218803188041880518806188071880818809188101881118812188131881418815188161881718818188191882018821188221882318824188251882618827188281882918830188311883218833188341883518836188371883818839188401884118842188431884418845188461884718848188491885018851188521885318854188551885618857188581885918860188611886218863188641886518866188671886818869188701887118872188731887418875188761887718878188791888018881188821888318884188851888618887188881888918890188911889218893188941889518896188971889818899189001890118902189031890418905189061890718908189091891018911189121891318914189151891618917189181891918920189211892218923189241892518926189271892818929189301893118932189331893418935189361893718938189391894018941189421894318944189451894618947189481894918950189511895218953189541895518956189571895818959189601896118962189631896418965189661896718968189691897018971189721897318974189751897618977189781897918980189811898218983189841898518986189871898818989189901899118992189931899418995189961899718998189991900019001190021900319004190051900619007190081900919010190111901219013190141901519016190171901819019190201902119022190231902419025190261902719028190291903019031190321903319034190351903619037190381903919040190411904219043190441904519046190471904819049190501905119052190531905419055190561905719058190591906019061190621906319064190651906619067190681906919070190711907219073190741907519076190771907819079190801908119082190831908419085190861908719088190891909019091190921909319094190951909619097190981909919100191011910219103191041910519106191071910819109191101911119112191131911419115191161911719118191191912019121191221912319124191251912619127191281912919130191311913219133191341913519136191371913819139191401914119142191431914419145191461914719148191491915019151191521915319154191551915619157191581915919160191611916219163191641916519166191671916819169191701917119172191731917419175191761917719178191791918019181191821918319184191851918619187191881918919190191911919219193191941919519196191971919819199192001920119202192031920419205192061920719208192091921019211192121921319214192151921619217192181921919220192211922219223192241922519226192271922819229192301923119232192331923419235192361923719238192391924019241192421924319244192451924619247192481924919250192511925219253192541925519256192571925819259192601926119262192631926419265192661926719268192691927019271192721927319274192751927619277192781927919280192811928219283192841928519286192871928819289192901929119292192931929419295192961929719298192991930019301193021930319304193051930619307193081930919310193111931219313193141931519316193171931819319193201932119322193231932419325193261932719328193291933019331193321933319334193351933619337193381933919340193411934219343193441934519346193471934819349193501935119352193531935419355193561935719358193591936019361193621936319364193651936619367193681936919370193711937219373193741937519376193771937819379193801938119382193831938419385193861938719388193891939019391193921939319394193951939619397193981939919400194011940219403194041940519406194071940819409194101941119412194131941419415194161941719418194191942019421194221942319424194251942619427194281942919430194311943219433194341943519436194371943819439194401944119442194431944419445194461944719448194491945019451194521945319454194551945619457194581945919460194611946219463194641946519466194671946819469194701947119472194731947419475194761947719478194791948019481194821948319484194851948619487194881948919490194911949219493194941949519496194971949819499195001950119502195031950419505195061950719508195091951019511195121951319514195151951619517195181951919520195211952219523195241952519526195271952819529195301953119532195331953419535195361953719538195391954019541195421954319544195451954619547195481954919550195511955219553195541955519556195571955819559195601956119562195631956419565195661956719568195691957019571195721957319574195751957619577195781957919580195811958219583195841958519586195871958819589195901959119592195931959419595195961959719598195991960019601196021960319604196051960619607196081960919610196111961219613196141961519616196171961819619196201962119622196231962419625196261962719628196291963019631196321963319634196351963619637196381963919640196411964219643196441964519646196471964819649196501965119652196531965419655196561965719658196591966019661196621966319664196651966619667196681966919670196711967219673196741967519676196771967819679196801968119682196831968419685196861968719688196891969019691196921969319694196951969619697196981969919700197011970219703197041970519706197071970819709197101971119712197131971419715197161971719718197191972019721197221972319724197251972619727197281972919730197311973219733197341973519736197371973819739197401974119742197431974419745197461974719748197491975019751197521975319754197551975619757197581975919760197611976219763197641976519766197671976819769197701977119772197731977419775197761977719778197791978019781197821978319784197851978619787197881978919790197911979219793197941979519796197971979819799198001980119802198031980419805198061980719808198091981019811198121981319814198151981619817198181981919820198211982219823198241982519826198271982819829198301983119832198331983419835198361983719838198391984019841198421984319844198451984619847198481984919850198511985219853198541985519856198571985819859198601986119862198631986419865198661986719868198691987019871198721987319874198751987619877198781987919880198811988219883198841988519886198871988819889198901989119892198931989419895198961989719898198991990019901199021990319904199051990619907199081990919910199111991219913199141991519916199171991819919199201992119922199231992419925199261992719928199291993019931199321993319934199351993619937199381993919940199411994219943199441994519946199471994819949199501995119952199531995419955199561995719958199591996019961199621996319964199651996619967199681996919970199711997219973199741997519976199771997819979199801998119982199831998419985199861998719988199891999019991199921999319994199951999619997199981999920000200012000220003200042000520006200072000820009200102001120012200132001420015200162001720018200192002020021200222002320024200252002620027200282002920030200312003220033200342003520036200372003820039200402004120042200432004420045200462004720048200492005020051200522005320054200552005620057200582005920060200612006220063200642006520066200672006820069200702007120072200732007420075200762007720078200792008020081200822008320084200852008620087200882008920090200912009220093200942009520096200972009820099201002010120102201032010420105201062010720108201092011020111201122011320114201152011620117201182011920120201212012220123201242012520126201272012820129201302013120132201332013420135201362013720138201392014020141201422014320144201452014620147201482014920150201512015220153201542015520156201572015820159201602016120162201632016420165201662016720168201692017020171201722017320174201752017620177201782017920180201812018220183201842018520186201872018820189201902019120192201932019420195201962019720198201992020020201202022020320204202052020620207202082020920210202112021220213202142021520216202172021820219202202022120222202232022420225202262022720228202292023020231202322023320234202352023620237202382023920240202412024220243202442024520246202472024820249202502025120252202532025420255202562025720258202592026020261202622026320264202652026620267202682026920270202712027220273202742027520276202772027820279202802028120282202832028420285202862028720288202892029020291202922029320294202952029620297202982029920300203012030220303203042030520306203072030820309203102031120312203132031420315203162031720318203192032020321203222032320324203252032620327203282032920330203312033220333203342033520336203372033820339203402034120342203432034420345203462034720348203492035020351203522035320354203552035620357203582035920360203612036220363203642036520366203672036820369203702037120372203732037420375203762037720378203792038020381203822038320384203852038620387203882038920390203912039220393203942039520396203972039820399204002040120402204032040420405204062040720408204092041020411204122041320414204152041620417204182041920420204212042220423204242042520426204272042820429204302043120432204332043420435204362043720438204392044020441204422044320444204452044620447204482044920450204512045220453204542045520456204572045820459204602046120462204632046420465204662046720468204692047020471204722047320474204752047620477204782047920480204812048220483204842048520486204872048820489204902049120492204932049420495204962049720498204992050020501205022050320504205052050620507205082050920510205112051220513205142051520516205172051820519205202052120522205232052420525205262052720528205292053020531205322053320534205352053620537205382053920540205412054220543205442054520546205472054820549205502055120552205532055420555205562055720558205592056020561205622056320564205652056620567205682056920570205712057220573205742057520576205772057820579205802058120582205832058420585205862058720588205892059020591205922059320594205952059620597205982059920600206012060220603206042060520606206072060820609206102061120612206132061420615206162061720618206192062020621206222062320624206252062620627206282062920630206312063220633206342063520636206372063820639206402064120642206432064420645206462064720648206492065020651206522065320654206552065620657206582065920660206612066220663206642066520666206672066820669206702067120672206732067420675206762067720678206792068020681206822068320684206852068620687206882068920690206912069220693206942069520696206972069820699207002070120702207032070420705207062070720708207092071020711207122071320714207152071620717207182071920720207212072220723207242072520726207272072820729207302073120732207332073420735207362073720738207392074020741207422074320744207452074620747207482074920750207512075220753207542075520756207572075820759207602076120762207632076420765207662076720768207692077020771207722077320774207752077620777207782077920780207812078220783207842078520786207872078820789207902079120792207932079420795207962079720798207992080020801208022080320804208052080620807208082080920810208112081220813208142081520816208172081820819208202082120822208232082420825208262082720828208292083020831208322083320834208352083620837208382083920840208412084220843208442084520846208472084820849208502085120852208532085420855208562085720858208592086020861208622086320864208652086620867208682086920870208712087220873208742087520876208772087820879208802088120882208832088420885208862088720888208892089020891208922089320894208952089620897208982089920900209012090220903209042090520906209072090820909209102091120912209132091420915209162091720918209192092020921209222092320924209252092620927209282092920930209312093220933209342093520936209372093820939209402094120942209432094420945209462094720948209492095020951209522095320954209552095620957209582095920960209612096220963209642096520966209672096820969209702097120972209732097420975209762097720978209792098020981209822098320984209852098620987209882098920990209912099220993209942099520996209972099820999210002100121002210032100421005210062100721008210092101021011210122101321014210152101621017210182101921020210212102221023210242102521026210272102821029210302103121032210332103421035210362103721038210392104021041210422104321044210452104621047210482104921050210512105221053210542105521056210572105821059210602106121062210632106421065210662106721068210692107021071210722107321074210752107621077210782107921080210812108221083210842108521086210872108821089210902109121092210932109421095210962109721098210992110021101211022110321104211052110621107211082110921110211112111221113211142111521116211172111821119211202112121122211232112421125211262112721128211292113021131211322113321134211352113621137211382113921140211412114221143211442114521146211472114821149211502115121152211532115421155211562115721158211592116021161211622116321164211652116621167211682116921170211712117221173211742117521176211772117821179211802118121182211832118421185211862118721188211892119021191211922119321194211952119621197211982119921200212012120221203212042120521206212072120821209212102121121212212132121421215212162121721218212192122021221212222122321224212252122621227212282122921230212312123221233212342123521236212372123821239212402124121242212432124421245212462124721248212492125021251212522125321254212552125621257212582125921260212612126221263212642126521266212672126821269212702127121272212732127421275212762127721278212792128021281212822128321284212852128621287212882128921290212912129221293212942129521296212972129821299213002130121302213032130421305213062130721308213092131021311213122131321314213152131621317213182131921320213212132221323213242132521326213272132821329213302133121332213332133421335213362133721338213392134021341213422134321344213452134621347213482134921350213512135221353213542135521356213572135821359213602136121362213632136421365213662136721368213692137021371213722137321374213752137621377213782137921380213812138221383213842138521386213872138821389213902139121392213932139421395213962139721398213992140021401214022140321404214052140621407214082140921410214112141221413214142141521416214172141821419214202142121422214232142421425214262142721428214292143021431214322143321434214352143621437214382143921440214412144221443214442144521446214472144821449214502145121452214532145421455214562145721458214592146021461214622146321464214652146621467214682146921470214712147221473214742147521476214772147821479214802148121482214832148421485214862148721488214892149021491214922149321494214952149621497214982149921500215012150221503215042150521506215072150821509215102151121512215132151421515215162151721518215192152021521215222152321524215252152621527215282152921530215312153221533215342153521536215372153821539215402154121542215432154421545215462154721548215492155021551215522155321554215552155621557215582155921560215612156221563215642156521566215672156821569215702157121572215732157421575215762157721578215792158021581215822158321584215852158621587215882158921590215912159221593215942159521596215972159821599216002160121602216032160421605216062160721608216092161021611216122161321614216152161621617216182161921620216212162221623216242162521626216272162821629216302163121632216332163421635216362163721638216392164021641216422164321644216452164621647216482164921650216512165221653216542165521656216572165821659216602166121662216632166421665216662166721668216692167021671216722167321674216752167621677216782167921680216812168221683216842168521686216872168821689216902169121692216932169421695216962169721698216992170021701217022170321704217052170621707217082170921710217112171221713217142171521716217172171821719217202172121722217232172421725217262172721728217292173021731217322173321734217352173621737217382173921740217412174221743217442174521746217472174821749217502175121752217532175421755217562175721758217592176021761217622176321764217652176621767217682176921770217712177221773217742177521776217772177821779217802178121782217832178421785217862178721788217892179021791217922179321794217952179621797217982179921800218012180221803218042180521806218072180821809218102181121812218132181421815218162181721818218192182021821218222182321824218252182621827218282182921830218312183221833218342183521836218372183821839218402184121842218432184421845218462184721848218492185021851218522185321854218552185621857218582185921860218612186221863218642186521866218672186821869218702187121872218732187421875218762187721878218792188021881218822188321884218852188621887218882188921890218912189221893218942189521896218972189821899219002190121902219032190421905219062190721908219092191021911219122191321914219152191621917219182191921920219212192221923219242192521926219272192821929219302193121932219332193421935219362193721938219392194021941219422194321944219452194621947219482194921950219512195221953219542195521956219572195821959219602196121962219632196421965219662196721968219692197021971219722197321974219752197621977219782197921980219812198221983219842198521986219872198821989219902199121992219932199421995219962199721998219992200022001220022200322004220052200622007220082200922010220112201222013220142201522016220172201822019220202202122022220232202422025220262202722028220292203022031220322203322034220352203622037220382203922040220412204222043220442204522046220472204822049220502205122052220532205422055220562205722058220592206022061220622206322064220652206622067220682206922070220712207222073220742207522076220772207822079220802208122082220832208422085220862208722088220892209022091220922209322094220952209622097220982209922100221012210222103221042210522106221072210822109221102211122112221132211422115221162211722118221192212022121221222212322124221252212622127221282212922130221312213222133221342213522136221372213822139221402214122142221432214422145221462214722148221492215022151221522215322154221552215622157221582215922160221612216222163221642216522166221672216822169221702217122172221732217422175221762217722178221792218022181221822218322184221852218622187221882218922190221912219222193221942219522196221972219822199222002220122202222032220422205222062220722208222092221022211222122221322214222152221622217222182221922220222212222222223222242222522226222272222822229222302223122232222332223422235222362223722238222392224022241222422224322244222452224622247222482224922250222512225222253222542225522256222572225822259222602226122262222632226422265222662226722268222692227022271222722227322274222752227622277222782227922280222812228222283222842228522286222872228822289222902229122292222932229422295222962229722298222992230022301223022230322304223052230622307223082230922310223112231222313223142231522316223172231822319223202232122322223232232422325223262232722328223292233022331223322233322334223352233622337223382233922340223412234222343223442234522346223472234822349223502235122352223532235422355223562235722358223592236022361223622236322364223652236622367223682236922370223712237222373223742237522376223772237822379223802238122382223832238422385223862238722388223892239022391223922239322394223952239622397223982239922400224012240222403224042240522406224072240822409224102241122412224132241422415224162241722418224192242022421224222242322424224252242622427224282242922430224312243222433224342243522436224372243822439224402244122442224432244422445224462244722448224492245022451224522245322454224552245622457224582245922460224612246222463224642246522466224672246822469224702247122472224732247422475224762247722478224792248022481224822248322484224852248622487224882248922490224912249222493224942249522496224972249822499225002250122502225032250422505225062250722508225092251022511225122251322514225152251622517225182251922520225212252222523225242252522526225272252822529225302253122532225332253422535225362253722538225392254022541225422254322544225452254622547225482254922550225512255222553225542255522556225572255822559225602256122562225632256422565225662256722568225692257022571225722257322574225752257622577225782257922580225812258222583225842258522586225872258822589225902259122592225932259422595225962259722598225992260022601226022260322604226052260622607226082260922610226112261222613226142261522616226172261822619226202262122622226232262422625226262262722628226292263022631226322263322634226352263622637226382263922640226412264222643226442264522646226472264822649226502265122652226532265422655226562265722658226592266022661226622266322664226652266622667226682266922670226712267222673226742267522676226772267822679226802268122682226832268422685226862268722688226892269022691226922269322694226952269622697226982269922700227012270222703227042270522706227072270822709227102271122712227132271422715227162271722718227192272022721227222272322724227252272622727227282272922730227312273222733227342273522736227372273822739227402274122742227432274422745227462274722748227492275022751227522275322754227552275622757227582275922760227612276222763227642276522766227672276822769227702277122772227732277422775227762277722778227792278022781227822278322784227852278622787227882278922790227912279222793227942279522796227972279822799228002280122802228032280422805228062280722808228092281022811228122281322814228152281622817228182281922820228212282222823228242282522826228272282822829228302283122832228332283422835228362283722838228392284022841228422284322844228452284622847228482284922850228512285222853228542285522856228572285822859228602286122862228632286422865228662286722868228692287022871228722287322874228752287622877228782287922880228812288222883228842288522886228872288822889228902289122892228932289422895228962289722898228992290022901229022290322904229052290622907229082290922910229112291222913229142291522916229172291822919229202292122922229232292422925229262292722928229292293022931229322293322934229352293622937229382293922940229412294222943229442294522946229472294822949229502295122952229532295422955229562295722958229592296022961229622296322964229652296622967229682296922970229712297222973229742297522976229772297822979229802298122982229832298422985229862298722988229892299022991229922299322994229952299622997229982299923000230012300223003230042300523006230072300823009230102301123012230132301423015230162301723018230192302023021230222302323024230252302623027230282302923030230312303223033230342303523036230372303823039230402304123042230432304423045230462304723048230492305023051230522305323054230552305623057230582305923060230612306223063230642306523066230672306823069230702307123072230732307423075230762307723078230792308023081230822308323084230852308623087230882308923090230912309223093230942309523096230972309823099231002310123102231032310423105231062310723108231092311023111231122311323114231152311623117231182311923120231212312223123231242312523126231272312823129231302313123132231332313423135231362313723138231392314023141231422314323144231452314623147231482314923150231512315223153231542315523156231572315823159231602316123162231632316423165231662316723168231692317023171231722317323174231752317623177231782317923180231812318223183231842318523186231872318823189231902319123192231932319423195231962319723198231992320023201232022320323204232052320623207232082320923210232112321223213232142321523216232172321823219232202322123222232232322423225232262322723228232292323023231232322323323234232352323623237232382323923240232412324223243232442324523246232472324823249232502325123252232532325423255232562325723258232592326023261232622326323264232652326623267232682326923270232712327223273232742327523276232772327823279232802328123282232832328423285232862328723288232892329023291232922329323294232952329623297232982329923300233012330223303233042330523306233072330823309233102331123312233132331423315233162331723318233192332023321233222332323324233252332623327233282332923330233312333223333233342333523336233372333823339233402334123342233432334423345233462334723348233492335023351233522335323354233552335623357233582335923360233612336223363233642336523366233672336823369233702337123372233732337423375233762337723378233792338023381233822338323384233852338623387233882338923390233912339223393233942339523396233972339823399234002340123402234032340423405234062340723408234092341023411234122341323414234152341623417234182341923420234212342223423234242342523426234272342823429234302343123432234332343423435234362343723438234392344023441234422344323444234452344623447234482344923450234512345223453234542345523456234572345823459234602346123462234632346423465234662346723468234692347023471234722347323474234752347623477234782347923480234812348223483234842348523486234872348823489234902349123492234932349423495234962349723498234992350023501235022350323504235052350623507235082350923510235112351223513235142351523516235172351823519235202352123522235232352423525235262352723528235292353023531235322353323534235352353623537235382353923540235412354223543235442354523546235472354823549235502355123552235532355423555235562355723558235592356023561235622356323564235652356623567235682356923570235712357223573235742357523576235772357823579235802358123582235832358423585235862358723588235892359023591235922359323594235952359623597235982359923600236012360223603236042360523606236072360823609236102361123612236132361423615236162361723618236192362023621236222362323624236252362623627236282362923630236312363223633236342363523636236372363823639236402364123642236432364423645236462364723648236492365023651236522365323654236552365623657236582365923660236612366223663236642366523666236672366823669236702367123672236732367423675236762367723678236792368023681236822368323684236852368623687236882368923690236912369223693236942369523696236972369823699237002370123702237032370423705237062370723708237092371023711237122371323714237152371623717237182371923720237212372223723237242372523726237272372823729237302373123732237332373423735237362373723738237392374023741237422374323744237452374623747237482374923750237512375223753237542375523756237572375823759237602376123762237632376423765237662376723768237692377023771237722377323774237752377623777237782377923780237812378223783237842378523786237872378823789237902379123792237932379423795237962379723798237992380023801238022380323804238052380623807238082380923810238112381223813238142381523816238172381823819238202382123822238232382423825238262382723828238292383023831238322383323834238352383623837238382383923840238412384223843238442384523846238472384823849238502385123852238532385423855238562385723858238592386023861238622386323864238652386623867238682386923870238712387223873238742387523876238772387823879238802388123882238832388423885238862388723888238892389023891238922389323894238952389623897238982389923900239012390223903239042390523906239072390823909239102391123912239132391423915239162391723918239192392023921239222392323924239252392623927239282392923930239312393223933239342393523936239372393823939239402394123942239432394423945239462394723948239492395023951239522395323954239552395623957239582395923960239612396223963239642396523966239672396823969239702397123972239732397423975239762397723978239792398023981239822398323984239852398623987239882398923990239912399223993239942399523996239972399823999240002400124002240032400424005240062400724008240092401024011240122401324014240152401624017240182401924020240212402224023240242402524026240272402824029240302403124032240332403424035240362403724038240392404024041240422404324044240452404624047240482404924050240512405224053240542405524056240572405824059240602406124062240632406424065240662406724068240692407024071240722407324074240752407624077240782407924080240812408224083240842408524086240872408824089240902409124092240932409424095240962409724098240992410024101241022410324104241052410624107241082410924110241112411224113241142411524116241172411824119241202412124122241232412424125241262412724128241292413024131241322413324134241352413624137241382413924140241412414224143241442414524146241472414824149241502415124152241532415424155241562415724158241592416024161241622416324164241652416624167241682416924170241712417224173241742417524176241772417824179241802418124182241832418424185241862418724188241892419024191241922419324194241952419624197241982419924200242012420224203242042420524206242072420824209242102421124212242132421424215242162421724218242192422024221242222422324224242252422624227242282422924230242312423224233242342423524236242372423824239242402424124242242432424424245242462424724248242492425024251242522425324254242552425624257242582425924260242612426224263242642426524266242672426824269242702427124272242732427424275242762427724278242792428024281242822428324284242852428624287242882428924290242912429224293242942429524296242972429824299243002430124302243032430424305243062430724308243092431024311243122431324314243152431624317243182431924320243212432224323243242432524326243272432824329243302433124332243332433424335243362433724338243392434024341243422434324344243452434624347243482434924350243512435224353243542435524356243572435824359243602436124362243632436424365243662436724368243692437024371243722437324374243752437624377243782437924380243812438224383243842438524386243872438824389243902439124392243932439424395243962439724398243992440024401244022440324404244052440624407244082440924410244112441224413244142441524416244172441824419244202442124422244232442424425244262442724428244292443024431244322443324434244352443624437244382443924440244412444224443244442444524446244472444824449244502445124452244532445424455244562445724458244592446024461244622446324464244652446624467244682446924470244712447224473244742447524476244772447824479244802448124482244832448424485244862448724488244892449024491244922449324494244952449624497244982449924500245012450224503245042450524506245072450824509245102451124512245132451424515245162451724518245192452024521245222452324524245252452624527245282452924530245312453224533245342453524536245372453824539245402454124542245432454424545245462454724548245492455024551245522455324554245552455624557245582455924560245612456224563245642456524566245672456824569245702457124572245732457424575245762457724578245792458024581245822458324584245852458624587245882458924590245912459224593245942459524596245972459824599246002460124602246032460424605246062460724608246092461024611246122461324614246152461624617246182461924620246212462224623246242462524626246272462824629246302463124632246332463424635246362463724638246392464024641246422464324644246452464624647246482464924650246512465224653246542465524656246572465824659246602466124662246632466424665246662466724668246692467024671246722467324674246752467624677246782467924680246812468224683246842468524686246872468824689246902469124692246932469424695246962469724698246992470024701247022470324704247052470624707247082470924710247112471224713247142471524716247172471824719247202472124722247232472424725247262472724728247292473024731247322473324734247352473624737247382473924740247412474224743247442474524746247472474824749247502475124752247532475424755247562475724758247592476024761247622476324764247652476624767247682476924770247712477224773247742477524776247772477824779247802478124782247832478424785247862478724788247892479024791247922479324794247952479624797247982479924800248012480224803248042480524806248072480824809248102481124812248132481424815248162481724818248192482024821248222482324824248252482624827248282482924830248312483224833248342483524836248372483824839248402484124842248432484424845248462484724848248492485024851248522485324854248552485624857248582485924860248612486224863248642486524866248672486824869248702487124872248732487424875248762487724878248792488024881248822488324884248852488624887248882488924890248912489224893248942489524896248972489824899249002490124902249032490424905249062490724908249092491024911249122491324914249152491624917249182491924920249212492224923249242492524926249272492824929249302493124932249332493424935249362493724938249392494024941249422494324944249452494624947249482494924950249512495224953249542495524956249572495824959249602496124962249632496424965249662496724968249692497024971249722497324974249752497624977249782497924980249812498224983249842498524986249872498824989249902499124992249932499424995249962499724998249992500025001250022500325004250052500625007250082500925010250112501225013250142501525016250172501825019250202502125022250232502425025250262502725028250292503025031250322503325034250352503625037250382503925040250412504225043250442504525046250472504825049250502505125052250532505425055250562505725058250592506025061250622506325064250652506625067250682506925070250712507225073250742507525076250772507825079250802508125082250832508425085250862508725088250892509025091250922509325094250952509625097250982509925100251012510225103251042510525106251072510825109251102511125112251132511425115251162511725118251192512025121251222512325124251252512625127251282512925130251312513225133251342513525136251372513825139251402514125142251432514425145251462514725148251492515025151
  1. /*
  2. * Linux cfg80211 driver
  3. *
  4. * Portions of this code are copyright (c) 2020 Cypress Semiconductor Corporation
  5. *
  6. * Copyright (C) 1999-2020, Broadcom Corporation
  7. *
  8. * Unless you and Broadcom execute a separate written software license
  9. * agreement governing use of this software, this software is licensed to you
  10. * under the terms of the GNU General Public License version 2 (the "GPL"),
  11. * available at http://www.broadcom.com/licenses/GPLv2.php, with the
  12. * following added to such license:
  13. *
  14. * As a special exception, the copyright holders of this software give you
  15. * permission to link this software with independent modules, and to copy and
  16. * distribute the resulting executable under terms of your choice, provided that
  17. * you also meet, for each linked independent module, the terms and conditions of
  18. * the license of that module. An independent module is a module which is not
  19. * derived from this software. The special exception does not apply to any
  20. * modifications of the software.
  21. *
  22. * Notwithstanding the above, under no circumstances may you combine this
  23. * software in any way with any other Broadcom software provided under a license
  24. * other than the GPL, without Broadcom's express prior written consent.
  25. *
  26. *
  27. * <<Broadcom-WL-IPTag/Open:>>
  28. *
  29. * $Id: wl_cfg80211.c 814814 2019-04-15 03:31:10Z $
  30. */
  31. /* */
  32. #include <typedefs.h>
  33. #include <linuxver.h>
  34. #include <linux/kernel.h>
  35. #include <bcmutils.h>
  36. #include <bcmstdlib_s.h>
  37. #include <bcmwifi_channels.h>
  38. #include <bcmendian.h>
  39. #include <ethernet.h>
  40. #ifdef WL_WPS_SYNC
  41. #include <eapol.h>
  42. #endif /* WL_WPS_SYNC */
  43. #include <802.11.h>
  44. #ifdef WL_FILS
  45. #include <fils.h>
  46. #include <frag.h>
  47. #endif /* WL_FILS */
  48. #include <bcmiov.h>
  49. #include <linux/if_arp.h>
  50. #include <asm/uaccess.h>
  51. #include <ethernet.h>
  52. #include <linux/kernel.h>
  53. #include <linux/kthread.h>
  54. #include <linux/netdevice.h>
  55. #include <linux/sched.h>
  56. #include <linux/etherdevice.h>
  57. #include <linux/wireless.h>
  58. #include <linux/ieee80211.h>
  59. #include <linux/wait.h>
  60. #include <net/cfg80211.h>
  61. #include <net/rtnetlink.h>
  62. #include <wlioctl.h>
  63. #include <bcmevent.h>
  64. #include <wldev_common.h>
  65. #include <wl_cfg80211.h>
  66. #include <wl_cfgp2p.h>
  67. #include <wl_cfgscan.h>
  68. #include <bcmdevs.h>
  69. #ifdef OEM_ANDROID
  70. #include <wl_android.h>
  71. #endif // endif
  72. #include <dngl_stats.h>
  73. #include <dhd.h>
  74. #include <dhd_linux.h>
  75. #include <dhd_linux_pktdump.h>
  76. #include <dhd_debug.h>
  77. #include <dhdioctl.h>
  78. #include <wlioctl.h>
  79. #include <dhd_cfg80211.h>
  80. #include <dhd_bus.h>
  81. #ifdef PNO_SUPPORT
  82. #include <dhd_pno.h>
  83. #endif /* PNO_SUPPORT */
  84. #include <wl_cfgvendor.h>
  85. #ifdef WL_NAN
  86. #include <wl_cfgnan.h>
  87. #endif /* WL_NAN */
  88. #ifdef PROP_TXSTATUS
  89. #include <dhd_wlfc.h>
  90. #endif // endif
  91. #ifdef BCMPCIE
  92. #include <dhd_flowring.h>
  93. #endif // endif
  94. #ifdef RTT_SUPPORT
  95. #include <dhd_rtt.h>
  96. #endif /* RTT_SUPPORT */
  97. #if defined(BIGDATA_SOFTAP) || defined(DHD_ENABLE_BIGDATA_LOGGING)
  98. #include <wl_bigdata.h>
  99. #endif /* BIGDATA_SOFTAP || DHD_ENABLE_BIGDATA_LOGGING */
  100. #ifdef DHD_EVENT_LOG_FILTER
  101. #include <dhd_event_log_filter.h>
  102. #endif /* DHD_EVENT_LOG_FILTER */
  103. #define BRCM_SAE_VENDOR_EVENT_BUF_LEN 500
  104. #ifdef DNGL_AXI_ERROR_LOGGING
  105. #include <bcmtlv.h>
  106. #endif /* DNGL_AXI_ERROR_LOGGING */
  107. #if defined(CONFIG_WLAN_BEYONDX) || defined(CONFIG_SEC_5GMODEL)
  108. #include <linux/dev_ril_bridge.h>
  109. #include <linux/notifier.h>
  110. #endif /* CONFIG_WLAN_BEYONDX || defined(CONFIG_SEC_5GMODEL) */
  111. #ifdef DHD_BANDSTEER
  112. #include <dhd_bandsteer.h>
  113. #endif /* DHD_BANDSTEER */
  114. #ifdef BCMWAPI_WPI
  115. /* these items should evetually go into wireless.h of the linux system headfile dir */
  116. #ifndef IW_ENCODE_ALG_SM4
  117. #define IW_ENCODE_ALG_SM4 0x20
  118. #endif // endif
  119. #ifndef IW_AUTH_WAPI_ENABLED
  120. #define IW_AUTH_WAPI_ENABLED 0x20
  121. #endif // endif
  122. #ifndef IW_AUTH_WAPI_VERSION_1
  123. #define IW_AUTH_WAPI_VERSION_1 0x00000008
  124. #endif // endif
  125. #ifndef IW_AUTH_CIPHER_SMS4
  126. #define IW_AUTH_CIPHER_SMS4 0x00000020
  127. #endif // endif
  128. #ifndef IW_AUTH_KEY_MGMT_WAPI_PSK
  129. #define IW_AUTH_KEY_MGMT_WAPI_PSK 4
  130. #endif // endif
  131. #ifndef IW_AUTH_KEY_MGMT_WAPI_CERT
  132. #define IW_AUTH_KEY_MGMT_WAPI_CERT 8
  133. #endif // endif
  134. #endif /* BCMWAPI_WPI */
  135. #ifdef BCMWAPI_WPI
  136. #define IW_WSEC_ENABLED(wsec) ((wsec) & (WEP_ENABLED | TKIP_ENABLED | AES_ENABLED | SMS4_ENABLED))
  137. #else /* BCMWAPI_WPI */
  138. #define IW_WSEC_ENABLED(wsec) ((wsec) & (WEP_ENABLED | TKIP_ENABLED | AES_ENABLED))
  139. #endif /* BCMWAPI_WPI */
  140. #ifdef WL_SAE
  141. #define MGMT_AUTH_FRAME_DWELL_TIME 4000
  142. #define MGMT_AUTH_FRAME_WAIT_TIME (MGMT_AUTH_FRAME_DWELL_TIME + 100)
  143. #endif /* WL_SAE */
  144. #if (defined(WL_FW_OCE_AP_SELECT) || defined(BCMFW_ROAM_ENABLE) && ((LINUX_VERSION_CODE \
  145. >= KERNEL_VERSION(3, 2, 0)) || defined(WL_COMPAT_WIRELESS)))
  146. uint fw_ap_select = true;
  147. #else
  148. uint fw_ap_select = false;
  149. #endif /* WL_FW_OCE_AP_SELECT && (ROAM_ENABLE || BCMFW_ROAM_ENABLE) */
  150. module_param(fw_ap_select, uint, 0660);
  151. static struct device *cfg80211_parent_dev = NULL;
  152. static struct bcm_cfg80211 *g_bcmcfg = NULL;
  153. u32 wl_dbg_level = WL_DBG_ERR | WL_DBG_P2P_ACTION | WL_DBG_INFO | WL_DBG_DBG | WL_DBG_TRACE;
  154. #define MAX_VIF_OFFSET 15
  155. #define MAX_WAIT_TIME 1500
  156. #ifdef WLAIBSS_MCHAN
  157. #define IBSS_IF_NAME "ibss%d"
  158. #endif /* WLAIBSS_MCHAN */
  159. #ifdef VSDB
  160. /* sleep time to keep STA's connecting or connection for continuous af tx or finding a peer */
  161. #define DEFAULT_SLEEP_TIME_VSDB 120
  162. #define OFF_CHAN_TIME_THRESHOLD_MS 200
  163. #define AF_RETRY_DELAY_TIME 40
  164. /* if sta is connected or connecting, sleep for a while before retry af tx or finding a peer */
  165. #define WL_AF_TX_KEEP_PRI_CONNECTION_VSDB(cfg) \
  166. do { \
  167. if (wl_get_drv_status(cfg, CONNECTED, bcmcfg_to_prmry_ndev(cfg)) || \
  168. wl_get_drv_status(cfg, CONNECTING, bcmcfg_to_prmry_ndev(cfg))) { \
  169. OSL_SLEEP(DEFAULT_SLEEP_TIME_VSDB); \
  170. } \
  171. } while (0)
  172. #else /* VSDB */
  173. /* if not VSDB, do nothing */
  174. #define WL_AF_TX_KEEP_PRI_CONNECTION_VSDB(cfg)
  175. #endif /* VSDB */
  176. #define DNGL_FUNC(func, parameters) func parameters
  177. #define COEX_DHCP
  178. #define WLAN_EID_SSID 0
  179. #define CH_MIN_5G_CHANNEL 34
  180. #ifdef WLAIBSS
  181. enum abiss_event_type {
  182. AIBSS_EVENT_TXFAIL
  183. };
  184. #endif // endif
  185. #ifdef WL_SAE
  186. /**
  187. * enum mgmt_tx_status - mgmt frame tx status
  188. *
  189. * @MGMT_TX_ACK: mgmt frame acked
  190. * @MGMT_TX_NOACK: mgmt frame not acked
  191. * @MGMT_TX_OFF_CHAN_COMPLETED: off-channel complete
  192. * @MGMT_TX_SEND_FRAME: mgmt frame tx is in progres
  193. */
  194. enum mgmt_tx_status {
  195. MGMT_TX_ACK,
  196. MGMT_TX_NOACK,
  197. MGMT_TX_OFF_CHAN_COMPLETED,
  198. MGMT_TX_SEND_FRAME
  199. };
  200. #endif /* WL_SAE */
  201. #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == \
  202. 4 && __GNUC_MINOR__ >= 6))
  203. #define BCM_SET_LIST_FIRST_ENTRY(entry, ptr, type, member) \
  204. GCC_DIAGNOSTIC_PUSH_SUPPRESS_CAST(); \
  205. (entry) = list_first_entry((ptr), type, member); \
  206. GCC_DIAGNOSTIC_POP(); \
  207. #define BCM_SET_CONTAINER_OF(entry, ptr, type, member) \
  208. GCC_DIAGNOSTIC_PUSH_SUPPRESS_CAST(); \
  209. entry = container_of((ptr), type, member); \
  210. GCC_DIAGNOSTIC_POP(); \
  211. #else
  212. #define BCM_SET_LIST_FIRST_ENTRY(entry, ptr, type, member) \
  213. (entry) = list_first_entry((ptr), type, member); \
  214. #define BCM_SET_CONTAINER_OF(entry, ptr, type, member) \
  215. entry = container_of((ptr), type, member); \
  216. #endif /* STRICT_GCC_WARNINGS */
  217. #ifdef WL_RELMCAST
  218. enum rmc_event_type {
  219. RMC_EVENT_NONE,
  220. RMC_EVENT_LEADER_CHECK_FAIL
  221. };
  222. #endif /* WL_RELMCAST */
  223. /* This is to override regulatory domains defined in cfg80211 module (reg.c)
  224. * By default world regulatory domain defined in reg.c puts the flags NL80211_RRF_PASSIVE_SCAN
  225. * and NL80211_RRF_NO_IBSS for 5GHz channels (for 36..48 and 149..165).
  226. * With respect to these flags, wpa_supplicant doesn't start p2p operations on 5GHz channels.
  227. * All the chnages in world regulatory domain are to be done here.
  228. *
  229. * this definition reuires disabling missing-field-initializer warning
  230. * as the ieee80211_regdomain definition differs in plain linux and in Android
  231. */
  232. #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == \
  233. 4 && __GNUC_MINOR__ >= 6))
  234. _Pragma("GCC diagnostic push")
  235. _Pragma("GCC diagnostic ignored \"-Wmissing-field-initializers\"")
  236. #endif // endif
  237. static const struct ieee80211_regdomain brcm_regdom = {
  238. .n_reg_rules = 4,
  239. .alpha2 = "99",
  240. .reg_rules = {
  241. /* IEEE 802.11b/g, channels 1..11 */
  242. REG_RULE(2412-10, 2472+10, 40, 6, 20, 0),
  243. /* If any */
  244. /* IEEE 802.11 channel 14 - Only JP enables
  245. * this and for 802.11b only
  246. */
  247. REG_RULE(2484-10, 2484+10, 20, 6, 20, 0),
  248. /* IEEE 802.11a, channel 36..64 */
  249. REG_RULE(5150-10, 5350+10, 80, 6, 20, 0),
  250. /* IEEE 802.11a, channel 100..165 */
  251. REG_RULE(5470-10, 5850+10, 80, 6, 20, 0), }
  252. };
  253. #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == \
  254. 4 && __GNUC_MINOR__ >= 6))
  255. _Pragma("GCC diagnostic pop")
  256. #endif // endif
  257. #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0)) && \
  258. (defined(WL_IFACE_COMB_NUM_CHANNELS) || defined(WL_CFG80211_P2P_DEV_IF))
  259. static const struct ieee80211_iface_limit common_if_limits[] = {
  260. {
  261. /*
  262. * Driver can support up to 2 AP's
  263. */
  264. .max = 2,
  265. .types = BIT(NL80211_IFTYPE_AP),
  266. },
  267. {
  268. /*
  269. * During P2P-GO removal, P2P-GO is first changed to STA and later only
  270. * removed. So setting maximum possible number of STA interfaces according
  271. * to kernel version.
  272. *
  273. * less than linux-3.8 - max:3 (wlan0 + p2p0 + group removal of p2p-p2p0-x)
  274. * linux-3.8 and above - max:4
  275. * sta + NAN NMI + NAN DPI open + NAN DPI sec (since there is no iface type
  276. * for NAN defined, registering it as STA type)
  277. */
  278. #ifdef WL_ENABLE_P2P_IF
  279. .max = 3,
  280. #else
  281. .max = 4,
  282. #endif /* WL_ENABLE_P2P_IF */
  283. .types = BIT(NL80211_IFTYPE_STATION),
  284. },
  285. {
  286. .max = 2,
  287. .types = BIT(NL80211_IFTYPE_P2P_GO) | BIT(NL80211_IFTYPE_P2P_CLIENT),
  288. },
  289. #if defined(WL_CFG80211_P2P_DEV_IF)
  290. {
  291. .max = 1,
  292. .types = BIT(NL80211_IFTYPE_P2P_DEVICE),
  293. },
  294. #endif /* WL_CFG80211_P2P_DEV_IF */
  295. {
  296. .max = 1,
  297. .types = BIT(NL80211_IFTYPE_ADHOC),
  298. },
  299. };
  300. #define NUM_DIFF_CHANNELS 3
  301. static const struct ieee80211_iface_combination
  302. common_iface_combinations[] = {
  303. {
  304. .num_different_channels = NUM_DIFF_CHANNELS,
  305. /*
  306. * At Max 5 network interfaces can be registered concurrently
  307. */
  308. .max_interfaces = IFACE_MAX_CNT,
  309. .limits = common_if_limits,
  310. .n_limits = ARRAY_SIZE(common_if_limits),
  311. },
  312. };
  313. #endif /* LINUX_VER >= 3.0 && (WL_IFACE_COMB_NUM_CHANNELS || WL_CFG80211_P2P_DEV_IF) */
  314. static const char *wl_if_state_strs[WL_IF_STATE_MAX + 1] = {
  315. "WL_IF_CREATE_REQ",
  316. "WL_IF_CREATE_DONE",
  317. "WL_IF_DELETE_REQ",
  318. "WL_IF_DELETE_DONE",
  319. "WL_IF_CHANGE_REQ",
  320. "WL_IF_CHANGE_DONE",
  321. "WL_IF_STATE_MAX"
  322. };
  323. #ifdef BCMWAPI_WPI
  324. #if defined(ANDROID_PLATFORM_VERSION) && (ANDROID_PLATFORM_VERSION >= 8)
  325. /* WAPI define in ieee80211.h is used */
  326. #else
  327. #undef WLAN_AKM_SUITE_WAPI_PSK
  328. #define WLAN_AKM_SUITE_WAPI_PSK 0x000FAC04
  329. #undef WLAN_AKM_SUITE_WAPI_CERT
  330. #define WLAN_AKM_SUITE_WAPI_CERT 0x000FAC12
  331. #undef NL80211_WAPI_VERSION_1
  332. #define NL80211_WAPI_VERSION_1 1 << 2
  333. #endif /* ANDROID_PLATFORM_VERSION && ANDROID_PLATFORM_VERSION >= 8 */
  334. #endif /* BCMWAPI_WPI */
  335. /* Data Element Definitions */
  336. #define WPS_ID_CONFIG_METHODS 0x1008
  337. #define WPS_ID_REQ_TYPE 0x103A
  338. #define WPS_ID_DEVICE_NAME 0x1011
  339. #define WPS_ID_VERSION 0x104A
  340. #define WPS_ID_DEVICE_PWD_ID 0x1012
  341. #define WPS_ID_REQ_DEV_TYPE 0x106A
  342. #define WPS_ID_SELECTED_REGISTRAR_CONFIG_METHODS 0x1053
  343. #define WPS_ID_PRIM_DEV_TYPE 0x1054
  344. /* Device Password ID */
  345. #define DEV_PW_DEFAULT 0x0000
  346. #define DEV_PW_USER_SPECIFIED 0x0001,
  347. #define DEV_PW_MACHINE_SPECIFIED 0x0002
  348. #define DEV_PW_REKEY 0x0003
  349. #define DEV_PW_PUSHBUTTON 0x0004
  350. #define DEV_PW_REGISTRAR_SPECIFIED 0x0005
  351. /* Config Methods */
  352. #define WPS_CONFIG_USBA 0x0001
  353. #define WPS_CONFIG_ETHERNET 0x0002
  354. #define WPS_CONFIG_LABEL 0x0004
  355. #define WPS_CONFIG_DISPLAY 0x0008
  356. #define WPS_CONFIG_EXT_NFC_TOKEN 0x0010
  357. #define WPS_CONFIG_INT_NFC_TOKEN 0x0020
  358. #define WPS_CONFIG_NFC_INTERFACE 0x0040
  359. #define WPS_CONFIG_PUSHBUTTON 0x0080
  360. #define WPS_CONFIG_KEYPAD 0x0100
  361. #define WPS_CONFIG_VIRT_PUSHBUTTON 0x0280
  362. #define WPS_CONFIG_PHY_PUSHBUTTON 0x0480
  363. #define WPS_CONFIG_VIRT_DISPLAY 0x2008
  364. #define WPS_CONFIG_PHY_DISPLAY 0x4008
  365. #define PM_BLOCK 1
  366. #define PM_ENABLE 0
  367. /* GCMP crypto supported above kernel v4.0 */
  368. #if (LINUX_VERSION_CODE > KERNEL_VERSION(4, 0, 0))
  369. #define WL_GCMP
  370. #endif /* (LINUX_VERSION_CODE > KERNEL_VERSION(4, 0, 0) */
  371. #ifndef IBSS_COALESCE_ALLOWED
  372. #define IBSS_COALESCE_ALLOWED IBSS_COALESCE_DEFAULT
  373. #endif // endif
  374. #ifndef IBSS_INITIAL_SCAN_ALLOWED
  375. #define IBSS_INITIAL_SCAN_ALLOWED IBSS_INITIAL_SCAN_ALLOWED_DEFAULT
  376. #endif // endif
  377. #define CUSTOM_RETRY_MASK 0xff000000 /* Mask for retry counter of custom dwell time */
  378. #define LONG_LISTEN_TIME 2000
  379. #ifdef WBTEXT
  380. typedef struct wl_wbtext_bssid {
  381. struct ether_addr ea;
  382. struct list_head list;
  383. } wl_wbtext_bssid_t;
  384. static void wl_cfg80211_wbtext_update_rcc(struct bcm_cfg80211 *cfg, struct net_device *dev);
  385. static bool wl_cfg80211_wbtext_check_bssid_list(struct bcm_cfg80211 *cfg, struct ether_addr *ea);
  386. static bool wl_cfg80211_wbtext_add_bssid_list(struct bcm_cfg80211 *cfg, struct ether_addr *ea);
  387. static void wl_cfg80211_wbtext_clear_bssid_list(struct bcm_cfg80211 *cfg);
  388. static bool wl_cfg80211_wbtext_send_nbr_req(struct bcm_cfg80211 *cfg, struct net_device *dev,
  389. struct wl_profile *profile);
  390. static bool wl_cfg80211_wbtext_send_btm_query(struct bcm_cfg80211 *cfg, struct net_device *dev,
  391. struct wl_profile *profile);
  392. static void wl_cfg80211_wbtext_set_wnm_maxidle(struct bcm_cfg80211 *cfg, struct net_device *dev);
  393. static int wl_cfg80211_recv_nbr_resp(struct net_device *dev, uint8 *body, uint body_len);
  394. #endif /* WBTEXT */
  395. #ifdef RTT_SUPPORT
  396. static s32 wl_cfg80211_rtt_event_handler(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev,
  397. const wl_event_msg_t *e, void *data);
  398. #endif /* RTT_SUPPORT */
  399. #ifdef WL_CHAN_UTIL
  400. static s32 wl_cfg80211_bssload_report_event_handler(struct bcm_cfg80211 *cfg,
  401. bcm_struct_cfgdev *cfgdev, const wl_event_msg_t *e, void *data);
  402. static s32 wl_cfg80211_start_bssload_report(struct net_device *ndev);
  403. #endif /* WL_CHAN_UTIL */
  404. #ifdef SUPPORT_AP_RADIO_PWRSAVE
  405. #define RADIO_PWRSAVE_PPS 10
  406. #define RADIO_PWRSAVE_QUIET_TIME 10
  407. #define RADIO_PWRSAVE_LEVEL 3
  408. #define RADIO_PWRSAVE_STAS_ASSOC_CHECK 0
  409. #define RADIO_PWRSAVE_LEVEL_MIN 1
  410. #define RADIO_PWRSAVE_LEVEL_MAX 9
  411. #define RADIO_PWRSAVE_PPS_MIN 1
  412. #define RADIO_PWRSAVE_QUIETTIME_MIN 1
  413. #define RADIO_PWRSAVE_ASSOCCHECK_MIN 0
  414. #define RADIO_PWRSAVE_ASSOCCHECK_MAX 1
  415. #define RADIO_PWRSAVE_MAJOR_VER 1
  416. #define RADIO_PWRSAVE_MINOR_VER 1
  417. #define RADIO_PWRSAVE_MAJOR_VER_SHIFT 8
  418. #define RADIO_PWRSAVE_VERSION \
  419. ((RADIO_PWRSAVE_MAJOR_VER << RADIO_PWRSAVE_MAJOR_VER_SHIFT)| RADIO_PWRSAVE_MINOR_VER)
  420. #endif /* SUPPORT_AP_RADIO_PWRSAVE */
  421. /* SoftAP related parameters */
  422. #define DEFAULT_2G_SOFTAP_CHANNEL 1
  423. #define DEFAULT_5G_SOFTAP_CHANNEL 149
  424. #define WL_MAX_NUM_CSA_COUNTERS 255
  425. #define MAX_VNDR_OUI_STR_LEN 256u
  426. #define VNDR_OUI_STR_LEN 10u
  427. #define DOT11_DISCONNECT_RC 2u
  428. static const uchar *exclude_vndr_oui_list[] = {
  429. "\x00\x50\xf2", /* Microsoft */
  430. "\x00\x00\xf0", /* Samsung Elec */
  431. WFA_OUI, /* WFA */
  432. NULL
  433. };
  434. typedef struct wl_vndr_oui_entry {
  435. uchar oui[DOT11_OUI_LEN];
  436. struct list_head list;
  437. } wl_vndr_oui_entry_t;
  438. static int wl_vndr_ies_get_vendor_oui(struct bcm_cfg80211 *cfg,
  439. struct net_device *ndev, char *vndr_oui, u32 vndr_oui_len);
  440. static void wl_vndr_ies_clear_vendor_oui_list(struct bcm_cfg80211 *cfg);
  441. static s32 wl_cfg80211_parse_vndr_ies(const u8 *parse, u32 len,
  442. struct parsed_vndr_ies *vndr_ies);
  443. #if defined(WL_FW_OCE_AP_SELECT)
  444. static bool
  445. wl_cfgoce_has_ie(const u8 *ie, const u8 **tlvs, u32 *tlvs_len, const u8 *oui, u32 oui_len, u8 type);
  446. /* Check whether the given IE looks like WFA OCE IE. */
  447. #define wl_cfgoce_is_oce_ie(ie, tlvs, len) wl_cfgoce_has_ie(ie, tlvs, len, \
  448. (const uint8 *)WFA_OUI, WFA_OUI_LEN, WFA_OUI_TYPE_MBO_OCE)
  449. /* Is any of the tlvs the expected entry? If
  450. * not update the tlvs buffer pointer/length.
  451. */
  452. static bool
  453. wl_cfgoce_has_ie(const u8 *ie, const u8 **tlvs, u32 *tlvs_len, const u8 *oui, u32 oui_len, u8 type)
  454. {
  455. /* If the contents match the OUI and the type */
  456. if (ie[TLV_LEN_OFF] >= oui_len + 1 &&
  457. !bcmp(&ie[TLV_BODY_OFF], oui, oui_len) &&
  458. type == ie[TLV_BODY_OFF + oui_len]) {
  459. return TRUE;
  460. }
  461. return FALSE;
  462. }
  463. #endif /* WL_FW_OCE_AP_SELECT */
  464. /*
  465. * cfg80211_ops api/callback list
  466. */
  467. static s32 wl_frame_get_mgmt(struct bcm_cfg80211 *cfg, u16 fc,
  468. const struct ether_addr *da, const struct ether_addr *sa,
  469. const struct ether_addr *bssid, u8 **pheader, u32 *body_len, u8 *pbody);
  470. static s32 wl_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed);
  471. #ifdef WLAIBSS_MCHAN
  472. static bcm_struct_cfgdev* bcm_cfg80211_add_ibss_if(struct wiphy *wiphy, char *name);
  473. static s32 bcm_cfg80211_del_ibss_if(struct wiphy *wiphy, bcm_struct_cfgdev *cfgdev);
  474. #endif /* WLAIBSS_MCHAN */
  475. static s32 wl_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *dev,
  476. struct cfg80211_ibss_params *params);
  477. static s32 wl_cfg80211_leave_ibss(struct wiphy *wiphy,
  478. struct net_device *dev);
  479. #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
  480. static s32 wl_cfg80211_get_station(struct wiphy *wiphy,
  481. struct net_device *dev, const u8 *mac,
  482. struct station_info *sinfo);
  483. #else
  484. static s32 wl_cfg80211_get_station(struct wiphy *wiphy,
  485. struct net_device *dev, u8 *mac,
  486. struct station_info *sinfo);
  487. #endif // endif
  488. static s32 wl_cfg80211_set_power_mgmt(struct wiphy *wiphy,
  489. struct net_device *dev, bool enabled,
  490. s32 timeout);
  491. static int wl_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev,
  492. struct cfg80211_connect_params *sme);
  493. #if defined(WL_FILS)
  494. static int wl_cfg80211_update_connect_params(struct wiphy *wiphy, struct net_device *dev,
  495. struct cfg80211_connect_params *sme, u32 changed);
  496. #endif /* WL_FILS */
  497. static s32 wl_cfg80211_disconnect(struct wiphy *wiphy, struct net_device *dev,
  498. u16 reason_code);
  499. #if defined(WL_CFG80211_P2P_DEV_IF)
  500. static s32
  501. wl_cfg80211_set_tx_power(struct wiphy *wiphy, struct wireless_dev *wdev,
  502. enum nl80211_tx_power_setting type, s32 mbm);
  503. #else
  504. static s32
  505. wl_cfg80211_set_tx_power(struct wiphy *wiphy,
  506. enum nl80211_tx_power_setting type, s32 dbm);
  507. #endif /* WL_CFG80211_P2P_DEV_IF */
  508. #if defined(WL_CFG80211_P2P_DEV_IF)
  509. static s32 wl_cfg80211_get_tx_power(struct wiphy *wiphy,
  510. struct wireless_dev *wdev, s32 *dbm);
  511. #else
  512. static s32 wl_cfg80211_get_tx_power(struct wiphy *wiphy, s32 *dbm);
  513. #endif /* WL_CFG80211_P2P_DEV_IF */
  514. static s32 wl_cfg80211_config_default_key(struct wiphy *wiphy,
  515. struct net_device *dev,
  516. u8 key_idx, bool unicast, bool multicast);
  517. static s32 wl_cfg80211_add_key(struct wiphy *wiphy, struct net_device *dev,
  518. u8 key_idx, bool pairwise, const u8 *mac_addr,
  519. struct key_params *params);
  520. static s32 wl_cfg80211_del_key(struct wiphy *wiphy, struct net_device *dev,
  521. u8 key_idx, bool pairwise, const u8 *mac_addr);
  522. static s32 wl_cfg80211_get_key(struct wiphy *wiphy, struct net_device *dev,
  523. u8 key_idx, bool pairwise, const u8 *mac_addr,
  524. void *cookie, void (*callback) (void *cookie,
  525. struct key_params *params));
  526. static s32 wl_cfg80211_config_default_mgmt_key(struct wiphy *wiphy,
  527. struct net_device *dev, u8 key_idx);
  528. static s32 wl_cfg80211_resume(struct wiphy *wiphy);
  529. #if defined(WL_SUPPORT_BACKPORTED_KPATCHES) || (LINUX_VERSION_CODE >= KERNEL_VERSION(3, \
  530. 2, 0))
  531. static s32 wl_cfg80211_mgmt_tx_cancel_wait(struct wiphy *wiphy,
  532. bcm_struct_cfgdev *cfgdev, u64 cookie);
  533. #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 19, 0))
  534. static s32 wl_cfg80211_del_station(
  535. struct wiphy *wiphy, struct net_device *ndev,
  536. struct station_del_parameters *params);
  537. #elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
  538. static s32 wl_cfg80211_del_station(struct wiphy *wiphy,
  539. struct net_device *ndev, const u8* mac_addr);
  540. #else
  541. static s32 wl_cfg80211_del_station(struct wiphy *wiphy,
  542. struct net_device *ndev, u8* mac_addr);
  543. #endif // endif
  544. #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
  545. static s32 wl_cfg80211_change_station(struct wiphy *wiphy,
  546. struct net_device *dev, const u8 *mac, struct station_parameters *params);
  547. #else
  548. static s32 wl_cfg80211_change_station(struct wiphy *wiphy,
  549. struct net_device *dev, u8 *mac, struct station_parameters *params);
  550. #endif // endif
  551. #endif /* WL_SUPPORT_BACKPORTED_KPATCHES || KERNEL_VER >= KERNEL_VERSION(3, 2, 0)) */
  552. #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 39)) || defined(WL_COMPAT_WIRELESS)
  553. static s32 wl_cfg80211_suspend(struct wiphy *wiphy, struct cfg80211_wowlan *wow);
  554. #else
  555. static s32 wl_cfg80211_suspend(struct wiphy *wiphy);
  556. #endif // endif
  557. static s32 wl_cfg80211_set_pmksa(struct wiphy *wiphy, struct net_device *dev,
  558. struct cfg80211_pmksa *pmksa);
  559. static s32 wl_cfg80211_del_pmksa(struct wiphy *wiphy, struct net_device *dev,
  560. struct cfg80211_pmksa *pmksa);
  561. static s32 wl_cfg80211_flush_pmksa(struct wiphy *wiphy,
  562. struct net_device *dev);
  563. #if (LINUX_VERSION_CODE > KERNEL_VERSION(3, 2, 0)) || defined(WL_COMPAT_WIRELESS)
  564. #if (defined(CONFIG_ARCH_MSM) && defined(TDLS_MGMT_VERSION2)) || (LINUX_VERSION_CODE < \
  565. KERNEL_VERSION(3, 16, 0) && LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0))
  566. static s32 wl_cfg80211_tdls_mgmt(struct wiphy *wiphy, struct net_device *dev,
  567. u8 *peer, u8 action_code, u8 dialog_token, u16 status_code,
  568. u32 peer_capability, const u8 *buf, size_t len);
  569. #elif ((LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0)) && \
  570. (LINUX_VERSION_CODE < KERNEL_VERSION(3, 18, 0)))
  571. static s32 wl_cfg80211_tdls_mgmt(struct wiphy *wiphy, struct net_device *dev,
  572. const u8 *peer, u8 action_code, u8 dialog_token, u16 status_code,
  573. u32 peer_capability, const u8 *buf, size_t len);
  574. #elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 18, 0))
  575. static s32 wl_cfg80211_tdls_mgmt(struct wiphy *wiphy, struct net_device *dev,
  576. const u8 *peer, u8 action_code, u8 dialog_token, u16 status_code,
  577. u32 peer_capability, bool initiator, const u8 *buf, size_t len);
  578. #else /* CONFIG_ARCH_MSM && TDLS_MGMT_VERSION2 */
  579. static s32 wl_cfg80211_tdls_mgmt(struct wiphy *wiphy, struct net_device *dev,
  580. u8 *peer, u8 action_code, u8 dialog_token, u16 status_code,
  581. const u8 *buf, size_t len);
  582. #endif /* CONFIG_ARCH_MSM && TDLS_MGMT_VERSION2 */
  583. #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
  584. static s32 wl_cfg80211_tdls_oper(struct wiphy *wiphy, struct net_device *dev,
  585. const u8 *peer, enum nl80211_tdls_operation oper);
  586. #else
  587. static s32 wl_cfg80211_tdls_oper(struct wiphy *wiphy, struct net_device *dev,
  588. u8 *peer, enum nl80211_tdls_operation oper);
  589. #endif // endif
  590. #endif /* LINUX_VERSION > KERNEL_VERSION(3,2,0) || WL_COMPAT_WIRELESS */
  591. static s32 wl_cfg80211_set_ap_role(struct bcm_cfg80211 *cfg, struct net_device *dev);
  592. struct wireless_dev *
  593. wl_cfg80211_create_iface(struct wiphy *wiphy, wl_iftype_t
  594. iface_type, u8 *mac_addr, const char *name);
  595. s32
  596. wl_cfg80211_del_iface(struct wiphy *wiphy, struct wireless_dev *wdev);
  597. s32 wl_cfg80211_interface_ops(struct bcm_cfg80211 *cfg,
  598. struct net_device *ndev, s32 bsscfg_idx,
  599. wl_iftype_t iftype, s32 del, u8 *addr);
  600. s32 wl_cfg80211_add_del_bss(struct bcm_cfg80211 *cfg,
  601. struct net_device *ndev, s32 bsscfg_idx,
  602. wl_iftype_t brcm_iftype, s32 del, u8 *addr);
  603. #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)) || defined(WL_COMPAT_WIRELESS)
  604. static s32 wl_cfg80211_stop_ap(struct wiphy *wiphy, struct net_device *dev);
  605. #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0) */
  606. #ifdef GTK_OFFLOAD_SUPPORT
  607. #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 1, 0))
  608. static s32 wl_cfg80211_set_rekey_data(struct wiphy *wiphy, struct net_device *dev,
  609. struct cfg80211_gtk_rekey_data *data);
  610. #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 1, 0) */
  611. #endif /* GTK_OFFLOAD_SUPPORT */
  612. chanspec_t wl_chspec_driver_to_host(chanspec_t chanspec);
  613. chanspec_t wl_chspec_host_to_driver(chanspec_t chanspec);
  614. static void wl_cfg80211_wait_for_disconnection(struct bcm_cfg80211 *cfg, struct net_device *dev);
  615. #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 12, 0))
  616. int wl_cfg80211_channel_switch(struct wiphy *wiphy, struct net_device *dev,
  617. struct cfg80211_csa_settings *params);
  618. #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 12, 0) */
  619. #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 13, 0))
  620. static int wl_cfg80211_set_pmk(struct wiphy *wiphy, struct net_device *dev,
  621. const struct cfg80211_pmk_conf *conf);
  622. static int wl_cfg80211_del_pmk(struct wiphy *wiphy, struct net_device *dev,
  623. const u8 *aa);
  624. #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(4, 13, 0) */
  625. #ifdef WL_SAE
  626. static int
  627. wl_cfg80211_external_auth(struct wiphy *wiphy, struct net_device *dev,
  628. struct cfg80211_external_auth_params *params);
  629. #endif /* WL_SAE */
  630. /*
  631. * event & event Q handlers for cfg80211 interfaces
  632. */
  633. static s32 wl_create_event_handler(struct bcm_cfg80211 *cfg);
  634. static void wl_destroy_event_handler(struct bcm_cfg80211 *cfg);
  635. static void wl_event_handler(struct work_struct *work_data);
  636. static void wl_init_eq(struct bcm_cfg80211 *cfg);
  637. static void wl_flush_eq(struct bcm_cfg80211 *cfg);
  638. static unsigned long wl_lock_eq(struct bcm_cfg80211 *cfg);
  639. static void wl_unlock_eq(struct bcm_cfg80211 *cfg, unsigned long flags);
  640. static void wl_init_eq_lock(struct bcm_cfg80211 *cfg);
  641. static void wl_init_event_handler(struct bcm_cfg80211 *cfg);
  642. static struct wl_event_q *wl_deq_event(struct bcm_cfg80211 *cfg);
  643. static s32 wl_enq_event(struct bcm_cfg80211 *cfg, struct net_device *ndev, u32 type,
  644. const wl_event_msg_t *msg, void *data);
  645. static void wl_put_event(struct bcm_cfg80211 *cfg, struct wl_event_q *e);
  646. static s32 wl_notify_connect_status_ap(struct bcm_cfg80211 *cfg, struct net_device *ndev,
  647. const wl_event_msg_t *e, void *data);
  648. static s32 wl_notify_connect_status(struct bcm_cfg80211 *cfg,
  649. bcm_struct_cfgdev *cfgdev, const wl_event_msg_t *e, void *data);
  650. static s32 wl_notify_roaming_status(struct bcm_cfg80211 *cfg,
  651. bcm_struct_cfgdev *cfgdev, const wl_event_msg_t *e, void *data);
  652. static s32 wl_bss_connect_done(struct bcm_cfg80211 *cfg, struct net_device *ndev,
  653. const wl_event_msg_t *e, void *data, bool completed);
  654. static s32 wl_bss_roaming_done(struct bcm_cfg80211 *cfg, struct net_device *ndev,
  655. const wl_event_msg_t *e, void *data);
  656. static s32 wl_notify_mic_status(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev,
  657. const wl_event_msg_t *e, void *data);
  658. #ifdef BT_WIFI_HANDOVER
  659. static s32 wl_notify_bt_wifi_handover_req(struct bcm_cfg80211 *cfg,
  660. bcm_struct_cfgdev *cfgdev, const wl_event_msg_t *e, void *data);
  661. #endif /* BT_WIFI_HANDOVER */
  662. #ifdef GSCAN_SUPPORT
  663. static s32 wl_handle_roam_exp_event(struct bcm_cfg80211 *wl, bcm_struct_cfgdev *cfgdev,
  664. const wl_event_msg_t *e, void *data);
  665. #endif /* GSCAN_SUPPORT */
  666. #ifdef RSSI_MONITOR_SUPPORT
  667. static s32 wl_handle_rssi_monitor_event(struct bcm_cfg80211 *wl, bcm_struct_cfgdev *cfgdev,
  668. const wl_event_msg_t *e, void *data);
  669. #endif /* RSSI_MONITOR_SUPPORT */
  670. static s32 wl_notifier_change_state(struct bcm_cfg80211 *cfg, struct net_info *_net_info,
  671. enum wl_status state, bool set);
  672. #ifdef CUSTOM_EVENT_PM_WAKE
  673. static s32 wl_check_pmstatus(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev,
  674. const wl_event_msg_t *e, void *data);
  675. #endif /* CUSTOM_EVENT_PM_WAKE */
  676. #if defined(DHD_LOSSLESS_ROAMING) || defined(DBG_PKT_MON)
  677. static s32 wl_notify_roam_prep_status(struct bcm_cfg80211 *cfg,
  678. bcm_struct_cfgdev *cfgdev, const wl_event_msg_t *e, void *data);
  679. #endif /* DHD_LOSSLESS_ROAMING || DBG_PKT_MON */
  680. #ifdef DHD_LOSSLESS_ROAMING
  681. static void wl_del_roam_timeout(struct bcm_cfg80211 *cfg);
  682. #endif /* DHD_LOSSLESS_ROAMING */
  683. #ifdef WL_MBO
  684. static s32
  685. wl_mbo_event_handler(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev,
  686. const wl_event_msg_t *e, void *data);
  687. #endif /* WL_MBO */
  688. static s32
  689. wl_notify_dos_status(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev,
  690. const wl_event_msg_t *e, void *data);
  691. #ifdef WL_SAE
  692. static s32
  693. wl_notify_extauth_req_event(struct bcm_cfg80211 *cfg,
  694. bcm_struct_cfgdev *cfgdev, const wl_event_msg_t *e, void *data);
  695. static s32
  696. wl_notify_mgmt_frame_tx_complete(struct bcm_cfg80211 *cfg,
  697. bcm_struct_cfgdev *cfgdev, const wl_event_msg_t *e, void *data);
  698. #endif /* WL_SAE */
  699. /*
  700. * register/deregister parent device
  701. */
  702. static void wl_cfg80211_clear_parent_dev(void);
  703. /*
  704. * ioctl utilites
  705. */
  706. /*
  707. * cfg80211 set_wiphy_params utilities
  708. */
  709. static s32 wl_set_frag(struct net_device *dev, u32 frag_threshold);
  710. static s32 wl_set_rts(struct net_device *dev, u32 frag_threshold);
  711. static s32 wl_set_retry(struct net_device *dev, u32 retry, bool l);
  712. /*
  713. * cfg profile utilities
  714. */
  715. static s32 wl_update_prof(struct bcm_cfg80211 *cfg, struct net_device *ndev,
  716. const wl_event_msg_t *e, const void *data, s32 item);
  717. static void wl_init_prof(struct bcm_cfg80211 *cfg, struct net_device *ndev);
  718. /*
  719. * cfg80211 connect utilites
  720. */
  721. static s32 wl_set_wpa_version(struct net_device *dev,
  722. struct cfg80211_connect_params *sme);
  723. static s32 wl_set_auth_type(struct net_device *dev,
  724. struct cfg80211_connect_params *sme);
  725. static s32 wl_set_set_cipher(struct net_device *dev,
  726. struct cfg80211_connect_params *sme);
  727. static s32 wl_set_key_mgmt(struct net_device *dev,
  728. struct cfg80211_connect_params *sme);
  729. static s32 wl_set_set_sharedkey(struct net_device *dev,
  730. struct cfg80211_connect_params *sme);
  731. #ifdef WL_FILS
  732. static s32 wl_set_fils_params(struct net_device *dev,
  733. struct cfg80211_connect_params *sme);
  734. #endif // endif
  735. #ifdef BCMWAPI_WPI
  736. static s32 wl_set_set_wapi_ie(struct net_device *dev,
  737. struct cfg80211_connect_params *sme);
  738. #endif // endif
  739. #ifdef WL_GCMP
  740. static s32 wl_set_wsec_info_algos(struct net_device *dev, uint32 algos, uint32 mask);
  741. #endif /* WL_GCMP */
  742. static s32 wl_get_assoc_ies(struct bcm_cfg80211 *cfg, struct net_device *ndev);
  743. static s32 wl_ch_to_chanspec(struct net_device *dev, int ch,
  744. struct wl_join_params *join_params, size_t *join_params_size);
  745. void wl_cfg80211_clear_security(struct bcm_cfg80211 *cfg);
  746. /*
  747. * information element utilities
  748. */
  749. static void wl_rst_ie(struct bcm_cfg80211 *cfg);
  750. static __used s32 wl_add_ie(struct bcm_cfg80211 *cfg, u8 t, u8 l, u8 *v);
  751. static void wl_update_hidden_ap_ie(wl_bss_info_t *bi, const u8 *ie_stream, u32 *ie_size,
  752. bool update_ssid);
  753. static s32 wl_mrg_ie(struct bcm_cfg80211 *cfg, u8 *ie_stream, u16 ie_size);
  754. static s32 wl_cp_ie(struct bcm_cfg80211 *cfg, u8 *dst, u16 dst_size);
  755. static u32 wl_get_ielen(struct bcm_cfg80211 *cfg);
  756. #ifdef MFP
  757. static int wl_cfg80211_get_rsn_capa(const bcm_tlv_t *wpa2ie, const u8** rsn_cap);
  758. #endif // endif
  759. static s32 wl_setup_wiphy(struct wireless_dev *wdev, struct device *dev, void *data);
  760. static void wl_free_wdev(struct bcm_cfg80211 *cfg);
  761. static s32 wl_inform_single_bss(struct bcm_cfg80211 *cfg, wl_bss_info_t *bi, bool update_ssid);
  762. static s32 wl_update_bss_info(struct bcm_cfg80211 *cfg, struct net_device *ndev, bool update_ssid);
  763. static chanspec_t wl_cfg80211_get_shared_freq(struct wiphy *wiphy);
  764. s32 wl_cfg80211_channel_to_freq(u32 channel);
  765. static void wl_cfg80211_work_handler(struct work_struct *work);
  766. static s32 wl_add_keyext(struct wiphy *wiphy, struct net_device *dev,
  767. u8 key_idx, const u8 *mac_addr,
  768. struct key_params *params);
  769. /*
  770. * key indianess swap utilities
  771. */
  772. static void swap_key_from_BE(struct wl_wsec_key *key);
  773. static void swap_key_to_BE(struct wl_wsec_key *key);
  774. /*
  775. * bcm_cfg80211 memory init/deinit utilities
  776. */
  777. static s32 wl_init_priv_mem(struct bcm_cfg80211 *cfg);
  778. static void wl_deinit_priv_mem(struct bcm_cfg80211 *cfg);
  779. static void wl_delay(u32 ms);
  780. /*
  781. * ibss mode utilities
  782. */
  783. static bool wl_is_ibssmode(struct bcm_cfg80211 *cfg, struct net_device *ndev);
  784. static __used bool wl_is_ibssstarter(struct bcm_cfg80211 *cfg);
  785. /*
  786. * link up/down , default configuration utilities
  787. */
  788. static s32 __wl_cfg80211_up(struct bcm_cfg80211 *cfg);
  789. static s32 __wl_cfg80211_down(struct bcm_cfg80211 *cfg);
  790. static bool wl_is_linkdown(struct bcm_cfg80211 *cfg, const wl_event_msg_t *e);
  791. static bool wl_is_linkup(struct bcm_cfg80211 *cfg, const wl_event_msg_t *e,
  792. struct net_device *ndev);
  793. static bool wl_is_nonetwork(struct bcm_cfg80211 *cfg, const wl_event_msg_t *e);
  794. static void wl_link_up(struct bcm_cfg80211 *cfg);
  795. static void wl_link_down(struct bcm_cfg80211 *cfg);
  796. static s32 wl_config_infra(struct bcm_cfg80211 *cfg, struct net_device *ndev, u16 iftype);
  797. static void wl_init_conf(struct wl_conf *conf);
  798. int wl_cfg80211_get_ioctl_version(void);
  799. /*
  800. * find most significant bit set
  801. */
  802. static __used u32 wl_find_msb(u16 bit16);
  803. /*
  804. * rfkill support
  805. */
  806. static int wl_setup_rfkill(struct bcm_cfg80211 *cfg, bool setup);
  807. static int wl_rfkill_set(void *data, bool blocked);
  808. #ifdef DEBUGFS_CFG80211
  809. static s32 wl_setup_debugfs(struct bcm_cfg80211 *cfg);
  810. static s32 wl_free_debugfs(struct bcm_cfg80211 *cfg);
  811. #endif // endif
  812. static bool check_dev_role_integrity(struct bcm_cfg80211 *cfg, s32 mode, u32 dev_role);
  813. #ifdef WL_CFG80211_ACL
  814. /* ACL */
  815. static int wl_cfg80211_set_mac_acl(struct wiphy *wiphy, struct net_device *cfgdev,
  816. const struct cfg80211_acl_data *acl);
  817. #endif /* WL_CFG80211_ACL */
  818. /*
  819. * Some external functions, TODO: move them to dhd_linux.h
  820. */
  821. int dhd_add_monitor(const char *name, struct net_device **new_ndev);
  822. int dhd_del_monitor(struct net_device *ndev);
  823. int dhd_monitor_init(void *dhd_pub);
  824. int dhd_monitor_uninit(void);
  825. int dhd_start_xmit(struct sk_buff *skb, struct net_device *net);
  826. #ifdef ESCAN_CHANNEL_CACHE
  827. void reset_roam_cache(struct bcm_cfg80211 *cfg);
  828. void add_roam_cache(struct bcm_cfg80211 *cfg, wl_bss_info_t *bi);
  829. int get_roam_channel_list(int target_chan, chanspec_t *channels,
  830. int n_channels, const wlc_ssid_t *ssid, int ioctl_ver);
  831. void set_roam_band(int band);
  832. #endif /* ESCAN_CHANNEL_CACHE */
  833. #ifdef ROAM_CHANNEL_CACHE
  834. int init_roam_cache(struct bcm_cfg80211 *cfg, int ioctl_ver);
  835. void print_roam_cache(struct bcm_cfg80211 *cfg);
  836. void update_roam_cache(struct bcm_cfg80211 *cfg, int ioctl_ver);
  837. #endif /* ROAM_CHANNEL_CACHE */
  838. #ifdef P2P_LISTEN_OFFLOADING
  839. s32 wl_cfg80211_p2plo_deinit(struct bcm_cfg80211 *cfg);
  840. #endif /* P2P_LISTEN_OFFLOADING */
  841. #ifdef CUSTOMER_HW4_DEBUG
  842. extern bool wl_scan_timeout_dbg_enabled;
  843. #endif /* CUSTOMER_HW4_DEBUG */
  844. #ifdef PKT_FILTER_SUPPORT
  845. extern uint dhd_pkt_filter_enable;
  846. extern uint dhd_master_mode;
  847. extern void dhd_pktfilter_offload_enable(dhd_pub_t * dhd, char *arg, int enable, int master_mode);
  848. #endif /* PKT_FILTER_SUPPORT */
  849. #ifdef SUPPORT_SET_CAC
  850. static void wl_cfg80211_set_cac(struct bcm_cfg80211 *cfg, int enable);
  851. #endif /* SUPPORT_SET_CAC */
  852. static int wl_cfg80211_delayed_roam(struct bcm_cfg80211 *cfg, struct net_device *ndev,
  853. const struct ether_addr *bssid);
  854. static s32 __wl_update_wiphybands(struct bcm_cfg80211 *cfg, bool notify);
  855. #ifdef WL_WPS_SYNC
  856. static void wl_init_wps_reauth_sm(struct bcm_cfg80211 *cfg);
  857. static void wl_deinit_wps_reauth_sm(struct bcm_cfg80211 *cfg);
  858. static void wl_wps_reauth_timeout(unsigned long data);
  859. static s32 wl_get_free_wps_inst(struct bcm_cfg80211 *cfg);
  860. static s32 wl_get_wps_inst_match(struct bcm_cfg80211 *cfg, struct net_device *ndev);
  861. static s32 wl_wps_session_add(struct net_device *ndev, u16 mode, u8 *peer_mac);
  862. static void wl_wps_session_del(struct net_device *ndev);
  863. static s32 wl_wps_session_update(struct net_device *ndev, u16 state, const u8 *peer_mac);
  864. static void wl_wps_handle_ifdel(struct net_device *ndev);
  865. #endif /* WL_WPS_SYNC */
  866. #if defined(WL_FW_OCE_AP_SELECT)
  867. bool static wl_cfg80211_is_oce_ap(struct wiphy *wiphy, const u8 *bssid_hint);
  868. #endif /* WL_FW_OCE_AP_SELECT */
  869. #ifdef WL_BCNRECV
  870. static s32 wl_bcnrecv_aborted_event_handler(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev,
  871. const wl_event_msg_t *e, void *data);
  872. #endif /* WL_BCNRECV */
  873. #ifdef WL_CAC_TS
  874. static s32 wl_cfg80211_cac_event_handler(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev,
  875. const wl_event_msg_t *e, void *data);
  876. #endif /* WL_CAC_TS */
  877. #if defined(WL_MBO) || defined(WL_OCE)
  878. static s32 wl_bssid_prune_event_handler(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev,
  879. const wl_event_msg_t *e, void *data);
  880. #endif /* WL_MBO || WL_OCE */
  881. static int bw2cap[] = { 0, 0, WLC_BW_CAP_20MHZ, WLC_BW_CAP_40MHZ, WLC_BW_CAP_80MHZ,
  882. WLC_BW_CAP_160MHZ, WLC_BW_CAP_160MHZ };
  883. #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0)) || (defined(CONFIG_ARCH_MSM) && \
  884. defined(CFG80211_DISCONNECTED_V2))
  885. #define CFG80211_GET_BSS(wiphy, channel, bssid, ssid, ssid_len) \
  886. cfg80211_get_bss(wiphy, channel, bssid, ssid, ssid_len, \
  887. IEEE80211_BSS_TYPE_ANY, IEEE80211_PRIVACY_ANY);
  888. #else
  889. #define CFG80211_GET_BSS(wiphy, channel, bssid, ssid, ssid_len) \
  890. cfg80211_get_bss(wiphy, channel, bssid, ssid, ssid_len, \
  891. WLAN_CAPABILITY_ESS, WLAN_CAPABILITY_ESS);
  892. #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0)) */
  893. #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 7, 0))
  894. #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 0)) || \
  895. defined(CFG80211_CONNECT_TIMEOUT_REASON_CODE) || defined(WL_FILS) || \
  896. defined(CONFIG_CFG80211_FILS_BKPORT)
  897. #define CFG80211_CONNECT_RESULT(dev, bssid, bss, req_ie, req_ie_len, resp_ie, \
  898. resp_ie_len, status, gfp) \
  899. cfg80211_connect_bss(dev, bssid, bss, req_ie, req_ie_len, resp_ie, \
  900. resp_ie_len, status, gfp, NL80211_TIMEOUT_UNSPECIFIED);
  901. #else
  902. #define CFG80211_CONNECT_RESULT(dev, bssid, bss, req_ie, req_ie_len, resp_ie, \
  903. resp_ie_len, status, gfp) \
  904. cfg80211_connect_bss(dev, bssid, bss, req_ie, req_ie_len, resp_ie, \
  905. resp_ie_len, status, gfp);
  906. #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 0) || \
  907. * (CFG80211_CONNECT_TIMEOUT_REASON_CODE) ||
  908. * WL_FILS || CONFIG_CFG80211_FILS_BKPORT
  909. */
  910. #elif defined(CFG80211_CONNECT_TIMEOUT_REASON_CODE)
  911. /* There are customer kernels with backported changes for
  912. * connect timeout. CFG80211_CONNECT_TIMEOUT_REASON_CODE define
  913. * is available for kernels < 4.7 in such cases.
  914. */
  915. #define CFG80211_CONNECT_RESULT(dev, bssid, bss, req_ie, req_ie_len, resp_ie, \
  916. resp_ie_len, status, gfp) \
  917. cfg80211_connect_bss(dev, bssid, bss, req_ie, req_ie_len, resp_ie, \
  918. resp_ie_len, status, gfp, NL80211_TIMEOUT_UNSPECIFIED);
  919. #else
  920. /* Kernels < 4.7 doesn't support cfg80211_connect_bss */
  921. #define CFG80211_CONNECT_RESULT(dev, bssid, bss, req_ie, req_ie_len, resp_ie, \
  922. resp_ie_len, status, gfp) \
  923. cfg80211_connect_result(dev, bssid, req_ie, req_ie_len, resp_ie, \
  924. resp_ie_len, status, gfp);
  925. #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(4, 7, 0) */
  926. #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 18, 0))
  927. #define CFG80211_RX_MGMT(ndev, freq, sig_dbm, buf, len, flags, gfp) \
  928. cfg80211_rx_mgmt(ndev_to_wdev(ndev), freq, sig_dbm, buf, len, flags)
  929. #elif ((LINUX_VERSION_CODE >= KERNEL_VERSION(3, 17, 0)) && \
  930. (LINUX_VERSION_CODE < KERNEL_VERSION(3, 18, 0)))
  931. #define CFG80211_RX_MGMT(ndev, freq, sig_dbm, buf, len, flags, gfp) \
  932. cfg80211_rx_mgmt(ndev_to_wdev(ndev), freq, sig_dbm, buf, len, flags, gfp)
  933. #elif ((LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0)) && \
  934. (LINUX_VERSION_CODE < KERNEL_VERSION(3, 17, 0)))
  935. #define CFG80211_RX_MGMT(ndev, freq, sig_dbm, buf, len, flags, gfp) \
  936. cfg80211_rx_mgmt(ndev_to_wdev(ndev), freq, sig_dbm, buf, len, gfp)
  937. #elif ((LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)) && \
  938. (LINUX_VERSION_CODE < KERNEL_VERSION(3, 6, 0))) || \
  939. defined(WL_COMPAT_WIRELESS)
  940. #define CFG80211_RX_MGMT(ndev, freq, sig_dbm, buf, len, flags, gfp) \
  941. cfg80211_rx_mgmt(ndev, freq, sig_dbm, buf, len, gfp)
  942. #elif (LINUX_VERSION_CODE < KERNEL_VERSION(3, 4, 0))
  943. #define CFG80211_RX_MGMT(ndev, freq, sig_dbm, buf, len, flags, gfp) \
  944. cfg80211_rx_mgmt(ndev, freq, buf, len, gfp)
  945. #endif /* (LINUX_VERSION_CODE < KERNEL_VERSION(3, 4, 0)) */
  946. #ifdef RSSI_OFFSET
  947. static s32 wl_rssi_offset(s32 rssi)
  948. {
  949. rssi += RSSI_OFFSET;
  950. if (rssi > 0)
  951. rssi = 0;
  952. return rssi;
  953. }
  954. #else
  955. #define wl_rssi_offset(x) x
  956. #endif // endif
  957. #define IS_WPA_AKM(akm) ((akm) == RSN_AKM_NONE || \
  958. (akm) == RSN_AKM_UNSPECIFIED || \
  959. (akm) == RSN_AKM_PSK)
  960. extern int dhd_wait_pend8021x(struct net_device *dev);
  961. #ifdef PROP_TXSTATUS_VSDB
  962. extern int disable_proptx;
  963. #endif /* PROP_TXSTATUS_VSDB */
  964. static s32
  965. wl_ap_start_ind(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev,
  966. const wl_event_msg_t *e, void *data);
  967. static s32
  968. wl_csa_complete_ind(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev,
  969. const wl_event_msg_t *e, void *data);
  970. #if ((LINUX_VERSION_CODE >= KERNEL_VERSION (3, 5, 0)) && (LINUX_VERSION_CODE <= (3, 7, \
  971. 0)))
  972. struct chan_info {
  973. int freq;
  974. int chan_type;
  975. };
  976. #endif // endif
  977. #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0))
  978. #define CFG80211_PUT_BSS(wiphy, bss) cfg80211_put_bss(wiphy, bss);
  979. #else
  980. #define CFG80211_PUT_BSS(wiphy, bss) cfg80211_put_bss(bss);
  981. #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0) */
  982. #define CHAN2G(_channel, _freq, _flags) { \
  983. .band = IEEE80211_BAND_2GHZ, \
  984. .center_freq = (_freq), \
  985. .hw_value = (_channel), \
  986. .flags = (_flags), \
  987. .max_antenna_gain = 0, \
  988. .max_power = 30, \
  989. }
  990. #define CHAN5G(_channel, _flags) { \
  991. .band = IEEE80211_BAND_5GHZ, \
  992. .center_freq = 5000 + (5 * (_channel)), \
  993. .hw_value = (_channel), \
  994. .flags = (_flags), \
  995. .max_antenna_gain = 0, \
  996. .max_power = 30, \
  997. }
  998. #define RATE_TO_BASE100KBPS(rate) (((rate) * 10) / 2)
  999. #define RATETAB_ENT(_rateid, _flags) \
  1000. { \
  1001. .bitrate = RATE_TO_BASE100KBPS(_rateid), \
  1002. .hw_value = (_rateid), \
  1003. .flags = (_flags), \
  1004. }
  1005. static struct ieee80211_rate __wl_rates[] = {
  1006. RATETAB_ENT(DOT11_RATE_1M, 0),
  1007. RATETAB_ENT(DOT11_RATE_2M, IEEE80211_RATE_SHORT_PREAMBLE),
  1008. RATETAB_ENT(DOT11_RATE_5M5, IEEE80211_RATE_SHORT_PREAMBLE),
  1009. RATETAB_ENT(DOT11_RATE_11M, IEEE80211_RATE_SHORT_PREAMBLE),
  1010. RATETAB_ENT(DOT11_RATE_6M, 0),
  1011. RATETAB_ENT(DOT11_RATE_9M, 0),
  1012. RATETAB_ENT(DOT11_RATE_12M, 0),
  1013. RATETAB_ENT(DOT11_RATE_18M, 0),
  1014. RATETAB_ENT(DOT11_RATE_24M, 0),
  1015. RATETAB_ENT(DOT11_RATE_36M, 0),
  1016. RATETAB_ENT(DOT11_RATE_48M, 0),
  1017. RATETAB_ENT(DOT11_RATE_54M, 0)
  1018. };
  1019. #define wl_a_rates (__wl_rates + 4)
  1020. #define wl_a_rates_size 8
  1021. #define wl_g_rates (__wl_rates + 0)
  1022. #define wl_g_rates_size 12
  1023. static struct ieee80211_channel __wl_2ghz_channels[] = {
  1024. CHAN2G(1, 2412, 0),
  1025. CHAN2G(2, 2417, 0),
  1026. CHAN2G(3, 2422, 0),
  1027. CHAN2G(4, 2427, 0),
  1028. CHAN2G(5, 2432, 0),
  1029. CHAN2G(6, 2437, 0),
  1030. CHAN2G(7, 2442, 0),
  1031. CHAN2G(8, 2447, 0),
  1032. CHAN2G(9, 2452, 0),
  1033. CHAN2G(10, 2457, 0),
  1034. CHAN2G(11, 2462, 0),
  1035. CHAN2G(12, 2467, 0),
  1036. CHAN2G(13, 2472, 0),
  1037. CHAN2G(14, 2484, 0)
  1038. };
  1039. static struct ieee80211_channel __wl_5ghz_a_channels[] = {
  1040. CHAN5G(34, 0), CHAN5G(36, 0),
  1041. CHAN5G(38, 0), CHAN5G(40, 0),
  1042. CHAN5G(42, 0), CHAN5G(44, 0),
  1043. CHAN5G(46, 0), CHAN5G(48, 0),
  1044. CHAN5G(52, 0), CHAN5G(56, 0),
  1045. CHAN5G(60, 0), CHAN5G(64, 0),
  1046. CHAN5G(100, 0), CHAN5G(104, 0),
  1047. CHAN5G(108, 0), CHAN5G(112, 0),
  1048. CHAN5G(116, 0), CHAN5G(120, 0),
  1049. CHAN5G(124, 0), CHAN5G(128, 0),
  1050. CHAN5G(132, 0), CHAN5G(136, 0),
  1051. CHAN5G(140, 0), CHAN5G(144, 0),
  1052. CHAN5G(149, 0), CHAN5G(153, 0),
  1053. CHAN5G(157, 0), CHAN5G(161, 0),
  1054. CHAN5G(165, 0)
  1055. };
  1056. static struct ieee80211_supported_band __wl_band_2ghz = {
  1057. .band = IEEE80211_BAND_2GHZ,
  1058. .channels = __wl_2ghz_channels,
  1059. .n_channels = ARRAY_SIZE(__wl_2ghz_channels),
  1060. .bitrates = wl_g_rates,
  1061. .n_bitrates = wl_g_rates_size
  1062. };
  1063. static struct ieee80211_supported_band __wl_band_5ghz_a = {
  1064. .band = IEEE80211_BAND_5GHZ,
  1065. .channels = __wl_5ghz_a_channels,
  1066. .n_channels = ARRAY_SIZE(__wl_5ghz_a_channels),
  1067. .bitrates = wl_a_rates,
  1068. .n_bitrates = wl_a_rates_size
  1069. };
  1070. static const u32 __wl_cipher_suites[] = {
  1071. WLAN_CIPHER_SUITE_WEP40,
  1072. WLAN_CIPHER_SUITE_WEP104,
  1073. WLAN_CIPHER_SUITE_TKIP,
  1074. WLAN_CIPHER_SUITE_CCMP,
  1075. #ifdef MFP
  1076. /*
  1077. * Advertising AES_CMAC cipher suite to userspace would imply that we
  1078. * are supporting MFP. So advertise only when MFP support is enabled.
  1079. */
  1080. WLAN_CIPHER_SUITE_AES_CMAC,
  1081. #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 0, 0))
  1082. WLAN_CIPHER_SUITE_BIP_GMAC_256,
  1083. WLAN_CIPHER_SUITE_BIP_GMAC_128,
  1084. WLAN_CIPHER_SUITE_BIP_CMAC_256,
  1085. #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(4, 0, 0) */
  1086. #endif /* MFP */
  1087. #ifdef BCMWAPI_WPI
  1088. WLAN_CIPHER_SUITE_SMS4,
  1089. #endif // endif
  1090. #if defined(WLAN_CIPHER_SUITE_PMK)
  1091. WLAN_CIPHER_SUITE_PMK,
  1092. #endif /* WLAN_CIPHER_SUITE_PMK */
  1093. #ifdef WL_GCMP
  1094. WLAN_CIPHER_SUITE_GCMP,
  1095. WLAN_CIPHER_SUITE_GCMP_256,
  1096. WLAN_CIPHER_SUITE_BIP_GMAC_128,
  1097. WLAN_CIPHER_SUITE_BIP_GMAC_256,
  1098. #endif /* WL_GCMP */
  1099. };
  1100. #ifdef WL_SUPPORT_ACS
  1101. /*
  1102. * The firmware code required for this feature to work is currently under
  1103. * BCMINTERNAL flag. In future if this is to enabled we need to bring the
  1104. * required firmware code out of the BCMINTERNAL flag.
  1105. */
  1106. struct wl_dump_survey {
  1107. u32 obss;
  1108. u32 ibss;
  1109. u32 no_ctg;
  1110. u32 no_pckt;
  1111. u32 tx;
  1112. u32 idle;
  1113. };
  1114. #endif /* WL_SUPPORT_ACS */
  1115. #ifdef WL_CFG80211_GON_COLLISION
  1116. #define BLOCK_GON_REQ_MAX_NUM 5
  1117. #endif /* WL_CFG80211_GON_COLLISION */
  1118. #if defined(USE_DYNAMIC_MAXPKT_RXGLOM)
  1119. static int maxrxpktglom = 0;
  1120. #endif // endif
  1121. /* IOCtl version read from targeted driver */
  1122. int ioctl_version;
  1123. #ifdef DEBUGFS_CFG80211
  1124. #define SUBLOGLEVEL 20
  1125. #define SUBLOGLEVELZ ((SUBLOGLEVEL) + (1))
  1126. static const struct {
  1127. u32 log_level;
  1128. char *sublogname;
  1129. } sublogname_map[] = {
  1130. {WL_DBG_ERR, "ERR"},
  1131. {WL_DBG_INFO, "INFO"},
  1132. {WL_DBG_DBG, "DBG"},
  1133. {WL_DBG_SCAN, "SCAN"},
  1134. {WL_DBG_TRACE, "TRACE"},
  1135. {WL_DBG_P2P_ACTION, "P2PACTION"}
  1136. };
  1137. #endif // endif
  1138. typedef struct rsn_cipher_algo_entry {
  1139. u32 cipher_suite;
  1140. u32 wsec_algo;
  1141. u32 wsec_key_algo;
  1142. } rsn_cipher_algo_entry_t;
  1143. static const rsn_cipher_algo_entry_t rsn_cipher_algo_lookup_tbl[] = {
  1144. {WLAN_CIPHER_SUITE_WEP40, WEP_ENABLED, CRYPTO_ALGO_WEP1},
  1145. {WLAN_CIPHER_SUITE_WEP104, WEP_ENABLED, CRYPTO_ALGO_WEP128},
  1146. {WLAN_CIPHER_SUITE_TKIP, TKIP_ENABLED, CRYPTO_ALGO_TKIP},
  1147. {WLAN_CIPHER_SUITE_CCMP, AES_ENABLED, CRYPTO_ALGO_AES_CCM},
  1148. {WLAN_CIPHER_SUITE_AES_CMAC, AES_ENABLED, CRYPTO_ALGO_BIP},
  1149. #ifdef BCMWAPI_WPI
  1150. {WLAN_CIPHER_SUITE_SMS4, SMS4_ENABLED, CRYPTO_ALGO_SMS4},
  1151. #endif /* BCMWAPI_WPI */
  1152. #ifdef WL_GCMP
  1153. {WLAN_CIPHER_SUITE_GCMP, AES_ENABLED, CRYPTO_ALGO_AES_GCM},
  1154. {WLAN_CIPHER_SUITE_GCMP_256, AES_ENABLED, CRYPTO_ALGO_AES_GCM256},
  1155. {WLAN_CIPHER_SUITE_BIP_GMAC_128, AES_ENABLED, CRYPTO_ALGO_BIP_GMAC},
  1156. {WLAN_CIPHER_SUITE_BIP_GMAC_256, AES_ENABLED, CRYPTO_ALGO_BIP_GMAC256},
  1157. #endif /* WL_GCMP */
  1158. #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 0, 0))
  1159. {WLAN_CIPHER_SUITE_BIP_CMAC_256, AES_ENABLED, CRYPTO_ALGO_BIP_CMAC256},
  1160. #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(4, 0, 0) */
  1161. };
  1162. typedef struct rsn_akm_wpa_auth_entry {
  1163. u32 akm_suite;
  1164. u32 wpa_auth;
  1165. } rsn_akm_wpa_auth_entry_t;
  1166. static const rsn_akm_wpa_auth_entry_t rsn_akm_wpa_auth_lookup_tbl[] = {
  1167. #ifdef WL_OWE
  1168. {WLAN_AKM_SUITE_OWE, WPA3_AUTH_OWE},
  1169. #endif /* WL_OWE */
  1170. {WLAN_AKM_SUITE_8021X, WPA2_AUTH_UNSPECIFIED},
  1171. {WL_AKM_SUITE_SHA256_1X, WPA2_AUTH_1X_SHA256},
  1172. {WL_AKM_SUITE_SHA256_PSK, WPA2_AUTH_PSK_SHA256},
  1173. {WLAN_AKM_SUITE_PSK, WPA2_AUTH_PSK},
  1174. {WLAN_AKM_SUITE_FT_8021X, WPA2_AUTH_UNSPECIFIED | WPA2_AUTH_FT},
  1175. {WLAN_AKM_SUITE_FT_PSK, WPA2_AUTH_PSK | WPA2_AUTH_FT},
  1176. {WLAN_AKM_SUITE_FILS_SHA256, WPA2_AUTH_FILS_SHA256},
  1177. {WLAN_AKM_SUITE_FILS_SHA384, WPA2_AUTH_FILS_SHA384},
  1178. {WLAN_AKM_SUITE_8021X_SUITE_B, WPA3_AUTH_1X_SUITE_B_SHA256},
  1179. {WLAN_AKM_SUITE_8021X_SUITE_B_192, WPA3_AUTH_1X_SUITE_B_SHA384},
  1180. #ifdef BCMWAPI_WPI
  1181. {WLAN_AKM_SUITE_WAPI_CERT, WAPI_AUTH_UNSPECIFIED},
  1182. {WLAN_AKM_SUITE_WAPI_PSK, WAPI_AUTH_PSK},
  1183. #endif /* BCMWAPI_WPI */
  1184. #ifdef WL_SAE
  1185. {WLAN_AKM_SUITE_SAE, WPA3_AUTH_SAE_PSK},
  1186. #endif /* WL_SAE */
  1187. {WLAN_AKM_SUITE_FT_8021X_SHA384, WPA3_AUTH_1X_SHA384 | WPA2_AUTH_FT},
  1188. {WLAN_AKM_SUITE_DPP, WFA_AUTH_DPP}
  1189. };
  1190. #define BUFSZ 8
  1191. #define BUFSZN BUFSZ + 1
  1192. #define _S(x) #x
  1193. #define S(x) _S(x)
  1194. #define SOFT_AP_IF_NAME "swlan0"
  1195. /* watchdog timer for disconnecting when fw is not associated for FW_ASSOC_WATCHDOG_TIME ms */
  1196. uint32 fw_assoc_watchdog_ms = 0;
  1197. bool fw_assoc_watchdog_started = 0;
  1198. #define FW_ASSOC_WATCHDOG_TIME 10 * 1000 /* msec */
  1199. static void wl_add_remove_pm_enable_work(struct bcm_cfg80211 *cfg,
  1200. enum wl_pm_workq_act_type type)
  1201. {
  1202. u16 wq_duration = 0;
  1203. #if defined(OEM_ANDROID)
  1204. dhd_pub_t *dhd = NULL;
  1205. #endif /* BCMDONGLEHOST && OEM_ANDROID */
  1206. if (cfg == NULL)
  1207. return;
  1208. #if defined(OEM_ANDROID)
  1209. dhd = (dhd_pub_t *)(cfg->pub);
  1210. #endif /* BCMDONGLEHOST && OEM_ANDROID */
  1211. mutex_lock(&cfg->pm_sync);
  1212. /*
  1213. * Make cancel and schedule work part mutually exclusive
  1214. * so that while cancelling, we are sure that there is no
  1215. * work getting scheduled.
  1216. */
  1217. if (delayed_work_pending(&cfg->pm_enable_work)) {
  1218. cancel_delayed_work(&cfg->pm_enable_work);
  1219. #if defined(OEM_ANDROID)
  1220. DHD_PM_WAKE_UNLOCK(cfg->pub);
  1221. #endif /* BCMDONGLEHOST && OEM_ANDROID */
  1222. }
  1223. if (type == WL_PM_WORKQ_SHORT) {
  1224. wq_duration = WL_PM_ENABLE_TIMEOUT;
  1225. } else if (type == WL_PM_WORKQ_LONG) {
  1226. wq_duration = (WL_PM_ENABLE_TIMEOUT*2);
  1227. }
  1228. /* It should schedule work item only if driver is up */
  1229. #if defined(OEM_ANDROID)
  1230. if (wq_duration && dhd->up) {
  1231. #else
  1232. if (wq_duration) {
  1233. #endif /* BCMDONGLEHOST && OEM_ANDROID */
  1234. if (schedule_delayed_work(&cfg->pm_enable_work,
  1235. msecs_to_jiffies((const unsigned int)wq_duration))) {
  1236. #if defined(OEM_ANDROID)
  1237. DHD_PM_WAKE_LOCK_TIMEOUT(cfg->pub, wq_duration);
  1238. #endif /* BCMDONGLEHOST && OEM_ANDROID */
  1239. } else {
  1240. WL_ERR(("Can't schedule pm work handler\n"));
  1241. }
  1242. }
  1243. mutex_unlock(&cfg->pm_sync);
  1244. }
  1245. /* Return a new chanspec given a legacy chanspec
  1246. * Returns INVCHANSPEC on error
  1247. */
  1248. chanspec_t
  1249. wl_chspec_from_legacy(chanspec_t legacy_chspec)
  1250. {
  1251. chanspec_t chspec;
  1252. /* get the channel number */
  1253. chspec = LCHSPEC_CHANNEL(legacy_chspec);
  1254. /* convert the band */
  1255. if (LCHSPEC_IS2G(legacy_chspec)) {
  1256. chspec |= WL_CHANSPEC_BAND_2G;
  1257. } else {
  1258. chspec |= WL_CHANSPEC_BAND_5G;
  1259. }
  1260. /* convert the bw and sideband */
  1261. if (LCHSPEC_IS20(legacy_chspec)) {
  1262. chspec |= WL_CHANSPEC_BW_20;
  1263. } else {
  1264. chspec |= WL_CHANSPEC_BW_40;
  1265. if (LCHSPEC_CTL_SB(legacy_chspec) == WL_LCHANSPEC_CTL_SB_LOWER) {
  1266. chspec |= WL_CHANSPEC_CTL_SB_L;
  1267. } else {
  1268. chspec |= WL_CHANSPEC_CTL_SB_U;
  1269. }
  1270. }
  1271. if (wf_chspec_malformed(chspec)) {
  1272. WL_ERR(("wl_chspec_from_legacy: output chanspec (0x%04X) malformed\n",
  1273. chspec));
  1274. return INVCHANSPEC;
  1275. }
  1276. return chspec;
  1277. }
  1278. /* Return a legacy chanspec given a new chanspec
  1279. * Returns INVCHANSPEC on error
  1280. */
  1281. static chanspec_t
  1282. wl_chspec_to_legacy(chanspec_t chspec)
  1283. {
  1284. chanspec_t lchspec;
  1285. if (wf_chspec_malformed(chspec)) {
  1286. WL_ERR(("wl_chspec_to_legacy: input chanspec (0x%04X) malformed\n",
  1287. chspec));
  1288. return INVCHANSPEC;
  1289. }
  1290. /* get the channel number */
  1291. lchspec = CHSPEC_CHANNEL(chspec);
  1292. /* convert the band */
  1293. if (CHSPEC_IS2G(chspec)) {
  1294. lchspec |= WL_LCHANSPEC_BAND_2G;
  1295. } else {
  1296. lchspec |= WL_LCHANSPEC_BAND_5G;
  1297. }
  1298. /* convert the bw and sideband */
  1299. if (CHSPEC_IS20(chspec)) {
  1300. lchspec |= WL_LCHANSPEC_BW_20;
  1301. lchspec |= WL_LCHANSPEC_CTL_SB_NONE;
  1302. } else if (CHSPEC_IS40(chspec)) {
  1303. lchspec |= WL_LCHANSPEC_BW_40;
  1304. if (CHSPEC_CTL_SB(chspec) == WL_CHANSPEC_CTL_SB_L) {
  1305. lchspec |= WL_LCHANSPEC_CTL_SB_LOWER;
  1306. } else {
  1307. lchspec |= WL_LCHANSPEC_CTL_SB_UPPER;
  1308. }
  1309. } else {
  1310. /* cannot express the bandwidth */
  1311. char chanbuf[CHANSPEC_STR_LEN];
  1312. WL_ERR((
  1313. "wl_chspec_to_legacy: unable to convert chanspec %s (0x%04X) "
  1314. "to pre-11ac format\n",
  1315. wf_chspec_ntoa(chspec, chanbuf), chspec));
  1316. return INVCHANSPEC;
  1317. }
  1318. return lchspec;
  1319. }
  1320. bool wl_cfg80211_is_hal_started(struct bcm_cfg80211 *cfg)
  1321. {
  1322. return cfg->hal_started;
  1323. }
  1324. /* given a chanspec value, do the endian and chanspec version conversion to
  1325. * a chanspec_t value
  1326. * Returns INVCHANSPEC on error
  1327. */
  1328. chanspec_t
  1329. wl_chspec_host_to_driver(chanspec_t chanspec)
  1330. {
  1331. if (ioctl_version == 1) {
  1332. chanspec = wl_chspec_to_legacy(chanspec);
  1333. if (chanspec == INVCHANSPEC) {
  1334. return chanspec;
  1335. }
  1336. }
  1337. chanspec = htodchanspec(chanspec);
  1338. return chanspec;
  1339. }
  1340. /* given a channel value, do the endian and chanspec version conversion to
  1341. * a chanspec_t value
  1342. * Returns INVCHANSPEC on error
  1343. */
  1344. chanspec_t
  1345. wl_ch_host_to_driver(u16 channel)
  1346. {
  1347. chanspec_t chanspec;
  1348. chanspec_band_t band;
  1349. band = WL_CHANNEL_BAND(channel);
  1350. chanspec = wf_create_20MHz_chspec(channel, band);
  1351. if (chanspec == INVCHANSPEC) {
  1352. return chanspec;
  1353. }
  1354. return wl_chspec_host_to_driver(chanspec);
  1355. }
  1356. /* given a chanspec value from the driver, do the endian and chanspec version conversion to
  1357. * a chanspec_t value
  1358. * Returns INVCHANSPEC on error
  1359. */
  1360. chanspec_t
  1361. wl_chspec_driver_to_host(chanspec_t chanspec)
  1362. {
  1363. chanspec = dtohchanspec(chanspec);
  1364. if (ioctl_version == 1) {
  1365. chanspec = wl_chspec_from_legacy(chanspec);
  1366. }
  1367. return chanspec;
  1368. }
  1369. /*
  1370. * convert ASCII string to MAC address (colon-delimited format)
  1371. * eg: 00:11:22:33:44:55
  1372. */
  1373. int
  1374. wl_cfg80211_ether_atoe(const char *a, struct ether_addr *n)
  1375. {
  1376. char *c = NULL;
  1377. int count = 0;
  1378. bzero(n, ETHER_ADDR_LEN);
  1379. for (;;) {
  1380. n->octet[count++] = (uint8)simple_strtoul(a, &c, 16);
  1381. if (!*c++ || count == ETHER_ADDR_LEN)
  1382. break;
  1383. a = c;
  1384. }
  1385. return (count == ETHER_ADDR_LEN);
  1386. }
  1387. /* There isn't a lot of sense in it, but you can transmit anything you like */
  1388. static const struct ieee80211_txrx_stypes
  1389. wl_cfg80211_default_mgmt_stypes[NUM_NL80211_IFTYPES] = {
  1390. [NL80211_IFTYPE_ADHOC] = {
  1391. .tx = 0xffff,
  1392. .rx = BIT(IEEE80211_STYPE_ACTION >> 4)
  1393. },
  1394. [NL80211_IFTYPE_STATION] = {
  1395. .tx = 0xffff,
  1396. .rx = BIT(IEEE80211_STYPE_ACTION >> 4) |
  1397. #ifdef WL_SAE
  1398. BIT(IEEE80211_STYPE_AUTH >> 4) |
  1399. #endif /* WL_SAE */
  1400. BIT(IEEE80211_STYPE_PROBE_REQ >> 4)
  1401. },
  1402. [NL80211_IFTYPE_AP] = {
  1403. .tx = 0xffff,
  1404. .rx = BIT(IEEE80211_STYPE_ASSOC_REQ >> 4) |
  1405. BIT(IEEE80211_STYPE_REASSOC_REQ >> 4) |
  1406. BIT(IEEE80211_STYPE_PROBE_REQ >> 4) |
  1407. BIT(IEEE80211_STYPE_DISASSOC >> 4) |
  1408. BIT(IEEE80211_STYPE_AUTH >> 4) |
  1409. BIT(IEEE80211_STYPE_DEAUTH >> 4) |
  1410. BIT(IEEE80211_STYPE_ACTION >> 4)
  1411. },
  1412. [NL80211_IFTYPE_AP_VLAN] = {
  1413. /* copy AP */
  1414. .tx = 0xffff,
  1415. .rx = BIT(IEEE80211_STYPE_ASSOC_REQ >> 4) |
  1416. BIT(IEEE80211_STYPE_REASSOC_REQ >> 4) |
  1417. BIT(IEEE80211_STYPE_PROBE_REQ >> 4) |
  1418. BIT(IEEE80211_STYPE_DISASSOC >> 4) |
  1419. BIT(IEEE80211_STYPE_AUTH >> 4) |
  1420. BIT(IEEE80211_STYPE_DEAUTH >> 4) |
  1421. BIT(IEEE80211_STYPE_ACTION >> 4)
  1422. },
  1423. [NL80211_IFTYPE_P2P_CLIENT] = {
  1424. .tx = 0xffff,
  1425. .rx = BIT(IEEE80211_STYPE_ACTION >> 4) |
  1426. BIT(IEEE80211_STYPE_PROBE_REQ >> 4)
  1427. },
  1428. [NL80211_IFTYPE_P2P_GO] = {
  1429. .tx = 0xffff,
  1430. .rx = BIT(IEEE80211_STYPE_ASSOC_REQ >> 4) |
  1431. BIT(IEEE80211_STYPE_REASSOC_REQ >> 4) |
  1432. BIT(IEEE80211_STYPE_PROBE_REQ >> 4) |
  1433. BIT(IEEE80211_STYPE_DISASSOC >> 4) |
  1434. BIT(IEEE80211_STYPE_AUTH >> 4) |
  1435. BIT(IEEE80211_STYPE_DEAUTH >> 4) |
  1436. BIT(IEEE80211_STYPE_ACTION >> 4)
  1437. },
  1438. #if defined(WL_CFG80211_P2P_DEV_IF)
  1439. [NL80211_IFTYPE_P2P_DEVICE] = {
  1440. .tx = 0xffff,
  1441. .rx = BIT(IEEE80211_STYPE_ACTION >> 4) |
  1442. BIT(IEEE80211_STYPE_PROBE_REQ >> 4)
  1443. },
  1444. #endif /* WL_CFG80211_P2P_DEV_IF */
  1445. };
  1446. static void swap_key_from_BE(struct wl_wsec_key *key)
  1447. {
  1448. key->index = htod32(key->index);
  1449. key->len = htod32(key->len);
  1450. key->algo = htod32(key->algo);
  1451. key->flags = htod32(key->flags);
  1452. key->rxiv.hi = htod32(key->rxiv.hi);
  1453. key->rxiv.lo = htod16(key->rxiv.lo);
  1454. key->iv_initialized = htod32(key->iv_initialized);
  1455. }
  1456. static void swap_key_to_BE(struct wl_wsec_key *key)
  1457. {
  1458. key->index = dtoh32(key->index);
  1459. key->len = dtoh32(key->len);
  1460. key->algo = dtoh32(key->algo);
  1461. key->flags = dtoh32(key->flags);
  1462. key->rxiv.hi = dtoh32(key->rxiv.hi);
  1463. key->rxiv.lo = dtoh16(key->rxiv.lo);
  1464. key->iv_initialized = dtoh32(key->iv_initialized);
  1465. }
  1466. #if defined(WL_FW_OCE_AP_SELECT)
  1467. bool static wl_cfg80211_is_oce_ap(struct wiphy *wiphy, const u8 *bssid_hint)
  1468. {
  1469. const u8 *parse = NULL;
  1470. bcm_tlv_t *ie;
  1471. const struct cfg80211_bss_ies *ies;
  1472. u32 len;
  1473. struct cfg80211_bss *bss;
  1474. bss = CFG80211_GET_BSS(wiphy, NULL, bssid_hint, 0, 0);
  1475. if (!bss) {
  1476. WL_ERR(("Unable to find AP in the cache"));
  1477. return false;
  1478. }
  1479. if (rcu_access_pointer(bss->ies)) {
  1480. ies = rcu_access_pointer(bss->ies);
  1481. parse = ies->data;
  1482. len = ies->len;
  1483. } else {
  1484. WL_ERR(("ies is NULL"));
  1485. return false;
  1486. }
  1487. while ((ie = bcm_parse_tlvs(parse, len, DOT11_MNG_VS_ID))) {
  1488. if (wl_cfgoce_is_oce_ie((const uint8*)ie, (u8 const **)&parse, &len) == TRUE) {
  1489. return true;
  1490. } else {
  1491. ie = bcm_next_tlv((const bcm_tlv_t*) ie, &len);
  1492. if (!ie) {
  1493. return false;
  1494. }
  1495. parse = (uint8 *)ie;
  1496. WL_DBG(("NON OCE IE. next ie ptr:%p", parse));
  1497. }
  1498. }
  1499. WL_DBG(("OCE IE NOT found"));
  1500. return false;
  1501. }
  1502. #endif /* WL_FW_OCE_AP_SELECT */
  1503. /* Dump the contents of the encoded wps ie buffer and get pbc value */
  1504. static void
  1505. wl_validate_wps_ie(const char *wps_ie, s32 wps_ie_len, bool *pbc)
  1506. {
  1507. #define WPS_IE_FIXED_LEN 6
  1508. s16 len;
  1509. const u8 *subel = NULL;
  1510. u16 subelt_id;
  1511. u16 subelt_len;
  1512. u16 val;
  1513. u8 *valptr = (uint8*) &val;
  1514. if (wps_ie == NULL || wps_ie_len < WPS_IE_FIXED_LEN) {
  1515. WL_ERR(("invalid argument : NULL\n"));
  1516. return;
  1517. }
  1518. len = (s16)wps_ie[TLV_LEN_OFF];
  1519. if (len > wps_ie_len) {
  1520. WL_ERR(("invalid length len %d, wps ie len %d\n", len, wps_ie_len));
  1521. return;
  1522. }
  1523. WL_DBG(("wps_ie len=%d\n", len));
  1524. len -= 4; /* for the WPS IE's OUI, oui_type fields */
  1525. subel = wps_ie + WPS_IE_FIXED_LEN;
  1526. while (len >= 4) { /* must have attr id, attr len fields */
  1527. valptr[0] = *subel++;
  1528. valptr[1] = *subel++;
  1529. subelt_id = HTON16(val);
  1530. valptr[0] = *subel++;
  1531. valptr[1] = *subel++;
  1532. subelt_len = HTON16(val);
  1533. len -= 4; /* for the attr id, attr len fields */
  1534. len -= (s16)subelt_len; /* for the remaining fields in this attribute */
  1535. if (len < 0) {
  1536. break;
  1537. }
  1538. WL_DBG((" subel=%p, subelt_id=0x%x subelt_len=%u\n",
  1539. subel, subelt_id, subelt_len));
  1540. if (subelt_id == WPS_ID_VERSION) {
  1541. WL_DBG((" attr WPS_ID_VERSION: %u\n", *subel));
  1542. } else if (subelt_id == WPS_ID_REQ_TYPE) {
  1543. WL_DBG((" attr WPS_ID_REQ_TYPE: %u\n", *subel));
  1544. } else if (subelt_id == WPS_ID_CONFIG_METHODS) {
  1545. valptr[0] = *subel;
  1546. valptr[1] = *(subel + 1);
  1547. WL_DBG((" attr WPS_ID_CONFIG_METHODS: %x\n", HTON16(val)));
  1548. } else if (subelt_id == WPS_ID_DEVICE_NAME) {
  1549. char devname[33];
  1550. int namelen = MIN(subelt_len, (sizeof(devname) - 1));
  1551. if (namelen) {
  1552. memcpy(devname, subel, namelen);
  1553. devname[namelen] = '\0';
  1554. /* Printing len as rx'ed in the IE */
  1555. WL_DBG((" attr WPS_ID_DEVICE_NAME: %s (len %u)\n",
  1556. devname, subelt_len));
  1557. }
  1558. } else if (subelt_id == WPS_ID_DEVICE_PWD_ID) {
  1559. valptr[0] = *subel;
  1560. valptr[1] = *(subel + 1);
  1561. WL_DBG((" attr WPS_ID_DEVICE_PWD_ID: %u\n", HTON16(val)));
  1562. *pbc = (HTON16(val) == DEV_PW_PUSHBUTTON) ? true : false;
  1563. } else if (subelt_id == WPS_ID_PRIM_DEV_TYPE) {
  1564. valptr[0] = *subel;
  1565. valptr[1] = *(subel + 1);
  1566. WL_DBG((" attr WPS_ID_PRIM_DEV_TYPE: cat=%u \n", HTON16(val)));
  1567. valptr[0] = *(subel + 6);
  1568. valptr[1] = *(subel + 7);
  1569. WL_DBG((" attr WPS_ID_PRIM_DEV_TYPE: subcat=%u\n", HTON16(val)));
  1570. } else if (subelt_id == WPS_ID_REQ_DEV_TYPE) {
  1571. valptr[0] = *subel;
  1572. valptr[1] = *(subel + 1);
  1573. WL_DBG((" attr WPS_ID_REQ_DEV_TYPE: cat=%u\n", HTON16(val)));
  1574. valptr[0] = *(subel + 6);
  1575. valptr[1] = *(subel + 7);
  1576. WL_DBG((" attr WPS_ID_REQ_DEV_TYPE: subcat=%u\n", HTON16(val)));
  1577. } else if (subelt_id == WPS_ID_SELECTED_REGISTRAR_CONFIG_METHODS) {
  1578. valptr[0] = *subel;
  1579. valptr[1] = *(subel + 1);
  1580. WL_DBG((" attr WPS_ID_SELECTED_REGISTRAR_CONFIG_METHODS"
  1581. ": cat=%u\n", HTON16(val)));
  1582. } else {
  1583. WL_DBG((" unknown attr 0x%x\n", subelt_id));
  1584. }
  1585. subel += subelt_len;
  1586. }
  1587. }
  1588. s32 wl_set_tx_power(struct net_device *dev,
  1589. enum nl80211_tx_power_setting type, s32 dbm)
  1590. {
  1591. s32 err = 0;
  1592. s32 disable = 0;
  1593. s32 txpwrqdbm;
  1594. struct bcm_cfg80211 *cfg = wl_get_cfg(dev);
  1595. /* Make sure radio is off or on as far as software is concerned */
  1596. disable = WL_RADIO_SW_DISABLE << 16;
  1597. disable = htod32(disable);
  1598. err = wldev_ioctl_set(dev, WLC_SET_RADIO, &disable, sizeof(disable));
  1599. if (unlikely(err)) {
  1600. WL_ERR(("WLC_SET_RADIO error (%d)\n", err));
  1601. return err;
  1602. }
  1603. if (dbm > 0xffff)
  1604. dbm = 0xffff;
  1605. txpwrqdbm = dbm * 4;
  1606. #ifdef SUPPORT_WL_TXPOWER
  1607. if (type == NL80211_TX_POWER_AUTOMATIC)
  1608. txpwrqdbm = 127;
  1609. else
  1610. txpwrqdbm |= WL_TXPWR_OVERRIDE;
  1611. #endif /* SUPPORT_WL_TXPOWER */
  1612. err = wldev_iovar_setbuf_bsscfg(dev, "qtxpower", (void *)&txpwrqdbm,
  1613. sizeof(txpwrqdbm), cfg->ioctl_buf, WLC_IOCTL_SMLEN, 0,
  1614. &cfg->ioctl_buf_sync);
  1615. if (unlikely(err))
  1616. WL_ERR(("qtxpower error (%d)\n", err));
  1617. else
  1618. WL_ERR(("dBm=%d, txpwrqdbm=0x%x\n", dbm, txpwrqdbm));
  1619. return err;
  1620. }
  1621. s32 wl_get_tx_power(struct net_device *dev, s32 *dbm)
  1622. {
  1623. s32 err = 0;
  1624. s32 txpwrdbm;
  1625. char ioctl_buf[WLC_IOCTL_SMLEN];
  1626. err = wldev_iovar_getbuf_bsscfg(dev, "qtxpower",
  1627. NULL, 0, ioctl_buf, WLC_IOCTL_SMLEN, 0, NULL);
  1628. if (unlikely(err)) {
  1629. WL_ERR(("error (%d)\n", err));
  1630. return err;
  1631. }
  1632. memcpy(&txpwrdbm, ioctl_buf, sizeof(txpwrdbm));
  1633. txpwrdbm = dtoh32(txpwrdbm);
  1634. *dbm = (txpwrdbm & ~WL_TXPWR_OVERRIDE) / 4;
  1635. WL_DBG(("dBm=%d, txpwrdbm=0x%x\n", *dbm, txpwrdbm));
  1636. return err;
  1637. }
  1638. static chanspec_t wl_cfg80211_get_shared_freq(struct wiphy *wiphy)
  1639. {
  1640. chanspec_t chspec;
  1641. int cur_band, err = 0;
  1642. struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
  1643. struct net_device *dev = bcmcfg_to_prmry_ndev(cfg);
  1644. struct ether_addr bssid;
  1645. wl_bss_info_t *bss = NULL;
  1646. u16 channel = WL_P2P_TEMP_CHAN;
  1647. char *buf;
  1648. bzero(&bssid, sizeof(bssid));
  1649. if ((err = wldev_ioctl_get(dev, WLC_GET_BSSID, &bssid, sizeof(bssid)))) {
  1650. /* STA interface is not associated. So start the new interface on a temp
  1651. * channel . Later proper channel will be applied by the above framework
  1652. * via set_channel (cfg80211 API).
  1653. */
  1654. WL_DBG(("Not associated. Return a temp channel. \n"));
  1655. cur_band = 0;
  1656. err = wldev_ioctl_get(dev, WLC_GET_BAND, &cur_band, sizeof(int));
  1657. if (unlikely(err)) {
  1658. WL_ERR(("Get band failed\n"));
  1659. } else if (cur_band == WLC_BAND_5G) {
  1660. channel = WL_P2P_TEMP_CHAN_5G;
  1661. }
  1662. return wl_ch_host_to_driver(channel);
  1663. }
  1664. buf = (char *)MALLOCZ(cfg->osh, WL_EXTRA_BUF_MAX);
  1665. if (!buf) {
  1666. WL_ERR(("buf alloc failed. use temp channel\n"));
  1667. return wl_ch_host_to_driver(channel);
  1668. }
  1669. *(u32 *)buf = htod32(WL_EXTRA_BUF_MAX);
  1670. if ((err = wldev_ioctl_get(dev, WLC_GET_BSS_INFO, buf,
  1671. WL_EXTRA_BUF_MAX))) {
  1672. WL_ERR(("Failed to get associated bss info, use temp channel \n"));
  1673. chspec = wl_ch_host_to_driver(channel);
  1674. }
  1675. else {
  1676. bss = (wl_bss_info_t *) (buf + 4);
  1677. chspec = bss->chanspec;
  1678. WL_DBG(("Valid BSS Found. chanspec:%d \n", chspec));
  1679. }
  1680. MFREE(cfg->osh, buf, WL_EXTRA_BUF_MAX);
  1681. return chspec;
  1682. }
  1683. static void
  1684. wl_wlfc_enable(struct bcm_cfg80211 *cfg, bool enable)
  1685. {
  1686. #ifdef PROP_TXSTATUS_VSDB
  1687. #if defined(BCMSDIO)
  1688. bool wlfc_enabled = FALSE;
  1689. s32 err;
  1690. dhd_pub_t *dhd;
  1691. struct net_device *primary_ndev = bcmcfg_to_prmry_ndev(cfg);
  1692. dhd = (dhd_pub_t *)(cfg->pub);
  1693. if (!dhd) {
  1694. return;
  1695. }
  1696. if (enable) {
  1697. if (!cfg->wlfc_on && !disable_proptx) {
  1698. dhd_wlfc_get_enable(dhd, &wlfc_enabled);
  1699. if (!wlfc_enabled && dhd->op_mode != DHD_FLAG_HOSTAP_MODE &&
  1700. dhd->op_mode != DHD_FLAG_IBSS_MODE) {
  1701. dhd_wlfc_init(dhd);
  1702. err = wldev_ioctl_set(primary_ndev, WLC_UP, &up, sizeof(s32));
  1703. if (err < 0)
  1704. WL_ERR(("WLC_UP return err:%d\n", err));
  1705. }
  1706. cfg->wlfc_on = true;
  1707. WL_DBG(("wlfc_on:%d \n", cfg->wlfc_on));
  1708. }
  1709. } else {
  1710. dhd_wlfc_deinit(dhd);
  1711. cfg->wlfc_on = false;
  1712. }
  1713. #endif /* defined(BCMSDIO) */
  1714. #endif /* PROP_TXSTATUS_VSDB */
  1715. }
  1716. struct wireless_dev *
  1717. wl_cfg80211_p2p_if_add(struct bcm_cfg80211 *cfg,
  1718. wl_iftype_t wl_iftype,
  1719. char const *name, u8 *mac_addr, s32 *ret_err)
  1720. {
  1721. u16 chspec;
  1722. s16 cfg_type;
  1723. long timeout;
  1724. s32 err;
  1725. u16 p2p_iftype;
  1726. int dhd_mode;
  1727. struct net_device *new_ndev = NULL;
  1728. struct wiphy *wiphy = bcmcfg_to_wiphy(cfg);
  1729. struct ether_addr *p2p_addr;
  1730. #if defined(WL_SUPPORT_MULTIP2P)
  1731. s32 is_mp2p_supported = BCME_ERROR;
  1732. #endif // endif
  1733. *ret_err = BCME_OK;
  1734. if (!cfg->p2p) {
  1735. WL_ERR(("p2p not initialized\n"));
  1736. return NULL;
  1737. }
  1738. #if defined(WL_CFG80211_P2P_DEV_IF)
  1739. if (wl_iftype == WL_IF_TYPE_P2P_DISC) {
  1740. /* Handle Dedicated P2P discovery Interface */
  1741. cfg->down_disc_if = FALSE;
  1742. return wl_cfgp2p_add_p2p_disc_if(cfg);
  1743. }
  1744. #endif /* WL_CFG80211_P2P_DEV_IF */
  1745. #if defined(WL_SUPPORT_MULTIP2P)
  1746. is_mp2p_supported = DHD_OPMODE_SUPPORTED(cfg->pub, DHD_FLAG_MP2P_MODE);
  1747. #endif /* WL_SUPPORT_MULTIP2P */
  1748. if (wl_iftype == WL_IF_TYPE_P2P_GO) {
  1749. p2p_iftype = WL_P2P_IF_GO;
  1750. } else {
  1751. p2p_iftype = WL_P2P_IF_CLIENT;
  1752. }
  1753. /* Dual p2p doesn't support multiple P2PGO interfaces,
  1754. * p2p_go_count is the counter for GO creation
  1755. * requests.
  1756. */
  1757. if (TRUE &&
  1758. #if defined(WL_SUPPORT_MULTIP2P)
  1759. (is_mp2p_supported <= 0) &&
  1760. #endif // endif
  1761. ((cfg->p2p->p2p_go_count > 0) && (wl_iftype == WL_IF_TYPE_P2P_GO))) {
  1762. WL_ERR(("FW does not support multiple GO\n"));
  1763. *ret_err = -ENOTSUPP;
  1764. return NULL;
  1765. }
  1766. if (!cfg->p2p->on) {
  1767. p2p_on(cfg) = true;
  1768. wl_cfgp2p_set_firm_p2p(cfg);
  1769. wl_cfgp2p_init_discovery(cfg);
  1770. }
  1771. strlcpy(cfg->p2p->vir_ifname, name, sizeof(cfg->p2p->vir_ifname));
  1772. /* In concurrency case, STA may be already associated in a particular channel.
  1773. * so retrieve the current channel of primary interface and then start the virtual
  1774. * interface on that.
  1775. */
  1776. chspec = wl_cfg80211_get_shared_freq(wiphy);
  1777. /* For P2P mode, use P2P-specific driver features to create the
  1778. * bss: "cfg p2p_ifadd"
  1779. */
  1780. wl_set_p2p_status(cfg, IF_ADDING);
  1781. bzero(&cfg->if_event_info, sizeof(cfg->if_event_info));
  1782. cfg_type = wl_cfgp2p_get_conn_idx(cfg);
  1783. if (cfg_type == BCME_ERROR) {
  1784. wl_clr_p2p_status(cfg, IF_ADDING);
  1785. WL_ERR(("Failed to get connection idx for p2p interface"));
  1786. return NULL;
  1787. }
  1788. p2p_addr = wl_to_p2p_bss_macaddr(cfg, cfg_type);
  1789. memcpy(p2p_addr->octet, mac_addr, ETH_ALEN);
  1790. err = wl_cfgp2p_ifadd(cfg, p2p_addr,
  1791. htod32(p2p_iftype), chspec);
  1792. if (unlikely(err)) {
  1793. wl_clr_p2p_status(cfg, IF_ADDING);
  1794. WL_ERR((" virtual iface add failed (%d) \n", err));
  1795. return NULL;
  1796. }
  1797. /* Wait for WLC_E_IF event with IF_ADD opcode */
  1798. timeout = wait_event_interruptible_timeout(cfg->netif_change_event,
  1799. ((wl_get_p2p_status(cfg, IF_ADDING) == false) &&
  1800. (cfg->if_event_info.valid)),
  1801. msecs_to_jiffies(MAX_WAIT_TIME));
  1802. if (timeout > 0 && !wl_get_p2p_status(cfg, IF_ADDING) && cfg->if_event_info.valid) {
  1803. wl_if_event_info *event = &cfg->if_event_info;
  1804. new_ndev = wl_cfg80211_post_ifcreate(bcmcfg_to_prmry_ndev(cfg), event,
  1805. event->mac, cfg->p2p->vir_ifname, false);
  1806. if (unlikely(!new_ndev)) {
  1807. goto fail;
  1808. }
  1809. if (wl_iftype == WL_IF_TYPE_P2P_GO) {
  1810. cfg->p2p->p2p_go_count++;
  1811. }
  1812. /* Fill p2p specific data */
  1813. wl_to_p2p_bss_ndev(cfg, cfg_type) = new_ndev;
  1814. wl_to_p2p_bss_bssidx(cfg, cfg_type) = event->bssidx;
  1815. WL_ERR((" virtual interface(%s) is "
  1816. "created net attach done\n", cfg->p2p->vir_ifname));
  1817. dhd_mode = (wl_iftype == WL_IF_TYPE_P2P_GC) ?
  1818. DHD_FLAG_P2P_GC_MODE : DHD_FLAG_P2P_GO_MODE;
  1819. DNGL_FUNC(dhd_cfg80211_set_p2p_info, (cfg, dhd_mode));
  1820. /* reinitialize completion to clear previous count */
  1821. #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 13, 0))
  1822. INIT_COMPLETION(cfg->iface_disable);
  1823. #else
  1824. init_completion(&cfg->iface_disable);
  1825. #endif /* LINUX_VERSION_CODE < KERNEL_VERSION(3, 13, 0) */
  1826. return new_ndev->ieee80211_ptr;
  1827. }
  1828. fail:
  1829. return NULL;
  1830. }
  1831. bool
  1832. wl_cfg80211_check_vif_in_use(struct net_device *ndev)
  1833. {
  1834. struct bcm_cfg80211 *cfg = wl_get_cfg(ndev);
  1835. dhd_pub_t *dhd = (dhd_pub_t *)(cfg->pub);
  1836. bool nan_enabled = FALSE;
  1837. #ifdef WL_NAN
  1838. nan_enabled = cfg->nan_enable;
  1839. #endif /* WL_NAN */
  1840. if (nan_enabled || (wl_cfgp2p_vif_created(cfg)) ||
  1841. (dhd->op_mode & DHD_FLAG_HOSTAP_MODE)) {
  1842. WL_MEM(("%s: Virtual interfaces in use. NAN %d P2P %d softAP %d\n",
  1843. __FUNCTION__, nan_enabled, wl_cfgp2p_vif_created(cfg),
  1844. (dhd->op_mode & DHD_FLAG_HOSTAP_MODE)));
  1845. return TRUE;
  1846. }
  1847. return FALSE;
  1848. }
  1849. void
  1850. wl_cfg80211_iface_state_ops(struct wireless_dev *wdev,
  1851. wl_interface_state_t state,
  1852. wl_iftype_t wl_iftype, u16 wl_mode)
  1853. {
  1854. struct net_device *ndev;
  1855. struct bcm_cfg80211 *cfg;
  1856. #if defined(CUSTOM_SET_CPUCORE)
  1857. dhd_pub_t *dhd;
  1858. #endif // endif
  1859. s32 bssidx;
  1860. WL_DBG(("state:%s wl_iftype:%d mode:%d\n",
  1861. wl_if_state_strs[state], wl_iftype, wl_mode));
  1862. if (!wdev) {
  1863. WL_ERR(("wdev null\n"));
  1864. return;
  1865. }
  1866. if ((wl_iftype == WL_IF_TYPE_P2P_DISC) || (wl_iftype == WL_IF_TYPE_NAN_NMI)) {
  1867. /* P2P discovery is a netless device and uses a
  1868. * hidden bsscfg interface in fw. Don't apply the
  1869. * iface ops state changes for p2p discovery I/F.
  1870. * NAN NMI is netless device and uses a hidden bsscfg interface in fw.
  1871. * Don't apply iface ops state changes for NMI I/F.
  1872. */
  1873. return;
  1874. }
  1875. cfg = wiphy_priv(wdev->wiphy);
  1876. ndev = wdev->netdev;
  1877. #ifdef CUSTOM_SET_CPUCORE
  1878. dhd = (dhd_pub_t *)(cfg->pub);
  1879. #endif /* CUSTOM_SET_CPUCORE */
  1880. bssidx = wl_get_bssidx_by_wdev(cfg, wdev);
  1881. if (!ndev || (bssidx < 0)) {
  1882. WL_ERR(("ndev null. skip iface state ops\n"));
  1883. return;
  1884. }
  1885. switch (state) {
  1886. case WL_IF_CREATE_REQ:
  1887. #ifdef WL_BCNRECV
  1888. /* check fakeapscan in progress then abort */
  1889. wl_android_bcnrecv_stop(ndev, WL_BCNRECV_CONCURRENCY);
  1890. #endif /* WL_BCNRECV */
  1891. wl_cfg80211_scan_abort(cfg);
  1892. wl_wlfc_enable(cfg, true);
  1893. #ifdef WLTDLS
  1894. /* disable TDLS if number of connected interfaces is >= 1 */
  1895. wl_cfg80211_tdls_config(cfg, TDLS_STATE_IF_CREATE, false);
  1896. #endif /* WLTDLS */
  1897. break;
  1898. case WL_IF_DELETE_REQ:
  1899. #ifdef WL_WPS_SYNC
  1900. wl_wps_handle_ifdel(ndev);
  1901. #endif /* WPS_SYNC */
  1902. if (wl_get_drv_status(cfg, SCANNING, ndev)) {
  1903. /* Send completion for any pending scans */
  1904. wl_cfg80211_cancel_scan(cfg);
  1905. }
  1906. #ifdef CUSTOM_SET_CPUCORE
  1907. dhd->chan_isvht80 &= ~DHD_FLAG_P2P_MODE;
  1908. if (!(dhd->chan_isvht80)) {
  1909. dhd_set_cpucore(dhd, FALSE);
  1910. }
  1911. #endif /* CUSTOM_SET_CPUCORE */
  1912. wl_add_remove_pm_enable_work(cfg, WL_PM_WORKQ_DEL);
  1913. break;
  1914. case WL_IF_CREATE_DONE:
  1915. if (wl_mode == WL_MODE_BSS) {
  1916. /* Common code for sta type interfaces - STA, GC */
  1917. wldev_iovar_setint(ndev, "buf_key_b4_m4", 1);
  1918. }
  1919. if (wl_iftype == WL_IF_TYPE_P2P_GC) {
  1920. /* Disable firmware roaming for P2P interface */
  1921. wldev_iovar_setint(ndev, "roam_off", 1);
  1922. }
  1923. if (wl_mode == WL_MODE_AP) {
  1924. /* Common code for AP/GO */
  1925. }
  1926. break;
  1927. case WL_IF_DELETE_DONE:
  1928. #ifdef WLTDLS
  1929. /* Enable back TDLS if connected interface is <= 1 */
  1930. wl_cfg80211_tdls_config(cfg, TDLS_STATE_IF_DELETE, false);
  1931. #endif /* WLTDLS */
  1932. wl_wlfc_enable(cfg, false);
  1933. break;
  1934. case WL_IF_CHANGE_REQ:
  1935. /* Flush existing IEs from firmware on role change */
  1936. wl_cfg80211_clear_per_bss_ies(cfg, wdev);
  1937. break;
  1938. case WL_IF_CHANGE_DONE:
  1939. if (wl_mode == WL_MODE_BSS) {
  1940. /* Enable buffering of PTK key till EAPOL 4/4 is sent out */
  1941. wldev_iovar_setint(ndev, "buf_key_b4_m4", 1);
  1942. }
  1943. break;
  1944. default:
  1945. WL_ERR(("Unsupported state: %d\n", state));
  1946. return;
  1947. }
  1948. }
  1949. static s32
  1950. wl_cfg80211_p2p_if_del(struct wiphy *wiphy, struct wireless_dev *wdev)
  1951. {
  1952. struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
  1953. s16 bssidx;
  1954. s16 err;
  1955. s32 cfg_type;
  1956. struct net_device *ndev;
  1957. long timeout;
  1958. if (unlikely(!wl_get_drv_status(cfg, READY, bcmcfg_to_prmry_ndev(cfg)))) {
  1959. WL_INFORM_MEM(("device is not ready\n"));
  1960. return BCME_NOTFOUND;
  1961. }
  1962. #ifdef WL_CFG80211_P2P_DEV_IF
  1963. if (wdev->iftype == NL80211_IFTYPE_P2P_DEVICE) {
  1964. /* Handle dedicated P2P discovery interface. */
  1965. return wl_cfgp2p_del_p2p_disc_if(wdev, cfg);
  1966. }
  1967. #endif /* WL_CFG80211_P2P_DEV_IF */
  1968. /* Handle P2P Group Interface */
  1969. bssidx = wl_get_bssidx_by_wdev(cfg, wdev);
  1970. if (bssidx <= 0) {
  1971. WL_ERR(("bssidx not found\n"));
  1972. return BCME_NOTFOUND;
  1973. }
  1974. if (wl_cfgp2p_find_type(cfg, bssidx, &cfg_type) != BCME_OK) {
  1975. /* Couldn't find matching iftype */
  1976. WL_MEM(("non P2P interface\n"));
  1977. return BCME_NOTFOUND;
  1978. }
  1979. ndev = wdev->netdev;
  1980. wl_clr_p2p_status(cfg, GO_NEG_PHASE);
  1981. wl_clr_p2p_status(cfg, IF_ADDING);
  1982. /* for GO */
  1983. if (wl_get_mode_by_netdev(cfg, ndev) == WL_MODE_AP) {
  1984. wl_add_remove_eventmsg(ndev, WLC_E_PROBREQ_MSG, false);
  1985. cfg->p2p->p2p_go_count--;
  1986. /* disable interface before bsscfg free */
  1987. err = wl_cfgp2p_ifdisable(cfg, wl_to_p2p_bss_macaddr(cfg, cfg_type));
  1988. /* if fw doesn't support "ifdis",
  1989. do not wait for link down of ap mode
  1990. */
  1991. if (err == 0) {
  1992. WL_ERR(("Wait for Link Down event for GO !!!\n"));
  1993. wait_for_completion_timeout(&cfg->iface_disable,
  1994. msecs_to_jiffies(500));
  1995. } else if (err != BCME_UNSUPPORTED) {
  1996. msleep(300);
  1997. }
  1998. } else {
  1999. /* GC case */
  2000. if (wl_get_drv_status(cfg, DISCONNECTING, ndev)) {
  2001. WL_ERR(("Wait for Link Down event for GC !\n"));
  2002. wait_for_completion_timeout
  2003. (&cfg->iface_disable, msecs_to_jiffies(500));
  2004. }
  2005. }
  2006. bzero(&cfg->if_event_info, sizeof(cfg->if_event_info));
  2007. wl_set_p2p_status(cfg, IF_DELETING);
  2008. DNGL_FUNC(dhd_cfg80211_clean_p2p_info, (cfg));
  2009. err = wl_cfgp2p_ifdel(cfg, wl_to_p2p_bss_macaddr(cfg, cfg_type));
  2010. if (unlikely(err)) {
  2011. WL_ERR(("IFDEL operation failed, error code = %d\n", err));
  2012. goto fail;
  2013. } else {
  2014. /* Wait for WLC_E_IF event */
  2015. timeout = wait_event_interruptible_timeout(cfg->netif_change_event,
  2016. ((wl_get_p2p_status(cfg, IF_DELETING) == false) &&
  2017. (cfg->if_event_info.valid)),
  2018. msecs_to_jiffies(MAX_WAIT_TIME));
  2019. if (timeout > 0 && !wl_get_p2p_status(cfg, IF_DELETING) &&
  2020. cfg->if_event_info.valid) {
  2021. WL_ERR(("P2P IFDEL operation done\n"));
  2022. err = BCME_OK;
  2023. } else {
  2024. WL_ERR(("IFDEL didn't complete properly\n"));
  2025. err = -EINVAL;
  2026. }
  2027. }
  2028. fail:
  2029. /* Even in failure case, attempt to remove the host data structure.
  2030. * Firmware would be cleaned up via WiFi reset done by the
  2031. * user space from hang event context (for android only).
  2032. */
  2033. bzero(cfg->p2p->vir_ifname, IFNAMSIZ);
  2034. wl_to_p2p_bss_bssidx(cfg, cfg_type) = -1;
  2035. wl_to_p2p_bss_ndev(cfg, cfg_type) = NULL;
  2036. wl_clr_drv_status(cfg, CONNECTED, wl_to_p2p_bss_ndev(cfg, cfg_type));
  2037. dhd_net_if_lock(ndev);
  2038. if (cfg->if_event_info.ifidx) {
  2039. /* Remove interface except for primary ifidx */
  2040. wl_cfg80211_remove_if(cfg, cfg->if_event_info.ifidx, ndev, FALSE);
  2041. }
  2042. dhd_net_if_unlock(ndev);
  2043. return err;
  2044. }
  2045. #ifdef WL_IFACE_MGMT_CONF
  2046. #ifdef WL_IFACE_MGMT
  2047. static s32
  2048. wl_cfg80211_is_policy_config_allowed(struct bcm_cfg80211 *cfg)
  2049. {
  2050. s32 ret = BCME_OK;
  2051. wl_iftype_t active_sec_iface = WL_IFACE_NOT_PRESENT;
  2052. bool p2p_disc_on = false;
  2053. bool sta_assoc_state = false;
  2054. mutex_lock(&cfg->if_sync);
  2055. sta_assoc_state = (wl_get_drv_status(cfg, CONNECTED, bcmcfg_to_prmry_ndev(cfg)) ||
  2056. wl_get_drv_status(cfg, CONNECTING, bcmcfg_to_prmry_ndev(cfg)));
  2057. active_sec_iface = wl_cfg80211_get_sec_iface(cfg);
  2058. p2p_disc_on = wl_get_p2p_status(cfg, SCANNING);
  2059. if ((sta_assoc_state == TRUE) || (p2p_disc_on == TRUE) ||
  2060. (cfg->nan_init_state == TRUE) ||
  2061. (active_sec_iface != WL_IFACE_NOT_PRESENT)) {
  2062. WL_INFORM_MEM(("Active iface matrix: sta_assoc_state = %d,"
  2063. " p2p_disc = %d, nan_disc = %d, active iface = %s\n",
  2064. sta_assoc_state, p2p_disc_on, cfg->nan_init_state,
  2065. wl_iftype_to_str(active_sec_iface)));
  2066. ret = BCME_BUSY;
  2067. }
  2068. mutex_unlock(&cfg->if_sync);
  2069. return ret;
  2070. }
  2071. #endif /* WL_IFACE_MGMT */
  2072. #ifdef WL_NANP2P
  2073. int
  2074. wl_cfg80211_set_iface_conc_disc(struct net_device *ndev,
  2075. uint8 arg_val)
  2076. {
  2077. struct bcm_cfg80211 *cfg = wl_get_cfg(ndev);
  2078. if (!cfg) {
  2079. WL_ERR(("%s: Cannot find cfg\n", __FUNCTION__));
  2080. return BCME_ERROR;
  2081. }
  2082. if (wl_cfg80211_is_policy_config_allowed(cfg) != BCME_OK) {
  2083. WL_ERR(("Cant allow iface management modifications\n"));
  2084. return BCME_BUSY;
  2085. }
  2086. if (arg_val) {
  2087. cfg->conc_disc |= arg_val;
  2088. } else {
  2089. cfg->conc_disc &= ~arg_val;
  2090. }
  2091. return BCME_OK;
  2092. }
  2093. uint8
  2094. wl_cfg80211_get_iface_conc_disc(struct net_device *ndev)
  2095. {
  2096. struct bcm_cfg80211 *cfg = wl_get_cfg(ndev);
  2097. if (!cfg) {
  2098. WL_ERR(("%s: Cannot find cfg\n", __FUNCTION__));
  2099. return BCME_ERROR;
  2100. }
  2101. return cfg->conc_disc;
  2102. }
  2103. #endif /* WL_NANP2P */
  2104. #ifdef WL_IFACE_MGMT
  2105. int
  2106. wl_cfg80211_set_iface_policy(struct net_device *ndev,
  2107. char *arg, int len)
  2108. {
  2109. int ret = BCME_OK;
  2110. uint8 i = 0;
  2111. iface_mgmt_data_t *iface_data = NULL;
  2112. struct bcm_cfg80211 *cfg = wl_get_cfg(ndev);
  2113. if (!cfg) {
  2114. WL_ERR(("%s: Cannot find cfg\n", __FUNCTION__));
  2115. return BCME_ERROR;
  2116. }
  2117. if (wl_cfg80211_is_policy_config_allowed(cfg) != BCME_OK) {
  2118. WL_ERR(("Cant allow iface management modifications\n"));
  2119. return BCME_BUSY;
  2120. }
  2121. if (!arg || len <= 0 || len > sizeof(iface_mgmt_data_t)) {
  2122. return BCME_BADARG;
  2123. }
  2124. iface_data = (iface_mgmt_data_t *)arg;
  2125. if (iface_data->policy >= WL_IF_POLICY_INVALID) {
  2126. WL_ERR(("Unexpected value of policy = %d\n",
  2127. iface_data->policy));
  2128. return BCME_BADARG;
  2129. }
  2130. bzero(&cfg->iface_data, sizeof(iface_mgmt_data_t));
  2131. ret = memcpy_s(&cfg->iface_data, sizeof(iface_mgmt_data_t), arg, len);
  2132. if (ret != BCME_OK) {
  2133. WL_ERR(("Failed to copy iface data, src len = %d\n", len));
  2134. return ret;
  2135. }
  2136. if (cfg->iface_data.policy == WL_IF_POLICY_ROLE_PRIORITY) {
  2137. for (i = 0; i < WL_IF_TYPE_MAX; i++) {
  2138. WL_DBG(("iface = %s, priority[i] = %d\n",
  2139. wl_iftype_to_str(i), cfg->iface_data.priority[i]));
  2140. }
  2141. }
  2142. return ret;
  2143. }
  2144. uint8
  2145. wl_cfg80211_get_iface_policy(struct net_device *ndev)
  2146. {
  2147. struct bcm_cfg80211 *cfg = wl_get_cfg(ndev);
  2148. if (!cfg) {
  2149. WL_ERR(("%s: Cannot find cfg\n", __FUNCTION__));
  2150. return BCME_ERROR;
  2151. }
  2152. return cfg->iface_data.policy;
  2153. }
  2154. #endif /* WL_IFACE_MGMT */
  2155. #endif /* WL_IFACE_MGMT_CONF */
  2156. #ifdef WL_IFACE_MGMT
  2157. /* Get active secondary data iface type */
  2158. wl_iftype_t
  2159. wl_cfg80211_get_sec_iface(struct bcm_cfg80211 *cfg)
  2160. {
  2161. #ifndef WL_STATIC_IF
  2162. dhd_pub_t *dhd = (dhd_pub_t *)(cfg->pub);
  2163. #endif /* !WL_STATIC_IF */
  2164. struct net_device *p2p_ndev = NULL;
  2165. p2p_ndev = wl_to_p2p_bss_ndev(cfg,
  2166. P2PAPI_BSSCFG_CONNECTION1);
  2167. #ifdef WL_STATIC_IF
  2168. if (IS_CFG80211_STATIC_IF_ACTIVE(cfg)) {
  2169. if (IS_AP_IFACE(cfg->static_ndev->ieee80211_ptr)) {
  2170. return WL_IF_TYPE_AP;
  2171. }
  2172. }
  2173. #else
  2174. if (dhd->op_mode & DHD_FLAG_HOSTAP_MODE) {
  2175. return WL_IF_TYPE_AP;
  2176. }
  2177. #endif /* WL_STATIC_IF */
  2178. if (p2p_ndev && p2p_ndev->ieee80211_ptr) {
  2179. if (p2p_ndev->ieee80211_ptr->iftype == NL80211_IFTYPE_P2P_GO) {
  2180. return WL_IF_TYPE_P2P_GO;
  2181. }
  2182. if (p2p_ndev->ieee80211_ptr->iftype == NL80211_IFTYPE_P2P_CLIENT) {
  2183. return WL_IF_TYPE_P2P_GC;
  2184. }
  2185. }
  2186. #ifdef WL_NAN
  2187. if (wl_cfgnan_is_dp_active(bcmcfg_to_prmry_ndev(cfg))) {
  2188. return WL_IF_TYPE_NAN;
  2189. }
  2190. #endif /* WL_NAN */
  2191. return WL_IFACE_NOT_PRESENT;
  2192. }
  2193. /*
  2194. * Handle incoming data interface request based on policy.
  2195. * If there is any conflicting interface, that will be
  2196. * deleted.
  2197. */
  2198. s32
  2199. wl_cfg80211_data_if_mgmt(struct bcm_cfg80211 *cfg,
  2200. wl_iftype_t new_wl_iftype)
  2201. {
  2202. s32 ret = BCME_OK;
  2203. bool del_iface = false;
  2204. wl_iftype_t sec_wl_if_type = wl_cfg80211_get_sec_iface(cfg);
  2205. if (sec_wl_if_type == WL_IF_TYPE_NAN &&
  2206. new_wl_iftype == WL_IF_TYPE_NAN) {
  2207. /* Multi NDP is allowed irrespective of Policy */
  2208. return BCME_OK;
  2209. }
  2210. if (sec_wl_if_type == WL_IFACE_NOT_PRESENT) {
  2211. /*
  2212. * If there is no active secondary I/F, there
  2213. * is no interface conflict. Do nothing.
  2214. */
  2215. return BCME_OK;
  2216. }
  2217. /* Handle secondary data link case */
  2218. switch (cfg->iface_data.policy) {
  2219. case WL_IF_POLICY_CUSTOM:
  2220. case WL_IF_POLICY_DEFAULT: {
  2221. if (sec_wl_if_type == WL_IF_TYPE_NAN) {
  2222. /* NAN has the lowest priority */
  2223. del_iface = true;
  2224. } else {
  2225. /* Active iface is present, returning error */
  2226. ret = BCME_ERROR;
  2227. }
  2228. break;
  2229. }
  2230. case WL_IF_POLICY_FCFS: {
  2231. WL_INFORM_MEM(("Found active iface = %s, can't support new iface = %s\n",
  2232. wl_iftype_to_str(sec_wl_if_type), wl_iftype_to_str(new_wl_iftype)));
  2233. ret = BCME_ERROR;
  2234. break;
  2235. }
  2236. case WL_IF_POLICY_LP: {
  2237. WL_INFORM_MEM(("Remove active sec data interface, allow incoming iface\n"));
  2238. /* Delete existing data iface and allow incoming sec iface */
  2239. del_iface = true;
  2240. break;
  2241. }
  2242. case WL_IF_POLICY_ROLE_PRIORITY: {
  2243. WL_INFORM_MEM(("Existing iface = %s (%d) and new iface = %s (%d)\n",
  2244. wl_iftype_to_str(sec_wl_if_type),
  2245. cfg->iface_data.priority[sec_wl_if_type],
  2246. wl_iftype_to_str(new_wl_iftype),
  2247. cfg->iface_data.priority[new_wl_iftype]));
  2248. if (cfg->iface_data.priority[new_wl_iftype] >
  2249. cfg->iface_data.priority[sec_wl_if_type]) {
  2250. del_iface = true;
  2251. } else {
  2252. WL_ERR(("Can't support new iface = %s\n",
  2253. wl_iftype_to_str(new_wl_iftype)));
  2254. ret = BCME_ERROR;
  2255. }
  2256. break;
  2257. }
  2258. default: {
  2259. WL_ERR(("Unsupported interface policy = %d\n",
  2260. cfg->iface_data.policy));
  2261. return BCME_ERROR;
  2262. }
  2263. }
  2264. if (del_iface) {
  2265. ret = wl_cfg80211_delete_iface(cfg, sec_wl_if_type);
  2266. }
  2267. return ret;
  2268. }
  2269. /* Handle discovery ifaces based on policy */
  2270. s32
  2271. wl_cfg80211_disc_if_mgmt(struct bcm_cfg80211 *cfg,
  2272. wl_iftype_t new_wl_iftype, bool *disable_nan, bool *disable_p2p)
  2273. {
  2274. s32 ret = BCME_OK;
  2275. wl_iftype_t sec_wl_if_type =
  2276. wl_cfg80211_get_sec_iface(cfg);
  2277. *disable_p2p = false;
  2278. *disable_nan = false;
  2279. if (sec_wl_if_type == WL_IF_TYPE_NAN &&
  2280. new_wl_iftype == WL_IF_TYPE_NAN) {
  2281. /* Multi NDP is allowed irrespective of Policy */
  2282. return BCME_OK;
  2283. }
  2284. /*
  2285. * Check for any policy conflicts with active secondary
  2286. * interface for incoming discovery iface
  2287. */
  2288. if ((sec_wl_if_type != WL_IFACE_NOT_PRESENT) &&
  2289. (is_discovery_iface(new_wl_iftype))) {
  2290. switch (cfg->iface_data.policy) {
  2291. case WL_IF_POLICY_CUSTOM: {
  2292. if (sec_wl_if_type == WL_IF_TYPE_NAN &&
  2293. new_wl_iftype == WL_IF_TYPE_P2P_DISC) {
  2294. WL_INFORM_MEM(("Allow P2P Discovery with active NDP\n"));
  2295. /* No further checks are required. */
  2296. return BCME_OK;
  2297. }
  2298. /*
  2299. * Intentional fall through to default policy
  2300. * as for AP and associated ifaces, both are same
  2301. */
  2302. }
  2303. /* fall through */
  2304. case WL_IF_POLICY_DEFAULT: {
  2305. if (sec_wl_if_type == WL_IF_TYPE_AP) {
  2306. WL_INFORM_MEM(("AP is active, cant support new iface\n"));
  2307. ret = BCME_ERROR;
  2308. } else if (sec_wl_if_type == WL_IF_TYPE_P2P_GC ||
  2309. sec_wl_if_type == WL_IF_TYPE_P2P_GO) {
  2310. if (new_wl_iftype == WL_IF_TYPE_P2P_DISC) {
  2311. /*
  2312. * Associated discovery case,
  2313. * Fall through
  2314. */
  2315. } else {
  2316. /* Active iface is present, returning error */
  2317. WL_INFORM_MEM(("P2P group is active,"
  2318. " cant support new iface\n"));
  2319. ret = BCME_ERROR;
  2320. }
  2321. } else if (sec_wl_if_type == WL_IF_TYPE_NAN) {
  2322. ret = wl_cfg80211_delete_iface(cfg, sec_wl_if_type);
  2323. }
  2324. break;
  2325. }
  2326. case WL_IF_POLICY_FCFS: {
  2327. WL_INFORM_MEM(("Can't support new iface = %s\n",
  2328. wl_iftype_to_str(new_wl_iftype)));
  2329. ret = BCME_ERROR;
  2330. break;
  2331. }
  2332. case WL_IF_POLICY_LP: {
  2333. /* Delete existing data iface n allow incoming sec iface */
  2334. WL_INFORM_MEM(("Remove active sec data interface = %s\n",
  2335. wl_iftype_to_str(sec_wl_if_type)));
  2336. ret = wl_cfg80211_delete_iface(cfg,
  2337. sec_wl_if_type);
  2338. break;
  2339. }
  2340. case WL_IF_POLICY_ROLE_PRIORITY: {
  2341. WL_INFORM_MEM(("Existing iface = %s (%d) and new iface = %s (%d)\n",
  2342. wl_iftype_to_str(sec_wl_if_type),
  2343. cfg->iface_data.priority[sec_wl_if_type],
  2344. wl_iftype_to_str(new_wl_iftype),
  2345. cfg->iface_data.priority[new_wl_iftype]));
  2346. if (cfg->iface_data.priority[new_wl_iftype] >
  2347. cfg->iface_data.priority[sec_wl_if_type]) {
  2348. WL_INFORM_MEM(("Remove active sec data iface\n"));
  2349. ret = wl_cfg80211_delete_iface(cfg,
  2350. sec_wl_if_type);
  2351. } else {
  2352. WL_ERR(("Can't support new iface = %s"
  2353. " due to low priority\n",
  2354. wl_iftype_to_str(new_wl_iftype)));
  2355. ret = BCME_ERROR;
  2356. }
  2357. break;
  2358. }
  2359. default: {
  2360. WL_ERR(("Unsupported policy\n"));
  2361. return BCME_ERROR;
  2362. }
  2363. }
  2364. } else {
  2365. /*
  2366. * Handle incoming new secondary iface request,
  2367. * irrespective of existing discovery ifaces
  2368. */
  2369. if ((cfg->iface_data.policy == WL_IF_POLICY_CUSTOM) &&
  2370. (new_wl_iftype == WL_IF_TYPE_NAN)) {
  2371. WL_INFORM_MEM(("Allow NAN Data Path\n"));
  2372. /* No further checks are required. */
  2373. return BCME_OK;
  2374. }
  2375. }
  2376. /* Check for any conflicting discovery iface */
  2377. switch (new_wl_iftype) {
  2378. case WL_IF_TYPE_P2P_DISC:
  2379. case WL_IF_TYPE_P2P_GO:
  2380. case WL_IF_TYPE_P2P_GC: {
  2381. *disable_nan = true;
  2382. break;
  2383. }
  2384. case WL_IF_TYPE_NAN_NMI:
  2385. case WL_IF_TYPE_NAN: {
  2386. *disable_p2p = true;
  2387. break;
  2388. }
  2389. case WL_IF_TYPE_STA:
  2390. case WL_IF_TYPE_AP: {
  2391. *disable_nan = true;
  2392. *disable_p2p = true;
  2393. break;
  2394. }
  2395. default: {
  2396. WL_ERR(("Unsupported\n"));
  2397. return BCME_ERROR;
  2398. }
  2399. }
  2400. return ret;
  2401. }
  2402. bool
  2403. wl_cfg80211_is_associated_discovery(struct bcm_cfg80211 *cfg,
  2404. wl_iftype_t new_wl_iftype)
  2405. {
  2406. struct net_device *p2p_ndev = NULL;
  2407. p2p_ndev = wl_to_p2p_bss_ndev(cfg, P2PAPI_BSSCFG_CONNECTION1);
  2408. if (new_wl_iftype == WL_IF_TYPE_P2P_DISC && p2p_ndev &&
  2409. p2p_ndev->ieee80211_ptr &&
  2410. is_p2p_group_iface(p2p_ndev->ieee80211_ptr)) {
  2411. return true;
  2412. }
  2413. #ifdef WL_NAN
  2414. else if ((new_wl_iftype == WL_IF_TYPE_NAN_NMI) &&
  2415. (wl_cfgnan_is_dp_active(bcmcfg_to_prmry_ndev(cfg)))) {
  2416. return true;
  2417. }
  2418. #endif /* WL_NAN */
  2419. return false;
  2420. }
  2421. /* Handle incoming discovery iface request */
  2422. s32
  2423. wl_cfg80211_handle_discovery_config(struct bcm_cfg80211 *cfg,
  2424. wl_iftype_t new_wl_iftype)
  2425. {
  2426. s32 ret = BCME_OK;
  2427. bool disable_p2p = false;
  2428. bool disable_nan = false;
  2429. wl_iftype_t active_sec_iface =
  2430. wl_cfg80211_get_sec_iface(cfg);
  2431. if (is_discovery_iface(new_wl_iftype) &&
  2432. (active_sec_iface != WL_IFACE_NOT_PRESENT)) {
  2433. if (wl_cfg80211_is_associated_discovery(cfg,
  2434. new_wl_iftype) == TRUE) {
  2435. WL_DBG(("Associate iface request is allowed= %s\n",
  2436. wl_iftype_to_str(new_wl_iftype)));
  2437. return ret;
  2438. }
  2439. }
  2440. ret = wl_cfg80211_disc_if_mgmt(cfg, new_wl_iftype,
  2441. &disable_nan, &disable_p2p);
  2442. if (ret != BCME_OK) {
  2443. WL_ERR(("Failed at disc iface mgmt, ret = %d\n", ret));
  2444. return ret;
  2445. }
  2446. #ifdef WL_NANP2P
  2447. if (((new_wl_iftype == WL_IF_TYPE_P2P_DISC) && disable_nan) ||
  2448. ((new_wl_iftype == WL_IF_TYPE_NAN_NMI) && disable_p2p)) {
  2449. if ((cfg->nan_p2p_supported == TRUE) &&
  2450. (cfg->conc_disc == WL_NANP2P_CONC_SUPPORT)) {
  2451. WL_INFORM_MEM(("P2P + NAN conc is supported\n"));
  2452. disable_p2p = false;
  2453. disable_nan = false;
  2454. }
  2455. }
  2456. #endif /* WL_NANP2P */
  2457. if (disable_nan) {
  2458. #ifdef WL_NAN
  2459. /* Disable nan */
  2460. ret = wl_cfgnan_disable(cfg, NAN_CONCURRENCY_CONFLICT);
  2461. if (ret != BCME_OK) {
  2462. WL_ERR(("failed to disable nan, error[%d]\n", ret));
  2463. return ret;
  2464. }
  2465. #endif /* WL_NAN */
  2466. }
  2467. if (disable_p2p) {
  2468. /* Disable p2p discovery */
  2469. ret = wl_cfg80211_deinit_p2p_discovery(cfg);
  2470. if (ret != BCME_OK) {
  2471. WL_ERR(("Failed to disable p2p_disc for allowing nan\n"));
  2472. return ret;
  2473. }
  2474. }
  2475. return ret;
  2476. }
  2477. /*
  2478. * Check for any conflicting iface before adding iface.
  2479. * Based on policy, either conflicting iface is removed
  2480. * or new iface add request is blocked.
  2481. */
  2482. s32
  2483. wl_cfg80211_handle_if_role_conflict(struct bcm_cfg80211 *cfg,
  2484. wl_iftype_t new_wl_iftype)
  2485. {
  2486. s32 ret = BCME_OK;
  2487. WL_INFORM_MEM(("Incoming iface = %s\n", wl_iftype_to_str(new_wl_iftype)));
  2488. if (!is_discovery_iface(new_wl_iftype)) {
  2489. /* Incoming data interface request */
  2490. if (wl_cfg80211_get_sec_iface(cfg) != WL_IFACE_NOT_PRESENT) {
  2491. /* active interface present - Apply interface data policy */
  2492. ret = wl_cfg80211_data_if_mgmt(cfg, new_wl_iftype);
  2493. if (ret != BCME_OK) {
  2494. WL_ERR(("if_mgmt fail:%d\n", ret));
  2495. return ret;
  2496. }
  2497. }
  2498. }
  2499. /* Apply discovery config */
  2500. ret = wl_cfg80211_handle_discovery_config(cfg, new_wl_iftype);
  2501. return ret;
  2502. }
  2503. #endif /* WL_IFACE_MGMT */
  2504. static struct wireless_dev *
  2505. wl_cfg80211_add_monitor_if(struct wiphy *wiphy, const char *name)
  2506. {
  2507. #if defined(WL_ENABLE_P2P_IF) || defined(WL_CFG80211_P2P_DEV_IF)
  2508. WL_ERR(("wl_cfg80211_add_monitor_if: No more support monitor interface\n"));
  2509. return ERR_PTR(-EOPNOTSUPP);
  2510. #else
  2511. struct wireless *wdev;
  2512. struct net_device* ndev = NULL;
  2513. dhd_add_monitor(name, &ndev);
  2514. wdev = kzalloc(sizeof(*wdev), GFP_KERNEL);
  2515. if (!wdev) {
  2516. WL_ERR(("wireless_dev alloc failed! \n"));
  2517. goto fail;
  2518. }
  2519. wdev->wiphy = wiphy;
  2520. wdev->iftype = iface_type;
  2521. ndev->ieee80211_ptr = wdev;
  2522. SET_NETDEV_DEV(ndev, wiphy_dev(wiphy));
  2523. WL_DBG(("wl_cfg80211_add_monitor_if net device returned: 0x%p\n", ndev));
  2524. return ndev->ieee80211_ptr;
  2525. #endif /* WL_ENABLE_P2P_IF || WL_CFG80211_P2P_DEV_IF */
  2526. }
  2527. static struct wireless_dev *
  2528. wl_cfg80211_add_ibss(struct wiphy *wiphy, u16 wl_iftype, char const *name)
  2529. {
  2530. #ifdef WLAIBSS_MCHAN
  2531. /* AIBSS */
  2532. return bcm_cfg80211_add_ibss_if(wiphy, (char *)name);
  2533. #else
  2534. /* Normal IBSS */
  2535. WL_ERR(("IBSS not supported on Virtual iface\n"));
  2536. return NULL;
  2537. #endif // endif
  2538. }
  2539. s32
  2540. wl_release_vif_macaddr(struct bcm_cfg80211 *cfg, u8 *mac_addr, u16 wl_iftype)
  2541. {
  2542. struct net_device *ndev = bcmcfg_to_prmry_ndev(cfg);
  2543. u16 org_toggle_bytes;
  2544. u16 cur_toggle_bytes;
  2545. u16 toggled_bit;
  2546. if (!ndev || !mac_addr || ETHER_ISNULLADDR(mac_addr)) {
  2547. return -EINVAL;
  2548. }
  2549. WL_DBG(("%s:Mac addr" MACDBG "\n",
  2550. __FUNCTION__, MAC2STRDBG(mac_addr)));
  2551. if ((wl_iftype == WL_IF_TYPE_P2P_DISC) || (wl_iftype == WL_IF_TYPE_AP) ||
  2552. (wl_iftype == WL_IF_TYPE_P2P_GO) || (wl_iftype == WL_IF_TYPE_P2P_GC)) {
  2553. /* Avoid invoking release mac addr code for interfaces using
  2554. * fixed mac addr.
  2555. */
  2556. return BCME_OK;
  2557. }
  2558. /* Fetch last two bytes of mac address */
  2559. org_toggle_bytes = ntoh16(*((u16 *)&ndev->dev_addr[4]));
  2560. cur_toggle_bytes = ntoh16(*((u16 *)&mac_addr[4]));
  2561. toggled_bit = (org_toggle_bytes ^ cur_toggle_bytes);
  2562. WL_DBG(("org_toggle_bytes:%04X cur_toggle_bytes:%04X\n",
  2563. org_toggle_bytes, cur_toggle_bytes));
  2564. if (toggled_bit & cfg->vif_macaddr_mask) {
  2565. /* This toggled_bit is marked in the used mac addr
  2566. * mask. Clear it.
  2567. */
  2568. cfg->vif_macaddr_mask &= ~toggled_bit;
  2569. WL_INFORM(("MAC address - " MACDBG " released. toggled_bit:%04X vif_mask:%04X\n",
  2570. MAC2STRDBG(mac_addr), toggled_bit, cfg->vif_macaddr_mask));
  2571. } else {
  2572. WL_ERR(("MAC address - " MACDBG " not found in the used list."
  2573. " toggled_bit:%04x vif_mask:%04x\n", MAC2STRDBG(mac_addr),
  2574. toggled_bit, cfg->vif_macaddr_mask));
  2575. return -EINVAL;
  2576. }
  2577. return BCME_OK;
  2578. }
  2579. s32
  2580. wl_get_vif_macaddr(struct bcm_cfg80211 *cfg, u16 wl_iftype, u8 *mac_addr)
  2581. {
  2582. struct net_device *ndev = bcmcfg_to_prmry_ndev(cfg);
  2583. u16 toggle_mask;
  2584. u16 toggle_bit;
  2585. u16 toggle_bytes;
  2586. u16 used;
  2587. u32 offset = 0;
  2588. /* Toggle mask starts from MSB of second last byte */
  2589. u16 mask = 0x8000;
  2590. if (!mac_addr) {
  2591. return -EINVAL;
  2592. }
  2593. memcpy(mac_addr, ndev->dev_addr, ETH_ALEN);
  2594. /*
  2595. * VIF MAC address managment
  2596. * P2P Device addres: Primary MAC with locally admin. bit set
  2597. * P2P Group address/NAN NMI/Softap/NAN DPI: Primary MAC addr
  2598. * with local admin bit set and one additional bit toggled.
  2599. * cfg->vif_macaddr_mask will hold the info regarding the mac address
  2600. * released. Ensure to call wl_release_vif_macaddress to free up
  2601. * the mac address.
  2602. */
  2603. #if defined(SPECIFIC_MAC_GEN_SCHEME)
  2604. if (wl_iftype == WL_IF_TYPE_P2P_DISC || wl_iftype == WL_IF_TYPE_AP) {
  2605. mac_addr[0] |= 0x02;
  2606. } else if ((wl_iftype == WL_IF_TYPE_P2P_GO) || (wl_iftype == WL_IF_TYPE_P2P_GC)) {
  2607. mac_addr[0] |= 0x02;
  2608. mac_addr[4] ^= 0x80;
  2609. }
  2610. #else
  2611. if (wl_iftype == WL_IF_TYPE_P2P_DISC) {
  2612. mac_addr[0] |= 0x02;
  2613. }
  2614. #endif /* SEPCIFIC_MAC_GEN_SCHEME */
  2615. else {
  2616. /* For locally administered mac addresses, we keep the
  2617. * OUI part constant and just work on the last two bytes.
  2618. */
  2619. mac_addr[0] |= 0x02;
  2620. toggle_mask = cfg->vif_macaddr_mask;
  2621. toggle_bytes = ntoh16(*((u16 *)&mac_addr[4]));
  2622. do {
  2623. used = toggle_mask & mask;
  2624. if (!used) {
  2625. /* Use this bit position */
  2626. toggle_bit = mask >> offset;
  2627. toggle_bytes ^= toggle_bit;
  2628. cfg->vif_macaddr_mask |= toggle_bit;
  2629. WL_DBG(("toggle_bit:%04X toggle_bytes:%04X toggle_mask:%04X\n",
  2630. toggle_bit, toggle_bytes, cfg->vif_macaddr_mask));
  2631. /* Macaddress are stored in network order */
  2632. mac_addr[5] = *((u8 *)&toggle_bytes);
  2633. mac_addr[4] = *(((u8 *)&toggle_bytes + 1));
  2634. break;
  2635. }
  2636. /* Shift by one */
  2637. toggle_mask = toggle_mask << 0x1;
  2638. offset++;
  2639. if (offset > MAX_VIF_OFFSET) {
  2640. /* We have used up all macaddresses. Something wrong! */
  2641. WL_ERR(("Entire range of macaddress used up.\n"));
  2642. ASSERT(0);
  2643. break;
  2644. }
  2645. } while (true);
  2646. }
  2647. WL_INFORM_MEM(("Get virtual I/F mac addr: "MACDBG"\n", MAC2STRDBG(mac_addr)));
  2648. return 0;
  2649. }
  2650. #ifdef DNGL_AXI_ERROR_LOGGING
  2651. static s32
  2652. _wl_cfg80211_check_axi_error(struct bcm_cfg80211 *cfg)
  2653. {
  2654. s32 ret = BCME_OK;
  2655. dhd_pub_t *dhd = (dhd_pub_t *)(cfg->pub);
  2656. hnd_ext_trap_hdr_t *hdr;
  2657. int axi_host_error_size;
  2658. uint8 *new_dst;
  2659. uint32 *ext_data = dhd->extended_trap_data;
  2660. struct file *fp = NULL;
  2661. char *filename = DHD_COMMON_DUMP_PATH
  2662. DHD_DUMP_AXI_ERROR_FILENAME
  2663. DHD_DUMP_HAL_FILENAME_SUFFIX;
  2664. WL_ERR(("%s: starts to read %s. Axi error \n", __FUNCTION__, filename));
  2665. fp = filp_open(filename, O_RDONLY, 0);
  2666. if (IS_ERR(fp) || (fp == NULL)) {
  2667. WL_ERR(("%s: Couldn't read the file, err %ld,File [%s] No previous axi error \n",
  2668. __FUNCTION__, PTR_ERR(fp), filename));
  2669. return ret;
  2670. }
  2671. kernel_read_compat(fp, fp->f_pos, (char *)dhd->axi_err_dump, sizeof(dhd_axi_error_dump_t));
  2672. filp_close(fp, NULL);
  2673. /* Delete axi error info file */
  2674. if (dhd_file_delete(filename) < 0) {
  2675. WL_ERR(("%s(): Failed to delete file: %s\n", __FUNCTION__, filename));
  2676. return ret;
  2677. }
  2678. WL_ERR(("%s(): Success to delete file: %s\n", __FUNCTION__, filename));
  2679. if (dhd->axi_err_dump->etd_axi_error_v1.signature != HND_EXT_TRAP_AXIERROR_SIGNATURE) {
  2680. WL_ERR(("%s: Invalid AXI signature: 0x%x\n",
  2681. __FUNCTION__, dhd->axi_err_dump->etd_axi_error_v1.signature));
  2682. }
  2683. /* First word is original trap_data */
  2684. ext_data++;
  2685. /* Followed by the extended trap data header */
  2686. hdr = (hnd_ext_trap_hdr_t *)ext_data;
  2687. new_dst = hdr->data;
  2688. axi_host_error_size = sizeof(dhd->axi_err_dump->axid)
  2689. + sizeof(dhd->axi_err_dump->fault_address);
  2690. /* TAG_TRAP_AXI_HOST_INFO tlv : host's axid, fault address */
  2691. new_dst = bcm_write_tlv(TAG_TRAP_AXI_HOST_INFO,
  2692. (const void *)dhd->axi_err_dump,
  2693. axi_host_error_size, new_dst);
  2694. /* TAG_TRAP_AXI_ERROR tlv */
  2695. new_dst = bcm_write_tlv(TAG_TRAP_AXI_ERROR,
  2696. (const void *)&dhd->axi_err_dump->etd_axi_error_v1,
  2697. sizeof(dhd->axi_err_dump->etd_axi_error_v1), new_dst);
  2698. hdr->len = new_dst - hdr->data;
  2699. dhd->dongle_trap_occured = TRUE;
  2700. #ifdef WL_CFGVENDOR_SEND_HANG_EVENT
  2701. copy_hang_info_trap(dhd);
  2702. #endif /* WL_CFGVENDOR_SEND_HANG_EVENT */
  2703. memset(dhd->axi_err_dump, 0, sizeof(dhd_axi_error_dump_t));
  2704. dhd->hang_reason = HANG_REASON_DONGLE_TRAP;
  2705. net_os_send_hang_message(bcmcfg_to_prmry_ndev(cfg));
  2706. ret = BCME_ERROR;
  2707. return ret;
  2708. }
  2709. #endif /* DNGL_AXI_ERROR_LOGGING */
  2710. /* All Android/Linux private/Vendor Interface calls should make
  2711. * use of below API for interface creation.
  2712. */
  2713. struct wireless_dev *
  2714. wl_cfg80211_add_if(struct bcm_cfg80211 *cfg,
  2715. struct net_device *primary_ndev,
  2716. wl_iftype_t wl_iftype, const char *name, u8 *mac)
  2717. {
  2718. u8 mac_addr[ETH_ALEN];
  2719. s32 err = -ENODEV;
  2720. struct wireless_dev *wdev = NULL;
  2721. struct wiphy *wiphy;
  2722. s32 wl_mode;
  2723. dhd_pub_t *dhd;
  2724. wl_iftype_t macaddr_iftype = wl_iftype;
  2725. char *tmp = NULL;
  2726. char vif_name[IFNAMSIZ] = {0};
  2727. u8 vif_mac_addr[ETH_ALEN] = {0};
  2728. WL_INFORM_MEM(("if name: %s, wl_iftype:%d \n",
  2729. name ? name : "NULL", wl_iftype));
  2730. if (!cfg || !primary_ndev || !name) {
  2731. WL_ERR(("cfg/ndev/name ptr null\n"));
  2732. return NULL;
  2733. }
  2734. if (wl_cfg80211_get_wdev_from_ifname(cfg, name)) {
  2735. WL_ERR(("Interface name %s exists!\n", name));
  2736. return NULL;
  2737. }
  2738. wiphy = bcmcfg_to_wiphy(cfg);
  2739. dhd = (dhd_pub_t *)(cfg->pub);
  2740. if (!dhd) {
  2741. return NULL;
  2742. }
  2743. if ((wl_mode = wl_iftype_to_mode(wl_iftype)) < 0) {
  2744. return NULL;
  2745. }
  2746. mutex_lock(&cfg->if_sync);
  2747. #ifdef WL_NAN
  2748. if (wl_iftype == WL_IF_TYPE_NAN) {
  2749. /*
  2750. * Bypass the role conflict check for NDI and handle it
  2751. * from dp req and dp resp context
  2752. * because in aware comms, ndi gets created soon after nan enable.
  2753. */
  2754. } else
  2755. #endif /* WL_NAN */
  2756. #ifdef WL_IFACE_MGMT
  2757. if ((err = wl_cfg80211_handle_if_role_conflict(cfg, wl_iftype)) < 0) {
  2758. mutex_unlock(&cfg->if_sync);
  2759. return NULL;
  2760. }
  2761. #endif /* WL_IFACE_MGMT */
  2762. #ifdef DNGL_AXI_ERROR_LOGGING
  2763. /* Check the previous smmu fault error */
  2764. if ((err = _wl_cfg80211_check_axi_error(cfg)) < 0) {
  2765. mutex_unlock(&cfg->if_sync);
  2766. return NULL;
  2767. }
  2768. #endif /* DNGL_AXI_ERROR_LOGGING */
  2769. /* Protect the interace op context */
  2770. /* Do pre-create ops */
  2771. wl_cfg80211_iface_state_ops(primary_ndev->ieee80211_ptr, WL_IF_CREATE_REQ,
  2772. wl_iftype, wl_mode);
  2773. if (strnicmp(name, SOFT_AP_IF_NAME, strlen(SOFT_AP_IF_NAME)) == 0) {
  2774. macaddr_iftype = WL_IF_TYPE_AP;
  2775. }
  2776. tmp = strchr(name, ' ');
  2777. /* For MBSS AP create_interface, command will be
  2778. * create_interface <interface_name> <ap_mac_addr>
  2779. * parsing the vif_name and vif_mac_addr from char name
  2780. */
  2781. if (tmp) {
  2782. int i;
  2783. /* skip space from delim after finding char */
  2784. tmp++;
  2785. mac = tmp;
  2786. for (i = 0; i < ETH_ALEN; i++) {
  2787. vif_mac_addr[i] = (hex_to_bin(mac[i * 3]) << 4)
  2788. | hex_to_bin(mac[i * 3 + 1]);
  2789. }
  2790. for (i = 0; i <= strlen(name); i++) {
  2791. if (*(name + i) != ' ') {
  2792. *(vif_name + i) = *(name + i);
  2793. } else {
  2794. *(vif_name + i) = '\0';
  2795. break;
  2796. }
  2797. }
  2798. }
  2799. if (mac) {
  2800. /* If mac address is provided, use that */
  2801. if (tmp != NULL)
  2802. memcpy(mac_addr, vif_mac_addr, ETH_ALEN);
  2803. else
  2804. memcpy(mac_addr, mac, ETH_ALEN);
  2805. } else if ((wl_get_vif_macaddr(cfg, macaddr_iftype, mac_addr) != BCME_OK)) {
  2806. /* Fetch the mac address to be used for virtual interface */
  2807. err = -EINVAL;
  2808. goto fail;
  2809. }
  2810. switch (wl_iftype) {
  2811. case WL_IF_TYPE_IBSS:
  2812. wdev = wl_cfg80211_add_ibss(wiphy, wl_iftype, name);
  2813. break;
  2814. case WL_IF_TYPE_MONITOR:
  2815. wdev = wl_cfg80211_add_monitor_if(wiphy, name);
  2816. break;
  2817. case WL_IF_TYPE_STA:
  2818. case WL_IF_TYPE_AP:
  2819. case WL_IF_TYPE_NAN:
  2820. if (cfg->iface_cnt >= (IFACE_MAX_CNT - 1)) {
  2821. WL_ERR(("iface_cnt exceeds max cnt. created iface_cnt: %d\n",
  2822. cfg->iface_cnt));
  2823. err = -ENOTSUPP;
  2824. goto fail;
  2825. }
  2826. if (*vif_name)
  2827. wdev = wl_cfg80211_create_iface(cfg->wdev->wiphy,
  2828. wl_iftype, mac_addr, vif_name);
  2829. else
  2830. wdev = wl_cfg80211_create_iface(cfg->wdev->wiphy,
  2831. wl_iftype, mac_addr, name);
  2832. break;
  2833. case WL_IF_TYPE_P2P_DISC:
  2834. case WL_IF_TYPE_P2P_GO:
  2835. /* Intentional fall through */
  2836. case WL_IF_TYPE_P2P_GC:
  2837. if (cfg->p2p_supported) {
  2838. wdev = wl_cfg80211_p2p_if_add(cfg, wl_iftype,
  2839. name, mac_addr, &err);
  2840. break;
  2841. }
  2842. /* Intentionally fall through for unsupported interface
  2843. * handling when firmware doesn't support p2p
  2844. */
  2845. /* Intentional fall through */
  2846. default:
  2847. WL_ERR(("Unsupported interface type\n"));
  2848. err = -ENOTSUPP;
  2849. goto fail;
  2850. }
  2851. if (!wdev) {
  2852. WL_ERR(("vif create failed. err:%d\n", err));
  2853. if (err != -ENOTSUPP) {
  2854. err = -ENODEV;
  2855. }
  2856. goto fail;
  2857. }
  2858. /* Ensure decrementing in case of failure */
  2859. cfg->vif_count++;
  2860. wl_cfg80211_iface_state_ops(wdev,
  2861. WL_IF_CREATE_DONE, wl_iftype, wl_mode);
  2862. WL_INFORM_MEM(("Vif created. dev->ifindex:%d"
  2863. " cfg_iftype:%d, vif_count:%d\n",
  2864. (wdev->netdev ? wdev->netdev->ifindex : 0xff),
  2865. wdev->iftype, cfg->vif_count));
  2866. mutex_unlock(&cfg->if_sync);
  2867. return wdev;
  2868. fail:
  2869. wl_cfg80211_iface_state_ops(primary_ndev->ieee80211_ptr,
  2870. WL_IF_DELETE_REQ, wl_iftype, wl_mode);
  2871. if (err != -ENOTSUPP) {
  2872. /* For non-supported interfaces, just return error and
  2873. * skip below recovery steps.
  2874. */
  2875. #ifdef WL_CFGVENDOR_SEND_HANG_EVENT
  2876. wl_copy_hang_info_if_falure(primary_ndev, HANG_REASON_IFACE_DEL_FAILURE, err);
  2877. #endif /* WL_CFGVENDOR_SEND_HANG_EVENT */
  2878. SUPP_LOG(("IF_ADD fail. err:%d\n", err));
  2879. wl_flush_fw_log_buffer(primary_ndev, FW_LOGSET_MASK_ALL);
  2880. if (dhd_query_bus_erros(dhd)) {
  2881. goto exit;
  2882. }
  2883. dhd->iface_op_failed = TRUE;
  2884. #if defined(DHD_DEBUG) && defined(BCMPCIE) && defined(DHD_FW_COREDUMP)
  2885. if (dhd->memdump_enabled) {
  2886. dhd->memdump_type = DUMP_TYPE_IFACE_OP_FAILURE;
  2887. dhd_bus_mem_dump(dhd);
  2888. }
  2889. #endif /* DHD_DEBUG && BCMPCIE && DHD_FW_COREDUMP */
  2890. #if defined(OEM_ANDROID)
  2891. dhd->hang_reason = HANG_REASON_IFACE_ADD_FAILURE;
  2892. net_os_send_hang_message(bcmcfg_to_prmry_ndev(cfg));
  2893. #endif /* BCMDONGLEHOST && OEM_ANDROID */
  2894. }
  2895. exit:
  2896. mutex_unlock(&cfg->if_sync);
  2897. return NULL;
  2898. }
  2899. static bcm_struct_cfgdev *
  2900. wl_cfg80211_add_virtual_iface(struct wiphy *wiphy,
  2901. #if defined(WL_CFG80211_P2P_DEV_IF)
  2902. const char *name,
  2903. #else
  2904. char *name,
  2905. #endif /* WL_CFG80211_P2P_DEV_IF */
  2906. #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0))
  2907. unsigned char name_assign_type,
  2908. #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0)) */
  2909. enum nl80211_iftype type,
  2910. #if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 12, 0))
  2911. u32 *flags,
  2912. #endif /* LINUX_VERSION_CODE < KERNEL_VERSION(4, 12, 0) */
  2913. struct vif_params *params)
  2914. {
  2915. u16 wl_iftype;
  2916. u16 wl_mode;
  2917. struct net_device *primary_ndev;
  2918. struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
  2919. struct wireless_dev *wdev;
  2920. WL_DBG(("Enter iftype: %d\n", type));
  2921. if (!cfg) {
  2922. return ERR_PTR(-EINVAL);
  2923. }
  2924. /* Use primary I/F for sending cmds down to firmware */
  2925. primary_ndev = bcmcfg_to_prmry_ndev(cfg);
  2926. if (unlikely(!wl_get_drv_status(cfg, READY, primary_ndev))) {
  2927. WL_ERR(("device is not ready\n"));
  2928. return ERR_PTR(-ENODEV);
  2929. }
  2930. if (!name) {
  2931. WL_ERR(("Interface name not provided \n"));
  2932. return ERR_PTR(-EINVAL);
  2933. }
  2934. if (cfg80211_to_wl_iftype(type, &wl_iftype, &wl_mode) < 0) {
  2935. return ERR_PTR(-EINVAL);
  2936. }
  2937. wdev = wl_cfg80211_add_if(cfg, primary_ndev, wl_iftype, name, NULL);
  2938. if (unlikely(!wdev)) {
  2939. return ERR_PTR(-ENODEV);
  2940. }
  2941. return wdev_to_cfgdev(wdev);
  2942. }
  2943. static s32
  2944. wl_cfg80211_del_ibss(struct wiphy *wiphy, struct wireless_dev *wdev)
  2945. {
  2946. WL_INFORM_MEM(("del ibss wdev_ptr:%p\n", wdev));
  2947. #ifdef WLAIBSS_MCHAN
  2948. /* AIBSS */
  2949. return bcm_cfg80211_del_ibss_if(wiphy, wdev);
  2950. #else
  2951. /* Normal IBSS */
  2952. return wl_cfg80211_del_iface(wiphy, wdev);
  2953. #endif // endif
  2954. }
  2955. s32
  2956. wl_cfg80211_del_if(struct bcm_cfg80211 *cfg, struct net_device *primary_ndev,
  2957. struct wireless_dev *wdev, char *ifname)
  2958. {
  2959. int ret = BCME_OK;
  2960. mutex_lock(&cfg->if_sync);
  2961. ret = _wl_cfg80211_del_if(cfg, primary_ndev, wdev, ifname);
  2962. mutex_unlock(&cfg->if_sync);
  2963. return ret;
  2964. }
  2965. s32
  2966. _wl_cfg80211_del_if(struct bcm_cfg80211 *cfg, struct net_device *primary_ndev,
  2967. struct wireless_dev *wdev, char *ifname)
  2968. {
  2969. int ret = BCME_OK;
  2970. s32 bssidx;
  2971. struct wiphy *wiphy;
  2972. u16 wl_mode;
  2973. u16 wl_iftype;
  2974. struct net_info *netinfo;
  2975. dhd_pub_t *dhd;
  2976. BCM_REFERENCE(dhd);
  2977. if (!cfg) {
  2978. return -EINVAL;
  2979. }
  2980. dhd = (dhd_pub_t *)(cfg->pub);
  2981. if (!wdev && ifname) {
  2982. /* If only ifname is provided, fetch corresponding wdev ptr from our
  2983. * internal data structure
  2984. */
  2985. wdev = wl_cfg80211_get_wdev_from_ifname(cfg, ifname);
  2986. }
  2987. /* Check whether we have a valid wdev ptr */
  2988. if (unlikely(!wdev)) {
  2989. WL_ERR(("wdev not found. '%s' does not exists\n", ifname));
  2990. return -ENODEV;
  2991. }
  2992. WL_INFORM_MEM(("del vif. wdev cfg_iftype:%d\n", wdev->iftype));
  2993. wiphy = wdev->wiphy;
  2994. #ifdef WL_CFG80211_P2P_DEV_IF
  2995. if (wdev->iftype == NL80211_IFTYPE_P2P_DEVICE) {
  2996. /* p2p discovery would be de-initialized in stop p2p
  2997. * device context/from other virtual i/f creation context
  2998. * so netinfo list may not have any node corresponding to
  2999. * discovery I/F. Handle it before bssidx check.
  3000. */
  3001. ret = wl_cfg80211_p2p_if_del(wiphy, wdev);
  3002. if (unlikely(ret)) {
  3003. goto exit;
  3004. } else {
  3005. /* success case. return from here */
  3006. if (cfg->vif_count) {
  3007. cfg->vif_count--;
  3008. }
  3009. return BCME_OK;
  3010. }
  3011. }
  3012. #endif /* WL_CFG80211_P2P_DEV_IF */
  3013. if ((netinfo = wl_get_netinfo_by_wdev(cfg, wdev)) == NULL) {
  3014. WL_ERR(("Find netinfo from wdev %p failed\n", wdev));
  3015. ret = -ENODEV;
  3016. goto exit;
  3017. }
  3018. if (!wdev->netdev) {
  3019. WL_ERR(("ndev null! \n"));
  3020. } else {
  3021. /* Disable tx before del */
  3022. netif_tx_disable(wdev->netdev);
  3023. }
  3024. wl_iftype = netinfo->iftype;
  3025. wl_mode = wl_iftype_to_mode(wl_iftype);
  3026. bssidx = netinfo->bssidx;
  3027. WL_INFORM_MEM(("[IFDEL] cfg_iftype:%d wl_iftype:%d mode:%d bssidx:%d\n",
  3028. wdev->iftype, wl_iftype, wl_mode, bssidx));
  3029. /* Do pre-interface del ops */
  3030. wl_cfg80211_iface_state_ops(wdev, WL_IF_DELETE_REQ, wl_iftype, wl_mode);
  3031. switch (wl_iftype) {
  3032. case WL_IF_TYPE_P2P_GO:
  3033. case WL_IF_TYPE_P2P_GC:
  3034. case WL_IF_TYPE_AP:
  3035. case WL_IF_TYPE_STA:
  3036. case WL_IF_TYPE_NAN:
  3037. ret = wl_cfg80211_del_iface(wiphy, wdev);
  3038. break;
  3039. case WL_IF_TYPE_IBSS:
  3040. ret = wl_cfg80211_del_ibss(wiphy, wdev);
  3041. break;
  3042. default:
  3043. WL_ERR(("Unsupported interface type\n"));
  3044. ret = BCME_ERROR;
  3045. }
  3046. exit:
  3047. if (ret == BCME_OK) {
  3048. /* Successful case */
  3049. if (cfg->vif_count) {
  3050. cfg->vif_count--;
  3051. }
  3052. wl_cfg80211_iface_state_ops(primary_ndev->ieee80211_ptr,
  3053. WL_IF_DELETE_DONE, wl_iftype, wl_mode);
  3054. #ifdef WL_NAN
  3055. if (!((cfg->nancfg.mac_rand) && (wl_iftype == WL_IF_TYPE_NAN)))
  3056. #endif /* WL_NAN */
  3057. {
  3058. wl_release_vif_macaddr(cfg, wdev->netdev->dev_addr, wl_iftype);
  3059. }
  3060. WL_INFORM_MEM(("vif deleted. vif_count:%d\n", cfg->vif_count));
  3061. } else {
  3062. if (!wdev->netdev) {
  3063. WL_ERR(("ndev null! \n"));
  3064. } else {
  3065. /* IF del failed. revert back tx queue status */
  3066. netif_tx_start_all_queues(wdev->netdev);
  3067. }
  3068. /* Skip generating log files and sending HANG event
  3069. * if driver state is not READY
  3070. */
  3071. if (wl_get_drv_status(cfg, READY, bcmcfg_to_prmry_ndev(cfg))) {
  3072. #ifdef WL_CFGVENDOR_SEND_HANG_EVENT
  3073. wl_copy_hang_info_if_falure(primary_ndev,
  3074. HANG_REASON_IFACE_DEL_FAILURE, ret);
  3075. #endif /* WL_CFGVENDOR_SEND_HANG_EVENT */
  3076. SUPP_LOG(("IF_DEL fail. err:%d\n", ret));
  3077. wl_flush_fw_log_buffer(primary_ndev, FW_LOGSET_MASK_ALL);
  3078. /* IF dongle is down due to previous hang or other conditions, sending
  3079. * one more hang notification is not needed.
  3080. */
  3081. if (dhd_query_bus_erros(dhd) || (ret == BCME_DONGLE_DOWN)) {
  3082. goto end;
  3083. }
  3084. dhd->iface_op_failed = TRUE;
  3085. #if defined(DHD_FW_COREDUMP)
  3086. if (dhd->memdump_enabled && (ret != -EBADTYPE)) {
  3087. dhd->memdump_type = DUMP_TYPE_IFACE_OP_FAILURE;
  3088. dhd_bus_mem_dump(dhd);
  3089. }
  3090. #endif /* DHD_FW_COREDUMP */
  3091. #if defined(OEM_ANDROID)
  3092. WL_ERR(("Notify hang event to upper layer \n"));
  3093. dhd->hang_reason = HANG_REASON_IFACE_DEL_FAILURE;
  3094. net_os_send_hang_message(bcmcfg_to_prmry_ndev(cfg));
  3095. #endif /* BCMDONGLEHOST && OEM_ANDROID */
  3096. }
  3097. }
  3098. end:
  3099. return ret;
  3100. }
  3101. static s32
  3102. wl_cfg80211_del_virtual_iface(struct wiphy *wiphy, bcm_struct_cfgdev *cfgdev)
  3103. {
  3104. struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
  3105. struct wireless_dev *wdev = cfgdev_to_wdev(cfgdev);
  3106. int ret = BCME_OK;
  3107. u16 wl_iftype;
  3108. u16 wl_mode;
  3109. struct net_device *primary_ndev;
  3110. if (!cfg) {
  3111. return -EINVAL;
  3112. }
  3113. primary_ndev = bcmcfg_to_prmry_ndev(cfg);
  3114. wdev = cfgdev_to_wdev(cfgdev);
  3115. if (!wdev) {
  3116. WL_ERR(("wdev null"));
  3117. return -ENODEV;
  3118. }
  3119. WL_DBG(("Enter wdev:%p iftype: %d\n", wdev, wdev->iftype));
  3120. if (cfg80211_to_wl_iftype(wdev->iftype, &wl_iftype, &wl_mode) < 0) {
  3121. WL_ERR(("Wrong iftype: %d\n", wdev->iftype));
  3122. return -ENODEV;
  3123. }
  3124. if ((ret = wl_cfg80211_del_if(cfg, primary_ndev,
  3125. wdev, NULL)) < 0) {
  3126. WL_ERR(("IF del failed\n"));
  3127. }
  3128. return ret;
  3129. }
  3130. static s32
  3131. wl_cfg80211_change_p2prole(struct wiphy *wiphy, struct net_device *ndev, enum nl80211_iftype type)
  3132. {
  3133. s32 wlif_type;
  3134. s32 mode = 0;
  3135. s32 index;
  3136. s32 err;
  3137. s32 conn_idx = -1;
  3138. chanspec_t chspec;
  3139. struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
  3140. dhd_pub_t *dhd = (dhd_pub_t *)(cfg->pub);
  3141. #if defined(WL_SUPPORT_MULTIP2P)
  3142. s32 is_mp2p_supported = BCME_ERROR;
  3143. #endif /* WL_SUPPORT_MULTIP2P */
  3144. WL_INFORM_MEM(("Enter. current_role:%d new_role:%d \n", ndev->ieee80211_ptr->iftype, type));
  3145. if (!cfg->p2p || !wl_cfgp2p_vif_created(cfg)) {
  3146. WL_ERR(("P2P not initialized \n"));
  3147. return -EINVAL;
  3148. }
  3149. if (!is_p2p_group_iface(ndev->ieee80211_ptr)) {
  3150. WL_ERR(("Wrong if type \n"));
  3151. return -EINVAL;
  3152. }
  3153. /* Abort any on-going scans to avoid race condition issues */
  3154. wl_cfg80211_cancel_scan(cfg);
  3155. index = wl_get_bssidx_by_wdev(cfg, ndev->ieee80211_ptr);
  3156. if (index < 0) {
  3157. WL_ERR(("Find bsscfg index from ndev(%p) failed\n", ndev));
  3158. return BCME_ERROR;
  3159. }
  3160. if (wl_cfgp2p_find_type(cfg, index, &conn_idx) != BCME_OK) {
  3161. return BCME_ERROR;
  3162. }
  3163. #if defined(WL_SUPPORT_MULTIP2P)
  3164. is_mp2p_supported = DHD_OPMODE_SUPPORTED(cfg->pub, DHD_FLAG_MP2P_MODE);
  3165. #endif /* WL_SUPPORT_MULTIP2P */
  3166. /* In concurrency case, STA may be already associated in a particular
  3167. * channel. so retrieve the current channel of primary interface and
  3168. * then start the virtual interface on that.
  3169. */
  3170. chspec = wl_cfg80211_get_shared_freq(wiphy);
  3171. if (type == NL80211_IFTYPE_P2P_GO) {
  3172. /* Dual p2p doesn't support multiple P2PGO interfaces,
  3173. * p2p_go_count is the counter for GO creation
  3174. * requests.
  3175. */
  3176. if (TRUE &&
  3177. #if defined(WL_SUPPORT_MULTIP2P)
  3178. (is_mp2p_supported <= 0) &&
  3179. #endif // endif
  3180. (cfg->p2p->p2p_go_count > 0) && (type == NL80211_IFTYPE_P2P_GO)) {
  3181. WL_ERR(("FW does not support multiple GO\n"));
  3182. return BCME_ERROR;
  3183. }
  3184. mode = WL_MODE_AP;
  3185. wlif_type = WL_P2P_IF_GO;
  3186. dhd->op_mode &= ~DHD_FLAG_P2P_GC_MODE;
  3187. dhd->op_mode |= DHD_FLAG_P2P_GO_MODE;
  3188. } else {
  3189. wlif_type = WL_P2P_IF_CLIENT;
  3190. /* for GO */
  3191. if (wl_get_mode_by_netdev(cfg, ndev) == WL_MODE_AP) {
  3192. WL_INFORM_MEM(("Downgrading P2P GO to cfg_iftype:%d \n", type));
  3193. wl_add_remove_eventmsg(ndev, WLC_E_PROBREQ_MSG, false);
  3194. cfg->p2p->p2p_go_count--;
  3195. /* disable interface before bsscfg free */
  3196. err = wl_cfgp2p_ifdisable(cfg, wl_to_p2p_bss_macaddr(cfg, conn_idx));
  3197. /* if fw doesn't support "ifdis",
  3198. * do not wait for link down of ap mode
  3199. */
  3200. if (err == 0) {
  3201. WL_DBG(("Wait for Link Down event for GO !!!\n"));
  3202. wait_for_completion_timeout(&cfg->iface_disable,
  3203. msecs_to_jiffies(500));
  3204. } else if (err != BCME_UNSUPPORTED) {
  3205. msleep(300);
  3206. }
  3207. }
  3208. }
  3209. wl_set_p2p_status(cfg, IF_CHANGING);
  3210. wl_clr_p2p_status(cfg, IF_CHANGED);
  3211. wl_cfgp2p_ifchange(cfg, wl_to_p2p_bss_macaddr(cfg, conn_idx),
  3212. htod32(wlif_type), chspec, conn_idx);
  3213. wait_event_interruptible_timeout(cfg->netif_change_event,
  3214. (wl_get_p2p_status(cfg, IF_CHANGED) == true),
  3215. msecs_to_jiffies(MAX_WAIT_TIME));
  3216. wl_clr_p2p_status(cfg, IF_CHANGING);
  3217. wl_clr_p2p_status(cfg, IF_CHANGED);
  3218. if (mode == WL_MODE_AP) {
  3219. wl_set_drv_status(cfg, CONNECTED, ndev);
  3220. }
  3221. return BCME_OK;
  3222. }
  3223. static s32
  3224. wl_cfg80211_change_virtual_iface(struct wiphy *wiphy, struct net_device *ndev,
  3225. enum nl80211_iftype type,
  3226. #if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 12, 0))
  3227. u32 *flags,
  3228. #endif /* (LINUX_VERSION_CODE < KERNEL_VERSION(4, 12, 0) */
  3229. struct vif_params *params)
  3230. {
  3231. s32 infra = 1;
  3232. s32 err = BCME_OK;
  3233. u16 wl_iftype;
  3234. u16 wl_mode;
  3235. struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
  3236. struct net_info *netinfo = NULL;
  3237. dhd_pub_t *dhd = (dhd_pub_t *)(cfg->pub);
  3238. struct net_device *primary_ndev;
  3239. if (!dhd)
  3240. return -EINVAL;
  3241. WL_INFORM_MEM(("[%s] Enter. current cfg_iftype:%d new cfg_iftype:%d \n",
  3242. ndev->name, ndev->ieee80211_ptr->iftype, type));
  3243. primary_ndev = bcmcfg_to_prmry_ndev(cfg);
  3244. if (cfg80211_to_wl_iftype(type, &wl_iftype, &wl_mode) < 0) {
  3245. WL_ERR(("Unknown role \n"));
  3246. return -EINVAL;
  3247. }
  3248. mutex_lock(&cfg->if_sync);
  3249. netinfo = wl_get_netinfo_by_wdev(cfg, ndev->ieee80211_ptr);
  3250. if (unlikely(!netinfo)) {
  3251. #ifdef WL_STATIC_IF
  3252. if (IS_CFG80211_STATIC_IF(cfg, ndev)) {
  3253. /* Incase of static interfaces, the netinfo will be
  3254. * allocated only when FW interface is initialized. So
  3255. * store the value and use it during initialization.
  3256. */
  3257. WL_INFORM_MEM(("skip change vif for static if\n"));
  3258. ndev->ieee80211_ptr->iftype = type;
  3259. err = BCME_OK;
  3260. } else
  3261. #endif /* WL_STATIC_IF */
  3262. {
  3263. WL_ERR(("netinfo not found \n"));
  3264. err = -ENODEV;
  3265. }
  3266. goto fail;
  3267. }
  3268. /* perform pre-if-change tasks */
  3269. wl_cfg80211_iface_state_ops(ndev->ieee80211_ptr,
  3270. WL_IF_CHANGE_REQ, wl_iftype, wl_mode);
  3271. switch (type) {
  3272. case NL80211_IFTYPE_ADHOC:
  3273. infra = 0;
  3274. break;
  3275. case NL80211_IFTYPE_STATION:
  3276. /* Supplicant sets iftype to STATION while removing p2p GO */
  3277. if (ndev->ieee80211_ptr->iftype == NL80211_IFTYPE_P2P_GO) {
  3278. /* Downgrading P2P GO */
  3279. err = wl_cfg80211_change_p2prole(wiphy, ndev, type);
  3280. if (unlikely(err)) {
  3281. WL_ERR(("P2P downgrade failed \n"));
  3282. }
  3283. } else if (ndev->ieee80211_ptr->iftype == NL80211_IFTYPE_AP) {
  3284. /* Downgrade role from AP to STA */
  3285. if ((err = wl_cfg80211_add_del_bss(cfg, ndev,
  3286. netinfo->bssidx, wl_iftype, 0, NULL)) < 0) {
  3287. WL_ERR(("AP-STA Downgrade failed \n"));
  3288. goto fail;
  3289. }
  3290. }
  3291. break;
  3292. case NL80211_IFTYPE_AP:
  3293. /* intentional fall through */
  3294. case NL80211_IFTYPE_AP_VLAN:
  3295. {
  3296. if (!wl_get_drv_status(cfg, AP_CREATED, ndev)) {
  3297. #if !defined(OEM_ANDROID)
  3298. dhd->op_mode = DHD_FLAG_HOSTAP_MODE;
  3299. #endif /* BCMDONGLEHOST */
  3300. err = wl_cfg80211_set_ap_role(cfg, ndev);
  3301. if (unlikely(err)) {
  3302. WL_ERR(("set ap role failed!\n"));
  3303. goto fail;
  3304. }
  3305. } else {
  3306. WL_INFORM_MEM(("AP_CREATED bit set. Skip role change\n"));
  3307. }
  3308. break;
  3309. }
  3310. case NL80211_IFTYPE_P2P_GO:
  3311. /* Intentional fall through */
  3312. case NL80211_IFTYPE_P2P_CLIENT:
  3313. infra = 1;
  3314. err = wl_cfg80211_change_p2prole(wiphy, ndev, type);
  3315. break;
  3316. case NL80211_IFTYPE_MONITOR:
  3317. case NL80211_IFTYPE_WDS:
  3318. case NL80211_IFTYPE_MESH_POINT:
  3319. /* Intentional fall through */
  3320. default:
  3321. WL_ERR(("Unsupported type:%d \n", type));
  3322. err = -EINVAL;
  3323. goto fail;
  3324. }
  3325. err = wldev_ioctl_set(ndev, WLC_SET_INFRA, &infra, sizeof(s32));
  3326. if (err < 0) {
  3327. WL_ERR(("SET INFRA/IBSS error %d\n", err));
  3328. goto fail;
  3329. }
  3330. wl_cfg80211_iface_state_ops(primary_ndev->ieee80211_ptr,
  3331. WL_IF_CHANGE_DONE, wl_iftype, wl_mode);
  3332. /* Update new iftype in relevant structures */
  3333. ndev->ieee80211_ptr->iftype = type;
  3334. netinfo->iftype = wl_iftype;
  3335. WL_INFORM_MEM(("[%s] cfg_iftype changed to %d\n", ndev->name, type));
  3336. fail:
  3337. if (err) {
  3338. wl_flush_fw_log_buffer(ndev, FW_LOGSET_MASK_ALL);
  3339. }
  3340. mutex_unlock(&cfg->if_sync);
  3341. return err;
  3342. }
  3343. s32
  3344. wl_cfg80211_notify_ifadd(struct net_device *dev,
  3345. int ifidx, char *name, uint8 *mac, uint8 bssidx, uint8 role)
  3346. {
  3347. bool ifadd_expected = FALSE;
  3348. struct bcm_cfg80211 *cfg = wl_get_cfg(dev);
  3349. bool bss_pending_op = TRUE;
  3350. /* P2P may send WLC_E_IF_ADD and/or WLC_E_IF_CHANGE during IF updating ("p2p_ifupd")
  3351. * redirect the IF_ADD event to ifchange as it is not a real "new" interface
  3352. */
  3353. if (wl_get_p2p_status(cfg, IF_CHANGING))
  3354. return wl_cfg80211_notify_ifchange(dev, ifidx, name, mac, bssidx);
  3355. /* Okay, we are expecting IF_ADD (as IF_ADDING is true) */
  3356. if (wl_get_p2p_status(cfg, IF_ADDING)) {
  3357. ifadd_expected = TRUE;
  3358. wl_clr_p2p_status(cfg, IF_ADDING);
  3359. } else if (cfg->bss_pending_op) {
  3360. ifadd_expected = TRUE;
  3361. bss_pending_op = FALSE;
  3362. }
  3363. if (ifadd_expected) {
  3364. wl_if_event_info *if_event_info = &cfg->if_event_info;
  3365. if_event_info->valid = TRUE;
  3366. if_event_info->ifidx = ifidx;
  3367. if_event_info->bssidx = bssidx;
  3368. if_event_info->role = role;
  3369. strlcpy(if_event_info->name, name, sizeof(if_event_info->name));
  3370. if_event_info->name[IFNAMSIZ - 1] = '\0';
  3371. if (mac)
  3372. memcpy(if_event_info->mac, mac, ETHER_ADDR_LEN);
  3373. /* Update bss pendig operation status */
  3374. if (!bss_pending_op) {
  3375. cfg->bss_pending_op = FALSE;
  3376. }
  3377. WL_INFORM_MEM(("IF_ADD ifidx:%d bssidx:%d role:%d\n",
  3378. ifidx, bssidx, role));
  3379. OSL_SMP_WMB();
  3380. wake_up_interruptible(&cfg->netif_change_event);
  3381. return BCME_OK;
  3382. }
  3383. return BCME_ERROR;
  3384. }
  3385. s32
  3386. wl_cfg80211_notify_ifdel(struct net_device *dev, int ifidx, char *name, uint8 *mac, uint8 bssidx)
  3387. {
  3388. bool ifdel_expected = FALSE;
  3389. struct bcm_cfg80211 *cfg = wl_get_cfg(dev);
  3390. wl_if_event_info *if_event_info = &cfg->if_event_info;
  3391. bool bss_pending_op = TRUE;
  3392. if (wl_get_p2p_status(cfg, IF_DELETING)) {
  3393. ifdel_expected = TRUE;
  3394. wl_clr_p2p_status(cfg, IF_DELETING);
  3395. } else if (cfg->bss_pending_op) {
  3396. ifdel_expected = TRUE;
  3397. bss_pending_op = FALSE;
  3398. }
  3399. if (ifdel_expected) {
  3400. if_event_info->valid = TRUE;
  3401. if_event_info->ifidx = ifidx;
  3402. if_event_info->bssidx = bssidx;
  3403. /* Update bss pendig operation status */
  3404. if (!bss_pending_op) {
  3405. cfg->bss_pending_op = FALSE;
  3406. }
  3407. WL_INFORM_MEM(("IF_DEL ifidx:%d bssidx:%d\n", ifidx, bssidx));
  3408. OSL_SMP_WMB();
  3409. wake_up_interruptible(&cfg->netif_change_event);
  3410. return BCME_OK;
  3411. }
  3412. return BCME_ERROR;
  3413. }
  3414. s32
  3415. wl_cfg80211_notify_ifchange(struct net_device * dev, int ifidx, char *name, uint8 *mac,
  3416. uint8 bssidx)
  3417. {
  3418. struct bcm_cfg80211 *cfg = wl_get_cfg(dev);
  3419. if (wl_get_p2p_status(cfg, IF_CHANGING)) {
  3420. wl_set_p2p_status(cfg, IF_CHANGED);
  3421. OSL_SMP_WMB();
  3422. wake_up_interruptible(&cfg->netif_change_event);
  3423. return BCME_OK;
  3424. }
  3425. return BCME_ERROR;
  3426. }
  3427. static s32 wl_set_rts(struct net_device *dev, u32 rts_threshold)
  3428. {
  3429. s32 err = 0;
  3430. err = wldev_iovar_setint(dev, "rtsthresh", rts_threshold);
  3431. if (unlikely(err)) {
  3432. WL_ERR(("Error (%d)\n", err));
  3433. return err;
  3434. }
  3435. return err;
  3436. }
  3437. static s32 wl_set_frag(struct net_device *dev, u32 frag_threshold)
  3438. {
  3439. s32 err = 0;
  3440. err = wldev_iovar_setint_bsscfg(dev, "fragthresh", frag_threshold, 0);
  3441. if (unlikely(err)) {
  3442. WL_ERR(("Error (%d)\n", err));
  3443. return err;
  3444. }
  3445. return err;
  3446. }
  3447. static s32 wl_set_retry(struct net_device *dev, u32 retry, bool l)
  3448. {
  3449. s32 err = 0;
  3450. u32 cmd = (l ? WLC_SET_LRL : WLC_SET_SRL);
  3451. #ifdef CUSTOM_LONG_RETRY_LIMIT
  3452. if ((cmd == WLC_SET_LRL) &&
  3453. (retry != CUSTOM_LONG_RETRY_LIMIT)) {
  3454. WL_DBG(("CUSTOM_LONG_RETRY_LIMIT is used.Ignore configuration"));
  3455. return err;
  3456. }
  3457. #endif /* CUSTOM_LONG_RETRY_LIMIT */
  3458. retry = htod32(retry);
  3459. err = wldev_ioctl_set(dev, cmd, &retry, sizeof(retry));
  3460. if (unlikely(err)) {
  3461. WL_ERR(("cmd (%d) , error (%d)\n", cmd, err));
  3462. return err;
  3463. }
  3464. return err;
  3465. }
  3466. static s32 wl_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed)
  3467. {
  3468. struct bcm_cfg80211 *cfg = (struct bcm_cfg80211 *)wiphy_priv(wiphy);
  3469. struct net_device *ndev = bcmcfg_to_prmry_ndev(cfg);
  3470. s32 err = 0;
  3471. RETURN_EIO_IF_NOT_UP(cfg);
  3472. WL_DBG(("Enter\n"));
  3473. if (changed & WIPHY_PARAM_RTS_THRESHOLD &&
  3474. (cfg->conf->rts_threshold != wiphy->rts_threshold)) {
  3475. cfg->conf->rts_threshold = wiphy->rts_threshold;
  3476. err = wl_set_rts(ndev, cfg->conf->rts_threshold);
  3477. if (err != BCME_OK)
  3478. return err;
  3479. }
  3480. if (changed & WIPHY_PARAM_FRAG_THRESHOLD &&
  3481. (cfg->conf->frag_threshold != wiphy->frag_threshold)) {
  3482. cfg->conf->frag_threshold = wiphy->frag_threshold;
  3483. err = wl_set_frag(ndev, cfg->conf->frag_threshold);
  3484. if (err != BCME_OK)
  3485. return err;
  3486. }
  3487. if (changed & WIPHY_PARAM_RETRY_LONG &&
  3488. (cfg->conf->retry_long != wiphy->retry_long)) {
  3489. cfg->conf->retry_long = wiphy->retry_long;
  3490. err = wl_set_retry(ndev, cfg->conf->retry_long, true);
  3491. if (err != BCME_OK)
  3492. return err;
  3493. }
  3494. if (changed & WIPHY_PARAM_RETRY_SHORT &&
  3495. (cfg->conf->retry_short != wiphy->retry_short)) {
  3496. cfg->conf->retry_short = wiphy->retry_short;
  3497. err = wl_set_retry(ndev, cfg->conf->retry_short, false);
  3498. if (err != BCME_OK) {
  3499. return err;
  3500. }
  3501. }
  3502. return err;
  3503. }
  3504. static chanspec_t
  3505. channel_to_chanspec(struct wiphy *wiphy, struct net_device *dev, u32 channel, u32 bw_cap)
  3506. {
  3507. struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
  3508. u8 *buf = NULL;
  3509. wl_uint32_list_t *list;
  3510. int err = BCME_OK;
  3511. chanspec_t c = 0, ret_c = 0;
  3512. int bw = 0, tmp_bw = 0;
  3513. int i;
  3514. u32 tmp_c;
  3515. #define LOCAL_BUF_SIZE 1024
  3516. buf = (u8 *)MALLOC(cfg->osh, LOCAL_BUF_SIZE);
  3517. if (!buf) {
  3518. WL_ERR(("buf memory alloc failed\n"));
  3519. goto exit;
  3520. }
  3521. err = wldev_iovar_getbuf_bsscfg(dev, "chanspecs", NULL,
  3522. 0, buf, LOCAL_BUF_SIZE, 0, &cfg->ioctl_buf_sync);
  3523. if (err != BCME_OK) {
  3524. WL_ERR(("get chanspecs failed with %d\n", err));
  3525. goto exit;
  3526. }
  3527. list = (wl_uint32_list_t *)(void *)buf;
  3528. for (i = 0; i < dtoh32(list->count); i++) {
  3529. c = dtoh32(list->element[i]);
  3530. if (channel <= CH_MAX_2G_CHANNEL) {
  3531. if (!CHSPEC_IS20(c))
  3532. continue;
  3533. if (channel == CHSPEC_CHANNEL(c)) {
  3534. ret_c = c;
  3535. bw = 20;
  3536. goto exit;
  3537. }
  3538. }
  3539. tmp_c = wf_chspec_ctlchan(c);
  3540. tmp_bw = bw2cap[CHSPEC_BW(c) >> WL_CHANSPEC_BW_SHIFT];
  3541. if (tmp_c != channel)
  3542. continue;
  3543. if ((tmp_bw > bw) && (tmp_bw <= bw_cap)) {
  3544. bw = tmp_bw;
  3545. ret_c = c;
  3546. if (bw == bw_cap)
  3547. goto exit;
  3548. }
  3549. }
  3550. exit:
  3551. if (buf) {
  3552. MFREE(cfg->osh, buf, LOCAL_BUF_SIZE);
  3553. }
  3554. #undef LOCAL_BUF_SIZE
  3555. WL_DBG(("return chanspec %x %d\n", ret_c, bw));
  3556. return ret_c;
  3557. }
  3558. void
  3559. wl_cfg80211_ibss_vsie_set_buffer(struct net_device *dev, vndr_ie_setbuf_t *ibss_vsie,
  3560. int ibss_vsie_len)
  3561. {
  3562. struct bcm_cfg80211 *cfg = wl_get_cfg(dev);
  3563. if (cfg != NULL && ibss_vsie != NULL) {
  3564. if (cfg->ibss_vsie != NULL) {
  3565. MFREE(cfg->osh, cfg->ibss_vsie, cfg->ibss_vsie_len);
  3566. }
  3567. cfg->ibss_vsie = ibss_vsie;
  3568. cfg->ibss_vsie_len = ibss_vsie_len;
  3569. }
  3570. }
  3571. static void
  3572. wl_cfg80211_ibss_vsie_free(struct bcm_cfg80211 *cfg)
  3573. {
  3574. /* free & initiralize VSIE (Vendor Specific IE) */
  3575. if (cfg->ibss_vsie != NULL) {
  3576. MFREE(cfg->osh, cfg->ibss_vsie, cfg->ibss_vsie_len);
  3577. cfg->ibss_vsie_len = 0;
  3578. }
  3579. }
  3580. s32
  3581. wl_cfg80211_ibss_vsie_delete(struct net_device *dev)
  3582. {
  3583. struct bcm_cfg80211 *cfg = wl_get_cfg(dev);
  3584. char *ioctl_buf = NULL;
  3585. s32 ret = BCME_OK, bssidx;
  3586. if (cfg != NULL && cfg->ibss_vsie != NULL) {
  3587. ioctl_buf = (char *)MALLOC(cfg->osh, WLC_IOCTL_MEDLEN);
  3588. if (!ioctl_buf) {
  3589. WL_ERR(("ioctl memory alloc failed\n"));
  3590. return -ENOMEM;
  3591. }
  3592. if ((bssidx = wl_get_bssidx_by_wdev(cfg, dev->ieee80211_ptr)) < 0) {
  3593. WL_ERR(("Find index failed\n"));
  3594. ret = BCME_ERROR;
  3595. goto end;
  3596. }
  3597. /* change the command from "add" to "del" */
  3598. strlcpy(cfg->ibss_vsie->cmd, "del", sizeof(cfg->ibss_vsie->cmd));
  3599. ret = wldev_iovar_setbuf_bsscfg(dev, "vndr_ie",
  3600. cfg->ibss_vsie, cfg->ibss_vsie_len,
  3601. ioctl_buf, WLC_IOCTL_MEDLEN, bssidx, NULL);
  3602. WL_ERR(("ret=%d\n", ret));
  3603. if (ret == BCME_OK) {
  3604. /* Free & initialize VSIE */
  3605. MFREE(cfg->osh, cfg->ibss_vsie, cfg->ibss_vsie_len);
  3606. cfg->ibss_vsie_len = 0;
  3607. }
  3608. end:
  3609. if (ioctl_buf) {
  3610. MFREE(cfg->osh, ioctl_buf, WLC_IOCTL_MEDLEN);
  3611. }
  3612. }
  3613. return ret;
  3614. }
  3615. #ifdef WLAIBSS_MCHAN
  3616. static bcm_struct_cfgdev*
  3617. bcm_cfg80211_add_ibss_if(struct wiphy *wiphy, char *name)
  3618. {
  3619. int err = 0;
  3620. struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
  3621. struct wireless_dev* wdev = NULL;
  3622. struct net_device *new_ndev = NULL;
  3623. struct net_device *primary_ndev = NULL;
  3624. long timeout;
  3625. wl_aibss_if_t aibss_if;
  3626. wl_if_event_info *event = NULL;
  3627. if (cfg->ibss_cfgdev != NULL) {
  3628. WL_ERR(("IBSS interface %s already exists\n", name));
  3629. return NULL;
  3630. }
  3631. WL_ERR(("Try to create IBSS interface %s\n", name));
  3632. primary_ndev = bcmcfg_to_prmry_ndev(cfg);
  3633. /* generate a new MAC address for the IBSS interface */
  3634. get_primary_mac(cfg, &cfg->ibss_if_addr);
  3635. cfg->ibss_if_addr.octet[4] ^= 0x40;
  3636. bzero(&aibss_if, sizeof(aibss_if));
  3637. memcpy(&aibss_if.addr, &cfg->ibss_if_addr, sizeof(aibss_if.addr));
  3638. aibss_if.chspec = 0;
  3639. aibss_if.len = sizeof(aibss_if);
  3640. cfg->bss_pending_op = TRUE;
  3641. bzero(&cfg->if_event_info, sizeof(cfg->if_event_info));
  3642. err = wldev_iovar_setbuf(primary_ndev, "aibss_ifadd", &aibss_if,
  3643. sizeof(aibss_if), cfg->ioctl_buf, WLC_IOCTL_MAXLEN, &cfg->ioctl_buf_sync);
  3644. if (err) {
  3645. WL_ERR(("IOVAR aibss_ifadd failed with error %d\n", err));
  3646. goto fail;
  3647. }
  3648. timeout = wait_event_interruptible_timeout(cfg->netif_change_event,
  3649. !cfg->bss_pending_op, msecs_to_jiffies(MAX_WAIT_TIME));
  3650. if (timeout <= 0 || cfg->bss_pending_op)
  3651. goto fail;
  3652. event = &cfg->if_event_info;
  3653. /* By calling wl_cfg80211_allocate_if (dhd_allocate_if eventually) we give the control
  3654. * over this net_device interface to dhd_linux, hence the interface is managed by dhd_liux
  3655. * and will be freed by dhd_detach unless it gets unregistered before that. The
  3656. * wireless_dev instance new_ndev->ieee80211_ptr associated with this net_device will
  3657. * be freed by wl_dealloc_netinfo
  3658. */
  3659. new_ndev = wl_cfg80211_allocate_if(cfg, event->ifidx, event->name,
  3660. event->mac, event->bssidx, event->name);
  3661. if (new_ndev == NULL)
  3662. goto fail;
  3663. wdev = (struct wireless_dev *)MALLOCZ(cfg->osh, sizeof(*wdev));
  3664. if (wdev == NULL)
  3665. goto fail;
  3666. wdev->wiphy = wiphy;
  3667. wdev->iftype = NL80211_IFTYPE_ADHOC;
  3668. wdev->netdev = new_ndev;
  3669. new_ndev->ieee80211_ptr = wdev;
  3670. SET_NETDEV_DEV(new_ndev, wiphy_dev(wdev->wiphy));
  3671. /* rtnl lock must have been acquired, if this is not the case, wl_cfg80211_register_if
  3672. * needs to be modified to take one parameter (bool need_rtnl_lock)
  3673. */
  3674. ASSERT_RTNL();
  3675. if (wl_cfg80211_register_if(cfg, event->ifidx, new_ndev, FALSE) != BCME_OK)
  3676. goto fail;
  3677. wl_alloc_netinfo(cfg, new_ndev, wdev, WL_IF_TYPE_IBSS,
  3678. PM_ENABLE, event->bssidx, event->ifidx);
  3679. cfg->ibss_cfgdev = ndev_to_cfgdev(new_ndev);
  3680. WL_ERR(("IBSS interface %s created\n", new_ndev->name));
  3681. return cfg->ibss_cfgdev;
  3682. fail:
  3683. WL_ERR(("failed to create IBSS interface %s \n", name));
  3684. cfg->bss_pending_op = FALSE;
  3685. if (new_ndev)
  3686. wl_cfg80211_remove_if(cfg, event->ifidx, new_ndev, FALSE);
  3687. if (wdev) {
  3688. MFREE(cfg->osh, wdev, sizeof(*wdev));
  3689. }
  3690. return NULL;
  3691. }
  3692. static s32
  3693. bcm_cfg80211_del_ibss_if(struct wiphy *wiphy, bcm_struct_cfgdev *cfgdev)
  3694. {
  3695. int err = 0;
  3696. struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
  3697. struct net_device *ndev = NULL;
  3698. struct net_device *primary_ndev = NULL;
  3699. long timeout;
  3700. if (!cfgdev || cfg->ibss_cfgdev != cfgdev || ETHER_ISNULLADDR(&cfg->ibss_if_addr.octet))
  3701. return -EINVAL;
  3702. ndev = (struct net_device *)cfgdev_to_ndev(cfg->ibss_cfgdev);
  3703. primary_ndev = bcmcfg_to_prmry_ndev(cfg);
  3704. cfg->bss_pending_op = TRUE;
  3705. bzero(&cfg->if_event_info, sizeof(cfg->if_event_info));
  3706. err = wldev_iovar_setbuf(primary_ndev, "aibss_ifdel", &cfg->ibss_if_addr,
  3707. sizeof(cfg->ibss_if_addr), cfg->ioctl_buf, WLC_IOCTL_MAXLEN, &cfg->ioctl_buf_sync);
  3708. if (err) {
  3709. WL_ERR(("IOVAR aibss_ifdel failed with error %d\n", err));
  3710. goto fail;
  3711. }
  3712. timeout = wait_event_interruptible_timeout(cfg->netif_change_event,
  3713. !cfg->bss_pending_op, msecs_to_jiffies(MAX_WAIT_TIME));
  3714. if (timeout <= 0 || cfg->bss_pending_op) {
  3715. WL_ERR(("timeout in waiting IF_DEL event\n"));
  3716. goto fail;
  3717. }
  3718. wl_cfg80211_remove_if(cfg, cfg->if_event_info.ifidx, ndev, FALSE);
  3719. cfg->ibss_cfgdev = NULL;
  3720. return 0;
  3721. fail:
  3722. cfg->bss_pending_op = FALSE;
  3723. return -1;
  3724. }
  3725. #endif /* WLAIBSS_MCHAN */
  3726. s32
  3727. wl_cfg80211_to_fw_iftype(wl_iftype_t iftype)
  3728. {
  3729. s32 ret = BCME_ERROR;
  3730. switch (iftype) {
  3731. case WL_IF_TYPE_AP:
  3732. ret = WL_INTERFACE_TYPE_AP;
  3733. break;
  3734. case WL_IF_TYPE_STA:
  3735. ret = WL_INTERFACE_TYPE_STA;
  3736. break;
  3737. case WL_IF_TYPE_NAN_NMI:
  3738. case WL_IF_TYPE_NAN:
  3739. ret = WL_INTERFACE_TYPE_NAN;
  3740. break;
  3741. case WL_IF_TYPE_P2P_DISC:
  3742. ret = WL_INTERFACE_TYPE_P2P_DISC;
  3743. break;
  3744. case WL_IF_TYPE_P2P_GO:
  3745. ret = WL_INTERFACE_TYPE_P2P_GO;
  3746. break;
  3747. case WL_IF_TYPE_P2P_GC:
  3748. ret = WL_INTERFACE_TYPE_P2P_GC;
  3749. break;
  3750. case WL_IF_TYPE_AWDL:
  3751. ret = WL_INTERFACE_TYPE_AWDL;
  3752. break;
  3753. default:
  3754. WL_ERR(("Unsupported type:%d \n", iftype));
  3755. ret = -EINVAL;
  3756. break;
  3757. }
  3758. return ret;
  3759. }
  3760. s32
  3761. wl_cfg80211_interface_ops(struct bcm_cfg80211 *cfg,
  3762. struct net_device *ndev, s32 bsscfg_idx,
  3763. wl_iftype_t cfg_iftype, s32 del, u8 *addr)
  3764. {
  3765. s32 ret;
  3766. struct wl_interface_create_v2 iface;
  3767. wl_interface_create_v3_t iface_v3;
  3768. struct wl_interface_info_v1 *info;
  3769. wl_interface_info_v2_t *info_v2;
  3770. uint32 ifflags = 0;
  3771. bool use_iface_info_v2 = false;
  3772. u8 ioctl_buf[WLC_IOCTL_SMLEN];
  3773. s32 iftype;
  3774. if (del) {
  3775. ret = wldev_iovar_setbuf(ndev, "interface_remove",
  3776. NULL, 0, ioctl_buf, sizeof(ioctl_buf), NULL);
  3777. if (unlikely(ret))
  3778. WL_ERR(("Interface remove failed!! ret %d\n", ret));
  3779. return ret;
  3780. }
  3781. /* Interface create */
  3782. bzero(&iface, sizeof(iface));
  3783. /*
  3784. * flags field is still used along with iftype inorder to support the old version of the
  3785. * FW work with the latest app changes.
  3786. */
  3787. iftype = wl_cfg80211_to_fw_iftype(cfg_iftype);
  3788. if (iftype < 0) {
  3789. return -ENOTSUPP;
  3790. }
  3791. if (addr) {
  3792. ifflags |= WL_INTERFACE_MAC_USE;
  3793. }
  3794. /* Pass ver = 0 for fetching the interface_create iovar version */
  3795. ret = wldev_iovar_getbuf(ndev, "interface_create",
  3796. &iface, sizeof(struct wl_interface_create_v2),
  3797. ioctl_buf, sizeof(ioctl_buf), NULL);
  3798. if (ret == BCME_UNSUPPORTED) {
  3799. WL_ERR(("interface_create iovar not supported\n"));
  3800. return ret;
  3801. } else if ((ret == 0) && *((uint32 *)ioctl_buf) == WL_INTERFACE_CREATE_VER_3) {
  3802. WL_DBG(("interface_create version 3. flags:0x%x \n", ifflags));
  3803. use_iface_info_v2 = true;
  3804. bzero(&iface_v3, sizeof(wl_interface_create_v3_t));
  3805. iface_v3.ver = WL_INTERFACE_CREATE_VER_3;
  3806. iface_v3.iftype = iftype;
  3807. iface_v3.flags = ifflags;
  3808. if (addr) {
  3809. memcpy(&iface_v3.mac_addr.octet, addr, ETH_ALEN);
  3810. }
  3811. ret = wldev_iovar_getbuf(ndev, "interface_create",
  3812. &iface_v3, sizeof(wl_interface_create_v3_t),
  3813. ioctl_buf, sizeof(ioctl_buf), NULL);
  3814. } else {
  3815. /* On any other error, attempt with iovar version 2 */
  3816. WL_DBG(("interface_create version 2. get_ver:%d ifflags:0x%x\n", ret, ifflags));
  3817. iface.ver = WL_INTERFACE_CREATE_VER_2;
  3818. iface.iftype = iftype;
  3819. iface.flags = ifflags;
  3820. if (addr) {
  3821. memcpy(&iface.mac_addr.octet, addr, ETH_ALEN);
  3822. }
  3823. ret = wldev_iovar_getbuf(ndev, "interface_create",
  3824. &iface, sizeof(struct wl_interface_create_v2),
  3825. ioctl_buf, sizeof(ioctl_buf), NULL);
  3826. }
  3827. if (unlikely(ret)) {
  3828. WL_ERR(("Interface create failed!! ret %d\n", ret));
  3829. return ret;
  3830. }
  3831. /* success case */
  3832. if (use_iface_info_v2 == true) {
  3833. info_v2 = (wl_interface_info_v2_t *)ioctl_buf;
  3834. ret = info_v2->bsscfgidx;
  3835. } else {
  3836. /* Use v1 struct */
  3837. info = (struct wl_interface_info_v1 *)ioctl_buf;
  3838. ret = info->bsscfgidx;
  3839. }
  3840. WL_DBG(("wl interface create success!! bssidx:%d \n", ret));
  3841. return ret;
  3842. }
  3843. #if defined(IGUANA_LEGACY_CHIPS)
  3844. #define BCM4355_REV_C1 0x0c
  3845. #define BCM4355_REV_D0 0x0d
  3846. bool
  3847. wl_customer6_legacy_chip_check(struct bcm_cfg80211 *cfg,
  3848. struct net_device *ndev)
  3849. {
  3850. u32 chipnum;
  3851. wlc_rev_info_t revinfo;
  3852. int ret;
  3853. /* Get the device rev info */
  3854. bzero(&revinfo, sizeof(revinfo));
  3855. ret = wldev_ioctl_get(ndev, WLC_GET_REVINFO, &revinfo, sizeof(revinfo));
  3856. if (ret < 0) {
  3857. WL_ERR(("wl_customer6_legacy_chip_check: GET revinfo FAILED. ret:%d\n", ret));
  3858. ASSERT(0);
  3859. return false;
  3860. }
  3861. WL_DBG(("wl_customer6_legacy_chip_check: GET_REVINFO device 0x%x, vendor 0x%x,"
  3862. " chipnum 0x%x\n",
  3863. dtoh32(revinfo.deviceid), dtoh32(revinfo.vendorid), dtoh32(revinfo.chipnum)));
  3864. chipnum = revinfo.chipnum;
  3865. if (
  3866. #ifdef BCM4350_CHIP_ID
  3867. (chipnum == BCM4350_CHIP_ID) ||
  3868. #endif /* BCM4350_CHIP_ID */
  3869. #ifdef BCM4355_CHIP_ID
  3870. ((chipnum == BCM4355_CHIP_ID) && (revinfo.chiprev < BCM4355_REV_C1 ||
  3871. revinfo.chiprev == BCM4355_REV_D0)) ||
  3872. #endif /* BCM4355_CHIP_ID */
  3873. #ifdef BCM4345_CHIP_ID
  3874. (chipnum == BCM4345_CHIP_ID) ||
  3875. #endif /* BCM4345_CHIP_ID */
  3876. #ifdef BCM4373_CHIP_ID
  3877. (chipnum == BCM4373_CHIP_ID) ||
  3878. #endif /* BCM4373_CHIP_ID */
  3879. false) {
  3880. /* WAR required */
  3881. WL_DBG(("%s: Customer6 legacy chip identified\n", __FUNCTION__));
  3882. return true;
  3883. }
  3884. return false;
  3885. }
  3886. void
  3887. wl_bss_iovar_war(struct bcm_cfg80211 *cfg,
  3888. struct net_device *ndev, s32 *val)
  3889. {
  3890. if (wl_customer6_legacy_chip_check(cfg, ndev)) {
  3891. /* Few firmware branches have issues in bss iovar handling and
  3892. * that can't be changed since they are in production.
  3893. */
  3894. if (*val == WLC_AP_IOV_OP_MANUAL_AP_BSSCFG_CREATE) {
  3895. *val = WLC_AP_IOV_OP_MANUAL_STA_BSSCFG_CREATE;
  3896. } else if (*val == WLC_AP_IOV_OP_MANUAL_STA_BSSCFG_CREATE) {
  3897. *val = WLC_AP_IOV_OP_MANUAL_AP_BSSCFG_CREATE;
  3898. } else {
  3899. /* Ignore for other bss enums */
  3900. return;
  3901. }
  3902. WL_ERR(("wl bss %d\n", *val));
  3903. }
  3904. }
  3905. #endif // endif
  3906. s32
  3907. wl_cfg80211_add_del_bss(struct bcm_cfg80211 *cfg,
  3908. struct net_device *ndev, s32 bsscfg_idx,
  3909. wl_iftype_t brcm_iftype, s32 del, u8 *addr)
  3910. {
  3911. s32 ret = BCME_OK;
  3912. s32 val = 0;
  3913. struct {
  3914. s32 cfg;
  3915. s32 val;
  3916. struct ether_addr ea;
  3917. } bss_setbuf;
  3918. WL_DBG(("wl_iftype:%d del:%d \n", brcm_iftype, del));
  3919. bzero(&bss_setbuf, sizeof(bss_setbuf));
  3920. /* AP=2, STA=3, up=1, down=0, val=-1 */
  3921. if (del) {
  3922. val = WLC_AP_IOV_OP_DELETE;
  3923. } else if (brcm_iftype == WL_IF_TYPE_AP) {
  3924. /* Add/role change to AP Interface */
  3925. WL_DBG(("Adding AP Interface \n"));
  3926. val = WLC_AP_IOV_OP_MANUAL_AP_BSSCFG_CREATE;
  3927. } else if (brcm_iftype == WL_IF_TYPE_STA) {
  3928. /* Add/role change to STA Interface */
  3929. WL_DBG(("Adding STA Interface \n"));
  3930. val = WLC_AP_IOV_OP_MANUAL_STA_BSSCFG_CREATE;
  3931. } else {
  3932. WL_ERR((" add_del_bss NOT supported for IFACE type:0x%x", brcm_iftype));
  3933. return -EINVAL;
  3934. }
  3935. #if defined(IGUANA_LEGACY_CHIPS)
  3936. if (!del) {
  3937. wl_bss_iovar_war(cfg, ndev, &val);
  3938. }
  3939. #endif // endif
  3940. bss_setbuf.cfg = htod32(bsscfg_idx);
  3941. bss_setbuf.val = htod32(val);
  3942. if (addr) {
  3943. memcpy(&bss_setbuf.ea.octet, addr, ETH_ALEN);
  3944. }
  3945. WL_INFORM_MEM(("wl bss %d bssidx:%d iface:%s \n", val, bsscfg_idx, ndev->name));
  3946. ret = wldev_iovar_setbuf(ndev, "bss", &bss_setbuf, sizeof(bss_setbuf),
  3947. cfg->ioctl_buf, WLC_IOCTL_MAXLEN, &cfg->ioctl_buf_sync);
  3948. if (ret != 0)
  3949. WL_ERR(("'bss %d' failed with %d\n", val, ret));
  3950. return ret;
  3951. }
  3952. s32
  3953. wl_cfg80211_bss_up(struct bcm_cfg80211 *cfg, struct net_device *ndev, s32 bsscfg_idx, s32 bss_up)
  3954. {
  3955. s32 ret = BCME_OK;
  3956. s32 val = bss_up ? 1 : 0;
  3957. struct {
  3958. s32 cfg;
  3959. s32 val;
  3960. } bss_setbuf;
  3961. bss_setbuf.cfg = htod32(bsscfg_idx);
  3962. bss_setbuf.val = htod32(val);
  3963. WL_INFORM_MEM(("wl bss -C %d %s\n", bsscfg_idx, bss_up ? "up" : "down"));
  3964. ret = wldev_iovar_setbuf(ndev, "bss", &bss_setbuf, sizeof(bss_setbuf),
  3965. cfg->ioctl_buf, WLC_IOCTL_MAXLEN, &cfg->ioctl_buf_sync);
  3966. if (ret != 0) {
  3967. WL_ERR(("'bss %d' failed with %d\n", bss_up, ret));
  3968. }
  3969. return ret;
  3970. }
  3971. bool
  3972. wl_cfg80211_bss_isup(struct net_device *ndev, int bsscfg_idx)
  3973. {
  3974. s32 result, val;
  3975. bool isup = false;
  3976. s8 getbuf[64];
  3977. /* Check if the BSS is up */
  3978. *(int*)getbuf = -1;
  3979. result = wldev_iovar_getbuf_bsscfg(ndev, "bss", &bsscfg_idx,
  3980. sizeof(bsscfg_idx), getbuf, sizeof(getbuf), 0, NULL);
  3981. if (result != 0) {
  3982. WL_ERR(("'cfg bss -C %d' failed: %d\n", bsscfg_idx, result));
  3983. WL_ERR(("NOTE: this ioctl error is normal "
  3984. "when the BSS has not been created yet.\n"));
  3985. } else {
  3986. val = *(int*)getbuf;
  3987. val = dtoh32(val);
  3988. WL_DBG(("wl bss -C %d = %d\n", bsscfg_idx, val));
  3989. isup = (val ? TRUE : FALSE);
  3990. }
  3991. return isup;
  3992. }
  3993. s32
  3994. wl_iftype_to_mode(wl_iftype_t iftype)
  3995. {
  3996. s32 mode = BCME_ERROR;
  3997. switch (iftype) {
  3998. case WL_IF_TYPE_STA:
  3999. case WL_IF_TYPE_P2P_GC:
  4000. case WL_IF_TYPE_P2P_DISC:
  4001. mode = WL_MODE_BSS;
  4002. break;
  4003. case WL_IF_TYPE_AP:
  4004. case WL_IF_TYPE_P2P_GO:
  4005. mode = WL_MODE_AP;
  4006. break;
  4007. case WL_IF_TYPE_NAN:
  4008. mode = WL_MODE_NAN;
  4009. break;
  4010. case WL_IF_TYPE_AWDL:
  4011. mode = WL_MODE_AWDL;
  4012. break;
  4013. case WL_IF_TYPE_AIBSS:
  4014. /* Intentional fall through */
  4015. case WL_IF_TYPE_IBSS:
  4016. mode = WL_MODE_IBSS;
  4017. break;
  4018. default:
  4019. WL_ERR(("Unsupported type:%d\n", iftype));
  4020. break;
  4021. }
  4022. return mode;
  4023. }
  4024. s32
  4025. cfg80211_to_wl_iftype(uint16 type, uint16 *role, uint16 *mode)
  4026. {
  4027. switch (type) {
  4028. case NL80211_IFTYPE_STATION:
  4029. *role = WL_IF_TYPE_STA;
  4030. *mode = WL_MODE_BSS;
  4031. break;
  4032. case NL80211_IFTYPE_AP:
  4033. *role = WL_IF_TYPE_AP;
  4034. *mode = WL_MODE_AP;
  4035. break;
  4036. #ifdef WL_CFG80211_P2P_DEV_IF
  4037. case NL80211_IFTYPE_P2P_DEVICE:
  4038. *role = WL_IF_TYPE_P2P_DISC;
  4039. *mode = WL_MODE_BSS;
  4040. break;
  4041. #endif /* WL_CFG80211_P2P_DEV_IF */
  4042. case NL80211_IFTYPE_P2P_GO:
  4043. *role = WL_IF_TYPE_P2P_GO;
  4044. *mode = WL_MODE_AP;
  4045. break;
  4046. case NL80211_IFTYPE_P2P_CLIENT:
  4047. *role = WL_IF_TYPE_P2P_GC;
  4048. *mode = WL_MODE_BSS;
  4049. break;
  4050. case NL80211_IFTYPE_MONITOR:
  4051. WL_ERR(("Unsupported mode \n"));
  4052. return BCME_UNSUPPORTED;
  4053. case NL80211_IFTYPE_ADHOC:
  4054. *role = WL_IF_TYPE_IBSS;
  4055. *mode = WL_MODE_IBSS;
  4056. break;
  4057. #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 9, 0))
  4058. case NL80211_IFTYPE_NAN:
  4059. *role = WL_IF_TYPE_NAN;
  4060. *mode = WL_MODE_NAN;
  4061. break;
  4062. #endif // endif
  4063. default:
  4064. WL_ERR(("Unknown interface type:0x%x\n", type));
  4065. return BCME_ERROR;
  4066. }
  4067. return BCME_OK;
  4068. }
  4069. static s32
  4070. wl_role_to_cfg80211_type(uint16 role, uint16 *wl_iftype, uint16 *mode)
  4071. {
  4072. switch (role) {
  4073. case WLC_E_IF_ROLE_STA:
  4074. *wl_iftype = WL_IF_TYPE_STA;
  4075. *mode = WL_MODE_BSS;
  4076. return NL80211_IFTYPE_STATION;
  4077. case WLC_E_IF_ROLE_AP:
  4078. *wl_iftype = WL_IF_TYPE_AP;
  4079. *mode = WL_MODE_AP;
  4080. return NL80211_IFTYPE_AP;
  4081. case WLC_E_IF_ROLE_P2P_GO:
  4082. *wl_iftype = WL_IF_TYPE_P2P_GO;
  4083. *mode = WL_MODE_AP;
  4084. return NL80211_IFTYPE_P2P_GO;
  4085. case WLC_E_IF_ROLE_P2P_CLIENT:
  4086. *wl_iftype = WL_IF_TYPE_P2P_GC;
  4087. *mode = WL_MODE_BSS;
  4088. return NL80211_IFTYPE_P2P_CLIENT;
  4089. case WLC_E_IF_ROLE_IBSS:
  4090. *wl_iftype = WL_IF_TYPE_IBSS;
  4091. *mode = WL_MODE_IBSS;
  4092. return NL80211_IFTYPE_ADHOC;
  4093. case WLC_E_IF_ROLE_NAN:
  4094. *wl_iftype = WL_IF_TYPE_NAN;
  4095. *mode = WL_MODE_NAN;
  4096. #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 9, 0)) && defined(WL_CFG80211_NAN)
  4097. /* NL80211_IFTYPE_NAN should only be used with CFG80211 NAN MGMT
  4098. * For Vendor HAL based NAN implementation, continue advertising
  4099. * as a STA interface
  4100. */
  4101. return NL80211_IFTYPE_NAN;
  4102. #else
  4103. return NL80211_IFTYPE_STATION;
  4104. #endif /* ((LINUX_VER >= KERNEL_VERSION(4, 9, 0))) && WL_CFG80211_NAN */
  4105. default:
  4106. WL_ERR(("Unknown interface role:0x%x. Forcing type station\n", role));
  4107. return BCME_ERROR;
  4108. }
  4109. }
  4110. struct net_device *
  4111. wl_cfg80211_post_ifcreate(struct net_device *ndev,
  4112. wl_if_event_info *event, u8 *addr,
  4113. const char *name, bool rtnl_lock_reqd)
  4114. {
  4115. struct bcm_cfg80211 *cfg;
  4116. struct net_device *primary_ndev;
  4117. struct net_device *new_ndev = NULL;
  4118. struct wireless_dev *wdev = NULL;
  4119. s32 iface_type;
  4120. s32 ret = BCME_OK;
  4121. u16 mode;
  4122. u8 mac_addr[ETH_ALEN];
  4123. u16 wl_iftype;
  4124. if (!ndev || !event) {
  4125. WL_ERR(("Wrong arg\n"));
  4126. return NULL;
  4127. }
  4128. cfg = wl_get_cfg(ndev);
  4129. if (!cfg) {
  4130. WL_ERR(("cfg null\n"));
  4131. return NULL;
  4132. }
  4133. WL_DBG(("Enter. role:%d ifidx:%d bssidx:%d\n",
  4134. event->role, event->ifidx, event->bssidx));
  4135. if (!event->ifidx || !event->bssidx) {
  4136. /* Fw returned primary idx (0) for virtual interface */
  4137. WL_ERR(("Wrong index. ifidx:%d bssidx:%d \n",
  4138. event->ifidx, event->bssidx));
  4139. return NULL;
  4140. }
  4141. iface_type = wl_role_to_cfg80211_type(event->role, &wl_iftype, &mode);
  4142. if (iface_type < 0) {
  4143. /* Unknown iface type */
  4144. WL_ERR(("Wrong iface type \n"));
  4145. return NULL;
  4146. }
  4147. WL_DBG(("mac_ptr:%p name:%s role:%d nl80211_iftype:%d " MACDBG "\n",
  4148. addr, name, event->role, iface_type, MAC2STRDBG(event->mac)));
  4149. if (!name) {
  4150. /* If iface name is not provided, use dongle ifname */
  4151. name = event->name;
  4152. }
  4153. if (!addr) {
  4154. /* If mac address is not set, use primary mac with locally administered
  4155. * bit set.
  4156. */
  4157. primary_ndev = bcmcfg_to_prmry_ndev(cfg);
  4158. memcpy(mac_addr, primary_ndev->dev_addr, ETH_ALEN);
  4159. /* For customer6 builds, use primary mac address for virtual interface */
  4160. mac_addr[0] |= 0x02;
  4161. addr = mac_addr;
  4162. }
  4163. #ifdef WL_STATIC_IF
  4164. if (IS_CFG80211_STATIC_IF_NAME(cfg, name)) {
  4165. new_ndev = wl_cfg80211_post_static_ifcreate(cfg, event, addr, iface_type);
  4166. if (!new_ndev) {
  4167. WL_ERR(("failed to get I/F pointer\n"));
  4168. return NULL;
  4169. }
  4170. wdev = new_ndev->ieee80211_ptr;
  4171. } else
  4172. #endif /* WL_STATIC_IF */
  4173. {
  4174. new_ndev = wl_cfg80211_allocate_if(cfg, event->ifidx,
  4175. name, addr, event->bssidx, event->name);
  4176. if (!new_ndev) {
  4177. WL_ERR(("I/F allocation failed! \n"));
  4178. return NULL;
  4179. } else {
  4180. WL_DBG(("I/F allocation succeeded! ifidx:0x%x bssidx:0x%x \n",
  4181. event->ifidx, event->bssidx));
  4182. }
  4183. wdev = (struct wireless_dev *)MALLOCZ(cfg->osh, sizeof(*wdev));
  4184. if (!wdev) {
  4185. WL_ERR(("wireless_dev alloc failed! \n"));
  4186. wl_cfg80211_remove_if(cfg, event->ifidx, new_ndev, rtnl_lock_reqd);
  4187. return NULL;
  4188. }
  4189. wdev->wiphy = bcmcfg_to_wiphy(cfg);
  4190. wdev->iftype = iface_type;
  4191. new_ndev->ieee80211_ptr = wdev;
  4192. SET_NETDEV_DEV(new_ndev, wiphy_dev(wdev->wiphy));
  4193. memcpy(new_ndev->dev_addr, addr, ETH_ALEN);
  4194. if (wl_cfg80211_register_if(cfg, event->ifidx, new_ndev, rtnl_lock_reqd)
  4195. != BCME_OK) {
  4196. WL_ERR(("IFACE register failed \n"));
  4197. /* Post interface registration, wdev would be freed from the netdev
  4198. * destructor path. For other cases, handle it here.
  4199. */
  4200. MFREE(cfg->osh, wdev, sizeof(*wdev));
  4201. wl_cfg80211_remove_if(cfg, event->ifidx, new_ndev, rtnl_lock_reqd);
  4202. return NULL;
  4203. }
  4204. }
  4205. /* Initialize with the station mode params */
  4206. ret = wl_alloc_netinfo(cfg, new_ndev, wdev, wl_iftype,
  4207. PM_ENABLE, event->bssidx, event->ifidx);
  4208. if (unlikely(ret)) {
  4209. WL_ERR(("wl_alloc_netinfo Error (%d)\n", ret));
  4210. goto fail;
  4211. }
  4212. /* Apply the mode & infra setting based on iftype */
  4213. if ((ret = wl_config_infra(cfg, new_ndev, wl_iftype)) < 0) {
  4214. WL_ERR(("config ifmode failure (%d)\n", ret));
  4215. goto fail;
  4216. }
  4217. if (mode == WL_MODE_AP) {
  4218. wl_set_drv_status(cfg, AP_CREATING, new_ndev);
  4219. }
  4220. WL_INFORM_MEM(("Network Interface (%s) registered with host."
  4221. " cfg_iftype:%d wl_role:%d " MACDBG "\n",
  4222. new_ndev->name, iface_type, event->role, MAC2STRDBG(new_ndev->dev_addr)));
  4223. #ifdef SUPPORT_SET_CAC
  4224. wl_cfg80211_set_cac(cfg, 0);
  4225. #endif /* SUPPORT_SET_CAC */
  4226. return new_ndev;
  4227. fail:
  4228. #ifdef WL_STATIC_IF
  4229. /* remove static if from iflist */
  4230. if (IS_CFG80211_STATIC_IF_NAME(cfg, name)) {
  4231. cfg->static_ndev_state = NDEV_STATE_FW_IF_FAILED;
  4232. wl_cfg80211_update_iflist_info(cfg, new_ndev, WL_STATIC_IFIDX, addr,
  4233. event->bssidx, event->name, NDEV_STATE_FW_IF_FAILED);
  4234. }
  4235. #endif /* WL_STATIC_IF */
  4236. if (new_ndev) {
  4237. /* wdev would be freed from netdev destructor call back */
  4238. wl_cfg80211_remove_if(cfg, event->ifidx, new_ndev, rtnl_lock_reqd);
  4239. }
  4240. return NULL;
  4241. }
  4242. s32
  4243. wl_cfg80211_delete_iface(struct bcm_cfg80211 *cfg,
  4244. wl_iftype_t sec_data_if_type)
  4245. {
  4246. struct net_info *iter, *next;
  4247. struct net_device *primary_ndev;
  4248. s32 ret = BCME_OK;
  4249. uint8 i = 0;
  4250. BCM_REFERENCE(i);
  4251. BCM_REFERENCE(ret);
  4252. /* Note: This function will clean up only the network interface and host
  4253. * data structures. The firmware interface clean up will happen in the
  4254. * during chip reset (ifconfig wlan0 down for built-in drivers/rmmod
  4255. * context for the module case).
  4256. */
  4257. primary_ndev = bcmcfg_to_prmry_ndev(cfg);
  4258. WL_DBG(("Enter, deleting iftype %s\n",
  4259. wl_iftype_to_str(sec_data_if_type)));
  4260. GCC_DIAGNOSTIC_PUSH_SUPPRESS_CAST();
  4261. for_each_ndev(cfg, iter, next) {
  4262. GCC_DIAGNOSTIC_POP();
  4263. if (iter->ndev && (iter->ndev != primary_ndev)) {
  4264. if (iter->iftype != sec_data_if_type) {
  4265. continue;
  4266. }
  4267. switch (sec_data_if_type) {
  4268. case WL_IF_TYPE_P2P_GO:
  4269. case WL_IF_TYPE_P2P_GC: {
  4270. ret = _wl_cfg80211_del_if(cfg,
  4271. iter->ndev, NULL, iter->ndev->name);
  4272. break;
  4273. }
  4274. #ifdef WL_NAN
  4275. case WL_IF_TYPE_NAN: {
  4276. if (cfg->nan_enable == false) {
  4277. WL_INFORM_MEM(("Nan is not active,"
  4278. " ignore NDI delete\n"));
  4279. } else {
  4280. ret = wl_cfgnan_delete_ndp(cfg, iter->ndev);
  4281. }
  4282. break;
  4283. }
  4284. #endif /* WL_NAN */
  4285. case WL_IF_TYPE_AP: {
  4286. /* Cleanup AP */
  4287. #ifdef WL_STATIC_IF
  4288. /* handle static ap */
  4289. if (IS_CFG80211_STATIC_IF(cfg, iter->ndev)) {
  4290. dev_close(iter->ndev);
  4291. } else
  4292. #endif /* WL_STATIC_IF */
  4293. {
  4294. /* handle virtual created AP */
  4295. ret = _wl_cfg80211_del_if(cfg, iter->ndev,
  4296. NULL, iter->ndev->name);
  4297. }
  4298. break;
  4299. }
  4300. default: {
  4301. WL_ERR(("Unsupported interface type\n"));
  4302. ret = -ENOTSUPP;
  4303. goto fail;
  4304. }
  4305. }
  4306. }
  4307. }
  4308. fail:
  4309. return ret;
  4310. }
  4311. void
  4312. wl_cfg80211_cleanup_virtual_ifaces(struct bcm_cfg80211 *cfg, bool rtnl_lock_reqd)
  4313. {
  4314. struct net_info *iter, *next;
  4315. struct net_device *primary_ndev;
  4316. /* Note: This function will clean up only the network interface and host
  4317. * data structures. The firmware interface clean up will happen in the
  4318. * during chip reset (ifconfig wlan0 down for built-in drivers/rmmod
  4319. * context for the module case).
  4320. */
  4321. primary_ndev = bcmcfg_to_prmry_ndev(cfg);
  4322. WL_DBG(("Enter\n"));
  4323. GCC_DIAGNOSTIC_PUSH_SUPPRESS_CAST();
  4324. for_each_ndev(cfg, iter, next) {
  4325. GCC_DIAGNOSTIC_POP();
  4326. if (iter->ndev && (iter->ndev != primary_ndev)) {
  4327. /* Ensure interfaces are down before deleting */
  4328. #ifdef WL_STATIC_IF
  4329. /* Avoiding cleaning static ifaces */
  4330. if (!IS_CFG80211_STATIC_IF(cfg, iter->ndev))
  4331. #endif /* WL_STATIC_IF */
  4332. {
  4333. dev_close(iter->ndev);
  4334. WL_DBG(("Cleaning up iface:%s \n", iter->ndev->name));
  4335. wl_cfg80211_post_ifdel(iter->ndev, rtnl_lock_reqd, 0);
  4336. }
  4337. }
  4338. }
  4339. }
  4340. s32
  4341. wl_cfg80211_post_ifdel(struct net_device *ndev, bool rtnl_lock_reqd, s32 ifidx)
  4342. {
  4343. s32 ret = BCME_OK;
  4344. struct bcm_cfg80211 *cfg;
  4345. struct net_info *netinfo = NULL;
  4346. if (!ndev || !ndev->ieee80211_ptr) {
  4347. /* No wireless dev done for this interface */
  4348. ret = -EINVAL;
  4349. goto exit;
  4350. }
  4351. cfg = wl_get_cfg(ndev);
  4352. if (!cfg) {
  4353. WL_ERR(("cfg null\n"));
  4354. ret = BCME_ERROR;
  4355. goto exit;
  4356. }
  4357. if (ifidx <= 0) {
  4358. WL_ERR(("Invalid IF idx for iface:%s\n", ndev->name));
  4359. ifidx = dhd_net2idx(((struct dhd_pub *)(cfg->pub))->info, ndev);
  4360. BCM_REFERENCE(ifidx);
  4361. if (ifidx <= 0) {
  4362. ASSERT(0);
  4363. ret = BCME_ERROR;
  4364. goto exit;
  4365. }
  4366. }
  4367. if ((netinfo = wl_get_netinfo_by_wdev(cfg, ndev_to_wdev(ndev))) == NULL) {
  4368. WL_ERR(("Find netinfo from wdev %p failed\n", ndev_to_wdev(ndev)));
  4369. ret = -ENODEV;
  4370. goto exit;
  4371. }
  4372. #ifdef WL_STATIC_IF
  4373. if (IS_CFG80211_STATIC_IF(cfg, ndev)) {
  4374. ret = wl_cfg80211_post_static_ifdel(cfg, ndev);
  4375. } else
  4376. #endif /* WL_STATIC_IF */
  4377. {
  4378. WL_INFORM_MEM(("[%s] cfg80211_remove_if ifidx:%d, vif_count:%d\n",
  4379. ndev->name, ifidx, cfg->vif_count));
  4380. wl_cfg80211_remove_if(cfg, ifidx, ndev, rtnl_lock_reqd);
  4381. cfg->bss_pending_op = FALSE;
  4382. }
  4383. #ifdef SUPPORT_SET_CAC
  4384. wl_cfg80211_set_cac(cfg, 1);
  4385. #endif /* SUPPORT_SET_CAC */
  4386. exit:
  4387. return ret;
  4388. }
  4389. int
  4390. wl_cfg80211_deinit_p2p_discovery(struct bcm_cfg80211 *cfg)
  4391. {
  4392. s32 ret = BCME_OK;
  4393. bcm_struct_cfgdev *cfgdev;
  4394. if (cfg->p2p) {
  4395. /* De-initialize the p2p discovery interface, if operational */
  4396. WL_ERR(("Disabling P2P Discovery Interface \n"));
  4397. #ifdef WL_CFG80211_P2P_DEV_IF
  4398. cfgdev = bcmcfg_to_p2p_wdev(cfg);
  4399. #else
  4400. cfgdev = cfg->p2p_net;
  4401. #endif // endif
  4402. if (cfgdev) {
  4403. ret = wl_cfg80211_scan_stop(cfg, cfgdev);
  4404. if (unlikely(ret < 0)) {
  4405. CFGP2P_ERR(("P2P scan stop failed, ret=%d\n", ret));
  4406. }
  4407. }
  4408. wl_cfgp2p_disable_discovery(cfg);
  4409. wl_to_p2p_bss_bssidx(cfg, P2PAPI_BSSCFG_DEVICE) = 0;
  4410. p2p_on(cfg) = false;
  4411. }
  4412. return ret;
  4413. }
  4414. /* Create a Generic Network Interface and initialize it depending up on
  4415. * the interface type
  4416. */
  4417. struct wireless_dev *
  4418. wl_cfg80211_create_iface(struct wiphy *wiphy,
  4419. wl_iftype_t wl_iftype,
  4420. u8 *mac_addr, const char *name)
  4421. {
  4422. struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
  4423. struct net_device *new_ndev = NULL;
  4424. struct net_device *primary_ndev = NULL;
  4425. s32 ret = BCME_OK;
  4426. s32 bsscfg_idx = 0;
  4427. long timeout;
  4428. wl_if_event_info *event = NULL;
  4429. u8 addr[ETH_ALEN];
  4430. struct net_info *iter, *next;
  4431. WL_DBG(("Enter\n"));
  4432. if (!name) {
  4433. WL_ERR(("Interface name not provided\n"));
  4434. return NULL;
  4435. }
  4436. else {
  4437. GCC_DIAGNOSTIC_PUSH_SUPPRESS_CAST();
  4438. for_each_ndev(cfg, iter, next) {
  4439. GCC_DIAGNOSTIC_POP();
  4440. if (iter->ndev) {
  4441. if (strncmp(iter->ndev->name, name, strlen(name)) == 0) {
  4442. WL_ERR(("Interface name,%s exists!\n", iter->ndev->name));
  4443. return NULL;
  4444. }
  4445. }
  4446. }
  4447. }
  4448. primary_ndev = bcmcfg_to_prmry_ndev(cfg);
  4449. if (likely(!mac_addr)) {
  4450. /* Use primary MAC with the locally administered bit for the
  4451. * Secondary STA I/F
  4452. */
  4453. memcpy(addr, primary_ndev->dev_addr, ETH_ALEN);
  4454. addr[0] |= 0x02;
  4455. } else {
  4456. /* Use the application provided mac address (if any) */
  4457. memcpy(addr, mac_addr, ETH_ALEN);
  4458. }
  4459. cfg->bss_pending_op = TRUE;
  4460. bzero(&cfg->if_event_info, sizeof(cfg->if_event_info));
  4461. /*
  4462. * Intialize the firmware I/F.
  4463. */
  4464. {
  4465. ret = wl_cfg80211_interface_ops(cfg, primary_ndev, bsscfg_idx,
  4466. wl_iftype, 0, addr);
  4467. }
  4468. if (ret == BCME_UNSUPPORTED) {
  4469. /* Use bssidx 1 by default */
  4470. bsscfg_idx = 1;
  4471. if ((ret = wl_cfg80211_add_del_bss(cfg, primary_ndev,
  4472. bsscfg_idx, wl_iftype, 0, addr)) < 0) {
  4473. goto exit;
  4474. }
  4475. } else if (ret < 0) {
  4476. WL_ERR(("Interface create failed!! ret:%d \n", ret));
  4477. goto exit;
  4478. } else {
  4479. /* Success */
  4480. bsscfg_idx = ret;
  4481. }
  4482. WL_DBG(("Interface created!! bssidx:%d \n", bsscfg_idx));
  4483. /*
  4484. * Wait till the firmware send a confirmation event back.
  4485. */
  4486. WL_DBG(("Wait for the FW I/F Event\n"));
  4487. timeout = wait_event_interruptible_timeout(cfg->netif_change_event,
  4488. !cfg->bss_pending_op, msecs_to_jiffies(MAX_WAIT_TIME));
  4489. if (timeout <= 0 || cfg->bss_pending_op) {
  4490. WL_ERR(("ADD_IF event, didn't come. Return. timeout:%lu bss_pending_op:%d\n",
  4491. timeout, cfg->bss_pending_op));
  4492. if (timeout == -ERESTARTSYS) {
  4493. WL_ERR(("waitqueue was interrupted by a signal, returns -ERESTARTSYS\n"));
  4494. }
  4495. goto exit;
  4496. }
  4497. event = &cfg->if_event_info;
  4498. /*
  4499. * Since FW operation is successful,we can go ahead with the
  4500. * the host interface creation.
  4501. */
  4502. new_ndev = wl_cfg80211_post_ifcreate(primary_ndev,
  4503. event, addr, name, false);
  4504. if (new_ndev) {
  4505. /* Iface post ops successful. Return ndev/wdev ptr */
  4506. return new_ndev->ieee80211_ptr;
  4507. }
  4508. exit:
  4509. cfg->bss_pending_op = FALSE;
  4510. return NULL;
  4511. }
  4512. s32
  4513. wl_cfg80211_del_iface(struct wiphy *wiphy, struct wireless_dev *wdev)
  4514. {
  4515. struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
  4516. struct net_device *ndev = NULL;
  4517. s32 ret = BCME_OK;
  4518. s32 bsscfg_idx = 1;
  4519. long timeout;
  4520. u16 wl_iftype;
  4521. u16 wl_mode;
  4522. WL_DBG(("Enter\n"));
  4523. /* If any scan is going on, abort it */
  4524. if (wl_get_drv_status_all(cfg, SCANNING)) {
  4525. WL_DBG(("Scan in progress. Aborting the scan!\n"));
  4526. wl_cfg80211_cancel_scan(cfg);
  4527. }
  4528. bsscfg_idx = wl_get_bssidx_by_wdev(cfg, wdev);
  4529. if (bsscfg_idx <= 0) {
  4530. /* validate bsscfgidx */
  4531. WL_ERR(("Wrong bssidx! \n"));
  4532. return -EINVAL;
  4533. }
  4534. /* Handle p2p iface */
  4535. if ((ret = wl_cfg80211_p2p_if_del(wiphy, wdev)) != BCME_NOTFOUND) {
  4536. WL_DBG(("P2P iface del handled \n"));
  4537. #ifdef SUPPORT_SET_CAC
  4538. wl_cfg80211_set_cac(cfg, 1);
  4539. #endif /* SUPPORT_SET_CAC */
  4540. return ret;
  4541. }
  4542. ndev = wdev->netdev;
  4543. if (unlikely(!ndev)) {
  4544. WL_ERR(("ndev null! \n"));
  4545. return -EINVAL;
  4546. }
  4547. memset(&cfg->if_event_info, 0, sizeof(cfg->if_event_info));
  4548. if (cfg80211_to_wl_iftype(ndev->ieee80211_ptr->iftype,
  4549. &wl_iftype, &wl_mode) < 0) {
  4550. return -EINVAL;
  4551. }
  4552. WL_DBG(("del interface. bssidx:%d cfg_iftype:%d wl_iftype:%d",
  4553. bsscfg_idx, ndev->ieee80211_ptr->iftype, wl_iftype));
  4554. /* Delete the firmware interface. "interface_remove" command
  4555. * should go on the interface to be deleted
  4556. */
  4557. if (wl_cfg80211_get_bus_state(cfg)) {
  4558. WL_ERR(("Bus state is down: %d\n", __LINE__));
  4559. ret = BCME_DONGLE_DOWN;
  4560. goto exit;
  4561. }
  4562. cfg->bss_pending_op = true;
  4563. ret = wl_cfg80211_interface_ops(cfg, ndev, bsscfg_idx,
  4564. wl_iftype, 1, NULL);
  4565. if (ret == BCME_UNSUPPORTED) {
  4566. if ((ret = wl_cfg80211_add_del_bss(cfg, ndev,
  4567. bsscfg_idx, wl_iftype, true, NULL)) < 0) {
  4568. WL_ERR(("DEL bss failed ret:%d \n", ret));
  4569. goto exit;
  4570. }
  4571. } else if ((ret == BCME_NOTAP) || (ret == BCME_NOTSTA)) {
  4572. /* De-init sequence involving role downgrade not happened.
  4573. * Do nothing and return error. The del command should be
  4574. * retried.
  4575. */
  4576. WL_ERR(("ifdel role mismatch:%d\n", ret));
  4577. ret = -EBADTYPE;
  4578. goto exit;
  4579. } else if (ret < 0) {
  4580. WL_ERR(("Interface DEL failed ret:%d \n", ret));
  4581. goto exit;
  4582. }
  4583. timeout = wait_event_interruptible_timeout(cfg->netif_change_event,
  4584. !cfg->bss_pending_op, msecs_to_jiffies(MAX_WAIT_TIME));
  4585. if (timeout <= 0 || cfg->bss_pending_op) {
  4586. WL_ERR(("timeout in waiting IF_DEL event\n"));
  4587. /* The interface unregister will happen from wifi reset context */
  4588. ret = -ETIMEDOUT;
  4589. /* fall through */
  4590. }
  4591. exit:
  4592. if (ret < 0) {
  4593. WL_ERR(("iface del failed:%d\n", ret));
  4594. #ifdef WL_STATIC_IF
  4595. if (IS_CFG80211_STATIC_IF(cfg, ndev)) {
  4596. /*
  4597. * For static interface, clean up the host data,
  4598. * irrespective of fw status. For dynamic
  4599. * interfaces it gets cleaned from dhd_stop context
  4600. */
  4601. wl_cfg80211_post_static_ifdel(cfg, ndev);
  4602. }
  4603. #endif /* WL_STATIC_IF */
  4604. } else {
  4605. ret = wl_cfg80211_post_ifdel(ndev, false, cfg->if_event_info.ifidx);
  4606. if (unlikely(ret)) {
  4607. WL_ERR(("post_ifdel failed\n"));
  4608. }
  4609. }
  4610. cfg->bss_pending_op = false;
  4611. return ret;
  4612. }
  4613. static s32
  4614. wl_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *dev,
  4615. struct cfg80211_ibss_params *params)
  4616. {
  4617. struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
  4618. struct cfg80211_bss *bss;
  4619. struct ieee80211_channel *chan;
  4620. struct wl_join_params join_params;
  4621. int scan_suppress;
  4622. struct cfg80211_ssid ssid;
  4623. s32 scan_retry = 0;
  4624. s32 err = 0;
  4625. size_t join_params_size;
  4626. chanspec_t chanspec = 0;
  4627. u32 param[2] = {0, 0};
  4628. u32 bw_cap = 0;
  4629. WL_TRACE(("In\n"));
  4630. RETURN_EIO_IF_NOT_UP(cfg);
  4631. WL_INFORM_MEM(("IBSS JOIN BSSID:" MACDBG "\n", MAC2STRDBG(params->bssid)));
  4632. if (!params->ssid || params->ssid_len <= 0 ||
  4633. params->ssid_len > DOT11_MAX_SSID_LEN) {
  4634. WL_ERR(("Invalid parameter\n"));
  4635. return -EINVAL;
  4636. }
  4637. #if defined(WL_CFG80211_P2P_DEV_IF)
  4638. chan = params->chandef.chan;
  4639. #else
  4640. chan = params->channel;
  4641. #endif /* WL_CFG80211_P2P_DEV_IF */
  4642. if (chan)
  4643. cfg->channel = ieee80211_frequency_to_channel(chan->center_freq);
  4644. if (wl_get_drv_status(cfg, CONNECTED, dev)) {
  4645. struct wlc_ssid *lssid = (struct wlc_ssid *)wl_read_prof(cfg, dev, WL_PROF_SSID);
  4646. u8 *bssid = (u8 *)wl_read_prof(cfg, dev, WL_PROF_BSSID);
  4647. u32 *channel = (u32 *)wl_read_prof(cfg, dev, WL_PROF_CHAN);
  4648. if (!params->bssid || ((memcmp(params->bssid, bssid, ETHER_ADDR_LEN) == 0) &&
  4649. (memcmp(params->ssid, lssid->SSID, lssid->SSID_len) == 0) &&
  4650. (*channel == cfg->channel))) {
  4651. WL_ERR(("Connection already existed to " MACDBG "\n",
  4652. MAC2STRDBG((u8 *)wl_read_prof(cfg, dev, WL_PROF_BSSID))));
  4653. return -EISCONN;
  4654. }
  4655. WL_ERR(("Ignore Previous connecton to %s (" MACDBG ")\n",
  4656. lssid->SSID, MAC2STRDBG(bssid)));
  4657. }
  4658. /* remove the VSIE */
  4659. wl_cfg80211_ibss_vsie_delete(dev);
  4660. bss = cfg80211_get_ibss(wiphy, NULL, params->ssid, params->ssid_len);
  4661. if (!bss) {
  4662. if (IBSS_INITIAL_SCAN_ALLOWED == TRUE) {
  4663. memcpy(ssid.ssid, params->ssid, params->ssid_len);
  4664. ssid.ssid_len = params->ssid_len;
  4665. do {
  4666. if (unlikely
  4667. (__wl_cfg80211_scan(wiphy, dev, NULL, &ssid) ==
  4668. -EBUSY)) {
  4669. wl_delay(150);
  4670. } else {
  4671. break;
  4672. }
  4673. } while (++scan_retry < WL_SCAN_RETRY_MAX);
  4674. /* rtnl lock code is removed here. don't see why rtnl lock
  4675. * needs to be released.
  4676. */
  4677. /* wait 4 secons till scan done.... */
  4678. schedule_timeout_interruptible(msecs_to_jiffies(4000));
  4679. bss = cfg80211_get_ibss(wiphy, NULL,
  4680. params->ssid, params->ssid_len);
  4681. }
  4682. }
  4683. if (bss && ((IBSS_COALESCE_ALLOWED == TRUE) ||
  4684. ((IBSS_COALESCE_ALLOWED == FALSE) && params->bssid &&
  4685. !memcmp(bss->bssid, params->bssid, ETHER_ADDR_LEN)))) {
  4686. cfg->ibss_starter = false;
  4687. WL_DBG(("Found IBSS\n"));
  4688. } else {
  4689. cfg->ibss_starter = true;
  4690. }
  4691. if (bss) {
  4692. CFG80211_PUT_BSS(wiphy, bss);
  4693. }
  4694. if (chan) {
  4695. if (chan->band == IEEE80211_BAND_5GHZ)
  4696. param[0] = WLC_BAND_5G;
  4697. else if (chan->band == IEEE80211_BAND_2GHZ)
  4698. param[0] = WLC_BAND_2G;
  4699. err = wldev_iovar_getint(dev, "bw_cap", param);
  4700. if (unlikely(err)) {
  4701. WL_ERR(("Get bw_cap Failed (%d)\n", err));
  4702. return err;
  4703. }
  4704. bw_cap = param[0];
  4705. chanspec = channel_to_chanspec(wiphy, dev, cfg->channel, bw_cap);
  4706. }
  4707. /*
  4708. * Join with specific BSSID and cached SSID
  4709. * If SSID is zero join based on BSSID only
  4710. */
  4711. bzero(&join_params, sizeof(join_params));
  4712. memcpy((void *)join_params.ssid.SSID, (const void *)params->ssid,
  4713. params->ssid_len);
  4714. join_params.ssid.SSID_len = htod32(params->ssid_len);
  4715. if (params->bssid) {
  4716. memcpy(&join_params.params.bssid, params->bssid, ETHER_ADDR_LEN);
  4717. err = wldev_ioctl_set(dev, WLC_SET_DESIRED_BSSID, &join_params.params.bssid,
  4718. ETHER_ADDR_LEN);
  4719. if (unlikely(err)) {
  4720. WL_ERR(("Error (%d)\n", err));
  4721. return err;
  4722. }
  4723. } else
  4724. bzero(&join_params.params.bssid, ETHER_ADDR_LEN);
  4725. if (IBSS_INITIAL_SCAN_ALLOWED == FALSE) {
  4726. scan_suppress = TRUE;
  4727. /* Set the SCAN SUPPRESS Flag in the firmware to skip join scan */
  4728. err = wldev_ioctl_set(dev, WLC_SET_SCANSUPPRESS,
  4729. &scan_suppress, sizeof(int));
  4730. if (unlikely(err)) {
  4731. WL_ERR(("Scan Suppress Setting Failed (%d)\n", err));
  4732. return err;
  4733. }
  4734. }
  4735. join_params.params.chanspec_list[0] = chanspec;
  4736. join_params.params.chanspec_num = 1;
  4737. wldev_iovar_setint(dev, "chanspec", chanspec);
  4738. join_params_size = sizeof(join_params);
  4739. /* Disable Authentication, IBSS will add key if it required */
  4740. wldev_iovar_setint(dev, "wpa_auth", WPA_AUTH_DISABLED);
  4741. wldev_iovar_setint(dev, "wsec", 0);
  4742. err = wldev_ioctl_set(dev, WLC_SET_SSID, &join_params,
  4743. join_params_size);
  4744. if (unlikely(err)) {
  4745. WL_ERR(("IBSS set_ssid Error (%d)\n", err));
  4746. return err;
  4747. }
  4748. if (IBSS_INITIAL_SCAN_ALLOWED == FALSE) {
  4749. scan_suppress = FALSE;
  4750. /* Reset the SCAN SUPPRESS Flag */
  4751. err = wldev_ioctl_set(dev, WLC_SET_SCANSUPPRESS,
  4752. &scan_suppress, sizeof(int));
  4753. if (unlikely(err)) {
  4754. WL_ERR(("Reset Scan Suppress Flag Failed (%d)\n", err));
  4755. return err;
  4756. }
  4757. }
  4758. wl_update_prof(cfg, dev, NULL, &join_params.ssid, WL_PROF_SSID);
  4759. wl_update_prof(cfg, dev, NULL, &cfg->channel, WL_PROF_CHAN);
  4760. #ifdef WLAIBSS
  4761. cfg->aibss_txfail_seq = 0; /* initialize the sequence */
  4762. #endif /* WLAIBSS */
  4763. #ifdef WL_RELMCAST
  4764. cfg->rmc_event_seq = 0; /* initialize rmcfail sequence */
  4765. #endif /* WL_RELMCAST */
  4766. return err;
  4767. }
  4768. static s32 wl_cfg80211_leave_ibss(struct wiphy *wiphy, struct net_device *dev)
  4769. {
  4770. struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
  4771. s32 err = 0;
  4772. scb_val_t scbval;
  4773. u8 *curbssid;
  4774. RETURN_EIO_IF_NOT_UP(cfg);
  4775. wl_link_down(cfg);
  4776. WL_INFORM_MEM(("Leave IBSS\n"));
  4777. curbssid = wl_read_prof(cfg, dev, WL_PROF_BSSID);
  4778. wl_set_drv_status(cfg, DISCONNECTING, dev);
  4779. scbval.val = 0;
  4780. memcpy(&scbval.ea, curbssid, ETHER_ADDR_LEN);
  4781. err = wldev_ioctl_set(dev, WLC_DISASSOC, &scbval,
  4782. sizeof(scb_val_t));
  4783. if (unlikely(err)) {
  4784. wl_clr_drv_status(cfg, DISCONNECTING, dev);
  4785. WL_ERR(("error(%d)\n", err));
  4786. return err;
  4787. }
  4788. /* remove the VSIE */
  4789. wl_cfg80211_ibss_vsie_delete(dev);
  4790. return err;
  4791. }
  4792. #ifdef MFP
  4793. static
  4794. int wl_cfg80211_get_rsn_capa(const bcm_tlv_t *wpa2ie,
  4795. const u8** rsn_cap)
  4796. {
  4797. u16 suite_count;
  4798. const wpa_suite_mcast_t *mcast;
  4799. const wpa_suite_ucast_t *ucast;
  4800. int len;
  4801. const wpa_suite_auth_key_mgmt_t *mgmt;
  4802. if (!wpa2ie)
  4803. return BCME_BADARG;
  4804. len = wpa2ie->len;
  4805. /* check for Multicast cipher suite */
  4806. if ((len -= (WPA_SUITE_LEN + WPA2_VERSION_LEN)) <= 0) {
  4807. return BCME_NOTFOUND;
  4808. }
  4809. mcast = (const wpa_suite_mcast_t *)&wpa2ie->data[WPA2_VERSION_LEN];
  4810. /* Check for the unicast suite(s) */
  4811. if (len < WPA_IE_SUITE_COUNT_LEN) {
  4812. return BCME_NOTFOUND;
  4813. }
  4814. ucast = (const wpa_suite_ucast_t *)&mcast[1];
  4815. suite_count = ltoh16_ua(&ucast->count);
  4816. if ((suite_count > NL80211_MAX_NR_CIPHER_SUITES) ||
  4817. (len -= (WPA_IE_SUITE_COUNT_LEN +
  4818. (WPA_SUITE_LEN * suite_count))) <= 0)
  4819. return BCME_BADLEN;
  4820. /* Check for AUTH key management suite(s) */
  4821. if (len < WPA_IE_SUITE_COUNT_LEN) {
  4822. return BCME_NOTFOUND;
  4823. }
  4824. mgmt = (const wpa_suite_auth_key_mgmt_t *)&ucast->list[suite_count];
  4825. suite_count = ltoh16_ua(&mgmt->count);
  4826. if ((suite_count <= NL80211_MAX_NR_CIPHER_SUITES) &&
  4827. (len -= (WPA_IE_SUITE_COUNT_LEN +
  4828. (WPA_SUITE_LEN * suite_count))) >= RSN_CAP_LEN) {
  4829. rsn_cap[0] = (const u8 *)&mgmt->list[suite_count];
  4830. } else {
  4831. return BCME_BADLEN;
  4832. }
  4833. return BCME_OK;
  4834. }
  4835. #endif /* MFP */
  4836. static s32
  4837. wl_set_wpa_version(struct net_device *dev, struct cfg80211_connect_params *sme)
  4838. {
  4839. struct bcm_cfg80211 *cfg = wl_get_cfg(dev);
  4840. struct wl_security *sec;
  4841. s32 val = 0;
  4842. s32 err = 0;
  4843. s32 bssidx;
  4844. if ((bssidx = wl_get_bssidx_by_wdev(cfg, dev->ieee80211_ptr)) < 0) {
  4845. WL_ERR(("Find p2p index from wdev(%p) failed\n", dev->ieee80211_ptr));
  4846. return BCME_ERROR;
  4847. }
  4848. if (sme->crypto.wpa_versions & NL80211_WPA_VERSION_1)
  4849. val = WPA_AUTH_PSK |
  4850. WPA_AUTH_UNSPECIFIED;
  4851. else if (sme->crypto.wpa_versions & NL80211_WPA_VERSION_2)
  4852. #ifdef WL_SAE
  4853. if (sme->crypto.akm_suites[0] == WLAN_AKM_SUITE_SAE)
  4854. val = WPA3_AUTH_SAE_PSK;
  4855. else
  4856. #endif /* WL_SAE */
  4857. val = WPA2_AUTH_PSK |
  4858. WPA2_AUTH_UNSPECIFIED;
  4859. #ifdef WL_SAE
  4860. else if (sme->crypto.wpa_versions & NL80211_WPA_VERSION_3)
  4861. val = WPA3_AUTH_SAE_PSK;
  4862. #endif /* WL_SAE */
  4863. else
  4864. val = WPA_AUTH_DISABLED;
  4865. if (is_wps_conn(sme))
  4866. val = WPA_AUTH_DISABLED;
  4867. #ifdef BCMWAPI_WPI
  4868. if (sme->crypto.wpa_versions & NL80211_WAPI_VERSION_1) {
  4869. WL_DBG((" * wl_set_wpa_version, set wpa_auth"
  4870. " to WPA_AUTH_WAPI 0x400"));
  4871. val = WAPI_AUTH_PSK | WAPI_AUTH_UNSPECIFIED;
  4872. }
  4873. #endif // endif
  4874. WL_INFORM_MEM(("[%s] wl wpa_auth 0x%0x\n", dev->name, val));
  4875. err = wldev_iovar_setint_bsscfg(dev, "wpa_auth", val, bssidx);
  4876. if (unlikely(err)) {
  4877. WL_ERR(("set wpa_auth failed (%d)\n", err));
  4878. return err;
  4879. }
  4880. sec = wl_read_prof(cfg, dev, WL_PROF_SEC);
  4881. sec->wpa_versions = sme->crypto.wpa_versions;
  4882. return err;
  4883. }
  4884. #ifdef BCMWAPI_WPI
  4885. static s32
  4886. wl_set_set_wapi_ie(struct net_device *dev, struct cfg80211_connect_params *sme)
  4887. {
  4888. struct bcm_cfg80211 *cfg = wl_get_cfg(dev);
  4889. s32 err = 0;
  4890. s32 bssidx;
  4891. WL_DBG((" wl_set_set_wapi_ie\n"));
  4892. if ((bssidx = wl_get_bssidx_by_wdev(cfg, dev->ieee80211_ptr)) < 0) {
  4893. WL_ERR(("Find p2p index from wdev(%p) failed\n", dev->ieee80211_ptr));
  4894. return BCME_ERROR;
  4895. }
  4896. err = wldev_iovar_setbuf_bsscfg(dev, "wapiie", (const void *)sme->ie, sme->ie_len,
  4897. cfg->ioctl_buf, WLC_IOCTL_MAXLEN, bssidx, &cfg->ioctl_buf_sync);
  4898. if (unlikely(err)) {
  4899. WL_ERR(("set_wapi_ie Error (%d)\n", err));
  4900. return err;
  4901. }
  4902. WL_INFORM_MEM(("wapi_ie successfully (%s)\n", dev->name));
  4903. return err;
  4904. }
  4905. #endif /* BCMWAPI_WPI */
  4906. static s32
  4907. wl_set_auth_type(struct net_device *dev, struct cfg80211_connect_params *sme)
  4908. {
  4909. struct bcm_cfg80211 *cfg = wl_get_cfg(dev);
  4910. struct wl_security *sec;
  4911. s32 val = 0;
  4912. s32 err = 0;
  4913. s32 bssidx;
  4914. if ((bssidx = wl_get_bssidx_by_wdev(cfg, dev->ieee80211_ptr)) < 0) {
  4915. WL_ERR(("Find p2p index from wdev(%p) failed\n", dev->ieee80211_ptr));
  4916. return BCME_ERROR;
  4917. }
  4918. switch (sme->auth_type) {
  4919. case NL80211_AUTHTYPE_OPEN_SYSTEM:
  4920. val = WL_AUTH_OPEN_SYSTEM;
  4921. WL_DBG(("open system\n"));
  4922. break;
  4923. case NL80211_AUTHTYPE_SHARED_KEY:
  4924. val = WL_AUTH_SHARED_KEY;
  4925. WL_DBG(("shared key\n"));
  4926. break;
  4927. case NL80211_AUTHTYPE_AUTOMATIC:
  4928. val = WL_AUTH_OPEN_SHARED;
  4929. WL_DBG(("automatic\n"));
  4930. break;
  4931. #ifdef WL_FILS
  4932. case NL80211_AUTHTYPE_FILS_SK:
  4933. WL_DBG(("fils shared key\n"));
  4934. val = WL_AUTH_FILS_SHARED;
  4935. break;
  4936. case NL80211_AUTHTYPE_FILS_SK_PFS:
  4937. val = WL_AUTH_FILS_SHARED_PFS;
  4938. WL_DBG(("fils shared key with pfs\n"));
  4939. break;
  4940. case NL80211_AUTHTYPE_FILS_PK:
  4941. WL_DBG(("fils public key\n"));
  4942. val = WL_AUTH_FILS_PUBLIC;
  4943. break;
  4944. #endif /* WL_FILS */
  4945. #ifdef WL_SAE
  4946. case NL80211_AUTHTYPE_SAE:
  4947. WL_DBG(("SAE authentication\n"));
  4948. val = WL_AUTH_SAE;
  4949. break;
  4950. #endif /* WL_SAE */
  4951. default:
  4952. val = 2;
  4953. WL_ERR(("invalid auth type (%d)\n", sme->auth_type));
  4954. break;
  4955. }
  4956. WL_INFORM_MEM(("[%s] wl auth 0x%0x \n", dev->name, val));
  4957. err = wldev_iovar_setint_bsscfg(dev, "auth", val, bssidx);
  4958. if (unlikely(err)) {
  4959. WL_ERR(("set auth failed (%d)\n", err));
  4960. return err;
  4961. }
  4962. sec = wl_read_prof(cfg, dev, WL_PROF_SEC);
  4963. sec->auth_type = sme->auth_type;
  4964. return err;
  4965. }
  4966. static u32
  4967. wl_rsn_cipher_wsec_algo_lookup(uint32 cipher)
  4968. {
  4969. uint i;
  4970. for (i = 0; i < ARRAYSIZE(rsn_cipher_algo_lookup_tbl); i++) {
  4971. if (cipher == rsn_cipher_algo_lookup_tbl[i].cipher_suite) {
  4972. return rsn_cipher_algo_lookup_tbl[i].wsec_algo;
  4973. }
  4974. }
  4975. return WSEC_NONE;
  4976. }
  4977. static u32
  4978. wl_rsn_cipher_wsec_key_algo_lookup(uint32 cipher)
  4979. {
  4980. uint i;
  4981. for (i = 0; i < ARRAYSIZE(rsn_cipher_algo_lookup_tbl); i++) {
  4982. if (cipher == rsn_cipher_algo_lookup_tbl[i].cipher_suite) {
  4983. return rsn_cipher_algo_lookup_tbl[i].wsec_key_algo;
  4984. }
  4985. }
  4986. return CRYPTO_ALGO_OFF;
  4987. }
  4988. static u32
  4989. wl_rsn_akm_wpa_auth_lookup(uint32 akm)
  4990. {
  4991. uint i;
  4992. for (i = 0; i < ARRAYSIZE(rsn_akm_wpa_auth_lookup_tbl); i++) {
  4993. if (akm == rsn_akm_wpa_auth_lookup_tbl[i].akm_suite) {
  4994. return rsn_akm_wpa_auth_lookup_tbl[i].wpa_auth;
  4995. }
  4996. }
  4997. return WPA_AUTH_DISABLED;
  4998. }
  4999. static s32
  5000. wl_set_set_cipher(struct net_device *dev, struct cfg80211_connect_params *sme)
  5001. {
  5002. struct bcm_cfg80211 *cfg = wl_get_cfg(dev);
  5003. struct wl_security *sec;
  5004. s32 pval = 0;
  5005. s32 gval = 0;
  5006. s32 err = 0;
  5007. s32 wsec_val = 0;
  5008. #ifdef BCMWAPI_WPI
  5009. s32 wapi_val = 0;
  5010. s32 val = 0;
  5011. #endif // endif
  5012. s32 bssidx;
  5013. #ifdef WL_GCMP
  5014. uint32 algos = 0, mask = 0;
  5015. #endif /* WL_GCMP */
  5016. if ((bssidx = wl_get_bssidx_by_wdev(cfg, dev->ieee80211_ptr)) < 0) {
  5017. WL_ERR(("Find p2p index from wdev(%p) failed\n", dev->ieee80211_ptr));
  5018. return BCME_ERROR;
  5019. }
  5020. if (sme->crypto.n_ciphers_pairwise) {
  5021. pval = wl_rsn_cipher_wsec_algo_lookup(sme->crypto.ciphers_pairwise[0]);
  5022. if (pval == WSEC_NONE) {
  5023. WL_ERR(("invalid cipher pairwise (%d)\n", sme->crypto.ciphers_pairwise[0]));
  5024. return BCME_BADARG;
  5025. }
  5026. switch (sme->crypto.ciphers_pairwise[0]) {
  5027. #ifdef BCMWAPI_WPI
  5028. case WLAN_CIPHER_SUITE_SMS4:
  5029. val = pval;
  5030. err = wl_set_set_wapi_ie(dev, sme);
  5031. if (unlikely(err)) {
  5032. WL_DBG(("Set wapi ie failed \n"));
  5033. return err;
  5034. } else {
  5035. WL_DBG(("Set wapi ie succeded\n"));
  5036. }
  5037. wapi_val = WAPI_AUTH_PSK | WAPI_AUTH_UNSPECIFIED;
  5038. WL_INFORM_MEM(("[WAPI] wl wpa_auth to 0x%0x (%s)\n", val, dev->name));
  5039. err = wldev_iovar_setint_bsscfg(dev, "wpa_auth", wapi_val, bssidx);
  5040. if (unlikely(err)) {
  5041. WL_ERR(("set wpa_auth failed (%d)\n", err));
  5042. return err;
  5043. }
  5044. break;
  5045. #endif /* BCMWAPI_WPI */
  5046. #ifdef WL_GCMP
  5047. case WLAN_CIPHER_SUITE_GCMP:
  5048. case WLAN_CIPHER_SUITE_GCMP_256:
  5049. algos = KEY_ALGO_MASK(wl_rsn_cipher_wsec_key_algo_lookup(
  5050. sme->crypto.ciphers_pairwise[0]));
  5051. mask = algos | KEY_ALGO_MASK(CRYPTO_ALGO_AES_CCM);
  5052. break;
  5053. #endif /* WL_GCMP */
  5054. default: /* No post processing required */
  5055. break;
  5056. }
  5057. }
  5058. #if defined(BCMSUP_4WAY_HANDSHAKE)
  5059. /* Ensure in-dongle supplicant is turned on when FBT wants to do the 4-way
  5060. * handshake.
  5061. * Note that the FW feature flag only exists on kernels that support the
  5062. * FT-EAP AKM suite.
  5063. */
  5064. if (cfg->wdev->wiphy->features & NL80211_FEATURE_FW_4WAY_HANDSHAKE) {
  5065. err = wldev_iovar_setint_bsscfg(dev, "sup_wpa", 1, bssidx);
  5066. if (err) {
  5067. WL_ERR(("FBT: Error setting sup_wpa (%d)\n", err));
  5068. return err;
  5069. } else {
  5070. WL_INFORM_MEM(("idsup enabled.\n"));
  5071. }
  5072. }
  5073. #endif /* BCMSUP_4WAY_HANDSHAKE */
  5074. if (sme->crypto.cipher_group) {
  5075. gval = wl_rsn_cipher_wsec_algo_lookup(sme->crypto.cipher_group);
  5076. if (gval == WSEC_NONE) {
  5077. WL_ERR(("invalid cipher group (%d)\n", sme->crypto.cipher_group));
  5078. return BCME_BADARG;
  5079. }
  5080. switch (sme->crypto.cipher_group) {
  5081. #ifdef BCMWAPI_WPI
  5082. case WLAN_CIPHER_SUITE_SMS4:
  5083. val = gval;
  5084. break;
  5085. #endif // endif
  5086. #ifdef WL_GCMP
  5087. case WLAN_CIPHER_SUITE_GCMP:
  5088. case WLAN_CIPHER_SUITE_GCMP_256:
  5089. algos = KEY_ALGO_MASK(
  5090. wl_rsn_cipher_wsec_key_algo_lookup(sme->crypto.cipher_group));
  5091. mask = algos | KEY_ALGO_MASK(CRYPTO_ALGO_AES_CCM);
  5092. break;
  5093. #endif /* WL_GCMP */
  5094. default: /* No post processing required */
  5095. break;
  5096. }
  5097. }
  5098. WL_DBG(("pval (%d) gval (%d)\n", pval, gval));
  5099. #ifdef WL_GCMP
  5100. WL_DBG(("algos:%x, mask:%x", algos, mask));
  5101. #endif /* WL_GCMP */
  5102. if (is_wps_conn(sme)) {
  5103. if (sme->privacy) {
  5104. wsec_val = 4;
  5105. } else {
  5106. /* WPS-2.0 allows no security */
  5107. wsec_val = 0;
  5108. }
  5109. } else {
  5110. #ifdef BCMWAPI_WPI
  5111. if (sme->crypto.cipher_group == WLAN_CIPHER_SUITE_SMS4) {
  5112. WL_DBG((" NO, is_wps_conn, WAPI set to SMS4_ENABLED"));
  5113. wsec_val = val;
  5114. } else
  5115. #endif // endif
  5116. {
  5117. WL_DBG((" NO, is_wps_conn, Set pval | gval to WSEC"));
  5118. wsec_val = pval | gval;
  5119. }
  5120. }
  5121. WL_INFORM_MEM(("[%s] wl wsec 0x%x\n", dev->name, wsec_val));
  5122. err = wldev_iovar_setint_bsscfg(dev, "wsec", wsec_val, bssidx);
  5123. if (unlikely(err)) {
  5124. WL_ERR(("error (%d)\n", err));
  5125. return err;
  5126. }
  5127. #ifdef WL_GCMP
  5128. if (wl_set_wsec_info_algos(dev, algos, mask)) {
  5129. WL_ERR(("set wsec_info error (%d)\n", err));
  5130. }
  5131. #endif /* WL_GCMP */
  5132. sec = wl_read_prof(cfg, dev, WL_PROF_SEC);
  5133. sec->cipher_pairwise = sme->crypto.ciphers_pairwise[0];
  5134. sec->cipher_group = sme->crypto.cipher_group;
  5135. return err;
  5136. }
  5137. #ifdef WL_GCMP
  5138. static s32
  5139. wl_set_wsec_info_algos(struct net_device *dev, uint32 algos, uint32 mask)
  5140. {
  5141. struct bcm_cfg80211 *cfg = wl_get_cfg(dev);
  5142. s32 bssidx;
  5143. s32 err = 0;
  5144. wl_wsec_info_t *wsec_info;
  5145. bcm_xtlv_t *wsec_info_tlv;
  5146. uint16 tlv_data_len;
  5147. uint8 tlv_data[8];
  5148. uint32 param_len;
  5149. uint8 * buf;
  5150. WL_DBG(("enter.\n"));
  5151. if (!cfg) {
  5152. return BCME_ERROR;
  5153. }
  5154. if ((bssidx = wl_get_bssidx_by_wdev(cfg, dev->ieee80211_ptr)) < 0) {
  5155. WL_ERR(("Find index from wdev(%p) failed\n", dev->ieee80211_ptr));
  5156. return BCME_ERROR;
  5157. }
  5158. buf = MALLOCZ(cfg->osh, sizeof(wl_wsec_info_t) + sizeof(tlv_data));
  5159. if (!buf) {
  5160. WL_ERR(("No memory"));
  5161. return BCME_NOMEM;
  5162. }
  5163. wsec_info = (wl_wsec_info_t *)buf;
  5164. wsec_info->version = WL_WSEC_INFO_VERSION;
  5165. wsec_info_tlv = (bcm_xtlv_t *)(buf + OFFSETOF(wl_wsec_info_t, tlvs));
  5166. wsec_info->num_tlvs++;
  5167. tlv_data_len = sizeof(tlv_data);
  5168. err = memcpy_s(tlv_data, sizeof(tlv_data), &algos, sizeof(algos));
  5169. if (err) {
  5170. goto exit;
  5171. }
  5172. err = memcpy_s(tlv_data + sizeof(algos), sizeof(mask), &mask, sizeof(mask));
  5173. if (err) {
  5174. goto exit;
  5175. }
  5176. bcm_xtlv_pack_xtlv(wsec_info_tlv, WL_WSEC_INFO_BSS_ALGOS, tlv_data_len, tlv_data, 0);
  5177. param_len = OFFSETOF(wl_wsec_info_t, tlvs) + WL_WSEC_INFO_TLV_HDR_LEN + tlv_data_len;
  5178. err = wldev_iovar_setbuf_bsscfg(dev, "wsec_info", wsec_info, param_len,
  5179. cfg->ioctl_buf, WLC_IOCTL_MAXLEN, bssidx, &cfg->ioctl_buf_sync);
  5180. exit:
  5181. MFREE(cfg->osh, buf, sizeof(wl_wsec_info_t) + sizeof(tlv_data));
  5182. return err;
  5183. }
  5184. #endif /* WL_GCMP */
  5185. #ifdef MFP
  5186. static s32
  5187. wl_cfg80211_set_mfp(struct bcm_cfg80211 *cfg,
  5188. struct net_device *dev,
  5189. struct cfg80211_connect_params *sme)
  5190. {
  5191. s32 mfp = WL_MFP_NONE;
  5192. s32 current_mfp = WL_MFP_NONE;
  5193. const bcm_tlv_t *wpa2_ie;
  5194. const u8* rsn_cap = NULL;
  5195. bool fw_support = false;
  5196. int err, count = 0;
  5197. const u8 *eptr = NULL, *ptr = NULL;
  5198. const u8* group_mgmt_cs = NULL;
  5199. const wpa_pmkid_list_t* pmkid = NULL;
  5200. if (!sme) {
  5201. /* No connection params from userspace, Do nothing. */
  5202. return 0;
  5203. }
  5204. /* Check fw support and retreive current mfp val */
  5205. err = wldev_iovar_getint(dev, "mfp", &current_mfp);
  5206. if (!err) {
  5207. fw_support = true;
  5208. }
  5209. /* Parse the wpa2ie to decode the MFP capablity */
  5210. if (((wpa2_ie = bcm_parse_tlvs((const u8 *)sme->ie, sme->ie_len,
  5211. DOT11_MNG_RSN_ID)) != NULL) &&
  5212. (wl_cfg80211_get_rsn_capa(wpa2_ie, &rsn_cap) == 0) && rsn_cap) {
  5213. WL_DBG(("rsn_cap 0x%x%x\n", rsn_cap[0], rsn_cap[1]));
  5214. /* Check for MFP cap in the RSN capability field */
  5215. #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0))
  5216. if (sme->mfp)
  5217. #endif // endif
  5218. {
  5219. if (rsn_cap[0] & RSN_CAP_MFPR) {
  5220. mfp = WL_MFP_REQUIRED;
  5221. } else if (rsn_cap[0] & RSN_CAP_MFPC) {
  5222. mfp = WL_MFP_CAPABLE;
  5223. }
  5224. }
  5225. /*
  5226. * eptr --> end/last byte addr of wpa2_ie
  5227. * ptr --> to keep track of current/required byte addr
  5228. */
  5229. eptr = (const u8*)wpa2_ie + (wpa2_ie->len + TLV_HDR_LEN);
  5230. /* pointing ptr to the next byte after rns_cap */
  5231. ptr = (const u8*)rsn_cap + RSN_CAP_LEN;
  5232. if (mfp && (eptr - ptr) >= WPA2_PMKID_COUNT_LEN) {
  5233. /* pmkid now to point to 1st byte addr of pmkid in wpa2_ie */
  5234. pmkid = (const wpa_pmkid_list_t*)ptr;
  5235. count = pmkid->count.low | (pmkid->count.high << 8);
  5236. /* ptr now to point to last byte addr of pmkid */
  5237. ptr = (const u8*)pmkid + (count * WPA2_PMKID_LEN
  5238. + WPA2_PMKID_COUNT_LEN);
  5239. if ((eptr - ptr) >= WPA_SUITE_LEN) {
  5240. /* group_mgmt_cs now to point to first byte addr of bip */
  5241. group_mgmt_cs = ptr;
  5242. }
  5243. }
  5244. }
  5245. WL_DBG(("mfp:%d wpa2_ie ptr:%p mfp fw_support:%d\n",
  5246. mfp, wpa2_ie, fw_support));
  5247. if (fw_support == false) {
  5248. if (mfp) {
  5249. /* if mfp > 0, mfp capability set in wpa ie, but
  5250. * FW indicated error for mfp. Propagate the error up.
  5251. */
  5252. WL_ERR(("mfp capability found in wpaie. But fw doesn't"
  5253. "seem to support MFP\n"));
  5254. err = -EINVAL;
  5255. goto exit;
  5256. } else {
  5257. /* Firmware doesn't support mfp. But since connection request
  5258. * is for non-mfp case, don't bother.
  5259. */
  5260. err = BCME_OK;
  5261. goto exit;
  5262. }
  5263. } else if (mfp != current_mfp) {
  5264. err = wldev_iovar_setint(dev, "mfp", mfp);
  5265. if (unlikely(err)) {
  5266. WL_ERR(("mfp (%d) set failed ret:%d \n", mfp, err));
  5267. goto exit;
  5268. }
  5269. WL_INFORM_MEM(("[%s] wl mfp 0x%x\n", dev->name, mfp));
  5270. }
  5271. if (group_mgmt_cs && bcmp((const uint8 *)WPA2_OUI,
  5272. group_mgmt_cs, (WPA_SUITE_LEN - 1)) == 0) {
  5273. WL_DBG(("BIP is found\n"));
  5274. err = wldev_iovar_setbuf(dev, "bip",
  5275. group_mgmt_cs, WPA_SUITE_LEN, cfg->ioctl_buf,
  5276. WLC_IOCTL_SMLEN, &cfg->ioctl_buf_sync);
  5277. /*
  5278. * Dont return failure for unsupported cases
  5279. * of bip iovar for backward compatibility
  5280. */
  5281. if (err != BCME_UNSUPPORTED && err < 0) {
  5282. WL_ERR(("bip set error (%d)\n", err));
  5283. #if defined(IGUANA_LEGACY_CHIPS)
  5284. if (wl_customer6_legacy_chip_check(cfg,
  5285. bcmcfg_to_prmry_ndev(cfg))) {
  5286. /* Ignore bip error: Some older firmwares doesn't
  5287. * support bip iovar/ return BCME_NOTUP while trying
  5288. * to set bip from connect context. These firmares
  5289. * include bip in RSNIE by default. So its okay to
  5290. * ignore the error.
  5291. */
  5292. err = BCME_OK;
  5293. goto exit;
  5294. } else
  5295. #endif // endif
  5296. {
  5297. goto exit;
  5298. }
  5299. } else {
  5300. WL_INFORM_MEM(("[%s] wl bip %02X:%02X:%02X\n",
  5301. dev->name, group_mgmt_cs[0], group_mgmt_cs[1],
  5302. group_mgmt_cs[2]));
  5303. }
  5304. }
  5305. exit:
  5306. if (err) {
  5307. wl_flush_fw_log_buffer(bcmcfg_to_prmry_ndev(cfg),
  5308. FW_LOGSET_MASK_ALL);
  5309. }
  5310. return 0;
  5311. }
  5312. #endif /* MFP */
  5313. #ifdef WL_FILS
  5314. bool
  5315. wl_is_fils_supported(struct net_device *ndev)
  5316. {
  5317. s32 err;
  5318. u8 ioctl_buf[WLC_IOCTL_SMLEN] = {0};
  5319. bcm_iov_buf_t *iov_buf = (bcm_iov_buf_t *)ioctl_buf;
  5320. iov_buf->version = WL_FILS_IOV_VERSION;
  5321. err = wldev_iovar_getbuf(ndev, "fils", (uint8*)iov_buf, sizeof(bcm_iov_buf_t),
  5322. iov_buf, WLC_IOCTL_SMLEN, NULL);
  5323. if (err == BCME_UNSUPPORTED) {
  5324. WL_DBG(("FILS NOT supported\n"));
  5325. return false;
  5326. }
  5327. WL_INFORM(("FILS supported\n"));
  5328. return true;
  5329. }
  5330. #define WL_NUM_OF_TLV_IN_SET_FILS_PARAMS 4u
  5331. static s32
  5332. wl_set_fils_params(struct net_device *dev, struct cfg80211_connect_params *sme)
  5333. {
  5334. struct bcm_cfg80211 *cfg = wl_get_cfg(dev);
  5335. bcm_iov_buf_t *iov_buf = NULL;
  5336. bcm_xtlvbuf_t tbuf;
  5337. s32 err = BCME_OK;
  5338. uint32 buf_size;
  5339. if ((sme->auth_type != NL80211_AUTHTYPE_FILS_SK) &&
  5340. (sme->auth_type != NL80211_AUTHTYPE_FILS_SK_PFS) &&
  5341. (sme->auth_type != NL80211_AUTHTYPE_FILS_PK)) {
  5342. return BCME_OK;
  5343. }
  5344. if (sme->fils_erp_rrk_len > WL_MAX_FILS_KEY_LEN) {
  5345. WL_ERR(("%s: FILS rRK exceed allowed size\n", __FUNCTION__));
  5346. err = BCME_BADARG;
  5347. goto exit;
  5348. }
  5349. /* Check incoming buffer length */
  5350. buf_size = sme->fils_erp_username_len + sme->fils_erp_realm_len + sme->fils_erp_rrk_len +
  5351. sizeof(sme->fils_erp_next_seq_num) +
  5352. WL_NUM_OF_TLV_IN_SET_FILS_PARAMS * BCM_XTLV_HDR_SIZE_EX(BCM_XTLV_OPTION_ALIGN32) +
  5353. sizeof(bcm_iov_buf_t) - 1u;
  5354. if (buf_size > WLC_IOCTL_SMLEN) {
  5355. WL_ERR(("%s: FILS connect params arguments exceed allowed size\n", __FUNCTION__));
  5356. err = BCME_BADARG;
  5357. goto exit;
  5358. }
  5359. iov_buf = MALLOCZ(cfg->osh, WLC_IOCTL_SMLEN);
  5360. if (!iov_buf) {
  5361. WL_ERR(("%s: iov_buf alloc failed! %d bytes\n", __FUNCTION__, WLC_IOCTL_SMLEN));
  5362. err = BCME_NOMEM;
  5363. goto exit;
  5364. }
  5365. iov_buf->version = WL_FILS_IOV_VERSION;
  5366. iov_buf->id = WL_FILS_CMD_ADD_CONNECT_PARAMS;
  5367. /* check if this should be len w/o headers */
  5368. err = bcm_xtlv_buf_init(&tbuf, (uint8*)&iov_buf->data[0],
  5369. WLC_IOCTL_SMLEN - sizeof(bcm_iov_buf_t) + sizeof(uint16),
  5370. BCM_XTLV_OPTION_ALIGN32);
  5371. if (err != BCME_OK) {
  5372. WL_ERR(("%s: xtlv_context initialization failed\n", __FUNCTION__));
  5373. goto exit;
  5374. }
  5375. if (sme->fils_erp_username_len && sme->fils_erp_username != NULL) {
  5376. err = bcm_xtlv_put_data(&tbuf, WL_FILS_XTLV_ERP_USERNAME,
  5377. sme->fils_erp_username, sme->fils_erp_username_len);
  5378. if (err != BCME_OK) {
  5379. WL_ERR(("%s: write xtlv failed\n", __FUNCTION__));
  5380. goto exit;
  5381. }
  5382. }
  5383. if (sme->fils_erp_realm_len && sme->fils_erp_realm != NULL) {
  5384. err = bcm_xtlv_put_data(&tbuf, WL_FILS_XTLV_ERP_REALM,
  5385. sme->fils_erp_realm, sme->fils_erp_realm_len);
  5386. if (err != BCME_OK) {
  5387. WL_ERR(("%s: write xtlv failed\n", __FUNCTION__));
  5388. goto exit;
  5389. }
  5390. }
  5391. if (sme->fils_erp_rrk_len && sme->fils_erp_rrk != NULL) {
  5392. err = bcm_xtlv_put_data(&tbuf, WL_FILS_XTLV_ERP_RRK,
  5393. sme->fils_erp_rrk, sme->fils_erp_rrk_len);
  5394. if (err != BCME_OK) {
  5395. WL_ERR(("%s: write xtlv failed\n", __FUNCTION__));
  5396. goto exit;
  5397. }
  5398. }
  5399. err = bcm_xtlv_put_data(&tbuf, WL_FILS_XTLV_ERP_NEXT_SEQ_NUM,
  5400. (u8 *)&sme->fils_erp_next_seq_num, sizeof(sme->fils_erp_next_seq_num));
  5401. if (err != BCME_OK) {
  5402. WL_ERR(("%s: write xtlv failed\n", __FUNCTION__));
  5403. goto exit;
  5404. }
  5405. iov_buf->len = bcm_xtlv_buf_len(&tbuf);
  5406. err = wldev_iovar_setbuf(dev, "fils", iov_buf, iov_buf->len + sizeof(bcm_iov_buf_t) -
  5407. sizeof(uint16), cfg->ioctl_buf, WLC_IOCTL_SMLEN, &cfg->ioctl_buf_sync);
  5408. if (unlikely(err)) {
  5409. WL_ERR(("set fils params ioctl error (%d)\n", err));
  5410. goto exit;
  5411. }
  5412. exit:
  5413. if (err != BCME_OK) {
  5414. WL_ERR(("set FILS params error %d\n", err));
  5415. }
  5416. else {
  5417. WL_INFORM_MEM(("FILS parameters succesfully applied\n"));
  5418. }
  5419. if (iov_buf) {
  5420. MFREE(cfg->osh, iov_buf, WLC_IOCTL_SMLEN);
  5421. }
  5422. return err;
  5423. }
  5424. #if !defined(WL_FILS_ROAM_OFFLD) && defined(WL_FILS)
  5425. static s32
  5426. wl_get_bcn_timeout(struct net_device *dev, u32 *bcn_timeout)
  5427. {
  5428. s32 err = 0;
  5429. err = wldev_iovar_getint(dev, "bcn_timeout", bcn_timeout);
  5430. if (unlikely(err)) {
  5431. WL_ERR(("could not get bcn_timeout (%d)\n", err));
  5432. }
  5433. return err;
  5434. }
  5435. #define WL_ROAM_ENABLE 0
  5436. #define WL_ROAM_DISABLE 1
  5437. /* Beacon Timeout beacon loss in case FILS roaming offload is not supported by fw */
  5438. #define WL_BCN_TIMEOUT 3
  5439. static s32
  5440. wl_fils_toggle_roaming(struct net_device *dev, u32 auth_type)
  5441. {
  5442. s32 err = 0;
  5443. struct bcm_cfg80211 *cfg = wl_get_cfg(dev);
  5444. if (WPA2_AUTH_IS_FILS(auth_type) && !cfg->fils_info.fils_roam_disabled) {
  5445. err = wl_get_bcn_timeout(dev, &cfg->fils_info.fils_bcn_timeout_cache);
  5446. if (unlikely(err)) {
  5447. return err;
  5448. }
  5449. wl_dongle_roam(dev, WL_ROAM_DISABLE, WL_BCN_TIMEOUT);
  5450. cfg->fils_info.fils_roam_disabled = true;
  5451. WL_INFORM_MEM(("fw roam disabled for FILS akm\n"));
  5452. } else if (cfg->fils_info.fils_roam_disabled) {
  5453. /* Enable roaming back for other auth types */
  5454. wl_dongle_roam(dev, WL_ROAM_ENABLE, cfg->fils_info.fils_bcn_timeout_cache);
  5455. cfg->fils_info.fils_roam_disabled = false;
  5456. WL_INFORM_MEM(("fw roam enabled\n"));
  5457. }
  5458. return err;
  5459. }
  5460. #endif /* !WL_FILS_ROAM_OFFLD && WL_FILS */
  5461. #endif /* WL_FILS */
  5462. static s32
  5463. wl_set_key_mgmt(struct net_device *dev, struct cfg80211_connect_params *sme)
  5464. {
  5465. struct bcm_cfg80211 *cfg = wl_get_cfg(dev);
  5466. struct wl_security *sec;
  5467. s32 val = 0;
  5468. s32 err = 0;
  5469. s32 bssidx;
  5470. if ((bssidx = wl_get_bssidx_by_wdev(cfg, dev->ieee80211_ptr)) < 0) {
  5471. WL_ERR(("Find p2p index from wdev(%p) failed\n", dev->ieee80211_ptr));
  5472. return BCME_ERROR;
  5473. }
  5474. if (sme->crypto.n_akm_suites) {
  5475. err = wldev_iovar_getint(dev, "wpa_auth", &val);
  5476. if (unlikely(err)) {
  5477. WL_ERR(("could not get wpa_auth (%d)\n", err));
  5478. return err;
  5479. }
  5480. if (val & (WPA_AUTH_PSK |
  5481. WPA_AUTH_UNSPECIFIED)) {
  5482. switch (sme->crypto.akm_suites[0]) {
  5483. case WLAN_AKM_SUITE_8021X:
  5484. val = WPA_AUTH_UNSPECIFIED;
  5485. break;
  5486. case WLAN_AKM_SUITE_PSK:
  5487. val = WPA_AUTH_PSK;
  5488. break;
  5489. default:
  5490. WL_ERR(("invalid akm suite (0x%x)\n",
  5491. sme->crypto.akm_suites[0]));
  5492. return -EINVAL;
  5493. }
  5494. } else if (val & (WPA2_AUTH_PSK |
  5495. WPA2_AUTH_UNSPECIFIED)) {
  5496. switch (sme->crypto.akm_suites[0]) {
  5497. #ifdef MFP
  5498. #if defined(IGUANA_LEGACY_CHIPS)
  5499. case WL_AKM_SUITE_SHA256_1X:
  5500. if (wl_customer6_legacy_chip_check(cfg, dev)) {
  5501. val = WPA2_AUTH_UNSPECIFIED;
  5502. } else {
  5503. val = WPA2_AUTH_1X_SHA256;
  5504. }
  5505. break;
  5506. case WL_AKM_SUITE_SHA256_PSK:
  5507. if (wl_customer6_legacy_chip_check(cfg, dev)) {
  5508. val = WPA2_AUTH_PSK;
  5509. } else {
  5510. val = WPA2_AUTH_PSK_SHA256;
  5511. }
  5512. break;
  5513. #else
  5514. case WL_AKM_SUITE_SHA256_1X:
  5515. val = WPA2_AUTH_1X_SHA256;
  5516. break;
  5517. case WL_AKM_SUITE_SHA256_PSK:
  5518. val = WPA2_AUTH_PSK_SHA256;
  5519. break;
  5520. #endif // endif
  5521. #endif /* MFP */
  5522. case WLAN_AKM_SUITE_8021X:
  5523. case WLAN_AKM_SUITE_PSK:
  5524. #if defined(WLFBT) && defined(WLAN_AKM_SUITE_FT_8021X)
  5525. case WLAN_AKM_SUITE_FT_8021X:
  5526. #endif // endif
  5527. #if defined(WLFBT) && defined(WLAN_AKM_SUITE_FT_PSK)
  5528. case WLAN_AKM_SUITE_FT_PSK:
  5529. #endif // endif
  5530. case WLAN_AKM_SUITE_FILS_SHA256:
  5531. case WLAN_AKM_SUITE_FILS_SHA384:
  5532. case WLAN_AKM_SUITE_8021X_SUITE_B:
  5533. case WLAN_AKM_SUITE_8021X_SUITE_B_192:
  5534. #ifdef WL_OWE
  5535. case WLAN_AKM_SUITE_OWE:
  5536. #endif /* WL_OWE */
  5537. #ifdef WL_SAE
  5538. case WLAN_AKM_SUITE_SAE:
  5539. #endif /* WL_SAE */
  5540. case WLAN_AKM_SUITE_DPP:
  5541. case WLAN_AKM_SUITE_FT_8021X_SHA384:
  5542. val = wl_rsn_akm_wpa_auth_lookup(sme->crypto.akm_suites[0]);
  5543. break;
  5544. case WLAN_AKM_SUITE_FT_FILS_SHA256:
  5545. val = WPA2_AUTH_FILS_SHA256 | WPA2_AUTH_FT;
  5546. break;
  5547. case WLAN_AKM_SUITE_FT_FILS_SHA384:
  5548. val = WPA2_AUTH_FILS_SHA384 | WPA2_AUTH_FT;
  5549. break;
  5550. default:
  5551. WL_ERR(("invalid akm suite (0x%x)\n",
  5552. sme->crypto.akm_suites[0]));
  5553. return -EINVAL;
  5554. }
  5555. }
  5556. #ifdef BCMWAPI_WPI
  5557. else if (val & (WAPI_AUTH_PSK | WAPI_AUTH_UNSPECIFIED)) {
  5558. switch (sme->crypto.akm_suites[0]) {
  5559. case WLAN_AKM_SUITE_WAPI_CERT:
  5560. val = WAPI_AUTH_UNSPECIFIED;
  5561. break;
  5562. case WLAN_AKM_SUITE_WAPI_PSK:
  5563. val = WAPI_AUTH_PSK;
  5564. break;
  5565. default:
  5566. WL_ERR(("invalid akm suite (0x%x)\n",
  5567. sme->crypto.akm_suites[0]));
  5568. return -EINVAL;
  5569. }
  5570. }
  5571. #endif // endif
  5572. #ifdef WL_FILS
  5573. #if !defined(WL_FILS_ROAM_OFFLD)
  5574. err = wl_fils_toggle_roaming(dev, val);
  5575. if (unlikely(err)) {
  5576. return err;
  5577. }
  5578. #endif /* !WL_FILS_ROAM_OFFLD */
  5579. #endif /* !WL_FILS */
  5580. #ifdef MFP
  5581. if ((err = wl_cfg80211_set_mfp(cfg, dev, sme)) < 0) {
  5582. WL_ERR(("MFP set failed err:%d\n", err));
  5583. return -EINVAL;
  5584. }
  5585. #endif /* MFP */
  5586. WL_INFORM_MEM(("[%s] wl wpa_auth to 0x%x\n", dev->name, val));
  5587. err = wldev_iovar_setint_bsscfg(dev, "wpa_auth", val, bssidx);
  5588. if (unlikely(err)) {
  5589. WL_ERR(("could not set wpa_auth (0x%x)\n", err));
  5590. return err;
  5591. }
  5592. }
  5593. sec = wl_read_prof(cfg, dev, WL_PROF_SEC);
  5594. sec->wpa_auth = sme->crypto.akm_suites[0];
  5595. return err;
  5596. }
  5597. static s32
  5598. wl_set_set_sharedkey(struct net_device *dev,
  5599. struct cfg80211_connect_params *sme)
  5600. {
  5601. struct bcm_cfg80211 *cfg = wl_get_cfg(dev);
  5602. struct wl_security *sec;
  5603. struct wl_wsec_key key;
  5604. s32 val;
  5605. s32 err = 0;
  5606. s32 bssidx;
  5607. if ((bssidx = wl_get_bssidx_by_wdev(cfg, dev->ieee80211_ptr)) < 0) {
  5608. WL_ERR(("Find p2p index from wdev(%p) failed\n", dev->ieee80211_ptr));
  5609. return BCME_ERROR;
  5610. }
  5611. WL_DBG(("key len (%d)\n", sme->key_len));
  5612. if (sme->key_len) {
  5613. sec = wl_read_prof(cfg, dev, WL_PROF_SEC);
  5614. WL_DBG(("wpa_versions 0x%x cipher_pairwise 0x%x\n",
  5615. sec->wpa_versions, sec->cipher_pairwise));
  5616. if (!(sec->wpa_versions & (NL80211_WPA_VERSION_1 |
  5617. NL80211_WPA_VERSION_2)) &&
  5618. #ifdef BCMWAPI_WPI
  5619. !is_wapi(sec->cipher_pairwise) &&
  5620. #endif // endif
  5621. (sec->cipher_pairwise & (WLAN_CIPHER_SUITE_WEP40 |
  5622. WLAN_CIPHER_SUITE_WEP104)))
  5623. {
  5624. bzero(&key, sizeof(key));
  5625. key.len = (u32) sme->key_len;
  5626. key.index = (u32) sme->key_idx;
  5627. if (unlikely(key.len > sizeof(key.data))) {
  5628. WL_ERR(("Too long key length (%u)\n", key.len));
  5629. return -EINVAL;
  5630. }
  5631. memcpy(key.data, sme->key, key.len);
  5632. key.flags = WL_PRIMARY_KEY;
  5633. if ((sec->cipher_pairwise == WLAN_CIPHER_SUITE_WEP40) ||
  5634. (sec->cipher_pairwise == WLAN_CIPHER_SUITE_WEP104)) {
  5635. key.algo = wl_rsn_cipher_wsec_key_algo_lookup(sec->cipher_pairwise);
  5636. } else {
  5637. WL_ERR(("Invalid algorithm (%d)\n",
  5638. sme->crypto.ciphers_pairwise[0]));
  5639. return -EINVAL;
  5640. }
  5641. /* Set the new key/index */
  5642. WL_DBG(("key length (%d) key index (%d) algo (%d)\n",
  5643. key.len, key.index, key.algo));
  5644. WL_DBG(("key \"%s\"\n", key.data));
  5645. swap_key_from_BE(&key);
  5646. err = wldev_iovar_setbuf_bsscfg(dev, "wsec_key", &key, sizeof(key),
  5647. cfg->ioctl_buf, WLC_IOCTL_MAXLEN, bssidx, &cfg->ioctl_buf_sync);
  5648. if (unlikely(err)) {
  5649. WL_ERR(("WLC_SET_KEY error (%d)\n", err));
  5650. return err;
  5651. }
  5652. WL_INFORM_MEM(("key applied to fw\n"));
  5653. if (sec->auth_type == NL80211_AUTHTYPE_SHARED_KEY) {
  5654. WL_DBG(("set auth_type to shared key\n"));
  5655. val = WL_AUTH_SHARED_KEY; /* shared key */
  5656. err = wldev_iovar_setint_bsscfg(dev, "auth", val, bssidx);
  5657. if (unlikely(err)) {
  5658. WL_ERR(("set auth failed (%d)\n", err));
  5659. return err;
  5660. }
  5661. }
  5662. }
  5663. }
  5664. return err;
  5665. }
  5666. #if defined(ESCAN_RESULT_PATCH)
  5667. static u8 connect_req_bssid[6];
  5668. static u8 broad_bssid[6];
  5669. #endif /* ESCAN_RESULT_PATCH */
  5670. #if defined(CUSTOM_SET_CPUCORE) || defined(CONFIG_TCPACK_FASTTX)
  5671. static bool wl_get_chan_isvht80(struct net_device *net, dhd_pub_t *dhd)
  5672. {
  5673. u32 chanspec = 0;
  5674. bool isvht80 = 0;
  5675. if (wldev_iovar_getint(net, "chanspec", (s32 *)&chanspec) == BCME_OK)
  5676. chanspec = wl_chspec_driver_to_host(chanspec);
  5677. isvht80 = chanspec & WL_CHANSPEC_BW_80;
  5678. WL_DBG(("wl_get_chan_isvht80: chanspec(%x:%d)\n", chanspec, isvht80));
  5679. return isvht80;
  5680. }
  5681. #endif /* CUSTOM_SET_CPUCORE || CONFIG_TCPACK_FASTTX */
  5682. int wl_cfg80211_cleanup_mismatch_status(struct net_device *dev, struct bcm_cfg80211 *cfg,
  5683. bool disassociate)
  5684. {
  5685. scb_val_t scbval;
  5686. int err = TRUE;
  5687. int wait_cnt;
  5688. if (disassociate) {
  5689. dhd_pub_t *dhdp = (dhd_pub_t *)(cfg->pub);
  5690. BCM_REFERENCE(dhdp);
  5691. DHD_STATLOG_CTRL(dhdp, ST(DISASSOC_INT_START),
  5692. dhd_net2idx(dhdp->info, dev), DOT11_RC_DISASSOC_LEAVING);
  5693. WL_ERR(("Disassociate previous connection!\n"));
  5694. wl_set_drv_status(cfg, DISCONNECTING, dev);
  5695. scbval.val = DOT11_RC_DISASSOC_LEAVING;
  5696. scbval.val = htod32(scbval.val);
  5697. err = wldev_ioctl_set(dev, WLC_DISASSOC, &scbval,
  5698. sizeof(scb_val_t));
  5699. if (unlikely(err)) {
  5700. wl_clr_drv_status(cfg, DISCONNECTING, dev);
  5701. WL_ERR(("error (%d)\n", err));
  5702. return err;
  5703. }
  5704. wait_cnt = 500/10;
  5705. } else {
  5706. wait_cnt = 200/10;
  5707. WL_ERR(("Waiting for previous DISCONNECTING status!\n"));
  5708. if (wl_get_drv_status(cfg, DISCONNECTING, dev)) {
  5709. wl_clr_drv_status(cfg, DISCONNECTING, dev);
  5710. }
  5711. }
  5712. while (wl_get_drv_status(cfg, DISCONNECTING, dev) && wait_cnt) {
  5713. WL_DBG(("Waiting for disconnection terminated, wait_cnt: %d\n",
  5714. wait_cnt));
  5715. wait_cnt--;
  5716. OSL_SLEEP(10);
  5717. }
  5718. if (wait_cnt == 0) {
  5719. WL_ERR(("DISCONNECING clean up failed!\n"));
  5720. /* Clear DISCONNECTING driver status as we have made sufficient attempts
  5721. * for driver clean up.
  5722. */
  5723. wl_clr_drv_status(cfg, DISCONNECTING, dev);
  5724. return BCME_NOTREADY;
  5725. }
  5726. return BCME_OK;
  5727. }
  5728. #ifdef WL_FILS
  5729. static int
  5730. wl_fils_add_hlp_container(struct bcm_cfg80211 *cfg, struct net_device *dev,
  5731. const uint8* ie_buf, uint16 ie_len)
  5732. {
  5733. const bcm_tlv_ext_t *hlp_ie;
  5734. if ((hlp_ie = (const bcm_tlv_ext_t*)bcm_parse_tlvs_dot11((const uint8 *)ie_buf, ie_len,
  5735. FILS_HLP_CONTAINER_EXT_ID, TRUE))) {
  5736. u16 hlp_len = hlp_ie->len;
  5737. u16 left_len = (ie_len - ((const uint8*)hlp_ie - ie_buf));
  5738. bcm_iov_buf_t *iov_buf = 0;
  5739. uint8* pxtlv;
  5740. int err;
  5741. size_t iov_buf_len;
  5742. bcm_tlv_dot11_frag_tot_len(ie_buf, ie_len, FILS_HLP_CONTAINER_EXT_ID,
  5743. TRUE, (uint*)&hlp_len);
  5744. hlp_len += BCM_TLV_EXT_HDR_SIZE;
  5745. if ((hlp_len > DOT11_MAX_MPDU_BODY_LEN) || (hlp_len > left_len)) {
  5746. WL_ERR(("bad HLP length %d\n", hlp_len));
  5747. return EFAULT;
  5748. }
  5749. iov_buf_len = sizeof(bcm_iov_buf_t) + sizeof(bcm_xtlv_t) - 1 + hlp_len;
  5750. iov_buf = MALLOCZ(cfg->osh, iov_buf_len);
  5751. if (iov_buf == NULL) {
  5752. WL_ERR(("failed to allocated iov_buf\n"));
  5753. return ENOMEM;
  5754. }
  5755. prhex("HLP, HLP", (const uchar *)hlp_ie, hlp_len);
  5756. pxtlv = (uint8 *)&iov_buf->data[0];
  5757. ((bcm_xtlv_t*)pxtlv)->id = WL_FILS_XTLV_HLP_IE;
  5758. ((bcm_xtlv_t*)pxtlv)->len = hlp_len;
  5759. memcpy(((bcm_xtlv_t*)pxtlv)->data, hlp_ie, ((bcm_xtlv_t*)pxtlv)->len);
  5760. iov_buf->version = WL_FILS_IOV_VERSION;
  5761. iov_buf->id = WL_FILS_CMD_ADD_HLP_IE;
  5762. iov_buf->len = ((sizeof(bcm_xtlv_t)-1) + ((bcm_xtlv_t*)pxtlv)->len);
  5763. err = wldev_iovar_setbuf(dev, "fils", iov_buf,
  5764. sizeof(bcm_iov_buf_t) + iov_buf->len,
  5765. cfg->ioctl_buf, WLC_IOCTL_MAXLEN, &cfg->ioctl_buf_sync);
  5766. if (unlikely(err)) {
  5767. WL_ERR(("fils wldev_iovar_setbuf error (%d)\n", err));
  5768. }
  5769. else {
  5770. WL_INFORM_MEM(("FILS HLP Packet succesfully updated\n"));
  5771. }
  5772. MFREE(cfg->osh, iov_buf, iov_buf_len);
  5773. }
  5774. return BCME_OK;
  5775. }
  5776. #endif /* WL_FILS */
  5777. #if defined(WL_FILS)
  5778. #ifndef UPDATE_FILS_ERP_INFO
  5779. #define UPDATE_FILS_ERP_INFO BIT(1)
  5780. #define UPDATE_AUTH_TYPE BIT(2)
  5781. #endif // endif
  5782. static int
  5783. wl_cfg80211_update_connect_params(struct wiphy *wiphy, struct net_device *dev,
  5784. struct cfg80211_connect_params *sme, u32 changed)
  5785. {
  5786. s32 err = BCME_OK;
  5787. if (changed & UPDATE_FILS_ERP_INFO) {
  5788. err = wl_set_fils_params(dev, sme);
  5789. if (unlikely(err)) {
  5790. WL_ERR(("Invalid FILS params\n"));
  5791. goto exit;
  5792. }
  5793. }
  5794. if (changed & UPDATE_AUTH_TYPE) {
  5795. err = wl_set_auth_type(dev, sme);
  5796. if (unlikely(err)) {
  5797. WL_ERR(("Invalid auth type\n"));
  5798. goto exit;
  5799. }
  5800. }
  5801. if ((changed & UPDATE_FILS_ERP_INFO) && !(changed & UPDATE_AUTH_TYPE)) {
  5802. WL_DBG(("Warning: FILS ERP params are set, but authentication type - not\n"));
  5803. }
  5804. exit:
  5805. return err;
  5806. }
  5807. #endif /* WL_FILS */
  5808. #ifdef WL_SAE
  5809. static int
  5810. wl_cfg80211_external_auth(struct wiphy *wiphy, struct net_device *dev,
  5811. struct cfg80211_external_auth_params *params)
  5812. {
  5813. int ret = 0;
  5814. struct wl_auth_req_status auth_status;
  5815. u8 ioctl_buf[WLC_IOCTL_SMLEN];
  5816. WL_DBG(("Enter\n"));
  5817. if (params->status == WLAN_STATUS_SUCCESS) {
  5818. auth_status.flags = WL_EXTAUTH_SUCCESS;
  5819. } else {
  5820. WL_ERR(("External authentication failed with %d\n",
  5821. params->status));
  5822. auth_status.flags = WL_EXTAUTH_FAIL;
  5823. }
  5824. memcpy(auth_status.peer_mac.octet, params->bssid, ETH_ALEN);
  5825. auth_status.ssid_len = min_t(u8, params->ssid.ssid_len,
  5826. IEEE80211_MAX_SSID_LEN);
  5827. memcpy(auth_status.ssid, params->ssid.ssid, auth_status.ssid_len);
  5828. memset(auth_status.pmkid, 0, WLAN_PMKID_LEN);
  5829. if (params->pmkid)
  5830. memcpy(auth_status.pmkid, params->pmkid, WLAN_PMKID_LEN);
  5831. ret = wldev_iovar_setbuf(dev, "auth_status", &auth_status,
  5832. sizeof(auth_status), ioctl_buf, WLC_IOCTL_SMLEN, NULL);
  5833. if (ret < 0)
  5834. WL_ERR(("auth_status iovar failed: ret=%d\n", ret));
  5835. return ret;
  5836. }
  5837. /**
  5838. * wl_notify_extauth_req_event() - host authentication request
  5839. *
  5840. * @cfg: object to handle cfg80211 interface
  5841. * @cfgdev: represents ndev or wdev
  5842. * @e: event message. Not used, to make it usable for fweh event dispatcher
  5843. * @data: payload of message, containing auth frame data
  5844. *
  5845. */
  5846. static s32
  5847. wl_notify_extauth_req_event(struct bcm_cfg80211 *cfg,
  5848. bcm_struct_cfgdev *cfgdev, const wl_event_msg_t *e, void *data)
  5849. {
  5850. struct cfg80211_external_auth_params params;
  5851. struct wl_auth_req_status *auth_req = (struct wl_auth_req_status *)data;
  5852. struct net_device *ndev = cfgdev_to_ndev(cfgdev);
  5853. int err = 0;
  5854. WL_DBG(("EVENT: EXT_AUTH_REQ received\n"));
  5855. if (e->datalen < sizeof(*auth_req)) {
  5856. WL_ERR(("Ext auth req event data too small. Ignoring event\n"));
  5857. return -EINVAL;
  5858. }
  5859. memset(&params, 0, sizeof(params));
  5860. params.action = NL80211_EXTERNAL_AUTH_START;
  5861. params.key_mgmt_suite = ntohl(WLAN_AKM_SUITE_SAE);
  5862. params.status = WLAN_STATUS_SUCCESS;
  5863. params.ssid.ssid_len = min_t(u32, IEEE80211_MAX_SSID_LEN, auth_req->ssid_len);
  5864. memcpy(params.ssid.ssid, auth_req->ssid, params.ssid.ssid_len);
  5865. memcpy(params.bssid, auth_req->peer_mac.octet, ETH_ALEN);
  5866. err = cfg80211_external_auth_request(ndev, &params, GFP_ATOMIC);
  5867. if (err) {
  5868. WL_ERR(("EXT_AUTH_REQ to supplicant failed\n"));
  5869. }
  5870. return err;
  5871. }
  5872. /**
  5873. * wl_notify_mgmt_frame_tx_complete() - transmit mgmt frame complete
  5874. *
  5875. * @cfg: object to handle cfg80211 interface
  5876. * @cfgdev: represents ndev or wdev
  5877. * @e: event message. Not used, to make it usable for fweh event dispatcher
  5878. * @data: payload of message, containing auth frame data
  5879. *
  5880. */
  5881. static s32
  5882. wl_notify_mgmt_frame_tx_complete(struct bcm_cfg80211 *cfg,
  5883. bcm_struct_cfgdev *cfgdev, const wl_event_msg_t *e, void *data)
  5884. {
  5885. u32 event_type = ntoh32(e->event_type);
  5886. u32 status = ntoh32(e->status);
  5887. struct net_device *ndev = NULL;
  5888. u32 *packetid = (u32 *)data;
  5889. struct net_info *_net_info;
  5890. WL_DBG((" Enter\n"));
  5891. ndev = cfgdev_to_wlc_ndev(cfgdev, cfg);
  5892. _net_info = wl_get_netinfo_by_netdev(cfg, ndev);
  5893. WL_DBG(("EVENT: mgmt tx status: event %s, status=%d\n",
  5894. event_type == WLC_E_MGMT_FRAME_TXSTATUS ?
  5895. "MGMT_FRAME_TXSTATUS" : "MGMT_FRAME_OFF_CHAN_COMPLETE", e->status));
  5896. if (!test_bit(MGMT_TX_SEND_FRAME, &_net_info->mgmt_txstatus) ||
  5897. (*packetid != _net_info->mgmt_txid)) {
  5898. return 0;
  5899. }
  5900. if (event_type == WLC_E_MGMT_FRAME_TXSTATUS) {
  5901. if (status == WLC_E_STATUS_SUCCESS) {
  5902. set_bit(MGMT_TX_ACK,
  5903. &_net_info->mgmt_txstatus);
  5904. } else {
  5905. set_bit(MGMT_TX_NOACK,
  5906. &_net_info->mgmt_txstatus);
  5907. }
  5908. } else {
  5909. set_bit(MGMT_TX_OFF_CHAN_COMPLETED,
  5910. &_net_info->mgmt_txstatus);
  5911. }
  5912. complete(&_net_info->mgmt_tx_cpl);
  5913. return BCME_OK;
  5914. }
  5915. #endif /* WL_SAE */
  5916. #define MAX_SCAN_ABORT_WAIT_CNT 20
  5917. #define WAIT_SCAN_ABORT_OSL_SLEEP_TIME 10
  5918. static s32
  5919. wl_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev,
  5920. struct cfg80211_connect_params *sme)
  5921. {
  5922. struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
  5923. struct ieee80211_channel *chan = sme->channel;
  5924. wl_extjoin_params_t *ext_join_params;
  5925. struct wl_join_params join_params;
  5926. size_t join_params_size;
  5927. dhd_pub_t *dhdp = (dhd_pub_t *)(cfg->pub);
  5928. #if defined(ROAM_ENABLE) && defined(ROAM_AP_ENV_DETECTION)
  5929. s32 roam_trigger[2] = {0, 0};
  5930. #endif /* ROAM_AP_ENV_DETECTION */
  5931. s32 err = 0;
  5932. const wpa_ie_fixed_t *wpa_ie;
  5933. const bcm_tlv_t *wpa2_ie;
  5934. const u8* wpaie = 0;
  5935. u32 wpaie_len = 0;
  5936. u32 chan_cnt = 0;
  5937. struct ether_addr bssid;
  5938. s32 bssidx = -1;
  5939. #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0))
  5940. bool skip_hints = fw_ap_select;
  5941. #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0) */
  5942. #ifdef ESCAN_CHANNEL_CACHE
  5943. chanspec_t chanspec_list[MAX_ROAM_CHANNEL];
  5944. #endif /* ESCAN_CHANNEL_CACHE */
  5945. int wait_cnt;
  5946. WL_DBG(("In\n"));
  5947. if (!dev) {
  5948. WL_ERR(("dev is null\n"));
  5949. return -EINVAL;
  5950. }
  5951. BCM_REFERENCE(dhdp);
  5952. DHD_STATLOG_CTRL(dhdp, ST(ASSOC_START), dhd_net2idx(dhdp->info, dev), 0);
  5953. #ifdef ESCAN_CHANNEL_CACHE
  5954. memset(chanspec_list, 0, (sizeof(chanspec_t) * MAX_ROAM_CHANNEL));
  5955. #endif /* ESCAN_CHANNEL_CACHE */
  5956. /* Connection attempted via linux-wireless */
  5957. wl_set_drv_status(cfg, CFG80211_CONNECT, dev);
  5958. #ifdef DHDTCPSYNC_FLOOD_BLK
  5959. dhd_reset_tcpsync_info_by_dev(dev);
  5960. #endif /* DHDTCPSYNC_FLOOD_BLK */
  5961. #if defined(SUPPORT_RANDOM_MAC_SCAN)
  5962. /* Disable scanmac if enabled */
  5963. if (cfg->scanmac_enabled) {
  5964. wl_cfg80211_scan_mac_disable(dev);
  5965. }
  5966. #endif /* SUPPORT_RANDOM_MAC_SCAN */
  5967. #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0))
  5968. #if defined(WL_FW_OCE_AP_SELECT)
  5969. /* override bssid_hint for oce networks */
  5970. skip_hints = (fw_ap_select && wl_cfg80211_is_oce_ap(wiphy, sme->bssid_hint));
  5971. #endif // endif
  5972. if (skip_hints) {
  5973. /* Let fw choose the best AP */
  5974. WL_INFORM(("skipping bssid & channel hint\n"));
  5975. } else {
  5976. if (sme->channel_hint) {
  5977. chan = sme->channel_hint;
  5978. WL_INFORM_MEM(("channel_hint (%d), channel_hint center_freq (%d)\n",
  5979. ieee80211_frequency_to_channel(sme->channel_hint->center_freq),
  5980. sme->channel_hint->center_freq));
  5981. }
  5982. if (sme->bssid_hint) {
  5983. sme->bssid = sme->bssid_hint;
  5984. WL_INFORM_MEM(("bssid_hint "MACDBG" \n", MAC2STRDBG(sme->bssid_hint)));
  5985. }
  5986. }
  5987. #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0) */
  5988. if (unlikely(!sme->ssid)) {
  5989. WL_ERR(("Invalid ssid\n"));
  5990. return -EOPNOTSUPP;
  5991. }
  5992. if (unlikely(sme->ssid_len > DOT11_MAX_SSID_LEN)) {
  5993. WL_ERR(("Invalid SSID info: SSID=%s, length=%zd\n",
  5994. sme->ssid, sme->ssid_len));
  5995. return -EINVAL;
  5996. }
  5997. WL_DBG(("SME IE : len=%zu\n", sme->ie_len));
  5998. if (sme->ie != NULL && sme->ie_len > 0 && (wl_dbg_level & WL_DBG_DBG)) {
  5999. prhex(NULL, sme->ie, sme->ie_len);
  6000. }
  6001. RETURN_EIO_IF_NOT_UP(cfg);
  6002. /*
  6003. * Cancel ongoing scan to sync up with sme state machine of cfg80211.
  6004. */
  6005. if (cfg->scan_request) {
  6006. WL_TRACE_HW4(("Aborting the scan! \n"));
  6007. wl_cfg80211_scan_abort(cfg);
  6008. wait_cnt = MAX_SCAN_ABORT_WAIT_CNT;
  6009. while (wl_get_drv_status(cfg, SCANNING, dev) && wait_cnt) {
  6010. WL_DBG(("Waiting for SCANNING terminated, wait_cnt: %d\n", wait_cnt));
  6011. wait_cnt--;
  6012. OSL_SLEEP(WAIT_SCAN_ABORT_OSL_SLEEP_TIME);
  6013. }
  6014. if (wl_get_drv_status(cfg, SCANNING, dev)) {
  6015. wl_cfg80211_cancel_scan(cfg);
  6016. }
  6017. }
  6018. #ifdef WL_SCHED_SCAN
  6019. /* Locks are taken in wl_cfg80211_sched_scan_stop()
  6020. * A start scan occuring during connect is unlikely
  6021. */
  6022. if (cfg->sched_scan_req) {
  6023. #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 0))
  6024. wl_cfg80211_sched_scan_stop(wiphy, bcmcfg_to_prmry_ndev(cfg),
  6025. cfg->sched_scan_req->reqid);
  6026. #else
  6027. wl_cfg80211_sched_scan_stop(wiphy, bcmcfg_to_prmry_ndev(cfg));
  6028. #endif /* LINUX_VERSION_CODE <= KERNEL_VERSION(4, 11, 0) */
  6029. }
  6030. #endif /* WL_SCHED_SCAN */
  6031. #ifdef WL_CFG80211_GON_COLLISION
  6032. /* init block gon req count */
  6033. cfg->block_gon_req_tx_count = 0;
  6034. cfg->block_gon_req_rx_count = 0;
  6035. #endif /* WL_CFG80211_GON_COLLISION */
  6036. #if defined(ESCAN_RESULT_PATCH)
  6037. if (sme->bssid)
  6038. memcpy(connect_req_bssid, sme->bssid, ETHER_ADDR_LEN);
  6039. else
  6040. bzero(connect_req_bssid, ETHER_ADDR_LEN);
  6041. bzero(broad_bssid, ETHER_ADDR_LEN);
  6042. #endif // endif
  6043. #if defined(USE_DYNAMIC_MAXPKT_RXGLOM)
  6044. maxrxpktglom = 0;
  6045. #endif // endif
  6046. if (wl_get_drv_status(cfg, CONNECTING, dev) || wl_get_drv_status(cfg, CONNECTED, dev)) {
  6047. /* set nested connect bit to identify the context */
  6048. wl_set_drv_status(cfg, NESTED_CONNECT, dev);
  6049. /* DHD prev status is CONNECTING/CONNECTED */
  6050. err = wl_cfg80211_cleanup_mismatch_status(dev, cfg, TRUE);
  6051. } else if (wl_get_drv_status(cfg, DISCONNECTING, dev)) {
  6052. /* DHD prev status is DISCONNECTING */
  6053. err = wl_cfg80211_cleanup_mismatch_status(dev, cfg, false);
  6054. } else if (!wl_get_drv_status(cfg, CONNECTED, dev)) {
  6055. /* DHD previous status is not connected and FW connected */
  6056. if (wldev_ioctl_get(dev, WLC_GET_BSSID, &bssid, ETHER_ADDR_LEN) == 0) {
  6057. /* set nested connect bit to identify the context */
  6058. wl_set_drv_status(cfg, NESTED_CONNECT, dev);
  6059. err = wl_cfg80211_cleanup_mismatch_status(dev, cfg, true);
  6060. }
  6061. }
  6062. if (sme->bssid) {
  6063. wl_update_prof(cfg, dev, NULL, sme->bssid, WL_PROF_LATEST_BSSID);
  6064. } else {
  6065. wl_update_prof(cfg, dev, NULL, &ether_bcast, WL_PROF_LATEST_BSSID);
  6066. }
  6067. /* 'connect' request received */
  6068. wl_set_drv_status(cfg, CONNECTING, dev);
  6069. /* clear nested connect bit on proceeding for connection */
  6070. wl_clr_drv_status(cfg, NESTED_CONNECT, dev);
  6071. /* Clean BSSID */
  6072. bzero(&bssid, sizeof(bssid));
  6073. if (!wl_get_drv_status(cfg, DISCONNECTING, dev))
  6074. wl_update_prof(cfg, dev, NULL, (void *)&bssid, WL_PROF_BSSID);
  6075. if (p2p_is_on(cfg) && (dev != bcmcfg_to_prmry_ndev(cfg))) {
  6076. /* we only allow to connect using virtual interface in case of P2P */
  6077. if ((bssidx = wl_get_bssidx_by_wdev(cfg, dev->ieee80211_ptr)) < 0) {
  6078. WL_ERR(("Find p2p index from wdev(%p) failed\n",
  6079. dev->ieee80211_ptr));
  6080. err = BCME_ERROR;
  6081. goto exit;
  6082. }
  6083. wl_cfg80211_set_mgmt_vndr_ies(cfg, ndev_to_cfgdev(dev), bssidx,
  6084. VNDR_IE_ASSOCREQ_FLAG, sme->ie, sme->ie_len);
  6085. } else if (dev == bcmcfg_to_prmry_ndev(cfg)) {
  6086. if ((bssidx = wl_get_bssidx_by_wdev(cfg, dev->ieee80211_ptr)) < 0) {
  6087. WL_ERR(("Find wlan index from wdev(%p) failed\n", dev->ieee80211_ptr));
  6088. err = BCME_ERROR;
  6089. goto exit;
  6090. }
  6091. /* find the RSN_IE */
  6092. if ((wpa2_ie = bcm_parse_tlvs((const u8 *)sme->ie, sme->ie_len,
  6093. DOT11_MNG_RSN_ID)) != NULL) {
  6094. WL_DBG((" WPA2 IE is found\n"));
  6095. }
  6096. /* find the WPA_IE */
  6097. if ((wpa_ie = wl_cfgp2p_find_wpaie(sme->ie,
  6098. sme->ie_len)) != NULL) {
  6099. WL_DBG((" WPA IE is found\n"));
  6100. }
  6101. if (wpa_ie != NULL || wpa2_ie != NULL) {
  6102. wpaie = (wpa_ie != NULL) ? (const u8 *)wpa_ie : (const u8 *)wpa2_ie;
  6103. wpaie_len = (wpa_ie != NULL) ? wpa_ie->length : wpa2_ie->len;
  6104. wpaie_len += WPA_RSN_IE_TAG_FIXED_LEN;
  6105. err = wldev_iovar_setbuf(dev, "wpaie", wpaie, wpaie_len,
  6106. cfg->ioctl_buf, WLC_IOCTL_MAXLEN, &cfg->ioctl_buf_sync);
  6107. if (unlikely(err)) {
  6108. WL_ERR(("wpaie set error (%d)\n", err));
  6109. goto exit;
  6110. }
  6111. } else {
  6112. err = wldev_iovar_setbuf(dev, "wpaie", NULL, 0,
  6113. cfg->ioctl_buf, WLC_IOCTL_MAXLEN, &cfg->ioctl_buf_sync);
  6114. if (unlikely(err)) {
  6115. WL_ERR(("wpaie set error (%d)\n", err));
  6116. goto exit;
  6117. }
  6118. }
  6119. err = wl_cfg80211_set_mgmt_vndr_ies(cfg, ndev_to_cfgdev(dev), bssidx,
  6120. VNDR_IE_ASSOCREQ_FLAG, (const u8 *)sme->ie, sme->ie_len);
  6121. if (unlikely(err)) {
  6122. goto exit;
  6123. }
  6124. }
  6125. #if defined(ROAM_ENABLE) && defined(ROAM_AP_ENV_DETECTION)
  6126. if (dhdp->roam_env_detection) {
  6127. bool is_roamtrig_reset = TRUE;
  6128. bool is_roam_env_ok = (wldev_iovar_setint(dev, "roam_env_detection",
  6129. AP_ENV_DETECT_NOT_USED) == BCME_OK);
  6130. #ifdef SKIP_ROAM_TRIGGER_RESET
  6131. roam_trigger[1] = WLC_BAND_2G;
  6132. is_roamtrig_reset =
  6133. (wldev_ioctl_get(dev, WLC_GET_ROAM_TRIGGER, roam_trigger,
  6134. sizeof(roam_trigger)) == BCME_OK) &&
  6135. (roam_trigger[0] == WL_AUTO_ROAM_TRIGGER-10);
  6136. #endif /* SKIP_ROAM_TRIGGER_RESET */
  6137. if (is_roamtrig_reset && is_roam_env_ok) {
  6138. roam_trigger[0] = WL_AUTO_ROAM_TRIGGER;
  6139. roam_trigger[1] = WLC_BAND_ALL;
  6140. err = wldev_ioctl_set(dev, WLC_SET_ROAM_TRIGGER, roam_trigger,
  6141. sizeof(roam_trigger));
  6142. if (unlikely(err)) {
  6143. WL_ERR((" failed to restore roam_trigger for auto env"
  6144. " detection\n"));
  6145. }
  6146. }
  6147. }
  6148. #endif /* ROAM_ENABLE && ROAM_AP_ENV_DETECTION */
  6149. if (chan &&
  6150. #ifdef H2_BRING_UP
  6151. FALSE &&
  6152. #endif /* H2_BRING_UP */
  6153. TRUE) {
  6154. cfg->channel = ieee80211_frequency_to_channel(chan->center_freq);
  6155. chan_cnt = 1;
  6156. WL_DBG(("channel (%d), center_req (%d), %d channels\n", cfg->channel,
  6157. chan->center_freq, chan_cnt));
  6158. } else {
  6159. WL_DBG(("No channel info from user space\n"));
  6160. cfg->channel = 0;
  6161. }
  6162. #ifdef ESCAN_CHANNEL_CACHE
  6163. /*
  6164. * No channel information from user space. if ECC is enabled, the ECC
  6165. * would prepare the channel list, else no channel would be provided
  6166. * and firmware would need to do a full channel scan.
  6167. *
  6168. * Use cached channels. This might take slightly longer time compared
  6169. * to using a single channel based join. But ECC would help choose
  6170. * a better AP for a given ssid. For a given SSID there might multiple
  6171. * APs on different channels and ECC would scan all those channels
  6172. * before deciding up on the AP. This accounts for the additional delay.
  6173. */
  6174. if (cfg->rcc_enabled || cfg->channel == 0)
  6175. {
  6176. wlc_ssid_t ssid;
  6177. int band;
  6178. err = wldev_get_band(dev, &band);
  6179. if (!err) {
  6180. set_roam_band(band);
  6181. }
  6182. memcpy(ssid.SSID, sme->ssid, sme->ssid_len);
  6183. ssid.SSID_len = (uint32)sme->ssid_len;
  6184. chan_cnt = get_roam_channel_list(cfg->channel, chanspec_list,
  6185. MAX_ROAM_CHANNEL, &ssid, ioctl_version);
  6186. WL_DBG(("RCC channel count:%d \n", chan_cnt));
  6187. }
  6188. #endif /* ESCAN_CHANNEL_CACHE */
  6189. WL_DBG(("3. set wpa version \n"));
  6190. err = wl_set_wpa_version(dev, sme);
  6191. if (unlikely(err)) {
  6192. WL_ERR(("Invalid wpa_version\n"));
  6193. goto exit;
  6194. }
  6195. #ifdef BCMWAPI_WPI
  6196. if (sme->crypto.wpa_versions & NL80211_WAPI_VERSION_1)
  6197. WL_DBG(("4. WAPI Dont Set wl_set_auth_type\n"));
  6198. else {
  6199. WL_DBG(("4. wl_set_auth_type\n"));
  6200. #endif // endif
  6201. err = wl_set_auth_type(dev, sme);
  6202. if (unlikely(err)) {
  6203. WL_ERR(("Invalid auth type\n"));
  6204. goto exit;
  6205. }
  6206. #ifdef BCMWAPI_WPI
  6207. }
  6208. #endif // endif
  6209. #ifdef WL_FILS
  6210. if (sme->ie && sme->ie_len) {
  6211. err = wl_fils_add_hlp_container(cfg, dev, sme->ie, sme->ie_len);
  6212. if (unlikely(err)) {
  6213. WL_ERR(("FILS sending HLP failed\n"));
  6214. goto exit;
  6215. }
  6216. }
  6217. #endif /* WL_FILS */
  6218. err = wl_set_set_cipher(dev, sme);
  6219. if (unlikely(err)) {
  6220. WL_ERR(("Invalid ciper\n"));
  6221. goto exit;
  6222. }
  6223. err = wl_set_key_mgmt(dev, sme);
  6224. if (unlikely(err)) {
  6225. WL_ERR(("Invalid key mgmt\n"));
  6226. goto exit;
  6227. }
  6228. err = wl_set_set_sharedkey(dev, sme);
  6229. if (unlikely(err)) {
  6230. WL_ERR(("Invalid shared key\n"));
  6231. goto exit;
  6232. }
  6233. #ifdef WL_FILS
  6234. err = wl_set_fils_params(dev, sme);
  6235. if (unlikely(err)) {
  6236. WL_ERR(("Invalid FILS params\n"));
  6237. goto exit;
  6238. }
  6239. #endif /* WL_FILS */
  6240. /*
  6241. * Join with specific BSSID and cached SSID
  6242. * If SSID is zero join based on BSSID only
  6243. */
  6244. join_params_size = WL_EXTJOIN_PARAMS_FIXED_SIZE +
  6245. chan_cnt * sizeof(chanspec_t);
  6246. ext_join_params = (wl_extjoin_params_t *)MALLOCZ(cfg->osh, join_params_size);
  6247. if (ext_join_params == NULL) {
  6248. err = -ENOMEM;
  6249. wl_clr_drv_status(cfg, CONNECTING, dev);
  6250. goto exit;
  6251. }
  6252. ext_join_params->ssid.SSID_len =
  6253. (uint32)min(sizeof(ext_join_params->ssid.SSID), sme->ssid_len);
  6254. memcpy(&ext_join_params->ssid.SSID, sme->ssid, ext_join_params->ssid.SSID_len);
  6255. wl_update_prof(cfg, dev, NULL, &ext_join_params->ssid, WL_PROF_SSID);
  6256. ext_join_params->ssid.SSID_len = htod32(ext_join_params->ssid.SSID_len);
  6257. /* increate dwell time to receive probe response or detect Beacon
  6258. * from target AP at a noisy air only during connect command
  6259. */
  6260. ext_join_params->scan.active_time = chan_cnt ? WL_SCAN_JOIN_ACTIVE_DWELL_TIME_MS : -1;
  6261. ext_join_params->scan.passive_time = chan_cnt ? WL_SCAN_JOIN_PASSIVE_DWELL_TIME_MS : -1;
  6262. /* Set up join scan parameters */
  6263. ext_join_params->scan.scan_type = -1;
  6264. ext_join_params->scan.nprobes = chan_cnt ?
  6265. (ext_join_params->scan.active_time/WL_SCAN_JOIN_PROBE_INTERVAL_MS) : -1;
  6266. ext_join_params->scan.home_time = -1;
  6267. if (sme->bssid)
  6268. memcpy(&ext_join_params->assoc.bssid, sme->bssid, ETH_ALEN);
  6269. else
  6270. memcpy(&ext_join_params->assoc.bssid, &ether_bcast, ETH_ALEN);
  6271. ext_join_params->assoc.chanspec_num = chan_cnt;
  6272. if (chan_cnt && !cfg->rcc_enabled) {
  6273. if (cfg->channel) {
  6274. /*
  6275. * Use the channel provided by userspace
  6276. */
  6277. u16 channel, band, bw, ctl_sb;
  6278. chanspec_t chspec;
  6279. channel = cfg->channel;
  6280. band = (channel <= CH_MAX_2G_CHANNEL) ? WL_CHANSPEC_BAND_2G
  6281. : WL_CHANSPEC_BAND_5G;
  6282. /* Get min_bw set for the interface */
  6283. bw = WL_CHANSPEC_BW_20;
  6284. if (bw == INVCHANSPEC) {
  6285. WL_ERR(("Invalid chanspec \n"));
  6286. MFREE(cfg->osh, ext_join_params, join_params_size);
  6287. err = BCME_ERROR;
  6288. goto exit;
  6289. }
  6290. ctl_sb = WL_CHANSPEC_CTL_SB_NONE;
  6291. chspec = (channel | band | bw | ctl_sb);
  6292. ext_join_params->assoc.chanspec_list[0] &= WL_CHANSPEC_CHAN_MASK;
  6293. ext_join_params->assoc.chanspec_list[0] |= chspec;
  6294. ext_join_params->assoc.chanspec_list[0] =
  6295. wl_chspec_host_to_driver(ext_join_params->assoc.chanspec_list[0]);
  6296. }
  6297. }
  6298. #ifdef ESCAN_CHANNEL_CACHE
  6299. else {
  6300. memcpy(ext_join_params->assoc.chanspec_list, chanspec_list,
  6301. sizeof(chanspec_t) * chan_cnt);
  6302. }
  6303. #endif /* ESCAN_CHANNEL_CACHE */
  6304. ext_join_params->assoc.chanspec_num = htod32(ext_join_params->assoc.chanspec_num);
  6305. if (ext_join_params->ssid.SSID_len < IEEE80211_MAX_SSID_LEN) {
  6306. WL_DBG(("ssid \"%s\", len (%d)\n", ext_join_params->ssid.SSID,
  6307. ext_join_params->ssid.SSID_len));
  6308. }
  6309. if ((bssidx = wl_get_bssidx_by_wdev(cfg, dev->ieee80211_ptr)) < 0) {
  6310. WL_ERR(("Find p2p index from wdev(%p) failed\n", dev->ieee80211_ptr));
  6311. MFREE(cfg->osh, ext_join_params, join_params_size);
  6312. err = BCME_ERROR;
  6313. goto exit;
  6314. }
  6315. #ifdef DHD_EVENT_LOG_FILTER
  6316. if (dev == bcmcfg_to_prmry_ndev(cfg)) {
  6317. /* inform only for STA Interface */
  6318. dhd_event_log_filter_notify_connect_request(dhdp,
  6319. (uint8 *)(&ext_join_params->assoc.bssid), cfg->channel);
  6320. }
  6321. #endif /* DHD_EVENT_LOG_FILTER */
  6322. #ifdef WLTDLS
  6323. /* disable TDLS if number of connected interfaces is >= 1 */
  6324. wl_cfg80211_tdls_config(cfg, TDLS_STATE_CONNECT, false);
  6325. #endif /* WLTDLS */
  6326. err = wldev_iovar_setbuf_bsscfg(dev, "join", ext_join_params, join_params_size,
  6327. cfg->ioctl_buf, WLC_IOCTL_MAXLEN, bssidx, &cfg->ioctl_buf_sync);
  6328. if (cfg->rcc_enabled) {
  6329. WL_ERR_KERN(("[%s] Connecting with " MACDBG " ssid \"%s\","
  6330. " len (%d) with rcc channels. chan_cnt:%d \n\n",
  6331. dev->name, MAC2STRDBG((u8*)(&ext_join_params->assoc.bssid)),
  6332. ext_join_params->ssid.SSID, ext_join_params->ssid.SSID_len, chan_cnt));
  6333. WL_INFORM_MEM(("[%s] Connecting with " MACDBG " ssid \"%s\","
  6334. " len (%d) with rcc channels. chan_cnt:%d \n\n",
  6335. dev->name, MAC2STRDBG((u8*)(&ext_join_params->assoc.bssid)),
  6336. "*****", ext_join_params->ssid.SSID_len, chan_cnt));
  6337. } else {
  6338. WL_ERR_KERN(("[%s] Connecting with " MACDBG " ssid \"%s\","
  6339. " len (%d) channels:%d \n\n",
  6340. dev->name, MAC2STRDBG((u8*)(&ext_join_params->assoc.bssid)),
  6341. ext_join_params->ssid.SSID, ext_join_params->ssid.SSID_len, cfg->channel));
  6342. WL_INFORM_MEM(("[%s] Connecting with " MACDBG " ssid \"%s\","
  6343. " len (%d) channels:%d \n\n",
  6344. dev->name, MAC2STRDBG((u8*)(&ext_join_params->assoc.bssid)),
  6345. "*****", ext_join_params->ssid.SSID_len, cfg->channel));
  6346. }
  6347. SUPP_LOG(("[%s] Connecting with " MACDBG " ssid \"%s\","
  6348. "channel:%d rcc:%d\n",
  6349. dev->name, MAC2STRDBG((u8*)(&ext_join_params->assoc.bssid)),
  6350. ext_join_params->ssid.SSID, cfg->channel, cfg->rcc_enabled));
  6351. MFREE(cfg->osh, ext_join_params, join_params_size);
  6352. if (err) {
  6353. wl_clr_drv_status(cfg, CONNECTING, dev);
  6354. if (err == BCME_UNSUPPORTED) {
  6355. WL_DBG(("join iovar is not supported\n"));
  6356. goto set_ssid;
  6357. } else {
  6358. WL_ERR(("join iovar error (%d)\n", err));
  6359. goto exit;
  6360. }
  6361. } else
  6362. goto exit;
  6363. set_ssid:
  6364. #if defined(ROAMEXP_SUPPORT)
  6365. /* Clear Blacklist bssid and Whitelist ssid list before join issue
  6366. * This is temporary fix since currently firmware roaming is not
  6367. * disabled by android framework before SSID join from framework
  6368. */
  6369. /* Flush blacklist bssid content */
  6370. dhd_dev_set_blacklist_bssid(dev, NULL, 0, true);
  6371. /* Flush whitelist ssid content */
  6372. dhd_dev_set_whitelist_ssid(dev, NULL, 0, true);
  6373. #endif /* ROAMEXP_SUPPORT */
  6374. bzero(&join_params, sizeof(join_params));
  6375. join_params_size = sizeof(join_params.ssid);
  6376. join_params.ssid.SSID_len = (uint32)min(sizeof(join_params.ssid.SSID), sme->ssid_len);
  6377. memcpy(&join_params.ssid.SSID, sme->ssid, join_params.ssid.SSID_len);
  6378. join_params.ssid.SSID_len = htod32(join_params.ssid.SSID_len);
  6379. wl_update_prof(cfg, dev, NULL, &join_params.ssid, WL_PROF_SSID);
  6380. if (sme->bssid)
  6381. memcpy(&join_params.params.bssid, sme->bssid, ETH_ALEN);
  6382. else
  6383. memcpy(&join_params.params.bssid, &ether_bcast, ETH_ALEN);
  6384. if (wl_ch_to_chanspec(dev, cfg->channel, &join_params, &join_params_size) < 0) {
  6385. WL_ERR(("Invalid chanspec\n"));
  6386. return -EINVAL;
  6387. }
  6388. WL_DBG(("join_param_size %zu\n", join_params_size));
  6389. if (join_params.ssid.SSID_len < IEEE80211_MAX_SSID_LEN) {
  6390. WL_INFORM_MEM(("ssid \"%s\", len (%d)\n", join_params.ssid.SSID,
  6391. join_params.ssid.SSID_len));
  6392. }
  6393. err = wldev_ioctl_set(dev, WLC_SET_SSID, &join_params, join_params_size);
  6394. exit:
  6395. if (err) {
  6396. WL_ERR(("error (%d)\n", err));
  6397. wl_clr_drv_status(cfg, CONNECTING, dev);
  6398. wl_flush_fw_log_buffer(dev, FW_LOGSET_MASK_ALL);
  6399. #ifdef WLTDLS
  6400. /* If connect fails, check whether we can enable back TDLS */
  6401. wl_cfg80211_tdls_config(cfg, TDLS_STATE_DISCONNECT, false);
  6402. #endif /* WLTDLS */
  6403. }
  6404. #ifdef DBG_PKT_MON
  6405. if ((dev == bcmcfg_to_prmry_ndev(cfg)) && !err) {
  6406. DHD_DBG_PKT_MON_START(dhdp);
  6407. }
  6408. #endif /* DBG_PKT_MON */
  6409. return err;
  6410. }
  6411. static void wl_cfg80211_disconnect_state_sync(struct bcm_cfg80211 *cfg, struct net_device *dev)
  6412. {
  6413. struct wireless_dev *wdev;
  6414. uint8 wait_cnt;
  6415. if (!dev || !dev->ieee80211_ptr) {
  6416. WL_ERR(("wrong ndev\n"));
  6417. return;
  6418. }
  6419. wdev = dev->ieee80211_ptr;
  6420. wait_cnt = WAIT_FOR_DISCONNECT_STATE_SYNC;
  6421. while ((wdev->current_bss) && wait_cnt) {
  6422. WL_DBG(("Waiting for disconnect sync, wait_cnt: %d\n", wait_cnt));
  6423. wait_cnt--;
  6424. OSL_SLEEP(50);
  6425. }
  6426. if (wait_cnt == 0) {
  6427. /* state didn't get cleared within given timeout */
  6428. WL_INFORM_MEM(("cfg80211 state. wdev->current_bss non null\n"));
  6429. } else {
  6430. WL_MEM(("cfg80211 disconnect state sync done\n"));
  6431. }
  6432. }
  6433. static void wl_cfg80211_wait_for_disconnection(struct bcm_cfg80211 *cfg, struct net_device *dev)
  6434. {
  6435. uint8 wait_cnt;
  6436. u32 status = 0;
  6437. wait_cnt = WAIT_FOR_DISCONNECT_MAX;
  6438. while ((status = wl_get_drv_status(cfg, DISCONNECTING, dev)) && wait_cnt) {
  6439. WL_DBG(("Waiting for disconnection, wait_cnt: %d\n", wait_cnt));
  6440. wait_cnt--;
  6441. OSL_SLEEP(50);
  6442. }
  6443. WL_INFORM_MEM(("Wait for disconnection done. status:%d wait_cnt:%d\n", status, wait_cnt));
  6444. if (!wait_cnt && wl_get_drv_status(cfg, DISCONNECTING, dev)) {
  6445. /* No response from firmware. Indicate connect result
  6446. * to clear cfg80211 state machine
  6447. */
  6448. WL_INFORM_MEM(("force send connect result\n"));
  6449. CFG80211_CONNECT_RESULT(dev, NULL, NULL, NULL, 0, NULL, 0,
  6450. WLAN_STATUS_UNSPECIFIED_FAILURE,
  6451. GFP_KERNEL);
  6452. wl_clr_drv_status(cfg, DISCONNECTING, dev);
  6453. }
  6454. return;
  6455. }
  6456. static s32
  6457. wl_cfg80211_disconnect(struct wiphy *wiphy, struct net_device *dev,
  6458. u16 reason_code)
  6459. {
  6460. struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
  6461. scb_val_t scbval;
  6462. bool act = false;
  6463. s32 err = 0;
  6464. u8 *curbssid = NULL;
  6465. u8 null_bssid[ETHER_ADDR_LEN];
  6466. s32 bssidx = 0;
  6467. dhd_pub_t *dhdp = (dhd_pub_t *)(cfg->pub);
  6468. WL_ERR(("Reason %d\n", reason_code));
  6469. RETURN_EIO_IF_NOT_UP(cfg);
  6470. act = *(bool *) wl_read_prof(cfg, dev, WL_PROF_ACT);
  6471. curbssid = wl_read_prof(cfg, dev, WL_PROF_BSSID);
  6472. BCM_REFERENCE(dhdp);
  6473. DHD_STATLOG_CTRL(dhdp, ST(DISASSOC_START),
  6474. dhd_net2idx(dhdp->info, dev), reason_code);
  6475. #ifdef DHD_4WAYM4_FAIL_DISCONNECT
  6476. dhd_cleanup_m4_state_work(dhdp, dhd_net2idx(dhdp->info, dev));
  6477. #endif /* DHD_4WAYM4_FAIL_DISCONNECT */
  6478. #ifdef ESCAN_RESULT_PATCH
  6479. if (wl_get_drv_status(cfg, CONNECTING, dev)) {
  6480. if (curbssid) {
  6481. WL_ERR(("Disconnecting while CONNECTING status"
  6482. " connecting device: " MACDBG "\n", MAC2STRDBG(curbssid)));
  6483. } else {
  6484. WL_ERR(("Disconnecting while CONNECTING status \n"));
  6485. }
  6486. act = true;
  6487. }
  6488. #endif /* ESCAN_RESULT_PATCH */
  6489. if (!curbssid) {
  6490. WL_ERR(("Disconnecting while CONNECTING status %d\n", (int)sizeof(null_bssid)));
  6491. bzero(null_bssid, sizeof(null_bssid));
  6492. curbssid = null_bssid;
  6493. }
  6494. if (act) {
  6495. #ifdef DBG_PKT_MON
  6496. /* Stop packet monitor */
  6497. if (dev == bcmcfg_to_prmry_ndev(cfg)) {
  6498. DHD_DBG_PKT_MON_STOP(dhdp);
  6499. }
  6500. #endif /* DBG_PKT_MON */
  6501. /*
  6502. * Cancel ongoing scan to sync up with sme state machine of cfg80211.
  6503. */
  6504. /* Let scan aborted by F/W */
  6505. if (cfg->scan_request) {
  6506. WL_TRACE_HW4(("Aborting the scan! \n"));
  6507. wl_cfg80211_cancel_scan(cfg);
  6508. }
  6509. /* Set DISCONNECTING state. We are clearing this state in all exit paths */
  6510. wl_set_drv_status(cfg, DISCONNECTING, dev);
  6511. if (wl_get_drv_status(cfg, CONNECTING, dev) ||
  6512. wl_get_drv_status(cfg, CONNECTED, dev)) {
  6513. scbval.val = reason_code;
  6514. memcpy(&scbval.ea, curbssid, ETHER_ADDR_LEN);
  6515. scbval.val = htod32(scbval.val);
  6516. WL_INFORM_MEM(("[%s] wl disassoc\n", dev->name));
  6517. err = wldev_ioctl_set(dev, WLC_DISASSOC, &scbval,
  6518. sizeof(scb_val_t));
  6519. if (unlikely(err)) {
  6520. wl_clr_drv_status(cfg, DISCONNECTING, dev);
  6521. WL_ERR(("error (%d)\n", err));
  6522. goto exit;
  6523. }
  6524. }
  6525. #ifdef WL_WPS_SYNC
  6526. /* If are in WPS reauth state, then we would be
  6527. * dropping the link down events. Ensure that
  6528. * Event is sent up for the disconnect Req
  6529. */
  6530. if (wl_wps_session_update(dev,
  6531. WPS_STATE_DISCONNECT, curbssid) == BCME_OK) {
  6532. WL_INFORM_MEM(("[WPS] Disconnect done.\n"));
  6533. wl_clr_drv_status(cfg, DISCONNECTING, dev);
  6534. }
  6535. #endif /* WPS_SYNC */
  6536. wl_cfg80211_wait_for_disconnection(cfg, dev);
  6537. } else {
  6538. /* Not in connecting or connected state. However since disconnect came
  6539. * from upper layer, indicate connect fail to clear any state mismatch
  6540. */
  6541. WL_INFORM_MEM(("act is false. report connect result fail.\n"));
  6542. CFG80211_CONNECT_RESULT(dev, NULL, NULL, NULL, 0, NULL, 0,
  6543. WLAN_STATUS_UNSPECIFIED_FAILURE, GFP_KERNEL);
  6544. }
  6545. #ifdef CUSTOM_SET_CPUCORE
  6546. /* set default cpucore */
  6547. if (dev == bcmcfg_to_prmry_ndev(cfg)) {
  6548. dhdp->chan_isvht80 &= ~DHD_FLAG_STA_MODE;
  6549. if (!(dhdp->chan_isvht80))
  6550. dhd_set_cpucore(dhdp, FALSE);
  6551. }
  6552. #endif /* CUSTOM_SET_CPUCORE */
  6553. cfg->rssi = 0; /* reset backup of rssi */
  6554. exit:
  6555. /* Clear IEs for disaasoc */
  6556. if ((bssidx = wl_get_bssidx_by_wdev(cfg, dev->ieee80211_ptr)) < 0) {
  6557. WL_ERR(("Find index failed\n"));
  6558. err = -EINVAL;
  6559. return err;
  6560. }
  6561. WL_ERR(("Clearing disconnect IEs \n"));
  6562. err = wl_cfg80211_set_mgmt_vndr_ies(cfg,
  6563. ndev_to_cfgdev(dev), bssidx, VNDR_IE_DISASSOC_FLAG, NULL, 0);
  6564. return err;
  6565. }
  6566. #if defined(WL_CFG80211_P2P_DEV_IF)
  6567. static s32
  6568. wl_cfg80211_set_tx_power(struct wiphy *wiphy, struct wireless_dev *wdev,
  6569. enum nl80211_tx_power_setting type, s32 mbm)
  6570. #else
  6571. static s32
  6572. wl_cfg80211_set_tx_power(struct wiphy *wiphy,
  6573. enum nl80211_tx_power_setting type, s32 dbm)
  6574. #endif /* WL_CFG80211_P2P_DEV_IF */
  6575. {
  6576. struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
  6577. struct net_device *ndev = bcmcfg_to_prmry_ndev(cfg);
  6578. s32 err = 0;
  6579. #if defined(WL_CFG80211_P2P_DEV_IF)
  6580. s32 dbm = MBM_TO_DBM(mbm);
  6581. #elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 3, 0)) || \
  6582. defined(WL_COMPAT_WIRELESS) || defined(WL_SUPPORT_BACKPORTED_KPATCHES)
  6583. dbm = MBM_TO_DBM(dbm);
  6584. #endif /* WL_CFG80211_P2P_DEV_IF */
  6585. RETURN_EIO_IF_NOT_UP(cfg);
  6586. switch (type) {
  6587. case NL80211_TX_POWER_AUTOMATIC:
  6588. break;
  6589. case NL80211_TX_POWER_LIMITED:
  6590. if (dbm < 0) {
  6591. WL_ERR(("TX_POWER_LIMITTED - dbm is negative\n"));
  6592. return -EINVAL;
  6593. }
  6594. break;
  6595. case NL80211_TX_POWER_FIXED:
  6596. if (dbm < 0) {
  6597. WL_ERR(("TX_POWER_FIXED - dbm is negative..\n"));
  6598. return -EINVAL;
  6599. }
  6600. break;
  6601. }
  6602. err = wl_set_tx_power(ndev, type, dbm);
  6603. if (unlikely(err)) {
  6604. WL_ERR(("error (%d)\n", err));
  6605. return err;
  6606. }
  6607. cfg->conf->tx_power = dbm;
  6608. return err;
  6609. }
  6610. #if defined(WL_CFG80211_P2P_DEV_IF)
  6611. static s32 wl_cfg80211_get_tx_power(struct wiphy *wiphy,
  6612. struct wireless_dev *wdev, s32 *dbm)
  6613. #else
  6614. static s32 wl_cfg80211_get_tx_power(struct wiphy *wiphy, s32 *dbm)
  6615. #endif /* WL_CFG80211_P2P_DEV_IF */
  6616. {
  6617. struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
  6618. struct net_device *ndev = bcmcfg_to_prmry_ndev(cfg);
  6619. s32 err = 0;
  6620. RETURN_EIO_IF_NOT_UP(cfg);
  6621. err = wl_get_tx_power(ndev, dbm);
  6622. if (unlikely(err))
  6623. WL_ERR(("error (%d)\n", err));
  6624. return err;
  6625. }
  6626. static s32
  6627. wl_cfg80211_config_default_key(struct wiphy *wiphy, struct net_device *dev,
  6628. u8 key_idx, bool unicast, bool multicast)
  6629. {
  6630. struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
  6631. u32 index;
  6632. s32 wsec;
  6633. s32 err = 0;
  6634. s32 bssidx;
  6635. if ((bssidx = wl_get_bssidx_by_wdev(cfg, dev->ieee80211_ptr)) < 0) {
  6636. WL_ERR(("Find p2p index from dev(%p) failed\n", dev->ieee80211_ptr));
  6637. return BCME_ERROR;
  6638. }
  6639. WL_DBG(("key index (%d)\n", key_idx));
  6640. RETURN_EIO_IF_NOT_UP(cfg);
  6641. err = wldev_iovar_getint_bsscfg(dev, "wsec", &wsec, bssidx);
  6642. if (unlikely(err)) {
  6643. WL_ERR(("WLC_GET_WSEC error (%d)\n", err));
  6644. return err;
  6645. }
  6646. if (wsec == WEP_ENABLED) {
  6647. /* Just select a new current key */
  6648. index = (u32) key_idx;
  6649. index = htod32(index);
  6650. err = wldev_ioctl_set(dev, WLC_SET_KEY_PRIMARY, &index,
  6651. sizeof(index));
  6652. if (unlikely(err)) {
  6653. WL_ERR(("error (%d)\n", err));
  6654. }
  6655. }
  6656. return err;
  6657. }
  6658. static s32
  6659. wl_add_keyext(struct wiphy *wiphy, struct net_device *dev,
  6660. u8 key_idx, const u8 *mac_addr, struct key_params *params)
  6661. {
  6662. struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
  6663. struct wl_wsec_key key;
  6664. s32 err = 0;
  6665. s32 bssidx;
  6666. s32 mode = wl_get_mode_by_netdev(cfg, dev);
  6667. WL_ERR(("key index (%d)\n", key_idx));
  6668. if ((bssidx = wl_get_bssidx_by_wdev(cfg, dev->ieee80211_ptr)) < 0) {
  6669. WL_ERR(("Find p2p index from wdev(%p) failed\n", dev->ieee80211_ptr));
  6670. return BCME_ERROR;
  6671. }
  6672. bzero(&key, sizeof(key));
  6673. key.index = (u32) key_idx;
  6674. if (!ETHER_ISMULTI(mac_addr))
  6675. memcpy((char *)&key.ea, (const void *)mac_addr, ETHER_ADDR_LEN);
  6676. key.len = (u32) params->key_len;
  6677. /* check for key index change */
  6678. if (key.len == 0) {
  6679. /* key delete */
  6680. swap_key_from_BE(&key);
  6681. err = wldev_iovar_setbuf_bsscfg(dev, "wsec_key", &key, sizeof(key),
  6682. cfg->ioctl_buf, WLC_IOCTL_MAXLEN, bssidx, &cfg->ioctl_buf_sync);
  6683. if (unlikely(err)) {
  6684. WL_ERR(("key delete error (%d)\n", err));
  6685. return err;
  6686. }
  6687. } else {
  6688. if (key.len > sizeof(key.data)) {
  6689. WL_ERR(("Invalid key length (%d)\n", key.len));
  6690. return -EINVAL;
  6691. }
  6692. WL_DBG(("Setting the key index %d\n", key.index));
  6693. memcpy(key.data, params->key, key.len);
  6694. if ((mode == WL_MODE_BSS) &&
  6695. (params->cipher == WLAN_CIPHER_SUITE_TKIP)) {
  6696. u8 keybuf[8];
  6697. memcpy(keybuf, &key.data[24], sizeof(keybuf));
  6698. memcpy(&key.data[24], &key.data[16], sizeof(keybuf));
  6699. memcpy(&key.data[16], keybuf, sizeof(keybuf));
  6700. }
  6701. /* if IW_ENCODE_EXT_RX_SEQ_VALID set */
  6702. if (params->seq && params->seq_len == 6) {
  6703. /* rx iv */
  6704. const u8 *ivptr;
  6705. ivptr = (const u8 *) params->seq;
  6706. key.rxiv.hi = (ivptr[5] << 24) | (ivptr[4] << 16) |
  6707. (ivptr[3] << 8) | ivptr[2];
  6708. key.rxiv.lo = (ivptr[1] << 8) | ivptr[0];
  6709. key.iv_initialized = true;
  6710. }
  6711. key.algo = wl_rsn_cipher_wsec_key_algo_lookup(params->cipher);
  6712. if (key.algo == CRYPTO_ALGO_OFF) { //not found.
  6713. WL_ERR(("Invalid cipher (0x%x)\n", params->cipher));
  6714. return -EINVAL;
  6715. }
  6716. swap_key_from_BE(&key);
  6717. /* need to guarantee EAPOL 4/4 send out before set key */
  6718. dhd_wait_pend8021x(dev);
  6719. err = wldev_iovar_setbuf_bsscfg(dev, "wsec_key", &key, sizeof(key),
  6720. cfg->ioctl_buf, WLC_IOCTL_MAXLEN, bssidx, &cfg->ioctl_buf_sync);
  6721. if (unlikely(err)) {
  6722. WL_ERR(("WLC_SET_KEY error (%d)\n", err));
  6723. return err;
  6724. }
  6725. WL_INFORM_MEM(("[%s] wsec key set\n", dev->name));
  6726. }
  6727. return err;
  6728. }
  6729. int
  6730. wl_cfg80211_enable_roam_offload(struct net_device *dev, int enable)
  6731. {
  6732. int err;
  6733. wl_eventmsg_buf_t ev_buf;
  6734. struct bcm_cfg80211 *cfg = wl_get_cfg(dev);
  6735. if (dev != bcmcfg_to_prmry_ndev(cfg)) {
  6736. /* roam offload is only for the primary device */
  6737. return -1;
  6738. }
  6739. WL_INFORM_MEM(("[%s] wl roam_offload %d\n", dev->name, enable));
  6740. err = wldev_iovar_setint(dev, "roam_offload", enable);
  6741. if (err)
  6742. return err;
  6743. bzero(&ev_buf, sizeof(wl_eventmsg_buf_t));
  6744. wl_cfg80211_add_to_eventbuffer(&ev_buf, WLC_E_PSK_SUP, !enable);
  6745. wl_cfg80211_add_to_eventbuffer(&ev_buf, WLC_E_ASSOC_REQ_IE, !enable);
  6746. wl_cfg80211_add_to_eventbuffer(&ev_buf, WLC_E_ASSOC_RESP_IE, !enable);
  6747. wl_cfg80211_add_to_eventbuffer(&ev_buf, WLC_E_REASSOC, !enable);
  6748. wl_cfg80211_add_to_eventbuffer(&ev_buf, WLC_E_JOIN, !enable);
  6749. wl_cfg80211_add_to_eventbuffer(&ev_buf, WLC_E_ROAM, !enable);
  6750. err = wl_cfg80211_apply_eventbuffer(dev, cfg, &ev_buf);
  6751. if (!err) {
  6752. cfg->roam_offload = enable;
  6753. }
  6754. return err;
  6755. }
  6756. struct wireless_dev *
  6757. wl_cfg80211_get_wdev_from_ifname(struct bcm_cfg80211 *cfg, const char *name)
  6758. {
  6759. struct net_info *iter, *next;
  6760. if (name == NULL) {
  6761. WL_ERR(("Iface name is not provided\n"));
  6762. return NULL;
  6763. }
  6764. GCC_DIAGNOSTIC_PUSH_SUPPRESS_CAST();
  6765. for_each_ndev(cfg, iter, next) {
  6766. GCC_DIAGNOSTIC_POP();
  6767. if (iter->ndev) {
  6768. if (strcmp(iter->ndev->name, name) == 0) {
  6769. return iter->ndev->ieee80211_ptr;
  6770. }
  6771. }
  6772. }
  6773. WL_DBG(("Iface %s not found\n", name));
  6774. return NULL;
  6775. }
  6776. #if defined(PKT_FILTER_SUPPORT) && defined(APSTA_BLOCK_ARP_DURING_DHCP)
  6777. void
  6778. wl_cfg80211_block_arp(struct net_device *dev, int enable)
  6779. {
  6780. struct bcm_cfg80211 *cfg = wl_get_cfg(dev);
  6781. dhd_pub_t *dhdp = (dhd_pub_t *)(cfg->pub);
  6782. WL_INFORM_MEM(("[%s] Enter. enable:%d\n", dev->name, enable));
  6783. if (!dhd_pkt_filter_enable) {
  6784. WL_DBG(("Packet filter isn't enabled\n"));
  6785. return;
  6786. }
  6787. /* Block/Unblock ARP frames only if STA is connected to
  6788. * the upstream AP in case of STA+SoftAP Concurrenct mode
  6789. */
  6790. if (!wl_get_drv_status(cfg, CONNECTED, dev)) {
  6791. WL_DBG(("STA not connected to upstream AP\n"));
  6792. return;
  6793. }
  6794. if (enable) {
  6795. WL_DBG(("Enable ARP Filter\n"));
  6796. /* Add ARP filter */
  6797. dhd_packet_filter_add_remove(dhdp, TRUE, DHD_BROADCAST_ARP_FILTER_NUM);
  6798. /* Enable ARP packet filter - blacklist */
  6799. dhd_master_mode = FALSE;
  6800. dhd_pktfilter_offload_enable(dhdp, dhdp->pktfilter[DHD_BROADCAST_ARP_FILTER_NUM],
  6801. TRUE, dhd_master_mode);
  6802. } else {
  6803. WL_DBG(("Disable ARP Filter\n"));
  6804. /* Disable ARP packet filter */
  6805. dhd_master_mode = TRUE;
  6806. dhd_pktfilter_offload_enable(dhdp, dhdp->pktfilter[DHD_BROADCAST_ARP_FILTER_NUM],
  6807. FALSE, dhd_master_mode);
  6808. /* Delete ARP filter */
  6809. dhd_packet_filter_add_remove(dhdp, FALSE, DHD_BROADCAST_ARP_FILTER_NUM);
  6810. }
  6811. }
  6812. #endif /* PKT_FILTER_SUPPORT && APSTA_BLOCK_ARP_DURING_DHCP */
  6813. static s32
  6814. wl_cfg80211_add_key(struct wiphy *wiphy, struct net_device *dev,
  6815. u8 key_idx, bool pairwise, const u8 *mac_addr,
  6816. struct key_params *params)
  6817. {
  6818. struct wl_wsec_key key;
  6819. s32 val = 0;
  6820. s32 wsec = 0;
  6821. s32 err = 0;
  6822. u8 keybuf[8];
  6823. s32 bssidx = 0;
  6824. struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
  6825. s32 mode = wl_get_mode_by_netdev(cfg, dev);
  6826. #ifdef WL_GCMP
  6827. uint32 algos = 0, mask = 0;
  6828. #endif /* WL_GCMP */
  6829. #if defined(WLAN_CIPHER_SUITE_PMK)
  6830. int j;
  6831. wsec_pmk_t pmk;
  6832. char keystring[WSEC_MAX_PSK_LEN + 1];
  6833. char* charptr = keystring;
  6834. u16 len;
  6835. struct wl_security *sec;
  6836. #endif /* defined(WLAN_CIPHER_SUITE_PMK) */
  6837. dhd_pub_t *dhdp = (dhd_pub_t *)(cfg->pub);
  6838. WL_INFORM_MEM(("key index (%d) (0x%x)\n", key_idx, params->cipher));
  6839. RETURN_EIO_IF_NOT_UP(cfg);
  6840. if ((bssidx = wl_get_bssidx_by_wdev(cfg, dev->ieee80211_ptr)) < 0) {
  6841. WL_ERR(("Find p2p index from dev(%p) failed\n", dev->ieee80211_ptr));
  6842. return BCME_ERROR;
  6843. }
  6844. if (mac_addr &&
  6845. ((params->cipher != WLAN_CIPHER_SUITE_WEP40) &&
  6846. (params->cipher != WLAN_CIPHER_SUITE_WEP104))) {
  6847. wl_add_keyext(wiphy, dev, key_idx, mac_addr, params);
  6848. goto exit;
  6849. }
  6850. BCM_REFERENCE(dhdp);
  6851. DHD_STATLOG_CTRL(dhdp, ST(INSTALL_KEY), dhd_net2idx(dhdp->info, dev), 0);
  6852. bzero(&key, sizeof(key));
  6853. /* Clear any buffered wep key */
  6854. bzero(&cfg->wep_key, sizeof(struct wl_wsec_key));
  6855. key.len = (u32) params->key_len;
  6856. key.index = (u32) key_idx;
  6857. if (unlikely(key.len > sizeof(key.data))) {
  6858. WL_ERR(("Too long key length (%u)\n", key.len));
  6859. return -EINVAL;
  6860. }
  6861. memcpy(key.data, params->key, key.len);
  6862. key.flags = WL_PRIMARY_KEY;
  6863. key.algo = wl_rsn_cipher_wsec_key_algo_lookup(params->cipher);
  6864. val = wl_rsn_cipher_wsec_algo_lookup(params->cipher);
  6865. if (val == WSEC_NONE) {
  6866. WL_ERR(("Invalid cipher (0x%x)\n", params->cipher));
  6867. #if defined(WLAN_CIPHER_SUITE_PMK)
  6868. /* WLAN_CIPHER_SUITE_PMK is not NL80211 standard ,but BRCM proprietary cipher suite.
  6869. * so it doesn't have right algo type too. Just for now, bypass this check for
  6870. * backward compatibility.
  6871. * TODO: deprecate this proprietary way and replace to nl80211 set_pmk API.
  6872. */
  6873. if (params->cipher != WLAN_CIPHER_SUITE_PMK)
  6874. #endif /* defined(WLAN_CIPHER_SUITE_PMK) */
  6875. return -EINVAL;
  6876. }
  6877. switch (params->cipher) {
  6878. case WLAN_CIPHER_SUITE_TKIP:
  6879. /* wpa_supplicant switches the third and fourth quarters of the TKIP key */
  6880. if (mode == WL_MODE_BSS) {
  6881. bcopy(&key.data[24], keybuf, sizeof(keybuf));
  6882. bcopy(&key.data[16], &key.data[24], sizeof(keybuf));
  6883. bcopy(keybuf, &key.data[16], sizeof(keybuf));
  6884. }
  6885. WL_DBG(("WLAN_CIPHER_SUITE_TKIP\n"));
  6886. break;
  6887. #if defined(WLAN_CIPHER_SUITE_PMK)
  6888. case WLAN_CIPHER_SUITE_PMK:
  6889. sec = wl_read_prof(cfg, dev, WL_PROF_SEC);
  6890. WL_MEM(("set_pmk: wpa_auth:%x akm:%x\n", sec->wpa_auth, params->cipher));
  6891. /* Avoid pmk set for SAE and OWE for external supplicant case. */
  6892. if (IS_AKM_SAE(sec->wpa_auth) || IS_AKM_OWE(sec->wpa_auth)) {
  6893. WL_INFORM_MEM(("skip pmk set for akm:%x\n", sec->wpa_auth));
  6894. break;
  6895. }
  6896. if ((sec->wpa_auth == WLAN_AKM_SUITE_8021X) ||
  6897. (sec->wpa_auth == WL_AKM_SUITE_SHA256_1X)) {
  6898. err = wldev_iovar_setbuf(dev, "okc_info_pmk", (const void *)params->key,
  6899. WSEC_MAX_PSK_LEN / 2, keystring, sizeof(keystring), NULL);
  6900. if (err) {
  6901. /* could fail in case that 'okc' is not supported */
  6902. WL_INFORM_MEM(("okc_info_pmk failed, err=%d (ignore)\n", err));
  6903. }
  6904. }
  6905. /* copy the raw hex key to the appropriate format */
  6906. for (j = 0; j < (WSEC_MAX_PSK_LEN / 2); j++) {
  6907. charptr += snprintf(charptr, sizeof(keystring), "%02x", params->key[j]);
  6908. }
  6909. len = (u16)strlen(keystring);
  6910. pmk.key_len = htod16(len);
  6911. bcopy(keystring, pmk.key, len);
  6912. pmk.flags = htod16(WSEC_PASSPHRASE);
  6913. err = wldev_ioctl_set(dev, WLC_SET_WSEC_PMK, &pmk, sizeof(pmk));
  6914. if (err) {
  6915. return err;
  6916. }
  6917. /* Clear key length to delete key */
  6918. key.len = 0;
  6919. break;
  6920. #endif /* WLAN_CIPHER_SUITE_PMK */
  6921. #ifdef WL_GCMP
  6922. case WLAN_CIPHER_SUITE_GCMP:
  6923. case WLAN_CIPHER_SUITE_GCMP_256:
  6924. case WLAN_CIPHER_SUITE_BIP_GMAC_128:
  6925. case WLAN_CIPHER_SUITE_BIP_GMAC_256:
  6926. algos = KEY_ALGO_MASK(key.algo);
  6927. mask = algos | KEY_ALGO_MASK(CRYPTO_ALGO_AES_CCM);
  6928. break;
  6929. #endif /* WL_GCMP */
  6930. default: /* No post processing required */
  6931. WL_DBG(("no post processing required (0x%x)\n", params->cipher));
  6932. break;
  6933. }
  6934. /* Set the new key/index */
  6935. if ((mode == WL_MODE_IBSS) && (val & (TKIP_ENABLED | AES_ENABLED))) {
  6936. WL_ERR(("IBSS KEY setted\n"));
  6937. wldev_iovar_setint(dev, "wpa_auth", WPA_AUTH_NONE);
  6938. }
  6939. swap_key_from_BE(&key);
  6940. if ((params->cipher == WLAN_CIPHER_SUITE_WEP40) ||
  6941. (params->cipher == WLAN_CIPHER_SUITE_WEP104)) {
  6942. /*
  6943. * For AP role, since we are doing a wl down before bringing up AP,
  6944. * the plumbed keys will be lost. So for AP once we bring up AP, we
  6945. * need to plumb keys again. So buffer the keys for future use. This
  6946. * is more like a WAR. If firmware later has the capability to do
  6947. * interface upgrade without doing a "wl down" and "wl apsta 0", then
  6948. * this will not be required.
  6949. */
  6950. WL_DBG(("Buffering WEP Keys \n"));
  6951. memcpy(&cfg->wep_key, &key, sizeof(struct wl_wsec_key));
  6952. }
  6953. err = wldev_iovar_setbuf_bsscfg(dev, "wsec_key", &key, sizeof(key), cfg->ioctl_buf,
  6954. WLC_IOCTL_MAXLEN, bssidx, &cfg->ioctl_buf_sync);
  6955. if (unlikely(err)) {
  6956. WL_ERR(("WLC_SET_KEY error (%d)\n", err));
  6957. return err;
  6958. }
  6959. exit:
  6960. err = wldev_iovar_getint_bsscfg(dev, "wsec", &wsec, bssidx);
  6961. if (unlikely(err)) {
  6962. WL_ERR(("get wsec error (%d)\n", err));
  6963. return err;
  6964. }
  6965. wsec |= val;
  6966. err = wldev_iovar_setint_bsscfg(dev, "wsec", wsec, bssidx);
  6967. if (unlikely(err)) {
  6968. WL_ERR(("set wsec error (%d)\n", err));
  6969. return err;
  6970. }
  6971. #ifdef WL_GCMP
  6972. if (wl_set_wsec_info_algos(dev, algos, mask)) {
  6973. WL_ERR(("set wsec_info error (%d)\n", err));
  6974. }
  6975. #endif /* WL_GCMP */
  6976. return err;
  6977. }
  6978. static s32
  6979. wl_cfg80211_del_key(struct wiphy *wiphy, struct net_device *dev,
  6980. u8 key_idx, bool pairwise, const u8 *mac_addr)
  6981. {
  6982. struct wl_wsec_key key;
  6983. struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
  6984. s32 err = 0;
  6985. s32 bssidx;
  6986. dhd_pub_t *dhdp = (dhd_pub_t *)(cfg->pub);
  6987. if ((bssidx = wl_get_bssidx_by_wdev(cfg, dev->ieee80211_ptr)) < 0) {
  6988. WL_ERR(("Find p2p index from wdev(%p) failed\n", dev->ieee80211_ptr));
  6989. return BCME_ERROR;
  6990. }
  6991. WL_DBG(("Enter\n"));
  6992. #ifndef MFP
  6993. if ((key_idx >= DOT11_MAX_DEFAULT_KEYS) && (key_idx < DOT11_MAX_DEFAULT_KEYS+2))
  6994. return -EINVAL;
  6995. #endif // endif
  6996. RETURN_EIO_IF_NOT_UP(cfg);
  6997. BCM_REFERENCE(dhdp);
  6998. DHD_STATLOG_CTRL(dhdp, ST(DELETE_KEY), dhd_net2idx(dhdp->info, dev), 0);
  6999. bzero(&key, sizeof(key));
  7000. key.flags = WL_PRIMARY_KEY;
  7001. key.algo = CRYPTO_ALGO_OFF;
  7002. key.index = (u32) key_idx;
  7003. WL_DBG(("key index (%d)\n", key_idx));
  7004. /* Set the new key/index */
  7005. swap_key_from_BE(&key);
  7006. err = wldev_iovar_setbuf_bsscfg(dev, "wsec_key", &key, sizeof(key), cfg->ioctl_buf,
  7007. WLC_IOCTL_MAXLEN, bssidx, &cfg->ioctl_buf_sync);
  7008. if (unlikely(err)) {
  7009. if (err == -EINVAL) {
  7010. if (key.index >= DOT11_MAX_DEFAULT_KEYS) {
  7011. /* we ignore this key index in this case */
  7012. WL_DBG(("invalid key index (%d)\n", key_idx));
  7013. }
  7014. } else {
  7015. WL_ERR(("WLC_SET_KEY error (%d)\n", err));
  7016. }
  7017. return err;
  7018. }
  7019. return err;
  7020. }
  7021. /* NOTE : this function cannot work as is and is never called */
  7022. static s32
  7023. wl_cfg80211_get_key(struct wiphy *wiphy, struct net_device *dev,
  7024. u8 key_idx, bool pairwise, const u8 *mac_addr, void *cookie,
  7025. void (*callback) (void *cookie, struct key_params * params))
  7026. {
  7027. struct key_params params;
  7028. struct wl_wsec_key key;
  7029. struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
  7030. struct wl_security *sec;
  7031. s32 wsec;
  7032. s32 err = 0;
  7033. s32 bssidx;
  7034. if ((bssidx = wl_get_bssidx_by_wdev(cfg, dev->ieee80211_ptr)) < 0) {
  7035. WL_ERR(("Find p2p index from wdev(%p) failed\n", dev->ieee80211_ptr));
  7036. return BCME_ERROR;
  7037. }
  7038. WL_DBG(("key index (%d)\n", key_idx));
  7039. RETURN_EIO_IF_NOT_UP(cfg);
  7040. bzero(&key, sizeof(key));
  7041. key.index = key_idx;
  7042. swap_key_to_BE(&key);
  7043. bzero(&params, sizeof(params));
  7044. params.key_len = (u8) min_t(u8, DOT11_MAX_KEY_SIZE, key.len);
  7045. params.key = key.data;
  7046. err = wldev_iovar_getint_bsscfg(dev, "wsec", &wsec, bssidx);
  7047. if (unlikely(err)) {
  7048. WL_ERR(("WLC_GET_WSEC error (%d)\n", err));
  7049. return err;
  7050. }
  7051. switch (WSEC_ENABLED(wsec)) {
  7052. case WEP_ENABLED:
  7053. sec = wl_read_prof(cfg, dev, WL_PROF_SEC);
  7054. if (sec->cipher_pairwise & WLAN_CIPHER_SUITE_WEP40) {
  7055. params.cipher = WLAN_CIPHER_SUITE_WEP40;
  7056. WL_DBG(("WLAN_CIPHER_SUITE_WEP40\n"));
  7057. } else if (sec->cipher_pairwise & WLAN_CIPHER_SUITE_WEP104) {
  7058. params.cipher = WLAN_CIPHER_SUITE_WEP104;
  7059. WL_DBG(("WLAN_CIPHER_SUITE_WEP104\n"));
  7060. }
  7061. break;
  7062. case TKIP_ENABLED:
  7063. params.cipher = WLAN_CIPHER_SUITE_TKIP;
  7064. WL_DBG(("WLAN_CIPHER_SUITE_TKIP\n"));
  7065. break;
  7066. case AES_ENABLED:
  7067. params.cipher = WLAN_CIPHER_SUITE_AES_CMAC;
  7068. WL_DBG(("WLAN_CIPHER_SUITE_AES_CMAC\n"));
  7069. break;
  7070. #ifdef BCMWAPI_WPI
  7071. case SMS4_ENABLED:
  7072. params.cipher = WLAN_CIPHER_SUITE_SMS4;
  7073. WL_DBG(("WLAN_CIPHER_SUITE_SMS4\n"));
  7074. break;
  7075. #endif // endif
  7076. #if defined(SUPPORT_SOFTAP_WPAWPA2_MIXED)
  7077. /* to connect to mixed mode AP */
  7078. case (AES_ENABLED | TKIP_ENABLED): /* TKIP CCMP */
  7079. params.cipher = WLAN_CIPHER_SUITE_AES_CMAC;
  7080. WL_DBG(("WLAN_CIPHER_SUITE_TKIP\n"));
  7081. break;
  7082. #endif // endif
  7083. default:
  7084. WL_ERR(("Invalid algo (0x%x)\n", wsec));
  7085. return -EINVAL;
  7086. }
  7087. callback(cookie, &params);
  7088. return err;
  7089. }
  7090. static s32
  7091. wl_cfg80211_config_default_mgmt_key(struct wiphy *wiphy,
  7092. struct net_device *dev, u8 key_idx)
  7093. {
  7094. #ifdef MFP
  7095. return 0;
  7096. #else
  7097. WL_INFORM_MEM(("Not supported\n"));
  7098. return -EOPNOTSUPP;
  7099. #endif /* MFP */
  7100. }
  7101. static bool
  7102. wl_check_assoc_state(struct bcm_cfg80211 *cfg, struct net_device *dev)
  7103. {
  7104. wl_assoc_info_t asinfo;
  7105. uint32 state = 0;
  7106. int err;
  7107. err = wldev_iovar_getbuf_bsscfg(dev, "assoc_info",
  7108. NULL, 0, cfg->ioctl_buf, WLC_IOCTL_MEDLEN, 0, &cfg->ioctl_buf_sync);
  7109. if (unlikely(err)) {
  7110. WL_ERR(("failed to get assoc_info : err=%d\n", err));
  7111. return FALSE;
  7112. } else {
  7113. memcpy(&asinfo, cfg->ioctl_buf, sizeof(wl_assoc_info_t));
  7114. state = dtoh32(asinfo.state);
  7115. WL_DBG(("assoc state=%d\n", state));
  7116. }
  7117. return (state > 0)? TRUE:FALSE;
  7118. }
  7119. static s32
  7120. wl_cfg80211_get_rssi(struct net_device *dev, struct bcm_cfg80211 *cfg, s32 *rssi)
  7121. {
  7122. s32 err = BCME_OK;
  7123. scb_val_t scb_val;
  7124. #ifdef SUPPORT_RSSI_SUM_REPORT
  7125. wl_rssi_ant_mimo_t rssi_ant_mimo;
  7126. #endif /* SUPPORT_RSSI_SUM_REPORT */
  7127. if (dev == NULL || cfg == NULL) {
  7128. return BCME_ERROR;
  7129. }
  7130. /* initialize rssi */
  7131. *rssi = 0;
  7132. #ifdef SUPPORT_RSSI_SUM_REPORT
  7133. /* Query RSSI sum across antennas */
  7134. bzero(&rssi_ant_mimo, sizeof(rssi_ant_mimo));
  7135. err = wl_get_rssi_per_ant(dev, dev->name, NULL, &rssi_ant_mimo);
  7136. if (err) {
  7137. WL_ERR(("Could not get rssi sum (%d)\n", err));
  7138. /* set rssi to zero and do not return error,
  7139. * because iovar phy_rssi_ant could return BCME_UNSUPPORTED
  7140. * when bssid was null during roaming
  7141. */
  7142. err = BCME_OK;
  7143. } else {
  7144. cfg->rssi_sum_report = TRUE;
  7145. if ((*rssi = rssi_ant_mimo.rssi_sum) >= 0) {
  7146. *rssi = 0;
  7147. }
  7148. }
  7149. #endif /* SUPPORT_RSSI_SUM_REPORT */
  7150. /* if SUPPORT_RSSI_SUM_REPORT works once, do not use legacy method anymore */
  7151. if (cfg->rssi_sum_report == FALSE) {
  7152. bzero(&scb_val, sizeof(scb_val));
  7153. scb_val.val = 0;
  7154. err = wldev_ioctl_get(dev, WLC_GET_RSSI, &scb_val,
  7155. sizeof(scb_val_t));
  7156. if (err) {
  7157. WL_ERR(("Could not get rssi (%d)\n", err));
  7158. return err;
  7159. }
  7160. *rssi = wl_rssi_offset(dtoh32(scb_val.val));
  7161. }
  7162. if (*rssi >= 0) {
  7163. /* check assoc status including roaming */
  7164. DHD_OS_WAKE_LOCK((dhd_pub_t *)(cfg->pub));
  7165. if (wl_get_drv_status(cfg, CONNECTED, dev) && wl_check_assoc_state(cfg, dev)) {
  7166. *rssi = cfg->rssi; /* use previous RSSI */
  7167. WL_DBG(("use previous RSSI %d dBm\n", cfg->rssi));
  7168. } else {
  7169. *rssi = 0;
  7170. }
  7171. DHD_OS_WAKE_UNLOCK((dhd_pub_t *)(cfg->pub));
  7172. } else {
  7173. /* backup the current rssi */
  7174. cfg->rssi = *rssi;
  7175. }
  7176. return err;
  7177. }
  7178. static int
  7179. wl_cfg80211_ifstats_counters_cb(void *ctx, const uint8 *data, uint16 type, uint16 len)
  7180. {
  7181. switch (type) {
  7182. case WL_IFSTATS_XTLV_IF_INDEX:
  7183. WL_DBG(("Stats received on interface index: %d\n", *data));
  7184. break;
  7185. case WL_IFSTATS_XTLV_GENERIC: {
  7186. if (len > sizeof(wl_if_stats_t)) {
  7187. WL_INFORM(("type 0x%x: cntbuf length too long! %d > %d\n",
  7188. type, len, (int)sizeof(wl_if_stats_t)));
  7189. }
  7190. memcpy(ctx, data, sizeof(wl_if_stats_t));
  7191. break;
  7192. }
  7193. default:
  7194. WL_DBG(("Unsupported counter type 0x%x\n", type));
  7195. break;
  7196. }
  7197. return BCME_OK;
  7198. }
  7199. /* Parameters to if_counters iovar need to be converted to XTLV format
  7200. * before sending to FW. The length of the top level XTLV container
  7201. * containing parameters should not exceed 228 bytes
  7202. */
  7203. #define IF_COUNTERS_PARAM_CONTAINER_LEN_MAX 228
  7204. int
  7205. wl_cfg80211_ifstats_counters(struct net_device *dev, wl_if_stats_t *if_stats)
  7206. {
  7207. struct bcm_cfg80211 *cfg = wl_get_cfg(dev);
  7208. dhd_pub_t *dhdp = (dhd_pub_t *)(cfg->pub);
  7209. uint8 *pbuf = NULL;
  7210. bcm_xtlvbuf_t xtlvbuf, local_xtlvbuf;
  7211. bcm_xtlv_t *xtlv;
  7212. uint16 expected_resp_len;
  7213. wl_stats_report_t *request = NULL, *response = NULL;
  7214. int bsscfg_idx;
  7215. int ret = BCME_OK;
  7216. pbuf = (uint8 *)MALLOCZ(dhdp->osh, WLC_IOCTL_MEDLEN);
  7217. if (!pbuf) {
  7218. WL_ERR(("Failed to allocate local pbuf\n"));
  7219. return BCME_NOMEM;
  7220. }
  7221. /* top level container length cannot exceed 228 bytes.
  7222. * This is because the output buffer is 1535 bytes long.
  7223. * Allow 1300 bytes for reporting stats coming in XTLV format
  7224. */
  7225. request = (wl_stats_report_t *)
  7226. MALLOCZ(dhdp->osh, IF_COUNTERS_PARAM_CONTAINER_LEN_MAX);
  7227. if (!request) {
  7228. WL_ERR(("Failed to allocate wl_stats_report_t with length (%d)\n",
  7229. IF_COUNTERS_PARAM_CONTAINER_LEN_MAX));
  7230. ret = BCME_NOMEM;
  7231. goto fail;
  7232. }
  7233. request->version = WL_STATS_REPORT_REQUEST_VERSION_V2;
  7234. /* Top level container... we will create it ourselves */
  7235. /* Leave space for report version, length, and top level XTLV
  7236. * WL_IFSTATS_XTLV_IF.
  7237. */
  7238. ret = bcm_xtlv_buf_init(&local_xtlvbuf,
  7239. (uint8*)(request->data) + BCM_XTLV_HDR_SIZE,
  7240. IF_COUNTERS_PARAM_CONTAINER_LEN_MAX -
  7241. offsetof(wl_stats_report_t, data) - BCM_XTLV_HDR_SIZE,
  7242. BCM_XTLV_OPTION_ALIGN32);
  7243. if (ret) {
  7244. goto fail;
  7245. }
  7246. /* Populate requests using this the local_xtlvbuf context. The xtlvbuf
  7247. * is used to fill the container containing the XTLVs populated using
  7248. * local_xtlvbuf.
  7249. */
  7250. ret = bcm_xtlv_buf_init(&xtlvbuf,
  7251. (uint8*)(request->data),
  7252. IF_COUNTERS_PARAM_CONTAINER_LEN_MAX -
  7253. offsetof(wl_stats_report_t, data),
  7254. BCM_XTLV_OPTION_ALIGN32);
  7255. if (ret) {
  7256. goto fail;
  7257. }
  7258. /* Request generic stats */
  7259. ret = bcm_xtlv_put_data(&local_xtlvbuf,
  7260. WL_IFSTATS_XTLV_GENERIC, NULL, 0);
  7261. if (ret) {
  7262. goto fail;
  7263. }
  7264. /* Complete the outer container with type and length
  7265. * only.
  7266. */
  7267. ret = bcm_xtlv_put_data(&xtlvbuf,
  7268. WL_IFSTATS_XTLV_IF,
  7269. NULL, bcm_xtlv_buf_len(&local_xtlvbuf));
  7270. if (ret) {
  7271. goto fail;
  7272. }
  7273. request->length = bcm_xtlv_buf_len(&xtlvbuf) +
  7274. offsetof(wl_stats_report_t, data);
  7275. bsscfg_idx = wl_get_bssidx_by_wdev(cfg, dev->ieee80211_ptr);
  7276. /* send the command over to the device and get teh output */
  7277. ret = wldev_iovar_getbuf_bsscfg(dev, "if_counters", (void *)request,
  7278. request->length, pbuf, WLC_IOCTL_MEDLEN, bsscfg_idx,
  7279. &cfg->ioctl_buf_sync);
  7280. if (ret < 0) {
  7281. WL_ERR(("if_counters not supported ret=%d\n", ret));
  7282. goto fail;
  7283. }
  7284. /* Reuse request to process response */
  7285. response = (wl_stats_report_t *)pbuf;
  7286. /* version check */
  7287. if (response->version != WL_STATS_REPORT_REQUEST_VERSION_V2) {
  7288. ret = BCME_VERSION;
  7289. goto fail;
  7290. }
  7291. xtlv = (bcm_xtlv_t *)(response->data);
  7292. expected_resp_len =
  7293. (BCM_XTLV_LEN(xtlv) + OFFSETOF(wl_stats_report_t, data));
  7294. /* Check if the received length is as expected */
  7295. if ((response->length > WLC_IOCTL_MEDLEN) ||
  7296. (response->length < expected_resp_len)) {
  7297. ret = BCME_ERROR;
  7298. WL_ERR(("Illegal response length received. Got: %d"
  7299. " Expected: %d. Expected len must be <= %u\n",
  7300. response->length, expected_resp_len, WLC_IOCTL_MEDLEN));
  7301. goto fail;
  7302. }
  7303. /* check the type. The return data will be in
  7304. * WL_IFSTATS_XTLV_IF container. So check if that container is
  7305. * present
  7306. */
  7307. if (BCM_XTLV_ID(xtlv) != WL_IFSTATS_XTLV_IF) {
  7308. ret = BCME_ERROR;
  7309. WL_ERR(("unexpected type received: %d Expected: %d\n",
  7310. BCM_XTLV_ID(xtlv), WL_IFSTATS_XTLV_IF));
  7311. goto fail;
  7312. }
  7313. /* Process XTLVs within WL_IFSTATS_XTLV_IF container */
  7314. ret = bcm_unpack_xtlv_buf(if_stats,
  7315. (uint8*)response->data + BCM_XTLV_HDR_SIZE,
  7316. BCM_XTLV_LEN(xtlv), /* total length of all TLVs in container */
  7317. BCM_XTLV_OPTION_ALIGN32, wl_cfg80211_ifstats_counters_cb);
  7318. if (ret) {
  7319. WL_ERR(("Error unpacking XTLVs in wl_ifstats_counters: %d\n", ret));
  7320. }
  7321. fail:
  7322. if (pbuf) {
  7323. MFREE(dhdp->osh, pbuf, WLC_IOCTL_MEDLEN);
  7324. }
  7325. if (request) {
  7326. MFREE(dhdp->osh, request, IF_COUNTERS_PARAM_CONTAINER_LEN_MAX);
  7327. }
  7328. return ret;
  7329. }
  7330. #undef IF_COUNTERS_PARAM_CONTAINER_LEN_MAX
  7331. #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
  7332. static s32
  7333. wl_cfg80211_get_station(struct wiphy *wiphy, struct net_device *dev,
  7334. const u8 *mac, struct station_info *sinfo)
  7335. #else
  7336. static s32
  7337. wl_cfg80211_get_station(struct wiphy *wiphy, struct net_device *dev,
  7338. u8 *mac, struct station_info *sinfo)
  7339. #endif // endif
  7340. {
  7341. struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
  7342. s32 rssi = 0;
  7343. s32 rate = 0;
  7344. s32 err = 0;
  7345. u16 wl_iftype = 0;
  7346. u16 wl_mode = 0;
  7347. get_pktcnt_t pktcnt;
  7348. wl_if_stats_t *if_stats = NULL;
  7349. sta_info_v4_t *sta = NULL;
  7350. u8 *curmacp = NULL;
  7351. #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0)) || defined(WL_COMPAT_WIRELESS)
  7352. s8 eabuf[ETHER_ADDR_STR_LEN];
  7353. #endif // endif
  7354. dhd_pub_t *dhd = (dhd_pub_t *)(cfg->pub);
  7355. bool fw_assoc_state = FALSE;
  7356. u32 dhd_assoc_state = 0;
  7357. void *buf;
  7358. RETURN_EIO_IF_NOT_UP(cfg);
  7359. if (cfg80211_to_wl_iftype(dev->ieee80211_ptr->iftype, &wl_iftype, &wl_mode) < 0) {
  7360. return -EINVAL;
  7361. }
  7362. buf = MALLOC(cfg->osh, MAX(sizeof(wl_if_stats_t), WLC_IOCTL_SMLEN));
  7363. if (buf == NULL) {
  7364. WL_ERR(("wl_cfg80211_get_station: MALLOC failed\n"));
  7365. goto error;
  7366. }
  7367. switch (wl_iftype) {
  7368. case WL_IF_TYPE_STA:
  7369. case WL_IF_TYPE_IBSS:
  7370. if (cfg->roam_offload) {
  7371. struct ether_addr bssid;
  7372. bzero(&bssid, sizeof(bssid));
  7373. err = wldev_ioctl_get(dev, WLC_GET_BSSID, &bssid, ETHER_ADDR_LEN);
  7374. if (err) {
  7375. WL_ERR(("Failed to get current BSSID\n"));
  7376. } else {
  7377. if (memcmp(mac, &bssid.octet, ETHER_ADDR_LEN) != 0) {
  7378. /* roaming is detected */
  7379. err = wl_cfg80211_delayed_roam(cfg, dev, &bssid);
  7380. if (err)
  7381. WL_ERR(("Failed to handle the delayed"
  7382. " roam, err=%d", err));
  7383. mac = (u8 *)bssid.octet;
  7384. }
  7385. }
  7386. }
  7387. dhd_assoc_state = wl_get_drv_status(cfg, CONNECTED, dev);
  7388. DHD_OS_WAKE_LOCK(dhd);
  7389. fw_assoc_state = dhd_is_associated(dhd, 0, &err);
  7390. if (dhd_assoc_state && !fw_assoc_state) {
  7391. /* check roam (join) status */
  7392. if (wl_check_assoc_state(cfg, dev)) {
  7393. fw_assoc_state = TRUE;
  7394. WL_DBG(("roam status\n"));
  7395. }
  7396. }
  7397. DHD_OS_WAKE_UNLOCK(dhd);
  7398. if (!dhd_assoc_state || !fw_assoc_state) {
  7399. WL_ERR(("NOT assoc\n"));
  7400. if (err == -ENODATA)
  7401. goto error;
  7402. if (!dhd_assoc_state) {
  7403. WL_TRACE_HW4(("drv state is not connected \n"));
  7404. }
  7405. if (!fw_assoc_state) {
  7406. WL_TRACE_HW4(("fw state is not associated \n"));
  7407. }
  7408. /* Disconnect due to fw is not associated for
  7409. * FW_ASSOC_WATCHDOG_TIME ms.
  7410. * 'err == 0' of dhd_is_associated() and '!fw_assoc_state'
  7411. * means that BSSID is null.
  7412. */
  7413. if (dhd_assoc_state && !fw_assoc_state && !err) {
  7414. if (!fw_assoc_watchdog_started) {
  7415. fw_assoc_watchdog_ms = OSL_SYSUPTIME();
  7416. fw_assoc_watchdog_started = TRUE;
  7417. WL_TRACE_HW4(("fw_assoc_watchdog_started \n"));
  7418. } else if (OSL_SYSUPTIME() - fw_assoc_watchdog_ms >
  7419. FW_ASSOC_WATCHDOG_TIME) {
  7420. fw_assoc_watchdog_started = FALSE;
  7421. err = -ENODEV;
  7422. WL_TRACE_HW4(("fw is not associated for %d ms \n",
  7423. (OSL_SYSUPTIME() - fw_assoc_watchdog_ms)));
  7424. goto get_station_err;
  7425. }
  7426. }
  7427. err = -ENODEV;
  7428. goto error;
  7429. }
  7430. if (dhd_is_associated(dhd, 0, NULL)) {
  7431. fw_assoc_watchdog_started = FALSE;
  7432. }
  7433. curmacp = wl_read_prof(cfg, dev, WL_PROF_BSSID);
  7434. if (memcmp(mac, curmacp, ETHER_ADDR_LEN)) {
  7435. WL_ERR(("Wrong Mac address: "MACDBG" != "MACDBG"\n",
  7436. MAC2STRDBG(mac), MAC2STRDBG(curmacp)));
  7437. }
  7438. /* go through to get another information */
  7439. /* fall through */
  7440. case WL_IF_TYPE_P2P_GC:
  7441. case WL_IF_TYPE_P2P_DISC:
  7442. if ((err = wl_cfg80211_get_rssi(dev, cfg, &rssi)) != BCME_OK) {
  7443. goto get_station_err;
  7444. }
  7445. sinfo->filled |= STA_INFO_BIT(INFO_SIGNAL);
  7446. sinfo->signal = rssi;
  7447. WL_DBG(("RSSI %d dBm\n", rssi));
  7448. /* go through to get another information */
  7449. /* fall through */
  7450. case WL_IF_TYPE_P2P_GO:
  7451. /* Report the current tx rate */
  7452. rate = 0;
  7453. err = wldev_ioctl_get(dev, WLC_GET_RATE, &rate, sizeof(rate));
  7454. if (err) {
  7455. WL_ERR(("Could not get rate (%d)\n", err));
  7456. } else {
  7457. #if defined(USE_DYNAMIC_MAXPKT_RXGLOM)
  7458. int rxpktglom;
  7459. #endif // endif
  7460. rate = dtoh32(rate);
  7461. sinfo->filled |= STA_INFO_BIT(INFO_TX_BITRATE);
  7462. sinfo->txrate.legacy = rate * 5;
  7463. WL_DBG(("Rate %d Mbps\n", (rate / 2)));
  7464. #if defined(USE_DYNAMIC_MAXPKT_RXGLOM)
  7465. rxpktglom = ((rate/2) > 150) ? 20 : 10;
  7466. if (maxrxpktglom != rxpktglom) {
  7467. maxrxpktglom = rxpktglom;
  7468. WL_DBG(("Rate %d Mbps, update bus:"
  7469. "maxtxpktglom=%d\n", (rate/2), maxrxpktglom));
  7470. err = wldev_iovar_setbuf(dev, "bus:maxtxpktglom",
  7471. (char*)&maxrxpktglom, 4, cfg->ioctl_buf,
  7472. WLC_IOCTL_MAXLEN, &cfg->ioctl_buf_sync);
  7473. if (err < 0) {
  7474. WL_ERR(("set bus:maxtxpktglom failed, %d\n", err));
  7475. }
  7476. }
  7477. #endif // endif
  7478. }
  7479. if_stats = (wl_if_stats_t *)buf;
  7480. bzero(if_stats, sizeof(*if_stats));
  7481. if (FW_SUPPORTED(dhd, ifst)) {
  7482. err = wl_cfg80211_ifstats_counters(dev, if_stats);
  7483. } else
  7484. {
  7485. err = wldev_iovar_getbuf(dev, "if_counters", NULL, 0,
  7486. (char *)if_stats, sizeof(*if_stats), NULL);
  7487. }
  7488. if (err) {
  7489. WL_ERR(("if_counters not supported ret=%d\n",
  7490. err));
  7491. bzero(&pktcnt, sizeof(pktcnt));
  7492. err = wldev_ioctl_get(dev, WLC_GET_PKTCNTS, &pktcnt,
  7493. sizeof(pktcnt));
  7494. if (!err) {
  7495. sinfo->rx_packets = pktcnt.rx_good_pkt;
  7496. sinfo->rx_dropped_misc = pktcnt.rx_bad_pkt;
  7497. sinfo->tx_packets = pktcnt.tx_good_pkt;
  7498. sinfo->tx_failed = pktcnt.tx_bad_pkt;
  7499. }
  7500. } else {
  7501. sinfo->rx_packets = (uint32)dtoh64(if_stats->rxframe);
  7502. sinfo->rx_dropped_misc = 0;
  7503. sinfo->tx_packets = (uint32)dtoh64(if_stats->txfrmsnt);
  7504. sinfo->tx_failed = (uint32)dtoh64(if_stats->txnobuf) +
  7505. (uint32)dtoh64(if_stats->txrunt) +
  7506. (uint32)dtoh64(if_stats->txfail);
  7507. }
  7508. sinfo->filled |= (STA_INFO_BIT(INFO_RX_PACKETS) |
  7509. STA_INFO_BIT(INFO_RX_DROP_MISC) |
  7510. STA_INFO_BIT(INFO_TX_PACKETS) |
  7511. STA_INFO_BIT(INFO_TX_FAILED));
  7512. get_station_err:
  7513. if (err && (err != -ENODATA)) {
  7514. /* Disconnect due to zero BSSID or error to get RSSI */
  7515. scb_val_t scbval;
  7516. DHD_STATLOG_CTRL(dhd, ST(DISASSOC_INT_START),
  7517. dhd_net2idx(dhd->info, dev), DOT11_RC_DISASSOC_LEAVING);
  7518. scbval.val = htod32(DOT11_RC_DISASSOC_LEAVING);
  7519. err = wldev_ioctl_set(dev, WLC_DISASSOC, &scbval,
  7520. sizeof(scb_val_t));
  7521. if (unlikely(err)) {
  7522. WL_ERR(("disassoc error (%d)\n", err));
  7523. }
  7524. WL_ERR(("force cfg80211_disconnected: %d\n", err));
  7525. wl_clr_drv_status(cfg, CONNECTED, dev);
  7526. DHD_STATLOG_CTRL(dhd, ST(DISASSOC_DONE),
  7527. dhd_net2idx(dhd->info, dev), DOT11_RC_DISASSOC_LEAVING);
  7528. CFG80211_DISCONNECTED(dev, 0, NULL, 0, false, GFP_KERNEL);
  7529. wl_link_down(cfg);
  7530. }
  7531. break;
  7532. case WL_IF_TYPE_AP:
  7533. err = wldev_iovar_getbuf(dev, "sta_info", (const void*)mac,
  7534. ETHER_ADDR_LEN, buf, WLC_IOCTL_SMLEN, NULL);
  7535. if (err < 0) {
  7536. WL_ERR(("GET STA INFO failed, %d\n", err));
  7537. goto error;
  7538. }
  7539. sinfo->filled = STA_INFO_BIT(INFO_INACTIVE_TIME);
  7540. sta = (sta_info_v4_t *)buf;
  7541. if (sta->ver != WL_STA_VER_4 && sta->ver != WL_STA_VER_5) {
  7542. WL_ERR(("GET STA INFO version mismatch, %d\n", err));
  7543. return BCME_VERSION;
  7544. }
  7545. sta->len = dtoh16(sta->len);
  7546. sta->cap = dtoh16(sta->cap);
  7547. sta->flags = dtoh32(sta->flags);
  7548. sta->idle = dtoh32(sta->idle);
  7549. sta->in = dtoh32(sta->in);
  7550. sinfo->inactive_time = sta->idle * 1000;
  7551. #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0)) || defined(WL_COMPAT_WIRELESS)
  7552. if (sta->flags & WL_STA_ASSOC) {
  7553. sinfo->filled |= STA_INFO_BIT(INFO_CONNECTED_TIME);
  7554. sinfo->connected_time = sta->in;
  7555. }
  7556. WL_INFORM_MEM(("[%s] STA %s : idle time : %d sec,"
  7557. " connected time :%d ms\n",
  7558. dev->name,
  7559. bcm_ether_ntoa((const struct ether_addr *)mac, eabuf),
  7560. sinfo->inactive_time, sta->idle * 1000));
  7561. #endif // endif
  7562. break;
  7563. default :
  7564. WL_ERR(("Invalid device mode %d\n", wl_get_mode_by_netdev(cfg, dev)));
  7565. }
  7566. error:
  7567. if (buf) {
  7568. MFREE(cfg->osh, buf, MAX(sizeof(wl_if_stats_t), WLC_IOCTL_SMLEN));
  7569. }
  7570. return err;
  7571. }
  7572. static s32
  7573. wl_cfg80211_set_power_mgmt(struct wiphy *wiphy, struct net_device *dev,
  7574. bool enabled, s32 timeout)
  7575. {
  7576. s32 pm;
  7577. s32 err = 0;
  7578. struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
  7579. struct net_info *_net_info = wl_get_netinfo_by_netdev(cfg, dev);
  7580. s32 mode;
  7581. #ifdef RTT_SUPPORT
  7582. dhd_pub_t *dhd = cfg->pub;
  7583. rtt_status_info_t *rtt_status;
  7584. #endif /* RTT_SUPPORT */
  7585. RETURN_EIO_IF_NOT_UP(cfg);
  7586. WL_DBG(("Enter\n"));
  7587. mode = wl_get_mode_by_netdev(cfg, dev);
  7588. if (cfg->p2p_net == dev || _net_info == NULL ||
  7589. !wl_get_drv_status(cfg, CONNECTED, dev) ||
  7590. ((mode != WL_MODE_BSS) &&
  7591. (mode != WL_MODE_IBSS))) {
  7592. return err;
  7593. }
  7594. /* Enlarge pm_enable_work */
  7595. wl_add_remove_pm_enable_work(cfg, WL_PM_WORKQ_LONG);
  7596. pm = enabled ? PM_FAST : PM_OFF;
  7597. if (_net_info->pm_block) {
  7598. WL_ERR(("%s:Do not enable the power save for pm_block %d\n",
  7599. dev->name, _net_info->pm_block));
  7600. pm = PM_OFF;
  7601. }
  7602. pm = htod32(pm);
  7603. WL_DBG(("%s:power save %s\n", dev->name, (pm ? "enabled" : "disabled")));
  7604. #ifdef RTT_SUPPORT
  7605. rtt_status = GET_RTTSTATE(dhd);
  7606. if (rtt_status->status != RTT_ENABLED) {
  7607. #endif /* RTT_SUPPORT */
  7608. err = wldev_ioctl_set(dev, WLC_SET_PM, &pm, sizeof(pm));
  7609. if (unlikely(err)) {
  7610. if (err == -ENODEV)
  7611. WL_DBG(("net_device is not ready yet\n"));
  7612. else
  7613. WL_ERR(("error (%d)\n", err));
  7614. return err;
  7615. }
  7616. #ifdef RTT_SUPPORT
  7617. }
  7618. #endif /* RTT_SUPPORT */
  7619. wl_cfg80211_update_power_mode(dev);
  7620. return err;
  7621. }
  7622. void wl_cfg80211_update_power_mode(struct net_device *dev)
  7623. {
  7624. int err, pm = -1;
  7625. err = wldev_ioctl_get(dev, WLC_GET_PM, &pm, sizeof(pm));
  7626. if (err)
  7627. WL_ERR(("wl_cfg80211_update_power_mode: error (%d)\n", err));
  7628. else if (pm != -1 && dev->ieee80211_ptr)
  7629. dev->ieee80211_ptr->ps = (pm == PM_OFF) ? false : true;
  7630. }
  7631. static __used u32 wl_find_msb(u16 bit16)
  7632. {
  7633. u32 ret = 0;
  7634. if (bit16 & 0xff00) {
  7635. ret += 8;
  7636. bit16 >>= 8;
  7637. }
  7638. if (bit16 & 0xf0) {
  7639. ret += 4;
  7640. bit16 >>= 4;
  7641. }
  7642. if (bit16 & 0xc) {
  7643. ret += 2;
  7644. bit16 >>= 2;
  7645. }
  7646. if (bit16 & 2)
  7647. ret += bit16 & 2;
  7648. else if (bit16)
  7649. ret += bit16;
  7650. return ret;
  7651. }
  7652. static s32 wl_cfg80211_resume(struct wiphy *wiphy)
  7653. {
  7654. struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
  7655. struct net_device *ndev = bcmcfg_to_prmry_ndev(cfg);
  7656. s32 err = BCME_OK;
  7657. #if ((LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 39)) || defined(WL_COMPAT_WIRELESS)) && \
  7658. !defined(OEM_ANDROID)
  7659. int pkt_filter_id = WL_WOWLAN_PKT_FILTER_ID_FIRST;
  7660. #endif /* (KERNEL_VERSION(2, 6, 39) || WL_COMPAT_WIRELES) && !OEM_ANDROID */
  7661. if (unlikely(!wl_get_drv_status(cfg, READY, ndev))) {
  7662. WL_INFORM_MEM(("device is not ready\n"));
  7663. return err;
  7664. }
  7665. #if ((LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 39)) || defined(WL_COMPAT_WIRELESS)) && \
  7666. !defined(OEM_ANDROID)
  7667. while (pkt_filter_id <= WL_WOWLAN_PKT_FILTER_ID_LAST) {
  7668. /* delete wowlan pkt filter if any */
  7669. err = wldev_iovar_setbuf(ndev, "pkt_filter_delete", &pkt_filter_id,
  7670. sizeof(pkt_filter_id), cfg->ioctl_buf, WLC_IOCTL_SMLEN,
  7671. &cfg->ioctl_buf_sync);
  7672. /* pkt_filter_delete would return BCME_BADARG when pkt filter id
  7673. * does not exist in filter list of firmware, ignore it.
  7674. */
  7675. if (BCME_BADARG == err)
  7676. err = BCME_OK;
  7677. if (BCME_OK != err) {
  7678. WL_ERR(("pkt_filter_delete failed, id=%d, err=%d\n",
  7679. pkt_filter_id, err));
  7680. }
  7681. pkt_filter_id++;
  7682. }
  7683. #endif /* (KERNEL_VERSION(2, 6, 39) || WL_COMPAT_WIRELES) && !OEM_ANDROID */
  7684. return err;
  7685. }
  7686. #if ((LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 39)) || defined(WL_COMPAT_WIRELESS)) && \
  7687. !defined(OEM_ANDROID)
  7688. static s32 wl_wowlan_config(struct wiphy *wiphy, struct cfg80211_wowlan *wow)
  7689. {
  7690. s32 err = BCME_OK;
  7691. struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
  7692. struct net_device *ndev = bcmcfg_to_prmry_ndev(cfg);
  7693. u32 i = 0, j = 0;
  7694. u32 buf_len = 0, pattern_size = 0;
  7695. wl_pkt_filter_t *pkt_filterp = NULL;
  7696. wl_pkt_filter_enable_t pkt_filter_enable;
  7697. u8 mask_bytes_len = 0, mask_byte_idx = 0, mask_bit_idx = 0;
  7698. const u32 max_buf_size = WL_PKT_FILTER_FIXED_LEN +
  7699. WL_PKT_FILTER_PATTERN_FIXED_LEN + (2 * WL_WOWLAN_MAX_PATTERN_LEN);
  7700. WL_DBG(("Enter\n"));
  7701. if (wow == NULL) {
  7702. WL_DBG(("wow config is null\n"));
  7703. return err;
  7704. }
  7705. /* configure wowlan pattern filters */
  7706. if (0 < wow->n_patterns) {
  7707. pkt_filterp = (wl_pkt_filter_t *)MALLOCZ(cfg->osh, max_buf_size);
  7708. if (pkt_filterp == NULL) {
  7709. WL_ERR(("Error allocating buffer for pkt filters\n"));
  7710. return -ENOMEM;
  7711. }
  7712. WL_DBG(("Pattern count=%d\n", wow->n_patterns));
  7713. while (i < wow->n_patterns) {
  7714. /* reset buffers */
  7715. buf_len = 0;
  7716. bzero(pkt_filterp, max_buf_size);
  7717. /* copy filter id */
  7718. store32_ua(&pkt_filterp->id, (WL_WOWLAN_PKT_FILTER_ID_FIRST + i));
  7719. /* copy filter type */
  7720. store32_ua(&pkt_filterp->type, WL_PKT_FILTER_TYPE_PATTERN_MATCH);
  7721. /* copy size */
  7722. pattern_size = htod32(wow->patterns[i].pattern_len);
  7723. store32_ua(&pkt_filterp->u.pattern.size_bytes, pattern_size);
  7724. #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0))
  7725. /* copy offset */
  7726. store32_ua(&pkt_filterp->u.pattern.offset, wow->patterns[i].pkt_offset);
  7727. #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0) */
  7728. /* convert mask from bit to byte format */
  7729. j = 0;
  7730. mask_bit_idx = 0;
  7731. mask_byte_idx = 0;
  7732. mask_bytes_len = DIV_ROUND_UP(pattern_size, 8);
  7733. while ((mask_byte_idx < mask_bytes_len) &&
  7734. (mask_bit_idx < pattern_size)) {
  7735. if (isbitset(wow->patterns[i].mask[mask_byte_idx], mask_bit_idx++))
  7736. pkt_filterp->u.pattern.mask_and_pattern[j] = 0xFF;
  7737. j++;
  7738. if (mask_bit_idx >= 8) {
  7739. /* move to next mask byte */
  7740. mask_bit_idx = 0;
  7741. mask_byte_idx++;
  7742. }
  7743. }
  7744. /* copy pattern to be matched */
  7745. memcpy(&pkt_filterp->u.pattern.mask_and_pattern[pattern_size],
  7746. wow->patterns[i].pattern, pattern_size);
  7747. /* calculate filter buffer len */
  7748. buf_len += WL_PKT_FILTER_FIXED_LEN;
  7749. buf_len += (WL_PKT_FILTER_PATTERN_FIXED_LEN + (2 * pattern_size));
  7750. /* add pkt filter */
  7751. err = wldev_iovar_setbuf(ndev, "pkt_filter_add", pkt_filterp, buf_len,
  7752. cfg->ioctl_buf, WLC_IOCTL_MEDLEN, &cfg->ioctl_buf_sync);
  7753. if (BCME_OK != err) {
  7754. WL_ERR(("pkt_filter_add failed, id=%d, err=%d\n",
  7755. pkt_filterp->id, err));
  7756. goto exit;
  7757. }
  7758. /* enable pkt filter id */
  7759. pkt_filter_enable.id = pkt_filterp->id;
  7760. pkt_filter_enable.enable = TRUE;
  7761. err = wldev_iovar_setbuf(ndev, "pkt_filter_enable", &pkt_filter_enable,
  7762. sizeof(pkt_filter_enable),
  7763. cfg->ioctl_buf, WLC_IOCTL_SMLEN, &cfg->ioctl_buf_sync);
  7764. if (BCME_OK != err) {
  7765. WL_ERR(("pkt_filter_enable failed, id=%d, err=%d\n",
  7766. pkt_filterp->id, err));
  7767. goto exit;
  7768. }
  7769. i++; /* move to next pattern */
  7770. }
  7771. } else
  7772. WL_DBG(("wowlan filters not found\n"));
  7773. exit:
  7774. if (pkt_filterp) {
  7775. MFREE(cfg->osh, pkt_filterp, max_buf_size);
  7776. }
  7777. return err;
  7778. }
  7779. #endif /* (KERNEL_VERSION(2, 6, 39) || WL_COMPAT_WIRELES) && !OEM_ANDROID */
  7780. #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 39)) || defined(WL_COMPAT_WIRELESS)
  7781. static s32 wl_cfg80211_suspend(struct wiphy *wiphy, struct cfg80211_wowlan *wow)
  7782. #else
  7783. static s32 wl_cfg80211_suspend(struct wiphy *wiphy)
  7784. #endif // endif
  7785. {
  7786. s32 err = BCME_OK;
  7787. #ifdef DHD_CLEAR_ON_SUSPEND
  7788. struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
  7789. struct net_info *iter, *next;
  7790. struct net_device *ndev = bcmcfg_to_prmry_ndev(cfg);
  7791. unsigned long flags;
  7792. if (unlikely(!wl_get_drv_status(cfg, READY, ndev))) {
  7793. WL_INFORM_MEM(("device is not ready : status (%d)\n",
  7794. (int)cfg->status));
  7795. return err;
  7796. }
  7797. for_each_ndev(cfg, iter, next) {
  7798. /* p2p discovery iface doesn't have a ndev associated with it (for kernel > 3.8) */
  7799. if (iter->ndev)
  7800. wl_set_drv_status(cfg, SCAN_ABORTING, iter->ndev);
  7801. }
  7802. WL_CFG_DRV_LOCK(&cfg->cfgdrv_lock, flags);
  7803. if (cfg->scan_request) {
  7804. cfg80211_scan_done(cfg->scan_request, true);
  7805. cfg->scan_request = NULL;
  7806. }
  7807. for_each_ndev(cfg, iter, next) {
  7808. if (iter->ndev) {
  7809. wl_clr_drv_status(cfg, SCANNING, iter->ndev);
  7810. wl_clr_drv_status(cfg, SCAN_ABORTING, iter->ndev);
  7811. }
  7812. }
  7813. WL_CFG_DRV_UNLOCK(&cfg->cfgdrv_lock, flags);
  7814. for_each_ndev(cfg, iter, next) {
  7815. if (iter->ndev) {
  7816. if (wl_get_drv_status(cfg, CONNECTING, iter->ndev)) {
  7817. wl_bss_connect_done(cfg, iter->ndev, NULL, NULL, false);
  7818. }
  7819. }
  7820. }
  7821. #endif /* DHD_CLEAR_ON_SUSPEND */
  7822. #if ((LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 39)) || defined(WL_COMPAT_WIRELESS)) && \
  7823. !defined(OEM_ANDROID)
  7824. err = wl_wowlan_config(wiphy, wow);
  7825. #endif /* (KERNEL_VERSION(2, 6, 39) || WL_COMPAT_WIRELES) && !OEM_ANDROID */
  7826. return err;
  7827. }
  7828. static s32
  7829. wl_update_pmklist(struct net_device *dev, struct wl_pmk_list *pmk_list,
  7830. s32 err)
  7831. {
  7832. int i, j;
  7833. struct bcm_cfg80211 *cfg = wl_get_cfg(dev);
  7834. struct net_device *primary_dev = bcmcfg_to_prmry_ndev(cfg);
  7835. int npmkids = cfg->pmk_list->pmkids.count;
  7836. ASSERT(cfg->pmk_list->pmkids.length >= (sizeof(u16)*2));
  7837. if (!pmk_list) {
  7838. WL_INFORM_MEM(("pmk_list is NULL\n"));
  7839. return -EINVAL;
  7840. }
  7841. /* pmk list is supported only for STA interface i.e. primary interface
  7842. * Refer code wlc_bsscfg.c->wlc_bsscfg_sta_init
  7843. */
  7844. if (primary_dev != dev) {
  7845. WL_INFORM_MEM(("Not supporting Flushing pmklist on virtual"
  7846. " interfaces than primary interface\n"));
  7847. return err;
  7848. }
  7849. WL_DBG(("No of elements %d\n", npmkids));
  7850. for (i = 0; i < npmkids; i++) {
  7851. WL_DBG(("PMKID[%d]: %pM =\n", i,
  7852. &pmk_list->pmkids.pmkid[i].bssid));
  7853. for (j = 0; j < WPA2_PMKID_LEN; j++) {
  7854. WL_DBG(("%02x\n", pmk_list->pmkids.pmkid[i].pmkid[j]));
  7855. }
  7856. }
  7857. if (cfg->wlc_ver.wlc_ver_major >= MIN_PMKID_LIST_V3_FW_MAJOR) {
  7858. pmk_list->pmkids.version = PMKID_LIST_VER_3;
  7859. err = wldev_iovar_setbuf(dev, "pmkid_info", (char *)pmk_list,
  7860. sizeof(*pmk_list), cfg->ioctl_buf,
  7861. WLC_IOCTL_MAXLEN, &cfg->ioctl_buf_sync);
  7862. }
  7863. else if (cfg->wlc_ver.wlc_ver_major == MIN_PMKID_LIST_V2_FW_MAJOR) {
  7864. u32 v2_list_size = (u32)(sizeof(pmkid_list_v2_t) + npmkids*sizeof(pmkid_v2_t));
  7865. pmkid_list_v2_t *pmkid_v2_list = (pmkid_list_v2_t *)MALLOCZ(cfg->osh, v2_list_size);
  7866. if (pmkid_v2_list == NULL) {
  7867. WL_ERR(("failed to allocate pmkid list\n"));
  7868. return BCME_NOMEM;
  7869. }
  7870. pmkid_v2_list->version = PMKID_LIST_VER_2;
  7871. /* Account for version, length and pmkid_v2_t fields */
  7872. pmkid_v2_list->length = (npmkids * sizeof(pmkid_v2_t)) + (2 * sizeof(u16));
  7873. for (i = 0; i < npmkids; i++) {
  7874. /* memcpy_s return checks not needed as buffers are of same size */
  7875. (void)memcpy_s(&pmkid_v2_list->pmkid[i].BSSID,
  7876. ETHER_ADDR_LEN, &pmk_list->pmkids.pmkid[i].bssid,
  7877. ETHER_ADDR_LEN);
  7878. /* copy pmkid if available */
  7879. if (pmk_list->pmkids.pmkid[i].pmkid_len) {
  7880. (void)memcpy_s(pmkid_v2_list->pmkid[i].PMKID,
  7881. WPA2_PMKID_LEN,
  7882. pmk_list->pmkids.pmkid[i].pmkid,
  7883. pmk_list->pmkids.pmkid[i].pmkid_len);
  7884. }
  7885. if (pmk_list->pmkids.pmkid[i].pmk_len) {
  7886. (void)memcpy_s(pmkid_v2_list->pmkid[i].pmk,
  7887. pmk_list->pmkids.pmkid[i].pmk_len,
  7888. pmk_list->pmkids.pmkid[i].pmk,
  7889. pmk_list->pmkids.pmkid[i].pmk_len);
  7890. pmkid_v2_list->pmkid[i].pmk_len = pmk_list->pmkids.pmkid[i].pmk_len;
  7891. }
  7892. if (pmk_list->pmkids.pmkid[i].ssid_len) {
  7893. (void)memcpy_s(pmkid_v2_list->pmkid[i].ssid.ssid,
  7894. pmk_list->pmkids.pmkid[i].ssid_len,
  7895. pmk_list->pmkids.pmkid[i].ssid,
  7896. pmk_list->pmkids.pmkid[i].ssid_len);
  7897. pmkid_v2_list->pmkid[i].ssid.ssid_len
  7898. = pmk_list->pmkids.pmkid[i].ssid_len;
  7899. }
  7900. (void)memcpy_s(pmkid_v2_list->pmkid[i].fils_cache_id,
  7901. FILS_CACHE_ID_LEN, &pmk_list->pmkids.pmkid[i].fils_cache_id,
  7902. FILS_CACHE_ID_LEN);
  7903. pmkid_v2_list->pmkid[i].length = PMKID_ELEM_V2_LENGTH;
  7904. }
  7905. err = wldev_iovar_setbuf(dev, "pmkid_info", (char *)pmkid_v2_list,
  7906. v2_list_size, cfg->ioctl_buf,
  7907. WLC_IOCTL_MAXLEN, &cfg->ioctl_buf_sync);
  7908. if (unlikely(err)) {
  7909. WL_ERR(("pmkid_info failed (%d)\n", err));
  7910. }
  7911. MFREE(cfg->osh, pmkid_v2_list, v2_list_size);
  7912. }
  7913. else {
  7914. u32 v1_list_size = (u32)(sizeof(pmkid_list_v1_t) + npmkids*sizeof(pmkid_v1_t));
  7915. pmkid_list_v1_t *pmkid_v1_list = (pmkid_list_v1_t *)MALLOCZ(cfg->osh, v1_list_size);
  7916. if (pmkid_v1_list == NULL) {
  7917. WL_ERR(("failed to allocate pmkid list\n"));
  7918. return BCME_NOMEM;
  7919. }
  7920. for (i = 0; i < npmkids; i++) {
  7921. /* memcpy_s return checks not needed as buffers are of same size */
  7922. (void)memcpy_s(&pmkid_v1_list->pmkid[i].BSSID,
  7923. ETHER_ADDR_LEN, &pmk_list->pmkids.pmkid[i].bssid,
  7924. ETHER_ADDR_LEN);
  7925. (void)memcpy_s(pmkid_v1_list->pmkid[i].PMKID,
  7926. WPA2_PMKID_LEN, pmk_list->pmkids.pmkid[i].pmkid,
  7927. WPA2_PMKID_LEN);
  7928. pmkid_v1_list->npmkid++;
  7929. }
  7930. err = wldev_iovar_setbuf(dev, "pmkid_info", (char *)pmkid_v1_list,
  7931. v1_list_size, cfg->ioctl_buf,
  7932. WLC_IOCTL_MAXLEN, &cfg->ioctl_buf_sync);
  7933. if (unlikely(err)) {
  7934. WL_ERR(("pmkid_info failed (%d)\n", err));
  7935. }
  7936. MFREE(cfg->osh, pmkid_v1_list, v1_list_size);
  7937. }
  7938. return err;
  7939. }
  7940. /* TODO: remove temporal cfg->pmk_list list, and call wl_cfg80211_update_pmksa for single
  7941. * entry operation.
  7942. */
  7943. static s32
  7944. wl_cfg80211_set_pmksa(struct wiphy *wiphy, struct net_device *dev,
  7945. struct cfg80211_pmksa *pmksa)
  7946. {
  7947. struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
  7948. s32 err = 0;
  7949. int i;
  7950. int npmkids = cfg->pmk_list->pmkids.count;
  7951. dhd_pub_t *dhdp = (dhd_pub_t *)(cfg->pub);
  7952. RETURN_EIO_IF_NOT_UP(cfg);
  7953. BCM_REFERENCE(dhdp);
  7954. DHD_STATLOG_CTRL(dhdp, ST(INSTALL_PMKSA), dhd_net2idx(dhdp->info, dev), 0);
  7955. for (i = 0; i < npmkids; i++) {
  7956. if (pmksa->bssid != NULL) {
  7957. if (!memcmp(pmksa->bssid, &cfg->pmk_list->pmkids.pmkid[i].bssid,
  7958. ETHER_ADDR_LEN))
  7959. break;
  7960. }
  7961. #ifdef WL_FILS
  7962. else if (pmksa->ssid != NULL) {
  7963. if (!memcmp(pmksa->ssid, &cfg->pmk_list->pmkids.pmkid[i].ssid,
  7964. pmksa->ssid_len))
  7965. break;
  7966. }
  7967. #endif /* WL_FILS */
  7968. }
  7969. if (i < WL_NUM_PMKIDS_MAX) {
  7970. if (pmksa->bssid != NULL) {
  7971. memcpy(&cfg->pmk_list->pmkids.pmkid[i].bssid, pmksa->bssid,
  7972. ETHER_ADDR_LEN);
  7973. }
  7974. #ifdef WL_FILS
  7975. else if (pmksa->ssid != NULL) {
  7976. cfg->pmk_list->pmkids.pmkid[i].ssid_len = pmksa->ssid_len;
  7977. memcpy(&cfg->pmk_list->pmkids.pmkid[i].ssid, pmksa->ssid,
  7978. pmksa->ssid_len);
  7979. memcpy(&cfg->pmk_list->pmkids.pmkid[i].fils_cache_id, pmksa->cache_id,
  7980. FILS_CACHE_ID_LEN);
  7981. }
  7982. #endif /* WL_FILS */
  7983. #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0) || defined(WL_FILS))
  7984. if (pmksa->pmk_len) {
  7985. if (memcpy_s(&cfg->pmk_list->pmkids.pmkid[i].pmk, PMK_LEN_MAX, pmksa->pmk,
  7986. pmksa->pmk_len)) {
  7987. WL_ERR(("invalid pmk len = %lu", pmksa->pmk_len));
  7988. } else {
  7989. cfg->pmk_list->pmkids.pmkid[i].pmk_len = pmksa->pmk_len;
  7990. }
  7991. }
  7992. #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0) || defined(WL_FILS) */
  7993. /* return check not required as buffer lengths are same */
  7994. (void)memcpy_s(cfg->pmk_list->pmkids.pmkid[i].pmkid, WPA2_PMKID_LEN, pmksa->pmkid,
  7995. WPA2_PMKID_LEN);
  7996. cfg->pmk_list->pmkids.pmkid[i].pmkid_len = WPA2_PMKID_LEN;
  7997. /* set lifetime not to expire in firmware by default.
  7998. * Currently, wpa_supplicant control PMKID lifetime on his end. e.g) set 12 hours
  7999. * when it expired, wpa_supplicant should call set_pmksa/del_pmksa to update
  8000. * corresponding entry.
  8001. */
  8002. cfg->pmk_list->pmkids.pmkid[i].time_left = KEY_PERM_PMK;
  8003. if (i == npmkids) {
  8004. cfg->pmk_list->pmkids.length += sizeof(pmkid_v3_t);
  8005. cfg->pmk_list->pmkids.count++;
  8006. }
  8007. } else {
  8008. err = -EINVAL;
  8009. }
  8010. #if (WL_DBG_LEVEL > 0)
  8011. if (pmksa->bssid != NULL) {
  8012. WL_DBG(("set_pmksa,IW_PMKSA_ADD - PMKID: %pM =\n",
  8013. &cfg->pmk_list->pmkids.pmkid[npmkids - 1].bssid));
  8014. }
  8015. for (i = 0; i < WPA2_PMKID_LEN; i++) {
  8016. WL_DBG(("%02x\n",
  8017. cfg->pmk_list->pmkids.pmkid[npmkids - 1].
  8018. pmkid[i]));
  8019. }
  8020. #endif /* (WL_DBG_LEVEL > 0) */
  8021. err = wl_update_pmklist(dev, cfg->pmk_list, err);
  8022. return err;
  8023. }
  8024. /* sending pmkid_info IOVAR to manipulate PMKID(PMKSA) list in firmware.
  8025. * input @pmksa: host given single pmksa info.
  8026. * if it's NULL, assume whole list manipulated. e.g) flush all PMKIDs in firmware.
  8027. * input @set: TRUE means adding PMKSA operation. FALSE means deleting.
  8028. * return: log internal BCME_XXX error, and convert it to -EINVAL to linux generic error code.
  8029. */
  8030. static s32 wl_cfg80211_update_pmksa(struct wiphy *wiphy, struct net_device *dev,
  8031. struct cfg80211_pmksa *pmksa, bool set) {
  8032. struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
  8033. s32 err = 0;
  8034. pmkid_list_v3_t *pmk_list;
  8035. uint32 alloc_len;
  8036. RETURN_EIO_IF_NOT_UP(cfg);
  8037. if (cfg->wlc_ver.wlc_ver_major < MIN_PMKID_LIST_V3_FW_MAJOR) {
  8038. WL_ERR(("wlc_ver_major not supported:%d\n", cfg->wlc_ver.wlc_ver_major));
  8039. return BCME_VERSION;
  8040. }
  8041. alloc_len = OFFSETOF(pmkid_list_v3_t, pmkid) + ((pmksa) ? sizeof(pmkid_v3_t) : 0);
  8042. pmk_list = (pmkid_list_v3_t *)MALLOCZ(cfg->osh, alloc_len);
  8043. if (pmk_list == NULL) {
  8044. return BCME_NOMEM;
  8045. }
  8046. pmk_list->version = PMKID_LIST_VER_3;
  8047. pmk_list->length = alloc_len;
  8048. pmk_list->count = (pmksa) ? 1 : 0; // 1 means single entry operation, 0 means whole list.
  8049. /* controll set/del action by lifetime parameter accordingly.
  8050. * if set == TRUE, it's set PMKID action with lifetime permanent.
  8051. * if set == FALSE, it's del PMKID action with lifetime zero.
  8052. */
  8053. pmk_list->pmkid->time_left = (set) ? KEY_PERM_PMK : 0;
  8054. if (pmksa) {
  8055. if (pmksa->bssid) {
  8056. err = memcpy_s(&pmk_list->pmkid->bssid, sizeof(pmk_list->pmkid->bssid),
  8057. pmksa->bssid, ETHER_ADDR_LEN);
  8058. if (err) {
  8059. goto exit;
  8060. }
  8061. }
  8062. if (pmksa->pmkid) {
  8063. err = memcpy_s(&pmk_list->pmkid->pmkid, sizeof(pmk_list->pmkid->pmkid),
  8064. pmksa->pmkid, WPA2_PMKID_LEN);
  8065. if (err) {
  8066. goto exit;
  8067. }
  8068. }
  8069. #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0))
  8070. if (pmksa->pmk) {
  8071. err = memcpy_s(&pmk_list->pmkid->pmk, sizeof(pmk_list->pmkid->pmk),
  8072. pmksa->pmk, pmksa->pmk_len);
  8073. if (err) {
  8074. goto exit;
  8075. }
  8076. pmk_list->pmkid->pmk_len = pmksa->pmk_len;
  8077. }
  8078. if (pmksa->ssid) {
  8079. err = memcpy_s(&pmk_list->pmkid->ssid, sizeof(pmk_list->pmkid->ssid),
  8080. pmksa->ssid, pmksa->ssid_len);
  8081. if (err) {
  8082. goto exit;
  8083. }
  8084. pmk_list->pmkid->ssid_len = pmksa->ssid_len;
  8085. }
  8086. if (pmksa->cache_id) {
  8087. pmk_list->pmkid->fils_cache_id = *pmksa->cache_id;
  8088. }
  8089. #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0) */
  8090. }
  8091. err = wldev_iovar_setbuf(dev, "pmkid_info", (char *)pmk_list,
  8092. alloc_len, cfg->ioctl_buf,
  8093. WLC_IOCTL_MAXLEN, &cfg->ioctl_buf_sync);
  8094. exit:
  8095. if (pmk_list) {
  8096. MFREE(cfg->osh, pmk_list, alloc_len);
  8097. }
  8098. return err;
  8099. }
  8100. /* TODO: remove temporal cfg->pmk_list list, and call wl_cfg80211_update_pmksa for single
  8101. * entry operation.
  8102. */
  8103. static s32
  8104. wl_cfg80211_del_pmksa(struct wiphy *wiphy, struct net_device *dev,
  8105. struct cfg80211_pmksa *pmksa)
  8106. {
  8107. struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
  8108. s32 err = 0;
  8109. int i;
  8110. int npmkids = cfg->pmk_list->pmkids.count;
  8111. RETURN_EIO_IF_NOT_UP(cfg);
  8112. if (!pmksa) {
  8113. WL_ERR(("pmksa is not initialized\n"));
  8114. return BCME_ERROR;
  8115. }
  8116. if (!npmkids) {
  8117. /* nmpkids = 0, nothing to delete */
  8118. WL_DBG(("npmkids=0. Skip del\n"));
  8119. return BCME_OK;
  8120. }
  8121. #if (WL_DBG_LEVEL > 0)
  8122. if (pmksa->bssid) {
  8123. WL_DBG(("del_pmksa,IW_PMKSA_REMOVE - PMKID: %pM =\n",
  8124. pmksa->bssid));
  8125. }
  8126. #ifdef WL_FILS
  8127. else if (pmksa->ssid) {
  8128. WL_DBG(("FILS: del_pmksa for ssid: "));
  8129. for (i = 0; i < pmksa->ssid_len; i++) {
  8130. WL_DBG(("%c", pmksa->ssid[i]));
  8131. }
  8132. WL_DBG(("\n"));
  8133. }
  8134. #endif /* WL_FILS */
  8135. if (pmksa->pmkid) {
  8136. for (i = 0; i < WPA2_PMKID_LEN; i++) {
  8137. WL_DBG(("%02x\n", pmksa->pmkid[i]));
  8138. }
  8139. }
  8140. #endif /* (WL_DBG_LEVEL > 0) */
  8141. for (i = 0; i < npmkids; i++) {
  8142. if (pmksa->bssid) {
  8143. if (!memcmp
  8144. (pmksa->bssid, &cfg->pmk_list->pmkids.pmkid[i].bssid,
  8145. ETHER_ADDR_LEN)) {
  8146. break;
  8147. }
  8148. }
  8149. #ifdef WL_FILS
  8150. else if (pmksa->ssid) {
  8151. if (!memcmp
  8152. (pmksa->ssid, &cfg->pmk_list->pmkids.pmkid[i].ssid,
  8153. pmksa->ssid_len)) {
  8154. break;
  8155. }
  8156. }
  8157. #endif /* WL_FILS */
  8158. }
  8159. if ((npmkids > 0) && (i < npmkids)) {
  8160. bzero(&cfg->pmk_list->pmkids.pmkid[i], sizeof(pmkid_v3_t));
  8161. for (; i < (npmkids - 1); i++) {
  8162. (void)memcpy_s(&cfg->pmk_list->pmkids.pmkid[i],
  8163. sizeof(pmkid_v3_t),
  8164. &cfg->pmk_list->pmkids.pmkid[i + 1],
  8165. sizeof(pmkid_v3_t));
  8166. }
  8167. npmkids--;
  8168. cfg->pmk_list->pmkids.length -= sizeof(pmkid_v3_t);
  8169. cfg->pmk_list->pmkids.count--;
  8170. } else {
  8171. err = -EINVAL;
  8172. }
  8173. /* current wl_update_pmklist() doesn't delete corresponding PMKID entry.
  8174. * inside firmware. So we need to issue delete action explicitely through
  8175. * this function.
  8176. */
  8177. err = wl_cfg80211_update_pmksa(wiphy, dev, pmksa, FALSE);
  8178. /* intentional fall through even on error.
  8179. * it should work above MIN_PMKID_LIST_V3_FW_MAJOR, otherwise let ignore it.
  8180. */
  8181. err = wl_update_pmklist(dev, cfg->pmk_list, err);
  8182. return err;
  8183. }
  8184. /* TODO: remove temporal cfg->pmk_list list, and call wl_cfg80211_update_pmksa for single
  8185. * entry operation.
  8186. */
  8187. static s32
  8188. wl_cfg80211_flush_pmksa(struct wiphy *wiphy, struct net_device *dev)
  8189. {
  8190. struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
  8191. s32 err = 0;
  8192. RETURN_EIO_IF_NOT_UP(cfg);
  8193. bzero(cfg->pmk_list, sizeof(*cfg->pmk_list));
  8194. cfg->pmk_list->pmkids.length = OFFSETOF(pmkid_list_v3_t, pmkid);
  8195. cfg->pmk_list->pmkids.count = 0;
  8196. cfg->pmk_list->pmkids.version = PMKID_LIST_VER_3;
  8197. err = wl_update_pmklist(dev, cfg->pmk_list, err);
  8198. return err;
  8199. }
  8200. #if defined(WL_CFG80211_P2P_DEV_IF)
  8201. static s32
  8202. wl_cfg80211_remain_on_channel(struct wiphy *wiphy, bcm_struct_cfgdev *cfgdev,
  8203. struct ieee80211_channel *channel, unsigned int duration, u64 *cookie)
  8204. #else
  8205. static s32
  8206. wl_cfg80211_remain_on_channel(struct wiphy *wiphy, bcm_struct_cfgdev *cfgdev,
  8207. struct ieee80211_channel * channel,
  8208. enum nl80211_channel_type channel_type,
  8209. unsigned int duration, u64 *cookie)
  8210. #endif /* WL_CFG80211_P2P_DEV_IF */
  8211. {
  8212. s32 target_channel;
  8213. u32 id;
  8214. s32 err = BCME_OK;
  8215. struct ether_addr primary_mac;
  8216. struct net_device *ndev = NULL;
  8217. struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
  8218. RETURN_EIO_IF_NOT_UP(cfg);
  8219. #ifdef DHD_IFDEBUG
  8220. PRINT_WDEV_INFO(cfgdev);
  8221. #endif /* DHD_IFDEBUG */
  8222. ndev = cfgdev_to_wlc_ndev(cfgdev, cfg);
  8223. mutex_lock(&cfg->usr_sync);
  8224. WL_DBG(("Enter, channel: %d, duration ms (%d) SCANNING ?? %s \n",
  8225. ieee80211_frequency_to_channel(channel->center_freq),
  8226. duration, (wl_get_drv_status(cfg, SCANNING, ndev)) ? "YES":"NO"));
  8227. if (!cfg->p2p) {
  8228. WL_ERR(("cfg->p2p is not initialized\n"));
  8229. err = BCME_ERROR;
  8230. goto exit;
  8231. }
  8232. #ifdef P2P_LISTEN_OFFLOADING
  8233. if (wl_get_p2p_status(cfg, DISC_IN_PROGRESS)) {
  8234. WL_ERR(("P2P_FIND: Discovery offload is in progress\n"));
  8235. err = -EAGAIN;
  8236. goto exit;
  8237. }
  8238. #endif /* P2P_LISTEN_OFFLOADING */
  8239. #ifndef WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST
  8240. if (wl_get_drv_status_all(cfg, SCANNING)) {
  8241. wl_cfg80211_cancel_scan(cfg);
  8242. }
  8243. #endif /* not WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST */
  8244. target_channel = ieee80211_frequency_to_channel(channel->center_freq);
  8245. memcpy(&cfg->remain_on_chan, channel, sizeof(struct ieee80211_channel));
  8246. #if defined(WL_ENABLE_P2P_IF)
  8247. cfg->remain_on_chan_type = channel_type;
  8248. #endif /* WL_ENABLE_P2P_IF */
  8249. id = ++cfg->last_roc_id;
  8250. if (id == 0)
  8251. id = ++cfg->last_roc_id;
  8252. *cookie = id;
  8253. #ifdef WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST
  8254. if (wl_get_drv_status(cfg, SCANNING, ndev)) {
  8255. timer_list_compat_t *_timer;
  8256. WL_DBG(("scan is running. go to fake listen state\n"));
  8257. if (duration > LONG_LISTEN_TIME) {
  8258. wl_cfg80211_scan_abort(cfg);
  8259. } else {
  8260. wl_set_drv_status(cfg, FAKE_REMAINING_ON_CHANNEL, ndev);
  8261. if (timer_pending(&cfg->p2p->listen_timer)) {
  8262. WL_DBG(("cancel current listen timer \n"));
  8263. del_timer_sync(&cfg->p2p->listen_timer);
  8264. }
  8265. _timer = &cfg->p2p->listen_timer;
  8266. wl_clr_p2p_status(cfg, LISTEN_EXPIRED);
  8267. INIT_TIMER(_timer, wl_cfgp2p_listen_expired, duration, 0);
  8268. err = BCME_OK;
  8269. goto exit;
  8270. }
  8271. }
  8272. #endif /* WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST */
  8273. #ifdef WL_BCNRECV
  8274. /* check fakeapscan in progress then abort */
  8275. wl_android_bcnrecv_stop(ndev, WL_BCNRECV_LISTENBUSY);
  8276. #endif /* WL_BCNRECV */
  8277. #ifdef WL_CFG80211_SYNC_GON
  8278. if (wl_get_drv_status_all(cfg, WAITING_NEXT_ACT_FRM_LISTEN)) {
  8279. /* do not enter listen mode again if we are in listen mode already for next af.
  8280. * remain on channel completion will be returned by waiting next af completion.
  8281. */
  8282. #ifdef WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST
  8283. wl_set_drv_status(cfg, FAKE_REMAINING_ON_CHANNEL, ndev);
  8284. #else
  8285. wl_set_drv_status(cfg, REMAINING_ON_CHANNEL, ndev);
  8286. #endif /* WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST */
  8287. goto exit;
  8288. }
  8289. #endif /* WL_CFG80211_SYNC_GON */
  8290. if (cfg->p2p && !cfg->p2p->on) {
  8291. /* In case of p2p_listen command, supplicant send remain_on_channel
  8292. * without turning on P2P
  8293. */
  8294. get_primary_mac(cfg, &primary_mac);
  8295. wl_cfgp2p_generate_bss_mac(cfg, &primary_mac);
  8296. p2p_on(cfg) = true;
  8297. }
  8298. if (p2p_is_on(cfg)) {
  8299. err = wl_cfgp2p_enable_discovery(cfg, ndev, NULL, 0);
  8300. if (unlikely(err)) {
  8301. goto exit;
  8302. }
  8303. #ifndef WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST
  8304. wl_set_drv_status(cfg, REMAINING_ON_CHANNEL, ndev);
  8305. #endif /* not WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST */
  8306. err = wl_cfgp2p_discover_listen(cfg, target_channel, duration);
  8307. #ifdef WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST
  8308. if (err == BCME_OK) {
  8309. wl_set_drv_status(cfg, REMAINING_ON_CHANNEL, ndev);
  8310. } else {
  8311. /* if failed, firmware may be internal scanning state.
  8312. * so other scan request shall not abort it
  8313. */
  8314. wl_set_drv_status(cfg, FAKE_REMAINING_ON_CHANNEL, ndev);
  8315. }
  8316. #endif /* WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST */
  8317. if (err) {
  8318. wl_flush_fw_log_buffer(ndev, FW_LOGSET_MASK_ALL);
  8319. }
  8320. /* WAR: set err = ok to prevent cookie mismatch in wpa_supplicant
  8321. * and expire timer will send a completion to the upper layer
  8322. */
  8323. err = BCME_OK;
  8324. }
  8325. exit:
  8326. if (err == BCME_OK) {
  8327. WL_DBG(("Success\n"));
  8328. #if defined(WL_CFG80211_P2P_DEV_IF)
  8329. cfg80211_ready_on_channel(cfgdev, *cookie, channel,
  8330. duration, GFP_KERNEL);
  8331. #else
  8332. cfg80211_ready_on_channel(cfgdev, *cookie, channel,
  8333. channel_type, duration, GFP_KERNEL);
  8334. #endif /* WL_CFG80211_P2P_DEV_IF */
  8335. } else {
  8336. WL_ERR(("Fail to Set (err=%d cookie:%llu)\n", err, *cookie));
  8337. }
  8338. mutex_unlock(&cfg->usr_sync);
  8339. return err;
  8340. }
  8341. static s32
  8342. wl_cfg80211_cancel_remain_on_channel(struct wiphy *wiphy,
  8343. bcm_struct_cfgdev *cfgdev, u64 cookie)
  8344. {
  8345. s32 err = 0;
  8346. struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
  8347. #ifdef P2PLISTEN_AP_SAMECHN
  8348. struct net_device *dev;
  8349. #endif /* P2PLISTEN_AP_SAMECHN */
  8350. RETURN_EIO_IF_NOT_UP(cfg);
  8351. #ifdef DHD_IFDEBUG
  8352. PRINT_WDEV_INFO(cfgdev);
  8353. #endif /* DHD_IFDEBUG */
  8354. #if defined(WL_CFG80211_P2P_DEV_IF)
  8355. if (cfgdev->iftype == NL80211_IFTYPE_P2P_DEVICE) {
  8356. WL_DBG((" enter ) on P2P dedicated discover interface\n"));
  8357. }
  8358. #else
  8359. WL_DBG((" enter ) netdev_ifidx: %d \n", cfgdev->ifindex));
  8360. #endif /* WL_CFG80211_P2P_DEV_IF */
  8361. #ifdef P2PLISTEN_AP_SAMECHN
  8362. if (cfg && cfg->p2p_resp_apchn_status) {
  8363. dev = bcmcfg_to_prmry_ndev(cfg);
  8364. wl_cfg80211_set_p2p_resp_ap_chn(dev, 0);
  8365. cfg->p2p_resp_apchn_status = false;
  8366. WL_DBG(("p2p_resp_apchn_status Turn OFF \n"));
  8367. }
  8368. #endif /* P2PLISTEN_AP_SAMECHN */
  8369. if (cfg->last_roc_id == cookie) {
  8370. wl_cfgp2p_set_p2p_mode(cfg, WL_P2P_DISC_ST_SCAN, 0, 0,
  8371. wl_to_p2p_bss_bssidx(cfg, P2PAPI_BSSCFG_DEVICE));
  8372. } else {
  8373. WL_ERR(("wl_cfg80211_cancel_remain_on_channel: ignore, request cookie(%llu)"
  8374. " is not matched. (cur : %llu)\n",
  8375. cookie, cfg->last_roc_id));
  8376. }
  8377. return err;
  8378. }
  8379. static void
  8380. wl_cfg80211_afx_handler(struct work_struct *work)
  8381. {
  8382. struct afx_hdl *afx_instance;
  8383. struct bcm_cfg80211 *cfg;
  8384. s32 ret = BCME_OK;
  8385. BCM_SET_CONTAINER_OF(afx_instance, work, struct afx_hdl, work);
  8386. if (afx_instance) {
  8387. cfg = wl_get_cfg(afx_instance->dev);
  8388. if (cfg != NULL && cfg->afx_hdl->is_active) {
  8389. if (cfg->afx_hdl->is_listen && cfg->afx_hdl->my_listen_chan) {
  8390. ret = wl_cfgp2p_discover_listen(cfg, cfg->afx_hdl->my_listen_chan,
  8391. (100 * (1 + (RANDOM32() % 3)))); /* 100ms ~ 300ms */
  8392. } else {
  8393. ret = wl_cfgp2p_act_frm_search(cfg, cfg->afx_hdl->dev,
  8394. cfg->afx_hdl->bssidx, cfg->afx_hdl->peer_listen_chan,
  8395. NULL);
  8396. }
  8397. if (unlikely(ret != BCME_OK)) {
  8398. WL_ERR(("ERROR occurred! returned value is (%d)\n", ret));
  8399. if (wl_get_drv_status_all(cfg, FINDING_COMMON_CHANNEL))
  8400. complete(&cfg->act_frm_scan);
  8401. }
  8402. }
  8403. }
  8404. }
  8405. static s32
  8406. wl_cfg80211_af_searching_channel(struct bcm_cfg80211 *cfg, struct net_device *dev)
  8407. {
  8408. u32 max_retry = WL_CHANNEL_SYNC_RETRY;
  8409. bool is_p2p_gas = false;
  8410. if (dev == NULL)
  8411. return -1;
  8412. WL_DBG((" enter ) \n"));
  8413. wl_set_drv_status(cfg, FINDING_COMMON_CHANNEL, dev);
  8414. cfg->afx_hdl->is_active = TRUE;
  8415. if (cfg->afx_hdl->pending_tx_act_frm) {
  8416. wl_action_frame_t *action_frame;
  8417. action_frame = &(cfg->afx_hdl->pending_tx_act_frm->action_frame);
  8418. if (wl_cfgp2p_is_p2p_gas_action(action_frame->data, action_frame->len))
  8419. is_p2p_gas = true;
  8420. }
  8421. /* Loop to wait until we find a peer's channel or the
  8422. * pending action frame tx is cancelled.
  8423. */
  8424. while ((cfg->afx_hdl->retry < max_retry) &&
  8425. (cfg->afx_hdl->peer_chan == WL_INVALID)) {
  8426. cfg->afx_hdl->is_listen = FALSE;
  8427. wl_set_drv_status(cfg, SCANNING, dev);
  8428. WL_DBG(("Scheduling the action frame for sending.. retry %d\n",
  8429. cfg->afx_hdl->retry));
  8430. /* search peer on peer's listen channel */
  8431. schedule_work(&cfg->afx_hdl->work);
  8432. wait_for_completion_timeout(&cfg->act_frm_scan,
  8433. msecs_to_jiffies(WL_AF_SEARCH_TIME_MAX));
  8434. if ((cfg->afx_hdl->peer_chan != WL_INVALID) ||
  8435. !(wl_get_drv_status(cfg, FINDING_COMMON_CHANNEL, dev)))
  8436. break;
  8437. if (is_p2p_gas)
  8438. break;
  8439. if (cfg->afx_hdl->my_listen_chan) {
  8440. WL_DBG(("Scheduling Listen peer in my listen channel = %d\n",
  8441. cfg->afx_hdl->my_listen_chan));
  8442. /* listen on my listen channel */
  8443. cfg->afx_hdl->is_listen = TRUE;
  8444. schedule_work(&cfg->afx_hdl->work);
  8445. wait_for_completion_timeout(&cfg->act_frm_scan,
  8446. msecs_to_jiffies(WL_AF_SEARCH_TIME_MAX));
  8447. }
  8448. if ((cfg->afx_hdl->peer_chan != WL_INVALID) ||
  8449. !(wl_get_drv_status(cfg, FINDING_COMMON_CHANNEL, dev)))
  8450. break;
  8451. cfg->afx_hdl->retry++;
  8452. WL_AF_TX_KEEP_PRI_CONNECTION_VSDB(cfg);
  8453. }
  8454. cfg->afx_hdl->is_active = FALSE;
  8455. wl_clr_drv_status(cfg, SCANNING, dev);
  8456. wl_clr_drv_status(cfg, FINDING_COMMON_CHANNEL, dev);
  8457. return (cfg->afx_hdl->peer_chan);
  8458. }
  8459. struct p2p_config_af_params {
  8460. s32 max_tx_retry; /* max tx retry count if tx no ack */
  8461. #ifdef WL_CFG80211_GON_COLLISION
  8462. /* drop tx go nego request if go nego collision occurs */
  8463. bool drop_tx_req;
  8464. #endif // endif
  8465. #ifdef WL_CFG80211_SYNC_GON
  8466. bool extra_listen;
  8467. #endif // endif
  8468. bool search_channel; /* 1: search peer's channel to send af */
  8469. };
  8470. #ifdef WL_DISABLE_HE_P2P
  8471. static s32
  8472. wl_cfg80211_he_p2p_disable(struct wiphy *wiphy, struct ether_addr peer_mac)
  8473. {
  8474. struct cfg80211_bss *bss;
  8475. u8 *ie = NULL;
  8476. u32 ie_len = 0;
  8477. struct net_device *ndev = NULL;
  8478. s32 bssidx = 0;
  8479. s32 err = BCME_OK;
  8480. struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
  8481. bss = CFG80211_GET_BSS(wiphy, NULL, peer_mac.octet, NULL, 0);
  8482. if (!bss) {
  8483. WL_ERR(("Could not find the Peer device\n"));
  8484. return BCME_ERROR;
  8485. } else {
  8486. GCC_DIAGNOSTIC_PUSH_SUPPRESS_CAST();
  8487. #if defined(WL_CFG80211_P2P_DEV_IF)
  8488. ie = (u8 *)bss->ies->data;
  8489. ie_len = bss->ies->len;
  8490. #else
  8491. ie = bss->information_elements;
  8492. ie_len = bss->len_information_elements;
  8493. #endif /* WL_CFG80211_P2P_DEV_IF */
  8494. GCC_DIAGNOSTIC_POP();
  8495. }
  8496. if (ie) {
  8497. if ((bcm_parse_tlvs_dot11(ie, ie_len,
  8498. EXT_MNG_HE_CAP_ID, TRUE)) == NULL) {
  8499. WL_DBG(("Peer does not support HE capability\n"));
  8500. ndev = wl_to_p2p_bss_ndev(cfg, P2PAPI_BSSCFG_CONNECTION1);
  8501. if (ndev && (bssidx =
  8502. wl_get_bssidx_by_wdev(cfg, ndev->ieee80211_ptr)) < 0) {
  8503. WL_ERR(("Find index failed\n"));
  8504. err = BCME_ERROR;
  8505. } else {
  8506. WL_DBG(("Disabling HE for P2P\n"));
  8507. err = wl_cfg80211_set_he_mode(ndev, cfg, bssidx,
  8508. WL_IF_TYPE_P2P_DISC, FALSE);
  8509. if (err < 0) {
  8510. WL_ERR(("failed to set he features, error=%d\n", err));
  8511. }
  8512. }
  8513. } else {
  8514. WL_DBG(("Peer supports HE capability\n"));
  8515. }
  8516. }
  8517. CFG80211_PUT_BSS(wiphy, bss);
  8518. return err;
  8519. }
  8520. #endif /* WL_DISABLE_HE_P2P */
  8521. static s32
  8522. wl_cfg80211_config_p2p_pub_af_tx(struct wiphy *wiphy,
  8523. wl_action_frame_t *action_frame, wl_af_params_t *af_params,
  8524. struct p2p_config_af_params *config_af_params)
  8525. {
  8526. s32 err = BCME_OK;
  8527. struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
  8528. wifi_p2p_pub_act_frame_t *act_frm =
  8529. (wifi_p2p_pub_act_frame_t *) (action_frame->data);
  8530. /* initialize default value */
  8531. #ifdef WL_CFG80211_GON_COLLISION
  8532. config_af_params->drop_tx_req = false;
  8533. #endif // endif
  8534. #ifdef WL_CFG80211_SYNC_GON
  8535. config_af_params->extra_listen = true;
  8536. #endif // endif
  8537. config_af_params->search_channel = false;
  8538. config_af_params->max_tx_retry = WL_AF_TX_MAX_RETRY;
  8539. cfg->next_af_subtype = P2P_PAF_SUBTYPE_INVALID;
  8540. switch (act_frm->subtype) {
  8541. case P2P_PAF_GON_REQ: {
  8542. /* Disable he if peer does not support before starting GONEG */
  8543. #ifdef WL_DISABLE_HE_P2P
  8544. wl_cfg80211_he_p2p_disable(wiphy, action_frame->da);
  8545. #endif /* WL_DISABLE_HE_P2P */
  8546. WL_DBG(("P2P: GO_NEG_PHASE status set \n"));
  8547. wl_set_p2p_status(cfg, GO_NEG_PHASE);
  8548. config_af_params->search_channel = true;
  8549. cfg->next_af_subtype = act_frm->subtype + 1;
  8550. /* increase dwell time to wait for RESP frame */
  8551. af_params->dwell_time = WL_MED_DWELL_TIME;
  8552. #ifdef WL_CFG80211_GON_COLLISION
  8553. config_af_params->drop_tx_req = true;
  8554. #endif /* WL_CFG80211_GON_COLLISION */
  8555. break;
  8556. }
  8557. case P2P_PAF_GON_RSP: {
  8558. cfg->next_af_subtype = act_frm->subtype + 1;
  8559. /* increase dwell time to wait for CONF frame */
  8560. af_params->dwell_time = WL_MED_DWELL_TIME + 100;
  8561. break;
  8562. }
  8563. case P2P_PAF_GON_CONF: {
  8564. /* If we reached till GO Neg confirmation reset the filter */
  8565. WL_DBG(("P2P: GO_NEG_PHASE status cleared \n"));
  8566. wl_clr_p2p_status(cfg, GO_NEG_PHASE);
  8567. /* minimize dwell time */
  8568. af_params->dwell_time = WL_MIN_DWELL_TIME;
  8569. #ifdef WL_CFG80211_GON_COLLISION
  8570. /* if go nego formation done, clear it */
  8571. cfg->block_gon_req_tx_count = 0;
  8572. cfg->block_gon_req_rx_count = 0;
  8573. #endif /* WL_CFG80211_GON_COLLISION */
  8574. #ifdef WL_CFG80211_SYNC_GON
  8575. config_af_params->extra_listen = false;
  8576. #endif /* WL_CFG80211_SYNC_GON */
  8577. break;
  8578. }
  8579. case P2P_PAF_INVITE_REQ: {
  8580. config_af_params->search_channel = true;
  8581. cfg->next_af_subtype = act_frm->subtype + 1;
  8582. /* increase dwell time */
  8583. af_params->dwell_time = WL_MED_DWELL_TIME;
  8584. break;
  8585. }
  8586. case P2P_PAF_INVITE_RSP:
  8587. /* minimize dwell time */
  8588. af_params->dwell_time = WL_MIN_DWELL_TIME;
  8589. #ifdef WL_CFG80211_SYNC_GON
  8590. config_af_params->extra_listen = false;
  8591. #endif /* WL_CFG80211_SYNC_GON */
  8592. break;
  8593. case P2P_PAF_DEVDIS_REQ: {
  8594. if (IS_ACTPUB_WITHOUT_GROUP_ID(&act_frm->elts[0],
  8595. action_frame->len)) {
  8596. config_af_params->search_channel = true;
  8597. }
  8598. cfg->next_af_subtype = act_frm->subtype + 1;
  8599. /* maximize dwell time to wait for RESP frame */
  8600. af_params->dwell_time = WL_LONG_DWELL_TIME;
  8601. break;
  8602. }
  8603. case P2P_PAF_DEVDIS_RSP:
  8604. /* minimize dwell time */
  8605. af_params->dwell_time = WL_MIN_DWELL_TIME;
  8606. #ifdef WL_CFG80211_SYNC_GON
  8607. config_af_params->extra_listen = false;
  8608. #endif /* WL_CFG80211_SYNC_GON */
  8609. break;
  8610. case P2P_PAF_PROVDIS_REQ: {
  8611. if (IS_ACTPUB_WITHOUT_GROUP_ID(&act_frm->elts[0],
  8612. action_frame->len)) {
  8613. config_af_params->search_channel = true;
  8614. }
  8615. cfg->next_af_subtype = act_frm->subtype + 1;
  8616. /* increase dwell time to wait for RESP frame */
  8617. af_params->dwell_time = WL_MED_DWELL_TIME;
  8618. break;
  8619. }
  8620. case P2P_PAF_PROVDIS_RSP: {
  8621. cfg->next_af_subtype = P2P_PAF_GON_REQ;
  8622. af_params->dwell_time = WL_MED_DWELL_TIME;
  8623. #ifdef WL_CFG80211_SYNC_GON
  8624. config_af_params->extra_listen = false;
  8625. #endif /* WL_CFG80211_SYNC_GON */
  8626. break;
  8627. }
  8628. default:
  8629. WL_DBG(("Unknown p2p pub act frame subtype: %d\n",
  8630. act_frm->subtype));
  8631. err = BCME_BADARG;
  8632. }
  8633. return err;
  8634. }
  8635. #ifdef WL11U
  8636. static bool
  8637. wl_cfg80211_check_DFS_channel(struct bcm_cfg80211 *cfg, wl_af_params_t *af_params,
  8638. void *frame, u16 frame_len)
  8639. {
  8640. struct wl_scan_results *bss_list;
  8641. wl_bss_info_t *bi = NULL;
  8642. bool result = false;
  8643. s32 i;
  8644. chanspec_t chanspec;
  8645. /* If DFS channel is 52~148, check to block it or not */
  8646. if (af_params &&
  8647. (af_params->channel >= 52 && af_params->channel <= 148)) {
  8648. if (!wl_cfgp2p_is_p2p_action(frame, frame_len)) {
  8649. bss_list = cfg->bss_list;
  8650. bi = next_bss(bss_list, bi);
  8651. for_each_bss(bss_list, bi, i) {
  8652. chanspec = wl_chspec_driver_to_host(bi->chanspec);
  8653. if (CHSPEC_IS5G(chanspec) &&
  8654. ((bi->ctl_ch ? bi->ctl_ch : CHSPEC_CHANNEL(chanspec))
  8655. == af_params->channel)) {
  8656. result = true; /* do not block the action frame */
  8657. break;
  8658. }
  8659. }
  8660. }
  8661. }
  8662. else {
  8663. result = true;
  8664. }
  8665. WL_DBG(("result=%s", result?"true":"false"));
  8666. return result;
  8667. }
  8668. #endif /* WL11U */
  8669. static bool
  8670. wl_cfg80211_check_dwell_overflow(int32 requested_dwell, ulong dwell_jiffies)
  8671. {
  8672. if ((requested_dwell & CUSTOM_RETRY_MASK) &&
  8673. (jiffies_to_msecs(jiffies - dwell_jiffies) >
  8674. (requested_dwell & ~CUSTOM_RETRY_MASK))) {
  8675. WL_ERR(("Action frame TX retry time over dwell time!\n"));
  8676. return true;
  8677. }
  8678. return false;
  8679. }
  8680. static bool
  8681. wl_cfg80211_send_action_frame(struct wiphy *wiphy, struct net_device *dev,
  8682. bcm_struct_cfgdev *cfgdev, wl_af_params_t *af_params,
  8683. wl_action_frame_t *action_frame, u16 action_frame_len, s32 bssidx)
  8684. {
  8685. #ifdef WL11U
  8686. struct net_device *ndev = NULL;
  8687. #endif /* WL11U */
  8688. struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
  8689. bool ack = false;
  8690. u8 category, action;
  8691. s32 tx_retry;
  8692. struct p2p_config_af_params config_af_params;
  8693. struct net_info *netinfo;
  8694. #ifdef VSDB
  8695. ulong off_chan_started_jiffies = 0;
  8696. #endif // endif
  8697. ulong dwell_jiffies = 0;
  8698. bool dwell_overflow = false;
  8699. dhd_pub_t *dhd = (dhd_pub_t *)(cfg->pub);
  8700. int32 requested_dwell = af_params->dwell_time;
  8701. /* Add the default dwell time
  8702. * Dwell time to stay off-channel to wait for a response action frame
  8703. * after transmitting an GO Negotiation action frame
  8704. */
  8705. af_params->dwell_time = WL_DWELL_TIME;
  8706. #ifdef WL11U
  8707. #if defined(WL_CFG80211_P2P_DEV_IF)
  8708. ndev = dev;
  8709. #else
  8710. ndev = ndev_to_cfgdev(cfgdev);
  8711. #endif /* WL_CFG80211_P2P_DEV_IF */
  8712. #endif /* WL11U */
  8713. category = action_frame->data[DOT11_ACTION_CAT_OFF];
  8714. action = action_frame->data[DOT11_ACTION_ACT_OFF];
  8715. /* initialize variables */
  8716. tx_retry = 0;
  8717. cfg->next_af_subtype = P2P_PAF_SUBTYPE_INVALID;
  8718. config_af_params.max_tx_retry = WL_AF_TX_MAX_RETRY;
  8719. config_af_params.search_channel = false;
  8720. #ifdef WL_CFG80211_GON_COLLISION
  8721. config_af_params.drop_tx_req = false;
  8722. #endif // endif
  8723. #ifdef WL_CFG80211_SYNC_GON
  8724. config_af_params.extra_listen = false;
  8725. #endif // endif
  8726. /* config parameters */
  8727. /* Public Action Frame Process - DOT11_ACTION_CAT_PUBLIC */
  8728. if (category == DOT11_ACTION_CAT_PUBLIC) {
  8729. if ((action == P2P_PUB_AF_ACTION) &&
  8730. (action_frame_len >= sizeof(wifi_p2p_pub_act_frame_t))) {
  8731. /* p2p public action frame process */
  8732. if (BCME_OK != wl_cfg80211_config_p2p_pub_af_tx(wiphy,
  8733. action_frame, af_params, &config_af_params)) {
  8734. WL_DBG(("Unknown subtype.\n"));
  8735. }
  8736. #ifdef WL_CFG80211_GON_COLLISION
  8737. if (config_af_params.drop_tx_req) {
  8738. if (cfg->block_gon_req_tx_count) {
  8739. /* drop gon req tx action frame */
  8740. WL_DBG(("Drop gon req tx action frame: count %d\n",
  8741. cfg->block_gon_req_tx_count));
  8742. goto exit;
  8743. }
  8744. }
  8745. #endif /* WL_CFG80211_GON_COLLISION */
  8746. } else if (action_frame_len >= sizeof(wifi_p2psd_gas_pub_act_frame_t)) {
  8747. /* service discovery process */
  8748. if (action == P2PSD_ACTION_ID_GAS_IREQ ||
  8749. action == P2PSD_ACTION_ID_GAS_CREQ) {
  8750. /* configure service discovery query frame */
  8751. config_af_params.search_channel = true;
  8752. /* save next af suptype to cancel remained dwell time */
  8753. cfg->next_af_subtype = action + 1;
  8754. af_params->dwell_time = WL_MED_DWELL_TIME;
  8755. if (requested_dwell & CUSTOM_RETRY_MASK) {
  8756. config_af_params.max_tx_retry =
  8757. (requested_dwell & CUSTOM_RETRY_MASK) >> 24;
  8758. af_params->dwell_time =
  8759. (requested_dwell & ~CUSTOM_RETRY_MASK);
  8760. WL_DBG(("Custom retry(%d) and dwell time(%d) is set.\n",
  8761. config_af_params.max_tx_retry,
  8762. af_params->dwell_time));
  8763. }
  8764. } else if (action == P2PSD_ACTION_ID_GAS_IRESP ||
  8765. action == P2PSD_ACTION_ID_GAS_CRESP) {
  8766. /* configure service discovery response frame */
  8767. af_params->dwell_time = WL_MIN_DWELL_TIME;
  8768. } else {
  8769. WL_DBG(("Unknown action type: %d\n", action));
  8770. }
  8771. } else {
  8772. WL_DBG(("Unknown Frame: category 0x%x, action 0x%x, length %d\n",
  8773. category, action, action_frame_len));
  8774. }
  8775. } else if (category == P2P_AF_CATEGORY) {
  8776. /* do not configure anything. it will be sent with a default configuration */
  8777. } else {
  8778. WL_DBG(("Unknown Frame: category 0x%x, action 0x%x\n",
  8779. category, action));
  8780. if (dhd->op_mode & DHD_FLAG_HOSTAP_MODE) {
  8781. wl_clr_drv_status(cfg, SENDING_ACT_FRM, dev);
  8782. return false;
  8783. }
  8784. }
  8785. netinfo = wl_get_netinfo_by_wdev(cfg, cfgdev_to_wdev(cfgdev));
  8786. /* validate channel and p2p ies */
  8787. if (config_af_params.search_channel && IS_P2P_SOCIAL(af_params->channel) &&
  8788. netinfo && netinfo->bss.ies.probe_req_ie_len) {
  8789. config_af_params.search_channel = true;
  8790. } else {
  8791. config_af_params.search_channel = false;
  8792. }
  8793. #ifdef WL11U
  8794. if (ndev == bcmcfg_to_prmry_ndev(cfg))
  8795. config_af_params.search_channel = false;
  8796. #endif /* WL11U */
  8797. #ifdef VSDB
  8798. /* if connecting on primary iface, sleep for a while before sending af tx for VSDB */
  8799. if (wl_get_drv_status(cfg, CONNECTING, bcmcfg_to_prmry_ndev(cfg))) {
  8800. OSL_SLEEP(50);
  8801. }
  8802. #endif // endif
  8803. /* if scan is ongoing, abort current scan. */
  8804. if (wl_get_drv_status_all(cfg, SCANNING)) {
  8805. wl_cfg80211_cancel_scan(cfg);
  8806. }
  8807. /* Abort P2P listen */
  8808. if (discover_cfgdev(cfgdev, cfg)) {
  8809. if (cfg->p2p_supported && cfg->p2p) {
  8810. wl_cfgp2p_set_p2p_mode(cfg, WL_P2P_DISC_ST_SCAN, 0, 0,
  8811. wl_to_p2p_bss_bssidx(cfg, P2PAPI_BSSCFG_DEVICE));
  8812. }
  8813. }
  8814. #ifdef WL11U
  8815. /* handling DFS channel exceptions */
  8816. if (!wl_cfg80211_check_DFS_channel(cfg, af_params, action_frame->data, action_frame->len)) {
  8817. return false; /* the action frame was blocked */
  8818. }
  8819. #endif /* WL11U */
  8820. /* set status and destination address before sending af */
  8821. if (cfg->next_af_subtype != P2P_PAF_SUBTYPE_INVALID) {
  8822. /* set this status to cancel the remained dwell time in rx process */
  8823. wl_set_drv_status(cfg, WAITING_NEXT_ACT_FRM, dev);
  8824. }
  8825. wl_set_drv_status(cfg, SENDING_ACT_FRM, dev);
  8826. memcpy(cfg->afx_hdl->tx_dst_addr.octet,
  8827. af_params->action_frame.da.octet,
  8828. sizeof(cfg->afx_hdl->tx_dst_addr.octet));
  8829. /* save af_params for rx process */
  8830. cfg->afx_hdl->pending_tx_act_frm = af_params;
  8831. if (wl_cfgp2p_is_p2p_gas_action(action_frame->data, action_frame->len)) {
  8832. WL_DBG(("Set GAS action frame config.\n"));
  8833. config_af_params.search_channel = false;
  8834. config_af_params.max_tx_retry = 1;
  8835. }
  8836. /* search peer's channel */
  8837. if (config_af_params.search_channel) {
  8838. /* initialize afx_hdl */
  8839. if ((cfg->afx_hdl->bssidx = wl_get_bssidx_by_wdev(cfg, dev->ieee80211_ptr)) < 0) {
  8840. WL_ERR(("Find p2p index from wdev(%p) failed\n", dev->ieee80211_ptr));
  8841. goto exit;
  8842. }
  8843. cfg->afx_hdl->dev = dev;
  8844. cfg->afx_hdl->retry = 0;
  8845. cfg->afx_hdl->peer_chan = WL_INVALID;
  8846. if (wl_cfg80211_af_searching_channel(cfg, dev) == WL_INVALID) {
  8847. WL_ERR(("couldn't find peer's channel.\n"));
  8848. wl_cfgp2p_print_actframe(true, action_frame->data, action_frame->len,
  8849. af_params->channel);
  8850. /* Even if we couldn't find peer channel, try to send the frame
  8851. * out. P2P cert 5.1.14 testbed device (realtek) doesn't seem to
  8852. * respond to probe request (Ideally it has to be in listen and
  8853. * responsd to probe request). However if we send Go neg req, the
  8854. * peer is sending GO-neg resp. So instead of giving up here, just
  8855. * proceed and attempt sending out the action frame.
  8856. */
  8857. }
  8858. wl_clr_drv_status(cfg, SCANNING, cfg->afx_hdl->dev);
  8859. /*
  8860. * Abort scan even for VSDB scenarios. Scan gets aborted in firmware
  8861. * but after the check of piggyback algorithm.
  8862. * To take care of current piggback algo, lets abort the scan here itself.
  8863. */
  8864. wl_cfg80211_cancel_scan(cfg);
  8865. /* Suspend P2P discovery's search-listen to prevent it from
  8866. * starting a scan or changing the channel.
  8867. */
  8868. if ((wl_cfgp2p_discover_enable_search(cfg, false)) < 0) {
  8869. WL_ERR(("Can not disable discovery mode\n"));
  8870. goto exit;
  8871. }
  8872. /* update channel */
  8873. if (cfg->afx_hdl->peer_chan != WL_INVALID) {
  8874. af_params->channel = cfg->afx_hdl->peer_chan;
  8875. WL_ERR(("Attempt tx on peer listen channel:%d ",
  8876. cfg->afx_hdl->peer_chan));
  8877. } else {
  8878. WL_ERR(("Attempt tx with the channel provided by userspace."
  8879. "Channel: %d\n", af_params->channel));
  8880. }
  8881. }
  8882. #ifdef VSDB
  8883. off_chan_started_jiffies = jiffies;
  8884. #endif /* VSDB */
  8885. wl_cfgp2p_print_actframe(true, action_frame->data, action_frame->len, af_params->channel);
  8886. wl_cfgp2p_need_wait_actfrmae(cfg, action_frame->data, action_frame->len, true);
  8887. dwell_jiffies = jiffies;
  8888. /* Now send a tx action frame */
  8889. ack = wl_cfgp2p_tx_action_frame(cfg, dev, af_params, bssidx) ? false : true;
  8890. dwell_overflow = wl_cfg80211_check_dwell_overflow(requested_dwell, dwell_jiffies);
  8891. /* if failed, retry it. tx_retry_max value is configure by .... */
  8892. while ((ack == false) && (tx_retry++ < config_af_params.max_tx_retry) &&
  8893. !dwell_overflow) {
  8894. #ifdef VSDB
  8895. if (af_params->channel) {
  8896. if (jiffies_to_msecs(jiffies - off_chan_started_jiffies) >
  8897. OFF_CHAN_TIME_THRESHOLD_MS) {
  8898. WL_AF_TX_KEEP_PRI_CONNECTION_VSDB(cfg);
  8899. off_chan_started_jiffies = jiffies;
  8900. } else
  8901. OSL_SLEEP(AF_RETRY_DELAY_TIME);
  8902. }
  8903. #endif /* VSDB */
  8904. ack = wl_cfgp2p_tx_action_frame(cfg, dev, af_params, bssidx) ?
  8905. false : true;
  8906. dwell_overflow = wl_cfg80211_check_dwell_overflow(requested_dwell, dwell_jiffies);
  8907. }
  8908. if (ack == false) {
  8909. WL_ERR(("Failed to send Action Frame(retry %d)\n", tx_retry));
  8910. }
  8911. WL_DBG(("Complete to send action frame\n"));
  8912. exit:
  8913. /* Clear SENDING_ACT_FRM after all sending af is done */
  8914. wl_clr_drv_status(cfg, SENDING_ACT_FRM, dev);
  8915. #ifdef WL_CFG80211_SYNC_GON
  8916. /* WAR: sometimes dongle does not keep the dwell time of 'actframe'.
  8917. * if we coundn't get the next action response frame and dongle does not keep
  8918. * the dwell time, go to listen state again to get next action response frame.
  8919. */
  8920. if (ack && config_af_params.extra_listen &&
  8921. #ifdef WL_CFG80211_GON_COLLISION
  8922. !cfg->block_gon_req_tx_count &&
  8923. #endif /* WL_CFG80211_GON_COLLISION */
  8924. wl_get_drv_status_all(cfg, WAITING_NEXT_ACT_FRM) &&
  8925. cfg->af_sent_channel == cfg->afx_hdl->my_listen_chan) {
  8926. s32 extar_listen_time;
  8927. extar_listen_time = af_params->dwell_time -
  8928. jiffies_to_msecs(jiffies - cfg->af_tx_sent_jiffies);
  8929. if (extar_listen_time > 50) {
  8930. wl_set_drv_status(cfg, WAITING_NEXT_ACT_FRM_LISTEN, dev);
  8931. WL_DBG(("Wait more time! actual af time:%d,"
  8932. "calculated extar listen:%d\n",
  8933. af_params->dwell_time, extar_listen_time));
  8934. if (wl_cfgp2p_discover_listen(cfg, cfg->af_sent_channel,
  8935. extar_listen_time + 100) == BCME_OK) {
  8936. wait_for_completion_timeout(&cfg->wait_next_af,
  8937. msecs_to_jiffies(extar_listen_time + 100 + 300));
  8938. }
  8939. wl_clr_drv_status(cfg, WAITING_NEXT_ACT_FRM_LISTEN, dev);
  8940. }
  8941. }
  8942. #endif /* WL_CFG80211_SYNC_GON */
  8943. wl_clr_drv_status(cfg, WAITING_NEXT_ACT_FRM, dev);
  8944. cfg->afx_hdl->pending_tx_act_frm = NULL;
  8945. if (ack) {
  8946. WL_DBG(("-- Action Frame Tx succeeded, listen chan: %d\n",
  8947. cfg->afx_hdl->my_listen_chan));
  8948. } else {
  8949. WL_ERR(("-- Action Frame Tx failed, listen chan: %d\n",
  8950. cfg->afx_hdl->my_listen_chan));
  8951. }
  8952. #ifdef WL_CFG80211_GON_COLLISION
  8953. if (cfg->block_gon_req_tx_count) {
  8954. cfg->block_gon_req_tx_count--;
  8955. /* if ack is ture, supplicant will wait more time(100ms).
  8956. * so we will return it as a success to get more time .
  8957. */
  8958. ack = true;
  8959. }
  8960. #endif /* WL_CFG80211_GON_COLLISION */
  8961. return ack;
  8962. }
  8963. #define MAX_NUM_OF_ASSOCIATED_DEV 64
  8964. #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0))
  8965. static s32
  8966. wl_cfg80211_mgmt_tx(struct wiphy *wiphy, bcm_struct_cfgdev *cfgdev,
  8967. struct cfg80211_mgmt_tx_params *params, u64 *cookie)
  8968. #else
  8969. static s32
  8970. wl_cfg80211_mgmt_tx(struct wiphy *wiphy, bcm_struct_cfgdev *cfgdev,
  8971. struct ieee80211_channel *channel, bool offchan,
  8972. #if (LINUX_VERSION_CODE <= KERNEL_VERSION(3, 7, 0))
  8973. enum nl80211_channel_type channel_type,
  8974. bool channel_type_valid,
  8975. #endif /* LINUX_VERSION_CODE <= KERNEL_VERSION(3, 7, 0) */
  8976. unsigned int wait, const u8* buf, size_t len,
  8977. #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 2, 0)) || defined(WL_COMPAT_WIRELESS)
  8978. bool no_cck,
  8979. #endif // endif
  8980. #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 3, 0)) || defined(WL_COMPAT_WIRELESS)
  8981. bool dont_wait_for_ack,
  8982. #endif // endif
  8983. u64 *cookie)
  8984. #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0) */
  8985. {
  8986. wl_action_frame_t *action_frame;
  8987. wl_af_params_t *af_params;
  8988. scb_val_t scb_val;
  8989. #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0))
  8990. struct ieee80211_channel *channel = params->chan;
  8991. const u8 *buf = params->buf;
  8992. size_t len = params->len;
  8993. #endif // endif
  8994. const struct ieee80211_mgmt *mgmt;
  8995. struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
  8996. struct net_device *dev = NULL;
  8997. s32 err = BCME_OK;
  8998. s32 bssidx = 0;
  8999. u32 id;
  9000. bool ack = false;
  9001. s8 eabuf[ETHER_ADDR_STR_LEN];
  9002. #ifdef WL_SAE
  9003. struct net_info *netinfo = NULL;
  9004. struct wl_mf_params *mf_params;
  9005. u32 mf_params_len = 0;
  9006. s32 timeout = 0;
  9007. s32 chan_nr;
  9008. #endif // endif
  9009. WL_DBG(("Enter \n"));
  9010. if (len > ACTION_FRAME_SIZE) {
  9011. WL_ERR(("bad length:%zu\n", len));
  9012. return BCME_BADLEN;
  9013. }
  9014. #ifdef DHD_IFDEBUG
  9015. PRINT_WDEV_INFO(cfgdev);
  9016. #endif /* DHD_IFDEBUG */
  9017. dev = cfgdev_to_wlc_ndev(cfgdev, cfg);
  9018. if (!dev) {
  9019. WL_ERR(("dev is NULL\n"));
  9020. return -EINVAL;
  9021. }
  9022. /* set bsscfg idx for iovar (wlan0: P2PAPI_BSSCFG_PRIMARY, p2p: P2PAPI_BSSCFG_DEVICE) */
  9023. if (discover_cfgdev(cfgdev, cfg)) {
  9024. if (!cfg->p2p_supported || !cfg->p2p) {
  9025. WL_ERR(("P2P doesn't setup completed yet\n"));
  9026. return -EINVAL;
  9027. }
  9028. bssidx = wl_to_p2p_bss_bssidx(cfg, P2PAPI_BSSCFG_DEVICE);
  9029. }
  9030. else {
  9031. if ((bssidx = wl_get_bssidx_by_wdev(cfg, cfgdev_to_wdev(cfgdev))) < 0) {
  9032. WL_ERR(("Find p2p index failed\n"));
  9033. return BCME_ERROR;
  9034. }
  9035. }
  9036. WL_DBG(("TX target bssidx=%d\n", bssidx));
  9037. if (p2p_is_on(cfg)) {
  9038. /* Suspend P2P discovery search-listen to prevent it from changing the
  9039. * channel.
  9040. */
  9041. if ((err = wl_cfgp2p_discover_enable_search(cfg, false)) < 0) {
  9042. WL_ERR(("Can not disable discovery mode\n"));
  9043. return -EFAULT;
  9044. }
  9045. }
  9046. *cookie = 0;
  9047. id = cfg->send_action_id++;
  9048. if (id == 0)
  9049. id = cfg->send_action_id++;
  9050. *cookie = id;
  9051. mgmt = (const struct ieee80211_mgmt *)buf;
  9052. if (ieee80211_is_mgmt(mgmt->frame_control)) {
  9053. if (ieee80211_is_probe_resp(mgmt->frame_control)) {
  9054. s32 ie_offset = DOT11_MGMT_HDR_LEN + DOT11_BCN_PRB_FIXED_LEN;
  9055. s32 ie_len = len - ie_offset;
  9056. if ((dev == bcmcfg_to_prmry_ndev(cfg)) && cfg->p2p) {
  9057. bssidx = wl_to_p2p_bss_bssidx(cfg, P2PAPI_BSSCFG_DEVICE);
  9058. }
  9059. wl_cfg80211_set_mgmt_vndr_ies(cfg, ndev_to_cfgdev(dev), bssidx,
  9060. VNDR_IE_PRBRSP_FLAG, (const u8 *)(buf + ie_offset), ie_len);
  9061. cfg80211_mgmt_tx_status(cfgdev, *cookie, buf, len, true, GFP_KERNEL);
  9062. #if defined(P2P_IE_MISSING_FIX)
  9063. if (!cfg->p2p_prb_noti) {
  9064. cfg->p2p_prb_noti = true;
  9065. WL_DBG(("wl_cfg80211_mgmt_tx: TX 802_1X Probe"
  9066. " Response first time.\n"));
  9067. }
  9068. #endif // endif
  9069. goto exit;
  9070. } else if (ieee80211_is_disassoc(mgmt->frame_control) ||
  9071. ieee80211_is_deauth(mgmt->frame_control)) {
  9072. char mac_buf[MAX_NUM_OF_ASSOCIATED_DEV *
  9073. sizeof(struct ether_addr) + sizeof(uint)] = {0};
  9074. int num_associated = 0;
  9075. struct maclist *assoc_maclist = (struct maclist *)mac_buf;
  9076. if (!bcmp((const uint8 *)BSSID_BROADCAST,
  9077. (const struct ether_addr *)mgmt->da, ETHER_ADDR_LEN)) {
  9078. assoc_maclist->count = MAX_NUM_OF_ASSOCIATED_DEV;
  9079. err = wldev_ioctl_get(dev, WLC_GET_ASSOCLIST,
  9080. assoc_maclist, sizeof(mac_buf));
  9081. if (err < 0)
  9082. WL_ERR(("WLC_GET_ASSOCLIST error %d\n", err));
  9083. else
  9084. num_associated = assoc_maclist->count;
  9085. }
  9086. memcpy(scb_val.ea.octet, mgmt->da, ETH_ALEN);
  9087. scb_val.val = mgmt->u.disassoc.reason_code;
  9088. err = wldev_ioctl_set(dev, WLC_SCB_DEAUTHENTICATE_FOR_REASON, &scb_val,
  9089. sizeof(scb_val_t));
  9090. if (err < 0)
  9091. WL_ERR(("WLC_SCB_DEAUTHENTICATE_FOR_REASON error %d\n", err));
  9092. WL_ERR(("Disconnect STA : " MACDBG " scb_val.val %d\n",
  9093. MAC2STRDBG(bcm_ether_ntoa((const struct ether_addr *)mgmt->da,
  9094. eabuf)), scb_val.val));
  9095. if (num_associated > 0 && ETHER_ISBCAST(mgmt->da))
  9096. wl_delay(400);
  9097. cfg80211_mgmt_tx_status(cfgdev, *cookie, buf, len, true, GFP_KERNEL);
  9098. goto exit;
  9099. } else if (ieee80211_is_action(mgmt->frame_control)) {
  9100. /* Abort the dwell time of any previous off-channel
  9101. * action frame that may be still in effect. Sending
  9102. * off-channel action frames relies on the driver's
  9103. * scan engine. If a previous off-channel action frame
  9104. * tx is still in progress (including the dwell time),
  9105. * then this new action frame will not be sent out.
  9106. */
  9107. /* Do not abort scan for VSDB. Scan will be aborted in firmware if necessary.
  9108. * And previous off-channel action frame must be ended before new af tx.
  9109. */
  9110. #ifndef WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST
  9111. wl_cfg80211_cancel_scan(cfg);
  9112. #endif /* not WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST */
  9113. #ifdef WL_SAE
  9114. } else if (ieee80211_is_auth(mgmt->frame_control)) {
  9115. netinfo = wl_get_netinfo_by_wdev(cfg, cfgdev_to_wdev(cfgdev));
  9116. reinit_completion(&netinfo->mgmt_tx_cpl);
  9117. clear_bit(MGMT_TX_ACK, &netinfo->mgmt_txstatus);
  9118. clear_bit(MGMT_TX_NOACK, &netinfo->mgmt_txstatus);
  9119. clear_bit(MGMT_TX_OFF_CHAN_COMPLETED,
  9120. &netinfo->mgmt_txstatus);
  9121. mf_params_len = offsetof(struct wl_mf_params, data) +
  9122. (len - DOT11_MGMT_HDR_LEN);
  9123. mf_params = (wl_mf_params_t *)MALLOCZ(cfg->osh, mf_params_len);
  9124. if (!mf_params) {
  9125. WL_ERR(("Insufficient memory to allocate auth frame\n"));
  9126. err = -ENOMEM;
  9127. goto exit;
  9128. }
  9129. mf_params->dwell_time = MGMT_AUTH_FRAME_DWELL_TIME;
  9130. mf_params->len = cpu_to_le16(len - DOT11_MGMT_HDR_LEN);
  9131. mf_params->fc = mgmt->frame_control;
  9132. /* update channel */
  9133. if (!channel) {
  9134. mf_params->channel = 0;
  9135. } else {
  9136. chan_nr = ieee80211_frequency_to_channel(channel->center_freq);
  9137. mf_params->channel = cpu_to_le32(chan_nr);
  9138. }
  9139. memcpy(&mf_params->da.octet, &mgmt->da[0], ETH_ALEN);
  9140. memcpy(&mf_params->bssid.octet, &mgmt->bssid[0], ETH_ALEN);
  9141. *cookie = (u64)mf_params->data;
  9142. mf_params->packetId = cpu_to_le32(*cookie);
  9143. memcpy(mf_params->data, &buf[DOT11_MGMT_HDR_LEN],
  9144. le16_to_cpu(mf_params->len));
  9145. WL_DBG(("Auth frame, cookie=%lld, fc=%x, len=%d, channel=%d\n",
  9146. *cookie, mf_params->fc,
  9147. le16_to_cpu(mf_params->len),
  9148. mf_params->channel));
  9149. netinfo->mgmt_txid = mf_params->packetId;
  9150. set_bit(MGMT_TX_SEND_FRAME, &netinfo->mgmt_txstatus);
  9151. err = wldev_iovar_setbuf_bsscfg(dev, "mgmt_frame", mf_params, mf_params_len,
  9152. cfg->ioctl_buf, WLC_IOCTL_MAXLEN, bssidx, &cfg->ioctl_buf_sync);
  9153. if (err < 0) {
  9154. WL_ERR(("Failed to send auth frame %d\n", err));
  9155. ack = false;
  9156. goto txstatus;
  9157. }
  9158. timeout = wait_for_completion_timeout(&netinfo->mgmt_tx_cpl,
  9159. MGMT_AUTH_FRAME_WAIT_TIME);
  9160. if ((timeout > 0) || test_bit(MGMT_TX_ACK, &netinfo->mgmt_txstatus)) {
  9161. WL_DBG(("TX auth frame operation is success\n"));
  9162. ack = true;
  9163. } else {
  9164. ack = false;
  9165. WL_ERR(("TX auth frame operation has failed, txstatus %ld\n",
  9166. netinfo->mgmt_txstatus));
  9167. }
  9168. txstatus:
  9169. cfg80211_mgmt_tx_status(cfgdev_to_wdev(cfgdev), *cookie,
  9170. buf, len, ack, GFP_KERNEL);
  9171. MFREE(cfg->osh, mf_params, mf_params_len);
  9172. goto exit;
  9173. #endif /* WL_SAE */
  9174. }
  9175. } else {
  9176. WL_ERR(("Driver only allows MGMT packet type\n"));
  9177. goto exit;
  9178. }
  9179. af_params = (wl_af_params_t *)MALLOCZ(cfg->osh, WL_WIFI_AF_PARAMS_SIZE);
  9180. if (af_params == NULL)
  9181. {
  9182. WL_ERR(("unable to allocate frame\n"));
  9183. return -ENOMEM;
  9184. }
  9185. action_frame = &af_params->action_frame;
  9186. /* Add the packet Id */
  9187. action_frame->packetId = *cookie;
  9188. WL_DBG(("action frame %d\n", action_frame->packetId));
  9189. /* Add BSSID */
  9190. memcpy(&action_frame->da, &mgmt->da[0], ETHER_ADDR_LEN);
  9191. memcpy(&af_params->BSSID, &mgmt->bssid[0], ETHER_ADDR_LEN);
  9192. /* Add the length exepted for 802.11 header */
  9193. action_frame->len = len - DOT11_MGMT_HDR_LEN;
  9194. WL_DBG(("action_frame->len: %d\n", action_frame->len));
  9195. /* Add the channel */
  9196. af_params->channel =
  9197. ieee80211_frequency_to_channel(channel->center_freq);
  9198. /* Save listen_chan for searching common channel */
  9199. cfg->afx_hdl->peer_listen_chan = af_params->channel;
  9200. WL_DBG(("channel from upper layer %d\n", cfg->afx_hdl->peer_listen_chan));
  9201. #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0))
  9202. af_params->dwell_time = params->wait;
  9203. #else
  9204. af_params->dwell_time = wait;
  9205. #endif // endif
  9206. memcpy(action_frame->data, &buf[DOT11_MGMT_HDR_LEN], action_frame->len);
  9207. ack = wl_cfg80211_send_action_frame(wiphy, dev, cfgdev, af_params,
  9208. action_frame, action_frame->len, bssidx);
  9209. cfg80211_mgmt_tx_status(cfgdev, *cookie, buf, len, ack, GFP_KERNEL);
  9210. MFREE(cfg->osh, af_params, WL_WIFI_AF_PARAMS_SIZE);
  9211. exit:
  9212. return err;
  9213. }
  9214. static void
  9215. wl_cfg80211_mgmt_frame_register(struct wiphy *wiphy, bcm_struct_cfgdev *cfgdev,
  9216. u16 frame, bool reg)
  9217. {
  9218. WL_DBG(("frame_type: %x, reg: %d\n", frame, reg));
  9219. if (frame != (IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_PROBE_REQ))
  9220. return;
  9221. return;
  9222. }
  9223. static s32
  9224. wl_cfg80211_change_bss(struct wiphy *wiphy,
  9225. struct net_device *dev,
  9226. struct bss_parameters *params)
  9227. {
  9228. s32 err = 0;
  9229. s32 ap_isolate = 0;
  9230. s32 ifidx = DHD_BAD_IF;
  9231. dhd_pub_t *dhd;
  9232. struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
  9233. dhd = (dhd_pub_t *)(cfg->pub);
  9234. #if defined(WL_ENABLE_P2P_IF)
  9235. if (cfg->p2p_net == dev)
  9236. dev = bcmcfg_to_prmry_ndev(cfg);
  9237. #endif // endif
  9238. if (params->use_cts_prot >= 0) {
  9239. }
  9240. if (params->use_short_preamble >= 0) {
  9241. }
  9242. if (params->use_short_slot_time >= 0) {
  9243. }
  9244. if (params->basic_rates) {
  9245. }
  9246. if (params->ap_isolate >= 0) {
  9247. ap_isolate = params->ap_isolate;
  9248. ifidx = dhd_net2idx(dhd->info, dev);
  9249. if (ifidx != DHD_BAD_IF) {
  9250. err = dhd_set_ap_isolate(dhd, ifidx, ap_isolate);
  9251. } else {
  9252. WL_ERR(("Failed to set ap_isolate\n"));
  9253. }
  9254. #ifdef BCMSDIO
  9255. /* Onus of intra-BSS packet forwarding moved to DHD.
  9256. * DHD will handle packet intra-bss packet forwarding.
  9257. */
  9258. err = wldev_iovar_setint(dev, "ap_isolate", AP_ISOLATE_SENDUP_ALL);
  9259. if (unlikely(err))
  9260. {
  9261. WL_ERR(("set ap_isolate Error (%d)\n", err));
  9262. }
  9263. #endif /* BCMSDIO */
  9264. }
  9265. if (params->ht_opmode >= 0) {
  9266. }
  9267. return err;
  9268. }
  9269. static int
  9270. wl_get_bandwidth_cap(struct net_device *ndev, uint32 band, uint32 *bandwidth)
  9271. {
  9272. u32 bw = WL_CHANSPEC_BW_20;
  9273. s32 err = BCME_OK;
  9274. s32 bw_cap = 0;
  9275. struct {
  9276. u32 band;
  9277. u32 bw_cap;
  9278. } param = {0, 0};
  9279. u8 ioctl_buf[WLC_IOCTL_SMLEN];
  9280. u32 channel_width = 0;
  9281. struct wireless_dev *wdev = ndev_to_wdev(ndev);
  9282. struct wiphy *wiphy = wdev->wiphy;
  9283. struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
  9284. if (band == IEEE80211_BAND_5GHZ) {
  9285. param.band = WLC_BAND_5G;
  9286. channel_width = wl_get_chanwidth_by_netdev(cfg, ndev);
  9287. switch (channel_width) {
  9288. case WL_CHANSPEC_BW_80:
  9289. case WL_CHANSPEC_BW_40:
  9290. case WL_CHANSPEC_BW_20:
  9291. bw = channel_width;
  9292. /* resetting user specified channel width */
  9293. wl_set_chanwidth_by_netdev(cfg, ndev, 0);
  9294. break;
  9295. default:
  9296. err = wldev_iovar_getbuf(ndev, "bw_cap", &param, sizeof(param),
  9297. ioctl_buf, sizeof(ioctl_buf), NULL);
  9298. if (err) {
  9299. if (err != BCME_UNSUPPORTED) {
  9300. WL_ERR(("bw_cap failed, %d\n", err));
  9301. return err;
  9302. } else {
  9303. err = wldev_iovar_getint(ndev, "mimo_bw_cap",
  9304. &bw_cap);
  9305. if (err) {
  9306. WL_ERR(("error get mimo_bw_cap (%d)\n",
  9307. err));
  9308. }
  9309. if (bw_cap != WLC_N_BW_20ALL) {
  9310. bw = WL_CHANSPEC_BW_40;
  9311. }
  9312. }
  9313. } else {
  9314. if (WL_BW_CAP_80MHZ(ioctl_buf[0])) {
  9315. bw = WL_CHANSPEC_BW_80;
  9316. } else if (WL_BW_CAP_40MHZ(ioctl_buf[0])) {
  9317. bw = WL_CHANSPEC_BW_40;
  9318. } else {
  9319. bw = WL_CHANSPEC_BW_20;
  9320. }
  9321. }
  9322. break;
  9323. }
  9324. } else if (band == IEEE80211_BAND_2GHZ) {
  9325. bw = WL_CHANSPEC_BW_20;
  9326. }
  9327. *bandwidth = bw;
  9328. return err;
  9329. }
  9330. static s32
  9331. wl_cfg80211_set_channel(struct wiphy *wiphy, struct net_device *dev,
  9332. struct ieee80211_channel *chan,
  9333. enum nl80211_channel_type channel_type)
  9334. {
  9335. s32 _chan;
  9336. chanspec_t chspec = 0;
  9337. chanspec_t fw_chspec = 0;
  9338. u32 bw = WL_CHANSPEC_BW_20;
  9339. s32 err = BCME_OK;
  9340. struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
  9341. #if defined(CUSTOM_SET_CPUCORE) || defined(APSTA_RESTRICTED_CHANNEL)
  9342. dhd_pub_t *dhd = (dhd_pub_t *)(cfg->pub);
  9343. #endif /* CUSTOM_SET_CPUCORE || APSTA_RESTRICTED_CHANNEL */
  9344. dev = ndev_to_wlc_ndev(dev, cfg);
  9345. _chan = ieee80211_frequency_to_channel(chan->center_freq);
  9346. WL_ERR(("netdev_ifidx(%d), chan_type(%d) target channel(%d) \n",
  9347. dev->ifindex, channel_type, _chan));
  9348. #if defined(APSTA_RESTRICTED_CHANNEL)
  9349. if (wl_get_mode_by_netdev(cfg, dev) == WL_MODE_AP &&
  9350. DHD_OPMODE_STA_SOFTAP_CONCURR(dhd) &&
  9351. wl_get_drv_status(cfg, CONNECTED, bcmcfg_to_prmry_ndev(cfg))) {
  9352. u32 *sta_chan = (u32 *)wl_read_prof(cfg,
  9353. bcmcfg_to_prmry_ndev(cfg), WL_PROF_CHAN);
  9354. u32 sta_band = (*sta_chan > CH_MAX_2G_CHANNEL) ?
  9355. IEEE80211_BAND_5GHZ : IEEE80211_BAND_2GHZ;
  9356. if (chan->band == sta_band) {
  9357. /* Do not try SCC in 5GHz if channel is not CH149 */
  9358. _chan = (sta_band == IEEE80211_BAND_5GHZ &&
  9359. *sta_chan != DEFAULT_5G_SOFTAP_CHANNEL) ?
  9360. DEFAULT_2G_SOFTAP_CHANNEL : *sta_chan;
  9361. WL_ERR(("target channel will be changed to %d\n", _chan));
  9362. if (_chan <= CH_MAX_2G_CHANNEL) {
  9363. bw = WL_CHANSPEC_BW_20;
  9364. goto set_channel;
  9365. }
  9366. }
  9367. }
  9368. #endif /* APSTA_RESTRICTED_CHANNEL */
  9369. err = wl_get_bandwidth_cap(dev, chan->band, &bw);
  9370. if (err < 0) {
  9371. WL_ERR(("Failed to get bandwidth information, err=%d\n", err));
  9372. return err;
  9373. }
  9374. set_channel:
  9375. chspec = wf_channel2chspec(_chan, bw);
  9376. if (wf_chspec_valid(chspec)) {
  9377. fw_chspec = wl_chspec_host_to_driver(chspec);
  9378. if (fw_chspec != INVCHANSPEC) {
  9379. if ((err = wldev_iovar_setint(dev, "chanspec",
  9380. fw_chspec)) == BCME_BADCHAN) {
  9381. if (bw == WL_CHANSPEC_BW_80)
  9382. goto change_bw;
  9383. err = wldev_ioctl_set(dev, WLC_SET_CHANNEL,
  9384. &_chan, sizeof(_chan));
  9385. if (err < 0) {
  9386. WL_ERR(("WLC_SET_CHANNEL error %d"
  9387. "chip may not be supporting this channel\n", err));
  9388. }
  9389. } else if (err) {
  9390. WL_ERR(("failed to set chanspec error %d\n", err));
  9391. }
  9392. #ifdef DISABLE_WL_FRAMEBURST_SOFTAP
  9393. else {
  9394. /* Disable Frameburst only for stand-alone 2GHz SoftAP */
  9395. if (wl_get_mode_by_netdev(cfg, dev) == WL_MODE_AP &&
  9396. DHD_OPMODE_SUPPORTED(cfg->pub, DHD_FLAG_HOSTAP_MODE) &&
  9397. (_chan <= CH_MAX_2G_CHANNEL) &&
  9398. !wl_get_drv_status(cfg, CONNECTED,
  9399. bcmcfg_to_prmry_ndev(cfg))) {
  9400. WL_DBG(("Disabling frameburst on "
  9401. "stand-alone 2GHz SoftAP\n"));
  9402. wl_cfg80211_set_frameburst(cfg, FALSE);
  9403. }
  9404. }
  9405. #endif /* DISABLE_WL_FRAMEBURST_SOFTAP */
  9406. } else {
  9407. WL_ERR(("failed to convert host chanspec to fw chanspec\n"));
  9408. err = BCME_ERROR;
  9409. }
  9410. } else {
  9411. change_bw:
  9412. if (bw == WL_CHANSPEC_BW_80)
  9413. bw = WL_CHANSPEC_BW_40;
  9414. else if (bw == WL_CHANSPEC_BW_40)
  9415. bw = WL_CHANSPEC_BW_20;
  9416. else
  9417. bw = 0;
  9418. if (bw)
  9419. goto set_channel;
  9420. WL_ERR(("Invalid chanspec 0x%x\n", chspec));
  9421. err = BCME_ERROR;
  9422. }
  9423. #ifdef CUSTOM_SET_CPUCORE
  9424. if (dhd->op_mode == DHD_FLAG_HOSTAP_MODE) {
  9425. WL_DBG(("SoftAP mode do not need to set cpucore\n"));
  9426. } else if (chspec & WL_CHANSPEC_BW_80) {
  9427. /* SoftAp only mode do not need to set cpucore */
  9428. if ((dev->ieee80211_ptr->iftype == NL80211_IFTYPE_AP) &&
  9429. dev != bcmcfg_to_prmry_ndev(cfg)) {
  9430. /* Soft AP on virtual Iface (AP+STA case) */
  9431. dhd->chan_isvht80 |= DHD_FLAG_HOSTAP_MODE;
  9432. dhd_set_cpucore(dhd, TRUE);
  9433. } else if (is_p2p_group_iface(dev->ieee80211_ptr)) {
  9434. /* If P2P IF is vht80 */
  9435. dhd->chan_isvht80 |= DHD_FLAG_P2P_MODE;
  9436. dhd_set_cpucore(dhd, TRUE);
  9437. }
  9438. }
  9439. #endif /* CUSTOM_SET_CPUCORE */
  9440. if (!err && (wl_get_mode_by_netdev(cfg, dev) == WL_MODE_AP)) {
  9441. /* Update AP/GO operating channel */
  9442. cfg->ap_oper_channel = ieee80211_frequency_to_channel(chan->center_freq);
  9443. }
  9444. if (err) {
  9445. wl_flush_fw_log_buffer(bcmcfg_to_prmry_ndev(cfg),
  9446. FW_LOGSET_MASK_ALL);
  9447. }
  9448. return err;
  9449. }
  9450. #ifdef WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST
  9451. struct net_device *
  9452. wl_cfg80211_get_remain_on_channel_ndev(struct bcm_cfg80211 *cfg)
  9453. {
  9454. struct net_info *_net_info, *next;
  9455. GCC_DIAGNOSTIC_PUSH_SUPPRESS_CAST();
  9456. list_for_each_entry_safe(_net_info, next, &cfg->net_list, list) {
  9457. GCC_DIAGNOSTIC_POP();
  9458. if (_net_info->ndev &&
  9459. test_bit(WL_STATUS_REMAINING_ON_CHANNEL, &_net_info->sme_state))
  9460. return _net_info->ndev;
  9461. }
  9462. return NULL;
  9463. }
  9464. #endif /* WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST */
  9465. static s32
  9466. wl_validate_opensecurity(struct net_device *dev, s32 bssidx, bool privacy)
  9467. {
  9468. s32 err = BCME_OK;
  9469. u32 wpa_val;
  9470. s32 wsec = 0;
  9471. /* set auth */
  9472. err = wldev_iovar_setint_bsscfg(dev, "auth", 0, bssidx);
  9473. if (err < 0) {
  9474. WL_ERR(("auth error %d\n", err));
  9475. return BCME_ERROR;
  9476. }
  9477. if (privacy) {
  9478. /* If privacy bit is set in open mode, then WEP would be enabled */
  9479. wsec = WEP_ENABLED;
  9480. WL_DBG(("Setting wsec to %d for WEP \n", wsec));
  9481. }
  9482. /* set wsec */
  9483. err = wldev_iovar_setint_bsscfg(dev, "wsec", wsec, bssidx);
  9484. if (err < 0) {
  9485. WL_ERR(("wsec error %d\n", err));
  9486. return BCME_ERROR;
  9487. }
  9488. /* set upper-layer auth */
  9489. if (dev->ieee80211_ptr->iftype == NL80211_IFTYPE_ADHOC)
  9490. wpa_val = WPA_AUTH_NONE;
  9491. else
  9492. wpa_val = WPA_AUTH_DISABLED;
  9493. err = wldev_iovar_setint_bsscfg(dev, "wpa_auth", wpa_val, bssidx);
  9494. if (err < 0) {
  9495. WL_ERR(("wpa_auth error %d\n", err));
  9496. return BCME_ERROR;
  9497. }
  9498. return 0;
  9499. }
  9500. #define MAX_FILS_IND_IE_LEN 1024u
  9501. static s32
  9502. wl_validate_fils_ind_ie(struct net_device *dev, const bcm_tlv_t *filsindie, s32 bssidx)
  9503. {
  9504. s32 err = BCME_OK;
  9505. struct bcm_cfg80211 *cfg = NULL;
  9506. bcm_iov_buf_t *iov_buf = NULL;
  9507. bcm_xtlv_t* pxtlv;
  9508. int iov_buf_size = 0;
  9509. if (!dev || !filsindie) {
  9510. WL_ERR(("%s: dev/filsidie is null\n", __FUNCTION__));
  9511. goto exit;
  9512. }
  9513. cfg = wl_get_cfg(dev);
  9514. if (!cfg) {
  9515. WL_ERR(("%s: cfg is null\n", __FUNCTION__));
  9516. goto exit;
  9517. }
  9518. iov_buf_size = sizeof(bcm_iov_buf_t) + sizeof(bcm_xtlv_t) + filsindie->len - 1;
  9519. iov_buf = MALLOCZ(cfg->osh, iov_buf_size);
  9520. if (!iov_buf) {
  9521. WL_ERR(("%s: iov_buf alloc failed! %d bytes\n", __FUNCTION__, iov_buf_size));
  9522. err = BCME_NOMEM;
  9523. goto exit;
  9524. }
  9525. iov_buf->version = WL_FILS_IOV_VERSION;
  9526. iov_buf->id = WL_FILS_CMD_ADD_IND_IE;
  9527. iov_buf->len = sizeof(bcm_xtlv_t) + filsindie->len - 1;
  9528. pxtlv = (bcm_xtlv_t*)&iov_buf->data[0];
  9529. pxtlv->id = WL_FILS_XTLV_IND_IE;
  9530. pxtlv->len = filsindie->len;
  9531. /* memcpy_s return check not required as buffer is allocated based on ie
  9532. * len
  9533. */
  9534. (void)memcpy_s(pxtlv->data, filsindie->len, filsindie->data, filsindie->len);
  9535. err = wldev_iovar_setbuf(dev, "fils", iov_buf, iov_buf_size,
  9536. cfg->ioctl_buf, WLC_IOCTL_SMLEN, &cfg->ioctl_buf_sync);
  9537. if (unlikely(err)) {
  9538. WL_ERR(("fils indication ioctl error (%d)\n", err));
  9539. goto exit;
  9540. }
  9541. exit:
  9542. if (err < 0) {
  9543. WL_ERR(("FILS Ind setting error %d\n", err));
  9544. }
  9545. if (iov_buf) {
  9546. MFREE(cfg->osh, iov_buf, iov_buf_size);
  9547. }
  9548. return err;
  9549. }
  9550. static s32
  9551. wl_validate_wpa2ie(struct net_device *dev, const bcm_tlv_t *wpa2ie, s32 bssidx)
  9552. {
  9553. s32 len = 0;
  9554. s32 err = BCME_OK;
  9555. u16 auth = 0; /* d11 open authentication */
  9556. u32 wsec;
  9557. u32 pval = 0;
  9558. u32 gval = 0;
  9559. u32 wpa_auth = 0;
  9560. const wpa_suite_mcast_t *mcast;
  9561. const wpa_suite_ucast_t *ucast;
  9562. const wpa_suite_auth_key_mgmt_t *mgmt;
  9563. const wpa_pmkid_list_t *pmkid;
  9564. int cnt = 0;
  9565. #ifdef MFP
  9566. int mfp = 0;
  9567. struct bcm_cfg80211 *cfg = wl_get_cfg(dev);
  9568. #endif /* MFP */
  9569. u16 suite_count;
  9570. u8 rsn_cap[2];
  9571. u32 wme_bss_disable;
  9572. if (wpa2ie == NULL)
  9573. goto exit;
  9574. WL_DBG(("Enter \n"));
  9575. len = wpa2ie->len - WPA2_VERSION_LEN;
  9576. /* check the mcast cipher */
  9577. mcast = (const wpa_suite_mcast_t *)&wpa2ie->data[WPA2_VERSION_LEN];
  9578. switch (mcast->type) {
  9579. case WPA_CIPHER_NONE:
  9580. gval = 0;
  9581. break;
  9582. case WPA_CIPHER_WEP_40:
  9583. case WPA_CIPHER_WEP_104:
  9584. gval = WEP_ENABLED;
  9585. break;
  9586. case WPA_CIPHER_TKIP:
  9587. gval = TKIP_ENABLED;
  9588. break;
  9589. case WPA_CIPHER_AES_CCM:
  9590. gval = AES_ENABLED;
  9591. break;
  9592. #ifdef BCMWAPI_WPI
  9593. case WAPI_CIPHER_SMS4:
  9594. gval = SMS4_ENABLED;
  9595. break;
  9596. #endif // endif
  9597. default:
  9598. WL_ERR(("No Security Info\n"));
  9599. break;
  9600. }
  9601. if ((len -= WPA_SUITE_LEN) <= 0)
  9602. return BCME_BADLEN;
  9603. /* check the unicast cipher */
  9604. ucast = (const wpa_suite_ucast_t *)&mcast[1];
  9605. suite_count = ltoh16_ua(&ucast->count);
  9606. switch (ucast->list[0].type) {
  9607. case WPA_CIPHER_NONE:
  9608. pval = 0;
  9609. break;
  9610. case WPA_CIPHER_WEP_40:
  9611. case WPA_CIPHER_WEP_104:
  9612. pval = WEP_ENABLED;
  9613. break;
  9614. case WPA_CIPHER_TKIP:
  9615. pval = TKIP_ENABLED;
  9616. break;
  9617. case WPA_CIPHER_AES_CCM:
  9618. pval = AES_ENABLED;
  9619. break;
  9620. #ifdef BCMWAPI_WPI
  9621. case WAPI_CIPHER_SMS4:
  9622. pval = SMS4_ENABLED;
  9623. break;
  9624. #endif // endif
  9625. default:
  9626. WL_ERR(("No Security Info\n"));
  9627. }
  9628. if ((len -= (WPA_IE_SUITE_COUNT_LEN + (WPA_SUITE_LEN * suite_count))) <= 0)
  9629. return BCME_BADLEN;
  9630. /* FOR WPS , set SEC_OW_ENABLED */
  9631. wsec = (pval | gval | SES_OW_ENABLED);
  9632. /* check the AKM */
  9633. mgmt = (const wpa_suite_auth_key_mgmt_t *)&ucast->list[suite_count];
  9634. suite_count = cnt = ltoh16_ua(&mgmt->count);
  9635. while (cnt--) {
  9636. if (!bcmp(mgmt->list[cnt].oui, WPA2_OUI, WPA2_OUI_LEN)) {
  9637. switch (mgmt->list[cnt].type) {
  9638. case RSN_AKM_NONE:
  9639. wpa_auth |= WPA_AUTH_NONE;
  9640. break;
  9641. case RSN_AKM_UNSPECIFIED:
  9642. wpa_auth |= WPA2_AUTH_UNSPECIFIED;
  9643. break;
  9644. case RSN_AKM_PSK:
  9645. wpa_auth |= WPA2_AUTH_PSK;
  9646. break;
  9647. #ifdef MFP
  9648. case RSN_AKM_MFP_PSK:
  9649. wpa_auth |= WPA2_AUTH_PSK_SHA256;
  9650. break;
  9651. case RSN_AKM_MFP_1X:
  9652. wpa_auth |= WPA2_AUTH_1X_SHA256;
  9653. break;
  9654. case RSN_AKM_FILS_SHA256:
  9655. wpa_auth |= WPA2_AUTH_FILS_SHA256;
  9656. break;
  9657. case RSN_AKM_FILS_SHA384:
  9658. wpa_auth |= WPA2_AUTH_FILS_SHA384;
  9659. break;
  9660. #ifdef WL_SAE
  9661. case RSN_AKM_SAE_PSK:
  9662. wpa_auth |= WPA3_AUTH_SAE_PSK;
  9663. break;
  9664. #endif /* WL_SAE */
  9665. #endif /* MFP */
  9666. default:
  9667. WL_ERR(("No Key Mgmt Info\n"));
  9668. }
  9669. } else if (!bcmp(mgmt->list[cnt].oui, WFA_OUI, WFA_OUI_LEN))
  9670. wpa_auth |= WFA_AUTH_DPP;
  9671. }
  9672. if ((len -= (WPA_IE_SUITE_COUNT_LEN + (WPA_SUITE_LEN * suite_count))) >= RSN_CAP_LEN) {
  9673. rsn_cap[0] = *(const u8 *)&mgmt->list[suite_count];
  9674. rsn_cap[1] = *((const u8 *)&mgmt->list[suite_count] + 1);
  9675. if (rsn_cap[0] & (RSN_CAP_16_REPLAY_CNTRS << RSN_CAP_PTK_REPLAY_CNTR_SHIFT)) {
  9676. wme_bss_disable = 0;
  9677. } else {
  9678. wme_bss_disable = 1;
  9679. }
  9680. #ifdef MFP
  9681. if (rsn_cap[0] & RSN_CAP_MFPR) {
  9682. WL_DBG(("MFP Required \n"));
  9683. mfp = WL_MFP_REQUIRED;
  9684. /* Our firmware has requirement that WPA2_AUTH_PSK/WPA2_AUTH_UNSPECIFIED
  9685. * be set, if SHA256 OUI is to be included in the rsn ie.
  9686. */
  9687. if (wpa_auth & WPA2_AUTH_PSK_SHA256) {
  9688. wpa_auth |= WPA2_AUTH_PSK;
  9689. } else if (wpa_auth & WPA2_AUTH_1X_SHA256) {
  9690. wpa_auth |= WPA2_AUTH_UNSPECIFIED;
  9691. }
  9692. } else if (rsn_cap[0] & RSN_CAP_MFPC) {
  9693. WL_DBG(("MFP Capable \n"));
  9694. mfp = WL_MFP_CAPABLE;
  9695. }
  9696. #endif /* MFP */
  9697. /* set wme_bss_disable to sync RSN Capabilities */
  9698. err = wldev_iovar_setint_bsscfg(dev, "wme_bss_disable", wme_bss_disable, bssidx);
  9699. if (err < 0) {
  9700. WL_ERR(("wme_bss_disable error %d\n", err));
  9701. return BCME_ERROR;
  9702. }
  9703. } else {
  9704. WL_DBG(("There is no RSN Capabilities. remained len %d\n", len));
  9705. }
  9706. len -= RSN_CAP_LEN;
  9707. if (len >= WPA2_PMKID_COUNT_LEN) {
  9708. pmkid = (const wpa_pmkid_list_t *)
  9709. ((const u8 *)&mgmt->list[suite_count] + RSN_CAP_LEN);
  9710. cnt = ltoh16_ua(&pmkid->count);
  9711. if (cnt != 0) {
  9712. WL_ERR(("AP has non-zero PMKID count. Wrong!\n"));
  9713. return BCME_ERROR;
  9714. }
  9715. /* since PMKID cnt is known to be 0 for AP, */
  9716. /* so don't bother to send down this info to firmware */
  9717. }
  9718. #ifdef MFP
  9719. len -= WPA2_PMKID_COUNT_LEN;
  9720. if (len >= WPA_SUITE_LEN) {
  9721. cfg->bip_pos =
  9722. (const u8 *)&mgmt->list[suite_count] + RSN_CAP_LEN + WPA2_PMKID_COUNT_LEN;
  9723. } else {
  9724. cfg->bip_pos = NULL;
  9725. }
  9726. #endif // endif
  9727. /* set auth */
  9728. err = wldev_iovar_setint_bsscfg(dev, "auth", auth, bssidx);
  9729. if (err < 0) {
  9730. WL_ERR(("auth error %d\n", err));
  9731. return BCME_ERROR;
  9732. }
  9733. /* set wsec */
  9734. err = wldev_iovar_setint_bsscfg(dev, "wsec", wsec, bssidx);
  9735. if (err < 0) {
  9736. WL_ERR(("wsec error %d\n", err));
  9737. return BCME_ERROR;
  9738. }
  9739. #ifdef MFP
  9740. cfg->mfp_mode = mfp;
  9741. #endif /* MFP */
  9742. /* set upper-layer auth */
  9743. err = wldev_iovar_setint_bsscfg(dev, "wpa_auth", wpa_auth, bssidx);
  9744. if (err < 0) {
  9745. WL_ERR(("wpa_auth error %d\n", err));
  9746. return BCME_ERROR;
  9747. }
  9748. exit:
  9749. return 0;
  9750. }
  9751. static s32
  9752. wl_validate_wpaie(struct net_device *dev, const wpa_ie_fixed_t *wpaie, s32 bssidx)
  9753. {
  9754. const wpa_suite_mcast_t *mcast;
  9755. const wpa_suite_ucast_t *ucast;
  9756. const wpa_suite_auth_key_mgmt_t *mgmt;
  9757. u16 auth = 0; /* d11 open authentication */
  9758. u16 count;
  9759. s32 err = BCME_OK;
  9760. s32 len = 0;
  9761. u32 i;
  9762. u32 wsec;
  9763. u32 pval = 0;
  9764. u32 gval = 0;
  9765. u32 wpa_auth = 0;
  9766. u32 tmp = 0;
  9767. if (wpaie == NULL)
  9768. goto exit;
  9769. WL_DBG(("Enter \n"));
  9770. len = wpaie->length; /* value length */
  9771. len -= WPA_IE_TAG_FIXED_LEN;
  9772. /* check for multicast cipher suite */
  9773. if (len < WPA_SUITE_LEN) {
  9774. WL_INFORM_MEM(("no multicast cipher suite\n"));
  9775. goto exit;
  9776. }
  9777. /* pick up multicast cipher */
  9778. mcast = (const wpa_suite_mcast_t *)&wpaie[1];
  9779. len -= WPA_SUITE_LEN;
  9780. if (!bcmp(mcast->oui, WPA_OUI, WPA_OUI_LEN)) {
  9781. if (IS_WPA_CIPHER(mcast->type)) {
  9782. tmp = 0;
  9783. switch (mcast->type) {
  9784. case WPA_CIPHER_NONE:
  9785. tmp = 0;
  9786. break;
  9787. case WPA_CIPHER_WEP_40:
  9788. case WPA_CIPHER_WEP_104:
  9789. tmp = WEP_ENABLED;
  9790. break;
  9791. case WPA_CIPHER_TKIP:
  9792. tmp = TKIP_ENABLED;
  9793. break;
  9794. case WPA_CIPHER_AES_CCM:
  9795. tmp = AES_ENABLED;
  9796. break;
  9797. default:
  9798. WL_ERR(("No Security Info\n"));
  9799. }
  9800. gval |= tmp;
  9801. }
  9802. }
  9803. /* Check for unicast suite(s) */
  9804. if (len < WPA_IE_SUITE_COUNT_LEN) {
  9805. WL_INFORM_MEM(("no unicast suite\n"));
  9806. goto exit;
  9807. }
  9808. /* walk thru unicast cipher list and pick up what we recognize */
  9809. ucast = (const wpa_suite_ucast_t *)&mcast[1];
  9810. count = ltoh16_ua(&ucast->count);
  9811. len -= WPA_IE_SUITE_COUNT_LEN;
  9812. for (i = 0; i < count && len >= WPA_SUITE_LEN;
  9813. i++, len -= WPA_SUITE_LEN) {
  9814. if (!bcmp(ucast->list[i].oui, WPA_OUI, WPA_OUI_LEN)) {
  9815. if (IS_WPA_CIPHER(ucast->list[i].type)) {
  9816. tmp = 0;
  9817. switch (ucast->list[i].type) {
  9818. case WPA_CIPHER_NONE:
  9819. tmp = 0;
  9820. break;
  9821. case WPA_CIPHER_WEP_40:
  9822. case WPA_CIPHER_WEP_104:
  9823. tmp = WEP_ENABLED;
  9824. break;
  9825. case WPA_CIPHER_TKIP:
  9826. tmp = TKIP_ENABLED;
  9827. break;
  9828. case WPA_CIPHER_AES_CCM:
  9829. tmp = AES_ENABLED;
  9830. break;
  9831. default:
  9832. WL_ERR(("No Security Info\n"));
  9833. }
  9834. pval |= tmp;
  9835. }
  9836. }
  9837. }
  9838. len -= (count - i) * WPA_SUITE_LEN;
  9839. /* Check for auth key management suite(s) */
  9840. if (len < WPA_IE_SUITE_COUNT_LEN) {
  9841. WL_INFORM_MEM((" no auth key mgmt suite\n"));
  9842. goto exit;
  9843. }
  9844. /* walk thru auth management suite list and pick up what we recognize */
  9845. mgmt = (const wpa_suite_auth_key_mgmt_t *)&ucast->list[count];
  9846. count = ltoh16_ua(&mgmt->count);
  9847. len -= WPA_IE_SUITE_COUNT_LEN;
  9848. for (i = 0; i < count && len >= WPA_SUITE_LEN;
  9849. i++, len -= WPA_SUITE_LEN) {
  9850. if (!bcmp(mgmt->list[i].oui, WPA_OUI, WPA_OUI_LEN)) {
  9851. if (IS_WPA_AKM(mgmt->list[i].type)) {
  9852. tmp = 0;
  9853. switch (mgmt->list[i].type) {
  9854. case RSN_AKM_NONE:
  9855. tmp = WPA_AUTH_NONE;
  9856. break;
  9857. case RSN_AKM_UNSPECIFIED:
  9858. tmp = WPA_AUTH_UNSPECIFIED;
  9859. break;
  9860. case RSN_AKM_PSK:
  9861. tmp = WPA_AUTH_PSK;
  9862. break;
  9863. default:
  9864. WL_ERR(("No Key Mgmt Info\n"));
  9865. }
  9866. wpa_auth |= tmp;
  9867. }
  9868. }
  9869. }
  9870. /* FOR WPS , set SEC_OW_ENABLED */
  9871. wsec = (pval | gval | SES_OW_ENABLED);
  9872. /* set auth */
  9873. err = wldev_iovar_setint_bsscfg(dev, "auth", auth, bssidx);
  9874. if (err < 0) {
  9875. WL_ERR(("auth error %d\n", err));
  9876. return BCME_ERROR;
  9877. }
  9878. /* set wsec */
  9879. err = wldev_iovar_setint_bsscfg(dev, "wsec", wsec, bssidx);
  9880. if (err < 0) {
  9881. WL_ERR(("wsec error %d\n", err));
  9882. return BCME_ERROR;
  9883. }
  9884. /* set upper-layer auth */
  9885. err = wldev_iovar_setint_bsscfg(dev, "wpa_auth", wpa_auth, bssidx);
  9886. if (err < 0) {
  9887. WL_ERR(("wpa_auth error %d\n", err));
  9888. return BCME_ERROR;
  9889. }
  9890. exit:
  9891. return 0;
  9892. }
  9893. #if defined(SUPPORT_SOFTAP_WPAWPA2_MIXED)
  9894. static u32 wl_get_cipher_type(uint8 type)
  9895. {
  9896. u32 ret = 0;
  9897. switch (type) {
  9898. case WPA_CIPHER_NONE:
  9899. ret = 0;
  9900. break;
  9901. case WPA_CIPHER_WEP_40:
  9902. case WPA_CIPHER_WEP_104:
  9903. ret = WEP_ENABLED;
  9904. break;
  9905. case WPA_CIPHER_TKIP:
  9906. ret = TKIP_ENABLED;
  9907. break;
  9908. case WPA_CIPHER_AES_CCM:
  9909. ret = AES_ENABLED;
  9910. break;
  9911. #ifdef BCMWAPI_WPI
  9912. case WAPI_CIPHER_SMS4:
  9913. ret = SMS4_ENABLED;
  9914. break;
  9915. #endif // endif
  9916. default:
  9917. WL_ERR(("No Security Info\n"));
  9918. }
  9919. return ret;
  9920. }
  9921. static u32 wl_get_suite_auth_key_mgmt_type(uint8 type, const wpa_suite_mcast_t *mcast)
  9922. {
  9923. u32 ret = 0;
  9924. u32 is_wpa2 = 0;
  9925. if (!bcmp(mcast->oui, WPA2_OUI, WPA2_OUI_LEN)) {
  9926. is_wpa2 = 1;
  9927. }
  9928. WL_INFORM_MEM(("%s, type = %d\n", is_wpa2 ? "WPA2":"WPA", type));
  9929. switch (type) {
  9930. case RSN_AKM_NONE:
  9931. /* For WPA and WPA2, AUTH_NONE is common */
  9932. ret = WPA_AUTH_NONE;
  9933. break;
  9934. case RSN_AKM_UNSPECIFIED:
  9935. if (is_wpa2) {
  9936. ret = WPA2_AUTH_UNSPECIFIED;
  9937. } else {
  9938. ret = WPA_AUTH_UNSPECIFIED;
  9939. }
  9940. break;
  9941. case RSN_AKM_PSK:
  9942. if (is_wpa2) {
  9943. ret = WPA2_AUTH_PSK;
  9944. } else {
  9945. ret = WPA_AUTH_PSK;
  9946. }
  9947. break;
  9948. #ifdef WL_SAE
  9949. case RSN_AKM_SAE_PSK:
  9950. ret = WPA3_AUTH_SAE_PSK;
  9951. break;
  9952. #endif /* WL_SAE */
  9953. default:
  9954. WL_ERR(("No Key Mgmt Info\n"));
  9955. }
  9956. return ret;
  9957. }
  9958. static s32
  9959. wl_validate_wpaie_wpa2ie(struct net_device *dev, const wpa_ie_fixed_t *wpaie,
  9960. const bcm_tlv_t *wpa2ie, s32 bssidx)
  9961. {
  9962. const wpa_suite_mcast_t *mcast;
  9963. const wpa_suite_ucast_t *ucast;
  9964. const wpa_suite_auth_key_mgmt_t *mgmt;
  9965. u16 auth = 0; /* d11 open authentication */
  9966. u16 count;
  9967. s32 err = BCME_OK;
  9968. u32 wme_bss_disable;
  9969. u16 suite_count;
  9970. u8 rsn_cap[2];
  9971. s32 len = 0;
  9972. u32 i;
  9973. u32 wsec1, wsec2, wsec;
  9974. u32 pval = 0;
  9975. u32 gval = 0;
  9976. u32 wpa_auth = 0;
  9977. u32 wpa_auth1 = 0;
  9978. u32 wpa_auth2 = 0;
  9979. if (wpaie == NULL || wpa2ie == NULL)
  9980. goto exit;
  9981. WL_DBG(("Enter \n"));
  9982. len = wpaie->length; /* value length */
  9983. len -= WPA_IE_TAG_FIXED_LEN;
  9984. /* check for multicast cipher suite */
  9985. if (len < WPA_SUITE_LEN) {
  9986. WL_INFORM_MEM(("no multicast cipher suite\n"));
  9987. goto exit;
  9988. }
  9989. /* pick up multicast cipher */
  9990. mcast = (const wpa_suite_mcast_t *)&wpaie[1];
  9991. len -= WPA_SUITE_LEN;
  9992. if (!bcmp(mcast->oui, WPA_OUI, WPA_OUI_LEN)) {
  9993. if (IS_WPA_CIPHER(mcast->type)) {
  9994. gval |= wl_get_cipher_type(mcast->type);
  9995. }
  9996. }
  9997. WL_DBG(("\nwpa ie validate\n"));
  9998. WL_DBG(("wpa ie mcast cipher = 0x%X\n", gval));
  9999. /* Check for unicast suite(s) */
  10000. if (len < WPA_IE_SUITE_COUNT_LEN) {
  10001. WL_INFORM_MEM(("no unicast suite\n"));
  10002. goto exit;
  10003. }
  10004. /* walk thru unicast cipher list and pick up what we recognize */
  10005. ucast = (const wpa_suite_ucast_t *)&mcast[1];
  10006. count = ltoh16_ua(&ucast->count);
  10007. len -= WPA_IE_SUITE_COUNT_LEN;
  10008. for (i = 0; i < count && len >= WPA_SUITE_LEN;
  10009. i++, len -= WPA_SUITE_LEN) {
  10010. if (!bcmp(ucast->list[i].oui, WPA_OUI, WPA_OUI_LEN)) {
  10011. if (IS_WPA_CIPHER(ucast->list[i].type)) {
  10012. pval |= wl_get_cipher_type(ucast->list[i].type);
  10013. }
  10014. }
  10015. }
  10016. WL_ERR(("wpa ie ucast count =%d, cipher = 0x%X\n", count, pval));
  10017. /* FOR WPS , set SEC_OW_ENABLED */
  10018. wsec1 = (pval | gval | SES_OW_ENABLED);
  10019. WL_ERR(("wpa ie wsec = 0x%X\n", wsec1));
  10020. len -= (count - i) * WPA_SUITE_LEN;
  10021. /* Check for auth key management suite(s) */
  10022. if (len < WPA_IE_SUITE_COUNT_LEN) {
  10023. WL_INFORM_MEM((" no auth key mgmt suite\n"));
  10024. goto exit;
  10025. }
  10026. /* walk thru auth management suite list and pick up what we recognize */
  10027. mgmt = (const wpa_suite_auth_key_mgmt_t *)&ucast->list[count];
  10028. count = ltoh16_ua(&mgmt->count);
  10029. len -= WPA_IE_SUITE_COUNT_LEN;
  10030. for (i = 0; i < count && len >= WPA_SUITE_LEN;
  10031. i++, len -= WPA_SUITE_LEN) {
  10032. if (!bcmp(mgmt->list[i].oui, WPA_OUI, WPA_OUI_LEN)) {
  10033. if (IS_WPA_AKM(mgmt->list[i].type)) {
  10034. wpa_auth1 |=
  10035. wl_get_suite_auth_key_mgmt_type(mgmt->list[i].type, mcast);
  10036. }
  10037. }
  10038. }
  10039. WL_ERR(("wpa ie wpa_suite_auth_key_mgmt count=%d, key_mgmt = 0x%X\n", count, wpa_auth1));
  10040. WL_ERR(("\nwpa2 ie validate\n"));
  10041. pval = 0;
  10042. gval = 0;
  10043. len = wpa2ie->len;
  10044. /* check the mcast cipher */
  10045. mcast = (const wpa_suite_mcast_t *)&wpa2ie->data[WPA2_VERSION_LEN];
  10046. gval = wl_get_cipher_type(mcast->type);
  10047. WL_ERR(("wpa2 ie mcast cipher = 0x%X\n", gval));
  10048. if ((len -= WPA_SUITE_LEN) <= 0)
  10049. {
  10050. WL_ERR(("P:wpa2 ie len[%d]", len));
  10051. return BCME_BADLEN;
  10052. }
  10053. /* check the unicast cipher */
  10054. ucast = (const wpa_suite_ucast_t *)&mcast[1];
  10055. suite_count = ltoh16_ua(&ucast->count);
  10056. WL_ERR((" WPA2 ucast cipher count=%d\n", suite_count));
  10057. pval |= wl_get_cipher_type(ucast->list[0].type);
  10058. if ((len -= (WPA_IE_SUITE_COUNT_LEN + (WPA_SUITE_LEN * suite_count))) <= 0)
  10059. return BCME_BADLEN;
  10060. WL_ERR(("wpa2 ie ucast cipher = 0x%X\n", pval));
  10061. /* FOR WPS , set SEC_OW_ENABLED */
  10062. wsec2 = (pval | gval | SES_OW_ENABLED);
  10063. WL_ERR(("wpa2 ie wsec = 0x%X\n", wsec2));
  10064. /* check the AKM */
  10065. mgmt = (const wpa_suite_auth_key_mgmt_t *)&ucast->list[suite_count];
  10066. suite_count = ltoh16_ua(&mgmt->count);
  10067. wpa_auth2 = wl_get_suite_auth_key_mgmt_type(mgmt->list[0].type, mcast);
  10068. WL_ERR(("wpa ie wpa_suite_auth_key_mgmt count=%d, key_mgmt = 0x%X\n", count, wpa_auth2));
  10069. if ((len -= (WPA_IE_SUITE_COUNT_LEN + (WPA_SUITE_LEN * suite_count))) >= RSN_CAP_LEN) {
  10070. rsn_cap[0] = *(const u8 *)&mgmt->list[suite_count];
  10071. rsn_cap[1] = *((const u8 *)&mgmt->list[suite_count] + 1);
  10072. if (rsn_cap[0] & (RSN_CAP_16_REPLAY_CNTRS << RSN_CAP_PTK_REPLAY_CNTR_SHIFT)) {
  10073. wme_bss_disable = 0;
  10074. } else {
  10075. wme_bss_disable = 1;
  10076. }
  10077. WL_DBG(("P:rsn_cap[0]=[0x%X]:wme_bss_disabled[%d]\n", rsn_cap[0], wme_bss_disable));
  10078. /* set wme_bss_disable to sync RSN Capabilities */
  10079. err = wldev_iovar_setint_bsscfg(dev, "wme_bss_disable", wme_bss_disable, bssidx);
  10080. if (err < 0) {
  10081. WL_ERR(("wme_bss_disable error %d\n", err));
  10082. return BCME_ERROR;
  10083. }
  10084. } else {
  10085. WL_DBG(("There is no RSN Capabilities. remained len %d\n", len));
  10086. }
  10087. wsec = (wsec1 | wsec2);
  10088. wpa_auth = (wpa_auth1 | wpa_auth2);
  10089. WL_ERR(("wpa_wpa2 wsec=0x%X wpa_auth=0x%X\n", wsec, wpa_auth));
  10090. /* set auth */
  10091. err = wldev_iovar_setint_bsscfg(dev, "auth", auth, bssidx);
  10092. if (err < 0) {
  10093. WL_ERR(("auth error %d\n", err));
  10094. return BCME_ERROR;
  10095. }
  10096. /* set wsec */
  10097. err = wldev_iovar_setint_bsscfg(dev, "wsec", wsec, bssidx);
  10098. if (err < 0) {
  10099. WL_ERR(("wsec error %d\n", err));
  10100. return BCME_ERROR;
  10101. }
  10102. /* set upper-layer auth */
  10103. err = wldev_iovar_setint_bsscfg(dev, "wpa_auth", wpa_auth, bssidx);
  10104. if (err < 0) {
  10105. WL_ERR(("wpa_auth error %d\n", err));
  10106. return BCME_ERROR;
  10107. }
  10108. exit:
  10109. return 0;
  10110. }
  10111. #endif /* SUPPORT_SOFTAP_WPAWPA2_MIXED */
  10112. static s32
  10113. wl_cfg80211_bcn_validate_sec(
  10114. struct net_device *dev,
  10115. struct parsed_ies *ies,
  10116. u32 dev_role,
  10117. s32 bssidx,
  10118. bool privacy)
  10119. {
  10120. struct bcm_cfg80211 *cfg = wl_get_cfg(dev);
  10121. wl_cfgbss_t *bss = wl_get_cfgbss_by_wdev(cfg, dev->ieee80211_ptr);
  10122. if (!bss) {
  10123. WL_ERR(("cfgbss is NULL \n"));
  10124. return BCME_ERROR;
  10125. }
  10126. if (dev_role == NL80211_IFTYPE_P2P_GO && (ies->wpa2_ie)) {
  10127. /* For P2P GO, the sec type is WPA2-PSK */
  10128. WL_DBG(("P2P GO: validating wpa2_ie"));
  10129. if (wl_validate_wpa2ie(dev, ies->wpa2_ie, bssidx) < 0)
  10130. return BCME_ERROR;
  10131. } else if (dev_role == NL80211_IFTYPE_AP) {
  10132. WL_DBG(("SoftAP: validating security"));
  10133. /* If wpa2_ie or wpa_ie is present validate it */
  10134. #if defined(SUPPORT_SOFTAP_WPAWPA2_MIXED)
  10135. if ((ies->wpa_ie != NULL && ies->wpa2_ie != NULL)) {
  10136. if (wl_validate_wpaie_wpa2ie(dev, ies->wpa_ie, ies->wpa2_ie, bssidx) < 0) {
  10137. bss->security_mode = false;
  10138. return BCME_ERROR;
  10139. }
  10140. }
  10141. else {
  10142. #endif /* SUPPORT_SOFTAP_WPAWPA2_MIXED */
  10143. if ((ies->wpa2_ie || ies->wpa_ie) &&
  10144. ((wl_validate_wpa2ie(dev, ies->wpa2_ie, bssidx) < 0 ||
  10145. wl_validate_wpaie(dev, ies->wpa_ie, bssidx) < 0))) {
  10146. bss->security_mode = false;
  10147. return BCME_ERROR;
  10148. }
  10149. if (ies->fils_ind_ie &&
  10150. (wl_validate_fils_ind_ie(dev, ies->fils_ind_ie, bssidx) < 0)) {
  10151. bss->security_mode = false;
  10152. return BCME_ERROR;
  10153. }
  10154. bss->security_mode = true;
  10155. if (bss->rsn_ie) {
  10156. MFREE(cfg->osh, bss->rsn_ie, bss->rsn_ie[1]
  10157. + WPA_RSN_IE_TAG_FIXED_LEN);
  10158. bss->rsn_ie = NULL;
  10159. }
  10160. if (bss->wpa_ie) {
  10161. MFREE(cfg->osh, bss->wpa_ie, bss->wpa_ie[1]
  10162. + WPA_RSN_IE_TAG_FIXED_LEN);
  10163. bss->wpa_ie = NULL;
  10164. }
  10165. if (bss->wps_ie) {
  10166. MFREE(cfg->osh, bss->wps_ie, bss->wps_ie[1] + 2);
  10167. bss->wps_ie = NULL;
  10168. }
  10169. if (bss->fils_ind_ie) {
  10170. MFREE(cfg->osh, bss->fils_ind_ie, bss->fils_ind_ie[1]
  10171. + FILS_INDICATION_IE_TAG_FIXED_LEN);
  10172. }
  10173. if (ies->wpa_ie != NULL) {
  10174. /* WPAIE */
  10175. bss->rsn_ie = NULL;
  10176. bss->wpa_ie = MALLOCZ(cfg->osh,
  10177. ies->wpa_ie->length
  10178. + WPA_RSN_IE_TAG_FIXED_LEN);
  10179. if (bss->wpa_ie) {
  10180. memcpy(bss->wpa_ie, ies->wpa_ie,
  10181. ies->wpa_ie->length
  10182. + WPA_RSN_IE_TAG_FIXED_LEN);
  10183. }
  10184. } else if (ies->wpa2_ie != NULL) {
  10185. /* RSNIE */
  10186. bss->wpa_ie = NULL;
  10187. bss->rsn_ie = MALLOCZ(cfg->osh,
  10188. ies->wpa2_ie->len
  10189. + WPA_RSN_IE_TAG_FIXED_LEN);
  10190. if (bss->rsn_ie) {
  10191. memcpy(bss->rsn_ie, ies->wpa2_ie,
  10192. ies->wpa2_ie->len
  10193. + WPA_RSN_IE_TAG_FIXED_LEN);
  10194. }
  10195. }
  10196. #ifdef WL_FILS
  10197. if (ies->fils_ind_ie) {
  10198. bss->fils_ind_ie = MALLOCZ(cfg->osh,
  10199. ies->fils_ind_ie->len
  10200. + FILS_INDICATION_IE_TAG_FIXED_LEN);
  10201. if (bss->fils_ind_ie) {
  10202. memcpy(bss->fils_ind_ie, ies->fils_ind_ie,
  10203. ies->fils_ind_ie->len
  10204. + FILS_INDICATION_IE_TAG_FIXED_LEN);
  10205. }
  10206. }
  10207. #endif /* WL_FILS */
  10208. #if defined(SUPPORT_SOFTAP_WPAWPA2_MIXED)
  10209. }
  10210. #endif /* SUPPORT_SOFTAP_WPAWPA2_MIXED */
  10211. if (!ies->wpa2_ie && !ies->wpa_ie) {
  10212. wl_validate_opensecurity(dev, bssidx, privacy);
  10213. bss->security_mode = false;
  10214. }
  10215. if (ies->wps_ie) {
  10216. bss->wps_ie = MALLOCZ(cfg->osh, ies->wps_ie_len);
  10217. if (bss->wps_ie) {
  10218. memcpy(bss->wps_ie, ies->wps_ie, ies->wps_ie_len);
  10219. }
  10220. }
  10221. }
  10222. return 0;
  10223. }
  10224. #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)) || defined(WL_COMPAT_WIRELESS)
  10225. static s32 wl_cfg80211_bcn_set_params(
  10226. struct cfg80211_ap_settings *info,
  10227. struct net_device *dev,
  10228. u32 dev_role, s32 bssidx)
  10229. {
  10230. struct bcm_cfg80211 *cfg = wl_get_cfg(dev);
  10231. s32 err = BCME_OK;
  10232. WL_DBG(("interval (%d) \ndtim_period (%d) \n",
  10233. info->beacon_interval, info->dtim_period));
  10234. if (info->beacon_interval) {
  10235. if ((err = wldev_ioctl_set(dev, WLC_SET_BCNPRD,
  10236. &info->beacon_interval, sizeof(s32))) < 0) {
  10237. WL_ERR(("Beacon Interval Set Error, %d\n", err));
  10238. return err;
  10239. }
  10240. }
  10241. if (info->dtim_period) {
  10242. if ((err = wldev_ioctl_set(dev, WLC_SET_DTIMPRD,
  10243. &info->dtim_period, sizeof(s32))) < 0) {
  10244. WL_ERR(("DTIM Interval Set Error, %d\n", err));
  10245. return err;
  10246. }
  10247. }
  10248. if ((info->ssid) && (info->ssid_len > 0) &&
  10249. (info->ssid_len <= DOT11_MAX_SSID_LEN)) {
  10250. WL_DBG(("SSID (%s) len:%zd \n", info->ssid, info->ssid_len));
  10251. if (dev_role == NL80211_IFTYPE_AP) {
  10252. /* Store the hostapd SSID */
  10253. bzero(cfg->hostapd_ssid.SSID, DOT11_MAX_SSID_LEN);
  10254. memcpy(cfg->hostapd_ssid.SSID, info->ssid, info->ssid_len);
  10255. cfg->hostapd_ssid.SSID_len = (uint32)info->ssid_len;
  10256. } else {
  10257. /* P2P GO */
  10258. bzero(cfg->p2p->ssid.SSID, DOT11_MAX_SSID_LEN);
  10259. memcpy(cfg->p2p->ssid.SSID, info->ssid, info->ssid_len);
  10260. cfg->p2p->ssid.SSID_len = (uint32)info->ssid_len;
  10261. }
  10262. }
  10263. return err;
  10264. }
  10265. #endif /* LINUX_VERSION >= VERSION(3,4,0) || WL_COMPAT_WIRELESS */
  10266. static s32
  10267. wl_cfg80211_parse_ies(const u8 *ptr, u32 len, struct parsed_ies *ies)
  10268. {
  10269. s32 err = BCME_OK;
  10270. bzero(ies, sizeof(struct parsed_ies));
  10271. /* find the WPSIE */
  10272. if ((ies->wps_ie = wl_cfgp2p_find_wpsie(ptr, len)) != NULL) {
  10273. WL_DBG(("WPSIE in beacon \n"));
  10274. ies->wps_ie_len = ies->wps_ie->length + WPA_RSN_IE_TAG_FIXED_LEN;
  10275. } else {
  10276. WL_ERR(("No WPSIE in beacon \n"));
  10277. }
  10278. /* find the RSN_IE */
  10279. if ((ies->wpa2_ie = bcm_parse_tlvs(ptr, len,
  10280. DOT11_MNG_RSN_ID)) != NULL) {
  10281. WL_DBG((" WPA2 IE found\n"));
  10282. ies->wpa2_ie_len = ies->wpa2_ie->len;
  10283. }
  10284. /* find the FILS_IND_IE */
  10285. if ((ies->fils_ind_ie = bcm_parse_tlvs(ptr, len,
  10286. DOT11_MNG_FILS_IND_ID)) != NULL) {
  10287. WL_DBG((" FILS IND IE found\n"));
  10288. ies->fils_ind_ie_len = ies->fils_ind_ie->len;
  10289. }
  10290. /* find the WPA_IE */
  10291. if ((ies->wpa_ie = wl_cfgp2p_find_wpaie(ptr, len)) != NULL) {
  10292. WL_DBG((" WPA found\n"));
  10293. ies->wpa_ie_len = ies->wpa_ie->length;
  10294. }
  10295. return err;
  10296. }
  10297. static s32
  10298. wl_cfg80211_set_ap_role(
  10299. struct bcm_cfg80211 *cfg,
  10300. struct net_device *dev)
  10301. {
  10302. s32 err = BCME_OK;
  10303. s32 infra = 1;
  10304. s32 ap = 0;
  10305. s32 pm;
  10306. s32 bssidx;
  10307. s32 apsta = 0;
  10308. if ((bssidx = wl_get_bssidx_by_wdev(cfg, dev->ieee80211_ptr)) < 0) {
  10309. WL_ERR(("Find p2p index from wdev(%p) failed\n", dev->ieee80211_ptr));
  10310. return -EINVAL;
  10311. }
  10312. WL_INFORM_MEM(("[%s] Bringup SoftAP on bssidx:%d \n", dev->name, bssidx));
  10313. if ((err = wl_cfg80211_add_del_bss(cfg, dev, bssidx,
  10314. WL_IF_TYPE_AP, 0, NULL)) < 0) {
  10315. WL_ERR(("wl add_del_bss returned error:%d\n", err));
  10316. return err;
  10317. }
  10318. /*
  10319. * For older chips, "bss" iovar does not support
  10320. * bsscfg role change/upgradation, and still
  10321. * return BCME_OK on attempt
  10322. * Hence, below traditional way to handle the same
  10323. */
  10324. if ((err = wldev_ioctl_get(dev,
  10325. WLC_GET_AP, &ap, sizeof(s32))) < 0) {
  10326. WL_ERR(("Getting AP mode failed %d \n", err));
  10327. return err;
  10328. }
  10329. if (!ap) {
  10330. /* AP mode switch not supported. Try setting up AP explicitly */
  10331. err = wldev_iovar_getint(dev, "apsta", (s32 *)&apsta);
  10332. if (unlikely(err)) {
  10333. WL_ERR(("Could not get apsta %d\n", err));
  10334. return err;
  10335. }
  10336. if (apsta == 0) {
  10337. /* If apsta is not set, set it */
  10338. /* Check for any connected interfaces before wl down */
  10339. if (wl_get_drv_status_all(cfg, CONNECTED) > 0) {
  10340. WL_ERR(("Concurrent i/f operational. can't do wl down"));
  10341. return BCME_ERROR;
  10342. }
  10343. err = wldev_ioctl_set(dev, WLC_DOWN, &ap, sizeof(s32));
  10344. if (err < 0) {
  10345. WL_ERR(("WLC_DOWN error %d\n", err));
  10346. return err;
  10347. }
  10348. err = wldev_iovar_setint(dev, "apsta", 1);
  10349. if (err < 0) {
  10350. WL_ERR(("wl apsta 0 error %d\n", err));
  10351. return err;
  10352. }
  10353. ap = 1;
  10354. if ((err = wldev_ioctl_set(dev,
  10355. WLC_SET_AP, &ap, sizeof(s32))) < 0) {
  10356. WL_ERR(("setting AP mode failed %d \n", err));
  10357. return err;
  10358. }
  10359. }
  10360. }
  10361. if (bssidx == 0) {
  10362. pm = 0;
  10363. if ((err = wldev_ioctl_set(dev, WLC_SET_PM, &pm, sizeof(pm))) != 0) {
  10364. WL_ERR(("wl PM 0 returned error:%d\n", err));
  10365. /* Ignore error, if any */
  10366. err = BCME_OK;
  10367. }
  10368. err = wldev_ioctl_set(dev, WLC_SET_INFRA, &infra, sizeof(s32));
  10369. if (err < 0) {
  10370. WL_ERR(("SET INFRA error %d\n", err));
  10371. return err;
  10372. }
  10373. }
  10374. /* On success, mark AP creation in progress. */
  10375. wl_set_drv_status(cfg, AP_CREATING, dev);
  10376. return 0;
  10377. }
  10378. /* In RSDB downgrade cases, the link up event can get delayed upto 7-8 secs */
  10379. #define MAX_AP_LINK_WAIT_TIME 10000
  10380. static s32
  10381. wl_cfg80211_bcn_bringup_ap(
  10382. struct net_device *dev,
  10383. struct parsed_ies *ies,
  10384. u32 dev_role, s32 bssidx)
  10385. {
  10386. struct bcm_cfg80211 *cfg = wl_get_cfg(dev);
  10387. struct wl_join_params join_params;
  10388. bool is_bssup = false;
  10389. s32 infra = 1;
  10390. s32 join_params_size = 0;
  10391. s32 wsec;
  10392. #ifdef DISABLE_11H_SOFTAP
  10393. s32 spect = 0;
  10394. #endif /* DISABLE_11H_SOFTAP */
  10395. #ifdef SOFTAP_UAPSD_OFF
  10396. uint32 wme_apsd = 0;
  10397. #endif /* SOFTAP_UAPSD_OFF */
  10398. s32 err = BCME_OK;
  10399. s32 is_rsdb_supported = BCME_ERROR;
  10400. long timeout;
  10401. dhd_pub_t *dhdp = (dhd_pub_t *)(cfg->pub);
  10402. #ifndef IGUANA_LEGACY_CHIPS
  10403. s32 ap = 1;
  10404. #endif // endif
  10405. is_rsdb_supported = DHD_OPMODE_SUPPORTED(cfg->pub, DHD_FLAG_RSDB_MODE);
  10406. if (is_rsdb_supported < 0)
  10407. return (-ENODEV);
  10408. WL_DBG(("Enter dev_role:%d bssidx:%d ifname:%s\n", dev_role, bssidx, dev->name));
  10409. /* Common code for SoftAP and P2P GO */
  10410. wl_clr_drv_status(cfg, AP_CREATED, dev);
  10411. /* Make sure INFRA is set for AP/GO */
  10412. err = wldev_ioctl_set(dev, WLC_SET_INFRA, &infra, sizeof(s32));
  10413. if (err < 0) {
  10414. WL_ERR(("SET INFRA error %d\n", err));
  10415. goto exit;
  10416. }
  10417. /* Do abort scan before creating GO */
  10418. wl_cfg80211_scan_abort(cfg);
  10419. if (dev_role == NL80211_IFTYPE_P2P_GO) {
  10420. is_bssup = wl_cfg80211_bss_isup(dev, bssidx);
  10421. if (!is_bssup && (ies->wpa2_ie != NULL)) {
  10422. err = wldev_iovar_setint_bsscfg(dev, "mpc", 0, bssidx);
  10423. if (err < 0) {
  10424. WL_ERR(("MPC setting failed, ret=%d\n", err));
  10425. goto exit;
  10426. }
  10427. err = wldev_iovar_setbuf_bsscfg(dev, "ssid", &cfg->p2p->ssid,
  10428. sizeof(cfg->p2p->ssid), cfg->ioctl_buf, WLC_IOCTL_MAXLEN,
  10429. bssidx, &cfg->ioctl_buf_sync);
  10430. if (err < 0) {
  10431. WL_ERR(("GO SSID setting error %d\n", err));
  10432. goto exit;
  10433. }
  10434. #ifdef MFP
  10435. err = wldev_iovar_setint_bsscfg(dev, "mfp", cfg->mfp_mode, bssidx);
  10436. if (err < 0) {
  10437. WL_ERR(("MFP Setting failed. ret = %d \n", err));
  10438. /* If fw doesn't support mfp, Ignore the error */
  10439. if (err != BCME_UNSUPPORTED) {
  10440. goto exit;
  10441. }
  10442. }
  10443. #endif /* MFP */
  10444. if ((err = wl_cfg80211_bss_up(cfg, dev, bssidx, 1)) < 0) {
  10445. WL_ERR(("GO Bring up error %d\n", err));
  10446. goto exit;
  10447. }
  10448. } else
  10449. WL_DBG(("Bss is already up\n"));
  10450. } else if (dev_role == NL80211_IFTYPE_AP) {
  10451. if (!wl_get_drv_status(cfg, AP_CREATING, dev)) {
  10452. /* Make sure fw is in proper state */
  10453. err = wl_cfg80211_set_ap_role(cfg, dev);
  10454. if (unlikely(err)) {
  10455. WL_ERR(("set ap role failed!\n"));
  10456. goto exit;
  10457. }
  10458. }
  10459. /* Device role SoftAP */
  10460. WL_DBG(("Creating AP bssidx:%d dev_role:%d\n", bssidx, dev_role));
  10461. /* Clear the status bit after use */
  10462. wl_clr_drv_status(cfg, AP_CREATING, dev);
  10463. #ifdef DISABLE_11H_SOFTAP
  10464. if (is_rsdb_supported == 0) {
  10465. err = wldev_ioctl_set(dev, WLC_DOWN, &ap, sizeof(s32));
  10466. if (err < 0) {
  10467. WL_ERR(("WLC_DOWN error %d\n", err));
  10468. goto exit;
  10469. }
  10470. }
  10471. err = wldev_ioctl_set(dev, WLC_SET_SPECT_MANAGMENT,
  10472. &spect, sizeof(s32));
  10473. if (err < 0) {
  10474. WL_ERR(("SET SPECT_MANAGMENT error %d\n", err));
  10475. goto exit;
  10476. }
  10477. #endif /* DISABLE_11H_SOFTAP */
  10478. #ifdef WL_DISABLE_HE_SOFTAP
  10479. err = wl_cfg80211_set_he_mode(dev, cfg, bssidx, WL_IF_TYPE_AP, FALSE);
  10480. if (err < 0) {
  10481. WL_ERR(("failed to set he features, error=%d\n", err));
  10482. }
  10483. #endif /* WL_DISABLE_HE_SOFTAP */
  10484. #ifdef SOFTAP_UAPSD_OFF
  10485. err = wldev_iovar_setbuf_bsscfg(dev, "wme_apsd", &wme_apsd, sizeof(wme_apsd),
  10486. cfg->ioctl_buf, WLC_IOCTL_SMLEN, bssidx, &cfg->ioctl_buf_sync);
  10487. if (err < 0) {
  10488. WL_ERR(("failed to disable uapsd, error=%d\n", err));
  10489. }
  10490. #endif /* SOFTAP_UAPSD_OFF */
  10491. #ifndef IGUANA_LEGACY_CHIPS
  10492. err = wldev_ioctl_set(dev, WLC_UP, &ap, sizeof(s32));
  10493. if (unlikely(err)) {
  10494. WL_ERR(("WLC_UP error (%d)\n", err));
  10495. goto exit;
  10496. }
  10497. #endif // endif
  10498. #ifdef MFP
  10499. if (cfg->bip_pos) {
  10500. err = wldev_iovar_setbuf_bsscfg(dev, "bip",
  10501. (const void *)(cfg->bip_pos), WPA_SUITE_LEN, cfg->ioctl_buf,
  10502. WLC_IOCTL_SMLEN, bssidx, &cfg->ioctl_buf_sync);
  10503. if (err < 0) {
  10504. WL_ERR(("bip set error %d\n", err));
  10505. #if defined(IGUANA_LEGACY_CHIPS)
  10506. if (wl_customer6_legacy_chip_check(cfg,
  10507. bcmcfg_to_prmry_ndev(cfg))) {
  10508. /* Ignore bip error: Some older firmwares doesn't
  10509. * support bip iovar/ return BCME_NOTUP while trying
  10510. * to set bip from AP bring up context. These firmares
  10511. * include bip in RSNIE by default. So its okay to ignore
  10512. * the error.
  10513. */
  10514. err = BCME_OK;
  10515. } else
  10516. #endif // endif
  10517. {
  10518. goto exit;
  10519. }
  10520. }
  10521. }
  10522. #endif /* MFP */
  10523. err = wldev_iovar_getint(dev, "wsec", (s32 *)&wsec);
  10524. if (unlikely(err)) {
  10525. WL_ERR(("Could not get wsec %d\n", err));
  10526. goto exit;
  10527. }
  10528. if ((wsec == WEP_ENABLED) && cfg->wep_key.len) {
  10529. WL_DBG(("Applying buffered WEP KEY \n"));
  10530. err = wldev_iovar_setbuf_bsscfg(dev, "wsec_key", &cfg->wep_key,
  10531. sizeof(struct wl_wsec_key), cfg->ioctl_buf,
  10532. WLC_IOCTL_MAXLEN, bssidx, &cfg->ioctl_buf_sync);
  10533. /* clear the key after use */
  10534. bzero(&cfg->wep_key, sizeof(struct wl_wsec_key));
  10535. if (unlikely(err)) {
  10536. WL_ERR(("WLC_SET_KEY error (%d)\n", err));
  10537. goto exit;
  10538. }
  10539. }
  10540. #ifdef MFP
  10541. /* This needs to go after wsec otherwise the wsec command will
  10542. * overwrite the values set by MFP
  10543. */
  10544. err = wldev_iovar_setint_bsscfg(dev, "mfp", cfg->mfp_mode, bssidx);
  10545. if (err < 0) {
  10546. WL_ERR(("MFP Setting failed. ret = %d \n", err));
  10547. /* If fw doesn't support mfp, Ignore the error */
  10548. if (err != BCME_UNSUPPORTED) {
  10549. goto exit;
  10550. }
  10551. }
  10552. #endif /* MFP */
  10553. bzero(&join_params, sizeof(join_params));
  10554. /* join parameters starts with ssid */
  10555. join_params_size = sizeof(join_params.ssid);
  10556. join_params.ssid.SSID_len = MIN(cfg->hostapd_ssid.SSID_len,
  10557. (uint32)DOT11_MAX_SSID_LEN);
  10558. memcpy(join_params.ssid.SSID, cfg->hostapd_ssid.SSID,
  10559. join_params.ssid.SSID_len);
  10560. join_params.ssid.SSID_len = htod32(join_params.ssid.SSID_len);
  10561. /* create softap */
  10562. if ((err = wldev_ioctl_set(dev, WLC_SET_SSID, &join_params,
  10563. join_params_size)) != 0) {
  10564. WL_ERR(("SoftAP/GO set ssid failed! \n"));
  10565. goto exit;
  10566. } else {
  10567. WL_DBG((" SoftAP SSID \"%s\" \n", join_params.ssid.SSID));
  10568. }
  10569. if ((err = wl_cfg80211_bss_up(cfg, dev, bssidx, 1)) < 0) {
  10570. WL_ERR(("AP Bring up error %d\n", err));
  10571. goto exit;
  10572. }
  10573. } else {
  10574. WL_ERR(("Wrong interface type %d\n", dev_role));
  10575. goto exit;
  10576. }
  10577. /* Wait for Linkup event to mark successful AP/GO bring up */
  10578. timeout = wait_event_interruptible_timeout(cfg->netif_change_event,
  10579. wl_get_drv_status(cfg, AP_CREATED, dev), msecs_to_jiffies(MAX_AP_LINK_WAIT_TIME));
  10580. if (timeout <= 0 || !wl_get_drv_status(cfg, AP_CREATED, dev)) {
  10581. WL_ERR(("Link up didn't come for AP interface. AP/GO creation failed! \n"));
  10582. if (timeout == -ERESTARTSYS) {
  10583. WL_ERR(("waitqueue was interrupted by a signal, returns -ERESTARTSYS\n"));
  10584. err = -ERESTARTSYS;
  10585. goto exit;
  10586. }
  10587. if (dhd_query_bus_erros(dhdp)) {
  10588. err = -ENODEV;
  10589. goto exit;
  10590. }
  10591. dhdp->iface_op_failed = TRUE;
  10592. #if defined(DHD_DEBUG) && defined(DHD_FW_COREDUMP)
  10593. if (dhdp->memdump_enabled) {
  10594. dhdp->memdump_type = DUMP_TYPE_AP_LINKUP_FAILURE;
  10595. dhd_bus_mem_dump(dhdp);
  10596. }
  10597. #endif /* DHD_DEBUG && DHD_FW_COREDUMP */
  10598. err = -ENODEV;
  10599. goto exit;
  10600. }
  10601. SUPP_LOG(("AP/GO Link up\n"));
  10602. exit:
  10603. if (cfg->wep_key.len) {
  10604. bzero(&cfg->wep_key, sizeof(struct wl_wsec_key));
  10605. }
  10606. #ifdef MFP
  10607. if (cfg->mfp_mode) {
  10608. cfg->mfp_mode = 0;
  10609. }
  10610. if (cfg->bip_pos) {
  10611. cfg->bip_pos = NULL;
  10612. }
  10613. #endif /* MFP */
  10614. if (err) {
  10615. SUPP_LOG(("AP/GO bring up fail. err:%d\n", err));
  10616. }
  10617. return err;
  10618. }
  10619. #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)) || defined(WL_COMPAT_WIRELESS)
  10620. s32
  10621. wl_cfg80211_parse_ap_ies(
  10622. struct net_device *dev,
  10623. struct cfg80211_beacon_data *info,
  10624. struct parsed_ies *ies)
  10625. {
  10626. struct parsed_ies prb_ies;
  10627. struct bcm_cfg80211 *cfg = wl_get_cfg(dev);
  10628. dhd_pub_t *dhd = (dhd_pub_t *)(cfg->pub);
  10629. const u8 *vndr = NULL;
  10630. u32 vndr_ie_len = 0;
  10631. s32 err = BCME_OK;
  10632. /* Parse Beacon IEs */
  10633. if (wl_cfg80211_parse_ies((const u8 *)info->tail,
  10634. info->tail_len, ies) < 0) {
  10635. WL_ERR(("Beacon get IEs failed \n"));
  10636. err = -EINVAL;
  10637. goto fail;
  10638. }
  10639. vndr = (const u8 *)info->proberesp_ies;
  10640. vndr_ie_len = (uint32)info->proberesp_ies_len;
  10641. if (dhd->op_mode & DHD_FLAG_HOSTAP_MODE) {
  10642. /* SoftAP mode */
  10643. const struct ieee80211_mgmt *mgmt;
  10644. mgmt = (const struct ieee80211_mgmt *)info->probe_resp;
  10645. if (mgmt != NULL) {
  10646. vndr = (const u8 *)&mgmt->u.probe_resp.variable;
  10647. vndr_ie_len = (uint32)(info->probe_resp_len -
  10648. offsetof(const struct ieee80211_mgmt, u.probe_resp.variable));
  10649. }
  10650. }
  10651. /* Parse Probe Response IEs */
  10652. if (wl_cfg80211_parse_ies((const u8 *)vndr, vndr_ie_len, &prb_ies) < 0) {
  10653. WL_ERR(("PROBE RESP get IEs failed \n"));
  10654. err = -EINVAL;
  10655. }
  10656. fail:
  10657. return err;
  10658. }
  10659. s32
  10660. wl_cfg80211_set_ies(
  10661. struct net_device *dev,
  10662. struct cfg80211_beacon_data *info,
  10663. s32 bssidx)
  10664. {
  10665. struct bcm_cfg80211 *cfg = wl_get_cfg(dev);
  10666. dhd_pub_t *dhd = (dhd_pub_t *)(cfg->pub);
  10667. const u8 *vndr = NULL;
  10668. u32 vndr_ie_len = 0;
  10669. s32 err = BCME_OK;
  10670. /* Set Beacon IEs to FW */
  10671. if ((err = wl_cfg80211_set_mgmt_vndr_ies(cfg, ndev_to_cfgdev(dev), bssidx,
  10672. VNDR_IE_BEACON_FLAG, (const u8 *)info->tail,
  10673. info->tail_len)) < 0) {
  10674. WL_ERR(("Set Beacon IE Failed \n"));
  10675. } else {
  10676. WL_DBG(("Applied Vndr IEs for Beacon \n"));
  10677. }
  10678. vndr = (const u8 *)info->proberesp_ies;
  10679. vndr_ie_len = (uint32)info->proberesp_ies_len;
  10680. if (dhd->op_mode & DHD_FLAG_HOSTAP_MODE) {
  10681. /* SoftAP mode */
  10682. const struct ieee80211_mgmt *mgmt;
  10683. mgmt = (const struct ieee80211_mgmt *)info->probe_resp;
  10684. if (mgmt != NULL) {
  10685. vndr = (const u8 *)&mgmt->u.probe_resp.variable;
  10686. vndr_ie_len = (uint32)(info->probe_resp_len -
  10687. offsetof(struct ieee80211_mgmt, u.probe_resp.variable));
  10688. }
  10689. }
  10690. /* Set Probe Response IEs to FW */
  10691. if ((err = wl_cfg80211_set_mgmt_vndr_ies(cfg, ndev_to_cfgdev(dev), bssidx,
  10692. VNDR_IE_PRBRSP_FLAG, vndr, vndr_ie_len)) < 0) {
  10693. WL_ERR(("Set Probe Resp Vndr IE Failed \n"));
  10694. } else {
  10695. WL_DBG(("Applied Vndr IEs for Probe Resp \n"));
  10696. }
  10697. /* Set Assoc Response IEs to FW */
  10698. vndr = (const u8 *)info->assocresp_ies;
  10699. vndr_ie_len = (uint32)info->assocresp_ies_len;
  10700. if ((err = wl_cfg80211_set_mgmt_vndr_ies(cfg, ndev_to_cfgdev(dev), bssidx,
  10701. VNDR_IE_ASSOCRSP_FLAG, vndr, vndr_ie_len)) < 0) {
  10702. WL_ERR(("Set Assoc Resp Vndr IE Failed \n"));
  10703. } else {
  10704. WL_DBG(("Applied Vndr IEs for Assoc Resp \n"));
  10705. }
  10706. return err;
  10707. }
  10708. #endif /* LINUX_VERSION >= VERSION(3,4,0) || WL_COMPAT_WIRELESS */
  10709. static s32 wl_cfg80211_hostapd_sec(
  10710. struct net_device *dev,
  10711. struct parsed_ies *ies,
  10712. s32 bssidx)
  10713. {
  10714. bool update_bss = 0;
  10715. struct bcm_cfg80211 *cfg = wl_get_cfg(dev);
  10716. wl_cfgbss_t *bss = wl_get_cfgbss_by_wdev(cfg, dev->ieee80211_ptr);
  10717. if (!bss) {
  10718. WL_ERR(("cfgbss is NULL \n"));
  10719. return -EINVAL;
  10720. }
  10721. if (ies->wps_ie) {
  10722. if (bss->wps_ie &&
  10723. memcmp(bss->wps_ie, ies->wps_ie, ies->wps_ie_len)) {
  10724. WL_DBG((" WPS IE is changed\n"));
  10725. MFREE(cfg->osh, bss->wps_ie, bss->wps_ie[1] + 2);
  10726. bss->wps_ie = MALLOCZ(cfg->osh, ies->wps_ie_len);
  10727. if (bss->wps_ie) {
  10728. memcpy(bss->wps_ie, ies->wps_ie, ies->wps_ie_len);
  10729. }
  10730. } else if (bss->wps_ie == NULL) {
  10731. WL_DBG((" WPS IE is added\n"));
  10732. bss->wps_ie = MALLOCZ(cfg->osh, ies->wps_ie_len);
  10733. if (bss->wps_ie) {
  10734. memcpy(bss->wps_ie, ies->wps_ie, ies->wps_ie_len);
  10735. }
  10736. }
  10737. #if defined(SUPPORT_SOFTAP_WPAWPA2_MIXED)
  10738. if (ies->wpa_ie != NULL && ies->wpa2_ie != NULL) {
  10739. WL_ERR(("update bss - wpa_ie and wpa2_ie is not null\n"));
  10740. if (!bss->security_mode) {
  10741. /* change from open mode to security mode */
  10742. update_bss = true;
  10743. bss->wpa_ie = MALLOCZ(cfg->osh,
  10744. ies->wpa_ie->length + WPA_RSN_IE_TAG_FIXED_LEN);
  10745. if (bss->wpa_ie) {
  10746. memcpy(bss->wpa_ie, ies->wpa_ie,
  10747. ies->wpa_ie->length + WPA_RSN_IE_TAG_FIXED_LEN);
  10748. }
  10749. bss->rsn_ie = MALLOCZ(cfg->osh,
  10750. ies->wpa2_ie->len + WPA_RSN_IE_TAG_FIXED_LEN);
  10751. if (bss->rsn_ie) {
  10752. memcpy(bss->rsn_ie, ies->wpa2_ie,
  10753. ies->wpa2_ie->len + WPA_RSN_IE_TAG_FIXED_LEN);
  10754. }
  10755. } else {
  10756. /* change from (WPA or WPA2 or WPA/WPA2) to WPA/WPA2 mixed mode */
  10757. if (bss->wpa_ie) {
  10758. if (memcmp(bss->wpa_ie,
  10759. ies->wpa_ie, ies->wpa_ie->length +
  10760. WPA_RSN_IE_TAG_FIXED_LEN)) {
  10761. MFREE(cfg->osh, bss->wpa_ie,
  10762. bss->wpa_ie[1] + WPA_RSN_IE_TAG_FIXED_LEN);
  10763. update_bss = true;
  10764. bss->wpa_ie = MALLOCZ(cfg->osh,
  10765. ies->wpa_ie->length
  10766. + WPA_RSN_IE_TAG_FIXED_LEN);
  10767. if (bss->wpa_ie) {
  10768. memcpy(bss->wpa_ie, ies->wpa_ie,
  10769. ies->wpa_ie->length
  10770. + WPA_RSN_IE_TAG_FIXED_LEN);
  10771. }
  10772. }
  10773. }
  10774. else {
  10775. update_bss = true;
  10776. bss->wpa_ie = MALLOCZ(cfg->osh,
  10777. ies->wpa_ie->length + WPA_RSN_IE_TAG_FIXED_LEN);
  10778. if (bss->wpa_ie) {
  10779. memcpy(bss->wpa_ie, ies->wpa_ie,
  10780. ies->wpa_ie->length
  10781. + WPA_RSN_IE_TAG_FIXED_LEN);
  10782. }
  10783. }
  10784. if (bss->rsn_ie) {
  10785. if (memcmp(bss->rsn_ie,
  10786. ies->wpa2_ie,
  10787. ies->wpa2_ie->len + WPA_RSN_IE_TAG_FIXED_LEN)) {
  10788. update_bss = true;
  10789. MFREE(cfg->osh, bss->rsn_ie,
  10790. bss->rsn_ie[1] + WPA_RSN_IE_TAG_FIXED_LEN);
  10791. bss->rsn_ie = MALLOCZ(cfg->osh,
  10792. ies->wpa2_ie->len
  10793. + WPA_RSN_IE_TAG_FIXED_LEN);
  10794. if (bss->rsn_ie) {
  10795. memcpy(bss->rsn_ie, ies->wpa2_ie,
  10796. ies->wpa2_ie->len
  10797. + WPA_RSN_IE_TAG_FIXED_LEN);
  10798. }
  10799. }
  10800. }
  10801. else {
  10802. update_bss = true;
  10803. bss->rsn_ie = MALLOCZ(cfg->osh,
  10804. ies->wpa2_ie->len
  10805. + WPA_RSN_IE_TAG_FIXED_LEN);
  10806. if (bss->rsn_ie) {
  10807. memcpy(bss->rsn_ie, ies->wpa2_ie,
  10808. ies->wpa2_ie->len
  10809. + WPA_RSN_IE_TAG_FIXED_LEN);
  10810. }
  10811. }
  10812. }
  10813. WL_ERR(("update_bss=%d\n", update_bss));
  10814. if (update_bss) {
  10815. bss->security_mode = true;
  10816. wl_cfg80211_bss_up(cfg, dev, bssidx, 0);
  10817. if (wl_validate_wpaie_wpa2ie(dev, ies->wpa_ie,
  10818. ies->wpa2_ie, bssidx) < 0) {
  10819. return BCME_ERROR;
  10820. }
  10821. wl_cfg80211_bss_up(cfg, dev, bssidx, 1);
  10822. }
  10823. }
  10824. else
  10825. #endif /* SUPPORT_SOFTAP_WPAWPA2_MIXED */
  10826. if ((ies->wpa_ie != NULL || ies->wpa2_ie != NULL)) {
  10827. if (!bss->security_mode) {
  10828. /* change from open mode to security mode */
  10829. update_bss = true;
  10830. if (ies->wpa_ie != NULL) {
  10831. bss->wpa_ie = MALLOCZ(cfg->osh,
  10832. ies->wpa_ie->length + WPA_RSN_IE_TAG_FIXED_LEN);
  10833. if (bss->wpa_ie) {
  10834. memcpy(bss->wpa_ie,
  10835. ies->wpa_ie,
  10836. ies->wpa_ie->length
  10837. + WPA_RSN_IE_TAG_FIXED_LEN);
  10838. }
  10839. } else {
  10840. bss->rsn_ie = MALLOCZ(cfg->osh,
  10841. ies->wpa2_ie->len + WPA_RSN_IE_TAG_FIXED_LEN);
  10842. if (bss->rsn_ie) {
  10843. memcpy(bss->rsn_ie,
  10844. ies->wpa2_ie,
  10845. ies->wpa2_ie->len
  10846. + WPA_RSN_IE_TAG_FIXED_LEN);
  10847. }
  10848. }
  10849. } else if (bss->wpa_ie) {
  10850. /* change from WPA2 mode to WPA mode */
  10851. if (ies->wpa_ie != NULL) {
  10852. update_bss = true;
  10853. MFREE(cfg->osh, bss->rsn_ie,
  10854. bss->rsn_ie[1] + WPA_RSN_IE_TAG_FIXED_LEN);
  10855. bss->wpa_ie = MALLOCZ(cfg->osh,
  10856. ies->wpa_ie->length + WPA_RSN_IE_TAG_FIXED_LEN);
  10857. if (bss->wpa_ie) {
  10858. memcpy(bss->wpa_ie,
  10859. ies->wpa_ie,
  10860. ies->wpa_ie->length
  10861. + WPA_RSN_IE_TAG_FIXED_LEN);
  10862. }
  10863. } else if (memcmp(bss->rsn_ie,
  10864. ies->wpa2_ie, ies->wpa2_ie->len
  10865. + WPA_RSN_IE_TAG_FIXED_LEN)) {
  10866. update_bss = true;
  10867. MFREE(cfg->osh, bss->rsn_ie,
  10868. bss->rsn_ie[1] + WPA_RSN_IE_TAG_FIXED_LEN);
  10869. bss->rsn_ie = MALLOCZ(cfg->osh,
  10870. ies->wpa2_ie->len + WPA_RSN_IE_TAG_FIXED_LEN);
  10871. if (bss->rsn_ie) {
  10872. memcpy(bss->rsn_ie,
  10873. ies->wpa2_ie,
  10874. ies->wpa2_ie->len
  10875. + WPA_RSN_IE_TAG_FIXED_LEN);
  10876. }
  10877. bss->wpa_ie = NULL;
  10878. }
  10879. }
  10880. if (update_bss) {
  10881. bss->security_mode = true;
  10882. wl_cfg80211_bss_up(cfg, dev, bssidx, 0);
  10883. if (wl_validate_wpa2ie(dev, ies->wpa2_ie, bssidx) < 0 ||
  10884. wl_validate_wpaie(dev, ies->wpa_ie, bssidx) < 0) {
  10885. return BCME_ERROR;
  10886. }
  10887. wl_cfg80211_bss_up(cfg, dev, bssidx, 1);
  10888. }
  10889. }
  10890. } else {
  10891. WL_ERR(("No WPSIE in beacon \n"));
  10892. }
  10893. return 0;
  10894. }
  10895. #if defined(WL_SUPPORT_BACKPORTED_KPATCHES) || (LINUX_VERSION_CODE >= KERNEL_VERSION(3, \
  10896. 2, 0))
  10897. #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 19, 0))
  10898. static s32
  10899. wl_cfg80211_del_station(
  10900. struct wiphy *wiphy, struct net_device *ndev,
  10901. struct station_del_parameters *params)
  10902. #elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
  10903. static s32
  10904. wl_cfg80211_del_station(
  10905. struct wiphy *wiphy,
  10906. struct net_device *ndev,
  10907. const u8* mac_addr)
  10908. #else
  10909. static s32
  10910. wl_cfg80211_del_station(
  10911. struct wiphy *wiphy,
  10912. struct net_device *ndev,
  10913. u8* mac_addr)
  10914. #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 19, 0)) */
  10915. {
  10916. struct net_device *dev;
  10917. struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
  10918. scb_val_t scb_val;
  10919. s8 eabuf[ETHER_ADDR_STR_LEN];
  10920. int err;
  10921. char mac_buf[MAX_NUM_OF_ASSOCIATED_DEV *
  10922. sizeof(struct ether_addr) + sizeof(uint)] = {0};
  10923. struct maclist *assoc_maclist = (struct maclist *)mac_buf;
  10924. int num_associated = 0;
  10925. #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 19, 0))
  10926. const u8 *mac_addr = params->mac;
  10927. #ifdef CUSTOM_BLOCK_DEAUTH_AT_EAP_FAILURE
  10928. u16 rc = params->reason_code;
  10929. #endif /* CUSTOM_BLOCK_DEAUTH_AT_EAP_FAILURE */
  10930. #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 19, 0)) */
  10931. WL_DBG(("Entry\n"));
  10932. if (mac_addr == NULL) {
  10933. WL_DBG(("mac_addr is NULL ignore it\n"));
  10934. return 0;
  10935. }
  10936. dev = ndev_to_wlc_ndev(ndev, cfg);
  10937. if (p2p_is_on(cfg)) {
  10938. /* Suspend P2P discovery search-listen to prevent it from changing the
  10939. * channel.
  10940. */
  10941. if ((wl_cfgp2p_discover_enable_search(cfg, false)) < 0) {
  10942. WL_ERR(("Can not disable discovery mode\n"));
  10943. return -EFAULT;
  10944. }
  10945. }
  10946. assoc_maclist->count = MAX_NUM_OF_ASSOCIATED_DEV;
  10947. err = wldev_ioctl_get(ndev, WLC_GET_ASSOCLIST,
  10948. assoc_maclist, sizeof(mac_buf));
  10949. if (err < 0)
  10950. WL_ERR(("WLC_GET_ASSOCLIST error %d\n", err));
  10951. else
  10952. num_associated = assoc_maclist->count;
  10953. memcpy(scb_val.ea.octet, mac_addr, ETHER_ADDR_LEN);
  10954. #ifdef CUSTOM_BLOCK_DEAUTH_AT_EAP_FAILURE
  10955. #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 19, 0))
  10956. if (rc == DOT11_RC_8021X_AUTH_FAIL) {
  10957. WL_ERR(("deauth will be sent at F/W\n"));
  10958. scb_val.val = DOT11_RC_8021X_AUTH_FAIL;
  10959. } else {
  10960. #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 19, 0)) */
  10961. #endif /* CUSTOM_BLOCK_DEAUTH_AT_EAP_FAILURE */
  10962. #ifdef WL_WPS_SYNC
  10963. if (wl_wps_session_update(ndev,
  10964. WPS_STATE_DISCONNECT_CLIENT, mac_addr) == BCME_UNSUPPORTED) {
  10965. /* Ignore disconnect command from upper layer */
  10966. WL_INFORM_MEM(("[WPS] Ignore client disconnect.\n"));
  10967. } else
  10968. #endif /* WL_WPS_SYNC */
  10969. {
  10970. /* need to guarantee EAP-Failure send out before deauth */
  10971. dhd_wait_pend8021x(dev);
  10972. #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 19, 0))
  10973. scb_val.val = cpu_to_le32(params->reason_code);
  10974. #else
  10975. scb_val.val = DOT11_RC_DEAUTH_LEAVING;
  10976. #endif // endif
  10977. err = wldev_ioctl_set(dev, WLC_SCB_DEAUTHENTICATE_FOR_REASON, &scb_val,
  10978. sizeof(scb_val_t));
  10979. if (err < 0) {
  10980. WL_ERR(("WLC_SCB_DEAUTHENTICATE_FOR_REASON err %d\n", err));
  10981. }
  10982. WL_INFORM_MEM(("Disconnect STA : " MACDBG " scb_val.val %d\n",
  10983. MAC2STRDBG(bcm_ether_ntoa((const struct ether_addr *)mac_addr,
  10984. eabuf)), scb_val.val));
  10985. }
  10986. #ifdef CUSTOM_BLOCK_DEAUTH_AT_EAP_FAILURE
  10987. #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 19, 0))
  10988. }
  10989. #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 19, 0)) */
  10990. #endif /* CUSTOM_BLOCK_DEAUTH_AT_EAP_FAILURE */
  10991. if (num_associated > 0 && ETHER_ISBCAST(mac_addr))
  10992. wl_delay(400);
  10993. return 0;
  10994. }
  10995. #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
  10996. static s32
  10997. wl_cfg80211_change_station(
  10998. struct wiphy *wiphy,
  10999. struct net_device *dev,
  11000. const u8 *mac,
  11001. struct station_parameters *params)
  11002. #else
  11003. static s32
  11004. wl_cfg80211_change_station(
  11005. struct wiphy *wiphy,
  11006. struct net_device *dev,
  11007. u8 *mac,
  11008. struct station_parameters *params)
  11009. #endif // endif
  11010. {
  11011. int err = BCME_OK;
  11012. struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
  11013. #ifdef WBTEXT
  11014. dhd_pub_t *dhdp = (dhd_pub_t *)(cfg->pub);
  11015. #endif /* WBTEXT */
  11016. WL_DBG(("SCB_AUTHORIZE mac_addr:"MACDBG" sta_flags_mask:0x%x "
  11017. "sta_flags_set:0x%x iface:%s \n", MAC2STRDBG(mac),
  11018. params->sta_flags_mask, params->sta_flags_set, dev->name));
  11019. if ((wl_get_mode_by_netdev(cfg, dev) == WL_MODE_BSS) &&
  11020. !(wl_get_drv_status(cfg, CONNECTED, dev))) {
  11021. /* Return error indicating not in connected state */
  11022. WL_ERR(("Ignore SCB_AUTHORIZE/DEAUTHORIZE in non connected state\n"));
  11023. return -ENOTSUPP;
  11024. }
  11025. /* Processing only authorize/de-authorize flag for now */
  11026. if (!(params->sta_flags_mask & BIT(NL80211_STA_FLAG_AUTHORIZED))) {
  11027. WL_ERR(("WLC_SCB_AUTHORIZE sta_flags_mask not set \n"));
  11028. return -ENOTSUPP;
  11029. }
  11030. if (!(params->sta_flags_set & BIT(NL80211_STA_FLAG_AUTHORIZED))) {
  11031. err = wldev_ioctl_set(dev, WLC_SCB_DEAUTHORIZE, mac, ETH_ALEN);
  11032. if (unlikely(err)) {
  11033. WL_ERR(("WLC_SCB_DEAUTHORIZE error (%d)\n", err));
  11034. } else {
  11035. WL_INFORM_MEM(("[%s] WLC_SCB_DEAUTHORIZE " MACDBG "\n",
  11036. dev->name, MAC2STRDBG(mac)));
  11037. }
  11038. return err;
  11039. }
  11040. err = wldev_ioctl_set(dev, WLC_SCB_AUTHORIZE, mac, ETH_ALEN);
  11041. if (unlikely(err)) {
  11042. WL_ERR(("WLC_SCB_AUTHORIZE error (%d)\n", err));
  11043. } else {
  11044. WL_INFORM_MEM(("[%s] WLC_SCB_AUTHORIZE " MACDBG "\n",
  11045. dev->name, MAC2STRDBG(mac)));
  11046. #ifdef WL_WPS_SYNC
  11047. wl_wps_session_update(dev, WPS_STATE_AUTHORIZE, mac);
  11048. #endif /* WL_WPS_SYNC */
  11049. }
  11050. #ifdef DHD_LOSSLESS_ROAMING
  11051. wl_del_roam_timeout(cfg);
  11052. #endif // endif
  11053. #ifdef WBTEXT
  11054. /* send nbr request or BTM query to update RCC
  11055. * after 4-way handshake is completed
  11056. */
  11057. if (dev->ieee80211_ptr->iftype == NL80211_IFTYPE_STATION &&
  11058. dhdp->wbtext_support) {
  11059. wl_cfg80211_wbtext_update_rcc(cfg, dev);
  11060. }
  11061. #endif /* WBTEXT */
  11062. return err;
  11063. }
  11064. #endif /* WL_SUPPORT_BACKPORTED_KPATCHES || KERNEL_VER >= KERNEL_VERSION(3, 2, 0)) */
  11065. static s32
  11066. wl_cfg80211_set_scb_timings(
  11067. struct bcm_cfg80211 *cfg,
  11068. struct net_device *dev)
  11069. {
  11070. int err;
  11071. u32 ps_pretend;
  11072. wl_scb_probe_t scb_probe;
  11073. u32 ps_pretend_retries;
  11074. bzero(&scb_probe, sizeof(wl_scb_probe_t));
  11075. scb_probe.scb_timeout = WL_SCB_TIMEOUT;
  11076. scb_probe.scb_activity_time = WL_SCB_ACTIVITY_TIME;
  11077. scb_probe.scb_max_probe = WL_SCB_MAX_PROBE;
  11078. err = wldev_iovar_setbuf(dev, "scb_probe", (void *)&scb_probe,
  11079. sizeof(wl_scb_probe_t), cfg->ioctl_buf, WLC_IOCTL_SMLEN,
  11080. &cfg->ioctl_buf_sync);
  11081. if (unlikely(err)) {
  11082. WL_ERR(("set 'scb_probe' failed, error = %d\n", err));
  11083. return err;
  11084. }
  11085. ps_pretend_retries = WL_PSPRETEND_RETRY_LIMIT;
  11086. err = wldev_iovar_setint(dev, "pspretend_retry_limit", ps_pretend_retries);
  11087. if (unlikely(err)) {
  11088. if (err == BCME_UNSUPPORTED) {
  11089. /* Ignore error if fw doesn't support the iovar */
  11090. WL_DBG(("set 'pspretend_retry_limit %d' failed, error = %d\n",
  11091. ps_pretend_retries, err));
  11092. } else {
  11093. WL_ERR(("set 'pspretend_retry_limit %d' failed, error = %d\n",
  11094. ps_pretend_retries, err));
  11095. return err;
  11096. }
  11097. }
  11098. ps_pretend = MAX(WL_SCB_MAX_PROBE / 2, WL_MIN_PSPRETEND_THRESHOLD);
  11099. err = wldev_iovar_setint(dev, "pspretend_threshold", ps_pretend);
  11100. if (unlikely(err)) {
  11101. if (err == BCME_UNSUPPORTED) {
  11102. /* Ignore error if fw doesn't support the iovar */
  11103. WL_DBG(("wl pspretend_threshold %d set error %d\n",
  11104. ps_pretend, err));
  11105. } else {
  11106. WL_ERR(("wl pspretend_threshold %d set error %d\n",
  11107. ps_pretend, err));
  11108. return err;
  11109. }
  11110. }
  11111. return 0;
  11112. }
  11113. #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)) || defined(WL_COMPAT_WIRELESS)
  11114. static s32
  11115. wl_cfg80211_start_ap(
  11116. struct wiphy *wiphy,
  11117. struct net_device *dev,
  11118. struct cfg80211_ap_settings *info)
  11119. {
  11120. struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
  11121. s32 err = BCME_OK;
  11122. struct parsed_ies ies;
  11123. s32 bssidx = 0;
  11124. u32 dev_role = 0;
  11125. dhd_pub_t *dhd = (dhd_pub_t *)(cfg->pub);
  11126. #ifdef WL11U
  11127. bcm_tlv_t *interworking_ie;
  11128. u32 iw_ie_len = 0;
  11129. u8 iw_ie[IW_IES_MAX_BUF_LEN];
  11130. #endif // endif
  11131. WL_DBG(("Enter \n"));
  11132. #if defined(SUPPORT_RANDOM_MAC_SCAN)
  11133. /* Disable scanmac if enabled */
  11134. if (cfg->scanmac_enabled) {
  11135. wl_cfg80211_scan_mac_disable(dev);
  11136. }
  11137. #endif /* SUPPORT_RANDOM_MAC_SCAN */
  11138. if ((bssidx = wl_get_bssidx_by_wdev(cfg, dev->ieee80211_ptr)) < 0) {
  11139. WL_ERR(("Find p2p index from wdev(%p) failed\n", dev->ieee80211_ptr));
  11140. return BCME_ERROR;
  11141. }
  11142. if (p2p_is_on(cfg) && (dev->ieee80211_ptr->iftype == NL80211_IFTYPE_P2P_GO)) {
  11143. dev_role = NL80211_IFTYPE_P2P_GO;
  11144. } else if (dev->ieee80211_ptr->iftype == NL80211_IFTYPE_AP) {
  11145. dev_role = NL80211_IFTYPE_AP;
  11146. dhd->op_mode |= DHD_FLAG_HOSTAP_MODE;
  11147. err = dhd_ndo_enable(dhd, FALSE);
  11148. WL_DBG(("Disabling NDO on Hostapd mode %d\n", err));
  11149. if (err) {
  11150. WL_ERR(("Disabling NDO Failed %d\n", err));
  11151. }
  11152. #ifdef PKT_FILTER_SUPPORT
  11153. /* Disable packet filter */
  11154. if (dhd->early_suspended) {
  11155. WL_ERR(("Disable pkt_filter\n"));
  11156. dhd_enable_packet_filter(0, dhd);
  11157. }
  11158. #endif /* PKT_FILTER_SUPPORT */
  11159. #ifdef ARP_OFFLOAD_SUPPORT
  11160. /* IF SoftAP is enabled, disable arpoe */
  11161. if (dhd->op_mode & DHD_FLAG_STA_MODE) {
  11162. dhd_arp_offload_set(dhd, 0);
  11163. dhd_arp_offload_enable(dhd, FALSE);
  11164. }
  11165. #endif /* ARP_OFFLOAD_SUPPORT */
  11166. } else {
  11167. /* only AP or GO role need to be handled here. */
  11168. err = -EINVAL;
  11169. goto fail;
  11170. }
  11171. /* disable TDLS */
  11172. #ifdef WLTDLS
  11173. if (bssidx == 0) {
  11174. /* Disable TDLS for primary Iface. For virtual interface,
  11175. * tdls disable will happen from interface create context
  11176. */
  11177. wl_cfg80211_tdls_config(cfg, TDLS_STATE_AP_CREATE, false);
  11178. }
  11179. #endif /* WLTDLS */
  11180. if (!check_dev_role_integrity(cfg, wl_get_mode_by_netdev(cfg, dev), dev_role)) {
  11181. err = -EINVAL;
  11182. goto fail;
  11183. }
  11184. #if ((LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0)) && !defined(WL_COMPAT_WIRELESS))
  11185. if ((err = wl_cfg80211_set_channel(wiphy, dev,
  11186. dev->ieee80211_ptr->preset_chandef.chan,
  11187. NL80211_CHAN_HT20) < 0)) {
  11188. WL_ERR(("Set channel failed \n"));
  11189. goto fail;
  11190. }
  11191. #endif /* ((LINUX_VERSION >= VERSION(3, 6, 0) && !WL_COMPAT_WIRELESS) */
  11192. if ((err = wl_cfg80211_bcn_set_params(info, dev,
  11193. dev_role, bssidx)) < 0) {
  11194. WL_ERR(("Beacon params set failed \n"));
  11195. goto fail;
  11196. }
  11197. /* Parse IEs */
  11198. if ((err = wl_cfg80211_parse_ap_ies(dev, &info->beacon, &ies)) < 0) {
  11199. WL_ERR(("Set IEs failed \n"));
  11200. goto fail;
  11201. }
  11202. if ((err = wl_cfg80211_bcn_validate_sec(dev, &ies,
  11203. dev_role, bssidx, info->privacy)) < 0)
  11204. {
  11205. WL_ERR(("Beacon set security failed \n"));
  11206. goto fail;
  11207. }
  11208. if ((err = wl_cfg80211_bcn_bringup_ap(dev, &ies,
  11209. dev_role, bssidx)) < 0) {
  11210. WL_ERR(("Beacon bring up AP/GO failed \n"));
  11211. goto fail;
  11212. }
  11213. #ifdef BCMSDIO
  11214. if (dev_role == NL80211_IFTYPE_AP) {
  11215. dhd_set_role(dhd, WLC_E_IF_ROLE_AP, bssidx);
  11216. } else if (dev_role == NL80211_IFTYPE_P2P_GO) {
  11217. dhd_set_role(dhd, WLC_E_IF_ROLE_P2P_GO, bssidx);
  11218. }
  11219. #endif /* BCMSDIO */
  11220. /* Set GC/STA SCB expiry timings. */
  11221. if ((err = wl_cfg80211_set_scb_timings(cfg, dev))) {
  11222. WL_ERR(("scb setting failed \n"));
  11223. goto fail;
  11224. }
  11225. wl_set_drv_status(cfg, CONNECTED, dev);
  11226. WL_DBG(("** AP/GO Created **\n"));
  11227. #ifdef WL_CFG80211_ACL
  11228. /* Enfoce Admission Control. */
  11229. if ((err = wl_cfg80211_set_mac_acl(wiphy, dev, info->acl)) < 0) {
  11230. WL_ERR(("Set ACL failed\n"));
  11231. }
  11232. #endif /* WL_CFG80211_ACL */
  11233. #ifdef WL11U
  11234. wl_get_iwdata_by_netdev(cfg, dev, iw_ie, &iw_ie_len);
  11235. /* Add interworking IE from beacon data */
  11236. if ((interworking_ie = wl_cfg80211_find_interworking_ie(
  11237. info->beacon.beacon_ies, info->beacon.beacon_ies_len)) != NULL) {
  11238. err = wl_cfg80211_add_iw_ie(cfg, dev, bssidx,
  11239. VNDR_IE_CUSTOM_FLAG, interworking_ie->id,
  11240. interworking_ie->data, interworking_ie->len);
  11241. if (unlikely(err)) {
  11242. WL_ERR(("Failed to add interworking IE"));
  11243. }
  11244. } else if (iw_ie_len != 0) {
  11245. /* we have to clear IW IE and disable gratuitous APR */
  11246. wl_cfg80211_clear_iw_ie(cfg, dev, bssidx);
  11247. (void)wldev_iovar_setint_bsscfg(dev, "grat_arp", 0,
  11248. bssidx);
  11249. wl_clear_iwdata_by_netdev(cfg, dev);
  11250. /* we don't care about error */
  11251. cfg->wl11u = FALSE;
  11252. }
  11253. #endif /* WL11U */
  11254. /* Set IEs to FW */
  11255. if ((err = wl_cfg80211_set_ies(dev, &info->beacon, bssidx)) < 0)
  11256. WL_ERR(("Set IEs failed \n"));
  11257. /* Enable Probe Req filter, WPS-AP certification 4.2.13 */
  11258. if ((dev_role == NL80211_IFTYPE_AP) && (ies.wps_ie != NULL)) {
  11259. bool pbc = 0;
  11260. wl_validate_wps_ie((const char *) ies.wps_ie, ies.wps_ie_len, &pbc);
  11261. if (pbc) {
  11262. WL_DBG(("set WLC_E_PROBREQ_MSG\n"));
  11263. wl_add_remove_eventmsg(dev, WLC_E_PROBREQ_MSG, true);
  11264. }
  11265. }
  11266. /* Configure hidden SSID */
  11267. if (info->hidden_ssid != NL80211_HIDDEN_SSID_NOT_IN_USE) {
  11268. if ((err = wldev_iovar_setint(dev, "closednet", 1)) < 0)
  11269. WL_ERR(("failed to set hidden : %d\n", err));
  11270. WL_DBG(("hidden_ssid_enum_val: %d \n", info->hidden_ssid));
  11271. }
  11272. #ifdef SUPPORT_AP_RADIO_PWRSAVE
  11273. if (dev_role == NL80211_IFTYPE_AP) {
  11274. if (!wl_set_ap_rps(dev, FALSE, dev->name)) {
  11275. wl_cfg80211_init_ap_rps(cfg);
  11276. } else {
  11277. WL_ERR(("Set rpsnoa failed \n"));
  11278. }
  11279. }
  11280. #endif /* SUPPORT_AP_RADIO_PWRSAVE */
  11281. fail:
  11282. if (err) {
  11283. WL_ERR(("ADD/SET beacon failed\n"));
  11284. wl_flush_fw_log_buffer(dev, FW_LOGSET_MASK_ALL);
  11285. wl_cfg80211_stop_ap(wiphy, dev);
  11286. if (dev_role == NL80211_IFTYPE_AP) {
  11287. dhd->op_mode &= ~DHD_FLAG_HOSTAP_MODE;
  11288. #ifdef PKT_FILTER_SUPPORT
  11289. /* Enable packet filter */
  11290. if (dhd->early_suspended) {
  11291. WL_ERR(("Enable pkt_filter\n"));
  11292. dhd_enable_packet_filter(1, dhd);
  11293. }
  11294. #endif /* PKT_FILTER_SUPPORT */
  11295. #ifdef ARP_OFFLOAD_SUPPORT
  11296. /* IF SoftAP is disabled, enable arpoe back for STA mode. */
  11297. if (dhd->op_mode & DHD_FLAG_STA_MODE) {
  11298. dhd_arp_offload_set(dhd, dhd_arp_mode);
  11299. dhd_arp_offload_enable(dhd, TRUE);
  11300. }
  11301. #endif /* ARP_OFFLOAD_SUPPORT */
  11302. #ifdef DISABLE_WL_FRAMEBURST_SOFTAP
  11303. wl_cfg80211_set_frameburst(cfg, TRUE);
  11304. #endif /* DISABLE_WL_FRAMEBURST_SOFTAP */
  11305. }
  11306. #ifdef WLTDLS
  11307. if (bssidx == 0) {
  11308. /* Since AP creation failed, re-enable TDLS */
  11309. wl_cfg80211_tdls_config(cfg, TDLS_STATE_AP_DELETE, false);
  11310. }
  11311. #endif /* WLTDLS */
  11312. }
  11313. return err;
  11314. }
  11315. static s32
  11316. wl_cfg80211_stop_ap(
  11317. struct wiphy *wiphy,
  11318. struct net_device *dev)
  11319. {
  11320. int err = 0;
  11321. u32 dev_role = 0;
  11322. int ap = 0;
  11323. s32 bssidx = 0;
  11324. struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
  11325. s32 is_rsdb_supported = BCME_ERROR;
  11326. dhd_pub_t *dhd = (dhd_pub_t *)(cfg->pub);
  11327. WL_DBG(("Enter \n"));
  11328. if (wl_cfg80211_get_bus_state(cfg)) {
  11329. /* since bus is down, iovar will fail. recovery path will bringup the bus. */
  11330. WL_ERR(("bus is not ready\n"));
  11331. return BCME_OK;
  11332. }
  11333. is_rsdb_supported = DHD_OPMODE_SUPPORTED(cfg->pub, DHD_FLAG_RSDB_MODE);
  11334. if (is_rsdb_supported < 0)
  11335. return (-ENODEV);
  11336. wl_clr_drv_status(cfg, AP_CREATING, dev);
  11337. wl_clr_drv_status(cfg, AP_CREATED, dev);
  11338. cfg->ap_oper_channel = 0;
  11339. if (dev->ieee80211_ptr->iftype == NL80211_IFTYPE_AP) {
  11340. dev_role = NL80211_IFTYPE_AP;
  11341. WL_DBG(("stopping AP operation\n"));
  11342. #ifdef DHD_BANDSTEER
  11343. if (dev->ieee80211_ptr->iftype == NL80211_IFTYPE_AP) {
  11344. /* Disable bandsteer */
  11345. cfg->ap_bs = 1;
  11346. cfg->p2p_bs = 1;
  11347. dhd_bandsteer_module_deinit(
  11348. bcmcfg_to_prmry_ndev(cfg), cfg->ap_bs, cfg->p2p_bs);
  11349. }
  11350. #endif /* DHD_BANDSTEER */
  11351. } else if (dev->ieee80211_ptr->iftype == NL80211_IFTYPE_P2P_GO) {
  11352. dev_role = NL80211_IFTYPE_P2P_GO;
  11353. WL_DBG(("stopping P2P GO operation\n"));
  11354. #ifdef DHD_BANDSTEER
  11355. if (dev->ieee80211_ptr->iftype == NL80211_IFTYPE_P2P_GO) {
  11356. /* Disable bandsteer */
  11357. cfg->ap_bs = 1;
  11358. cfg->p2p_bs = 1;
  11359. dhd_bandsteer_module_deinit(
  11360. bcmcfg_to_prmry_ndev(cfg), cfg->ap_bs, cfg->p2p_bs);
  11361. }
  11362. #endif /* DHD_BANDSTEER */
  11363. } else {
  11364. WL_ERR(("no AP/P2P GO interface is operational.\n"));
  11365. return -EINVAL;
  11366. }
  11367. if ((bssidx = wl_get_bssidx_by_wdev(cfg, dev->ieee80211_ptr)) < 0) {
  11368. WL_ERR(("find p2p index from wdev(%p) failed\n", dev->ieee80211_ptr));
  11369. return BCME_ERROR;
  11370. }
  11371. if (!check_dev_role_integrity(cfg, wl_get_mode_by_netdev(cfg, dev), dev_role)) {
  11372. WL_ERR(("role integrity check failed \n"));
  11373. err = -EINVAL;
  11374. goto exit;
  11375. }
  11376. /* Free up resources */
  11377. wl_cfg80211_cleanup_if(dev);
  11378. /* Clear AP/GO connected status */
  11379. wl_clr_drv_status(cfg, CONNECTED, dev);
  11380. if ((err = wl_cfg80211_bss_up(cfg, dev, bssidx, 0)) < 0) {
  11381. WL_ERR(("bss down error %d\n", err));
  11382. }
  11383. if (dev_role == NL80211_IFTYPE_AP) {
  11384. #ifdef DISABLE_WL_FRAMEBURST_SOFTAP
  11385. wl_cfg80211_set_frameburst(cfg, TRUE);
  11386. #endif /* DISABLE_WL_FRAMEBURST_SOFTAP */
  11387. #ifdef PKT_FILTER_SUPPORT
  11388. /* Enable packet filter */
  11389. if (dhd->early_suspended) {
  11390. WL_ERR(("Enable pkt_filter\n"));
  11391. dhd_enable_packet_filter(1, dhd);
  11392. }
  11393. #endif /* PKT_FILTER_SUPPORT */
  11394. #ifdef ARP_OFFLOAD_SUPPORT
  11395. /* IF SoftAP is disabled, enable arpoe back for STA mode. */
  11396. if (dhd->op_mode & DHD_FLAG_STA_MODE) {
  11397. dhd_arp_offload_set(dhd, dhd_arp_mode);
  11398. dhd_arp_offload_enable(dhd, TRUE);
  11399. }
  11400. #endif /* ARP_OFFLOAD_SUPPORT */
  11401. if (is_rsdb_supported == 0) {
  11402. /* For non-rsdb chips, we use stand alone AP. Do wl down on stop AP */
  11403. err = wldev_ioctl_set(dev, WLC_UP, &ap, sizeof(s32));
  11404. if (unlikely(err)) {
  11405. WL_ERR(("WLC_UP error (%d)\n", err));
  11406. err = -EINVAL;
  11407. goto exit;
  11408. }
  11409. }
  11410. #ifdef WL_DISABLE_HE_SOFTAP
  11411. if (wl_cfg80211_set_he_mode(dev, cfg, bssidx, WL_IF_TYPE_AP, TRUE) != BCME_OK) {
  11412. WL_ERR(("failed to set he features\n"));
  11413. }
  11414. #endif /* WL_DISABLE_HE_SOFTAP */
  11415. wl_cfg80211_clear_per_bss_ies(cfg, dev->ieee80211_ptr);
  11416. #ifdef SUPPORT_AP_RADIO_PWRSAVE
  11417. if (!wl_set_ap_rps(dev, FALSE, dev->name)) {
  11418. wl_cfg80211_init_ap_rps(cfg);
  11419. } else {
  11420. WL_ERR(("Set rpsnoa failed \n"));
  11421. }
  11422. #endif /* SUPPORT_AP_RADIO_PWRSAVE */
  11423. } else {
  11424. WL_DBG(("Stopping P2P GO \n"));
  11425. #if defined(OEM_ANDROID)
  11426. DHD_OS_WAKE_LOCK_CTRL_TIMEOUT_ENABLE((dhd_pub_t *)(cfg->pub),
  11427. DHD_EVENT_TIMEOUT_MS*3);
  11428. DHD_OS_WAKE_LOCK_TIMEOUT((dhd_pub_t *)(cfg->pub));
  11429. #endif // endif
  11430. }
  11431. SUPP_LOG(("AP/GO Link down\n"));
  11432. exit:
  11433. if (err) {
  11434. /* In case of failure, flush fw logs */
  11435. wl_flush_fw_log_buffer(dev, FW_LOGSET_MASK_ALL);
  11436. SUPP_LOG(("AP/GO Link down fail. err:%d\n", err));
  11437. }
  11438. #ifdef WLTDLS
  11439. if (bssidx == 0) {
  11440. /* re-enable TDLS if the number of connected interfaces is less than 2 */
  11441. wl_cfg80211_tdls_config(cfg, TDLS_STATE_AP_DELETE, false);
  11442. }
  11443. #endif /* WLTDLS */
  11444. if (dev_role == NL80211_IFTYPE_AP) {
  11445. /* clear the AP mode */
  11446. dhd->op_mode &= ~DHD_FLAG_HOSTAP_MODE;
  11447. }
  11448. return err;
  11449. }
  11450. static s32
  11451. wl_cfg80211_change_beacon(
  11452. struct wiphy *wiphy,
  11453. struct net_device *dev,
  11454. struct cfg80211_beacon_data *info)
  11455. {
  11456. s32 err = BCME_OK;
  11457. struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
  11458. struct parsed_ies ies;
  11459. u32 dev_role = 0;
  11460. s32 bssidx = 0;
  11461. bool pbc = 0;
  11462. #ifdef WL11U
  11463. bcm_tlv_t *interworking_ie;
  11464. u32 iw_ie_len = 0;
  11465. u8 iw_ie[IW_IES_MAX_BUF_LEN];
  11466. #endif // endif
  11467. WL_DBG(("Enter \n"));
  11468. if ((bssidx = wl_get_bssidx_by_wdev(cfg, dev->ieee80211_ptr)) < 0) {
  11469. WL_ERR(("Find p2p index from wdev(%p) failed\n", dev->ieee80211_ptr));
  11470. return BCME_ERROR;
  11471. }
  11472. if (dev->ieee80211_ptr->iftype == NL80211_IFTYPE_P2P_GO) {
  11473. dev_role = NL80211_IFTYPE_P2P_GO;
  11474. } else if (dev->ieee80211_ptr->iftype == NL80211_IFTYPE_AP) {
  11475. dev_role = NL80211_IFTYPE_AP;
  11476. } else {
  11477. err = -EINVAL;
  11478. goto fail;
  11479. }
  11480. if (!check_dev_role_integrity(cfg, wl_get_mode_by_netdev(cfg, dev), dev_role)) {
  11481. err = -EINVAL;
  11482. goto fail;
  11483. }
  11484. if ((dev_role == NL80211_IFTYPE_P2P_GO) && (cfg->p2p_wdev == NULL)) {
  11485. WL_ERR(("P2P already down status!\n"));
  11486. err = BCME_ERROR;
  11487. goto fail;
  11488. }
  11489. /* Parse IEs */
  11490. if ((err = wl_cfg80211_parse_ap_ies(dev, info, &ies)) < 0) {
  11491. WL_ERR(("Parse IEs failed \n"));
  11492. goto fail;
  11493. }
  11494. #ifdef WL11U
  11495. wl_get_iwdata_by_netdev(cfg, dev, iw_ie, &iw_ie_len);
  11496. /* Add interworking IE from beacon data */
  11497. if ((interworking_ie = wl_cfg80211_find_interworking_ie(
  11498. info->beacon_ies, info->beacon_ies_len)) != NULL) {
  11499. err = wl_cfg80211_add_iw_ie(cfg, dev, bssidx,
  11500. VNDR_IE_CUSTOM_FLAG, interworking_ie->id,
  11501. interworking_ie->data, interworking_ie->len);
  11502. if (unlikely(err)) {
  11503. WL_ERR(("Failed to add interworking IE"));
  11504. }
  11505. } else if (iw_ie_len != 0) {
  11506. /* we have to clear IW IE and disable gratuitous APR */
  11507. wl_cfg80211_clear_iw_ie(cfg, dev, bssidx);
  11508. /* we don't bother whether grat_arp gets disabled or not */
  11509. (void)wldev_iovar_setint_bsscfg(dev, "grat_arp", 0,
  11510. bssidx);
  11511. wl_clear_iwdata_by_netdev(cfg, dev);
  11512. cfg->wl11u = FALSE;
  11513. } else {
  11514. WL_DBG(("no update in iw ie\n"));
  11515. }
  11516. #endif /* WL11U */
  11517. /* Set IEs to FW */
  11518. if ((err = wl_cfg80211_set_ies(dev, info, bssidx)) < 0) {
  11519. WL_ERR(("Set IEs failed \n"));
  11520. goto fail;
  11521. }
  11522. if (dev_role == NL80211_IFTYPE_AP) {
  11523. if (wl_cfg80211_hostapd_sec(dev, &ies, bssidx) < 0) {
  11524. WL_ERR(("Hostapd update sec failed \n"));
  11525. err = -EINVAL;
  11526. goto fail;
  11527. }
  11528. /* Enable Probe Req filter, WPS-AP certification 4.2.13 */
  11529. if ((dev_role == NL80211_IFTYPE_AP) && (ies.wps_ie != NULL)) {
  11530. wl_validate_wps_ie((const char *) ies.wps_ie, ies.wps_ie_len, &pbc);
  11531. WL_DBG((" WPS AP, wps_ie is exists pbc=%d\n", pbc));
  11532. if (pbc)
  11533. wl_add_remove_eventmsg(dev, WLC_E_PROBREQ_MSG, true);
  11534. else
  11535. wl_add_remove_eventmsg(dev, WLC_E_PROBREQ_MSG, false);
  11536. }
  11537. }
  11538. fail:
  11539. if (err) {
  11540. wl_flush_fw_log_buffer(dev, FW_LOGSET_MASK_ALL);
  11541. }
  11542. return err;
  11543. }
  11544. #else
  11545. static s32
  11546. wl_cfg80211_add_set_beacon(struct wiphy *wiphy, struct net_device *dev,
  11547. struct beacon_parameters *info)
  11548. {
  11549. s32 err = BCME_OK;
  11550. struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
  11551. s32 ie_offset = 0;
  11552. s32 bssidx = 0;
  11553. u32 dev_role = NL80211_IFTYPE_AP;
  11554. struct parsed_ies ies;
  11555. bcm_tlv_t *ssid_ie;
  11556. bool pbc = 0;
  11557. bool privacy;
  11558. bool is_bss_up = 0;
  11559. dhd_pub_t *dhd = (dhd_pub_t *)(cfg->pub);
  11560. WL_DBG(("interval (%d) dtim_period (%d) head_len (%d) tail_len (%d)\n",
  11561. info->interval, info->dtim_period, info->head_len, info->tail_len));
  11562. if (dev == bcmcfg_to_prmry_ndev(cfg)) {
  11563. dev_role = NL80211_IFTYPE_AP;
  11564. }
  11565. #if defined(WL_ENABLE_P2P_IF)
  11566. else if (dev == cfg->p2p_net) {
  11567. /* Group Add request on p2p0 */
  11568. dev = bcmcfg_to_prmry_ndev(cfg);
  11569. dev_role = NL80211_IFTYPE_P2P_GO;
  11570. }
  11571. #endif /* WL_ENABLE_P2P_IF */
  11572. if ((bssidx = wl_get_bssidx_by_wdev(cfg, dev->ieee80211_ptr)) < 0) {
  11573. WL_ERR(("Find p2p index from wdev(%p) failed\n", dev->ieee80211_ptr));
  11574. return BCME_ERROR;
  11575. }
  11576. if (dev->ieee80211_ptr->iftype == NL80211_IFTYPE_P2P_GO) {
  11577. dev_role = NL80211_IFTYPE_P2P_GO;
  11578. } else if (dev->ieee80211_ptr->iftype == NL80211_IFTYPE_AP) {
  11579. dhd->op_mode |= DHD_FLAG_HOSTAP_MODE;
  11580. }
  11581. if (!check_dev_role_integrity(cfg, wl_get_mode_by_netdev(cfg, dev), dev_role)) {
  11582. err = -ENODEV;
  11583. goto fail;
  11584. }
  11585. if ((dev_role == NL80211_IFTYPE_P2P_GO) && (cfg->p2p_wdev == NULL)) {
  11586. WL_ERR(("P2P already down status!\n"));
  11587. err = BCME_ERROR;
  11588. goto fail;
  11589. }
  11590. ie_offset = DOT11_MGMT_HDR_LEN + DOT11_BCN_PRB_FIXED_LEN;
  11591. /* find the SSID */
  11592. if ((ssid_ie = bcm_parse_tlvs((u8 *)&info->head[ie_offset],
  11593. info->head_len - ie_offset,
  11594. DOT11_MNG_SSID_ID)) != NULL) {
  11595. if (dev_role == NL80211_IFTYPE_AP) {
  11596. /* Store the hostapd SSID */
  11597. bzero(&cfg->hostapd_ssid.SSID[0], DOT11_MAX_SSID_LEN);
  11598. cfg->hostapd_ssid.SSID_len = MIN(ssid_ie->len, DOT11_MAX_SSID_LEN);
  11599. memcpy(&cfg->hostapd_ssid.SSID[0], ssid_ie->data,
  11600. cfg->hostapd_ssid.SSID_len);
  11601. } else {
  11602. /* P2P GO */
  11603. bzero(&cfg->p2p->ssid.SSID[0], DOT11_MAX_SSID_LEN);
  11604. cfg->p2p->ssid.SSID_len = MIN(ssid_ie->len, DOT11_MAX_SSID_LEN);
  11605. memcpy(cfg->p2p->ssid.SSID, ssid_ie->data,
  11606. cfg->p2p->ssid.SSID_len);
  11607. }
  11608. }
  11609. if (wl_cfg80211_parse_ies((u8 *)info->tail,
  11610. info->tail_len, &ies) < 0) {
  11611. WL_ERR(("Beacon get IEs failed \n"));
  11612. err = -EINVAL;
  11613. goto fail;
  11614. }
  11615. if ((err = wl_cfg80211_set_mgmt_vndr_ies(cfg, ndev_to_cfgdev(dev), bssidx,
  11616. VNDR_IE_BEACON_FLAG, (u8 *)info->tail,
  11617. info->tail_len)) < 0) {
  11618. WL_ERR(("Beacon set IEs failed \n"));
  11619. goto fail;
  11620. } else {
  11621. WL_DBG(("Applied Vndr IEs for Beacon \n"));
  11622. }
  11623. #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 2, 0))
  11624. if ((err = wl_cfg80211_set_mgmt_vndr_ies(cfg, ndev_to_cfgdev(dev), bssidx,
  11625. VNDR_IE_PRBRSP_FLAG, (u8 *)info->proberesp_ies,
  11626. info->proberesp_ies_len)) < 0) {
  11627. WL_ERR(("ProbeRsp set IEs failed \n"));
  11628. goto fail;
  11629. } else {
  11630. WL_DBG(("Applied Vndr IEs for ProbeRsp \n"));
  11631. }
  11632. #endif // endif
  11633. is_bss_up = wl_cfg80211_bss_isup(dev, bssidx);
  11634. #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 2, 0))
  11635. privacy = info->privacy;
  11636. #else
  11637. privacy = 0;
  11638. #endif // endif
  11639. if (!is_bss_up &&
  11640. (wl_cfg80211_bcn_validate_sec(dev, &ies, dev_role, bssidx, privacy) < 0))
  11641. {
  11642. WL_ERR(("Beacon set security failed \n"));
  11643. err = -EINVAL;
  11644. goto fail;
  11645. }
  11646. /* Set BI and DTIM period */
  11647. if (info->interval) {
  11648. if ((err = wldev_ioctl_set(dev, WLC_SET_BCNPRD,
  11649. &info->interval, sizeof(s32))) < 0) {
  11650. WL_ERR(("Beacon Interval Set Error, %d\n", err));
  11651. return err;
  11652. }
  11653. }
  11654. if (info->dtim_period) {
  11655. if ((err = wldev_ioctl_set(dev, WLC_SET_DTIMPRD,
  11656. &info->dtim_period, sizeof(s32))) < 0) {
  11657. WL_ERR(("DTIM Interval Set Error, %d\n", err));
  11658. return err;
  11659. }
  11660. }
  11661. /* If bss is already up, skip bring up */
  11662. if (!is_bss_up &&
  11663. (err = wl_cfg80211_bcn_bringup_ap(dev, &ies, dev_role, bssidx)) < 0)
  11664. {
  11665. WL_ERR(("Beacon bring up AP/GO failed \n"));
  11666. goto fail;
  11667. }
  11668. /* Set GC/STA SCB expiry timings. */
  11669. if ((err = wl_cfg80211_set_scb_timings(cfg, dev))) {
  11670. WL_ERR(("scb setting failed \n"));
  11671. goto fail;
  11672. }
  11673. if (wl_get_drv_status(cfg, AP_CREATED, dev)) {
  11674. /* Soft AP already running. Update changed params */
  11675. if (wl_cfg80211_hostapd_sec(dev, &ies, bssidx) < 0) {
  11676. WL_ERR(("Hostapd update sec failed \n"));
  11677. err = -EINVAL;
  11678. goto fail;
  11679. }
  11680. }
  11681. /* Enable Probe Req filter */
  11682. if (((dev_role == NL80211_IFTYPE_P2P_GO) ||
  11683. (dev_role == NL80211_IFTYPE_AP)) && (ies.wps_ie != NULL)) {
  11684. wl_validate_wps_ie((char *) ies.wps_ie, ies.wps_ie_len, &pbc);
  11685. if (pbc)
  11686. wl_add_remove_eventmsg(dev, WLC_E_PROBREQ_MSG, true);
  11687. }
  11688. WL_DBG(("** ADD/SET beacon done **\n"));
  11689. wl_set_drv_status(cfg, CONNECTED, dev);
  11690. fail:
  11691. if (err) {
  11692. WL_ERR(("ADD/SET beacon failed\n"));
  11693. if (dev_role == NL80211_IFTYPE_AP) {
  11694. /* clear the AP mode */
  11695. dhd->op_mode &= ~DHD_FLAG_HOSTAP_MODE;
  11696. }
  11697. }
  11698. return err;
  11699. }
  11700. static s32
  11701. wl_cfg80211_del_beacon(struct wiphy *wiphy, struct net_device *dev)
  11702. {
  11703. int err = 0;
  11704. s32 bssidx = 0;
  11705. int infra = 0;
  11706. struct wireless_dev *wdev = dev->ieee80211_ptr;
  11707. struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
  11708. dhd_pub_t *dhd = (dhd_pub_t *)(cfg->pub);
  11709. WL_DBG(("Enter. \n"));
  11710. if (!wdev) {
  11711. WL_ERR(("wdev null \n"));
  11712. return -EINVAL;
  11713. }
  11714. if ((wdev->iftype != NL80211_IFTYPE_P2P_GO) && (wdev->iftype != NL80211_IFTYPE_AP)) {
  11715. WL_ERR(("Unspported iface type iftype:%d \n", wdev->iftype));
  11716. }
  11717. wl_clr_drv_status(cfg, AP_CREATING, dev);
  11718. wl_clr_drv_status(cfg, AP_CREATED, dev);
  11719. /* Clear AP/GO connected status */
  11720. wl_clr_drv_status(cfg, CONNECTED, dev);
  11721. cfg->ap_oper_channel = 0;
  11722. if ((bssidx = wl_get_bssidx_by_wdev(cfg, dev->ieee80211_ptr)) < 0) {
  11723. WL_ERR(("find p2p index from wdev(%p) failed\n", dev->ieee80211_ptr));
  11724. return BCME_ERROR;
  11725. }
  11726. /* Do bss down */
  11727. if ((err = wl_cfg80211_bss_up(cfg, dev, bssidx, 0)) < 0) {
  11728. WL_ERR(("bss down error %d\n", err));
  11729. }
  11730. /* fall through is intentional */
  11731. err = wldev_ioctl_set(dev, WLC_SET_INFRA, &infra, sizeof(s32));
  11732. if (err < 0) {
  11733. WL_ERR(("SET INFRA error %d\n", err));
  11734. }
  11735. wl_cfg80211_clear_per_bss_ies(cfg, dev->ieee80211_ptr);
  11736. if (wdev->iftype == NL80211_IFTYPE_AP) {
  11737. /* clear the AP mode */
  11738. dhd->op_mode &= ~DHD_FLAG_HOSTAP_MODE;
  11739. }
  11740. return 0;
  11741. }
  11742. #endif /* LINUX_VERSION < VERSION(3,4,0) || WL_COMPAT_WIRELESS */
  11743. #ifdef WL_SUPPORT_ACS
  11744. /*
  11745. * Currently the dump_obss IOVAR is returning string as output so we need to
  11746. * parse the output buffer in an unoptimized way. Going forward if we get the
  11747. * IOVAR output in binary format this method can be optimized
  11748. */
  11749. static int wl_parse_dump_obss(char *buf, struct wl_dump_survey *survey)
  11750. {
  11751. int i;
  11752. char *token;
  11753. char delim[] = " \n";
  11754. token = strsep(&buf, delim);
  11755. while (token != NULL) {
  11756. if (!strcmp(token, "OBSS")) {
  11757. for (i = 0; i < OBSS_TOKEN_IDX; i++)
  11758. token = strsep(&buf, delim);
  11759. survey->obss = simple_strtoul(token, NULL, 10);
  11760. }
  11761. if (!strcmp(token, "IBSS")) {
  11762. for (i = 0; i < IBSS_TOKEN_IDX; i++)
  11763. token = strsep(&buf, delim);
  11764. survey->ibss = simple_strtoul(token, NULL, 10);
  11765. }
  11766. if (!strcmp(token, "TXDur")) {
  11767. for (i = 0; i < TX_TOKEN_IDX; i++)
  11768. token = strsep(&buf, delim);
  11769. survey->tx = simple_strtoul(token, NULL, 10);
  11770. }
  11771. if (!strcmp(token, "Category")) {
  11772. for (i = 0; i < CTG_TOKEN_IDX; i++)
  11773. token = strsep(&buf, delim);
  11774. survey->no_ctg = simple_strtoul(token, NULL, 10);
  11775. }
  11776. if (!strcmp(token, "Packet")) {
  11777. for (i = 0; i < PKT_TOKEN_IDX; i++)
  11778. token = strsep(&buf, delim);
  11779. survey->no_pckt = simple_strtoul(token, NULL, 10);
  11780. }
  11781. if (!strcmp(token, "Opp(time):")) {
  11782. for (i = 0; i < IDLE_TOKEN_IDX; i++)
  11783. token = strsep(&buf, delim);
  11784. survey->idle = simple_strtoul(token, NULL, 10);
  11785. }
  11786. token = strsep(&buf, delim);
  11787. }
  11788. return 0;
  11789. }
  11790. static int wl_dump_obss(struct net_device *ndev, cca_msrmnt_query req,
  11791. struct wl_dump_survey *survey)
  11792. {
  11793. cca_stats_n_flags *results;
  11794. char *buf;
  11795. int retry, err;
  11796. struct bcm_cfg80211 *cfg = wl_get_cfg(ndev);
  11797. buf = (char *)MALLOCZ(cfg->osh, sizeof(char) * WLC_IOCTL_MAXLEN);
  11798. if (unlikely(!buf)) {
  11799. WL_ERR(("%s: buf alloc failed\n", __func__));
  11800. return -ENOMEM;
  11801. }
  11802. retry = IOCTL_RETRY_COUNT;
  11803. while (retry--) {
  11804. err = wldev_iovar_getbuf(ndev, "dump_obss", &req, sizeof(req),
  11805. buf, WLC_IOCTL_MAXLEN, NULL);
  11806. if (err >= 0) {
  11807. break;
  11808. }
  11809. WL_DBG(("attempt = %d, err = %d, \n",
  11810. (IOCTL_RETRY_COUNT - retry), err));
  11811. }
  11812. if (retry <= 0) {
  11813. WL_ERR(("failure, dump_obss IOVAR failed\n"));
  11814. err = -EINVAL;
  11815. goto exit;
  11816. }
  11817. results = (cca_stats_n_flags *)(buf);
  11818. wl_parse_dump_obss(results->buf, survey);
  11819. MFREE(cfg->osh, buf, sizeof(char) * WLC_IOCTL_MAXLEN);
  11820. return 0;
  11821. exit:
  11822. MFREE(cfg->osh, buf, sizeof(char) * WLC_IOCTL_MAXLEN);
  11823. return err;
  11824. }
  11825. static int wl_cfg80211_dump_survey(struct wiphy *wiphy, struct net_device *ndev,
  11826. int idx, struct survey_info *info)
  11827. {
  11828. struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
  11829. struct wl_dump_survey *survey;
  11830. struct ieee80211_supported_band *band;
  11831. struct ieee80211_channel*chan;
  11832. cca_msrmnt_query req;
  11833. int val, err, noise, retry;
  11834. dhd_pub_t *dhd = (dhd_pub_t *)(cfg->pub);
  11835. if (!(dhd->op_mode & DHD_FLAG_HOSTAP_MODE)) {
  11836. return -ENOENT;
  11837. }
  11838. band = wiphy->bands[IEEE80211_BAND_2GHZ];
  11839. if (band && idx >= band->n_channels) {
  11840. idx -= band->n_channels;
  11841. band = NULL;
  11842. }
  11843. if (!band || idx >= band->n_channels) {
  11844. /* Move to 5G band */
  11845. band = wiphy->bands[IEEE80211_BAND_5GHZ];
  11846. if (idx >= band->n_channels) {
  11847. return -ENOENT;
  11848. }
  11849. }
  11850. chan = &band->channels[idx];
  11851. /* Setting current channel to the requested channel */
  11852. if ((err = wl_cfg80211_set_channel(wiphy, ndev, chan,
  11853. NL80211_CHAN_HT20) < 0)) {
  11854. WL_ERR(("Set channel failed \n"));
  11855. }
  11856. if (!idx) {
  11857. /* Set interface up, explicitly. */
  11858. val = 1;
  11859. err = wldev_ioctl_set(ndev, WLC_UP, (void *)&val, sizeof(val));
  11860. if (err < 0) {
  11861. WL_ERR(("set interface up failed, error = %d\n", err));
  11862. }
  11863. }
  11864. /* Get noise value */
  11865. retry = IOCTL_RETRY_COUNT;
  11866. while (retry--) {
  11867. noise = 0;
  11868. err = wldev_ioctl_get(ndev, WLC_GET_PHY_NOISE, &noise,
  11869. sizeof(noise));
  11870. if (err >= 0) {
  11871. break;
  11872. }
  11873. WL_DBG(("attempt = %d, err = %d, \n",
  11874. (IOCTL_RETRY_COUNT - retry), err));
  11875. }
  11876. if (retry <= 0) {
  11877. WL_ERR(("Get Phy Noise failed, error = %d\n", err));
  11878. noise = CHAN_NOISE_DUMMY;
  11879. }
  11880. survey = (struct wl_dump_survey *)MALLOCZ(cfg->osh,
  11881. sizeof(struct wl_dump_survey));
  11882. if (unlikely(!survey)) {
  11883. WL_ERR(("%s: alloc failed\n", __func__));
  11884. return -ENOMEM;
  11885. }
  11886. /* Start Measurement for obss stats on current channel */
  11887. req.msrmnt_query = 0;
  11888. req.time_req = ACS_MSRMNT_DELAY;
  11889. if ((err = wl_dump_obss(ndev, req, survey)) < 0) {
  11890. goto exit;
  11891. }
  11892. /*
  11893. * Wait for the meaurement to complete, adding a buffer value of 10 to take
  11894. * into consideration any delay in IOVAR completion
  11895. */
  11896. msleep(ACS_MSRMNT_DELAY + 10);
  11897. /* Issue IOVAR to collect measurement results */
  11898. req.msrmnt_query = 1;
  11899. if ((err = wl_dump_obss(ndev, req, survey)) < 0) {
  11900. goto exit;
  11901. }
  11902. info->channel = chan;
  11903. info->noise = noise;
  11904. info->channel_time = ACS_MSRMNT_DELAY;
  11905. info->channel_time_busy = ACS_MSRMNT_DELAY - survey->idle;
  11906. info->channel_time_rx = survey->obss + survey->ibss + survey->no_ctg +
  11907. survey->no_pckt;
  11908. info->channel_time_tx = survey->tx;
  11909. info->filled = SURVEY_INFO_NOISE_DBM |SURVEY_INFO_CHANNEL_TIME |
  11910. SURVEY_INFO_CHANNEL_TIME_BUSY | SURVEY_INFO_CHANNEL_TIME_RX |
  11911. SURVEY_INFO_CHANNEL_TIME_TX;
  11912. MFREE(cfg->osh, survey, sizeof(struct wl_dump_survey));
  11913. return 0;
  11914. exit:
  11915. MFREE(cfg->osh, survey, sizeof(struct wl_dump_survey));
  11916. return err;
  11917. }
  11918. #endif /* WL_SUPPORT_ACS */
  11919. static struct cfg80211_ops wl_cfg80211_ops = {
  11920. .add_virtual_intf = wl_cfg80211_add_virtual_iface,
  11921. .del_virtual_intf = wl_cfg80211_del_virtual_iface,
  11922. .change_virtual_intf = wl_cfg80211_change_virtual_iface,
  11923. #if defined(WL_CFG80211_P2P_DEV_IF)
  11924. .start_p2p_device = wl_cfgp2p_start_p2p_device,
  11925. .stop_p2p_device = wl_cfgp2p_stop_p2p_device,
  11926. #endif /* WL_CFG80211_P2P_DEV_IF */
  11927. .scan = wl_cfg80211_scan,
  11928. #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 5, 0))
  11929. .abort_scan = wl_cfg80211_abort_scan,
  11930. #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 5, 0)) */
  11931. .set_wiphy_params = wl_cfg80211_set_wiphy_params,
  11932. .join_ibss = wl_cfg80211_join_ibss,
  11933. .leave_ibss = wl_cfg80211_leave_ibss,
  11934. .get_station = wl_cfg80211_get_station,
  11935. .set_tx_power = wl_cfg80211_set_tx_power,
  11936. .get_tx_power = wl_cfg80211_get_tx_power,
  11937. .add_key = wl_cfg80211_add_key,
  11938. .del_key = wl_cfg80211_del_key,
  11939. .get_key = wl_cfg80211_get_key,
  11940. .set_default_key = wl_cfg80211_config_default_key,
  11941. .set_default_mgmt_key = wl_cfg80211_config_default_mgmt_key,
  11942. .set_power_mgmt = wl_cfg80211_set_power_mgmt,
  11943. .connect = wl_cfg80211_connect,
  11944. .disconnect = wl_cfg80211_disconnect,
  11945. .suspend = wl_cfg80211_suspend,
  11946. .resume = wl_cfg80211_resume,
  11947. .set_pmksa = wl_cfg80211_set_pmksa,
  11948. .del_pmksa = wl_cfg80211_del_pmksa,
  11949. .flush_pmksa = wl_cfg80211_flush_pmksa,
  11950. .remain_on_channel = wl_cfg80211_remain_on_channel,
  11951. .cancel_remain_on_channel = wl_cfg80211_cancel_remain_on_channel,
  11952. .mgmt_tx = wl_cfg80211_mgmt_tx,
  11953. .mgmt_frame_register = wl_cfg80211_mgmt_frame_register,
  11954. .change_bss = wl_cfg80211_change_bss,
  11955. #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 6, 0)) || defined(WL_COMPAT_WIRELESS)
  11956. .set_channel = wl_cfg80211_set_channel,
  11957. #endif /* ((LINUX_VERSION < VERSION(3, 6, 0)) || WL_COMPAT_WIRELESS */
  11958. #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 4, 0)) && !defined(WL_COMPAT_WIRELESS)
  11959. .set_beacon = wl_cfg80211_add_set_beacon,
  11960. .add_beacon = wl_cfg80211_add_set_beacon,
  11961. .del_beacon = wl_cfg80211_del_beacon,
  11962. #else
  11963. .change_beacon = wl_cfg80211_change_beacon,
  11964. .start_ap = wl_cfg80211_start_ap,
  11965. .stop_ap = wl_cfg80211_stop_ap,
  11966. #endif /* LINUX_VERSION < KERNEL_VERSION(3,4,0) && !WL_COMPAT_WIRELESS */
  11967. #ifdef WL_SCHED_SCAN
  11968. .sched_scan_start = wl_cfg80211_sched_scan_start,
  11969. .sched_scan_stop = wl_cfg80211_sched_scan_stop,
  11970. #endif /* WL_SCHED_SCAN */
  11971. #if defined(WL_SUPPORT_BACKPORTED_KPATCHES) || (LINUX_VERSION_CODE >= KERNEL_VERSION(3, \
  11972. 2, 0))
  11973. .del_station = wl_cfg80211_del_station,
  11974. .change_station = wl_cfg80211_change_station,
  11975. .mgmt_tx_cancel_wait = wl_cfg80211_mgmt_tx_cancel_wait,
  11976. #endif /* WL_SUPPORT_BACKPORTED_KPATCHES || KERNEL_VERSION >= (3,2,0) */
  11977. #if (LINUX_VERSION_CODE > KERNEL_VERSION(3, 2, 0)) || defined(WL_COMPAT_WIRELESS)
  11978. .tdls_mgmt = wl_cfg80211_tdls_mgmt,
  11979. .tdls_oper = wl_cfg80211_tdls_oper,
  11980. #endif /* LINUX_VERSION > VERSION(3, 2, 0) || WL_COMPAT_WIRELESS */
  11981. #ifdef WL_SUPPORT_ACS
  11982. .dump_survey = wl_cfg80211_dump_survey,
  11983. #endif /* WL_SUPPORT_ACS */
  11984. #ifdef WL_CFG80211_ACL
  11985. .set_mac_acl = wl_cfg80211_set_mac_acl,
  11986. #endif /* WL_CFG80211_ACL */
  11987. #ifdef GTK_OFFLOAD_SUPPORT
  11988. #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 1, 0))
  11989. .set_rekey_data = wl_cfg80211_set_rekey_data,
  11990. #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 1, 0) */
  11991. #endif /* GTK_OFFLOAD_SUPPORT */
  11992. #if defined(WL_FILS)
  11993. /* This should be enabled from kernel version which supports this */
  11994. .update_connect_params = wl_cfg80211_update_connect_params,
  11995. #endif /* WL_FILS */
  11996. #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 13, 0))
  11997. .set_pmk = wl_cfg80211_set_pmk,
  11998. .del_pmk = wl_cfg80211_del_pmk,
  11999. #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(4, 13, 0) */
  12000. #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 12, 0))
  12001. .channel_switch = wl_cfg80211_channel_switch,
  12002. #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 12, 0) */
  12003. #ifdef WL_SAE
  12004. .external_auth = wl_cfg80211_external_auth,
  12005. #endif /* WL_SAE */
  12006. };
  12007. s32 wl_mode_to_nl80211_iftype(s32 mode)
  12008. {
  12009. s32 err = 0;
  12010. switch (mode) {
  12011. case WL_MODE_BSS:
  12012. return NL80211_IFTYPE_STATION;
  12013. case WL_MODE_IBSS:
  12014. return NL80211_IFTYPE_ADHOC;
  12015. case WL_MODE_AP:
  12016. return NL80211_IFTYPE_AP;
  12017. default:
  12018. return NL80211_IFTYPE_UNSPECIFIED;
  12019. }
  12020. return err;
  12021. }
  12022. s32
  12023. wl_cfg80211_set_country_code(struct net_device *net, char *country_code,
  12024. bool notify, bool user_enforced, int revinfo)
  12025. {
  12026. s32 ret = BCME_OK;
  12027. #ifdef WL_NAN
  12028. struct wireless_dev *wdev = ndev_to_wdev(net);
  12029. struct wiphy *wiphy = wdev->wiphy;
  12030. struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
  12031. if (cfg->nan_enable) {
  12032. mutex_lock(&cfg->if_sync);
  12033. ret = wl_cfgnan_disable(cfg, NAN_COUNTRY_CODE_CHANGE);
  12034. mutex_unlock(&cfg->if_sync);
  12035. if (ret != BCME_OK) {
  12036. WL_ERR(("failed to disable nan, error[%d]\n", ret));
  12037. return ret;
  12038. }
  12039. }
  12040. #endif /* WL_NAN */
  12041. ret = wldev_set_country(net, country_code,
  12042. notify, user_enforced, revinfo);
  12043. if (ret < 0) {
  12044. WL_ERR(("set country Failed :%d\n", ret));
  12045. }
  12046. return ret;
  12047. }
  12048. #ifdef CONFIG_PM
  12049. #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0))
  12050. static const struct wiphy_wowlan_support brcm_wowlan_support = {
  12051. .flags = WIPHY_WOWLAN_ANY,
  12052. .n_patterns = WL_WOWLAN_MAX_PATTERNS,
  12053. .pattern_min_len = WL_WOWLAN_MIN_PATTERN_LEN,
  12054. .pattern_max_len = WL_WOWLAN_MAX_PATTERN_LEN,
  12055. #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0))
  12056. .max_pkt_offset = WL_WOWLAN_MAX_PATTERN_LEN,
  12057. #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0) */
  12058. };
  12059. #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0) */
  12060. #endif /* CONFIG_PM */
  12061. int wl_features_set(u8 *array, uint8 len, u32 ftidx)
  12062. {
  12063. u8* ft_byte;
  12064. if ((ftidx / 8u) >= len)
  12065. return BCME_BADARG;
  12066. ft_byte = &array[ftidx / 8u];
  12067. *ft_byte |= BIT(ftidx % 8u);
  12068. return BCME_OK;
  12069. }
  12070. static s32 wl_setup_wiphy(struct wireless_dev *wdev, struct device *sdiofunc_dev, void *context)
  12071. {
  12072. s32 err = 0;
  12073. #ifdef CONFIG_PM
  12074. #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0))
  12075. struct cfg80211_wowlan *brcm_wowlan_config = NULL;
  12076. #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0) */
  12077. #endif /* CONFIG_PM */
  12078. #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0) || defined(WL_COMPAT_WIRELESS))
  12079. dhd_pub_t *dhd = (dhd_pub_t *)context;
  12080. BCM_REFERENCE(dhd);
  12081. if (!dhd) {
  12082. WL_ERR(("DHD is NULL!!"));
  12083. err = -ENODEV;
  12084. return err;
  12085. }
  12086. #endif // endif
  12087. wdev->wiphy =
  12088. wiphy_new(&wl_cfg80211_ops, sizeof(struct bcm_cfg80211));
  12089. if (unlikely(!wdev->wiphy)) {
  12090. WL_ERR(("Couldn not allocate wiphy device\n"));
  12091. err = -ENOMEM;
  12092. return err;
  12093. }
  12094. set_wiphy_dev(wdev->wiphy, sdiofunc_dev);
  12095. wdev->wiphy->max_scan_ie_len = WL_SCAN_IE_LEN_MAX;
  12096. /* Report how many SSIDs Driver can support per Scan request */
  12097. wdev->wiphy->max_scan_ssids = WL_SCAN_PARAMS_SSID_MAX;
  12098. wdev->wiphy->max_num_pmkids = WL_NUM_PMKIDS_MAX;
  12099. #ifdef WL_SCHED_SCAN
  12100. wdev->wiphy->max_sched_scan_ssids = MAX_PFN_LIST_COUNT;
  12101. wdev->wiphy->max_match_sets = MAX_PFN_LIST_COUNT;
  12102. wdev->wiphy->max_sched_scan_ie_len = WL_SCAN_IE_LEN_MAX;
  12103. #if (LINUX_VERSION_CODE <= KERNEL_VERSION(4, 11, 0))
  12104. wdev->wiphy->flags |= WIPHY_FLAG_SUPPORTS_SCHED_SCAN;
  12105. #endif /* (LINUX_VERSION_CODE <= KERNEL_VERSION(4, 11, 0)) */
  12106. #endif /* WL_SCHED_SCAN */
  12107. wdev->wiphy->interface_modes =
  12108. BIT(NL80211_IFTYPE_STATION)
  12109. | BIT(NL80211_IFTYPE_ADHOC)
  12110. #if !defined(WL_ENABLE_P2P_IF) && !defined(WL_CFG80211_P2P_DEV_IF)
  12111. | BIT(NL80211_IFTYPE_MONITOR)
  12112. #endif /* !WL_ENABLE_P2P_IF && !WL_CFG80211_P2P_DEV_IF */
  12113. #if defined(WL_IFACE_COMB_NUM_CHANNELS) || defined(WL_CFG80211_P2P_DEV_IF)
  12114. | BIT(NL80211_IFTYPE_P2P_CLIENT)
  12115. | BIT(NL80211_IFTYPE_P2P_GO)
  12116. #endif /* WL_IFACE_COMB_NUM_CHANNELS || WL_CFG80211_P2P_DEV_IF */
  12117. #if defined(WL_CFG80211_P2P_DEV_IF)
  12118. | BIT(NL80211_IFTYPE_P2P_DEVICE)
  12119. #endif /* WL_CFG80211_P2P_DEV_IF */
  12120. | BIT(NL80211_IFTYPE_AP);
  12121. #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0)) && \
  12122. (defined(WL_IFACE_COMB_NUM_CHANNELS) || defined(WL_CFG80211_P2P_DEV_IF))
  12123. WL_DBG(("Setting interface combinations for common mode\n"));
  12124. wdev->wiphy->iface_combinations = common_iface_combinations;
  12125. wdev->wiphy->n_iface_combinations =
  12126. ARRAY_SIZE(common_iface_combinations);
  12127. #endif /* LINUX_VER >= 3.0 && (WL_IFACE_COMB_NUM_CHANNELS || WL_CFG80211_P2P_DEV_IF) */
  12128. wdev->wiphy->bands[IEEE80211_BAND_2GHZ] = &__wl_band_2ghz;
  12129. wdev->wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
  12130. wdev->wiphy->cipher_suites = __wl_cipher_suites;
  12131. wdev->wiphy->n_cipher_suites = ARRAY_SIZE(__wl_cipher_suites);
  12132. wdev->wiphy->max_remain_on_channel_duration = 5000;
  12133. wdev->wiphy->mgmt_stypes = wl_cfg80211_default_mgmt_stypes;
  12134. #ifndef WL_POWERSAVE_DISABLED
  12135. wdev->wiphy->flags |= WIPHY_FLAG_PS_ON_BY_DEFAULT;
  12136. #else
  12137. wdev->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT;
  12138. #endif /* !WL_POWERSAVE_DISABLED */
  12139. wdev->wiphy->flags |= WIPHY_FLAG_NETNS_OK |
  12140. WIPHY_FLAG_4ADDR_AP |
  12141. #if (LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 39)) && !defined(WL_COMPAT_WIRELESS)
  12142. WIPHY_FLAG_SUPPORTS_SEPARATE_DEFAULT_KEYS |
  12143. #endif // endif
  12144. WIPHY_FLAG_4ADDR_STATION;
  12145. #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0))
  12146. /*
  12147. * If FW ROAM flag is advertised, upper layer doesn't provide the
  12148. * bssid & freq in the connect command. However, kernel ver >= 3.15,
  12149. * provides bssid_hint & freq_hint which can be used by the firmware.
  12150. * fw_ap_select variable determines whether FW selects the AP or the
  12151. * user space selects the target AP within the given ESS.
  12152. */
  12153. wdev->wiphy->flags |= WIPHY_FLAG_SUPPORTS_FW_ROAM;
  12154. #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0) */
  12155. #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 3, 0)) || defined(WL_COMPAT_WIRELESS)
  12156. wdev->wiphy->flags |= WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL |
  12157. WIPHY_FLAG_OFFCHAN_TX;
  12158. #endif // endif
  12159. #if defined(WL_SUPPORT_BACKPORTED_KPATCHES) || (LINUX_VERSION_CODE >= KERNEL_VERSION(3, \
  12160. 4, 0))
  12161. /* From 3.4 kernel ownards AP_SME flag can be advertised
  12162. * to remove the patch from supplicant
  12163. */
  12164. wdev->wiphy->flags |= WIPHY_FLAG_HAVE_AP_SME;
  12165. #ifdef WL_CFG80211_ACL
  12166. /* Configure ACL capabilities. */
  12167. wdev->wiphy->max_acl_mac_addrs = MAX_NUM_MAC_FILT;
  12168. #endif // endif
  12169. #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0) || defined(WL_COMPAT_WIRELESS))
  12170. /* Supplicant distinguish between the SoftAP mode and other
  12171. * modes (e.g. P2P, WPS, HS2.0) when it builds the probe
  12172. * response frame from Supplicant MR1 and Kernel 3.4.0 or
  12173. * later version. To add Vendor specific IE into the
  12174. * probe response frame in case of SoftAP mode,
  12175. * AP_PROBE_RESP_OFFLOAD flag is set to wiphy->flags variable.
  12176. */
  12177. if (dhd_get_fw_mode(dhd->info) == DHD_FLAG_HOSTAP_MODE) {
  12178. wdev->wiphy->flags |= WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD;
  12179. wdev->wiphy->probe_resp_offload = 0;
  12180. }
  12181. #endif // endif
  12182. #endif /* WL_SUPPORT_BACKPORTED_KPATCHES) || (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)) */
  12183. #if (LINUX_VERSION_CODE > KERNEL_VERSION(3, 2, 0)) || defined(WL_COMPAT_WIRELESS)
  12184. wdev->wiphy->flags |= WIPHY_FLAG_SUPPORTS_TDLS;
  12185. #endif // endif
  12186. #if defined(CONFIG_PM) && defined(WL_CFG80211_P2P_DEV_IF)
  12187. /*
  12188. * From linux-3.10 kernel, wowlan packet filter is mandated to avoid the
  12189. * disconnection of connected network before suspend. So a dummy wowlan
  12190. * filter is configured for kernels linux-3.8 and above.
  12191. */
  12192. #if 0
  12193. #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0))
  12194. wdev->wiphy->wowlan = &brcm_wowlan_support;
  12195. /* If this is not provided cfg stack will get disconnect
  12196. * during suspend.
  12197. * Note: wiphy->wowlan_config is freed by cfg80211 layer.
  12198. * so use malloc instead of MALLOC(osh) to avoid false alarm.
  12199. */
  12200. brcm_wowlan_config = kmalloc(sizeof(struct cfg80211_wowlan), GFP_KERNEL);
  12201. if (brcm_wowlan_config) {
  12202. brcm_wowlan_config->disconnect = true;
  12203. brcm_wowlan_config->gtk_rekey_failure = true;
  12204. brcm_wowlan_config->eap_identity_req = true;
  12205. brcm_wowlan_config->four_way_handshake = true;
  12206. brcm_wowlan_config->patterns = NULL;
  12207. brcm_wowlan_config->n_patterns = 0;
  12208. brcm_wowlan_config->tcp = NULL;
  12209. #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 19, 0))
  12210. brcm_wowlan_config->nd_config = NULL;
  12211. #endif // endif
  12212. } else {
  12213. WL_ERR(("Can not allocate memory for brcm_wowlan_config,"
  12214. " So wiphy->wowlan_config is set to NULL\n"));
  12215. }
  12216. wdev->wiphy->wowlan_config = brcm_wowlan_config;
  12217. #else
  12218. wdev->wiphy->wowlan.flags = WIPHY_WOWLAN_ANY;
  12219. wdev->wiphy->wowlan.n_patterns = WL_WOWLAN_MAX_PATTERNS;
  12220. wdev->wiphy->wowlan.pattern_min_len = WL_WOWLAN_MIN_PATTERN_LEN;
  12221. wdev->wiphy->wowlan.pattern_max_len = WL_WOWLAN_MAX_PATTERN_LEN;
  12222. #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0))
  12223. wdev->wiphy->wowlan.max_pkt_offset = WL_WOWLAN_MAX_PATTERN_LEN;
  12224. #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0) */
  12225. #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0) */
  12226. #endif
  12227. #endif /* CONFIG_PM && WL_CFG80211_P2P_DEV_IF */
  12228. WL_DBG(("Registering custom regulatory)\n"));
  12229. #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0))
  12230. wdev->wiphy->regulatory_flags |= REGULATORY_CUSTOM_REG;
  12231. #else
  12232. wdev->wiphy->flags |= WIPHY_FLAG_CUSTOM_REGULATORY;
  12233. #endif // endif
  12234. wiphy_apply_custom_regulatory(wdev->wiphy, &brcm_regdom);
  12235. #if (LINUX_VERSION_CODE > KERNEL_VERSION(3, 14, 0)) || defined(WL_VENDOR_EXT_SUPPORT)
  12236. WL_INFORM_MEM(("Registering Vendor80211\n"));
  12237. err = wl_cfgvendor_attach(wdev->wiphy, dhd);
  12238. if (unlikely(err < 0)) {
  12239. WL_ERR(("Couldn not attach vendor commands (%d)\n", err));
  12240. }
  12241. #endif /* (LINUX_VERSION_CODE > KERNEL_VERSION(3, 14, 0)) || defined(WL_VENDOR_EXT_SUPPORT) */
  12242. #ifdef WL_FILS
  12243. wiphy_ext_feature_set(wdev->wiphy, NL80211_EXT_FEATURE_FILS_SK_OFFLOAD);
  12244. #endif /* WL_FILS */
  12245. #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 12, 0))
  12246. wdev->wiphy->flags |= WIPHY_FLAG_HAS_CHANNEL_SWITCH;
  12247. wdev->wiphy->max_num_csa_counters = WL_MAX_NUM_CSA_COUNTERS;
  12248. #endif /* LINUX_VERSION_CODE > KERNEL_VERSION(3, 12, 0) */
  12249. #if ((LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0)) && (LINUX_VERSION_CODE <= \
  12250. KERNEL_VERSION(3, 3, 0))) && defined(WL_IFACE_COMB_NUM_CHANNELS)
  12251. wdev->wiphy->flags &= ~WIPHY_FLAG_ENFORCE_COMBINATIONS;
  12252. #endif // endif
  12253. #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 19, 0)) && \
  12254. defined(SUPPORT_RANDOM_MAC_SCAN)
  12255. wdev->wiphy->features |= (NL80211_FEATURE_SCHED_SCAN_RANDOM_MAC_ADDR |
  12256. NL80211_FEATURE_SCAN_RANDOM_MAC_ADDR);
  12257. wdev->wiphy->max_sched_scan_plans = 1; /* multiple plans not supported */
  12258. #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 19, 0)) && defined(SUPPORT_RANDOM_MAC_SCAN) */
  12259. #ifdef WL_SAE
  12260. wdev->wiphy->features |= NL80211_FEATURE_SAE;
  12261. #endif /* WL_SAE */
  12262. #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 13, 0)) && defined(BCMSUP_4WAY_HANDSHAKE)
  12263. if (FW_SUPPORTED(dhd, idsup)) {
  12264. err = wiphy_ext_feature_set(wdev->wiphy,
  12265. NL80211_EXT_FEATURE_4WAY_HANDSHAKE_STA_PSK);
  12266. if (err) {
  12267. return err;
  12268. }
  12269. err = wiphy_ext_feature_set(wdev->wiphy,
  12270. NL80211_EXT_FEATURE_4WAY_HANDSHAKE_STA_1X);
  12271. if (err) {
  12272. return err;
  12273. }
  12274. }
  12275. #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(4, 13, 0) && defined(BCMSUP_4WAY_HANDSHAKE) */
  12276. #ifdef WL_SCAN_TYPE
  12277. /* These scan types will be mapped to default scan on non-supported chipset */
  12278. /* Advertise scan type capability. */
  12279. wiphy_ext_feature_set(wdev->wiphy, NL80211_EXT_FEATURE_LOW_SPAN_SCAN);
  12280. wiphy_ext_feature_set(wdev->wiphy, NL80211_EXT_FEATURE_LOW_POWER_SCAN);
  12281. wiphy_ext_feature_set(wdev->wiphy, NL80211_EXT_FEATURE_HIGH_ACCURACY_SCAN);
  12282. wdev->wiphy->features |= NL80211_FEATURE_LOW_PRIORITY_SCAN;
  12283. #endif /* WL_SCAN_TYPE */
  12284. /* Now we can register wiphy with cfg80211 module */
  12285. err = wiphy_register(wdev->wiphy);
  12286. if (unlikely(err < 0)) {
  12287. WL_ERR(("Couldn not register wiphy device (%d)\n", err));
  12288. wiphy_free(wdev->wiphy);
  12289. }
  12290. return err;
  12291. }
  12292. static void wl_free_wdev(struct bcm_cfg80211 *cfg)
  12293. {
  12294. struct wireless_dev *wdev = cfg->wdev;
  12295. struct wiphy *wiphy = NULL;
  12296. if (!wdev) {
  12297. WL_ERR(("wdev is invalid\n"));
  12298. return;
  12299. }
  12300. if (wdev->wiphy) {
  12301. wiphy = wdev->wiphy;
  12302. #if (LINUX_VERSION_CODE > KERNEL_VERSION(3, 14, 0)) || defined(WL_VENDOR_EXT_SUPPORT)
  12303. wl_cfgvendor_detach(wdev->wiphy);
  12304. #endif /* (LINUX_VERSION_CODE > KERNEL_VERSION(3, 14, 0)) || defined(WL_VENDOR_EXT_SUPPORT) */
  12305. #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0))
  12306. /* Reset wowlan & wowlan_config before Unregister to avoid Kernel Panic */
  12307. WL_DBG(("clear wowlan\n"));
  12308. #if 0
  12309. wdev->wiphy->wowlan = NULL;
  12310. #endif
  12311. #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0) */
  12312. wiphy_unregister(wdev->wiphy);
  12313. wdev->wiphy->dev.parent = NULL;
  12314. wdev->wiphy = NULL;
  12315. }
  12316. wl_delete_all_netinfo(cfg);
  12317. if (wiphy) {
  12318. MFREE(cfg->osh, wdev, sizeof(*wdev));
  12319. wiphy_free(wiphy);
  12320. }
  12321. /* PLEASE do NOT call any function after wiphy_free, the driver's private structure "cfg",
  12322. * which is the private part of wiphy, has been freed in wiphy_free !!!!!!!!!!!
  12323. */
  12324. }
  12325. s32 wl_inform_bss(struct bcm_cfg80211 *cfg)
  12326. {
  12327. struct wl_scan_results *bss_list;
  12328. wl_bss_info_t *bi = NULL; /* must be initialized */
  12329. s32 err = 0;
  12330. s32 i;
  12331. bss_list = cfg->bss_list;
  12332. WL_MEM(("scanned AP count (%d)\n", bss_list->count));
  12333. #ifdef ESCAN_CHANNEL_CACHE
  12334. reset_roam_cache(cfg);
  12335. #endif /* ESCAN_CHANNEL_CACHE */
  12336. preempt_disable();
  12337. bi = next_bss(bss_list, bi);
  12338. for_each_bss(bss_list, bi, i) {
  12339. #ifdef ESCAN_CHANNEL_CACHE
  12340. add_roam_cache(cfg, bi);
  12341. #endif /* ESCAN_CHANNEL_CACHE */
  12342. err = wl_inform_single_bss(cfg, bi, false);
  12343. if (unlikely(err)) {
  12344. WL_ERR(("bss inform failed\n"));
  12345. }
  12346. }
  12347. preempt_enable();
  12348. WL_MEM(("cfg80211 scan cache updated\n"));
  12349. #ifdef ROAM_CHANNEL_CACHE
  12350. /* print_roam_cache(); */
  12351. update_roam_cache(cfg, ioctl_version);
  12352. #endif /* ROAM_CHANNEL_CACHE */
  12353. return err;
  12354. }
  12355. static s32 wl_inform_single_bss(struct bcm_cfg80211 *cfg, wl_bss_info_t *bi, bool update_ssid)
  12356. {
  12357. struct wiphy *wiphy = bcmcfg_to_wiphy(cfg);
  12358. struct ieee80211_mgmt *mgmt;
  12359. struct ieee80211_channel *channel;
  12360. struct ieee80211_supported_band *band;
  12361. struct wl_cfg80211_bss_info *notif_bss_info;
  12362. struct wl_scan_req *sr = wl_to_sr(cfg);
  12363. struct beacon_proberesp *beacon_proberesp;
  12364. struct cfg80211_bss *cbss = NULL;
  12365. dhd_pub_t *dhdp = (dhd_pub_t *)(cfg->pub);
  12366. log_conn_event_t *event_data = NULL;
  12367. tlv_log *tlv_data = NULL;
  12368. u32 alloc_len, tlv_len;
  12369. u32 payload_len;
  12370. s32 mgmt_type;
  12371. s32 signal;
  12372. u32 freq;
  12373. s32 err = 0;
  12374. gfp_t aflags;
  12375. u8 tmp_buf[IEEE80211_MAX_SSID_LEN + 1];
  12376. if (unlikely(dtoh32(bi->length) > WL_BSS_INFO_MAX)) {
  12377. WL_DBG(("Beacon is larger than buffer. Discarding\n"));
  12378. return err;
  12379. }
  12380. if (bi->SSID_len > IEEE80211_MAX_SSID_LEN) {
  12381. WL_ERR(("wrong SSID len:%d\n", bi->SSID_len));
  12382. return -EINVAL;
  12383. }
  12384. aflags = (in_atomic()) ? GFP_ATOMIC : GFP_KERNEL;
  12385. notif_bss_info = (struct wl_cfg80211_bss_info *)MALLOCZ(cfg->osh,
  12386. sizeof(*notif_bss_info) + sizeof(*mgmt) - sizeof(u8) + WL_BSS_INFO_MAX);
  12387. if (unlikely(!notif_bss_info)) {
  12388. WL_ERR(("notif_bss_info alloc failed\n"));
  12389. return -ENOMEM;
  12390. }
  12391. mgmt = (struct ieee80211_mgmt *)notif_bss_info->frame_buf;
  12392. notif_bss_info->channel =
  12393. wf_chspec_ctlchan(wl_chspec_driver_to_host(bi->chanspec));
  12394. if (notif_bss_info->channel <= CH_MAX_2G_CHANNEL)
  12395. band = wiphy->bands[IEEE80211_BAND_2GHZ];
  12396. else
  12397. band = wiphy->bands[IEEE80211_BAND_5GHZ];
  12398. if (!band) {
  12399. WL_ERR(("No valid band"));
  12400. MFREE(cfg->osh, notif_bss_info, sizeof(*notif_bss_info)
  12401. + sizeof(*mgmt) - sizeof(u8) + WL_BSS_INFO_MAX);
  12402. return -EINVAL;
  12403. }
  12404. notif_bss_info->rssi = wl_rssi_offset(dtoh16(bi->RSSI));
  12405. memcpy(mgmt->bssid, &bi->BSSID, ETHER_ADDR_LEN);
  12406. mgmt_type = cfg->active_scan ?
  12407. IEEE80211_STYPE_PROBE_RESP : IEEE80211_STYPE_BEACON;
  12408. if (!memcmp(bi->SSID, sr->ssid.SSID, bi->SSID_len)) {
  12409. mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | mgmt_type);
  12410. }
  12411. beacon_proberesp = cfg->active_scan ?
  12412. (struct beacon_proberesp *)&mgmt->u.probe_resp :
  12413. (struct beacon_proberesp *)&mgmt->u.beacon;
  12414. beacon_proberesp->timestamp = 0;
  12415. beacon_proberesp->beacon_int = cpu_to_le16(bi->beacon_period);
  12416. beacon_proberesp->capab_info = cpu_to_le16(bi->capability);
  12417. wl_rst_ie(cfg);
  12418. wl_update_hidden_ap_ie(bi, ((u8 *) bi) + bi->ie_offset, &bi->ie_length, update_ssid);
  12419. wl_mrg_ie(cfg, ((u8 *) bi) + bi->ie_offset, bi->ie_length);
  12420. wl_cp_ie(cfg, beacon_proberesp->variable, WL_BSS_INFO_MAX -
  12421. offsetof(struct wl_cfg80211_bss_info, frame_buf));
  12422. notif_bss_info->frame_len = offsetof(struct ieee80211_mgmt,
  12423. u.beacon.variable) + wl_get_ielen(cfg);
  12424. #if LINUX_VERSION_CODE == KERNEL_VERSION(2, 6, 38) && !defined(WL_COMPAT_WIRELESS)
  12425. freq = ieee80211_channel_to_frequency(notif_bss_info->channel);
  12426. (void)band->band;
  12427. #else
  12428. freq = ieee80211_channel_to_frequency(notif_bss_info->channel, band->band);
  12429. #endif // endif
  12430. if (freq == 0) {
  12431. WL_ERR(("Invalid channel, fail to chcnage channel to freq\n"));
  12432. MFREE(cfg->osh, notif_bss_info, sizeof(*notif_bss_info)
  12433. + sizeof(*mgmt) - sizeof(u8) + WL_BSS_INFO_MAX);
  12434. return -EINVAL;
  12435. }
  12436. channel = ieee80211_get_channel(wiphy, freq);
  12437. if (unlikely(!channel)) {
  12438. WL_ERR(("ieee80211_get_channel error\n"));
  12439. MFREE(cfg->osh, notif_bss_info, sizeof(*notif_bss_info)
  12440. + sizeof(*mgmt) - sizeof(u8) + WL_BSS_INFO_MAX);
  12441. return -EINVAL;
  12442. }
  12443. memcpy(tmp_buf, bi->SSID, bi->SSID_len);
  12444. tmp_buf[bi->SSID_len] = '\0';
  12445. WL_DBG(("SSID : \"%s\", rssi %d, channel %d, capability : 0x04%x, bssid %pM"
  12446. "mgmt_type %d frame_len %d\n", tmp_buf,
  12447. notif_bss_info->rssi, notif_bss_info->channel,
  12448. mgmt->u.beacon.capab_info, &bi->BSSID, mgmt_type,
  12449. notif_bss_info->frame_len));
  12450. signal = notif_bss_info->rssi * 100;
  12451. if (!mgmt->u.probe_resp.timestamp) {
  12452. #if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 20, 0))
  12453. struct timespec ts;
  12454. get_monotonic_boottime(&ts);
  12455. mgmt->u.probe_resp.timestamp = ((u64)ts.tv_sec*1000000)
  12456. + ts.tv_nsec / 1000;
  12457. #else
  12458. struct timeval tv;
  12459. do_gettimeofday(&tv);
  12460. mgmt->u.probe_resp.timestamp = ((u64)tv.tv_sec*1000000)
  12461. + tv.tv_usec;
  12462. #endif // endif
  12463. }
  12464. cbss = cfg80211_inform_bss_frame(wiphy, channel, mgmt,
  12465. le16_to_cpu(notif_bss_info->frame_len), signal, aflags);
  12466. if (unlikely(!cbss)) {
  12467. WL_ERR(("cfg80211_inform_bss_frame error bssid " MACDBG " channel %d \n",
  12468. MAC2STRDBG((u8*)(&bi->BSSID)), notif_bss_info->channel));
  12469. err = -EINVAL;
  12470. goto out_err;
  12471. }
  12472. CFG80211_PUT_BSS(wiphy, cbss);
  12473. if (DBG_RING_ACTIVE(dhdp, DHD_EVENT_RING_ID) &&
  12474. (cfg->sched_scan_req && !cfg->scan_request)) {
  12475. alloc_len = sizeof(log_conn_event_t) + IEEE80211_MAX_SSID_LEN + sizeof(uint16) +
  12476. sizeof(int16);
  12477. event_data = (log_conn_event_t *)MALLOCZ(dhdp->osh, alloc_len);
  12478. if (!event_data) {
  12479. WL_ERR(("%s: failed to allocate the log_conn_event_t with "
  12480. "length(%d)\n", __func__, alloc_len));
  12481. goto out_err;
  12482. }
  12483. tlv_len = 3 * sizeof(tlv_log);
  12484. event_data->tlvs = (tlv_log *)MALLOCZ(cfg->osh, tlv_len);
  12485. if (!event_data->tlvs) {
  12486. WL_ERR(("%s: failed to allocate the log_conn_event_t with "
  12487. "length(%d)\n", __func__, tlv_len));
  12488. goto free_evt_data;
  12489. }
  12490. payload_len = sizeof(log_conn_event_t);
  12491. event_data->event = WIFI_EVENT_DRIVER_PNO_SCAN_RESULT_FOUND;
  12492. tlv_data = event_data->tlvs;
  12493. /* ssid */
  12494. tlv_data->tag = WIFI_TAG_SSID;
  12495. tlv_data->len = bi->SSID_len;
  12496. memcpy(tlv_data->value, bi->SSID, bi->SSID_len);
  12497. payload_len += TLV_LOG_SIZE(tlv_data);
  12498. tlv_data = TLV_LOG_NEXT(tlv_data);
  12499. /* channel */
  12500. tlv_data->tag = WIFI_TAG_CHANNEL;
  12501. tlv_data->len = sizeof(uint16);
  12502. memcpy(tlv_data->value, &notif_bss_info->channel, sizeof(uint16));
  12503. payload_len += TLV_LOG_SIZE(tlv_data);
  12504. tlv_data = TLV_LOG_NEXT(tlv_data);
  12505. /* rssi */
  12506. tlv_data->tag = WIFI_TAG_RSSI;
  12507. tlv_data->len = sizeof(int16);
  12508. memcpy(tlv_data->value, &notif_bss_info->rssi, sizeof(int16));
  12509. payload_len += TLV_LOG_SIZE(tlv_data);
  12510. tlv_data = TLV_LOG_NEXT(tlv_data);
  12511. dhd_os_push_push_ring_data(dhdp, DHD_EVENT_RING_ID,
  12512. event_data, payload_len);
  12513. MFREE(dhdp->osh, event_data->tlvs, tlv_len);
  12514. free_evt_data:
  12515. MFREE(dhdp->osh, event_data, alloc_len);
  12516. }
  12517. out_err:
  12518. MFREE(cfg->osh, notif_bss_info, sizeof(*notif_bss_info)
  12519. + sizeof(*mgmt) - sizeof(u8) + WL_BSS_INFO_MAX);
  12520. return err;
  12521. }
  12522. static bool wl_is_linkup(struct bcm_cfg80211 *cfg, const wl_event_msg_t *e, struct net_device *ndev)
  12523. {
  12524. u32 event = ntoh32(e->event_type);
  12525. u32 status = ntoh32(e->status);
  12526. u16 flags = ntoh16(e->flags);
  12527. #if defined(CUSTOM_SET_OCLOFF) || defined(CUSTOM_SET_ANTNPM)
  12528. dhd_pub_t *dhd;
  12529. dhd = (dhd_pub_t *)(cfg->pub);
  12530. #endif /* CUSTOM_SET_OCLOFF || CUSTOM_SET_ANTNPM */
  12531. WL_DBG(("event %d, status %d flags %x\n", event, status, flags));
  12532. if (event == WLC_E_SET_SSID) {
  12533. if (status == WLC_E_STATUS_SUCCESS) {
  12534. #ifdef CUSTOM_SET_OCLOFF
  12535. if (dhd->ocl_off) {
  12536. int err = 0;
  12537. int ocl_enable = 0;
  12538. err = wldev_iovar_setint(ndev, "ocl_enable", ocl_enable);
  12539. if (err != 0) {
  12540. WL_ERR(("[WIFI_SEC] wl_is_linkup: Set ocl_enable %d"
  12541. " failed %d\n",
  12542. ocl_enable, err));
  12543. } else {
  12544. WL_ERR(("[WIFI_SEC] wl_is_linkup: Set ocl_enable %d"
  12545. " succeeded %d\n",
  12546. ocl_enable, err));
  12547. }
  12548. }
  12549. #endif /* CUSTOM_SET_OCLOFF */
  12550. #ifdef CUSTOM_SET_ANTNPM
  12551. if (dhd->mimo_ant_set) {
  12552. int err = 0;
  12553. WL_ERR(("[WIFI_SEC] mimo_ant_set = %d\n", dhd->mimo_ant_set));
  12554. err = wldev_iovar_setint(ndev, "txchain", dhd->mimo_ant_set);
  12555. if (err != 0) {
  12556. WL_ERR(("[WIFI_SEC] Fail set txchain\n"));
  12557. }
  12558. err = wldev_iovar_setint(ndev, "rxchain", dhd->mimo_ant_set);
  12559. if (err != 0) {
  12560. WL_ERR(("[WIFI_SEC] Fail set rxchain\n"));
  12561. }
  12562. }
  12563. #endif /* CUSTOM_SET_ANTNPM */
  12564. if (!wl_is_ibssmode(cfg, ndev))
  12565. return true;
  12566. }
  12567. } else if (event == WLC_E_LINK) {
  12568. if (flags & WLC_EVENT_MSG_LINK)
  12569. return true;
  12570. }
  12571. WL_DBG(("wl_is_linkup false\n"));
  12572. return false;
  12573. }
  12574. static bool wl_is_linkdown(struct bcm_cfg80211 *cfg, const wl_event_msg_t *e)
  12575. {
  12576. u32 event = ntoh32(e->event_type);
  12577. u16 flags = ntoh16(e->flags);
  12578. if (event == WLC_E_DEAUTH_IND ||
  12579. event == WLC_E_DISASSOC_IND ||
  12580. event == WLC_E_DISASSOC ||
  12581. event == WLC_E_DEAUTH) {
  12582. WL_ERR(("Link down Reason : %s\n", bcmevent_get_name(event)));
  12583. return true;
  12584. } else if (event == WLC_E_LINK) {
  12585. if (!(flags & WLC_EVENT_MSG_LINK)) {
  12586. WL_ERR(("Link down Reason : %s\n", bcmevent_get_name(event)));
  12587. return true;
  12588. }
  12589. }
  12590. return false;
  12591. }
  12592. static bool wl_is_nonetwork(struct bcm_cfg80211 *cfg, const wl_event_msg_t *e)
  12593. {
  12594. u32 event = ntoh32(e->event_type);
  12595. u32 status = ntoh32(e->status);
  12596. if (event == WLC_E_LINK && status == WLC_E_STATUS_NO_NETWORKS)
  12597. return true;
  12598. if (event == WLC_E_SET_SSID && status != WLC_E_STATUS_SUCCESS)
  12599. return true;
  12600. if (event == WLC_E_ASSOC_RESP_IE && status != WLC_E_STATUS_SUCCESS)
  12601. return true;
  12602. return false;
  12603. }
  12604. #ifdef WL_SAE
  12605. static s32
  12606. wl_cfg80211_event_sae_key(struct bcm_cfg80211 *cfg, struct net_device *ndev,
  12607. wl_sae_key_info_t *sae_key)
  12608. {
  12609. struct sk_buff *skb;
  12610. gfp_t kflags;
  12611. struct wiphy *wiphy = bcmcfg_to_wiphy(cfg);
  12612. int err = BCME_OK;
  12613. kflags = in_atomic() ? GFP_ATOMIC : GFP_KERNEL;
  12614. #if (defined(CONFIG_ARCH_MSM) && defined(SUPPORT_WDEV_CFG80211_VENDOR_EVENT_ALLOC)) || \
  12615. LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0)
  12616. skb = cfg80211_vendor_event_alloc(wiphy, ndev_to_wdev(ndev), BRCM_SAE_VENDOR_EVENT_BUF_LEN,
  12617. BRCM_VENDOR_EVENT_SAE_KEY, kflags);
  12618. #else
  12619. skb = cfg80211_vendor_event_alloc(wiphy, BRCM_SAE_VENDOR_EVENT_BUF_LEN,
  12620. BRCM_VENDOR_EVENT_SAE_KEY, kflags);
  12621. #endif /* (defined(CONFIG_ARCH_MSM) && defined(SUPPORT_WDEV_CFG80211_VENDOR_EVENT_ALLOC)) || */
  12622. /* LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0) */
  12623. if (!skb) {
  12624. WL_ERR(("skb alloc failed"));
  12625. err = BCME_NOMEM;
  12626. goto done;
  12627. }
  12628. WL_INFORM_MEM(("Received Sae Key event for "MACDBG" key length %x %x",
  12629. MAC2STRDBG(sae_key->peer_mac), sae_key->pmk_len, sae_key->pmkid_len));
  12630. nla_put(skb, BRCM_SAE_KEY_ATTR_PEER_MAC, ETHER_ADDR_LEN, sae_key->peer_mac);
  12631. nla_put(skb, BRCM_SAE_KEY_ATTR_PMK, sae_key->pmk_len, sae_key->pmk);
  12632. nla_put(skb, BRCM_SAE_KEY_ATTR_PMKID, sae_key->pmkid_len, sae_key->pmkid);
  12633. cfg80211_vendor_event(skb, kflags);
  12634. done:
  12635. return err;
  12636. }
  12637. static s32
  12638. wl_bss_handle_sae_auth(struct bcm_cfg80211 *cfg, struct net_device *ndev,
  12639. const wl_event_msg_t *event, void *data)
  12640. {
  12641. int err = BCME_OK;
  12642. uint status = ntoh32(event->status);
  12643. wl_auth_event_t *auth_data;
  12644. wl_sae_key_info_t sae_key;
  12645. uint16 tlv_buf_len;
  12646. if (status == WLC_E_STATUS_SUCCESS) {
  12647. auth_data = (wl_auth_event_t *)data;
  12648. if (auth_data->version != WL_AUTH_EVENT_DATA_V1) {
  12649. WL_ERR(("unknown auth event data version %x\n",
  12650. auth_data->version));
  12651. err = BCME_VERSION;
  12652. goto done;
  12653. }
  12654. tlv_buf_len = auth_data->length - WL_AUTH_EVENT_FIXED_LEN_V1;
  12655. /* check if PMK info present */
  12656. sae_key.pmk = bcm_get_data_from_xtlv_buf(auth_data->xtlvs, tlv_buf_len,
  12657. WL_AUTH_PMK_TLV_ID, &(sae_key.pmk_len), BCM_XTLV_OPTION_ALIGN32);
  12658. if (!sae_key.pmk || !sae_key.pmk_len) {
  12659. WL_ERR(("Mandatory PMK info not present"));
  12660. err = BCME_NOTFOUND;
  12661. goto done;
  12662. }
  12663. /* check if PMKID info present */
  12664. sae_key.pmkid = bcm_get_data_from_xtlv_buf(auth_data->xtlvs, tlv_buf_len,
  12665. WL_AUTH_PMKID_TLV_ID, &(sae_key.pmkid_len), BCM_XTLV_OPTION_ALIGN32);
  12666. if (!sae_key.pmkid || !sae_key.pmkid_len) {
  12667. WL_ERR(("Mandatory PMKID info not present\n"));
  12668. err = BCME_NOTFOUND;
  12669. goto done;
  12670. }
  12671. memcpy_s(sae_key.peer_mac, ETHER_ADDR_LEN, event->addr.octet, ETHER_ADDR_LEN);
  12672. err = wl_cfg80211_event_sae_key(cfg, ndev, &sae_key);
  12673. if (err) {
  12674. WL_ERR(("Failed to event sae key info\n"));
  12675. }
  12676. } else {
  12677. WL_ERR(("sae auth status failure:%d\n", status));
  12678. }
  12679. done:
  12680. return err;
  12681. }
  12682. #endif /* WL_SAE */
  12683. static s32
  12684. wl_get_auth_assoc_status(struct bcm_cfg80211 *cfg, struct net_device *ndev,
  12685. const wl_event_msg_t *e, void *data)
  12686. {
  12687. u32 reason = ntoh32(e->reason);
  12688. u32 event = ntoh32(e->event_type);
  12689. #ifdef WL_SAE
  12690. uint auth_type = ntoh32(e->auth_type);
  12691. #endif /* WL_SAE */
  12692. struct wl_security *sec = wl_read_prof(cfg, ndev, WL_PROF_SEC);
  12693. WL_DBG(("event type : %d, reason : %d\n", event, reason));
  12694. #if defined(DHD_ENABLE_BIGDATA_LOGGING)
  12695. (void)memcpy_s(&cfg->event_auth_assoc, sizeof(wl_event_msg_t),
  12696. e, sizeof(wl_event_msg_t));
  12697. WL_ERR(("event=%d status %d reason %d \n",
  12698. ntoh32(cfg->event_auth_assoc.event_type),
  12699. ntoh32(cfg->event_auth_assoc.status),
  12700. ntoh32(cfg->event_auth_assoc.reason)));
  12701. #endif /* DHD_ENABLE_BIGDATA_LOGGING */
  12702. if (sec) {
  12703. switch (event) {
  12704. case WLC_E_ASSOC:
  12705. case WLC_E_AUTH:
  12706. case WLC_E_AUTH_IND:
  12707. sec->auth_assoc_res_status = reason;
  12708. #ifdef WL_SAE
  12709. if ((event == WLC_E_AUTH || event == WLC_E_AUTH_IND) &&
  12710. auth_type == DOT11_SAE) {
  12711. wl_bss_handle_sae_auth(cfg, ndev, e, data);
  12712. }
  12713. #endif /* WL_SAE */
  12714. break;
  12715. default:
  12716. break;
  12717. }
  12718. } else {
  12719. WL_ERR(("sec is NULL\n"));
  12720. }
  12721. return 0;
  12722. }
  12723. #if ((LINUX_VERSION_CODE < KERNEL_VERSION(3, 2, 0)) && !defined(WL_CFG80211_STA_EVENT) \
  12724. && !defined(WL_COMPAT_WIRELESS)) || defined(WL_CFG80211_AP_RX_MGMT_DISCONNECT)
  12725. static s32
  12726. wl_notify_connect_status_ap_rx_mgmt(struct bcm_cfg80211 *cfg, struct net_device *ndev,
  12727. const wl_event_msg_t *e, void *data)
  12728. {
  12729. s32 err = 0;
  12730. u32 event = ntoh32(e->event_type);
  12731. u32 reason = ntoh32(e->reason);
  12732. u32 len = ntoh32(e->datalen);
  12733. bool isfree = false;
  12734. u8 *mgmt_frame;
  12735. u8 bsscfgidx = e->bsscfgidx;
  12736. s32 freq;
  12737. s32 channel;
  12738. u8 *body = NULL;
  12739. u16 fc = 0;
  12740. struct ieee80211_supported_band *band;
  12741. struct ether_addr da;
  12742. struct ether_addr bssid;
  12743. struct wiphy *wiphy = bcmcfg_to_wiphy(cfg);
  12744. channel_info_t ci;
  12745. WL_DBG(("Enter \n"));
  12746. if (!len && (event == WLC_E_DEAUTH)) {
  12747. len = 2; /* reason code field */
  12748. data = &reason;
  12749. }
  12750. if (len) {
  12751. body = kzalloc(len, GFP_KERNEL);
  12752. if (body == NULL) {
  12753. WL_ERR(("wl_notify_connect_status: Failed to allocate body\n"));
  12754. return WL_INVALID;
  12755. }
  12756. }
  12757. memset(&bssid, 0, ETHER_ADDR_LEN);
  12758. WL_DBG(("Enter event %d ndev %p\n", event, ndev));
  12759. if (wl_get_mode_by_netdev(cfg, ndev) == WL_INVALID) {
  12760. kfree(body);
  12761. return WL_INVALID;
  12762. }
  12763. if (len)
  12764. memcpy(body, data, len);
  12765. wldev_iovar_getbuf_bsscfg(ndev, "cur_etheraddr",
  12766. NULL, 0, cfg->ioctl_buf, WLC_IOCTL_SMLEN, bsscfgidx, &cfg->ioctl_buf_sync);
  12767. memcpy(da.octet, cfg->ioctl_buf, ETHER_ADDR_LEN);
  12768. memset(&bssid, 0, sizeof(bssid));
  12769. err = wldev_ioctl_get(ndev, WLC_GET_BSSID, &bssid, ETHER_ADDR_LEN);
  12770. switch (event) {
  12771. case WLC_E_ASSOC_IND:
  12772. fc = FC_ASSOC_REQ;
  12773. break;
  12774. case WLC_E_REASSOC_IND:
  12775. fc = FC_REASSOC_REQ;
  12776. break;
  12777. case WLC_E_DISASSOC_IND:
  12778. fc = FC_DISASSOC;
  12779. break;
  12780. case WLC_E_DEAUTH_IND:
  12781. fc = FC_DISASSOC;
  12782. break;
  12783. case WLC_E_DEAUTH:
  12784. fc = FC_DISASSOC;
  12785. break;
  12786. default:
  12787. fc = 0;
  12788. goto exit;
  12789. }
  12790. memset(&ci, 0, sizeof(ci));
  12791. if ((err = wldev_ioctl_get(ndev, WLC_GET_CHANNEL, &ci, sizeof(ci)))) {
  12792. kfree(body);
  12793. return err;
  12794. }
  12795. channel = dtoh32(ci.hw_channel);
  12796. if (channel <= CH_MAX_2G_CHANNEL)
  12797. band = wiphy->bands[IEEE80211_BAND_2GHZ];
  12798. else
  12799. band = wiphy->bands[IEEE80211_BAND_5GHZ];
  12800. if (!band) {
  12801. WL_ERR(("No valid band"));
  12802. if (body)
  12803. kfree(body);
  12804. return -EINVAL;
  12805. }
  12806. #if LINUX_VERSION_CODE == KERNEL_VERSION(2, 6, 38) && !defined(WL_COMPAT_WIRELESS)
  12807. freq = ieee80211_channel_to_frequency(channel);
  12808. (void)band->band;
  12809. #else
  12810. freq = ieee80211_channel_to_frequency(channel, band->band);
  12811. #endif // endif
  12812. err = wl_frame_get_mgmt(cfg, fc, &da, &e->addr, &bssid,
  12813. &mgmt_frame, &len, body);
  12814. if (err < 0)
  12815. goto exit;
  12816. isfree = true;
  12817. if (((event == WLC_E_ASSOC_IND) || (event == WLC_E_REASSOC_IND)) &&
  12818. reason == DOT11_SC_SUCCESS) {
  12819. CFG80211_RX_MGMT(ndev, freq, 0, mgmt_frame, len,
  12820. NL80211_RXMGMT_FLAG_ANSWERED, GFP_ATOMIC);
  12821. } else if (event == WLC_E_DISASSOC_IND) {
  12822. CFG80211_RX_MGMT(ndev, freq, 0, mgmt_frame, len,
  12823. NL80211_RXMGMT_FLAG_ANSWERED, GFP_ATOMIC);
  12824. } else if ((event == WLC_E_DEAUTH_IND) || (event == WLC_E_DEAUTH)) {
  12825. CFG80211_RX_MGMT(ndev, freq, 0, mgmt_frame, len,
  12826. NL80211_RXMGMT_FLAG_ANSWERED, GFP_ATOMIC);
  12827. }
  12828. exit:
  12829. if (isfree)
  12830. kfree(mgmt_frame);
  12831. if (body)
  12832. kfree(body);
  12833. return err;
  12834. }
  12835. #endif /* LINUX_VERSION < VERSION(3,2,0) && !WL_CFG80211_STA_EVENT && !WL_COMPAT_WIRELESS */
  12836. /* The mainline kernel >= 3.2.0 has support for indicating new/del station
  12837. * to AP/P2P GO via events. If this change is backported to kernel for which
  12838. * this driver is being built, then define WL_CFG80211_STA_EVENT. You
  12839. * should use this new/del sta event mechanism for BRCM supplicant >= 22.
  12840. */
  12841. static s32
  12842. wl_notify_connect_status_ap(struct bcm_cfg80211 *cfg, struct net_device *ndev,
  12843. const wl_event_msg_t *e, void *data)
  12844. {
  12845. s32 err = 0;
  12846. u32 event = ntoh32(e->event_type);
  12847. u32 reason = ntoh32(e->reason);
  12848. u32 status = ntoh32(e->status);
  12849. #ifdef BIGDATA_SOFTAP
  12850. dhd_pub_t *dhdp;
  12851. #endif /* BIGDATA_SOFTAP */
  12852. WL_INFORM_MEM(("[%s] Mode AP/GO. Event:%d status:%d reason:%d\n",
  12853. ndev->name, event, ntoh32(e->status), reason));
  12854. if (event == WLC_E_AUTH_IND) {
  12855. wl_get_auth_assoc_status(cfg, ndev, e, data);
  12856. return 0;
  12857. }
  12858. /* if link down, bsscfg is disabled. */
  12859. if (event == WLC_E_LINK && reason == WLC_E_LINK_BSSCFG_DIS &&
  12860. wl_get_p2p_status(cfg, IF_DELETING) && (ndev != bcmcfg_to_prmry_ndev(cfg))) {
  12861. wl_add_remove_eventmsg(ndev, WLC_E_PROBREQ_MSG, false);
  12862. WL_INFORM_MEM(("AP mode link down !! \n"));
  12863. complete(&cfg->iface_disable);
  12864. return 0;
  12865. }
  12866. if ((event == WLC_E_LINK) && (status == WLC_E_STATUS_SUCCESS) &&
  12867. (reason == WLC_E_REASON_INITIAL_ASSOC) &&
  12868. (wl_get_mode_by_netdev(cfg, ndev) == WL_MODE_AP)) {
  12869. if (!wl_get_drv_status(cfg, AP_CREATED, ndev)) {
  12870. /* AP/GO brought up successfull in firmware */
  12871. WL_INFORM_MEM(("AP/GO Link up\n"));
  12872. wl_set_drv_status(cfg, AP_CREATED, ndev);
  12873. OSL_SMP_WMB();
  12874. wake_up_interruptible(&cfg->netif_change_event);
  12875. #ifdef BIGDATA_SOFTAP
  12876. wl_ap_stainfo_init(cfg);
  12877. #endif /* BIGDATA_SOFTAP */
  12878. #ifdef WL_BCNRECV
  12879. /* check fakeapscan is in progress, if progress then abort */
  12880. wl_android_bcnrecv_stop(ndev, WL_BCNRECV_CONCURRENCY);
  12881. #endif /* WL_BCNRECV */
  12882. return 0;
  12883. }
  12884. }
  12885. if (event == WLC_E_DISASSOC_IND || event == WLC_E_DEAUTH_IND || event == WLC_E_DEAUTH) {
  12886. WL_DBG(("event %s(%d) status %d reason %d\n",
  12887. bcmevent_get_name(event), event, ntoh32(e->status), reason));
  12888. }
  12889. #ifdef BIGDATA_SOFTAP
  12890. if (event == WLC_E_LINK && reason == WLC_E_LINK_BSSCFG_DIS) {
  12891. WL_ERR(("AP link down - skip get sta data\n"));
  12892. } else {
  12893. dhdp = (dhd_pub_t *)(cfg->pub);
  12894. if (dhdp && dhdp->op_mode & DHD_FLAG_HOSTAP_MODE) {
  12895. dhd_schedule_gather_ap_stadata(cfg, ndev, e);
  12896. }
  12897. }
  12898. #endif /* BIGDATA_SOFTAP */
  12899. #if !defined(WL_CFG80211_STA_EVENT) && !defined(WL_COMPAT_WIRELESS) && \
  12900. (LINUX_VERSION_CODE < KERNEL_VERSION(3, 2, 0))
  12901. return wl_notify_connect_status_ap_rx_mgmt(cfg, ndev, e, data);
  12902. #else /* LINUX_VERSION < VERSION(3,2,0) && !WL_CFG80211_STA_EVENT && !WL_COMPAT_WIRELESS */
  12903. if (((event == WLC_E_ASSOC_IND) || (event == WLC_E_REASSOC_IND)) &&
  12904. reason == DOT11_SC_SUCCESS) {
  12905. u32 len = ntoh32(e->datalen);
  12906. struct station_info sinfo;
  12907. #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 15, 0))
  12908. memset(&sinfo, 0, sizeof(struct station_info));
  12909. #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 15, 0)) */
  12910. sinfo.filled = 0;
  12911. /* Linux ver >= 4.0 assoc_req_ies_len is used instead of
  12912. * STATION_INFO_ASSOC_REQ_IES flag
  12913. */
  12914. #if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0))
  12915. sinfo.filled = STA_INFO_BIT(INFO_ASSOC_REQ_IES);
  12916. #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 0, 0)) */
  12917. if (!data) {
  12918. WL_ERR(("No IEs present in ASSOC/REASSOC_IND"));
  12919. return -EINVAL;
  12920. }
  12921. sinfo.assoc_req_ies = data;
  12922. sinfo.assoc_req_ies_len = len;
  12923. WL_INFORM_MEM(("[%s] new sta event for "MACDBG "\n",
  12924. ndev->name, MAC2STRDBG(e->addr.octet)));
  12925. cfg80211_new_sta(ndev, e->addr.octet, &sinfo, GFP_ATOMIC);
  12926. #ifdef WL_WPS_SYNC
  12927. wl_wps_session_update(ndev, WPS_STATE_LINKUP, e->addr.octet);
  12928. #endif /* WL_WPS_SYNC */
  12929. } else if ((event == WLC_E_DEAUTH_IND) ||
  12930. ((event == WLC_E_DEAUTH) && (reason != DOT11_RC_RESERVED)) ||
  12931. (event == WLC_E_DISASSOC_IND)) {
  12932. #if defined(WL_CFG80211_AP_RX_MGMT_DISCONNECT)
  12933. err = wl_notify_connect_status_ap_rx_mgmt(cfg, ndev, e, data);
  12934. #else
  12935. WL_INFORM_MEM(("[%s] del sta event for "MACDBG "\n",
  12936. ndev->name, MAC2STRDBG(e->addr.octet)));
  12937. cfg80211_del_sta(ndev, e->addr.octet, GFP_ATOMIC);
  12938. #endif /* WL_CFG80211_AP_RX_MGMT_DISCONNECT */
  12939. #ifdef WL_WPS_SYNC
  12940. wl_wps_session_update(ndev, WPS_STATE_LINKDOWN, e->addr.octet);
  12941. #endif /* WL_WPS_SYNC */
  12942. }
  12943. #endif /* LINUX_VERSION < VERSION(3,2,0) && !WL_CFG80211_STA_EVENT && !WL_COMPAT_WIRELESS */
  12944. return err;
  12945. }
  12946. #if defined(DHD_ENABLE_BIGDATA_LOGGING)
  12947. enum {
  12948. BIGDATA_ASSOC_REJECT_NO_ACK = 1,
  12949. BIGDATA_ASSOC_REJECT_FAIL = 2,
  12950. BIGDATA_ASSOC_REJECT_UNSOLICITED = 3,
  12951. BIGDATA_ASSOC_REJECT_TIMEOUT = 4,
  12952. BIGDATA_ASSOC_REJECT_ABORT = 5,
  12953. BIGDATA_ASSOC_REJECT_NO_NETWWORKS = 6,
  12954. BIGDATA_ASSOC_REJECT_MAX = 50
  12955. };
  12956. int wl_get_connect_failed_status(struct bcm_cfg80211 *cfg, const wl_event_msg_t *e)
  12957. {
  12958. u32 status = ntoh32(e->status);
  12959. cfg->assoc_reject_status = 0;
  12960. if (status != WLC_E_STATUS_SUCCESS) {
  12961. WL_ERR(("auth assoc status event=%d e->status %d e->reason %d \n",
  12962. ntoh32(cfg->event_auth_assoc.event_type),
  12963. (int)ntoh32(cfg->event_auth_assoc.status),
  12964. (int)ntoh32(cfg->event_auth_assoc.reason)));
  12965. switch ((int)ntoh32(cfg->event_auth_assoc.status)) {
  12966. case WLC_E_STATUS_NO_ACK:
  12967. cfg->assoc_reject_status = BIGDATA_ASSOC_REJECT_NO_ACK;
  12968. break;
  12969. case WLC_E_STATUS_FAIL:
  12970. cfg->assoc_reject_status = BIGDATA_ASSOC_REJECT_FAIL;
  12971. break;
  12972. case WLC_E_STATUS_UNSOLICITED:
  12973. cfg->assoc_reject_status = BIGDATA_ASSOC_REJECT_UNSOLICITED;
  12974. break;
  12975. case WLC_E_STATUS_TIMEOUT:
  12976. cfg->assoc_reject_status = BIGDATA_ASSOC_REJECT_TIMEOUT;
  12977. break;
  12978. case WLC_E_STATUS_ABORT:
  12979. cfg->assoc_reject_status = BIGDATA_ASSOC_REJECT_ABORT;
  12980. break;
  12981. case WLC_E_STATUS_SUCCESS:
  12982. if (status == WLC_E_STATUS_NO_NETWORKS) {
  12983. cfg->assoc_reject_status =
  12984. BIGDATA_ASSOC_REJECT_NO_NETWWORKS;
  12985. break;
  12986. }
  12987. default:
  12988. cfg->assoc_reject_status = BIGDATA_ASSOC_REJECT_MAX;
  12989. break;
  12990. }
  12991. if (cfg->assoc_reject_status) {
  12992. if (ntoh32(cfg->event_auth_assoc.event_type) == WLC_E_ASSOC) {
  12993. cfg->assoc_reject_status += BIGDATA_ASSOC_REJECT_MAX;
  12994. }
  12995. }
  12996. }
  12997. WL_ERR(("assoc_reject_status %d \n", cfg->assoc_reject_status));
  12998. return 0;
  12999. }
  13000. s32 wl_cfg80211_get_connect_failed_status(struct net_device *dev, char* cmd, int total_len)
  13001. {
  13002. struct bcm_cfg80211 *cfg = wl_get_cfg(dev);
  13003. int bytes_written = 0;
  13004. if (cfg == NULL) {
  13005. return -1;
  13006. }
  13007. bytes_written = snprintf(cmd, total_len, "assoc_reject.status %d",
  13008. cfg->assoc_reject_status);
  13009. WL_ERR(("cmd: %s \n", cmd));
  13010. return bytes_written;
  13011. }
  13012. #endif /* DHD_ENABLE_BIGDATA_LOGGING */
  13013. static s32
  13014. wl_notify_connect_status_ibss(struct bcm_cfg80211 *cfg, struct net_device *ndev,
  13015. const wl_event_msg_t *e, void *data)
  13016. {
  13017. s32 err = 0;
  13018. u32 event = ntoh32(e->event_type);
  13019. u16 flags = ntoh16(e->flags);
  13020. u32 status = ntoh32(e->status);
  13021. bool active;
  13022. #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0)
  13023. struct ieee80211_channel *channel = NULL;
  13024. struct wiphy *wiphy = bcmcfg_to_wiphy(cfg);
  13025. u32 chanspec, chan;
  13026. u32 freq, band;
  13027. #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0) */
  13028. if (event == WLC_E_JOIN) {
  13029. WL_INFORM_MEM(("[%s] joined in IBSS network\n", ndev->name));
  13030. }
  13031. if (event == WLC_E_START) {
  13032. WL_INFORM_MEM(("[%s] started IBSS network\n", ndev->name));
  13033. }
  13034. if (event == WLC_E_JOIN || event == WLC_E_START ||
  13035. (event == WLC_E_LINK && (flags == WLC_EVENT_MSG_LINK))) {
  13036. #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0)
  13037. err = wldev_iovar_getint(ndev, "chanspec", (s32 *)&chanspec);
  13038. if (unlikely(err)) {
  13039. WL_ERR(("Could not get chanspec %d\n", err));
  13040. return err;
  13041. }
  13042. chan = wf_chspec_ctlchan(wl_chspec_driver_to_host(chanspec));
  13043. band = (chan <= CH_MAX_2G_CHANNEL) ? IEEE80211_BAND_2GHZ : IEEE80211_BAND_5GHZ;
  13044. freq = ieee80211_channel_to_frequency(chan, band);
  13045. channel = ieee80211_get_channel(wiphy, freq);
  13046. #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0) */
  13047. if (wl_get_drv_status(cfg, CONNECTED, ndev)) {
  13048. /* ROAM or Redundant */
  13049. u8 *cur_bssid = wl_read_prof(cfg, ndev, WL_PROF_BSSID);
  13050. if (memcmp(cur_bssid, &e->addr, ETHER_ADDR_LEN) == 0) {
  13051. WL_DBG(("IBSS connected event from same BSSID("
  13052. MACDBG "), ignore it\n", MAC2STRDBG(cur_bssid)));
  13053. return err;
  13054. }
  13055. WL_INFORM_MEM(("[%s] IBSS BSSID is changed from " MACDBG " to " MACDBG "\n",
  13056. ndev->name, MAC2STRDBG(cur_bssid),
  13057. MAC2STRDBG((const u8 *)&e->addr)));
  13058. wl_get_assoc_ies(cfg, ndev);
  13059. wl_update_prof(cfg, ndev, NULL, (const void *)&e->addr, WL_PROF_BSSID);
  13060. wl_update_bss_info(cfg, ndev, false);
  13061. #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0)
  13062. cfg80211_ibss_joined(ndev, (const s8 *)&e->addr, channel, GFP_KERNEL);
  13063. #else
  13064. cfg80211_ibss_joined(ndev, (const s8 *)&e->addr, GFP_KERNEL);
  13065. #endif // endif
  13066. }
  13067. else {
  13068. /* New connection */
  13069. WL_INFORM_MEM(("[%s] IBSS connected to " MACDBG "\n",
  13070. ndev->name, MAC2STRDBG((const u8 *)&e->addr)));
  13071. wl_link_up(cfg);
  13072. wl_get_assoc_ies(cfg, ndev);
  13073. wl_update_prof(cfg, ndev, NULL, (const void *)&e->addr, WL_PROF_BSSID);
  13074. wl_update_bss_info(cfg, ndev, false);
  13075. #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0)
  13076. cfg80211_ibss_joined(ndev, (const s8 *)&e->addr, channel, GFP_KERNEL);
  13077. #else
  13078. cfg80211_ibss_joined(ndev, (const s8 *)&e->addr, GFP_KERNEL);
  13079. #endif // endif
  13080. wl_set_drv_status(cfg, CONNECTED, ndev);
  13081. active = true;
  13082. wl_update_prof(cfg, ndev, NULL, (const void *)&active, WL_PROF_ACT);
  13083. }
  13084. } else if ((event == WLC_E_LINK && !(flags & WLC_EVENT_MSG_LINK)) ||
  13085. event == WLC_E_DEAUTH_IND || event == WLC_E_DISASSOC_IND) {
  13086. wl_clr_drv_status(cfg, CONNECTED, ndev);
  13087. wl_link_down(cfg);
  13088. wl_init_prof(cfg, ndev);
  13089. }
  13090. else if (event == WLC_E_SET_SSID && status == WLC_E_STATUS_NO_NETWORKS) {
  13091. WL_INFORM_MEM(("no action - join fail (IBSS mode)\n"));
  13092. }
  13093. else {
  13094. WL_DBG(("no action (IBSS mode)\n"));
  13095. }
  13096. return err;
  13097. }
  13098. #if defined(DHD_ENABLE_BIGDATA_LOGGING)
  13099. #define WiFiALL_OUI "\x50\x6F\x9A" /* Wi-FiAll OUI */
  13100. #define WiFiALL_OUI_LEN 3
  13101. #define WiFiALL_OUI_TYPE 16
  13102. /* 11kv feature flag for big data */
  13103. #define WL_BIGDATA_11KV_QBSSLOAD 0x00000001
  13104. #define WL_BIGDATA_11KV_PROXYARP 0x00000002
  13105. #define WL_BIGDATA_11KV_TFS 0x00000004
  13106. #define WL_BIGDATA_11KV_SLEEP 0x00000008
  13107. #define WL_BIGDATA_11KV_TIMBC 0x00000010
  13108. #define WL_BIGDATA_11KV_BSSTRANS 0x00000020
  13109. #define WL_BIGDATA_11KV_DMS 0x00000040
  13110. #define WL_BIGDATA_11KV_LINK_MEA 0x00000080
  13111. #define WL_BIGDATA_11KV_NBRREP 0x00000100
  13112. #define WL_BIGDATA_11KV_BCNPASSIVE 0x00000200
  13113. #define WL_BIGDATA_11KV_BCNACTIVE 0x00000400
  13114. #define WL_BIGDATA_11KV_BCNTABLE 0x00000800
  13115. #define WL_BIGDATA_11KV_BSSAAD 0x00001000
  13116. #define WL_BIGDATA_11KV_MAX 0x00002000
  13117. #define WL_BIGDATA_SUPPORT_11K 0x00000001
  13118. #define WL_BIGDATA_SUPPORT_11V 0x00000002
  13119. typedef struct {
  13120. uint8 bitmap;
  13121. uint8 octet_len;
  13122. uint32 flag;
  13123. } bigdata_11kv_t;
  13124. bigdata_11kv_t bigdata_11k_info[] = {
  13125. {DOT11_RRM_CAP_LINK, DOT11_RRM_CAP_LEN, WL_BIGDATA_11KV_LINK_MEA},
  13126. {DOT11_RRM_CAP_NEIGHBOR_REPORT, DOT11_RRM_CAP_LEN, WL_BIGDATA_11KV_NBRREP},
  13127. {DOT11_RRM_CAP_BCN_PASSIVE, DOT11_RRM_CAP_LEN, WL_BIGDATA_11KV_BCNPASSIVE},
  13128. {DOT11_RRM_CAP_BCN_ACTIVE, DOT11_RRM_CAP_LEN, WL_BIGDATA_11KV_BCNACTIVE},
  13129. {DOT11_RRM_CAP_BCN_TABLE, DOT11_RRM_CAP_LEN, WL_BIGDATA_11KV_BCNTABLE},
  13130. {DOT11_RRM_CAP_BSSAAD, DOT11_RRM_CAP_LEN, WL_BIGDATA_11KV_BSSAAD},
  13131. };
  13132. bigdata_11kv_t bigdata_11v_info[] = {
  13133. {DOT11_EXT_CAP_PROXY_ARP, DOT11_EXTCAP_LEN_PROXY_ARP, WL_BIGDATA_11KV_PROXYARP},
  13134. {DOT11_EXT_CAP_TFS, DOT11_EXTCAP_LEN_TFS, WL_BIGDATA_11KV_TFS},
  13135. {DOT11_EXT_CAP_WNM_SLEEP, DOT11_EXTCAP_LEN_WNM_SLEEP, WL_BIGDATA_11KV_SLEEP},
  13136. {DOT11_EXT_CAP_TIMBC, DOT11_EXTCAP_LEN_TIMBC, WL_BIGDATA_11KV_TIMBC},
  13137. {DOT11_EXT_CAP_BSSTRANS_MGMT, DOT11_EXTCAP_LEN_BSSTRANS, WL_BIGDATA_11KV_BSSTRANS},
  13138. {DOT11_EXT_CAP_DMS, DOT11_EXTCAP_LEN_DMS, WL_BIGDATA_11KV_DMS}
  13139. };
  13140. static void
  13141. wl_get_11kv_info(u8 *ie, u32 ie_len, uint8 *support_11kv, uint32 *flag_11kv)
  13142. {
  13143. bcm_tlv_t *ie_11kv = NULL;
  13144. uint32 flag_11k = 0, flag_11v = 0;
  13145. int i;
  13146. /* parsing QBSS load ie */
  13147. if ((bcm_parse_tlvs(ie, (u32)ie_len,
  13148. DOT11_MNG_QBSS_LOAD_ID)) != NULL) {
  13149. flag_11k |= WL_BIGDATA_11KV_QBSSLOAD;
  13150. }
  13151. /* parsing RM IE for 11k */
  13152. if ((ie_11kv = bcm_parse_tlvs(ie, (u32)ie_len,
  13153. DOT11_MNG_RRM_CAP_ID)) != NULL) {
  13154. for (i = 0; i < ARRAYSIZE(bigdata_11k_info); i++) {
  13155. if ((ie_11kv->len >= bigdata_11k_info[i].octet_len) &&
  13156. isset(ie_11kv->data, bigdata_11k_info[i].bitmap)) {
  13157. flag_11k |= bigdata_11k_info[i].flag;
  13158. }
  13159. }
  13160. }
  13161. /* parsing extended cap. IE for 11v */
  13162. if ((ie_11kv = bcm_parse_tlvs(ie, (u32)ie_len,
  13163. DOT11_MNG_EXT_CAP_ID)) != NULL) {
  13164. for (i = 0; i < ARRAYSIZE(bigdata_11v_info); i++) {
  13165. if ((ie_11kv->len >= bigdata_11v_info[i].octet_len) &&
  13166. isset(ie_11kv->data, bigdata_11v_info[i].bitmap)) {
  13167. flag_11v |= bigdata_11v_info[i].flag;
  13168. }
  13169. }
  13170. }
  13171. if (flag_11k > 0) {
  13172. *support_11kv |= WL_BIGDATA_SUPPORT_11K;
  13173. }
  13174. if (flag_11v > 0) {
  13175. *support_11kv |= WL_BIGDATA_SUPPORT_11V;
  13176. }
  13177. *flag_11kv = flag_11k | flag_11v;
  13178. }
  13179. int wl_get_bss_info(struct bcm_cfg80211 *cfg, struct net_device *dev, struct ether_addr const *mac)
  13180. {
  13181. s32 err = 0;
  13182. wl_bss_info_v109_1_t *bi;
  13183. uint8 eabuf[ETHER_ADDR_LEN];
  13184. u32 rate, channel, freq, supported_rate, nss = 0, mcs_map, mode_80211 = 0;
  13185. char rate_str[4];
  13186. u8 *ie = NULL;
  13187. u32 ie_len;
  13188. struct wiphy *wiphy;
  13189. struct cfg80211_bss *bss;
  13190. bcm_tlv_t *interworking_ie = NULL;
  13191. bcm_tlv_t *tlv_ie = NULL;
  13192. bcm_tlv_t *vht_ie = NULL;
  13193. vndr_ie_t *vndrie;
  13194. int16 ie_11u_rel_num = -1, ie_mu_mimo_cap = -1;
  13195. u32 i, remained_len, count = 0;
  13196. char roam_count_str[4], akm_str[4];
  13197. s32 val = 0;
  13198. uint8 support_11kv = 0;
  13199. uint32 flag_11kv = 0; /* bit flags of 11kv big data */
  13200. /* get BSS information */
  13201. strlcpy(cfg->bss_info, "x x x x x x x x x x x x x x x", sizeof(cfg->bss_info));
  13202. *(u32 *) cfg->extra_buf = htod32(WL_EXTRA_BUF_MAX);
  13203. err = wldev_ioctl_get(dev, WLC_GET_BSS_INFO, cfg->extra_buf, WL_EXTRA_BUF_MAX);
  13204. if (unlikely(err)) {
  13205. WL_ERR(("Could not get bss info %d\n", err));
  13206. cfg->roam_count = 0;
  13207. return -1;
  13208. }
  13209. if (!mac) {
  13210. WL_ERR(("mac is null \n"));
  13211. cfg->roam_count = 0;
  13212. return -1;
  13213. }
  13214. memcpy(eabuf, mac, ETHER_ADDR_LEN);
  13215. bi = (wl_bss_info_v109_1_t *)(cfg->extra_buf + 4);
  13216. channel = wf_chspec_ctlchan(bi->chanspec);
  13217. #if LINUX_VERSION_CODE == KERNEL_VERSION(2, 6, 38) && !defined(WL_COMPAT_WIRELESS)
  13218. freq = ieee80211_channel_to_frequency(channel);
  13219. #else
  13220. if (channel > 14) {
  13221. freq = ieee80211_channel_to_frequency(channel, IEEE80211_BAND_5GHZ);
  13222. } else {
  13223. freq = ieee80211_channel_to_frequency(channel, IEEE80211_BAND_2GHZ);
  13224. }
  13225. #endif // endif
  13226. rate = 0;
  13227. err = wldev_ioctl_get(dev, WLC_GET_RATE, &rate, sizeof(rate));
  13228. if (err) {
  13229. WL_ERR(("Could not get rate (%d)\n", err));
  13230. snprintf(rate_str, sizeof(rate_str), "x"); /* Unknown */
  13231. } else {
  13232. rate = dtoh32(rate);
  13233. snprintf(rate_str, sizeof(rate_str), "%d", (rate/2));
  13234. }
  13235. /* supported maximum rate */
  13236. supported_rate = (bi->rateset.rates[bi->rateset.count - 1] & 0x7f) / 2;
  13237. if (supported_rate < 12) {
  13238. mode_80211 = BIGDATA_DOT11_11B_MODE; /* 11b maximum rate is 11Mbps. 11b mode */
  13239. } else {
  13240. /* It's not HT Capable case. */
  13241. if (channel > 14) {
  13242. mode_80211 = BIGDATA_DOT11_11A_MODE; /* 11a mode */
  13243. } else {
  13244. mode_80211 = BIGDATA_DOT11_11G_MODE; /* 11g mode */
  13245. }
  13246. }
  13247. if (bi->n_cap) {
  13248. /* check Rx MCS Map for HT */
  13249. nss = 0;
  13250. mode_80211 = BIGDATA_DOT11_11N_MODE;
  13251. for (i = 0; i < MAX_STREAMS_SUPPORTED; i++) {
  13252. int8 bitmap = DOT11_HT_MCS_RATE_MASK;
  13253. if (i == MAX_STREAMS_SUPPORTED-1) {
  13254. bitmap = DOT11_RATE_MASK;
  13255. }
  13256. if (bi->basic_mcs[i] & bitmap) {
  13257. nss++;
  13258. }
  13259. }
  13260. }
  13261. if (bi->vht_cap) {
  13262. nss = 0;
  13263. mode_80211 = BIGDATA_DOT11_11AC_MODE;
  13264. for (i = 1; i <= VHT_CAP_MCS_MAP_NSS_MAX; i++) {
  13265. mcs_map = VHT_MCS_MAP_GET_MCS_PER_SS(i, dtoh16(bi->vht_rxmcsmap));
  13266. if (mcs_map != VHT_CAP_MCS_MAP_NONE) {
  13267. nss++;
  13268. }
  13269. }
  13270. }
  13271. #if defined(WL11AX)
  13272. if (bi->he_cap) {
  13273. nss = 0;
  13274. mode_80211 = BIGDATA_DOT11_11AX_MODE;
  13275. for (i = 1; i <= HE_MCS_MAP_NSS_MAX; i++) {
  13276. mcs_map = HE_MCS_NSS_GET_MCS(i, dtoh32(bi->he_rxmcsmap));
  13277. if (mcs_map != HE_MCS_CODE_NONE) {
  13278. nss++;
  13279. }
  13280. }
  13281. }
  13282. #endif /* WL11AX */
  13283. if (nss) {
  13284. nss = nss - 1;
  13285. }
  13286. wiphy = bcmcfg_to_wiphy(cfg);
  13287. bss = CFG80211_GET_BSS(wiphy, NULL, eabuf, bi->SSID, bi->SSID_len);
  13288. if (!bss) {
  13289. WL_ERR(("Could not find the AP\n"));
  13290. } else {
  13291. GCC_DIAGNOSTIC_PUSH_SUPPRESS_CAST();
  13292. #if defined(WL_CFG80211_P2P_DEV_IF)
  13293. ie = (u8 *)bss->ies->data;
  13294. ie_len = bss->ies->len;
  13295. #else
  13296. ie = bss->information_elements;
  13297. ie_len = bss->len_information_elements;
  13298. #endif /* WL_CFG80211_P2P_DEV_IF */
  13299. GCC_DIAGNOSTIC_POP();
  13300. }
  13301. if (ie) {
  13302. ie_mu_mimo_cap = 0;
  13303. ie_11u_rel_num = 0;
  13304. if (bi->vht_cap) {
  13305. if ((vht_ie = bcm_parse_tlvs(ie, ie_len,
  13306. DOT11_MNG_VHT_CAP_ID)) != NULL) {
  13307. if (vht_ie->len >= VHT_CAP_IE_LEN) {
  13308. ie_mu_mimo_cap = (vht_ie->data[2] & 0x08) >> 3;
  13309. }
  13310. }
  13311. }
  13312. if ((interworking_ie = bcm_parse_tlvs(ie, ie_len,
  13313. DOT11_MNG_INTERWORKING_ID)) != NULL) {
  13314. if ((tlv_ie = bcm_parse_tlvs(ie, ie_len, DOT11_MNG_VS_ID)) != NULL) {
  13315. remained_len = ie_len;
  13316. while (tlv_ie) {
  13317. if (count > MAX_VNDR_IE_NUMBER)
  13318. break;
  13319. if (tlv_ie->id == DOT11_MNG_VS_ID) {
  13320. vndrie = (vndr_ie_t *) tlv_ie;
  13321. if (vndrie->len < (VNDR_IE_MIN_LEN + 1)) {
  13322. WL_ERR(("wl_get_bss_info: invalid vndr ie."
  13323. "length is too small %d\n",
  13324. vndrie->len));
  13325. break;
  13326. }
  13327. if (!bcmp(vndrie->oui,
  13328. (u8*)WiFiALL_OUI, WiFiALL_OUI_LEN) &&
  13329. (vndrie->data[0] == WiFiALL_OUI_TYPE))
  13330. {
  13331. WL_ERR(("Found Wi-FiAll OUI oui.\n"));
  13332. ie_11u_rel_num = vndrie->data[1];
  13333. ie_11u_rel_num = (ie_11u_rel_num & 0xf0)>>4;
  13334. ie_11u_rel_num += 1;
  13335. break;
  13336. }
  13337. }
  13338. count++;
  13339. tlv_ie = bcm_next_tlv(tlv_ie, &remained_len);
  13340. }
  13341. }
  13342. }
  13343. /* get 11kv information from ie of current bss */
  13344. wl_get_11kv_info(ie, ie_len, &support_11kv, &flag_11kv);
  13345. }
  13346. for (i = 0; i < bi->SSID_len; i++) {
  13347. if (bi->SSID[i] == ' ') {
  13348. bi->SSID[i] = '_';
  13349. }
  13350. }
  13351. /* 0 : None, 1 : OKC, 2 : FT, 3 : CCKM */
  13352. err = wldev_iovar_getint(dev, "wpa_auth", &val);
  13353. if (unlikely(err)) {
  13354. WL_ERR(("could not get wpa_auth (%d)\n", err));
  13355. snprintf(akm_str, sizeof(akm_str), "x"); /* Unknown */
  13356. } else {
  13357. WL_ERR(("wpa_auth val %d \n", val));
  13358. if (val & WPA2_AUTH_FT) {
  13359. snprintf(akm_str, sizeof(akm_str), "2");
  13360. } else if (val & (WPA_AUTH_UNSPECIFIED | WPA2_AUTH_UNSPECIFIED)) {
  13361. snprintf(akm_str, sizeof(akm_str), "1");
  13362. } else {
  13363. snprintf(akm_str, sizeof(akm_str), "0");
  13364. }
  13365. }
  13366. if (cfg->roam_offload) {
  13367. snprintf(roam_count_str, sizeof(roam_count_str), "x"); /* Unknown */
  13368. } else {
  13369. snprintf(roam_count_str, sizeof(roam_count_str), "%d", cfg->roam_count);
  13370. }
  13371. cfg->roam_count = 0;
  13372. WL_ERR(("BSSID:" MACDBG " SSID %s \n", MAC2STRDBG(eabuf), "*****"));
  13373. WL_ERR(("freq:%d, BW:%s, RSSI:%d dBm, Rate:%d Mbps, 11mode:%d, stream:%d,"
  13374. "MU-MIMO:%d, Passpoint:%d, SNR:%d, Noise:%d, \n"
  13375. "akm:%s, roam:%s, 11kv:%d/%d \n",
  13376. freq, wf_chspec_to_bw_str(bi->chanspec),
  13377. dtoh32(bi->RSSI), (rate / 2), mode_80211, nss,
  13378. ie_mu_mimo_cap, ie_11u_rel_num, bi->SNR, bi->phy_noise,
  13379. akm_str, roam_count_str, support_11kv, flag_11kv));
  13380. if (ie) {
  13381. snprintf(cfg->bss_info, GET_BSS_INFO_LEN,
  13382. MACOUI" %d %s %d %s %d %d %d %d %d %d %s %s %d %d",
  13383. MACOUI2STR(eabuf), freq, wf_chspec_to_bw_str(bi->chanspec),
  13384. dtoh32(bi->RSSI), rate_str, mode_80211, nss, ie_mu_mimo_cap,
  13385. ie_11u_rel_num, bi->SNR, bi->phy_noise, akm_str, roam_count_str,
  13386. support_11kv, flag_11kv);
  13387. } else {
  13388. /* ie_mu_mimo_cap and ie_11u_rel_num is unknow. */
  13389. snprintf(cfg->bss_info, GET_BSS_INFO_LEN,
  13390. MACOUI" %d %s %d %s %d %d x x %d %d %s %s x x",
  13391. MACOUI2STR(eabuf), freq, wf_chspec_to_bw_str(bi->chanspec),
  13392. dtoh32(bi->RSSI), rate_str, mode_80211, nss, bi->SNR,
  13393. bi->phy_noise, akm_str, roam_count_str);
  13394. }
  13395. CFG80211_PUT_BSS(wiphy, bss);
  13396. return 0;
  13397. }
  13398. s32 wl_cfg80211_get_bss_info(struct net_device *dev, char* cmd, int total_len)
  13399. {
  13400. struct bcm_cfg80211 *cfg = wl_get_cfg(dev);
  13401. if (cfg == NULL) {
  13402. return -1;
  13403. }
  13404. if (total_len < GET_BSS_INFO_LEN) {
  13405. WL_ERR(("wl_cfg80211_get_bss_info: Buffer insuffient %d\n", total_len));
  13406. return -1;
  13407. }
  13408. bzero(cmd, total_len);
  13409. memcpy(cmd, cfg->bss_info, GET_BSS_INFO_LEN);
  13410. WL_ERR_KERN(("cmd: %s \n", cmd));
  13411. return GET_BSS_INFO_LEN;
  13412. }
  13413. #endif /* DHD_ENABLE_BIGDATA_LOGGING */
  13414. void wl_cfg80211_disassoc(struct net_device *ndev, uint32 reason)
  13415. {
  13416. scb_val_t scbval;
  13417. s32 err;
  13418. struct bcm_cfg80211 *cfg = wl_get_cfg(ndev);
  13419. dhd_pub_t *dhdp = (dhd_pub_t *)(cfg->pub);
  13420. BCM_REFERENCE(cfg);
  13421. BCM_REFERENCE(dhdp);
  13422. DHD_STATLOG_CTRL(dhdp, ST(DISASSOC_INT_START),
  13423. dhd_net2idx(dhdp->info, ndev), WLAN_REASON_DEAUTH_LEAVING);
  13424. memset_s(&scbval, sizeof(scb_val_t), 0x0, sizeof(scb_val_t));
  13425. scbval.val = htod32(reason);
  13426. err = wldev_ioctl_set(ndev, WLC_DISASSOC, &scbval, sizeof(scb_val_t));
  13427. if (err < 0) {
  13428. WL_ERR(("WLC_DISASSOC error %d\n", err));
  13429. }
  13430. }
  13431. void wl_cfg80211_del_all_sta(struct net_device *ndev, uint32 reason)
  13432. {
  13433. struct net_device *dev;
  13434. struct bcm_cfg80211 *cfg = wl_get_cfg(ndev);
  13435. scb_val_t scb_val;
  13436. int err;
  13437. char mac_buf[MAX_NUM_OF_ASSOCIATED_DEV *
  13438. sizeof(struct ether_addr) + sizeof(uint)] = {0};
  13439. struct maclist *assoc_maclist = (struct maclist *)mac_buf;
  13440. int num_associated = 0;
  13441. dev = ndev_to_wlc_ndev(ndev, cfg);
  13442. if (p2p_is_on(cfg)) {
  13443. /* Suspend P2P discovery search-listen to prevent it from changing the
  13444. * channel.
  13445. */
  13446. if ((wl_cfgp2p_discover_enable_search(cfg, false)) < 0) {
  13447. WL_ERR(("Can not disable discovery mode\n"));
  13448. return;
  13449. }
  13450. }
  13451. assoc_maclist->count = MAX_NUM_OF_ASSOCIATED_DEV;
  13452. err = wldev_ioctl_get(ndev, WLC_GET_ASSOCLIST,
  13453. assoc_maclist, sizeof(mac_buf));
  13454. if (err < 0)
  13455. WL_ERR(("WLC_GET_ASSOCLIST error %d\n", err));
  13456. else
  13457. num_associated = assoc_maclist->count;
  13458. memset(scb_val.ea.octet, 0xff, ETHER_ADDR_LEN);
  13459. scb_val.val = DOT11_RC_DEAUTH_LEAVING;
  13460. scb_val.val = htod32(reason);
  13461. err = wldev_ioctl_set(dev, WLC_SCB_DEAUTHENTICATE_FOR_REASON, &scb_val,
  13462. sizeof(scb_val_t));
  13463. if (err < 0) {
  13464. WL_ERR(("WLC_SCB_DEAUTHENTICATE_FOR_REASON err %d\n", err));
  13465. }
  13466. if (num_associated > 0)
  13467. wl_delay(400);
  13468. return;
  13469. }
  13470. /* API to handle the Deauth from the AP.
  13471. * For now we are deleting the PMKID cache in DHD/FW
  13472. * in case of current connection is using SAE authnetication
  13473. */
  13474. static s32
  13475. wl_cfg80211_handle_deauth_ind(struct bcm_cfg80211 *cfg, struct net_device *ndev,
  13476. const wl_event_msg_t *e, void *data)
  13477. {
  13478. int err = BCME_OK;
  13479. #ifdef WL_SAE
  13480. uint8 bssid[ETHER_ADDR_LEN];
  13481. struct cfg80211_pmksa pmksa;
  13482. s32 val = 0;
  13483. err = wldev_iovar_getint(ndev, "wpa_auth", &val);
  13484. if (unlikely(err)) {
  13485. WL_ERR(("could not get wpa_auth (%d)\n", err));
  13486. goto done;
  13487. }
  13488. if (val == WPA3_AUTH_SAE_PSK) {
  13489. (void)memcpy_s(bssid, ETHER_ADDR_LEN,
  13490. (const uint8*)&e->addr, ETHER_ADDR_LEN);
  13491. memset_s(&pmksa, sizeof(pmksa), 0, sizeof(pmksa));
  13492. pmksa.bssid = bssid;
  13493. WL_INFORM_MEM(("Deleting the PMKSA for SAE AP "MACDBG,
  13494. MAC2STRDBG(e->addr.octet)));
  13495. wl_cfg80211_del_pmksa(cfg->wdev->wiphy, ndev, &pmksa);
  13496. }
  13497. done:
  13498. #endif /* WL_SAE */
  13499. return err;
  13500. }
  13501. static void
  13502. wl_cache_assoc_resp_ies(struct bcm_cfg80211 *cfg, struct net_device *ndev,
  13503. const wl_event_msg_t *e, void *data)
  13504. {
  13505. struct wl_connect_info *conn_info = wl_to_conn(cfg);
  13506. u32 datalen = ntoh32(e->datalen);
  13507. u32 event_type = ntoh32(e->event_type);
  13508. if (datalen > VNDR_IE_MIN_LEN &&
  13509. datalen < VNDR_IE_MAX_LEN &&
  13510. data) {
  13511. conn_info->resp_ie_len = datalen;
  13512. WL_DBG((" assoc resp IES len = %d\n", conn_info->resp_ie_len));
  13513. bzero(conn_info->resp_ie, sizeof(conn_info->resp_ie));
  13514. (void)memcpy_s(conn_info->resp_ie, sizeof(conn_info->resp_ie),
  13515. data, datalen);
  13516. WL_INFORM_MEM(("[%s] copied assoc resp ies, sent to upper layer:"
  13517. "event %d reason=%d ie_len=%d from " MACDBG "\n",
  13518. ndev->name, event_type, ntoh32(e->reason), datalen,
  13519. MAC2STRDBG((const u8*)(&e->addr))));
  13520. }
  13521. }
  13522. static s32
  13523. wl_notify_connect_status(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev,
  13524. const wl_event_msg_t *e, void *data)
  13525. {
  13526. bool act;
  13527. struct net_device *ndev = NULL;
  13528. s32 err = 0;
  13529. u32 event = ntoh32(e->event_type);
  13530. u32 datalen = ntoh32(e->datalen);
  13531. struct wiphy *wiphy = NULL;
  13532. struct cfg80211_bss *bss = NULL;
  13533. struct wlc_ssid *ssid = NULL;
  13534. u8 *bssid = 0;
  13535. s32 bssidx = 0;
  13536. u8 *ie_ptr = NULL;
  13537. uint32 ie_len = 0;
  13538. #ifdef WL_ANALYTICS
  13539. struct parsed_vndr_ies disco_vndr_ie;
  13540. struct parsed_vndr_ie_info *vndrie_info = NULL;
  13541. uint32 i = 0;
  13542. #endif /* WL_ANALYTICS */
  13543. dhd_pub_t *dhdp;
  13544. u32 mode;
  13545. int vndr_oui_num = 0;
  13546. char vndr_oui[MAX_VNDR_OUI_STR_LEN] = {0, };
  13547. bool loc_gen = false;
  13548. #ifdef DHD_LOSSLESS_ROAMING
  13549. struct wl_security *sec;
  13550. #endif /* DHD_LOSSLESS_ROAMING */
  13551. ndev = cfgdev_to_wlc_ndev(cfgdev, cfg);
  13552. #ifdef DHD_LOSSLESS_ROAMING
  13553. sec = wl_read_prof(cfg, ndev, WL_PROF_SEC);
  13554. #endif /* DHD_LOSSLESS_ROAMING */
  13555. dhdp = (dhd_pub_t *)(cfg->pub);
  13556. BCM_REFERENCE(dhdp);
  13557. mode = wl_get_mode_by_netdev(cfg, ndev);
  13558. /* Push link events to upper layer log */
  13559. SUPP_LOG(("[%s] Mode:%d event:%d status:0x%x reason:%d\n",
  13560. ndev->name, mode, ntoh32(e->event_type),
  13561. ntoh32(e->status), ntoh32(e->reason)));
  13562. if (mode == WL_MODE_AP) {
  13563. err = wl_notify_connect_status_ap(cfg, ndev, e, data);
  13564. } else if (mode == WL_MODE_IBSS) {
  13565. err = wl_notify_connect_status_ibss(cfg, ndev, e, data);
  13566. } else if (mode == WL_MODE_BSS) {
  13567. WL_INFORM_MEM(("[%s] Mode BSS. event:%d status:%d reason:%d\n",
  13568. ndev->name, ntoh32(e->event_type),
  13569. ntoh32(e->status), ntoh32(e->reason)));
  13570. if (!wl_get_drv_status(cfg, CFG80211_CONNECT, ndev)) {
  13571. /* Join attempt via non-cfg80211 interface.
  13572. * Don't send resultant events to cfg80211
  13573. * layer
  13574. */
  13575. WL_INFORM_MEM(("Event received in non-cfg80211"
  13576. " connect state. Ignore\n"));
  13577. return BCME_OK;
  13578. }
  13579. if (event == WLC_E_ASSOC || event == WLC_E_AUTH) {
  13580. wl_get_auth_assoc_status(cfg, ndev, e, data);
  13581. return 0;
  13582. }
  13583. if (event == WLC_E_ASSOC_RESP_IE) {
  13584. if (ntoh32(e->status) != WLC_E_STATUS_SUCCESS) {
  13585. wl_cache_assoc_resp_ies(cfg, ndev, e, data);
  13586. }
  13587. return 0;
  13588. }
  13589. #if defined(OEM_ANDROID)
  13590. DHD_DISABLE_RUNTIME_PM((dhd_pub_t *)cfg->pub);
  13591. #endif // endif
  13592. if (wl_is_linkup(cfg, e, ndev)) {
  13593. wl_link_up(cfg);
  13594. act = true;
  13595. if (!wl_get_drv_status(cfg, DISCONNECTING, ndev)) {
  13596. WL_INFORM_MEM(("[%s] link up for bssid " MACDBG "\n",
  13597. ndev->name, MAC2STRDBG((const u8*)(&e->addr))));
  13598. if ((event == WLC_E_LINK) &&
  13599. (ntoh16(e->flags) & WLC_EVENT_MSG_LINK) &&
  13600. !wl_get_drv_status(cfg, CONNECTED, ndev) &&
  13601. !wl_get_drv_status(cfg, CONNECTING, ndev)) {
  13602. WL_INFORM_MEM(("link up in non-connected/"
  13603. "non-connecting state\n"));
  13604. wl_cfg80211_disassoc(ndev, WLAN_REASON_DEAUTH_LEAVING);
  13605. return BCME_OK;
  13606. }
  13607. #ifdef WL_WPS_SYNC
  13608. /* Avoid invocation for Roam cases */
  13609. if ((event == WLC_E_LINK) &&
  13610. !wl_get_drv_status(cfg, CONNECTED, ndev)) {
  13611. wl_wps_session_update(ndev,
  13612. WPS_STATE_LINKUP, e->addr.octet);
  13613. }
  13614. #endif /* WL_WPS_SYNC */
  13615. #ifdef DHD_EVENT_LOG_FILTER
  13616. if (event == WLC_E_LINK && ndev == bcmcfg_to_prmry_ndev(cfg)) {
  13617. int roam = FALSE;
  13618. uint8 eth_addr[ETHER_ADDR_LEN];
  13619. if (TRUE &&
  13620. #ifdef DHD_LOSSLESS_ROAMING
  13621. !cfg->roam_offload &&
  13622. #endif /* DHD_LOSSLESS_ROAMING */
  13623. wl_get_drv_status(cfg, CONNECTED, ndev)) {
  13624. roam = TRUE;
  13625. }
  13626. memcpy(eth_addr, &(e->addr), ETHER_ADDR_LEN);
  13627. dhd_event_log_filter_notify_connect_done(dhdp,
  13628. eth_addr, roam);
  13629. }
  13630. #endif /* DHD_EVENT_LOG_FILTER */
  13631. #ifdef DHD_LOSSLESS_ROAMING
  13632. if (event == WLC_E_LINK &&
  13633. !cfg->roam_offload &&
  13634. !IS_AKM_SUITE_FT(sec) &&
  13635. wl_get_drv_status(cfg, CONNECTED, ndev))
  13636. wl_bss_roaming_done(cfg, ndev, e, data);
  13637. #endif /* DHD_LOSSLESS_ROAMING */
  13638. wl_update_prof(cfg, ndev, e, &act, WL_PROF_ACT);
  13639. wl_bss_connect_done(cfg, ndev, e, data, true);
  13640. if (ndev == bcmcfg_to_prmry_ndev(cfg)) {
  13641. vndr_oui_num = wl_vndr_ies_get_vendor_oui(cfg,
  13642. ndev, vndr_oui, ARRAY_SIZE(vndr_oui));
  13643. if (vndr_oui_num > 0) {
  13644. WL_INFORM_MEM(("[%s] vendor oui: %s\n",
  13645. ndev->name, vndr_oui));
  13646. }
  13647. }
  13648. WL_DBG(("joined in BSS network \"%s\"\n",
  13649. ((struct wlc_ssid *)wl_read_prof(cfg, ndev,
  13650. WL_PROF_SSID))->SSID));
  13651. #ifdef WBTEXT
  13652. if (ndev->ieee80211_ptr->iftype == NL80211_IFTYPE_STATION &&
  13653. dhdp->wbtext_support && event == WLC_E_SET_SSID) {
  13654. /* set wnm_keepalives_max_idle after association */
  13655. wl_cfg80211_wbtext_set_wnm_maxidle(cfg, ndev);
  13656. }
  13657. #endif /* WBTEXT */
  13658. }
  13659. wl_update_prof(cfg, ndev, e, &act, WL_PROF_ACT);
  13660. wl_update_prof(cfg, ndev, NULL, (const void *)&e->addr, WL_PROF_BSSID);
  13661. #if defined(IGUANA_LEGACY_CHIPS)
  13662. } else if (wl_is_linkdown(cfg, e)) {
  13663. /* Lagacy chips like 4350 sends faliure status for WLC_E_SET_SSID even in
  13664. * case of successful connection. Since these firmware are in production,
  13665. * firmware change is avoided.
  13666. */
  13667. #else
  13668. } else if (wl_is_linkdown(cfg, e) ||
  13669. ((event == WLC_E_SET_SSID) &&
  13670. (ntoh32(e->status) != WLC_E_STATUS_SUCCESS) &&
  13671. (wl_get_drv_status(cfg, CONNECTED, ndev)))) {
  13672. #endif // endif
  13673. if (wl_is_linkdown(cfg, e)) {
  13674. /* Clear IEs for disaasoc */
  13675. if ((bssidx = wl_get_bssidx_by_wdev(cfg,
  13676. ndev->ieee80211_ptr)) < 0) {
  13677. WL_ERR(("Find index failed\n"));
  13678. } else {
  13679. WL_ERR(("link down--clearing disconnect IEs\n"));
  13680. if ((err = wl_cfg80211_set_mgmt_vndr_ies(cfg,
  13681. ndev_to_cfgdev(ndev), bssidx, VNDR_IE_DISASSOC_FLAG,
  13682. NULL, 0)) != BCME_OK) {
  13683. WL_ERR(("Failed to clear ies err = %d\n", err));
  13684. }
  13685. }
  13686. }
  13687. WL_INFORM_MEM(("link down. connection state bit status: [%u:%u:%u:%u]\n",
  13688. wl_get_drv_status(cfg, CONNECTING, ndev),
  13689. wl_get_drv_status(cfg, CONNECTED, ndev),
  13690. wl_get_drv_status(cfg, DISCONNECTING, ndev),
  13691. wl_get_drv_status(cfg, NESTED_CONNECT, ndev)));
  13692. #ifdef WL_WPS_SYNC
  13693. {
  13694. u8 wps_state;
  13695. if ((event == WLC_E_SET_SSID) &&
  13696. (ntoh32(e->status) != WLC_E_STATUS_SUCCESS)) {
  13697. /* connect fail */
  13698. wps_state = WPS_STATE_CONNECT_FAIL;
  13699. } else {
  13700. wps_state = WPS_STATE_LINKDOWN;
  13701. }
  13702. if (wl_wps_session_update(ndev,
  13703. wps_state, e->addr.octet) == BCME_UNSUPPORTED) {
  13704. /* Unexpected event. Ignore it. */
  13705. return 0;
  13706. }
  13707. }
  13708. #endif /* WL_WPS_SYNC */
  13709. if (wl_get_drv_status(cfg, DISCONNECTING, ndev) &&
  13710. (wl_get_drv_status(cfg, NESTED_CONNECT, ndev) ||
  13711. wl_get_drv_status(cfg, CONNECTING, ndev))) {
  13712. /* wl_cfg80211_connect was called before 'DISCONNECTING' was
  13713. * cleared. Deauth/Link down event is caused by WLC_DISASSOC
  13714. * command issued from the wl_cfg80211_connect context. Ignore
  13715. * the event to avoid pre-empting the current connection
  13716. */
  13717. WL_DBG(("Nested connection case. Drop event. \n"));
  13718. wl_clr_drv_status(cfg, NESTED_CONNECT, ndev);
  13719. wl_clr_drv_status(cfg, DISCONNECTING, ndev);
  13720. /* Not in 'CONNECTED' state, clear it */
  13721. wl_clr_drv_status(cfg, CONNECTED, ndev);
  13722. return 0;
  13723. }
  13724. if (wl_get_drv_status(cfg, CONNECTED, ndev)) {
  13725. wl_flush_fw_log_buffer(bcmcfg_to_prmry_ndev(cfg),
  13726. FW_LOGSET_MASK_ALL);
  13727. }
  13728. #ifdef DHD_LOSSLESS_ROAMING
  13729. wl_del_roam_timeout(cfg);
  13730. #endif // endif
  13731. #ifdef P2PLISTEN_AP_SAMECHN
  13732. if (ndev == bcmcfg_to_prmry_ndev(cfg)) {
  13733. wl_cfg80211_set_p2p_resp_ap_chn(ndev, 0);
  13734. cfg->p2p_resp_apchn_status = false;
  13735. WL_DBG(("p2p_resp_apchn_status Turn OFF \n"));
  13736. }
  13737. #endif /* P2PLISTEN_AP_SAMECHN */
  13738. wl_cfg80211_cancel_scan(cfg);
  13739. #if defined(DHD_ENABLE_BIGDATA_LOGGING)
  13740. if (wl_get_drv_status(cfg, CONNECTED, ndev)) {
  13741. wl_get_bss_info(cfg, ndev, &e->addr);
  13742. }
  13743. #endif /* DHD_ENABLE_BIGDATA_LOGGING */
  13744. /* Explicitly calling unlink to remove BSS in CFG */
  13745. wiphy = bcmcfg_to_wiphy(cfg);
  13746. ssid = (struct wlc_ssid *)wl_read_prof(cfg, ndev, WL_PROF_SSID);
  13747. bssid = (u8 *)wl_read_prof(cfg, ndev, WL_PROF_BSSID);
  13748. if (ssid && bssid) {
  13749. bss = CFG80211_GET_BSS(wiphy, NULL, bssid,
  13750. ssid->SSID, ssid->SSID_len);
  13751. if (bss) {
  13752. cfg80211_unlink_bss(wiphy, bss);
  13753. CFG80211_PUT_BSS(wiphy, bss);
  13754. }
  13755. }
  13756. if (wl_get_drv_status(cfg, CONNECTED, ndev)) {
  13757. scb_val_t scbval;
  13758. u8 *curbssid = wl_read_prof(cfg, ndev, WL_PROF_BSSID);
  13759. uint32 reason = 0;
  13760. struct ether_addr bssid_dongle = {{0, 0, 0, 0, 0, 0}};
  13761. struct ether_addr bssid_null = {{0, 0, 0, 0, 0, 0}};
  13762. if (event == WLC_E_DEAUTH_IND || event == WLC_E_DISASSOC_IND) {
  13763. reason = ntoh32(e->reason);
  13764. if (reason > WLC_E_DEAUTH_MAX_REASON) {
  13765. WL_ERR(("Event %d original reason is %d, "
  13766. "changed 0xFF\n", event, reason));
  13767. reason = WLC_E_DEAUTH_MAX_REASON;
  13768. }
  13769. wl_cfg80211_handle_deauth_ind(cfg, ndev, e, data);
  13770. }
  13771. #ifdef SET_SSID_FAIL_CUSTOM_RC
  13772. if ((event == WLC_E_SET_SSID) &&
  13773. (ntoh32(e->status) == WLC_E_STATUS_TIMEOUT)) {
  13774. reason = SET_SSID_FAIL_CUSTOM_RC;
  13775. }
  13776. #endif /* SET_SSID_FAIL_CUSTOM_RC */
  13777. /* roam offload does not sync BSSID always, get it from dongle */
  13778. if (cfg->roam_offload) {
  13779. bzero(&bssid_dongle, sizeof(bssid_dongle));
  13780. if (wldev_ioctl_get(ndev, WLC_GET_BSSID, &bssid_dongle,
  13781. sizeof(bssid_dongle)) == BCME_OK) {
  13782. /* if not roam case, it would return null bssid */
  13783. if (memcmp(&bssid_dongle, &bssid_null,
  13784. ETHER_ADDR_LEN) != 0) {
  13785. curbssid = (u8 *)&bssid_dongle;
  13786. }
  13787. }
  13788. }
  13789. if (memcmp(curbssid, &e->addr, ETHER_ADDR_LEN) != 0) {
  13790. bool fw_assoc_state = TRUE;
  13791. dhd_pub_t *dhd = (dhd_pub_t *)cfg->pub;
  13792. fw_assoc_state = dhd_is_associated(dhd, e->ifidx, &err);
  13793. if (!fw_assoc_state) {
  13794. WL_ERR(("Event sends up even different BSSID"
  13795. " cur: " MACDBG " event: " MACDBG"\n",
  13796. MAC2STRDBG(curbssid),
  13797. MAC2STRDBG((const u8*)(&e->addr))));
  13798. } else {
  13799. WL_ERR(("BSSID of event is not the connected BSSID"
  13800. "(ignore it) cur: " MACDBG
  13801. " event: " MACDBG"\n",
  13802. MAC2STRDBG(curbssid),
  13803. MAC2STRDBG((const u8*)(&e->addr))));
  13804. return 0;
  13805. }
  13806. }
  13807. #ifdef DBG_PKT_MON
  13808. /* Stop packet monitor */
  13809. if (ndev == bcmcfg_to_prmry_ndev(cfg)) {
  13810. DHD_DBG_PKT_MON_STOP(dhdp);
  13811. }
  13812. #endif /* DBG_PKT_MON */
  13813. /* clear RSSI monitor, framework will set new cfg */
  13814. #ifdef RSSI_MONITOR_SUPPORT
  13815. dhd_dev_set_rssi_monitor_cfg(bcmcfg_to_prmry_ndev(cfg),
  13816. FALSE, 0, 0);
  13817. #endif /* RSSI_MONITOR_SUPPORT */
  13818. wl_clr_drv_status(cfg, CONNECTED, ndev);
  13819. if (!wl_get_drv_status(cfg, DISCONNECTING, ndev)) {
  13820. DHD_STATLOG_CTRL(dhdp, ST(DISASSOC_INT_START),
  13821. dhd_net2idx(dhdp->info, ndev),
  13822. WLAN_REASON_DEAUTH_LEAVING);
  13823. /* To make sure disconnect, explictly send dissassoc
  13824. * for BSSID 00:00:00:00:00:00 issue
  13825. */
  13826. scbval.val = WLAN_REASON_DEAUTH_LEAVING;
  13827. WL_INFORM_MEM(("clear fw state\n"));
  13828. memcpy(&scbval.ea, curbssid, ETHER_ADDR_LEN);
  13829. scbval.val = htod32(scbval.val);
  13830. err = wldev_ioctl_set(ndev, WLC_DISASSOC, &scbval,
  13831. sizeof(scb_val_t));
  13832. if (err < 0) {
  13833. WL_ERR(("WLC_DISASSOC error %d\n", err));
  13834. err = 0;
  13835. }
  13836. }
  13837. if (wl_get_drv_status(cfg, DISCONNECTING, ndev)) {
  13838. loc_gen = true;
  13839. }
  13840. WL_INFORM_MEM(("[%s] Indicate disconnect event to upper layer. "
  13841. "event: %d reason=%d from " MACDBG "\n",
  13842. ndev->name, event, ntoh32(e->reason),
  13843. MAC2STRDBG((const u8*)(&e->addr))));
  13844. #ifdef WBTEXT
  13845. /* when STA was disconnected, clear join pref and set wbtext */
  13846. if (ndev->ieee80211_ptr->iftype == NL80211_IFTYPE_STATION &&
  13847. dhdp->wbtext_policy
  13848. == WL_BSSTRANS_POLICY_PRODUCT_WBTEXT) {
  13849. char smbuf[WLC_IOCTL_SMLEN];
  13850. char clear[] = { 0x01, 0x02, 0x00, 0x00, 0x03,
  13851. 0x02, 0x00, 0x00, 0x04, 0x02, 0x00, 0x00 };
  13852. if ((err = wldev_iovar_setbuf(ndev, "join_pref",
  13853. clear, sizeof(clear), smbuf,
  13854. sizeof(smbuf), NULL))
  13855. == BCME_OK) {
  13856. if ((err = wldev_iovar_setint(ndev,
  13857. "wnm_bsstrans_resp",
  13858. dhdp->wbtext_policy))
  13859. == BCME_OK) {
  13860. wl_cfg80211_wbtext_set_default(ndev);
  13861. } else {
  13862. WL_ERR(("wl_notify_connect_status:"
  13863. " Failed to"
  13864. " set wbtext = %d\n",
  13865. err));
  13866. }
  13867. } else {
  13868. WL_ERR(("wl_notify_connect_status:"
  13869. " Failed to clear join pref = %d\n",
  13870. err));
  13871. }
  13872. wl_cfg80211_wbtext_clear_bssid_list(cfg);
  13873. }
  13874. #endif /* WBTEXT */
  13875. DHD_STATLOG_CTRL(dhdp, ST(DISASSOC_DONE),
  13876. dhd_net2idx(dhdp->info, ndev), reason);
  13877. /* Send up deauth and clear states */
  13878. /*
  13879. * FW sends body and body len as a part of deauth
  13880. * and disassoc events (WLC_E_DISASSOC_IND, WLC_E_DEAUTH_IND)
  13881. * The VIEs sits after reason code in the body. Reason code is
  13882. * 2 bytes long.
  13883. */
  13884. WL_DBG(("recv disconnect ies ie_len = %d\n", ie_len));
  13885. if (event == WLC_E_DISASSOC_IND || event == WLC_E_DEAUTH_IND) {
  13886. if ((datalen > DOT11_DISCONNECT_RC) &&
  13887. datalen < (VNDR_IE_MAX_LEN + DOT11_DISCONNECT_RC) &&
  13888. data) {
  13889. ie_ptr = (uchar*)data + DOT11_DISCONNECT_RC;
  13890. ie_len = datalen - DOT11_DISCONNECT_RC;
  13891. }
  13892. } else if (event == WLC_E_LINK &&
  13893. ntoh32(e->reason) == WLC_E_LINK_BCN_LOSS) {
  13894. #ifdef WL_ANALYTICS
  13895. /*
  13896. * In case of linkdown, FW sends prb rsp IEs. Disco VIE
  13897. * are appended with prb rsp ies. Remove prb rsp IES and
  13898. * send disco vie to upper layer.
  13899. * Disco VIE has fixed len of 11 octets.
  13900. * As per SS spec.(2 octet header + 9 octet VIE)
  13901. */
  13902. if (datalen < (VNDR_IE_MAX_LEN + DOT11_DISCONNECT_RC) &&
  13903. datalen >= DOT11_DISCONNECT_RC &&
  13904. ((err = wl_cfg80211_parse_vndr_ies(
  13905. (const u8 *)data, datalen,
  13906. &disco_vndr_ie)) == BCME_OK)) {
  13907. for (i = 0; i < disco_vndr_ie.count; i++) {
  13908. vndrie_info = &disco_vndr_ie.ie_info[i];
  13909. if ((vndrie_info->vndrie.id ==
  13910. 0xDD) && (!memcmp(
  13911. vndrie_info->vndrie.oui,
  13912. SSE_OUI, DOT11_OUI_LEN)) &&
  13913. (vndrie_info->vndrie.data[0] ==
  13914. VENDOR_ENTERPRISE_STA_OUI_TYPE)) {
  13915. ie_ptr = (u8 *)vndrie_info->ie_ptr;
  13916. ie_len = vndrie_info->ie_len;
  13917. }
  13918. }
  13919. }
  13920. #endif /* WL_ANALYTICS */
  13921. }
  13922. CFG80211_DISCONNECTED(ndev, reason, ie_ptr, ie_len,
  13923. loc_gen, GFP_KERNEL);
  13924. WL_INFORM_MEM(("[%s] Disconnect event sent to upper layer"
  13925. "event:%d reason=%d ie_len=%d from " MACDBG "\n",
  13926. ndev->name, event, ntoh32(e->reason), ie_len,
  13927. MAC2STRDBG((const u8*)(&e->addr))));
  13928. /* Wait for status to be cleared to prevent race condition
  13929. * issues with connect context
  13930. */
  13931. wl_cfg80211_disconnect_state_sync(cfg, ndev);
  13932. wl_link_down(cfg);
  13933. wl_init_prof(cfg, ndev);
  13934. }
  13935. else if (wl_get_drv_status(cfg, CONNECTING, ndev)) {
  13936. DHD_STATLOG_CTRL(dhdp, ST(DISASSOC_INT_START),
  13937. dhd_net2idx(dhdp->info, ndev), 0);
  13938. WL_INFORM_MEM(("link down, during connecting\n"));
  13939. /* Issue WLC_DISASSOC to prevent FW roam attempts.
  13940. * Do not issue WLC_DISASSOC again if the linkdown is
  13941. * generated due to local disassoc, to avoid connect-disconnect
  13942. * loop.
  13943. */
  13944. if (!((event == WLC_E_LINK) &&
  13945. (ntoh32(e->reason) == WLC_E_LINK_DISASSOC) &&
  13946. (ntoh32(e->status) == WLC_E_STATUS_SUCCESS))) {
  13947. err = wldev_ioctl_set(ndev, WLC_DISASSOC, NULL, 0);
  13948. if (err < 0) {
  13949. WL_ERR(("CONNECTING state,"
  13950. " WLC_DISASSOC error %d\n",
  13951. err));
  13952. err = 0;
  13953. }
  13954. #ifdef ESCAN_RESULT_PATCH
  13955. if ((memcmp(connect_req_bssid, broad_bssid,
  13956. ETHER_ADDR_LEN) == 0) ||
  13957. (memcmp(&e->addr, broad_bssid,
  13958. ETHER_ADDR_LEN) == 0) ||
  13959. (memcmp(&e->addr, connect_req_bssid,
  13960. ETHER_ADDR_LEN) == 0))
  13961. /* In case this event comes while associating
  13962. * another AP
  13963. */
  13964. #endif /* ESCAN_RESULT_PATCH */
  13965. wl_bss_connect_done(cfg, ndev, e, data, false);
  13966. }
  13967. }
  13968. wl_clr_drv_status(cfg, DISCONNECTING, ndev);
  13969. /* if link down, bsscfg is diabled */
  13970. if (ndev != bcmcfg_to_prmry_ndev(cfg))
  13971. complete(&cfg->iface_disable);
  13972. #ifdef REVERSE_AIFSN
  13973. ((dhd_pub_t *)cfg->pub)->aifsn_reverse = FALSE;
  13974. #endif /* REVERSE_AIFSN */
  13975. #ifdef WLTDLS
  13976. /* re-enable TDLS if the number of connected interfaces
  13977. * is less than 2.
  13978. */
  13979. wl_cfg80211_tdls_config(cfg, TDLS_STATE_DISCONNECT, false);
  13980. #endif /* WLTDLS */
  13981. } else if (wl_is_nonetwork(cfg, e)) {
  13982. WL_ERR(("connect failed event=%d e->status %d e->reason %d \n",
  13983. event, (int)ntoh32(e->status), (int)ntoh32(e->reason)));
  13984. #ifdef WL_WPS_SYNC
  13985. if (wl_wps_session_update(ndev,
  13986. WPS_STATE_CONNECT_FAIL, e->addr.octet) == BCME_UNSUPPORTED) {
  13987. /* Unexpected event. Ignore it. */
  13988. return 0;
  13989. }
  13990. #endif /* WL_WPS_SYNC */
  13991. #if defined(DHD_ENABLE_BIGDATA_LOGGING)
  13992. if (event == WLC_E_SET_SSID) {
  13993. wl_get_connect_failed_status(cfg, e);
  13994. }
  13995. #endif /* DHD_ENABLE_BIGDATA_LOGGING */
  13996. /* Dump FW preserve buffer content */
  13997. wl_flush_fw_log_buffer(ndev, FW_LOGSET_MASK_ALL);
  13998. /* Clean up any pending scan request */
  13999. wl_cfg80211_cancel_scan(cfg);
  14000. if (wl_get_drv_status(cfg, CONNECTING, ndev)) {
  14001. if (!wl_get_drv_status(cfg, DISCONNECTING, ndev)) {
  14002. WL_INFORM_MEM(("wl dissassoc\n"));
  14003. err = wldev_ioctl_set(ndev, WLC_DISASSOC, NULL, 0);
  14004. if (err < 0) {
  14005. WL_ERR(("WLC_DISASSOC error %d\n", err));
  14006. err = 0;
  14007. }
  14008. } else {
  14009. WL_DBG(("connect fail. clear disconnecting bit\n"));
  14010. wl_clr_drv_status(cfg, DISCONNECTING, ndev);
  14011. }
  14012. wl_bss_connect_done(cfg, ndev, e, data, false);
  14013. wl_clr_drv_status(cfg, CONNECTING, ndev);
  14014. WL_INFORM_MEM(("connect fail reported\n"));
  14015. }
  14016. } else {
  14017. WL_DBG(("wl_notify_connect_status nothing\n"));
  14018. }
  14019. #if defined(OEM_ANDROID)
  14020. DHD_ENABLE_RUNTIME_PM((dhd_pub_t *)cfg->pub);
  14021. #endif // endif
  14022. } else {
  14023. WL_ERR(("Invalid ndev status %d\n", wl_get_mode_by_netdev(cfg, ndev)));
  14024. }
  14025. return err;
  14026. }
  14027. #ifdef WL_RELMCAST
  14028. void wl_cfg80211_set_rmc_pid(struct net_device *dev, int pid)
  14029. {
  14030. struct bcm_cfg80211 *cfg = wl_get_cfg(dev);
  14031. if (pid > 0)
  14032. cfg->rmc_event_pid = pid;
  14033. WL_DBG(("set pid for rmc event : pid=%d\n", pid));
  14034. }
  14035. #endif /* WL_RELMCAST */
  14036. #ifdef WLAIBSS
  14037. void wl_cfg80211_set_txfail_pid(struct net_device *dev, int pid)
  14038. {
  14039. struct bcm_cfg80211 *cfg = wl_get_cfg(dev);
  14040. if (pid > 0)
  14041. cfg->aibss_txfail_pid = pid;
  14042. WL_DBG(("set pid for aibss fail event : pid=%d\n", pid));
  14043. }
  14044. static s32
  14045. wl_notify_aibss_txfail(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev,
  14046. const wl_event_msg_t *e, void *data)
  14047. {
  14048. u32 evt = ntoh32(e->event_type);
  14049. int ret = -1;
  14050. #ifdef PCIE_FULL_DONGLE
  14051. dhd_pub_t *dhd = (dhd_pub_t *)(cfg->pub);
  14052. u32 reason = ntoh32(e->reason);
  14053. #endif // endif
  14054. if (cfg->aibss_txfail_pid != 0) {
  14055. #ifdef PCIE_FULL_DONGLE
  14056. if (reason == AIBSS_PEER_FREE) {
  14057. uint8 ifindex;
  14058. wl_event_msg_t event;
  14059. bzero(&event, sizeof(wl_event_msg_t));
  14060. memcpy(&event, e, sizeof(wl_event_msg_t));
  14061. ifindex = (uint8)dhd_ifname2idx(dhd->info, event.ifname);
  14062. WL_INFORM_MEM(("Peer freed. Flow rings delete for peer.\n"));
  14063. dhd_flow_rings_delete_for_peer(dhd, ifindex,
  14064. (void *)&event.addr.octet[0]);
  14065. return 0;
  14066. }
  14067. #endif // endif
  14068. ret = wl_netlink_send_msg(cfg->aibss_txfail_pid, AIBSS_EVENT_TXFAIL,
  14069. cfg->aibss_txfail_seq++, &e->addr, ETHER_ADDR_LEN);
  14070. }
  14071. WL_DBG(("txfail : evt=%d, pid=%d, ret=%d, mac=" MACF "\n",
  14072. evt, cfg->aibss_txfail_pid, ret, CONST_ETHERP_TO_MACF(&e->addr)));
  14073. return ret;
  14074. }
  14075. #endif /* WLAIBSS */
  14076. #ifdef WL_RELMCAST
  14077. static s32
  14078. wl_notify_rmc_status(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev,
  14079. const wl_event_msg_t *e, void *data)
  14080. {
  14081. u32 evt = ntoh32(e->event_type);
  14082. u32 reason = ntoh32(e->reason);
  14083. int ret = -1;
  14084. switch (reason) {
  14085. case WLC_E_REASON_RMC_AR_LOST:
  14086. case WLC_E_REASON_RMC_AR_NO_ACK:
  14087. if (cfg->rmc_event_pid != 0) {
  14088. ret = wl_netlink_send_msg(cfg->rmc_event_pid,
  14089. RMC_EVENT_LEADER_CHECK_FAIL,
  14090. cfg->rmc_event_seq++, NULL, 0);
  14091. }
  14092. break;
  14093. default:
  14094. break;
  14095. }
  14096. WL_DBG(("rmcevent : evt=%d, pid=%d, ret=%d\n", evt, cfg->rmc_event_pid, ret));
  14097. return ret;
  14098. }
  14099. #endif /* WL_RELMCAST */
  14100. #ifdef GSCAN_SUPPORT
  14101. static s32
  14102. wl_handle_roam_exp_event(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev,
  14103. const wl_event_msg_t *e, void *data)
  14104. {
  14105. struct net_device *ndev = NULL;
  14106. u32 datalen = be32_to_cpu(e->datalen);
  14107. if (datalen) {
  14108. wl_roam_exp_event_t *evt_data = (wl_roam_exp_event_t *)data;
  14109. if (evt_data->version == ROAM_EXP_EVENT_VERSION) {
  14110. wlc_ssid_t *ssid = &evt_data->cur_ssid;
  14111. struct wireless_dev *wdev;
  14112. ndev = cfgdev_to_wlc_ndev(cfgdev, cfg);
  14113. if (ndev) {
  14114. wdev = ndev->ieee80211_ptr;
  14115. wdev->ssid_len = min(ssid->SSID_len, (uint32)DOT11_MAX_SSID_LEN);
  14116. memcpy(wdev->ssid, ssid->SSID, wdev->ssid_len);
  14117. WL_ERR(("SSID is %s\n", ssid->SSID));
  14118. wl_update_prof(cfg, ndev, NULL, ssid, WL_PROF_SSID);
  14119. } else {
  14120. WL_ERR(("NULL ndev!\n"));
  14121. }
  14122. } else {
  14123. WL_ERR(("Version mismatch %d, expected %d", evt_data->version,
  14124. ROAM_EXP_EVENT_VERSION));
  14125. }
  14126. }
  14127. return BCME_OK;
  14128. }
  14129. #endif /* GSCAN_SUPPORT */
  14130. #ifdef RSSI_MONITOR_SUPPORT
  14131. static s32 wl_handle_rssi_monitor_event(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev,
  14132. const wl_event_msg_t *e, void *data)
  14133. {
  14134. #if defined(WL_VENDOR_EXT_SUPPORT) || defined(CONFIG_BCMDHD_VENDOR_EXT)
  14135. u32 datalen = be32_to_cpu(e->datalen);
  14136. struct net_device *ndev = cfgdev_to_wlc_ndev(cfgdev, cfg);
  14137. struct wiphy *wiphy = bcmcfg_to_wiphy(cfg);
  14138. if (datalen) {
  14139. wl_rssi_monitor_evt_t *evt_data = (wl_rssi_monitor_evt_t *)data;
  14140. if (evt_data->version == RSSI_MONITOR_VERSION) {
  14141. dhd_rssi_monitor_evt_t monitor_data;
  14142. monitor_data.version = DHD_RSSI_MONITOR_EVT_VERSION;
  14143. monitor_data.cur_rssi = evt_data->cur_rssi;
  14144. memcpy(&monitor_data.BSSID, &e->addr, ETHER_ADDR_LEN);
  14145. wl_cfgvendor_send_async_event(wiphy, ndev,
  14146. GOOGLE_RSSI_MONITOR_EVENT,
  14147. &monitor_data, sizeof(monitor_data));
  14148. } else {
  14149. WL_ERR(("Version mismatch %d, expected %d", evt_data->version,
  14150. RSSI_MONITOR_VERSION));
  14151. }
  14152. }
  14153. #endif /* WL_VENDOR_EXT_SUPPORT || CONFIG_BCMDHD_VENDOR_EXT */
  14154. return BCME_OK;
  14155. }
  14156. #endif /* RSSI_MONITOR_SUPPORT */
  14157. static s32
  14158. wl_notify_roaming_status(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev,
  14159. const wl_event_msg_t *e, void *data)
  14160. {
  14161. bool act;
  14162. struct net_device *ndev = NULL;
  14163. s32 err = 0;
  14164. u32 event = be32_to_cpu(e->event_type);
  14165. u32 status = be32_to_cpu(e->status);
  14166. #ifdef DHD_LOSSLESS_ROAMING
  14167. struct wl_security *sec;
  14168. #endif // endif
  14169. #if defined(WBTEXT)
  14170. dhd_pub_t *dhdp = (dhd_pub_t *)(cfg->pub);
  14171. #endif /* WBTEXT */
  14172. WL_DBG(("Enter \n"));
  14173. ndev = cfgdev_to_wlc_ndev(cfgdev, cfg);
  14174. if ((!cfg->disable_roam_event) && (event == WLC_E_BSSID)) {
  14175. wl_add_remove_eventmsg(ndev, WLC_E_ROAM, false);
  14176. cfg->disable_roam_event = TRUE;
  14177. }
  14178. if ((cfg->disable_roam_event) && (event == WLC_E_ROAM))
  14179. return err;
  14180. if ((event == WLC_E_ROAM || event == WLC_E_BSSID) && status == WLC_E_STATUS_SUCCESS) {
  14181. if (wl_get_drv_status(cfg, CONNECTED, ndev)) {
  14182. #ifdef DHD_LOSSLESS_ROAMING
  14183. sec = wl_read_prof(cfg, ndev, WL_PROF_SEC);
  14184. /* In order to reduce roaming delay, wl_bss_roaming_done is
  14185. * early called with WLC_E_LINK event. It is called from
  14186. * here only if WLC_E_LINK event is blocked for specific
  14187. * security type.
  14188. */
  14189. if (IS_AKM_SUITE_FT(sec)) {
  14190. wl_bss_roaming_done(cfg, ndev, e, data);
  14191. }
  14192. /* Roam timer is deleted mostly from wl_cfg80211_change_station
  14193. * after roaming is finished successfully. We need to delete
  14194. * the timer from here only for some security types that aren't
  14195. * using wl_cfg80211_change_station to authorize SCB
  14196. */
  14197. if (IS_AKM_SUITE_FT(sec) || IS_AKM_SUITE_CCKM(sec)) {
  14198. wl_del_roam_timeout(cfg);
  14199. }
  14200. #else
  14201. #if !defined(DHD_NONFT_ROAMING)
  14202. wl_bss_roaming_done(cfg, ndev, e, data);
  14203. #endif /* !DHD_NONFT_ROAMING */
  14204. #endif /* DHD_LOSSLESS_ROAMING */
  14205. #ifdef WBTEXT
  14206. if (dhdp->wbtext_support) {
  14207. /* set wnm_keepalives_max_idle after association */
  14208. wl_cfg80211_wbtext_set_wnm_maxidle(cfg, ndev);
  14209. /* Mostly nbr request of BTM query will be handled
  14210. * from wl_cfg80211_change_station
  14211. * after key negotiation is finished.
  14212. * This part is only for some specific security
  14213. * types (FT, CCKM) that don't call
  14214. * wl_cfg80211_change_station after roaming
  14215. */
  14216. if (IS_AKM_SUITE_FT(sec) || IS_AKM_SUITE_CCKM(sec)) {
  14217. /* send nbr request or BTM query to update RCC
  14218. * after roaming completed
  14219. */
  14220. wl_cfg80211_wbtext_update_rcc(cfg, ndev);
  14221. }
  14222. }
  14223. #endif /* WBTEXT */
  14224. } else {
  14225. wl_bss_connect_done(cfg, ndev, e, data, true);
  14226. }
  14227. act = true;
  14228. wl_update_prof(cfg, ndev, e, &act, WL_PROF_ACT);
  14229. wl_update_prof(cfg, ndev, NULL, (const void *)&e->addr, WL_PROF_BSSID);
  14230. if (ndev == bcmcfg_to_prmry_ndev(cfg)) {
  14231. wl_vndr_ies_get_vendor_oui(cfg, ndev, NULL, 0);
  14232. }
  14233. }
  14234. #ifdef DHD_LOSSLESS_ROAMING
  14235. else if ((event == WLC_E_ROAM || event == WLC_E_BSSID) && status != WLC_E_STATUS_SUCCESS) {
  14236. wl_del_roam_timeout(cfg);
  14237. }
  14238. #endif // endif
  14239. return err;
  14240. }
  14241. #ifdef CUSTOM_EVENT_PM_WAKE
  14242. uint32 last_dpm_upd_time = 0; /* ms */
  14243. #define DPM_UPD_LMT_TIME ((CUSTOM_EVENT_PM_WAKE + (5)) * (1000) * (4)) /* ms */
  14244. #define DPM_UPD_LMT_RSSI -85 /* dbm */
  14245. static s32
  14246. wl_check_pmstatus(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev,
  14247. const wl_event_msg_t *e, void *data)
  14248. {
  14249. s32 err = BCME_OK;
  14250. struct net_device *ndev = NULL;
  14251. u8 *pbuf = NULL;
  14252. uint32 cur_dpm_upd_time = 0;
  14253. dhd_pub_t *dhd = (dhd_pub_t *)(cfg->pub);
  14254. s32 rssi;
  14255. #ifdef SUPPORT_RSSI_SUM_REPORT
  14256. wl_rssi_ant_mimo_t rssi_ant_mimo;
  14257. #endif /* SUPPORT_RSSI_SUM_REPORT */
  14258. ndev = cfgdev_to_wlc_ndev(cfgdev, cfg);
  14259. pbuf = (u8 *)MALLOCZ(cfg->osh, WLC_IOCTL_MEDLEN);
  14260. if (pbuf == NULL) {
  14261. WL_ERR(("failed to allocate local pbuf\n"));
  14262. return -ENOMEM;
  14263. }
  14264. err = wldev_iovar_getbuf_bsscfg(ndev, "dump",
  14265. "pm", strlen("pm"), pbuf, WLC_IOCTL_MEDLEN,
  14266. 0, &cfg->ioctl_buf_sync);
  14267. if (err) {
  14268. WL_ERR(("dump ioctl err = %d", err));
  14269. } else {
  14270. WL_ERR(("PM status : %s\n", pbuf));
  14271. }
  14272. if (pbuf) {
  14273. MFREE(cfg->osh, pbuf, WLC_IOCTL_MEDLEN);
  14274. }
  14275. if (dhd->early_suspended) {
  14276. /* LCD off */
  14277. #ifdef SUPPORT_RSSI_SUM_REPORT
  14278. /* Query RSSI sum across antennas */
  14279. memset(&rssi_ant_mimo, 0, sizeof(rssi_ant_mimo));
  14280. err = wl_get_rssi_per_ant(ndev, ndev->name, NULL, &rssi_ant_mimo);
  14281. if (err) {
  14282. WL_ERR(("Could not get rssi sum (%d)\n", err));
  14283. }
  14284. rssi = rssi_ant_mimo.rssi_sum;
  14285. if (rssi == 0)
  14286. #endif /* SUPPORT_RSSI_SUM_REPORT */
  14287. {
  14288. scb_val_t scb_val;
  14289. memset(&scb_val, 0, sizeof(scb_val_t));
  14290. scb_val.val = 0;
  14291. err = wldev_ioctl_get(ndev, WLC_GET_RSSI, &scb_val, sizeof(scb_val_t));
  14292. if (err) {
  14293. WL_ERR(("Could not get rssi (%d)\n", err));
  14294. }
  14295. rssi = wl_rssi_offset(dtoh32(scb_val.val));
  14296. }
  14297. WL_ERR(("RSSI %d dBm\n", rssi));
  14298. if (rssi > DPM_UPD_LMT_RSSI) {
  14299. return err;
  14300. }
  14301. } else {
  14302. /* LCD on */
  14303. return err;
  14304. }
  14305. if (last_dpm_upd_time == 0) {
  14306. last_dpm_upd_time = OSL_SYSUPTIME();
  14307. } else {
  14308. cur_dpm_upd_time = OSL_SYSUPTIME();
  14309. if (cur_dpm_upd_time - last_dpm_upd_time < DPM_UPD_LMT_TIME) {
  14310. scb_val_t scbval;
  14311. DHD_STATLOG_CTRL(dhd, ST(DISASSOC_INT_START),
  14312. dhd_net2idx(dhd->info, ndev), 0);
  14313. bzero(&scbval, sizeof(scb_val_t));
  14314. err = wldev_ioctl_set(ndev, WLC_DISASSOC,
  14315. &scbval, sizeof(scb_val_t));
  14316. if (err < 0) {
  14317. WL_ERR(("Disassoc error %d\n", err));
  14318. return err;
  14319. }
  14320. WL_ERR(("Force Disassoc due to updated DPM event.\n"));
  14321. last_dpm_upd_time = 0;
  14322. } else {
  14323. last_dpm_upd_time = cur_dpm_upd_time;
  14324. }
  14325. }
  14326. return err;
  14327. }
  14328. #endif /* CUSTOM_EVENT_PM_WAKE */
  14329. #ifdef QOS_MAP_SET
  14330. /* get user priority table */
  14331. uint8 *
  14332. wl_get_up_table(dhd_pub_t * dhdp, int idx)
  14333. {
  14334. struct net_device *ndev;
  14335. struct bcm_cfg80211 *cfg;
  14336. ndev = dhd_idx2net(dhdp, idx);
  14337. if (ndev) {
  14338. cfg = wl_get_cfg(ndev);
  14339. if (cfg)
  14340. return (uint8 *)(cfg->up_table);
  14341. }
  14342. return NULL;
  14343. }
  14344. #endif /* QOS_MAP_SET */
  14345. #if defined(DHD_LOSSLESS_ROAMING) || defined(DBG_PKT_MON)
  14346. static s32
  14347. wl_notify_roam_prep_status(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev,
  14348. const wl_event_msg_t *e, void *data)
  14349. {
  14350. struct wl_security *sec;
  14351. struct net_device *ndev;
  14352. dhd_pub_t *dhdp = (dhd_pub_t *)(cfg->pub);
  14353. u32 status = ntoh32(e->status);
  14354. u32 reason = ntoh32(e->reason);
  14355. BCM_REFERENCE(sec);
  14356. if (status == WLC_E_STATUS_SUCCESS && reason != WLC_E_REASON_INITIAL_ASSOC) {
  14357. WL_ERR(("Attempting roam with reason code : %d\n", reason));
  14358. }
  14359. #ifdef CONFIG_SILENT_ROAM
  14360. if (dhdp->in_suspend && reason == WLC_E_REASON_SILENT_ROAM) {
  14361. dhdp->sroamed = TRUE;
  14362. }
  14363. #endif /* CONFIG_SILENT_ROAM */
  14364. ndev = cfgdev_to_wlc_ndev(cfgdev, cfg);
  14365. #ifdef DBG_PKT_MON
  14366. if (ndev == bcmcfg_to_prmry_ndev(cfg)) {
  14367. DHD_DBG_PKT_MON_STOP(dhdp);
  14368. DHD_DBG_PKT_MON_START(dhdp);
  14369. }
  14370. #endif /* DBG_PKT_MON */
  14371. #ifdef DHD_LOSSLESS_ROAMING
  14372. sec = wl_read_prof(cfg, ndev, WL_PROF_SEC);
  14373. /* Disable Lossless Roaming for specific AKM suite
  14374. * Any other AKM suite can be added below if transition time
  14375. * is delayed because of Lossless Roaming
  14376. * and it causes any certication failure
  14377. */
  14378. if (IS_AKM_SUITE_FT(sec)) {
  14379. return BCME_OK;
  14380. }
  14381. dhdp->dequeue_prec_map = 1 << PRIO_8021D_NC;
  14382. /* Restore flow control */
  14383. dhd_txflowcontrol(dhdp, ALL_INTERFACES, OFF);
  14384. mod_timer(&cfg->roam_timeout, jiffies + msecs_to_jiffies(WL_ROAM_TIMEOUT_MS));
  14385. #endif /* DHD_LOSSLESS_ROAMING */
  14386. return BCME_OK;
  14387. }
  14388. #endif /* DHD_LOSSLESS_ROAMING || DBG_PKT_MON */
  14389. static s32
  14390. wl_notify_roam_start_status(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev,
  14391. const wl_event_msg_t *e, void *data)
  14392. {
  14393. #if (LINUX_VERSION_CODE > KERNEL_VERSION(3, 13, 0)) || defined(WL_VENDOR_EXT_SUPPORT)
  14394. struct net_device *ndev = cfgdev_to_wlc_ndev(cfgdev, cfg);
  14395. struct wiphy *wiphy = bcmcfg_to_wiphy(cfg);
  14396. int event_type;
  14397. event_type = WIFI_EVENT_ROAM_SCAN_STARTED;
  14398. wl_cfgvendor_send_async_event(wiphy, ndev, GOOGLE_ROAM_EVENT_START,
  14399. &event_type, sizeof(int));
  14400. #endif /* (LINUX_VERSION_CODE > KERNEL_VERSION(3, 13, 0)) || (WL_VENDOR_EXT_SUPPORT) */
  14401. return BCME_OK;
  14402. }
  14403. static s32 wl_get_assoc_ies(struct bcm_cfg80211 *cfg, struct net_device *ndev)
  14404. {
  14405. wl_assoc_info_t assoc_info;
  14406. struct wl_connect_info *conn_info = wl_to_conn(cfg);
  14407. s32 err = 0;
  14408. #ifdef QOS_MAP_SET
  14409. bcm_tlv_t * qos_map_ie = NULL;
  14410. #endif /* QOS_MAP_SET */
  14411. WL_DBG(("Enter \n"));
  14412. err = wldev_iovar_getbuf(ndev, "assoc_info", NULL, 0, cfg->extra_buf,
  14413. WL_ASSOC_INFO_MAX, NULL);
  14414. if (unlikely(err)) {
  14415. WL_ERR(("could not get assoc info (%d)\n", err));
  14416. return err;
  14417. }
  14418. memcpy(&assoc_info, cfg->extra_buf, sizeof(wl_assoc_info_t));
  14419. assoc_info.req_len = htod32(assoc_info.req_len);
  14420. assoc_info.resp_len = htod32(assoc_info.resp_len);
  14421. assoc_info.flags = htod32(assoc_info.flags);
  14422. if (conn_info->req_ie_len) {
  14423. conn_info->req_ie_len = 0;
  14424. bzero(conn_info->req_ie, sizeof(conn_info->req_ie));
  14425. }
  14426. if (conn_info->resp_ie_len) {
  14427. conn_info->resp_ie_len = 0;
  14428. bzero(conn_info->resp_ie, sizeof(conn_info->resp_ie));
  14429. }
  14430. if (assoc_info.req_len) {
  14431. err = wldev_iovar_getbuf(ndev, "assoc_req_ies", NULL, 0, cfg->extra_buf,
  14432. assoc_info.req_len, NULL);
  14433. if (unlikely(err)) {
  14434. WL_ERR(("could not get assoc req (%d)\n", err));
  14435. return err;
  14436. }
  14437. if (assoc_info.req_len < sizeof(struct dot11_assoc_req)) {
  14438. WL_ERR(("req_len %d lessthan %d \n", assoc_info.req_len,
  14439. (int)sizeof(struct dot11_assoc_req)));
  14440. return BCME_BADLEN;
  14441. }
  14442. conn_info->req_ie_len = (uint32)(assoc_info.req_len
  14443. - sizeof(struct dot11_assoc_req));
  14444. if (assoc_info.flags & WLC_ASSOC_REQ_IS_REASSOC) {
  14445. conn_info->req_ie_len -= ETHER_ADDR_LEN;
  14446. }
  14447. if (conn_info->req_ie_len <= MAX_REQ_LINE)
  14448. memcpy(conn_info->req_ie, cfg->extra_buf, conn_info->req_ie_len);
  14449. else {
  14450. WL_ERR(("IE size %d above max %d size \n",
  14451. conn_info->req_ie_len, MAX_REQ_LINE));
  14452. return err;
  14453. }
  14454. } else {
  14455. conn_info->req_ie_len = 0;
  14456. }
  14457. if (assoc_info.resp_len) {
  14458. err = wldev_iovar_getbuf(ndev, "assoc_resp_ies", NULL, 0, cfg->extra_buf,
  14459. assoc_info.resp_len, NULL);
  14460. if (unlikely(err)) {
  14461. WL_ERR(("could not get assoc resp (%d)\n", err));
  14462. return err;
  14463. }
  14464. if (assoc_info.resp_len < sizeof(struct dot11_assoc_resp)) {
  14465. WL_ERR(("resp_len %d is lessthan %d \n", assoc_info.resp_len,
  14466. (int)sizeof(struct dot11_assoc_resp)));
  14467. return BCME_BADLEN;
  14468. }
  14469. conn_info->resp_ie_len = assoc_info.resp_len -
  14470. (uint32)sizeof(struct dot11_assoc_resp);
  14471. if (conn_info->resp_ie_len <= MAX_REQ_LINE) {
  14472. memcpy(conn_info->resp_ie, cfg->extra_buf, conn_info->resp_ie_len);
  14473. } else {
  14474. WL_ERR(("IE size %d above max %d size \n",
  14475. conn_info->resp_ie_len, MAX_REQ_LINE));
  14476. return err;
  14477. }
  14478. #ifdef QOS_MAP_SET
  14479. /* find qos map set ie */
  14480. if ((qos_map_ie = bcm_parse_tlvs(conn_info->resp_ie, conn_info->resp_ie_len,
  14481. DOT11_MNG_QOS_MAP_ID)) != NULL) {
  14482. WL_DBG((" QoS map set IE found in assoc response\n"));
  14483. if (!cfg->up_table) {
  14484. cfg->up_table = (uint8 *)MALLOC(cfg->osh, UP_TABLE_MAX);
  14485. }
  14486. wl_set_up_table(cfg->up_table, qos_map_ie);
  14487. } else {
  14488. MFREE(cfg->osh, cfg->up_table, UP_TABLE_MAX);
  14489. }
  14490. #endif /* QOS_MAP_SET */
  14491. } else {
  14492. conn_info->resp_ie_len = 0;
  14493. }
  14494. WL_DBG(("req len (%d) resp len (%d)\n", conn_info->req_ie_len,
  14495. conn_info->resp_ie_len));
  14496. #ifdef REVERSE_AIFSN
  14497. DHD_REVERSE_AIFSN(cfg->pub, ndev);
  14498. #endif /* REVERSE_AIFSN */
  14499. return err;
  14500. }
  14501. static s32 wl_ch_to_chanspec(struct net_device *dev, int ch, struct wl_join_params *join_params,
  14502. size_t *join_params_size)
  14503. {
  14504. chanspec_t chanspec = 0, chspec;
  14505. struct bcm_cfg80211 *cfg =
  14506. (struct bcm_cfg80211 *)wiphy_priv(dev->ieee80211_ptr->wiphy);
  14507. if ((ch != 0) && (cfg && !cfg->rcc_enabled)) {
  14508. join_params->params.chanspec_num = 1;
  14509. join_params->params.chanspec_list[0] = ch;
  14510. if (join_params->params.chanspec_list[0] <= CH_MAX_2G_CHANNEL)
  14511. chanspec |= WL_CHANSPEC_BAND_2G;
  14512. else
  14513. chanspec |= WL_CHANSPEC_BAND_5G;
  14514. /* Get the min_bw set for the interface */
  14515. chspec = WL_CHANSPEC_BW_20;
  14516. if (chspec == INVCHANSPEC) {
  14517. WL_ERR(("Invalid chanspec \n"));
  14518. return -EINVAL;
  14519. }
  14520. chanspec |= chspec;
  14521. chanspec |= WL_CHANSPEC_CTL_SB_NONE;
  14522. *join_params_size += WL_ASSOC_PARAMS_FIXED_SIZE +
  14523. join_params->params.chanspec_num * sizeof(chanspec_t);
  14524. join_params->params.chanspec_list[0] &= WL_CHANSPEC_CHAN_MASK;
  14525. join_params->params.chanspec_list[0] |= chanspec;
  14526. join_params->params.chanspec_list[0] =
  14527. wl_chspec_host_to_driver(join_params->params.chanspec_list[0]);
  14528. join_params->params.chanspec_num =
  14529. htod32(join_params->params.chanspec_num);
  14530. }
  14531. #ifdef ESCAN_CHANNEL_CACHE
  14532. else {
  14533. /* If channel is not present and ESCAN_CHANNEL_CACHE is enabled,
  14534. * use the cached channel list
  14535. */
  14536. int n_channels;
  14537. n_channels = get_roam_channel_list(ch, join_params->params.chanspec_list,
  14538. MAX_ROAM_CHANNEL, &join_params->ssid, ioctl_version);
  14539. join_params->params.chanspec_num = htod32(n_channels);
  14540. *join_params_size += WL_ASSOC_PARAMS_FIXED_SIZE +
  14541. join_params->params.chanspec_num * sizeof(chanspec_t);
  14542. }
  14543. #endif /* ESCAN_CHANNEL_CACHE */
  14544. WL_DBG(("join_params->params.chanspec_list[0]= %X, %d channels\n",
  14545. join_params->params.chanspec_list[0],
  14546. join_params->params.chanspec_num));
  14547. return 0;
  14548. }
  14549. static s32 wl_update_bss_info(struct bcm_cfg80211 *cfg, struct net_device *ndev,
  14550. bool update_ssid)
  14551. {
  14552. struct cfg80211_bss *bss;
  14553. wl_bss_info_t *bi;
  14554. struct wlc_ssid *ssid;
  14555. const struct bcm_tlv *tim;
  14556. s32 beacon_interval;
  14557. s32 dtim_period;
  14558. size_t ie_len;
  14559. const u8 *ie;
  14560. u8 *curbssid;
  14561. s32 err = 0;
  14562. struct wiphy *wiphy;
  14563. u32 channel;
  14564. char *buf;
  14565. u32 freq, band;
  14566. wiphy = bcmcfg_to_wiphy(cfg);
  14567. ssid = (struct wlc_ssid *)wl_read_prof(cfg, ndev, WL_PROF_SSID);
  14568. curbssid = wl_read_prof(cfg, ndev, WL_PROF_BSSID);
  14569. bss = CFG80211_GET_BSS(wiphy, NULL, curbssid,
  14570. ssid->SSID, ssid->SSID_len);
  14571. buf = (char *)MALLOCZ(cfg->osh, WL_EXTRA_BUF_MAX);
  14572. if (!buf) {
  14573. WL_ERR(("buffer alloc failed.\n"));
  14574. return BCME_NOMEM;
  14575. }
  14576. mutex_lock(&cfg->usr_sync);
  14577. *(u32 *)buf = htod32(WL_EXTRA_BUF_MAX);
  14578. err = wldev_ioctl_get(ndev, WLC_GET_BSS_INFO, buf, WL_EXTRA_BUF_MAX);
  14579. if (unlikely(err)) {
  14580. WL_ERR(("Could not get bss info %d\n", err));
  14581. goto update_bss_info_out;
  14582. }
  14583. bi = (wl_bss_info_t *)(buf + 4);
  14584. channel = wf_chspec_ctlchan(wl_chspec_driver_to_host(bi->chanspec));
  14585. wl_update_prof(cfg, ndev, NULL, &channel, WL_PROF_CHAN);
  14586. if (!bss) {
  14587. WL_DBG(("Could not find the AP\n"));
  14588. if (memcmp(bi->BSSID.octet, curbssid, ETHER_ADDR_LEN)) {
  14589. WL_ERR(("Bssid doesn't match\n"));
  14590. err = -EIO;
  14591. goto update_bss_info_out;
  14592. }
  14593. err = wl_inform_single_bss(cfg, bi, update_ssid);
  14594. if (unlikely(err))
  14595. goto update_bss_info_out;
  14596. ie = ((u8 *)bi) + bi->ie_offset;
  14597. ie_len = bi->ie_length;
  14598. beacon_interval = cpu_to_le16(bi->beacon_period);
  14599. } else {
  14600. WL_DBG(("Found the AP in the list - BSSID %pM\n", bss->bssid));
  14601. #if LINUX_VERSION_CODE == KERNEL_VERSION(2, 6, 38) && !defined(WL_COMPAT_WIRELESS)
  14602. freq = ieee80211_channel_to_frequency(channel);
  14603. #else
  14604. band = (channel <= CH_MAX_2G_CHANNEL) ? IEEE80211_BAND_2GHZ : IEEE80211_BAND_5GHZ;
  14605. freq = ieee80211_channel_to_frequency(channel, band);
  14606. #endif // endif
  14607. bss->channel = ieee80211_get_channel(wiphy, freq);
  14608. #if defined(WL_CFG80211_P2P_DEV_IF)
  14609. ie = (const u8 *)bss->ies->data;
  14610. ie_len = bss->ies->len;
  14611. #else
  14612. ie = bss->information_elements;
  14613. ie_len = bss->len_information_elements;
  14614. #endif /* WL_CFG80211_P2P_DEV_IF */
  14615. beacon_interval = bss->beacon_interval;
  14616. CFG80211_PUT_BSS(wiphy, bss);
  14617. }
  14618. tim = bcm_parse_tlvs(ie, ie_len, WLAN_EID_TIM);
  14619. if (tim) {
  14620. dtim_period = tim->data[1];
  14621. } else {
  14622. /*
  14623. * active scan was done so we could not get dtim
  14624. * information out of probe response.
  14625. * so we speficially query dtim information.
  14626. */
  14627. dtim_period = 0;
  14628. err = wldev_ioctl_get(ndev, WLC_GET_DTIMPRD,
  14629. &dtim_period, sizeof(dtim_period));
  14630. if (unlikely(err)) {
  14631. WL_ERR(("WLC_GET_DTIMPRD error (%d)\n", err));
  14632. goto update_bss_info_out;
  14633. }
  14634. }
  14635. wl_update_prof(cfg, ndev, NULL, &beacon_interval, WL_PROF_BEACONINT);
  14636. wl_update_prof(cfg, ndev, NULL, &dtim_period, WL_PROF_DTIMPERIOD);
  14637. update_bss_info_out:
  14638. if (unlikely(err)) {
  14639. WL_ERR(("Failed with error %d\n", err));
  14640. }
  14641. MFREE(cfg->osh, buf, WL_EXTRA_BUF_MAX);
  14642. mutex_unlock(&cfg->usr_sync);
  14643. return err;
  14644. }
  14645. static s32
  14646. wl_bss_roaming_done(struct bcm_cfg80211 *cfg, struct net_device *ndev,
  14647. const wl_event_msg_t *e, void *data)
  14648. {
  14649. struct wl_connect_info *conn_info = wl_to_conn(cfg);
  14650. s32 err = 0;
  14651. u8 *curbssid;
  14652. u32 *channel;
  14653. scb_val_t scbval;
  14654. #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 39)) || defined(WL_COMPAT_WIRELESS)
  14655. struct wiphy *wiphy = bcmcfg_to_wiphy(cfg);
  14656. struct ieee80211_supported_band *band;
  14657. struct ieee80211_channel *notify_channel = NULL;
  14658. u32 freq;
  14659. #ifdef BCM4359_CHIP
  14660. struct channel_info ci;
  14661. u32 cur_channel;
  14662. #endif /* BCM4359_CHIP */
  14663. #endif /* LINUX_VERSION > 2.6.39 || WL_COMPAT_WIRELESS */
  14664. #if (defined(CONFIG_ARCH_MSM) && defined(CFG80211_ROAMED_API_UNIFIED)) || \
  14665. (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0)) || defined(WL_FILS_ROAM_OFFLD) || \
  14666. defined(CFG80211_ROAM_API_GE_4_12)
  14667. struct cfg80211_roam_info roam_info;
  14668. #endif /* (CONFIG_ARCH_MSM && CFG80211_ROAMED_API_UNIFIED) || LINUX_VERSION >= 4.12.0 */
  14669. #if defined(WL_FILS_ROAM_OFFLD)
  14670. struct wl_fils_info *fils_info = wl_to_fils_info(cfg);
  14671. struct wl_security *sec = wl_read_prof(cfg, ndev, WL_PROF_SEC);
  14672. #endif // endif
  14673. dhd_pub_t *dhdp = (dhd_pub_t *)(cfg->pub);
  14674. #ifdef DHD_POST_EAPOL_M1_AFTER_ROAM_EVT
  14675. dhd_if_t *ifp = NULL;
  14676. #endif /* DHD_POST_EAPOL_M1_AFTER_ROAM_EVT */
  14677. #ifdef WLFBT
  14678. uint32 data_len = 0;
  14679. if (data)
  14680. data_len = ntoh32(e->datalen);
  14681. #endif /* WLFBT */
  14682. BCM_REFERENCE(dhdp);
  14683. curbssid = wl_read_prof(cfg, ndev, WL_PROF_BSSID);
  14684. channel = (u32 *)wl_read_prof(cfg, ndev, WL_PROF_CHAN);
  14685. #ifdef BCM4359_CHIP
  14686. #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 39)) || defined(WL_COMPAT_WIRELESS)
  14687. /* Skip calling cfg80211_roamed If the channels are same and
  14688. * the current bssid & the new bssid are same
  14689. * Also clear timer roam_timeout.
  14690. * Only used on BCM4359 devices.
  14691. */
  14692. bzero(&ci, sizeof(ci));
  14693. if ((wldev_ioctl_get(ndev, WLC_GET_CHANNEL, &ci,
  14694. sizeof(ci))) < 0) {
  14695. WL_ERR(("Failed to get current channel !"));
  14696. err = BCME_ERROR;
  14697. goto fail;
  14698. }
  14699. cur_channel = dtoh32(ci.hw_channel);
  14700. if ((*channel == cur_channel) && ((memcmp(curbssid, &e->addr,
  14701. ETHER_ADDR_LEN) == 0) || (memcmp(&cfg->last_roamed_addr,
  14702. &e->addr, ETHER_ADDR_LEN) == 0))) {
  14703. WL_ERR(("BSS already present, Skipping roamed event to"
  14704. " upper layer\n"));
  14705. goto fail;
  14706. }
  14707. #endif /* LINUX_VERSION > 2.6.39 || WL_COMPAT_WIRELESS */
  14708. #endif /* BCM4359 CHIP */
  14709. if ((err = wl_get_assoc_ies(cfg, ndev)) != BCME_OK) {
  14710. DHD_STATLOG_CTRL(dhdp, ST(DISASSOC_INT_START),
  14711. dhd_net2idx(dhdp->info, ndev), WLAN_REASON_DEAUTH_LEAVING);
  14712. WL_ERR(("Fetching Assoc IEs failed, Skipping roamed event to"
  14713. " upper layer\n"));
  14714. /* To make sure disconnect, and fw sync, explictly send dissassoc
  14715. * for BSSID 00:00:00:00:00:00 issue
  14716. */
  14717. bzero(&scbval, sizeof(scb_val_t));
  14718. scbval.val = WLAN_REASON_DEAUTH_LEAVING;
  14719. memcpy(&scbval.ea, curbssid, ETHER_ADDR_LEN);
  14720. scbval.val = htod32(scbval.val);
  14721. if (wldev_ioctl_set(ndev, WLC_DISASSOC, &scbval,
  14722. sizeof(scb_val_t)) < 0) {
  14723. WL_ERR(("WLC_DISASSOC error\n"));
  14724. }
  14725. goto fail;
  14726. }
  14727. wl_update_prof(cfg, ndev, NULL, (const void *)(e->addr.octet), WL_PROF_BSSID);
  14728. curbssid = wl_read_prof(cfg, ndev, WL_PROF_BSSID);
  14729. if ((err = wl_update_bss_info(cfg, ndev, true)) != BCME_OK) {
  14730. WL_ERR(("failed to update bss info, err=%d\n", err));
  14731. goto fail;
  14732. }
  14733. wl_update_pmklist(ndev, cfg->pmk_list, err);
  14734. channel = (u32 *)wl_read_prof(cfg, ndev, WL_PROF_CHAN);
  14735. #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 39)) || defined(WL_COMPAT_WIRELESS)
  14736. /* channel info for cfg80211_roamed introduced in 2.6.39-rc1 */
  14737. if (*channel <= CH_MAX_2G_CHANNEL)
  14738. band = wiphy->bands[IEEE80211_BAND_2GHZ];
  14739. else
  14740. band = wiphy->bands[IEEE80211_BAND_5GHZ];
  14741. freq = ieee80211_channel_to_frequency(*channel, band->band);
  14742. notify_channel = ieee80211_get_channel(wiphy, freq);
  14743. #endif /* LINUX_VERSION > 2.6.39 || WL_COMPAT_WIRELESS */
  14744. #ifdef WLFBT
  14745. /* back up the given FBT key for the further supplicant request,
  14746. * currently not checking the FBT is enabled for current BSS in DHD,
  14747. * because the supplicant decides to take it or not.
  14748. */
  14749. if (data && (data_len == FBT_KEYLEN)) {
  14750. memcpy(cfg->fbt_key, data, FBT_KEYLEN);
  14751. }
  14752. #endif /* WLFBT */
  14753. #ifdef CUSTOM_LONG_RETRY_LIMIT
  14754. if (wl_set_retry(ndev, CUSTOM_LONG_RETRY_LIMIT, 1) < 0) {
  14755. WL_ERR(("CUSTOM_LONG_RETRY_LIMIT set fail!\n"));
  14756. }
  14757. #endif /* CUSTOM_LONG_RETRY_LIMIT */
  14758. DHD_STATLOG_CTRL(dhdp, ST(REASSOC_INFORM),
  14759. dhd_net2idx(dhdp->info, ndev), 0);
  14760. WL_ERR(("Report roam event to upper layer. " MACDBG " (ch:%d)\n",
  14761. MAC2STRDBG((const u8*)(&e->addr)), *channel));
  14762. #if (defined(CONFIG_ARCH_MSM) && defined(CFG80211_ROAMED_API_UNIFIED)) || \
  14763. (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0)) || defined(WL_FILS_ROAM_OFFLD) || \
  14764. defined(CFG80211_ROAM_API_GE_4_12)
  14765. memset(&roam_info, 0, sizeof(struct cfg80211_roam_info));
  14766. roam_info.channel = notify_channel;
  14767. roam_info.bssid = curbssid;
  14768. roam_info.req_ie = conn_info->req_ie;
  14769. roam_info.req_ie_len = conn_info->req_ie_len;
  14770. roam_info.resp_ie = conn_info->resp_ie;
  14771. roam_info.resp_ie_len = conn_info->resp_ie_len;
  14772. #if defined(WL_FILS_ROAM_OFFLD)
  14773. if ((sec->auth_type == DOT11_FILS_SKEY_PFS)||(sec->auth_type == DOT11_FILS_SKEY)) {
  14774. roam_info.fils.kek = fils_info->fils_kek;
  14775. roam_info.fils.kek_len = fils_info->fils_kek_len;
  14776. roam_info.fils.update_erp_next_seq_num = true;
  14777. roam_info.fils.erp_next_seq_num = fils_info->fils_erp_next_seq_num;
  14778. roam_info.fils.pmk = fils_info->fils_pmk;
  14779. roam_info.fils.pmk_len = fils_info->fils_kek_len;
  14780. roam_info.fils.pmkid = fils_info->fils_pmkid;
  14781. }
  14782. #endif // endif
  14783. cfg80211_roamed(ndev, &roam_info, GFP_KERNEL);
  14784. #else
  14785. cfg80211_roamed(ndev,
  14786. #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 39)) || defined(WL_COMPAT_WIRELESS)
  14787. notify_channel,
  14788. #endif // endif
  14789. curbssid,
  14790. conn_info->req_ie, conn_info->req_ie_len,
  14791. conn_info->resp_ie, conn_info->resp_ie_len, GFP_KERNEL);
  14792. #endif /* (CONFIG_ARCH_MSM && CFG80211_ROAMED_API_UNIFIED) || LINUX_VERSION >= 4.12.0 */
  14793. memcpy(&cfg->last_roamed_addr, &e->addr, ETHER_ADDR_LEN);
  14794. wl_set_drv_status(cfg, CONNECTED, ndev);
  14795. #if defined(DHD_ENABLE_BIGDATA_LOGGING)
  14796. cfg->roam_count++;
  14797. #endif /* DHD_ENABLE_BIGDATA_LOGGING */
  14798. #ifdef WL_BAM
  14799. if (wl_adps_bad_ap_check(cfg, &e->addr)) {
  14800. if (wl_adps_enabled(cfg, ndev)) {
  14801. wl_adps_set_suspend(cfg, ndev, ADPS_SUSPEND);
  14802. }
  14803. }
  14804. #endif /* WL_BAM */
  14805. #ifdef DHD_POST_EAPOL_M1_AFTER_ROAM_EVT
  14806. ifp = dhd_get_ifp(dhdp, e->ifidx);
  14807. if (ifp) {
  14808. ifp->post_roam_evt = TRUE;
  14809. }
  14810. #endif /* DHD_POST_EAPOL_M1_AFTER_ROAM_EVT */
  14811. /* Arm pkt logging timer */
  14812. dhd_dump_mod_pkt_timer(dhdp, PKT_CNT_RSN_ROAM);
  14813. return err;
  14814. fail:
  14815. #ifdef DHD_LOSSLESS_ROAMING
  14816. wl_del_roam_timeout(cfg);
  14817. #endif /* DHD_LOSSLESS_ROAMING */
  14818. return err;
  14819. }
  14820. static bool
  14821. wl_cfg80211_verify_bss(struct bcm_cfg80211 *cfg, struct net_device *ndev,
  14822. struct cfg80211_bss **bss)
  14823. {
  14824. struct wiphy *wiphy;
  14825. struct wlc_ssid *ssid;
  14826. uint8 *curbssid;
  14827. int count = 0;
  14828. int ret = false;
  14829. u8 cur_ssid[DOT11_MAX_SSID_LEN + 1];
  14830. wiphy = bcmcfg_to_wiphy(cfg);
  14831. ssid = (struct wlc_ssid *)wl_read_prof(cfg, ndev, WL_PROF_SSID);
  14832. curbssid = wl_read_prof(cfg, ndev, WL_PROF_BSSID);
  14833. if (!ssid) {
  14834. WL_ERR(("No SSID found in the saved profile \n"));
  14835. return false;
  14836. }
  14837. do {
  14838. *bss = CFG80211_GET_BSS(wiphy, NULL, curbssid,
  14839. ssid->SSID, ssid->SSID_len);
  14840. if (*bss || (count > 5)) {
  14841. break;
  14842. }
  14843. count++;
  14844. msleep(100);
  14845. } while (*bss == NULL);
  14846. WL_DBG(("cfg80211 bss_ptr:%p loop_cnt:%d\n", *bss, count));
  14847. if (*bss) {
  14848. #if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 7, 0))
  14849. /* Update the reference count after use. In case of kernel version >= 4.7
  14850. * the cfg802_put_bss is called in cfg80211_connect_bss context
  14851. */
  14852. CFG80211_PUT_BSS(wiphy, *bss);
  14853. #endif /* LINUX_VERSION_CODE < KERNEL_VERSION(4, 7, 0) */
  14854. ret = true;
  14855. } else {
  14856. memset(cur_ssid, 0, DOT11_MAX_SSID_LEN);
  14857. strncpy(cur_ssid, ssid->SSID,
  14858. MIN(ssid->SSID_len, DOT11_MAX_SSID_LEN));
  14859. WL_ERR(("No bss entry for ssid:%s bssid:"MACDBG"\n",
  14860. cur_ssid, MAC2STRDBG(curbssid)));
  14861. }
  14862. return ret;
  14863. }
  14864. _Pragma("GCC diagnostic ignored \"-Wmissing-field-initializers\"")
  14865. #ifdef WL_FILS
  14866. static s32
  14867. wl_get_fils_connect_params(struct bcm_cfg80211 *cfg, struct net_device *ndev)
  14868. {
  14869. const bcm_xtlv_t* pxtlv_out;
  14870. struct wl_fils_info *fils_info = wl_to_fils_info(cfg);
  14871. int err = BCME_OK;
  14872. bcm_iov_buf_t *iov_buf_in = NULL;
  14873. bcm_iov_buf_t iov_buf_out = {0};
  14874. u16 len;
  14875. u16 type;
  14876. const u8 *data;
  14877. iov_buf_in = MALLOCZ(cfg->osh, WLC_IOCTL_SMLEN);
  14878. if (!iov_buf_in) {
  14879. WL_ERR(("buf memory alloc failed\n"));
  14880. err = BCME_NOMEM;
  14881. goto exit;
  14882. }
  14883. iov_buf_out.version = WL_FILS_IOV_VERSION;
  14884. iov_buf_out.id = WL_FILS_CMD_GET_CONNECT_PARAMS;
  14885. err = wldev_iovar_getbuf(ndev, "fils", (uint8*)&iov_buf_out, sizeof(bcm_iov_buf_t),
  14886. iov_buf_in, WLC_IOCTL_SMLEN, &cfg->ioctl_buf_sync);
  14887. if (unlikely(err)) {
  14888. WL_ERR(("Get FILS Params Error (%d)\n", err));
  14889. goto exit;
  14890. }
  14891. pxtlv_out = (bcm_xtlv_t*)((bcm_iov_buf_t*)iov_buf_in)->data;
  14892. len = iov_buf_in->len;
  14893. do {
  14894. if (!bcm_valid_xtlv(pxtlv_out, iov_buf_in->len, BCM_XTLV_OPTION_ALIGN32)) {
  14895. WL_ERR(("%s: XTLV is not valid\n", __func__));
  14896. err = BCME_BADARG;
  14897. goto exit;
  14898. }
  14899. bcm_xtlv_unpack_xtlv(pxtlv_out, &type, &len, &data, BCM_XTLV_OPTION_ALIGN32);
  14900. switch (type) {
  14901. case WL_FILS_XTLV_ERP_NEXT_SEQ_NUM:
  14902. fils_info->fils_erp_next_seq_num = *(const u16 *)data;
  14903. break;
  14904. case WL_FILS_XTLV_KEK:
  14905. if (memcpy_s(fils_info->fils_kek,
  14906. WL_MAX_FILS_KEY_LEN, data, len) < 0) {
  14907. err = BCME_BADARG;
  14908. goto exit;
  14909. }
  14910. fils_info->fils_kek_len = len;
  14911. break;
  14912. case WL_FILS_XTLV_PMK:
  14913. if (memcpy_s(fils_info->fils_pmk,
  14914. WL_MAX_FILS_KEY_LEN, data, len) < 0) {
  14915. err = BCME_BADARG;
  14916. goto exit;
  14917. }
  14918. fils_info->fils_pmk_len = len;
  14919. break;
  14920. case WL_FILS_XTLV_PMKID:
  14921. if (memcpy_s(fils_info->fils_pmkid,
  14922. WL_MAX_FILS_KEY_LEN, data, len) < 0) {
  14923. err = BCME_BADARG;
  14924. goto exit;
  14925. }
  14926. break;
  14927. default:
  14928. WL_ERR(("%s: wrong XTLV code\n", __func__));
  14929. break;
  14930. }
  14931. } while ((pxtlv_out = bcm_next_xtlv(pxtlv_out, (int *)&iov_buf_in->len,
  14932. BCM_XTLV_OPTION_ALIGN32)) && iov_buf_in->len);
  14933. exit:
  14934. if (iov_buf_in) {
  14935. MFREE(cfg->osh, iov_buf_in, WLC_IOCTL_SMLEN);
  14936. }
  14937. return err;
  14938. }
  14939. #endif /* WL_FILS */
  14940. static s32
  14941. wl_bss_connect_done(struct bcm_cfg80211 *cfg, struct net_device *ndev,
  14942. const wl_event_msg_t *e, void *data, bool completed)
  14943. {
  14944. struct wl_connect_info *conn_info = wl_to_conn(cfg);
  14945. struct wl_security *sec = wl_read_prof(cfg, ndev, WL_PROF_SEC);
  14946. s32 err = 0;
  14947. #ifdef WL_FILS
  14948. struct cfg80211_connect_resp_params resp_params = {0};
  14949. struct wl_fils_info *fils_info = NULL;
  14950. struct wlc_ssid *ssid = NULL;
  14951. struct wiphy *wiphy = NULL;
  14952. #endif /* WL_FILS */
  14953. u8 *curbssid = wl_read_prof(cfg, ndev, WL_PROF_BSSID);
  14954. u32 event_type = ntoh32(e->event_type);
  14955. struct cfg80211_bss *bss = NULL;
  14956. dhd_pub_t *dhdp;
  14957. dhdp = (dhd_pub_t *)(cfg->pub);
  14958. BCM_REFERENCE(dhdp);
  14959. if (!sec) {
  14960. WL_ERR(("sec is NULL\n"));
  14961. return -ENODEV;
  14962. }
  14963. WL_DBG((" enter\n"));
  14964. #ifdef ESCAN_RESULT_PATCH
  14965. if (wl_get_drv_status(cfg, CONNECTED, ndev)) {
  14966. if (memcmp(curbssid, connect_req_bssid, ETHER_ADDR_LEN) == 0) {
  14967. WL_INFORM_MEM((" Connected event of connected device "
  14968. "e=%d s=%d, ignore it\n",
  14969. ntoh32(e->event_type), ntoh32(e->status)));
  14970. return err;
  14971. }
  14972. }
  14973. if (memcmp(curbssid, broad_bssid, ETHER_ADDR_LEN) == 0 &&
  14974. memcmp(broad_bssid, connect_req_bssid, ETHER_ADDR_LEN) != 0) {
  14975. WL_DBG(("copy bssid\n"));
  14976. memcpy(curbssid, connect_req_bssid, ETHER_ADDR_LEN);
  14977. }
  14978. #else
  14979. if (cfg->scan_request) {
  14980. wl_cfg80211_cancel_scan(cfg);
  14981. }
  14982. #endif /* ESCAN_RESULT_PATCH */
  14983. if (wl_get_drv_status(cfg, CONNECTING, ndev)) {
  14984. wl_cfg80211_scan_abort(cfg);
  14985. if (completed) {
  14986. wl_get_assoc_ies(cfg, ndev);
  14987. wl_update_prof(cfg, ndev, NULL, (const void *)(e->addr.octet),
  14988. WL_PROF_BSSID);
  14989. curbssid = wl_read_prof(cfg, ndev, WL_PROF_BSSID);
  14990. /*
  14991. * CFG layer relies on cached IEs (from probe/beacon) to fetch matching bss.
  14992. * For cases, there is no match available,
  14993. * need to update the cache based on bss info from fw.
  14994. */
  14995. wl_update_bss_info(cfg, ndev, true);
  14996. wl_update_pmklist(ndev, cfg->pmk_list, err);
  14997. wl_set_drv_status(cfg, CONNECTED, ndev);
  14998. #if defined(ROAM_ENABLE) && defined(ROAM_AP_ENV_DETECTION)
  14999. if (dhdp->roam_env_detection)
  15000. wldev_iovar_setint(ndev, "roam_env_detection",
  15001. AP_ENV_INDETERMINATE);
  15002. #endif /* ROAM_AP_ENV_DETECTION */
  15003. if (ndev != bcmcfg_to_prmry_ndev(cfg)) {
  15004. #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 13, 0)
  15005. init_completion(&cfg->iface_disable);
  15006. #else
  15007. /* reinitialize completion to clear previous count */
  15008. INIT_COMPLETION(cfg->iface_disable);
  15009. #endif // endif
  15010. }
  15011. #ifdef CUSTOM_SET_CPUCORE
  15012. if (wl_get_chan_isvht80(ndev, dhdp)) {
  15013. if (ndev == bcmcfg_to_prmry_ndev(cfg))
  15014. dhdp->chan_isvht80 |= DHD_FLAG_STA_MODE; /* STA mode */
  15015. else if (is_p2p_group_iface(ndev->ieee80211_ptr))
  15016. dhdp->chan_isvht80 |= DHD_FLAG_P2P_MODE; /* p2p mode */
  15017. dhd_set_cpucore(dhdp, TRUE);
  15018. }
  15019. #endif /* CUSTOM_SET_CPUCORE */
  15020. #ifdef CUSTOM_LONG_RETRY_LIMIT
  15021. if (wl_set_retry(ndev, CUSTOM_LONG_RETRY_LIMIT, 1) < 0) {
  15022. WL_ERR(("CUSTOM_LONG_RETRY_LIMIT set fail!\n"));
  15023. }
  15024. #endif /* CUSTOM_LONG_RETRY_LIMIT */
  15025. bzero(&cfg->last_roamed_addr, ETHER_ADDR_LEN);
  15026. }
  15027. wl_clr_drv_status(cfg, CONNECTING, ndev);
  15028. if (completed && (wl_cfg80211_verify_bss(cfg, ndev, &bss) != true)) {
  15029. /* If bss entry is not available in the cfg80211 bss cache
  15030. * the wireless stack will complain and won't populate
  15031. * wdev->current_bss ptr
  15032. */
  15033. WL_ERR(("BSS entry not found. Indicate assoc event failure\n"));
  15034. completed = false;
  15035. sec->auth_assoc_res_status = WLAN_STATUS_UNSPECIFIED_FAILURE;
  15036. }
  15037. #ifdef WL_FILS
  15038. if ((sec->auth_type == DOT11_FILS_SKEY_PFS)||(sec->auth_type == DOT11_FILS_SKEY)) {
  15039. wl_get_fils_connect_params(cfg, ndev);
  15040. fils_info = wl_to_fils_info(cfg);
  15041. ssid = (struct wlc_ssid *)wl_read_prof(cfg, ndev, WL_PROF_SSID);
  15042. wiphy = bcmcfg_to_wiphy(cfg);
  15043. resp_params.status = completed ? WLAN_STATUS_SUCCESS :
  15044. (sec->auth_assoc_res_status) ?
  15045. sec->auth_assoc_res_status :
  15046. WLAN_STATUS_UNSPECIFIED_FAILURE;
  15047. resp_params.bssid = curbssid;
  15048. resp_params.bss = CFG80211_GET_BSS(wiphy, NULL, curbssid,
  15049. ssid->SSID, ssid->SSID_len);
  15050. resp_params.req_ie = conn_info->req_ie;
  15051. resp_params.req_ie_len = conn_info->req_ie_len;
  15052. resp_params.resp_ie = conn_info->resp_ie;
  15053. resp_params.resp_ie_len = conn_info->resp_ie_len;
  15054. #ifdef WL_FILS_ROAM_OFFLD
  15055. resp_params.fils.kek = fils_info->fils_kek;
  15056. resp_params.fils.kek_len = fils_info->fils_kek_len;
  15057. resp_params.fils.update_erp_next_seq_num = true;
  15058. resp_params.fils.erp_next_seq_num = fils_info->fils_erp_next_seq_num;
  15059. resp_params.fils.pmk = fils_info->fils_pmk;
  15060. resp_params.fils.pmk_len = fils_info->fils_kek_len;
  15061. resp_params.fils.pmkid = fils_info->fils_pmkid;
  15062. #else
  15063. resp_params.fils_kek = fils_info->fils_kek;
  15064. resp_params.fils_kek_len = fils_info->fils_kek_len;
  15065. resp_params.update_erp_next_seq_num = true;
  15066. resp_params.fils_erp_next_seq_num = fils_info->fils_erp_next_seq_num;
  15067. resp_params.pmk = fils_info->fils_pmk;
  15068. resp_params.pmk_len = fils_info->fils_kek_len;
  15069. resp_params.pmkid = fils_info->fils_pmkid;
  15070. #endif /* WL_FILS_ROAM_OFFLD */
  15071. cfg80211_connect_done(ndev, &resp_params, GFP_KERNEL);
  15072. }
  15073. else
  15074. #endif /* WL_FILS */
  15075. {
  15076. CFG80211_CONNECT_RESULT(ndev,
  15077. curbssid,
  15078. bss,
  15079. conn_info->req_ie,
  15080. conn_info->req_ie_len,
  15081. conn_info->resp_ie,
  15082. conn_info->resp_ie_len,
  15083. completed ? WLAN_STATUS_SUCCESS :
  15084. (sec->auth_assoc_res_status) ?
  15085. sec->auth_assoc_res_status :
  15086. WLAN_STATUS_UNSPECIFIED_FAILURE,
  15087. GFP_KERNEL);
  15088. }
  15089. if (completed) {
  15090. WL_INFORM_MEM(("[%s] Report connect result - "
  15091. "connection succeeded\n", ndev->name));
  15092. #ifdef WL_BAM
  15093. if (wl_adps_bad_ap_check(cfg, &e->addr)) {
  15094. if (wl_adps_enabled(cfg, ndev)) {
  15095. wl_adps_set_suspend(cfg, ndev, ADPS_SUSPEND);
  15096. }
  15097. }
  15098. #endif /* WL_BAM */
  15099. } else
  15100. WL_ERR(("[%s] Report connect result - connection failed\n", ndev->name));
  15101. } else {
  15102. WL_INFORM_MEM(("[%s] Ignore event:%d. drv status"
  15103. " connecting:%x. connected:%d\n",
  15104. ndev->name, event_type, wl_get_drv_status(cfg, CONNECTING, ndev),
  15105. wl_get_drv_status(cfg, CONNECTED, ndev)));
  15106. }
  15107. #ifdef CONFIG_TCPACK_FASTTX
  15108. if (wl_get_chan_isvht80(ndev, dhdp))
  15109. wldev_iovar_setint(ndev, "tcpack_fast_tx", 0);
  15110. else
  15111. wldev_iovar_setint(ndev, "tcpack_fast_tx", 1);
  15112. #endif /* CONFIG_TCPACK_FASTTX */
  15113. return err;
  15114. }
  15115. static s32
  15116. wl_notify_mic_status(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev,
  15117. const wl_event_msg_t *e, void *data)
  15118. {
  15119. struct net_device *ndev = NULL;
  15120. u16 flags = ntoh16(e->flags);
  15121. enum nl80211_key_type key_type;
  15122. ndev = cfgdev_to_wlc_ndev(cfgdev, cfg);
  15123. WL_INFORM_MEM(("[%s] mic fail event - " MACDBG " \n",
  15124. ndev->name, MAC2STRDBG(e->addr.octet)));
  15125. mutex_lock(&cfg->usr_sync);
  15126. if (flags & WLC_EVENT_MSG_GROUP)
  15127. key_type = NL80211_KEYTYPE_GROUP;
  15128. else
  15129. key_type = NL80211_KEYTYPE_PAIRWISE;
  15130. wl_flush_fw_log_buffer(ndev, FW_LOGSET_MASK_ALL);
  15131. cfg80211_michael_mic_failure(ndev, (const u8 *)&e->addr, key_type, -1,
  15132. NULL, GFP_KERNEL);
  15133. mutex_unlock(&cfg->usr_sync);
  15134. return 0;
  15135. }
  15136. #ifdef BT_WIFI_HANDOVER
  15137. static s32
  15138. wl_notify_bt_wifi_handover_req(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev,
  15139. const wl_event_msg_t *e, void *data)
  15140. {
  15141. struct net_device *ndev = NULL;
  15142. u32 event = ntoh32(e->event_type);
  15143. u32 datalen = ntoh32(e->datalen);
  15144. s32 err;
  15145. WL_ERR(("wl_notify_bt_wifi_handover_req: event_type : %d, datalen : %d\n", event, datalen));
  15146. ndev = cfgdev_to_wlc_ndev(cfgdev, cfg);
  15147. err = wl_genl_send_msg(ndev, event, data, (u16)datalen, 0, 0);
  15148. return err;
  15149. }
  15150. #endif /* BT_WIFI_HANDOVER */
  15151. static s32
  15152. wl_frame_get_mgmt(struct bcm_cfg80211 *cfg, u16 fc,
  15153. const struct ether_addr *da, const struct ether_addr *sa,
  15154. const struct ether_addr *bssid, u8 **pheader, u32 *body_len, u8 *pbody)
  15155. {
  15156. struct dot11_management_header *hdr;
  15157. u32 totlen = 0;
  15158. s32 err = 0;
  15159. u8 *offset;
  15160. u32 prebody_len = *body_len;
  15161. switch (fc) {
  15162. case FC_ASSOC_REQ:
  15163. /* capability , listen interval */
  15164. totlen = DOT11_ASSOC_REQ_FIXED_LEN;
  15165. *body_len += DOT11_ASSOC_REQ_FIXED_LEN;
  15166. break;
  15167. case FC_REASSOC_REQ:
  15168. /* capability, listen inteval, ap address */
  15169. totlen = DOT11_REASSOC_REQ_FIXED_LEN;
  15170. *body_len += DOT11_REASSOC_REQ_FIXED_LEN;
  15171. break;
  15172. }
  15173. totlen += DOT11_MGMT_HDR_LEN + prebody_len;
  15174. *pheader = (u8 *)MALLOCZ(cfg->osh, totlen);
  15175. if (*pheader == NULL) {
  15176. WL_ERR(("memory alloc failed \n"));
  15177. return -ENOMEM;
  15178. }
  15179. hdr = (struct dot11_management_header *) (*pheader);
  15180. hdr->fc = htol16(fc);
  15181. hdr->durid = 0;
  15182. hdr->seq = 0;
  15183. offset = (u8*)(hdr + 1) + (totlen - DOT11_MGMT_HDR_LEN - prebody_len);
  15184. bcopy((const char*)da, (u8*)&hdr->da, ETHER_ADDR_LEN);
  15185. bcopy((const char*)sa, (u8*)&hdr->sa, ETHER_ADDR_LEN);
  15186. bcopy((const char*)bssid, (u8*)&hdr->bssid, ETHER_ADDR_LEN);
  15187. if ((pbody != NULL) && prebody_len)
  15188. bcopy((const char*)pbody, offset, prebody_len);
  15189. *body_len = totlen;
  15190. return err;
  15191. }
  15192. #ifdef WL_CFG80211_GON_COLLISION
  15193. static void
  15194. wl_gon_req_collision(struct bcm_cfg80211 *cfg, wl_action_frame_t *tx_act_frm,
  15195. wifi_p2p_pub_act_frame_t *rx_act_frm, struct net_device *ndev,
  15196. struct ether_addr sa, struct ether_addr da)
  15197. {
  15198. if (cfg->afx_hdl->pending_tx_act_frm == NULL)
  15199. return;
  15200. if (tx_act_frm &&
  15201. wl_cfgp2p_is_pub_action(tx_act_frm->data, tx_act_frm->len)) {
  15202. wifi_p2p_pub_act_frame_t *pact_frm;
  15203. pact_frm = (wifi_p2p_pub_act_frame_t *)tx_act_frm->data;
  15204. if (!(pact_frm->subtype == P2P_PAF_GON_REQ &&
  15205. rx_act_frm->subtype == P2P_PAF_GON_REQ)) {
  15206. return;
  15207. }
  15208. }
  15209. WL_ERR((" GO NEGO Request COLLISION !!! \n"));
  15210. /* if sa(peer) addr is less than da(my) addr,
  15211. * my device will process peer's gon request and block to send my gon req.
  15212. *
  15213. * if not (sa addr > da addr),
  15214. * my device will process gon request and drop gon req of peer.
  15215. */
  15216. if (memcmp(sa.octet, da.octet, ETHER_ADDR_LEN) < 0) {
  15217. /* block to send tx gon request */
  15218. cfg->block_gon_req_tx_count = BLOCK_GON_REQ_MAX_NUM;
  15219. WL_ERR((" block to send gon req tx !!!\n"));
  15220. /* if we are finding a common channel for sending af,
  15221. * do not scan more to block to send current gon req
  15222. */
  15223. if (wl_get_drv_status_all(cfg, FINDING_COMMON_CHANNEL)) {
  15224. wl_clr_drv_status(cfg, FINDING_COMMON_CHANNEL, ndev);
  15225. complete(&cfg->act_frm_scan);
  15226. }
  15227. } else {
  15228. /* drop gon request of peer to process gon request by my device. */
  15229. WL_ERR((" drop to receive gon req rx !!! \n"));
  15230. cfg->block_gon_req_rx_count = BLOCK_GON_REQ_MAX_NUM;
  15231. }
  15232. return;
  15233. }
  15234. #endif /* WL_CFG80211_GON_COLLISION */
  15235. void
  15236. wl_stop_wait_next_action_frame(struct bcm_cfg80211 *cfg, struct net_device *ndev, u8 bsscfgidx)
  15237. {
  15238. s32 err = 0;
  15239. if (wl_get_drv_status_all(cfg, FINDING_COMMON_CHANNEL)) {
  15240. if (timer_pending(&cfg->p2p->listen_timer)) {
  15241. del_timer_sync(&cfg->p2p->listen_timer);
  15242. }
  15243. if (cfg->afx_hdl != NULL) {
  15244. if (cfg->afx_hdl->dev != NULL) {
  15245. wl_clr_drv_status(cfg, SCANNING, cfg->afx_hdl->dev);
  15246. wl_clr_drv_status(cfg, FINDING_COMMON_CHANNEL, cfg->afx_hdl->dev);
  15247. }
  15248. cfg->afx_hdl->peer_chan = WL_INVALID;
  15249. }
  15250. complete(&cfg->act_frm_scan);
  15251. WL_DBG(("*** Wake UP ** Working afx searching is cleared\n"));
  15252. } else if (wl_get_drv_status_all(cfg, SENDING_ACT_FRM)) {
  15253. if (!(wl_get_p2p_status(cfg, ACTION_TX_COMPLETED) ||
  15254. wl_get_p2p_status(cfg, ACTION_TX_NOACK)))
  15255. wl_set_p2p_status(cfg, ACTION_TX_COMPLETED);
  15256. WL_DBG(("*** Wake UP ** abort actframe iovar on bsscfxidx %d\n", bsscfgidx));
  15257. /* Scan engine is not used for sending action frames in the latest driver
  15258. * branches. actframe_abort is used in the latest driver branches
  15259. * instead of scan abort.
  15260. * If actframe_abort iovar succeeds, don't execute scan abort.
  15261. * If actframe_abort fails with unsupported error,
  15262. * execute scan abort (for backward copmatibility).
  15263. */
  15264. if (cfg->af_sent_channel) {
  15265. err = wldev_iovar_setint_bsscfg(ndev, "actframe_abort", 1, bsscfgidx);
  15266. if (err < 0) {
  15267. if (err == BCME_UNSUPPORTED) {
  15268. wl_cfg80211_scan_abort(cfg);
  15269. } else {
  15270. WL_ERR(("actframe_abort failed. ret:%d\n", err));
  15271. }
  15272. }
  15273. }
  15274. }
  15275. #ifdef WL_CFG80211_SYNC_GON
  15276. else if (wl_get_drv_status_all(cfg, WAITING_NEXT_ACT_FRM_LISTEN)) {
  15277. WL_DBG(("*** Wake UP ** abort listen for next af frame\n"));
  15278. /* So abort scan to cancel listen */
  15279. wl_cfg80211_scan_abort(cfg);
  15280. }
  15281. #endif /* WL_CFG80211_SYNC_GON */
  15282. }
  15283. #if defined(WLTDLS)
  15284. bool wl_cfg80211_is_tdls_tunneled_frame(void *frame, u32 frame_len)
  15285. {
  15286. unsigned char *data;
  15287. if (frame == NULL) {
  15288. WL_ERR(("Invalid frame \n"));
  15289. return false;
  15290. }
  15291. if (frame_len < 5) {
  15292. WL_ERR(("Invalid frame length [%d] \n", frame_len));
  15293. return false;
  15294. }
  15295. data = frame;
  15296. if (!memcmp(data, TDLS_TUNNELED_PRB_REQ, 5) ||
  15297. !memcmp(data, TDLS_TUNNELED_PRB_RESP, 5)) {
  15298. WL_DBG(("TDLS Vendor Specific Received type\n"));
  15299. return true;
  15300. }
  15301. return false;
  15302. }
  15303. #endif /* WLTDLS */
  15304. #if defined(WES_SUPPORT)
  15305. static int wes_mode = 0;
  15306. int wl_cfg80211_set_wes_mode(int mode)
  15307. {
  15308. wes_mode = mode;
  15309. return 0;
  15310. }
  15311. int wl_cfg80211_get_wes_mode(void)
  15312. {
  15313. return wes_mode;
  15314. }
  15315. bool wl_cfg80211_is_wes(void *frame, u32 frame_len)
  15316. {
  15317. unsigned char *data;
  15318. if (frame == NULL) {
  15319. WL_ERR(("Invalid frame \n"));
  15320. return false;
  15321. }
  15322. if (frame_len < 4) {
  15323. WL_ERR(("Invalid frame length [%d] \n", frame_len));
  15324. return false;
  15325. }
  15326. data = frame;
  15327. if (memcmp(data, "\x7f\x00\x00\xf0", 4) == 0) {
  15328. WL_DBG(("Receive WES VS Action Frame \n"));
  15329. return true;
  15330. }
  15331. return false;
  15332. }
  15333. #endif /* WES_SUPPORT */
  15334. int wl_cfg80211_get_ioctl_version(void)
  15335. {
  15336. return ioctl_version;
  15337. }
  15338. static s32
  15339. wl_notify_rx_mgmt_frame(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev,
  15340. const wl_event_msg_t *e, void *data)
  15341. {
  15342. struct ieee80211_supported_band *band;
  15343. struct wiphy *wiphy = bcmcfg_to_wiphy(cfg);
  15344. struct ether_addr da;
  15345. struct ether_addr bssid;
  15346. bool isfree = false;
  15347. s32 err = 0;
  15348. s32 freq;
  15349. struct net_device *ndev = NULL;
  15350. wifi_p2p_pub_act_frame_t *act_frm = NULL;
  15351. wifi_p2p_action_frame_t *p2p_act_frm = NULL;
  15352. wifi_p2psd_gas_pub_act_frame_t *sd_act_frm = NULL;
  15353. wl_event_rx_frame_data_t *rxframe;
  15354. u32 event;
  15355. u8 *mgmt_frame;
  15356. u8 bsscfgidx;
  15357. u32 mgmt_frame_len;
  15358. u16 channel;
  15359. #if defined(TDLS_MSG_ONLY_WFD) && defined(WLTDLS)
  15360. dhd_pub_t *dhdp = (dhd_pub_t *)(cfg->pub);
  15361. #endif /* BCMDONGLEHOST && TDLS_MSG_ONLY_WFD && WLTDLS */
  15362. if (ntoh32(e->datalen) < sizeof(wl_event_rx_frame_data_t)) {
  15363. WL_ERR(("wrong datalen:%d\n", ntoh32(e->datalen)));
  15364. return -EINVAL;
  15365. }
  15366. mgmt_frame_len = ntoh32(e->datalen) - (uint32)sizeof(wl_event_rx_frame_data_t);
  15367. event = ntoh32(e->event_type);
  15368. bsscfgidx = e->bsscfgidx;
  15369. rxframe = (wl_event_rx_frame_data_t *)data;
  15370. if (!rxframe) {
  15371. WL_ERR(("rxframe: NULL\n"));
  15372. return -EINVAL;
  15373. }
  15374. channel = (ntoh16(rxframe->channel) & WL_CHANSPEC_CHAN_MASK);
  15375. bzero(&bssid, ETHER_ADDR_LEN);
  15376. ndev = cfgdev_to_wlc_ndev(cfgdev, cfg);
  15377. if ((ndev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP) &&
  15378. (event == WLC_E_PROBREQ_MSG)) {
  15379. struct net_info *iter, *next;
  15380. GCC_DIAGNOSTIC_PUSH_SUPPRESS_CAST();
  15381. for_each_ndev(cfg, iter, next) {
  15382. GCC_DIAGNOSTIC_POP();
  15383. if (iter->ndev && iter->wdev &&
  15384. iter->wdev->iftype == NL80211_IFTYPE_AP) {
  15385. ndev = iter->ndev;
  15386. cfgdev = ndev_to_cfgdev(ndev);
  15387. break;
  15388. }
  15389. }
  15390. }
  15391. if (channel <= CH_MAX_2G_CHANNEL)
  15392. band = wiphy->bands[IEEE80211_BAND_2GHZ];
  15393. else
  15394. band = wiphy->bands[IEEE80211_BAND_5GHZ];
  15395. if (!band) {
  15396. WL_ERR(("No valid band"));
  15397. return -EINVAL;
  15398. }
  15399. #if LINUX_VERSION_CODE == KERNEL_VERSION(2, 6, 38) && !defined(WL_COMPAT_WIRELESS)
  15400. freq = ieee80211_channel_to_frequency(channel);
  15401. (void)band->band;
  15402. #else
  15403. freq = ieee80211_channel_to_frequency(channel, band->band);
  15404. #endif // endif
  15405. if (event == WLC_E_ACTION_FRAME_RX) {
  15406. u8 ioctl_buf[WLC_IOCTL_SMLEN];
  15407. if ((err = wldev_iovar_getbuf_bsscfg(ndev, "cur_etheraddr",
  15408. NULL, 0, ioctl_buf, sizeof(ioctl_buf), bsscfgidx,
  15409. NULL)) != BCME_OK) {
  15410. WL_ERR(("WLC_GET_CUR_ETHERADDR failed, error %d\n", err));
  15411. goto exit;
  15412. }
  15413. err = wldev_ioctl_get(ndev, WLC_GET_BSSID, &bssid, ETHER_ADDR_LEN);
  15414. if (err < 0)
  15415. WL_ERR(("WLC_GET_BSSID error %d\n", err));
  15416. memcpy(da.octet, ioctl_buf, ETHER_ADDR_LEN);
  15417. err = wl_frame_get_mgmt(cfg, FC_ACTION, &da, &e->addr, &bssid,
  15418. &mgmt_frame, &mgmt_frame_len,
  15419. (u8 *)((wl_event_rx_frame_data_t *)rxframe + 1));
  15420. if (err < 0) {
  15421. WL_ERR(("Error in receiving action frame len %d channel %d freq %d\n",
  15422. mgmt_frame_len, channel, freq));
  15423. goto exit;
  15424. }
  15425. isfree = true;
  15426. if (wl_cfgp2p_is_pub_action(&mgmt_frame[DOT11_MGMT_HDR_LEN],
  15427. mgmt_frame_len - DOT11_MGMT_HDR_LEN)) {
  15428. act_frm = (wifi_p2p_pub_act_frame_t *)
  15429. (&mgmt_frame[DOT11_MGMT_HDR_LEN]);
  15430. } else if (wl_cfgp2p_is_p2p_action(&mgmt_frame[DOT11_MGMT_HDR_LEN],
  15431. mgmt_frame_len - DOT11_MGMT_HDR_LEN)) {
  15432. p2p_act_frm = (wifi_p2p_action_frame_t *)
  15433. (&mgmt_frame[DOT11_MGMT_HDR_LEN]);
  15434. (void) p2p_act_frm;
  15435. } else if (wl_cfgp2p_is_gas_action(&mgmt_frame[DOT11_MGMT_HDR_LEN],
  15436. mgmt_frame_len - DOT11_MGMT_HDR_LEN)) {
  15437. sd_act_frm = (wifi_p2psd_gas_pub_act_frame_t *)
  15438. (&mgmt_frame[DOT11_MGMT_HDR_LEN]);
  15439. if (sd_act_frm && wl_get_drv_status_all(cfg, WAITING_NEXT_ACT_FRM)) {
  15440. if (cfg->next_af_subtype == sd_act_frm->action) {
  15441. WL_DBG(("We got a right next frame of SD!(%d)\n",
  15442. sd_act_frm->action));
  15443. wl_clr_drv_status(cfg, WAITING_NEXT_ACT_FRM, ndev);
  15444. /* Stop waiting for next AF. */
  15445. wl_stop_wait_next_action_frame(cfg, ndev, bsscfgidx);
  15446. }
  15447. }
  15448. (void) sd_act_frm;
  15449. #ifdef WLTDLS
  15450. } else if ((mgmt_frame[DOT11_MGMT_HDR_LEN] == TDLS_AF_CATEGORY) ||
  15451. (wl_cfg80211_is_tdls_tunneled_frame(
  15452. &mgmt_frame[DOT11_MGMT_HDR_LEN],
  15453. mgmt_frame_len - DOT11_MGMT_HDR_LEN))) {
  15454. if (mgmt_frame[DOT11_MGMT_HDR_LEN] == TDLS_AF_CATEGORY) {
  15455. WL_ERR((" TDLS Action Frame Received type = %d \n",
  15456. mgmt_frame[DOT11_MGMT_HDR_LEN + 1]));
  15457. }
  15458. #ifdef TDLS_MSG_ONLY_WFD
  15459. if (!dhdp->tdls_mode) {
  15460. WL_DBG((" TDLS Frame filtered \n"));
  15461. goto exit;
  15462. }
  15463. #else
  15464. if (mgmt_frame[DOT11_MGMT_HDR_LEN + 1] == TDLS_ACTION_SETUP_RESP) {
  15465. cfg->tdls_mgmt_frame = mgmt_frame;
  15466. cfg->tdls_mgmt_frame_len = mgmt_frame_len;
  15467. cfg->tdls_mgmt_freq = freq;
  15468. return 0;
  15469. }
  15470. #endif /* TDLS_MSG_ONLY_WFD */
  15471. #endif /* WLTDLS */
  15472. #ifdef QOS_MAP_SET
  15473. } else if (mgmt_frame[DOT11_MGMT_HDR_LEN] == DOT11_ACTION_CAT_QOS) {
  15474. /* update QoS map set table */
  15475. bcm_tlv_t * qos_map_ie = NULL;
  15476. if ((qos_map_ie = bcm_parse_tlvs(&mgmt_frame[DOT11_MGMT_HDR_LEN],
  15477. mgmt_frame_len - DOT11_MGMT_HDR_LEN,
  15478. DOT11_MNG_QOS_MAP_ID)) != NULL) {
  15479. WL_DBG((" QoS map set IE found in QoS action frame\n"));
  15480. if (!cfg->up_table) {
  15481. cfg->up_table = (uint8 *)MALLOC(cfg->osh, UP_TABLE_MAX);
  15482. }
  15483. wl_set_up_table(cfg->up_table, qos_map_ie);
  15484. } else {
  15485. MFREE(cfg->osh, cfg->up_table, UP_TABLE_MAX);
  15486. }
  15487. #endif /* QOS_MAP_SET */
  15488. #ifdef WBTEXT
  15489. } else if (mgmt_frame[DOT11_MGMT_HDR_LEN] == DOT11_ACTION_CAT_RRM) {
  15490. /* radio measurement category */
  15491. switch (mgmt_frame[DOT11_MGMT_HDR_LEN+1]) {
  15492. case DOT11_RM_ACTION_NR_REP:
  15493. if (wl_cfg80211_recv_nbr_resp(ndev,
  15494. &mgmt_frame[DOT11_MGMT_HDR_LEN],
  15495. mgmt_frame_len - DOT11_MGMT_HDR_LEN)
  15496. == BCME_OK) {
  15497. WL_DBG(("RCC updated by nbr response\n"));
  15498. }
  15499. break;
  15500. default:
  15501. break;
  15502. }
  15503. #endif /* WBTEXT */
  15504. } else {
  15505. /*
  15506. * if we got normal action frame and ndev is p2p0,
  15507. * we have to change ndev from p2p0 to wlan0
  15508. */
  15509. #if defined(WES_SUPPORT)
  15510. if (wl_cfg80211_is_wes(&mgmt_frame[DOT11_MGMT_HDR_LEN],
  15511. mgmt_frame_len - DOT11_MGMT_HDR_LEN) && wes_mode == 0) {
  15512. /* Ignore WES VS Action frame */
  15513. goto exit;
  15514. }
  15515. #endif /* WES_SUPPORT */
  15516. if (cfg->next_af_subtype != P2P_PAF_SUBTYPE_INVALID) {
  15517. u8 action = 0;
  15518. if (wl_get_public_action(&mgmt_frame[DOT11_MGMT_HDR_LEN],
  15519. mgmt_frame_len - DOT11_MGMT_HDR_LEN, &action) != BCME_OK) {
  15520. WL_DBG(("Recived action is not public action frame\n"));
  15521. } else if (cfg->next_af_subtype == action) {
  15522. WL_DBG(("Recived action is the waiting action(%d)\n",
  15523. action));
  15524. wl_clr_drv_status(cfg, WAITING_NEXT_ACT_FRM, ndev);
  15525. /* Stop waiting for next AF. */
  15526. wl_stop_wait_next_action_frame(cfg, ndev, bsscfgidx);
  15527. }
  15528. }
  15529. }
  15530. if (act_frm) {
  15531. #ifdef WL_CFG80211_GON_COLLISION
  15532. if (act_frm->subtype == P2P_PAF_GON_REQ) {
  15533. wl_gon_req_collision(cfg,
  15534. &cfg->afx_hdl->pending_tx_act_frm->action_frame,
  15535. act_frm, ndev, e->addr, da);
  15536. if (cfg->block_gon_req_rx_count) {
  15537. WL_ERR(("drop frame GON Req Rx : count (%d)\n",
  15538. cfg->block_gon_req_rx_count));
  15539. cfg->block_gon_req_rx_count--;
  15540. goto exit;
  15541. }
  15542. } else if (act_frm->subtype == P2P_PAF_GON_CONF) {
  15543. /* if go formation done, clear it */
  15544. cfg->block_gon_req_tx_count = 0;
  15545. cfg->block_gon_req_rx_count = 0;
  15546. }
  15547. #endif /* WL_CFG80211_GON_COLLISION */
  15548. if (wl_get_drv_status_all(cfg, WAITING_NEXT_ACT_FRM)) {
  15549. if (cfg->next_af_subtype == act_frm->subtype) {
  15550. WL_DBG(("We got a right next frame!(%d)\n",
  15551. act_frm->subtype));
  15552. wl_clr_drv_status(cfg, WAITING_NEXT_ACT_FRM, ndev);
  15553. if (cfg->next_af_subtype == P2P_PAF_GON_CONF) {
  15554. OSL_SLEEP(20);
  15555. }
  15556. /* Stop waiting for next AF. */
  15557. wl_stop_wait_next_action_frame(cfg, ndev, bsscfgidx);
  15558. } else if ((cfg->next_af_subtype == P2P_PAF_GON_RSP) &&
  15559. (act_frm->subtype == P2P_PAF_GON_REQ)) {
  15560. /* If current received frame is GO NEG REQ and next
  15561. * expected frame is GO NEG RESP, do not send it up.
  15562. */
  15563. WL_ERR(("GO Neg req received while waiting for RESP."
  15564. "Discard incoming frame\n"));
  15565. goto exit;
  15566. }
  15567. }
  15568. }
  15569. wl_cfgp2p_print_actframe(false, &mgmt_frame[DOT11_MGMT_HDR_LEN],
  15570. mgmt_frame_len - DOT11_MGMT_HDR_LEN, channel);
  15571. if (act_frm && (act_frm->subtype == P2P_PAF_GON_CONF)) {
  15572. WL_DBG(("P2P: GO_NEG_PHASE status cleared \n"));
  15573. wl_clr_p2p_status(cfg, GO_NEG_PHASE);
  15574. }
  15575. } else if (event == WLC_E_PROBREQ_MSG) {
  15576. /* Handle probe reqs frame
  15577. * WPS-AP certification 4.2.13
  15578. */
  15579. struct parsed_ies prbreq_ies;
  15580. u32 prbreq_ie_len = 0;
  15581. bool pbc = 0;
  15582. WL_DBG((" Event WLC_E_PROBREQ_MSG received\n"));
  15583. mgmt_frame = (u8 *)(data);
  15584. mgmt_frame_len = ntoh32(e->datalen);
  15585. if (mgmt_frame_len < DOT11_MGMT_HDR_LEN) {
  15586. WL_ERR(("wrong datalen:%d\n", mgmt_frame_len));
  15587. return -EINVAL;
  15588. }
  15589. prbreq_ie_len = mgmt_frame_len - DOT11_MGMT_HDR_LEN;
  15590. /* Parse prob_req IEs */
  15591. if (wl_cfg80211_parse_ies(&mgmt_frame[DOT11_MGMT_HDR_LEN],
  15592. prbreq_ie_len, &prbreq_ies) < 0) {
  15593. WL_ERR(("Prob req get IEs failed\n"));
  15594. return 0;
  15595. }
  15596. if (prbreq_ies.wps_ie != NULL) {
  15597. wl_validate_wps_ie(
  15598. (const char *)prbreq_ies.wps_ie, prbreq_ies.wps_ie_len, &pbc);
  15599. WL_DBG((" wps_ie exist pbc = %d\n", pbc));
  15600. /* if pbc method, send prob_req mgmt frame to upper layer */
  15601. if (!pbc)
  15602. return 0;
  15603. } else
  15604. return 0;
  15605. #ifdef WL_SAE
  15606. } else if (event == WLC_E_EXT_AUTH_FRAME_RX) {
  15607. u8 ioctl_buf[WLC_IOCTL_SMLEN];
  15608. u8 *frame;
  15609. WL_DBG(("EVENT: auth frame rx received\n"));
  15610. if (e->datalen < sizeof(*rxframe)) {
  15611. WL_ERR(("EXT_AUTH_RX: event data too small. Ignoring event\n"));
  15612. return -EINVAL;
  15613. }
  15614. bzero(&da, sizeof(da));
  15615. if ((err = wldev_iovar_getbuf_bsscfg(ndev, "cur_etheraddr",
  15616. NULL, 0, ioctl_buf, sizeof(ioctl_buf), bsscfgidx,
  15617. NULL)) != BCME_OK) {
  15618. WL_ERR(("EXT_AUTH_RX: cur_etheraddr iovar failed, error %d\n", err));
  15619. goto exit;
  15620. }
  15621. memcpy(da.octet, ioctl_buf, ETHER_ADDR_LEN);
  15622. err = wldev_ioctl_get(ndev, WLC_GET_BSSID, &bssid, ETHER_ADDR_LEN);
  15623. if (err < 0) {
  15624. if (cfgdev_to_wdev(cfgdev)->iftype == NL80211_IFTYPE_STATION) {
  15625. memcpy(bssid.octet, da.octet, ETHER_ADDR_LEN);
  15626. } else {
  15627. WL_ERR(("EXT_AUTH_RX: WLC_GET_BSSID failed, error %d\n", err));
  15628. }
  15629. }
  15630. frame = (u8 *)((wl_event_rx_frame_data_t *)rxframe + 1);
  15631. frame += DOT11_MGMT_HDR_LEN;
  15632. mgmt_frame_len -= DOT11_MGMT_HDR_LEN;
  15633. err = wl_frame_get_mgmt(cfg, FC_AUTH, &da, &e->addr, &bssid,
  15634. &mgmt_frame, &mgmt_frame_len, frame);
  15635. if (err < 0) {
  15636. WL_ERR(("EXT_AUTH_RX: mgmt frame to cfg80211, len %d channel %d freq %d\n",
  15637. mgmt_frame_len, channel, freq));
  15638. goto exit;
  15639. }
  15640. isfree = true;
  15641. #endif /* WL_SAE */
  15642. } else {
  15643. mgmt_frame = (u8 *)((wl_event_rx_frame_data_t *)rxframe + 1);
  15644. /* wpa supplicant use probe request event for restarting another GON Req.
  15645. * but it makes GON Req repetition.
  15646. * so if src addr of prb req is same as my target device,
  15647. * do not send probe request event during sending action frame.
  15648. */
  15649. if (event == WLC_E_P2P_PROBREQ_MSG) {
  15650. WL_DBG((" Event %s\n", (event == WLC_E_P2P_PROBREQ_MSG) ?
  15651. "WLC_E_P2P_PROBREQ_MSG":"WLC_E_PROBREQ_MSG"));
  15652. #ifdef WL_CFG80211_USE_PRB_REQ_FOR_AF_TX
  15653. if (WL_DRV_STATUS_SENDING_AF_FRM_EXT(cfg) &&
  15654. !memcmp(cfg->afx_hdl->tx_dst_addr.octet, e->addr.octet,
  15655. ETHER_ADDR_LEN)) {
  15656. if (cfg->afx_hdl->pending_tx_act_frm &&
  15657. wl_get_drv_status_all(cfg, FINDING_COMMON_CHANNEL)) {
  15658. s32 channel = CHSPEC_CHANNEL(hton16(rxframe->channel));
  15659. WL_DBG(("PROBE REQUEST : Peer found, channel : %d\n",
  15660. channel));
  15661. cfg->afx_hdl->peer_chan = channel;
  15662. complete(&cfg->act_frm_scan);
  15663. }
  15664. }
  15665. #endif /* WL_CFG80211_USE_PRB_REQ_FOR_AF_TX */
  15666. /* Filter any P2P probe reqs arriving during the
  15667. * GO-NEG Phase
  15668. */
  15669. if (cfg->p2p &&
  15670. #if defined(P2P_IE_MISSING_FIX)
  15671. cfg->p2p_prb_noti &&
  15672. #endif // endif
  15673. wl_get_p2p_status(cfg, GO_NEG_PHASE)) {
  15674. WL_DBG(("Filtering P2P probe_req while "
  15675. "being in GO-Neg state\n"));
  15676. return 0;
  15677. }
  15678. }
  15679. }
  15680. if (discover_cfgdev(cfgdev, cfg))
  15681. WL_DBG(("Rx Managment frame For P2P Discovery Interface \n"));
  15682. else
  15683. WL_DBG(("Rx Managment frame For Iface (%s) \n", ndev->name));
  15684. #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 18, 0))
  15685. cfg80211_rx_mgmt(cfgdev, freq, 0, mgmt_frame, mgmt_frame_len, 0);
  15686. #elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 12, 0))
  15687. cfg80211_rx_mgmt(cfgdev, freq, 0, mgmt_frame, mgmt_frame_len, 0, GFP_ATOMIC);
  15688. #elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)) || \
  15689. defined(WL_COMPAT_WIRELESS)
  15690. cfg80211_rx_mgmt(cfgdev, freq, 0, mgmt_frame, mgmt_frame_len, GFP_ATOMIC);
  15691. #else
  15692. cfg80211_rx_mgmt(cfgdev, freq, mgmt_frame, mgmt_frame_len, GFP_ATOMIC);
  15693. #endif /* LINUX_VERSION >= VERSION(3, 18, 0) */
  15694. WL_DBG(("mgmt_frame_len (%d) , e->datalen (%d), channel (%d), freq (%d)\n",
  15695. mgmt_frame_len, ntoh32(e->datalen), channel, freq));
  15696. exit:
  15697. if (isfree) {
  15698. MFREE(cfg->osh, mgmt_frame, mgmt_frame_len);
  15699. }
  15700. return err;
  15701. }
  15702. static void wl_init_conf(struct wl_conf *conf)
  15703. {
  15704. WL_DBG(("Enter \n"));
  15705. conf->frag_threshold = (u32)-1;
  15706. conf->rts_threshold = (u32)-1;
  15707. conf->retry_short = (u32)-1;
  15708. conf->retry_long = (u32)-1;
  15709. conf->tx_power = -1;
  15710. }
  15711. static void wl_init_prof(struct bcm_cfg80211 *cfg, struct net_device *ndev)
  15712. {
  15713. unsigned long flags;
  15714. struct wl_profile *profile = wl_get_profile_by_netdev(cfg, ndev);
  15715. if (!profile) {
  15716. WL_ERR(("profile null\n"));
  15717. return;
  15718. }
  15719. WL_CFG_DRV_LOCK(&cfg->cfgdrv_lock, flags);
  15720. bzero(profile, sizeof(struct wl_profile));
  15721. WL_CFG_DRV_UNLOCK(&cfg->cfgdrv_lock, flags);
  15722. }
  15723. static void wl_init_event_handler(struct bcm_cfg80211 *cfg)
  15724. {
  15725. bzero(cfg->evt_handler, sizeof(cfg->evt_handler));
  15726. cfg->evt_handler[WLC_E_SCAN_COMPLETE] = wl_notify_scan_status;
  15727. cfg->evt_handler[WLC_E_AUTH] = wl_notify_connect_status;
  15728. cfg->evt_handler[WLC_E_ASSOC] = wl_notify_connect_status;
  15729. cfg->evt_handler[WLC_E_LINK] = wl_notify_connect_status;
  15730. cfg->evt_handler[WLC_E_DEAUTH_IND] = wl_notify_connect_status;
  15731. cfg->evt_handler[WLC_E_DEAUTH] = wl_notify_connect_status;
  15732. cfg->evt_handler[WLC_E_DISASSOC_IND] = wl_notify_connect_status;
  15733. cfg->evt_handler[WLC_E_ASSOC_IND] = wl_notify_connect_status;
  15734. cfg->evt_handler[WLC_E_REASSOC_IND] = wl_notify_connect_status;
  15735. cfg->evt_handler[WLC_E_ROAM] = wl_notify_roaming_status;
  15736. cfg->evt_handler[WLC_E_MIC_ERROR] = wl_notify_mic_status;
  15737. cfg->evt_handler[WLC_E_SET_SSID] = wl_notify_connect_status;
  15738. cfg->evt_handler[WLC_E_ACTION_FRAME_RX] = wl_notify_rx_mgmt_frame;
  15739. cfg->evt_handler[WLC_E_PROBREQ_MSG] = wl_notify_rx_mgmt_frame;
  15740. cfg->evt_handler[WLC_E_P2P_PROBREQ_MSG] = wl_notify_rx_mgmt_frame;
  15741. cfg->evt_handler[WLC_E_P2P_DISC_LISTEN_COMPLETE] = wl_cfgp2p_listen_complete;
  15742. cfg->evt_handler[WLC_E_ACTION_FRAME_COMPLETE] = wl_cfgp2p_action_tx_complete;
  15743. cfg->evt_handler[WLC_E_ACTION_FRAME_OFF_CHAN_COMPLETE] = wl_cfgp2p_action_tx_complete;
  15744. cfg->evt_handler[WLC_E_JOIN] = wl_notify_connect_status;
  15745. cfg->evt_handler[WLC_E_START] = wl_notify_connect_status;
  15746. cfg->evt_handler[WLC_E_AUTH_IND] = wl_notify_connect_status;
  15747. cfg->evt_handler[WLC_E_ASSOC_RESP_IE] = wl_notify_connect_status;
  15748. #ifdef PNO_SUPPORT
  15749. cfg->evt_handler[WLC_E_PFN_NET_FOUND] = wl_notify_pfn_status;
  15750. #endif /* PNO_SUPPORT */
  15751. #ifdef GSCAN_SUPPORT
  15752. cfg->evt_handler[WLC_E_PFN_BEST_BATCHING] = wl_notify_gscan_event;
  15753. cfg->evt_handler[WLC_E_PFN_SCAN_COMPLETE] = wl_notify_gscan_event;
  15754. cfg->evt_handler[WLC_E_PFN_GSCAN_FULL_RESULT] = wl_notify_gscan_event;
  15755. cfg->evt_handler[WLC_E_PFN_BSSID_NET_FOUND] = wl_notify_gscan_event;
  15756. cfg->evt_handler[WLC_E_PFN_BSSID_NET_LOST] = wl_notify_gscan_event;
  15757. cfg->evt_handler[WLC_E_PFN_SSID_EXT] = wl_notify_gscan_event;
  15758. cfg->evt_handler[WLC_E_GAS_FRAGMENT_RX] = wl_notify_gscan_event;
  15759. cfg->evt_handler[WLC_E_ROAM_EXP_EVENT] = wl_handle_roam_exp_event;
  15760. #endif /* GSCAN_SUPPORT */
  15761. #ifdef RSSI_MONITOR_SUPPORT
  15762. cfg->evt_handler[WLC_E_RSSI_LQM] = wl_handle_rssi_monitor_event;
  15763. #endif /* RSSI_MONITOR_SUPPORT */
  15764. #ifdef WLTDLS
  15765. cfg->evt_handler[WLC_E_TDLS_PEER_EVENT] = wl_tdls_event_handler;
  15766. #endif /* WLTDLS */
  15767. cfg->evt_handler[WLC_E_BSSID] = wl_notify_roaming_status;
  15768. #ifdef WLAIBSS
  15769. cfg->evt_handler[WLC_E_AIBSS_TXFAIL] = wl_notify_aibss_txfail;
  15770. #endif /* WLAIBSS */
  15771. #ifdef WL_RELMCAST
  15772. cfg->evt_handler[WLC_E_RMC_EVENT] = wl_notify_rmc_status;
  15773. #endif /* WL_RELMCAST */
  15774. #ifdef BT_WIFI_HANDOVER
  15775. cfg->evt_handler[WLC_E_BT_WIFI_HANDOVER_REQ] = wl_notify_bt_wifi_handover_req;
  15776. #endif // endif
  15777. #ifdef WL_NAN
  15778. cfg->evt_handler[WLC_E_NAN_CRITICAL] = wl_cfgnan_notify_nan_status;
  15779. cfg->evt_handler[WLC_E_NAN_NON_CRITICAL] = wl_cfgnan_notify_nan_status;
  15780. #endif /* WL_NAN */
  15781. cfg->evt_handler[WLC_E_CSA_COMPLETE_IND] = wl_csa_complete_ind;
  15782. cfg->evt_handler[WLC_E_AP_STARTED] = wl_ap_start_ind;
  15783. #ifdef CUSTOM_EVENT_PM_WAKE
  15784. cfg->evt_handler[WLC_E_EXCESS_PM_WAKE_EVENT] = wl_check_pmstatus;
  15785. #endif /* CUSTOM_EVENT_PM_WAKE */
  15786. #if defined(DHD_LOSSLESS_ROAMING) || defined(DBG_PKT_MON)
  15787. cfg->evt_handler[WLC_E_ROAM_PREP] = wl_notify_roam_prep_status;
  15788. #endif /* DHD_LOSSLESS_ROAMING || DBG_PKT_MON */
  15789. cfg->evt_handler[WLC_E_ROAM_START] = wl_notify_roam_start_status;
  15790. #ifdef WL_BAM
  15791. cfg->evt_handler[WLC_E_ADPS] = wl_adps_event_handler;
  15792. #endif /* WL_BAM */
  15793. cfg->evt_handler[WLC_E_PSK_SUP] = wl_cfg80211_sup_event_handler;
  15794. #ifdef WL_BCNRECV
  15795. cfg->evt_handler[WLC_E_BCNRECV_ABORTED] = wl_bcnrecv_aborted_event_handler;
  15796. #endif /* WL_BCNRECV */
  15797. #ifdef WL_MBO
  15798. cfg->evt_handler[WLC_E_MBO] = wl_mbo_event_handler;
  15799. #endif /* WL_MBO */
  15800. #ifdef WL_CAC_TS
  15801. cfg->evt_handler[WLC_E_ADDTS_IND] = wl_cfg80211_cac_event_handler;
  15802. cfg->evt_handler[WLC_E_DELTS_IND] = wl_cfg80211_cac_event_handler;
  15803. #endif /* WL_CAC_TS */
  15804. #if defined(WL_MBO) || defined(WL_OCE)
  15805. cfg->evt_handler[WLC_E_PRUNE] = wl_bssid_prune_event_handler;
  15806. #endif /* WL_MBO || WL_OCE */
  15807. #ifdef RTT_SUPPORT
  15808. cfg->evt_handler[WLC_E_PROXD] = wl_cfg80211_rtt_event_handler;
  15809. #endif // endif
  15810. #ifdef WL_CHAN_UTIL
  15811. cfg->evt_handler[WLC_E_BSS_LOAD] = wl_cfg80211_bssload_report_event_handler;
  15812. #endif /* WL_CHAN_UTIL */
  15813. cfg->evt_handler[WLC_E_IND_DOS_STATUS] = wl_notify_dos_status;
  15814. #ifdef WL_SAE
  15815. cfg->evt_handler[WLC_E_EXT_AUTH_REQ] = wl_notify_extauth_req_event;
  15816. cfg->evt_handler[WLC_E_EXT_AUTH_FRAME_RX] = wl_notify_rx_mgmt_frame;
  15817. cfg->evt_handler[WLC_E_MGMT_FRAME_TXSTATUS] = wl_notify_mgmt_frame_tx_complete;
  15818. cfg->evt_handler[WLC_E_MGMT_FRAME_OFF_CHAN_COMPLETE] = wl_notify_mgmt_frame_tx_complete;
  15819. #endif /* WL_SAE */
  15820. }
  15821. #if defined(STATIC_WL_PRIV_STRUCT)
  15822. static int
  15823. wl_init_escan_result_buf(struct bcm_cfg80211 *cfg)
  15824. {
  15825. #ifdef DUAL_ESCAN_RESULT_BUFFER
  15826. cfg->escan_info.escan_buf[0] = DHD_OS_PREALLOC(cfg->pub,
  15827. DHD_PREALLOC_WIPHY_ESCAN0, ESCAN_BUF_SIZE);
  15828. if (cfg->escan_info.escan_buf[0] == NULL) {
  15829. WL_ERR(("Failed to alloc ESCAN_BUF0\n"));
  15830. return -ENOMEM;
  15831. }
  15832. cfg->escan_info.escan_buf[1] = DHD_OS_PREALLOC(cfg->pub,
  15833. DHD_PREALLOC_WIPHY_ESCAN1, ESCAN_BUF_SIZE);
  15834. if (cfg->escan_info.escan_buf[1] == NULL) {
  15835. WL_ERR(("Failed to alloc ESCAN_BUF1\n"));
  15836. return -ENOMEM;
  15837. }
  15838. bzero(cfg->escan_info.escan_buf[0], ESCAN_BUF_SIZE);
  15839. bzero(cfg->escan_info.escan_buf[1], ESCAN_BUF_SIZE);
  15840. cfg->escan_info.escan_type[0] = 0;
  15841. cfg->escan_info.escan_type[1] = 0;
  15842. #else
  15843. cfg->escan_info.escan_buf = DHD_OS_PREALLOC(cfg->pub,
  15844. DHD_PREALLOC_WIPHY_ESCAN0, ESCAN_BUF_SIZE);
  15845. if (cfg->escan_info.escan_buf == NULL) {
  15846. WL_ERR(("Failed to alloc ESCAN_BUF\n"));
  15847. return -ENOMEM;
  15848. }
  15849. bzero(cfg->escan_info.escan_buf, ESCAN_BUF_SIZE);
  15850. #endif /* DUAL_ESCAN_RESULT_BUFFER */
  15851. return 0;
  15852. }
  15853. static void
  15854. wl_deinit_escan_result_buf(struct bcm_cfg80211 *cfg)
  15855. {
  15856. #ifdef DUAL_ESCAN_RESULT_BUFFER
  15857. if (cfg->escan_info.escan_buf[0] != NULL) {
  15858. cfg->escan_info.escan_buf[0] = NULL;
  15859. cfg->escan_info.escan_type[0] = 0;
  15860. }
  15861. if (cfg->escan_info.escan_buf[1] != NULL) {
  15862. cfg->escan_info.escan_buf[1] = NULL;
  15863. cfg->escan_info.escan_type[1] = 0;
  15864. }
  15865. #else
  15866. if (cfg->escan_info.escan_buf != NULL) {
  15867. cfg->escan_info.escan_buf = NULL;
  15868. }
  15869. #endif /* DUAL_ESCAN_RESULT_BUFFER */
  15870. }
  15871. #endif /* STATIC_WL_PRIV_STRUCT */
  15872. static s32 wl_init_priv_mem(struct bcm_cfg80211 *cfg)
  15873. {
  15874. WL_DBG(("Enter \n"));
  15875. cfg->scan_results = (struct wl_scan_results *)MALLOCZ(cfg->osh,
  15876. WL_SCAN_BUF_MAX);
  15877. if (unlikely(!cfg->scan_results)) {
  15878. WL_ERR(("Scan results alloc failed\n"));
  15879. goto init_priv_mem_out;
  15880. }
  15881. cfg->conf = (struct wl_conf *)MALLOCZ(cfg->osh, sizeof(*cfg->conf));
  15882. if (unlikely(!cfg->conf)) {
  15883. WL_ERR(("wl_conf alloc failed\n"));
  15884. goto init_priv_mem_out;
  15885. }
  15886. cfg->scan_req_int = (void *)MALLOCZ(cfg->osh,
  15887. sizeof(*cfg->scan_req_int));
  15888. if (unlikely(!cfg->scan_req_int)) {
  15889. WL_ERR(("Scan req alloc failed\n"));
  15890. goto init_priv_mem_out;
  15891. }
  15892. cfg->ioctl_buf = (u8 *)MALLOCZ(cfg->osh, WLC_IOCTL_MAXLEN);
  15893. if (unlikely(!cfg->ioctl_buf)) {
  15894. WL_ERR(("Ioctl buf alloc failed\n"));
  15895. goto init_priv_mem_out;
  15896. }
  15897. cfg->escan_ioctl_buf = (void *)MALLOCZ(cfg->osh, WLC_IOCTL_MAXLEN);
  15898. if (unlikely(!cfg->escan_ioctl_buf)) {
  15899. WL_ERR(("Ioctl buf alloc failed\n"));
  15900. goto init_priv_mem_out;
  15901. }
  15902. cfg->extra_buf = (void *)MALLOCZ(cfg->osh, WL_EXTRA_BUF_MAX);
  15903. if (unlikely(!cfg->extra_buf)) {
  15904. WL_ERR(("Extra buf alloc failed\n"));
  15905. goto init_priv_mem_out;
  15906. }
  15907. cfg->pmk_list = (void *)MALLOCZ(cfg->osh, sizeof(*cfg->pmk_list));
  15908. if (unlikely(!cfg->pmk_list)) {
  15909. WL_ERR(("pmk list alloc failed\n"));
  15910. goto init_priv_mem_out;
  15911. }
  15912. #if defined(STATIC_WL_PRIV_STRUCT)
  15913. cfg->conn_info = (void *)MALLOCZ(cfg->osh, sizeof(*cfg->conn_info));
  15914. if (unlikely(!cfg->conn_info)) {
  15915. WL_ERR(("cfg->conn_info alloc failed\n"));
  15916. goto init_priv_mem_out;
  15917. }
  15918. cfg->ie = (void *)MALLOC(cfg->osh, sizeof(*cfg->ie));
  15919. if (unlikely(!cfg->ie)) {
  15920. WL_ERR(("cfg->ie alloc failed\n"));
  15921. goto init_priv_mem_out;
  15922. }
  15923. if (unlikely(wl_init_escan_result_buf(cfg))) {
  15924. WL_ERR(("Failed to init escan resul buf\n"));
  15925. goto init_priv_mem_out;
  15926. }
  15927. #endif /* STATIC_WL_PRIV_STRUCT */
  15928. cfg->afx_hdl = (void *)MALLOCZ(cfg->osh, sizeof(*cfg->afx_hdl));
  15929. if (unlikely(!cfg->afx_hdl)) {
  15930. WL_ERR(("afx hdl alloc failed\n"));
  15931. goto init_priv_mem_out;
  15932. } else {
  15933. init_completion(&cfg->act_frm_scan);
  15934. init_completion(&cfg->wait_next_af);
  15935. INIT_WORK(&cfg->afx_hdl->work, wl_cfg80211_afx_handler);
  15936. }
  15937. #ifdef WLTDLS
  15938. if (cfg->tdls_mgmt_frame) {
  15939. MFREE(cfg->osh, cfg->tdls_mgmt_frame, cfg->tdls_mgmt_frame_len);
  15940. cfg->tdls_mgmt_frame = NULL;
  15941. cfg->tdls_mgmt_frame_len = 0;
  15942. }
  15943. #endif /* WLTDLS */
  15944. return 0;
  15945. init_priv_mem_out:
  15946. wl_deinit_priv_mem(cfg);
  15947. return -ENOMEM;
  15948. }
  15949. static void wl_deinit_priv_mem(struct bcm_cfg80211 *cfg)
  15950. {
  15951. MFREE(cfg->osh, cfg->scan_results, WL_SCAN_BUF_MAX);
  15952. MFREE(cfg->osh, cfg->conf, sizeof(*cfg->conf));
  15953. MFREE(cfg->osh, cfg->scan_req_int, sizeof(*cfg->scan_req_int));
  15954. MFREE(cfg->osh, cfg->ioctl_buf, WLC_IOCTL_MAXLEN);
  15955. MFREE(cfg->osh, cfg->escan_ioctl_buf, WLC_IOCTL_MAXLEN);
  15956. MFREE(cfg->osh, cfg->extra_buf, WL_EXTRA_BUF_MAX);
  15957. MFREE(cfg->osh, cfg->pmk_list, sizeof(*cfg->pmk_list));
  15958. #if defined(STATIC_WL_PRIV_STRUCT)
  15959. MFREE(cfg->osh, cfg->conn_info, sizeof(*cfg->conn_info));
  15960. MFREE(cfg->osh, cfg->ie, sizeof(*cfg->ie));
  15961. wl_deinit_escan_result_buf(cfg);
  15962. #endif /* STATIC_WL_PRIV_STRUCT */
  15963. if (cfg->afx_hdl) {
  15964. cancel_work_sync(&cfg->afx_hdl->work);
  15965. MFREE(cfg->osh, cfg->afx_hdl, sizeof(*cfg->afx_hdl));
  15966. }
  15967. }
  15968. static s32 wl_create_event_handler(struct bcm_cfg80211 *cfg)
  15969. {
  15970. int ret = 0;
  15971. WL_DBG(("Enter \n"));
  15972. #ifdef OEM_ANDROID
  15973. /* Allocate workqueue for event */
  15974. if (!cfg->event_workq) {
  15975. cfg->event_workq = alloc_workqueue("dhd_eventd",
  15976. WQ_MEM_RECLAIM | WQ_HIGHPRI | WQ_UNBOUND, 1);
  15977. }
  15978. if (!cfg->event_workq) {
  15979. ret = -ENOMEM;
  15980. } else {
  15981. INIT_WORK(&cfg->event_work, wl_event_handler);
  15982. }
  15983. #else
  15984. INIT_WORK(&cfg->event_work, wl_event_handler);
  15985. cfg->event_workq_init = true;
  15986. #endif /* OEM_ANDROID */
  15987. return ret;
  15988. }
  15989. static void wl_destroy_event_handler(struct bcm_cfg80211 *cfg)
  15990. {
  15991. #ifdef OEM_ANDROID
  15992. if (cfg && cfg->event_workq) {
  15993. cancel_work_sync(&cfg->event_work);
  15994. destroy_workqueue(cfg->event_workq);
  15995. cfg->event_workq = NULL;
  15996. }
  15997. #else
  15998. if (cfg && cfg->event_workq_init) {
  15999. cancel_work_sync(&cfg->event_work);
  16000. cfg->event_workq_init = false;
  16001. }
  16002. #endif /* OEM_ANDROID */
  16003. }
  16004. void wl_terminate_event_handler(struct net_device *dev)
  16005. {
  16006. struct bcm_cfg80211 *cfg = wl_get_cfg(dev);
  16007. if (cfg) {
  16008. wl_destroy_event_handler(cfg);
  16009. wl_flush_eq(cfg);
  16010. }
  16011. }
  16012. #ifdef DHD_LOSSLESS_ROAMING
  16013. static void wl_del_roam_timeout(struct bcm_cfg80211 *cfg)
  16014. {
  16015. dhd_pub_t *dhdp = (dhd_pub_t *)(cfg->pub);
  16016. /* restore prec_map to ALLPRIO */
  16017. dhdp->dequeue_prec_map = ALLPRIO;
  16018. if (timer_pending(&cfg->roam_timeout)) {
  16019. del_timer_sync(&cfg->roam_timeout);
  16020. }
  16021. }
  16022. static void wl_roam_timeout(unsigned long data)
  16023. {
  16024. struct bcm_cfg80211 *cfg = (struct bcm_cfg80211 *)data;
  16025. dhd_pub_t *dhdp = (dhd_pub_t *)(cfg->pub);
  16026. WL_ERR(("roam timer expired\n"));
  16027. /* restore prec_map to ALLPRIO */
  16028. dhdp->dequeue_prec_map = ALLPRIO;
  16029. }
  16030. #endif /* DHD_LOSSLESS_ROAMING */
  16031. #if defined(CONFIG_WLAN_BEYONDX) || defined(CONFIG_SEC_5GMODEL)
  16032. #define CP_CHAN_INFO_RAT_MODE_LTE 3
  16033. #define CP_CHAN_INFO_RAT_MODE_NR5G 7
  16034. int g_mhs_chan_for_cpcoex = 0;
  16035. struct __packed cam_cp_noti_info {
  16036. u8 rat;
  16037. u32 band;
  16038. u32 channel;
  16039. };
  16040. int
  16041. wl_cfg80211_send_msg_to_ril()
  16042. {
  16043. int id, buf = 1;
  16044. id = IPC_SYSTEM_CP_CHANNEL_INFO;
  16045. dev_ril_bridge_send_msg(id, sizeof(int), &buf);
  16046. WL_ERR(("[BeyondX] send message to ril.\n"));
  16047. OSL_SLEEP(500);
  16048. return 0;
  16049. }
  16050. int
  16051. wl_cfg80211_ril_bridge_notifier_call(struct notifier_block *nb,
  16052. unsigned long size, void *buf)
  16053. {
  16054. struct dev_ril_bridge_msg *msg;
  16055. struct cam_cp_noti_info *cp_noti_info;
  16056. static int mhs_channel_for_4g, mhs_channel_for_5g;
  16057. static int recv_msg_4g, recv_msg_5g;
  16058. WL_ERR(("[BeyondX] receive message from ril.\n"));
  16059. msg = (struct dev_ril_bridge_msg *)buf;
  16060. if (msg->dev_id == IPC_SYSTEM_CP_CHANNEL_INFO &&
  16061. msg->data_len <= sizeof(struct cam_cp_noti_info)) {
  16062. u8 rat;
  16063. u32 band;
  16064. u32 channel;
  16065. cp_noti_info = (struct cam_cp_noti_info *)msg->data;
  16066. rat = cp_noti_info->rat;
  16067. band = cp_noti_info->band;
  16068. channel = cp_noti_info->channel;
  16069. /* LTE/5G Band/Freq information => Mobile Hotspot channel mapping.
  16070. * LTE/B40: 38650~39649 => Ch.11
  16071. * LTE/B41: 39650~41589 => Ch.1
  16072. * 5G/N41: 499200~537999 => Ch.1
  16073. */
  16074. if (rat == CP_CHAN_INFO_RAT_MODE_LTE) {
  16075. recv_msg_4g = 1;
  16076. if (channel >= 38650 && channel <= 39649) {
  16077. mhs_channel_for_4g = 11;
  16078. } else if (channel >= 39650 && channel <= 41589) {
  16079. mhs_channel_for_4g = 1;
  16080. }
  16081. }
  16082. if (rat == CP_CHAN_INFO_RAT_MODE_NR5G) {
  16083. recv_msg_5g = 1;
  16084. if (channel >= 499200 && channel <= 537999) {
  16085. mhs_channel_for_5g = 1;
  16086. }
  16087. }
  16088. WL_DBG(("[BeyondX] rat: %u, band: %u, channel: %u, mhs_channel_for_4g: %u, "
  16089. "mhs_channel_for_5g: %u\n", rat, band, channel,
  16090. mhs_channel_for_4g, mhs_channel_for_5g));
  16091. if (recv_msg_4g && recv_msg_5g) {
  16092. if (mhs_channel_for_4g && mhs_channel_for_5g) {
  16093. /* if 4G/B40 + 5G/N41, select channel 6 for MHS */
  16094. if (mhs_channel_for_4g == 11 && mhs_channel_for_5g == 1) {
  16095. g_mhs_chan_for_cpcoex = 6;
  16096. /* if 4G(except for B40) + 5G/N41, select channel 1 for MHS */
  16097. } else {
  16098. g_mhs_chan_for_cpcoex = 1;
  16099. }
  16100. } else {
  16101. g_mhs_chan_for_cpcoex = mhs_channel_for_4g ? mhs_channel_for_4g :
  16102. mhs_channel_for_5g ? mhs_channel_for_5g : 0;
  16103. }
  16104. mhs_channel_for_4g = mhs_channel_for_5g = 0;
  16105. recv_msg_4g = recv_msg_5g = 0;
  16106. }
  16107. }
  16108. return 0;
  16109. }
  16110. static struct notifier_block wl_cfg80211_ril_bridge_notifier = {
  16111. .notifier_call = wl_cfg80211_ril_bridge_notifier_call,
  16112. };
  16113. static bool wl_cfg80211_ril_bridge_notifier_registered = FALSE;
  16114. #endif /* CONFIG_WLAN_BEYONDX || defined(CONFIG_SEC_5GMODEL) */
  16115. static s32
  16116. wl_cfg80211_netdev_notifier_call(struct notifier_block * nb,
  16117. unsigned long state, void *ptr)
  16118. {
  16119. #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 11, 0))
  16120. struct net_device *dev = ptr;
  16121. #else
  16122. struct net_device *dev = netdev_notifier_info_to_dev(ptr);
  16123. #endif /* LINUX_VERSION < VERSION(3, 11, 0) */
  16124. struct wireless_dev *wdev = NULL;
  16125. struct bcm_cfg80211 *cfg = NULL;
  16126. WL_DBG(("Enter state:%lu ndev%p \n", state, dev));
  16127. if (!dev) {
  16128. WL_ERR(("dev null\n"));
  16129. return NOTIFY_DONE;
  16130. }
  16131. wdev = ndev_to_wdev(dev);
  16132. if (!wdev) {
  16133. WL_ERR(("wdev null. Do nothing\n"));
  16134. return NOTIFY_DONE;
  16135. }
  16136. cfg = (struct bcm_cfg80211 *)wiphy_priv(wdev->wiphy);
  16137. if (!cfg || (cfg != wl_cfg80211_get_bcmcfg())) {
  16138. /* If cfg80211 priv is null or doesn't match return */
  16139. WL_ERR(("wrong cfg ptr (%p)\n", cfg));
  16140. return NOTIFY_DONE;
  16141. }
  16142. if (dev == bcmcfg_to_prmry_ndev(cfg)) {
  16143. /* Nothing to be done for primary I/F */
  16144. return NOTIFY_DONE;
  16145. }
  16146. switch (state) {
  16147. case NETDEV_DOWN:
  16148. {
  16149. #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 11, 0))
  16150. int max_wait_timeout = 2;
  16151. int max_wait_count = 100;
  16152. int refcnt = 0;
  16153. unsigned long limit = jiffies + max_wait_timeout * HZ;
  16154. while (work_pending(&wdev->cleanup_work)) {
  16155. if (refcnt%5 == 0) {
  16156. WL_ERR(("[NETDEV_DOWN] wait for "
  16157. "complete of cleanup_work"
  16158. " (%d th)\n", refcnt));
  16159. }
  16160. if (!time_before(jiffies, limit)) {
  16161. WL_ERR(("[NETDEV_DOWN] cleanup_work"
  16162. " of CFG80211 is not"
  16163. " completed in %d sec\n",
  16164. max_wait_timeout));
  16165. break;
  16166. }
  16167. if (refcnt >= max_wait_count) {
  16168. WL_ERR(("[NETDEV_DOWN] cleanup_work"
  16169. " of CFG80211 is not"
  16170. " completed in %d loop\n",
  16171. max_wait_count));
  16172. break;
  16173. }
  16174. set_current_state(TASK_INTERRUPTIBLE);
  16175. (void)schedule_timeout(100);
  16176. set_current_state(TASK_RUNNING);
  16177. refcnt++;
  16178. }
  16179. #endif /* LINUX_VERSION < VERSION(3, 14, 0) */
  16180. break;
  16181. }
  16182. case NETDEV_UNREGISTER:
  16183. wl_cfg80211_clear_per_bss_ies(cfg, wdev);
  16184. /* after calling list_del_rcu(&wdev->list) */
  16185. wl_dealloc_netinfo_by_wdev(cfg, wdev);
  16186. break;
  16187. case NETDEV_GOING_DOWN:
  16188. /*
  16189. * At NETDEV_DOWN state, wdev_cleanup_work work will be called.
  16190. * In front of door, the function checks whether current scan
  16191. * is working or not. If the scanning is still working,
  16192. * wdev_cleanup_work call WARN_ON and make the scan done forcibly.
  16193. */
  16194. if (wl_get_drv_status(cfg, SCANNING, dev))
  16195. wl_cfg80211_cancel_scan(cfg);
  16196. break;
  16197. }
  16198. return NOTIFY_DONE;
  16199. }
  16200. static struct notifier_block wl_cfg80211_netdev_notifier = {
  16201. .notifier_call = wl_cfg80211_netdev_notifier_call,
  16202. };
  16203. /*
  16204. * to make sure we won't register the same notifier twice, otherwise a loop is likely to be
  16205. * created in kernel notifier link list (with 'next' pointing to itself)
  16206. */
  16207. static bool wl_cfg80211_netdev_notifier_registered = FALSE;
  16208. static void wl_cfg80211_concurrent_roam(struct bcm_cfg80211 *cfg, int enable)
  16209. {
  16210. u32 connected_cnt = wl_get_drv_status_all(cfg, CONNECTED);
  16211. bool p2p_connected = wl_cfgp2p_vif_created(cfg);
  16212. struct net_info *iter, *next;
  16213. if (!(cfg->roam_flags & WL_ROAM_OFF_ON_CONCURRENT))
  16214. return;
  16215. WL_DBG(("roam off:%d p2p_connected:%d connected_cnt:%d \n",
  16216. enable, p2p_connected, connected_cnt));
  16217. /* Disable FW roam when we have a concurrent P2P connection */
  16218. if (enable && p2p_connected && connected_cnt > 1) {
  16219. /* Mark it as to be reverted */
  16220. cfg->roam_flags |= WL_ROAM_REVERT_STATUS;
  16221. GCC_DIAGNOSTIC_PUSH_SUPPRESS_CAST();
  16222. for_each_ndev(cfg, iter, next) {
  16223. GCC_DIAGNOSTIC_POP();
  16224. if (iter->ndev && iter->wdev &&
  16225. iter->wdev->iftype == NL80211_IFTYPE_STATION) {
  16226. if (wldev_iovar_setint(iter->ndev, "roam_off", TRUE)
  16227. == BCME_OK) {
  16228. iter->roam_off = TRUE;
  16229. }
  16230. else {
  16231. WL_ERR(("error to enable roam_off\n"));
  16232. }
  16233. }
  16234. }
  16235. }
  16236. else if (!enable && (cfg->roam_flags & WL_ROAM_REVERT_STATUS)) {
  16237. cfg->roam_flags &= ~WL_ROAM_REVERT_STATUS;
  16238. GCC_DIAGNOSTIC_PUSH_SUPPRESS_CAST();
  16239. for_each_ndev(cfg, iter, next) {
  16240. GCC_DIAGNOSTIC_POP();
  16241. if (iter->ndev && iter->wdev &&
  16242. iter->wdev->iftype == NL80211_IFTYPE_STATION) {
  16243. if (iter->roam_off != WL_INVALID) {
  16244. if (wldev_iovar_setint(iter->ndev, "roam_off", FALSE)
  16245. == BCME_OK) {
  16246. iter->roam_off = FALSE;
  16247. }
  16248. else {
  16249. WL_ERR(("error to disable roam_off\n"));
  16250. }
  16251. }
  16252. }
  16253. }
  16254. }
  16255. return;
  16256. }
  16257. static void wl_cfg80211_determine_vsdb_mode(struct bcm_cfg80211 *cfg)
  16258. {
  16259. struct net_info *iter, *next;
  16260. u32 ctl_chan = 0;
  16261. u32 chanspec = 0;
  16262. u32 pre_ctl_chan = 0;
  16263. u32 connected_cnt = wl_get_drv_status_all(cfg, CONNECTED);
  16264. cfg->vsdb_mode = false;
  16265. if (connected_cnt <= 1) {
  16266. return;
  16267. }
  16268. GCC_DIAGNOSTIC_PUSH_SUPPRESS_CAST();
  16269. for_each_ndev(cfg, iter, next) {
  16270. GCC_DIAGNOSTIC_POP();
  16271. /* p2p discovery iface ndev could be null */
  16272. if (iter->ndev) {
  16273. chanspec = 0;
  16274. ctl_chan = 0;
  16275. if (wl_get_drv_status(cfg, CONNECTED, iter->ndev)) {
  16276. if (wldev_iovar_getint(iter->ndev, "chanspec",
  16277. (s32 *)&chanspec) == BCME_OK) {
  16278. chanspec = wl_chspec_driver_to_host(chanspec);
  16279. ctl_chan = wf_chspec_ctlchan(chanspec);
  16280. wl_update_prof(cfg, iter->ndev, NULL,
  16281. &ctl_chan, WL_PROF_CHAN);
  16282. }
  16283. if (!cfg->vsdb_mode) {
  16284. if (!pre_ctl_chan && ctl_chan)
  16285. pre_ctl_chan = ctl_chan;
  16286. else if (pre_ctl_chan && (pre_ctl_chan != ctl_chan)) {
  16287. cfg->vsdb_mode = true;
  16288. }
  16289. }
  16290. }
  16291. }
  16292. }
  16293. WL_ERR(("%s concurrency is enabled\n", cfg->vsdb_mode ? "Multi Channel" : "Same Channel"));
  16294. return;
  16295. }
  16296. int
  16297. wl_cfg80211_determine_p2p_rsdb_mode(struct bcm_cfg80211 *cfg)
  16298. {
  16299. struct net_info *iter, *next;
  16300. u32 chanspec = 0;
  16301. u32 band = 0;
  16302. u32 pre_band = 0;
  16303. bool is_rsdb_supported = FALSE;
  16304. bool rsdb_mode = FALSE;
  16305. is_rsdb_supported = DHD_OPMODE_SUPPORTED(cfg->pub, DHD_FLAG_RSDB_MODE);
  16306. if (!is_rsdb_supported) {
  16307. return 0;
  16308. }
  16309. GCC_DIAGNOSTIC_PUSH_SUPPRESS_CAST();
  16310. for_each_ndev(cfg, iter, next) {
  16311. GCC_DIAGNOSTIC_POP();
  16312. /* p2p discovery iface ndev could be null */
  16313. if (iter->ndev) {
  16314. chanspec = 0;
  16315. band = 0;
  16316. if (wl_get_drv_status(cfg, CONNECTED, iter->ndev)) {
  16317. if (wldev_iovar_getint(iter->ndev, "chanspec",
  16318. (s32 *)&chanspec) == BCME_OK) {
  16319. chanspec = wl_chspec_driver_to_host(chanspec);
  16320. band = CHSPEC_BAND(chanspec);
  16321. }
  16322. if (!pre_band && band) {
  16323. pre_band = band;
  16324. } else if (pre_band && (pre_band != band)) {
  16325. rsdb_mode = TRUE;
  16326. }
  16327. }
  16328. }
  16329. }
  16330. WL_DBG(("RSDB mode is %s\n", rsdb_mode ? "enabled" : "disabled"));
  16331. return rsdb_mode;
  16332. }
  16333. static s32 wl_notifier_change_state(struct bcm_cfg80211 *cfg, struct net_info *_net_info,
  16334. enum wl_status state, bool set)
  16335. {
  16336. s32 pm = PM_FAST;
  16337. s32 err = BCME_OK;
  16338. u32 mode;
  16339. u32 chan = 0;
  16340. struct net_device *primary_dev = bcmcfg_to_prmry_ndev(cfg);
  16341. dhd_pub_t *dhd = cfg->pub;
  16342. #ifdef RTT_SUPPORT
  16343. rtt_status_info_t *rtt_status;
  16344. #endif /* RTT_SUPPORT */
  16345. if (dhd->busstate == DHD_BUS_DOWN) {
  16346. WL_ERR(("busstate is DHD_BUS_DOWN!\n"));
  16347. return 0;
  16348. }
  16349. WL_DBG(("Enter state %d set %d _net_info->pm_restore %d iface %s\n",
  16350. state, set, _net_info->pm_restore, _net_info->ndev->name));
  16351. if (state != WL_STATUS_CONNECTED)
  16352. return 0;
  16353. mode = wl_get_mode_by_netdev(cfg, _net_info->ndev);
  16354. if (set) {
  16355. wl_cfg80211_concurrent_roam(cfg, 1);
  16356. wl_cfg80211_determine_vsdb_mode(cfg);
  16357. if (mode == WL_MODE_AP) {
  16358. if (wl_add_remove_eventmsg(primary_dev, WLC_E_P2P_PROBREQ_MSG, false))
  16359. WL_ERR((" failed to unset WLC_E_P2P_PROPREQ_MSG\n"));
  16360. }
  16361. pm = PM_OFF;
  16362. if ((err = wldev_ioctl_set(_net_info->ndev, WLC_SET_PM, &pm,
  16363. sizeof(pm))) != 0) {
  16364. if (err == -ENODEV)
  16365. WL_DBG(("%s:netdev not ready\n",
  16366. _net_info->ndev->name));
  16367. else
  16368. WL_ERR(("%s:error (%d)\n",
  16369. _net_info->ndev->name, err));
  16370. wl_cfg80211_update_power_mode(_net_info->ndev);
  16371. }
  16372. wl_add_remove_pm_enable_work(cfg, WL_PM_WORKQ_SHORT);
  16373. #if defined(WLTDLS)
  16374. if (wl_cfg80211_is_concurrent_mode(primary_dev)) {
  16375. err = wldev_iovar_setint(primary_dev, "tdls_enable", 0);
  16376. }
  16377. #endif /* defined(WLTDLS) */
  16378. #ifdef DISABLE_FRAMEBURST_VSDB
  16379. if (!DHD_OPMODE_SUPPORTED(cfg->pub, DHD_FLAG_HOSTAP_MODE) &&
  16380. wl_cfg80211_is_concurrent_mode(primary_dev) &&
  16381. !wl_cfg80211_determine_p2p_rsdb_mode(cfg)) {
  16382. wl_cfg80211_set_frameburst(cfg, FALSE);
  16383. }
  16384. #endif /* DISABLE_FRAMEBURST_VSDB */
  16385. #ifdef DISABLE_WL_FRAMEBURST_SOFTAP
  16386. if (DHD_OPMODE_STA_SOFTAP_CONCURR(dhd) &&
  16387. wl_get_drv_status(cfg, CONNECTED, bcmcfg_to_prmry_ndev(cfg))) {
  16388. /* Enable frameburst for
  16389. * STA/SoftAP concurrent mode
  16390. */
  16391. wl_cfg80211_set_frameburst(cfg, TRUE);
  16392. }
  16393. #endif /* DISABLE_WL_FRAMEBURST_SOFTAP */
  16394. } else { /* clear */
  16395. chan = 0;
  16396. /* clear chan information when the net device is disconnected */
  16397. wl_update_prof(cfg, _net_info->ndev, NULL, &chan, WL_PROF_CHAN);
  16398. wl_cfg80211_determine_vsdb_mode(cfg);
  16399. if (primary_dev == _net_info->ndev) {
  16400. pm = PM_FAST;
  16401. #ifdef RTT_SUPPORT
  16402. rtt_status = GET_RTTSTATE(dhd);
  16403. if (rtt_status->status != RTT_ENABLED)
  16404. #endif /* RTT_SUPPORT */
  16405. if ((err = wldev_ioctl_set(_net_info->ndev, WLC_SET_PM, &pm,
  16406. sizeof(pm))) != 0) {
  16407. if (err == -ENODEV)
  16408. WL_DBG(("%s:netdev not ready\n",
  16409. _net_info->ndev->name));
  16410. else
  16411. WL_ERR(("%s:error (%d)\n",
  16412. _net_info->ndev->name, err));
  16413. wl_cfg80211_update_power_mode(_net_info->ndev);
  16414. }
  16415. }
  16416. wl_cfg80211_concurrent_roam(cfg, 0);
  16417. #if defined(WLTDLS)
  16418. if (!wl_cfg80211_is_concurrent_mode(primary_dev)) {
  16419. err = wldev_iovar_setint(primary_dev, "tdls_enable", 1);
  16420. }
  16421. #endif /* defined(WLTDLS) */
  16422. #if defined(DISABLE_FRAMEBURST_VSDB)
  16423. if (!DHD_OPMODE_SUPPORTED(cfg->pub, DHD_FLAG_HOSTAP_MODE)) {
  16424. wl_cfg80211_set_frameburst(cfg, TRUE);
  16425. }
  16426. #endif /* DISABLE_FRAMEBURST_VSDB */
  16427. #ifdef DISABLE_WL_FRAMEBURST_SOFTAP
  16428. if (DHD_OPMODE_STA_SOFTAP_CONCURR(dhd) &&
  16429. (cfg->ap_oper_channel <= CH_MAX_2G_CHANNEL)) {
  16430. /* Disable frameburst for stand-alone 2GHz SoftAP */
  16431. wl_cfg80211_set_frameburst(cfg, FALSE);
  16432. }
  16433. #endif /* DISABLE_WL_FRAMEBURST_SOFTAP */
  16434. }
  16435. return err;
  16436. }
  16437. #ifdef DHD_LOSSLESS_ROAMING
  16438. static s32 wl_init_roam_timeout(struct bcm_cfg80211 *cfg)
  16439. {
  16440. int err = 0;
  16441. /* Init roam timer */
  16442. init_timer_compat(&cfg->roam_timeout, wl_roam_timeout, cfg);
  16443. return err;
  16444. }
  16445. #endif /* DHD_LOSSLESS_ROAMING */
  16446. static s32 wl_init_priv(struct bcm_cfg80211 *cfg)
  16447. {
  16448. struct wiphy *wiphy = bcmcfg_to_wiphy(cfg);
  16449. struct net_device *ndev = bcmcfg_to_prmry_ndev(cfg);
  16450. s32 err = 0;
  16451. cfg->scan_request = NULL;
  16452. cfg->pwr_save = !!(wiphy->flags & WIPHY_FLAG_PS_ON_BY_DEFAULT);
  16453. #ifdef DISABLE_BUILTIN_ROAM
  16454. cfg->roam_on = false;
  16455. #else
  16456. cfg->roam_on = true;
  16457. #endif /* DISABLE_BUILTIN_ROAM */
  16458. cfg->active_scan = true;
  16459. cfg->rf_blocked = false;
  16460. cfg->vsdb_mode = false;
  16461. #if defined(BCMSDIO)
  16462. cfg->wlfc_on = false;
  16463. #endif /* defined(BCMSDIO) */
  16464. cfg->roam_flags |= WL_ROAM_OFF_ON_CONCURRENT;
  16465. cfg->disable_roam_event = false;
  16466. /* register interested state */
  16467. set_bit(WL_STATUS_CONNECTED, &cfg->interrested_state);
  16468. spin_lock_init(&cfg->cfgdrv_lock);
  16469. mutex_init(&cfg->ioctl_buf_sync);
  16470. init_waitqueue_head(&cfg->netif_change_event);
  16471. init_completion(&cfg->send_af_done);
  16472. init_completion(&cfg->iface_disable);
  16473. wl_init_eq(cfg);
  16474. err = wl_init_priv_mem(cfg);
  16475. if (err)
  16476. return err;
  16477. if (wl_create_event_handler(cfg))
  16478. return -ENOMEM;
  16479. wl_init_event_handler(cfg);
  16480. mutex_init(&cfg->usr_sync);
  16481. mutex_init(&cfg->event_sync);
  16482. mutex_init(&cfg->if_sync);
  16483. mutex_init(&cfg->scan_sync);
  16484. #ifdef WLTDLS
  16485. mutex_init(&cfg->tdls_sync);
  16486. #endif /* WLTDLS */
  16487. #ifdef WL_BCNRECV
  16488. mutex_init(&cfg->bcn_sync);
  16489. #endif /* WL_BCNRECV */
  16490. #ifdef WL_WPS_SYNC
  16491. wl_init_wps_reauth_sm(cfg);
  16492. #endif /* WL_WPS_SYNC */
  16493. err = wl_init_scan(cfg);
  16494. if (err)
  16495. return err;
  16496. #ifdef DHD_LOSSLESS_ROAMING
  16497. err = wl_init_roam_timeout(cfg);
  16498. if (err) {
  16499. return err;
  16500. }
  16501. #endif /* DHD_LOSSLESS_ROAMING */
  16502. wl_init_conf(cfg->conf);
  16503. wl_init_prof(cfg, ndev);
  16504. wl_link_down(cfg);
  16505. DNGL_FUNC(dhd_cfg80211_init, (cfg));
  16506. #ifdef WL_NAN
  16507. cfg->nan_dp_state = NAN_DP_STATE_DISABLED;
  16508. init_waitqueue_head(&cfg->ndp_if_change_event);
  16509. #endif /* WL_NAN */
  16510. cfg->pmk_list->pmkids.length = OFFSETOF(pmkid_list_v3_t, pmkid);
  16511. cfg->pmk_list->pmkids.count = 0;
  16512. cfg->pmk_list->pmkids.version = PMKID_LIST_VER_3;
  16513. return err;
  16514. }
  16515. static void wl_deinit_priv(struct bcm_cfg80211 *cfg)
  16516. {
  16517. DNGL_FUNC(dhd_cfg80211_deinit, (cfg));
  16518. wl_destroy_event_handler(cfg);
  16519. wl_flush_eq(cfg);
  16520. wl_link_down(cfg);
  16521. del_timer_sync(&cfg->scan_timeout);
  16522. #ifdef DHD_LOSSLESS_ROAMING
  16523. del_timer_sync(&cfg->roam_timeout);
  16524. #endif // endif
  16525. wl_deinit_priv_mem(cfg);
  16526. if (wl_cfg80211_netdev_notifier_registered) {
  16527. wl_cfg80211_netdev_notifier_registered = FALSE;
  16528. unregister_netdevice_notifier(&wl_cfg80211_netdev_notifier);
  16529. }
  16530. }
  16531. #if defined(WL_ENABLE_P2P_IF) || defined(WL_NEWCFG_PRIVCMD_SUPPORT)
  16532. static s32 wl_cfg80211_attach_p2p(struct bcm_cfg80211 *cfg)
  16533. {
  16534. WL_TRACE(("Enter \n"));
  16535. if (wl_cfgp2p_register_ndev(cfg) < 0) {
  16536. WL_ERR(("P2P attach failed. \n"));
  16537. return -ENODEV;
  16538. }
  16539. return 0;
  16540. }
  16541. static s32 wl_cfg80211_detach_p2p(struct bcm_cfg80211 *cfg)
  16542. {
  16543. #ifndef WL_NEWCFG_PRIVCMD_SUPPORT
  16544. struct wireless_dev *wdev;
  16545. #endif /* WL_NEWCFG_PRIVCMD_SUPPORT */
  16546. WL_DBG(("Enter \n"));
  16547. if (!cfg) {
  16548. WL_ERR(("Invalid Ptr\n"));
  16549. return -EINVAL;
  16550. }
  16551. #ifndef WL_NEWCFG_PRIVCMD_SUPPORT
  16552. else {
  16553. wdev = cfg->p2p_wdev;
  16554. if (!wdev) {
  16555. WL_ERR(("Invalid Ptr\n"));
  16556. return -EINVAL;
  16557. }
  16558. }
  16559. #endif /* WL_NEWCFG_PRIVCMD_SUPPORT */
  16560. wl_cfgp2p_unregister_ndev(cfg);
  16561. cfg->p2p_wdev = NULL;
  16562. cfg->p2p_net = NULL;
  16563. #ifndef WL_NEWCFG_PRIVCMD_SUPPORT
  16564. WL_DBG(("Freeing 0x%p \n", wdev));
  16565. MFREE(cfg->osh, wdev, sizeof(*wdev));
  16566. #endif /* WL_NEWCFG_PRIVCMD_SUPPORT */
  16567. return 0;
  16568. }
  16569. #endif /* WL_ENABLE_P2P_IF || WL_NEWCFG_PRIVCMD_SUPPORT */
  16570. static s32 wl_cfg80211_attach_post(struct net_device *ndev)
  16571. {
  16572. struct bcm_cfg80211 * cfg;
  16573. s32 err = 0;
  16574. s32 ret = 0;
  16575. WL_TRACE(("In\n"));
  16576. if (unlikely(!ndev)) {
  16577. WL_ERR(("ndev is invaild\n"));
  16578. return -ENODEV;
  16579. }
  16580. cfg = wl_get_cfg(ndev);
  16581. if (unlikely(!cfg)) {
  16582. WL_ERR(("cfg is invaild\n"));
  16583. return -EINVAL;
  16584. }
  16585. if (!wl_get_drv_status(cfg, READY, ndev)) {
  16586. if (cfg->wdev) {
  16587. ret = wl_cfgp2p_supported(cfg, ndev);
  16588. if (ret > 0) {
  16589. #if !defined(WL_ENABLE_P2P_IF)
  16590. cfg->wdev->wiphy->interface_modes |=
  16591. (BIT(NL80211_IFTYPE_P2P_CLIENT)|
  16592. BIT(NL80211_IFTYPE_P2P_GO));
  16593. #endif /* !WL_ENABLE_P2P_IF */
  16594. if ((err = wl_cfgp2p_init_priv(cfg)) != 0)
  16595. goto fail;
  16596. #if defined(WL_ENABLE_P2P_IF)
  16597. if (cfg->p2p_net) {
  16598. /* Update MAC addr for p2p0 interface here. */
  16599. memcpy(cfg->p2p_net->dev_addr, ndev->dev_addr, ETH_ALEN);
  16600. cfg->p2p_net->dev_addr[0] |= 0x02;
  16601. WL_ERR(("%s: p2p_dev_addr="MACDBG "\n",
  16602. cfg->p2p_net->name,
  16603. MAC2STRDBG(cfg->p2p_net->dev_addr)));
  16604. } else {
  16605. WL_ERR(("p2p_net not yet populated."
  16606. " Couldn't update the MAC Address for p2p0 \n"));
  16607. return -ENODEV;
  16608. }
  16609. #endif /* WL_ENABLE_P2P_IF */
  16610. cfg->p2p_supported = true;
  16611. } else if (ret == 0) {
  16612. if ((err = wl_cfgp2p_init_priv(cfg)) != 0)
  16613. goto fail;
  16614. } else {
  16615. /* SDIO bus timeout */
  16616. err = -ENODEV;
  16617. goto fail;
  16618. }
  16619. }
  16620. }
  16621. wl_set_drv_status(cfg, READY, ndev);
  16622. fail:
  16623. return err;
  16624. }
  16625. struct bcm_cfg80211 *wl_get_cfg(struct net_device *ndev)
  16626. {
  16627. struct wireless_dev *wdev = ndev->ieee80211_ptr;
  16628. if (!wdev)
  16629. return NULL;
  16630. return wiphy_priv(wdev->wiphy);
  16631. }
  16632. s32
  16633. wl_cfg80211_net_attach(struct net_device *primary_ndev)
  16634. {
  16635. struct bcm_cfg80211 *cfg = wl_get_cfg(primary_ndev);
  16636. if (!cfg) {
  16637. WL_ERR(("cfg null\n"));
  16638. return BCME_ERROR;
  16639. }
  16640. #ifdef WL_STATIC_IF
  16641. /* Register dummy n/w iface. FW init will happen only from dev_open */
  16642. if (wl_cfg80211_register_static_if(cfg, NL80211_IFTYPE_STATION,
  16643. WL_STATIC_IFNAME_PREFIX) == NULL) {
  16644. WL_ERR(("static i/f registration failed!\n"));
  16645. return BCME_ERROR;
  16646. }
  16647. #endif /* WL_STATIC_IF */
  16648. return BCME_OK;
  16649. }
  16650. s32 wl_cfg80211_attach(struct net_device *ndev, void *context)
  16651. {
  16652. struct wireless_dev *wdev;
  16653. struct bcm_cfg80211 *cfg;
  16654. s32 err = 0;
  16655. struct device *dev;
  16656. u16 bssidx = 0;
  16657. u16 ifidx = 0;
  16658. dhd_pub_t *dhd = (struct dhd_pub *)(context);
  16659. WL_TRACE(("In\n"));
  16660. if (!ndev) {
  16661. WL_ERR(("ndev is invaild\n"));
  16662. return -ENODEV;
  16663. }
  16664. WL_DBG(("func %p\n", wl_cfg80211_get_parent_dev()));
  16665. dev = wl_cfg80211_get_parent_dev();
  16666. wdev = (struct wireless_dev *)MALLOCZ(dhd->osh, sizeof(*wdev));
  16667. if (unlikely(!wdev)) {
  16668. WL_ERR(("Could not allocate wireless device\n"));
  16669. return -ENOMEM;
  16670. }
  16671. err = wl_setup_wiphy(wdev, dev, context);
  16672. if (unlikely(err)) {
  16673. MFREE(dhd->osh, wdev, sizeof(*wdev));
  16674. return -ENOMEM;
  16675. }
  16676. wdev->iftype = wl_mode_to_nl80211_iftype(WL_MODE_BSS);
  16677. cfg = wiphy_priv(wdev->wiphy);
  16678. cfg->wdev = wdev;
  16679. cfg->pub = context;
  16680. cfg->osh = dhd->osh;
  16681. INIT_LIST_HEAD(&cfg->net_list);
  16682. #ifdef WBTEXT
  16683. INIT_LIST_HEAD(&cfg->wbtext_bssid_list);
  16684. #endif /* WBTEXT */
  16685. INIT_LIST_HEAD(&cfg->vndr_oui_list);
  16686. spin_lock_init(&cfg->vndr_oui_sync);
  16687. spin_lock_init(&cfg->net_list_sync);
  16688. ndev->ieee80211_ptr = wdev;
  16689. SET_NETDEV_DEV(ndev, wiphy_dev(wdev->wiphy));
  16690. wdev->netdev = ndev;
  16691. cfg->state_notifier = wl_notifier_change_state;
  16692. err = wl_alloc_netinfo(cfg, ndev, wdev, WL_IF_TYPE_STA, PM_ENABLE, bssidx, ifidx);
  16693. if (err) {
  16694. WL_ERR(("Failed to alloc net_info (%d)\n", err));
  16695. goto cfg80211_attach_out;
  16696. }
  16697. err = wl_init_priv(cfg);
  16698. if (err) {
  16699. WL_ERR(("Failed to init iwm_priv (%d)\n", err));
  16700. goto cfg80211_attach_out;
  16701. }
  16702. err = wl_setup_rfkill(cfg, TRUE);
  16703. if (err) {
  16704. WL_ERR(("Failed to setup rfkill %d\n", err));
  16705. goto cfg80211_attach_out;
  16706. }
  16707. #ifdef DEBUGFS_CFG80211
  16708. err = wl_setup_debugfs(cfg);
  16709. if (err) {
  16710. WL_ERR(("Failed to setup debugfs %d\n", err));
  16711. goto cfg80211_attach_out;
  16712. }
  16713. #endif // endif
  16714. if (!wl_cfg80211_netdev_notifier_registered) {
  16715. wl_cfg80211_netdev_notifier_registered = TRUE;
  16716. err = register_netdevice_notifier(&wl_cfg80211_netdev_notifier);
  16717. if (err) {
  16718. wl_cfg80211_netdev_notifier_registered = FALSE;
  16719. WL_ERR(("Failed to register notifierl %d\n", err));
  16720. goto cfg80211_attach_out;
  16721. }
  16722. }
  16723. #if defined(OEM_ANDROID) && defined(COEX_DHCP)
  16724. cfg->btcoex_info = wl_cfg80211_btcoex_init(cfg->wdev->netdev);
  16725. if (!cfg->btcoex_info)
  16726. goto cfg80211_attach_out;
  16727. #endif /* defined(OEM_ANDROID) && defined(COEX_DHCP) */
  16728. #if defined(SUPPORT_RANDOM_MAC_SCAN)
  16729. cfg->random_mac_enabled = FALSE;
  16730. #endif /* SUPPORT_RANDOM_MAC_SCAN */
  16731. #if defined(WL_ENABLE_P2P_IF) || defined(WL_NEWCFG_PRIVCMD_SUPPORT)
  16732. err = wl_cfg80211_attach_p2p(cfg);
  16733. if (err)
  16734. goto cfg80211_attach_out;
  16735. #endif /* WL_ENABLE_P2P_IF || WL_NEWCFG_PRIVCMD_SUPPORT */
  16736. INIT_DELAYED_WORK(&cfg->pm_enable_work, wl_cfg80211_work_handler);
  16737. mutex_init(&cfg->pm_sync);
  16738. #ifdef WL_NAN
  16739. mutex_init(&cfg->nancfg.nan_sync);
  16740. init_waitqueue_head(&cfg->nancfg.nan_event_wait);
  16741. #endif /* WL_NAN */
  16742. cfg->rssi_sum_report = FALSE;
  16743. #ifdef WL_BAM
  16744. wl_bad_ap_mngr_init(cfg);
  16745. #endif /* WL_BAM */
  16746. #ifdef BIGDATA_SOFTAP
  16747. wl_attach_ap_stainfo(cfg);
  16748. #endif /* BIGDATA_SOFTAP */
  16749. #ifdef WL_STATIC_IF
  16750. /* Register dummy n/w iface. FW init will happen only from dev_open */
  16751. if (wl_cfg80211_register_static_if(cfg, WL_IF_TYPE_AP,
  16752. WL_STATIC_IFNAME_PREFIX) == NULL) {
  16753. WL_ERR(("static i/f registration failed!\n"));
  16754. err = -ENODEV;
  16755. goto cfg80211_attach_out;
  16756. }
  16757. #endif /* WL_STATIC_IF */
  16758. return err;
  16759. cfg80211_attach_out:
  16760. wl_setup_rfkill(cfg, FALSE);
  16761. wl_free_wdev(cfg);
  16762. return err;
  16763. }
  16764. void wl_cfg80211_detach(struct bcm_cfg80211 *cfg)
  16765. {
  16766. WL_DBG(("Enter\n"));
  16767. if (!cfg) {
  16768. return;
  16769. }
  16770. wl_add_remove_pm_enable_work(cfg, WL_PM_WORKQ_DEL);
  16771. #if defined(OEM_ANDROID) && defined(COEX_DHCP)
  16772. wl_cfg80211_btcoex_deinit();
  16773. cfg->btcoex_info = NULL;
  16774. #endif /* defined(OEM_ANDROID) && defined(COEX_DHCP) */
  16775. wl_setup_rfkill(cfg, FALSE);
  16776. #ifdef DEBUGFS_CFG80211
  16777. wl_free_debugfs(cfg);
  16778. #endif // endif
  16779. if (cfg->p2p_supported) {
  16780. if (timer_pending(&cfg->p2p->listen_timer))
  16781. del_timer_sync(&cfg->p2p->listen_timer);
  16782. wl_cfgp2p_deinit_priv(cfg);
  16783. }
  16784. #ifdef WL_WPS_SYNC
  16785. wl_deinit_wps_reauth_sm(cfg);
  16786. #endif /* WL_WPS_SYNC */
  16787. if (timer_pending(&cfg->scan_timeout))
  16788. del_timer_sync(&cfg->scan_timeout);
  16789. #ifdef DHD_LOSSLESS_ROAMING
  16790. if (timer_pending(&cfg->roam_timeout)) {
  16791. del_timer_sync(&cfg->roam_timeout);
  16792. }
  16793. #endif /* DHD_LOSSLESS_ROAMING */
  16794. #ifdef WL_STATIC_IF
  16795. wl_cfg80211_unregister_static_if(cfg);
  16796. #endif /* WL_STATIC_IF */
  16797. #if defined(WL_CFG80211_P2P_DEV_IF)
  16798. if (cfg->p2p_wdev)
  16799. wl_cfgp2p_del_p2p_disc_if(cfg->p2p_wdev, cfg);
  16800. #endif /* WL_CFG80211_P2P_DEV_IF */
  16801. #if defined(WL_ENABLE_P2P_IF) || defined(WL_NEWCFG_PRIVCMD_SUPPORT)
  16802. wl_cfg80211_detach_p2p(cfg);
  16803. #endif /* WL_ENABLE_P2P_IF || WL_NEWCFG_PRIVCMD_SUPPORT */
  16804. #ifdef WL_BAM
  16805. wl_bad_ap_mngr_deinit(cfg);
  16806. #endif /* WL_BAM */
  16807. #ifdef BIGDATA_SOFTAP
  16808. wl_detach_ap_stainfo(cfg);
  16809. #endif /* BIGDATA_SOFTAP */
  16810. wl_cfg80211_ibss_vsie_free(cfg);
  16811. wl_dealloc_netinfo_by_wdev(cfg, cfg->wdev);
  16812. wl_cfg80211_set_bcmcfg(NULL);
  16813. wl_deinit_priv(cfg);
  16814. wl_cfg80211_clear_parent_dev();
  16815. wl_free_wdev(cfg);
  16816. /* PLEASE do NOT call any function after wl_free_wdev, the driver's private
  16817. * structure "cfg", which is the private part of wiphy, has been freed in
  16818. * wl_free_wdev !!!!!!!!!!!
  16819. */
  16820. WL_DBG(("Exit\n"));
  16821. }
  16822. #if defined(CONFIG_WLAN_BEYONDX) || defined(CONFIG_SEC_5GMODEL)
  16823. void wl_cfg80211_register_dev_ril_bridge_event_notifier()
  16824. {
  16825. WL_DBG(("Enter\n"));
  16826. if (!wl_cfg80211_ril_bridge_notifier_registered) {
  16827. s32 err = 0;
  16828. wl_cfg80211_ril_bridge_notifier_registered = TRUE;
  16829. err = register_dev_ril_bridge_event_notifier(&wl_cfg80211_ril_bridge_notifier);
  16830. if (err) {
  16831. wl_cfg80211_ril_bridge_notifier_registered = FALSE;
  16832. WL_ERR(("Failed to register ril_notifier! %d\n", err));
  16833. }
  16834. }
  16835. }
  16836. void wl_cfg80211_unregister_dev_ril_bridge_event_notifier()
  16837. {
  16838. WL_DBG(("Enter\n"));
  16839. if (wl_cfg80211_ril_bridge_notifier_registered) {
  16840. wl_cfg80211_ril_bridge_notifier_registered = FALSE;
  16841. unregister_dev_ril_bridge_event_notifier(&wl_cfg80211_ril_bridge_notifier);
  16842. }
  16843. }
  16844. #endif /* CONFIG_WLAN_BEYONDX || defined(CONFIG_SEC_5GMODEL) */
  16845. static void wl_print_event_data(struct bcm_cfg80211 *cfg,
  16846. uint32 event_type, const wl_event_msg_t *e)
  16847. {
  16848. s32 status = ntoh32(e->status);
  16849. s32 reason = ntoh32(e->reason);
  16850. s32 ifidx = ntoh32(e->ifidx);
  16851. s32 bssidx = ntoh32(e->bsscfgidx);
  16852. switch (event_type) {
  16853. case WLC_E_ESCAN_RESULT:
  16854. if ((status == WLC_E_STATUS_SUCCESS) ||
  16855. (status == WLC_E_STATUS_ABORT)) {
  16856. WL_INFORM_MEM(("event_type (%d), ifidx: %d"
  16857. " bssidx: %d scan_type:%d\n",
  16858. event_type, ifidx, bssidx, status));
  16859. }
  16860. break;
  16861. case WLC_E_LINK:
  16862. case WLC_E_DISASSOC:
  16863. case WLC_E_DISASSOC_IND:
  16864. case WLC_E_DEAUTH:
  16865. case WLC_E_DEAUTH_IND:
  16866. WL_INFORM_MEM(("event_type (%d), ifidx: %d bssidx: %d"
  16867. " status:%d reason:%d\n",
  16868. event_type, ifidx, bssidx, status, reason));
  16869. break;
  16870. default:
  16871. /* Print only when DBG verbose is enabled */
  16872. WL_DBG(("event_type (%d), ifidx: %d bssidx: %d status:%d reason: %d\n",
  16873. event_type, ifidx, bssidx, status, reason));
  16874. }
  16875. }
  16876. static void wl_event_handler(struct work_struct *work_data)
  16877. {
  16878. struct bcm_cfg80211 *cfg = NULL;
  16879. struct wl_event_q *e;
  16880. struct wireless_dev *wdev = NULL;
  16881. WL_DBG(("Enter \n"));
  16882. BCM_SET_CONTAINER_OF(cfg, work_data, struct bcm_cfg80211, event_work);
  16883. cfg->wl_evt_hdlr_entry_time = OSL_LOCALTIME_NS();
  16884. DHD_EVENT_WAKE_LOCK(cfg->pub);
  16885. while ((e = wl_deq_event(cfg))) {
  16886. s32 status = ntoh32(e->emsg.status);
  16887. u32 event_type = ntoh32(e->emsg.event_type);
  16888. bool scan_cmplt_evt = (event_type == WLC_E_ESCAN_RESULT) &&
  16889. ((status == WLC_E_STATUS_SUCCESS) || (status == WLC_E_STATUS_ABORT));
  16890. cfg->wl_evt_deq_time = OSL_LOCALTIME_NS();
  16891. if (scan_cmplt_evt) {
  16892. cfg->scan_deq_time = OSL_LOCALTIME_NS();
  16893. }
  16894. /* Print only critical events to avoid too many prints */
  16895. wl_print_event_data(cfg, e->etype, &e->emsg);
  16896. if (e->emsg.ifidx > WL_MAX_IFS) {
  16897. WL_ERR((" Event ifidx not in range. val:%d \n", e->emsg.ifidx));
  16898. goto fail;
  16899. }
  16900. /* Make sure iface operations, don't creat race conditions */
  16901. mutex_lock(&cfg->if_sync);
  16902. if (!(wdev = wl_get_wdev_by_fw_idx(cfg,
  16903. e->emsg.bsscfgidx, e->emsg.ifidx))) {
  16904. /* For WLC_E_IF would be handled by wl_host_event */
  16905. if (e->etype != WLC_E_IF)
  16906. WL_ERR(("No wdev corresponding to bssidx: 0x%x found!"
  16907. " Ignoring event.\n", e->emsg.bsscfgidx));
  16908. } else if (e->etype < WLC_E_LAST && cfg->evt_handler[e->etype]) {
  16909. dhd_pub_t *dhd = (struct dhd_pub *)(cfg->pub);
  16910. if (dhd->busstate == DHD_BUS_DOWN) {
  16911. WL_ERR((": BUS is DOWN.\n"));
  16912. } else
  16913. {
  16914. WL_DBG(("event_type %d event_sub %d\n",
  16915. ntoh32(e->emsg.event_type),
  16916. ntoh32(e->emsg.reason)));
  16917. cfg->evt_handler[e->etype](cfg, wdev_to_cfgdev(wdev),
  16918. &e->emsg, e->edata);
  16919. if (scan_cmplt_evt) {
  16920. cfg->scan_hdlr_cmplt_time = OSL_LOCALTIME_NS();
  16921. }
  16922. }
  16923. } else {
  16924. WL_DBG(("Unknown Event (%d): ignoring\n", e->etype));
  16925. }
  16926. mutex_unlock(&cfg->if_sync);
  16927. fail:
  16928. wl_put_event(cfg, e);
  16929. if (scan_cmplt_evt) {
  16930. cfg->scan_cmplt_time = OSL_LOCALTIME_NS();
  16931. }
  16932. cfg->wl_evt_hdlr_exit_time = OSL_LOCALTIME_NS();
  16933. }
  16934. DHD_EVENT_WAKE_UNLOCK(cfg->pub);
  16935. }
  16936. /*
  16937. * Generic API to handle critical events which doesnt need
  16938. * cfg enquening and sleepable API calls.
  16939. */
  16940. s32
  16941. wl_cfg80211_handle_critical_events(struct bcm_cfg80211 *cfg,
  16942. const wl_event_msg_t * e)
  16943. {
  16944. s32 ret = BCME_ERROR;
  16945. u32 event_type = ntoh32(e->event_type);
  16946. if (event_type >= WLC_E_LAST) {
  16947. return BCME_ERROR;
  16948. }
  16949. switch (event_type) {
  16950. case WLC_E_NAN_CRITICAL: {
  16951. #ifdef WL_NAN
  16952. if (ntoh32(e->reason) == WL_NAN_EVENT_STOP) {
  16953. /* Wakeup nan stop event waiting thread */
  16954. WL_INFORM_MEM((">> Critical Nan Stop Event Received\n"));
  16955. OSL_SMP_WMB();
  16956. cfg->nancfg.nan_event_recvd = true;
  16957. OSL_SMP_WMB();
  16958. wake_up(&cfg->nancfg.nan_event_wait);
  16959. ret = BCME_OK;
  16960. }
  16961. #endif /* WL_NAN */
  16962. break;
  16963. }
  16964. default:
  16965. ret = BCME_ERROR;
  16966. }
  16967. return ret;
  16968. }
  16969. void
  16970. wl_cfg80211_event(struct net_device *ndev, const wl_event_msg_t * e, void *data)
  16971. {
  16972. s32 status = ntoh32(e->status);
  16973. u32 event_type = ntoh32(e->event_type);
  16974. struct bcm_cfg80211 *cfg = wl_get_cfg(ndev);
  16975. struct net_info *netinfo;
  16976. WL_TRACE(("event_type (%d): reason (%d): %s\n", event_type, ntoh32(e->reason),
  16977. bcmevent_get_name(event_type)));
  16978. if ((cfg == NULL) || (cfg->p2p_supported && cfg->p2p == NULL)) {
  16979. WL_ERR(("Stale event ignored\n"));
  16980. return;
  16981. }
  16982. #ifdef OEM_ANDROID
  16983. if (cfg->event_workq == NULL) {
  16984. WL_ERR(("Event handler is not created\n"));
  16985. return;
  16986. }
  16987. #else
  16988. if (!cfg->event_workq_init) {
  16989. WL_ERR(("Event handler is not created\n"));
  16990. return;
  16991. }
  16992. #endif /* OEM_ANDROID */
  16993. if (event_type == WLC_E_IF) {
  16994. /* Don't process WLC_E_IF events in wl_cfg80211 layer */
  16995. return;
  16996. }
  16997. netinfo = wl_get_netinfo_by_fw_idx(cfg, e->bsscfgidx, e->ifidx);
  16998. if (!netinfo) {
  16999. /* Since the netinfo entry is not there, the netdev entry is not
  17000. * created via cfg80211 interface. so the event is not of interest
  17001. * to the cfg80211 layer.
  17002. */
  17003. WL_TRACE(("ignore event %d, not interested\n", event_type));
  17004. return;
  17005. }
  17006. /* Handle wl_cfg80211_critical_events */
  17007. if (wl_cfg80211_handle_critical_events(cfg, e) == BCME_OK) {
  17008. return;
  17009. }
  17010. if (event_type == WLC_E_PFN_NET_FOUND) {
  17011. WL_DBG((" PNOEVENT: PNO_NET_FOUND\n"));
  17012. }
  17013. else if (event_type == WLC_E_PFN_NET_LOST) {
  17014. WL_DBG((" PNOEVENT: PNO_NET_LOST\n"));
  17015. }
  17016. if (likely(!wl_enq_event(cfg, ndev, event_type, e, data))) {
  17017. #ifdef OEM_ANDROID
  17018. queue_work(cfg->event_workq, &cfg->event_work);
  17019. #else
  17020. schedule_work(&cfg->event_work);
  17021. #endif /* OEM_ANDROID */
  17022. }
  17023. /* Mark timeout value for thread sched */
  17024. if ((event_type == WLC_E_ESCAN_RESULT) &&
  17025. ((status == WLC_E_STATUS_SUCCESS) ||
  17026. (status == WLC_E_STATUS_ABORT))) {
  17027. cfg->scan_enq_time = OSL_LOCALTIME_NS();
  17028. WL_INFORM_MEM(("Enqueing escan completion (%d). WQ state:0x%x \n",
  17029. status, work_busy(&cfg->event_work)));
  17030. }
  17031. }
  17032. static void wl_init_eq(struct bcm_cfg80211 *cfg)
  17033. {
  17034. wl_init_eq_lock(cfg);
  17035. INIT_LIST_HEAD(&cfg->eq_list);
  17036. }
  17037. static void wl_flush_eq(struct bcm_cfg80211 *cfg)
  17038. {
  17039. struct wl_event_q *e;
  17040. unsigned long flags;
  17041. flags = wl_lock_eq(cfg);
  17042. while (!list_empty_careful(&cfg->eq_list)) {
  17043. BCM_SET_LIST_FIRST_ENTRY(e, &cfg->eq_list, struct wl_event_q, eq_list);
  17044. list_del(&e->eq_list);
  17045. MFREE(cfg->osh, e, e->datalen + sizeof(struct wl_event_q));
  17046. }
  17047. wl_unlock_eq(cfg, flags);
  17048. }
  17049. /*
  17050. * retrieve first queued event from head
  17051. */
  17052. static struct wl_event_q *wl_deq_event(struct bcm_cfg80211 *cfg)
  17053. {
  17054. struct wl_event_q *e = NULL;
  17055. unsigned long flags;
  17056. flags = wl_lock_eq(cfg);
  17057. if (likely(!list_empty(&cfg->eq_list))) {
  17058. BCM_SET_LIST_FIRST_ENTRY(e, &cfg->eq_list, struct wl_event_q, eq_list);
  17059. list_del(&e->eq_list);
  17060. }
  17061. wl_unlock_eq(cfg, flags);
  17062. return e;
  17063. }
  17064. /*
  17065. * push event to tail of the queue
  17066. */
  17067. static s32
  17068. wl_enq_event(struct bcm_cfg80211 *cfg, struct net_device *ndev, u32 event,
  17069. const wl_event_msg_t *msg, void *data)
  17070. {
  17071. struct wl_event_q *e;
  17072. s32 err = 0;
  17073. uint32 evtq_size;
  17074. uint32 data_len;
  17075. unsigned long flags;
  17076. data_len = 0;
  17077. if (data)
  17078. data_len = ntoh32(msg->datalen);
  17079. evtq_size = (uint32)(sizeof(struct wl_event_q) + data_len);
  17080. e = (struct wl_event_q *)MALLOCZ(cfg->osh, evtq_size);
  17081. if (unlikely(!e)) {
  17082. WL_ERR(("event alloc failed\n"));
  17083. return -ENOMEM;
  17084. }
  17085. e->etype = event;
  17086. memcpy(&e->emsg, msg, sizeof(wl_event_msg_t));
  17087. if (data)
  17088. memcpy(e->edata, data, data_len);
  17089. e->datalen = data_len;
  17090. flags = wl_lock_eq(cfg);
  17091. list_add_tail(&e->eq_list, &cfg->eq_list);
  17092. wl_unlock_eq(cfg, flags);
  17093. return err;
  17094. }
  17095. static void wl_put_event(struct bcm_cfg80211 *cfg, struct wl_event_q *e)
  17096. {
  17097. MFREE(cfg->osh, e, e->datalen + sizeof(struct wl_event_q));
  17098. }
  17099. static s32 wl_config_infra(struct bcm_cfg80211 *cfg, struct net_device *ndev, u16 iftype)
  17100. {
  17101. s32 infra = 0;
  17102. s32 err = 0;
  17103. bool skip_infra = false;
  17104. switch (iftype) {
  17105. case WL_IF_TYPE_IBSS:
  17106. case WL_IF_TYPE_AIBSS:
  17107. infra = 0;
  17108. break;
  17109. case WL_IF_TYPE_AP:
  17110. case WL_IF_TYPE_STA:
  17111. case WL_IF_TYPE_P2P_GO:
  17112. case WL_IF_TYPE_P2P_GC:
  17113. /* Intentional fall through */
  17114. infra = 1;
  17115. break;
  17116. case WL_IF_TYPE_MONITOR:
  17117. case WL_IF_TYPE_AWDL:
  17118. case WL_IF_TYPE_NAN:
  17119. /* Intentionall fall through */
  17120. default:
  17121. skip_infra = true;
  17122. WL_ERR(("Skipping infra setting for type:%d\n", iftype));
  17123. break;
  17124. }
  17125. if (!skip_infra) {
  17126. infra = htod32(infra);
  17127. err = wldev_ioctl_set(ndev, WLC_SET_INFRA, &infra, sizeof(infra));
  17128. if (unlikely(err)) {
  17129. WL_ERR(("WLC_SET_INFRA error (%d)\n", err));
  17130. return err;
  17131. }
  17132. }
  17133. return 0;
  17134. }
  17135. void wl_cfg80211_add_to_eventbuffer(struct wl_eventmsg_buf *ev, u16 event, bool set)
  17136. {
  17137. if (!ev || (event > WLC_E_LAST))
  17138. return;
  17139. if (ev->num < MAX_EVENT_BUF_NUM) {
  17140. ev->event[ev->num].type = event;
  17141. ev->event[ev->num].set = set;
  17142. ev->num++;
  17143. } else {
  17144. WL_ERR(("evenbuffer doesn't support > %u events. Update"
  17145. " the define MAX_EVENT_BUF_NUM \n", MAX_EVENT_BUF_NUM));
  17146. ASSERT(0);
  17147. }
  17148. }
  17149. s32 wl_cfg80211_apply_eventbuffer(
  17150. struct net_device *ndev,
  17151. struct bcm_cfg80211 *cfg,
  17152. wl_eventmsg_buf_t *ev)
  17153. {
  17154. char eventmask[WL_EVENTING_MASK_LEN];
  17155. int i, ret = 0;
  17156. s8 iovbuf[WL_EVENTING_MASK_LEN + 12];
  17157. if (!ev || (!ev->num))
  17158. return -EINVAL;
  17159. mutex_lock(&cfg->event_sync);
  17160. /* Read event_msgs mask */
  17161. ret = wldev_iovar_getbuf(ndev, "event_msgs", NULL, 0, iovbuf, sizeof(iovbuf), NULL);
  17162. if (unlikely(ret)) {
  17163. WL_ERR(("Get event_msgs error (%d)\n", ret));
  17164. goto exit;
  17165. }
  17166. memcpy(eventmask, iovbuf, WL_EVENTING_MASK_LEN);
  17167. /* apply the set bits */
  17168. for (i = 0; i < ev->num; i++) {
  17169. if (ev->event[i].set)
  17170. setbit(eventmask, ev->event[i].type);
  17171. else
  17172. clrbit(eventmask, ev->event[i].type);
  17173. }
  17174. /* Write updated Event mask */
  17175. ret = wldev_iovar_setbuf(ndev, "event_msgs", eventmask, sizeof(eventmask), iovbuf,
  17176. sizeof(iovbuf), NULL);
  17177. if (unlikely(ret)) {
  17178. WL_ERR(("Set event_msgs error (%d)\n", ret));
  17179. }
  17180. exit:
  17181. mutex_unlock(&cfg->event_sync);
  17182. return ret;
  17183. }
  17184. s32 wl_add_remove_eventmsg(struct net_device *ndev, u16 event, bool add)
  17185. {
  17186. s8 iovbuf[WL_EVENTING_MASK_LEN + 12];
  17187. s8 eventmask[WL_EVENTING_MASK_LEN];
  17188. s32 err = 0;
  17189. struct bcm_cfg80211 *cfg;
  17190. if (!ndev)
  17191. return -ENODEV;
  17192. cfg = wl_get_cfg(ndev);
  17193. if (!cfg)
  17194. return -ENODEV;
  17195. mutex_lock(&cfg->event_sync);
  17196. /* Setup event_msgs */
  17197. err = wldev_iovar_getbuf(ndev, "event_msgs", NULL, 0, iovbuf, sizeof(iovbuf), NULL);
  17198. if (unlikely(err)) {
  17199. WL_ERR(("Get event_msgs error (%d)\n", err));
  17200. goto eventmsg_out;
  17201. }
  17202. memcpy(eventmask, iovbuf, WL_EVENTING_MASK_LEN);
  17203. if (add) {
  17204. setbit(eventmask, event);
  17205. } else {
  17206. clrbit(eventmask, event);
  17207. }
  17208. err = wldev_iovar_setbuf(ndev, "event_msgs", eventmask, WL_EVENTING_MASK_LEN, iovbuf,
  17209. sizeof(iovbuf), NULL);
  17210. if (unlikely(err)) {
  17211. WL_ERR(("Set event_msgs error (%d)\n", err));
  17212. goto eventmsg_out;
  17213. }
  17214. eventmsg_out:
  17215. mutex_unlock(&cfg->event_sync);
  17216. return err;
  17217. }
  17218. static void wl_get_bwcap(struct bcm_cfg80211 *cfg, u32 bw_cap[])
  17219. {
  17220. u32 band, mimo_bwcap;
  17221. int err;
  17222. struct net_device *dev = bcmcfg_to_prmry_ndev(cfg);
  17223. band = WLC_BAND_2G;
  17224. err = wldev_iovar_getint(dev, "bw_cap", &band);
  17225. if (likely(!err)) {
  17226. bw_cap[NL80211_BAND_2GHZ] = band;
  17227. band = WLC_BAND_5G;
  17228. err = wldev_iovar_getint(dev, "bw_cap", &band);
  17229. if (likely(!err)) {
  17230. bw_cap[NL80211_BAND_5GHZ] = band;
  17231. return;
  17232. }
  17233. bw_cap[NL80211_BAND_5GHZ] |= WLC_BW_20MHZ_BIT;
  17234. WARN_ON(1);
  17235. return;
  17236. }
  17237. WL_ERR(("fallback to mimo_bw_cap info\n"));
  17238. mimo_bwcap = 0;
  17239. err = wldev_iovar_getint(dev, "mimo_bw_cap", &mimo_bwcap);
  17240. if (unlikely(err))
  17241. /* assume 20MHz if firmware does not give a clue */
  17242. mimo_bwcap = WLC_N_BW_20ALL;
  17243. switch (mimo_bwcap) {
  17244. case WLC_N_BW_40ALL:
  17245. bw_cap[NL80211_BAND_2GHZ] |= WLC_BW_40MHZ_BIT;
  17246. /* fall-thru */
  17247. case WLC_N_BW_20IN2G_40IN5G:
  17248. bw_cap[NL80211_BAND_5GHZ] |= WLC_BW_40MHZ_BIT;
  17249. /* fall-thru */
  17250. case WLC_N_BW_20ALL:
  17251. bw_cap[NL80211_BAND_2GHZ] |= WLC_BW_20MHZ_BIT;
  17252. bw_cap[NL80211_BAND_5GHZ] |= WLC_BW_20MHZ_BIT;
  17253. break;
  17254. default:
  17255. WL_ERR(("invalid mimo_bw_cap value\n"));
  17256. bw_cap[NL80211_BAND_2GHZ] |= WLC_BW_20MHZ_BIT;
  17257. bw_cap[NL80211_BAND_5GHZ] |= WLC_BW_20MHZ_BIT;
  17258. }
  17259. }
  17260. static void wl_update_ht_cap(struct ieee80211_supported_band *band,
  17261. u32 bwcap, u32 nchain)
  17262. {
  17263. band->ht_cap.ht_supported = TRUE;
  17264. if (bwcap & WLC_BW_40MHZ_BIT) {
  17265. band->ht_cap.cap |= IEEE80211_HT_CAP_SGI_40;
  17266. band->ht_cap.cap |= IEEE80211_HT_CAP_SUP_WIDTH_20_40;
  17267. }
  17268. band->ht_cap.cap |= IEEE80211_HT_CAP_SGI_20;
  17269. band->ht_cap.cap |= IEEE80211_HT_CAP_DSSSCCK40;
  17270. band->ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K;
  17271. band->ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_16;
  17272. band->ht_cap.mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED;
  17273. /* An HT shall support all EQM rates for one spatial stream */
  17274. memset(band->ht_cap.mcs.rx_mask, 0xff, nchain);
  17275. }
  17276. #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0))
  17277. static void wl_update_vht_cap(struct bcm_cfg80211 *cfg, struct ieee80211_supported_band *band,
  17278. u32 bwcap)
  17279. {
  17280. struct net_device *dev = bcmcfg_to_prmry_ndev(cfg);
  17281. s32 err = 0;
  17282. u32 j = 0;
  17283. s32 txstreams = 0;
  17284. s32 rxstreams = 0;
  17285. s32 ldpc_cap = 0;
  17286. s32 stbc_rx = 0;
  17287. s32 stbc_tx = 0;
  17288. s32 txbf_bfe_cap = 0;
  17289. s32 txbf_bfr_cap = 0;
  17290. /* not allowed in 2.4G band */
  17291. if (band->band == IEEE80211_BAND_2GHZ)
  17292. return;
  17293. if (bwcap == WLC_N_BW_40ALL || bwcap == WLC_N_BW_20IN2G_40IN5G)
  17294. band->ht_cap.cap |= IEEE80211_HT_CAP_SGI_40;
  17295. band->vht_cap.vht_supported = true;
  17296. err = wldev_iovar_getint(dev, "txstreams", &txstreams);
  17297. if (unlikely(err)) {
  17298. WL_ERR(("error reading txstreams (%d)\n", err));
  17299. }
  17300. err = wldev_iovar_getint(dev, "rxstreams", &rxstreams);
  17301. if (unlikely(err)) {
  17302. WL_ERR(("error reading rxstreams (%d)\n", err));
  17303. }
  17304. err = wldev_iovar_getint(dev, "ldpc_cap", &ldpc_cap);
  17305. if (unlikely(err)) {
  17306. WL_ERR(("error reading ldpc_cap (%d)\n", err));
  17307. }
  17308. err = wldev_iovar_getint(dev, "stbc_rx", &stbc_rx);
  17309. if (unlikely(err)) {
  17310. WL_ERR(("error reading stbc_rx (%d)\n", err));
  17311. }
  17312. err = wldev_iovar_getint(dev, "stbc_tx", &stbc_tx);
  17313. if (unlikely(err)) {
  17314. WL_ERR(("error reading stbc_tx (%d)\n", err));
  17315. }
  17316. err = wldev_iovar_getint(dev, "txbf_bfe_cap", &txbf_bfe_cap);
  17317. if (unlikely(err)) {
  17318. WL_ERR(("error reading txbf_bfe_cap (%d)\n", err));
  17319. }
  17320. err = wldev_iovar_getint(dev, "txbf_bfr_cap", &txbf_bfr_cap);
  17321. if (unlikely(err)) {
  17322. WL_ERR(("error reading txbf_bfr_cap (%d)\n", err));
  17323. }
  17324. /* Supported */
  17325. band->vht_cap.vht_supported = TRUE;
  17326. for (j = 1; j <= VHT_CAP_MCS_MAP_NSS_MAX; j++) {
  17327. /* TX stream rates. */
  17328. if (j <= txstreams) {
  17329. VHT_MCS_MAP_SET_MCS_PER_SS(j, VHT_CAP_MCS_MAP_0_9,
  17330. band->vht_cap.vht_mcs.tx_mcs_map);
  17331. } else {
  17332. VHT_MCS_MAP_SET_MCS_PER_SS(j, VHT_CAP_MCS_MAP_NONE,
  17333. band->vht_cap.vht_mcs.tx_mcs_map);
  17334. }
  17335. /* RX stream rates. */
  17336. if (j <= rxstreams) {
  17337. VHT_MCS_MAP_SET_MCS_PER_SS(j, VHT_CAP_MCS_MAP_0_9,
  17338. band->vht_cap.vht_mcs.rx_mcs_map);
  17339. } else {
  17340. VHT_MCS_MAP_SET_MCS_PER_SS(j, VHT_CAP_MCS_MAP_NONE,
  17341. band->vht_cap.vht_mcs.rx_mcs_map);
  17342. }
  17343. }
  17344. /* Capabilities */
  17345. /* 80 MHz is mandatory */
  17346. band->vht_cap.cap |=
  17347. IEEE80211_VHT_CAP_SHORT_GI_80;
  17348. if (WL_BW_CAP_160MHZ(bwcap)) {
  17349. band->vht_cap.cap |=
  17350. IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ;
  17351. band->vht_cap.cap |=
  17352. IEEE80211_VHT_CAP_SHORT_GI_160;
  17353. }
  17354. band->vht_cap.cap |=
  17355. IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_11454;
  17356. if (ldpc_cap)
  17357. band->vht_cap.cap |=
  17358. IEEE80211_VHT_CAP_RXLDPC;
  17359. if (stbc_tx)
  17360. band->vht_cap.cap |=
  17361. IEEE80211_VHT_CAP_TXSTBC;
  17362. if (stbc_rx)
  17363. band->vht_cap.cap |=
  17364. (stbc_rx << VHT_CAP_INFO_RX_STBC_SHIFT);
  17365. if (txbf_bfe_cap)
  17366. band->vht_cap.cap |=
  17367. IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE;
  17368. if (txbf_bfr_cap) {
  17369. band->vht_cap.cap |=
  17370. IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE;
  17371. }
  17372. if (txbf_bfe_cap || txbf_bfr_cap) {
  17373. band->vht_cap.cap |=
  17374. (2 << VHT_CAP_INFO_NUM_BMFMR_ANT_SHIFT);
  17375. band->vht_cap.cap |=
  17376. ((txstreams - 1) <<
  17377. VHT_CAP_INFO_NUM_SOUNDING_DIM_SHIFT);
  17378. band->vht_cap.cap |=
  17379. IEEE80211_VHT_CAP_VHT_LINK_ADAPTATION_VHT_MRQ_MFB;
  17380. }
  17381. /* AMPDU length limit, support max 1MB (2 ^ (13 + 7)) */
  17382. band->vht_cap.cap |=
  17383. (7 << VHT_CAP_INFO_AMPDU_MAXLEN_EXP_SHIFT);
  17384. WL_DBG(("%s 5GHz band vht_enab=%d vht_cap=%08x "
  17385. "vht_rx_mcs_map=%04x vht_tx_mcs_map=%04x\n",
  17386. __FUNCTION__,
  17387. band->vht_cap.vht_supported,
  17388. band->vht_cap.cap,
  17389. band->vht_cap.vht_mcs.rx_mcs_map,
  17390. band->vht_cap.vht_mcs.tx_mcs_map));
  17391. }
  17392. #endif // endif
  17393. static int wl_construct_reginfo(struct bcm_cfg80211 *cfg, s32 bw_cap[])
  17394. {
  17395. struct net_device *dev = bcmcfg_to_prmry_ndev(cfg);
  17396. struct ieee80211_channel *band_chan_arr = NULL;
  17397. wl_uint32_list_t *list;
  17398. u32 i, j, index, n_2g, n_5g, band, channel, array_size;
  17399. u32 *n_cnt = NULL;
  17400. chanspec_t c = 0;
  17401. s32 err = BCME_OK;
  17402. bool update;
  17403. bool ht40_allowed;
  17404. u8 *pbuf = NULL;
  17405. bool dfs_radar_disabled = FALSE;
  17406. #define LOCAL_BUF_LEN 2048
  17407. pbuf = (u8 *)MALLOCZ(cfg->osh, LOCAL_BUF_LEN);
  17408. if (pbuf == NULL) {
  17409. WL_ERR(("failed to allocate local buf\n"));
  17410. return -ENOMEM;
  17411. }
  17412. err = wldev_iovar_getbuf_bsscfg(dev, "chanspecs", NULL,
  17413. 0, pbuf, LOCAL_BUF_LEN, 0, &cfg->ioctl_buf_sync);
  17414. if (err != 0) {
  17415. WL_ERR(("get chanspecs failed with %d\n", err));
  17416. MFREE(cfg->osh, pbuf, LOCAL_BUF_LEN);
  17417. return err;
  17418. }
  17419. list = (wl_uint32_list_t *)(void *)pbuf;
  17420. band = array_size = n_2g = n_5g = 0;
  17421. for (i = 0; i < dtoh32(list->count); i++) {
  17422. index = 0;
  17423. update = false;
  17424. ht40_allowed = false;
  17425. c = (chanspec_t)dtoh32(list->element[i]);
  17426. c = wl_chspec_driver_to_host(c);
  17427. channel = wf_chspec_ctlchan(c);
  17428. if (!CHSPEC_IS40(c) && ! CHSPEC_IS20(c)) {
  17429. WL_DBG(("HT80/160/80p80 center channel : %d\n", channel));
  17430. continue;
  17431. }
  17432. if (CHSPEC_IS2G(c) && (channel >= CH_MIN_2G_CHANNEL) &&
  17433. (channel <= CH_MAX_2G_CHANNEL)) {
  17434. band_chan_arr = __wl_2ghz_channels;
  17435. array_size = ARRAYSIZE(__wl_2ghz_channels);
  17436. n_cnt = &n_2g;
  17437. band = IEEE80211_BAND_2GHZ;
  17438. ht40_allowed = (bw_cap[band] == WLC_N_BW_40ALL)? true : false;
  17439. } else if (CHSPEC_IS5G(c) && channel >= CH_MIN_5G_CHANNEL) {
  17440. band_chan_arr = __wl_5ghz_a_channels;
  17441. array_size = ARRAYSIZE(__wl_5ghz_a_channels);
  17442. n_cnt = &n_5g;
  17443. band = IEEE80211_BAND_5GHZ;
  17444. ht40_allowed = (bw_cap[band] == WLC_N_BW_20ALL)? false : true;
  17445. } else {
  17446. WL_ERR(("Invalid channel Sepc. 0x%x.\n", c));
  17447. continue;
  17448. }
  17449. if (!ht40_allowed && CHSPEC_IS40(c))
  17450. continue;
  17451. for (j = 0; (j < *n_cnt && (*n_cnt < array_size)); j++) {
  17452. if (band_chan_arr[j].hw_value == channel) {
  17453. update = true;
  17454. break;
  17455. }
  17456. }
  17457. if (update)
  17458. index = j;
  17459. else
  17460. index = *n_cnt;
  17461. if (index < array_size) {
  17462. #if LINUX_VERSION_CODE == KERNEL_VERSION(2, 6, 38) && !defined(WL_COMPAT_WIRELESS)
  17463. band_chan_arr[index].center_freq =
  17464. ieee80211_channel_to_frequency(channel);
  17465. #else
  17466. band_chan_arr[index].center_freq =
  17467. ieee80211_channel_to_frequency(channel, band);
  17468. #endif // endif
  17469. band_chan_arr[index].hw_value = channel;
  17470. band_chan_arr[index].beacon_found = false;
  17471. if (CHSPEC_IS40(c) && ht40_allowed) {
  17472. /* assuming the order is HT20, HT40 Upper,
  17473. * HT40 lower from chanspecs
  17474. */
  17475. u32 ht40_flag = band_chan_arr[index].flags & IEEE80211_CHAN_NO_HT40;
  17476. if (CHSPEC_SB_UPPER(c)) {
  17477. if (ht40_flag == IEEE80211_CHAN_NO_HT40)
  17478. band_chan_arr[index].flags &=
  17479. ~IEEE80211_CHAN_NO_HT40;
  17480. band_chan_arr[index].flags |= IEEE80211_CHAN_NO_HT40PLUS;
  17481. } else {
  17482. /* It should be one of
  17483. * IEEE80211_CHAN_NO_HT40 or IEEE80211_CHAN_NO_HT40PLUS
  17484. */
  17485. band_chan_arr[index].flags &= ~IEEE80211_CHAN_NO_HT40;
  17486. if (ht40_flag == IEEE80211_CHAN_NO_HT40)
  17487. band_chan_arr[index].flags |=
  17488. IEEE80211_CHAN_NO_HT40MINUS;
  17489. }
  17490. } else {
  17491. band_chan_arr[index].flags = IEEE80211_CHAN_NO_HT40;
  17492. if (!dfs_radar_disabled) {
  17493. if (band == IEEE80211_BAND_2GHZ)
  17494. channel |= WL_CHANSPEC_BAND_2G;
  17495. else
  17496. channel |= WL_CHANSPEC_BAND_5G;
  17497. channel |= WL_CHANSPEC_BW_20;
  17498. channel = wl_chspec_host_to_driver(channel);
  17499. err = wldev_iovar_getint(dev, "per_chan_info", &channel);
  17500. if (!err) {
  17501. if (channel & WL_CHAN_RADAR) {
  17502. #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 14, 0))
  17503. band_chan_arr[index].flags |=
  17504. (IEEE80211_CHAN_RADAR
  17505. | IEEE80211_CHAN_NO_IBSS);
  17506. #else
  17507. band_chan_arr[index].flags |=
  17508. IEEE80211_CHAN_RADAR;
  17509. #endif // endif
  17510. }
  17511. if (channel & WL_CHAN_PASSIVE)
  17512. #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 14, 0))
  17513. band_chan_arr[index].flags |=
  17514. IEEE80211_CHAN_PASSIVE_SCAN;
  17515. #else
  17516. band_chan_arr[index].flags |=
  17517. IEEE80211_CHAN_NO_IR;
  17518. #endif // endif
  17519. } else if (err == BCME_UNSUPPORTED) {
  17520. dfs_radar_disabled = TRUE;
  17521. WL_ERR(("does not support per_chan_info\n"));
  17522. }
  17523. }
  17524. }
  17525. if (!update)
  17526. (*n_cnt)++;
  17527. }
  17528. }
  17529. __wl_band_2ghz.n_channels = n_2g;
  17530. __wl_band_5ghz_a.n_channels = n_5g;
  17531. MFREE(cfg->osh, pbuf, LOCAL_BUF_LEN);
  17532. #undef LOCAL_BUF_LEN
  17533. return err;
  17534. }
  17535. static s32 __wl_update_wiphybands(struct bcm_cfg80211 *cfg, bool notify)
  17536. {
  17537. struct wiphy *wiphy;
  17538. struct net_device *dev = bcmcfg_to_prmry_ndev(cfg);
  17539. u32 bandlist[3];
  17540. u32 nband = 0;
  17541. u32 i = 0;
  17542. s32 err = 0;
  17543. s32 index = 0;
  17544. s32 nmode = 0;
  17545. u32 rxchain;
  17546. u32 nchain;
  17547. #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0))
  17548. s32 vhtmode = 0;
  17549. #endif // endif
  17550. u32 bw_cap[2] = { WLC_BW_20MHZ_BIT, WLC_BW_20MHZ_BIT };
  17551. s32 cur_band = -1;
  17552. struct ieee80211_supported_band *bands[IEEE80211_NUM_BANDS] = {NULL, };
  17553. bzero(bandlist, sizeof(bandlist));
  17554. err = wldev_ioctl_get(dev, WLC_GET_BANDLIST, bandlist,
  17555. sizeof(bandlist));
  17556. if (unlikely(err)) {
  17557. WL_ERR(("error read bandlist (%d)\n", err));
  17558. return err;
  17559. }
  17560. err = wldev_ioctl_get(dev, WLC_GET_BAND, &cur_band,
  17561. sizeof(s32));
  17562. if (unlikely(err)) {
  17563. WL_ERR(("error (%d)\n", err));
  17564. return err;
  17565. }
  17566. err = wldev_iovar_getint(dev, "nmode", &nmode);
  17567. if (unlikely(err)) {
  17568. WL_ERR(("error reading nmode (%d)\n", err));
  17569. }
  17570. #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0))
  17571. err = wldev_iovar_getint(dev, "vhtmode", &vhtmode);
  17572. if (unlikely(err)) {
  17573. WL_ERR(("error reading vhtmode (%d)\n", err));
  17574. }
  17575. #endif // endif
  17576. /* For nmode and vhtmode check bw cap */
  17577. if (nmode ||
  17578. #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0))
  17579. vhtmode ||
  17580. #endif // endif
  17581. 0) {
  17582. wl_get_bwcap(cfg, bw_cap);
  17583. }
  17584. err = wldev_iovar_getint(dev, "rxchain", &rxchain);
  17585. if (err) {
  17586. WL_ERR(("rxchain error (%d)\n", err));
  17587. nchain = 1;
  17588. } else {
  17589. for (nchain = 0; rxchain; nchain++)
  17590. rxchain = rxchain & (rxchain - 1);
  17591. }
  17592. WL_DBG(("nchain=%d\n", nchain));
  17593. err = wl_construct_reginfo(cfg, bw_cap);
  17594. if (err) {
  17595. WL_ERR(("wl_construct_reginfo() fails err=%d\n", err));
  17596. if (err != BCME_UNSUPPORTED)
  17597. return err;
  17598. }
  17599. wiphy = bcmcfg_to_wiphy(cfg);
  17600. nband = bandlist[0];
  17601. for (i = 1; i <= nband && i < ARRAYSIZE(bandlist); i++) {
  17602. index = -1;
  17603. if (bandlist[i] == WLC_BAND_5G && __wl_band_5ghz_a.n_channels > 0) {
  17604. index = IEEE80211_BAND_5GHZ;
  17605. bands[index] = &__wl_band_5ghz_a;
  17606. #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0))
  17607. if (vhtmode) {
  17608. wl_update_vht_cap(cfg, bands[index], bw_cap[index]);
  17609. }
  17610. #endif // endif
  17611. }
  17612. else if (bandlist[i] == WLC_BAND_2G && __wl_band_2ghz.n_channels > 0) {
  17613. index = IEEE80211_BAND_2GHZ;
  17614. bands[index] = &__wl_band_2ghz;
  17615. }
  17616. if ((index >= 0) && nmode) {
  17617. wl_update_ht_cap(bands[index], bw_cap[index], nchain);
  17618. }
  17619. }
  17620. wiphy->bands[IEEE80211_BAND_2GHZ] = bands[IEEE80211_BAND_2GHZ];
  17621. wiphy->bands[IEEE80211_BAND_5GHZ] = bands[IEEE80211_BAND_5GHZ];
  17622. /* check if any bands populated otherwise makes 2Ghz as default */
  17623. if (wiphy->bands[IEEE80211_BAND_2GHZ] == NULL &&
  17624. wiphy->bands[IEEE80211_BAND_5GHZ] == NULL) {
  17625. /* Setup 2Ghz band as default */
  17626. wiphy->bands[IEEE80211_BAND_2GHZ] = &__wl_band_2ghz;
  17627. }
  17628. if (notify)
  17629. wiphy_apply_custom_regulatory(wiphy, &brcm_regdom);
  17630. return 0;
  17631. }
  17632. s32 wl_update_wiphybands(struct bcm_cfg80211 *cfg, bool notify)
  17633. {
  17634. s32 err;
  17635. mutex_lock(&cfg->usr_sync);
  17636. err = __wl_update_wiphybands(cfg, notify);
  17637. mutex_unlock(&cfg->usr_sync);
  17638. return err;
  17639. }
  17640. static s32 __wl_cfg80211_up(struct bcm_cfg80211 *cfg)
  17641. {
  17642. s32 err = 0;
  17643. #ifdef WL_HOST_BAND_MGMT
  17644. s32 ret = 0;
  17645. #endif /* WL_HOST_BAND_MGMT */
  17646. struct net_info *netinfo = NULL;
  17647. struct net_device *ndev = bcmcfg_to_prmry_ndev(cfg);
  17648. struct wireless_dev *wdev = ndev->ieee80211_ptr;
  17649. #ifdef WBTEXT
  17650. dhd_pub_t *dhd = (dhd_pub_t *)(cfg->pub);
  17651. #endif /* WBTEXT */
  17652. #ifdef WLTDLS
  17653. u32 tdls;
  17654. #endif /* WLTDLS */
  17655. u16 wl_iftype = 0;
  17656. u16 wl_mode = 0;
  17657. u8 ioctl_buf[WLC_IOCTL_SMLEN];
  17658. WL_DBG(("In\n"));
  17659. /* Reserve 0x8000 toggle bit for P2P GO/GC */
  17660. cfg->vif_macaddr_mask = 0x8000;
  17661. err = dhd_config_dongle(cfg);
  17662. if (unlikely(err))
  17663. return err;
  17664. /* Always bring up interface in STA mode.
  17665. * Did observe , if previous SofAP Bringup/cleanup
  17666. * is not done properly, iftype is stuck with AP mode.
  17667. * So during next wlan0 up, forcing the type to STA
  17668. */
  17669. netinfo = wl_get_netinfo_by_wdev(cfg, wdev);
  17670. if (!netinfo) {
  17671. WL_ERR(("there is no netinfo\n"));
  17672. return -ENODEV;
  17673. }
  17674. ndev->ieee80211_ptr->iftype = NL80211_IFTYPE_STATION;
  17675. netinfo->iftype = WL_IF_TYPE_STA;
  17676. if (cfg80211_to_wl_iftype(wdev->iftype, &wl_iftype, &wl_mode) < 0) {
  17677. return -EINVAL;
  17678. }
  17679. err = wl_config_infra(cfg, ndev, wl_iftype);
  17680. if (unlikely(err && err != -EINPROGRESS)) {
  17681. WL_ERR(("wl_config_infra failed\n"));
  17682. if (err == -1) {
  17683. WL_ERR(("return error %d\n", err));
  17684. return err;
  17685. }
  17686. }
  17687. err = __wl_update_wiphybands(cfg, true);
  17688. if (unlikely(err)) {
  17689. WL_ERR(("wl_update_wiphybands failed\n"));
  17690. if (err == -1) {
  17691. WL_ERR(("return error %d\n", err));
  17692. return err;
  17693. }
  17694. }
  17695. if (!dhd_download_fw_on_driverload) {
  17696. err = wl_create_event_handler(cfg);
  17697. if (err) {
  17698. WL_ERR(("wl_create_event_handler failed\n"));
  17699. return err;
  17700. }
  17701. wl_init_event_handler(cfg);
  17702. }
  17703. err = wl_init_scan(cfg);
  17704. if (err) {
  17705. WL_ERR(("wl_init_scan failed\n"));
  17706. return err;
  17707. }
  17708. err = wldev_iovar_getbuf(ndev, "wlc_ver", NULL, 0,
  17709. &cfg->wlc_ver, sizeof(wl_wlc_version_t), NULL);
  17710. if (likely(!err)) {
  17711. WL_INFORM(("wl version. Major: %d\n",
  17712. cfg->wlc_ver.wlc_ver_major));
  17713. if ((cfg->wlc_ver.wlc_ver_major >= MIN_ESCAN_PARAM_V2_FW_MAJOR) &&
  17714. (wldev_iovar_getbuf(ndev, "scan_ver", NULL, 0,
  17715. ioctl_buf, sizeof(ioctl_buf), NULL) == BCME_OK)) {
  17716. WL_INFORM_MEM(("scan_params v2\n"));
  17717. /* use scan_params ver2 */
  17718. cfg->scan_params_v2 = true;
  17719. }
  17720. } else {
  17721. if (err == BCME_UNSUPPORTED) {
  17722. /* Ignore on unsupported chips */
  17723. err = BCME_OK;
  17724. } else {
  17725. WL_ERR(("wlc_ver query failed. err: %d\n", err));
  17726. return err;
  17727. }
  17728. }
  17729. #ifdef DHD_LOSSLESS_ROAMING
  17730. if (timer_pending(&cfg->roam_timeout)) {
  17731. del_timer_sync(&cfg->roam_timeout);
  17732. }
  17733. #endif /* DHD_LOSSLESS_ROAMING */
  17734. err = dhd_monitor_init(cfg->pub);
  17735. #ifdef WL_HOST_BAND_MGMT
  17736. /* By default the curr_band is initialized to BAND_AUTO */
  17737. if ((ret = wl_cfg80211_set_band(ndev, WLC_BAND_AUTO)) < 0) {
  17738. if (ret == BCME_UNSUPPORTED) {
  17739. /* Don't fail the initialization, lets just
  17740. * fall back to the original method
  17741. */
  17742. WL_ERR(("WL_HOST_BAND_MGMT defined, "
  17743. "but roam_band iovar not supported \n"));
  17744. } else {
  17745. WL_ERR(("roam_band failed. ret=%d", ret));
  17746. err = -1;
  17747. }
  17748. }
  17749. #endif /* WL_HOST_BAND_MGMT */
  17750. #if defined(WES_SUPPORT)
  17751. /* Reset WES mode to 0 */
  17752. wes_mode = 0;
  17753. #endif // endif
  17754. #ifdef WBTEXT
  17755. /* when wifi up, set roam_prof to default value */
  17756. if (dhd->wbtext_support) {
  17757. if (dhd->op_mode & DHD_FLAG_STA_MODE) {
  17758. wl_cfg80211_wbtext_set_default(ndev);
  17759. wl_cfg80211_wbtext_clear_bssid_list(cfg);
  17760. }
  17761. }
  17762. #endif /* WBTEXT */
  17763. #ifdef WLTDLS
  17764. if (wldev_iovar_getint(ndev, "tdls_enable", &tdls) == 0) {
  17765. WL_DBG(("TDLS supported in fw\n"));
  17766. cfg->tdls_supported = true;
  17767. }
  17768. #endif /* WLTDLS */
  17769. #ifdef WL_IFACE_MGMT
  17770. #ifdef CUSTOM_IF_MGMT_POLICY
  17771. cfg->iface_data.policy = CUSTOM_IF_MGMT_POLICY;
  17772. #else
  17773. cfg->iface_data.policy = WL_IF_POLICY_DEFAULT;
  17774. #endif /* CUSTOM_IF_MGMT_POLICY */
  17775. #endif /* WL_IFACE_MGMT */
  17776. #ifdef WL_NAN
  17777. #ifdef WL_NANP2P
  17778. if (FW_SUPPORTED(dhd, nanp2p)) {
  17779. /* Enable NANP2P concurrent support */
  17780. cfg->conc_disc = WL_NANP2P_CONC_SUPPORT;
  17781. WL_INFORM_MEM(("nan + p2p conc discovery is supported\n"));
  17782. cfg->nan_p2p_supported = true;
  17783. }
  17784. #endif /* WL_NANP2P */
  17785. #endif /* WL_NAN */
  17786. INIT_DELAYED_WORK(&cfg->pm_enable_work, wl_cfg80211_work_handler);
  17787. wl_set_drv_status(cfg, READY, ndev);
  17788. return err;
  17789. }
  17790. static s32 __wl_cfg80211_down(struct bcm_cfg80211 *cfg)
  17791. {
  17792. s32 err = 0;
  17793. struct net_info *iter, *next;
  17794. struct net_device *ndev = bcmcfg_to_prmry_ndev(cfg);
  17795. #if defined(WL_CFG80211) && (defined(WL_ENABLE_P2P_IF) || \
  17796. defined(WL_NEWCFG_PRIVCMD_SUPPORT)) && !defined(PLATFORM_SLP)
  17797. struct net_device *p2p_net = cfg->p2p_net;
  17798. #endif /* WL_CFG80211 && (WL_ENABLE_P2P_IF || WL_NEWCFG_PRIVCMD_SUPPORT) && !PLATFORM_SLP */
  17799. dhd_pub_t *dhd = (dhd_pub_t *)(cfg->pub);
  17800. WL_INFORM_MEM(("cfg80211 down\n"));
  17801. /* Check if cfg80211 interface is already down */
  17802. if (!wl_get_drv_status(cfg, READY, ndev)) {
  17803. WL_DBG(("cfg80211 interface is already down\n"));
  17804. return err; /* it is even not ready */
  17805. }
  17806. #ifdef SHOW_LOGTRACE
  17807. /* Stop the event logging */
  17808. wl_add_remove_eventmsg(ndev, WLC_E_TRACE, FALSE);
  17809. #endif /* SHOW_LOGTRACE */
  17810. /* clear vendor OUI list */
  17811. wl_vndr_ies_clear_vendor_oui_list(cfg);
  17812. /* Delete pm_enable_work */
  17813. wl_add_remove_pm_enable_work(cfg, WL_PM_WORKQ_DEL);
  17814. if (cfg->p2p_supported) {
  17815. wl_clr_p2p_status(cfg, GO_NEG_PHASE);
  17816. #ifdef PROP_TXSTATUS_VSDB
  17817. #if defined(BCMSDIO)
  17818. if (wl_cfgp2p_vif_created(cfg)) {
  17819. bool enabled = false;
  17820. dhd_wlfc_get_enable(dhd, &enabled);
  17821. if (enabled && cfg->wlfc_on && dhd->op_mode != DHD_FLAG_HOSTAP_MODE &&
  17822. dhd->op_mode != DHD_FLAG_IBSS_MODE) {
  17823. dhd_wlfc_deinit(dhd);
  17824. cfg->wlfc_on = false;
  17825. }
  17826. }
  17827. #endif /* defined(BCMSDIO) */
  17828. #endif /* PROP_TXSTATUS_VSDB */
  17829. }
  17830. #ifdef WL_NAN
  17831. mutex_lock(&cfg->if_sync);
  17832. wl_cfgnan_disable(cfg, NAN_BUS_IS_DOWN);
  17833. mutex_unlock(&cfg->if_sync);
  17834. #endif /* WL_NAN */
  17835. if (!dhd_download_fw_on_driverload) {
  17836. /* For built-in drivers/other drivers that do reset on
  17837. * "ifconfig <primary_iface> down", cleanup any left
  17838. * over interfaces
  17839. */
  17840. wl_cfg80211_cleanup_virtual_ifaces(cfg, false);
  17841. }
  17842. /* Clear used mac addr mask */
  17843. cfg->vif_macaddr_mask = 0;
  17844. if (dhd->up)
  17845. {
  17846. /* If primary BSS is operational (for e.g SoftAP), bring it down */
  17847. if (wl_cfg80211_bss_isup(ndev, 0)) {
  17848. if (wl_cfg80211_bss_up(cfg, ndev, 0, 0) < 0)
  17849. WL_ERR(("BSS down failed \n"));
  17850. }
  17851. /* clear all the security setting on primary Interface */
  17852. wl_cfg80211_clear_security(cfg);
  17853. }
  17854. GCC_DIAGNOSTIC_PUSH_SUPPRESS_CAST();
  17855. for_each_ndev(cfg, iter, next) {
  17856. GCC_DIAGNOSTIC_POP();
  17857. if (iter->ndev) /* p2p discovery iface is null */
  17858. wl_set_drv_status(cfg, SCAN_ABORTING, iter->ndev);
  17859. }
  17860. #ifdef P2P_LISTEN_OFFLOADING
  17861. wl_cfg80211_p2plo_deinit(cfg);
  17862. #endif /* P2P_LISTEN_OFFLOADING */
  17863. /* cancel and notify scan complete, if scan request is pending */
  17864. wl_cfg80211_cancel_scan(cfg);
  17865. GCC_DIAGNOSTIC_PUSH_SUPPRESS_CAST();
  17866. for_each_ndev(cfg, iter, next) {
  17867. GCC_DIAGNOSTIC_POP();
  17868. /* p2p discovery iface ndev ptr could be null */
  17869. if (iter->ndev == NULL)
  17870. continue;
  17871. #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0))
  17872. WL_INFORM_MEM(("wl_cfg80211_down. connection state bit status: [%u:%u:%u:%u]\n",
  17873. wl_get_drv_status(cfg, CONNECTING, ndev),
  17874. wl_get_drv_status(cfg, CONNECTED, ndev),
  17875. wl_get_drv_status(cfg, DISCONNECTING, ndev),
  17876. wl_get_drv_status(cfg, NESTED_CONNECT, ndev)));
  17877. if (wl_get_drv_status(cfg, CONNECTED, iter->ndev)) {
  17878. CFG80211_DISCONNECTED(iter->ndev, 0, NULL, 0, false, GFP_KERNEL);
  17879. }
  17880. if ((iter->ndev->ieee80211_ptr->iftype == NL80211_IFTYPE_STATION) &&
  17881. wl_get_drv_status(cfg, CONNECTING, iter->ndev)) {
  17882. u8 *latest_bssid = wl_read_prof(cfg, ndev, WL_PROF_LATEST_BSSID);
  17883. struct wiphy *wiphy = bcmcfg_to_wiphy(cfg);
  17884. struct wireless_dev *wdev = ndev->ieee80211_ptr;
  17885. struct cfg80211_bss *bss = CFG80211_GET_BSS(wiphy, NULL, latest_bssid,
  17886. wdev->ssid, wdev->ssid_len);
  17887. BCM_REFERENCE(bss);
  17888. CFG80211_CONNECT_RESULT(ndev,
  17889. latest_bssid, bss, NULL, 0, NULL, 0,
  17890. WLAN_STATUS_UNSPECIFIED_FAILURE,
  17891. GFP_KERNEL);
  17892. }
  17893. #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)) */
  17894. wl_clr_drv_status(cfg, READY, iter->ndev);
  17895. wl_clr_drv_status(cfg, SCANNING, iter->ndev);
  17896. wl_clr_drv_status(cfg, SCAN_ABORTING, iter->ndev);
  17897. wl_clr_drv_status(cfg, CONNECTING, iter->ndev);
  17898. wl_clr_drv_status(cfg, CONNECTED, iter->ndev);
  17899. wl_clr_drv_status(cfg, DISCONNECTING, iter->ndev);
  17900. wl_clr_drv_status(cfg, AP_CREATED, iter->ndev);
  17901. wl_clr_drv_status(cfg, AP_CREATING, iter->ndev);
  17902. wl_clr_drv_status(cfg, NESTED_CONNECT, iter->ndev);
  17903. wl_clr_drv_status(cfg, CFG80211_CONNECT, iter->ndev);
  17904. }
  17905. bcmcfg_to_prmry_ndev(cfg)->ieee80211_ptr->iftype =
  17906. NL80211_IFTYPE_STATION;
  17907. #if defined(WL_CFG80211) && (defined(WL_ENABLE_P2P_IF) || \
  17908. defined(WL_NEWCFG_PRIVCMD_SUPPORT)) && !defined(PLATFORM_SLP)
  17909. #ifdef SUPPORT_DEEP_SLEEP
  17910. if (!trigger_deep_sleep)
  17911. #endif /* SUPPORT_DEEP_SLEEP */
  17912. if (p2p_net)
  17913. dev_close(p2p_net);
  17914. #endif /* WL_CFG80211 && (WL_ENABLE_P2P_IF || WL_NEWCFG_PRIVCMD_SUPPORT)&& !PLATFORM_SLP */
  17915. /* Avoid deadlock from wl_cfg80211_down */
  17916. if (!dhd_download_fw_on_driverload) {
  17917. mutex_unlock(&cfg->usr_sync);
  17918. wl_destroy_event_handler(cfg);
  17919. mutex_lock(&cfg->usr_sync);
  17920. }
  17921. wl_flush_eq(cfg);
  17922. wl_link_down(cfg);
  17923. if (cfg->p2p_supported) {
  17924. if (timer_pending(&cfg->p2p->listen_timer))
  17925. del_timer_sync(&cfg->p2p->listen_timer);
  17926. wl_cfgp2p_down(cfg);
  17927. }
  17928. if (timer_pending(&cfg->scan_timeout)) {
  17929. del_timer_sync(&cfg->scan_timeout);
  17930. }
  17931. wl_cfg80211_clear_mgmt_vndr_ies(cfg);
  17932. #if defined(OEM_ANDROID)
  17933. DHD_OS_SCAN_WAKE_UNLOCK((dhd_pub_t *)(cfg->pub));
  17934. #endif // endif
  17935. dhd_monitor_uninit();
  17936. #ifdef WLAIBSS_MCHAN
  17937. bcm_cfg80211_del_ibss_if(cfg->wdev->wiphy, cfg->ibss_cfgdev);
  17938. #endif /* WLAIBSS_MCHAN */
  17939. #ifdef WL11U
  17940. /* Clear interworking element. */
  17941. if (cfg->wl11u) {
  17942. wl_clear_iwdata(cfg);
  17943. cfg->wl11u = FALSE;
  17944. }
  17945. #endif /* WL11U */
  17946. #ifdef CUSTOMER_HW4_DEBUG
  17947. if (wl_scan_timeout_dbg_enabled) {
  17948. wl_scan_timeout_dbg_clear();
  17949. }
  17950. #endif /* CUSTOMER_HW4_DEBUG */
  17951. cfg->disable_roam_event = false;
  17952. DNGL_FUNC(dhd_cfg80211_down, (cfg));
  17953. #ifdef DHD_IFDEBUG
  17954. /* Printout all netinfo entries */
  17955. wl_probe_wdev_all(cfg);
  17956. #endif /* DHD_IFDEBUG */
  17957. return err;
  17958. }
  17959. s32 wl_cfg80211_up(struct net_device *net)
  17960. {
  17961. struct bcm_cfg80211 *cfg;
  17962. s32 err = 0;
  17963. int val = 1;
  17964. dhd_pub_t *dhd;
  17965. #ifdef DISABLE_PM_BCNRX
  17966. s32 interr = 0;
  17967. uint param = 0;
  17968. s8 iovbuf[WLC_IOCTL_SMLEN];
  17969. #endif /* DISABLE_PM_BCNRX */
  17970. WL_DBG(("In\n"));
  17971. cfg = wl_get_cfg(net);
  17972. if ((err = wldev_ioctl_get(bcmcfg_to_prmry_ndev(cfg), WLC_GET_VERSION, &val,
  17973. sizeof(int)) < 0)) {
  17974. WL_ERR(("WLC_GET_VERSION failed, err=%d\n", err));
  17975. return err;
  17976. }
  17977. val = dtoh32(val);
  17978. if (val != WLC_IOCTL_VERSION && val != 1) {
  17979. WL_ERR(("Version mismatch, please upgrade. Got %d, expected %d or 1\n",
  17980. val, WLC_IOCTL_VERSION));
  17981. return BCME_VERSION;
  17982. }
  17983. ioctl_version = val;
  17984. WL_TRACE(("WLC_GET_VERSION=%d\n", ioctl_version));
  17985. mutex_lock(&cfg->usr_sync);
  17986. dhd = (dhd_pub_t *)(cfg->pub);
  17987. if (!(dhd->op_mode & DHD_FLAG_HOSTAP_MODE)) {
  17988. err = wl_cfg80211_attach_post(bcmcfg_to_prmry_ndev(cfg));
  17989. if (unlikely(err)) {
  17990. mutex_unlock(&cfg->usr_sync);
  17991. return err;
  17992. }
  17993. }
  17994. #if defined(BCMSUP_4WAY_HANDSHAKE)
  17995. if (dhd->fw_4way_handshake) {
  17996. /* This is a hacky method to indicate fw 4WHS support and
  17997. * is used only for kernels (kernels < 3.14). For newer
  17998. * kernels, we would be using vendor extn. path to advertise
  17999. * FW based 4-way handshake feature support.
  18000. */
  18001. cfg->wdev->wiphy->features |= NL80211_FEATURE_FW_4WAY_HANDSHAKE;
  18002. }
  18003. #endif /* BCMSUP_4WAY_HANDSHAKE */
  18004. err = __wl_cfg80211_up(cfg);
  18005. if (unlikely(err))
  18006. WL_ERR(("__wl_cfg80211_up failed\n"));
  18007. #ifdef ROAM_CHANNEL_CACHE
  18008. if (init_roam_cache(cfg, ioctl_version) == 0) {
  18009. /* Enable support for Roam cache */
  18010. cfg->rcc_enabled = true;
  18011. WL_ERR(("Roam channel cache enabled\n"));
  18012. } else {
  18013. WL_ERR(("Failed to enable RCC.\n"));
  18014. }
  18015. #endif /* ROAM_CHANNEL_CACHE */
  18016. /* IOVAR configurations with 'up' condition */
  18017. #ifdef DISABLE_PM_BCNRX
  18018. interr = wldev_iovar_setbuf(net, "pm_bcnrx", (char *)&param, sizeof(param), iovbuf,
  18019. sizeof(iovbuf), &cfg->ioctl_buf_sync);
  18020. if (unlikely(interr)) {
  18021. WL_ERR(("Set pm_bcnrx returned (%d)\n", interr));
  18022. }
  18023. #endif /* DISABLE_PM_BCNRX */
  18024. #ifdef WL_CHAN_UTIL
  18025. interr = wl_cfg80211_start_bssload_report(net);
  18026. if (unlikely(interr)) {
  18027. WL_ERR(("%s: Failed to start bssload_report eventing, err=%d\n",
  18028. __FUNCTION__, interr));
  18029. }
  18030. #endif /* WL_CHAN_UTIL */
  18031. mutex_unlock(&cfg->usr_sync);
  18032. #ifdef WLAIBSS_MCHAN
  18033. bcm_cfg80211_add_ibss_if(cfg->wdev->wiphy, IBSS_IF_NAME);
  18034. #endif /* WLAIBSS_MCHAN */
  18035. return err;
  18036. }
  18037. /* Private Event to Supplicant with indication that chip hangs */
  18038. int wl_cfg80211_hang(struct net_device *dev, u16 reason)
  18039. {
  18040. struct bcm_cfg80211 *cfg = wl_get_cfg(dev);
  18041. dhd_pub_t *dhd;
  18042. #if defined(SOFTAP_SEND_HANGEVT)
  18043. /* specifc mac address used for hang event */
  18044. uint8 hang_mac[ETHER_ADDR_LEN] = {0x11, 0x11, 0x11, 0x11, 0x11, 0x11};
  18045. #endif /* SOFTAP_SEND_HANGEVT */
  18046. if (!cfg) {
  18047. return BCME_ERROR;
  18048. }
  18049. RETURN_EIO_IF_NOT_UP(cfg);
  18050. dhd = (dhd_pub_t *)(cfg->pub);
  18051. #if defined(DHD_HANG_SEND_UP_TEST)
  18052. if (dhd->req_hang_type) {
  18053. WL_ERR(("wl_cfg80211_hang, Clear HANG test request 0x%x\n",
  18054. dhd->req_hang_type));
  18055. dhd->req_hang_type = 0;
  18056. }
  18057. #endif /* DHD_HANG_SEND_UP_TEST */
  18058. if ((dhd->hang_reason <= HANG_REASON_MASK) || (dhd->hang_reason >= HANG_REASON_MAX)) {
  18059. WL_ERR(("wl_cfg80211_hang, Invalid hang reason 0x%x\n",
  18060. dhd->hang_reason));
  18061. dhd->hang_reason = HANG_REASON_UNKNOWN;
  18062. }
  18063. #ifdef DHD_USE_EXTENDED_HANG_REASON
  18064. if (dhd->hang_reason != 0) {
  18065. reason = dhd->hang_reason;
  18066. }
  18067. #endif /* DHD_USE_EXTENDED_HANG_REASON */
  18068. WL_ERR(("In : chip crash eventing, reason=0x%x\n", (uint32)(dhd->hang_reason)));
  18069. wl_add_remove_pm_enable_work(cfg, WL_PM_WORKQ_DEL);
  18070. #ifdef SOFTAP_SEND_HANGEVT
  18071. if (dhd->op_mode & DHD_FLAG_HOSTAP_MODE) {
  18072. cfg80211_del_sta(dev, hang_mac, GFP_ATOMIC);
  18073. } else
  18074. #endif /* SOFTAP_SEND_HANGEVT */
  18075. {
  18076. if (dhd->up == TRUE) {
  18077. #ifdef WL_CFGVENDOR_SEND_HANG_EVENT
  18078. wl_cfgvendor_send_hang_event(dev, reason,
  18079. dhd->hang_info, dhd->hang_info_cnt);
  18080. #else
  18081. CFG80211_DISCONNECTED(dev, reason, NULL, 0, false, GFP_KERNEL);
  18082. #endif /* WL_CFGVENDOR_SEND_HANG_EVENT */
  18083. }
  18084. }
  18085. if (cfg != NULL) {
  18086. wl_link_down(cfg);
  18087. }
  18088. return 0;
  18089. }
  18090. s32 wl_cfg80211_down(struct net_device *dev)
  18091. {
  18092. struct bcm_cfg80211 *cfg = wl_get_cfg(dev);
  18093. s32 err = BCME_ERROR;
  18094. WL_DBG(("In\n"));
  18095. if (cfg) {
  18096. mutex_lock(&cfg->usr_sync);
  18097. err = __wl_cfg80211_down(cfg);
  18098. mutex_unlock(&cfg->usr_sync);
  18099. }
  18100. return err;
  18101. }
  18102. void
  18103. wl_cfg80211_sta_ifdown(struct net_device *dev)
  18104. {
  18105. struct bcm_cfg80211 *cfg = wl_get_cfg(dev);
  18106. WL_DBG(("In\n"));
  18107. if (cfg) {
  18108. /* cancel scan if anything pending */
  18109. wl_cfg80211_cancel_scan(cfg);
  18110. #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0))
  18111. if ((dev->ieee80211_ptr->iftype == NL80211_IFTYPE_STATION) &&
  18112. wl_get_drv_status(cfg, CONNECTED, dev)) {
  18113. CFG80211_DISCONNECTED(dev, 0, NULL, 0, false, GFP_KERNEL);
  18114. }
  18115. #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)) */
  18116. }
  18117. }
  18118. void *wl_read_prof(struct bcm_cfg80211 *cfg, struct net_device *ndev, s32 item)
  18119. {
  18120. unsigned long flags;
  18121. void *rptr = NULL;
  18122. struct wl_profile *profile = wl_get_profile_by_netdev(cfg, ndev);
  18123. if (!profile)
  18124. return NULL;
  18125. WL_CFG_DRV_LOCK(&cfg->cfgdrv_lock, flags);
  18126. switch (item) {
  18127. case WL_PROF_SEC:
  18128. rptr = &profile->sec;
  18129. break;
  18130. case WL_PROF_ACT:
  18131. rptr = &profile->active;
  18132. break;
  18133. case WL_PROF_BSSID:
  18134. rptr = profile->bssid;
  18135. break;
  18136. case WL_PROF_SSID:
  18137. rptr = &profile->ssid;
  18138. break;
  18139. case WL_PROF_CHAN:
  18140. rptr = &profile->channel;
  18141. break;
  18142. case WL_PROF_LATEST_BSSID:
  18143. rptr = profile->latest_bssid;
  18144. break;
  18145. }
  18146. WL_CFG_DRV_UNLOCK(&cfg->cfgdrv_lock, flags);
  18147. if (!rptr)
  18148. WL_ERR(("invalid item (%d)\n", item));
  18149. return rptr;
  18150. }
  18151. static s32
  18152. wl_update_prof(struct bcm_cfg80211 *cfg, struct net_device *ndev,
  18153. const wl_event_msg_t *e, const void *data, s32 item)
  18154. {
  18155. s32 err = 0;
  18156. const struct wlc_ssid *ssid;
  18157. unsigned long flags;
  18158. struct wl_profile *profile = wl_get_profile_by_netdev(cfg, ndev);
  18159. if (!profile)
  18160. return WL_INVALID;
  18161. WL_CFG_DRV_LOCK(&cfg->cfgdrv_lock, flags);
  18162. switch (item) {
  18163. case WL_PROF_SSID:
  18164. ssid = (const wlc_ssid_t *) data;
  18165. bzero(profile->ssid.SSID,
  18166. sizeof(profile->ssid.SSID));
  18167. profile->ssid.SSID_len = MIN(ssid->SSID_len, DOT11_MAX_SSID_LEN);
  18168. memcpy(profile->ssid.SSID, ssid->SSID, profile->ssid.SSID_len);
  18169. break;
  18170. case WL_PROF_BSSID:
  18171. if (data)
  18172. memcpy(profile->bssid, data, ETHER_ADDR_LEN);
  18173. else
  18174. bzero(profile->bssid, ETHER_ADDR_LEN);
  18175. break;
  18176. case WL_PROF_SEC:
  18177. memcpy(&profile->sec, data, sizeof(profile->sec));
  18178. break;
  18179. case WL_PROF_ACT:
  18180. profile->active = *(const bool *)data;
  18181. break;
  18182. case WL_PROF_BEACONINT:
  18183. profile->beacon_interval = *(const u16 *)data;
  18184. break;
  18185. case WL_PROF_DTIMPERIOD:
  18186. profile->dtim_period = *(const u8 *)data;
  18187. break;
  18188. case WL_PROF_CHAN:
  18189. profile->channel = *(const u32*)data;
  18190. break;
  18191. case WL_PROF_LATEST_BSSID:
  18192. if (data) {
  18193. memcpy_s(profile->latest_bssid, sizeof(profile->latest_bssid),
  18194. data, ETHER_ADDR_LEN);
  18195. } else {
  18196. memset_s(profile->latest_bssid, sizeof(profile->latest_bssid),
  18197. 0, ETHER_ADDR_LEN);
  18198. }
  18199. break;
  18200. default:
  18201. err = -EOPNOTSUPP;
  18202. break;
  18203. }
  18204. WL_CFG_DRV_UNLOCK(&cfg->cfgdrv_lock, flags);
  18205. if (err == -EOPNOTSUPP)
  18206. WL_ERR(("unsupported item (%d)\n", item));
  18207. return err;
  18208. }
  18209. void wl_cfg80211_dbg_level(u32 level)
  18210. {
  18211. /*
  18212. * prohibit to change debug level
  18213. * by insmod parameter.
  18214. * eventually debug level will be configured
  18215. * in compile time by using CONFIG_XXX
  18216. */
  18217. /* wl_dbg_level = level; */
  18218. }
  18219. static bool wl_is_ibssmode(struct bcm_cfg80211 *cfg, struct net_device *ndev)
  18220. {
  18221. return wl_get_mode_by_netdev(cfg, ndev) == WL_MODE_IBSS;
  18222. }
  18223. static __used bool wl_is_ibssstarter(struct bcm_cfg80211 *cfg)
  18224. {
  18225. return cfg->ibss_starter;
  18226. }
  18227. static void wl_rst_ie(struct bcm_cfg80211 *cfg)
  18228. {
  18229. struct wl_ie *ie = wl_to_ie(cfg);
  18230. ie->offset = 0;
  18231. bzero(ie->buf, sizeof(ie->buf));
  18232. }
  18233. static __used s32 wl_add_ie(struct bcm_cfg80211 *cfg, u8 t, u8 l, u8 *v)
  18234. {
  18235. struct wl_ie *ie = wl_to_ie(cfg);
  18236. s32 err = 0;
  18237. if (unlikely(ie->offset + l + 2 > WL_TLV_INFO_MAX)) {
  18238. WL_ERR(("ei crosses buffer boundary\n"));
  18239. return -ENOSPC;
  18240. }
  18241. ie->buf[ie->offset] = t;
  18242. ie->buf[ie->offset + 1] = l;
  18243. memcpy(&ie->buf[ie->offset + 2], v, l);
  18244. ie->offset += l + 2;
  18245. return err;
  18246. }
  18247. static void wl_update_hidden_ap_ie(wl_bss_info_t *bi, const u8 *ie_stream, u32 *ie_size,
  18248. bool update_ssid)
  18249. {
  18250. u8 *ssidie;
  18251. int32 ssid_len = MIN(bi->SSID_len, DOT11_MAX_SSID_LEN);
  18252. int32 remaining_ie_buf_len, available_buffer_len, unused_buf_len;
  18253. /* cfg80211_find_ie defined in kernel returning const u8 */
  18254. GCC_DIAGNOSTIC_PUSH_SUPPRESS_CAST();
  18255. ssidie = (u8 *)cfg80211_find_ie(WLAN_EID_SSID, ie_stream, *ie_size);
  18256. GCC_DIAGNOSTIC_POP();
  18257. /* ERROR out if
  18258. * 1. No ssid IE is FOUND or
  18259. * 2. New ssid length is > what was allocated for existing ssid (as
  18260. * we do not want to overwrite the rest of the IEs) or
  18261. * 3. If in case of erroneous buffer input where ssid length doesnt match the space
  18262. * allocated to it.
  18263. */
  18264. if (!ssidie) {
  18265. return;
  18266. }
  18267. available_buffer_len = ((int)(*ie_size)) - (ssidie + 2 - ie_stream);
  18268. remaining_ie_buf_len = available_buffer_len - (int)ssidie[1];
  18269. unused_buf_len = WL_EXTRA_BUF_MAX - (4 + bi->length + *ie_size);
  18270. if (ssidie[1] > available_buffer_len) {
  18271. WL_ERR_MEM(("wl_update_hidden_ap_ie: skip wl_update_hidden_ap_ie : overflow\n"));
  18272. return;
  18273. }
  18274. if (ssidie[1] != ssid_len) {
  18275. if (ssidie[1]) {
  18276. WL_ERR_RLMT(("wl_update_hidden_ap_ie: Wrong SSID len: %d != %d\n",
  18277. ssidie[1], bi->SSID_len));
  18278. }
  18279. /*
  18280. * The bss info in firmware gets updated from beacon and probe resp.
  18281. * In case of hidden network, the bss_info that got updated by beacon,
  18282. * will not carry SSID and this can result in cfg80211_get_bss not finding a match.
  18283. * so include the SSID element.
  18284. */
  18285. if ((update_ssid && (ssid_len > ssidie[1])) && (unused_buf_len > ssid_len)) {
  18286. WL_INFORM_MEM(("Changing the SSID Info.\n"));
  18287. memmove(ssidie + ssid_len + 2,
  18288. (ssidie + 2) + ssidie[1],
  18289. remaining_ie_buf_len);
  18290. memcpy(ssidie + 2, bi->SSID, ssid_len);
  18291. *ie_size = *ie_size + ssid_len - ssidie[1];
  18292. ssidie[1] = ssid_len;
  18293. } else if (ssid_len < ssidie[1]) {
  18294. WL_ERR_MEM(("wl_update_hidden_ap_ie: Invalid SSID len: %d < %d\n",
  18295. bi->SSID_len, ssidie[1]));
  18296. }
  18297. return;
  18298. }
  18299. if (*(ssidie + 2) == '\0')
  18300. memcpy(ssidie + 2, bi->SSID, ssid_len);
  18301. return;
  18302. }
  18303. static s32 wl_mrg_ie(struct bcm_cfg80211 *cfg, u8 *ie_stream, u16 ie_size)
  18304. {
  18305. struct wl_ie *ie = wl_to_ie(cfg);
  18306. s32 err = 0;
  18307. if (unlikely(ie->offset + ie_size > WL_TLV_INFO_MAX)) {
  18308. WL_ERR(("ei_stream crosses buffer boundary\n"));
  18309. return -ENOSPC;
  18310. }
  18311. memcpy(&ie->buf[ie->offset], ie_stream, ie_size);
  18312. ie->offset += ie_size;
  18313. return err;
  18314. }
  18315. static s32 wl_cp_ie(struct bcm_cfg80211 *cfg, u8 *dst, u16 dst_size)
  18316. {
  18317. struct wl_ie *ie = wl_to_ie(cfg);
  18318. s32 err = 0;
  18319. if (unlikely(ie->offset > dst_size)) {
  18320. WL_ERR(("dst_size is not enough\n"));
  18321. return -ENOSPC;
  18322. }
  18323. memcpy(dst, &ie->buf[0], ie->offset);
  18324. return err;
  18325. }
  18326. static u32 wl_get_ielen(struct bcm_cfg80211 *cfg)
  18327. {
  18328. struct wl_ie *ie = wl_to_ie(cfg);
  18329. return ie->offset;
  18330. }
  18331. static void wl_link_up(struct bcm_cfg80211 *cfg)
  18332. {
  18333. cfg->link_up = true;
  18334. }
  18335. static void wl_link_down(struct bcm_cfg80211 *cfg)
  18336. {
  18337. struct wl_connect_info *conn_info = wl_to_conn(cfg);
  18338. WL_DBG(("In\n"));
  18339. cfg->link_up = false;
  18340. conn_info->req_ie_len = 0;
  18341. conn_info->resp_ie_len = 0;
  18342. }
  18343. static unsigned long wl_lock_eq(struct bcm_cfg80211 *cfg)
  18344. {
  18345. unsigned long flags;
  18346. WL_CFG_EQ_LOCK(&cfg->eq_lock, flags);
  18347. return flags;
  18348. }
  18349. static void wl_unlock_eq(struct bcm_cfg80211 *cfg, unsigned long flags)
  18350. {
  18351. WL_CFG_EQ_UNLOCK(&cfg->eq_lock, flags);
  18352. }
  18353. static void wl_init_eq_lock(struct bcm_cfg80211 *cfg)
  18354. {
  18355. spin_lock_init(&cfg->eq_lock);
  18356. }
  18357. static void wl_delay(u32 ms)
  18358. {
  18359. if (in_atomic() || (ms < jiffies_to_msecs(1))) {
  18360. OSL_DELAY(ms*1000);
  18361. } else {
  18362. OSL_SLEEP(ms);
  18363. }
  18364. }
  18365. s32 wl_cfg80211_get_p2p_dev_addr(struct net_device *net, struct ether_addr *p2pdev_addr)
  18366. {
  18367. struct bcm_cfg80211 *cfg = wl_get_cfg(net);
  18368. struct ether_addr primary_mac;
  18369. if (!cfg->p2p)
  18370. return -1;
  18371. if (!p2p_is_on(cfg)) {
  18372. get_primary_mac(cfg, &primary_mac);
  18373. wl_cfgp2p_generate_bss_mac(cfg, &primary_mac);
  18374. memcpy((void *)&p2pdev_addr, (void *)&primary_mac, ETHER_ADDR_LEN);
  18375. } else {
  18376. memcpy(p2pdev_addr->octet, wl_to_p2p_bss_macaddr(cfg, P2PAPI_BSSCFG_DEVICE).octet,
  18377. ETHER_ADDR_LEN);
  18378. }
  18379. return 0;
  18380. }
  18381. s32 wl_cfg80211_set_p2p_noa(struct net_device *net, char* buf, int len)
  18382. {
  18383. struct bcm_cfg80211 *cfg = wl_get_cfg(net);
  18384. return wl_cfgp2p_set_p2p_noa(cfg, net, buf, len);
  18385. }
  18386. s32 wl_cfg80211_get_p2p_noa(struct net_device *net, char* buf, int len)
  18387. {
  18388. struct bcm_cfg80211 *cfg = wl_get_cfg(net);
  18389. return wl_cfgp2p_get_p2p_noa(cfg, net, buf, len);
  18390. }
  18391. s32 wl_cfg80211_set_p2p_ps(struct net_device *net, char* buf, int len)
  18392. {
  18393. struct bcm_cfg80211 *cfg = wl_get_cfg(net);
  18394. return wl_cfgp2p_set_p2p_ps(cfg, net, buf, len);
  18395. }
  18396. s32 wl_cfg80211_set_p2p_ecsa(struct net_device *net, char* buf, int len)
  18397. {
  18398. struct bcm_cfg80211 *cfg = wl_get_cfg(net);
  18399. return wl_cfgp2p_set_p2p_ecsa(cfg, net, buf, len);
  18400. }
  18401. s32 wl_cfg80211_increase_p2p_bw(struct net_device *net, char* buf, int len)
  18402. {
  18403. struct bcm_cfg80211 *cfg = wl_get_cfg(net);
  18404. return wl_cfgp2p_increase_p2p_bw(cfg, net, buf, len);
  18405. }
  18406. #ifdef P2PLISTEN_AP_SAMECHN
  18407. s32 wl_cfg80211_set_p2p_resp_ap_chn(struct net_device *net, s32 enable)
  18408. {
  18409. s32 ret = wldev_iovar_setint(net, "p2p_resp_ap_chn", enable);
  18410. if ((ret == 0) && enable) {
  18411. /* disable PM for p2p responding on infra AP channel */
  18412. s32 pm = PM_OFF;
  18413. ret = wldev_ioctl_set(net, WLC_SET_PM, &pm, sizeof(pm));
  18414. }
  18415. return ret;
  18416. }
  18417. #endif /* P2PLISTEN_AP_SAMECHN */
  18418. s32 wl_cfg80211_channel_to_freq(u32 channel)
  18419. {
  18420. int freq = 0;
  18421. #if LINUX_VERSION_CODE == KERNEL_VERSION(2, 6, 38) && !defined(WL_COMPAT_WIRELESS)
  18422. freq = ieee80211_channel_to_frequency(channel);
  18423. #else
  18424. {
  18425. u16 band = 0;
  18426. if (channel <= CH_MAX_2G_CHANNEL)
  18427. band = IEEE80211_BAND_2GHZ;
  18428. else
  18429. band = IEEE80211_BAND_5GHZ;
  18430. freq = ieee80211_channel_to_frequency(channel, band);
  18431. }
  18432. #endif // endif
  18433. return freq;
  18434. }
  18435. #ifdef WLTDLS
  18436. s32
  18437. wl_tdls_event_handler(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev,
  18438. const wl_event_msg_t *e, void *data) {
  18439. struct net_device *ndev = NULL;
  18440. u32 reason = ntoh32(e->reason);
  18441. s8 *msg = NULL;
  18442. ndev = cfgdev_to_wlc_ndev(cfgdev, cfg);
  18443. switch (reason) {
  18444. case WLC_E_TDLS_PEER_DISCOVERED :
  18445. msg = " TDLS PEER DISCOVERD ";
  18446. break;
  18447. case WLC_E_TDLS_PEER_CONNECTED :
  18448. if (cfg->tdls_mgmt_frame) {
  18449. #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 18, 0))
  18450. cfg80211_rx_mgmt(cfgdev, cfg->tdls_mgmt_freq, 0,
  18451. cfg->tdls_mgmt_frame, cfg->tdls_mgmt_frame_len, 0);
  18452. #elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 12, 0))
  18453. cfg80211_rx_mgmt(cfgdev, cfg->tdls_mgmt_freq, 0,
  18454. cfg->tdls_mgmt_frame, cfg->tdls_mgmt_frame_len, 0,
  18455. GFP_ATOMIC);
  18456. #elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)) || \
  18457. defined(WL_COMPAT_WIRELESS)
  18458. cfg80211_rx_mgmt(cfgdev, cfg->tdls_mgmt_freq, 0,
  18459. cfg->tdls_mgmt_frame, cfg->tdls_mgmt_frame_len,
  18460. GFP_ATOMIC);
  18461. #else
  18462. cfg80211_rx_mgmt(cfgdev, cfg->tdls_mgmt_freq,
  18463. cfg->tdls_mgmt_frame, cfg->tdls_mgmt_frame_len, GFP_ATOMIC);
  18464. #endif /* LINUX_VERSION >= VERSION(3, 18,0) || WL_COMPAT_WIRELESS */
  18465. }
  18466. msg = " TDLS PEER CONNECTED ";
  18467. #ifdef SUPPORT_SET_CAC
  18468. /* TDLS connect reset CAC */
  18469. wl_cfg80211_set_cac(cfg, 0);
  18470. #endif /* SUPPORT_SET_CAC */
  18471. break;
  18472. case WLC_E_TDLS_PEER_DISCONNECTED :
  18473. if (cfg->tdls_mgmt_frame) {
  18474. MFREE(cfg->osh, cfg->tdls_mgmt_frame, cfg->tdls_mgmt_frame_len);
  18475. cfg->tdls_mgmt_frame_len = 0;
  18476. cfg->tdls_mgmt_freq = 0;
  18477. }
  18478. msg = "TDLS PEER DISCONNECTED ";
  18479. #ifdef SUPPORT_SET_CAC
  18480. /* TDLS disconnec, set CAC */
  18481. wl_cfg80211_set_cac(cfg, 1);
  18482. #endif /* SUPPORT_SET_CAC */
  18483. break;
  18484. }
  18485. if (msg) {
  18486. WL_ERR(("%s: " MACDBG " on %s ndev\n", msg, MAC2STRDBG((const u8*)(&e->addr)),
  18487. (bcmcfg_to_prmry_ndev(cfg) == ndev) ? "primary" : "secondary"));
  18488. }
  18489. return 0;
  18490. }
  18491. #endif /* WLTDLS */
  18492. #if (LINUX_VERSION_CODE > KERNEL_VERSION(3, 2, 0)) || defined(WL_COMPAT_WIRELESS)
  18493. #if (defined(CONFIG_ARCH_MSM) && defined(TDLS_MGMT_VERSION2)) || (LINUX_VERSION_CODE < \
  18494. KERNEL_VERSION(3, 16, 0) && LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0))
  18495. static s32
  18496. wl_cfg80211_tdls_mgmt(struct wiphy *wiphy, struct net_device *dev,
  18497. u8 *peer, u8 action_code, u8 dialog_token, u16 status_code,
  18498. u32 peer_capability, const u8 *buf, size_t len)
  18499. #elif ((LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0)) && \
  18500. (LINUX_VERSION_CODE < KERNEL_VERSION(3, 18, 0)))
  18501. static s32 wl_cfg80211_tdls_mgmt(struct wiphy *wiphy, struct net_device *dev,
  18502. const u8 *peer, u8 action_code, u8 dialog_token, u16 status_code,
  18503. u32 peer_capability, const u8 *buf, size_t len)
  18504. #elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 18, 0))
  18505. static s32 wl_cfg80211_tdls_mgmt(struct wiphy *wiphy, struct net_device *dev,
  18506. const u8 *peer, u8 action_code, u8 dialog_token, u16 status_code,
  18507. u32 peer_capability, bool initiator, const u8 *buf, size_t len)
  18508. #else /* CONFIG_ARCH_MSM && TDLS_MGMT_VERSION2 */
  18509. static s32
  18510. wl_cfg80211_tdls_mgmt(struct wiphy *wiphy, struct net_device *dev,
  18511. u8 *peer, u8 action_code, u8 dialog_token, u16 status_code,
  18512. const u8 *buf, size_t len)
  18513. #endif /* CONFIG_ARCH_MSM && TDLS_MGMT_VERSION2 */
  18514. {
  18515. s32 ret = 0;
  18516. #if defined(TDLS_MSG_ONLY_WFD) && defined(WLTDLS)
  18517. struct bcm_cfg80211 *cfg;
  18518. tdls_wfd_ie_iovar_t info;
  18519. bzero(&info, sizeof(info));
  18520. cfg = wl_get_cfg(dev);
  18521. #if defined(CONFIG_ARCH_MSM) && defined(TDLS_MGMT_VERSION2)
  18522. /* Some customer platform back ported this feature from kernel 3.15 to kernel 3.10
  18523. * and that cuases build error
  18524. */
  18525. BCM_REFERENCE(peer_capability);
  18526. #endif /* CONFIG_ARCH_MSM && TDLS_MGMT_VERSION2 */
  18527. switch (action_code) {
  18528. /* We need to set TDLS Wifi Display IE to firmware
  18529. * using tdls_wfd_ie iovar
  18530. */
  18531. case WLAN_TDLS_SET_PROBE_WFD_IE:
  18532. WL_ERR(("wl_cfg80211_tdls_mgmt: WLAN_TDLS_SET_PROBE_WFD_IE\n"));
  18533. info.mode = TDLS_WFD_PROBE_IE_TX;
  18534. if (len > sizeof(info.data)) {
  18535. return -EINVAL;
  18536. }
  18537. memcpy(&info.data, buf, len);
  18538. info.length = len;
  18539. break;
  18540. case WLAN_TDLS_SET_SETUP_WFD_IE:
  18541. WL_ERR(("wl_cfg80211_tdls_mgmt: WLAN_TDLS_SET_SETUP_WFD_IE\n"));
  18542. info.mode = TDLS_WFD_IE_TX;
  18543. if (len > sizeof(info.data)) {
  18544. return -EINVAL;
  18545. }
  18546. memcpy(&info.data, buf, len);
  18547. info.length = len;
  18548. break;
  18549. case WLAN_TDLS_SET_WFD_ENABLED:
  18550. WL_ERR(("wl_cfg80211_tdls_mgmt: WLAN_TDLS_SET_MODE_WFD_ENABLED\n"));
  18551. dhd_tdls_set_mode((dhd_pub_t *)(cfg->pub), true);
  18552. goto out;
  18553. case WLAN_TDLS_SET_WFD_DISABLED:
  18554. WL_ERR(("wl_cfg80211_tdls_mgmt: WLAN_TDLS_SET_MODE_WFD_DISABLED\n"));
  18555. dhd_tdls_set_mode((dhd_pub_t *)(cfg->pub), false);
  18556. goto out;
  18557. default:
  18558. WL_ERR(("Unsupported action code : %d\n", action_code));
  18559. goto out;
  18560. }
  18561. ret = wldev_iovar_setbuf(dev, "tdls_wfd_ie", &info, sizeof(info),
  18562. cfg->ioctl_buf, WLC_IOCTL_MAXLEN, &cfg->ioctl_buf_sync);
  18563. if (ret) {
  18564. WL_ERR(("tdls_wfd_ie error %d\n", ret));
  18565. }
  18566. out:
  18567. #endif /* TDLS_MSG_ONLY_WFD && WLTDLS */
  18568. return ret;
  18569. }
  18570. #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
  18571. static s32
  18572. wl_cfg80211_tdls_oper(struct wiphy *wiphy, struct net_device *dev,
  18573. const u8 *peer, enum nl80211_tdls_operation oper)
  18574. #else
  18575. static s32
  18576. wl_cfg80211_tdls_oper(struct wiphy *wiphy, struct net_device *dev,
  18577. u8 *peer, enum nl80211_tdls_operation oper)
  18578. #endif // endif
  18579. {
  18580. s32 ret = 0;
  18581. #ifdef WLTDLS
  18582. struct bcm_cfg80211 *cfg = wl_get_cfg(dev);
  18583. tdls_iovar_t info;
  18584. dhd_pub_t *dhdp;
  18585. bool tdls_auto_mode = false;
  18586. dhdp = (dhd_pub_t *)(cfg->pub);
  18587. bzero(&info, sizeof(tdls_iovar_t));
  18588. if (peer) {
  18589. memcpy(&info.ea, peer, ETHER_ADDR_LEN);
  18590. } else {
  18591. return -1;
  18592. }
  18593. switch (oper) {
  18594. case NL80211_TDLS_DISCOVERY_REQ:
  18595. /* If the discovery request is broadcast then we need to set
  18596. * info.mode to Tunneled Probe Request
  18597. */
  18598. if (memcmp(peer, (const uint8 *)BSSID_BROADCAST, ETHER_ADDR_LEN) == 0) {
  18599. info.mode = TDLS_MANUAL_EP_WFD_TPQ;
  18600. WL_ERR(("wl_cfg80211_tdls_oper: TDLS TUNNELED PRBOBE REQUEST\n"));
  18601. } else {
  18602. info.mode = TDLS_MANUAL_EP_DISCOVERY;
  18603. }
  18604. break;
  18605. case NL80211_TDLS_SETUP:
  18606. if (dhdp->tdls_mode == true) {
  18607. info.mode = TDLS_MANUAL_EP_CREATE;
  18608. tdls_auto_mode = false;
  18609. /* Do tear down and create a fresh one */
  18610. ret = wl_cfg80211_tdls_config(cfg, TDLS_STATE_TEARDOWN, tdls_auto_mode);
  18611. if (ret < 0) {
  18612. return ret;
  18613. }
  18614. } else {
  18615. tdls_auto_mode = true;
  18616. }
  18617. break;
  18618. case NL80211_TDLS_TEARDOWN:
  18619. info.mode = TDLS_MANUAL_EP_DELETE;
  18620. break;
  18621. default:
  18622. WL_ERR(("Unsupported operation : %d\n", oper));
  18623. goto out;
  18624. }
  18625. /* turn on TDLS */
  18626. ret = wl_cfg80211_tdls_config(cfg, TDLS_STATE_SETUP, tdls_auto_mode);
  18627. if (ret < 0) {
  18628. return ret;
  18629. }
  18630. if (info.mode) {
  18631. ret = wldev_iovar_setbuf(dev, "tdls_endpoint", &info, sizeof(info),
  18632. cfg->ioctl_buf, WLC_IOCTL_MAXLEN, &cfg->ioctl_buf_sync);
  18633. if (ret) {
  18634. WL_ERR(("tdls_endpoint error %d\n", ret));
  18635. }
  18636. }
  18637. out:
  18638. if (ret) {
  18639. wl_flush_fw_log_buffer(dev, FW_LOGSET_MASK_ALL);
  18640. return -ENOTSUPP;
  18641. }
  18642. #endif /* WLTDLS */
  18643. return ret;
  18644. }
  18645. #endif /* LINUX_VERSION > VERSION(3,2,0) || WL_COMPAT_WIRELESS */
  18646. s32 wl_cfg80211_set_wps_p2p_ie(struct net_device *ndev, char *buf, int len,
  18647. enum wl_management_type type)
  18648. {
  18649. struct bcm_cfg80211 *cfg;
  18650. s32 ret = 0;
  18651. struct ether_addr primary_mac;
  18652. s32 bssidx = 0;
  18653. s32 pktflag = 0;
  18654. cfg = wl_get_cfg(ndev);
  18655. if (wl_get_drv_status(cfg, AP_CREATING, ndev)) {
  18656. /* Vendor IEs should be set to FW
  18657. * after SoftAP interface is brought up
  18658. */
  18659. WL_DBG(("Skipping set IE since AP is not up \n"));
  18660. goto exit;
  18661. } else if (ndev == bcmcfg_to_prmry_ndev(cfg)) {
  18662. /* Either stand alone AP case or P2P discovery */
  18663. if (wl_get_drv_status(cfg, AP_CREATED, ndev)) {
  18664. /* Stand alone AP case on primary interface */
  18665. WL_DBG(("Apply IEs for Primary AP Interface \n"));
  18666. bssidx = 0;
  18667. } else {
  18668. if (!cfg->p2p) {
  18669. /* If p2p not initialized, return failure */
  18670. WL_ERR(("P2P not initialized \n"));
  18671. goto exit;
  18672. }
  18673. /* P2P Discovery case (p2p listen) */
  18674. if (!cfg->p2p->on) {
  18675. /* Turn on Discovery interface */
  18676. get_primary_mac(cfg, &primary_mac);
  18677. wl_cfgp2p_generate_bss_mac(cfg, &primary_mac);
  18678. p2p_on(cfg) = true;
  18679. ret = wl_cfgp2p_enable_discovery(cfg, ndev, NULL, 0);
  18680. if (unlikely(ret)) {
  18681. WL_ERR(("Enable discovery failed \n"));
  18682. goto exit;
  18683. }
  18684. }
  18685. WL_DBG(("Apply IEs for P2P Discovery Iface \n"));
  18686. ndev = wl_to_p2p_bss_ndev(cfg, P2PAPI_BSSCFG_PRIMARY);
  18687. bssidx = wl_to_p2p_bss_bssidx(cfg, P2PAPI_BSSCFG_DEVICE);
  18688. }
  18689. } else {
  18690. /* Virtual AP/ P2P Group Interface */
  18691. WL_DBG(("Apply IEs for iface:%s\n", ndev->name));
  18692. bssidx = wl_get_bssidx_by_wdev(cfg, ndev->ieee80211_ptr);
  18693. }
  18694. if (ndev != NULL) {
  18695. switch (type) {
  18696. case WL_BEACON:
  18697. pktflag = VNDR_IE_BEACON_FLAG;
  18698. break;
  18699. case WL_PROBE_RESP:
  18700. pktflag = VNDR_IE_PRBRSP_FLAG;
  18701. break;
  18702. case WL_ASSOC_RESP:
  18703. pktflag = VNDR_IE_ASSOCRSP_FLAG;
  18704. break;
  18705. }
  18706. if (pktflag) {
  18707. ret = wl_cfg80211_set_mgmt_vndr_ies(cfg,
  18708. ndev_to_cfgdev(ndev), bssidx, pktflag, buf, len);
  18709. }
  18710. }
  18711. exit:
  18712. return ret;
  18713. }
  18714. #ifdef WL_SUPPORT_AUTO_CHANNEL
  18715. static s32
  18716. wl_cfg80211_set_auto_channel_scan_state(struct net_device *ndev)
  18717. {
  18718. u32 val = 0;
  18719. s32 ret = BCME_ERROR;
  18720. struct bcm_cfg80211 *cfg = wl_get_cfg(ndev);
  18721. /* Set interface up, explicitly. */
  18722. val = 1;
  18723. ret = wldev_ioctl_set(ndev, WLC_UP, (void *)&val, sizeof(val));
  18724. if (ret < 0) {
  18725. WL_ERR(("set interface up failed, error = %d\n", ret));
  18726. goto done;
  18727. }
  18728. /* Stop all scan explicitly, till auto channel selection complete. */
  18729. wl_set_drv_status(cfg, SCANNING, ndev);
  18730. if (cfg->escan_info.ndev == NULL) {
  18731. ret = BCME_OK;
  18732. goto done;
  18733. }
  18734. wl_cfg80211_cancel_scan(cfg);
  18735. done:
  18736. return ret;
  18737. }
  18738. static bool
  18739. wl_cfg80211_valid_chanspec_p2p(chanspec_t chanspec)
  18740. {
  18741. bool valid = false;
  18742. char chanbuf[CHANSPEC_STR_LEN];
  18743. /* channel 1 to 14 */
  18744. if ((chanspec >= 0x2b01) && (chanspec <= 0x2b0e)) {
  18745. valid = true;
  18746. }
  18747. #ifdef IGUANA_LEGACY_CHIPS
  18748. /* channel 36 to 48 */
  18749. else if ((chanspec >= 0xd024) && (chanspec <= 0xd030)) {
  18750. valid = true;
  18751. }
  18752. /* channel 149 to 161 */
  18753. else if ((chanspec >= 0xd095) && (chanspec <= 0xd0a5)) {
  18754. valid = true;
  18755. }
  18756. #else
  18757. /* channel 36 to 48 */
  18758. else if ((chanspec >= 0x1b24) && (chanspec <= 0x1b30)) {
  18759. valid = true;
  18760. }
  18761. /* channel 149 to 161 */
  18762. else if ((chanspec >= 0x1b95) && (chanspec <= 0x1ba1)) {
  18763. valid = true;
  18764. }
  18765. #endif /* IGUANA_LEGACY_CHIPS */
  18766. else {
  18767. valid = false;
  18768. WL_INFORM_MEM(("invalid P2P chanspec, chanspec = %s\n",
  18769. wf_chspec_ntoa_ex(chanspec, chanbuf)));
  18770. }
  18771. return valid;
  18772. }
  18773. s32
  18774. wl_cfg80211_get_chanspecs_2g(struct net_device *ndev, void *buf, s32 buflen)
  18775. {
  18776. s32 ret = BCME_ERROR;
  18777. struct bcm_cfg80211 *cfg = NULL;
  18778. chanspec_t chanspec = 0;
  18779. cfg = wl_get_cfg(ndev);
  18780. /* Restrict channels to 2.4GHz, 20MHz BW, no SB. */
  18781. chanspec |= (WL_CHANSPEC_BAND_2G | WL_CHANSPEC_BW_20 |
  18782. WL_CHANSPEC_CTL_SB_NONE);
  18783. chanspec = wl_chspec_host_to_driver(chanspec);
  18784. ret = wldev_iovar_getbuf_bsscfg(ndev, "chanspecs", (void *)&chanspec,
  18785. sizeof(chanspec), buf, buflen, 0, &cfg->ioctl_buf_sync);
  18786. if (ret < 0) {
  18787. WL_ERR(("get 'chanspecs' failed, error = %d\n", ret));
  18788. }
  18789. return ret;
  18790. }
  18791. s32
  18792. wl_cfg80211_get_chanspecs_5g(struct net_device *ndev, void *buf, s32 buflen)
  18793. {
  18794. u32 channel = 0;
  18795. s32 ret = BCME_ERROR;
  18796. s32 i = 0;
  18797. s32 j = 0;
  18798. struct bcm_cfg80211 *cfg = wl_get_cfg(ndev);
  18799. wl_uint32_list_t *list = NULL;
  18800. chanspec_t chanspec = 0;
  18801. /* Restrict channels to 5GHz, 20MHz BW, no SB. */
  18802. chanspec |= (WL_CHANSPEC_BAND_5G | WL_CHANSPEC_BW_20 |
  18803. WL_CHANSPEC_CTL_SB_NONE);
  18804. chanspec = wl_chspec_host_to_driver(chanspec);
  18805. ret = wldev_iovar_getbuf_bsscfg(ndev, "chanspecs", (void *)&chanspec,
  18806. sizeof(chanspec), buf, buflen, 0, &cfg->ioctl_buf_sync);
  18807. if (ret < 0) {
  18808. WL_ERR(("get 'chanspecs' failed, error = %d\n", ret));
  18809. goto done;
  18810. }
  18811. list = (wl_uint32_list_t *)buf;
  18812. /* Skip DFS and inavlid P2P channel. */
  18813. for (i = 0, j = 0; i < dtoh32(list->count); i++) {
  18814. chanspec = (chanspec_t) dtoh32(list->element[i]);
  18815. channel = CHSPEC_CHANNEL(chanspec);
  18816. ret = wldev_iovar_getint(ndev, "per_chan_info", &channel);
  18817. if (ret < 0) {
  18818. WL_ERR(("get 'per_chan_info' failed, error = %d\n", ret));
  18819. goto done;
  18820. }
  18821. if (CHANNEL_IS_RADAR(channel) ||
  18822. !(wl_cfg80211_valid_chanspec_p2p(chanspec))) {
  18823. continue;
  18824. } else {
  18825. list->element[j] = list->element[i];
  18826. }
  18827. j++;
  18828. }
  18829. list->count = j;
  18830. done:
  18831. return ret;
  18832. }
  18833. static s32
  18834. wl_cfg80211_get_best_channel(struct net_device *ndev, void *buf, int buflen,
  18835. int *channel)
  18836. {
  18837. s32 ret = BCME_ERROR;
  18838. int chosen = 0;
  18839. int retry = 0;
  18840. /* Start auto channel selection scan. */
  18841. ret = wldev_ioctl_set(ndev, WLC_START_CHANNEL_SEL, NULL, 0);
  18842. if (ret < 0) {
  18843. WL_ERR(("can't start auto channel scan, error = %d\n", ret));
  18844. *channel = 0;
  18845. goto done;
  18846. }
  18847. /* Wait for auto channel selection, worst case possible delay is 5250ms. */
  18848. retry = CHAN_SEL_RETRY_COUNT;
  18849. while (retry--) {
  18850. OSL_SLEEP(CHAN_SEL_IOCTL_DELAY);
  18851. chosen = 0;
  18852. ret = wldev_ioctl_get(ndev, WLC_GET_CHANNEL_SEL, &chosen, sizeof(chosen));
  18853. if ((ret == 0) && (dtoh32(chosen) != 0)) {
  18854. *channel = (u16)(chosen & 0x00FF);
  18855. WL_INFORM_MEM(("selected channel = %d\n", *channel));
  18856. break;
  18857. }
  18858. WL_DBG(("attempt = %d, ret = %d, chosen = %d\n",
  18859. (CHAN_SEL_RETRY_COUNT - retry), ret, dtoh32(chosen)));
  18860. }
  18861. if (retry <= 0) {
  18862. WL_ERR(("failure, auto channel selection timed out\n"));
  18863. *channel = 0;
  18864. ret = BCME_ERROR;
  18865. }
  18866. done:
  18867. return ret;
  18868. }
  18869. static s32
  18870. wl_cfg80211_restore_auto_channel_scan_state(struct net_device *ndev)
  18871. {
  18872. struct bcm_cfg80211 *cfg = wl_get_cfg(ndev);
  18873. /* Clear scan stop driver status. */
  18874. wl_clr_drv_status(cfg, SCANNING, ndev);
  18875. return BCME_OK;
  18876. }
  18877. s32
  18878. wl_cfg80211_get_best_channels(struct net_device *dev, char* cmd, int total_len)
  18879. {
  18880. int channel = 0;
  18881. s32 ret = BCME_ERROR;
  18882. u8 *buf = NULL;
  18883. char *pos = cmd;
  18884. struct bcm_cfg80211 *cfg = NULL;
  18885. struct net_device *ndev = NULL;
  18886. bzero(cmd, total_len);
  18887. cfg = wl_get_cfg(dev);
  18888. buf = (u8 *)MALLOC(cfg->osh, CHANSPEC_BUF_SIZE);
  18889. if (buf == NULL) {
  18890. WL_ERR(("failed to allocate chanspec buffer\n"));
  18891. return -ENOMEM;
  18892. }
  18893. /*
  18894. * Always use primary interface, irrespective of interface on which
  18895. * command came.
  18896. */
  18897. ndev = bcmcfg_to_prmry_ndev(cfg);
  18898. /*
  18899. * Make sure that FW and driver are in right state to do auto channel
  18900. * selection scan.
  18901. */
  18902. ret = wl_cfg80211_set_auto_channel_scan_state(ndev);
  18903. if (ret < 0) {
  18904. WL_ERR(("can't set auto channel scan state, error = %d\n", ret));
  18905. goto done;
  18906. }
  18907. /* Best channel selection in 2.4GHz band. */
  18908. ret = wl_cfg80211_get_chanspecs_2g(ndev, (void *)buf, CHANSPEC_BUF_SIZE);
  18909. if (ret < 0) {
  18910. WL_ERR(("can't get chanspecs in 2.4GHz, error = %d\n", ret));
  18911. goto done;
  18912. }
  18913. ret = wl_cfg80211_get_best_channel(ndev, (void *)buf, CHANSPEC_BUF_SIZE,
  18914. &channel);
  18915. if (ret < 0) {
  18916. WL_ERR(("can't select best channel scan in 2.4GHz, error = %d\n", ret));
  18917. goto done;
  18918. }
  18919. if (CHANNEL_IS_2G(channel)) {
  18920. channel = ieee80211_channel_to_frequency(channel, IEEE80211_BAND_2GHZ);
  18921. } else {
  18922. WL_ERR(("invalid 2.4GHz channel, channel = %d\n", channel));
  18923. channel = 0;
  18924. }
  18925. pos += snprintf(pos, total_len, "%04d ", channel);
  18926. /* Best channel selection in 5GHz band. */
  18927. ret = wl_cfg80211_get_chanspecs_5g(ndev, (void *)buf, CHANSPEC_BUF_SIZE);
  18928. if (ret < 0) {
  18929. WL_ERR(("can't get chanspecs in 5GHz, error = %d\n", ret));
  18930. goto done;
  18931. }
  18932. ret = wl_cfg80211_get_best_channel(ndev, (void *)buf, CHANSPEC_BUF_SIZE,
  18933. &channel);
  18934. if (ret < 0) {
  18935. WL_ERR(("can't select best channel scan in 5GHz, error = %d\n", ret));
  18936. goto done;
  18937. }
  18938. if (CHANNEL_IS_5G(channel)) {
  18939. channel = ieee80211_channel_to_frequency(channel, IEEE80211_BAND_5GHZ);
  18940. } else {
  18941. WL_ERR(("invalid 5GHz channel, channel = %d\n", channel));
  18942. channel = 0;
  18943. }
  18944. pos += snprintf(pos, total_len - (pos - cmd), "%04d ", channel);
  18945. /* Set overall best channel same as 5GHz best channel. */
  18946. pos += snprintf(pos, total_len - (pos - cmd), "%04d ", channel);
  18947. done:
  18948. if (NULL != buf) {
  18949. MFREE(cfg->osh, buf, CHANSPEC_BUF_SIZE);
  18950. }
  18951. /* Restore FW and driver back to normal state. */
  18952. ret = wl_cfg80211_restore_auto_channel_scan_state(ndev);
  18953. if (ret < 0) {
  18954. WL_ERR(("can't restore auto channel scan state, error = %d\n", ret));
  18955. }
  18956. return (pos - cmd);
  18957. }
  18958. #endif /* WL_SUPPORT_AUTO_CHANNEL */
  18959. static const struct rfkill_ops wl_rfkill_ops = {
  18960. .set_block = wl_rfkill_set
  18961. };
  18962. static int wl_rfkill_set(void *data, bool blocked)
  18963. {
  18964. struct bcm_cfg80211 *cfg = (struct bcm_cfg80211 *)data;
  18965. WL_DBG(("Enter \n"));
  18966. WL_DBG(("RF %s\n", blocked ? "blocked" : "unblocked"));
  18967. if (!cfg)
  18968. return -EINVAL;
  18969. cfg->rf_blocked = blocked;
  18970. return 0;
  18971. }
  18972. static int wl_setup_rfkill(struct bcm_cfg80211 *cfg, bool setup)
  18973. {
  18974. s32 err = 0;
  18975. WL_DBG(("Enter \n"));
  18976. if (!cfg)
  18977. return -EINVAL;
  18978. if (setup) {
  18979. cfg->rfkill = rfkill_alloc("brcmfmac-wifi",
  18980. wl_cfg80211_get_parent_dev(),
  18981. RFKILL_TYPE_WLAN, &wl_rfkill_ops, (void *)cfg);
  18982. if (!cfg->rfkill) {
  18983. err = -ENOMEM;
  18984. goto err_out;
  18985. }
  18986. err = rfkill_register(cfg->rfkill);
  18987. if (err)
  18988. rfkill_destroy(cfg->rfkill);
  18989. } else {
  18990. if (!cfg->rfkill) {
  18991. err = -ENOMEM;
  18992. goto err_out;
  18993. }
  18994. rfkill_unregister(cfg->rfkill);
  18995. rfkill_destroy(cfg->rfkill);
  18996. }
  18997. err_out:
  18998. return err;
  18999. }
  19000. #ifdef DEBUGFS_CFG80211
  19001. /**
  19002. * Format : echo "SCAN:1 DBG:1" > /sys/kernel/debug/dhd/debug_level
  19003. * to turn on SCAN and DBG log.
  19004. * To turn off SCAN partially, echo "SCAN:0" > /sys/kernel/debug/dhd/debug_level
  19005. * To see current setting of debug level,
  19006. * cat /sys/kernel/debug/dhd/debug_level
  19007. */
  19008. static ssize_t
  19009. wl_debuglevel_write(struct file *file, const char __user *userbuf,
  19010. size_t count, loff_t *ppos)
  19011. {
  19012. char tbuf[SUBLOGLEVELZ * ARRAYSIZE(sublogname_map)], sublog[SUBLOGLEVELZ];
  19013. char *params, *token, *colon;
  19014. uint i, tokens, log_on = 0;
  19015. size_t minsize = min_t(size_t, (sizeof(tbuf) - 1), count);
  19016. bzero(tbuf, sizeof(tbuf));
  19017. bzero(sublog, sizeof(sublog));
  19018. if (copy_from_user(&tbuf, userbuf, minsize)) {
  19019. return -EFAULT;
  19020. }
  19021. tbuf[minsize] = '\0';
  19022. params = &tbuf[0];
  19023. colon = strchr(params, '\n');
  19024. if (colon != NULL)
  19025. *colon = '\0';
  19026. while ((token = strsep(&params, " ")) != NULL) {
  19027. bzero(sublog, sizeof(sublog));
  19028. if (token == NULL || !*token)
  19029. break;
  19030. if (*token == '\0')
  19031. continue;
  19032. colon = strchr(token, ':');
  19033. if (colon != NULL) {
  19034. *colon = ' ';
  19035. }
  19036. tokens = sscanf(token, "%"S(SUBLOGLEVEL)"s %u", sublog, &log_on);
  19037. if (colon != NULL)
  19038. *colon = ':';
  19039. if (tokens == 2) {
  19040. for (i = 0; i < ARRAYSIZE(sublogname_map); i++) {
  19041. if (!strncmp(sublog, sublogname_map[i].sublogname,
  19042. strlen(sublogname_map[i].sublogname))) {
  19043. if (log_on)
  19044. wl_dbg_level |=
  19045. (sublogname_map[i].log_level);
  19046. else
  19047. wl_dbg_level &=
  19048. ~(sublogname_map[i].log_level);
  19049. }
  19050. }
  19051. } else
  19052. WL_ERR(("%s: can't parse '%s' as a "
  19053. "SUBMODULE:LEVEL (%d tokens)\n",
  19054. tbuf, token, tokens));
  19055. }
  19056. return count;
  19057. }
  19058. static ssize_t
  19059. wl_debuglevel_read(struct file *file, char __user *user_buf,
  19060. size_t count, loff_t *ppos)
  19061. {
  19062. char *param;
  19063. char tbuf[SUBLOGLEVELZ * ARRAYSIZE(sublogname_map)];
  19064. uint i;
  19065. bzero(tbuf, sizeof(tbuf));
  19066. param = &tbuf[0];
  19067. for (i = 0; i < ARRAYSIZE(sublogname_map); i++) {
  19068. param += snprintf(param, sizeof(tbuf) - 1, "%s:%d ",
  19069. sublogname_map[i].sublogname,
  19070. (wl_dbg_level & sublogname_map[i].log_level) ? 1 : 0);
  19071. }
  19072. *param = '\n';
  19073. return simple_read_from_buffer(user_buf, count, ppos, tbuf, strlen(&tbuf[0]));
  19074. }
  19075. static const struct file_operations fops_debuglevel = {
  19076. .open = NULL,
  19077. .write = wl_debuglevel_write,
  19078. .read = wl_debuglevel_read,
  19079. .owner = THIS_MODULE,
  19080. .llseek = NULL,
  19081. };
  19082. static s32 wl_setup_debugfs(struct bcm_cfg80211 *cfg)
  19083. {
  19084. s32 err = 0;
  19085. struct dentry *_dentry;
  19086. if (!cfg)
  19087. return -EINVAL;
  19088. cfg->debugfs = debugfs_create_dir(KBUILD_MODNAME, NULL);
  19089. if (!cfg->debugfs || IS_ERR(cfg->debugfs)) {
  19090. if (cfg->debugfs == ERR_PTR(-ENODEV))
  19091. WL_ERR(("Debugfs is not enabled on this kernel\n"));
  19092. else
  19093. WL_ERR(("Can not create debugfs directory\n"));
  19094. cfg->debugfs = NULL;
  19095. goto exit;
  19096. }
  19097. _dentry = debugfs_create_file("debug_level", S_IRUSR | S_IWUSR,
  19098. cfg->debugfs, cfg, &fops_debuglevel);
  19099. if (!_dentry || IS_ERR(_dentry)) {
  19100. WL_ERR(("failed to create debug_level debug file\n"));
  19101. wl_free_debugfs(cfg);
  19102. }
  19103. exit:
  19104. return err;
  19105. }
  19106. static s32 wl_free_debugfs(struct bcm_cfg80211 *cfg)
  19107. {
  19108. if (!cfg)
  19109. return -EINVAL;
  19110. if (cfg->debugfs)
  19111. debugfs_remove_recursive(cfg->debugfs);
  19112. cfg->debugfs = NULL;
  19113. return 0;
  19114. }
  19115. #endif /* DEBUGFS_CFG80211 */
  19116. struct bcm_cfg80211 *wl_cfg80211_get_bcmcfg(void)
  19117. {
  19118. return g_bcmcfg;
  19119. }
  19120. void wl_cfg80211_set_bcmcfg(struct bcm_cfg80211 *cfg)
  19121. {
  19122. g_bcmcfg = cfg;
  19123. }
  19124. struct device *wl_cfg80211_get_parent_dev(void)
  19125. {
  19126. return cfg80211_parent_dev;
  19127. }
  19128. void wl_cfg80211_set_parent_dev(void *dev)
  19129. {
  19130. cfg80211_parent_dev = dev;
  19131. }
  19132. static void wl_cfg80211_clear_parent_dev(void)
  19133. {
  19134. cfg80211_parent_dev = NULL;
  19135. }
  19136. void get_primary_mac(struct bcm_cfg80211 *cfg, struct ether_addr *mac)
  19137. {
  19138. u8 ioctl_buf[WLC_IOCTL_SMLEN];
  19139. if (wldev_iovar_getbuf_bsscfg(bcmcfg_to_prmry_ndev(cfg),
  19140. "cur_etheraddr", NULL, 0, ioctl_buf, sizeof(ioctl_buf),
  19141. 0, NULL) == BCME_OK) {
  19142. memcpy(mac->octet, ioctl_buf, ETHER_ADDR_LEN);
  19143. } else {
  19144. bzero(mac->octet, ETHER_ADDR_LEN);
  19145. }
  19146. }
  19147. static bool check_dev_role_integrity(struct bcm_cfg80211 *cfg, s32 mode, u32 dev_role)
  19148. {
  19149. dhd_pub_t *dhd = (dhd_pub_t *)(cfg->pub);
  19150. if (((dev_role == NL80211_IFTYPE_AP) || (dev_role == NL80211_IFTYPE_P2P_GO)) &&
  19151. (mode != WL_MODE_AP))
  19152. {
  19153. WL_ERR(("device role select failed role:%d op_mode:%d \n", dev_role, dhd->op_mode));
  19154. return false;
  19155. }
  19156. return true;
  19157. }
  19158. int wl_cfg80211_do_driver_init(struct net_device *net)
  19159. {
  19160. struct bcm_cfg80211 *cfg = *(struct bcm_cfg80211 **)netdev_priv(net);
  19161. if (!cfg || !cfg->wdev)
  19162. return -EINVAL;
  19163. if (dhd_do_driver_init(cfg->wdev->netdev) < 0)
  19164. return -1;
  19165. return 0;
  19166. }
  19167. void wl_cfg80211_enable_trace(bool set, u32 level)
  19168. {
  19169. if (set)
  19170. wl_dbg_level = level & WL_DBG_LEVEL;
  19171. else
  19172. wl_dbg_level |= (WL_DBG_LEVEL & level);
  19173. }
  19174. #if defined(WL_SUPPORT_BACKPORTED_KPATCHES) || (LINUX_VERSION_CODE >= KERNEL_VERSION(3, \
  19175. 2, 0))
  19176. static s32
  19177. wl_cfg80211_mgmt_tx_cancel_wait(struct wiphy *wiphy,
  19178. bcm_struct_cfgdev *cfgdev, u64 cookie)
  19179. {
  19180. /* CFG80211 checks for tx_cancel_wait callback when ATTR_DURATION
  19181. * is passed with CMD_FRAME. This callback is supposed to cancel
  19182. * the OFFCHANNEL Wait. Since we are already taking care of that
  19183. * with the tx_mgmt logic, do nothing here.
  19184. */
  19185. return 0;
  19186. }
  19187. #endif /* WL_SUPPORT_BACKPORTED_PATCHES || KERNEL >= 3.2.0 */
  19188. #ifdef WL_HOST_BAND_MGMT
  19189. s32
  19190. wl_cfg80211_set_band(struct net_device *ndev, int band)
  19191. {
  19192. struct bcm_cfg80211 *cfg = wl_get_cfg(ndev);
  19193. int ret = 0;
  19194. char ioctl_buf[50];
  19195. if ((band < WLC_BAND_AUTO) || (band > WLC_BAND_2G)) {
  19196. WL_ERR(("Invalid band\n"));
  19197. return -EINVAL;
  19198. }
  19199. if ((ret = wldev_iovar_setbuf(ndev, "roam_band", &band,
  19200. sizeof(int), ioctl_buf, sizeof(ioctl_buf), NULL)) < 0) {
  19201. WL_ERR(("seting roam_band failed code=%d\n", ret));
  19202. return ret;
  19203. }
  19204. WL_DBG(("Setting band to %d\n", band));
  19205. cfg->curr_band = band;
  19206. return 0;
  19207. }
  19208. #endif /* WL_HOST_BAND_MGMT */
  19209. s32
  19210. wl_cfg80211_set_if_band(struct net_device *ndev, int band)
  19211. {
  19212. struct bcm_cfg80211 *cfg = wl_get_cfg(ndev);
  19213. int ret = 0, wait_cnt;
  19214. char ioctl_buf[32];
  19215. if ((band < WLC_BAND_AUTO) || (band > WLC_BAND_2G)) {
  19216. WL_ERR(("Invalid band\n"));
  19217. return -EINVAL;
  19218. }
  19219. if (wl_get_drv_status(cfg, CONNECTED, ndev)) {
  19220. dhd_pub_t *dhdp = (dhd_pub_t *)(cfg->pub);
  19221. BCM_REFERENCE(dhdp);
  19222. DHD_STATLOG_CTRL(dhdp, ST(DISASSOC_INT_START),
  19223. dhd_net2idx(dhdp->info, ndev), 0);
  19224. ret = wldev_ioctl_set(ndev, WLC_DISASSOC, NULL, 0);
  19225. if (ret < 0) {
  19226. WL_ERR(("WLC_DISASSOC error %d\n", ret));
  19227. /* continue to set 'if_band' */
  19228. }
  19229. else {
  19230. /* This is to ensure that 'if_band' iovar is issued only after
  19231. * disconnection is completed
  19232. */
  19233. wait_cnt = WAIT_FOR_DISCONNECT_MAX;
  19234. while (wl_get_drv_status(cfg, CONNECTED, ndev) && wait_cnt) {
  19235. WL_DBG(("Wait until disconnected. wait_cnt: %d\n", wait_cnt));
  19236. wait_cnt--;
  19237. OSL_SLEEP(50);
  19238. }
  19239. }
  19240. }
  19241. if ((ret = wldev_iovar_setbuf(ndev, "if_band", &band,
  19242. sizeof(int), ioctl_buf, sizeof(ioctl_buf), NULL)) < 0) {
  19243. WL_ERR(("seting if_band failed ret=%d\n", ret));
  19244. /* issue 'WLC_SET_BAND' if if_band is not supported */
  19245. if (ret == BCME_UNSUPPORTED) {
  19246. ret = wldev_set_band(ndev, band);
  19247. if (ret < 0) {
  19248. WL_ERR(("seting band failed ret=%d\n", ret));
  19249. }
  19250. }
  19251. }
  19252. return ret;
  19253. }
  19254. s32
  19255. wl_cfg80211_dfs_ap_move(struct net_device *ndev, char *data, char *command, int total_len)
  19256. {
  19257. char ioctl_buf[WLC_IOCTL_SMLEN];
  19258. int err = 0;
  19259. uint32 val = 0;
  19260. chanspec_t chanspec = 0;
  19261. int abort;
  19262. int bytes_written = 0;
  19263. struct wl_dfs_ap_move_status_v2 *status;
  19264. char chanbuf[CHANSPEC_STR_LEN];
  19265. const char *dfs_state_str[DFS_SCAN_S_MAX] = {
  19266. "Radar Free On Channel",
  19267. "Radar Found On Channel",
  19268. "Radar Scan In Progress",
  19269. "Radar Scan Aborted",
  19270. "RSDB Mode switch in Progress For Scan"
  19271. };
  19272. if (ndev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP) {
  19273. bytes_written = snprintf(command, total_len, "AP is not up\n");
  19274. return bytes_written;
  19275. }
  19276. if (!*data) {
  19277. if ((err = wldev_iovar_getbuf(ndev, "dfs_ap_move", NULL, 0,
  19278. ioctl_buf, sizeof(ioctl_buf), NULL))) {
  19279. WL_ERR(("setting dfs_ap_move failed with err=%d \n", err));
  19280. return err;
  19281. }
  19282. status = (struct wl_dfs_ap_move_status_v2 *)ioctl_buf;
  19283. if (status->version != WL_DFS_AP_MOVE_VERSION) {
  19284. err = BCME_UNSUPPORTED;
  19285. WL_ERR(("err=%d version=%d\n", err, status->version));
  19286. return err;
  19287. }
  19288. if (status->move_status != (int8) DFS_SCAN_S_IDLE) {
  19289. chanspec = wl_chspec_driver_to_host(status->chanspec);
  19290. if (chanspec != 0 && chanspec != INVCHANSPEC) {
  19291. wf_chspec_ntoa(chanspec, chanbuf);
  19292. bytes_written = snprintf(command, total_len,
  19293. "AP Target Chanspec %s (0x%x)\n", chanbuf, chanspec);
  19294. }
  19295. bytes_written += snprintf(command + bytes_written,
  19296. total_len - bytes_written,
  19297. "%s\n", dfs_state_str[status->move_status]);
  19298. return bytes_written;
  19299. } else {
  19300. bytes_written = snprintf(command, total_len, "dfs AP move in IDLE state\n");
  19301. return bytes_written;
  19302. }
  19303. }
  19304. abort = bcm_atoi(data);
  19305. if (abort == -1) {
  19306. if ((err = wldev_iovar_setbuf(ndev, "dfs_ap_move", &abort,
  19307. sizeof(int), ioctl_buf, sizeof(ioctl_buf), NULL)) < 0) {
  19308. WL_ERR(("seting dfs_ap_move failed with err %d\n", err));
  19309. return err;
  19310. }
  19311. } else {
  19312. chanspec = wf_chspec_aton(data);
  19313. if (chanspec != 0) {
  19314. val = wl_chspec_host_to_driver(chanspec);
  19315. if (val != INVCHANSPEC) {
  19316. if ((err = wldev_iovar_setbuf(ndev, "dfs_ap_move", &val,
  19317. sizeof(int), ioctl_buf, sizeof(ioctl_buf), NULL)) < 0) {
  19318. WL_ERR(("seting dfs_ap_move failed with err %d\n", err));
  19319. return err;
  19320. }
  19321. WL_DBG((" set dfs_ap_move successfull"));
  19322. } else {
  19323. err = BCME_USAGE_ERROR;
  19324. }
  19325. }
  19326. }
  19327. return err;
  19328. }
  19329. bool wl_cfg80211_is_concurrent_mode(struct net_device *dev)
  19330. {
  19331. struct bcm_cfg80211 *cfg = wl_get_cfg(dev);
  19332. if ((cfg) && (wl_get_drv_status_all(cfg, CONNECTED) > 1)) {
  19333. return true;
  19334. } else {
  19335. return false;
  19336. }
  19337. }
  19338. void* wl_cfg80211_get_dhdp(struct net_device *dev)
  19339. {
  19340. struct bcm_cfg80211 *cfg = wl_get_cfg(dev);
  19341. return cfg->pub;
  19342. }
  19343. bool wl_cfg80211_is_p2p_active(struct net_device *dev)
  19344. {
  19345. struct bcm_cfg80211 *cfg = wl_get_cfg(dev);
  19346. return (cfg && cfg->p2p);
  19347. }
  19348. bool wl_cfg80211_is_roam_offload(struct net_device * dev)
  19349. {
  19350. struct bcm_cfg80211 *cfg = wl_get_cfg(dev);
  19351. return (cfg && cfg->roam_offload);
  19352. }
  19353. bool wl_cfg80211_is_event_from_connected_bssid(struct net_device * dev, const wl_event_msg_t *e,
  19354. int ifidx)
  19355. {
  19356. u8 *curbssid = NULL;
  19357. struct bcm_cfg80211 *cfg = wl_get_cfg(dev);
  19358. if (!cfg) {
  19359. /* When interface is created using wl
  19360. * ndev->ieee80211_ptr will be NULL.
  19361. */
  19362. return NULL;
  19363. }
  19364. curbssid = wl_read_prof(cfg, dev, WL_PROF_BSSID);
  19365. if (memcmp(curbssid, &e->addr, ETHER_ADDR_LEN) == 0) {
  19366. return true;
  19367. }
  19368. return false;
  19369. }
  19370. static void wl_cfg80211_work_handler(struct work_struct * work)
  19371. {
  19372. struct bcm_cfg80211 *cfg = NULL;
  19373. struct net_info *iter, *next;
  19374. s32 err = BCME_OK;
  19375. s32 pm = PM_FAST;
  19376. BCM_SET_CONTAINER_OF(cfg, work, struct bcm_cfg80211, pm_enable_work.work);
  19377. WL_DBG(("Enter \n"));
  19378. GCC_DIAGNOSTIC_PUSH_SUPPRESS_CAST();
  19379. for_each_ndev(cfg, iter, next) {
  19380. GCC_DIAGNOSTIC_POP();
  19381. /* p2p discovery iface ndev could be null */
  19382. if (iter->ndev) {
  19383. if (!wl_get_drv_status(cfg, CONNECTED, iter->ndev) ||
  19384. (wl_get_mode_by_netdev(cfg, iter->ndev) != WL_MODE_BSS &&
  19385. wl_get_mode_by_netdev(cfg, iter->ndev) != WL_MODE_IBSS))
  19386. continue;
  19387. if (iter->ndev) {
  19388. if ((err = wldev_ioctl_set(iter->ndev, WLC_SET_PM,
  19389. &pm, sizeof(pm))) != 0) {
  19390. if (err == -ENODEV)
  19391. WL_DBG(("%s:netdev not ready\n",
  19392. iter->ndev->name));
  19393. else
  19394. WL_ERR(("%s:error (%d)\n",
  19395. iter->ndev->name, err));
  19396. } else
  19397. wl_cfg80211_update_power_mode(iter->ndev);
  19398. }
  19399. }
  19400. }
  19401. #if defined(OEM_ANDROID)
  19402. DHD_PM_WAKE_UNLOCK(cfg->pub);
  19403. #endif /* BCMDONGLEHOST && OEM_ANDROID */
  19404. }
  19405. u8
  19406. wl_get_action_category(void *frame, u32 frame_len)
  19407. {
  19408. u8 category;
  19409. u8 *ptr = (u8 *)frame;
  19410. if (frame == NULL)
  19411. return DOT11_ACTION_CAT_ERR_MASK;
  19412. if (frame_len < DOT11_ACTION_HDR_LEN)
  19413. return DOT11_ACTION_CAT_ERR_MASK;
  19414. category = ptr[DOT11_ACTION_CAT_OFF];
  19415. WL_DBG(("Action Category: %d\n", category));
  19416. return category;
  19417. }
  19418. int
  19419. wl_get_public_action(void *frame, u32 frame_len, u8 *ret_action)
  19420. {
  19421. u8 *ptr = (u8 *)frame;
  19422. if (frame == NULL || ret_action == NULL)
  19423. return BCME_ERROR;
  19424. if (frame_len < DOT11_ACTION_HDR_LEN)
  19425. return BCME_ERROR;
  19426. if (DOT11_ACTION_CAT_PUBLIC != wl_get_action_category(frame, frame_len))
  19427. return BCME_ERROR;
  19428. *ret_action = ptr[DOT11_ACTION_ACT_OFF];
  19429. WL_DBG(("Public Action : %d\n", *ret_action));
  19430. return BCME_OK;
  19431. }
  19432. #ifdef WLFBT
  19433. int
  19434. wl_cfg80211_get_fbt_key(struct net_device *dev, uint8 *key, int total_len)
  19435. {
  19436. struct bcm_cfg80211 * cfg = wl_get_cfg(dev);
  19437. int bytes_written = -1;
  19438. if (total_len < FBT_KEYLEN) {
  19439. WL_ERR(("wl_cfg80211_get_fbt_key: Insufficient buffer \n"));
  19440. goto end;
  19441. }
  19442. if (cfg) {
  19443. memcpy(key, cfg->fbt_key, FBT_KEYLEN);
  19444. bytes_written = FBT_KEYLEN;
  19445. } else {
  19446. bzero(key, FBT_KEYLEN);
  19447. WL_ERR(("wl_cfg80211_get_fbt_key: Failed to copy KCK and KEK \n"));
  19448. }
  19449. prhex("KCK, KEK", (uchar *)key, FBT_KEYLEN);
  19450. end:
  19451. return bytes_written;
  19452. }
  19453. #endif /* WLFBT */
  19454. static int
  19455. wl_cfg80211_delayed_roam(struct bcm_cfg80211 *cfg, struct net_device *ndev,
  19456. const struct ether_addr *bssid)
  19457. {
  19458. s32 err;
  19459. wl_event_msg_t e;
  19460. bzero(&e, sizeof(e));
  19461. e.event_type = cpu_to_be32(WLC_E_ROAM);
  19462. memcpy(&e.addr, bssid, ETHER_ADDR_LEN);
  19463. /* trigger the roam event handler */
  19464. err = wl_notify_roaming_status(cfg, ndev_to_cfgdev(ndev), &e, NULL);
  19465. return err;
  19466. }
  19467. static s32
  19468. wl_cfg80211_parse_vndr_ies(const u8 *parse, u32 len,
  19469. struct parsed_vndr_ies *vndr_ies)
  19470. {
  19471. s32 err = BCME_OK;
  19472. const vndr_ie_t *vndrie;
  19473. const bcm_tlv_t *ie;
  19474. struct parsed_vndr_ie_info *parsed_info;
  19475. u32 count = 0;
  19476. u32 remained_len;
  19477. remained_len = len;
  19478. bzero(vndr_ies, sizeof(*vndr_ies));
  19479. WL_DBG(("---> len %d\n", len));
  19480. ie = (const bcm_tlv_t *) parse;
  19481. if (!bcm_valid_tlv(ie, remained_len))
  19482. ie = NULL;
  19483. while (ie) {
  19484. if (count >= MAX_VNDR_IE_NUMBER)
  19485. break;
  19486. if (ie->id == DOT11_MNG_VS_ID || (ie->id == DOT11_MNG_ID_EXT_ID)) {
  19487. vndrie = (const vndr_ie_t *) ie;
  19488. if (ie->id == DOT11_MNG_ID_EXT_ID) {
  19489. /* len should be bigger than sizeof ID extn field at least */
  19490. if (vndrie->len < MIN_VENDOR_EXTN_IE_LEN) {
  19491. WL_ERR(("%s: invalid vndr extn ie."
  19492. " length %d\n",
  19493. __FUNCTION__, vndrie->len));
  19494. goto end;
  19495. }
  19496. } else {
  19497. /* len should be bigger than OUI length +
  19498. * one data length at least
  19499. */
  19500. if (vndrie->len < (VNDR_IE_MIN_LEN + 1)) {
  19501. WL_ERR(("wl_cfg80211_parse_vndr_ies:"
  19502. " invalid vndr ie. length is too small %d\n",
  19503. vndrie->len));
  19504. goto end;
  19505. }
  19506. /* if wpa or wme ie, do not add ie */
  19507. if (!bcmp(vndrie->oui, (u8*)WPA_OUI, WPA_OUI_LEN) &&
  19508. ((vndrie->data[0] == WPA_OUI_TYPE) ||
  19509. (vndrie->data[0] == WME_OUI_TYPE))) {
  19510. CFGP2P_DBG(("Found WPA/WME oui. Do not add it\n"));
  19511. goto end;
  19512. }
  19513. }
  19514. parsed_info = &vndr_ies->ie_info[count++];
  19515. /* save vndr ie information */
  19516. parsed_info->ie_ptr = (const char *)vndrie;
  19517. parsed_info->ie_len = (vndrie->len + TLV_HDR_LEN);
  19518. memcpy(&parsed_info->vndrie, vndrie, sizeof(vndr_ie_t));
  19519. vndr_ies->count = count;
  19520. if (ie->id == DOT11_MNG_ID_EXT_ID) {
  19521. WL_DBG(("\t ** Vendor Extension ie id: 0x%02x, len:%d\n",
  19522. ie->id, parsed_info->ie_len));
  19523. } else {
  19524. WL_DBG(("\t ** OUI "MACOUIDBG", type 0x%02x len:%d\n",
  19525. MACOUI2STRDBG(parsed_info->vndrie.oui),
  19526. parsed_info->vndrie.data[0], parsed_info->ie_len));
  19527. }
  19528. }
  19529. end:
  19530. ie = bcm_next_tlv(ie, &remained_len);
  19531. }
  19532. return err;
  19533. }
  19534. static bool
  19535. wl_vndr_ies_exclude_vndr_oui(struct parsed_vndr_ie_info *vndr_info)
  19536. {
  19537. int i = 0;
  19538. while (exclude_vndr_oui_list[i]) {
  19539. if (!memcmp(vndr_info->vndrie.oui,
  19540. exclude_vndr_oui_list[i],
  19541. DOT11_OUI_LEN)) {
  19542. return TRUE;
  19543. }
  19544. i++;
  19545. }
  19546. return FALSE;
  19547. }
  19548. static bool
  19549. wl_vndr_ies_check_duplicate_vndr_oui(struct bcm_cfg80211 *cfg,
  19550. struct parsed_vndr_ie_info *vndr_info)
  19551. {
  19552. wl_vndr_oui_entry_t *oui_entry = NULL;
  19553. unsigned long flags;
  19554. WL_CFG_VNDR_OUI_SYNC_LOCK(&cfg->vndr_oui_sync, flags);
  19555. GCC_DIAGNOSTIC_PUSH_SUPPRESS_CAST();
  19556. list_for_each_entry(oui_entry, &cfg->vndr_oui_list, list) {
  19557. GCC_DIAGNOSTIC_POP();
  19558. if (!memcmp(oui_entry->oui, vndr_info->vndrie.oui, DOT11_OUI_LEN)) {
  19559. WL_CFG_VNDR_OUI_SYNC_UNLOCK(&cfg->vndr_oui_sync, flags);
  19560. return TRUE;
  19561. }
  19562. }
  19563. WL_CFG_VNDR_OUI_SYNC_UNLOCK(&cfg->vndr_oui_sync, flags);
  19564. return FALSE;
  19565. }
  19566. static bool
  19567. wl_vndr_ies_add_vendor_oui_list(struct bcm_cfg80211 *cfg,
  19568. struct parsed_vndr_ie_info *vndr_info)
  19569. {
  19570. wl_vndr_oui_entry_t *oui_entry = NULL;
  19571. unsigned long flags;
  19572. oui_entry = kmalloc(sizeof(*oui_entry), GFP_KERNEL);
  19573. if (oui_entry == NULL) {
  19574. WL_ERR(("alloc failed\n"));
  19575. return FALSE;
  19576. }
  19577. memcpy(oui_entry->oui, vndr_info->vndrie.oui, DOT11_OUI_LEN);
  19578. INIT_LIST_HEAD(&oui_entry->list);
  19579. WL_CFG_VNDR_OUI_SYNC_LOCK(&cfg->vndr_oui_sync, flags);
  19580. list_add_tail(&oui_entry->list, &cfg->vndr_oui_list);
  19581. WL_CFG_VNDR_OUI_SYNC_UNLOCK(&cfg->vndr_oui_sync, flags);
  19582. return TRUE;
  19583. }
  19584. static void
  19585. wl_vndr_ies_clear_vendor_oui_list(struct bcm_cfg80211 *cfg)
  19586. {
  19587. wl_vndr_oui_entry_t *oui_entry = NULL;
  19588. unsigned long flags;
  19589. WL_CFG_VNDR_OUI_SYNC_LOCK(&cfg->vndr_oui_sync, flags);
  19590. while (!list_empty(&cfg->vndr_oui_list)) {
  19591. GCC_DIAGNOSTIC_PUSH_SUPPRESS_CAST();
  19592. oui_entry = list_entry(cfg->vndr_oui_list.next, wl_vndr_oui_entry_t, list);
  19593. GCC_DIAGNOSTIC_POP();
  19594. if (oui_entry) {
  19595. list_del(&oui_entry->list);
  19596. kfree(oui_entry);
  19597. }
  19598. }
  19599. WL_CFG_VNDR_OUI_SYNC_UNLOCK(&cfg->vndr_oui_sync, flags);
  19600. }
  19601. static int
  19602. wl_vndr_ies_get_vendor_oui(struct bcm_cfg80211 *cfg, struct net_device *ndev,
  19603. char *vndr_oui, u32 vndr_oui_len)
  19604. {
  19605. int i;
  19606. int vndr_oui_num = 0;
  19607. struct wl_connect_info *conn_info = wl_to_conn(cfg);
  19608. wl_vndr_oui_entry_t *oui_entry = NULL;
  19609. struct parsed_vndr_ie_info *vndr_info;
  19610. struct parsed_vndr_ies vndr_ies;
  19611. char *pos = vndr_oui;
  19612. u32 remained_buf_len = vndr_oui_len;
  19613. unsigned long flags;
  19614. if (!conn_info->resp_ie_len) {
  19615. return BCME_ERROR;
  19616. }
  19617. wl_vndr_ies_clear_vendor_oui_list(cfg);
  19618. if ((wl_cfg80211_parse_vndr_ies((u8 *)conn_info->resp_ie,
  19619. conn_info->resp_ie_len, &vndr_ies)) == BCME_OK) {
  19620. for (i = 0; i < vndr_ies.count; i++) {
  19621. vndr_info = &vndr_ies.ie_info[i];
  19622. if (wl_vndr_ies_exclude_vndr_oui(vndr_info)) {
  19623. continue;
  19624. }
  19625. if (wl_vndr_ies_check_duplicate_vndr_oui(cfg, vndr_info)) {
  19626. continue;
  19627. }
  19628. wl_vndr_ies_add_vendor_oui_list(cfg, vndr_info);
  19629. vndr_oui_num++;
  19630. }
  19631. }
  19632. if (vndr_oui) {
  19633. WL_CFG_VNDR_OUI_SYNC_LOCK(&cfg->vndr_oui_sync, flags);
  19634. GCC_DIAGNOSTIC_PUSH_SUPPRESS_CAST();
  19635. list_for_each_entry(oui_entry, &cfg->vndr_oui_list, list) {
  19636. GCC_DIAGNOSTIC_POP();
  19637. if (remained_buf_len < VNDR_OUI_STR_LEN) {
  19638. WL_CFG_VNDR_OUI_SYNC_UNLOCK(&cfg->vndr_oui_sync, flags);
  19639. return BCME_ERROR;
  19640. }
  19641. pos += snprintf(pos, VNDR_OUI_STR_LEN, "%02X-%02X-%02X ",
  19642. oui_entry->oui[0], oui_entry->oui[1], oui_entry->oui[2]);
  19643. remained_buf_len -= VNDR_OUI_STR_LEN;
  19644. }
  19645. WL_CFG_VNDR_OUI_SYNC_UNLOCK(&cfg->vndr_oui_sync, flags);
  19646. }
  19647. return vndr_oui_num;
  19648. }
  19649. void
  19650. wl_cfg80211_clear_p2p_disc_ies(struct bcm_cfg80211 *cfg)
  19651. {
  19652. /* Legacy P2P used to store it in primary dev cache */
  19653. s32 index;
  19654. struct net_device *ndev;
  19655. s32 bssidx;
  19656. s32 ret;
  19657. s32 vndrie_flag[] = {VNDR_IE_BEACON_FLAG, VNDR_IE_PRBRSP_FLAG,
  19658. VNDR_IE_ASSOCRSP_FLAG, VNDR_IE_PRBREQ_FLAG, VNDR_IE_ASSOCREQ_FLAG};
  19659. WL_DBG(("Clear IEs for P2P Discovery Iface \n"));
  19660. /* certain vendors uses p2p0 interface in addition to
  19661. * the dedicated p2p interface supported by the linux
  19662. * kernel.
  19663. */
  19664. ndev = wl_to_p2p_bss_ndev(cfg, P2PAPI_BSSCFG_PRIMARY);
  19665. bssidx = wl_to_p2p_bss_bssidx(cfg, P2PAPI_BSSCFG_DEVICE);
  19666. if (bssidx == WL_INVALID) {
  19667. WL_DBG(("No discovery I/F available. Do nothing.\n"));
  19668. return;
  19669. }
  19670. for (index = 0; index < ARRAYSIZE(vndrie_flag); index++) {
  19671. if ((ret = wl_cfg80211_set_mgmt_vndr_ies(cfg, ndev_to_cfgdev(ndev),
  19672. bssidx, vndrie_flag[index], NULL, 0)) < 0) {
  19673. if (ret != BCME_NOTFOUND) {
  19674. WL_ERR(("vndr_ies clear failed (%d). Ignoring.. \n", ret));
  19675. }
  19676. }
  19677. }
  19678. if (cfg->p2p_wdev && (ndev->ieee80211_ptr != cfg->p2p_wdev)) {
  19679. /* clear IEs for dedicated p2p interface */
  19680. wl_cfg80211_clear_per_bss_ies(cfg, cfg->p2p_wdev);
  19681. }
  19682. }
  19683. s32
  19684. wl_cfg80211_clear_per_bss_ies(struct bcm_cfg80211 *cfg, struct wireless_dev *wdev)
  19685. {
  19686. s32 index;
  19687. s32 ret;
  19688. struct net_info *netinfo;
  19689. s32 vndrie_flag[] = {VNDR_IE_BEACON_FLAG, VNDR_IE_PRBRSP_FLAG,
  19690. VNDR_IE_ASSOCRSP_FLAG, VNDR_IE_PRBREQ_FLAG, VNDR_IE_ASSOCREQ_FLAG};
  19691. netinfo = wl_get_netinfo_by_wdev(cfg, wdev);
  19692. if (!netinfo || !netinfo->wdev) {
  19693. WL_ERR(("netinfo or netinfo->wdev is NULL\n"));
  19694. return -1;
  19695. }
  19696. WL_DBG(("clear management vendor IEs for bssidx:%d \n", netinfo->bssidx));
  19697. /* Clear the IEs set in the firmware so that host is in sync with firmware */
  19698. for (index = 0; index < ARRAYSIZE(vndrie_flag); index++) {
  19699. if ((ret = wl_cfg80211_set_mgmt_vndr_ies(cfg, wdev_to_cfgdev(netinfo->wdev),
  19700. netinfo->bssidx, vndrie_flag[index], NULL, 0)) < 0)
  19701. if (ret != BCME_NOTFOUND) {
  19702. WL_ERR(("vndr_ies clear failed. Ignoring.. \n"));
  19703. }
  19704. }
  19705. return 0;
  19706. }
  19707. s32
  19708. wl_cfg80211_clear_mgmt_vndr_ies(struct bcm_cfg80211 *cfg)
  19709. {
  19710. struct net_info *iter, *next;
  19711. WL_DBG(("clear management vendor IEs \n"));
  19712. GCC_DIAGNOSTIC_PUSH_SUPPRESS_CAST();
  19713. for_each_ndev(cfg, iter, next) {
  19714. GCC_DIAGNOSTIC_POP();
  19715. wl_cfg80211_clear_per_bss_ies(cfg, iter->wdev);
  19716. }
  19717. return 0;
  19718. }
  19719. #define WL_VNDR_IE_MAXLEN 2048
  19720. static s8 g_mgmt_ie_buf[WL_VNDR_IE_MAXLEN];
  19721. int
  19722. wl_cfg80211_set_mgmt_vndr_ies(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev,
  19723. s32 bssidx, s32 pktflag, const u8 *vndr_ie, u32 vndr_ie_len)
  19724. {
  19725. struct net_device *ndev = NULL;
  19726. s32 ret = BCME_OK;
  19727. u8 *curr_ie_buf = NULL;
  19728. u8 *mgmt_ie_buf = NULL;
  19729. u32 mgmt_ie_buf_len = 0;
  19730. u32 *mgmt_ie_len = 0;
  19731. u32 del_add_ie_buf_len = 0;
  19732. u32 total_ie_buf_len = 0;
  19733. u32 parsed_ie_buf_len = 0;
  19734. struct parsed_vndr_ies old_vndr_ies;
  19735. struct parsed_vndr_ies new_vndr_ies;
  19736. s32 i;
  19737. u8 *ptr;
  19738. s32 remained_buf_len;
  19739. wl_bss_vndr_ies_t *ies = NULL;
  19740. struct net_info *netinfo;
  19741. struct wireless_dev *wdev;
  19742. ndev = cfgdev_to_wlc_ndev(cfgdev, cfg);
  19743. wdev = cfgdev_to_wdev(cfgdev);
  19744. if (bssidx > WL_MAX_IFS) {
  19745. WL_ERR(("bssidx > supported concurrent Ifaces \n"));
  19746. return -EINVAL;
  19747. }
  19748. netinfo = wl_get_netinfo_by_wdev(cfg, wdev);
  19749. if (!netinfo) {
  19750. WL_ERR(("net_info ptr is NULL \n"));
  19751. return -EINVAL;
  19752. }
  19753. /* Clear the global buffer */
  19754. bzero(g_mgmt_ie_buf, sizeof(g_mgmt_ie_buf));
  19755. curr_ie_buf = g_mgmt_ie_buf;
  19756. ies = &netinfo->bss.ies;
  19757. WL_DBG(("Enter. pktflag:0x%x bssidx:%x vnd_ie_len:%d wdev:%p\n",
  19758. pktflag, bssidx, vndr_ie_len, wdev));
  19759. switch (pktflag) {
  19760. case VNDR_IE_PRBRSP_FLAG :
  19761. mgmt_ie_buf = ies->probe_res_ie;
  19762. mgmt_ie_len = &ies->probe_res_ie_len;
  19763. mgmt_ie_buf_len = sizeof(ies->probe_res_ie);
  19764. break;
  19765. case VNDR_IE_ASSOCRSP_FLAG :
  19766. mgmt_ie_buf = ies->assoc_res_ie;
  19767. mgmt_ie_len = &ies->assoc_res_ie_len;
  19768. mgmt_ie_buf_len = sizeof(ies->assoc_res_ie);
  19769. break;
  19770. case VNDR_IE_BEACON_FLAG :
  19771. mgmt_ie_buf = ies->beacon_ie;
  19772. mgmt_ie_len = &ies->beacon_ie_len;
  19773. mgmt_ie_buf_len = sizeof(ies->beacon_ie);
  19774. break;
  19775. case VNDR_IE_PRBREQ_FLAG :
  19776. mgmt_ie_buf = ies->probe_req_ie;
  19777. mgmt_ie_len = &ies->probe_req_ie_len;
  19778. mgmt_ie_buf_len = sizeof(ies->probe_req_ie);
  19779. break;
  19780. case VNDR_IE_ASSOCREQ_FLAG :
  19781. mgmt_ie_buf = ies->assoc_req_ie;
  19782. mgmt_ie_len = &ies->assoc_req_ie_len;
  19783. mgmt_ie_buf_len = sizeof(ies->assoc_req_ie);
  19784. break;
  19785. case VNDR_IE_DISASSOC_FLAG :
  19786. mgmt_ie_buf = ies->disassoc_ie;
  19787. mgmt_ie_len = &ies->disassoc_ie_len;
  19788. mgmt_ie_buf_len = sizeof(ies->disassoc_ie);
  19789. break;
  19790. default:
  19791. mgmt_ie_buf = NULL;
  19792. mgmt_ie_len = NULL;
  19793. WL_ERR(("not suitable packet type (%d)\n", pktflag));
  19794. return BCME_ERROR;
  19795. }
  19796. if (vndr_ie_len > mgmt_ie_buf_len) {
  19797. WL_ERR(("extra IE size too big\n"));
  19798. ret = -ENOMEM;
  19799. } else {
  19800. /* parse and save new vndr_ie in curr_ie_buff before comparing it */
  19801. if (vndr_ie && vndr_ie_len && curr_ie_buf) {
  19802. ptr = curr_ie_buf;
  19803. if ((ret = wl_cfg80211_parse_vndr_ies((const u8 *)vndr_ie,
  19804. vndr_ie_len, &new_vndr_ies)) < 0) {
  19805. WL_ERR(("parse vndr ie failed \n"));
  19806. goto exit;
  19807. }
  19808. for (i = 0; i < new_vndr_ies.count; i++) {
  19809. struct parsed_vndr_ie_info *vndrie_info =
  19810. &new_vndr_ies.ie_info[i];
  19811. if ((parsed_ie_buf_len + vndrie_info->ie_len) > WL_VNDR_IE_MAXLEN) {
  19812. WL_ERR(("IE size is too big (%d > %d)\n",
  19813. parsed_ie_buf_len, WL_VNDR_IE_MAXLEN));
  19814. ret = -EINVAL;
  19815. goto exit;
  19816. }
  19817. memcpy(ptr + parsed_ie_buf_len, vndrie_info->ie_ptr,
  19818. vndrie_info->ie_len);
  19819. parsed_ie_buf_len += vndrie_info->ie_len;
  19820. }
  19821. }
  19822. if (mgmt_ie_buf != NULL) {
  19823. if (parsed_ie_buf_len && (parsed_ie_buf_len == *mgmt_ie_len) &&
  19824. (memcmp(mgmt_ie_buf, curr_ie_buf, parsed_ie_buf_len) == 0)) {
  19825. WL_DBG(("Previous mgmt IE is equals to current IE"));
  19826. goto exit;
  19827. }
  19828. /* parse old vndr_ie */
  19829. if ((ret = wl_cfg80211_parse_vndr_ies(mgmt_ie_buf, *mgmt_ie_len,
  19830. &old_vndr_ies)) < 0) {
  19831. WL_ERR(("parse vndr ie failed \n"));
  19832. goto exit;
  19833. }
  19834. /* make a command to delete old ie */
  19835. for (i = 0; i < old_vndr_ies.count; i++) {
  19836. struct parsed_vndr_ie_info *vndrie_info =
  19837. &old_vndr_ies.ie_info[i];
  19838. #if defined(WL_MBO) || defined(WL_OCE)
  19839. {
  19840. if ((vndrie_info->vndrie.id == 0xDD) &&
  19841. (!memcmp(vndrie_info->vndrie.oui, WFA_OUI, WFA_OUI_LEN)) &&
  19842. (vndrie_info->vndrie.data[0] == WFA_OUI_TYPE_MBO_OCE)) {
  19843. WL_DBG(("skipping ID : %d, Len: %d, OUI:"MACOUIDBG
  19844. ", type: %0x\n",
  19845. vndrie_info->vndrie.id,
  19846. vndrie_info->vndrie.len,
  19847. MACOUI2STRDBG(vndrie_info->vndrie.oui),
  19848. vndrie_info->vndrie.data[0]));
  19849. continue;
  19850. }
  19851. }
  19852. #endif /* WL_MBO || WL_OCE */
  19853. if (vndrie_info->vndrie.id == DOT11_MNG_ID_EXT_ID) {
  19854. WL_DBG(("DELETED VENDOR EXTN ID : %d, TYPE: %d Len: %d\n",
  19855. vndrie_info->vndrie.id, vndrie_info->vndrie.oui[0],
  19856. vndrie_info->vndrie.len));
  19857. } else {
  19858. WL_DBG(("DELETED ID : %d, Len: %d , OUI:"MACOUIDBG"\n",
  19859. vndrie_info->vndrie.id, vndrie_info->vndrie.len,
  19860. MACOUI2STRDBG(vndrie_info->vndrie.oui)));
  19861. }
  19862. del_add_ie_buf_len = wl_cfgp2p_vndr_ie(cfg, curr_ie_buf,
  19863. pktflag, vndrie_info->vndrie.oui,
  19864. vndrie_info->vndrie.id,
  19865. vndrie_info->ie_ptr + VNDR_IE_FIXED_LEN,
  19866. vndrie_info->ie_len - VNDR_IE_FIXED_LEN,
  19867. "del");
  19868. curr_ie_buf += del_add_ie_buf_len;
  19869. total_ie_buf_len += del_add_ie_buf_len;
  19870. }
  19871. }
  19872. *mgmt_ie_len = 0;
  19873. /* Add if there is any extra IE */
  19874. if (mgmt_ie_buf && parsed_ie_buf_len) {
  19875. ptr = mgmt_ie_buf;
  19876. remained_buf_len = mgmt_ie_buf_len;
  19877. /* make a command to add new ie */
  19878. for (i = 0; i < new_vndr_ies.count; i++) {
  19879. struct parsed_vndr_ie_info *vndrie_info =
  19880. &new_vndr_ies.ie_info[i];
  19881. #if defined(WL_MBO) || defined(WL_OCE)
  19882. {
  19883. if ((vndrie_info->vndrie.id == 0xDD) &&
  19884. (!memcmp(vndrie_info->vndrie.oui, WFA_OUI, WFA_OUI_LEN)) &&
  19885. (vndrie_info->vndrie.data[0] == WFA_OUI_TYPE_MBO_OCE)) {
  19886. WL_DBG(("skipping ID : %d, Len: %d, OUI:"MACOUIDBG
  19887. ",type :%0x\n",
  19888. vndrie_info->vndrie.id,
  19889. vndrie_info->vndrie.len,
  19890. MACOUI2STRDBG(vndrie_info->vndrie.oui),
  19891. vndrie_info->vndrie.data[0]));
  19892. continue;
  19893. }
  19894. }
  19895. #endif /* WL_MBO || WL_OCE */
  19896. if (vndrie_info->vndrie.id == DOT11_MNG_ID_EXT_ID) {
  19897. WL_DBG(("ADDED VENDOR EXTN ID : %d, TYPE = %d, Len: %d\n",
  19898. vndrie_info->vndrie.id, vndrie_info->vndrie.oui[0],
  19899. vndrie_info->vndrie.len));
  19900. } else {
  19901. WL_DBG(("ADDED ID : %d, Len: %d(%d), OUI:"MACOUIDBG"\n",
  19902. vndrie_info->vndrie.id, vndrie_info->vndrie.len,
  19903. vndrie_info->ie_len - 2,
  19904. MACOUI2STRDBG(vndrie_info->vndrie.oui)));
  19905. }
  19906. del_add_ie_buf_len = wl_cfgp2p_vndr_ie(cfg, curr_ie_buf,
  19907. pktflag, vndrie_info->vndrie.oui,
  19908. vndrie_info->vndrie.id,
  19909. vndrie_info->ie_ptr + VNDR_IE_FIXED_LEN,
  19910. vndrie_info->ie_len - VNDR_IE_FIXED_LEN,
  19911. "add");
  19912. /* verify remained buf size before copy data */
  19913. if (remained_buf_len >= vndrie_info->ie_len) {
  19914. remained_buf_len -= vndrie_info->ie_len;
  19915. } else {
  19916. WL_ERR(("no space in mgmt_ie_buf: pktflag = %d, "
  19917. "found vndr ies # = %d(cur %d), remained len %d, "
  19918. "cur mgmt_ie_len %d, new ie len = %d\n",
  19919. pktflag, new_vndr_ies.count, i, remained_buf_len,
  19920. *mgmt_ie_len, vndrie_info->ie_len));
  19921. break;
  19922. }
  19923. /* save the parsed IE in cfg struct */
  19924. memcpy(ptr + (*mgmt_ie_len), vndrie_info->ie_ptr,
  19925. vndrie_info->ie_len);
  19926. *mgmt_ie_len += vndrie_info->ie_len;
  19927. curr_ie_buf += del_add_ie_buf_len;
  19928. total_ie_buf_len += del_add_ie_buf_len;
  19929. }
  19930. }
  19931. if (total_ie_buf_len && cfg->ioctl_buf != NULL) {
  19932. ret = wldev_iovar_setbuf_bsscfg(ndev, "vndr_ie", g_mgmt_ie_buf,
  19933. total_ie_buf_len, cfg->ioctl_buf, WLC_IOCTL_MAXLEN,
  19934. bssidx, &cfg->ioctl_buf_sync);
  19935. if (ret)
  19936. WL_ERR(("vndr ie set error : %d\n", ret));
  19937. }
  19938. }
  19939. exit:
  19940. return ret;
  19941. }
  19942. #ifdef WL_CFG80211_ACL
  19943. static int
  19944. wl_cfg80211_set_mac_acl(struct wiphy *wiphy, struct net_device *cfgdev,
  19945. const struct cfg80211_acl_data *acl)
  19946. {
  19947. int i;
  19948. int ret = 0;
  19949. int macnum = 0;
  19950. int macmode = MACLIST_MODE_DISABLED;
  19951. struct maclist *list;
  19952. struct bcm_cfg80211 *cfg = wl_get_cfg(cfgdev);
  19953. /* get the MAC filter mode */
  19954. if (acl && acl->acl_policy == NL80211_ACL_POLICY_DENY_UNLESS_LISTED) {
  19955. macmode = MACLIST_MODE_ALLOW;
  19956. } else if (acl && acl->acl_policy == NL80211_ACL_POLICY_ACCEPT_UNLESS_LISTED &&
  19957. acl->n_acl_entries) {
  19958. macmode = MACLIST_MODE_DENY;
  19959. }
  19960. /* if acl == NULL, macmode is still disabled.. */
  19961. if (macmode == MACLIST_MODE_DISABLED) {
  19962. if ((ret = wl_android_set_ap_mac_list(cfgdev, macmode, NULL)) != 0)
  19963. WL_ERR(("wl_cfg80211_set_mac_acl: Setting MAC list"
  19964. " failed error=%d\n", ret));
  19965. return ret;
  19966. }
  19967. macnum = acl->n_acl_entries;
  19968. if (macnum < 0 || macnum > MAX_NUM_MAC_FILT) {
  19969. WL_ERR(("wl_cfg80211_set_mac_acl: invalid number of MAC address entries %d\n",
  19970. macnum));
  19971. return -1;
  19972. }
  19973. /* allocate memory for the MAC list */
  19974. list = (struct maclist *)MALLOC(cfg->osh, sizeof(int) +
  19975. sizeof(struct ether_addr) * macnum);
  19976. if (!list) {
  19977. WL_ERR(("wl_cfg80211_set_mac_acl: failed to allocate memory\n"));
  19978. return -1;
  19979. }
  19980. /* prepare the MAC list */
  19981. list->count = htod32(macnum);
  19982. for (i = 0; i < macnum; i++) {
  19983. memcpy(&list->ea[i], &acl->mac_addrs[i], ETHER_ADDR_LEN);
  19984. }
  19985. /* set the list */
  19986. if ((ret = wl_android_set_ap_mac_list(cfgdev, macmode, list)) != 0)
  19987. WL_ERR(("wl_cfg80211_set_mac_acl: Setting MAC list failed error=%d\n", ret));
  19988. MFREE(cfg->osh, list, sizeof(int) +
  19989. sizeof(struct ether_addr) * macnum);
  19990. return ret;
  19991. }
  19992. #endif /* WL_CFG80211_ACL */
  19993. #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0))
  19994. int wl_chspec_chandef(chanspec_t chanspec,
  19995. #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0))
  19996. struct cfg80211_chan_def *chandef,
  19997. #elif (LINUX_VERSION_CODE >= KERNEL_VERSION (3, 5, 0) && (LINUX_VERSION_CODE <= (3, 7, \
  19998. \
  19999. 0)))
  20000. struct chan_info *chaninfo,
  20001. #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0)) */
  20002. struct wiphy *wiphy)
  20003. {
  20004. uint16 freq = 0;
  20005. int chan_type = 0;
  20006. int channel = 0;
  20007. struct ieee80211_channel *chan;
  20008. if (!chandef) {
  20009. return -1;
  20010. }
  20011. channel = CHSPEC_CHANNEL(chanspec);
  20012. switch (CHSPEC_BW(chanspec)) {
  20013. case WL_CHANSPEC_BW_20:
  20014. chan_type = NL80211_CHAN_HT20;
  20015. break;
  20016. case WL_CHANSPEC_BW_40:
  20017. {
  20018. if (CHSPEC_SB_UPPER(chanspec)) {
  20019. channel += CH_10MHZ_APART;
  20020. chan_type = NL80211_CHAN_HT40MINUS;
  20021. } else {
  20022. channel -= CH_10MHZ_APART;
  20023. chan_type = NL80211_CHAN_HT40PLUS;
  20024. }
  20025. }
  20026. break;
  20027. #if (LINUX_VERSION_CODE >= KERNEL_VERSION (3, 8, 0))
  20028. case WL_CHANSPEC_BW_80:
  20029. case WL_CHANSPEC_BW_8080:
  20030. {
  20031. uint16 sb = CHSPEC_CTL_SB(chanspec);
  20032. if (sb == WL_CHANSPEC_CTL_SB_LL) {
  20033. channel -= (CH_10MHZ_APART + CH_20MHZ_APART);
  20034. } else if (sb == WL_CHANSPEC_CTL_SB_LU) {
  20035. channel -= CH_10MHZ_APART;
  20036. } else if (sb == WL_CHANSPEC_CTL_SB_UL) {
  20037. channel += CH_10MHZ_APART;
  20038. } else {
  20039. /* WL_CHANSPEC_CTL_SB_UU */
  20040. channel += (CH_10MHZ_APART + CH_20MHZ_APART);
  20041. }
  20042. if (sb == WL_CHANSPEC_CTL_SB_LU || sb == WL_CHANSPEC_CTL_SB_UU)
  20043. chan_type = NL80211_CHAN_HT40MINUS;
  20044. else if (sb == WL_CHANSPEC_CTL_SB_LL || sb == WL_CHANSPEC_CTL_SB_UL)
  20045. chan_type = NL80211_CHAN_HT40PLUS;
  20046. }
  20047. break;
  20048. #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION (3, 8, 0)) */
  20049. default:
  20050. chan_type = NL80211_CHAN_HT20;
  20051. break;
  20052. }
  20053. if (CHSPEC_IS5G(chanspec))
  20054. freq = ieee80211_channel_to_frequency(channel, NL80211_BAND_5GHZ);
  20055. else
  20056. freq = ieee80211_channel_to_frequency(channel, NL80211_BAND_2GHZ);
  20057. chan = ieee80211_get_channel(wiphy, freq);
  20058. WL_DBG(("channel:%d freq:%d chan_type: %d chan_ptr:%p \n",
  20059. channel, freq, chan_type, chan));
  20060. if (unlikely(!chan)) {
  20061. /* fw and cfg80211 channel lists are not in sync */
  20062. WL_ERR(("Couldn't find matching channel in wiphy channel list \n"));
  20063. ASSERT(0);
  20064. return -EINVAL;
  20065. }
  20066. #if (LINUX_VERSION_CODE >= KERNEL_VERSION (3, 8, 0))
  20067. cfg80211_chandef_create(chandef, chan, chan_type);
  20068. #elif (LINUX_VERSION_CODE >= KERNEL_VERSION (3, 5, 0) && (LINUX_VERSION_CODE <= (3, 7, \
  20069. \
  20070. 0)))
  20071. chaninfo->freq = freq;
  20072. chaninfo->chan_type = chan_type;
  20073. #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION (3, 8, 0)) */
  20074. return 0;
  20075. }
  20076. void
  20077. wl_cfg80211_ch_switch_notify(struct net_device *dev, uint16 chanspec, struct wiphy *wiphy)
  20078. {
  20079. u32 freq;
  20080. #if (LINUX_VERSION_CODE >= KERNEL_VERSION (3, 8, 0))
  20081. struct cfg80211_chan_def chandef;
  20082. #elif (LINUX_VERSION_CODE >= KERNEL_VERSION (3, 5, 0) && (LINUX_VERSION_CODE <= (3, 7, \
  20083. \
  20084. 0)))
  20085. struct chan_info chaninfo;
  20086. #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION (3, 8, 0)) */
  20087. if (!wiphy) {
  20088. WL_ERR(("wiphy is null\n"));
  20089. return;
  20090. }
  20091. #if (LINUX_VERSION_CODE <= KERNEL_VERSION (3, 18, 0))
  20092. /* Channel switch support is only for AP/GO/ADHOC/MESH */
  20093. if (dev->ieee80211_ptr->iftype == NL80211_IFTYPE_STATION ||
  20094. dev->ieee80211_ptr->iftype == NL80211_IFTYPE_P2P_CLIENT) {
  20095. WL_ERR(("No channel switch notify support for STA/GC\n"));
  20096. return;
  20097. }
  20098. #endif /* (LINUX_VERSION_CODE <= KERNEL_VERSION (3, 18, 0)) */
  20099. #if (LINUX_VERSION_CODE >= KERNEL_VERSION (3, 8, 0))
  20100. if (wl_chspec_chandef(chanspec, &chandef, wiphy)) {
  20101. #elif (LINUX_VERSION_CODE >= KERNEL_VERSION (3, 5, 0) && (LINUX_VERSION_CODE <= (3, 7, \
  20102. \
  20103. 0)))
  20104. if (wl_chspec_chandef(chanspec, &chaninfo, wiphy)) {
  20105. #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION (3, 8, 0)) */
  20106. WL_ERR(("chspec_chandef failed\n"));
  20107. return;
  20108. }
  20109. #if (LINUX_VERSION_CODE >= KERNEL_VERSION (3, 8, 0))
  20110. freq = chandef.chan ? chandef.chan->center_freq : chandef.center_freq1;
  20111. cfg80211_ch_switch_notify(dev, &chandef);
  20112. #elif (LINUX_VERSION_CODE >= KERNEL_VERSION (3, 5, 0) && (LINUX_VERSION_CODE <= (3, 7, \
  20113. \
  20114. 0)))
  20115. freq = chan_info.freq;
  20116. cfg80211_ch_switch_notify(dev, freq, chan_info.chan_type);
  20117. #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION (3, 8, 0)) */
  20118. WL_ERR(("Channel switch notification for freq: %d chanspec: 0x%x\n", freq, chanspec));
  20119. return;
  20120. }
  20121. #endif /* LINUX_VERSION_CODE >= (3, 5, 0) */
  20122. static void
  20123. wl_ap_channel_ind(struct bcm_cfg80211 *cfg,
  20124. struct net_device *ndev,
  20125. chanspec_t chanspec)
  20126. {
  20127. u32 channel = LCHSPEC_CHANNEL(chanspec);
  20128. WL_INFORM_MEM(("(%s) AP channel:%d chspec:0x%x \n",
  20129. ndev->name, channel, chanspec));
  20130. if (cfg->ap_oper_channel && (cfg->ap_oper_channel != channel)) {
  20131. /*
  20132. * If cached channel is different from the channel indicated
  20133. * by the event, notify user space about the channel switch.
  20134. */
  20135. #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0))
  20136. wl_cfg80211_ch_switch_notify(ndev, chanspec, bcmcfg_to_wiphy(cfg));
  20137. #endif /* LINUX_VERSION_CODE >= (3, 5, 0) */
  20138. cfg->ap_oper_channel = channel;
  20139. }
  20140. }
  20141. static s32
  20142. wl_ap_start_ind(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev,
  20143. const wl_event_msg_t *e, void *data)
  20144. {
  20145. struct net_device *ndev = NULL;
  20146. chanspec_t chanspec;
  20147. WL_DBG(("Enter\n"));
  20148. if (unlikely(e->status)) {
  20149. WL_ERR(("status:0x%x \n", e->status));
  20150. return -1;
  20151. }
  20152. if (!data) {
  20153. return -EINVAL;
  20154. }
  20155. if (likely(cfgdev)) {
  20156. ndev = cfgdev_to_wlc_ndev(cfgdev, cfg);
  20157. chanspec = *((chanspec_t *)data);
  20158. if (wl_get_mode_by_netdev(cfg, ndev) == WL_MODE_AP) {
  20159. /* For AP/GO role */
  20160. wl_ap_channel_ind(cfg, ndev, chanspec);
  20161. }
  20162. }
  20163. return 0;
  20164. }
  20165. static s32
  20166. wl_csa_complete_ind(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev,
  20167. const wl_event_msg_t *e, void *data)
  20168. {
  20169. int error = 0;
  20170. u32 chanspec = 0;
  20171. struct net_device *ndev = NULL;
  20172. struct ether_addr bssid;
  20173. WL_DBG(("Enter\n"));
  20174. if (unlikely(e->status)) {
  20175. WL_ERR(("status:0x%x \n", e->status));
  20176. return -1;
  20177. }
  20178. if (likely(cfgdev)) {
  20179. ndev = cfgdev_to_wlc_ndev(cfgdev, cfg);
  20180. /* Get association state if not AP and then query chanspec */
  20181. if (!((wl_get_mode_by_netdev(cfg, ndev)) == WL_MODE_AP)) {
  20182. error = wldev_ioctl_get(ndev, WLC_GET_BSSID, &bssid, ETHER_ADDR_LEN);
  20183. if (error) {
  20184. WL_ERR(("CSA on %s. Not associated. error=%d\n",
  20185. ndev->name, error));
  20186. return BCME_ERROR;
  20187. }
  20188. }
  20189. error = wldev_iovar_getint(ndev, "chanspec", &chanspec);
  20190. if (unlikely(error)) {
  20191. WL_ERR(("Get chanspec error: %d \n", error));
  20192. return -1;
  20193. }
  20194. WL_INFORM_MEM(("[%s] CSA ind. ch:0x%x\n", ndev->name, chanspec));
  20195. if (wl_get_mode_by_netdev(cfg, ndev) == WL_MODE_AP) {
  20196. /* For AP/GO role */
  20197. wl_ap_channel_ind(cfg, ndev, chanspec);
  20198. } else {
  20199. /* STA/GC roles */
  20200. if (!wl_get_drv_status(cfg, CONNECTED, ndev)) {
  20201. WL_ERR(("CSA on %s. Not associated.\n", ndev->name));
  20202. return BCME_ERROR;
  20203. }
  20204. #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0))
  20205. wl_cfg80211_ch_switch_notify(ndev, chanspec, bcmcfg_to_wiphy(cfg));
  20206. #endif /* LINUX_VERSION_CODE >= (3, 5, 0) */
  20207. }
  20208. }
  20209. return 0;
  20210. }
  20211. void wl_cfg80211_clear_security(struct bcm_cfg80211 *cfg)
  20212. {
  20213. struct net_device *dev = bcmcfg_to_prmry_ndev(cfg);
  20214. int err;
  20215. /* Clear the security settings on the primary Interface */
  20216. err = wldev_iovar_setint(dev, "wsec", 0);
  20217. if (unlikely(err)) {
  20218. WL_ERR(("wsec clear failed \n"));
  20219. }
  20220. err = wldev_iovar_setint(dev, "auth", 0);
  20221. if (unlikely(err)) {
  20222. WL_ERR(("auth clear failed \n"));
  20223. }
  20224. err = wldev_iovar_setint(dev, "wpa_auth", WPA_AUTH_DISABLED);
  20225. if (unlikely(err)) {
  20226. WL_ERR(("wpa_auth clear failed \n"));
  20227. }
  20228. }
  20229. #ifdef WL_CFG80211_P2P_DEV_IF
  20230. void wl_cfg80211_del_p2p_wdev(struct net_device *dev)
  20231. {
  20232. struct bcm_cfg80211 *cfg = wl_get_cfg(dev);
  20233. struct wireless_dev *wdev = NULL;
  20234. WL_DBG(("Enter \n"));
  20235. if (!cfg) {
  20236. WL_ERR(("Invalid Ptr\n"));
  20237. return;
  20238. } else {
  20239. wdev = cfg->p2p_wdev;
  20240. }
  20241. if (wdev && cfg->down_disc_if) {
  20242. wl_cfgp2p_del_p2p_disc_if(wdev, cfg);
  20243. cfg->down_disc_if = FALSE;
  20244. }
  20245. }
  20246. #endif /* WL_CFG80211_P2P_DEV_IF */
  20247. #ifdef GTK_OFFLOAD_SUPPORT
  20248. #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 1, 0))
  20249. static s32
  20250. wl_cfg80211_set_rekey_data(struct wiphy *wiphy, struct net_device *dev,
  20251. struct cfg80211_gtk_rekey_data *data)
  20252. {
  20253. struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
  20254. s32 err = 0;
  20255. gtk_keyinfo_t keyinfo;
  20256. WL_DBG(("Enter\n"));
  20257. if (data == NULL || cfg->p2p_net == dev) {
  20258. WL_ERR(("data is NULL or wrong net device\n"));
  20259. return -EINVAL;
  20260. }
  20261. prhex("kck", (const u8 *) (data->kck), RSN_KCK_LENGTH);
  20262. prhex("kek", (const u8 *) (data->kek), RSN_KEK_LENGTH);
  20263. prhex("replay_ctr", (const u8 *) (data->replay_ctr), RSN_REPLAY_LEN);
  20264. bcopy(data->kck, keyinfo.KCK, RSN_KCK_LENGTH);
  20265. bcopy(data->kek, keyinfo.KEK, RSN_KEK_LENGTH);
  20266. bcopy(data->replay_ctr, keyinfo.ReplayCounter, RSN_REPLAY_LEN);
  20267. if ((err = wldev_iovar_setbuf(dev, "gtk_key_info", &keyinfo, sizeof(keyinfo),
  20268. cfg->ioctl_buf, WLC_IOCTL_SMLEN, &cfg->ioctl_buf_sync)) < 0) {
  20269. WL_ERR(("seting gtk_key_info failed code=%d\n", err));
  20270. return err;
  20271. }
  20272. WL_DBG(("Exit\n"));
  20273. return err;
  20274. }
  20275. #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 1, 0) */
  20276. #endif /* GTK_OFFLOAD_SUPPORT */
  20277. #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 13, 0))
  20278. static int wl_cfg80211_set_pmk(struct wiphy *wiphy, struct net_device *dev,
  20279. const struct cfg80211_pmk_conf *conf)
  20280. {
  20281. int ret = 0;
  20282. wsec_pmk_t pmk;
  20283. struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
  20284. struct wl_security *sec;
  20285. s32 bssidx;
  20286. pmk.key_len = conf->pmk_len;
  20287. if (pmk.key_len > sizeof(pmk.key)) {
  20288. ret = -EINVAL;
  20289. return ret;
  20290. }
  20291. pmk.flags = 0;
  20292. ret = memcpy_s(&pmk.key, sizeof(pmk.key), conf->pmk, conf->pmk_len);
  20293. if (ret) {
  20294. ret = -EINVAL;
  20295. return ret;
  20296. }
  20297. if ((bssidx = wl_get_bssidx_by_wdev(cfg, dev->ieee80211_ptr)) < 0) {
  20298. WL_ERR(("Find index failed\n"));
  20299. ret = -EINVAL;
  20300. return ret;
  20301. }
  20302. sec = wl_read_prof(cfg, dev, WL_PROF_SEC);
  20303. if ((sec->wpa_auth == WLAN_AKM_SUITE_8021X) ||
  20304. (sec->wpa_auth == WL_AKM_SUITE_SHA256_1X)) {
  20305. ret = wldev_iovar_setbuf_bsscfg(dev, "okc_info_pmk", pmk.key, pmk.key_len,
  20306. cfg->ioctl_buf, WLC_IOCTL_SMLEN, bssidx, &cfg->ioctl_buf_sync);
  20307. if (ret) {
  20308. /* could fail in case that 'okc' is not supported */
  20309. WL_INFORM_MEM(("okc_info_pmk failed, err=%d (ignore)\n", ret));
  20310. }
  20311. }
  20312. ret = wldev_ioctl_set(dev, WLC_SET_WSEC_PMK, &pmk, sizeof(pmk));
  20313. if (ret) {
  20314. WL_ERR(("wl_cfg80211_set_pmk error:%d", ret));
  20315. ret = -EINVAL;
  20316. return ret;
  20317. }
  20318. return 0;
  20319. }
  20320. static int wl_cfg80211_del_pmk(struct wiphy *wiphy, struct net_device *dev,
  20321. const u8 *aa)
  20322. {
  20323. int err = BCME_OK;
  20324. struct cfg80211_pmksa pmksa;
  20325. /* build up cfg80211_pmksa structure to use existing wl_cfg80211_update_pmksa API */
  20326. bzero(&pmksa, sizeof(pmksa));
  20327. pmksa.bssid = aa;
  20328. err = wl_cfg80211_update_pmksa(wiphy, dev, &pmksa, FALSE);
  20329. if (err) {
  20330. WL_ERR(("wl_cfg80211_update_pmksa err:%d\n", err));
  20331. err = -EINVAL;
  20332. }
  20333. return err;
  20334. }
  20335. #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(4, 13, 0) */
  20336. #if defined(WL_SUPPORT_AUTO_CHANNEL)
  20337. int
  20338. wl_cfg80211_set_spect(struct net_device *dev, int spect)
  20339. {
  20340. int wlc_down = 1;
  20341. int wlc_up = 1;
  20342. int err = BCME_OK;
  20343. err = wldev_ioctl_set(dev, WLC_DOWN, &wlc_down, sizeof(wlc_down));
  20344. if (err) {
  20345. WL_ERR(("%s: WLC_DOWN failed: code: %d\n", __func__, err));
  20346. return err;
  20347. }
  20348. err = wldev_ioctl_set(dev, WLC_SET_SPECT_MANAGMENT, &spect, sizeof(spect));
  20349. if (err) {
  20350. WL_ERR(("%s: error setting spect: code: %d\n", __func__, err));
  20351. return err;
  20352. }
  20353. err = wldev_ioctl_set(dev, WLC_UP, &wlc_up, sizeof(wlc_up));
  20354. if (err) {
  20355. WL_ERR(("%s: WLC_UP failed: code: %d\n", __func__, err));
  20356. return err;
  20357. }
  20358. return err;
  20359. }
  20360. int
  20361. wl_cfg80211_get_sta_channel(struct bcm_cfg80211 *cfg)
  20362. {
  20363. int channel = 0;
  20364. if (wl_get_drv_status(cfg, CONNECTED, bcmcfg_to_prmry_ndev(cfg))) {
  20365. channel = cfg->channel;
  20366. }
  20367. return channel;
  20368. }
  20369. #endif /* WL_SUPPORT_AUTO_CHANNEL */
  20370. u64
  20371. wl_cfg80211_get_new_roc_id(struct bcm_cfg80211 *cfg)
  20372. {
  20373. u64 id = 0;
  20374. id = ++cfg->last_roc_id;
  20375. #ifdef P2P_LISTEN_OFFLOADING
  20376. if (id == P2PO_COOKIE) {
  20377. id = ++cfg->last_roc_id;
  20378. }
  20379. #endif /* P2P_LISTEN_OFFLOADING */
  20380. if (id == 0)
  20381. id = ++cfg->last_roc_id;
  20382. return id;
  20383. }
  20384. #ifdef WLTDLS
  20385. s32
  20386. wl_cfg80211_tdls_config(struct bcm_cfg80211 *cfg, enum wl_tdls_config state, bool auto_mode)
  20387. {
  20388. struct net_device *ndev = bcmcfg_to_prmry_ndev(cfg);
  20389. int err = 0;
  20390. struct net_info *iter, *next;
  20391. int update_reqd = 0;
  20392. int enable = 0;
  20393. dhd_pub_t *dhdp;
  20394. dhdp = (dhd_pub_t *)(cfg->pub);
  20395. /*
  20396. * TDLS need to be enabled only if we have a single STA/GC
  20397. * connection.
  20398. */
  20399. WL_DBG(("Enter state:%d\n", state));
  20400. if (!cfg->tdls_supported) {
  20401. /* FW doesn't support tdls. Do nothing */
  20402. return -ENODEV;
  20403. }
  20404. /* Protect tdls config session */
  20405. mutex_lock(&cfg->tdls_sync);
  20406. if (state == TDLS_STATE_TEARDOWN) {
  20407. /* Host initiated TDLS tear down */
  20408. err = dhd_tdls_enable(ndev, false, auto_mode, NULL);
  20409. goto exit;
  20410. } else if ((state == TDLS_STATE_AP_CREATE) ||
  20411. (state == TDLS_STATE_NMI_CREATE)) {
  20412. /* We don't support tdls while AP/GO/NAN is operational */
  20413. update_reqd = true;
  20414. enable = false;
  20415. } else if ((state == TDLS_STATE_CONNECT) || (state == TDLS_STATE_IF_CREATE)) {
  20416. if (wl_get_drv_status_all(cfg,
  20417. CONNECTED) >= TDLS_MAX_IFACE_FOR_ENABLE) {
  20418. /* For STA/GC connect command request, disable
  20419. * tdls if we have any concurrent interfaces
  20420. * operational.
  20421. */
  20422. WL_DBG(("Interface limit restriction. disable tdls.\n"));
  20423. update_reqd = true;
  20424. enable = false;
  20425. }
  20426. } else if ((state == TDLS_STATE_DISCONNECT) ||
  20427. (state == TDLS_STATE_AP_DELETE) ||
  20428. (state == TDLS_STATE_SETUP) ||
  20429. (state == TDLS_STATE_IF_DELETE)) {
  20430. /* Enable back the tdls connection only if we have less than
  20431. * or equal to a single STA/GC connection.
  20432. */
  20433. if (wl_get_drv_status_all(cfg,
  20434. CONNECTED) == 0) {
  20435. /* If there are no interfaces connected, enable tdls */
  20436. update_reqd = true;
  20437. enable = true;
  20438. } else if (wl_get_drv_status_all(cfg,
  20439. CONNECTED) == TDLS_MAX_IFACE_FOR_ENABLE) {
  20440. /* We have one interface in CONNECTED state.
  20441. * Verify whether its a STA interface before
  20442. * we enable back tdls.
  20443. */
  20444. GCC_DIAGNOSTIC_PUSH_SUPPRESS_CAST();
  20445. for_each_ndev(cfg, iter, next) {
  20446. GCC_DIAGNOSTIC_POP();
  20447. if ((iter->ndev) && (wl_get_drv_status(cfg, CONNECTED, ndev)) &&
  20448. (ndev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION)) {
  20449. WL_DBG(("Non STA iface operational. cfg_iftype:%d"
  20450. " Can't enable tdls.\n",
  20451. ndev->ieee80211_ptr->iftype));
  20452. err = -ENOTSUPP;
  20453. goto exit;
  20454. }
  20455. }
  20456. /* No AP/GO found. Enable back tdls */
  20457. update_reqd = true;
  20458. enable = true;
  20459. } else {
  20460. WL_DBG(("Concurrent connection mode. Can't enable tdls. \n"));
  20461. err = -ENOTSUPP;
  20462. goto exit;
  20463. }
  20464. } else {
  20465. WL_ERR(("Unknown tdls state:%d \n", state));
  20466. err = -EINVAL;
  20467. goto exit;
  20468. }
  20469. if (update_reqd == true) {
  20470. if (dhdp->tdls_enable == enable) {
  20471. WL_DBG(("No change in tdls state. Do nothing."
  20472. " tdls_enable:%d\n", enable));
  20473. goto exit;
  20474. }
  20475. err = wldev_iovar_setint(ndev, "tdls_enable", enable);
  20476. if (unlikely(err)) {
  20477. WL_ERR(("tdls_enable setting failed. err:%d\n", err));
  20478. goto exit;
  20479. } else {
  20480. WL_INFORM_MEM(("tdls_enable %d state:%d\n", enable, state));
  20481. /* Update the dhd state variable to be in sync */
  20482. dhdp->tdls_enable = enable;
  20483. if (state == TDLS_STATE_SETUP) {
  20484. /* For host initiated setup, apply TDLS params
  20485. * Don't propagate errors up for param config
  20486. * failures
  20487. */
  20488. dhd_tdls_enable(ndev, true, auto_mode, NULL);
  20489. }
  20490. }
  20491. } else {
  20492. WL_DBG(("Skip tdls config. state:%d update_reqd:%d "
  20493. "current_status:%d \n",
  20494. state, update_reqd, dhdp->tdls_enable));
  20495. }
  20496. exit:
  20497. if (err) {
  20498. wl_flush_fw_log_buffer(ndev, FW_LOGSET_MASK_ALL);
  20499. }
  20500. mutex_unlock(&cfg->tdls_sync);
  20501. return err;
  20502. }
  20503. #endif /* WLTDLS */
  20504. struct net_device* wl_get_ap_netdev(struct bcm_cfg80211 *cfg, char *ifname)
  20505. {
  20506. struct net_info *iter, *next;
  20507. struct net_device *ndev = NULL;
  20508. GCC_DIAGNOSTIC_PUSH_SUPPRESS_CAST();
  20509. for_each_ndev(cfg, iter, next) {
  20510. GCC_DIAGNOSTIC_POP();
  20511. if (iter->ndev) {
  20512. if (strncmp(iter->ndev->name, ifname, IFNAMSIZ) == 0) {
  20513. if (iter->ndev->ieee80211_ptr->iftype == NL80211_IFTYPE_AP) {
  20514. ndev = iter->ndev;
  20515. break;
  20516. }
  20517. }
  20518. }
  20519. }
  20520. return ndev;
  20521. }
  20522. struct net_device*
  20523. wl_get_netdev_by_name(struct bcm_cfg80211 *cfg, char *ifname)
  20524. {
  20525. struct net_info *iter, *next;
  20526. struct net_device *ndev = NULL;
  20527. GCC_DIAGNOSTIC_PUSH_SUPPRESS_CAST();
  20528. for_each_ndev(cfg, iter, next) {
  20529. GCC_DIAGNOSTIC_POP();
  20530. if (iter->ndev) {
  20531. if (strncmp(iter->ndev->name, ifname, IFNAMSIZ) == 0) {
  20532. ndev = iter->ndev;
  20533. break;
  20534. }
  20535. }
  20536. }
  20537. return ndev;
  20538. }
  20539. #ifdef SUPPORT_AP_HIGHER_BEACONRATE
  20540. #define WLC_RATE_FLAG 0x80
  20541. #define RATE_MASK 0x7f
  20542. int wl_set_ap_beacon_rate(struct net_device *dev, int val, char *ifname)
  20543. {
  20544. struct bcm_cfg80211 *cfg = wl_get_cfg(dev);
  20545. dhd_pub_t *dhdp;
  20546. wl_rateset_args_t rs;
  20547. int error = BCME_ERROR, i;
  20548. struct net_device *ndev = NULL;
  20549. dhdp = (dhd_pub_t *)(cfg->pub);
  20550. if (dhdp && !(dhdp->op_mode & DHD_FLAG_HOSTAP_MODE)) {
  20551. WL_ERR(("Not Hostapd mode\n"));
  20552. return BCME_NOTAP;
  20553. }
  20554. ndev = wl_get_ap_netdev(cfg, ifname);
  20555. if (ndev == NULL) {
  20556. WL_ERR(("No softAP interface named %s\n", ifname));
  20557. return BCME_NOTAP;
  20558. }
  20559. bzero(&rs, sizeof(wl_rateset_args_t));
  20560. error = wldev_iovar_getbuf(ndev, "rateset", NULL, 0,
  20561. &rs, sizeof(wl_rateset_args_t), NULL);
  20562. if (error < 0) {
  20563. WL_ERR(("get rateset failed = %d\n", error));
  20564. return error;
  20565. }
  20566. if (rs.count < 1) {
  20567. WL_ERR(("Failed to get rate count\n"));
  20568. return BCME_ERROR;
  20569. }
  20570. /* Host delivers target rate in the unit of 500kbps */
  20571. /* To make it to 1mbps unit, atof should be implemented for 5.5mbps basic rate */
  20572. for (i = 0; i < rs.count && i < WL_NUMRATES; i++)
  20573. if (rs.rates[i] & WLC_RATE_FLAG)
  20574. if ((rs.rates[i] & RATE_MASK) == val)
  20575. break;
  20576. /* Valid rate has been delivered as an argument */
  20577. if (i < rs.count && i < WL_NUMRATES) {
  20578. error = wldev_iovar_setint(ndev, "force_bcn_rspec", val);
  20579. if (error < 0) {
  20580. WL_ERR(("set beacon rate failed = %d\n", error));
  20581. return BCME_ERROR;
  20582. }
  20583. } else {
  20584. WL_ERR(("Rate is invalid"));
  20585. return BCME_BADARG;
  20586. }
  20587. return BCME_OK;
  20588. }
  20589. int
  20590. wl_get_ap_basic_rate(struct net_device *dev, char* command, char *ifname, int total_len)
  20591. {
  20592. struct bcm_cfg80211 *cfg = wl_get_cfg(dev);
  20593. dhd_pub_t *dhdp;
  20594. wl_rateset_args_t rs;
  20595. int error = BCME_ERROR;
  20596. int i, bytes_written = 0;
  20597. struct net_device *ndev = NULL;
  20598. dhdp = (dhd_pub_t *)(cfg->pub);
  20599. if (!(dhdp->op_mode & DHD_FLAG_HOSTAP_MODE)) {
  20600. WL_ERR(("Not Hostapd mode\n"));
  20601. return BCME_NOTAP;
  20602. }
  20603. ndev = wl_get_ap_netdev(cfg, ifname);
  20604. if (ndev == NULL) {
  20605. WL_ERR(("No softAP interface named %s\n", ifname));
  20606. return BCME_NOTAP;
  20607. }
  20608. bzero(&rs, sizeof(wl_rateset_args_t));
  20609. error = wldev_iovar_getbuf(ndev, "rateset", NULL, 0,
  20610. &rs, sizeof(wl_rateset_args_t), NULL);
  20611. if (error < 0) {
  20612. WL_ERR(("get rateset failed = %d\n", error));
  20613. return error;
  20614. }
  20615. if (rs.count < 1) {
  20616. WL_ERR(("Failed to get rate count\n"));
  20617. return BCME_ERROR;
  20618. }
  20619. /* Delivers basic rate in the unit of 500kbps to host */
  20620. for (i = 0; i < rs.count && i < WL_NUMRATES; i++)
  20621. if (rs.rates[i] & WLC_RATE_FLAG)
  20622. bytes_written += snprintf(command + bytes_written, total_len,
  20623. "%d ", rs.rates[i] & RATE_MASK);
  20624. /* Remove last space in the command buffer */
  20625. if (bytes_written && (bytes_written < total_len)) {
  20626. command[bytes_written - 1] = '\0';
  20627. bytes_written--;
  20628. }
  20629. return bytes_written;
  20630. }
  20631. #endif /* SUPPORT_AP_HIGHER_BEACONRATE */
  20632. #ifdef SUPPORT_AP_RADIO_PWRSAVE
  20633. #define MSEC_PER_MIN (60000L)
  20634. static int
  20635. _wl_update_ap_rps_params(struct net_device *dev)
  20636. {
  20637. struct bcm_cfg80211 *cfg = NULL;
  20638. rpsnoa_iovar_params_t iovar;
  20639. u8 smbuf[WLC_IOCTL_SMLEN];
  20640. if (!dev)
  20641. return BCME_BADARG;
  20642. cfg = wl_get_cfg(dev);
  20643. bzero(&iovar, sizeof(iovar));
  20644. bzero(smbuf, sizeof(smbuf));
  20645. iovar.hdr.ver = RADIO_PWRSAVE_VERSION;
  20646. iovar.hdr.subcmd = WL_RPSNOA_CMD_PARAMS;
  20647. iovar.hdr.len = sizeof(iovar);
  20648. iovar.param->band = WLC_BAND_ALL;
  20649. iovar.param->level = cfg->ap_rps_info.level;
  20650. iovar.param->stas_assoc_check = cfg->ap_rps_info.sta_assoc_check;
  20651. iovar.param->pps = cfg->ap_rps_info.pps;
  20652. iovar.param->quiet_time = cfg->ap_rps_info.quiet_time;
  20653. if (wldev_iovar_setbuf(dev, "rpsnoa", &iovar, sizeof(iovar),
  20654. smbuf, sizeof(smbuf), NULL)) {
  20655. WL_ERR(("Failed to set rpsnoa params"));
  20656. return BCME_ERROR;
  20657. }
  20658. return BCME_OK;
  20659. }
  20660. int
  20661. wl_get_ap_rps(struct net_device *dev, char* command, char *ifname, int total_len)
  20662. {
  20663. struct bcm_cfg80211 *cfg = wl_get_cfg(dev);
  20664. dhd_pub_t *dhdp;
  20665. int error = BCME_ERROR;
  20666. int bytes_written = 0;
  20667. struct net_device *ndev = NULL;
  20668. rpsnoa_iovar_status_t iovar;
  20669. u8 smbuf[WLC_IOCTL_SMLEN];
  20670. u32 chanspec = 0;
  20671. u8 idx = 0;
  20672. u16 state;
  20673. u32 sleep;
  20674. u32 time_since_enable;
  20675. dhdp = (dhd_pub_t *)(cfg->pub);
  20676. if (!dhdp) {
  20677. error = BCME_NOTUP;
  20678. goto fail;
  20679. }
  20680. if (!(dhdp->op_mode & DHD_FLAG_HOSTAP_MODE)) {
  20681. WL_ERR(("Not Hostapd mode\n"));
  20682. error = BCME_NOTAP;
  20683. goto fail;
  20684. }
  20685. ndev = wl_get_ap_netdev(cfg, ifname);
  20686. if (ndev == NULL) {
  20687. WL_ERR(("No softAP interface named %s\n", ifname));
  20688. error = BCME_NOTAP;
  20689. goto fail;
  20690. }
  20691. bzero(&iovar, sizeof(iovar));
  20692. bzero(smbuf, sizeof(smbuf));
  20693. iovar.hdr.ver = RADIO_PWRSAVE_VERSION;
  20694. iovar.hdr.subcmd = WL_RPSNOA_CMD_STATUS;
  20695. iovar.hdr.len = sizeof(iovar);
  20696. iovar.stats->band = WLC_BAND_ALL;
  20697. error = wldev_iovar_getbuf(ndev, "rpsnoa", &iovar, sizeof(iovar),
  20698. smbuf, sizeof(smbuf), NULL);
  20699. if (error < 0) {
  20700. WL_ERR(("get ap radio pwrsave failed = %d\n", error));
  20701. goto fail;
  20702. }
  20703. /* RSDB event doesn't seem to be handled correctly.
  20704. * So check chanspec of AP directly from the firmware
  20705. */
  20706. error = wldev_iovar_getint(ndev, "chanspec", (s32 *)&chanspec);
  20707. if (error < 0) {
  20708. WL_ERR(("get chanspec from AP failed = %d\n", error));
  20709. goto fail;
  20710. }
  20711. chanspec = wl_chspec_driver_to_host(chanspec);
  20712. if (CHSPEC_IS2G(chanspec))
  20713. idx = 0;
  20714. else if (CHSPEC_IS5G(chanspec))
  20715. idx = 1;
  20716. else {
  20717. error = BCME_BADCHAN;
  20718. goto fail;
  20719. }
  20720. state = ((rpsnoa_iovar_status_t *)smbuf)->stats[idx].state;
  20721. sleep = ((rpsnoa_iovar_status_t *)smbuf)->stats[idx].sleep_dur;
  20722. time_since_enable = ((rpsnoa_iovar_status_t *)smbuf)->stats[idx].sleep_avail_dur;
  20723. /* Conver ms to minute, round down only */
  20724. sleep = DIV_U64_BY_U32(sleep, MSEC_PER_MIN);
  20725. time_since_enable = DIV_U64_BY_U32(time_since_enable, MSEC_PER_MIN);
  20726. bytes_written += snprintf(command + bytes_written, total_len,
  20727. "state=%d sleep=%d time_since_enable=%d", state, sleep, time_since_enable);
  20728. error = bytes_written;
  20729. fail:
  20730. return error;
  20731. }
  20732. int
  20733. wl_set_ap_rps(struct net_device *dev, bool enable, char *ifname)
  20734. {
  20735. struct bcm_cfg80211 *cfg = wl_get_cfg(dev);
  20736. dhd_pub_t *dhdp;
  20737. struct net_device *ndev = NULL;
  20738. rpsnoa_iovar_t iovar;
  20739. u8 smbuf[WLC_IOCTL_SMLEN];
  20740. int ret = BCME_OK;
  20741. dhdp = (dhd_pub_t *)(cfg->pub);
  20742. if (!dhdp) {
  20743. ret = BCME_NOTUP;
  20744. goto exit;
  20745. }
  20746. if (!(dhdp->op_mode & DHD_FLAG_HOSTAP_MODE)) {
  20747. WL_ERR(("Not Hostapd mode\n"));
  20748. ret = BCME_NOTAP;
  20749. goto exit;
  20750. }
  20751. ndev = wl_get_ap_netdev(cfg, ifname);
  20752. if (ndev == NULL) {
  20753. WL_ERR(("No softAP interface named %s\n", ifname));
  20754. ret = BCME_NOTAP;
  20755. goto exit;
  20756. }
  20757. if (cfg->ap_rps_info.enable != enable) {
  20758. cfg->ap_rps_info.enable = enable;
  20759. if (enable) {
  20760. ret = _wl_update_ap_rps_params(ndev);
  20761. if (ret) {
  20762. WL_ERR(("Filed to update rpsnoa params\n"));
  20763. goto exit;
  20764. }
  20765. }
  20766. bzero(&iovar, sizeof(iovar));
  20767. bzero(smbuf, sizeof(smbuf));
  20768. iovar.hdr.ver = RADIO_PWRSAVE_VERSION;
  20769. iovar.hdr.subcmd = WL_RPSNOA_CMD_ENABLE;
  20770. iovar.hdr.len = sizeof(iovar);
  20771. iovar.data->band = WLC_BAND_ALL;
  20772. iovar.data->value = (int16)enable;
  20773. ret = wldev_iovar_setbuf(ndev, "rpsnoa", &iovar, sizeof(iovar),
  20774. smbuf, sizeof(smbuf), NULL);
  20775. if (ret) {
  20776. WL_ERR(("Failed to enable AP radio power save"));
  20777. goto exit;
  20778. }
  20779. cfg->ap_rps_info.enable = enable;
  20780. }
  20781. exit:
  20782. return ret;
  20783. }
  20784. int
  20785. wl_update_ap_rps_params(struct net_device *dev, ap_rps_info_t* rps, char *ifname)
  20786. {
  20787. struct bcm_cfg80211 *cfg = wl_get_cfg(dev);
  20788. dhd_pub_t *dhdp;
  20789. struct net_device *ndev = NULL;
  20790. dhdp = (dhd_pub_t *)(cfg->pub);
  20791. if (!dhdp)
  20792. return BCME_NOTUP;
  20793. if (!(dhdp->op_mode & DHD_FLAG_HOSTAP_MODE)) {
  20794. WL_ERR(("Not Hostapd mode\n"));
  20795. return BCME_NOTAP;
  20796. }
  20797. ndev = wl_get_ap_netdev(cfg, ifname);
  20798. if (ndev == NULL) {
  20799. WL_ERR(("No softAP interface named %s\n", ifname));
  20800. return BCME_NOTAP;
  20801. }
  20802. if (!rps)
  20803. return BCME_BADARG;
  20804. if (rps->pps < RADIO_PWRSAVE_PPS_MIN)
  20805. return BCME_BADARG;
  20806. if (rps->level < RADIO_PWRSAVE_LEVEL_MIN ||
  20807. rps->level > RADIO_PWRSAVE_LEVEL_MAX)
  20808. return BCME_BADARG;
  20809. if (rps->quiet_time < RADIO_PWRSAVE_QUIETTIME_MIN)
  20810. return BCME_BADARG;
  20811. if (rps->sta_assoc_check > RADIO_PWRSAVE_ASSOCCHECK_MAX ||
  20812. rps->sta_assoc_check < RADIO_PWRSAVE_ASSOCCHECK_MIN)
  20813. return BCME_BADARG;
  20814. cfg->ap_rps_info.pps = rps->pps;
  20815. cfg->ap_rps_info.level = rps->level;
  20816. cfg->ap_rps_info.quiet_time = rps->quiet_time;
  20817. cfg->ap_rps_info.sta_assoc_check = rps->sta_assoc_check;
  20818. if (cfg->ap_rps_info.enable) {
  20819. if (_wl_update_ap_rps_params(ndev)) {
  20820. WL_ERR(("Failed to update rpsnoa params"));
  20821. return BCME_ERROR;
  20822. }
  20823. }
  20824. return BCME_OK;
  20825. }
  20826. void
  20827. wl_cfg80211_init_ap_rps(struct bcm_cfg80211 *cfg)
  20828. {
  20829. cfg->ap_rps_info.enable = FALSE;
  20830. cfg->ap_rps_info.sta_assoc_check = RADIO_PWRSAVE_STAS_ASSOC_CHECK;
  20831. cfg->ap_rps_info.pps = RADIO_PWRSAVE_PPS;
  20832. cfg->ap_rps_info.quiet_time = RADIO_PWRSAVE_QUIET_TIME;
  20833. cfg->ap_rps_info.level = RADIO_PWRSAVE_LEVEL;
  20834. }
  20835. #endif /* SUPPORT_AP_RADIO_PWRSAVE */
  20836. int
  20837. wl_cfg80211_iface_count(struct net_device *dev)
  20838. {
  20839. struct bcm_cfg80211 *cfg = wl_get_cfg(dev);
  20840. struct net_info *iter, *next;
  20841. int iface_count = 0;
  20842. /* Return the count of network interfaces (skip netless p2p discovery
  20843. * interface)
  20844. */
  20845. GCC_DIAGNOSTIC_PUSH_SUPPRESS_CAST();
  20846. for_each_ndev(cfg, iter, next) {
  20847. GCC_DIAGNOSTIC_POP();
  20848. if (iter->ndev) {
  20849. iface_count++;
  20850. }
  20851. }
  20852. return iface_count;
  20853. }
  20854. #ifdef WBTEXT
  20855. static bool wl_cfg80211_wbtext_check_bssid_list(struct bcm_cfg80211 *cfg, struct ether_addr *ea)
  20856. {
  20857. wl_wbtext_bssid_t *bssid = NULL;
  20858. GCC_DIAGNOSTIC_PUSH_SUPPRESS_CAST();
  20859. /* check duplicate */
  20860. list_for_each_entry(bssid, &cfg->wbtext_bssid_list, list) {
  20861. GCC_DIAGNOSTIC_POP();
  20862. if (!memcmp(bssid->ea.octet, ea, ETHER_ADDR_LEN)) {
  20863. return FALSE;
  20864. }
  20865. }
  20866. return TRUE;
  20867. }
  20868. static bool wl_cfg80211_wbtext_add_bssid_list(struct bcm_cfg80211 *cfg, struct ether_addr *ea)
  20869. {
  20870. wl_wbtext_bssid_t *bssid = NULL;
  20871. char eabuf[ETHER_ADDR_STR_LEN];
  20872. bssid = (wl_wbtext_bssid_t *)MALLOC(cfg->osh, sizeof(wl_wbtext_bssid_t));
  20873. if (bssid == NULL) {
  20874. WL_ERR(("alloc failed\n"));
  20875. return FALSE;
  20876. }
  20877. memcpy(bssid->ea.octet, ea, ETHER_ADDR_LEN);
  20878. INIT_LIST_HEAD(&bssid->list);
  20879. list_add_tail(&bssid->list, &cfg->wbtext_bssid_list);
  20880. WL_DBG(("add wbtext bssid : %s\n", bcm_ether_ntoa(ea, eabuf)));
  20881. return TRUE;
  20882. }
  20883. static void wl_cfg80211_wbtext_clear_bssid_list(struct bcm_cfg80211 *cfg)
  20884. {
  20885. wl_wbtext_bssid_t *bssid = NULL;
  20886. char eabuf[ETHER_ADDR_STR_LEN];
  20887. while (!list_empty(&cfg->wbtext_bssid_list)) {
  20888. GCC_DIAGNOSTIC_PUSH_SUPPRESS_CAST();
  20889. bssid = list_entry(cfg->wbtext_bssid_list.next, wl_wbtext_bssid_t, list);
  20890. GCC_DIAGNOSTIC_POP();
  20891. if (bssid) {
  20892. WL_DBG(("clear wbtext bssid : %s\n", bcm_ether_ntoa(&bssid->ea, eabuf)));
  20893. list_del(&bssid->list);
  20894. MFREE(cfg->osh, bssid, sizeof(wl_wbtext_bssid_t));
  20895. }
  20896. }
  20897. }
  20898. static void wl_cfg80211_wbtext_update_rcc(struct bcm_cfg80211 *cfg, struct net_device *dev)
  20899. {
  20900. struct wl_connect_info *conn_info = wl_to_conn(cfg);
  20901. bcm_tlv_t * cap_ie = NULL;
  20902. bool req_sent = FALSE;
  20903. struct wl_profile *profile;
  20904. WL_DBG(("Enter\n"));
  20905. profile = wl_get_profile_by_netdev(cfg, dev);
  20906. if (!profile) {
  20907. WL_ERR(("no profile exists\n"));
  20908. return;
  20909. }
  20910. if (wl_cfg80211_wbtext_check_bssid_list(cfg,
  20911. (struct ether_addr *)&profile->bssid) == FALSE) {
  20912. WL_DBG(("already updated\n"));
  20913. return;
  20914. }
  20915. /* first, check NBR bit in RRM IE */
  20916. if ((cap_ie = bcm_parse_tlvs(conn_info->resp_ie, conn_info->resp_ie_len,
  20917. DOT11_MNG_RRM_CAP_ID)) != NULL) {
  20918. if (isset(cap_ie->data, DOT11_RRM_CAP_NEIGHBOR_REPORT)) {
  20919. WL_DBG(("sending neighbor report\n"));
  20920. req_sent = wl_cfg80211_wbtext_send_nbr_req(cfg, dev, profile);
  20921. }
  20922. }
  20923. /* if RRM nbr was not supported, check BTM bit in extend cap. IE */
  20924. if (!req_sent) {
  20925. if ((cap_ie = bcm_parse_tlvs(conn_info->resp_ie, conn_info->resp_ie_len,
  20926. DOT11_MNG_EXT_CAP_ID)) != NULL) {
  20927. if (cap_ie->len >= DOT11_EXTCAP_LEN_BSSTRANS &&
  20928. isset(cap_ie->data, DOT11_EXT_CAP_BSSTRANS_MGMT)) {
  20929. WL_DBG(("sending btm query\n"));
  20930. wl_cfg80211_wbtext_send_btm_query(cfg, dev, profile);
  20931. }
  20932. }
  20933. }
  20934. }
  20935. static bool wl_cfg80211_wbtext_send_nbr_req(struct bcm_cfg80211 *cfg, struct net_device *dev,
  20936. struct wl_profile *profile)
  20937. {
  20938. int error = -1;
  20939. char *smbuf = NULL;
  20940. struct wl_connect_info *conn_info = wl_to_conn(cfg);
  20941. bcm_tlv_t * rrm_cap_ie = NULL;
  20942. wlc_ssid_t *ssid = NULL;
  20943. bool ret = FALSE;
  20944. WL_DBG(("Enter\n"));
  20945. /* check RRM nbr bit in extend cap. IE of assoc response */
  20946. if ((rrm_cap_ie = bcm_parse_tlvs(conn_info->resp_ie, conn_info->resp_ie_len,
  20947. DOT11_MNG_RRM_CAP_ID)) != NULL) {
  20948. if (!isset(rrm_cap_ie->data, DOT11_RRM_CAP_NEIGHBOR_REPORT)) {
  20949. WL_DBG(("AP doesn't support neighbor report\n"));
  20950. return FALSE;
  20951. }
  20952. }
  20953. smbuf = (char *)MALLOCZ(cfg->osh, WLC_IOCTL_MAXLEN);
  20954. if (smbuf == NULL) {
  20955. WL_ERR(("failed to allocated memory\n"));
  20956. goto nbr_req_out;
  20957. }
  20958. ssid = (wlc_ssid_t *)MALLOCZ(cfg->osh, sizeof(wlc_ssid_t));
  20959. if (ssid == NULL) {
  20960. WL_ERR(("failed to allocated memory\n"));
  20961. goto nbr_req_out;
  20962. }
  20963. ssid->SSID_len = MIN(profile->ssid.SSID_len, DOT11_MAX_SSID_LEN);
  20964. memcpy(ssid->SSID, profile->ssid.SSID, ssid->SSID_len);
  20965. error = wldev_iovar_setbuf(dev, "rrm_nbr_req", ssid,
  20966. sizeof(wlc_ssid_t), smbuf, WLC_IOCTL_MAXLEN, NULL);
  20967. if (error == BCME_OK) {
  20968. ret = wl_cfg80211_wbtext_add_bssid_list(cfg,
  20969. (struct ether_addr *)&profile->bssid);
  20970. } else {
  20971. WL_ERR(("failed to send neighbor report request, error=%d\n", error));
  20972. }
  20973. nbr_req_out:
  20974. if (ssid) {
  20975. MFREE(cfg->osh, ssid, sizeof(wlc_ssid_t));
  20976. }
  20977. if (smbuf) {
  20978. MFREE(cfg->osh, smbuf, WLC_IOCTL_MAXLEN);
  20979. }
  20980. return ret;
  20981. }
  20982. static bool wl_cfg80211_wbtext_send_btm_query(struct bcm_cfg80211 *cfg, struct net_device *dev,
  20983. struct wl_profile *profile)
  20984. {
  20985. int error = -1;
  20986. bool ret = FALSE;
  20987. wl_bsstrans_query_t btq;
  20988. WL_DBG(("Enter\n"));
  20989. bzero(&btq, sizeof(wl_bsstrans_query_t));
  20990. btq.version = WL_BSSTRANS_QUERY_VERSION_1;
  20991. error = wldev_iovar_setbuf(dev, "wnm_bsstrans_query", &btq,
  20992. sizeof(btq), cfg->ioctl_buf, WLC_IOCTL_SMLEN, &cfg->ioctl_buf_sync);
  20993. if (error == BCME_OK) {
  20994. ret = wl_cfg80211_wbtext_add_bssid_list(cfg,
  20995. (struct ether_addr *)&profile->bssid);
  20996. } else {
  20997. WL_ERR(("wl_cfg80211_wbtext_send_btm_query: failed to set BTM query,"
  20998. " error=%d\n", error));
  20999. }
  21000. return ret;
  21001. }
  21002. static void wl_cfg80211_wbtext_set_wnm_maxidle(struct bcm_cfg80211 *cfg, struct net_device *dev)
  21003. {
  21004. keepalives_max_idle_t keepalive = {0, 0, 0, 0};
  21005. s32 bssidx, error;
  21006. int wnm_maxidle = 0;
  21007. struct wl_connect_info *conn_info = wl_to_conn(cfg);
  21008. /* AP supports wnm max idle ? */
  21009. if (bcm_parse_tlvs(conn_info->resp_ie, conn_info->resp_ie_len,
  21010. DOT11_MNG_BSS_MAX_IDLE_PERIOD_ID) != NULL) {
  21011. error = wldev_iovar_getint(dev, "wnm_maxidle", &wnm_maxidle);
  21012. if (error < 0) {
  21013. WL_ERR(("failed to get wnm max idle period : %d\n", error));
  21014. }
  21015. }
  21016. WL_DBG(("wnm max idle period : %d\n", wnm_maxidle));
  21017. /* if wnm maxidle has valid period, set it as keep alive */
  21018. if (wnm_maxidle > 0) {
  21019. keepalive.keepalive_count = 1;
  21020. }
  21021. if ((bssidx = wl_get_bssidx_by_wdev(cfg, dev->ieee80211_ptr)) >= 0) {
  21022. error = wldev_iovar_setbuf_bsscfg(dev, "wnm_keepalives_max_idle", &keepalive,
  21023. sizeof(keepalives_max_idle_t), cfg->ioctl_buf, WLC_IOCTL_SMLEN,
  21024. bssidx, &cfg->ioctl_buf_sync);
  21025. if (error < 0) {
  21026. WL_ERR(("set wnm_keepalives_max_idle failed : %d\n", error));
  21027. }
  21028. }
  21029. }
  21030. static int
  21031. wl_cfg80211_recv_nbr_resp(struct net_device *dev, uint8 *body, uint body_len)
  21032. {
  21033. dot11_rm_action_t *rm_rep;
  21034. bcm_tlv_t *tlvs;
  21035. uint tlv_len;
  21036. int i, error;
  21037. dot11_neighbor_rep_ie_t *nbr_rep_ie;
  21038. chanspec_t ch;
  21039. wl_roam_channel_list_t channel_list;
  21040. char iobuf[WLC_IOCTL_SMLEN];
  21041. if (body_len < DOT11_RM_ACTION_LEN) {
  21042. WL_ERR(("Received Neighbor Report frame with incorrect length %d\n",
  21043. body_len));
  21044. return BCME_ERROR;
  21045. }
  21046. rm_rep = (dot11_rm_action_t *)body;
  21047. WL_DBG(("received neighbor report (token = %d)\n", rm_rep->token));
  21048. tlvs = (bcm_tlv_t *)&rm_rep->data[0];
  21049. tlv_len = body_len - DOT11_RM_ACTION_LEN;
  21050. while (tlvs && tlvs->id == DOT11_MNG_NEIGHBOR_REP_ID) {
  21051. nbr_rep_ie = (dot11_neighbor_rep_ie_t *)tlvs;
  21052. if (nbr_rep_ie->len < DOT11_NEIGHBOR_REP_IE_FIXED_LEN) {
  21053. WL_ERR(("malformed Neighbor Report element with length %d\n",
  21054. nbr_rep_ie->len));
  21055. tlvs = bcm_next_tlv(tlvs, &tlv_len);
  21056. continue;
  21057. }
  21058. ch = CH20MHZ_CHSPEC(nbr_rep_ie->channel);
  21059. WL_DBG(("ch:%d, bssid:"MACDBG"\n",
  21060. ch, MAC2STRDBG(nbr_rep_ie->bssid.octet)));
  21061. /* get RCC list */
  21062. error = wldev_iovar_getbuf(dev, "roamscan_channels", 0, 0,
  21063. (void *)&channel_list, sizeof(channel_list), NULL);
  21064. if (error) {
  21065. WL_ERR(("Failed to get roamscan channels, error = %d\n", error));
  21066. return BCME_ERROR;
  21067. }
  21068. /* update RCC */
  21069. if (channel_list.n < MAX_ROAM_CHANNEL) {
  21070. for (i = 0; i < channel_list.n; i++) {
  21071. if (channel_list.channels[i] == ch) {
  21072. break;
  21073. }
  21074. }
  21075. if (i == channel_list.n) {
  21076. channel_list.channels[channel_list.n] = ch;
  21077. channel_list.n++;
  21078. }
  21079. }
  21080. /* set RCC list */
  21081. error = wldev_iovar_setbuf(dev, "roamscan_channels", &channel_list,
  21082. sizeof(channel_list), iobuf, sizeof(iobuf), NULL);
  21083. if (error) {
  21084. WL_DBG(("Failed to set roamscan channels, error = %d\n", error));
  21085. }
  21086. tlvs = bcm_next_tlv(tlvs, &tlv_len);
  21087. }
  21088. return BCME_OK;
  21089. }
  21090. #endif /* WBTEXT */
  21091. #ifdef SUPPORT_SET_CAC
  21092. static void
  21093. wl_cfg80211_set_cac(struct bcm_cfg80211 *cfg, int enable)
  21094. {
  21095. int ret = 0;
  21096. dhd_pub_t *dhd = (dhd_pub_t *)(cfg->pub);
  21097. WL_DBG(("cac enable %d\n", enable));
  21098. if (!dhd) {
  21099. WL_ERR(("dhd is NULL\n"));
  21100. return;
  21101. }
  21102. if ((ret = dhd_wl_ioctl_set_intiovar(dhd, "cac", enable,
  21103. WLC_SET_VAR, TRUE, 0)) < 0) {
  21104. WL_ERR(("Failed set CAC, ret=%d\n", ret));
  21105. } else {
  21106. WL_DBG(("CAC set successfully\n"));
  21107. }
  21108. return;
  21109. }
  21110. #endif /* SUPPORT_SET_CAC */
  21111. #ifdef SUPPORT_RSSI_SUM_REPORT
  21112. int
  21113. wl_get_rssi_per_ant(struct net_device *dev, char *ifname, char *peer_mac, void *param)
  21114. {
  21115. struct bcm_cfg80211 *cfg = wl_get_cfg(dev);
  21116. wl_rssi_ant_mimo_t *get_param = (wl_rssi_ant_mimo_t *)param;
  21117. rssi_ant_param_t *set_param = NULL;
  21118. struct net_device *ifdev = NULL;
  21119. char iobuf[WLC_IOCTL_SMLEN];
  21120. int err = BCME_OK;
  21121. int iftype = 0;
  21122. bzero(iobuf, WLC_IOCTL_SMLEN);
  21123. /* Check the interface type */
  21124. ifdev = wl_get_netdev_by_name(cfg, ifname);
  21125. if (ifdev == NULL) {
  21126. WL_ERR(("Could not find net_device for ifname:%s\n", ifname));
  21127. err = BCME_BADARG;
  21128. goto fail;
  21129. }
  21130. iftype = ifdev->ieee80211_ptr->iftype;
  21131. if (iftype == NL80211_IFTYPE_AP || iftype == NL80211_IFTYPE_P2P_GO) {
  21132. if (peer_mac) {
  21133. set_param = (rssi_ant_param_t *)MALLOCZ(cfg->osh, sizeof(rssi_ant_param_t));
  21134. err = wl_cfg80211_ether_atoe(peer_mac, &set_param->ea);
  21135. if (!err) {
  21136. WL_ERR(("Invalid Peer MAC format\n"));
  21137. err = BCME_BADARG;
  21138. goto fail;
  21139. }
  21140. } else {
  21141. WL_ERR(("Peer MAC is not provided for iftype %d\n", iftype));
  21142. err = BCME_BADARG;
  21143. goto fail;
  21144. }
  21145. }
  21146. err = wldev_iovar_getbuf(ifdev, "phy_rssi_ant", peer_mac ?
  21147. (void *)&(set_param->ea) : NULL, peer_mac ? ETHER_ADDR_LEN : 0,
  21148. (void *)iobuf, sizeof(iobuf), NULL);
  21149. if (unlikely(err)) {
  21150. WL_ERR(("Failed to get rssi info, err=%d\n", err));
  21151. } else {
  21152. memcpy(get_param, iobuf, sizeof(wl_rssi_ant_mimo_t));
  21153. if (get_param->count == 0) {
  21154. WL_ERR(("Not supported on this chip\n"));
  21155. err = BCME_UNSUPPORTED;
  21156. }
  21157. }
  21158. fail:
  21159. if (set_param) {
  21160. MFREE(cfg->osh, set_param, sizeof(rssi_ant_param_t));
  21161. }
  21162. return err;
  21163. }
  21164. int
  21165. wl_get_rssi_logging(struct net_device *dev, void *param)
  21166. {
  21167. rssilog_get_param_t *get_param = (rssilog_get_param_t *)param;
  21168. char iobuf[WLC_IOCTL_SMLEN];
  21169. int err = BCME_OK;
  21170. bzero(iobuf, WLC_IOCTL_SMLEN);
  21171. bzero(get_param, sizeof(*get_param));
  21172. err = wldev_iovar_getbuf(dev, "rssilog", NULL, 0, (void *)iobuf,
  21173. sizeof(iobuf), NULL);
  21174. if (err) {
  21175. WL_ERR(("Failed to get rssi logging info, err=%d\n", err));
  21176. } else {
  21177. memcpy(get_param, iobuf, sizeof(*get_param));
  21178. }
  21179. return err;
  21180. }
  21181. int
  21182. wl_set_rssi_logging(struct net_device *dev, void *param)
  21183. {
  21184. struct bcm_cfg80211 *cfg = wl_get_cfg(dev);
  21185. rssilog_set_param_t *set_param = (rssilog_set_param_t *)param;
  21186. int err;
  21187. err = wldev_iovar_setbuf(dev, "rssilog", set_param,
  21188. sizeof(*set_param), cfg->ioctl_buf, WLC_IOCTL_SMLEN,
  21189. &cfg->ioctl_buf_sync);
  21190. if (err) {
  21191. WL_ERR(("Failed to set rssi logging param, err=%d\n", err));
  21192. }
  21193. return err;
  21194. }
  21195. #endif /* SUPPORT_RSSI_SUM_REPORT */
  21196. /* Function to flush the FW preserve buffer content
  21197. * The buffer content is sent to host in form of events.
  21198. */
  21199. void
  21200. wl_flush_fw_log_buffer(struct net_device *dev, uint32 logset_mask)
  21201. {
  21202. struct bcm_cfg80211 *cfg = wl_get_cfg(dev);
  21203. dhd_pub_t *dhd = (dhd_pub_t *)(cfg->pub);
  21204. int i;
  21205. int err = 0;
  21206. u8 buf[WLC_IOCTL_SMLEN] = {0};
  21207. wl_el_set_params_t set_param;
  21208. /* Set the size of data to retrieve */
  21209. memset(&set_param, 0, sizeof(set_param));
  21210. set_param.size = WLC_IOCTL_SMLEN;
  21211. for (i = 0; i < dhd->event_log_max_sets; i++)
  21212. {
  21213. if ((0x01u << i) & logset_mask) {
  21214. set_param.set = i;
  21215. err = wldev_iovar_setbuf(dev, "event_log_get", &set_param,
  21216. sizeof(struct wl_el_set_params_s), buf, WLC_IOCTL_SMLEN,
  21217. NULL);
  21218. if (err) {
  21219. WL_DBG(("Failed to get fw preserve logs, err=%d\n", err));
  21220. }
  21221. }
  21222. }
  21223. }
  21224. #ifdef USE_WFA_CERT_CONF
  21225. extern int g_frameburst;
  21226. #endif /* USE_WFA_CERT_CONF */
  21227. int
  21228. wl_cfg80211_set_frameburst(struct bcm_cfg80211 *cfg, bool enable)
  21229. {
  21230. int ret = BCME_OK;
  21231. int val = enable ? 1 : 0;
  21232. #ifdef USE_WFA_CERT_CONF
  21233. if (!g_frameburst) {
  21234. WL_DBG(("Skip setting frameburst\n"));
  21235. return 0;
  21236. }
  21237. #endif /* USE_WFA_CERT_CONF */
  21238. WL_DBG(("Set frameburst %d\n", val));
  21239. ret = wldev_ioctl_set(bcmcfg_to_prmry_ndev(cfg), WLC_SET_FAKEFRAG, &val, sizeof(val));
  21240. if (ret < 0) {
  21241. WL_ERR(("Failed set frameburst, ret=%d\n", ret));
  21242. } else {
  21243. WL_INFORM_MEM(("frameburst is %s\n", enable ? "enabled" : "disabled"));
  21244. }
  21245. return ret;
  21246. }
  21247. s32
  21248. wl_cfg80211_set_dbg_verbose(struct net_device *ndev, u32 level)
  21249. {
  21250. /* configure verbose level for debugging */
  21251. if (level) {
  21252. /* Enable increased verbose */
  21253. wl_dbg_level |= WL_DBG_DBG;
  21254. } else {
  21255. /* Disable */
  21256. wl_dbg_level &= ~WL_DBG_DBG;
  21257. }
  21258. WL_INFORM(("debug verbose set to %d\n", level));
  21259. return BCME_OK;
  21260. }
  21261. const u8 *
  21262. wl_find_attribute(const u8 *buf, u16 len, u16 element_id)
  21263. {
  21264. const u8 *attrib;
  21265. u16 attrib_id;
  21266. u16 attrib_len;
  21267. if (!buf) {
  21268. WL_ERR(("buf null\n"));
  21269. return NULL;
  21270. }
  21271. attrib = buf;
  21272. while (len >= 4) {
  21273. /* attribute id */
  21274. attrib_id = *attrib++ << 8;
  21275. attrib_id |= *attrib++;
  21276. len -= 2;
  21277. /* 2-byte little endian */
  21278. attrib_len = *attrib++ << 8;
  21279. attrib_len |= *attrib++;
  21280. len -= 2;
  21281. if (attrib_id == element_id) {
  21282. /* This will point to start of subelement attrib after
  21283. * attribute id & len
  21284. */
  21285. return attrib;
  21286. }
  21287. if (len > attrib_len) {
  21288. len -= attrib_len; /* for the remaining subelt fields */
  21289. WL_DBG(("Attribue:%4x attrib_len:%d rem_len:%d\n",
  21290. attrib_id, attrib_len, len));
  21291. /* Go to next subelement */
  21292. attrib += attrib_len;
  21293. } else {
  21294. WL_ERR(("Incorrect Attribue:%4x attrib_len:%d\n",
  21295. attrib_id, attrib_len));
  21296. return NULL;
  21297. }
  21298. }
  21299. return NULL;
  21300. }
  21301. uint8 wl_cfg80211_get_bus_state(struct bcm_cfg80211 *cfg)
  21302. {
  21303. dhd_pub_t *dhd = (dhd_pub_t *)(cfg->pub);
  21304. WL_INFORM(("dhd->hang_was_sent = %d and busstate = %d\n",
  21305. dhd->hang_was_sent, dhd->busstate));
  21306. return ((dhd->busstate == DHD_BUS_DOWN) || dhd->hang_was_sent);
  21307. }
  21308. #ifdef WL_WPS_SYNC
  21309. static void wl_wps_reauth_timeout(unsigned long data)
  21310. {
  21311. struct net_device *ndev = (struct net_device *)data;
  21312. struct bcm_cfg80211 *cfg = wl_get_cfg(ndev);
  21313. s32 inst;
  21314. unsigned long flags;
  21315. WL_CFG_WPS_SYNC_LOCK(&cfg->wps_sync, flags);
  21316. inst = wl_get_wps_inst_match(cfg, ndev);
  21317. if (inst >= 0) {
  21318. WL_ERR(("[%s][WPS] Reauth Timeout Inst:%d! state:%d\n",
  21319. ndev->name, inst, cfg->wps_session[inst].state));
  21320. if (cfg->wps_session[inst].state == WPS_STATE_REAUTH_WAIT) {
  21321. /* Session should get deleted from success (linkup) or
  21322. * deauth case. Just in case, link reassoc failed, clear
  21323. * state here.
  21324. */
  21325. WL_ERR(("[%s][WPS] Reauth Timeout Inst:%d!\n",
  21326. ndev->name, inst));
  21327. cfg->wps_session[inst].state = WPS_STATE_IDLE;
  21328. cfg->wps_session[inst].in_use = false;
  21329. }
  21330. }
  21331. WL_CFG_WPS_SYNC_UNLOCK(&cfg->wps_sync, flags);
  21332. }
  21333. static void wl_init_wps_reauth_sm(struct bcm_cfg80211 *cfg)
  21334. {
  21335. /* Only two instances are supported as of now. one for
  21336. * infra STA and other for infra STA/GC.
  21337. */
  21338. int i = 0;
  21339. struct net_device *pdev = bcmcfg_to_prmry_ndev(cfg);
  21340. spin_lock_init(&cfg->wps_sync);
  21341. for (i = 0; i < WPS_MAX_SESSIONS; i++) {
  21342. /* Init scan_timeout timer */
  21343. init_timer_compat(&cfg->wps_session[i].timer, wl_wps_reauth_timeout, pdev);
  21344. cfg->wps_session[i].in_use = false;
  21345. cfg->wps_session[i].state = WPS_STATE_IDLE;
  21346. }
  21347. }
  21348. static void wl_deinit_wps_reauth_sm(struct bcm_cfg80211 *cfg)
  21349. {
  21350. int i = 0;
  21351. for (i = 0; i < WPS_MAX_SESSIONS; i++) {
  21352. cfg->wps_session[i].in_use = false;
  21353. cfg->wps_session[i].state = WPS_STATE_IDLE;
  21354. if (timer_pending(&cfg->wps_session[i].timer)) {
  21355. del_timer_sync(&cfg->wps_session[i].timer);
  21356. }
  21357. }
  21358. }
  21359. static s32
  21360. wl_get_free_wps_inst(struct bcm_cfg80211 *cfg)
  21361. {
  21362. int i;
  21363. for (i = 0; i < WPS_MAX_SESSIONS; i++) {
  21364. if (!cfg->wps_session[i].in_use) {
  21365. return i;
  21366. }
  21367. }
  21368. return BCME_ERROR;
  21369. }
  21370. static s32
  21371. wl_get_wps_inst_match(struct bcm_cfg80211 *cfg, struct net_device *ndev)
  21372. {
  21373. int i;
  21374. for (i = 0; i < WPS_MAX_SESSIONS; i++) {
  21375. if ((cfg->wps_session[i].in_use) &&
  21376. (ndev == cfg->wps_session[i].ndev)) {
  21377. return i;
  21378. }
  21379. }
  21380. return BCME_ERROR;
  21381. }
  21382. static s32
  21383. wl_wps_session_add(struct net_device *ndev, u16 mode, u8 *mac_addr)
  21384. {
  21385. s32 inst;
  21386. struct bcm_cfg80211 *cfg = wl_get_cfg(ndev);
  21387. unsigned long flags;
  21388. WL_CFG_WPS_SYNC_LOCK(&cfg->wps_sync, flags);
  21389. /* Fetch and initialize a wps instance */
  21390. inst = wl_get_free_wps_inst(cfg);
  21391. if (inst == BCME_ERROR) {
  21392. WL_ERR(("[WPS] No free insance\n"));
  21393. WL_CFG_WPS_SYNC_UNLOCK(&cfg->wps_sync, flags);
  21394. return BCME_ERROR;
  21395. }
  21396. cfg->wps_session[inst].in_use = true;
  21397. cfg->wps_session[inst].state = WPS_STATE_STARTED;
  21398. cfg->wps_session[inst].ndev = ndev;
  21399. cfg->wps_session[inst].mode = mode;
  21400. /* return check not required since both buffer lens are same */
  21401. (void)memcpy_s(cfg->wps_session[inst].peer_mac, ETH_ALEN, mac_addr, ETH_ALEN);
  21402. WL_CFG_WPS_SYNC_UNLOCK(&cfg->wps_sync, flags);
  21403. WL_INFORM_MEM(("[%s][WPS] session created. Peer: " MACDBG "\n",
  21404. ndev->name, MAC2STRDBG(mac_addr)));
  21405. return BCME_OK;
  21406. }
  21407. static void
  21408. wl_wps_session_del(struct net_device *ndev)
  21409. {
  21410. s32 inst;
  21411. struct bcm_cfg80211 *cfg = wl_get_cfg(ndev);
  21412. unsigned long flags;
  21413. u16 cur_state;
  21414. WL_CFG_WPS_SYNC_LOCK(&cfg->wps_sync, flags);
  21415. /* Get current instance for the given ndev */
  21416. inst = wl_get_wps_inst_match(cfg, ndev);
  21417. if (inst == BCME_ERROR) {
  21418. WL_DBG(("[WPS] instance match NOT found\n"));
  21419. WL_CFG_WPS_SYNC_UNLOCK(&cfg->wps_sync, flags);
  21420. return;
  21421. }
  21422. cur_state = cfg->wps_session[inst].state;
  21423. if (cur_state != WPS_STATE_DONE) {
  21424. WL_DBG(("[WPS] wrong state:%d\n", cur_state));
  21425. WL_CFG_WPS_SYNC_UNLOCK(&cfg->wps_sync, flags);
  21426. return;
  21427. }
  21428. /* Mark this as unused */
  21429. cfg->wps_session[inst].in_use = false;
  21430. cfg->wps_session[inst].state = WPS_STATE_IDLE;
  21431. WL_CFG_WPS_SYNC_UNLOCK(&cfg->wps_sync, flags);
  21432. /* Ensure this API is called from sleepable context. */
  21433. if (timer_pending(&cfg->wps_session[inst].timer)) {
  21434. del_timer_sync(&cfg->wps_session[inst].timer);
  21435. }
  21436. WL_INFORM_MEM(("[%s][WPS] session deleted\n", ndev->name));
  21437. }
  21438. static void
  21439. wl_wps_handle_ifdel(struct net_device *ndev)
  21440. {
  21441. struct bcm_cfg80211 *cfg = wl_get_cfg(ndev);
  21442. unsigned long flags;
  21443. u16 cur_state;
  21444. s32 inst;
  21445. WL_CFG_WPS_SYNC_LOCK(&cfg->wps_sync, flags);
  21446. inst = wl_get_wps_inst_match(cfg, ndev);
  21447. if (inst == BCME_ERROR) {
  21448. WL_DBG(("[WPS] instance match NOT found\n"));
  21449. WL_CFG_WPS_SYNC_UNLOCK(&cfg->wps_sync, flags);
  21450. return;
  21451. }
  21452. cur_state = cfg->wps_session[inst].state;
  21453. cfg->wps_session[inst].state = WPS_STATE_DONE;
  21454. WL_CFG_WPS_SYNC_UNLOCK(&cfg->wps_sync, flags);
  21455. WL_INFORM_MEM(("[%s][WPS] state:%x\n", ndev->name, cur_state));
  21456. if (cur_state > WPS_STATE_IDLE) {
  21457. wl_wps_session_del(ndev);
  21458. }
  21459. }
  21460. static s32
  21461. wl_wps_handle_sta_linkdown(struct net_device *ndev, u16 inst)
  21462. {
  21463. struct bcm_cfg80211 *cfg = wl_get_cfg(ndev);
  21464. unsigned long flags;
  21465. u16 cur_state;
  21466. bool wps_done = false;
  21467. WL_CFG_WPS_SYNC_LOCK(&cfg->wps_sync, flags);
  21468. cur_state = cfg->wps_session[inst].state;
  21469. if (cur_state == WPS_STATE_REAUTH_WAIT) {
  21470. WL_CFG_WPS_SYNC_UNLOCK(&cfg->wps_sync, flags);
  21471. wl_clr_drv_status(cfg, CONNECTED, ndev);
  21472. wl_clr_drv_status(cfg, DISCONNECTING, ndev);
  21473. WL_INFORM_MEM(("[%s][WPS] REAUTH link down\n", ndev->name));
  21474. /* Drop the link down event while we are waiting for reauth */
  21475. return BCME_UNSUPPORTED;
  21476. } else if (cur_state == WPS_STATE_STARTED) {
  21477. /* Link down before reaching EAP-FAIL. End WPS session */
  21478. cfg->wps_session[inst].state = WPS_STATE_DONE;
  21479. wps_done = true;
  21480. WL_INFORM_MEM(("[%s][WPS] link down after wps start\n", ndev->name));
  21481. } else {
  21482. WL_DBG(("[%s][WPS] link down in state:%d\n",
  21483. ndev->name, cur_state));
  21484. }
  21485. WL_CFG_WPS_SYNC_UNLOCK(&cfg->wps_sync, flags);
  21486. if (wps_done) {
  21487. wl_wps_session_del(ndev);
  21488. }
  21489. return BCME_OK;
  21490. }
  21491. static s32
  21492. wl_wps_handle_peersta_linkdown(struct net_device *ndev, u16 inst, const u8 *peer_mac)
  21493. {
  21494. struct bcm_cfg80211 *cfg = wl_get_cfg(ndev);
  21495. unsigned long flags;
  21496. u16 cur_state;
  21497. s32 ret = BCME_OK;
  21498. bool wps_done = false;
  21499. WL_CFG_WPS_SYNC_LOCK(&cfg->wps_sync, flags);
  21500. cur_state = cfg->wps_session[inst].state;
  21501. if (!peer_mac) {
  21502. WL_ERR(("Invalid arg\n"));
  21503. ret = BCME_ERROR;
  21504. goto exit;
  21505. }
  21506. /* AP/GO can have multiple clients. so validate peer_mac addr
  21507. * and ensure states are updated only for right peer.
  21508. */
  21509. if (memcmp(cfg->wps_session[inst].peer_mac, peer_mac, ETH_ALEN)) {
  21510. /* Mac addr not matching. Ignore. */
  21511. WL_DBG(("[%s][WPS] No active WPS session"
  21512. "for the peer:" MACDBG "\n", ndev->name, MAC2STRDBG(peer_mac)));
  21513. ret = BCME_OK;
  21514. goto exit;
  21515. }
  21516. if (cur_state == WPS_STATE_REAUTH_WAIT) {
  21517. WL_INFORM_MEM(("[%s][WPS] REAUTH link down."
  21518. " Peer: " MACDBG "\n",
  21519. ndev->name, MAC2STRDBG(peer_mac)));
  21520. } else if (cur_state == WPS_STATE_STARTED) {
  21521. /* Link down before reaching REAUTH_WAIT state. WPS
  21522. * session ended.
  21523. */
  21524. cfg->wps_session[inst].state = WPS_STATE_DONE;
  21525. WL_INFORM_MEM(("[%s][WPS] link down after wps start"
  21526. " client:" MACDBG "\n",
  21527. ndev->name, MAC2STRDBG(peer_mac)));
  21528. wps_done = true;
  21529. /* since we have freed lock above, return from here */
  21530. ret = BCME_OK;
  21531. } else {
  21532. WL_ERR(("[%s][WPS] Unsupported state:%d",
  21533. ndev->name, cur_state));
  21534. ret = BCME_ERROR;
  21535. }
  21536. exit:
  21537. WL_CFG_WPS_SYNC_UNLOCK(&cfg->wps_sync, flags);
  21538. if (wps_done) {
  21539. wl_wps_session_del(ndev);
  21540. }
  21541. return ret;
  21542. }
  21543. static s32
  21544. wl_wps_handle_sta_linkup(struct net_device *ndev, u16 inst)
  21545. {
  21546. struct bcm_cfg80211 *cfg = wl_get_cfg(ndev);
  21547. unsigned long flags;
  21548. u16 cur_state;
  21549. s32 ret = BCME_OK;
  21550. bool wps_done = false;
  21551. WL_CFG_WPS_SYNC_LOCK(&cfg->wps_sync, flags);
  21552. cur_state = cfg->wps_session[inst].state;
  21553. if (cur_state == WPS_STATE_REAUTH_WAIT) {
  21554. /* WPS session succeeded. del session. */
  21555. cfg->wps_session[inst].state = WPS_STATE_DONE;
  21556. wps_done = true;
  21557. WL_INFORM_MEM(("[%s][WPS] WPS_REAUTH link up (WPS DONE)\n", ndev->name));
  21558. ret = BCME_OK;
  21559. } else {
  21560. WL_ERR(("[%s][WPS] unexpected link up in state:%d \n",
  21561. ndev->name, cur_state));
  21562. ret = BCME_ERROR;
  21563. }
  21564. WL_CFG_WPS_SYNC_UNLOCK(&cfg->wps_sync, flags);
  21565. if (wps_done) {
  21566. wl_wps_session_del(ndev);
  21567. }
  21568. return ret;
  21569. }
  21570. static s32
  21571. wl_wps_handle_peersta_linkup(struct net_device *ndev, u16 inst, const u8 *peer_mac)
  21572. {
  21573. struct bcm_cfg80211 *cfg = wl_get_cfg(ndev);
  21574. unsigned long flags;
  21575. u16 cur_state;
  21576. s32 ret = BCME_OK;
  21577. WL_CFG_WPS_SYNC_LOCK(&cfg->wps_sync, flags);
  21578. cur_state = cfg->wps_session[inst].state;
  21579. /* For AP case, check whether call came for right peer */
  21580. if (!peer_mac ||
  21581. memcmp(cfg->wps_session[inst].peer_mac, peer_mac, ETH_ALEN)) {
  21582. WL_ERR(("[WPS] macaddr mismatch\n"));
  21583. WL_CFG_WPS_SYNC_UNLOCK(&cfg->wps_sync, flags);
  21584. /* Mac addr not matching. Ignore. */
  21585. return BCME_ERROR;
  21586. }
  21587. if (cur_state == WPS_STATE_REAUTH_WAIT) {
  21588. WL_INFORM_MEM(("[%s][WPS] REAUTH link up\n", ndev->name));
  21589. ret = BCME_OK;
  21590. } else {
  21591. WL_INFORM_MEM(("[%s][WPS] unexpected link up in state:%d \n",
  21592. ndev->name, cur_state));
  21593. ret = BCME_ERROR;
  21594. }
  21595. WL_CFG_WPS_SYNC_UNLOCK(&cfg->wps_sync, flags);
  21596. return ret;
  21597. }
  21598. static s32
  21599. wl_wps_handle_authorize(struct net_device *ndev, u16 inst, const u8 *peer_mac)
  21600. {
  21601. struct bcm_cfg80211 *cfg = wl_get_cfg(ndev);
  21602. unsigned long flags;
  21603. u16 cur_state;
  21604. bool wps_done = false;
  21605. s32 ret = BCME_OK;
  21606. WL_CFG_WPS_SYNC_LOCK(&cfg->wps_sync, flags);
  21607. cur_state = cfg->wps_session[inst].state;
  21608. /* For AP case, check whether call came for right peer */
  21609. if (!peer_mac ||
  21610. memcmp(cfg->wps_session[inst].peer_mac, peer_mac, ETH_ALEN)) {
  21611. WL_ERR(("[WPS] macaddr mismatch\n"));
  21612. WL_CFG_WPS_SYNC_UNLOCK(&cfg->wps_sync, flags);
  21613. /* Mac addr not matching. Ignore. */
  21614. return BCME_ERROR;
  21615. }
  21616. if (cur_state == WPS_STATE_REAUTH_WAIT) {
  21617. /* WPS session succeeded. del session. */
  21618. cfg->wps_session[inst].state = WPS_STATE_DONE;
  21619. wps_done = true;
  21620. WL_INFORM_MEM(("[%s][WPS] Authorize done (WPS DONE)\n", ndev->name));
  21621. ret = BCME_OK;
  21622. } else {
  21623. WL_INFORM_MEM(("[%s][WPS] unexpected Authorize in state:%d \n",
  21624. ndev->name, cur_state));
  21625. ret = BCME_ERROR;
  21626. }
  21627. WL_CFG_WPS_SYNC_UNLOCK(&cfg->wps_sync, flags);
  21628. if (wps_done) {
  21629. wl_wps_session_del(ndev);
  21630. }
  21631. return ret;
  21632. }
  21633. static s32
  21634. wl_wps_handle_reauth(struct net_device *ndev, u16 inst, const u8 *peer_mac)
  21635. {
  21636. struct bcm_cfg80211 *cfg = wl_get_cfg(ndev);
  21637. unsigned long flags;
  21638. u16 cur_state;
  21639. u16 mode;
  21640. s32 ret = BCME_OK;
  21641. WL_CFG_WPS_SYNC_LOCK(&cfg->wps_sync, flags);
  21642. cur_state = cfg->wps_session[inst].state;
  21643. mode = cfg->wps_session[inst].mode;
  21644. if (((mode == WL_MODE_BSS) && (cur_state == WPS_STATE_STARTED)) ||
  21645. ((mode == WL_MODE_AP) && (cur_state == WPS_STATE_M8_SENT))) {
  21646. /* Move to reauth wait */
  21647. cfg->wps_session[inst].state = WPS_STATE_REAUTH_WAIT;
  21648. /* Use ndev to find the wps instance which fired the timer */
  21649. timer_set_private(&cfg->wps_session[inst].timer, ndev);
  21650. WL_CFG_WPS_SYNC_UNLOCK(&cfg->wps_sync, flags);
  21651. mod_timer(&cfg->wps_session[inst].timer,
  21652. jiffies + msecs_to_jiffies(WL_WPS_REAUTH_TIMEOUT));
  21653. WL_INFORM_MEM(("[%s][WPS] STATE_REAUTH_WAIT mode:%d Peer: " MACDBG "\n",
  21654. ndev->name, mode, MAC2STRDBG(peer_mac)));
  21655. return BCME_OK;
  21656. } else {
  21657. /* 802.1x cases */
  21658. WL_DBG(("[%s][WPS] EAP-FAIL\n", ndev->name));
  21659. }
  21660. WL_CFG_WPS_SYNC_UNLOCK(&cfg->wps_sync, flags);
  21661. return ret;
  21662. }
  21663. static s32
  21664. wl_wps_handle_disconnect(struct net_device *ndev, u16 inst, const u8 *peer_mac)
  21665. {
  21666. struct bcm_cfg80211 *cfg = wl_get_cfg(ndev);
  21667. unsigned long flags;
  21668. u16 cur_state;
  21669. s32 ret = BCME_OK;
  21670. WL_CFG_WPS_SYNC_LOCK(&cfg->wps_sync, flags);
  21671. cur_state = cfg->wps_session[inst].state;
  21672. /* If Disconnect command comes from user space for STA/GC,
  21673. * respond with event without waiting for event from fw as
  21674. * it would be dropped by the WPS_SYNC code.
  21675. */
  21676. if (cur_state == WPS_STATE_REAUTH_WAIT) {
  21677. if (ETHER_ISBCAST(peer_mac)) {
  21678. WL_DBG(("[WPS] Bcast peer. Do nothing.\n"));
  21679. } else {
  21680. /* Notify link down */
  21681. CFG80211_DISCONNECTED(ndev,
  21682. WLAN_REASON_DEAUTH_LEAVING, NULL, 0,
  21683. true, GFP_ATOMIC);
  21684. }
  21685. } else {
  21686. WL_DBG(("[%s][WPS] Not valid state to report disconnected:%d",
  21687. ndev->name, cur_state));
  21688. ret = BCME_UNSUPPORTED;
  21689. }
  21690. WL_CFG_WPS_SYNC_UNLOCK(&cfg->wps_sync, flags);
  21691. return ret;
  21692. }
  21693. static s32
  21694. wl_wps_handle_disconnect_client(struct net_device *ndev, u16 inst, const u8 *peer_mac)
  21695. {
  21696. struct bcm_cfg80211 *cfg = wl_get_cfg(ndev);
  21697. unsigned long flags;
  21698. u16 cur_state;
  21699. s32 ret = BCME_OK;
  21700. bool wps_done = false;
  21701. WL_CFG_WPS_SYNC_LOCK(&cfg->wps_sync, flags);
  21702. cur_state = cfg->wps_session[inst].state;
  21703. /* For GO/AP, ignore disconnect client during reauth state */
  21704. if (cur_state == WPS_STATE_REAUTH_WAIT) {
  21705. if (ETHER_ISBCAST(peer_mac)) {
  21706. /* If there is broadcast deauth, then mark wps session as ended */
  21707. cfg->wps_session[inst].state = WPS_STATE_DONE;
  21708. wps_done = true;
  21709. WL_INFORM_MEM(("[%s][WPS] BCAST deauth. WPS stopped.\n", ndev->name));
  21710. ret = BCME_OK;
  21711. goto exit;
  21712. } else if (!(memcmp(cfg->wps_session[inst].peer_mac,
  21713. peer_mac, ETH_ALEN))) {
  21714. WL_ERR(("[%s][WPS] Drop disconnect client\n", ndev->name));
  21715. ret = BCME_UNSUPPORTED;
  21716. }
  21717. }
  21718. exit:
  21719. WL_CFG_WPS_SYNC_UNLOCK(&cfg->wps_sync, flags);
  21720. if (wps_done) {
  21721. wl_wps_session_del(ndev);
  21722. }
  21723. return ret;
  21724. }
  21725. static s32
  21726. wl_wps_handle_connect_fail(struct net_device *ndev, u16 inst)
  21727. {
  21728. struct bcm_cfg80211 *cfg = wl_get_cfg(ndev);
  21729. unsigned long flags;
  21730. u16 cur_state;
  21731. bool wps_done = false;
  21732. WL_CFG_WPS_SYNC_LOCK(&cfg->wps_sync, flags);
  21733. cur_state = cfg->wps_session[inst].state;
  21734. if (cur_state == WPS_STATE_REAUTH_WAIT) {
  21735. cfg->wps_session[inst].state = WPS_STATE_DONE;
  21736. wps_done = true;
  21737. WL_INFORM_MEM(("[%s][WPS] Connect fail. WPS stopped.\n",
  21738. ndev->name));
  21739. } else {
  21740. WL_ERR(("[%s][WPS] Connect fail. state:%d\n",
  21741. ndev->name, cur_state));
  21742. }
  21743. WL_CFG_WPS_SYNC_UNLOCK(&cfg->wps_sync, flags);
  21744. if (wps_done) {
  21745. wl_wps_session_del(ndev);
  21746. }
  21747. return BCME_OK;
  21748. }
  21749. static s32
  21750. wl_wps_handle_m8_sent(struct net_device *ndev, u16 inst, const u8 *peer_mac)
  21751. {
  21752. struct bcm_cfg80211 *cfg = wl_get_cfg(ndev);
  21753. unsigned long flags;
  21754. u16 cur_state;
  21755. s32 ret = BCME_OK;
  21756. WL_CFG_WPS_SYNC_LOCK(&cfg->wps_sync, flags);
  21757. cur_state = cfg->wps_session[inst].state;
  21758. if (cur_state == WPS_STATE_STARTED) {
  21759. /* Move to M8 sent state */
  21760. cfg->wps_session[inst].state = WPS_STATE_M8_SENT;
  21761. WL_CFG_WPS_SYNC_UNLOCK(&cfg->wps_sync, flags);
  21762. return BCME_OK;
  21763. } else {
  21764. /* 802.1x cases */
  21765. WL_DBG(("[%s][WPS] Not valid state to send M8\n", ndev->name));
  21766. }
  21767. WL_CFG_WPS_SYNC_UNLOCK(&cfg->wps_sync, flags);
  21768. return ret;
  21769. }
  21770. static s32
  21771. wl_wps_session_update(struct net_device *ndev, u16 state, const u8 *peer_mac)
  21772. {
  21773. s32 inst;
  21774. u16 mode;
  21775. struct bcm_cfg80211 *cfg = wl_get_cfg(ndev);
  21776. s32 ret = BCME_ERROR;
  21777. unsigned long flags;
  21778. WL_CFG_WPS_SYNC_LOCK(&cfg->wps_sync, flags);
  21779. /* Get current instance for the given ndev */
  21780. inst = wl_get_wps_inst_match(cfg, ndev);
  21781. if (inst == BCME_ERROR) {
  21782. /* No active WPS session. Do Nothing. */
  21783. WL_DBG(("[%s][WPS] No matching instance.\n", ndev->name));
  21784. WL_CFG_WPS_SYNC_UNLOCK(&cfg->wps_sync, flags);
  21785. return BCME_NOTFOUND;
  21786. }
  21787. mode = cfg->wps_session[inst].mode;
  21788. WL_CFG_WPS_SYNC_UNLOCK(&cfg->wps_sync, flags);
  21789. WL_DBG(("[%s][WPS] state:%d mode:%d Peer: " MACDBG "\n",
  21790. ndev->name, state, mode, MAC2STRDBG(peer_mac)));
  21791. switch (state) {
  21792. case WPS_STATE_M8_RECVD:
  21793. {
  21794. /* Occasionally, due to race condition between ctrl
  21795. * and data path, deauth ind is recvd before EAP-FAIL.
  21796. * Ignore deauth ind before EAP-FAIL
  21797. * So move to REAUTH WAIT on receiving M8 on GC and
  21798. * ignore deauth ind before EAP-FAIL till 'x' timeout.
  21799. * Kickoff a timer to monitor reauth status.
  21800. */
  21801. if (mode == WL_MODE_BSS) {
  21802. ret = wl_wps_handle_reauth(ndev, inst, peer_mac);
  21803. } else {
  21804. /* Nothing to be done for AP/GO mode */
  21805. ret = BCME_OK;
  21806. }
  21807. break;
  21808. }
  21809. case WPS_STATE_M8_SENT:
  21810. {
  21811. /* Mantain the M8 sent state to verify
  21812. * EAP-FAIL sent is valid
  21813. */
  21814. if (mode == WL_MODE_AP) {
  21815. ret = wl_wps_handle_m8_sent(ndev, inst, peer_mac);
  21816. } else {
  21817. /* Nothing to be done for STA/GC mode */
  21818. ret = BCME_OK;
  21819. }
  21820. break;
  21821. }
  21822. case WPS_STATE_EAP_FAIL:
  21823. {
  21824. /* Move to REAUTH WAIT following EAP-FAIL TX on GO/AP.
  21825. * Kickoff a timer to monitor reauth status
  21826. */
  21827. if (mode == WL_MODE_AP) {
  21828. ret = wl_wps_handle_reauth(ndev, inst, peer_mac);
  21829. } else {
  21830. /* Nothing to be done for STA/GC mode */
  21831. ret = BCME_OK;
  21832. }
  21833. break;
  21834. }
  21835. case WPS_STATE_LINKDOWN:
  21836. {
  21837. if (mode == WL_MODE_BSS) {
  21838. ret = wl_wps_handle_sta_linkdown(ndev, inst);
  21839. } else if (mode == WL_MODE_AP) {
  21840. /* Take action only for matching peer mac */
  21841. if (!memcmp(cfg->wps_session[inst].peer_mac, peer_mac, ETH_ALEN)) {
  21842. ret = wl_wps_handle_peersta_linkdown(ndev, inst, peer_mac);
  21843. }
  21844. }
  21845. break;
  21846. }
  21847. case WPS_STATE_LINKUP:
  21848. {
  21849. if (mode == WL_MODE_BSS) {
  21850. wl_wps_handle_sta_linkup(ndev, inst);
  21851. } else if (mode == WL_MODE_AP) {
  21852. /* Take action only for matching peer mac */
  21853. if (!memcmp(cfg->wps_session[inst].peer_mac, peer_mac, ETH_ALEN)) {
  21854. wl_wps_handle_peersta_linkup(ndev, inst, peer_mac);
  21855. }
  21856. }
  21857. break;
  21858. }
  21859. case WPS_STATE_DISCONNECT_CLIENT:
  21860. {
  21861. /* Disconnect STA/GC command from user space */
  21862. if (mode == WL_MODE_AP) {
  21863. ret = wl_wps_handle_disconnect_client(ndev, inst, peer_mac);
  21864. } else {
  21865. WL_ERR(("[WPS] Unsupported mode %d\n", mode));
  21866. }
  21867. break;
  21868. }
  21869. case WPS_STATE_DISCONNECT:
  21870. {
  21871. /* Disconnect command on STA/GC interface */
  21872. if (mode == WL_MODE_BSS) {
  21873. ret = wl_wps_handle_disconnect(ndev, inst, peer_mac);
  21874. }
  21875. break;
  21876. }
  21877. case WPS_STATE_CONNECT_FAIL:
  21878. {
  21879. if (mode == WL_MODE_BSS) {
  21880. ret = wl_wps_handle_connect_fail(ndev, inst);
  21881. } else {
  21882. WL_ERR(("[WPS] Unsupported mode %d\n", mode));
  21883. }
  21884. break;
  21885. }
  21886. case WPS_STATE_AUTHORIZE:
  21887. {
  21888. if (mode == WL_MODE_AP) {
  21889. /* Take action only for matching peer mac */
  21890. if (!memcmp(cfg->wps_session[inst].peer_mac, peer_mac, ETH_ALEN)) {
  21891. wl_wps_handle_authorize(ndev, inst, peer_mac);
  21892. } else {
  21893. WL_INFORM_MEM(("[WPS] Authorize Request for wrong peer\n"));
  21894. }
  21895. }
  21896. break;
  21897. }
  21898. default:
  21899. WL_ERR(("[WPS] Unsupported state:%d mode:%d\n", state, mode));
  21900. ret = BCME_ERROR;
  21901. }
  21902. return ret;
  21903. }
  21904. #define EAP_EXP_ATTRIB_DATA_OFFSET 14
  21905. void
  21906. wl_handle_wps_states(struct net_device *ndev, u8 *pkt, u16 len, bool direction)
  21907. {
  21908. eapol_header_t *eapol_hdr;
  21909. bool tx_packet = direction;
  21910. u16 eapol_type;
  21911. u16 mode;
  21912. u8 *peer_mac;
  21913. if (!ndev || !pkt) {
  21914. WL_ERR(("[WPS] Invalid arg\n"));
  21915. return;
  21916. }
  21917. if (len < (ETHER_HDR_LEN + EAPOL_HDR_LEN)) {
  21918. WL_ERR(("[WPS] Invalid len\n"));
  21919. return;
  21920. }
  21921. eapol_hdr = (eapol_header_t *)pkt;
  21922. eapol_type = eapol_hdr->type;
  21923. peer_mac = tx_packet ? eapol_hdr->eth.ether_dhost :
  21924. eapol_hdr->eth.ether_shost;
  21925. /*
  21926. * The implementation assumes only one WPS session would be active
  21927. * per interface at a time. Even for hostap, the wps_pin session
  21928. * is limited to one enrollee/client at a time. A session is marked
  21929. * started on WSC_START and gets cleared from below contexts
  21930. * a) Deauth/link down before reaching EAP-FAIL state. (Fail case)
  21931. * b) Link up following EAP-FAIL. (success case)
  21932. * c) Link up timeout after EAP-FAIL. (Fail case)
  21933. */
  21934. if (eapol_type == EAP_PACKET) {
  21935. wl_eap_header_t *eap;
  21936. if (len > sizeof(*eap)) {
  21937. eap = (wl_eap_header_t *)(pkt + ETHER_HDR_LEN + EAPOL_HDR_LEN);
  21938. if (eap->type == EAP_EXPANDED_TYPE) {
  21939. wl_eap_exp_t *exp = (wl_eap_exp_t *)eap->data;
  21940. if (eap->length > EAP_EXP_HDR_MIN_LENGTH) {
  21941. /* opcode is at fixed offset */
  21942. u8 opcode = exp->opcode;
  21943. u16 eap_len = ntoh16(eap->length);
  21944. WL_DBG(("[%s][WPS] EAP EXPANDED packet. opcode:%x len:%d\n",
  21945. ndev->name, opcode, eap_len));
  21946. if (opcode == EAP_WSC_MSG) {
  21947. const u8 *msg;
  21948. const u8* parse_buf = exp->data;
  21949. /* Check if recvd pkt is fragmented */
  21950. if ((!tx_packet) &&
  21951. (exp->flags &
  21952. EAP_EXP_FLAGS_FRAGMENTED_DATA)) {
  21953. if ((eap_len - EAP_EXP_ATTRIB_DATA_OFFSET)
  21954. > 2) {
  21955. parse_buf +=
  21956. EAP_EXP_FRAGMENT_LEN_OFFSET;
  21957. eap_len -=
  21958. EAP_EXP_FRAGMENT_LEN_OFFSET;
  21959. WL_DBG(("Rcvd EAP"
  21960. " fragmented pkt\n"));
  21961. } else {
  21962. /* If recvd pkt is fragmented
  21963. * and does not have
  21964. * length field drop the packet.
  21965. */
  21966. return;
  21967. }
  21968. }
  21969. msg = wl_find_attribute(parse_buf,
  21970. (eap_len - EAP_EXP_ATTRIB_DATA_OFFSET),
  21971. EAP_ATTRIB_MSGTYPE);
  21972. if (unlikely(!msg)) {
  21973. WL_ERR(("[WPS] ATTRIB MSG not found!\n"));
  21974. } else if ((*msg == EAP_WSC_MSG_M8) &&
  21975. !tx_packet) {
  21976. WL_INFORM_MEM(("[%s][WPS] M8\n",
  21977. ndev->name));
  21978. wl_wps_session_update(ndev,
  21979. WPS_STATE_M8_RECVD, peer_mac);
  21980. } else if ((*msg == EAP_WSC_MSG_M8) &&
  21981. tx_packet) {
  21982. WL_INFORM_MEM(("[%s][WPS] M8 Sent\n",
  21983. ndev->name));
  21984. wl_wps_session_update(ndev,
  21985. WPS_STATE_M8_SENT, peer_mac);
  21986. } else {
  21987. WL_DBG(("[%s][WPS] EAP WSC MSG: 0x%X\n",
  21988. ndev->name, *msg));
  21989. }
  21990. } else if (opcode == EAP_WSC_START) {
  21991. /* WSC session started. WSC_START - Tx from GO/AP.
  21992. * Session will be deleted on successful link up or
  21993. * on failure (deauth context)
  21994. */
  21995. mode = tx_packet ? WL_MODE_AP : WL_MODE_BSS;
  21996. wl_wps_session_add(ndev, mode, peer_mac);
  21997. WL_INFORM_MEM(("[%s][WPS] WSC_START Mode:%d\n",
  21998. ndev->name, mode));
  21999. } else if (opcode == EAP_WSC_DONE) {
  22000. /* WSC session done. TX on STA/GC. RX on GO/AP
  22001. * On devices where config file save fails, it may
  22002. * return WPS_NAK with config_error:0. But the
  22003. * connection would still proceed. Hence don't let
  22004. * state machine depend on WSC DONE.
  22005. */
  22006. WL_INFORM_MEM(("[%s][WPS] WSC_DONE\n", ndev->name));
  22007. }
  22008. }
  22009. }
  22010. if (eap->code == EAP_CODE_FAILURE) {
  22011. /* EAP_FAIL */
  22012. WL_INFORM_MEM(("[%s][WPS] EAP_FAIL\n", ndev->name));
  22013. wl_wps_session_update(ndev,
  22014. WPS_STATE_EAP_FAIL, peer_mac);
  22015. }
  22016. }
  22017. }
  22018. }
  22019. #endif /* WL_WPS_SYNC */
  22020. s32
  22021. wl_cfg80211_sup_event_handler(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev,
  22022. const wl_event_msg_t *event, void *data)
  22023. {
  22024. int err = BCME_OK;
  22025. u32 status = ntoh32(event->status);
  22026. struct net_device *ndev = bcmcfg_to_prmry_ndev(cfg);
  22027. u32 reason = ntoh32(event->reason);
  22028. if ((status == WLC_SUP_KEYED || status == WLC_SUP_KEYXCHANGE_WAIT_G1) &&
  22029. reason == WLC_E_SUP_OTHER) {
  22030. #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 15, 0))
  22031. /* NL80211_CMD_PORT_AUTHORIZED supported above >= 4.15 */
  22032. cfg80211_port_authorized(ndev, (u8 *)wl_read_prof(cfg, ndev, WL_PROF_BSSID),
  22033. GFP_KERNEL);
  22034. WL_INFORM_MEM(("4way HS finished. port authorized event sent\n"));
  22035. #elif ((LINUX_VERSION_CODE > KERNEL_VERSION(3, 14, 0)) || \
  22036. defined(WL_VENDOR_EXT_SUPPORT))
  22037. err = wl_cfgvendor_send_async_event(bcmcfg_to_wiphy(cfg), ndev,
  22038. BRCM_VENDOR_EVENT_PORT_AUTHORIZED, NULL, 0);
  22039. WL_INFORM_MEM(("4way HS finished. port authorized event sent\n"));
  22040. #else
  22041. /* not supported in kernel <= 3,14,0 */
  22042. #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(4, 15, 0) */
  22043. } else if (status < WLC_SUP_KEYXCHANGE_WAIT_G1 && reason != WLC_E_SUP_OTHER) {
  22044. /* if any failure seen while 4way HS, should send NL80211_CMD_DISCONNECT */
  22045. WL_ERR(("4way HS error. status:%d, reason:%d\n", status, reason));
  22046. CFG80211_DISCONNECTED(ndev, 0, NULL, 0, false, GFP_KERNEL);
  22047. }
  22048. return err;
  22049. }
  22050. #ifdef WL_BCNRECV
  22051. static s32
  22052. wl_bcnrecv_aborted_event_handler(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev,
  22053. const wl_event_msg_t *e, void *data)
  22054. {
  22055. s32 status = ntoh32(e->status);
  22056. struct net_device *ndev = bcmcfg_to_prmry_ndev(cfg);
  22057. /* Abort fakeapscan, when Roam is in progress */
  22058. if (status == WLC_E_STATUS_RXBCN_ABORT) {
  22059. wl_android_bcnrecv_stop(ndev, WL_BCNRECV_ROAMABORT);
  22060. } else {
  22061. WL_ERR(("UNKNOWN STATUS. status:%d\n", status));
  22062. }
  22063. return BCME_OK;
  22064. }
  22065. #endif /* WL_BCNRECV */
  22066. #ifdef WL_MBO
  22067. static s32
  22068. wl_mbo_event_handler(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev,
  22069. const wl_event_msg_t *e, void *data)
  22070. {
  22071. s32 err = 0;
  22072. wl_event_mbo_t *mbo_evt = (wl_event_mbo_t *)data;
  22073. wl_event_mbo_cell_nw_switch_t *cell_sw_evt = NULL;
  22074. wl_btm_event_type_data_t *evt_data = NULL;
  22075. WL_INFORM(("MBO: Evt %u\n", mbo_evt->type));
  22076. if (mbo_evt->type == WL_MBO_E_CELLULAR_NW_SWITCH) {
  22077. cell_sw_evt = (wl_event_mbo_cell_nw_switch_t *)mbo_evt->data;
  22078. BCM_REFERENCE(cell_sw_evt);
  22079. SUPP_EVENT(("CTRL-EVENT-CELLULAR-SWITCH", "reason %d cur_assoc_time_left %u "
  22080. "reassoc_delay %u\n", cell_sw_evt->reason,
  22081. cell_sw_evt->assoc_time_remain, cell_sw_evt->reassoc_delay));
  22082. } else if (mbo_evt->type == WL_MBO_E_BTM_RCVD) {
  22083. evt_data = (wl_btm_event_type_data_t *)mbo_evt->data;
  22084. if (evt_data->version != WL_BTM_EVENT_DATA_VER_1) {
  22085. WL_ERR(("version mismatch. rcvd %u expected %u\n",
  22086. evt_data->version, WL_BTM_EVENT_DATA_VER_1));
  22087. return -1;
  22088. }
  22089. SUPP_EVENT(("CTRL-EVENT-BRCM-BTM-REQ-RCVD", "reason=%u\n",
  22090. evt_data->transition_reason));
  22091. } else {
  22092. WL_INFORM(("UNKNOWN EVENT. type:%u\n", mbo_evt->type));
  22093. }
  22094. return err;
  22095. }
  22096. #endif /* WL_MBO */
  22097. #ifdef WL_CAC_TS
  22098. static s32
  22099. wl_cfg80211_cac_event_handler(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev,
  22100. const wl_event_msg_t *e, void *data)
  22101. {
  22102. u32 event = ntoh32(e->event_type);
  22103. s32 status = ntoh32(e->status);
  22104. s32 reason = ntoh32(e->reason);
  22105. BCM_REFERENCE(reason);
  22106. if (event == WLC_E_ADDTS_IND) {
  22107. /* The supp log format of adding ts_delay in success case needs to be maintained */
  22108. if (status == WLC_E_STATUS_SUCCESS) {
  22109. uint *ts_delay = (uint *)data;
  22110. BCM_REFERENCE(ts_delay);
  22111. SUPP_EVENT(("CTRL-EVENT-CAC-ADDTS", "status=%d reason=%d ts_delay=%u\n",
  22112. status, reason, *ts_delay));
  22113. } else {
  22114. SUPP_EVENT(("CTRL-EVENT-CAC-ADDTS", "status=%d reason=%d\n",
  22115. status, reason));
  22116. }
  22117. } else if (event == WLC_E_DELTS_IND) {
  22118. SUPP_EVENT(("CTRL-EVENT-CAC-DELTS", "status=%d reason=%d\n", status, reason));
  22119. }
  22120. return BCME_OK;
  22121. }
  22122. #endif /* WL_CAC_TS */
  22123. #if defined(WL_MBO) || defined(WL_OCE)
  22124. static s32
  22125. wl_bssid_prune_event_handler(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev,
  22126. const wl_event_msg_t *e, void *data)
  22127. {
  22128. s32 err = 0;
  22129. uint reason = 0;
  22130. wl_bssid_pruned_evt_info_t *evt_info = (wl_bssid_pruned_evt_info_t *)data;
  22131. if (evt_info->version == WL_BSSID_PRUNE_EVT_VER_1) {
  22132. if (evt_info->reason == WLC_E_PRUNE_ASSOC_RETRY_DELAY) {
  22133. /* MBO assoc retry delay */
  22134. reason = WIFI_PRUNE_ASSOC_RETRY_DELAY;
  22135. SUPP_EVENT(("CTRL-EVENT-BRCM-BSSID-PRUNED", "ssid=%s bssid=" MACF
  22136. " reason=%u timeout_val=%u(ms)\n", evt_info->SSID,
  22137. ETHER_TO_MACF(evt_info->BSSID), reason, evt_info->time_remaining));
  22138. } else if (evt_info->reason == WLC_E_PRUNE_RSSI_ASSOC_REJ) {
  22139. /* OCE RSSI-based assoc rejection */
  22140. reason = WIFI_PRUNE_RSSI_ASSOC_REJ;
  22141. SUPP_EVENT(("CTRL-EVENT-BRCM-BSSID-PRUNED", "ssid=%s bssid=" MACF
  22142. " reason=%u timeout_val=%u(ms) rssi_threshold=%d(dBm)\n",
  22143. evt_info->SSID, ETHER_TO_MACF(evt_info->BSSID),
  22144. reason, evt_info->time_remaining, evt_info->rssi_threshold));
  22145. } else {
  22146. /* Invalid other than the assoc retry delay/RSSI assoc rejection
  22147. * in the current handler
  22148. */
  22149. BCM_REFERENCE(reason);
  22150. WL_INFORM(("INVALID. reason:%u\n", evt_info->reason));
  22151. }
  22152. } else {
  22153. WL_INFORM(("version mismatch. rcvd %u expected %u\n", evt_info->version,
  22154. WL_BSSID_PRUNE_EVT_VER_1));
  22155. }
  22156. return err;
  22157. }
  22158. #endif /* WL_MBO || WL_OCE */
  22159. #ifdef RTT_SUPPORT
  22160. static s32
  22161. wl_cfg80211_rtt_event_handler(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev,
  22162. const wl_event_msg_t *e, void *data)
  22163. {
  22164. dhd_pub_t *dhdp = (dhd_pub_t *)(cfg->pub);
  22165. wl_event_msg_t event;
  22166. (void)memcpy_s(&event, sizeof(wl_event_msg_t),
  22167. e, sizeof(wl_event_msg_t));
  22168. return dhd_rtt_event_handler(dhdp, &event, data);
  22169. }
  22170. #endif /* RTT_SUPPORT */
  22171. static s32
  22172. wl_notify_dos_status(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev,
  22173. const wl_event_msg_t *e, void *data)
  22174. {
  22175. u32 event = ntoh32(e->event_type);
  22176. s32 status = ntoh32(e->status);
  22177. if (event == WLC_E_IND_DOS_STATUS)
  22178. {
  22179. WL_INFORM(("DOS_STATUS_IND_EVENT_DETECTED\n"));
  22180. if ((status) == 1) {
  22181. WL_INFORM(("NORMAL\n"));
  22182. }
  22183. else if ((status) == 2) {
  22184. WL_INFORM(("ALERT\n"));
  22185. }
  22186. else if ((status) == 3) {
  22187. WL_INFORM(("PROTECTED\n"));
  22188. }
  22189. else if ((status) == 4) {
  22190. WL_INFORM(("MONITOR\n"));
  22191. }
  22192. else {
  22193. WL_INFORM(("STATE_UNKNOWN\n"));
  22194. }
  22195. }
  22196. else
  22197. WL_INFORM(("unknown_event\n"));
  22198. return 0;
  22199. }
  22200. void
  22201. wl_print_verinfo(struct bcm_cfg80211 *cfg)
  22202. {
  22203. char *ver_ptr;
  22204. uint32 alloc_len = MOD_PARAM_INFOLEN;
  22205. if (!cfg) {
  22206. WL_ERR(("cfg is NULL\n"));
  22207. return;
  22208. }
  22209. ver_ptr = (char *)MALLOCZ(cfg->osh, alloc_len);
  22210. if (!ver_ptr) {
  22211. WL_ERR(("Failed to alloc ver_ptr\n"));
  22212. return;
  22213. }
  22214. if (!dhd_os_get_version(bcmcfg_to_prmry_ndev(cfg),
  22215. TRUE, &ver_ptr, alloc_len)) {
  22216. WL_ERR(("DHD Version: %s\n", ver_ptr));
  22217. }
  22218. if (!dhd_os_get_version(bcmcfg_to_prmry_ndev(cfg),
  22219. FALSE, &ver_ptr, alloc_len)) {
  22220. WL_ERR(("F/W Version: %s\n", ver_ptr));
  22221. }
  22222. MFREE(cfg->osh, ver_ptr, alloc_len);
  22223. }
  22224. #if defined(WL_DISABLE_HE_SOFTAP) || defined(WL_DISABLE_HE_P2P)
  22225. typedef struct {
  22226. uint16 id;
  22227. uint16 len;
  22228. uint32 val;
  22229. } he_xtlv_v32;
  22230. static bool
  22231. wl_he_get_uint_cb(void *ctx, uint16 *id, uint16 *len)
  22232. {
  22233. he_xtlv_v32 *v32 = ctx;
  22234. *id = v32->id;
  22235. *len = v32->len;
  22236. return FALSE;
  22237. }
  22238. static void
  22239. wl_he_pack_uint_cb(void *ctx, uint16 id, uint16 len, uint8 *buf)
  22240. {
  22241. he_xtlv_v32 *v32 = ctx;
  22242. BCM_REFERENCE(id);
  22243. BCM_REFERENCE(len);
  22244. v32->val = htod32(v32->val);
  22245. switch (v32->len) {
  22246. case sizeof(uint8):
  22247. *buf = (uint8)v32->val;
  22248. break;
  22249. case sizeof(uint16):
  22250. store16_ua(buf, (uint16)v32->val);
  22251. break;
  22252. case sizeof(uint32):
  22253. store32_ua(buf, v32->val);
  22254. break;
  22255. default:
  22256. /* ASSERT(0); */
  22257. break;
  22258. }
  22259. }
  22260. int wl_cfg80211_set_he_mode(struct net_device *dev, struct bcm_cfg80211 *cfg,
  22261. s32 bssidx, u32 interface_type, bool set)
  22262. {
  22263. bcm_xtlv_t read_he_xtlv;
  22264. uint8 se_he_xtlv[32];
  22265. int se_he_xtlv_len = sizeof(se_he_xtlv);
  22266. he_xtlv_v32 v32;
  22267. u32 he_feature = 0;
  22268. s32 err = 0;
  22269. u32 he_interface = 0;
  22270. read_he_xtlv.id = WL_HE_CMD_FEATURES;
  22271. read_he_xtlv.len = 0;
  22272. err = wldev_iovar_getbuf_bsscfg(dev, "he", &read_he_xtlv, sizeof(read_he_xtlv),
  22273. cfg->ioctl_buf, WLC_IOCTL_SMLEN, bssidx, NULL);
  22274. if (err < 0) {
  22275. if (err == BCME_UNSUPPORTED) {
  22276. /* HE not supported. Do nothing. */
  22277. return BCME_OK;
  22278. }
  22279. WL_ERR(("HE get failed. error=%d\n", err));
  22280. } else {
  22281. he_feature = *(int*)cfg->ioctl_buf;
  22282. he_feature = dtoh32(he_feature);
  22283. }
  22284. v32.id = WL_HE_CMD_FEATURES;
  22285. v32.len = sizeof(s32);
  22286. if (interface_type == WL_IF_TYPE_P2P_DISC) {
  22287. he_interface = WL_HE_FEATURES_HE_P2P;
  22288. } else if (interface_type == WL_IF_TYPE_AP) {
  22289. he_interface = WL_HE_FEATURES_HE_AP;
  22290. } else {
  22291. WL_ERR(("HE request for Invalid interface type"));
  22292. err = BCME_BADARG;
  22293. return err;
  22294. }
  22295. if (set) {
  22296. v32.val = (he_feature | he_interface);
  22297. } else {
  22298. v32.val = (he_feature & ~he_interface);
  22299. }
  22300. err = bcm_pack_xtlv_buf((void *)&v32, se_he_xtlv, sizeof(se_he_xtlv),
  22301. BCM_XTLV_OPTION_ALIGN32, wl_he_get_uint_cb, wl_he_pack_uint_cb,
  22302. &se_he_xtlv_len);
  22303. if (err != BCME_OK) {
  22304. WL_ERR(("failed to pack he settvl=%d\n", err));
  22305. }
  22306. err = wldev_iovar_setbuf_bsscfg(dev, "he", &se_he_xtlv, sizeof(se_he_xtlv),
  22307. cfg->ioctl_buf, WLC_IOCTL_SMLEN, bssidx, &cfg->ioctl_buf_sync);
  22308. if (err < 0) {
  22309. WL_ERR(("failed to set he features, error=%d\n", err));
  22310. }
  22311. WL_INFORM(("Set HE[%d] done\n", set));
  22312. return err;
  22313. }
  22314. #endif /* WL_DISABLE_HE_SOFTAP || WL_DISABLE_HE_P2P */
  22315. /* Get the concurrency mode */
  22316. int wl_cfg80211_get_concurrency_mode(struct bcm_cfg80211 *cfg)
  22317. {
  22318. struct net_info *iter, *next;
  22319. uint cmode = CONCURRENCY_MODE_NONE;
  22320. u32 connected_cnt = 0;
  22321. u32 pre_channel = 0, channel = 0;
  22322. u32 pre_band = 0;
  22323. u32 chanspec = 0;
  22324. u32 band = 0;
  22325. connected_cnt = wl_get_drv_status_all(cfg, CONNECTED);
  22326. if (connected_cnt <= 1) {
  22327. return cmode;
  22328. }
  22329. GCC_DIAGNOSTIC_PUSH_SUPPRESS_CAST();
  22330. for_each_ndev(cfg, iter, next) {
  22331. if (iter->ndev) {
  22332. if (wl_get_drv_status(cfg, CONNECTED, iter->ndev)) {
  22333. if (wldev_iovar_getint(iter->ndev, "chanspec",
  22334. (s32 *)&chanspec) == BCME_OK) {
  22335. channel = wf_chspec_ctlchan(
  22336. wl_chspec_driver_to_host(chanspec));
  22337. band = (channel <= CH_MAX_2G_CHANNEL) ?
  22338. IEEE80211_BAND_2GHZ : IEEE80211_BAND_5GHZ;
  22339. }
  22340. if ((!pre_channel && channel)) {
  22341. pre_band = band;
  22342. pre_channel = channel;
  22343. } else if (pre_channel) {
  22344. if ((pre_band == band) && (pre_channel == channel)) {
  22345. cmode = CONCURRENCY_SCC_MODE;
  22346. goto exit;
  22347. } else if ((pre_band == band) && (pre_channel != channel)) {
  22348. cmode = CONCURRENCY_VSDB_MODE;
  22349. goto exit;
  22350. } else if (pre_band != band) {
  22351. cmode = CONCURRENCY_RSDB_MODE;
  22352. goto exit;
  22353. }
  22354. }
  22355. }
  22356. }
  22357. }
  22358. #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == \
  22359. 4 && __GNUC_MINOR__ >= 6))
  22360. _Pragma("GCC diagnostic pop")
  22361. #endif // endif
  22362. exit:
  22363. return cmode;
  22364. }
  22365. #ifdef WL_CHAN_UTIL
  22366. static s32
  22367. wl_cfg80211_bssload_report_event_handler(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev,
  22368. const wl_event_msg_t *e, void *data)
  22369. {
  22370. s32 err = BCME_OK;
  22371. struct sk_buff *skb = NULL;
  22372. s32 status = ntoh32(e->status);
  22373. u8 chan_use_percentage = 0;
  22374. #if (defined(CONFIG_ARCH_MSM) && defined(SUPPORT_WDEV_CFG80211_VENDOR_EVENT_ALLOC)) || \
  22375. LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0)
  22376. struct net_device *ndev = bcmcfg_to_prmry_ndev(cfg);
  22377. #endif /* (defined(CONFIG_ARCH_MSM) && defined(SUPPORT_WDEV_CFG80211_VENDOR_EVENT_ALLOC)) || */
  22378. /* LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0) */
  22379. #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0))
  22380. struct wiphy *wiphy = bcmcfg_to_wiphy(cfg);
  22381. uint len;
  22382. gfp_t kflags;
  22383. #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0) */
  22384. #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0))
  22385. len = CU_ATTR_HDR_LEN + sizeof(u8);
  22386. kflags = in_atomic() ? GFP_ATOMIC : GFP_KERNEL;
  22387. #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0) */
  22388. #if (defined(CONFIG_ARCH_MSM) && defined(SUPPORT_WDEV_CFG80211_VENDOR_EVENT_ALLOC)) || \
  22389. LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0)
  22390. skb = cfg80211_vendor_event_alloc(wiphy, ndev_to_wdev(ndev), len,
  22391. BRCM_VENDOR_EVENT_CU, kflags);
  22392. #elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0))
  22393. skb = cfg80211_vendor_event_alloc(wiphy, len, BRCM_VENDOR_EVENT_CU, kflags);
  22394. #else
  22395. /* No support exist */
  22396. #endif /* (defined(CONFIG_ARCH_MSM) && defined(SUPPORT_WDEV_CFG80211_VENDOR_EVENT_ALLOC)) || */
  22397. /* LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0) */
  22398. if (!skb) {
  22399. WL_ERR(("skb alloc failed"));
  22400. return -ENOMEM;
  22401. }
  22402. if ((status == WLC_E_STATUS_SUCCESS) && data) {
  22403. wl_bssload_t *bssload_report = (wl_bssload_t *)data;
  22404. chan_use_percentage = (bssload_report->chan_util * 100) / 255;
  22405. WL_DBG(("ChannelUtilization=%hhu\n", chan_use_percentage));
  22406. err = nla_put_u8(skb, CU_ATTR_PERCENTAGE, chan_use_percentage);
  22407. if (err < 0) {
  22408. WL_ERR(("Failed to put CU_ATTR_PERCENTAGE, err:%d\n", err));
  22409. }
  22410. }
  22411. #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0))
  22412. cfg80211_vendor_event(skb, kflags);
  22413. #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0) */
  22414. return err;
  22415. }
  22416. #define WL_CHAN_UTIL_DEFAULT_INTERVAL 3000
  22417. #define WL_CHAN_UTIL_THRESH_MIN 15
  22418. #define WL_CHAN_UTIL_THRESH_INTERVAL 10
  22419. #ifndef CUSTOM_CU_INTERVAL
  22420. #define CUSTOM_CU_INTERVAL WL_CHAN_UTIL_DEFAULT_INTERVAL
  22421. #endif /* CUSTOM_CU_INTERVAL */
  22422. static s32
  22423. wl_cfg80211_start_bssload_report(struct net_device *ndev)
  22424. {
  22425. s32 err = BCME_OK;
  22426. wl_bssload_cfg_t blcfg;
  22427. u8 i;
  22428. struct bcm_cfg80211 *cfg;
  22429. if (!ndev) {
  22430. return -ENODEV;
  22431. }
  22432. cfg = wl_get_cfg(ndev);
  22433. if (!cfg) {
  22434. return -ENODEV;
  22435. }
  22436. /* Typecasting to void as the buffer size is same as the memset size */
  22437. (void)memset_s(&blcfg, sizeof(wl_bssload_cfg_t), 0, sizeof(wl_bssload_cfg_t));
  22438. /* Set default report interval 3 sec and 8 threshhold levels between 15 to 85% */
  22439. blcfg.rate_limit_msec = CUSTOM_CU_INTERVAL;
  22440. blcfg.num_util_levels = MAX_BSSLOAD_LEVELS;
  22441. for (i = 0; i < MAX_BSSLOAD_LEVELS; i++) {
  22442. blcfg.util_levels[i] = (((WL_CHAN_UTIL_THRESH_MIN +
  22443. (i * WL_CHAN_UTIL_THRESH_INTERVAL)) * 255) / 100);
  22444. }
  22445. err = wldev_iovar_setbuf(ndev, "bssload_report_event", &blcfg,
  22446. sizeof(wl_bssload_cfg_t), cfg->ioctl_buf, WLC_IOCTL_SMLEN, &cfg->ioctl_buf_sync);
  22447. if (unlikely(err)) {
  22448. WL_ERR(("Set event_msgs error (%d)\n", err));
  22449. }
  22450. return err;
  22451. }
  22452. #endif /* WL_CHAN_UTIL */
  22453. s32
  22454. wl_cfg80211_config_suspend_events(struct net_device *ndev, bool enable)
  22455. {
  22456. s8 iovbuf[WL_EVENTING_MASK_LEN + 12];
  22457. s8 eventmask[WL_EVENTING_MASK_LEN];
  22458. s32 err = 0;
  22459. struct bcm_cfg80211 *cfg;
  22460. if (!ndev) {
  22461. return -ENODEV;
  22462. }
  22463. cfg = wl_get_cfg(ndev);
  22464. if (!cfg) {
  22465. return -ENODEV;
  22466. }
  22467. mutex_lock(&cfg->event_sync);
  22468. err = wldev_iovar_getbuf(ndev, "event_msgs", NULL, 0, iovbuf, sizeof(iovbuf), NULL);
  22469. if (unlikely(err)) {
  22470. WL_ERR(("Get event_msgs error (%d)\n", err));
  22471. goto eventmsg_out;
  22472. }
  22473. (void)memcpy_s(eventmask, WL_EVENTING_MASK_LEN, iovbuf, WL_EVENTING_MASK_LEN);
  22474. /* Add set/clear of event mask under feature specific flags */
  22475. if (enable) {
  22476. WL_DBG(("%s: Enabling events on resume\n", __FUNCTION__));
  22477. #ifdef WL_CHAN_UTIL
  22478. setbit(eventmask, WLC_E_BSS_LOAD);
  22479. #endif /* WL_CHAN_UTIL */
  22480. } else {
  22481. WL_DBG(("%s: Disabling events before suspend\n", __FUNCTION__));
  22482. #ifdef WL_CHAN_UTIL
  22483. clrbit(eventmask, WLC_E_BSS_LOAD);
  22484. #endif /* WL_CHAN_UTIL */
  22485. }
  22486. err = wldev_iovar_setbuf(ndev, "event_msgs", eventmask, WL_EVENTING_MASK_LEN, iovbuf,
  22487. sizeof(iovbuf), NULL);
  22488. if (unlikely(err)) {
  22489. WL_ERR(("Set event_msgs error (%d)\n", err));
  22490. goto eventmsg_out;
  22491. }
  22492. eventmsg_out:
  22493. mutex_unlock(&cfg->event_sync);
  22494. return err;
  22495. }
  22496. #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 12, 0))
  22497. int
  22498. wl_cfg80211_channel_switch(struct wiphy *wiphy, struct net_device *dev,
  22499. struct cfg80211_csa_settings *params)
  22500. {
  22501. s32 err = BCME_OK;
  22502. s32 chan = 0;
  22503. u32 band = 0;
  22504. u32 bw = WL_CHANSPEC_BW_20;
  22505. chanspec_t chspec = 0;
  22506. wl_chan_switch_t csa_arg;
  22507. struct cfg80211_chan_def *chandef = &params->chandef;
  22508. struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
  22509. dev = ndev_to_wlc_ndev(dev, cfg);
  22510. chan = ieee80211_frequency_to_channel(chandef->chan->center_freq);
  22511. band = chandef->chan->band;
  22512. WL_ERR(("netdev_ifidx(%d), target channel(%d) target bandwidth(%d),"
  22513. " mode(%d), count(%d)\n", dev->ifindex, chan, chandef->width,
  22514. params->block_tx, params->count));
  22515. if (wl_get_mode_by_netdev(cfg, dev) != WL_MODE_AP) {
  22516. WL_ERR(("Channel Switch doesn't support on "
  22517. "the non-SoftAP mode\n"));
  22518. return -EINVAL;
  22519. }
  22520. if (chan == cfg->ap_oper_channel) {
  22521. WL_ERR(("Channel %d is same as current operating channel,"
  22522. " so skip\n", chan));
  22523. return BCME_OK;
  22524. }
  22525. if (band == IEEE80211_BAND_5GHZ) {
  22526. #ifdef APSTA_RESTRICTED_CHANNEL
  22527. if (chan != DEFAULT_5G_SOFTAP_CHANNEL) {
  22528. WL_ERR(("Invalid 5G Channel, chan=%d\n", chan));
  22529. return -EINVAL;
  22530. }
  22531. #endif /* APSTA_RESTRICTED_CHANNEL */
  22532. err = wl_get_bandwidth_cap(bcmcfg_to_prmry_ndev(cfg),
  22533. band, &bw);
  22534. if (err < 0) {
  22535. WL_ERR(("Failed to get bandwidth information,"
  22536. " err=%d\n", err));
  22537. return err;
  22538. }
  22539. } else if (band == IEEE80211_BAND_2GHZ) {
  22540. #ifdef APSTA_RESTRICTED_CHANNEL
  22541. dhd_pub_t *dhdp = (dhd_pub_t *)(cfg->pub);
  22542. u32 *sta_chan = (u32 *)wl_read_prof(cfg,
  22543. bcmcfg_to_prmry_ndev(cfg), WL_PROF_CHAN);
  22544. /* In 2GHz STA/SoftAP concurrent mode, the operating channel
  22545. * of STA and SoftAP should be confgiured to the same 2GHz
  22546. * channel. Otherwise, it is an invalid configuration.
  22547. */
  22548. if (DHD_OPMODE_STA_SOFTAP_CONCURR(dhdp) &&
  22549. wl_get_drv_status(cfg, CONNECTED,
  22550. bcmcfg_to_prmry_ndev(cfg)) && sta_chan &&
  22551. (*sta_chan != chan)) {
  22552. WL_ERR(("Invalid 2G Channel in case of STA/SoftAP"
  22553. " concurrent mode, sta_chan=%d, chan=%d\n",
  22554. *sta_chan, chan));
  22555. return -EINVAL;
  22556. }
  22557. #endif /* APSTA_RESTRICTED_CHANNEL */
  22558. bw = WL_CHANSPEC_BW_20;
  22559. } else {
  22560. WL_ERR(("invalid band (%d)\n", band));
  22561. return -EINVAL;
  22562. }
  22563. chspec = wf_channel2chspec(chan, bw);
  22564. if (!wf_chspec_valid(chspec)) {
  22565. WL_ERR(("Invalid chanspec 0x%x\n", chspec));
  22566. return -EINVAL;
  22567. }
  22568. /* Send CSA to associated STAs */
  22569. memset(&csa_arg, 0, sizeof(wl_chan_switch_t));
  22570. csa_arg.mode = params->block_tx;
  22571. csa_arg.count = params->count;
  22572. csa_arg.chspec = chspec;
  22573. csa_arg.frame_type = CSA_BROADCAST_ACTION_FRAME;
  22574. csa_arg.reg = 0;
  22575. err = wldev_iovar_setbuf(dev, "csa", &csa_arg, sizeof(wl_chan_switch_t),
  22576. cfg->ioctl_buf, WLC_IOCTL_SMLEN, &cfg->ioctl_buf_sync);
  22577. if (err < 0) {
  22578. WL_ERR(("Failed to switch channel, err=%d\n", err));
  22579. }
  22580. return err;
  22581. }
  22582. #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 12, 0) */
  22583. #ifdef WL_WIPSEVT
  22584. int
  22585. wl_cfg80211_wips_event(uint16 misdeauth, char* bssid)
  22586. {
  22587. s32 err = BCME_OK;
  22588. #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0))
  22589. struct sk_buff *skb;
  22590. gfp_t kflags;
  22591. struct bcm_cfg80211 *cfg;
  22592. struct net_device *ndev;
  22593. struct wiphy *wiphy;
  22594. cfg = wl_cfg80211_get_bcmcfg();
  22595. if (!cfg || !cfg->wdev) {
  22596. WL_ERR(("WIPS evt invalid arg\n"));
  22597. return err;
  22598. }
  22599. ndev = bcmcfg_to_prmry_ndev(cfg);
  22600. wiphy = bcmcfg_to_wiphy(cfg);
  22601. kflags = in_atomic() ? GFP_ATOMIC : GFP_KERNEL;
  22602. skb = CFG80211_VENDOR_EVENT_ALLOC(wiphy, ndev_to_wdev(ndev),
  22603. BRCM_VENDOR_WIPS_EVENT_BUF_LEN, BRCM_VENDOR_EVENT_WIPS, kflags);
  22604. if (!skb) {
  22605. WL_ERR(("skb alloc failed"));
  22606. return BCME_NOMEM;
  22607. }
  22608. err = nla_put_u16(skb, WIPS_ATTR_DEAUTH_CNT, misdeauth);
  22609. if (unlikely(err)) {
  22610. WL_ERR(("nla_put_u16 WIPS_ATTR_DEAUTH_CNT failed\n"));
  22611. goto fail;
  22612. }
  22613. err = nla_put(skb, WPPS_ATTR_DEAUTH_BSSID, ETHER_ADDR_LEN, bssid);
  22614. if (unlikely(err)) {
  22615. WL_ERR(("nla_put WPPS_ATTR_DEAUTH_BSSID failed\n"));
  22616. goto fail;
  22617. }
  22618. cfg80211_vendor_event(skb, kflags);
  22619. return err;
  22620. fail:
  22621. if (skb) {
  22622. nlmsg_free(skb);
  22623. }
  22624. #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0) */
  22625. return err;
  22626. }
  22627. #endif /* WL_WIPSEVT */