705-dpaa2-support-layerscape.patch 658 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832383338343835383638373838383938403841384238433844384538463847384838493850385138523853385438553856385738583859386038613862386338643865386638673868386938703871387238733874387538763877387838793880388138823883388438853886388738883889389038913892389338943895389638973898389939003901390239033904390539063907390839093910391139123913391439153916391739183919392039213922392339243925392639273928392939303931393239333934393539363937393839393940394139423943394439453946394739483949395039513952395339543955395639573958395939603961396239633964396539663967396839693970397139723973397439753976397739783979398039813982398339843985398639873988398939903991399239933994399539963997399839994000400140024003400440054006400740084009401040114012401340144015401640174018401940204021402240234024402540264027402840294030403140324033403440354036403740384039404040414042404340444045404640474048404940504051405240534054405540564057405840594060406140624063406440654066406740684069407040714072407340744075407640774078407940804081408240834084408540864087408840894090409140924093409440954096409740984099410041014102410341044105410641074108410941104111411241134114411541164117411841194120412141224123412441254126412741284129413041314132413341344135413641374138413941404141414241434144414541464147414841494150415141524153415441554156415741584159416041614162416341644165416641674168416941704171417241734174417541764177417841794180418141824183418441854186418741884189419041914192419341944195419641974198419942004201420242034204420542064207420842094210421142124213421442154216421742184219422042214222422342244225422642274228422942304231423242334234423542364237423842394240424142424243424442454246424742484249425042514252425342544255425642574258425942604261426242634264426542664267426842694270427142724273427442754276427742784279428042814282428342844285428642874288428942904291429242934294429542964297429842994300430143024303430443054306430743084309431043114312431343144315431643174318431943204321432243234324432543264327432843294330433143324333433443354336433743384339434043414342434343444345434643474348434943504351435243534354435543564357435843594360436143624363436443654366436743684369437043714372437343744375437643774378437943804381438243834384438543864387438843894390439143924393439443954396439743984399440044014402440344044405440644074408440944104411441244134414441544164417441844194420442144224423442444254426442744284429443044314432443344344435443644374438443944404441444244434444444544464447444844494450445144524453445444554456445744584459446044614462446344644465446644674468446944704471447244734474447544764477447844794480448144824483448444854486448744884489449044914492449344944495449644974498449945004501450245034504450545064507450845094510451145124513451445154516451745184519452045214522452345244525452645274528452945304531453245334534453545364537453845394540454145424543454445454546454745484549455045514552455345544555455645574558455945604561456245634564456545664567456845694570457145724573457445754576457745784579458045814582458345844585458645874588458945904591459245934594459545964597459845994600460146024603460446054606460746084609461046114612461346144615461646174618461946204621462246234624462546264627462846294630463146324633463446354636463746384639464046414642464346444645464646474648464946504651465246534654465546564657465846594660466146624663466446654666466746684669467046714672467346744675467646774678467946804681468246834684468546864687468846894690469146924693469446954696469746984699470047014702470347044705470647074708470947104711471247134714471547164717471847194720472147224723472447254726472747284729473047314732473347344735473647374738473947404741474247434744474547464747474847494750475147524753475447554756475747584759476047614762476347644765476647674768476947704771477247734774477547764777477847794780478147824783478447854786478747884789479047914792479347944795479647974798479948004801480248034804480548064807480848094810481148124813481448154816481748184819482048214822482348244825482648274828482948304831483248334834483548364837483848394840484148424843484448454846484748484849485048514852485348544855485648574858485948604861486248634864486548664867486848694870487148724873487448754876487748784879488048814882488348844885488648874888488948904891489248934894489548964897489848994900490149024903490449054906490749084909491049114912491349144915491649174918491949204921492249234924492549264927492849294930493149324933493449354936493749384939494049414942494349444945494649474948494949504951495249534954495549564957495849594960496149624963496449654966496749684969497049714972497349744975497649774978497949804981498249834984498549864987498849894990499149924993499449954996499749984999500050015002500350045005500650075008500950105011501250135014501550165017501850195020502150225023502450255026502750285029503050315032503350345035503650375038503950405041504250435044504550465047504850495050505150525053505450555056505750585059506050615062506350645065506650675068506950705071507250735074507550765077507850795080508150825083508450855086508750885089509050915092509350945095509650975098509951005101510251035104510551065107510851095110511151125113511451155116511751185119512051215122512351245125512651275128512951305131513251335134513551365137513851395140514151425143514451455146514751485149515051515152515351545155515651575158515951605161516251635164516551665167516851695170517151725173517451755176517751785179518051815182518351845185518651875188518951905191519251935194519551965197519851995200520152025203520452055206520752085209521052115212521352145215521652175218521952205221522252235224522552265227522852295230523152325233523452355236523752385239524052415242524352445245524652475248524952505251525252535254525552565257525852595260526152625263526452655266526752685269527052715272527352745275527652775278527952805281528252835284528552865287528852895290529152925293529452955296529752985299530053015302530353045305530653075308530953105311531253135314531553165317531853195320532153225323532453255326532753285329533053315332533353345335533653375338533953405341534253435344534553465347534853495350535153525353535453555356535753585359536053615362536353645365536653675368536953705371537253735374537553765377537853795380538153825383538453855386538753885389539053915392539353945395539653975398539954005401540254035404540554065407540854095410541154125413541454155416541754185419542054215422542354245425542654275428542954305431543254335434543554365437543854395440544154425443544454455446544754485449545054515452545354545455545654575458545954605461546254635464546554665467546854695470547154725473547454755476547754785479548054815482548354845485548654875488548954905491549254935494549554965497549854995500550155025503550455055506550755085509551055115512551355145515551655175518551955205521552255235524552555265527552855295530553155325533553455355536553755385539554055415542554355445545554655475548554955505551555255535554555555565557555855595560556155625563556455655566556755685569557055715572557355745575557655775578557955805581558255835584558555865587558855895590559155925593559455955596559755985599560056015602560356045605560656075608560956105611561256135614561556165617561856195620562156225623562456255626562756285629563056315632563356345635563656375638563956405641564256435644564556465647564856495650565156525653565456555656565756585659566056615662566356645665566656675668566956705671567256735674567556765677567856795680568156825683568456855686568756885689569056915692569356945695569656975698569957005701570257035704570557065707570857095710571157125713571457155716571757185719572057215722572357245725572657275728572957305731573257335734573557365737573857395740574157425743574457455746574757485749575057515752575357545755575657575758575957605761576257635764576557665767576857695770577157725773577457755776577757785779578057815782578357845785578657875788578957905791579257935794579557965797579857995800580158025803580458055806580758085809581058115812581358145815581658175818581958205821582258235824582558265827582858295830583158325833583458355836583758385839584058415842584358445845584658475848584958505851585258535854585558565857585858595860586158625863586458655866586758685869587058715872587358745875587658775878587958805881588258835884588558865887588858895890589158925893589458955896589758985899590059015902590359045905590659075908590959105911591259135914591559165917591859195920592159225923592459255926592759285929593059315932593359345935593659375938593959405941594259435944594559465947594859495950595159525953595459555956595759585959596059615962596359645965596659675968596959705971597259735974597559765977597859795980598159825983598459855986598759885989599059915992599359945995599659975998599960006001600260036004600560066007600860096010601160126013601460156016601760186019602060216022602360246025602660276028602960306031603260336034603560366037603860396040604160426043604460456046604760486049605060516052605360546055605660576058605960606061606260636064606560666067606860696070607160726073607460756076607760786079608060816082608360846085608660876088608960906091609260936094609560966097609860996100610161026103610461056106610761086109611061116112611361146115611661176118611961206121612261236124612561266127612861296130613161326133613461356136613761386139614061416142614361446145614661476148614961506151615261536154615561566157615861596160616161626163616461656166616761686169617061716172617361746175617661776178617961806181618261836184618561866187618861896190619161926193619461956196619761986199620062016202620362046205620662076208620962106211621262136214621562166217621862196220622162226223622462256226622762286229623062316232623362346235623662376238623962406241624262436244624562466247624862496250625162526253625462556256625762586259626062616262626362646265626662676268626962706271627262736274627562766277627862796280628162826283628462856286628762886289629062916292629362946295629662976298629963006301630263036304630563066307630863096310631163126313631463156316631763186319632063216322632363246325632663276328632963306331633263336334633563366337633863396340634163426343634463456346634763486349635063516352635363546355635663576358635963606361636263636364636563666367636863696370637163726373637463756376637763786379638063816382638363846385638663876388638963906391639263936394639563966397639863996400640164026403640464056406640764086409641064116412641364146415641664176418641964206421642264236424642564266427642864296430643164326433643464356436643764386439644064416442644364446445644664476448644964506451645264536454645564566457645864596460646164626463646464656466646764686469647064716472647364746475647664776478647964806481648264836484648564866487648864896490649164926493649464956496649764986499650065016502650365046505650665076508650965106511651265136514651565166517651865196520652165226523652465256526652765286529653065316532653365346535653665376538653965406541654265436544654565466547654865496550655165526553655465556556655765586559656065616562656365646565656665676568656965706571657265736574657565766577657865796580658165826583658465856586658765886589659065916592659365946595659665976598659966006601660266036604660566066607660866096610661166126613661466156616661766186619662066216622662366246625662666276628662966306631663266336634663566366637663866396640664166426643664466456646664766486649665066516652665366546655665666576658665966606661666266636664666566666667666866696670667166726673667466756676667766786679668066816682668366846685668666876688668966906691669266936694669566966697669866996700670167026703670467056706670767086709671067116712671367146715671667176718671967206721672267236724672567266727672867296730673167326733673467356736673767386739674067416742674367446745674667476748674967506751675267536754675567566757675867596760676167626763676467656766676767686769677067716772677367746775677667776778677967806781678267836784678567866787678867896790679167926793679467956796679767986799680068016802680368046805680668076808680968106811681268136814681568166817681868196820682168226823682468256826682768286829683068316832683368346835683668376838683968406841684268436844684568466847684868496850685168526853685468556856685768586859686068616862686368646865686668676868686968706871687268736874687568766877687868796880688168826883688468856886688768886889689068916892689368946895689668976898689969006901690269036904690569066907690869096910691169126913691469156916691769186919692069216922692369246925692669276928692969306931693269336934693569366937693869396940694169426943694469456946694769486949695069516952695369546955695669576958695969606961696269636964696569666967696869696970697169726973697469756976697769786979698069816982698369846985698669876988698969906991699269936994699569966997699869997000700170027003700470057006700770087009701070117012701370147015701670177018701970207021702270237024702570267027702870297030703170327033703470357036703770387039704070417042704370447045704670477048704970507051705270537054705570567057705870597060706170627063706470657066706770687069707070717072707370747075707670777078707970807081708270837084708570867087708870897090709170927093709470957096709770987099710071017102710371047105710671077108710971107111711271137114711571167117711871197120712171227123712471257126712771287129713071317132713371347135713671377138713971407141714271437144714571467147714871497150715171527153715471557156715771587159716071617162716371647165716671677168716971707171717271737174717571767177717871797180718171827183718471857186718771887189719071917192719371947195719671977198719972007201720272037204720572067207720872097210721172127213721472157216721772187219722072217222722372247225722672277228722972307231723272337234723572367237723872397240724172427243724472457246724772487249725072517252725372547255725672577258725972607261726272637264726572667267726872697270727172727273727472757276727772787279728072817282728372847285728672877288728972907291729272937294729572967297729872997300730173027303730473057306730773087309731073117312731373147315731673177318731973207321732273237324732573267327732873297330733173327333733473357336733773387339734073417342734373447345734673477348734973507351735273537354735573567357735873597360736173627363736473657366736773687369737073717372737373747375737673777378737973807381738273837384738573867387738873897390739173927393739473957396739773987399740074017402740374047405740674077408740974107411741274137414741574167417741874197420742174227423742474257426742774287429743074317432743374347435743674377438743974407441744274437444744574467447744874497450745174527453745474557456745774587459746074617462746374647465746674677468746974707471747274737474747574767477747874797480748174827483748474857486748774887489749074917492749374947495749674977498749975007501750275037504750575067507750875097510751175127513751475157516751775187519752075217522752375247525752675277528752975307531753275337534753575367537753875397540754175427543754475457546754775487549755075517552755375547555755675577558755975607561756275637564756575667567756875697570757175727573757475757576757775787579758075817582758375847585758675877588758975907591759275937594759575967597759875997600760176027603760476057606760776087609761076117612761376147615761676177618761976207621762276237624762576267627762876297630763176327633763476357636763776387639764076417642764376447645764676477648764976507651765276537654765576567657765876597660766176627663766476657666766776687669767076717672767376747675767676777678767976807681768276837684768576867687768876897690769176927693769476957696769776987699770077017702770377047705770677077708770977107711771277137714771577167717771877197720772177227723772477257726772777287729773077317732773377347735773677377738773977407741774277437744774577467747774877497750775177527753775477557756775777587759776077617762776377647765776677677768776977707771777277737774777577767777777877797780778177827783778477857786778777887789779077917792779377947795779677977798779978007801780278037804780578067807780878097810781178127813781478157816781778187819782078217822782378247825782678277828782978307831783278337834783578367837783878397840784178427843784478457846784778487849785078517852785378547855785678577858785978607861786278637864786578667867786878697870787178727873787478757876787778787879788078817882788378847885788678877888788978907891789278937894789578967897789878997900790179027903790479057906790779087909791079117912791379147915791679177918791979207921792279237924792579267927792879297930793179327933793479357936793779387939794079417942794379447945794679477948794979507951795279537954795579567957795879597960796179627963796479657966796779687969797079717972797379747975797679777978797979807981798279837984798579867987798879897990799179927993799479957996799779987999800080018002800380048005800680078008800980108011801280138014801580168017801880198020802180228023802480258026802780288029803080318032803380348035803680378038803980408041804280438044804580468047804880498050805180528053805480558056805780588059806080618062806380648065806680678068806980708071807280738074807580768077807880798080808180828083808480858086808780888089809080918092809380948095809680978098809981008101810281038104810581068107810881098110811181128113811481158116811781188119812081218122812381248125812681278128812981308131813281338134813581368137813881398140814181428143814481458146814781488149815081518152815381548155815681578158815981608161816281638164816581668167816881698170817181728173817481758176817781788179818081818182818381848185818681878188818981908191819281938194819581968197819881998200820182028203820482058206820782088209821082118212821382148215821682178218821982208221822282238224822582268227822882298230823182328233823482358236823782388239824082418242824382448245824682478248824982508251825282538254825582568257825882598260826182628263826482658266826782688269827082718272827382748275827682778278827982808281828282838284828582868287828882898290829182928293829482958296829782988299830083018302830383048305830683078308830983108311831283138314831583168317831883198320832183228323832483258326832783288329833083318332833383348335833683378338833983408341834283438344834583468347834883498350835183528353835483558356835783588359836083618362836383648365836683678368836983708371837283738374837583768377837883798380838183828383838483858386838783888389839083918392839383948395839683978398839984008401840284038404840584068407840884098410841184128413841484158416841784188419842084218422842384248425842684278428842984308431843284338434843584368437843884398440844184428443844484458446844784488449845084518452845384548455845684578458845984608461846284638464846584668467846884698470847184728473847484758476847784788479848084818482848384848485848684878488848984908491849284938494849584968497849884998500850185028503850485058506850785088509851085118512851385148515851685178518851985208521852285238524852585268527852885298530853185328533853485358536853785388539854085418542854385448545854685478548854985508551855285538554855585568557855885598560856185628563856485658566856785688569857085718572857385748575857685778578857985808581858285838584858585868587858885898590859185928593859485958596859785988599860086018602860386048605860686078608860986108611861286138614861586168617861886198620862186228623862486258626862786288629863086318632863386348635863686378638863986408641864286438644864586468647864886498650865186528653865486558656865786588659866086618662866386648665866686678668866986708671867286738674867586768677867886798680868186828683868486858686868786888689869086918692869386948695869686978698869987008701870287038704870587068707870887098710871187128713871487158716871787188719872087218722872387248725872687278728872987308731873287338734873587368737873887398740874187428743874487458746874787488749875087518752875387548755875687578758875987608761876287638764876587668767876887698770877187728773877487758776877787788779878087818782878387848785878687878788878987908791879287938794879587968797879887998800880188028803880488058806880788088809881088118812881388148815881688178818881988208821882288238824882588268827882888298830883188328833883488358836883788388839884088418842884388448845884688478848884988508851885288538854885588568857885888598860886188628863886488658866886788688869887088718872887388748875887688778878887988808881888288838884888588868887888888898890889188928893889488958896889788988899890089018902890389048905890689078908890989108911891289138914891589168917891889198920892189228923892489258926892789288929893089318932893389348935893689378938893989408941894289438944894589468947894889498950895189528953895489558956895789588959896089618962896389648965896689678968896989708971897289738974897589768977897889798980898189828983898489858986898789888989899089918992899389948995899689978998899990009001900290039004900590069007900890099010901190129013901490159016901790189019902090219022902390249025902690279028902990309031903290339034903590369037903890399040904190429043904490459046904790489049905090519052905390549055905690579058905990609061906290639064906590669067906890699070907190729073907490759076907790789079908090819082908390849085908690879088908990909091909290939094909590969097909890999100910191029103910491059106910791089109911091119112911391149115911691179118911991209121912291239124912591269127912891299130913191329133913491359136913791389139914091419142914391449145914691479148914991509151915291539154915591569157915891599160916191629163916491659166916791689169917091719172917391749175917691779178917991809181918291839184918591869187918891899190919191929193919491959196919791989199920092019202920392049205920692079208920992109211921292139214921592169217921892199220922192229223922492259226922792289229923092319232923392349235923692379238923992409241924292439244924592469247924892499250925192529253925492559256925792589259926092619262926392649265926692679268926992709271927292739274927592769277927892799280928192829283928492859286928792889289929092919292929392949295929692979298929993009301930293039304930593069307930893099310931193129313931493159316931793189319932093219322932393249325932693279328932993309331933293339334933593369337933893399340934193429343934493459346934793489349935093519352935393549355935693579358935993609361936293639364936593669367936893699370937193729373937493759376937793789379938093819382938393849385938693879388938993909391939293939394939593969397939893999400940194029403940494059406940794089409941094119412941394149415941694179418941994209421942294239424942594269427942894299430943194329433943494359436943794389439944094419442944394449445944694479448944994509451945294539454945594569457945894599460946194629463946494659466946794689469947094719472947394749475947694779478947994809481948294839484948594869487948894899490949194929493949494959496949794989499950095019502950395049505950695079508950995109511951295139514951595169517951895199520952195229523952495259526952795289529953095319532953395349535953695379538953995409541954295439544954595469547954895499550955195529553955495559556955795589559956095619562956395649565956695679568956995709571957295739574957595769577957895799580958195829583958495859586958795889589959095919592959395949595959695979598959996009601960296039604960596069607960896099610961196129613961496159616961796189619962096219622962396249625962696279628962996309631963296339634963596369637963896399640964196429643964496459646964796489649965096519652965396549655965696579658965996609661966296639664966596669667966896699670967196729673967496759676967796789679968096819682968396849685968696879688968996909691969296939694969596969697969896999700970197029703970497059706970797089709971097119712971397149715971697179718971997209721972297239724972597269727972897299730973197329733973497359736973797389739974097419742974397449745974697479748974997509751975297539754975597569757975897599760976197629763976497659766976797689769977097719772977397749775977697779778977997809781978297839784978597869787978897899790979197929793979497959796979797989799980098019802980398049805980698079808980998109811981298139814981598169817981898199820982198229823982498259826982798289829983098319832983398349835983698379838983998409841984298439844984598469847984898499850985198529853985498559856985798589859986098619862986398649865986698679868986998709871987298739874987598769877987898799880988198829883988498859886988798889889989098919892989398949895989698979898989999009901990299039904990599069907990899099910991199129913991499159916991799189919992099219922992399249925992699279928992999309931993299339934993599369937993899399940994199429943994499459946994799489949995099519952995399549955995699579958995999609961996299639964996599669967996899699970997199729973997499759976997799789979998099819982998399849985998699879988998999909991999299939994999599969997999899991000010001100021000310004100051000610007100081000910010100111001210013100141001510016100171001810019100201002110022100231002410025100261002710028100291003010031100321003310034100351003610037100381003910040100411004210043100441004510046100471004810049100501005110052100531005410055100561005710058100591006010061100621006310064100651006610067100681006910070100711007210073100741007510076100771007810079100801008110082100831008410085100861008710088100891009010091100921009310094100951009610097100981009910100101011010210103101041010510106101071010810109101101011110112101131011410115101161011710118101191012010121101221012310124101251012610127101281012910130101311013210133101341013510136101371013810139101401014110142101431014410145101461014710148101491015010151101521015310154101551015610157101581015910160101611016210163101641016510166101671016810169101701017110172101731017410175101761017710178101791018010181101821018310184101851018610187101881018910190101911019210193101941019510196101971019810199102001020110202102031020410205102061020710208102091021010211102121021310214102151021610217102181021910220102211022210223102241022510226102271022810229102301023110232102331023410235102361023710238102391024010241102421024310244102451024610247102481024910250102511025210253102541025510256102571025810259102601026110262102631026410265102661026710268102691027010271102721027310274102751027610277102781027910280102811028210283102841028510286102871028810289102901029110292102931029410295102961029710298102991030010301103021030310304103051030610307103081030910310103111031210313103141031510316103171031810319103201032110322103231032410325103261032710328103291033010331103321033310334103351033610337103381033910340103411034210343103441034510346103471034810349103501035110352103531035410355103561035710358103591036010361103621036310364103651036610367103681036910370103711037210373103741037510376103771037810379103801038110382103831038410385103861038710388103891039010391103921039310394103951039610397103981039910400104011040210403104041040510406104071040810409104101041110412104131041410415104161041710418104191042010421104221042310424104251042610427104281042910430104311043210433104341043510436104371043810439104401044110442104431044410445104461044710448104491045010451104521045310454104551045610457104581045910460104611046210463104641046510466104671046810469104701047110472104731047410475104761047710478104791048010481104821048310484104851048610487104881048910490104911049210493104941049510496104971049810499105001050110502105031050410505105061050710508105091051010511105121051310514105151051610517105181051910520105211052210523105241052510526105271052810529105301053110532105331053410535105361053710538105391054010541105421054310544105451054610547105481054910550105511055210553105541055510556105571055810559105601056110562105631056410565105661056710568105691057010571105721057310574105751057610577105781057910580105811058210583105841058510586105871058810589105901059110592105931059410595105961059710598105991060010601106021060310604106051060610607106081060910610106111061210613106141061510616106171061810619106201062110622106231062410625106261062710628106291063010631106321063310634106351063610637106381063910640106411064210643106441064510646106471064810649106501065110652106531065410655106561065710658106591066010661106621066310664106651066610667106681066910670106711067210673106741067510676106771067810679106801068110682106831068410685106861068710688106891069010691106921069310694106951069610697106981069910700107011070210703107041070510706107071070810709107101071110712107131071410715107161071710718107191072010721107221072310724107251072610727107281072910730107311073210733107341073510736107371073810739107401074110742107431074410745107461074710748107491075010751107521075310754107551075610757107581075910760107611076210763107641076510766107671076810769107701077110772107731077410775107761077710778107791078010781107821078310784107851078610787107881078910790107911079210793107941079510796107971079810799108001080110802108031080410805108061080710808108091081010811108121081310814108151081610817108181081910820108211082210823108241082510826108271082810829108301083110832108331083410835108361083710838108391084010841108421084310844108451084610847108481084910850108511085210853108541085510856108571085810859108601086110862108631086410865108661086710868108691087010871108721087310874108751087610877108781087910880108811088210883108841088510886108871088810889108901089110892108931089410895108961089710898108991090010901109021090310904109051090610907109081090910910109111091210913109141091510916109171091810919109201092110922109231092410925109261092710928109291093010931109321093310934109351093610937109381093910940109411094210943109441094510946109471094810949109501095110952109531095410955109561095710958109591096010961109621096310964109651096610967109681096910970109711097210973109741097510976109771097810979109801098110982109831098410985109861098710988109891099010991109921099310994109951099610997109981099911000110011100211003110041100511006110071100811009110101101111012110131101411015110161101711018110191102011021110221102311024110251102611027110281102911030110311103211033110341103511036110371103811039110401104111042110431104411045110461104711048110491105011051110521105311054110551105611057110581105911060110611106211063110641106511066110671106811069110701107111072110731107411075110761107711078110791108011081110821108311084110851108611087110881108911090110911109211093110941109511096110971109811099111001110111102111031110411105111061110711108111091111011111111121111311114111151111611117111181111911120111211112211123111241112511126111271112811129111301113111132111331113411135111361113711138111391114011141111421114311144111451114611147111481114911150111511115211153111541115511156111571115811159111601116111162111631116411165111661116711168111691117011171111721117311174111751117611177111781117911180111811118211183111841118511186111871118811189111901119111192111931119411195111961119711198111991120011201112021120311204112051120611207112081120911210112111121211213112141121511216112171121811219112201122111222112231122411225112261122711228112291123011231112321123311234112351123611237112381123911240112411124211243112441124511246112471124811249112501125111252112531125411255112561125711258112591126011261112621126311264112651126611267112681126911270112711127211273112741127511276112771127811279112801128111282112831128411285112861128711288112891129011291112921129311294112951129611297112981129911300113011130211303113041130511306113071130811309113101131111312113131131411315113161131711318113191132011321113221132311324113251132611327113281132911330113311133211333113341133511336113371133811339113401134111342113431134411345113461134711348113491135011351113521135311354113551135611357113581135911360113611136211363113641136511366113671136811369113701137111372113731137411375113761137711378113791138011381113821138311384113851138611387113881138911390113911139211393113941139511396113971139811399114001140111402114031140411405114061140711408114091141011411114121141311414114151141611417114181141911420114211142211423114241142511426114271142811429114301143111432114331143411435114361143711438114391144011441114421144311444114451144611447114481144911450114511145211453114541145511456114571145811459114601146111462114631146411465114661146711468114691147011471114721147311474114751147611477114781147911480114811148211483114841148511486114871148811489114901149111492114931149411495114961149711498114991150011501115021150311504115051150611507115081150911510115111151211513115141151511516115171151811519115201152111522115231152411525115261152711528115291153011531115321153311534115351153611537115381153911540115411154211543115441154511546115471154811549115501155111552115531155411555115561155711558115591156011561115621156311564115651156611567115681156911570115711157211573115741157511576115771157811579115801158111582115831158411585115861158711588115891159011591115921159311594115951159611597115981159911600116011160211603116041160511606116071160811609116101161111612116131161411615116161161711618116191162011621116221162311624116251162611627116281162911630116311163211633116341163511636116371163811639116401164111642116431164411645116461164711648116491165011651116521165311654116551165611657116581165911660116611166211663116641166511666116671166811669116701167111672116731167411675116761167711678116791168011681116821168311684116851168611687116881168911690116911169211693116941169511696116971169811699117001170111702117031170411705117061170711708117091171011711117121171311714117151171611717117181171911720117211172211723117241172511726117271172811729117301173111732117331173411735117361173711738117391174011741117421174311744117451174611747117481174911750117511175211753117541175511756117571175811759117601176111762117631176411765117661176711768117691177011771117721177311774117751177611777117781177911780117811178211783117841178511786117871178811789117901179111792117931179411795117961179711798117991180011801118021180311804118051180611807118081180911810118111181211813118141181511816118171181811819118201182111822118231182411825118261182711828118291183011831118321183311834118351183611837118381183911840118411184211843118441184511846118471184811849118501185111852118531185411855118561185711858118591186011861118621186311864118651186611867118681186911870118711187211873118741187511876118771187811879118801188111882118831188411885118861188711888118891189011891118921189311894118951189611897118981189911900119011190211903119041190511906119071190811909119101191111912119131191411915119161191711918119191192011921119221192311924119251192611927119281192911930119311193211933119341193511936119371193811939119401194111942119431194411945119461194711948119491195011951119521195311954119551195611957119581195911960119611196211963119641196511966119671196811969119701197111972119731197411975119761197711978119791198011981119821198311984119851198611987119881198911990119911199211993119941199511996119971199811999120001200112002120031200412005120061200712008120091201012011120121201312014120151201612017120181201912020120211202212023120241202512026120271202812029120301203112032120331203412035120361203712038120391204012041120421204312044120451204612047120481204912050120511205212053120541205512056120571205812059120601206112062120631206412065120661206712068120691207012071120721207312074120751207612077120781207912080120811208212083120841208512086120871208812089120901209112092120931209412095120961209712098120991210012101121021210312104121051210612107121081210912110121111211212113121141211512116121171211812119121201212112122121231212412125121261212712128121291213012131121321213312134121351213612137121381213912140121411214212143121441214512146121471214812149121501215112152121531215412155121561215712158121591216012161121621216312164121651216612167121681216912170121711217212173121741217512176121771217812179121801218112182121831218412185121861218712188121891219012191121921219312194121951219612197121981219912200122011220212203122041220512206122071220812209122101221112212122131221412215122161221712218122191222012221122221222312224122251222612227122281222912230122311223212233122341223512236122371223812239122401224112242122431224412245122461224712248122491225012251122521225312254122551225612257122581225912260122611226212263122641226512266122671226812269122701227112272122731227412275122761227712278122791228012281122821228312284122851228612287122881228912290122911229212293122941229512296122971229812299123001230112302123031230412305123061230712308123091231012311123121231312314123151231612317123181231912320123211232212323123241232512326123271232812329123301233112332123331233412335123361233712338123391234012341123421234312344123451234612347123481234912350123511235212353123541235512356123571235812359123601236112362123631236412365123661236712368123691237012371123721237312374123751237612377123781237912380123811238212383123841238512386123871238812389123901239112392123931239412395123961239712398123991240012401124021240312404124051240612407124081240912410124111241212413124141241512416124171241812419124201242112422124231242412425124261242712428124291243012431124321243312434124351243612437124381243912440124411244212443124441244512446124471244812449124501245112452124531245412455124561245712458124591246012461124621246312464124651246612467124681246912470124711247212473124741247512476124771247812479124801248112482124831248412485124861248712488124891249012491124921249312494124951249612497124981249912500125011250212503125041250512506125071250812509125101251112512125131251412515125161251712518125191252012521125221252312524125251252612527125281252912530125311253212533125341253512536125371253812539125401254112542125431254412545125461254712548125491255012551125521255312554125551255612557125581255912560125611256212563125641256512566125671256812569125701257112572125731257412575125761257712578125791258012581125821258312584125851258612587125881258912590125911259212593125941259512596125971259812599126001260112602126031260412605126061260712608126091261012611126121261312614126151261612617126181261912620126211262212623126241262512626126271262812629126301263112632126331263412635126361263712638126391264012641126421264312644126451264612647126481264912650126511265212653126541265512656126571265812659126601266112662126631266412665126661266712668126691267012671126721267312674126751267612677126781267912680126811268212683126841268512686126871268812689126901269112692126931269412695126961269712698126991270012701127021270312704127051270612707127081270912710127111271212713127141271512716127171271812719127201272112722127231272412725127261272712728127291273012731127321273312734127351273612737127381273912740127411274212743127441274512746127471274812749127501275112752127531275412755127561275712758127591276012761127621276312764127651276612767127681276912770127711277212773127741277512776127771277812779127801278112782127831278412785127861278712788127891279012791127921279312794127951279612797127981279912800128011280212803128041280512806128071280812809128101281112812128131281412815128161281712818128191282012821128221282312824128251282612827128281282912830128311283212833128341283512836128371283812839128401284112842128431284412845128461284712848128491285012851128521285312854128551285612857128581285912860128611286212863128641286512866128671286812869128701287112872128731287412875128761287712878128791288012881128821288312884128851288612887128881288912890128911289212893128941289512896128971289812899129001290112902129031290412905129061290712908129091291012911129121291312914129151291612917129181291912920129211292212923129241292512926129271292812929129301293112932129331293412935129361293712938129391294012941129421294312944129451294612947129481294912950129511295212953129541295512956129571295812959129601296112962129631296412965129661296712968129691297012971129721297312974129751297612977129781297912980129811298212983129841298512986129871298812989129901299112992129931299412995129961299712998129991300013001130021300313004130051300613007130081300913010130111301213013130141301513016130171301813019130201302113022130231302413025130261302713028130291303013031130321303313034130351303613037130381303913040130411304213043130441304513046130471304813049130501305113052130531305413055130561305713058130591306013061130621306313064130651306613067130681306913070130711307213073130741307513076130771307813079130801308113082130831308413085130861308713088130891309013091130921309313094130951309613097130981309913100131011310213103131041310513106131071310813109131101311113112131131311413115131161311713118131191312013121131221312313124131251312613127131281312913130131311313213133131341313513136131371313813139131401314113142131431314413145131461314713148131491315013151131521315313154131551315613157131581315913160131611316213163131641316513166131671316813169131701317113172131731317413175131761317713178131791318013181131821318313184131851318613187131881318913190131911319213193131941319513196131971319813199132001320113202132031320413205132061320713208132091321013211132121321313214132151321613217132181321913220132211322213223132241322513226132271322813229132301323113232132331323413235132361323713238132391324013241132421324313244132451324613247132481324913250132511325213253132541325513256132571325813259132601326113262132631326413265132661326713268132691327013271132721327313274132751327613277132781327913280132811328213283132841328513286132871328813289132901329113292132931329413295132961329713298132991330013301133021330313304133051330613307133081330913310133111331213313133141331513316133171331813319133201332113322133231332413325133261332713328133291333013331133321333313334133351333613337133381333913340133411334213343133441334513346133471334813349133501335113352133531335413355133561335713358133591336013361133621336313364133651336613367133681336913370133711337213373133741337513376133771337813379133801338113382133831338413385133861338713388133891339013391133921339313394133951339613397133981339913400134011340213403134041340513406134071340813409134101341113412134131341413415134161341713418134191342013421134221342313424134251342613427134281342913430134311343213433134341343513436134371343813439134401344113442134431344413445134461344713448134491345013451134521345313454134551345613457134581345913460134611346213463134641346513466134671346813469134701347113472134731347413475134761347713478134791348013481134821348313484134851348613487134881348913490134911349213493134941349513496134971349813499135001350113502135031350413505135061350713508135091351013511135121351313514135151351613517135181351913520135211352213523135241352513526135271352813529135301353113532135331353413535135361353713538135391354013541135421354313544135451354613547135481354913550135511355213553135541355513556135571355813559135601356113562135631356413565135661356713568135691357013571135721357313574135751357613577135781357913580135811358213583135841358513586135871358813589135901359113592135931359413595135961359713598135991360013601136021360313604136051360613607136081360913610136111361213613136141361513616136171361813619136201362113622136231362413625136261362713628136291363013631136321363313634136351363613637136381363913640136411364213643136441364513646136471364813649136501365113652136531365413655136561365713658136591366013661136621366313664136651366613667136681366913670136711367213673136741367513676136771367813679136801368113682136831368413685136861368713688136891369013691136921369313694136951369613697136981369913700137011370213703137041370513706137071370813709137101371113712137131371413715137161371713718137191372013721137221372313724137251372613727137281372913730137311373213733137341373513736137371373813739137401374113742137431374413745137461374713748137491375013751137521375313754137551375613757137581375913760137611376213763137641376513766137671376813769137701377113772137731377413775137761377713778137791378013781137821378313784137851378613787137881378913790137911379213793137941379513796137971379813799138001380113802138031380413805138061380713808138091381013811138121381313814138151381613817138181381913820138211382213823138241382513826138271382813829138301383113832138331383413835138361383713838138391384013841138421384313844138451384613847138481384913850138511385213853138541385513856138571385813859138601386113862138631386413865138661386713868138691387013871138721387313874138751387613877138781387913880138811388213883138841388513886138871388813889138901389113892138931389413895138961389713898138991390013901139021390313904139051390613907139081390913910139111391213913139141391513916139171391813919139201392113922139231392413925139261392713928139291393013931139321393313934139351393613937139381393913940139411394213943139441394513946139471394813949139501395113952139531395413955139561395713958139591396013961139621396313964139651396613967139681396913970139711397213973139741397513976139771397813979139801398113982139831398413985139861398713988139891399013991139921399313994139951399613997139981399914000140011400214003140041400514006140071400814009140101401114012140131401414015140161401714018140191402014021140221402314024140251402614027140281402914030140311403214033140341403514036140371403814039140401404114042140431404414045140461404714048140491405014051140521405314054140551405614057140581405914060140611406214063140641406514066140671406814069140701407114072140731407414075140761407714078140791408014081140821408314084140851408614087140881408914090140911409214093140941409514096140971409814099141001410114102141031410414105141061410714108141091411014111141121411314114141151411614117141181411914120141211412214123141241412514126141271412814129141301413114132141331413414135141361413714138141391414014141141421414314144141451414614147141481414914150141511415214153141541415514156141571415814159141601416114162141631416414165141661416714168141691417014171141721417314174141751417614177141781417914180141811418214183141841418514186141871418814189141901419114192141931419414195141961419714198141991420014201142021420314204142051420614207142081420914210142111421214213142141421514216142171421814219142201422114222142231422414225142261422714228142291423014231142321423314234142351423614237142381423914240142411424214243142441424514246142471424814249142501425114252142531425414255142561425714258142591426014261142621426314264142651426614267142681426914270142711427214273142741427514276142771427814279142801428114282142831428414285142861428714288142891429014291142921429314294142951429614297142981429914300143011430214303143041430514306143071430814309143101431114312143131431414315143161431714318143191432014321143221432314324143251432614327143281432914330143311433214333143341433514336143371433814339143401434114342143431434414345143461434714348143491435014351143521435314354143551435614357143581435914360143611436214363143641436514366143671436814369143701437114372143731437414375143761437714378143791438014381143821438314384143851438614387143881438914390143911439214393143941439514396143971439814399144001440114402144031440414405144061440714408144091441014411144121441314414144151441614417144181441914420144211442214423144241442514426144271442814429144301443114432144331443414435144361443714438144391444014441144421444314444144451444614447144481444914450144511445214453144541445514456144571445814459144601446114462144631446414465144661446714468144691447014471144721447314474144751447614477144781447914480144811448214483144841448514486144871448814489144901449114492144931449414495144961449714498144991450014501145021450314504145051450614507145081450914510145111451214513145141451514516145171451814519145201452114522145231452414525145261452714528145291453014531145321453314534145351453614537145381453914540145411454214543145441454514546145471454814549145501455114552145531455414555145561455714558145591456014561145621456314564145651456614567145681456914570145711457214573145741457514576145771457814579145801458114582145831458414585145861458714588145891459014591145921459314594145951459614597145981459914600146011460214603146041460514606146071460814609146101461114612146131461414615146161461714618146191462014621146221462314624146251462614627146281462914630146311463214633146341463514636146371463814639146401464114642146431464414645146461464714648146491465014651146521465314654146551465614657146581465914660146611466214663146641466514666146671466814669146701467114672146731467414675146761467714678146791468014681146821468314684146851468614687146881468914690146911469214693146941469514696146971469814699147001470114702147031470414705147061470714708147091471014711147121471314714147151471614717147181471914720147211472214723147241472514726147271472814729147301473114732147331473414735147361473714738147391474014741147421474314744147451474614747147481474914750147511475214753147541475514756147571475814759147601476114762147631476414765147661476714768147691477014771147721477314774147751477614777147781477914780147811478214783147841478514786147871478814789147901479114792147931479414795147961479714798147991480014801148021480314804148051480614807148081480914810148111481214813148141481514816148171481814819148201482114822148231482414825148261482714828148291483014831148321483314834148351483614837148381483914840148411484214843148441484514846148471484814849148501485114852148531485414855148561485714858148591486014861148621486314864148651486614867148681486914870148711487214873148741487514876148771487814879148801488114882148831488414885148861488714888148891489014891148921489314894148951489614897148981489914900149011490214903149041490514906149071490814909149101491114912149131491414915149161491714918149191492014921149221492314924149251492614927149281492914930149311493214933149341493514936149371493814939149401494114942149431494414945149461494714948149491495014951149521495314954149551495614957149581495914960149611496214963149641496514966149671496814969149701497114972149731497414975149761497714978149791498014981149821498314984149851498614987149881498914990149911499214993149941499514996149971499814999150001500115002150031500415005150061500715008150091501015011150121501315014150151501615017150181501915020150211502215023150241502515026150271502815029150301503115032150331503415035150361503715038150391504015041150421504315044150451504615047150481504915050150511505215053150541505515056150571505815059150601506115062150631506415065150661506715068150691507015071150721507315074150751507615077150781507915080150811508215083150841508515086150871508815089150901509115092150931509415095150961509715098150991510015101151021510315104151051510615107151081510915110151111511215113151141511515116151171511815119151201512115122151231512415125151261512715128151291513015131151321513315134151351513615137151381513915140151411514215143151441514515146151471514815149151501515115152151531515415155151561515715158151591516015161151621516315164151651516615167151681516915170151711517215173151741517515176151771517815179151801518115182151831518415185151861518715188151891519015191151921519315194151951519615197151981519915200152011520215203152041520515206152071520815209152101521115212152131521415215152161521715218152191522015221152221522315224152251522615227152281522915230152311523215233152341523515236152371523815239152401524115242152431524415245152461524715248152491525015251152521525315254152551525615257152581525915260152611526215263152641526515266152671526815269152701527115272152731527415275152761527715278152791528015281152821528315284152851528615287152881528915290152911529215293152941529515296152971529815299153001530115302153031530415305153061530715308153091531015311153121531315314153151531615317153181531915320153211532215323153241532515326153271532815329153301533115332153331533415335153361533715338153391534015341153421534315344153451534615347153481534915350153511535215353153541535515356153571535815359153601536115362153631536415365153661536715368153691537015371153721537315374153751537615377153781537915380153811538215383153841538515386153871538815389153901539115392153931539415395153961539715398153991540015401154021540315404154051540615407154081540915410154111541215413154141541515416154171541815419154201542115422154231542415425154261542715428154291543015431154321543315434154351543615437154381543915440154411544215443154441544515446154471544815449154501545115452154531545415455154561545715458154591546015461154621546315464154651546615467154681546915470154711547215473154741547515476154771547815479154801548115482154831548415485154861548715488154891549015491154921549315494154951549615497154981549915500155011550215503155041550515506155071550815509155101551115512155131551415515155161551715518155191552015521155221552315524155251552615527155281552915530155311553215533155341553515536155371553815539155401554115542155431554415545155461554715548155491555015551155521555315554155551555615557155581555915560155611556215563155641556515566155671556815569155701557115572155731557415575155761557715578155791558015581155821558315584155851558615587155881558915590155911559215593155941559515596155971559815599156001560115602156031560415605156061560715608156091561015611156121561315614156151561615617156181561915620156211562215623156241562515626156271562815629156301563115632156331563415635156361563715638156391564015641156421564315644156451564615647156481564915650156511565215653156541565515656156571565815659156601566115662156631566415665156661566715668156691567015671156721567315674156751567615677156781567915680156811568215683156841568515686156871568815689156901569115692156931569415695156961569715698156991570015701157021570315704157051570615707157081570915710157111571215713157141571515716157171571815719157201572115722157231572415725157261572715728157291573015731157321573315734157351573615737157381573915740157411574215743157441574515746157471574815749157501575115752157531575415755157561575715758157591576015761157621576315764157651576615767157681576915770157711577215773157741577515776157771577815779157801578115782157831578415785157861578715788157891579015791157921579315794157951579615797157981579915800158011580215803158041580515806158071580815809158101581115812158131581415815158161581715818158191582015821158221582315824158251582615827158281582915830158311583215833158341583515836158371583815839158401584115842158431584415845158461584715848158491585015851158521585315854158551585615857158581585915860158611586215863158641586515866158671586815869158701587115872158731587415875158761587715878158791588015881158821588315884158851588615887158881588915890158911589215893158941589515896158971589815899159001590115902159031590415905159061590715908159091591015911159121591315914159151591615917159181591915920159211592215923159241592515926159271592815929159301593115932159331593415935159361593715938159391594015941159421594315944159451594615947159481594915950159511595215953159541595515956159571595815959159601596115962159631596415965159661596715968159691597015971159721597315974159751597615977159781597915980159811598215983159841598515986159871598815989159901599115992159931599415995159961599715998159991600016001160021600316004160051600616007160081600916010160111601216013160141601516016160171601816019160201602116022160231602416025160261602716028160291603016031160321603316034160351603616037160381603916040160411604216043160441604516046160471604816049160501605116052160531605416055160561605716058160591606016061160621606316064160651606616067160681606916070160711607216073160741607516076160771607816079160801608116082160831608416085160861608716088160891609016091160921609316094160951609616097160981609916100161011610216103161041610516106161071610816109161101611116112161131611416115161161611716118161191612016121161221612316124161251612616127161281612916130161311613216133161341613516136161371613816139161401614116142161431614416145161461614716148161491615016151161521615316154161551615616157161581615916160161611616216163161641616516166161671616816169161701617116172161731617416175161761617716178161791618016181161821618316184161851618616187161881618916190161911619216193161941619516196161971619816199162001620116202162031620416205162061620716208162091621016211162121621316214162151621616217162181621916220162211622216223162241622516226162271622816229162301623116232162331623416235162361623716238162391624016241162421624316244162451624616247162481624916250162511625216253162541625516256162571625816259162601626116262162631626416265162661626716268162691627016271162721627316274162751627616277162781627916280162811628216283162841628516286162871628816289162901629116292162931629416295162961629716298162991630016301163021630316304163051630616307163081630916310163111631216313163141631516316163171631816319163201632116322163231632416325163261632716328163291633016331163321633316334163351633616337163381633916340163411634216343163441634516346163471634816349163501635116352163531635416355163561635716358163591636016361163621636316364163651636616367163681636916370163711637216373163741637516376163771637816379163801638116382163831638416385163861638716388163891639016391163921639316394163951639616397163981639916400164011640216403164041640516406164071640816409164101641116412164131641416415164161641716418164191642016421164221642316424164251642616427164281642916430164311643216433164341643516436164371643816439164401644116442164431644416445164461644716448164491645016451164521645316454164551645616457164581645916460164611646216463164641646516466164671646816469164701647116472164731647416475164761647716478164791648016481164821648316484164851648616487164881648916490164911649216493164941649516496164971649816499165001650116502165031650416505165061650716508165091651016511165121651316514165151651616517165181651916520165211652216523165241652516526165271652816529165301653116532165331653416535165361653716538165391654016541165421654316544165451654616547165481654916550165511655216553165541655516556165571655816559165601656116562165631656416565165661656716568165691657016571165721657316574165751657616577165781657916580165811658216583165841658516586165871658816589165901659116592165931659416595165961659716598165991660016601166021660316604166051660616607166081660916610166111661216613166141661516616166171661816619166201662116622166231662416625166261662716628166291663016631166321663316634166351663616637166381663916640166411664216643166441664516646166471664816649166501665116652166531665416655166561665716658166591666016661166621666316664166651666616667166681666916670166711667216673166741667516676166771667816679166801668116682166831668416685166861668716688166891669016691166921669316694166951669616697166981669916700167011670216703167041670516706167071670816709167101671116712167131671416715167161671716718167191672016721167221672316724167251672616727167281672916730167311673216733167341673516736167371673816739167401674116742167431674416745167461674716748167491675016751167521675316754167551675616757167581675916760167611676216763167641676516766167671676816769167701677116772167731677416775167761677716778167791678016781167821678316784167851678616787167881678916790167911679216793167941679516796167971679816799168001680116802168031680416805168061680716808168091681016811168121681316814168151681616817168181681916820168211682216823168241682516826168271682816829168301683116832168331683416835168361683716838168391684016841168421684316844168451684616847168481684916850168511685216853168541685516856168571685816859168601686116862168631686416865168661686716868168691687016871168721687316874168751687616877168781687916880168811688216883168841688516886168871688816889168901689116892168931689416895168961689716898168991690016901169021690316904169051690616907169081690916910169111691216913169141691516916169171691816919169201692116922169231692416925169261692716928169291693016931169321693316934169351693616937169381693916940169411694216943169441694516946169471694816949169501695116952169531695416955169561695716958169591696016961169621696316964169651696616967169681696916970169711697216973169741697516976169771697816979169801698116982169831698416985169861698716988169891699016991169921699316994169951699616997169981699917000170011700217003170041700517006170071700817009170101701117012170131701417015170161701717018170191702017021170221702317024170251702617027170281702917030170311703217033170341703517036170371703817039170401704117042170431704417045170461704717048170491705017051170521705317054170551705617057170581705917060170611706217063170641706517066170671706817069170701707117072170731707417075170761707717078170791708017081170821708317084170851708617087170881708917090170911709217093170941709517096170971709817099171001710117102171031710417105171061710717108171091711017111171121711317114171151711617117171181711917120171211712217123171241712517126171271712817129171301713117132171331713417135171361713717138171391714017141171421714317144171451714617147171481714917150171511715217153171541715517156171571715817159171601716117162171631716417165171661716717168171691717017171171721717317174171751717617177171781717917180171811718217183171841718517186171871718817189171901719117192171931719417195171961719717198171991720017201172021720317204172051720617207172081720917210172111721217213172141721517216172171721817219172201722117222172231722417225172261722717228172291723017231172321723317234172351723617237172381723917240172411724217243172441724517246172471724817249172501725117252172531725417255172561725717258172591726017261172621726317264172651726617267172681726917270172711727217273172741727517276172771727817279172801728117282172831728417285172861728717288172891729017291172921729317294172951729617297172981729917300173011730217303173041730517306173071730817309173101731117312173131731417315173161731717318173191732017321173221732317324173251732617327173281732917330173311733217333173341733517336173371733817339173401734117342173431734417345173461734717348173491735017351173521735317354173551735617357173581735917360173611736217363173641736517366173671736817369173701737117372173731737417375173761737717378173791738017381173821738317384173851738617387173881738917390173911739217393173941739517396173971739817399174001740117402174031740417405174061740717408174091741017411174121741317414174151741617417174181741917420174211742217423174241742517426174271742817429174301743117432174331743417435174361743717438174391744017441174421744317444174451744617447174481744917450174511745217453174541745517456174571745817459174601746117462174631746417465174661746717468174691747017471174721747317474174751747617477174781747917480174811748217483174841748517486174871748817489174901749117492174931749417495174961749717498174991750017501175021750317504175051750617507175081750917510175111751217513175141751517516175171751817519175201752117522175231752417525175261752717528175291753017531175321753317534175351753617537175381753917540175411754217543175441754517546175471754817549175501755117552175531755417555175561755717558175591756017561175621756317564175651756617567175681756917570175711757217573175741757517576175771757817579175801758117582175831758417585175861758717588175891759017591175921759317594175951759617597175981759917600176011760217603176041760517606176071760817609176101761117612176131761417615176161761717618176191762017621176221762317624176251762617627176281762917630176311763217633176341763517636176371763817639176401764117642176431764417645176461764717648176491765017651176521765317654176551765617657176581765917660176611766217663176641766517666176671766817669176701767117672176731767417675176761767717678176791768017681176821768317684176851768617687176881768917690176911769217693176941769517696176971769817699177001770117702177031770417705177061770717708177091771017711177121771317714177151771617717177181771917720177211772217723177241772517726177271772817729177301773117732177331773417735177361773717738177391774017741177421774317744177451774617747177481774917750177511775217753177541775517756177571775817759177601776117762177631776417765177661776717768177691777017771177721777317774177751777617777177781777917780177811778217783177841778517786177871778817789177901779117792177931779417795177961779717798177991780017801178021780317804178051780617807178081780917810178111781217813178141781517816178171781817819178201782117822178231782417825178261782717828178291783017831178321783317834178351783617837178381783917840178411784217843178441784517846178471784817849178501785117852178531785417855178561785717858178591786017861178621786317864178651786617867178681786917870178711787217873178741787517876178771787817879178801788117882178831788417885178861788717888178891789017891178921789317894178951789617897178981789917900179011790217903179041790517906179071790817909179101791117912179131791417915179161791717918179191792017921179221792317924179251792617927179281792917930179311793217933179341793517936179371793817939179401794117942179431794417945179461794717948179491795017951179521795317954179551795617957179581795917960179611796217963179641796517966179671796817969179701797117972179731797417975179761797717978179791798017981179821798317984179851798617987179881798917990179911799217993179941799517996179971799817999180001800118002180031800418005180061800718008180091801018011180121801318014180151801618017180181801918020180211802218023180241802518026180271802818029180301803118032180331803418035180361803718038180391804018041180421804318044180451804618047180481804918050180511805218053180541805518056180571805818059180601806118062180631806418065180661806718068180691807018071180721807318074180751807618077180781807918080180811808218083180841808518086180871808818089180901809118092180931809418095180961809718098180991810018101181021810318104181051810618107181081810918110181111811218113181141811518116181171811818119181201812118122181231812418125181261812718128181291813018131181321813318134181351813618137181381813918140181411814218143181441814518146181471814818149181501815118152181531815418155181561815718158181591816018161181621816318164181651816618167181681816918170181711817218173181741817518176181771817818179181801818118182181831818418185181861818718188181891819018191181921819318194181951819618197181981819918200182011820218203182041820518206182071820818209182101821118212182131821418215182161821718218182191822018221182221822318224182251822618227182281822918230182311823218233182341823518236182371823818239182401824118242182431824418245182461824718248182491825018251182521825318254182551825618257182581825918260182611826218263182641826518266182671826818269182701827118272182731827418275182761827718278182791828018281182821828318284182851828618287182881828918290182911829218293182941829518296182971829818299183001830118302183031830418305183061830718308183091831018311183121831318314183151831618317183181831918320183211832218323183241832518326183271832818329183301833118332183331833418335183361833718338183391834018341183421834318344183451834618347183481834918350183511835218353183541835518356183571835818359183601836118362183631836418365183661836718368183691837018371183721837318374183751837618377183781837918380183811838218383183841838518386183871838818389183901839118392183931839418395183961839718398183991840018401184021840318404184051840618407184081840918410184111841218413184141841518416184171841818419184201842118422184231842418425184261842718428184291843018431184321843318434184351843618437184381843918440184411844218443184441844518446184471844818449184501845118452184531845418455184561845718458184591846018461184621846318464184651846618467184681846918470184711847218473184741847518476184771847818479184801848118482184831848418485184861848718488184891849018491184921849318494184951849618497184981849918500185011850218503185041850518506185071850818509185101851118512185131851418515185161851718518185191852018521185221852318524185251852618527185281852918530185311853218533185341853518536185371853818539185401854118542185431854418545185461854718548185491855018551185521855318554185551855618557185581855918560185611856218563185641856518566185671856818569185701857118572185731857418575185761857718578185791858018581185821858318584185851858618587185881858918590185911859218593185941859518596185971859818599186001860118602186031860418605186061860718608186091861018611186121861318614186151861618617186181861918620186211862218623186241862518626186271862818629186301863118632186331863418635186361863718638186391864018641186421864318644186451864618647186481864918650186511865218653186541865518656186571865818659186601866118662186631866418665186661866718668186691867018671186721867318674186751867618677186781867918680186811868218683186841868518686186871868818689186901869118692186931869418695186961869718698186991870018701187021870318704187051870618707187081870918710187111871218713187141871518716187171871818719187201872118722187231872418725187261872718728187291873018731187321873318734187351873618737187381873918740187411874218743187441874518746187471874818749187501875118752187531875418755187561875718758187591876018761187621876318764187651876618767187681876918770187711877218773187741877518776187771877818779187801878118782187831878418785187861878718788187891879018791187921879318794187951879618797187981879918800188011880218803188041880518806188071880818809188101881118812188131881418815188161881718818188191882018821188221882318824188251882618827188281882918830188311883218833188341883518836188371883818839188401884118842188431884418845188461884718848188491885018851188521885318854188551885618857188581885918860188611886218863188641886518866188671886818869188701887118872188731887418875188761887718878188791888018881188821888318884188851888618887188881888918890188911889218893188941889518896188971889818899189001890118902189031890418905189061890718908189091891018911189121891318914189151891618917189181891918920189211892218923189241892518926189271892818929189301893118932189331893418935189361893718938189391894018941189421894318944189451894618947189481894918950189511895218953189541895518956189571895818959189601896118962189631896418965189661896718968189691897018971189721897318974189751897618977189781897918980189811898218983189841898518986189871898818989189901899118992189931899418995189961899718998189991900019001190021900319004190051900619007190081900919010190111901219013190141901519016190171901819019190201902119022190231902419025190261902719028190291903019031190321903319034190351903619037190381903919040190411904219043190441904519046190471904819049190501905119052190531905419055190561905719058190591906019061190621906319064190651906619067190681906919070190711907219073190741907519076190771907819079190801908119082190831908419085190861908719088190891909019091190921909319094190951909619097190981909919100191011910219103191041910519106191071910819109191101911119112191131911419115191161911719118191191912019121191221912319124191251912619127191281912919130191311913219133191341913519136191371913819139191401914119142191431914419145191461914719148191491915019151191521915319154191551915619157191581915919160191611916219163191641916519166191671916819169191701917119172191731917419175191761917719178191791918019181191821918319184191851918619187191881918919190191911919219193191941919519196191971919819199192001920119202192031920419205192061920719208192091921019211192121921319214192151921619217192181921919220192211922219223192241922519226192271922819229192301923119232192331923419235192361923719238192391924019241192421924319244192451924619247192481924919250192511925219253192541925519256192571925819259192601926119262192631926419265192661926719268192691927019271192721927319274192751927619277192781927919280192811928219283192841928519286192871928819289192901929119292192931929419295192961929719298192991930019301193021930319304193051930619307193081930919310193111931219313193141931519316193171931819319193201932119322193231932419325193261932719328193291933019331193321933319334193351933619337193381933919340193411934219343193441934519346193471934819349193501935119352193531935419355193561935719358193591936019361193621936319364193651936619367193681936919370193711937219373193741937519376193771937819379193801938119382193831938419385193861938719388193891939019391193921939319394193951939619397193981939919400194011940219403194041940519406194071940819409194101941119412194131941419415194161941719418194191942019421194221942319424194251942619427194281942919430194311943219433194341943519436194371943819439194401944119442194431944419445194461944719448194491945019451194521945319454194551945619457194581945919460194611946219463194641946519466194671946819469194701947119472194731947419475194761947719478194791948019481194821948319484194851948619487194881948919490194911949219493194941949519496194971949819499195001950119502195031950419505195061950719508195091951019511195121951319514195151951619517195181951919520195211952219523195241952519526195271952819529195301953119532195331953419535195361953719538195391954019541195421954319544195451954619547195481954919550195511955219553195541955519556195571955819559195601956119562195631956419565195661956719568195691957019571195721957319574195751957619577195781957919580195811958219583195841958519586195871958819589195901959119592195931959419595195961959719598195991960019601196021960319604196051960619607196081960919610196111961219613196141961519616196171961819619196201962119622196231962419625196261962719628196291963019631196321963319634196351963619637196381963919640196411964219643196441964519646196471964819649196501965119652196531965419655196561965719658196591966019661196621966319664196651966619667196681966919670196711967219673196741967519676196771967819679196801968119682196831968419685196861968719688196891969019691196921969319694196951969619697196981969919700197011970219703197041970519706197071970819709197101971119712197131971419715197161971719718197191972019721197221972319724197251972619727197281972919730197311973219733197341973519736197371973819739197401974119742197431974419745197461974719748197491975019751197521975319754197551975619757197581975919760197611976219763197641976519766197671976819769197701977119772197731977419775197761977719778197791978019781197821978319784197851978619787197881978919790197911979219793197941979519796197971979819799198001980119802198031980419805198061980719808198091981019811198121981319814198151981619817198181981919820198211982219823198241982519826198271982819829198301983119832198331983419835198361983719838198391984019841198421984319844198451984619847198481984919850198511985219853198541985519856198571985819859198601986119862198631986419865198661986719868198691987019871198721987319874198751987619877198781987919880198811988219883198841988519886198871988819889198901989119892198931989419895198961989719898198991990019901199021990319904199051990619907199081990919910199111991219913199141991519916199171991819919199201992119922199231992419925199261992719928199291993019931199321993319934199351993619937199381993919940199411994219943199441994519946199471994819949199501995119952199531995419955199561995719958199591996019961199621996319964199651996619967199681996919970199711997219973199741997519976199771997819979199801998119982199831998419985199861998719988199891999019991199921999319994199951999619997199981999920000200012000220003200042000520006200072000820009200102001120012200132001420015200162001720018200192002020021200222002320024200252002620027200282002920030200312003220033200342003520036200372003820039200402004120042200432004420045200462004720048200492005020051200522005320054200552005620057200582005920060200612006220063200642006520066200672006820069200702007120072200732007420075200762007720078200792008020081200822008320084200852008620087200882008920090200912009220093200942009520096200972009820099201002010120102201032010420105201062010720108201092011020111201122011320114201152011620117201182011920120201212012220123201242012520126201272012820129201302013120132201332013420135201362013720138201392014020141201422014320144201452014620147201482014920150201512015220153201542015520156201572015820159201602016120162201632016420165201662016720168201692017020171201722017320174201752017620177201782017920180201812018220183201842018520186201872018820189201902019120192201932019420195201962019720198201992020020201202022020320204202052020620207202082020920210202112021220213202142021520216202172021820219202202022120222202232022420225202262022720228202292023020231202322023320234202352023620237202382023920240202412024220243202442024520246202472024820249202502025120252202532025420255202562025720258202592026020261202622026320264202652026620267202682026920270202712027220273202742027520276202772027820279202802028120282202832028420285202862028720288202892029020291202922029320294202952029620297202982029920300203012030220303203042030520306203072030820309203102031120312203132031420315203162031720318203192032020321203222032320324203252032620327203282032920330203312033220333203342033520336203372033820339203402034120342203432034420345203462034720348203492035020351203522035320354203552035620357203582035920360203612036220363203642036520366203672036820369203702037120372203732037420375203762037720378203792038020381203822038320384203852038620387203882038920390203912039220393203942039520396203972039820399204002040120402204032040420405204062040720408204092041020411204122041320414204152041620417204182041920420204212042220423204242042520426204272042820429204302043120432204332043420435204362043720438204392044020441204422044320444204452044620447204482044920450204512045220453204542045520456204572045820459204602046120462204632046420465204662046720468204692047020471204722047320474204752047620477204782047920480204812048220483204842048520486204872048820489204902049120492204932049420495204962049720498204992050020501205022050320504205052050620507205082050920510205112051220513205142051520516205172051820519205202052120522205232052420525205262052720528205292053020531205322053320534205352053620537205382053920540205412054220543205442054520546205472054820549205502055120552205532055420555205562055720558205592056020561205622056320564205652056620567205682056920570205712057220573205742057520576205772057820579205802058120582205832058420585205862058720588205892059020591205922059320594205952059620597205982059920600206012060220603206042060520606206072060820609206102061120612206132061420615206162061720618206192062020621206222062320624206252062620627206282062920630206312063220633206342063520636206372063820639206402064120642206432064420645206462064720648206492065020651206522065320654206552065620657206582065920660206612066220663206642066520666206672066820669206702067120672206732067420675206762067720678206792068020681206822068320684206852068620687206882068920690206912069220693206942069520696206972069820699207002070120702207032070420705207062070720708207092071020711207122071320714207152071620717207182071920720207212072220723207242072520726207272072820729207302073120732207332073420735207362073720738207392074020741207422074320744207452074620747207482074920750207512075220753207542075520756207572075820759207602076120762207632076420765207662076720768207692077020771207722077320774207752077620777207782077920780207812078220783207842078520786207872078820789207902079120792207932079420795207962079720798207992080020801208022080320804208052080620807208082080920810208112081220813208142081520816208172081820819208202082120822208232082420825208262082720828208292083020831208322083320834208352083620837208382083920840208412084220843208442084520846208472084820849208502085120852208532085420855208562085720858208592086020861208622086320864208652086620867208682086920870208712087220873208742087520876208772087820879208802088120882208832088420885208862088720888208892089020891208922089320894208952089620897208982089920900209012090220903209042090520906209072090820909209102091120912209132091420915209162091720918209192092020921209222092320924209252092620927209282092920930209312093220933209342093520936209372093820939209402094120942209432094420945209462094720948209492095020951209522095320954209552095620957209582095920960209612096220963209642096520966209672096820969209702097120972209732097420975209762097720978209792098020981209822098320984209852098620987209882098920990209912099220993209942099520996209972099820999210002100121002210032100421005210062100721008210092101021011210122101321014210152101621017210182101921020210212102221023210242102521026210272102821029210302103121032210332103421035210362103721038210392104021041210422104321044210452104621047210482104921050210512105221053210542105521056210572105821059210602106121062210632106421065210662106721068210692107021071210722107321074210752107621077210782107921080210812108221083210842108521086210872108821089210902109121092210932109421095210962109721098210992110021101211022110321104211052110621107211082110921110211112111221113211142111521116211172111821119211202112121122211232112421125211262112721128211292113021131211322113321134211352113621137211382113921140211412114221143211442114521146211472114821149211502115121152211532115421155211562115721158211592116021161211622116321164211652116621167211682116921170211712117221173211742117521176211772117821179211802118121182211832118421185211862118721188211892119021191211922119321194211952119621197211982119921200212012120221203212042120521206212072120821209212102121121212212132121421215212162121721218212192122021221212222122321224212252122621227212282122921230212312123221233212342123521236212372123821239212402124121242212432124421245212462124721248212492125021251212522125321254212552125621257212582125921260212612126221263212642126521266212672126821269212702127121272212732127421275212762127721278212792128021281212822128321284212852128621287212882128921290212912129221293212942129521296212972129821299213002130121302213032130421305213062130721308213092131021311213122131321314213152131621317213182131921320213212132221323213242132521326213272132821329213302133121332213332133421335213362133721338213392134021341213422134321344213452134621347213482134921350213512135221353213542135521356213572135821359213602136121362213632136421365213662136721368213692137021371213722137321374213752137621377213782137921380213812138221383213842138521386213872138821389213902139121392213932139421395213962139721398213992140021401214022140321404214052140621407214082140921410214112141221413214142141521416214172141821419214202142121422214232142421425214262142721428214292143021431214322143321434214352143621437214382143921440214412144221443214442144521446214472144821449214502145121452214532145421455214562145721458214592146021461214622146321464214652146621467214682146921470214712147221473214742147521476214772147821479214802148121482214832148421485214862148721488214892149021491214922149321494214952149621497214982149921500215012150221503215042150521506215072150821509215102151121512215132151421515215162151721518215192152021521215222152321524215252152621527215282152921530215312153221533215342153521536215372153821539215402154121542215432154421545215462154721548215492155021551215522155321554215552155621557215582155921560215612156221563215642156521566215672156821569215702157121572215732157421575215762157721578215792158021581215822158321584215852158621587215882158921590215912159221593215942159521596215972159821599216002160121602216032160421605216062160721608216092161021611216122161321614216152161621617216182161921620216212162221623216242162521626216272162821629216302163121632216332163421635216362163721638216392164021641216422164321644216452164621647216482164921650216512165221653216542165521656216572165821659216602166121662216632166421665216662166721668216692167021671216722167321674216752167621677216782167921680216812168221683216842168521686216872168821689216902169121692216932169421695216962169721698216992170021701217022170321704217052170621707217082170921710217112171221713217142171521716217172171821719217202172121722217232172421725217262172721728217292173021731217322173321734217352173621737217382173921740217412174221743217442174521746217472174821749217502175121752217532175421755217562175721758217592176021761217622176321764217652176621767217682176921770217712177221773217742177521776217772177821779217802178121782217832178421785217862178721788217892179021791217922179321794217952179621797217982179921800218012180221803218042180521806218072180821809218102181121812218132181421815218162181721818218192182021821218222182321824218252182621827218282182921830218312183221833218342183521836218372183821839218402184121842218432184421845218462184721848218492185021851218522185321854218552185621857218582185921860218612186221863218642186521866218672186821869218702187121872218732187421875218762187721878218792188021881218822188321884218852188621887218882188921890218912189221893218942189521896218972189821899219002190121902219032190421905219062190721908219092191021911219122191321914219152191621917219182191921920219212192221923219242192521926219272192821929219302193121932219332193421935219362193721938219392194021941219422194321944219452194621947219482194921950219512195221953219542195521956219572195821959219602196121962219632196421965219662196721968219692197021971219722197321974219752197621977219782197921980219812198221983219842198521986219872198821989219902199121992219932199421995219962199721998219992200022001220022200322004220052200622007220082200922010220112201222013220142201522016220172201822019220202202122022220232202422025220262202722028220292203022031220322203322034220352203622037220382203922040220412204222043220442204522046220472204822049220502205122052220532205422055220562205722058220592206022061220622206322064220652206622067220682206922070220712207222073220742207522076220772207822079220802208122082220832208422085220862208722088220892209022091220922209322094220952209622097220982209922100221012210222103221042210522106221072210822109221102211122112221132211422115221162211722118221192212022121221222212322124221252212622127221282212922130221312213222133221342213522136221372213822139221402214122142221432214422145221462214722148221492215022151221522215322154221552215622157221582215922160221612216222163221642216522166221672216822169221702217122172221732217422175221762217722178221792218022181221822218322184221852218622187221882218922190221912219222193221942219522196221972219822199222002220122202222032220422205222062220722208222092221022211222122221322214222152221622217222182221922220222212222222223222242222522226222272222822229222302223122232222332223422235222362223722238222392224022241222422224322244222452224622247222482224922250222512225222253222542225522256222572225822259222602226122262222632226422265222662226722268222692227022271222722227322274222752227622277222782227922280222812228222283222842228522286222872228822289222902229122292222932229422295222962229722298222992230022301223022230322304223052230622307223082230922310223112231222313223142231522316223172231822319223202232122322223232232422325223262232722328223292233022331223322233322334223352233622337223382233922340223412234222343223442234522346223472234822349223502235122352223532235422355223562235722358223592236022361223622236322364223652236622367223682236922370223712237222373223742237522376223772237822379223802238122382223832238422385223862238722388223892239022391223922239322394223952239622397223982239922400224012240222403224042240522406224072240822409224102241122412224132241422415224162241722418224192242022421224222242322424224252242622427224282242922430224312243222433224342243522436224372243822439224402244122442224432244422445224462244722448224492245022451224522245322454224552245622457224582245922460224612246222463224642246522466224672246822469224702247122472224732247422475224762247722478224792248022481224822248322484224852248622487224882248922490224912249222493224942249522496224972249822499225002250122502225032250422505225062250722508225092251022511225122251322514225152251622517225182251922520225212252222523225242252522526225272252822529225302253122532225332253422535225362253722538225392254022541225422254322544225452254622547225482254922550225512255222553225542255522556225572255822559225602256122562225632256422565225662256722568225692257022571225722257322574225752257622577225782257922580225812258222583225842258522586225872258822589225902259122592225932259422595225962259722598225992260022601226022260322604226052260622607226082260922610226112261222613226142261522616226172261822619226202262122622226232262422625226262262722628226292263022631226322263322634226352263622637226382263922640226412264222643226442264522646226472264822649226502265122652226532265422655226562265722658226592266022661226622266322664226652266622667226682266922670226712267222673226742267522676226772267822679226802268122682226832268422685226862268722688226892269022691226922269322694226952269622697226982269922700227012270222703227042270522706227072270822709227102271122712227132271422715227162271722718227192272022721227222272322724227252272622727227282272922730227312273222733227342273522736227372273822739227402274122742227432274422745227462274722748227492275022751227522275322754227552275622757227582275922760227612276222763227642276522766227672276822769227702277122772227732277422775227762277722778227792278022781227822278322784227852278622787227882278922790227912279222793227942279522796227972279822799228002280122802228032280422805228062280722808228092281022811228122281322814228152281622817228182281922820228212282222823228242282522826228272282822829228302283122832228332283422835228362283722838228392284022841228422284322844228452284622847228482284922850228512285222853228542285522856228572285822859228602286122862228632286422865228662286722868228692287022871228722287322874228752287622877228782287922880228812288222883228842288522886228872288822889228902289122892228932289422895228962289722898228992290022901229022290322904229052290622907
  1. From 3a302437605308079db398b67000a77a4fe92da8 Mon Sep 17 00:00:00 2001
  2. From: Yangbo Lu <[email protected]>
  3. Date: Mon, 25 Sep 2017 12:07:58 +0800
  4. Subject: [PATCH] dpaa2: support layerscape
  5. This is a integrated patch for layerscape dpaa2 support.
  6. Signed-off-by: Bogdan Purcareata <[email protected]>
  7. Signed-off-by: Ioana Radulescu <[email protected]>
  8. Signed-off-by: Razvan Stefanescu <[email protected]>
  9. Signed-off-by: costi <[email protected]>
  10. Signed-off-by: Catalin Horghidan <[email protected]>
  11. Signed-off-by: Yangbo Lu <[email protected]>
  12. ---
  13. drivers/soc/fsl/ls2-console/Kconfig | 4 +
  14. drivers/soc/fsl/ls2-console/Makefile | 1 +
  15. drivers/soc/fsl/ls2-console/ls2-console.c | 284 ++
  16. drivers/staging/fsl-dpaa2/ethernet/Makefile | 11 +
  17. drivers/staging/fsl-dpaa2/ethernet/README | 186 ++
  18. .../staging/fsl-dpaa2/ethernet/dpaa2-eth-debugfs.c | 350 +++
  19. .../staging/fsl-dpaa2/ethernet/dpaa2-eth-debugfs.h | 60 +
  20. .../staging/fsl-dpaa2/ethernet/dpaa2-eth-trace.h | 184 ++
  21. drivers/staging/fsl-dpaa2/ethernet/dpaa2-eth.c | 3155 ++++++++++++++++++++
  22. drivers/staging/fsl-dpaa2/ethernet/dpaa2-eth.h | 460 +++
  23. drivers/staging/fsl-dpaa2/ethernet/dpaa2-ethtool.c | 856 ++++++
  24. drivers/staging/fsl-dpaa2/ethernet/dpkg.h | 176 ++
  25. drivers/staging/fsl-dpaa2/ethernet/dpni-cmd.h | 600 ++++
  26. drivers/staging/fsl-dpaa2/ethernet/dpni.c | 1770 +++++++++++
  27. drivers/staging/fsl-dpaa2/ethernet/dpni.h | 989 ++++++
  28. drivers/staging/fsl-dpaa2/ethernet/net.h | 480 +++
  29. drivers/staging/fsl-dpaa2/ethsw/Kconfig | 6 +
  30. drivers/staging/fsl-dpaa2/ethsw/Makefile | 10 +
  31. drivers/staging/fsl-dpaa2/ethsw/dpsw-cmd.h | 851 ++++++
  32. drivers/staging/fsl-dpaa2/ethsw/dpsw.c | 2762 +++++++++++++++++
  33. drivers/staging/fsl-dpaa2/ethsw/dpsw.h | 1269 ++++++++
  34. drivers/staging/fsl-dpaa2/ethsw/switch.c | 1857 ++++++++++++
  35. drivers/staging/fsl-dpaa2/evb/Kconfig | 7 +
  36. drivers/staging/fsl-dpaa2/evb/Makefile | 10 +
  37. drivers/staging/fsl-dpaa2/evb/dpdmux-cmd.h | 279 ++
  38. drivers/staging/fsl-dpaa2/evb/dpdmux.c | 1112 +++++++
  39. drivers/staging/fsl-dpaa2/evb/dpdmux.h | 453 +++
  40. drivers/staging/fsl-dpaa2/evb/evb.c | 1350 +++++++++
  41. drivers/staging/fsl-dpaa2/mac/Kconfig | 23 +
  42. drivers/staging/fsl-dpaa2/mac/Makefile | 10 +
  43. drivers/staging/fsl-dpaa2/mac/dpmac-cmd.h | 172 ++
  44. drivers/staging/fsl-dpaa2/mac/dpmac.c | 620 ++++
  45. drivers/staging/fsl-dpaa2/mac/dpmac.h | 342 +++
  46. drivers/staging/fsl-dpaa2/mac/mac.c | 666 +++++
  47. drivers/staging/fsl-dpaa2/rtc/Makefile | 10 +
  48. drivers/staging/fsl-dpaa2/rtc/dprtc-cmd.h | 160 +
  49. drivers/staging/fsl-dpaa2/rtc/dprtc.c | 746 +++++
  50. drivers/staging/fsl-dpaa2/rtc/dprtc.h | 172 ++
  51. drivers/staging/fsl-dpaa2/rtc/rtc.c | 243 ++
  52. 39 files changed, 22696 insertions(+)
  53. create mode 100644 drivers/soc/fsl/ls2-console/Kconfig
  54. create mode 100644 drivers/soc/fsl/ls2-console/Makefile
  55. create mode 100644 drivers/soc/fsl/ls2-console/ls2-console.c
  56. create mode 100644 drivers/staging/fsl-dpaa2/ethernet/Makefile
  57. create mode 100644 drivers/staging/fsl-dpaa2/ethernet/README
  58. create mode 100644 drivers/staging/fsl-dpaa2/ethernet/dpaa2-eth-debugfs.c
  59. create mode 100644 drivers/staging/fsl-dpaa2/ethernet/dpaa2-eth-debugfs.h
  60. create mode 100644 drivers/staging/fsl-dpaa2/ethernet/dpaa2-eth-trace.h
  61. create mode 100644 drivers/staging/fsl-dpaa2/ethernet/dpaa2-eth.c
  62. create mode 100644 drivers/staging/fsl-dpaa2/ethernet/dpaa2-eth.h
  63. create mode 100644 drivers/staging/fsl-dpaa2/ethernet/dpaa2-ethtool.c
  64. create mode 100644 drivers/staging/fsl-dpaa2/ethernet/dpkg.h
  65. create mode 100644 drivers/staging/fsl-dpaa2/ethernet/dpni-cmd.h
  66. create mode 100644 drivers/staging/fsl-dpaa2/ethernet/dpni.c
  67. create mode 100644 drivers/staging/fsl-dpaa2/ethernet/dpni.h
  68. create mode 100644 drivers/staging/fsl-dpaa2/ethernet/net.h
  69. create mode 100644 drivers/staging/fsl-dpaa2/ethsw/Kconfig
  70. create mode 100644 drivers/staging/fsl-dpaa2/ethsw/Makefile
  71. create mode 100644 drivers/staging/fsl-dpaa2/ethsw/dpsw-cmd.h
  72. create mode 100644 drivers/staging/fsl-dpaa2/ethsw/dpsw.c
  73. create mode 100644 drivers/staging/fsl-dpaa2/ethsw/dpsw.h
  74. create mode 100644 drivers/staging/fsl-dpaa2/ethsw/switch.c
  75. create mode 100644 drivers/staging/fsl-dpaa2/evb/Kconfig
  76. create mode 100644 drivers/staging/fsl-dpaa2/evb/Makefile
  77. create mode 100644 drivers/staging/fsl-dpaa2/evb/dpdmux-cmd.h
  78. create mode 100644 drivers/staging/fsl-dpaa2/evb/dpdmux.c
  79. create mode 100644 drivers/staging/fsl-dpaa2/evb/dpdmux.h
  80. create mode 100644 drivers/staging/fsl-dpaa2/evb/evb.c
  81. create mode 100644 drivers/staging/fsl-dpaa2/mac/Kconfig
  82. create mode 100644 drivers/staging/fsl-dpaa2/mac/Makefile
  83. create mode 100644 drivers/staging/fsl-dpaa2/mac/dpmac-cmd.h
  84. create mode 100644 drivers/staging/fsl-dpaa2/mac/dpmac.c
  85. create mode 100644 drivers/staging/fsl-dpaa2/mac/dpmac.h
  86. create mode 100644 drivers/staging/fsl-dpaa2/mac/mac.c
  87. create mode 100644 drivers/staging/fsl-dpaa2/rtc/Makefile
  88. create mode 100644 drivers/staging/fsl-dpaa2/rtc/dprtc-cmd.h
  89. create mode 100644 drivers/staging/fsl-dpaa2/rtc/dprtc.c
  90. create mode 100644 drivers/staging/fsl-dpaa2/rtc/dprtc.h
  91. create mode 100644 drivers/staging/fsl-dpaa2/rtc/rtc.c
  92. --- /dev/null
  93. +++ b/drivers/soc/fsl/ls2-console/Kconfig
  94. @@ -0,0 +1,4 @@
  95. +config FSL_LS2_CONSOLE
  96. + tristate "Layerscape MC and AIOP console support"
  97. + depends on ARCH_LAYERSCAPE
  98. + default y
  99. --- /dev/null
  100. +++ b/drivers/soc/fsl/ls2-console/Makefile
  101. @@ -0,0 +1 @@
  102. +obj-$(CONFIG_FSL_LS2_CONSOLE) += ls2-console.o
  103. --- /dev/null
  104. +++ b/drivers/soc/fsl/ls2-console/ls2-console.c
  105. @@ -0,0 +1,284 @@
  106. +/* Copyright 2015-2016 Freescale Semiconductor Inc.
  107. + *
  108. + * Redistribution and use in source and binary forms, with or without
  109. + * modification, are permitted provided that the following conditions are met:
  110. + * * Redistributions of source code must retain the above copyright
  111. + * notice, this list of conditions and the following disclaimer.
  112. + * * Redistributions in binary form must reproduce the above copyright
  113. + * notice, this list of conditions and the following disclaimer in the
  114. + * documentation and/or other materials provided with the distribution.
  115. + * * Neither the name of the above-listed copyright holders nor the
  116. + * names of any contributors may be used to endorse or promote products
  117. + * derived from this software without specific prior written permission.
  118. + *
  119. + *
  120. + * ALTERNATIVELY, this software may be distributed under the terms of the
  121. + * GNU General Public License ("GPL") as published by the Free Software
  122. + * Foundation, either version 2 of that License or (at your option) any
  123. + * later version.
  124. + *
  125. + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  126. + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  127. + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  128. + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
  129. + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  130. + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  131. + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  132. + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  133. + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  134. + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  135. + * POSSIBILITY OF SUCH DAMAGE.
  136. + */
  137. +
  138. +#include <linux/miscdevice.h>
  139. +#include <linux/uaccess.h>
  140. +#include <linux/poll.h>
  141. +#include <linux/compat.h>
  142. +#include <linux/module.h>
  143. +#include <linux/slab.h>
  144. +#include <linux/io.h>
  145. +
  146. +/* SoC address for the MC firmware base low/high registers */
  147. +#define SOC_CCSR_MC_FW_BASE_ADDR_REGS 0x8340020
  148. +#define SOC_CCSR_MC_FW_BASE_ADDR_REGS_SIZE 2
  149. +/* MC firmware base low/high registers indexes */
  150. +#define MCFBALR_OFFSET 0
  151. +#define MCFBAHR_OFFSET 1
  152. +
  153. +/* Bit mask used to obtain the most significant part of the MC base address */
  154. +#define MC_FW_HIGH_ADDR_MASK 0x1FFFF
  155. +/* Bit mask used to obtain the least significant part of the MC base address */
  156. +#define MC_FW_LOW_ADDR_MASK 0xE0000000
  157. +
  158. +#define MC_BUFFER_OFFSET 0x01000000
  159. +#define MC_BUFFER_SIZE (1024*1024*16)
  160. +#define MC_OFFSET_DELTA (MC_BUFFER_OFFSET)
  161. +
  162. +#define AIOP_BUFFER_OFFSET 0x06000000
  163. +#define AIOP_BUFFER_SIZE (1024*1024*16)
  164. +#define AIOP_OFFSET_DELTA (0)
  165. +
  166. +struct log_header {
  167. + char magic_word[8]; /* magic word */
  168. + uint32_t buf_start; /* holds the 32-bit little-endian
  169. + * offset of the start of the buffer
  170. + */
  171. + uint32_t buf_length; /* holds the 32-bit little-endian
  172. + * length of the buffer
  173. + */
  174. + uint32_t last_byte; /* holds the 32-bit little-endian offset
  175. + * of the byte after the last byte that
  176. + * was written
  177. + */
  178. + char reserved[44];
  179. +};
  180. +
  181. +#define LOG_HEADER_FLAG_BUFFER_WRAPAROUND 0x80000000
  182. +#define LOG_VERSION_MAJOR 1
  183. +#define LOG_VERSION_MINOR 0
  184. +
  185. +
  186. +#define invalidate(p) { asm volatile("dc ivac, %0" : : "r" (p) : "memory"); }
  187. +
  188. +struct console_data {
  189. + char *map_addr;
  190. + struct log_header *hdr;
  191. + char *start_addr; /* Start of buffer */
  192. + char *end_addr; /* End of buffer */
  193. + char *end_of_data; /* Current end of data */
  194. + char *cur_ptr; /* Last data sent to console */
  195. +};
  196. +
  197. +#define LAST_BYTE(a) ((a) & ~(LOG_HEADER_FLAG_BUFFER_WRAPAROUND))
  198. +
  199. +static inline void __adjust_end(struct console_data *cd)
  200. +{
  201. + cd->end_of_data = cd->start_addr
  202. + + LAST_BYTE(le32_to_cpu(cd->hdr->last_byte));
  203. +}
  204. +
  205. +static inline void adjust_end(struct console_data *cd)
  206. +{
  207. + invalidate(cd->hdr);
  208. + __adjust_end(cd);
  209. +}
  210. +
  211. +static inline uint64_t get_mc_fw_base_address(void)
  212. +{
  213. + u32 *mcfbaregs = (u32 *) ioremap(SOC_CCSR_MC_FW_BASE_ADDR_REGS,
  214. + SOC_CCSR_MC_FW_BASE_ADDR_REGS_SIZE);
  215. + u64 mcfwbase = 0ULL;
  216. +
  217. + mcfwbase = readl(mcfbaregs + MCFBAHR_OFFSET) & MC_FW_HIGH_ADDR_MASK;
  218. + mcfwbase <<= 32;
  219. + mcfwbase |= readl(mcfbaregs + MCFBALR_OFFSET) & MC_FW_LOW_ADDR_MASK;
  220. + iounmap(mcfbaregs);
  221. + pr_info("fsl-ls2-console: MC base address at 0x%016llx\n", mcfwbase);
  222. + return mcfwbase;
  223. +}
  224. +
  225. +static int fsl_ls2_generic_console_open(struct inode *node, struct file *fp,
  226. + u64 offset, u64 size,
  227. + uint8_t *emagic, uint8_t magic_len,
  228. + u32 offset_delta)
  229. +{
  230. + struct console_data *cd;
  231. + uint8_t *magic;
  232. + uint32_t wrapped;
  233. +
  234. + cd = kmalloc(sizeof(*cd), GFP_KERNEL);
  235. + if (cd == NULL)
  236. + return -ENOMEM;
  237. + fp->private_data = cd;
  238. + cd->map_addr = ioremap(get_mc_fw_base_address() + offset, size);
  239. +
  240. + cd->hdr = (struct log_header *) cd->map_addr;
  241. + invalidate(cd->hdr);
  242. +
  243. + magic = cd->hdr->magic_word;
  244. + if (memcmp(magic, emagic, magic_len)) {
  245. + pr_info("magic didn't match!\n");
  246. + pr_info("expected: %02x %02x %02x %02x %02x %02x %02x %02x\n",
  247. + emagic[0], emagic[1], emagic[2], emagic[3],
  248. + emagic[4], emagic[5], emagic[6], emagic[7]);
  249. + pr_info(" seen: %02x %02x %02x %02x %02x %02x %02x %02x\n",
  250. + magic[0], magic[1], magic[2], magic[3],
  251. + magic[4], magic[5], magic[6], magic[7]);
  252. + kfree(cd);
  253. + iounmap(cd->map_addr);
  254. + return -EIO;
  255. + }
  256. +
  257. + cd->start_addr = cd->map_addr
  258. + + le32_to_cpu(cd->hdr->buf_start) - offset_delta;
  259. + cd->end_addr = cd->start_addr + le32_to_cpu(cd->hdr->buf_length);
  260. +
  261. + wrapped = le32_to_cpu(cd->hdr->last_byte)
  262. + & LOG_HEADER_FLAG_BUFFER_WRAPAROUND;
  263. +
  264. + __adjust_end(cd);
  265. + if (wrapped && (cd->end_of_data != cd->end_addr))
  266. + cd->cur_ptr = cd->end_of_data+1;
  267. + else
  268. + cd->cur_ptr = cd->start_addr;
  269. +
  270. + return 0;
  271. +}
  272. +
  273. +static int fsl_ls2_mc_console_open(struct inode *node, struct file *fp)
  274. +{
  275. + uint8_t magic_word[] = { 0, 1, 'C', 'M' };
  276. +
  277. + return fsl_ls2_generic_console_open(node, fp,
  278. + MC_BUFFER_OFFSET, MC_BUFFER_SIZE,
  279. + magic_word, sizeof(magic_word),
  280. + MC_OFFSET_DELTA);
  281. +}
  282. +
  283. +static int fsl_ls2_aiop_console_open(struct inode *node, struct file *fp)
  284. +{
  285. + uint8_t magic_word[] = { 'P', 'O', 'I', 'A' };
  286. +
  287. + return fsl_ls2_generic_console_open(node, fp,
  288. + AIOP_BUFFER_OFFSET, AIOP_BUFFER_SIZE,
  289. + magic_word, sizeof(magic_word),
  290. + AIOP_OFFSET_DELTA);
  291. +}
  292. +
  293. +static int fsl_ls2_console_close(struct inode *node, struct file *fp)
  294. +{
  295. + struct console_data *cd = fp->private_data;
  296. +
  297. + iounmap(cd->map_addr);
  298. + kfree(cd);
  299. + return 0;
  300. +}
  301. +
  302. +ssize_t fsl_ls2_console_read(struct file *fp, char __user *buf, size_t count,
  303. + loff_t *f_pos)
  304. +{
  305. + struct console_data *cd = fp->private_data;
  306. + size_t bytes = 0;
  307. + char data;
  308. +
  309. + /* Check if we need to adjust the end of data addr */
  310. + adjust_end(cd);
  311. +
  312. + while ((count != bytes) && (cd->end_of_data != cd->cur_ptr)) {
  313. + if (((u64)cd->cur_ptr) % 64 == 0)
  314. + invalidate(cd->cur_ptr);
  315. +
  316. + data = *(cd->cur_ptr);
  317. + if (copy_to_user(&buf[bytes], &data, 1))
  318. + return -EFAULT;
  319. + cd->cur_ptr++;
  320. + if (cd->cur_ptr >= cd->end_addr)
  321. + cd->cur_ptr = cd->start_addr;
  322. + ++bytes;
  323. + }
  324. + return bytes;
  325. +}
  326. +
  327. +static const struct file_operations fsl_ls2_mc_console_fops = {
  328. + .owner = THIS_MODULE,
  329. + .open = fsl_ls2_mc_console_open,
  330. + .release = fsl_ls2_console_close,
  331. + .read = fsl_ls2_console_read,
  332. +};
  333. +
  334. +static struct miscdevice fsl_ls2_mc_console_dev = {
  335. + .minor = MISC_DYNAMIC_MINOR,
  336. + .name = "fsl_mc_console",
  337. + .fops = &fsl_ls2_mc_console_fops
  338. +};
  339. +
  340. +static const struct file_operations fsl_ls2_aiop_console_fops = {
  341. + .owner = THIS_MODULE,
  342. + .open = fsl_ls2_aiop_console_open,
  343. + .release = fsl_ls2_console_close,
  344. + .read = fsl_ls2_console_read,
  345. +};
  346. +
  347. +static struct miscdevice fsl_ls2_aiop_console_dev = {
  348. + .minor = MISC_DYNAMIC_MINOR,
  349. + .name = "fsl_aiop_console",
  350. + .fops = &fsl_ls2_aiop_console_fops
  351. +};
  352. +
  353. +static int __init fsl_ls2_console_init(void)
  354. +{
  355. + int err = 0;
  356. +
  357. + pr_info("Freescale LS2 console driver\n");
  358. + err = misc_register(&fsl_ls2_mc_console_dev);
  359. + if (err) {
  360. + pr_err("fsl_mc_console: cannot register device\n");
  361. + return err;
  362. + }
  363. + pr_info("fsl-ls2-console: device %s registered\n",
  364. + fsl_ls2_mc_console_dev.name);
  365. +
  366. + err = misc_register(&fsl_ls2_aiop_console_dev);
  367. + if (err) {
  368. + pr_err("fsl_aiop_console: cannot register device\n");
  369. + return err;
  370. + }
  371. + pr_info("fsl-ls2-console: device %s registered\n",
  372. + fsl_ls2_aiop_console_dev.name);
  373. +
  374. + return 0;
  375. +}
  376. +
  377. +static void __exit fsl_ls2_console_exit(void)
  378. +{
  379. + misc_deregister(&fsl_ls2_mc_console_dev);
  380. +
  381. + misc_deregister(&fsl_ls2_aiop_console_dev);
  382. +}
  383. +
  384. +module_init(fsl_ls2_console_init);
  385. +module_exit(fsl_ls2_console_exit);
  386. +
  387. +MODULE_AUTHOR("Roy Pledge <[email protected]>");
  388. +MODULE_LICENSE("Dual BSD/GPL");
  389. +MODULE_DESCRIPTION("Freescale LS2 console driver");
  390. --- /dev/null
  391. +++ b/drivers/staging/fsl-dpaa2/ethernet/Makefile
  392. @@ -0,0 +1,11 @@
  393. +#
  394. +# Makefile for the Freescale DPAA2 Ethernet controller
  395. +#
  396. +
  397. +obj-$(CONFIG_FSL_DPAA2_ETH) += fsl-dpaa2-eth.o
  398. +
  399. +fsl-dpaa2-eth-objs := dpaa2-eth.o dpaa2-ethtool.o dpni.o
  400. +fsl-dpaa2-eth-${CONFIG_FSL_DPAA2_ETH_DEBUGFS} += dpaa2-eth-debugfs.o
  401. +
  402. +# Needed by the tracing framework
  403. +CFLAGS_dpaa2-eth.o := -I$(src)
  404. --- /dev/null
  405. +++ b/drivers/staging/fsl-dpaa2/ethernet/README
  406. @@ -0,0 +1,186 @@
  407. +Freescale DPAA2 Ethernet driver
  408. +===============================
  409. +
  410. +This file provides documentation for the Freescale DPAA2 Ethernet driver.
  411. +
  412. +
  413. +Contents
  414. +========
  415. + Supported Platforms
  416. + Architecture Overview
  417. + Creating a Network Interface
  418. + Features & Offloads
  419. +
  420. +
  421. +Supported Platforms
  422. +===================
  423. +This driver provides networking support for Freescale DPAA2 SoCs, e.g.
  424. +LS2080A, LS2088A, LS1088A.
  425. +
  426. +
  427. +Architecture Overview
  428. +=====================
  429. +Unlike regular NICs, in the DPAA2 architecture there is no single hardware block
  430. +representing network interfaces; instead, several separate hardware resources
  431. +concur to provide the networking functionality:
  432. + - network interfaces
  433. + - queues, channels
  434. + - buffer pools
  435. + - MAC/PHY
  436. +
  437. +All hardware resources are allocated and configured through the Management
  438. +Complex (MC) portals. MC abstracts most of these resources as DPAA2 objects
  439. +and exposes ABIs through which they can be configured and controlled. A few
  440. +hardware resources, like queues, do not have a corresponding MC object and
  441. +are treated as internal resources of other objects.
  442. +
  443. +For a more detailed description of the DPAA2 architecture and its object
  444. +abstractions see:
  445. + drivers/staging/fsl-mc/README.txt
  446. +
  447. +Each Linux net device is built on top of a Datapath Network Interface (DPNI)
  448. +object and uses Buffer Pools (DPBPs), I/O Portals (DPIOs) and Concentrators
  449. +(DPCONs).
  450. +
  451. +Configuration interface:
  452. +
  453. + -----------------------
  454. + | DPAA2 Ethernet Driver |
  455. + -----------------------
  456. + . . .
  457. + . . .
  458. + . . . . . . . . . . . .
  459. + . . .
  460. + . . .
  461. + ---------- ---------- -----------
  462. + | DPBP API | | DPNI API | | DPCON API |
  463. + ---------- ---------- -----------
  464. + . . . software
  465. +=========== . ========== . ============ . ===================
  466. + . . . hardware
  467. + ------------------------------------------
  468. + | MC hardware portals |
  469. + ------------------------------------------
  470. + . . .
  471. + . . .
  472. + ------ ------ -------
  473. + | DPBP | | DPNI | | DPCON |
  474. + ------ ------ -------
  475. +
  476. +The DPNIs are network interfaces without a direct one-on-one mapping to PHYs.
  477. +DPBPs represent hardware buffer pools. Packet I/O is performed in the context
  478. +of DPCON objects, using DPIO portals for managing and communicating with the
  479. +hardware resources.
  480. +
  481. +Datapath (I/O) interface:
  482. +
  483. + -----------------------------------------------
  484. + | DPAA2 Ethernet Driver |
  485. + -----------------------------------------------
  486. + | ^ ^ | |
  487. + | | | | |
  488. + enqueue| dequeue| data | dequeue| seed |
  489. + (Tx) | (Rx, TxC)| avail.| request| buffers|
  490. + | | notify| | |
  491. + | | | | |
  492. + V | | V V
  493. + -----------------------------------------------
  494. + | DPIO Driver |
  495. + -----------------------------------------------
  496. + | | | | | software
  497. + | | | | | ================
  498. + | | | | | hardware
  499. + -----------------------------------------------
  500. + | I/O hardware portals |
  501. + -----------------------------------------------
  502. + | ^ ^ | |
  503. + | | | | |
  504. + | | | V |
  505. + V | ================ V
  506. + ---------------------- | -------------
  507. + queues ---------------------- | | Buffer pool |
  508. + ---------------------- | -------------
  509. + =======================
  510. + Channel
  511. +
  512. +Datapath I/O (DPIO) portals provide enqueue and dequeue services, data
  513. +availability notifications and buffer pool management. DPIOs are shared between
  514. +all DPAA2 objects (and implicitly all DPAA2 kernel drivers) that work with data
  515. +frames, but must be affine to the CPUs for the purpose of traffic distribution.
  516. +
  517. +Frames are transmitted and received through hardware frame queues, which can be
  518. +grouped in channels for the purpose of hardware scheduling. The Ethernet driver
  519. +enqueues TX frames on egress queues and after transmission is complete a TX
  520. +confirmation frame is sent back to the CPU.
  521. +
  522. +When frames are available on ingress queues, a data availability notification
  523. +is sent to the CPU; notifications are raised per channel, so even if multiple
  524. +queues in the same channel have available frames, only one notification is sent.
  525. +After a channel fires a notification, is must be explicitly rearmed.
  526. +
  527. +Each network interface can have multiple Rx, Tx and confirmation queues affined
  528. +to CPUs, and one channel (DPCON) for each CPU that services at least one queue.
  529. +DPCONs are used to distribute ingress traffic to different CPUs via the cores'
  530. +affine DPIOs.
  531. +
  532. +The role of hardware buffer pools is storage of ingress frame data. Each network
  533. +interface has a privately owned buffer pool which it seeds with kernel allocated
  534. +buffers.
  535. +
  536. +
  537. +DPNIs are decoupled from PHYs; a DPNI can be connected to a PHY through a DPMAC
  538. +object or to another DPNI through an internal link, but the connection is
  539. +managed by MC and completely transparent to the Ethernet driver.
  540. +
  541. + --------- --------- ---------
  542. + | eth if1 | | eth if2 | | eth ifn |
  543. + --------- --------- ---------
  544. + . . .
  545. + . . .
  546. + . . .
  547. + ---------------------------
  548. + | DPAA2 Ethernet Driver |
  549. + ---------------------------
  550. + . . .
  551. + . . .
  552. + . . .
  553. + ------ ------ ------ -------
  554. + | DPNI | | DPNI | | DPNI | | DPMAC |----+
  555. + ------ ------ ------ ------- |
  556. + | | | | |
  557. + | | | | -----
  558. + =========== ================== | PHY |
  559. + -----
  560. +
  561. +Creating a Network Interface
  562. +============================
  563. +A net device is created for each DPNI object probed on the MC bus. Each DPNI has
  564. +a number of properties which determine the network interface configuration
  565. +options and associated hardware resources.
  566. +
  567. +DPNI objects (and the other DPAA2 objects needed for a network interface) can be
  568. +added to a container on the MC bus in one of two ways: statically, through a
  569. +Datapath Layout Binary file (DPL) that is parsed by MC at boot time; or created
  570. +dynamically at runtime, via the DPAA2 objects APIs.
  571. +
  572. +
  573. +Features & Offloads
  574. +===================
  575. +Hardware checksum offloading is supported for TCP and UDP over IPv4/6 frames.
  576. +The checksum offloads can be independently configured on RX and TX through
  577. +ethtool.
  578. +
  579. +Hardware offload of unicast and multicast MAC filtering is supported on the
  580. +ingress path and permanently enabled.
  581. +
  582. +Scatter-gather frames are supported on both RX and TX paths. On TX, SG support
  583. +is configurable via ethtool; on RX it is always enabled.
  584. +
  585. +The DPAA2 hardware can process jumbo Ethernet frames of up to 10K bytes.
  586. +
  587. +The Ethernet driver defines a static flow hashing scheme that distributes
  588. +traffic based on a 5-tuple key: src IP, dst IP, IP proto, L4 src port,
  589. +L4 dst port. No user configuration is supported for now.
  590. +
  591. +Hardware specific statistics for the network interface as well as some
  592. +non-standard driver stats can be consulted through ethtool -S option.
  593. --- /dev/null
  594. +++ b/drivers/staging/fsl-dpaa2/ethernet/dpaa2-eth-debugfs.c
  595. @@ -0,0 +1,350 @@
  596. +
  597. +/* Copyright 2015 Freescale Semiconductor Inc.
  598. + *
  599. + * Redistribution and use in source and binary forms, with or without
  600. + * modification, are permitted provided that the following conditions are met:
  601. + * * Redistributions of source code must retain the above copyright
  602. + * notice, this list of conditions and the following disclaimer.
  603. + * * Redistributions in binary form must reproduce the above copyright
  604. + * notice, this list of conditions and the following disclaimer in the
  605. + * documentation and/or other materials provided with the distribution.
  606. + * * Neither the name of Freescale Semiconductor nor the
  607. + * names of its contributors may be used to endorse or promote products
  608. + * derived from this software without specific prior written permission.
  609. + *
  610. + *
  611. + * ALTERNATIVELY, this software may be distributed under the terms of the
  612. + * GNU General Public License ("GPL") as published by the Free Software
  613. + * Foundation, either version 2 of that License or (at your option) any
  614. + * later version.
  615. + *
  616. + * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
  617. + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  618. + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  619. + * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
  620. + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  621. + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  622. + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  623. + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  624. + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  625. + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  626. + */
  627. +
  628. +#include <linux/module.h>
  629. +#include <linux/debugfs.h>
  630. +#include "dpaa2-eth.h"
  631. +#include "dpaa2-eth-debugfs.h"
  632. +
  633. +#define DPAA2_ETH_DBG_ROOT "dpaa2-eth"
  634. +
  635. +static struct dentry *dpaa2_dbg_root;
  636. +
  637. +static int dpaa2_dbg_cpu_show(struct seq_file *file, void *offset)
  638. +{
  639. + struct dpaa2_eth_priv *priv = (struct dpaa2_eth_priv *)file->private;
  640. + struct rtnl_link_stats64 *stats;
  641. + struct dpaa2_eth_drv_stats *extras;
  642. + int i;
  643. +
  644. + seq_printf(file, "Per-CPU stats for %s\n", priv->net_dev->name);
  645. + seq_printf(file, "%s%16s%16s%16s%16s%16s%16s%16s%16s\n",
  646. + "CPU", "Rx", "Rx Err", "Rx SG", "Tx", "Tx Err", "Tx conf",
  647. + "Tx SG", "Enq busy");
  648. +
  649. + for_each_online_cpu(i) {
  650. + stats = per_cpu_ptr(priv->percpu_stats, i);
  651. + extras = per_cpu_ptr(priv->percpu_extras, i);
  652. + seq_printf(file, "%3d%16llu%16llu%16llu%16llu%16llu%16llu%16llu%16llu\n",
  653. + i,
  654. + stats->rx_packets,
  655. + stats->rx_errors,
  656. + extras->rx_sg_frames,
  657. + stats->tx_packets,
  658. + stats->tx_errors,
  659. + extras->tx_conf_frames,
  660. + extras->tx_sg_frames,
  661. + extras->tx_portal_busy);
  662. + }
  663. +
  664. + return 0;
  665. +}
  666. +
  667. +static int dpaa2_dbg_cpu_open(struct inode *inode, struct file *file)
  668. +{
  669. + int err;
  670. + struct dpaa2_eth_priv *priv = (struct dpaa2_eth_priv *)inode->i_private;
  671. +
  672. + err = single_open(file, dpaa2_dbg_cpu_show, priv);
  673. + if (err < 0)
  674. + netdev_err(priv->net_dev, "single_open() failed\n");
  675. +
  676. + return err;
  677. +}
  678. +
  679. +static const struct file_operations dpaa2_dbg_cpu_ops = {
  680. + .open = dpaa2_dbg_cpu_open,
  681. + .read = seq_read,
  682. + .llseek = seq_lseek,
  683. + .release = single_release,
  684. +};
  685. +
  686. +static char *fq_type_to_str(struct dpaa2_eth_fq *fq)
  687. +{
  688. + switch (fq->type) {
  689. + case DPAA2_RX_FQ:
  690. + return "Rx";
  691. + case DPAA2_TX_CONF_FQ:
  692. + return "Tx conf";
  693. + case DPAA2_RX_ERR_FQ:
  694. + return "Rx err";
  695. + default:
  696. + return "N/A";
  697. + }
  698. +}
  699. +
  700. +static int dpaa2_dbg_fqs_show(struct seq_file *file, void *offset)
  701. +{
  702. + struct dpaa2_eth_priv *priv = (struct dpaa2_eth_priv *)file->private;
  703. + struct dpaa2_eth_fq *fq;
  704. + u32 fcnt, bcnt;
  705. + int i, err;
  706. +
  707. + seq_printf(file, "FQ stats for %s:\n", priv->net_dev->name);
  708. + seq_printf(file, "%s%16s%16s%16s%16s%16s\n",
  709. + "VFQID", "CPU", "Type", "Frames", "Pending frames",
  710. + "Congestion");
  711. +
  712. + for (i = 0; i < priv->num_fqs; i++) {
  713. + fq = &priv->fq[i];
  714. + err = dpaa2_io_query_fq_count(NULL, fq->fqid, &fcnt, &bcnt);
  715. + if (err)
  716. + fcnt = 0;
  717. +
  718. + seq_printf(file, "%5d%16d%16s%16llu%16u%16llu\n",
  719. + fq->fqid,
  720. + fq->target_cpu,
  721. + fq_type_to_str(fq),
  722. + fq->stats.frames,
  723. + fcnt,
  724. + fq->stats.congestion_entry);
  725. + }
  726. +
  727. + return 0;
  728. +}
  729. +
  730. +static int dpaa2_dbg_fqs_open(struct inode *inode, struct file *file)
  731. +{
  732. + int err;
  733. + struct dpaa2_eth_priv *priv = (struct dpaa2_eth_priv *)inode->i_private;
  734. +
  735. + err = single_open(file, dpaa2_dbg_fqs_show, priv);
  736. + if (err < 0)
  737. + netdev_err(priv->net_dev, "single_open() failed\n");
  738. +
  739. + return err;
  740. +}
  741. +
  742. +static const struct file_operations dpaa2_dbg_fq_ops = {
  743. + .open = dpaa2_dbg_fqs_open,
  744. + .read = seq_read,
  745. + .llseek = seq_lseek,
  746. + .release = single_release,
  747. +};
  748. +
  749. +static int dpaa2_dbg_ch_show(struct seq_file *file, void *offset)
  750. +{
  751. + struct dpaa2_eth_priv *priv = (struct dpaa2_eth_priv *)file->private;
  752. + struct dpaa2_eth_channel *ch;
  753. + int i;
  754. +
  755. + seq_printf(file, "Channel stats for %s:\n", priv->net_dev->name);
  756. + seq_printf(file, "%s%16s%16s%16s%16s%16s\n",
  757. + "CHID", "CPU", "Deq busy", "Frames", "CDANs",
  758. + "Avg frm/CDAN");
  759. +
  760. + for (i = 0; i < priv->num_channels; i++) {
  761. + ch = priv->channel[i];
  762. + seq_printf(file, "%4d%16d%16llu%16llu%16llu%16llu\n",
  763. + ch->ch_id,
  764. + ch->nctx.desired_cpu,
  765. + ch->stats.dequeue_portal_busy,
  766. + ch->stats.frames,
  767. + ch->stats.cdan,
  768. + ch->stats.frames / ch->stats.cdan);
  769. + }
  770. +
  771. + return 0;
  772. +}
  773. +
  774. +static int dpaa2_dbg_ch_open(struct inode *inode, struct file *file)
  775. +{
  776. + int err;
  777. + struct dpaa2_eth_priv *priv = (struct dpaa2_eth_priv *)inode->i_private;
  778. +
  779. + err = single_open(file, dpaa2_dbg_ch_show, priv);
  780. + if (err < 0)
  781. + netdev_err(priv->net_dev, "single_open() failed\n");
  782. +
  783. + return err;
  784. +}
  785. +
  786. +static const struct file_operations dpaa2_dbg_ch_ops = {
  787. + .open = dpaa2_dbg_ch_open,
  788. + .read = seq_read,
  789. + .llseek = seq_lseek,
  790. + .release = single_release,
  791. +};
  792. +
  793. +static ssize_t dpaa2_dbg_reset_write(struct file *file, const char __user *buf,
  794. + size_t count, loff_t *offset)
  795. +{
  796. + struct dpaa2_eth_priv *priv = file->private_data;
  797. + struct rtnl_link_stats64 *percpu_stats;
  798. + struct dpaa2_eth_drv_stats *percpu_extras;
  799. + struct dpaa2_eth_fq *fq;
  800. + struct dpaa2_eth_channel *ch;
  801. + int i;
  802. +
  803. + for_each_online_cpu(i) {
  804. + percpu_stats = per_cpu_ptr(priv->percpu_stats, i);
  805. + memset(percpu_stats, 0, sizeof(*percpu_stats));
  806. +
  807. + percpu_extras = per_cpu_ptr(priv->percpu_extras, i);
  808. + memset(percpu_extras, 0, sizeof(*percpu_extras));
  809. + }
  810. +
  811. + for (i = 0; i < priv->num_fqs; i++) {
  812. + fq = &priv->fq[i];
  813. + memset(&fq->stats, 0, sizeof(fq->stats));
  814. + }
  815. +
  816. + for (i = 0; i < priv->num_channels; i++) {
  817. + ch = priv->channel[i];
  818. + memset(&ch->stats, 0, sizeof(ch->stats));
  819. + }
  820. +
  821. + return count;
  822. +}
  823. +
  824. +static const struct file_operations dpaa2_dbg_reset_ops = {
  825. + .open = simple_open,
  826. + .write = dpaa2_dbg_reset_write,
  827. +};
  828. +
  829. +static ssize_t dpaa2_dbg_reset_mc_write(struct file *file,
  830. + const char __user *buf,
  831. + size_t count, loff_t *offset)
  832. +{
  833. + struct dpaa2_eth_priv *priv = file->private_data;
  834. + int err;
  835. +
  836. + err = dpni_reset_statistics(priv->mc_io, 0, priv->mc_token);
  837. + if (err)
  838. + netdev_err(priv->net_dev,
  839. + "dpni_reset_statistics() failed %d\n", err);
  840. +
  841. + return count;
  842. +}
  843. +
  844. +static const struct file_operations dpaa2_dbg_reset_mc_ops = {
  845. + .open = simple_open,
  846. + .write = dpaa2_dbg_reset_mc_write,
  847. +};
  848. +
  849. +void dpaa2_dbg_add(struct dpaa2_eth_priv *priv)
  850. +{
  851. + if (!dpaa2_dbg_root)
  852. + return;
  853. +
  854. + /* Create a directory for the interface */
  855. + priv->dbg.dir = debugfs_create_dir(priv->net_dev->name,
  856. + dpaa2_dbg_root);
  857. + if (!priv->dbg.dir) {
  858. + netdev_err(priv->net_dev, "debugfs_create_dir() failed\n");
  859. + return;
  860. + }
  861. +
  862. + /* per-cpu stats file */
  863. + priv->dbg.cpu_stats = debugfs_create_file("cpu_stats", 0444,
  864. + priv->dbg.dir, priv,
  865. + &dpaa2_dbg_cpu_ops);
  866. + if (!priv->dbg.cpu_stats) {
  867. + netdev_err(priv->net_dev, "debugfs_create_file() failed\n");
  868. + goto err_cpu_stats;
  869. + }
  870. +
  871. + /* per-fq stats file */
  872. + priv->dbg.fq_stats = debugfs_create_file("fq_stats", 0444,
  873. + priv->dbg.dir, priv,
  874. + &dpaa2_dbg_fq_ops);
  875. + if (!priv->dbg.fq_stats) {
  876. + netdev_err(priv->net_dev, "debugfs_create_file() failed\n");
  877. + goto err_fq_stats;
  878. + }
  879. +
  880. + /* per-fq stats file */
  881. + priv->dbg.ch_stats = debugfs_create_file("ch_stats", 0444,
  882. + priv->dbg.dir, priv,
  883. + &dpaa2_dbg_ch_ops);
  884. + if (!priv->dbg.fq_stats) {
  885. + netdev_err(priv->net_dev, "debugfs_create_file() failed\n");
  886. + goto err_ch_stats;
  887. + }
  888. +
  889. + /* reset stats */
  890. + priv->dbg.reset_stats = debugfs_create_file("reset_stats", 0200,
  891. + priv->dbg.dir, priv,
  892. + &dpaa2_dbg_reset_ops);
  893. + if (!priv->dbg.reset_stats) {
  894. + netdev_err(priv->net_dev, "debugfs_create_file() failed\n");
  895. + goto err_reset_stats;
  896. + }
  897. +
  898. + /* reset MC stats */
  899. + priv->dbg.reset_mc_stats = debugfs_create_file("reset_mc_stats",
  900. + 0222, priv->dbg.dir, priv,
  901. + &dpaa2_dbg_reset_mc_ops);
  902. + if (!priv->dbg.reset_mc_stats) {
  903. + netdev_err(priv->net_dev, "debugfs_create_file() failed\n");
  904. + goto err_reset_mc_stats;
  905. + }
  906. +
  907. + return;
  908. +
  909. +err_reset_mc_stats:
  910. + debugfs_remove(priv->dbg.reset_stats);
  911. +err_reset_stats:
  912. + debugfs_remove(priv->dbg.ch_stats);
  913. +err_ch_stats:
  914. + debugfs_remove(priv->dbg.fq_stats);
  915. +err_fq_stats:
  916. + debugfs_remove(priv->dbg.cpu_stats);
  917. +err_cpu_stats:
  918. + debugfs_remove(priv->dbg.dir);
  919. +}
  920. +
  921. +void dpaa2_dbg_remove(struct dpaa2_eth_priv *priv)
  922. +{
  923. + debugfs_remove(priv->dbg.reset_mc_stats);
  924. + debugfs_remove(priv->dbg.reset_stats);
  925. + debugfs_remove(priv->dbg.fq_stats);
  926. + debugfs_remove(priv->dbg.ch_stats);
  927. + debugfs_remove(priv->dbg.cpu_stats);
  928. + debugfs_remove(priv->dbg.dir);
  929. +}
  930. +
  931. +void dpaa2_eth_dbg_init(void)
  932. +{
  933. + dpaa2_dbg_root = debugfs_create_dir(DPAA2_ETH_DBG_ROOT, NULL);
  934. + if (!dpaa2_dbg_root) {
  935. + pr_err("DPAA2-ETH: debugfs create failed\n");
  936. + return;
  937. + }
  938. +
  939. + pr_info("DPAA2-ETH: debugfs created\n");
  940. +}
  941. +
  942. +void __exit dpaa2_eth_dbg_exit(void)
  943. +{
  944. + debugfs_remove(dpaa2_dbg_root);
  945. +}
  946. --- /dev/null
  947. +++ b/drivers/staging/fsl-dpaa2/ethernet/dpaa2-eth-debugfs.h
  948. @@ -0,0 +1,60 @@
  949. +/* Copyright 2015 Freescale Semiconductor Inc.
  950. + *
  951. + * Redistribution and use in source and binary forms, with or without
  952. + * modification, are permitted provided that the following conditions are met:
  953. + * * Redistributions of source code must retain the above copyright
  954. + * notice, this list of conditions and the following disclaimer.
  955. + * * Redistributions in binary form must reproduce the above copyright
  956. + * notice, this list of conditions and the following disclaimer in the
  957. + * documentation and/or other materials provided with the distribution.
  958. + * * Neither the name of Freescale Semiconductor nor the
  959. + * names of its contributors may be used to endorse or promote products
  960. + * derived from this software without specific prior written permission.
  961. + *
  962. + *
  963. + * ALTERNATIVELY, this software may be distributed under the terms of the
  964. + * GNU General Public License ("GPL") as published by the Free Software
  965. + * Foundation, either version 2 of that License or (at your option) any
  966. + * later version.
  967. + *
  968. + * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
  969. + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  970. + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  971. + * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
  972. + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  973. + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  974. + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  975. + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  976. + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  977. + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  978. + */
  979. +
  980. +#ifndef DPAA2_ETH_DEBUGFS_H
  981. +#define DPAA2_ETH_DEBUGFS_H
  982. +
  983. +#include <linux/dcache.h>
  984. +
  985. +struct dpaa2_eth_priv;
  986. +
  987. +struct dpaa2_debugfs {
  988. + struct dentry *dir;
  989. + struct dentry *fq_stats;
  990. + struct dentry *ch_stats;
  991. + struct dentry *cpu_stats;
  992. + struct dentry *reset_stats;
  993. + struct dentry *reset_mc_stats;
  994. +};
  995. +
  996. +#ifdef CONFIG_FSL_DPAA2_ETH_DEBUGFS
  997. +void dpaa2_eth_dbg_init(void);
  998. +void dpaa2_eth_dbg_exit(void);
  999. +void dpaa2_dbg_add(struct dpaa2_eth_priv *priv);
  1000. +void dpaa2_dbg_remove(struct dpaa2_eth_priv *priv);
  1001. +#else
  1002. +static inline void dpaa2_eth_dbg_init(void) {}
  1003. +static inline void dpaa2_eth_dbg_exit(void) {}
  1004. +static inline void dpaa2_dbg_add(struct dpaa2_eth_priv *priv) {}
  1005. +static inline void dpaa2_dbg_remove(struct dpaa2_eth_priv *priv) {}
  1006. +#endif /* CONFIG_FSL_DPAA2_ETH_DEBUGFS */
  1007. +
  1008. +#endif /* DPAA2_ETH_DEBUGFS_H */
  1009. --- /dev/null
  1010. +++ b/drivers/staging/fsl-dpaa2/ethernet/dpaa2-eth-trace.h
  1011. @@ -0,0 +1,184 @@
  1012. +/* Copyright 2014-2015 Freescale Semiconductor Inc.
  1013. + *
  1014. + * Redistribution and use in source and binary forms, with or without
  1015. + * modification, are permitted provided that the following conditions are met:
  1016. + * * Redistributions of source code must retain the above copyright
  1017. + * notice, this list of conditions and the following disclaimer.
  1018. + * * Redistributions in binary form must reproduce the above copyright
  1019. + * notice, this list of conditions and the following disclaimer in the
  1020. + * documentation and/or other materials provided with the distribution.
  1021. + * * Neither the name of Freescale Semiconductor nor the
  1022. + * names of its contributors may be used to endorse or promote products
  1023. + * derived from this software without specific prior written permission.
  1024. + *
  1025. + *
  1026. + * ALTERNATIVELY, this software may be distributed under the terms of the
  1027. + * GNU General Public License ("GPL") as published by the Free Software
  1028. + * Foundation, either version 2 of that License or (at your option) any
  1029. + * later version.
  1030. + *
  1031. + * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
  1032. + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  1033. + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  1034. + * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
  1035. + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  1036. + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  1037. + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  1038. + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  1039. + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  1040. + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  1041. + */
  1042. +
  1043. +#undef TRACE_SYSTEM
  1044. +#define TRACE_SYSTEM dpaa2_eth
  1045. +
  1046. +#if !defined(_DPAA2_ETH_TRACE_H) || defined(TRACE_HEADER_MULTI_READ)
  1047. +#define _DPAA2_ETH_TRACE_H
  1048. +
  1049. +#include <linux/skbuff.h>
  1050. +#include <linux/netdevice.h>
  1051. +#include <linux/tracepoint.h>
  1052. +
  1053. +#define TR_FMT "[%s] fd: addr=0x%llx, len=%u, off=%u"
  1054. +/* trace_printk format for raw buffer event class */
  1055. +#define TR_BUF_FMT "[%s] vaddr=%p size=%zu dma_addr=%pad map_size=%zu bpid=%d"
  1056. +
  1057. +/* This is used to declare a class of events.
  1058. + * individual events of this type will be defined below.
  1059. + */
  1060. +
  1061. +/* Store details about a frame descriptor */
  1062. +DECLARE_EVENT_CLASS(dpaa2_eth_fd,
  1063. + /* Trace function prototype */
  1064. + TP_PROTO(struct net_device *netdev,
  1065. + const struct dpaa2_fd *fd),
  1066. +
  1067. + /* Repeat argument list here */
  1068. + TP_ARGS(netdev, fd),
  1069. +
  1070. + /* A structure containing the relevant information we want
  1071. + * to record. Declare name and type for each normal element,
  1072. + * name, type and size for arrays. Use __string for variable
  1073. + * length strings.
  1074. + */
  1075. + TP_STRUCT__entry(
  1076. + __field(u64, fd_addr)
  1077. + __field(u32, fd_len)
  1078. + __field(u16, fd_offset)
  1079. + __string(name, netdev->name)
  1080. + ),
  1081. +
  1082. + /* The function that assigns values to the above declared
  1083. + * fields
  1084. + */
  1085. + TP_fast_assign(
  1086. + __entry->fd_addr = dpaa2_fd_get_addr(fd);
  1087. + __entry->fd_len = dpaa2_fd_get_len(fd);
  1088. + __entry->fd_offset = dpaa2_fd_get_offset(fd);
  1089. + __assign_str(name, netdev->name);
  1090. + ),
  1091. +
  1092. + /* This is what gets printed when the trace event is
  1093. + * triggered.
  1094. + */
  1095. + TP_printk(TR_FMT,
  1096. + __get_str(name),
  1097. + __entry->fd_addr,
  1098. + __entry->fd_len,
  1099. + __entry->fd_offset)
  1100. +);
  1101. +
  1102. +/* Now declare events of the above type. Format is:
  1103. + * DEFINE_EVENT(class, name, proto, args), with proto and args same as for class
  1104. + */
  1105. +
  1106. +/* Tx (egress) fd */
  1107. +DEFINE_EVENT(dpaa2_eth_fd, dpaa2_tx_fd,
  1108. + TP_PROTO(struct net_device *netdev,
  1109. + const struct dpaa2_fd *fd),
  1110. +
  1111. + TP_ARGS(netdev, fd)
  1112. +);
  1113. +
  1114. +/* Rx fd */
  1115. +DEFINE_EVENT(dpaa2_eth_fd, dpaa2_rx_fd,
  1116. + TP_PROTO(struct net_device *netdev,
  1117. + const struct dpaa2_fd *fd),
  1118. +
  1119. + TP_ARGS(netdev, fd)
  1120. +);
  1121. +
  1122. +/* Tx confirmation fd */
  1123. +DEFINE_EVENT(dpaa2_eth_fd, dpaa2_tx_conf_fd,
  1124. + TP_PROTO(struct net_device *netdev,
  1125. + const struct dpaa2_fd *fd),
  1126. +
  1127. + TP_ARGS(netdev, fd)
  1128. +);
  1129. +
  1130. +/* Log data about raw buffers. Useful for tracing DPBP content. */
  1131. +TRACE_EVENT(dpaa2_eth_buf_seed,
  1132. + /* Trace function prototype */
  1133. + TP_PROTO(struct net_device *netdev,
  1134. + /* virtual address and size */
  1135. + void *vaddr,
  1136. + size_t size,
  1137. + /* dma map address and size */
  1138. + dma_addr_t dma_addr,
  1139. + size_t map_size,
  1140. + /* buffer pool id, if relevant */
  1141. + u16 bpid),
  1142. +
  1143. + /* Repeat argument list here */
  1144. + TP_ARGS(netdev, vaddr, size, dma_addr, map_size, bpid),
  1145. +
  1146. + /* A structure containing the relevant information we want
  1147. + * to record. Declare name and type for each normal element,
  1148. + * name, type and size for arrays. Use __string for variable
  1149. + * length strings.
  1150. + */
  1151. + TP_STRUCT__entry(
  1152. + __field(void *, vaddr)
  1153. + __field(size_t, size)
  1154. + __field(dma_addr_t, dma_addr)
  1155. + __field(size_t, map_size)
  1156. + __field(u16, bpid)
  1157. + __string(name, netdev->name)
  1158. + ),
  1159. +
  1160. + /* The function that assigns values to the above declared
  1161. + * fields
  1162. + */
  1163. + TP_fast_assign(
  1164. + __entry->vaddr = vaddr;
  1165. + __entry->size = size;
  1166. + __entry->dma_addr = dma_addr;
  1167. + __entry->map_size = map_size;
  1168. + __entry->bpid = bpid;
  1169. + __assign_str(name, netdev->name);
  1170. + ),
  1171. +
  1172. + /* This is what gets printed when the trace event is
  1173. + * triggered.
  1174. + */
  1175. + TP_printk(TR_BUF_FMT,
  1176. + __get_str(name),
  1177. + __entry->vaddr,
  1178. + __entry->size,
  1179. + &__entry->dma_addr,
  1180. + __entry->map_size,
  1181. + __entry->bpid)
  1182. +);
  1183. +
  1184. +/* If only one event of a certain type needs to be declared, use TRACE_EVENT().
  1185. + * The syntax is the same as for DECLARE_EVENT_CLASS().
  1186. + */
  1187. +
  1188. +#endif /* _DPAA2_ETH_TRACE_H */
  1189. +
  1190. +/* This must be outside ifdef _DPAA2_ETH_TRACE_H */
  1191. +#undef TRACE_INCLUDE_PATH
  1192. +#define TRACE_INCLUDE_PATH .
  1193. +#undef TRACE_INCLUDE_FILE
  1194. +#define TRACE_INCLUDE_FILE dpaa2-eth-trace
  1195. +#include <trace/define_trace.h>
  1196. --- /dev/null
  1197. +++ b/drivers/staging/fsl-dpaa2/ethernet/dpaa2-eth.c
  1198. @@ -0,0 +1,3155 @@
  1199. +/* Copyright 2014-2015 Freescale Semiconductor Inc.
  1200. + *
  1201. + * Redistribution and use in source and binary forms, with or without
  1202. + * modification, are permitted provided that the following conditions are met:
  1203. + * * Redistributions of source code must retain the above copyright
  1204. + * notice, this list of conditions and the following disclaimer.
  1205. + * * Redistributions in binary form must reproduce the above copyright
  1206. + * notice, this list of conditions and the following disclaimer in the
  1207. + * documentation and/or other materials provided with the distribution.
  1208. + * * Neither the name of Freescale Semiconductor nor the
  1209. + * names of its contributors may be used to endorse or promote products
  1210. + * derived from this software without specific prior written permission.
  1211. + *
  1212. + *
  1213. + * ALTERNATIVELY, this software may be distributed under the terms of the
  1214. + * GNU General Public License ("GPL") as published by the Free Software
  1215. + * Foundation, either version 2 of that License or (at your option) any
  1216. + * later version.
  1217. + *
  1218. + * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
  1219. + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  1220. + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  1221. + * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
  1222. + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  1223. + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  1224. + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  1225. + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  1226. + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  1227. + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  1228. + */
  1229. +#include <linux/init.h>
  1230. +#include <linux/module.h>
  1231. +#include <linux/platform_device.h>
  1232. +#include <linux/etherdevice.h>
  1233. +#include <linux/of_net.h>
  1234. +#include <linux/interrupt.h>
  1235. +#include <linux/debugfs.h>
  1236. +#include <linux/kthread.h>
  1237. +#include <linux/msi.h>
  1238. +#include <linux/net_tstamp.h>
  1239. +#include <linux/iommu.h>
  1240. +
  1241. +#include "../../fsl-mc/include/dpbp.h"
  1242. +#include "../../fsl-mc/include/dpcon.h"
  1243. +#include "../../fsl-mc/include/mc.h"
  1244. +#include "../../fsl-mc/include/mc-sys.h"
  1245. +#include "dpaa2-eth.h"
  1246. +#include "dpkg.h"
  1247. +
  1248. +/* CREATE_TRACE_POINTS only needs to be defined once. Other dpa files
  1249. + * using trace events only need to #include <trace/events/sched.h>
  1250. + */
  1251. +#define CREATE_TRACE_POINTS
  1252. +#include "dpaa2-eth-trace.h"
  1253. +
  1254. +MODULE_LICENSE("Dual BSD/GPL");
  1255. +MODULE_AUTHOR("Freescale Semiconductor, Inc");
  1256. +MODULE_DESCRIPTION("Freescale DPAA2 Ethernet Driver");
  1257. +
  1258. +const char dpaa2_eth_drv_version[] = "0.1";
  1259. +
  1260. +void *dpaa2_eth_iova_to_virt(struct iommu_domain *domain, dma_addr_t iova_addr)
  1261. +{
  1262. + phys_addr_t phys_addr;
  1263. +
  1264. + phys_addr = domain ? iommu_iova_to_phys(domain, iova_addr) : iova_addr;
  1265. +
  1266. + return phys_to_virt(phys_addr);
  1267. +}
  1268. +
  1269. +static void validate_rx_csum(struct dpaa2_eth_priv *priv,
  1270. + u32 fd_status,
  1271. + struct sk_buff *skb)
  1272. +{
  1273. + skb_checksum_none_assert(skb);
  1274. +
  1275. + /* HW checksum validation is disabled, nothing to do here */
  1276. + if (!(priv->net_dev->features & NETIF_F_RXCSUM))
  1277. + return;
  1278. +
  1279. + /* Read checksum validation bits */
  1280. + if (!((fd_status & DPAA2_FAS_L3CV) &&
  1281. + (fd_status & DPAA2_FAS_L4CV)))
  1282. + return;
  1283. +
  1284. + /* Inform the stack there's no need to compute L3/L4 csum anymore */
  1285. + skb->ip_summed = CHECKSUM_UNNECESSARY;
  1286. +}
  1287. +
  1288. +/* Free a received FD.
  1289. + * Not to be used for Tx conf FDs or on any other paths.
  1290. + */
  1291. +static void free_rx_fd(struct dpaa2_eth_priv *priv,
  1292. + const struct dpaa2_fd *fd,
  1293. + void *vaddr)
  1294. +{
  1295. + struct device *dev = priv->net_dev->dev.parent;
  1296. + dma_addr_t addr = dpaa2_fd_get_addr(fd);
  1297. + u8 fd_format = dpaa2_fd_get_format(fd);
  1298. + struct dpaa2_sg_entry *sgt;
  1299. + void *sg_vaddr;
  1300. + int i;
  1301. +
  1302. + /* If single buffer frame, just free the data buffer */
  1303. + if (fd_format == dpaa2_fd_single)
  1304. + goto free_buf;
  1305. + else if (fd_format != dpaa2_fd_sg)
  1306. + /* we don't support any other format */
  1307. + return;
  1308. +
  1309. + /* For S/G frames, we first need to free all SG entries */
  1310. + sgt = vaddr + dpaa2_fd_get_offset(fd);
  1311. + for (i = 0; i < DPAA2_ETH_MAX_SG_ENTRIES; i++) {
  1312. + addr = dpaa2_sg_get_addr(&sgt[i]);
  1313. + sg_vaddr = dpaa2_eth_iova_to_virt(priv->iommu_domain, addr);
  1314. +
  1315. + dma_unmap_single(dev, addr, DPAA2_ETH_RX_BUF_SIZE,
  1316. + DMA_FROM_DEVICE);
  1317. +
  1318. + put_page(virt_to_head_page(sg_vaddr));
  1319. +
  1320. + if (dpaa2_sg_is_final(&sgt[i]))
  1321. + break;
  1322. + }
  1323. +
  1324. +free_buf:
  1325. + put_page(virt_to_head_page(vaddr));
  1326. +}
  1327. +
  1328. +/* Build a linear skb based on a single-buffer frame descriptor */
  1329. +static struct sk_buff *build_linear_skb(struct dpaa2_eth_priv *priv,
  1330. + struct dpaa2_eth_channel *ch,
  1331. + const struct dpaa2_fd *fd,
  1332. + void *fd_vaddr)
  1333. +{
  1334. + struct sk_buff *skb = NULL;
  1335. + u16 fd_offset = dpaa2_fd_get_offset(fd);
  1336. + u32 fd_length = dpaa2_fd_get_len(fd);
  1337. +
  1338. + skb = build_skb(fd_vaddr, DPAA2_ETH_SKB_SIZE);
  1339. + if (unlikely(!skb))
  1340. + return NULL;
  1341. +
  1342. + skb_reserve(skb, fd_offset);
  1343. + skb_put(skb, fd_length);
  1344. +
  1345. + ch->buf_count--;
  1346. +
  1347. + return skb;
  1348. +}
  1349. +
  1350. +/* Build a non linear (fragmented) skb based on a S/G table */
  1351. +static struct sk_buff *build_frag_skb(struct dpaa2_eth_priv *priv,
  1352. + struct dpaa2_eth_channel *ch,
  1353. + struct dpaa2_sg_entry *sgt)
  1354. +{
  1355. + struct sk_buff *skb = NULL;
  1356. + struct device *dev = priv->net_dev->dev.parent;
  1357. + void *sg_vaddr;
  1358. + dma_addr_t sg_addr;
  1359. + u16 sg_offset;
  1360. + u32 sg_length;
  1361. + struct page *page, *head_page;
  1362. + int page_offset;
  1363. + int i;
  1364. +
  1365. + for (i = 0; i < DPAA2_ETH_MAX_SG_ENTRIES; i++) {
  1366. + struct dpaa2_sg_entry *sge = &sgt[i];
  1367. +
  1368. + /* NOTE: We only support SG entries in dpaa2_sg_single format,
  1369. + * but this is the only format we may receive from HW anyway
  1370. + */
  1371. +
  1372. + /* Get the address and length from the S/G entry */
  1373. + sg_addr = dpaa2_sg_get_addr(sge);
  1374. + sg_vaddr = dpaa2_eth_iova_to_virt(priv->iommu_domain, sg_addr);
  1375. + dma_unmap_single(dev, sg_addr, DPAA2_ETH_RX_BUF_SIZE,
  1376. + DMA_FROM_DEVICE);
  1377. +
  1378. + sg_length = dpaa2_sg_get_len(sge);
  1379. +
  1380. + if (i == 0) {
  1381. + /* We build the skb around the first data buffer */
  1382. + skb = build_skb(sg_vaddr, DPAA2_ETH_SKB_SIZE);
  1383. + if (unlikely(!skb))
  1384. + return NULL;
  1385. +
  1386. + sg_offset = dpaa2_sg_get_offset(sge);
  1387. + skb_reserve(skb, sg_offset);
  1388. + skb_put(skb, sg_length);
  1389. + } else {
  1390. + /* Rest of the data buffers are stored as skb frags */
  1391. + page = virt_to_page(sg_vaddr);
  1392. + head_page = virt_to_head_page(sg_vaddr);
  1393. +
  1394. + /* Offset in page (which may be compound).
  1395. + * Data in subsequent SG entries is stored from the
  1396. + * beginning of the buffer, so we don't need to add the
  1397. + * sg_offset.
  1398. + */
  1399. + page_offset = ((unsigned long)sg_vaddr &
  1400. + (PAGE_SIZE - 1)) +
  1401. + (page_address(page) - page_address(head_page));
  1402. +
  1403. + skb_add_rx_frag(skb, i - 1, head_page, page_offset,
  1404. + sg_length, DPAA2_ETH_RX_BUF_SIZE);
  1405. + }
  1406. +
  1407. + if (dpaa2_sg_is_final(sge))
  1408. + break;
  1409. + }
  1410. +
  1411. + /* Count all data buffers + SG table buffer */
  1412. + ch->buf_count -= i + 2;
  1413. +
  1414. + return skb;
  1415. +}
  1416. +
  1417. +/* Main Rx frame processing routine */
  1418. +static void dpaa2_eth_rx(struct dpaa2_eth_priv *priv,
  1419. + struct dpaa2_eth_channel *ch,
  1420. + const struct dpaa2_fd *fd,
  1421. + struct napi_struct *napi,
  1422. + u16 queue_id)
  1423. +{
  1424. + dma_addr_t addr = dpaa2_fd_get_addr(fd);
  1425. + u8 fd_format = dpaa2_fd_get_format(fd);
  1426. + void *vaddr;
  1427. + struct sk_buff *skb;
  1428. + struct rtnl_link_stats64 *percpu_stats;
  1429. + struct dpaa2_eth_drv_stats *percpu_extras;
  1430. + struct device *dev = priv->net_dev->dev.parent;
  1431. + struct dpaa2_fas *fas;
  1432. + void *buf_data;
  1433. + u32 status = 0;
  1434. +
  1435. + /* Tracing point */
  1436. + trace_dpaa2_rx_fd(priv->net_dev, fd);
  1437. +
  1438. + vaddr = dpaa2_eth_iova_to_virt(priv->iommu_domain, addr);
  1439. + dma_unmap_single(dev, addr, DPAA2_ETH_RX_BUF_SIZE, DMA_FROM_DEVICE);
  1440. +
  1441. + /* HWA - FAS, timestamp */
  1442. + fas = dpaa2_eth_get_fas(vaddr);
  1443. + prefetch(fas);
  1444. + /* data / SG table */
  1445. + buf_data = vaddr + dpaa2_fd_get_offset(fd);
  1446. + prefetch(buf_data);
  1447. +
  1448. + percpu_stats = this_cpu_ptr(priv->percpu_stats);
  1449. + percpu_extras = this_cpu_ptr(priv->percpu_extras);
  1450. +
  1451. + switch (fd_format) {
  1452. + case dpaa2_fd_single:
  1453. + skb = build_linear_skb(priv, ch, fd, vaddr);
  1454. + break;
  1455. + case dpaa2_fd_sg:
  1456. + skb = build_frag_skb(priv, ch, buf_data);
  1457. + put_page(virt_to_head_page(vaddr));
  1458. + percpu_extras->rx_sg_frames++;
  1459. + percpu_extras->rx_sg_bytes += dpaa2_fd_get_len(fd);
  1460. + break;
  1461. + default:
  1462. + /* We don't support any other format */
  1463. + goto err_frame_format;
  1464. + }
  1465. +
  1466. + if (unlikely(!skb))
  1467. + goto err_build_skb;
  1468. +
  1469. + prefetch(skb->data);
  1470. +
  1471. + /* Get the timestamp value */
  1472. + if (priv->ts_rx_en) {
  1473. + struct skb_shared_hwtstamps *shhwtstamps = skb_hwtstamps(skb);
  1474. + u64 *ns = (u64 *)dpaa2_eth_get_ts(vaddr);
  1475. +
  1476. + *ns = DPAA2_PTP_NOMINAL_FREQ_PERIOD_NS * le64_to_cpup(ns);
  1477. + memset(shhwtstamps, 0, sizeof(*shhwtstamps));
  1478. + shhwtstamps->hwtstamp = ns_to_ktime(*ns);
  1479. + }
  1480. +
  1481. + /* Check if we need to validate the L4 csum */
  1482. + if (likely(dpaa2_fd_get_frc(fd) & DPAA2_FD_FRC_FASV)) {
  1483. + status = le32_to_cpu(fas->status);
  1484. + validate_rx_csum(priv, status, skb);
  1485. + }
  1486. +
  1487. + skb->protocol = eth_type_trans(skb, priv->net_dev);
  1488. +
  1489. + /* Record Rx queue - this will be used when picking a Tx queue to
  1490. + * forward the frames. We're keeping flow affinity through the
  1491. + * network stack.
  1492. + */
  1493. + skb_record_rx_queue(skb, queue_id);
  1494. +
  1495. + percpu_stats->rx_packets++;
  1496. + percpu_stats->rx_bytes += dpaa2_fd_get_len(fd);
  1497. +
  1498. + napi_gro_receive(napi, skb);
  1499. +
  1500. + return;
  1501. +
  1502. +err_build_skb:
  1503. + free_rx_fd(priv, fd, vaddr);
  1504. +err_frame_format:
  1505. + percpu_stats->rx_dropped++;
  1506. +}
  1507. +
  1508. +#ifdef CONFIG_FSL_DPAA2_ETH_USE_ERR_QUEUE
  1509. +/* Processing of Rx frames received on the error FQ
  1510. + * We check and print the error bits and then free the frame
  1511. + */
  1512. +static void dpaa2_eth_rx_err(struct dpaa2_eth_priv *priv,
  1513. + struct dpaa2_eth_channel *ch,
  1514. + const struct dpaa2_fd *fd,
  1515. + struct napi_struct *napi __always_unused,
  1516. + u16 queue_id __always_unused)
  1517. +{
  1518. + struct device *dev = priv->net_dev->dev.parent;
  1519. + dma_addr_t addr = dpaa2_fd_get_addr(fd);
  1520. + void *vaddr;
  1521. + struct rtnl_link_stats64 *percpu_stats;
  1522. + struct dpaa2_fas *fas;
  1523. + u32 status = 0;
  1524. + bool check_fas_errors = false;
  1525. +
  1526. + vaddr = dpaa2_eth_iova_to_virt(priv->iommu_domain, addr);
  1527. + dma_unmap_single(dev, addr, DPAA2_ETH_RX_BUF_SIZE, DMA_FROM_DEVICE);
  1528. +
  1529. + /* check frame errors in the FD field */
  1530. + if (fd->simple.ctrl & DPAA2_FD_RX_ERR_MASK) {
  1531. + check_fas_errors = !!(fd->simple.ctrl & FD_CTRL_FAERR) &&
  1532. + !!(dpaa2_fd_get_frc(fd) & DPAA2_FD_FRC_FASV);
  1533. + if (net_ratelimit())
  1534. + netdev_dbg(priv->net_dev, "Rx frame FD err: %x08\n",
  1535. + fd->simple.ctrl & DPAA2_FD_RX_ERR_MASK);
  1536. + }
  1537. +
  1538. + /* check frame errors in the FAS field */
  1539. + if (check_fas_errors) {
  1540. + fas = dpaa2_eth_get_fas(vaddr);
  1541. + status = le32_to_cpu(fas->status);
  1542. + if (net_ratelimit())
  1543. + netdev_dbg(priv->net_dev, "Rx frame FAS err: 0x%08x\n",
  1544. + status & DPAA2_FAS_RX_ERR_MASK);
  1545. + }
  1546. + free_rx_fd(priv, fd, vaddr);
  1547. +
  1548. + percpu_stats = this_cpu_ptr(priv->percpu_stats);
  1549. + percpu_stats->rx_errors++;
  1550. +}
  1551. +#endif
  1552. +
  1553. +/* Consume all frames pull-dequeued into the store. This is the simplest way to
  1554. + * make sure we don't accidentally issue another volatile dequeue which would
  1555. + * overwrite (leak) frames already in the store.
  1556. + *
  1557. + * The number of frames is returned using the last 2 output arguments,
  1558. + * separately for Rx and Tx confirmations.
  1559. + *
  1560. + * Observance of NAPI budget is not our concern, leaving that to the caller.
  1561. + */
  1562. +static bool consume_frames(struct dpaa2_eth_channel *ch, int *rx_cleaned,
  1563. + int *tx_conf_cleaned)
  1564. +{
  1565. + struct dpaa2_eth_priv *priv = ch->priv;
  1566. + struct dpaa2_eth_fq *fq = NULL;
  1567. + struct dpaa2_dq *dq;
  1568. + const struct dpaa2_fd *fd;
  1569. + int cleaned = 0;
  1570. + int is_last;
  1571. +
  1572. + do {
  1573. + dq = dpaa2_io_store_next(ch->store, &is_last);
  1574. + if (unlikely(!dq)) {
  1575. + /* If we're here, we *must* have placed a
  1576. + * volatile dequeue comnmand, so keep reading through
  1577. + * the store until we get some sort of valid response
  1578. + * token (either a valid frame or an "empty dequeue")
  1579. + */
  1580. + continue;
  1581. + }
  1582. +
  1583. + fd = dpaa2_dq_fd(dq);
  1584. +
  1585. + /* prefetch the frame descriptor */
  1586. + prefetch(fd);
  1587. +
  1588. + fq = (struct dpaa2_eth_fq *)dpaa2_dq_fqd_ctx(dq);
  1589. + fq->consume(priv, ch, fd, &ch->napi, fq->flowid);
  1590. + cleaned++;
  1591. + } while (!is_last);
  1592. +
  1593. + if (!cleaned)
  1594. + return false;
  1595. +
  1596. + /* All frames brought in store by a volatile dequeue
  1597. + * come from the same queue
  1598. + */
  1599. + if (fq->type == DPAA2_TX_CONF_FQ)
  1600. + *tx_conf_cleaned += cleaned;
  1601. + else
  1602. + *rx_cleaned += cleaned;
  1603. +
  1604. + fq->stats.frames += cleaned;
  1605. + ch->stats.frames += cleaned;
  1606. +
  1607. + return true;
  1608. +}
  1609. +
  1610. +/* Configure the egress frame annotation for timestamp update */
  1611. +static void enable_tx_tstamp(struct dpaa2_fd *fd, void *buf_start)
  1612. +{
  1613. + struct dpaa2_faead *faead;
  1614. + u32 ctrl;
  1615. + u32 frc;
  1616. +
  1617. + /* Mark the egress frame annotation area as valid */
  1618. + frc = dpaa2_fd_get_frc(fd);
  1619. + dpaa2_fd_set_frc(fd, frc | DPAA2_FD_FRC_FAEADV);
  1620. +
  1621. + /* enable UPD (update prepanded data) bit in FAEAD field of
  1622. + * hardware frame annotation area
  1623. + */
  1624. + ctrl = DPAA2_FAEAD_A2V | DPAA2_FAEAD_UPDV | DPAA2_FAEAD_UPD;
  1625. + faead = dpaa2_eth_get_faead(buf_start);
  1626. + faead->ctrl = cpu_to_le32(ctrl);
  1627. +}
  1628. +
  1629. +/* Create a frame descriptor based on a fragmented skb */
  1630. +static int build_sg_fd(struct dpaa2_eth_priv *priv,
  1631. + struct sk_buff *skb,
  1632. + struct dpaa2_fd *fd)
  1633. +{
  1634. + struct device *dev = priv->net_dev->dev.parent;
  1635. + void *sgt_buf = NULL;
  1636. + dma_addr_t addr;
  1637. + int nr_frags = skb_shinfo(skb)->nr_frags;
  1638. + struct dpaa2_sg_entry *sgt;
  1639. + int i, err;
  1640. + int sgt_buf_size;
  1641. + struct scatterlist *scl, *crt_scl;
  1642. + int num_sg;
  1643. + int num_dma_bufs;
  1644. + struct dpaa2_fas *fas;
  1645. + struct dpaa2_eth_swa *swa;
  1646. +
  1647. + /* Create and map scatterlist.
  1648. + * We don't advertise NETIF_F_FRAGLIST, so skb_to_sgvec() will not have
  1649. + * to go beyond nr_frags+1.
  1650. + * Note: We don't support chained scatterlists
  1651. + */
  1652. + if (unlikely(PAGE_SIZE / sizeof(struct scatterlist) < nr_frags + 1))
  1653. + return -EINVAL;
  1654. +
  1655. + scl = kcalloc(nr_frags + 1, sizeof(struct scatterlist), GFP_ATOMIC);
  1656. + if (unlikely(!scl))
  1657. + return -ENOMEM;
  1658. +
  1659. + sg_init_table(scl, nr_frags + 1);
  1660. + num_sg = skb_to_sgvec(skb, scl, 0, skb->len);
  1661. + num_dma_bufs = dma_map_sg(dev, scl, num_sg, DMA_TO_DEVICE);
  1662. + if (unlikely(!num_dma_bufs)) {
  1663. + err = -ENOMEM;
  1664. + goto dma_map_sg_failed;
  1665. + }
  1666. +
  1667. + /* Prepare the HW SGT structure */
  1668. + sgt_buf_size = priv->tx_data_offset +
  1669. + sizeof(struct dpaa2_sg_entry) * (1 + num_dma_bufs);
  1670. + sgt_buf = kzalloc(sgt_buf_size + DPAA2_ETH_TX_BUF_ALIGN, GFP_ATOMIC);
  1671. + if (unlikely(!sgt_buf)) {
  1672. + err = -ENOMEM;
  1673. + goto sgt_buf_alloc_failed;
  1674. + }
  1675. + sgt_buf = PTR_ALIGN(sgt_buf, DPAA2_ETH_TX_BUF_ALIGN);
  1676. +
  1677. + /* PTA from egress side is passed as is to the confirmation side so
  1678. + * we need to clear some fields here in order to find consistent values
  1679. + * on TX confirmation. We are clearing FAS (Frame Annotation Status)
  1680. + * field from the hardware annotation area
  1681. + */
  1682. + fas = dpaa2_eth_get_fas(sgt_buf);
  1683. + memset(fas, 0, DPAA2_FAS_SIZE);
  1684. +
  1685. + sgt = (struct dpaa2_sg_entry *)(sgt_buf + priv->tx_data_offset);
  1686. +
  1687. + /* Fill in the HW SGT structure.
  1688. + *
  1689. + * sgt_buf is zeroed out, so the following fields are implicit
  1690. + * in all sgt entries:
  1691. + * - offset is 0
  1692. + * - format is 'dpaa2_sg_single'
  1693. + */
  1694. + for_each_sg(scl, crt_scl, num_dma_bufs, i) {
  1695. + dpaa2_sg_set_addr(&sgt[i], sg_dma_address(crt_scl));
  1696. + dpaa2_sg_set_len(&sgt[i], sg_dma_len(crt_scl));
  1697. + }
  1698. + dpaa2_sg_set_final(&sgt[i - 1], true);
  1699. +
  1700. + /* Store the skb backpointer in the SGT buffer.
  1701. + * Fit the scatterlist and the number of buffers alongside the
  1702. + * skb backpointer in the software annotation area. We'll need
  1703. + * all of them on Tx Conf.
  1704. + */
  1705. + swa = (struct dpaa2_eth_swa *)sgt_buf;
  1706. + swa->skb = skb;
  1707. + swa->scl = scl;
  1708. + swa->num_sg = num_sg;
  1709. + swa->num_dma_bufs = num_dma_bufs;
  1710. +
  1711. + /* Separately map the SGT buffer */
  1712. + addr = dma_map_single(dev, sgt_buf, sgt_buf_size, DMA_BIDIRECTIONAL);
  1713. + if (unlikely(dma_mapping_error(dev, addr))) {
  1714. + err = -ENOMEM;
  1715. + goto dma_map_single_failed;
  1716. + }
  1717. + dpaa2_fd_set_offset(fd, priv->tx_data_offset);
  1718. + dpaa2_fd_set_format(fd, dpaa2_fd_sg);
  1719. + dpaa2_fd_set_addr(fd, addr);
  1720. + dpaa2_fd_set_len(fd, skb->len);
  1721. +
  1722. + fd->simple.ctrl = DPAA2_FD_CTRL_ASAL | FD_CTRL_PTA | FD_CTRL_PTV1;
  1723. +
  1724. + if (priv->ts_tx_en && skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP)
  1725. + enable_tx_tstamp(fd, sgt_buf);
  1726. +
  1727. + return 0;
  1728. +
  1729. +dma_map_single_failed:
  1730. + kfree(sgt_buf);
  1731. +sgt_buf_alloc_failed:
  1732. + dma_unmap_sg(dev, scl, num_sg, DMA_TO_DEVICE);
  1733. +dma_map_sg_failed:
  1734. + kfree(scl);
  1735. + return err;
  1736. +}
  1737. +
  1738. +/* Create a frame descriptor based on a linear skb */
  1739. +static int build_single_fd(struct dpaa2_eth_priv *priv,
  1740. + struct sk_buff *skb,
  1741. + struct dpaa2_fd *fd)
  1742. +{
  1743. + struct device *dev = priv->net_dev->dev.parent;
  1744. + u8 *buffer_start;
  1745. + struct sk_buff **skbh;
  1746. + dma_addr_t addr;
  1747. + struct dpaa2_fas *fas;
  1748. +
  1749. + buffer_start = PTR_ALIGN(skb->data - priv->tx_data_offset -
  1750. + DPAA2_ETH_TX_BUF_ALIGN,
  1751. + DPAA2_ETH_TX_BUF_ALIGN);
  1752. +
  1753. + /* PTA from egress side is passed as is to the confirmation side so
  1754. + * we need to clear some fields here in order to find consistent values
  1755. + * on TX confirmation. We are clearing FAS (Frame Annotation Status)
  1756. + * field from the hardware annotation area
  1757. + */
  1758. + fas = dpaa2_eth_get_fas(buffer_start);
  1759. + memset(fas, 0, DPAA2_FAS_SIZE);
  1760. +
  1761. + /* Store a backpointer to the skb at the beginning of the buffer
  1762. + * (in the private data area) such that we can release it
  1763. + * on Tx confirm
  1764. + */
  1765. + skbh = (struct sk_buff **)buffer_start;
  1766. + *skbh = skb;
  1767. +
  1768. + addr = dma_map_single(dev, buffer_start,
  1769. + skb_tail_pointer(skb) - buffer_start,
  1770. + DMA_BIDIRECTIONAL);
  1771. + if (unlikely(dma_mapping_error(dev, addr)))
  1772. + return -ENOMEM;
  1773. +
  1774. + dpaa2_fd_set_addr(fd, addr);
  1775. + dpaa2_fd_set_offset(fd, (u16)(skb->data - buffer_start));
  1776. + dpaa2_fd_set_len(fd, skb->len);
  1777. + dpaa2_fd_set_format(fd, dpaa2_fd_single);
  1778. +
  1779. + fd->simple.ctrl = DPAA2_FD_CTRL_ASAL | FD_CTRL_PTA | FD_CTRL_PTV1;
  1780. +
  1781. + if (priv->ts_tx_en && skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP)
  1782. + enable_tx_tstamp(fd, buffer_start);
  1783. +
  1784. + return 0;
  1785. +}
  1786. +
  1787. +/* FD freeing routine on the Tx path
  1788. + *
  1789. + * DMA-unmap and free FD and possibly SGT buffer allocated on Tx. The skb
  1790. + * back-pointed to is also freed.
  1791. + * This can be called either from dpaa2_eth_tx_conf() or on the error path of
  1792. + * dpaa2_eth_tx().
  1793. + * Optionally, return the frame annotation status word (FAS), which needs
  1794. + * to be checked if we're on the confirmation path.
  1795. + */
  1796. +static void free_tx_fd(const struct dpaa2_eth_priv *priv,
  1797. + const struct dpaa2_fd *fd,
  1798. + u32 *status)
  1799. +{
  1800. + struct device *dev = priv->net_dev->dev.parent;
  1801. + dma_addr_t fd_addr;
  1802. + struct sk_buff **skbh, *skb;
  1803. + unsigned char *buffer_start;
  1804. + int unmap_size;
  1805. + struct scatterlist *scl;
  1806. + int num_sg, num_dma_bufs;
  1807. + struct dpaa2_eth_swa *swa;
  1808. + u8 fd_format = dpaa2_fd_get_format(fd);
  1809. + struct dpaa2_fas *fas;
  1810. +
  1811. + fd_addr = dpaa2_fd_get_addr(fd);
  1812. + skbh = dpaa2_eth_iova_to_virt(priv->iommu_domain, fd_addr);
  1813. +
  1814. + /* HWA - FAS, timestamp (for Tx confirmation frames) */
  1815. + fas = dpaa2_eth_get_fas(skbh);
  1816. + prefetch(fas);
  1817. +
  1818. + switch (fd_format) {
  1819. + case dpaa2_fd_single:
  1820. + skb = *skbh;
  1821. + buffer_start = (unsigned char *)skbh;
  1822. + /* Accessing the skb buffer is safe before dma unmap, because
  1823. + * we didn't map the actual skb shell.
  1824. + */
  1825. + dma_unmap_single(dev, fd_addr,
  1826. + skb_tail_pointer(skb) - buffer_start,
  1827. + DMA_BIDIRECTIONAL);
  1828. + break;
  1829. + case dpaa2_fd_sg:
  1830. + swa = (struct dpaa2_eth_swa *)skbh;
  1831. + skb = swa->skb;
  1832. + scl = swa->scl;
  1833. + num_sg = swa->num_sg;
  1834. + num_dma_bufs = swa->num_dma_bufs;
  1835. +
  1836. + /* Unmap the scatterlist */
  1837. + dma_unmap_sg(dev, scl, num_sg, DMA_TO_DEVICE);
  1838. + kfree(scl);
  1839. +
  1840. + /* Unmap the SGT buffer */
  1841. + unmap_size = priv->tx_data_offset +
  1842. + sizeof(struct dpaa2_sg_entry) * (1 + num_dma_bufs);
  1843. + dma_unmap_single(dev, fd_addr, unmap_size, DMA_BIDIRECTIONAL);
  1844. + break;
  1845. + default:
  1846. + /* Unsupported format, mark it as errored and give up */
  1847. + if (status)
  1848. + *status = ~0;
  1849. + return;
  1850. + }
  1851. +
  1852. + /* Get the timestamp value */
  1853. + if (priv->ts_tx_en && skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP) {
  1854. + struct skb_shared_hwtstamps shhwtstamps;
  1855. + u64 *ns;
  1856. +
  1857. + memset(&shhwtstamps, 0, sizeof(shhwtstamps));
  1858. +
  1859. + ns = (u64 *)dpaa2_eth_get_ts(skbh);
  1860. + *ns = DPAA2_PTP_NOMINAL_FREQ_PERIOD_NS * le64_to_cpup(ns);
  1861. + shhwtstamps.hwtstamp = ns_to_ktime(*ns);
  1862. + skb_tstamp_tx(skb, &shhwtstamps);
  1863. + }
  1864. +
  1865. + /* Read the status from the Frame Annotation after we unmap the first
  1866. + * buffer but before we free it. The caller function is responsible
  1867. + * for checking the status value.
  1868. + */
  1869. + if (status)
  1870. + *status = le32_to_cpu(fas->status);
  1871. +
  1872. + /* Free SGT buffer kmalloc'ed on tx */
  1873. + if (fd_format != dpaa2_fd_single)
  1874. + kfree(skbh);
  1875. +
  1876. + /* Move on with skb release */
  1877. + dev_kfree_skb(skb);
  1878. +}
  1879. +
  1880. +static int dpaa2_eth_tx(struct sk_buff *skb, struct net_device *net_dev)
  1881. +{
  1882. + struct dpaa2_eth_priv *priv = netdev_priv(net_dev);
  1883. + struct device *dev = net_dev->dev.parent;
  1884. + struct dpaa2_fd fd;
  1885. + struct rtnl_link_stats64 *percpu_stats;
  1886. + struct dpaa2_eth_drv_stats *percpu_extras;
  1887. + struct dpaa2_eth_fq *fq;
  1888. + u16 queue_mapping = skb_get_queue_mapping(skb);
  1889. + int err, i;
  1890. +
  1891. + /* If we're congested, stop this tx queue; transmission of the
  1892. + * current skb happens regardless of congestion state
  1893. + */
  1894. + fq = &priv->fq[queue_mapping];
  1895. +
  1896. + dma_sync_single_for_cpu(dev, priv->cscn_dma,
  1897. + DPAA2_CSCN_SIZE, DMA_FROM_DEVICE);
  1898. + if (unlikely(dpaa2_cscn_state_congested(priv->cscn_mem))) {
  1899. + netif_stop_subqueue(net_dev, queue_mapping);
  1900. + fq->stats.congestion_entry++;
  1901. + }
  1902. +
  1903. + percpu_stats = this_cpu_ptr(priv->percpu_stats);
  1904. + percpu_extras = this_cpu_ptr(priv->percpu_extras);
  1905. +
  1906. + if (unlikely(skb_headroom(skb) < DPAA2_ETH_NEEDED_HEADROOM(priv))) {
  1907. + struct sk_buff *ns;
  1908. +
  1909. + ns = skb_realloc_headroom(skb, DPAA2_ETH_NEEDED_HEADROOM(priv));
  1910. + if (unlikely(!ns)) {
  1911. + percpu_stats->tx_dropped++;
  1912. + goto err_alloc_headroom;
  1913. + }
  1914. + dev_kfree_skb(skb);
  1915. + skb = ns;
  1916. + }
  1917. +
  1918. + /* We'll be holding a back-reference to the skb until Tx Confirmation;
  1919. + * we don't want that overwritten by a concurrent Tx with a cloned skb.
  1920. + */
  1921. + skb = skb_unshare(skb, GFP_ATOMIC);
  1922. + if (unlikely(!skb)) {
  1923. + /* skb_unshare() has already freed the skb */
  1924. + percpu_stats->tx_dropped++;
  1925. + return NETDEV_TX_OK;
  1926. + }
  1927. +
  1928. + /* Setup the FD fields */
  1929. + memset(&fd, 0, sizeof(fd));
  1930. +
  1931. + if (skb_is_nonlinear(skb)) {
  1932. + err = build_sg_fd(priv, skb, &fd);
  1933. + percpu_extras->tx_sg_frames++;
  1934. + percpu_extras->tx_sg_bytes += skb->len;
  1935. + } else {
  1936. + err = build_single_fd(priv, skb, &fd);
  1937. + }
  1938. +
  1939. + if (unlikely(err)) {
  1940. + percpu_stats->tx_dropped++;
  1941. + goto err_build_fd;
  1942. + }
  1943. +
  1944. + /* Tracing point */
  1945. + trace_dpaa2_tx_fd(net_dev, &fd);
  1946. +
  1947. + for (i = 0; i < DPAA2_ETH_ENQUEUE_RETRIES; i++) {
  1948. + err = dpaa2_io_service_enqueue_qd(NULL, priv->tx_qdid, 0,
  1949. + fq->tx_qdbin, &fd);
  1950. + /* TODO: This doesn't work. Check on simulator.
  1951. + * err = dpaa2_io_service_enqueue_fq(NULL,
  1952. + * priv->fq[0].fqid_tx, &fd);
  1953. + */
  1954. + if (err != -EBUSY)
  1955. + break;
  1956. + }
  1957. + percpu_extras->tx_portal_busy += i;
  1958. + if (unlikely(err < 0)) {
  1959. + percpu_stats->tx_errors++;
  1960. + /* Clean up everything, including freeing the skb */
  1961. + free_tx_fd(priv, &fd, NULL);
  1962. + } else {
  1963. + percpu_stats->tx_packets++;
  1964. + percpu_stats->tx_bytes += dpaa2_fd_get_len(&fd);
  1965. + }
  1966. +
  1967. + return NETDEV_TX_OK;
  1968. +
  1969. +err_build_fd:
  1970. +err_alloc_headroom:
  1971. + dev_kfree_skb(skb);
  1972. +
  1973. + return NETDEV_TX_OK;
  1974. +}
  1975. +
  1976. +/* Tx confirmation frame processing routine */
  1977. +static void dpaa2_eth_tx_conf(struct dpaa2_eth_priv *priv,
  1978. + struct dpaa2_eth_channel *ch,
  1979. + const struct dpaa2_fd *fd,
  1980. + struct napi_struct *napi __always_unused,
  1981. + u16 queue_id)
  1982. +{
  1983. + struct device *dev = priv->net_dev->dev.parent;
  1984. + struct rtnl_link_stats64 *percpu_stats;
  1985. + struct dpaa2_eth_drv_stats *percpu_extras;
  1986. + u32 status = 0;
  1987. + bool errors = !!(fd->simple.ctrl & DPAA2_FD_TX_ERR_MASK);
  1988. + bool check_fas_errors = false;
  1989. +
  1990. + /* Tracing point */
  1991. + trace_dpaa2_tx_conf_fd(priv->net_dev, fd);
  1992. +
  1993. + percpu_extras = this_cpu_ptr(priv->percpu_extras);
  1994. + percpu_extras->tx_conf_frames++;
  1995. + percpu_extras->tx_conf_bytes += dpaa2_fd_get_len(fd);
  1996. +
  1997. + /* Check congestion state and wake all queues if necessary */
  1998. + if (unlikely(__netif_subqueue_stopped(priv->net_dev, queue_id))) {
  1999. + dma_sync_single_for_cpu(dev, priv->cscn_dma,
  2000. + DPAA2_CSCN_SIZE, DMA_FROM_DEVICE);
  2001. + if (!dpaa2_cscn_state_congested(priv->cscn_mem))
  2002. + netif_tx_wake_all_queues(priv->net_dev);
  2003. + }
  2004. +
  2005. + /* check frame errors in the FD field */
  2006. + if (unlikely(errors)) {
  2007. + check_fas_errors = !!(fd->simple.ctrl & FD_CTRL_FAERR) &&
  2008. + !!(dpaa2_fd_get_frc(fd) & DPAA2_FD_FRC_FASV);
  2009. + if (net_ratelimit())
  2010. + netdev_dbg(priv->net_dev, "Tx frame FD err: %x08\n",
  2011. + fd->simple.ctrl & DPAA2_FD_TX_ERR_MASK);
  2012. + }
  2013. +
  2014. + free_tx_fd(priv, fd, check_fas_errors ? &status : NULL);
  2015. +
  2016. + /* if there are no errors, we're done */
  2017. + if (likely(!errors))
  2018. + return;
  2019. +
  2020. + percpu_stats = this_cpu_ptr(priv->percpu_stats);
  2021. + /* Tx-conf logically pertains to the egress path. */
  2022. + percpu_stats->tx_errors++;
  2023. +
  2024. + if (net_ratelimit())
  2025. + netdev_dbg(priv->net_dev, "Tx frame FAS err: %x08\n",
  2026. + status & DPAA2_FAS_TX_ERR_MASK);
  2027. +}
  2028. +
  2029. +static int set_rx_csum(struct dpaa2_eth_priv *priv, bool enable)
  2030. +{
  2031. + int err;
  2032. +
  2033. + err = dpni_set_offload(priv->mc_io, 0, priv->mc_token,
  2034. + DPNI_OFF_RX_L3_CSUM, enable);
  2035. + if (err) {
  2036. + netdev_err(priv->net_dev,
  2037. + "dpni_set_offload() DPNI_OFF_RX_L3_CSUM failed\n");
  2038. + return err;
  2039. + }
  2040. +
  2041. + err = dpni_set_offload(priv->mc_io, 0, priv->mc_token,
  2042. + DPNI_OFF_RX_L4_CSUM, enable);
  2043. + if (err) {
  2044. + netdev_err(priv->net_dev,
  2045. + "dpni_set_offload() DPNI_OFF_RX_L4_CSUM failed\n");
  2046. + return err;
  2047. + }
  2048. +
  2049. + return 0;
  2050. +}
  2051. +
  2052. +static int set_tx_csum(struct dpaa2_eth_priv *priv, bool enable)
  2053. +{
  2054. + int err;
  2055. +
  2056. + err = dpni_set_offload(priv->mc_io, 0, priv->mc_token,
  2057. + DPNI_OFF_TX_L3_CSUM, enable);
  2058. + if (err) {
  2059. + netdev_err(priv->net_dev,
  2060. + "dpni_set_offload() DPNI_OFF_RX_L3_CSUM failed\n");
  2061. + return err;
  2062. + }
  2063. +
  2064. + err = dpni_set_offload(priv->mc_io, 0, priv->mc_token,
  2065. + DPNI_OFF_TX_L4_CSUM, enable);
  2066. + if (err) {
  2067. + netdev_err(priv->net_dev,
  2068. + "dpni_set_offload() DPNI_OFF_RX_L4_CSUM failed\n");
  2069. + return err;
  2070. + }
  2071. +
  2072. + return 0;
  2073. +}
  2074. +
  2075. +/* Perform a single release command to add buffers
  2076. + * to the specified buffer pool
  2077. + */
  2078. +static int add_bufs(struct dpaa2_eth_priv *priv, u16 bpid)
  2079. +{
  2080. + struct device *dev = priv->net_dev->dev.parent;
  2081. + u64 buf_array[DPAA2_ETH_BUFS_PER_CMD];
  2082. + void *buf;
  2083. + dma_addr_t addr;
  2084. + int i;
  2085. +
  2086. + for (i = 0; i < DPAA2_ETH_BUFS_PER_CMD; i++) {
  2087. + /* Allocate buffer visible to WRIOP + skb shared info +
  2088. + * alignment padding.
  2089. + */
  2090. + buf = napi_alloc_frag(DPAA2_ETH_BUF_RAW_SIZE(priv));
  2091. + if (unlikely(!buf))
  2092. + goto err_alloc;
  2093. +
  2094. + buf = PTR_ALIGN(buf, priv->rx_buf_align);
  2095. +
  2096. + addr = dma_map_single(dev, buf, DPAA2_ETH_RX_BUF_SIZE,
  2097. + DMA_FROM_DEVICE);
  2098. + if (unlikely(dma_mapping_error(dev, addr)))
  2099. + goto err_map;
  2100. +
  2101. + buf_array[i] = addr;
  2102. +
  2103. + /* tracing point */
  2104. + trace_dpaa2_eth_buf_seed(priv->net_dev,
  2105. + buf, DPAA2_ETH_BUF_RAW_SIZE(priv),
  2106. + addr, DPAA2_ETH_RX_BUF_SIZE,
  2107. + bpid);
  2108. + }
  2109. +
  2110. +release_bufs:
  2111. + /* In case the portal is busy, retry until successful.
  2112. + * The buffer release function would only fail if the QBMan portal
  2113. + * was busy, which implies portal contention (i.e. more CPUs than
  2114. + * portals, i.e. GPPs w/o affine DPIOs). For all practical purposes,
  2115. + * there is little we can realistically do, short of giving up -
  2116. + * in which case we'd risk depleting the buffer pool and never again
  2117. + * receiving the Rx interrupt which would kick-start the refill logic.
  2118. + * So just keep retrying, at the risk of being moved to ksoftirqd.
  2119. + */
  2120. + while (dpaa2_io_service_release(NULL, bpid, buf_array, i))
  2121. + cpu_relax();
  2122. + return i;
  2123. +
  2124. +err_map:
  2125. + put_page(virt_to_head_page(buf));
  2126. +err_alloc:
  2127. + if (i)
  2128. + goto release_bufs;
  2129. +
  2130. + return 0;
  2131. +}
  2132. +
  2133. +static int seed_pool(struct dpaa2_eth_priv *priv, u16 bpid)
  2134. +{
  2135. + int i, j;
  2136. + int new_count;
  2137. +
  2138. + /* This is the lazy seeding of Rx buffer pools.
  2139. + * dpaa2_add_bufs() is also used on the Rx hotpath and calls
  2140. + * napi_alloc_frag(). The trouble with that is that it in turn ends up
  2141. + * calling this_cpu_ptr(), which mandates execution in atomic context.
  2142. + * Rather than splitting up the code, do a one-off preempt disable.
  2143. + */
  2144. + preempt_disable();
  2145. + for (j = 0; j < priv->num_channels; j++) {
  2146. + priv->channel[j]->buf_count = 0;
  2147. + for (i = 0; i < priv->num_bufs;
  2148. + i += DPAA2_ETH_BUFS_PER_CMD) {
  2149. + new_count = add_bufs(priv, bpid);
  2150. + priv->channel[j]->buf_count += new_count;
  2151. +
  2152. + if (new_count < DPAA2_ETH_BUFS_PER_CMD) {
  2153. + preempt_enable();
  2154. + return -ENOMEM;
  2155. + }
  2156. + }
  2157. + }
  2158. + preempt_enable();
  2159. +
  2160. + return 0;
  2161. +}
  2162. +
  2163. +/**
  2164. + * Drain the specified number of buffers from the DPNI's private buffer pool.
  2165. + * @count must not exceeed DPAA2_ETH_BUFS_PER_CMD
  2166. + */
  2167. +static void drain_bufs(struct dpaa2_eth_priv *priv, int count)
  2168. +{
  2169. + struct device *dev = priv->net_dev->dev.parent;
  2170. + u64 buf_array[DPAA2_ETH_BUFS_PER_CMD];
  2171. + void *vaddr;
  2172. + int ret, i;
  2173. +
  2174. + do {
  2175. + ret = dpaa2_io_service_acquire(NULL, priv->bpid,
  2176. + buf_array, count);
  2177. + if (ret < 0) {
  2178. + netdev_err(priv->net_dev, "dpaa2_io_service_acquire() failed\n");
  2179. + return;
  2180. + }
  2181. + for (i = 0; i < ret; i++) {
  2182. + /* Same logic as on regular Rx path */
  2183. + vaddr = dpaa2_eth_iova_to_virt(priv->iommu_domain,
  2184. + buf_array[i]);
  2185. + dma_unmap_single(dev, buf_array[i],
  2186. + DPAA2_ETH_RX_BUF_SIZE,
  2187. + DMA_FROM_DEVICE);
  2188. + put_page(virt_to_head_page(vaddr));
  2189. + }
  2190. + } while (ret);
  2191. +}
  2192. +
  2193. +static void drain_pool(struct dpaa2_eth_priv *priv)
  2194. +{
  2195. + preempt_disable();
  2196. + drain_bufs(priv, DPAA2_ETH_BUFS_PER_CMD);
  2197. + drain_bufs(priv, 1);
  2198. + preempt_enable();
  2199. +}
  2200. +
  2201. +/* Function is called from softirq context only, so we don't need to guard
  2202. + * the access to percpu count
  2203. + */
  2204. +static int refill_pool(struct dpaa2_eth_priv *priv,
  2205. + struct dpaa2_eth_channel *ch,
  2206. + u16 bpid)
  2207. +{
  2208. + int new_count;
  2209. +
  2210. + if (likely(ch->buf_count >= priv->refill_thresh))
  2211. + return 0;
  2212. +
  2213. + do {
  2214. + new_count = add_bufs(priv, bpid);
  2215. + if (unlikely(!new_count)) {
  2216. + /* Out of memory; abort for now, we'll try later on */
  2217. + break;
  2218. + }
  2219. + ch->buf_count += new_count;
  2220. + } while (ch->buf_count < priv->num_bufs);
  2221. +
  2222. + if (unlikely(ch->buf_count < priv->num_bufs))
  2223. + return -ENOMEM;
  2224. +
  2225. + return 0;
  2226. +}
  2227. +
  2228. +static int pull_channel(struct dpaa2_eth_channel *ch)
  2229. +{
  2230. + int err;
  2231. + int dequeues = -1;
  2232. +
  2233. + /* Retry while portal is busy */
  2234. + do {
  2235. + err = dpaa2_io_service_pull_channel(NULL, ch->ch_id, ch->store);
  2236. + dequeues++;
  2237. + cpu_relax();
  2238. + } while (err == -EBUSY);
  2239. +
  2240. + ch->stats.dequeue_portal_busy += dequeues;
  2241. + if (unlikely(err))
  2242. + ch->stats.pull_err++;
  2243. +
  2244. + return err;
  2245. +}
  2246. +
  2247. +/* NAPI poll routine
  2248. + *
  2249. + * Frames are dequeued from the QMan channel associated with this NAPI context.
  2250. + * Rx and (if configured) Rx error frames count towards the NAPI budget. Tx
  2251. + * confirmation frames are limited by a threshold per NAPI poll cycle.
  2252. + */
  2253. +static int dpaa2_eth_poll(struct napi_struct *napi, int budget)
  2254. +{
  2255. + struct dpaa2_eth_channel *ch;
  2256. + int rx_cleaned = 0, tx_conf_cleaned = 0;
  2257. + bool store_cleaned;
  2258. + struct dpaa2_eth_priv *priv;
  2259. + int err;
  2260. +
  2261. + ch = container_of(napi, struct dpaa2_eth_channel, napi);
  2262. + priv = ch->priv;
  2263. +
  2264. + do {
  2265. + err = pull_channel(ch);
  2266. + if (unlikely(err))
  2267. + break;
  2268. +
  2269. + /* Refill pool if appropriate */
  2270. + refill_pool(priv, ch, priv->bpid);
  2271. +
  2272. + store_cleaned = consume_frames(ch, &rx_cleaned,
  2273. + &tx_conf_cleaned);
  2274. +
  2275. + /* If we've either consumed the budget with Rx frames,
  2276. + * or reached the Tx conf threshold, we're done.
  2277. + */
  2278. + if (rx_cleaned >= budget ||
  2279. + tx_conf_cleaned >= TX_CONF_PER_NAPI_POLL)
  2280. + return budget;
  2281. + } while (store_cleaned);
  2282. +
  2283. + /* We didn't consume the entire budget, finish napi and
  2284. + * re-enable data availability notifications.
  2285. + */
  2286. + napi_complete(napi);
  2287. + do {
  2288. + err = dpaa2_io_service_rearm(NULL, &ch->nctx);
  2289. + cpu_relax();
  2290. + } while (err == -EBUSY);
  2291. +
  2292. + return max(rx_cleaned, 1);
  2293. +}
  2294. +
  2295. +static void enable_ch_napi(struct dpaa2_eth_priv *priv)
  2296. +{
  2297. + struct dpaa2_eth_channel *ch;
  2298. + int i;
  2299. +
  2300. + for (i = 0; i < priv->num_channels; i++) {
  2301. + ch = priv->channel[i];
  2302. + napi_enable(&ch->napi);
  2303. + }
  2304. +}
  2305. +
  2306. +static void disable_ch_napi(struct dpaa2_eth_priv *priv)
  2307. +{
  2308. + struct dpaa2_eth_channel *ch;
  2309. + int i;
  2310. +
  2311. + for (i = 0; i < priv->num_channels; i++) {
  2312. + ch = priv->channel[i];
  2313. + napi_disable(&ch->napi);
  2314. + }
  2315. +}
  2316. +
  2317. +static int link_state_update(struct dpaa2_eth_priv *priv)
  2318. +{
  2319. + struct dpni_link_state state;
  2320. + int err;
  2321. +
  2322. + err = dpni_get_link_state(priv->mc_io, 0, priv->mc_token, &state);
  2323. + if (unlikely(err)) {
  2324. + netdev_err(priv->net_dev,
  2325. + "dpni_get_link_state() failed\n");
  2326. + return err;
  2327. + }
  2328. +
  2329. + /* Chech link state; speed / duplex changes are not treated yet */
  2330. + if (priv->link_state.up == state.up)
  2331. + return 0;
  2332. +
  2333. + priv->link_state = state;
  2334. + if (state.up) {
  2335. + netif_carrier_on(priv->net_dev);
  2336. + netif_tx_start_all_queues(priv->net_dev);
  2337. + } else {
  2338. + netif_tx_stop_all_queues(priv->net_dev);
  2339. + netif_carrier_off(priv->net_dev);
  2340. + }
  2341. +
  2342. + netdev_info(priv->net_dev, "Link Event: state %s",
  2343. + state.up ? "up" : "down");
  2344. +
  2345. + return 0;
  2346. +}
  2347. +
  2348. +static int dpaa2_eth_open(struct net_device *net_dev)
  2349. +{
  2350. + struct dpaa2_eth_priv *priv = netdev_priv(net_dev);
  2351. + int err;
  2352. +
  2353. + /* We'll only start the txqs when the link is actually ready; make sure
  2354. + * we don't race against the link up notification, which may come
  2355. + * immediately after dpni_enable();
  2356. + */
  2357. + netif_tx_stop_all_queues(net_dev);
  2358. +
  2359. + /* Also, explicitly set carrier off, otherwise netif_carrier_ok() will
  2360. + * return true and cause 'ip link show' to report the LOWER_UP flag,
  2361. + * even though the link notification wasn't even received.
  2362. + */
  2363. + netif_carrier_off(net_dev);
  2364. +
  2365. + err = seed_pool(priv, priv->bpid);
  2366. + if (err) {
  2367. + /* Not much to do; the buffer pool, though not filled up,
  2368. + * may still contain some buffers which would enable us
  2369. + * to limp on.
  2370. + */
  2371. + netdev_err(net_dev, "Buffer seeding failed for DPBP %d (bpid=%d)\n",
  2372. + priv->dpbp_dev->obj_desc.id, priv->bpid);
  2373. + }
  2374. +
  2375. + if (priv->tx_pause_frames)
  2376. + priv->refill_thresh = priv->num_bufs - DPAA2_ETH_BUFS_PER_CMD;
  2377. + else
  2378. + priv->refill_thresh = DPAA2_ETH_REFILL_THRESH_TD;
  2379. +
  2380. + err = dpni_enable(priv->mc_io, 0, priv->mc_token);
  2381. + if (err < 0) {
  2382. + netdev_err(net_dev, "dpni_enable() failed\n");
  2383. + goto enable_err;
  2384. + }
  2385. +
  2386. + /* If the DPMAC object has already processed the link up interrupt,
  2387. + * we have to learn the link state ourselves.
  2388. + */
  2389. + err = link_state_update(priv);
  2390. + if (err < 0) {
  2391. + netdev_err(net_dev, "Can't update link state\n");
  2392. + goto link_state_err;
  2393. + }
  2394. +
  2395. + return 0;
  2396. +
  2397. +link_state_err:
  2398. +enable_err:
  2399. + priv->refill_thresh = 0;
  2400. + drain_pool(priv);
  2401. + return err;
  2402. +}
  2403. +
  2404. +static int dpaa2_eth_stop(struct net_device *net_dev)
  2405. +{
  2406. + struct dpaa2_eth_priv *priv = netdev_priv(net_dev);
  2407. + int dpni_enabled;
  2408. + int retries = 10, i;
  2409. +
  2410. + netif_tx_stop_all_queues(net_dev);
  2411. + netif_carrier_off(net_dev);
  2412. +
  2413. + /* Loop while dpni_disable() attempts to drain the egress FQs
  2414. + * and confirm them back to us.
  2415. + */
  2416. + do {
  2417. + dpni_disable(priv->mc_io, 0, priv->mc_token);
  2418. + dpni_is_enabled(priv->mc_io, 0, priv->mc_token, &dpni_enabled);
  2419. + if (dpni_enabled)
  2420. + /* Allow the MC some slack */
  2421. + msleep(100);
  2422. + } while (dpni_enabled && --retries);
  2423. + if (!retries) {
  2424. + netdev_warn(net_dev, "Retry count exceeded disabling DPNI\n");
  2425. + /* Must go on and disable NAPI nonetheless, so we don't crash at
  2426. + * the next "ifconfig up"
  2427. + */
  2428. + }
  2429. +
  2430. + priv->refill_thresh = 0;
  2431. +
  2432. + /* Wait for all running napi poll routines to finish, so that no
  2433. + * new refill operations are started.
  2434. + */
  2435. + for (i = 0; i < priv->num_channels; i++)
  2436. + napi_synchronize(&priv->channel[i]->napi);
  2437. +
  2438. + /* Empty the buffer pool */
  2439. + drain_pool(priv);
  2440. +
  2441. + return 0;
  2442. +}
  2443. +
  2444. +static int dpaa2_eth_init(struct net_device *net_dev)
  2445. +{
  2446. + u64 supported = 0;
  2447. + u64 not_supported = 0;
  2448. + struct dpaa2_eth_priv *priv = netdev_priv(net_dev);
  2449. + u32 options = priv->dpni_attrs.options;
  2450. +
  2451. + /* Capabilities listing */
  2452. + supported |= IFF_LIVE_ADDR_CHANGE;
  2453. +
  2454. + if (options & DPNI_OPT_NO_MAC_FILTER)
  2455. + not_supported |= IFF_UNICAST_FLT;
  2456. + else
  2457. + supported |= IFF_UNICAST_FLT;
  2458. +
  2459. + net_dev->priv_flags |= supported;
  2460. + net_dev->priv_flags &= ~not_supported;
  2461. +
  2462. + /* Features */
  2463. + net_dev->features = NETIF_F_RXCSUM |
  2464. + NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM |
  2465. + NETIF_F_SG | NETIF_F_HIGHDMA |
  2466. + NETIF_F_LLTX;
  2467. + net_dev->hw_features = net_dev->features;
  2468. +
  2469. + return 0;
  2470. +}
  2471. +
  2472. +static int dpaa2_eth_set_addr(struct net_device *net_dev, void *addr)
  2473. +{
  2474. + struct dpaa2_eth_priv *priv = netdev_priv(net_dev);
  2475. + struct device *dev = net_dev->dev.parent;
  2476. + int err;
  2477. +
  2478. + err = eth_mac_addr(net_dev, addr);
  2479. + if (err < 0) {
  2480. + dev_err(dev, "eth_mac_addr() failed (%d)\n", err);
  2481. + return err;
  2482. + }
  2483. +
  2484. + err = dpni_set_primary_mac_addr(priv->mc_io, 0, priv->mc_token,
  2485. + net_dev->dev_addr);
  2486. + if (err) {
  2487. + dev_err(dev, "dpni_set_primary_mac_addr() failed (%d)\n", err);
  2488. + return err;
  2489. + }
  2490. +
  2491. + return 0;
  2492. +}
  2493. +
  2494. +/** Fill in counters maintained by the GPP driver. These may be different from
  2495. + * the hardware counters obtained by ethtool.
  2496. + */
  2497. +static void dpaa2_eth_get_stats(struct net_device *net_dev,
  2498. + struct rtnl_link_stats64 *stats)
  2499. +{
  2500. + struct dpaa2_eth_priv *priv = netdev_priv(net_dev);
  2501. + struct rtnl_link_stats64 *percpu_stats;
  2502. + u64 *cpustats;
  2503. + u64 *netstats = (u64 *)stats;
  2504. + int i, j;
  2505. + int num = sizeof(struct rtnl_link_stats64) / sizeof(u64);
  2506. +
  2507. + for_each_possible_cpu(i) {
  2508. + percpu_stats = per_cpu_ptr(priv->percpu_stats, i);
  2509. + cpustats = (u64 *)percpu_stats;
  2510. + for (j = 0; j < num; j++)
  2511. + netstats[j] += cpustats[j];
  2512. + }
  2513. +}
  2514. +
  2515. +static int dpaa2_eth_change_mtu(struct net_device *net_dev, int mtu)
  2516. +{
  2517. + struct dpaa2_eth_priv *priv = netdev_priv(net_dev);
  2518. + int err;
  2519. +
  2520. + /* Set the maximum Rx frame length to match the transmit side;
  2521. + * account for L2 headers when computing the MFL
  2522. + */
  2523. + err = dpni_set_max_frame_length(priv->mc_io, 0, priv->mc_token,
  2524. + (u16)DPAA2_ETH_L2_MAX_FRM(mtu));
  2525. + if (err) {
  2526. + netdev_err(net_dev, "dpni_set_max_frame_length() failed\n");
  2527. + return err;
  2528. + }
  2529. +
  2530. + net_dev->mtu = mtu;
  2531. + return 0;
  2532. +}
  2533. +
  2534. +/* Copy mac unicast addresses from @net_dev to @priv.
  2535. + * Its sole purpose is to make dpaa2_eth_set_rx_mode() more readable.
  2536. + */
  2537. +static void add_uc_hw_addr(const struct net_device *net_dev,
  2538. + struct dpaa2_eth_priv *priv)
  2539. +{
  2540. + struct netdev_hw_addr *ha;
  2541. + int err;
  2542. +
  2543. + netdev_for_each_uc_addr(ha, net_dev) {
  2544. + err = dpni_add_mac_addr(priv->mc_io, 0, priv->mc_token,
  2545. + ha->addr);
  2546. + if (err)
  2547. + netdev_warn(priv->net_dev,
  2548. + "Could not add ucast MAC %pM to the filtering table (err %d)\n",
  2549. + ha->addr, err);
  2550. + }
  2551. +}
  2552. +
  2553. +/* Copy mac multicast addresses from @net_dev to @priv
  2554. + * Its sole purpose is to make dpaa2_eth_set_rx_mode() more readable.
  2555. + */
  2556. +static void add_mc_hw_addr(const struct net_device *net_dev,
  2557. + struct dpaa2_eth_priv *priv)
  2558. +{
  2559. + struct netdev_hw_addr *ha;
  2560. + int err;
  2561. +
  2562. + netdev_for_each_mc_addr(ha, net_dev) {
  2563. + err = dpni_add_mac_addr(priv->mc_io, 0, priv->mc_token,
  2564. + ha->addr);
  2565. + if (err)
  2566. + netdev_warn(priv->net_dev,
  2567. + "Could not add mcast MAC %pM to the filtering table (err %d)\n",
  2568. + ha->addr, err);
  2569. + }
  2570. +}
  2571. +
  2572. +static void dpaa2_eth_set_rx_mode(struct net_device *net_dev)
  2573. +{
  2574. + struct dpaa2_eth_priv *priv = netdev_priv(net_dev);
  2575. + int uc_count = netdev_uc_count(net_dev);
  2576. + int mc_count = netdev_mc_count(net_dev);
  2577. + u8 max_mac = priv->dpni_attrs.mac_filter_entries;
  2578. + u32 options = priv->dpni_attrs.options;
  2579. + u16 mc_token = priv->mc_token;
  2580. + struct fsl_mc_io *mc_io = priv->mc_io;
  2581. + int err;
  2582. +
  2583. + /* Basic sanity checks; these probably indicate a misconfiguration */
  2584. + if (options & DPNI_OPT_NO_MAC_FILTER && max_mac != 0)
  2585. + netdev_info(net_dev,
  2586. + "mac_filter_entries=%d, DPNI_OPT_NO_MAC_FILTER option must be disabled\n",
  2587. + max_mac);
  2588. +
  2589. + /* Force promiscuous if the uc or mc counts exceed our capabilities. */
  2590. + if (uc_count > max_mac) {
  2591. + netdev_info(net_dev,
  2592. + "Unicast addr count reached %d, max allowed is %d; forcing promisc\n",
  2593. + uc_count, max_mac);
  2594. + goto force_promisc;
  2595. + }
  2596. + if (mc_count + uc_count > max_mac) {
  2597. + netdev_info(net_dev,
  2598. + "Unicast + Multicast addr count reached %d, max allowed is %d; forcing promisc\n",
  2599. + uc_count + mc_count, max_mac);
  2600. + goto force_mc_promisc;
  2601. + }
  2602. +
  2603. + /* Adjust promisc settings due to flag combinations */
  2604. + if (net_dev->flags & IFF_PROMISC)
  2605. + goto force_promisc;
  2606. + if (net_dev->flags & IFF_ALLMULTI) {
  2607. + /* First, rebuild unicast filtering table. This should be done
  2608. + * in promisc mode, in order to avoid frame loss while we
  2609. + * progressively add entries to the table.
  2610. + * We don't know whether we had been in promisc already, and
  2611. + * making an MC call to find out is expensive; so set uc promisc
  2612. + * nonetheless.
  2613. + */
  2614. + err = dpni_set_unicast_promisc(mc_io, 0, mc_token, 1);
  2615. + if (err)
  2616. + netdev_warn(net_dev, "Can't set uc promisc\n");
  2617. +
  2618. + /* Actual uc table reconstruction. */
  2619. + err = dpni_clear_mac_filters(mc_io, 0, mc_token, 1, 0);
  2620. + if (err)
  2621. + netdev_warn(net_dev, "Can't clear uc filters\n");
  2622. + add_uc_hw_addr(net_dev, priv);
  2623. +
  2624. + /* Finally, clear uc promisc and set mc promisc as requested. */
  2625. + err = dpni_set_unicast_promisc(mc_io, 0, mc_token, 0);
  2626. + if (err)
  2627. + netdev_warn(net_dev, "Can't clear uc promisc\n");
  2628. + goto force_mc_promisc;
  2629. + }
  2630. +
  2631. + /* Neither unicast, nor multicast promisc will be on... eventually.
  2632. + * For now, rebuild mac filtering tables while forcing both of them on.
  2633. + */
  2634. + err = dpni_set_unicast_promisc(mc_io, 0, mc_token, 1);
  2635. + if (err)
  2636. + netdev_warn(net_dev, "Can't set uc promisc (%d)\n", err);
  2637. + err = dpni_set_multicast_promisc(mc_io, 0, mc_token, 1);
  2638. + if (err)
  2639. + netdev_warn(net_dev, "Can't set mc promisc (%d)\n", err);
  2640. +
  2641. + /* Actual mac filtering tables reconstruction */
  2642. + err = dpni_clear_mac_filters(mc_io, 0, mc_token, 1, 1);
  2643. + if (err)
  2644. + netdev_warn(net_dev, "Can't clear mac filters\n");
  2645. + add_mc_hw_addr(net_dev, priv);
  2646. + add_uc_hw_addr(net_dev, priv);
  2647. +
  2648. + /* Now we can clear both ucast and mcast promisc, without risking
  2649. + * to drop legitimate frames anymore.
  2650. + */
  2651. + err = dpni_set_unicast_promisc(mc_io, 0, mc_token, 0);
  2652. + if (err)
  2653. + netdev_warn(net_dev, "Can't clear ucast promisc\n");
  2654. + err = dpni_set_multicast_promisc(mc_io, 0, mc_token, 0);
  2655. + if (err)
  2656. + netdev_warn(net_dev, "Can't clear mcast promisc\n");
  2657. +
  2658. + return;
  2659. +
  2660. +force_promisc:
  2661. + err = dpni_set_unicast_promisc(mc_io, 0, mc_token, 1);
  2662. + if (err)
  2663. + netdev_warn(net_dev, "Can't set ucast promisc\n");
  2664. +force_mc_promisc:
  2665. + err = dpni_set_multicast_promisc(mc_io, 0, mc_token, 1);
  2666. + if (err)
  2667. + netdev_warn(net_dev, "Can't set mcast promisc\n");
  2668. +}
  2669. +
  2670. +static int dpaa2_eth_set_features(struct net_device *net_dev,
  2671. + netdev_features_t features)
  2672. +{
  2673. + struct dpaa2_eth_priv *priv = netdev_priv(net_dev);
  2674. + netdev_features_t changed = features ^ net_dev->features;
  2675. + bool enable;
  2676. + int err;
  2677. +
  2678. + if (changed & NETIF_F_RXCSUM) {
  2679. + enable = !!(features & NETIF_F_RXCSUM);
  2680. + err = set_rx_csum(priv, enable);
  2681. + if (err)
  2682. + return err;
  2683. + }
  2684. +
  2685. + if (changed & (NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM)) {
  2686. + enable = !!(features & (NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM));
  2687. + err = set_tx_csum(priv, enable);
  2688. + if (err)
  2689. + return err;
  2690. + }
  2691. +
  2692. + return 0;
  2693. +}
  2694. +
  2695. +static int dpaa2_eth_ts_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
  2696. +{
  2697. + struct dpaa2_eth_priv *priv = netdev_priv(dev);
  2698. + struct hwtstamp_config config;
  2699. +
  2700. + if (copy_from_user(&config, rq->ifr_data, sizeof(config)))
  2701. + return -EFAULT;
  2702. +
  2703. + switch (config.tx_type) {
  2704. + case HWTSTAMP_TX_OFF:
  2705. + priv->ts_tx_en = false;
  2706. + break;
  2707. + case HWTSTAMP_TX_ON:
  2708. + priv->ts_tx_en = true;
  2709. + break;
  2710. + default:
  2711. + return -ERANGE;
  2712. + }
  2713. +
  2714. + if (config.rx_filter == HWTSTAMP_FILTER_NONE) {
  2715. + priv->ts_rx_en = false;
  2716. + } else {
  2717. + priv->ts_rx_en = true;
  2718. + /* TS is set for all frame types, not only those requested */
  2719. + config.rx_filter = HWTSTAMP_FILTER_ALL;
  2720. + }
  2721. +
  2722. + return copy_to_user(rq->ifr_data, &config, sizeof(config)) ?
  2723. + -EFAULT : 0;
  2724. +}
  2725. +
  2726. +static int dpaa2_eth_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
  2727. +{
  2728. + if (cmd == SIOCSHWTSTAMP)
  2729. + return dpaa2_eth_ts_ioctl(dev, rq, cmd);
  2730. +
  2731. + return -EINVAL;
  2732. +}
  2733. +
  2734. +static const struct net_device_ops dpaa2_eth_ops = {
  2735. + .ndo_open = dpaa2_eth_open,
  2736. + .ndo_start_xmit = dpaa2_eth_tx,
  2737. + .ndo_stop = dpaa2_eth_stop,
  2738. + .ndo_init = dpaa2_eth_init,
  2739. + .ndo_set_mac_address = dpaa2_eth_set_addr,
  2740. + .ndo_get_stats64 = dpaa2_eth_get_stats,
  2741. + .ndo_change_mtu = dpaa2_eth_change_mtu,
  2742. + .ndo_set_rx_mode = dpaa2_eth_set_rx_mode,
  2743. + .ndo_set_features = dpaa2_eth_set_features,
  2744. + .ndo_do_ioctl = dpaa2_eth_ioctl,
  2745. +};
  2746. +
  2747. +static void cdan_cb(struct dpaa2_io_notification_ctx *ctx)
  2748. +{
  2749. + struct dpaa2_eth_channel *ch;
  2750. +
  2751. + ch = container_of(ctx, struct dpaa2_eth_channel, nctx);
  2752. +
  2753. + /* Update NAPI statistics */
  2754. + ch->stats.cdan++;
  2755. +
  2756. + napi_schedule_irqoff(&ch->napi);
  2757. +}
  2758. +
  2759. +/* Allocate and configure a DPCON object */
  2760. +static struct fsl_mc_device *setup_dpcon(struct dpaa2_eth_priv *priv)
  2761. +{
  2762. + struct fsl_mc_device *dpcon;
  2763. + struct device *dev = priv->net_dev->dev.parent;
  2764. + struct dpcon_attr attrs;
  2765. + int err;
  2766. +
  2767. + err = fsl_mc_object_allocate(to_fsl_mc_device(dev),
  2768. + FSL_MC_POOL_DPCON, &dpcon);
  2769. + if (err) {
  2770. + dev_info(dev, "Not enough DPCONs, will go on as-is\n");
  2771. + return NULL;
  2772. + }
  2773. +
  2774. + err = dpcon_open(priv->mc_io, 0, dpcon->obj_desc.id, &dpcon->mc_handle);
  2775. + if (err) {
  2776. + dev_err(dev, "dpcon_open() failed\n");
  2777. + goto err_open;
  2778. + }
  2779. +
  2780. + err = dpcon_reset(priv->mc_io, 0, dpcon->mc_handle);
  2781. + if (err) {
  2782. + dev_err(dev, "dpcon_reset() failed\n");
  2783. + goto err_reset;
  2784. + }
  2785. +
  2786. + err = dpcon_get_attributes(priv->mc_io, 0, dpcon->mc_handle, &attrs);
  2787. + if (err) {
  2788. + dev_err(dev, "dpcon_get_attributes() failed\n");
  2789. + goto err_get_attr;
  2790. + }
  2791. +
  2792. + err = dpcon_enable(priv->mc_io, 0, dpcon->mc_handle);
  2793. + if (err) {
  2794. + dev_err(dev, "dpcon_enable() failed\n");
  2795. + goto err_enable;
  2796. + }
  2797. +
  2798. + return dpcon;
  2799. +
  2800. +err_enable:
  2801. +err_get_attr:
  2802. +err_reset:
  2803. + dpcon_close(priv->mc_io, 0, dpcon->mc_handle);
  2804. +err_open:
  2805. + fsl_mc_object_free(dpcon);
  2806. +
  2807. + return NULL;
  2808. +}
  2809. +
  2810. +static void free_dpcon(struct dpaa2_eth_priv *priv,
  2811. + struct fsl_mc_device *dpcon)
  2812. +{
  2813. + dpcon_disable(priv->mc_io, 0, dpcon->mc_handle);
  2814. + dpcon_close(priv->mc_io, 0, dpcon->mc_handle);
  2815. + fsl_mc_object_free(dpcon);
  2816. +}
  2817. +
  2818. +static struct dpaa2_eth_channel *
  2819. +alloc_channel(struct dpaa2_eth_priv *priv)
  2820. +{
  2821. + struct dpaa2_eth_channel *channel;
  2822. + struct dpcon_attr attr;
  2823. + struct device *dev = priv->net_dev->dev.parent;
  2824. + int err;
  2825. +
  2826. + channel = kzalloc(sizeof(*channel), GFP_KERNEL);
  2827. + if (!channel)
  2828. + return NULL;
  2829. +
  2830. + channel->dpcon = setup_dpcon(priv);
  2831. + if (!channel->dpcon)
  2832. + goto err_setup;
  2833. +
  2834. + err = dpcon_get_attributes(priv->mc_io, 0, channel->dpcon->mc_handle,
  2835. + &attr);
  2836. + if (err) {
  2837. + dev_err(dev, "dpcon_get_attributes() failed\n");
  2838. + goto err_get_attr;
  2839. + }
  2840. +
  2841. + channel->dpcon_id = attr.id;
  2842. + channel->ch_id = attr.qbman_ch_id;
  2843. + channel->priv = priv;
  2844. +
  2845. + return channel;
  2846. +
  2847. +err_get_attr:
  2848. + free_dpcon(priv, channel->dpcon);
  2849. +err_setup:
  2850. + kfree(channel);
  2851. + return NULL;
  2852. +}
  2853. +
  2854. +static void free_channel(struct dpaa2_eth_priv *priv,
  2855. + struct dpaa2_eth_channel *channel)
  2856. +{
  2857. + free_dpcon(priv, channel->dpcon);
  2858. + kfree(channel);
  2859. +}
  2860. +
  2861. +/* DPIO setup: allocate and configure QBMan channels, setup core affinity
  2862. + * and register data availability notifications
  2863. + */
  2864. +static int setup_dpio(struct dpaa2_eth_priv *priv)
  2865. +{
  2866. + struct dpaa2_io_notification_ctx *nctx;
  2867. + struct dpaa2_eth_channel *channel;
  2868. + struct dpcon_notification_cfg dpcon_notif_cfg;
  2869. + struct device *dev = priv->net_dev->dev.parent;
  2870. + int i, err;
  2871. +
  2872. + /* We want the ability to spread ingress traffic (RX, TX conf) to as
  2873. + * many cores as possible, so we need one channel for each core
  2874. + * (unless there's fewer queues than cores, in which case the extra
  2875. + * channels would be wasted).
  2876. + * Allocate one channel per core and register it to the core's
  2877. + * affine DPIO. If not enough channels are available for all cores
  2878. + * or if some cores don't have an affine DPIO, there will be no
  2879. + * ingress frame processing on those cores.
  2880. + */
  2881. + cpumask_clear(&priv->dpio_cpumask);
  2882. + for_each_online_cpu(i) {
  2883. + /* Try to allocate a channel */
  2884. + channel = alloc_channel(priv);
  2885. + if (!channel) {
  2886. + dev_info(dev,
  2887. + "No affine channel for cpu %d and above\n", i);
  2888. + goto err_alloc_ch;
  2889. + }
  2890. +
  2891. + priv->channel[priv->num_channels] = channel;
  2892. +
  2893. + nctx = &channel->nctx;
  2894. + nctx->is_cdan = 1;
  2895. + nctx->cb = cdan_cb;
  2896. + nctx->id = channel->ch_id;
  2897. + nctx->desired_cpu = i;
  2898. +
  2899. + /* Register the new context */
  2900. + err = dpaa2_io_service_register(NULL, nctx);
  2901. + if (err) {
  2902. + dev_dbg(dev, "No affine DPIO for cpu %d\n", i);
  2903. + /* If no affine DPIO for this core, there's probably
  2904. + * none available for next cores either.
  2905. + */
  2906. + goto err_service_reg;
  2907. + }
  2908. +
  2909. + /* Register DPCON notification with MC */
  2910. + dpcon_notif_cfg.dpio_id = nctx->dpio_id;
  2911. + dpcon_notif_cfg.priority = 0;
  2912. + dpcon_notif_cfg.user_ctx = nctx->qman64;
  2913. + err = dpcon_set_notification(priv->mc_io, 0,
  2914. + channel->dpcon->mc_handle,
  2915. + &dpcon_notif_cfg);
  2916. + if (err) {
  2917. + dev_err(dev, "dpcon_set_notification failed()\n");
  2918. + goto err_set_cdan;
  2919. + }
  2920. +
  2921. + /* If we managed to allocate a channel and also found an affine
  2922. + * DPIO for this core, add it to the final mask
  2923. + */
  2924. + cpumask_set_cpu(i, &priv->dpio_cpumask);
  2925. + priv->num_channels++;
  2926. +
  2927. + /* Stop if we already have enough channels to accommodate all
  2928. + * RX and TX conf queues
  2929. + */
  2930. + if (priv->num_channels == dpaa2_eth_queue_count(priv))
  2931. + break;
  2932. + }
  2933. +
  2934. + /* Tx confirmation queues can only be serviced by cpus
  2935. + * with an affine DPIO/channel
  2936. + */
  2937. + cpumask_copy(&priv->txconf_cpumask, &priv->dpio_cpumask);
  2938. +
  2939. + return 0;
  2940. +
  2941. +err_set_cdan:
  2942. + dpaa2_io_service_deregister(NULL, nctx);
  2943. +err_service_reg:
  2944. + free_channel(priv, channel);
  2945. +err_alloc_ch:
  2946. + if (cpumask_empty(&priv->dpio_cpumask)) {
  2947. + dev_dbg(dev, "No cpu with an affine DPIO/DPCON\n");
  2948. + return -ENODEV;
  2949. + }
  2950. + cpumask_copy(&priv->txconf_cpumask, &priv->dpio_cpumask);
  2951. +
  2952. + dev_info(dev, "Cores %*pbl available for processing ingress traffic\n",
  2953. + cpumask_pr_args(&priv->dpio_cpumask));
  2954. +
  2955. + return 0;
  2956. +}
  2957. +
  2958. +static void free_dpio(struct dpaa2_eth_priv *priv)
  2959. +{
  2960. + int i;
  2961. + struct dpaa2_eth_channel *ch;
  2962. +
  2963. + /* deregister CDAN notifications and free channels */
  2964. + for (i = 0; i < priv->num_channels; i++) {
  2965. + ch = priv->channel[i];
  2966. + dpaa2_io_service_deregister(NULL, &ch->nctx);
  2967. + free_channel(priv, ch);
  2968. + }
  2969. +}
  2970. +
  2971. +static struct dpaa2_eth_channel *get_affine_channel(struct dpaa2_eth_priv *priv,
  2972. + int cpu)
  2973. +{
  2974. + struct device *dev = priv->net_dev->dev.parent;
  2975. + int i;
  2976. +
  2977. + for (i = 0; i < priv->num_channels; i++)
  2978. + if (priv->channel[i]->nctx.desired_cpu == cpu)
  2979. + return priv->channel[i];
  2980. +
  2981. + /* We should never get here. Issue a warning and return
  2982. + * the first channel, because it's still better than nothing
  2983. + */
  2984. + dev_warn(dev, "No affine channel found for cpu %d\n", cpu);
  2985. +
  2986. + return priv->channel[0];
  2987. +}
  2988. +
  2989. +static void set_fq_affinity(struct dpaa2_eth_priv *priv)
  2990. +{
  2991. + struct device *dev = priv->net_dev->dev.parent;
  2992. + struct cpumask xps_mask = CPU_MASK_NONE;
  2993. + struct dpaa2_eth_fq *fq;
  2994. + int rx_cpu, txc_cpu;
  2995. + int i, err;
  2996. +
  2997. + /* For each FQ, pick one channel/CPU to deliver frames to.
  2998. + * This may well change at runtime, either through irqbalance or
  2999. + * through direct user intervention.
  3000. + */
  3001. + rx_cpu = cpumask_first(&priv->dpio_cpumask);
  3002. + txc_cpu = cpumask_first(&priv->txconf_cpumask);
  3003. +
  3004. + for (i = 0; i < priv->num_fqs; i++) {
  3005. + fq = &priv->fq[i];
  3006. + switch (fq->type) {
  3007. + case DPAA2_RX_FQ:
  3008. + case DPAA2_RX_ERR_FQ:
  3009. + fq->target_cpu = rx_cpu;
  3010. + rx_cpu = cpumask_next(rx_cpu, &priv->dpio_cpumask);
  3011. + if (rx_cpu >= nr_cpu_ids)
  3012. + rx_cpu = cpumask_first(&priv->dpio_cpumask);
  3013. + break;
  3014. + case DPAA2_TX_CONF_FQ:
  3015. + fq->target_cpu = txc_cpu;
  3016. +
  3017. + /* register txc_cpu to XPS */
  3018. + cpumask_set_cpu(txc_cpu, &xps_mask);
  3019. + err = netif_set_xps_queue(priv->net_dev, &xps_mask,
  3020. + fq->flowid);
  3021. + if (err)
  3022. + dev_info_once(dev,
  3023. + "Tx: error setting XPS queue\n");
  3024. + cpumask_clear_cpu(txc_cpu, &xps_mask);
  3025. +
  3026. + txc_cpu = cpumask_next(txc_cpu, &priv->txconf_cpumask);
  3027. + if (txc_cpu >= nr_cpu_ids)
  3028. + txc_cpu = cpumask_first(&priv->txconf_cpumask);
  3029. + break;
  3030. + default:
  3031. + dev_err(dev, "Unknown FQ type: %d\n", fq->type);
  3032. + }
  3033. + fq->channel = get_affine_channel(priv, fq->target_cpu);
  3034. + }
  3035. +}
  3036. +
  3037. +static void setup_fqs(struct dpaa2_eth_priv *priv)
  3038. +{
  3039. + int i;
  3040. +
  3041. + /* We have one TxConf FQ per Tx flow. Tx queues MUST be at the
  3042. + * beginning of the queue array.
  3043. + * Number of Rx and Tx queues are the same.
  3044. + * We only support one traffic class for now.
  3045. + */
  3046. + for (i = 0; i < dpaa2_eth_queue_count(priv); i++) {
  3047. + priv->fq[priv->num_fqs].type = DPAA2_TX_CONF_FQ;
  3048. + priv->fq[priv->num_fqs].consume = dpaa2_eth_tx_conf;
  3049. + priv->fq[priv->num_fqs++].flowid = (u16)i;
  3050. + }
  3051. +
  3052. + for (i = 0; i < dpaa2_eth_queue_count(priv); i++) {
  3053. + priv->fq[priv->num_fqs].type = DPAA2_RX_FQ;
  3054. + priv->fq[priv->num_fqs].consume = dpaa2_eth_rx;
  3055. + priv->fq[priv->num_fqs++].flowid = (u16)i;
  3056. + }
  3057. +
  3058. +#ifdef CONFIG_FSL_DPAA2_ETH_USE_ERR_QUEUE
  3059. + /* We have exactly one Rx error queue per DPNI */
  3060. + priv->fq[priv->num_fqs].type = DPAA2_RX_ERR_FQ;
  3061. + priv->fq[priv->num_fqs++].consume = dpaa2_eth_rx_err;
  3062. +#endif
  3063. +
  3064. + /* For each FQ, decide on which core to process incoming frames */
  3065. + set_fq_affinity(priv);
  3066. +}
  3067. +
  3068. +/* Allocate and configure one buffer pool for each interface */
  3069. +static int setup_dpbp(struct dpaa2_eth_priv *priv)
  3070. +{
  3071. + int err;
  3072. + struct fsl_mc_device *dpbp_dev;
  3073. + struct dpbp_attr dpbp_attrs;
  3074. + struct device *dev = priv->net_dev->dev.parent;
  3075. +
  3076. + err = fsl_mc_object_allocate(to_fsl_mc_device(dev), FSL_MC_POOL_DPBP,
  3077. + &dpbp_dev);
  3078. + if (err) {
  3079. + dev_err(dev, "DPBP device allocation failed\n");
  3080. + return err;
  3081. + }
  3082. +
  3083. + priv->dpbp_dev = dpbp_dev;
  3084. +
  3085. + err = dpbp_open(priv->mc_io, 0, priv->dpbp_dev->obj_desc.id,
  3086. + &dpbp_dev->mc_handle);
  3087. + if (err) {
  3088. + dev_err(dev, "dpbp_open() failed\n");
  3089. + goto err_open;
  3090. + }
  3091. +
  3092. + err = dpbp_reset(priv->mc_io, 0, dpbp_dev->mc_handle);
  3093. + if (err) {
  3094. + dev_err(dev, "dpbp_reset() failed\n");
  3095. + goto err_reset;
  3096. + }
  3097. +
  3098. + err = dpbp_enable(priv->mc_io, 0, dpbp_dev->mc_handle);
  3099. + if (err) {
  3100. + dev_err(dev, "dpbp_enable() failed\n");
  3101. + goto err_enable;
  3102. + }
  3103. +
  3104. + err = dpbp_get_attributes(priv->mc_io, 0, dpbp_dev->mc_handle,
  3105. + &dpbp_attrs);
  3106. + if (err) {
  3107. + dev_err(dev, "dpbp_get_attributes() failed\n");
  3108. + goto err_get_attr;
  3109. + }
  3110. +
  3111. + priv->bpid = dpbp_attrs.bpid;
  3112. + priv->num_bufs = DPAA2_ETH_NUM_BUFS_FC / priv->num_channels;
  3113. +
  3114. + return 0;
  3115. +
  3116. +err_get_attr:
  3117. + dpbp_disable(priv->mc_io, 0, dpbp_dev->mc_handle);
  3118. +err_enable:
  3119. +err_reset:
  3120. + dpbp_close(priv->mc_io, 0, dpbp_dev->mc_handle);
  3121. +err_open:
  3122. + fsl_mc_object_free(dpbp_dev);
  3123. +
  3124. + return err;
  3125. +}
  3126. +
  3127. +static void free_dpbp(struct dpaa2_eth_priv *priv)
  3128. +{
  3129. + drain_pool(priv);
  3130. + dpbp_disable(priv->mc_io, 0, priv->dpbp_dev->mc_handle);
  3131. + dpbp_close(priv->mc_io, 0, priv->dpbp_dev->mc_handle);
  3132. + fsl_mc_object_free(priv->dpbp_dev);
  3133. +}
  3134. +
  3135. +static int setup_tx_congestion(struct dpaa2_eth_priv *priv)
  3136. +{
  3137. + struct dpni_congestion_notification_cfg cong_notif_cfg = { 0 };
  3138. + struct device *dev = priv->net_dev->dev.parent;
  3139. + int err;
  3140. +
  3141. + priv->cscn_unaligned = kzalloc(DPAA2_CSCN_SIZE + DPAA2_CSCN_ALIGN,
  3142. + GFP_KERNEL);
  3143. + if (!priv->cscn_unaligned)
  3144. + return -ENOMEM;
  3145. +
  3146. + priv->cscn_mem = PTR_ALIGN(priv->cscn_unaligned, DPAA2_CSCN_ALIGN);
  3147. + priv->cscn_dma = dma_map_single(dev, priv->cscn_mem, DPAA2_CSCN_SIZE,
  3148. + DMA_FROM_DEVICE);
  3149. + if (dma_mapping_error(dev, priv->cscn_dma)) {
  3150. + dev_err(dev, "Error mapping CSCN memory area\n");
  3151. + err = -ENOMEM;
  3152. + goto err_dma_map;
  3153. + }
  3154. +
  3155. + cong_notif_cfg.units = DPNI_CONGESTION_UNIT_BYTES;
  3156. + cong_notif_cfg.threshold_entry = DPAA2_ETH_TX_CONG_ENTRY_THRESH;
  3157. + cong_notif_cfg.threshold_exit = DPAA2_ETH_TX_CONG_EXIT_THRESH;
  3158. + cong_notif_cfg.message_ctx = (u64)priv;
  3159. + cong_notif_cfg.message_iova = priv->cscn_dma;
  3160. + cong_notif_cfg.notification_mode = DPNI_CONG_OPT_WRITE_MEM_ON_ENTER |
  3161. + DPNI_CONG_OPT_WRITE_MEM_ON_EXIT |
  3162. + DPNI_CONG_OPT_COHERENT_WRITE;
  3163. + err = dpni_set_congestion_notification(priv->mc_io, 0, priv->mc_token,
  3164. + DPNI_QUEUE_TX, 0,
  3165. + &cong_notif_cfg);
  3166. + if (err) {
  3167. + dev_err(dev, "dpni_set_congestion_notification failed\n");
  3168. + goto err_set_cong;
  3169. + }
  3170. +
  3171. + return 0;
  3172. +
  3173. +err_set_cong:
  3174. + dma_unmap_single(dev, priv->cscn_dma, DPAA2_CSCN_SIZE, DMA_FROM_DEVICE);
  3175. +err_dma_map:
  3176. + kfree(priv->cscn_unaligned);
  3177. +
  3178. + return err;
  3179. +}
  3180. +
  3181. +/* Configure the DPNI object this interface is associated with */
  3182. +static int setup_dpni(struct fsl_mc_device *ls_dev)
  3183. +{
  3184. + struct device *dev = &ls_dev->dev;
  3185. + struct dpaa2_eth_priv *priv;
  3186. + struct net_device *net_dev;
  3187. + struct dpni_buffer_layout buf_layout;
  3188. + struct dpni_link_cfg cfg = {0};
  3189. + int err;
  3190. +
  3191. + net_dev = dev_get_drvdata(dev);
  3192. + priv = netdev_priv(net_dev);
  3193. +
  3194. + priv->dpni_id = ls_dev->obj_desc.id;
  3195. +
  3196. + /* get a handle for the DPNI object */
  3197. + err = dpni_open(priv->mc_io, 0, priv->dpni_id, &priv->mc_token);
  3198. + if (err) {
  3199. + dev_err(dev, "dpni_open() failed\n");
  3200. + goto err_open;
  3201. + }
  3202. +
  3203. + ls_dev->mc_io = priv->mc_io;
  3204. + ls_dev->mc_handle = priv->mc_token;
  3205. +
  3206. + err = dpni_reset(priv->mc_io, 0, priv->mc_token);
  3207. + if (err) {
  3208. + dev_err(dev, "dpni_reset() failed\n");
  3209. + goto err_reset;
  3210. + }
  3211. +
  3212. + err = dpni_get_attributes(priv->mc_io, 0, priv->mc_token,
  3213. + &priv->dpni_attrs);
  3214. +
  3215. + if (err) {
  3216. + dev_err(dev, "dpni_get_attributes() failed (err=%d)\n", err);
  3217. + goto err_get_attr;
  3218. + }
  3219. +
  3220. + /* due to a limitation in WRIOP 1.0.0 (ERR009354), the Rx buf
  3221. + * align value must be a multiple of 256.
  3222. + */
  3223. + priv->rx_buf_align =
  3224. + priv->dpni_attrs.wriop_version & 0x3ff ?
  3225. + DPAA2_ETH_RX_BUF_ALIGN : DPAA2_ETH_RX_BUF_ALIGN_V1;
  3226. +
  3227. + /* Update number of logical FQs in netdev */
  3228. + err = netif_set_real_num_tx_queues(net_dev,
  3229. + dpaa2_eth_queue_count(priv));
  3230. + if (err) {
  3231. + dev_err(dev, "netif_set_real_num_tx_queues failed (%d)\n", err);
  3232. + goto err_set_tx_queues;
  3233. + }
  3234. +
  3235. + err = netif_set_real_num_rx_queues(net_dev,
  3236. + dpaa2_eth_queue_count(priv));
  3237. + if (err) {
  3238. + dev_err(dev, "netif_set_real_num_rx_queues failed (%d)\n", err);
  3239. + goto err_set_rx_queues;
  3240. + }
  3241. +
  3242. + /* Configure buffer layouts */
  3243. + /* rx buffer */
  3244. + buf_layout.pass_parser_result = true;
  3245. + buf_layout.pass_frame_status = true;
  3246. + buf_layout.private_data_size = DPAA2_ETH_SWA_SIZE;
  3247. + buf_layout.data_align = priv->rx_buf_align;
  3248. + buf_layout.data_head_room = DPAA2_ETH_RX_HEAD_ROOM;
  3249. + buf_layout.options = DPNI_BUF_LAYOUT_OPT_PARSER_RESULT |
  3250. + DPNI_BUF_LAYOUT_OPT_FRAME_STATUS |
  3251. + DPNI_BUF_LAYOUT_OPT_PRIVATE_DATA_SIZE |
  3252. + DPNI_BUF_LAYOUT_OPT_DATA_ALIGN |
  3253. + DPNI_BUF_LAYOUT_OPT_DATA_HEAD_ROOM;
  3254. + err = dpni_set_buffer_layout(priv->mc_io, 0, priv->mc_token,
  3255. + DPNI_QUEUE_RX, &buf_layout);
  3256. + if (err) {
  3257. + dev_err(dev,
  3258. + "dpni_set_buffer_layout(RX) failed\n");
  3259. + goto err_buf_layout;
  3260. + }
  3261. +
  3262. + /* tx buffer */
  3263. + buf_layout.options = DPNI_BUF_LAYOUT_OPT_FRAME_STATUS |
  3264. + DPNI_BUF_LAYOUT_OPT_TIMESTAMP |
  3265. + DPNI_BUF_LAYOUT_OPT_PRIVATE_DATA_SIZE;
  3266. + buf_layout.pass_timestamp = true;
  3267. + err = dpni_set_buffer_layout(priv->mc_io, 0, priv->mc_token,
  3268. + DPNI_QUEUE_TX, &buf_layout);
  3269. + if (err) {
  3270. + dev_err(dev,
  3271. + "dpni_set_buffer_layout(TX) failed\n");
  3272. + goto err_buf_layout;
  3273. + }
  3274. +
  3275. + /* tx-confirm buffer */
  3276. + buf_layout.options = DPNI_BUF_LAYOUT_OPT_FRAME_STATUS |
  3277. + DPNI_BUF_LAYOUT_OPT_TIMESTAMP;
  3278. + err = dpni_set_buffer_layout(priv->mc_io, 0, priv->mc_token,
  3279. + DPNI_QUEUE_TX_CONFIRM, &buf_layout);
  3280. + if (err) {
  3281. + dev_err(dev, "dpni_set_buffer_layout(TX_CONF) failed\n");
  3282. + goto err_buf_layout;
  3283. + }
  3284. +
  3285. + /* Now that we've set our tx buffer layout, retrieve the minimum
  3286. + * required tx data offset.
  3287. + */
  3288. + err = dpni_get_tx_data_offset(priv->mc_io, 0, priv->mc_token,
  3289. + &priv->tx_data_offset);
  3290. + if (err) {
  3291. + dev_err(dev, "dpni_get_tx_data_offset() failed (%d)\n", err);
  3292. + goto err_data_offset;
  3293. + }
  3294. +
  3295. + if ((priv->tx_data_offset % 64) != 0)
  3296. + dev_warn(dev, "Tx data offset (%d) not a multiple of 64B",
  3297. + priv->tx_data_offset);
  3298. +
  3299. + /* Accommodate software annotation space (SWA) */
  3300. + priv->tx_data_offset += DPAA2_ETH_SWA_SIZE;
  3301. +
  3302. + /* Enable congestion notifications for Tx queues */
  3303. + err = setup_tx_congestion(priv);
  3304. + if (err)
  3305. + goto err_tx_cong;
  3306. +
  3307. + /* allocate classification rule space */
  3308. + priv->cls_rule = kzalloc(sizeof(*priv->cls_rule) *
  3309. + dpaa2_eth_fs_count(priv), GFP_KERNEL);
  3310. + if (!priv->cls_rule)
  3311. + goto err_cls_rule;
  3312. +
  3313. + /* Enable flow control */
  3314. + cfg.options = DPNI_LINK_OPT_AUTONEG | DPNI_LINK_OPT_PAUSE;
  3315. + priv->tx_pause_frames = 1;
  3316. +
  3317. + err = dpni_set_link_cfg(priv->mc_io, 0, priv->mc_token, &cfg);
  3318. + if (err) {
  3319. + netdev_err(net_dev, "ERROR %d setting link cfg", err);
  3320. + goto err_set_link_cfg;
  3321. + }
  3322. +
  3323. + return 0;
  3324. +
  3325. +err_set_link_cfg:
  3326. +err_cls_rule:
  3327. +err_tx_cong:
  3328. +err_data_offset:
  3329. +err_buf_layout:
  3330. +err_set_rx_queues:
  3331. +err_set_tx_queues:
  3332. +err_get_attr:
  3333. +err_reset:
  3334. + dpni_close(priv->mc_io, 0, priv->mc_token);
  3335. +err_open:
  3336. + return err;
  3337. +}
  3338. +
  3339. +static void free_dpni(struct dpaa2_eth_priv *priv)
  3340. +{
  3341. + struct device *dev = priv->net_dev->dev.parent;
  3342. + int err;
  3343. +
  3344. + err = dpni_reset(priv->mc_io, 0, priv->mc_token);
  3345. + if (err)
  3346. + netdev_warn(priv->net_dev, "dpni_reset() failed (err %d)\n",
  3347. + err);
  3348. +
  3349. + dpni_close(priv->mc_io, 0, priv->mc_token);
  3350. +
  3351. + kfree(priv->cls_rule);
  3352. +
  3353. + dma_unmap_single(dev, priv->cscn_dma, DPAA2_CSCN_SIZE, DMA_FROM_DEVICE);
  3354. + kfree(priv->cscn_unaligned);
  3355. +}
  3356. +
  3357. +int setup_fqs_taildrop(struct dpaa2_eth_priv *priv,
  3358. + bool enable)
  3359. +{
  3360. + struct device *dev = priv->net_dev->dev.parent;
  3361. + struct dpni_taildrop td;
  3362. + int err = 0, i;
  3363. +
  3364. + td.enable = enable;
  3365. + td.threshold = DPAA2_ETH_TAILDROP_THRESH;
  3366. +
  3367. + if (enable) {
  3368. + priv->num_bufs = DPAA2_ETH_NUM_BUFS_TD;
  3369. + priv->refill_thresh = DPAA2_ETH_REFILL_THRESH_TD;
  3370. + } else {
  3371. + priv->num_bufs = DPAA2_ETH_NUM_BUFS_FC /
  3372. + priv->num_channels;
  3373. + priv->refill_thresh = priv->num_bufs - DPAA2_ETH_BUFS_PER_CMD;
  3374. + }
  3375. +
  3376. + for (i = 0; i < priv->num_fqs; i++) {
  3377. + if (priv->fq[i].type != DPAA2_RX_FQ)
  3378. + continue;
  3379. +
  3380. + err = dpni_set_taildrop(priv->mc_io, 0, priv->mc_token,
  3381. + DPNI_CP_QUEUE, DPNI_QUEUE_RX, 0,
  3382. + priv->fq[i].flowid, &td);
  3383. + if (err) {
  3384. + dev_err(dev, "dpni_set_taildrop() failed (%d)\n", err);
  3385. + break;
  3386. + }
  3387. + }
  3388. +
  3389. + return err;
  3390. +}
  3391. +
  3392. +static int setup_rx_flow(struct dpaa2_eth_priv *priv,
  3393. + struct dpaa2_eth_fq *fq)
  3394. +{
  3395. + struct device *dev = priv->net_dev->dev.parent;
  3396. + struct dpni_queue q = { { 0 } };
  3397. + struct dpni_queue_id qid;
  3398. + u8 q_opt = DPNI_QUEUE_OPT_USER_CTX | DPNI_QUEUE_OPT_DEST;
  3399. + int err;
  3400. +
  3401. + err = dpni_get_queue(priv->mc_io, 0, priv->mc_token,
  3402. + DPNI_QUEUE_RX, 0, fq->flowid, &q, &qid);
  3403. + if (err) {
  3404. + dev_err(dev, "dpni_get_queue() failed (%d)\n", err);
  3405. + return err;
  3406. + }
  3407. +
  3408. + fq->fqid = qid.fqid;
  3409. +
  3410. + q.destination.id = fq->channel->dpcon_id;
  3411. + q.destination.type = DPNI_DEST_DPCON;
  3412. + q.destination.priority = 1;
  3413. + q.user_context = (u64)fq;
  3414. + err = dpni_set_queue(priv->mc_io, 0, priv->mc_token,
  3415. + DPNI_QUEUE_RX, 0, fq->flowid, q_opt, &q);
  3416. + if (err) {
  3417. + dev_err(dev, "dpni_set_queue() failed (%d)\n", err);
  3418. + return err;
  3419. + }
  3420. +
  3421. + return 0;
  3422. +}
  3423. +
  3424. +static int setup_tx_flow(struct dpaa2_eth_priv *priv,
  3425. + struct dpaa2_eth_fq *fq)
  3426. +{
  3427. + struct device *dev = priv->net_dev->dev.parent;
  3428. + struct dpni_queue q = { { 0 } };
  3429. + struct dpni_queue_id qid;
  3430. + u8 q_opt = DPNI_QUEUE_OPT_USER_CTX | DPNI_QUEUE_OPT_DEST;
  3431. + int err;
  3432. +
  3433. + err = dpni_get_queue(priv->mc_io, 0, priv->mc_token,
  3434. + DPNI_QUEUE_TX, 0, fq->flowid, &q, &qid);
  3435. + if (err) {
  3436. + dev_err(dev, "dpni_get_queue() failed (%d)\n", err);
  3437. + return err;
  3438. + }
  3439. +
  3440. + fq->tx_qdbin = qid.qdbin;
  3441. +
  3442. + err = dpni_get_queue(priv->mc_io, 0, priv->mc_token,
  3443. + DPNI_QUEUE_TX_CONFIRM, 0, fq->flowid, &q, &qid);
  3444. + if (err) {
  3445. + dev_err(dev, "dpni_get_queue() failed (%d)\n", err);
  3446. + return err;
  3447. + }
  3448. +
  3449. + fq->fqid = qid.fqid;
  3450. +
  3451. + q.destination.id = fq->channel->dpcon_id;
  3452. + q.destination.type = DPNI_DEST_DPCON;
  3453. + q.destination.priority = 0;
  3454. + q.user_context = (u64)fq;
  3455. + err = dpni_set_queue(priv->mc_io, 0, priv->mc_token,
  3456. + DPNI_QUEUE_TX_CONFIRM, 0, fq->flowid, q_opt, &q);
  3457. + if (err) {
  3458. + dev_err(dev, "dpni_get_queue() failed (%d)\n", err);
  3459. + return err;
  3460. + }
  3461. +
  3462. + return 0;
  3463. +}
  3464. +
  3465. +#ifdef CONFIG_FSL_DPAA2_ETH_USE_ERR_QUEUE
  3466. +static int setup_rx_err_flow(struct dpaa2_eth_priv *priv,
  3467. + struct dpaa2_eth_fq *fq)
  3468. +{
  3469. + struct device *dev = priv->net_dev->dev.parent;
  3470. + struct dpni_queue q = { { 0 } };
  3471. + struct dpni_queue_id qid;
  3472. + u8 q_opt = DPNI_QUEUE_OPT_USER_CTX | DPNI_QUEUE_OPT_DEST;
  3473. + int err;
  3474. +
  3475. + err = dpni_get_queue(priv->mc_io, 0, priv->mc_token,
  3476. + DPNI_QUEUE_RX_ERR, 0, 0, &q, &qid);
  3477. + if (err) {
  3478. + dev_err(dev, "dpni_get_queue() failed (%d)\n", err);
  3479. + return err;
  3480. + }
  3481. +
  3482. + fq->fqid = qid.fqid;
  3483. +
  3484. + q.destination.id = fq->channel->dpcon_id;
  3485. + q.destination.type = DPNI_DEST_DPCON;
  3486. + q.destination.priority = 1;
  3487. + q.user_context = (u64)fq;
  3488. + err = dpni_set_queue(priv->mc_io, 0, priv->mc_token,
  3489. + DPNI_QUEUE_RX_ERR, 0, 0, q_opt, &q);
  3490. + if (err) {
  3491. + dev_err(dev, "dpni_set_queue() failed (%d)\n", err);
  3492. + return err;
  3493. + }
  3494. +
  3495. + return 0;
  3496. +}
  3497. +#endif
  3498. +
  3499. +/* default hash key fields */
  3500. +static struct dpaa2_eth_hash_fields default_hash_fields[] = {
  3501. + {
  3502. + /* L2 header */
  3503. + .rxnfc_field = RXH_L2DA,
  3504. + .cls_prot = NET_PROT_ETH,
  3505. + .cls_field = NH_FLD_ETH_DA,
  3506. + .size = 6,
  3507. + }, {
  3508. + .cls_prot = NET_PROT_ETH,
  3509. + .cls_field = NH_FLD_ETH_SA,
  3510. + .size = 6,
  3511. + }, {
  3512. + /* This is the last ethertype field parsed:
  3513. + * depending on frame format, it can be the MAC ethertype
  3514. + * or the VLAN etype.
  3515. + */
  3516. + .cls_prot = NET_PROT_ETH,
  3517. + .cls_field = NH_FLD_ETH_TYPE,
  3518. + .size = 2,
  3519. + }, {
  3520. + /* VLAN header */
  3521. + .rxnfc_field = RXH_VLAN,
  3522. + .cls_prot = NET_PROT_VLAN,
  3523. + .cls_field = NH_FLD_VLAN_TCI,
  3524. + .size = 2,
  3525. + }, {
  3526. + /* IP header */
  3527. + .rxnfc_field = RXH_IP_SRC,
  3528. + .cls_prot = NET_PROT_IP,
  3529. + .cls_field = NH_FLD_IP_SRC,
  3530. + .size = 4,
  3531. + }, {
  3532. + .rxnfc_field = RXH_IP_DST,
  3533. + .cls_prot = NET_PROT_IP,
  3534. + .cls_field = NH_FLD_IP_DST,
  3535. + .size = 4,
  3536. + }, {
  3537. + .rxnfc_field = RXH_L3_PROTO,
  3538. + .cls_prot = NET_PROT_IP,
  3539. + .cls_field = NH_FLD_IP_PROTO,
  3540. + .size = 1,
  3541. + }, {
  3542. + /* Using UDP ports, this is functionally equivalent to raw
  3543. + * byte pairs from L4 header.
  3544. + */
  3545. + .rxnfc_field = RXH_L4_B_0_1,
  3546. + .cls_prot = NET_PROT_UDP,
  3547. + .cls_field = NH_FLD_UDP_PORT_SRC,
  3548. + .size = 2,
  3549. + }, {
  3550. + .rxnfc_field = RXH_L4_B_2_3,
  3551. + .cls_prot = NET_PROT_UDP,
  3552. + .cls_field = NH_FLD_UDP_PORT_DST,
  3553. + .size = 2,
  3554. + },
  3555. +};
  3556. +
  3557. +/* Set RX hash options */
  3558. +static int set_hash(struct dpaa2_eth_priv *priv)
  3559. +{
  3560. + struct device *dev = priv->net_dev->dev.parent;
  3561. + struct dpkg_profile_cfg cls_cfg;
  3562. + struct dpni_rx_tc_dist_cfg dist_cfg;
  3563. + u8 *dma_mem;
  3564. + int i;
  3565. + int err = 0;
  3566. +
  3567. + memset(&cls_cfg, 0, sizeof(cls_cfg));
  3568. +
  3569. + for (i = 0; i < priv->num_hash_fields; i++) {
  3570. + struct dpkg_extract *key =
  3571. + &cls_cfg.extracts[cls_cfg.num_extracts];
  3572. +
  3573. + key->type = DPKG_EXTRACT_FROM_HDR;
  3574. + key->extract.from_hdr.prot = priv->hash_fields[i].cls_prot;
  3575. + key->extract.from_hdr.type = DPKG_FULL_FIELD;
  3576. + key->extract.from_hdr.field = priv->hash_fields[i].cls_field;
  3577. + cls_cfg.num_extracts++;
  3578. +
  3579. + priv->rx_flow_hash |= priv->hash_fields[i].rxnfc_field;
  3580. + }
  3581. +
  3582. + dma_mem = kzalloc(DPAA2_CLASSIFIER_DMA_SIZE, GFP_DMA | GFP_KERNEL);
  3583. + if (!dma_mem)
  3584. + return -ENOMEM;
  3585. +
  3586. + err = dpni_prepare_key_cfg(&cls_cfg, dma_mem);
  3587. + if (err) {
  3588. + dev_err(dev, "dpni_prepare_key_cfg() failed (%d)", err);
  3589. + goto err_prep_key;
  3590. + }
  3591. +
  3592. + memset(&dist_cfg, 0, sizeof(dist_cfg));
  3593. +
  3594. + /* Prepare for setting the rx dist */
  3595. + dist_cfg.key_cfg_iova = dma_map_single(dev, dma_mem,
  3596. + DPAA2_CLASSIFIER_DMA_SIZE,
  3597. + DMA_TO_DEVICE);
  3598. + if (dma_mapping_error(dev, dist_cfg.key_cfg_iova)) {
  3599. + dev_err(dev, "DMA mapping failed\n");
  3600. + err = -ENOMEM;
  3601. + goto err_dma_map;
  3602. + }
  3603. +
  3604. + dist_cfg.dist_size = dpaa2_eth_queue_count(priv);
  3605. + if (dpaa2_eth_fs_enabled(priv)) {
  3606. + dist_cfg.dist_mode = DPNI_DIST_MODE_FS;
  3607. + dist_cfg.fs_cfg.miss_action = DPNI_FS_MISS_HASH;
  3608. + } else {
  3609. + dist_cfg.dist_mode = DPNI_DIST_MODE_HASH;
  3610. + }
  3611. +
  3612. + err = dpni_set_rx_tc_dist(priv->mc_io, 0, priv->mc_token, 0, &dist_cfg);
  3613. + dma_unmap_single(dev, dist_cfg.key_cfg_iova,
  3614. + DPAA2_CLASSIFIER_DMA_SIZE, DMA_TO_DEVICE);
  3615. + if (err)
  3616. + dev_err(dev, "dpni_set_rx_tc_dist() failed (%d)\n", err);
  3617. +
  3618. +err_dma_map:
  3619. +err_prep_key:
  3620. + kfree(dma_mem);
  3621. + return err;
  3622. +}
  3623. +
  3624. +/* Bind the DPNI to its needed objects and resources: buffer pool, DPIOs,
  3625. + * frame queues and channels
  3626. + */
  3627. +static int bind_dpni(struct dpaa2_eth_priv *priv)
  3628. +{
  3629. + struct net_device *net_dev = priv->net_dev;
  3630. + struct device *dev = net_dev->dev.parent;
  3631. + struct dpni_pools_cfg pools_params;
  3632. + struct dpni_error_cfg err_cfg;
  3633. + int err = 0;
  3634. + int i;
  3635. +
  3636. + pools_params.num_dpbp = 1;
  3637. + pools_params.pools[0].dpbp_id = priv->dpbp_dev->obj_desc.id;
  3638. + pools_params.pools[0].backup_pool = 0;
  3639. + pools_params.pools[0].buffer_size = DPAA2_ETH_RX_BUF_SIZE;
  3640. + err = dpni_set_pools(priv->mc_io, 0, priv->mc_token, &pools_params);
  3641. + if (err) {
  3642. + dev_err(dev, "dpni_set_pools() failed\n");
  3643. + return err;
  3644. + }
  3645. +
  3646. + /* Verify classification options and disable hashing and/or
  3647. + * flow steering support in case of invalid configuration values
  3648. + */
  3649. + priv->hash_fields = default_hash_fields;
  3650. + priv->num_hash_fields = ARRAY_SIZE(default_hash_fields);
  3651. + check_cls_support(priv);
  3652. +
  3653. + /* have the interface implicitly distribute traffic based on
  3654. + * a static hash key
  3655. + */
  3656. + if (dpaa2_eth_hash_enabled(priv)) {
  3657. + err = set_hash(priv);
  3658. + if (err) {
  3659. + dev_err(dev, "Hashing configuration failed\n");
  3660. + return err;
  3661. + }
  3662. + }
  3663. +
  3664. + /* Configure handling of error frames */
  3665. + err_cfg.errors = DPAA2_FAS_RX_ERR_MASK;
  3666. + err_cfg.set_frame_annotation = 1;
  3667. +#ifdef CONFIG_FSL_DPAA2_ETH_USE_ERR_QUEUE
  3668. + err_cfg.error_action = DPNI_ERROR_ACTION_SEND_TO_ERROR_QUEUE;
  3669. +#else
  3670. + err_cfg.error_action = DPNI_ERROR_ACTION_DISCARD;
  3671. +#endif
  3672. + err = dpni_set_errors_behavior(priv->mc_io, 0, priv->mc_token,
  3673. + &err_cfg);
  3674. + if (err) {
  3675. + dev_err(dev, "dpni_set_errors_behavior() failed (%d)\n", err);
  3676. + return err;
  3677. + }
  3678. +
  3679. + /* Configure Rx and Tx conf queues to generate CDANs */
  3680. + for (i = 0; i < priv->num_fqs; i++) {
  3681. + switch (priv->fq[i].type) {
  3682. + case DPAA2_RX_FQ:
  3683. + err = setup_rx_flow(priv, &priv->fq[i]);
  3684. + break;
  3685. + case DPAA2_TX_CONF_FQ:
  3686. + err = setup_tx_flow(priv, &priv->fq[i]);
  3687. + break;
  3688. +#ifdef CONFIG_FSL_DPAA2_ETH_USE_ERR_QUEUE
  3689. + case DPAA2_RX_ERR_FQ:
  3690. + err = setup_rx_err_flow(priv, &priv->fq[i]);
  3691. + break;
  3692. +#endif
  3693. + default:
  3694. + dev_err(dev, "Invalid FQ type %d\n", priv->fq[i].type);
  3695. + return -EINVAL;
  3696. + }
  3697. + if (err)
  3698. + return err;
  3699. + }
  3700. +
  3701. + err = dpni_get_qdid(priv->mc_io, 0, priv->mc_token, DPNI_QUEUE_TX,
  3702. + &priv->tx_qdid);
  3703. + if (err) {
  3704. + dev_err(dev, "dpni_get_qdid() failed\n");
  3705. + return err;
  3706. + }
  3707. +
  3708. + return 0;
  3709. +}
  3710. +
  3711. +/* Allocate rings for storing incoming frame descriptors */
  3712. +static int alloc_rings(struct dpaa2_eth_priv *priv)
  3713. +{
  3714. + struct net_device *net_dev = priv->net_dev;
  3715. + struct device *dev = net_dev->dev.parent;
  3716. + int i;
  3717. +
  3718. + for (i = 0; i < priv->num_channels; i++) {
  3719. + priv->channel[i]->store =
  3720. + dpaa2_io_store_create(DPAA2_ETH_STORE_SIZE, dev);
  3721. + if (!priv->channel[i]->store) {
  3722. + netdev_err(net_dev, "dpaa2_io_store_create() failed\n");
  3723. + goto err_ring;
  3724. + }
  3725. + }
  3726. +
  3727. + return 0;
  3728. +
  3729. +err_ring:
  3730. + for (i = 0; i < priv->num_channels; i++) {
  3731. + if (!priv->channel[i]->store)
  3732. + break;
  3733. + dpaa2_io_store_destroy(priv->channel[i]->store);
  3734. + }
  3735. +
  3736. + return -ENOMEM;
  3737. +}
  3738. +
  3739. +static void free_rings(struct dpaa2_eth_priv *priv)
  3740. +{
  3741. + int i;
  3742. +
  3743. + for (i = 0; i < priv->num_channels; i++)
  3744. + dpaa2_io_store_destroy(priv->channel[i]->store);
  3745. +}
  3746. +
  3747. +static int netdev_init(struct net_device *net_dev)
  3748. +{
  3749. + int err;
  3750. + struct device *dev = net_dev->dev.parent;
  3751. + struct dpaa2_eth_priv *priv = netdev_priv(net_dev);
  3752. + u8 mac_addr[ETH_ALEN], dpni_mac_addr[ETH_ALEN];
  3753. + u8 bcast_addr[ETH_ALEN];
  3754. + u16 rx_headroom, rx_req_headroom;
  3755. +
  3756. + net_dev->netdev_ops = &dpaa2_eth_ops;
  3757. +
  3758. + /* Get firmware address, if any */
  3759. + err = dpni_get_port_mac_addr(priv->mc_io, 0, priv->mc_token, mac_addr);
  3760. + if (err) {
  3761. + dev_err(dev, "dpni_get_port_mac_addr() failed (%d)\n", err);
  3762. + return err;
  3763. + }
  3764. +
  3765. + /* Get DPNI atttributes address, if any */
  3766. + err = dpni_get_primary_mac_addr(priv->mc_io, 0, priv->mc_token,
  3767. + dpni_mac_addr);
  3768. + if (err) {
  3769. + dev_err(dev, "dpni_get_primary_mac_addr() failed (%d)\n", err);
  3770. + return err;
  3771. + }
  3772. +
  3773. + /* First check if firmware has any address configured by bootloader */
  3774. + if (!is_zero_ether_addr(mac_addr)) {
  3775. + /* If the DPMAC addr != the DPNI addr, update it */
  3776. + if (!ether_addr_equal(mac_addr, dpni_mac_addr)) {
  3777. + err = dpni_set_primary_mac_addr(priv->mc_io, 0,
  3778. + priv->mc_token,
  3779. + mac_addr);
  3780. + if (err) {
  3781. + dev_err(dev,
  3782. + "dpni_set_primary_mac_addr() failed (%d)\n",
  3783. + err);
  3784. + return err;
  3785. + }
  3786. + }
  3787. + memcpy(net_dev->dev_addr, mac_addr, net_dev->addr_len);
  3788. + } else if (is_zero_ether_addr(dpni_mac_addr)) {
  3789. + /* Fills in net_dev->dev_addr, as required by
  3790. + * register_netdevice()
  3791. + */
  3792. + eth_hw_addr_random(net_dev);
  3793. + /* Make the user aware, without cluttering the boot log */
  3794. + dev_dbg_once(dev, " device(s) have all-zero hwaddr, replaced with random\n");
  3795. + err = dpni_set_primary_mac_addr(priv->mc_io, 0,
  3796. + priv->mc_token, net_dev->dev_addr);
  3797. + if (err) {
  3798. + dev_err(dev,
  3799. + "dpni_set_primary_mac_addr() failed (%d)\n", err);
  3800. + return err;
  3801. + }
  3802. + /* Override NET_ADDR_RANDOM set by eth_hw_addr_random(); for all
  3803. + * practical purposes, this will be our "permanent" mac address,
  3804. + * at least until the next reboot. This move will also permit
  3805. + * register_netdevice() to properly fill up net_dev->perm_addr.
  3806. + */
  3807. + net_dev->addr_assign_type = NET_ADDR_PERM;
  3808. + /* If DPMAC address is non-zero, use that one */
  3809. + } else {
  3810. + /* NET_ADDR_PERM is default, all we have to do is
  3811. + * fill in the device addr.
  3812. + */
  3813. + memcpy(net_dev->dev_addr, dpni_mac_addr, net_dev->addr_len);
  3814. + }
  3815. +
  3816. + /* Explicitly add the broadcast address to the MAC filtering table;
  3817. + * the MC won't do that for us.
  3818. + */
  3819. + eth_broadcast_addr(bcast_addr);
  3820. + err = dpni_add_mac_addr(priv->mc_io, 0, priv->mc_token, bcast_addr);
  3821. + if (err) {
  3822. + dev_warn(dev, "dpni_add_mac_addr() failed (%d)\n", err);
  3823. + /* Won't return an error; at least, we'd have egress traffic */
  3824. + }
  3825. +
  3826. + /* Reserve enough space to align buffer as per hardware requirement;
  3827. + * NOTE: priv->tx_data_offset MUST be initialized at this point.
  3828. + */
  3829. + net_dev->needed_headroom = DPAA2_ETH_NEEDED_HEADROOM(priv);
  3830. +
  3831. + /* Set MTU limits */
  3832. + net_dev->min_mtu = 68;
  3833. + net_dev->max_mtu = DPAA2_ETH_MAX_MTU;
  3834. +
  3835. + /* Required headroom for Rx skbs, to avoid reallocation on
  3836. + * forwarding path.
  3837. + */
  3838. + rx_req_headroom = LL_RESERVED_SPACE(net_dev) - ETH_HLEN;
  3839. + rx_headroom = ALIGN(DPAA2_ETH_RX_HWA_SIZE + DPAA2_ETH_SWA_SIZE +
  3840. + DPAA2_ETH_RX_HEAD_ROOM, priv->rx_buf_align);
  3841. + if (rx_req_headroom > rx_headroom)
  3842. + dev_info_once(dev,
  3843. + "Required headroom (%d) greater than available (%d).\n"
  3844. + "This will impact performance due to reallocations.\n",
  3845. + rx_req_headroom, rx_headroom);
  3846. +
  3847. + /* Our .ndo_init will be called herein */
  3848. + err = register_netdev(net_dev);
  3849. + if (err < 0) {
  3850. + dev_err(dev, "register_netdev() failed (%d)\n", err);
  3851. + return err;
  3852. + }
  3853. +
  3854. + return 0;
  3855. +}
  3856. +
  3857. +static int poll_link_state(void *arg)
  3858. +{
  3859. + struct dpaa2_eth_priv *priv = (struct dpaa2_eth_priv *)arg;
  3860. + int err;
  3861. +
  3862. + while (!kthread_should_stop()) {
  3863. + err = link_state_update(priv);
  3864. + if (unlikely(err))
  3865. + return err;
  3866. +
  3867. + msleep(DPAA2_ETH_LINK_STATE_REFRESH);
  3868. + }
  3869. +
  3870. + return 0;
  3871. +}
  3872. +
  3873. +static irqreturn_t dpni_irq0_handler(int irq_num, void *arg)
  3874. +{
  3875. + return IRQ_WAKE_THREAD;
  3876. +}
  3877. +
  3878. +static irqreturn_t dpni_irq0_handler_thread(int irq_num, void *arg)
  3879. +{
  3880. + u32 status = 0, clear = 0;
  3881. + struct device *dev = (struct device *)arg;
  3882. + struct fsl_mc_device *dpni_dev = to_fsl_mc_device(dev);
  3883. + struct net_device *net_dev = dev_get_drvdata(dev);
  3884. + int err;
  3885. +
  3886. + err = dpni_get_irq_status(dpni_dev->mc_io, 0, dpni_dev->mc_handle,
  3887. + DPNI_IRQ_INDEX, &status);
  3888. + if (unlikely(err)) {
  3889. + netdev_err(net_dev, "Can't get irq status (err %d)", err);
  3890. + clear = 0xffffffff;
  3891. + goto out;
  3892. + }
  3893. +
  3894. + if (status & DPNI_IRQ_EVENT_LINK_CHANGED) {
  3895. + clear |= DPNI_IRQ_EVENT_LINK_CHANGED;
  3896. + link_state_update(netdev_priv(net_dev));
  3897. + }
  3898. +
  3899. +out:
  3900. + dpni_clear_irq_status(dpni_dev->mc_io, 0, dpni_dev->mc_handle,
  3901. + DPNI_IRQ_INDEX, clear);
  3902. + return IRQ_HANDLED;
  3903. +}
  3904. +
  3905. +static int setup_irqs(struct fsl_mc_device *ls_dev)
  3906. +{
  3907. + int err = 0;
  3908. + struct fsl_mc_device_irq *irq;
  3909. +
  3910. + err = fsl_mc_allocate_irqs(ls_dev);
  3911. + if (err) {
  3912. + dev_err(&ls_dev->dev, "MC irqs allocation failed\n");
  3913. + return err;
  3914. + }
  3915. +
  3916. + irq = ls_dev->irqs[0];
  3917. + err = devm_request_threaded_irq(&ls_dev->dev, irq->msi_desc->irq,
  3918. + dpni_irq0_handler,
  3919. + dpni_irq0_handler_thread,
  3920. + IRQF_NO_SUSPEND | IRQF_ONESHOT,
  3921. + dev_name(&ls_dev->dev), &ls_dev->dev);
  3922. + if (err < 0) {
  3923. + dev_err(&ls_dev->dev, "devm_request_threaded_irq(): %d", err);
  3924. + goto free_mc_irq;
  3925. + }
  3926. +
  3927. + err = dpni_set_irq_mask(ls_dev->mc_io, 0, ls_dev->mc_handle,
  3928. + DPNI_IRQ_INDEX, DPNI_IRQ_EVENT_LINK_CHANGED);
  3929. + if (err < 0) {
  3930. + dev_err(&ls_dev->dev, "dpni_set_irq_mask(): %d", err);
  3931. + goto free_irq;
  3932. + }
  3933. +
  3934. + err = dpni_set_irq_enable(ls_dev->mc_io, 0, ls_dev->mc_handle,
  3935. + DPNI_IRQ_INDEX, 1);
  3936. + if (err < 0) {
  3937. + dev_err(&ls_dev->dev, "dpni_set_irq_enable(): %d", err);
  3938. + goto free_irq;
  3939. + }
  3940. +
  3941. + return 0;
  3942. +
  3943. +free_irq:
  3944. + devm_free_irq(&ls_dev->dev, irq->msi_desc->irq, &ls_dev->dev);
  3945. +free_mc_irq:
  3946. + fsl_mc_free_irqs(ls_dev);
  3947. +
  3948. + return err;
  3949. +}
  3950. +
  3951. +static void add_ch_napi(struct dpaa2_eth_priv *priv)
  3952. +{
  3953. + int i;
  3954. + struct dpaa2_eth_channel *ch;
  3955. +
  3956. + for (i = 0; i < priv->num_channels; i++) {
  3957. + ch = priv->channel[i];
  3958. + /* NAPI weight *MUST* be a multiple of DPAA2_ETH_STORE_SIZE */
  3959. + netif_napi_add(priv->net_dev, &ch->napi, dpaa2_eth_poll,
  3960. + NAPI_POLL_WEIGHT);
  3961. + }
  3962. +}
  3963. +
  3964. +static void del_ch_napi(struct dpaa2_eth_priv *priv)
  3965. +{
  3966. + int i;
  3967. + struct dpaa2_eth_channel *ch;
  3968. +
  3969. + for (i = 0; i < priv->num_channels; i++) {
  3970. + ch = priv->channel[i];
  3971. + netif_napi_del(&ch->napi);
  3972. + }
  3973. +}
  3974. +
  3975. +/* SysFS support */
  3976. +static ssize_t dpaa2_eth_show_tx_shaping(struct device *dev,
  3977. + struct device_attribute *attr,
  3978. + char *buf)
  3979. +{
  3980. + struct dpaa2_eth_priv *priv = netdev_priv(to_net_dev(dev));
  3981. + /* No MC API for getting the shaping config. We're stateful. */
  3982. + struct dpni_tx_shaping_cfg *scfg = &priv->shaping_cfg;
  3983. +
  3984. + return sprintf(buf, "%u %hu\n", scfg->rate_limit, scfg->max_burst_size);
  3985. +}
  3986. +
  3987. +static ssize_t dpaa2_eth_write_tx_shaping(struct device *dev,
  3988. + struct device_attribute *attr,
  3989. + const char *buf,
  3990. + size_t count)
  3991. +{
  3992. + int err, items;
  3993. + struct dpaa2_eth_priv *priv = netdev_priv(to_net_dev(dev));
  3994. + struct dpni_tx_shaping_cfg scfg;
  3995. +
  3996. + items = sscanf(buf, "%u %hu", &scfg.rate_limit, &scfg.max_burst_size);
  3997. + if (items != 2) {
  3998. + pr_err("Expected format: \"rate_limit(Mbps) max_burst_size(bytes)\"\n");
  3999. + return -EINVAL;
  4000. + }
  4001. + /* Size restriction as per MC API documentation */
  4002. + if (scfg.max_burst_size > DPAA2_ETH_MAX_BURST_SIZE) {
  4003. + pr_err("max_burst_size must be <= %d\n",
  4004. + DPAA2_ETH_MAX_BURST_SIZE);
  4005. + return -EINVAL;
  4006. + }
  4007. +
  4008. + err = dpni_set_tx_shaping(priv->mc_io, 0, priv->mc_token, &scfg);
  4009. + if (err) {
  4010. + dev_err(dev, "dpni_set_tx_shaping() failed\n");
  4011. + return -EPERM;
  4012. + }
  4013. + /* If successful, save the current configuration for future inquiries */
  4014. + priv->shaping_cfg = scfg;
  4015. +
  4016. + return count;
  4017. +}
  4018. +
  4019. +static ssize_t dpaa2_eth_show_txconf_cpumask(struct device *dev,
  4020. + struct device_attribute *attr,
  4021. + char *buf)
  4022. +{
  4023. + struct dpaa2_eth_priv *priv = netdev_priv(to_net_dev(dev));
  4024. +
  4025. + return cpumap_print_to_pagebuf(1, buf, &priv->txconf_cpumask);
  4026. +}
  4027. +
  4028. +static ssize_t dpaa2_eth_write_txconf_cpumask(struct device *dev,
  4029. + struct device_attribute *attr,
  4030. + const char *buf,
  4031. + size_t count)
  4032. +{
  4033. + struct dpaa2_eth_priv *priv = netdev_priv(to_net_dev(dev));
  4034. + struct dpaa2_eth_fq *fq;
  4035. + bool running = netif_running(priv->net_dev);
  4036. + int i, err;
  4037. +
  4038. + err = cpulist_parse(buf, &priv->txconf_cpumask);
  4039. + if (err)
  4040. + return err;
  4041. +
  4042. + /* Only accept CPUs that have an affine DPIO */
  4043. + if (!cpumask_subset(&priv->txconf_cpumask, &priv->dpio_cpumask)) {
  4044. + netdev_info(priv->net_dev,
  4045. + "cpumask must be a subset of 0x%lx\n",
  4046. + *cpumask_bits(&priv->dpio_cpumask));
  4047. + cpumask_and(&priv->txconf_cpumask, &priv->dpio_cpumask,
  4048. + &priv->txconf_cpumask);
  4049. + }
  4050. +
  4051. + /* Rewiring the TxConf FQs requires interface shutdown.
  4052. + */
  4053. + if (running) {
  4054. + err = dpaa2_eth_stop(priv->net_dev);
  4055. + if (err)
  4056. + return -ENODEV;
  4057. + }
  4058. +
  4059. + /* Set the new TxConf FQ affinities */
  4060. + set_fq_affinity(priv);
  4061. +
  4062. + /* dpaa2_eth_open() below will *stop* the Tx queues until an explicit
  4063. + * link up notification is received. Give the polling thread enough time
  4064. + * to detect the link state change, or else we'll end up with the
  4065. + * transmission side forever shut down.
  4066. + */
  4067. + if (priv->do_link_poll)
  4068. + msleep(2 * DPAA2_ETH_LINK_STATE_REFRESH);
  4069. +
  4070. + for (i = 0; i < priv->num_fqs; i++) {
  4071. + fq = &priv->fq[i];
  4072. + if (fq->type != DPAA2_TX_CONF_FQ)
  4073. + continue;
  4074. + setup_tx_flow(priv, fq);
  4075. + }
  4076. +
  4077. + if (running) {
  4078. + err = dpaa2_eth_open(priv->net_dev);
  4079. + if (err)
  4080. + return -ENODEV;
  4081. + }
  4082. +
  4083. + return count;
  4084. +}
  4085. +
  4086. +static struct device_attribute dpaa2_eth_attrs[] = {
  4087. + __ATTR(txconf_cpumask,
  4088. + 0600,
  4089. + dpaa2_eth_show_txconf_cpumask,
  4090. + dpaa2_eth_write_txconf_cpumask),
  4091. +
  4092. + __ATTR(tx_shaping,
  4093. + 0600,
  4094. + dpaa2_eth_show_tx_shaping,
  4095. + dpaa2_eth_write_tx_shaping),
  4096. +};
  4097. +
  4098. +static void dpaa2_eth_sysfs_init(struct device *dev)
  4099. +{
  4100. + int i, err;
  4101. +
  4102. + for (i = 0; i < ARRAY_SIZE(dpaa2_eth_attrs); i++) {
  4103. + err = device_create_file(dev, &dpaa2_eth_attrs[i]);
  4104. + if (err) {
  4105. + dev_err(dev, "ERROR creating sysfs file\n");
  4106. + goto undo;
  4107. + }
  4108. + }
  4109. + return;
  4110. +
  4111. +undo:
  4112. + while (i > 0)
  4113. + device_remove_file(dev, &dpaa2_eth_attrs[--i]);
  4114. +}
  4115. +
  4116. +static void dpaa2_eth_sysfs_remove(struct device *dev)
  4117. +{
  4118. + int i;
  4119. +
  4120. + for (i = 0; i < ARRAY_SIZE(dpaa2_eth_attrs); i++)
  4121. + device_remove_file(dev, &dpaa2_eth_attrs[i]);
  4122. +}
  4123. +
  4124. +static int dpaa2_eth_probe(struct fsl_mc_device *dpni_dev)
  4125. +{
  4126. + struct device *dev;
  4127. + struct net_device *net_dev = NULL;
  4128. + struct dpaa2_eth_priv *priv = NULL;
  4129. + int err = 0;
  4130. +
  4131. + dev = &dpni_dev->dev;
  4132. +
  4133. + /* Net device */
  4134. + net_dev = alloc_etherdev_mq(sizeof(*priv), DPAA2_ETH_MAX_TX_QUEUES);
  4135. + if (!net_dev) {
  4136. + dev_err(dev, "alloc_etherdev_mq() failed\n");
  4137. + return -ENOMEM;
  4138. + }
  4139. +
  4140. + SET_NETDEV_DEV(net_dev, dev);
  4141. + dev_set_drvdata(dev, net_dev);
  4142. +
  4143. + priv = netdev_priv(net_dev);
  4144. + priv->net_dev = net_dev;
  4145. +
  4146. + priv->iommu_domain = iommu_get_domain_for_dev(dev);
  4147. +
  4148. + /* Obtain a MC portal */
  4149. + err = fsl_mc_portal_allocate(dpni_dev, FSL_MC_IO_ATOMIC_CONTEXT_PORTAL,
  4150. + &priv->mc_io);
  4151. + if (err) {
  4152. + dev_err(dev, "MC portal allocation failed\n");
  4153. + goto err_portal_alloc;
  4154. + }
  4155. +
  4156. + /* MC objects initialization and configuration */
  4157. + err = setup_dpni(dpni_dev);
  4158. + if (err)
  4159. + goto err_dpni_setup;
  4160. +
  4161. + err = setup_dpio(priv);
  4162. + if (err) {
  4163. + dev_info(dev, "Defer probing as no DPIO available\n");
  4164. + err = -EPROBE_DEFER;
  4165. + goto err_dpio_setup;
  4166. + }
  4167. +
  4168. + setup_fqs(priv);
  4169. +
  4170. + err = setup_dpbp(priv);
  4171. + if (err)
  4172. + goto err_dpbp_setup;
  4173. +
  4174. + err = bind_dpni(priv);
  4175. + if (err)
  4176. + goto err_bind;
  4177. +
  4178. + /* Add a NAPI context for each channel */
  4179. + add_ch_napi(priv);
  4180. + enable_ch_napi(priv);
  4181. +
  4182. + /* Percpu statistics */
  4183. + priv->percpu_stats = alloc_percpu(*priv->percpu_stats);
  4184. + if (!priv->percpu_stats) {
  4185. + dev_err(dev, "alloc_percpu(percpu_stats) failed\n");
  4186. + err = -ENOMEM;
  4187. + goto err_alloc_percpu_stats;
  4188. + }
  4189. + priv->percpu_extras = alloc_percpu(*priv->percpu_extras);
  4190. + if (!priv->percpu_extras) {
  4191. + dev_err(dev, "alloc_percpu(percpu_extras) failed\n");
  4192. + err = -ENOMEM;
  4193. + goto err_alloc_percpu_extras;
  4194. + }
  4195. +
  4196. + snprintf(net_dev->name, IFNAMSIZ, "ni%d", dpni_dev->obj_desc.id);
  4197. + if (!dev_valid_name(net_dev->name)) {
  4198. + dev_warn(&net_dev->dev,
  4199. + "netdevice name \"%s\" cannot be used, reverting to default..\n",
  4200. + net_dev->name);
  4201. + dev_alloc_name(net_dev, "eth%d");
  4202. + dev_warn(&net_dev->dev, "using name \"%s\"\n", net_dev->name);
  4203. + }
  4204. +
  4205. + err = netdev_init(net_dev);
  4206. + if (err)
  4207. + goto err_netdev_init;
  4208. +
  4209. + /* Configure checksum offload based on current interface flags */
  4210. + err = set_rx_csum(priv, !!(net_dev->features & NETIF_F_RXCSUM));
  4211. + if (err)
  4212. + goto err_csum;
  4213. +
  4214. + err = set_tx_csum(priv, !!(net_dev->features &
  4215. + (NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM)));
  4216. + if (err)
  4217. + goto err_csum;
  4218. +
  4219. + err = alloc_rings(priv);
  4220. + if (err)
  4221. + goto err_alloc_rings;
  4222. +
  4223. + net_dev->ethtool_ops = &dpaa2_ethtool_ops;
  4224. +
  4225. + err = setup_irqs(dpni_dev);
  4226. + if (err) {
  4227. + netdev_warn(net_dev, "Failed to set link interrupt, fall back to polling\n");
  4228. + priv->poll_thread = kthread_run(poll_link_state, priv,
  4229. + "%s_poll_link", net_dev->name);
  4230. + if (IS_ERR(priv->poll_thread)) {
  4231. + netdev_err(net_dev, "Error starting polling thread\n");
  4232. + goto err_poll_thread;
  4233. + }
  4234. + priv->do_link_poll = true;
  4235. + }
  4236. +
  4237. + dpaa2_eth_sysfs_init(&net_dev->dev);
  4238. +#ifdef CONFIG_FSL_DPAA2_ETH_DEBUGFS
  4239. + dpaa2_dbg_add(priv);
  4240. +#endif
  4241. +
  4242. + dev_info(dev, "Probed interface %s\n", net_dev->name);
  4243. + return 0;
  4244. +
  4245. +err_poll_thread:
  4246. + free_rings(priv);
  4247. +err_alloc_rings:
  4248. +err_csum:
  4249. + unregister_netdev(net_dev);
  4250. +err_netdev_init:
  4251. + free_percpu(priv->percpu_extras);
  4252. +err_alloc_percpu_extras:
  4253. + free_percpu(priv->percpu_stats);
  4254. +err_alloc_percpu_stats:
  4255. + disable_ch_napi(priv);
  4256. + del_ch_napi(priv);
  4257. +err_bind:
  4258. + free_dpbp(priv);
  4259. +err_dpbp_setup:
  4260. + free_dpio(priv);
  4261. +err_dpio_setup:
  4262. + free_dpni(priv);
  4263. +err_dpni_setup:
  4264. + fsl_mc_portal_free(priv->mc_io);
  4265. +err_portal_alloc:
  4266. + dev_set_drvdata(dev, NULL);
  4267. + free_netdev(net_dev);
  4268. +
  4269. + return err;
  4270. +}
  4271. +
  4272. +static int dpaa2_eth_remove(struct fsl_mc_device *ls_dev)
  4273. +{
  4274. + struct device *dev;
  4275. + struct net_device *net_dev;
  4276. + struct dpaa2_eth_priv *priv;
  4277. +
  4278. + dev = &ls_dev->dev;
  4279. + net_dev = dev_get_drvdata(dev);
  4280. + priv = netdev_priv(net_dev);
  4281. +
  4282. +#ifdef CONFIG_FSL_DPAA2_ETH_DEBUGFS
  4283. + dpaa2_dbg_remove(priv);
  4284. +#endif
  4285. + dpaa2_eth_sysfs_remove(&net_dev->dev);
  4286. +
  4287. + unregister_netdev(net_dev);
  4288. + dev_info(net_dev->dev.parent, "Removed interface %s\n", net_dev->name);
  4289. +
  4290. + if (priv->do_link_poll)
  4291. + kthread_stop(priv->poll_thread);
  4292. + else
  4293. + fsl_mc_free_irqs(ls_dev);
  4294. +
  4295. + free_rings(priv);
  4296. + free_percpu(priv->percpu_stats);
  4297. + free_percpu(priv->percpu_extras);
  4298. +
  4299. + disable_ch_napi(priv);
  4300. + del_ch_napi(priv);
  4301. + free_dpbp(priv);
  4302. + free_dpio(priv);
  4303. + free_dpni(priv);
  4304. +
  4305. + fsl_mc_portal_free(priv->mc_io);
  4306. +
  4307. + dev_set_drvdata(dev, NULL);
  4308. + free_netdev(net_dev);
  4309. +
  4310. + return 0;
  4311. +}
  4312. +
  4313. +static const struct fsl_mc_device_id dpaa2_eth_match_id_table[] = {
  4314. + {
  4315. + .vendor = FSL_MC_VENDOR_FREESCALE,
  4316. + .obj_type = "dpni",
  4317. + },
  4318. + { .vendor = 0x0 }
  4319. +};
  4320. +MODULE_DEVICE_TABLE(fslmc, dpaa2_eth_match_id_table);
  4321. +
  4322. +static struct fsl_mc_driver dpaa2_eth_driver = {
  4323. + .driver = {
  4324. + .name = KBUILD_MODNAME,
  4325. + .owner = THIS_MODULE,
  4326. + },
  4327. + .probe = dpaa2_eth_probe,
  4328. + .remove = dpaa2_eth_remove,
  4329. + .match_id_table = dpaa2_eth_match_id_table
  4330. +};
  4331. +
  4332. +static int __init dpaa2_eth_driver_init(void)
  4333. +{
  4334. + int err;
  4335. +
  4336. + dpaa2_eth_dbg_init();
  4337. + err = fsl_mc_driver_register(&dpaa2_eth_driver);
  4338. + if (err) {
  4339. + dpaa2_eth_dbg_exit();
  4340. + return err;
  4341. + }
  4342. +
  4343. + return 0;
  4344. +}
  4345. +
  4346. +static void __exit dpaa2_eth_driver_exit(void)
  4347. +{
  4348. + dpaa2_eth_dbg_exit();
  4349. + fsl_mc_driver_unregister(&dpaa2_eth_driver);
  4350. +}
  4351. +
  4352. +module_init(dpaa2_eth_driver_init);
  4353. +module_exit(dpaa2_eth_driver_exit);
  4354. --- /dev/null
  4355. +++ b/drivers/staging/fsl-dpaa2/ethernet/dpaa2-eth.h
  4356. @@ -0,0 +1,460 @@
  4357. +/* Copyright 2014-2015 Freescale Semiconductor Inc.
  4358. + *
  4359. + * Redistribution and use in source and binary forms, with or without
  4360. + * modification, are permitted provided that the following conditions are met:
  4361. + * * Redistributions of source code must retain the above copyright
  4362. + * notice, this list of conditions and the following disclaimer.
  4363. + * * Redistributions in binary form must reproduce the above copyright
  4364. + * notice, this list of conditions and the following disclaimer in the
  4365. + * documentation and/or other materials provided with the distribution.
  4366. + * * Neither the name of Freescale Semiconductor nor the
  4367. + * names of its contributors may be used to endorse or promote products
  4368. + * derived from this software without specific prior written permission.
  4369. + *
  4370. + *
  4371. + * ALTERNATIVELY, this software may be distributed under the terms of the
  4372. + * GNU General Public License ("GPL") as published by the Free Software
  4373. + * Foundation, either version 2 of that License or (at your option) any
  4374. + * later version.
  4375. + *
  4376. + * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
  4377. + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  4378. + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  4379. + * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
  4380. + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  4381. + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  4382. + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  4383. + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  4384. + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  4385. + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  4386. + */
  4387. +
  4388. +#ifndef __DPAA2_ETH_H
  4389. +#define __DPAA2_ETH_H
  4390. +
  4391. +#include <linux/atomic.h>
  4392. +#include <linux/netdevice.h>
  4393. +#include <linux/if_vlan.h>
  4394. +#include "../../fsl-mc/include/dpaa2-io.h"
  4395. +#include "dpni.h"
  4396. +#include "net.h"
  4397. +
  4398. +#include "dpaa2-eth-debugfs.h"
  4399. +
  4400. +#define DPAA2_ETH_STORE_SIZE 16
  4401. +
  4402. +/* We set a max threshold for how many Tx confirmations we should process
  4403. + * on a NAPI poll call, they take less processing time.
  4404. + */
  4405. +#define TX_CONF_PER_NAPI_POLL 256
  4406. +
  4407. +/* Maximum number of scatter-gather entries in an ingress frame,
  4408. + * considering the maximum receive frame size is 64K
  4409. + */
  4410. +#define DPAA2_ETH_MAX_SG_ENTRIES ((64 * 1024) / DPAA2_ETH_RX_BUF_SIZE)
  4411. +
  4412. +/* Maximum acceptable MTU value. It is in direct relation with the hardware
  4413. + * enforced Max Frame Length (currently 10k).
  4414. + */
  4415. +#define DPAA2_ETH_MFL (10 * 1024)
  4416. +#define DPAA2_ETH_MAX_MTU (DPAA2_ETH_MFL - VLAN_ETH_HLEN)
  4417. +/* Convert L3 MTU to L2 MFL */
  4418. +#define DPAA2_ETH_L2_MAX_FRM(mtu) ((mtu) + VLAN_ETH_HLEN)
  4419. +
  4420. +/* Maximum burst size value for Tx shaping */
  4421. +#define DPAA2_ETH_MAX_BURST_SIZE 0xF7FF
  4422. +
  4423. +/* Maximum number of buffers that can be acquired/released through a single
  4424. + * QBMan command
  4425. + */
  4426. +#define DPAA2_ETH_BUFS_PER_CMD 7
  4427. +
  4428. +/* Set the taildrop threshold (in bytes) to allow the enqueue of several jumbo
  4429. + * frames in the Rx queues (length of the current frame is not
  4430. + * taken into account when making the taildrop decision)
  4431. + */
  4432. +#define DPAA2_ETH_TAILDROP_THRESH (64 * 1024)
  4433. +
  4434. +/* Buffer quota per queue. Must be large enough such that for minimum sized
  4435. + * frames taildrop kicks in before the bpool gets depleted, so we compute
  4436. + * how many 64B frames fit inside the taildrop threshold and add a margin
  4437. + * to accommodate the buffer refill delay.
  4438. + */
  4439. +#define DPAA2_ETH_MAX_FRAMES_PER_QUEUE (DPAA2_ETH_TAILDROP_THRESH / 64)
  4440. +#define DPAA2_ETH_NUM_BUFS_TD (DPAA2_ETH_MAX_FRAMES_PER_QUEUE + 256)
  4441. +#define DPAA2_ETH_REFILL_THRESH_TD \
  4442. + (DPAA2_ETH_NUM_BUFS_TD - DPAA2_ETH_BUFS_PER_CMD)
  4443. +
  4444. +/* Buffer quota per queue to use when flow control is active. */
  4445. +#define DPAA2_ETH_NUM_BUFS_FC 256
  4446. +
  4447. +/* Hardware requires alignment for ingress/egress buffer addresses
  4448. + * and ingress buffer lengths.
  4449. + */
  4450. +#define DPAA2_ETH_RX_BUF_SIZE 2048
  4451. +#define DPAA2_ETH_TX_BUF_ALIGN 64
  4452. +#define DPAA2_ETH_RX_BUF_ALIGN 64
  4453. +#define DPAA2_ETH_RX_BUF_ALIGN_V1 256
  4454. +#define DPAA2_ETH_NEEDED_HEADROOM(p_priv) \
  4455. + ((p_priv)->tx_data_offset + DPAA2_ETH_TX_BUF_ALIGN)
  4456. +
  4457. +/* rx_extra_head prevents reallocations in L3 processing. */
  4458. +#define DPAA2_ETH_SKB_SIZE \
  4459. + (DPAA2_ETH_RX_BUF_SIZE + \
  4460. + SKB_DATA_ALIGN(sizeof(struct skb_shared_info)))
  4461. +
  4462. +/* Hardware only sees DPAA2_ETH_RX_BUF_SIZE, but we need to allocate ingress
  4463. + * buffers large enough to allow building an skb around them and also account
  4464. + * for alignment restrictions.
  4465. + */
  4466. +#define DPAA2_ETH_BUF_RAW_SIZE(p_priv) \
  4467. + (DPAA2_ETH_SKB_SIZE + \
  4468. + (p_priv)->rx_buf_align)
  4469. +
  4470. +/* PTP nominal frequency 1GHz */
  4471. +#define DPAA2_PTP_NOMINAL_FREQ_PERIOD_NS 1
  4472. +
  4473. +/* Leave enough extra space in the headroom to make sure the skb is
  4474. + * not realloc'd in forwarding scenarios.
  4475. + */
  4476. +#define DPAA2_ETH_RX_HEAD_ROOM 192
  4477. +
  4478. +/* We are accommodating a skb backpointer and some S/G info
  4479. + * in the frame's software annotation. The hardware
  4480. + * options are either 0 or 64, so we choose the latter.
  4481. + */
  4482. +#define DPAA2_ETH_SWA_SIZE 64
  4483. +
  4484. +/* Must keep this struct smaller than DPAA2_ETH_SWA_SIZE */
  4485. +struct dpaa2_eth_swa {
  4486. + struct sk_buff *skb;
  4487. + struct scatterlist *scl;
  4488. + int num_sg;
  4489. + int num_dma_bufs;
  4490. +};
  4491. +
  4492. +/* Annotation valid bits in FD FRC */
  4493. +#define DPAA2_FD_FRC_FASV 0x8000
  4494. +#define DPAA2_FD_FRC_FAEADV 0x4000
  4495. +#define DPAA2_FD_FRC_FAPRV 0x2000
  4496. +#define DPAA2_FD_FRC_FAIADV 0x1000
  4497. +#define DPAA2_FD_FRC_FASWOV 0x0800
  4498. +#define DPAA2_FD_FRC_FAICFDV 0x0400
  4499. +
  4500. +#define DPAA2_FD_RX_ERR_MASK (FD_CTRL_SBE | FD_CTRL_FAERR)
  4501. +#define DPAA2_FD_TX_ERR_MASK (FD_CTRL_UFD | \
  4502. + FD_CTRL_SBE | \
  4503. + FD_CTRL_FSE | \
  4504. + FD_CTRL_FAERR)
  4505. +
  4506. +/* Annotation bits in FD CTRL */
  4507. +#define DPAA2_FD_CTRL_ASAL 0x00020000 /* ASAL = 128 */
  4508. +
  4509. +/* Size of hardware annotation area based on the current buffer layout
  4510. + * configuration
  4511. + */
  4512. +#define DPAA2_ETH_RX_HWA_SIZE 64
  4513. +#define DPAA2_ETH_TX_HWA_SIZE 128
  4514. +
  4515. +/* Frame annotation status */
  4516. +struct dpaa2_fas {
  4517. + u8 reserved;
  4518. + u8 ppid;
  4519. + __le16 ifpid;
  4520. + __le32 status;
  4521. +} __packed;
  4522. +
  4523. +/* Frame annotation status word is located in the first 8 bytes
  4524. + * of the buffer's hardware annotation area
  4525. + */
  4526. +#define DPAA2_FAS_OFFSET 0
  4527. +#define DPAA2_FAS_SIZE (sizeof(struct dpaa2_fas))
  4528. +
  4529. +/* Timestamp is located in the next 8 bytes of the buffer's
  4530. + * hardware annotation area
  4531. + */
  4532. +#define DPAA2_TS_OFFSET 0x8
  4533. +
  4534. +/* Frame annotation egress action descriptor */
  4535. +#define DPAA2_FAEAD_OFFSET 0x58
  4536. +
  4537. +struct dpaa2_faead {
  4538. + __le32 conf_fqid;
  4539. + __le32 ctrl;
  4540. +};
  4541. +
  4542. +#define DPAA2_FAEAD_A2V 0x20000000
  4543. +#define DPAA2_FAEAD_UPDV 0x00001000
  4544. +#define DPAA2_FAEAD_UPD 0x00000010
  4545. +
  4546. +/* accessors for the hardware annotation fields that we use */
  4547. +#define dpaa2_eth_get_hwa(buf_addr) \
  4548. + ((void *)(buf_addr) + DPAA2_ETH_SWA_SIZE)
  4549. +
  4550. +#define dpaa2_eth_get_fas(buf_addr) \
  4551. + (struct dpaa2_fas *)(dpaa2_eth_get_hwa(buf_addr) + DPAA2_FAS_OFFSET)
  4552. +
  4553. +#define dpaa2_eth_get_ts(buf_addr) \
  4554. + (u64 *)(dpaa2_eth_get_hwa(buf_addr) + DPAA2_TS_OFFSET)
  4555. +
  4556. +#define dpaa2_eth_get_faead(buf_addr) \
  4557. + (struct dpaa2_faead *)(dpaa2_eth_get_hwa(buf_addr) + DPAA2_FAEAD_OFFSET)
  4558. +
  4559. +/* Error and status bits in the frame annotation status word */
  4560. +/* Debug frame, otherwise supposed to be discarded */
  4561. +#define DPAA2_FAS_DISC 0x80000000
  4562. +/* MACSEC frame */
  4563. +#define DPAA2_FAS_MS 0x40000000
  4564. +#define DPAA2_FAS_PTP 0x08000000
  4565. +/* Ethernet multicast frame */
  4566. +#define DPAA2_FAS_MC 0x04000000
  4567. +/* Ethernet broadcast frame */
  4568. +#define DPAA2_FAS_BC 0x02000000
  4569. +#define DPAA2_FAS_KSE 0x00040000
  4570. +#define DPAA2_FAS_EOFHE 0x00020000
  4571. +#define DPAA2_FAS_MNLE 0x00010000
  4572. +#define DPAA2_FAS_TIDE 0x00008000
  4573. +#define DPAA2_FAS_PIEE 0x00004000
  4574. +/* Frame length error */
  4575. +#define DPAA2_FAS_FLE 0x00002000
  4576. +/* Frame physical error */
  4577. +#define DPAA2_FAS_FPE 0x00001000
  4578. +#define DPAA2_FAS_PTE 0x00000080
  4579. +#define DPAA2_FAS_ISP 0x00000040
  4580. +#define DPAA2_FAS_PHE 0x00000020
  4581. +#define DPAA2_FAS_BLE 0x00000010
  4582. +/* L3 csum validation performed */
  4583. +#define DPAA2_FAS_L3CV 0x00000008
  4584. +/* L3 csum error */
  4585. +#define DPAA2_FAS_L3CE 0x00000004
  4586. +/* L4 csum validation performed */
  4587. +#define DPAA2_FAS_L4CV 0x00000002
  4588. +/* L4 csum error */
  4589. +#define DPAA2_FAS_L4CE 0x00000001
  4590. +/* Possible errors on the ingress path */
  4591. +#define DPAA2_FAS_RX_ERR_MASK ((DPAA2_FAS_KSE) | \
  4592. + (DPAA2_FAS_EOFHE) | \
  4593. + (DPAA2_FAS_MNLE) | \
  4594. + (DPAA2_FAS_TIDE) | \
  4595. + (DPAA2_FAS_PIEE) | \
  4596. + (DPAA2_FAS_FLE) | \
  4597. + (DPAA2_FAS_FPE) | \
  4598. + (DPAA2_FAS_PTE) | \
  4599. + (DPAA2_FAS_ISP) | \
  4600. + (DPAA2_FAS_PHE) | \
  4601. + (DPAA2_FAS_BLE) | \
  4602. + (DPAA2_FAS_L3CE) | \
  4603. + (DPAA2_FAS_L4CE))
  4604. +/* Tx errors */
  4605. +#define DPAA2_FAS_TX_ERR_MASK ((DPAA2_FAS_KSE) | \
  4606. + (DPAA2_FAS_EOFHE) | \
  4607. + (DPAA2_FAS_MNLE) | \
  4608. + (DPAA2_FAS_TIDE))
  4609. +
  4610. +/* Time in milliseconds between link state updates */
  4611. +#define DPAA2_ETH_LINK_STATE_REFRESH 1000
  4612. +
  4613. +/* Number of times to retry a frame enqueue before giving up.
  4614. + * Value determined empirically, in order to minimize the number
  4615. + * of frames dropped on Tx
  4616. + */
  4617. +#define DPAA2_ETH_ENQUEUE_RETRIES 10
  4618. +
  4619. +/* Tx congestion entry & exit thresholds, in number of bytes.
  4620. + * We allow a maximum of 512KB worth of frames pending processing on the Tx
  4621. + * queues of an interface
  4622. + */
  4623. +#define DPAA2_ETH_TX_CONG_ENTRY_THRESH (512 * 1024)
  4624. +#define DPAA2_ETH_TX_CONG_EXIT_THRESH (DPAA2_ETH_TX_CONG_ENTRY_THRESH * 9/10)
  4625. +
  4626. +/* Driver statistics, other than those in struct rtnl_link_stats64.
  4627. + * These are usually collected per-CPU and aggregated by ethtool.
  4628. + */
  4629. +struct dpaa2_eth_drv_stats {
  4630. + __u64 tx_conf_frames;
  4631. + __u64 tx_conf_bytes;
  4632. + __u64 tx_sg_frames;
  4633. + __u64 tx_sg_bytes;
  4634. + __u64 rx_sg_frames;
  4635. + __u64 rx_sg_bytes;
  4636. + /* Enqueues retried due to portal busy */
  4637. + __u64 tx_portal_busy;
  4638. +};
  4639. +
  4640. +/* Per-FQ statistics */
  4641. +struct dpaa2_eth_fq_stats {
  4642. + /* Number of frames received on this queue */
  4643. + __u64 frames;
  4644. + /* Number of times this queue entered congestion */
  4645. + __u64 congestion_entry;
  4646. +};
  4647. +
  4648. +/* Per-channel statistics */
  4649. +struct dpaa2_eth_ch_stats {
  4650. + /* Volatile dequeues retried due to portal busy */
  4651. + __u64 dequeue_portal_busy;
  4652. + /* Number of CDANs; useful to estimate avg NAPI len */
  4653. + __u64 cdan;
  4654. + /* Number of frames received on queues from this channel */
  4655. + __u64 frames;
  4656. + /* Pull errors */
  4657. + __u64 pull_err;
  4658. +};
  4659. +
  4660. +/* Maximum number of queues associated with a DPNI */
  4661. +#define DPAA2_ETH_MAX_RX_QUEUES 16
  4662. +#define DPAA2_ETH_MAX_TX_QUEUES NR_CPUS
  4663. +#define DPAA2_ETH_MAX_RX_ERR_QUEUES 1
  4664. +#define DPAA2_ETH_MAX_QUEUES (DPAA2_ETH_MAX_RX_QUEUES + \
  4665. + DPAA2_ETH_MAX_TX_QUEUES + \
  4666. + DPAA2_ETH_MAX_RX_ERR_QUEUES)
  4667. +
  4668. +#define DPAA2_ETH_MAX_DPCONS NR_CPUS
  4669. +
  4670. +enum dpaa2_eth_fq_type {
  4671. + DPAA2_RX_FQ = 0,
  4672. + DPAA2_TX_CONF_FQ,
  4673. + DPAA2_RX_ERR_FQ
  4674. +};
  4675. +
  4676. +struct dpaa2_eth_priv;
  4677. +
  4678. +struct dpaa2_eth_fq {
  4679. + u32 fqid;
  4680. + u32 tx_qdbin;
  4681. + u16 flowid;
  4682. + int target_cpu;
  4683. + struct dpaa2_eth_channel *channel;
  4684. + enum dpaa2_eth_fq_type type;
  4685. +
  4686. + void (*consume)(struct dpaa2_eth_priv *,
  4687. + struct dpaa2_eth_channel *,
  4688. + const struct dpaa2_fd *,
  4689. + struct napi_struct *,
  4690. + u16 queue_id);
  4691. + struct dpaa2_eth_fq_stats stats;
  4692. +};
  4693. +
  4694. +struct dpaa2_eth_channel {
  4695. + struct dpaa2_io_notification_ctx nctx;
  4696. + struct fsl_mc_device *dpcon;
  4697. + int dpcon_id;
  4698. + int ch_id;
  4699. + int dpio_id;
  4700. + struct napi_struct napi;
  4701. + struct dpaa2_io_store *store;
  4702. + struct dpaa2_eth_priv *priv;
  4703. + int buf_count;
  4704. + struct dpaa2_eth_ch_stats stats;
  4705. +};
  4706. +
  4707. +struct dpaa2_eth_cls_rule {
  4708. + struct ethtool_rx_flow_spec fs;
  4709. + bool in_use;
  4710. +};
  4711. +
  4712. +struct dpaa2_eth_hash_fields {
  4713. + u64 rxnfc_field;
  4714. + enum net_prot cls_prot;
  4715. + int cls_field;
  4716. + int offset;
  4717. + int size;
  4718. +};
  4719. +
  4720. +/* Driver private data */
  4721. +struct dpaa2_eth_priv {
  4722. + struct net_device *net_dev;
  4723. +
  4724. + /* Standard statistics */
  4725. + struct rtnl_link_stats64 __percpu *percpu_stats;
  4726. + /* Extra stats, in addition to the ones known by the kernel */
  4727. + struct dpaa2_eth_drv_stats __percpu *percpu_extras;
  4728. + struct iommu_domain *iommu_domain;
  4729. +
  4730. + bool ts_tx_en; /* Tx timestamping enabled */
  4731. + bool ts_rx_en; /* Rx timestamping enabled */
  4732. +
  4733. + u16 tx_data_offset;
  4734. + u16 rx_buf_align;
  4735. +
  4736. + u16 bpid;
  4737. + u16 tx_qdid;
  4738. +
  4739. + int tx_pause_frames;
  4740. + int num_bufs;
  4741. + int refill_thresh;
  4742. +
  4743. + /* Tx congestion notifications are written here */
  4744. + void *cscn_mem;
  4745. + void *cscn_unaligned;
  4746. + dma_addr_t cscn_dma;
  4747. +
  4748. + u8 num_fqs;
  4749. + /* Tx queues are at the beginning of the array */
  4750. + struct dpaa2_eth_fq fq[DPAA2_ETH_MAX_QUEUES];
  4751. +
  4752. + u8 num_channels;
  4753. + struct dpaa2_eth_channel *channel[DPAA2_ETH_MAX_DPCONS];
  4754. +
  4755. + int dpni_id;
  4756. + struct dpni_attr dpni_attrs;
  4757. + struct fsl_mc_device *dpbp_dev;
  4758. +
  4759. + struct fsl_mc_io *mc_io;
  4760. + /* SysFS-controlled affinity mask for TxConf FQs */
  4761. + struct cpumask txconf_cpumask;
  4762. + /* Cores which have an affine DPIO/DPCON.
  4763. + * This is the cpu set on which Rx frames are processed;
  4764. + * Tx confirmation frames are processed on a subset of this,
  4765. + * depending on user settings.
  4766. + */
  4767. + struct cpumask dpio_cpumask;
  4768. +
  4769. + u16 mc_token;
  4770. +
  4771. + struct dpni_link_state link_state;
  4772. + bool do_link_poll;
  4773. + struct task_struct *poll_thread;
  4774. +
  4775. + struct dpaa2_eth_hash_fields *hash_fields;
  4776. + u8 num_hash_fields;
  4777. + /* enabled ethtool hashing bits */
  4778. + u64 rx_flow_hash;
  4779. +
  4780. +#ifdef CONFIG_FSL_DPAA2_ETH_DEBUGFS
  4781. + struct dpaa2_debugfs dbg;
  4782. +#endif
  4783. +
  4784. + /* array of classification rules */
  4785. + struct dpaa2_eth_cls_rule *cls_rule;
  4786. +
  4787. + struct dpni_tx_shaping_cfg shaping_cfg;
  4788. +};
  4789. +
  4790. +#define dpaa2_eth_hash_enabled(priv) \
  4791. + ((priv)->dpni_attrs.num_queues > 1)
  4792. +
  4793. +#define dpaa2_eth_fs_enabled(priv) \
  4794. + (!((priv)->dpni_attrs.options & DPNI_OPT_NO_FS))
  4795. +
  4796. +#define dpaa2_eth_fs_mask_enabled(priv) \
  4797. + ((priv)->dpni_attrs.options & DPNI_OPT_HAS_KEY_MASKING)
  4798. +
  4799. +#define dpaa2_eth_fs_count(priv) \
  4800. + ((priv)->dpni_attrs.fs_entries)
  4801. +
  4802. +/* size of DMA memory used to pass configuration to classifier, in bytes */
  4803. +#define DPAA2_CLASSIFIER_DMA_SIZE 256
  4804. +
  4805. +extern const struct ethtool_ops dpaa2_ethtool_ops;
  4806. +extern const char dpaa2_eth_drv_version[];
  4807. +
  4808. +static inline int dpaa2_eth_queue_count(struct dpaa2_eth_priv *priv)
  4809. +{
  4810. + return priv->dpni_attrs.num_queues;
  4811. +}
  4812. +
  4813. +void check_cls_support(struct dpaa2_eth_priv *priv);
  4814. +
  4815. +int setup_fqs_taildrop(struct dpaa2_eth_priv *priv, bool enable);
  4816. +#endif /* __DPAA2_H */
  4817. --- /dev/null
  4818. +++ b/drivers/staging/fsl-dpaa2/ethernet/dpaa2-ethtool.c
  4819. @@ -0,0 +1,856 @@
  4820. +/* Copyright 2014-2015 Freescale Semiconductor Inc.
  4821. + *
  4822. + * Redistribution and use in source and binary forms, with or without
  4823. + * modification, are permitted provided that the following conditions are met:
  4824. + * * Redistributions of source code must retain the above copyright
  4825. + * notice, this list of conditions and the following disclaimer.
  4826. + * * Redistributions in binary form must reproduce the above copyright
  4827. + * notice, this list of conditions and the following disclaimer in the
  4828. + * documentation and/or other materials provided with the distribution.
  4829. + * * Neither the name of Freescale Semiconductor nor the
  4830. + * names of its contributors may be used to endorse or promote products
  4831. + * derived from this software without specific prior written permission.
  4832. + *
  4833. + *
  4834. + * ALTERNATIVELY, this software may be distributed under the terms of the
  4835. + * GNU General Public License ("GPL") as published by the Free Software
  4836. + * Foundation, either version 2 of that License or (at your option) any
  4837. + * later version.
  4838. + *
  4839. + * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
  4840. + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  4841. + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  4842. + * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
  4843. + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  4844. + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  4845. + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  4846. + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  4847. + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  4848. + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  4849. + */
  4850. +
  4851. +#include "dpni.h" /* DPNI_LINK_OPT_* */
  4852. +#include "dpaa2-eth.h"
  4853. +
  4854. +/* To be kept in sync with dpni_statistics */
  4855. +static char dpaa2_ethtool_stats[][ETH_GSTRING_LEN] = {
  4856. + "rx frames",
  4857. + "rx bytes",
  4858. + "rx mcast frames",
  4859. + "rx mcast bytes",
  4860. + "rx bcast frames",
  4861. + "rx bcast bytes",
  4862. + "tx frames",
  4863. + "tx bytes",
  4864. + "tx mcast frames",
  4865. + "tx mcast bytes",
  4866. + "tx bcast frames",
  4867. + "tx bcast bytes",
  4868. + "rx filtered frames",
  4869. + "rx discarded frames",
  4870. + "rx nobuffer discards",
  4871. + "tx discarded frames",
  4872. + "tx confirmed frames",
  4873. +};
  4874. +
  4875. +#define DPAA2_ETH_NUM_STATS ARRAY_SIZE(dpaa2_ethtool_stats)
  4876. +
  4877. +/* To be kept in sync with 'struct dpaa2_eth_drv_stats' */
  4878. +static char dpaa2_ethtool_extras[][ETH_GSTRING_LEN] = {
  4879. + /* per-cpu stats */
  4880. +
  4881. + "tx conf frames",
  4882. + "tx conf bytes",
  4883. + "tx sg frames",
  4884. + "tx sg bytes",
  4885. + "rx sg frames",
  4886. + "rx sg bytes",
  4887. + /* how many times we had to retry the enqueue command */
  4888. + "enqueue portal busy",
  4889. +
  4890. + /* Channel stats */
  4891. + /* How many times we had to retry the volatile dequeue command */
  4892. + "dequeue portal busy",
  4893. + "channel pull errors",
  4894. + /* Number of notifications received */
  4895. + "cdan",
  4896. + "tx congestion state",
  4897. +#ifdef CONFIG_FSL_QBMAN_DEBUG
  4898. + /* FQ stats */
  4899. + "rx pending frames",
  4900. + "rx pending bytes",
  4901. + "tx conf pending frames",
  4902. + "tx conf pending bytes",
  4903. + "buffer count"
  4904. +#endif
  4905. +};
  4906. +
  4907. +#define DPAA2_ETH_NUM_EXTRA_STATS ARRAY_SIZE(dpaa2_ethtool_extras)
  4908. +
  4909. +static void dpaa2_eth_get_drvinfo(struct net_device *net_dev,
  4910. + struct ethtool_drvinfo *drvinfo)
  4911. +{
  4912. + strlcpy(drvinfo->driver, KBUILD_MODNAME, sizeof(drvinfo->driver));
  4913. + strlcpy(drvinfo->version, dpaa2_eth_drv_version,
  4914. + sizeof(drvinfo->version));
  4915. + strlcpy(drvinfo->fw_version, "N/A", sizeof(drvinfo->fw_version));
  4916. + strlcpy(drvinfo->bus_info, dev_name(net_dev->dev.parent->parent),
  4917. + sizeof(drvinfo->bus_info));
  4918. +}
  4919. +
  4920. +static int dpaa2_eth_get_settings(struct net_device *net_dev,
  4921. + struct ethtool_cmd *cmd)
  4922. +{
  4923. + struct dpni_link_state state = {0};
  4924. + int err = 0;
  4925. + struct dpaa2_eth_priv *priv = netdev_priv(net_dev);
  4926. +
  4927. + err = dpni_get_link_state(priv->mc_io, 0, priv->mc_token, &state);
  4928. + if (err) {
  4929. + netdev_err(net_dev, "ERROR %d getting link state", err);
  4930. + goto out;
  4931. + }
  4932. +
  4933. + /* At the moment, we have no way of interrogating the DPMAC
  4934. + * from the DPNI side - and for that matter there may exist
  4935. + * no DPMAC at all. So for now we just don't report anything
  4936. + * beyond the DPNI attributes.
  4937. + */
  4938. + if (state.options & DPNI_LINK_OPT_AUTONEG)
  4939. + cmd->autoneg = AUTONEG_ENABLE;
  4940. + if (!(state.options & DPNI_LINK_OPT_HALF_DUPLEX))
  4941. + cmd->duplex = DUPLEX_FULL;
  4942. + ethtool_cmd_speed_set(cmd, state.rate);
  4943. +
  4944. +out:
  4945. + return err;
  4946. +}
  4947. +
  4948. +static int dpaa2_eth_set_settings(struct net_device *net_dev,
  4949. + struct ethtool_cmd *cmd)
  4950. +{
  4951. + struct dpaa2_eth_priv *priv = netdev_priv(net_dev);
  4952. + struct dpni_link_state state = {0};
  4953. + struct dpni_link_cfg cfg = {0};
  4954. + int err = 0;
  4955. +
  4956. + netdev_dbg(net_dev, "Setting link parameters...");
  4957. +
  4958. + /* Need to interrogate on link state to get flow control params */
  4959. + err = dpni_get_link_state(priv->mc_io, 0, priv->mc_token, &state);
  4960. + if (err) {
  4961. + netdev_err(net_dev, "ERROR %d getting link state", err);
  4962. + goto out;
  4963. + }
  4964. +
  4965. + cfg.options = state.options;
  4966. + cfg.rate = ethtool_cmd_speed(cmd);
  4967. + if (cmd->autoneg == AUTONEG_ENABLE)
  4968. + cfg.options |= DPNI_LINK_OPT_AUTONEG;
  4969. + else
  4970. + cfg.options &= ~DPNI_LINK_OPT_AUTONEG;
  4971. + if (cmd->duplex == DUPLEX_HALF)
  4972. + cfg.options |= DPNI_LINK_OPT_HALF_DUPLEX;
  4973. + else
  4974. + cfg.options &= ~DPNI_LINK_OPT_HALF_DUPLEX;
  4975. +
  4976. + err = dpni_set_link_cfg(priv->mc_io, 0, priv->mc_token, &cfg);
  4977. + if (err)
  4978. + /* ethtool will be loud enough if we return an error; no point
  4979. + * in putting our own error message on the console by default
  4980. + */
  4981. + netdev_dbg(net_dev, "ERROR %d setting link cfg", err);
  4982. +
  4983. +out:
  4984. + return err;
  4985. +}
  4986. +
  4987. +static void dpaa2_eth_get_pauseparam(struct net_device *net_dev,
  4988. + struct ethtool_pauseparam *pause)
  4989. +{
  4990. + struct dpaa2_eth_priv *priv = netdev_priv(net_dev);
  4991. + struct dpni_link_state state = {0};
  4992. + int err;
  4993. +
  4994. + err = dpni_get_link_state(priv->mc_io, 0, priv->mc_token, &state);
  4995. + if (err)
  4996. + netdev_dbg(net_dev, "ERROR %d getting link state", err);
  4997. +
  4998. + /* for now, pause frames autonegotiation is not separate */
  4999. + pause->autoneg = !!(state.options & DPNI_LINK_OPT_AUTONEG);
  5000. + pause->rx_pause = !!(state.options & DPNI_LINK_OPT_PAUSE);
  5001. + pause->tx_pause = pause->rx_pause ^
  5002. + !!(state.options & DPNI_LINK_OPT_ASYM_PAUSE);
  5003. +}
  5004. +
  5005. +static int dpaa2_eth_set_pauseparam(struct net_device *net_dev,
  5006. + struct ethtool_pauseparam *pause)
  5007. +{
  5008. + struct dpaa2_eth_priv *priv = netdev_priv(net_dev);
  5009. + struct dpni_link_state state = {0};
  5010. + struct dpni_link_cfg cfg = {0};
  5011. + u32 current_tx_pause;
  5012. + int err = 0;
  5013. +
  5014. + err = dpni_get_link_state(priv->mc_io, 0, priv->mc_token, &state);
  5015. + if (err) {
  5016. + netdev_dbg(net_dev, "ERROR %d getting link state", err);
  5017. + goto out;
  5018. + }
  5019. +
  5020. + cfg.rate = state.rate;
  5021. + cfg.options = state.options;
  5022. + current_tx_pause = !!(cfg.options & DPNI_LINK_OPT_PAUSE) ^
  5023. + !!(cfg.options & DPNI_LINK_OPT_ASYM_PAUSE);
  5024. +
  5025. + if (pause->autoneg != !!(state.options & DPNI_LINK_OPT_AUTONEG))
  5026. + netdev_warn(net_dev,
  5027. + "WARN: Can't change pause frames autoneg separately\n");
  5028. +
  5029. + if (pause->rx_pause)
  5030. + cfg.options |= DPNI_LINK_OPT_PAUSE;
  5031. + else
  5032. + cfg.options &= ~DPNI_LINK_OPT_PAUSE;
  5033. +
  5034. + if (pause->rx_pause ^ pause->tx_pause)
  5035. + cfg.options |= DPNI_LINK_OPT_ASYM_PAUSE;
  5036. + else
  5037. + cfg.options &= ~DPNI_LINK_OPT_ASYM_PAUSE;
  5038. +
  5039. + err = dpni_set_link_cfg(priv->mc_io, 0, priv->mc_token, &cfg);
  5040. + if (err) {
  5041. + /* ethtool will be loud enough if we return an error; no point
  5042. + * in putting our own error message on the console by default
  5043. + */
  5044. + netdev_dbg(net_dev, "ERROR %d setting link cfg", err);
  5045. + goto out;
  5046. + }
  5047. +
  5048. + /* Enable / disable taildrops if Tx pause frames have changed */
  5049. + if (current_tx_pause == pause->tx_pause)
  5050. + goto out;
  5051. +
  5052. + err = setup_fqs_taildrop(priv, !pause->tx_pause);
  5053. + if (err)
  5054. + netdev_dbg(net_dev, "ERROR %d configuring taildrop", err);
  5055. +
  5056. + priv->tx_pause_frames = pause->tx_pause;
  5057. +out:
  5058. + return err;
  5059. +}
  5060. +
  5061. +static void dpaa2_eth_get_strings(struct net_device *netdev, u32 stringset,
  5062. + u8 *data)
  5063. +{
  5064. + u8 *p = data;
  5065. + int i;
  5066. +
  5067. + switch (stringset) {
  5068. + case ETH_SS_STATS:
  5069. + for (i = 0; i < DPAA2_ETH_NUM_STATS; i++) {
  5070. + strlcpy(p, dpaa2_ethtool_stats[i], ETH_GSTRING_LEN);
  5071. + p += ETH_GSTRING_LEN;
  5072. + }
  5073. + for (i = 0; i < DPAA2_ETH_NUM_EXTRA_STATS; i++) {
  5074. + strlcpy(p, dpaa2_ethtool_extras[i], ETH_GSTRING_LEN);
  5075. + p += ETH_GSTRING_LEN;
  5076. + }
  5077. + break;
  5078. + }
  5079. +}
  5080. +
  5081. +static int dpaa2_eth_get_sset_count(struct net_device *net_dev, int sset)
  5082. +{
  5083. + switch (sset) {
  5084. + case ETH_SS_STATS: /* ethtool_get_stats(), ethtool_get_drvinfo() */
  5085. + return DPAA2_ETH_NUM_STATS + DPAA2_ETH_NUM_EXTRA_STATS;
  5086. + default:
  5087. + return -EOPNOTSUPP;
  5088. + }
  5089. +}
  5090. +
  5091. +/** Fill in hardware counters, as returned by MC.
  5092. + */
  5093. +static void dpaa2_eth_get_ethtool_stats(struct net_device *net_dev,
  5094. + struct ethtool_stats *stats,
  5095. + u64 *data)
  5096. +{
  5097. + int i = 0; /* Current index in the data array */
  5098. + int j = 0, k, err;
  5099. + union dpni_statistics dpni_stats;
  5100. +
  5101. +#ifdef CONFIG_FSL_QBMAN_DEBUG
  5102. + u32 fcnt, bcnt;
  5103. + u32 fcnt_rx_total = 0, fcnt_tx_total = 0;
  5104. + u32 bcnt_rx_total = 0, bcnt_tx_total = 0;
  5105. + u32 buf_cnt;
  5106. +#endif
  5107. + u64 cdan = 0;
  5108. + u64 portal_busy = 0, pull_err = 0;
  5109. + struct dpaa2_eth_priv *priv = netdev_priv(net_dev);
  5110. + struct dpaa2_eth_drv_stats *extras;
  5111. + struct dpaa2_eth_ch_stats *ch_stats;
  5112. +
  5113. + memset(data, 0,
  5114. + sizeof(u64) * (DPAA2_ETH_NUM_STATS + DPAA2_ETH_NUM_EXTRA_STATS));
  5115. +
  5116. + /* Print standard counters, from DPNI statistics */
  5117. + for (j = 0; j <= 2; j++) {
  5118. + err = dpni_get_statistics(priv->mc_io, 0, priv->mc_token,
  5119. + j, &dpni_stats);
  5120. + if (err != 0)
  5121. + netdev_warn(net_dev, "Err %d getting DPNI stats page %d",
  5122. + err, j);
  5123. +
  5124. + switch (j) {
  5125. + case 0:
  5126. + *(data + i++) = dpni_stats.page_0.ingress_all_frames;
  5127. + *(data + i++) = dpni_stats.page_0.ingress_all_bytes;
  5128. + *(data + i++) = dpni_stats.page_0.ingress_multicast_frames;
  5129. + *(data + i++) = dpni_stats.page_0.ingress_multicast_bytes;
  5130. + *(data + i++) = dpni_stats.page_0.ingress_broadcast_frames;
  5131. + *(data + i++) = dpni_stats.page_0.ingress_broadcast_bytes;
  5132. + break;
  5133. + case 1:
  5134. + *(data + i++) = dpni_stats.page_1.egress_all_frames;
  5135. + *(data + i++) = dpni_stats.page_1.egress_all_bytes;
  5136. + *(data + i++) = dpni_stats.page_1.egress_multicast_frames;
  5137. + *(data + i++) = dpni_stats.page_1.egress_multicast_bytes;
  5138. + *(data + i++) = dpni_stats.page_1.egress_broadcast_frames;
  5139. + *(data + i++) = dpni_stats.page_1.egress_broadcast_bytes;
  5140. + break;
  5141. + case 2:
  5142. + *(data + i++) = dpni_stats.page_2.ingress_filtered_frames;
  5143. + *(data + i++) = dpni_stats.page_2.ingress_discarded_frames;
  5144. + *(data + i++) = dpni_stats.page_2.ingress_nobuffer_discards;
  5145. + *(data + i++) = dpni_stats.page_2.egress_discarded_frames;
  5146. + *(data + i++) = dpni_stats.page_2.egress_confirmed_frames;
  5147. + break;
  5148. + default:
  5149. + break;
  5150. + }
  5151. + }
  5152. +
  5153. + /* Print per-cpu extra stats */
  5154. + for_each_online_cpu(k) {
  5155. + extras = per_cpu_ptr(priv->percpu_extras, k);
  5156. + for (j = 0; j < sizeof(*extras) / sizeof(__u64); j++)
  5157. + *((__u64 *)data + i + j) += *((__u64 *)extras + j);
  5158. + }
  5159. +
  5160. + i += j;
  5161. +
  5162. + /* We may be using fewer DPIOs than actual CPUs */
  5163. + for (j = 0; j < priv->num_channels; j++) {
  5164. + ch_stats = &priv->channel[j]->stats;
  5165. + cdan += ch_stats->cdan;
  5166. + portal_busy += ch_stats->dequeue_portal_busy;
  5167. + pull_err += ch_stats->pull_err;
  5168. + }
  5169. +
  5170. + *(data + i++) = portal_busy;
  5171. + *(data + i++) = pull_err;
  5172. + *(data + i++) = cdan;
  5173. +
  5174. + *(data + i++) = dpaa2_cscn_state_congested(priv->cscn_mem);
  5175. +
  5176. +#ifdef CONFIG_FSL_QBMAN_DEBUG
  5177. + for (j = 0; j < priv->num_fqs; j++) {
  5178. + /* Print FQ instantaneous counts */
  5179. + err = dpaa2_io_query_fq_count(NULL, priv->fq[j].fqid,
  5180. + &fcnt, &bcnt);
  5181. + if (err) {
  5182. + netdev_warn(net_dev, "FQ query error %d", err);
  5183. + return;
  5184. + }
  5185. +
  5186. + if (priv->fq[j].type == DPAA2_TX_CONF_FQ) {
  5187. + fcnt_tx_total += fcnt;
  5188. + bcnt_tx_total += bcnt;
  5189. + } else {
  5190. + fcnt_rx_total += fcnt;
  5191. + bcnt_rx_total += bcnt;
  5192. + }
  5193. + }
  5194. +
  5195. + *(data + i++) = fcnt_rx_total;
  5196. + *(data + i++) = bcnt_rx_total;
  5197. + *(data + i++) = fcnt_tx_total;
  5198. + *(data + i++) = bcnt_tx_total;
  5199. +
  5200. + err = dpaa2_io_query_bp_count(NULL, priv->bpid, &buf_cnt);
  5201. + if (err) {
  5202. + netdev_warn(net_dev, "Buffer count query error %d\n", err);
  5203. + return;
  5204. + }
  5205. + *(data + i++) = buf_cnt;
  5206. +#endif
  5207. +}
  5208. +
  5209. +static int cls_key_off(struct dpaa2_eth_priv *priv, int prot, int field)
  5210. +{
  5211. + int i, off = 0;
  5212. +
  5213. + for (i = 0; i < priv->num_hash_fields; i++) {
  5214. + if (priv->hash_fields[i].cls_prot == prot &&
  5215. + priv->hash_fields[i].cls_field == field)
  5216. + return off;
  5217. + off += priv->hash_fields[i].size;
  5218. + }
  5219. +
  5220. + return -1;
  5221. +}
  5222. +
  5223. +static u8 cls_key_size(struct dpaa2_eth_priv *priv)
  5224. +{
  5225. + u8 i, size = 0;
  5226. +
  5227. + for (i = 0; i < priv->num_hash_fields; i++)
  5228. + size += priv->hash_fields[i].size;
  5229. +
  5230. + return size;
  5231. +}
  5232. +
  5233. +void check_cls_support(struct dpaa2_eth_priv *priv)
  5234. +{
  5235. + u8 key_size = cls_key_size(priv);
  5236. + struct device *dev = priv->net_dev->dev.parent;
  5237. +
  5238. + if (dpaa2_eth_hash_enabled(priv)) {
  5239. + if (priv->dpni_attrs.fs_key_size < key_size) {
  5240. + dev_info(dev, "max_dist_key_size = %d, expected %d. Hashing and steering are disabled\n",
  5241. + priv->dpni_attrs.fs_key_size,
  5242. + key_size);
  5243. + goto disable_fs;
  5244. + }
  5245. + if (priv->num_hash_fields > DPKG_MAX_NUM_OF_EXTRACTS) {
  5246. + dev_info(dev, "Too many key fields (max = %d). Hashing and steering are disabled\n",
  5247. + DPKG_MAX_NUM_OF_EXTRACTS);
  5248. + goto disable_fs;
  5249. + }
  5250. + }
  5251. +
  5252. + if (dpaa2_eth_fs_enabled(priv)) {
  5253. + if (!dpaa2_eth_hash_enabled(priv)) {
  5254. + dev_info(dev, "Insufficient queues. Steering is disabled\n");
  5255. + goto disable_fs;
  5256. + }
  5257. +
  5258. + if (!dpaa2_eth_fs_mask_enabled(priv)) {
  5259. + dev_info(dev, "Key masks not supported. Steering is disabled\n");
  5260. + goto disable_fs;
  5261. + }
  5262. + }
  5263. +
  5264. + return;
  5265. +
  5266. +disable_fs:
  5267. + priv->dpni_attrs.options |= DPNI_OPT_NO_FS;
  5268. + priv->dpni_attrs.options &= ~DPNI_OPT_HAS_KEY_MASKING;
  5269. +}
  5270. +
  5271. +static int prep_l4_rule(struct dpaa2_eth_priv *priv,
  5272. + struct ethtool_tcpip4_spec *l4_value,
  5273. + struct ethtool_tcpip4_spec *l4_mask,
  5274. + void *key, void *mask, u8 l4_proto)
  5275. +{
  5276. + int offset;
  5277. +
  5278. + if (l4_mask->tos) {
  5279. + netdev_err(priv->net_dev, "ToS is not supported for IPv4 L4\n");
  5280. + return -EOPNOTSUPP;
  5281. + }
  5282. +
  5283. + if (l4_mask->ip4src) {
  5284. + offset = cls_key_off(priv, NET_PROT_IP, NH_FLD_IP_SRC);
  5285. + *(u32 *)(key + offset) = l4_value->ip4src;
  5286. + *(u32 *)(mask + offset) = l4_mask->ip4src;
  5287. + }
  5288. +
  5289. + if (l4_mask->ip4dst) {
  5290. + offset = cls_key_off(priv, NET_PROT_IP, NH_FLD_IP_DST);
  5291. + *(u32 *)(key + offset) = l4_value->ip4dst;
  5292. + *(u32 *)(mask + offset) = l4_mask->ip4dst;
  5293. + }
  5294. +
  5295. + if (l4_mask->psrc) {
  5296. + offset = cls_key_off(priv, NET_PROT_UDP, NH_FLD_UDP_PORT_SRC);
  5297. + *(u32 *)(key + offset) = l4_value->psrc;
  5298. + *(u32 *)(mask + offset) = l4_mask->psrc;
  5299. + }
  5300. +
  5301. + if (l4_mask->pdst) {
  5302. + offset = cls_key_off(priv, NET_PROT_UDP, NH_FLD_UDP_PORT_DST);
  5303. + *(u32 *)(key + offset) = l4_value->pdst;
  5304. + *(u32 *)(mask + offset) = l4_mask->pdst;
  5305. + }
  5306. +
  5307. + /* Only apply the rule for the user-specified L4 protocol
  5308. + * and if ethertype matches IPv4
  5309. + */
  5310. + offset = cls_key_off(priv, NET_PROT_ETH, NH_FLD_ETH_TYPE);
  5311. + *(u16 *)(key + offset) = htons(ETH_P_IP);
  5312. + *(u16 *)(mask + offset) = 0xFFFF;
  5313. +
  5314. + offset = cls_key_off(priv, NET_PROT_IP, NH_FLD_IP_PROTO);
  5315. + *(u8 *)(key + offset) = l4_proto;
  5316. + *(u8 *)(mask + offset) = 0xFF;
  5317. +
  5318. + /* TODO: check IP version */
  5319. +
  5320. + return 0;
  5321. +}
  5322. +
  5323. +static int prep_eth_rule(struct dpaa2_eth_priv *priv,
  5324. + struct ethhdr *eth_value, struct ethhdr *eth_mask,
  5325. + void *key, void *mask)
  5326. +{
  5327. + int offset;
  5328. +
  5329. + if (eth_mask->h_proto) {
  5330. + netdev_err(priv->net_dev, "Ethertype is not supported!\n");
  5331. + return -EOPNOTSUPP;
  5332. + }
  5333. +
  5334. + if (!is_zero_ether_addr(eth_mask->h_source)) {
  5335. + offset = cls_key_off(priv, NET_PROT_ETH, NH_FLD_ETH_SA);
  5336. + ether_addr_copy(key + offset, eth_value->h_source);
  5337. + ether_addr_copy(mask + offset, eth_mask->h_source);
  5338. + }
  5339. +
  5340. + if (!is_zero_ether_addr(eth_mask->h_dest)) {
  5341. + offset = cls_key_off(priv, NET_PROT_ETH, NH_FLD_ETH_DA);
  5342. + ether_addr_copy(key + offset, eth_value->h_dest);
  5343. + ether_addr_copy(mask + offset, eth_mask->h_dest);
  5344. + }
  5345. +
  5346. + return 0;
  5347. +}
  5348. +
  5349. +static int prep_user_ip_rule(struct dpaa2_eth_priv *priv,
  5350. + struct ethtool_usrip4_spec *uip_value,
  5351. + struct ethtool_usrip4_spec *uip_mask,
  5352. + void *key, void *mask)
  5353. +{
  5354. + int offset;
  5355. +
  5356. + if (uip_mask->tos)
  5357. + return -EOPNOTSUPP;
  5358. +
  5359. + if (uip_mask->ip4src) {
  5360. + offset = cls_key_off(priv, NET_PROT_IP, NH_FLD_IP_SRC);
  5361. + *(u32 *)(key + offset) = uip_value->ip4src;
  5362. + *(u32 *)(mask + offset) = uip_mask->ip4src;
  5363. + }
  5364. +
  5365. + if (uip_mask->ip4dst) {
  5366. + offset = cls_key_off(priv, NET_PROT_IP, NH_FLD_IP_DST);
  5367. + *(u32 *)(key + offset) = uip_value->ip4dst;
  5368. + *(u32 *)(mask + offset) = uip_mask->ip4dst;
  5369. + }
  5370. +
  5371. + if (uip_mask->proto) {
  5372. + offset = cls_key_off(priv, NET_PROT_IP, NH_FLD_IP_PROTO);
  5373. + *(u32 *)(key + offset) = uip_value->proto;
  5374. + *(u32 *)(mask + offset) = uip_mask->proto;
  5375. + }
  5376. + if (uip_mask->l4_4_bytes) {
  5377. + offset = cls_key_off(priv, NET_PROT_UDP, NH_FLD_UDP_PORT_SRC);
  5378. + *(u16 *)(key + offset) = uip_value->l4_4_bytes << 16;
  5379. + *(u16 *)(mask + offset) = uip_mask->l4_4_bytes << 16;
  5380. +
  5381. + offset = cls_key_off(priv, NET_PROT_UDP, NH_FLD_UDP_PORT_DST);
  5382. + *(u16 *)(key + offset) = uip_value->l4_4_bytes & 0xFFFF;
  5383. + *(u16 *)(mask + offset) = uip_mask->l4_4_bytes & 0xFFFF;
  5384. + }
  5385. +
  5386. + /* Ethertype must be IP */
  5387. + offset = cls_key_off(priv, NET_PROT_ETH, NH_FLD_ETH_TYPE);
  5388. + *(u16 *)(key + offset) = htons(ETH_P_IP);
  5389. + *(u16 *)(mask + offset) = 0xFFFF;
  5390. +
  5391. + return 0;
  5392. +}
  5393. +
  5394. +static int prep_ext_rule(struct dpaa2_eth_priv *priv,
  5395. + struct ethtool_flow_ext *ext_value,
  5396. + struct ethtool_flow_ext *ext_mask,
  5397. + void *key, void *mask)
  5398. +{
  5399. + int offset;
  5400. +
  5401. + if (ext_mask->vlan_etype)
  5402. + return -EOPNOTSUPP;
  5403. +
  5404. + if (ext_mask->vlan_tci) {
  5405. + offset = cls_key_off(priv, NET_PROT_VLAN, NH_FLD_VLAN_TCI);
  5406. + *(u16 *)(key + offset) = ext_value->vlan_tci;
  5407. + *(u16 *)(mask + offset) = ext_mask->vlan_tci;
  5408. + }
  5409. +
  5410. + return 0;
  5411. +}
  5412. +
  5413. +static int prep_mac_ext_rule(struct dpaa2_eth_priv *priv,
  5414. + struct ethtool_flow_ext *ext_value,
  5415. + struct ethtool_flow_ext *ext_mask,
  5416. + void *key, void *mask)
  5417. +{
  5418. + int offset;
  5419. +
  5420. + if (!is_zero_ether_addr(ext_mask->h_dest)) {
  5421. + offset = cls_key_off(priv, NET_PROT_ETH, NH_FLD_ETH_DA);
  5422. + ether_addr_copy(key + offset, ext_value->h_dest);
  5423. + ether_addr_copy(mask + offset, ext_mask->h_dest);
  5424. + }
  5425. +
  5426. + return 0;
  5427. +}
  5428. +
  5429. +static int prep_cls_rule(struct net_device *net_dev,
  5430. + struct ethtool_rx_flow_spec *fs,
  5431. + void *key)
  5432. +{
  5433. + struct dpaa2_eth_priv *priv = netdev_priv(net_dev);
  5434. + const u8 key_size = cls_key_size(priv);
  5435. + void *msk = key + key_size;
  5436. + int err;
  5437. +
  5438. + memset(key, 0, key_size * 2);
  5439. +
  5440. + switch (fs->flow_type & 0xff) {
  5441. + case TCP_V4_FLOW:
  5442. + err = prep_l4_rule(priv, &fs->h_u.tcp_ip4_spec,
  5443. + &fs->m_u.tcp_ip4_spec, key, msk,
  5444. + IPPROTO_TCP);
  5445. + break;
  5446. + case UDP_V4_FLOW:
  5447. + err = prep_l4_rule(priv, &fs->h_u.udp_ip4_spec,
  5448. + &fs->m_u.udp_ip4_spec, key, msk,
  5449. + IPPROTO_UDP);
  5450. + break;
  5451. + case SCTP_V4_FLOW:
  5452. + err = prep_l4_rule(priv, &fs->h_u.sctp_ip4_spec,
  5453. + &fs->m_u.sctp_ip4_spec, key, msk,
  5454. + IPPROTO_SCTP);
  5455. + break;
  5456. + case ETHER_FLOW:
  5457. + err = prep_eth_rule(priv, &fs->h_u.ether_spec,
  5458. + &fs->m_u.ether_spec, key, msk);
  5459. + break;
  5460. + case IP_USER_FLOW:
  5461. + err = prep_user_ip_rule(priv, &fs->h_u.usr_ip4_spec,
  5462. + &fs->m_u.usr_ip4_spec, key, msk);
  5463. + break;
  5464. + default:
  5465. + /* TODO: AH, ESP */
  5466. + return -EOPNOTSUPP;
  5467. + }
  5468. + if (err)
  5469. + return err;
  5470. +
  5471. + if (fs->flow_type & FLOW_EXT) {
  5472. + err = prep_ext_rule(priv, &fs->h_ext, &fs->m_ext, key, msk);
  5473. + if (err)
  5474. + return err;
  5475. + }
  5476. +
  5477. + if (fs->flow_type & FLOW_MAC_EXT) {
  5478. + err = prep_mac_ext_rule(priv, &fs->h_ext, &fs->m_ext, key, msk);
  5479. + if (err)
  5480. + return err;
  5481. + }
  5482. +
  5483. + return 0;
  5484. +}
  5485. +
  5486. +static int del_cls(struct net_device *net_dev, int location);
  5487. +
  5488. +static int do_cls(struct net_device *net_dev,
  5489. + struct ethtool_rx_flow_spec *fs,
  5490. + bool add)
  5491. +{
  5492. + struct dpaa2_eth_priv *priv = netdev_priv(net_dev);
  5493. + struct device *dev = net_dev->dev.parent;
  5494. + const int rule_cnt = dpaa2_eth_fs_count(priv);
  5495. + struct dpni_rule_cfg rule_cfg;
  5496. + struct dpni_fs_action_cfg fs_act = { 0 };
  5497. + void *dma_mem;
  5498. + int err = 0;
  5499. +
  5500. + if (!dpaa2_eth_fs_enabled(priv)) {
  5501. + netdev_err(net_dev, "dev does not support steering!\n");
  5502. + /* dev doesn't support steering */
  5503. + return -EOPNOTSUPP;
  5504. + }
  5505. +
  5506. + if ((fs->ring_cookie != RX_CLS_FLOW_DISC &&
  5507. + fs->ring_cookie >= dpaa2_eth_queue_count(priv)) ||
  5508. + fs->location >= rule_cnt)
  5509. + return -EINVAL;
  5510. +
  5511. + /* When adding a new rule, check if location if available,
  5512. + * and if not free the existing table entry before inserting
  5513. + * the new one
  5514. + */
  5515. + if (add && (priv->cls_rule[fs->location].in_use == true))
  5516. + del_cls(net_dev, fs->location);
  5517. +
  5518. + memset(&rule_cfg, 0, sizeof(rule_cfg));
  5519. + rule_cfg.key_size = cls_key_size(priv);
  5520. +
  5521. + /* allocate twice the key size, for the actual key and for mask */
  5522. + dma_mem = kzalloc(rule_cfg.key_size * 2, GFP_DMA | GFP_KERNEL);
  5523. + if (!dma_mem)
  5524. + return -ENOMEM;
  5525. +
  5526. + err = prep_cls_rule(net_dev, fs, dma_mem);
  5527. + if (err)
  5528. + goto err_free_mem;
  5529. +
  5530. + rule_cfg.key_iova = dma_map_single(dev, dma_mem,
  5531. + rule_cfg.key_size * 2,
  5532. + DMA_TO_DEVICE);
  5533. +
  5534. + rule_cfg.mask_iova = rule_cfg.key_iova + rule_cfg.key_size;
  5535. +
  5536. + if (fs->ring_cookie == RX_CLS_FLOW_DISC)
  5537. + fs_act.options |= DPNI_FS_OPT_DISCARD;
  5538. + else
  5539. + fs_act.flow_id = fs->ring_cookie;
  5540. +
  5541. + if (add)
  5542. + err = dpni_add_fs_entry(priv->mc_io, 0, priv->mc_token,
  5543. + 0, fs->location, &rule_cfg, &fs_act);
  5544. + else
  5545. + err = dpni_remove_fs_entry(priv->mc_io, 0, priv->mc_token,
  5546. + 0, &rule_cfg);
  5547. +
  5548. + dma_unmap_single(dev, rule_cfg.key_iova,
  5549. + rule_cfg.key_size * 2, DMA_TO_DEVICE);
  5550. +
  5551. + if (err)
  5552. + netdev_err(net_dev, "dpaa2_add/remove_cls() error %d\n", err);
  5553. +
  5554. +err_free_mem:
  5555. + kfree(dma_mem);
  5556. +
  5557. + return err;
  5558. +}
  5559. +
  5560. +static int add_cls(struct net_device *net_dev,
  5561. + struct ethtool_rx_flow_spec *fs)
  5562. +{
  5563. + struct dpaa2_eth_priv *priv = netdev_priv(net_dev);
  5564. + int err;
  5565. +
  5566. + err = do_cls(net_dev, fs, true);
  5567. + if (err)
  5568. + return err;
  5569. +
  5570. + priv->cls_rule[fs->location].in_use = true;
  5571. + priv->cls_rule[fs->location].fs = *fs;
  5572. +
  5573. + return 0;
  5574. +}
  5575. +
  5576. +static int del_cls(struct net_device *net_dev, int location)
  5577. +{
  5578. + struct dpaa2_eth_priv *priv = netdev_priv(net_dev);
  5579. + int err;
  5580. +
  5581. + err = do_cls(net_dev, &priv->cls_rule[location].fs, false);
  5582. + if (err)
  5583. + return err;
  5584. +
  5585. + priv->cls_rule[location].in_use = false;
  5586. +
  5587. + return 0;
  5588. +}
  5589. +
  5590. +static int dpaa2_eth_set_rxnfc(struct net_device *net_dev,
  5591. + struct ethtool_rxnfc *rxnfc)
  5592. +{
  5593. + int err = 0;
  5594. +
  5595. + switch (rxnfc->cmd) {
  5596. + case ETHTOOL_SRXCLSRLINS:
  5597. + err = add_cls(net_dev, &rxnfc->fs);
  5598. + break;
  5599. +
  5600. + case ETHTOOL_SRXCLSRLDEL:
  5601. + err = del_cls(net_dev, rxnfc->fs.location);
  5602. + break;
  5603. +
  5604. + default:
  5605. + err = -EOPNOTSUPP;
  5606. + }
  5607. +
  5608. + return err;
  5609. +}
  5610. +
  5611. +static int dpaa2_eth_get_rxnfc(struct net_device *net_dev,
  5612. + struct ethtool_rxnfc *rxnfc, u32 *rule_locs)
  5613. +{
  5614. + struct dpaa2_eth_priv *priv = netdev_priv(net_dev);
  5615. + const int rule_cnt = dpaa2_eth_fs_count(priv);
  5616. + int i, j;
  5617. +
  5618. + switch (rxnfc->cmd) {
  5619. + case ETHTOOL_GRXFH:
  5620. + /* we purposely ignore cmd->flow_type, because the hashing key
  5621. + * is the same (and fixed) for all protocols
  5622. + */
  5623. + rxnfc->data = priv->rx_flow_hash;
  5624. + break;
  5625. +
  5626. + case ETHTOOL_GRXRINGS:
  5627. + rxnfc->data = dpaa2_eth_queue_count(priv);
  5628. + break;
  5629. +
  5630. + case ETHTOOL_GRXCLSRLCNT:
  5631. + for (i = 0, rxnfc->rule_cnt = 0; i < rule_cnt; i++)
  5632. + if (priv->cls_rule[i].in_use)
  5633. + rxnfc->rule_cnt++;
  5634. + rxnfc->data = rule_cnt;
  5635. + break;
  5636. +
  5637. + case ETHTOOL_GRXCLSRULE:
  5638. + if (!priv->cls_rule[rxnfc->fs.location].in_use)
  5639. + return -EINVAL;
  5640. +
  5641. + rxnfc->fs = priv->cls_rule[rxnfc->fs.location].fs;
  5642. + break;
  5643. +
  5644. + case ETHTOOL_GRXCLSRLALL:
  5645. + for (i = 0, j = 0; i < rule_cnt; i++) {
  5646. + if (!priv->cls_rule[i].in_use)
  5647. + continue;
  5648. + if (j == rxnfc->rule_cnt)
  5649. + return -EMSGSIZE;
  5650. + rule_locs[j++] = i;
  5651. + }
  5652. + rxnfc->rule_cnt = j;
  5653. + rxnfc->data = rule_cnt;
  5654. + break;
  5655. +
  5656. + default:
  5657. + return -EOPNOTSUPP;
  5658. + }
  5659. +
  5660. + return 0;
  5661. +}
  5662. +
  5663. +const struct ethtool_ops dpaa2_ethtool_ops = {
  5664. + .get_drvinfo = dpaa2_eth_get_drvinfo,
  5665. + .get_link = ethtool_op_get_link,
  5666. + .get_settings = dpaa2_eth_get_settings,
  5667. + .set_settings = dpaa2_eth_set_settings,
  5668. + .get_pauseparam = dpaa2_eth_get_pauseparam,
  5669. + .set_pauseparam = dpaa2_eth_set_pauseparam,
  5670. + .get_sset_count = dpaa2_eth_get_sset_count,
  5671. + .get_ethtool_stats = dpaa2_eth_get_ethtool_stats,
  5672. + .get_strings = dpaa2_eth_get_strings,
  5673. + .get_rxnfc = dpaa2_eth_get_rxnfc,
  5674. + .set_rxnfc = dpaa2_eth_set_rxnfc,
  5675. +};
  5676. --- /dev/null
  5677. +++ b/drivers/staging/fsl-dpaa2/ethernet/dpkg.h
  5678. @@ -0,0 +1,176 @@
  5679. +/* Copyright 2013-2015 Freescale Semiconductor Inc.
  5680. + *
  5681. + * Redistribution and use in source and binary forms, with or without
  5682. + * modification, are permitted provided that the following conditions are met:
  5683. + * * Redistributions of source code must retain the above copyright
  5684. + * notice, this list of conditions and the following disclaimer.
  5685. + * * Redistributions in binary form must reproduce the above copyright
  5686. + * notice, this list of conditions and the following disclaimer in the
  5687. + * documentation and/or other materials provided with the distribution.
  5688. + * * Neither the name of the above-listed copyright holders nor the
  5689. + * names of any contributors may be used to endorse or promote products
  5690. + * derived from this software without specific prior written permission.
  5691. + *
  5692. + *
  5693. + * ALTERNATIVELY, this software may be distributed under the terms of the
  5694. + * GNU General Public License ("GPL") as published by the Free Software
  5695. + * Foundation, either version 2 of that License or (at your option) any
  5696. + * later version.
  5697. + *
  5698. + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  5699. + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  5700. + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  5701. + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
  5702. + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  5703. + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  5704. + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  5705. + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  5706. + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  5707. + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  5708. + * POSSIBILITY OF SUCH DAMAGE.
  5709. + */
  5710. +#ifndef __FSL_DPKG_H_
  5711. +#define __FSL_DPKG_H_
  5712. +
  5713. +#include <linux/types.h>
  5714. +#include "net.h"
  5715. +
  5716. +/* Data Path Key Generator API
  5717. + * Contains initialization APIs and runtime APIs for the Key Generator
  5718. + */
  5719. +
  5720. +/** Key Generator properties */
  5721. +
  5722. +/**
  5723. + * Number of masks per key extraction
  5724. + */
  5725. +#define DPKG_NUM_OF_MASKS 4
  5726. +/**
  5727. + * Number of extractions per key profile
  5728. + */
  5729. +#define DPKG_MAX_NUM_OF_EXTRACTS 10
  5730. +
  5731. +/**
  5732. + * enum dpkg_extract_from_hdr_type - Selecting extraction by header types
  5733. + * @DPKG_FROM_HDR: Extract selected bytes from header, by offset
  5734. + * @DPKG_FROM_FIELD: Extract selected bytes from header, by offset from field
  5735. + * @DPKG_FULL_FIELD: Extract a full field
  5736. + */
  5737. +enum dpkg_extract_from_hdr_type {
  5738. + DPKG_FROM_HDR = 0,
  5739. + DPKG_FROM_FIELD = 1,
  5740. + DPKG_FULL_FIELD = 2
  5741. +};
  5742. +
  5743. +/**
  5744. + * enum dpkg_extract_type - Enumeration for selecting extraction type
  5745. + * @DPKG_EXTRACT_FROM_HDR: Extract from the header
  5746. + * @DPKG_EXTRACT_FROM_DATA: Extract from data not in specific header
  5747. + * @DPKG_EXTRACT_FROM_PARSE: Extract from parser-result;
  5748. + * e.g. can be used to extract header existence;
  5749. + * please refer to 'Parse Result definition' section in the parser BG
  5750. + */
  5751. +enum dpkg_extract_type {
  5752. + DPKG_EXTRACT_FROM_HDR = 0,
  5753. + DPKG_EXTRACT_FROM_DATA = 1,
  5754. + DPKG_EXTRACT_FROM_PARSE = 3
  5755. +};
  5756. +
  5757. +/**
  5758. + * struct dpkg_mask - A structure for defining a single extraction mask
  5759. + * @mask: Byte mask for the extracted content
  5760. + * @offset: Offset within the extracted content
  5761. + */
  5762. +struct dpkg_mask {
  5763. + u8 mask;
  5764. + u8 offset;
  5765. +};
  5766. +
  5767. +/**
  5768. + * struct dpkg_extract - A structure for defining a single extraction
  5769. + * @type: Determines how the union below is interpreted:
  5770. + * DPKG_EXTRACT_FROM_HDR: selects 'from_hdr';
  5771. + * DPKG_EXTRACT_FROM_DATA: selects 'from_data';
  5772. + * DPKG_EXTRACT_FROM_PARSE: selects 'from_parse'
  5773. + * @extract: Selects extraction method
  5774. + * @num_of_byte_masks: Defines the number of valid entries in the array below;
  5775. + * This is also the number of bytes to be used as masks
  5776. + * @masks: Masks parameters
  5777. + */
  5778. +struct dpkg_extract {
  5779. + enum dpkg_extract_type type;
  5780. + /**
  5781. + * union extract - Selects extraction method
  5782. + * @from_hdr - Used when 'type = DPKG_EXTRACT_FROM_HDR'
  5783. + * @from_data - Used when 'type = DPKG_EXTRACT_FROM_DATA'
  5784. + * @from_parse - Used when 'type = DPKG_EXTRACT_FROM_PARSE'
  5785. + */
  5786. + union {
  5787. + /**
  5788. + * struct from_hdr - Used when 'type = DPKG_EXTRACT_FROM_HDR'
  5789. + * @prot: Any of the supported headers
  5790. + * @type: Defines the type of header extraction:
  5791. + * DPKG_FROM_HDR: use size & offset below;
  5792. + * DPKG_FROM_FIELD: use field, size and offset below;
  5793. + * DPKG_FULL_FIELD: use field below
  5794. + * @field: One of the supported fields (NH_FLD_)
  5795. + *
  5796. + * @size: Size in bytes
  5797. + * @offset: Byte offset
  5798. + * @hdr_index: Clear for cases not listed below;
  5799. + * Used for protocols that may have more than a single
  5800. + * header, 0 indicates an outer header;
  5801. + * Supported protocols (possible values):
  5802. + * NET_PROT_VLAN (0, HDR_INDEX_LAST);
  5803. + * NET_PROT_MPLS (0, 1, HDR_INDEX_LAST);
  5804. + * NET_PROT_IP(0, HDR_INDEX_LAST);
  5805. + * NET_PROT_IPv4(0, HDR_INDEX_LAST);
  5806. + * NET_PROT_IPv6(0, HDR_INDEX_LAST);
  5807. + */
  5808. +
  5809. + struct {
  5810. + enum net_prot prot;
  5811. + enum dpkg_extract_from_hdr_type type;
  5812. + u32 field;
  5813. + u8 size;
  5814. + u8 offset;
  5815. + u8 hdr_index;
  5816. + } from_hdr;
  5817. + /**
  5818. + * struct from_data - Used when 'type = DPKG_EXTRACT_FROM_DATA'
  5819. + * @size: Size in bytes
  5820. + * @offset: Byte offset
  5821. + */
  5822. + struct {
  5823. + u8 size;
  5824. + u8 offset;
  5825. + } from_data;
  5826. +
  5827. + /**
  5828. + * struct from_parse - Used when
  5829. + * 'type = DPKG_EXTRACT_FROM_PARSE'
  5830. + * @size: Size in bytes
  5831. + * @offset: Byte offset
  5832. + */
  5833. + struct {
  5834. + u8 size;
  5835. + u8 offset;
  5836. + } from_parse;
  5837. + } extract;
  5838. +
  5839. + u8 num_of_byte_masks;
  5840. + struct dpkg_mask masks[DPKG_NUM_OF_MASKS];
  5841. +};
  5842. +
  5843. +/**
  5844. + * struct dpkg_profile_cfg - A structure for defining a full Key Generation
  5845. + * profile (rule)
  5846. + * @num_extracts: Defines the number of valid entries in the array below
  5847. + * @extracts: Array of required extractions
  5848. + */
  5849. +struct dpkg_profile_cfg {
  5850. + u8 num_extracts;
  5851. + struct dpkg_extract extracts[DPKG_MAX_NUM_OF_EXTRACTS];
  5852. +};
  5853. +
  5854. +#endif /* __FSL_DPKG_H_ */
  5855. --- /dev/null
  5856. +++ b/drivers/staging/fsl-dpaa2/ethernet/dpni-cmd.h
  5857. @@ -0,0 +1,600 @@
  5858. +/* Copyright 2013-2016 Freescale Semiconductor Inc.
  5859. + * Copyright 2016 NXP
  5860. + *
  5861. + * Redistribution and use in source and binary forms, with or without
  5862. + * modification, are permitted provided that the following conditions are met:
  5863. + * * Redistributions of source code must retain the above copyright
  5864. + * notice, this list of conditions and the following disclaimer.
  5865. + * * Redistributions in binary form must reproduce the above copyright
  5866. + * notice, this list of conditions and the following disclaimer in the
  5867. + * documentation and/or other materials provided with the distribution.
  5868. + * * Neither the name of the above-listed copyright holders nor the
  5869. + * names of any contributors may be used to endorse or promote products
  5870. + * derived from this software without specific prior written permission.
  5871. + *
  5872. + *
  5873. + * ALTERNATIVELY, this software may be distributed under the terms of the
  5874. + * GNU General Public License ("GPL") as published by the Free Software
  5875. + * Foundation, either version 2 of that License or (at your option) any
  5876. + * later version.
  5877. + *
  5878. + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  5879. + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  5880. + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  5881. + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
  5882. + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  5883. + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  5884. + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  5885. + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  5886. + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  5887. + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  5888. + * POSSIBILITY OF SUCH DAMAGE.
  5889. + */
  5890. +#ifndef _FSL_DPNI_CMD_H
  5891. +#define _FSL_DPNI_CMD_H
  5892. +
  5893. +/* DPNI Version */
  5894. +#define DPNI_VER_MAJOR 7
  5895. +#define DPNI_VER_MINOR 0
  5896. +#define DPNI_CMD_BASE_VERSION 1
  5897. +#define DPNI_CMD_ID_OFFSET 4
  5898. +
  5899. +#define DPNI_CMD(id) (((id) << DPNI_CMD_ID_OFFSET) | DPNI_CMD_BASE_VERSION)
  5900. +
  5901. +#define DPNI_CMDID_OPEN DPNI_CMD(0x801)
  5902. +#define DPNI_CMDID_CLOSE DPNI_CMD(0x800)
  5903. +#define DPNI_CMDID_CREATE DPNI_CMD(0x901)
  5904. +#define DPNI_CMDID_DESTROY DPNI_CMD(0x900)
  5905. +#define DPNI_CMDID_GET_API_VERSION DPNI_CMD(0xa01)
  5906. +
  5907. +#define DPNI_CMDID_ENABLE DPNI_CMD(0x002)
  5908. +#define DPNI_CMDID_DISABLE DPNI_CMD(0x003)
  5909. +#define DPNI_CMDID_GET_ATTR DPNI_CMD(0x004)
  5910. +#define DPNI_CMDID_RESET DPNI_CMD(0x005)
  5911. +#define DPNI_CMDID_IS_ENABLED DPNI_CMD(0x006)
  5912. +
  5913. +#define DPNI_CMDID_SET_IRQ DPNI_CMD(0x010)
  5914. +#define DPNI_CMDID_GET_IRQ DPNI_CMD(0x011)
  5915. +#define DPNI_CMDID_SET_IRQ_ENABLE DPNI_CMD(0x012)
  5916. +#define DPNI_CMDID_GET_IRQ_ENABLE DPNI_CMD(0x013)
  5917. +#define DPNI_CMDID_SET_IRQ_MASK DPNI_CMD(0x014)
  5918. +#define DPNI_CMDID_GET_IRQ_MASK DPNI_CMD(0x015)
  5919. +#define DPNI_CMDID_GET_IRQ_STATUS DPNI_CMD(0x016)
  5920. +#define DPNI_CMDID_CLEAR_IRQ_STATUS DPNI_CMD(0x017)
  5921. +
  5922. +#define DPNI_CMDID_SET_POOLS DPNI_CMD(0x200)
  5923. +#define DPNI_CMDID_SET_ERRORS_BEHAVIOR DPNI_CMD(0x20B)
  5924. +
  5925. +#define DPNI_CMDID_GET_QDID DPNI_CMD(0x210)
  5926. +#define DPNI_CMDID_GET_TX_DATA_OFFSET DPNI_CMD(0x212)
  5927. +#define DPNI_CMDID_GET_LINK_STATE DPNI_CMD(0x215)
  5928. +#define DPNI_CMDID_SET_MAX_FRAME_LENGTH DPNI_CMD(0x216)
  5929. +#define DPNI_CMDID_GET_MAX_FRAME_LENGTH DPNI_CMD(0x217)
  5930. +#define DPNI_CMDID_SET_LINK_CFG DPNI_CMD(0x21A)
  5931. +#define DPNI_CMDID_SET_TX_SHAPING DPNI_CMD(0x21B)
  5932. +
  5933. +#define DPNI_CMDID_SET_MCAST_PROMISC DPNI_CMD(0x220)
  5934. +#define DPNI_CMDID_GET_MCAST_PROMISC DPNI_CMD(0x221)
  5935. +#define DPNI_CMDID_SET_UNICAST_PROMISC DPNI_CMD(0x222)
  5936. +#define DPNI_CMDID_GET_UNICAST_PROMISC DPNI_CMD(0x223)
  5937. +#define DPNI_CMDID_SET_PRIM_MAC DPNI_CMD(0x224)
  5938. +#define DPNI_CMDID_GET_PRIM_MAC DPNI_CMD(0x225)
  5939. +#define DPNI_CMDID_ADD_MAC_ADDR DPNI_CMD(0x226)
  5940. +#define DPNI_CMDID_REMOVE_MAC_ADDR DPNI_CMD(0x227)
  5941. +#define DPNI_CMDID_CLR_MAC_FILTERS DPNI_CMD(0x228)
  5942. +
  5943. +#define DPNI_CMDID_SET_RX_TC_DIST DPNI_CMD(0x235)
  5944. +
  5945. +#define DPNI_CMDID_ADD_FS_ENT DPNI_CMD(0x244)
  5946. +#define DPNI_CMDID_REMOVE_FS_ENT DPNI_CMD(0x245)
  5947. +#define DPNI_CMDID_CLR_FS_ENT DPNI_CMD(0x246)
  5948. +
  5949. +#define DPNI_CMDID_GET_STATISTICS DPNI_CMD(0x25D)
  5950. +#define DPNI_CMDID_RESET_STATISTICS DPNI_CMD(0x25E)
  5951. +#define DPNI_CMDID_GET_QUEUE DPNI_CMD(0x25F)
  5952. +#define DPNI_CMDID_SET_QUEUE DPNI_CMD(0x260)
  5953. +#define DPNI_CMDID_GET_TAILDROP DPNI_CMD(0x261)
  5954. +#define DPNI_CMDID_SET_TAILDROP DPNI_CMD(0x262)
  5955. +
  5956. +#define DPNI_CMDID_GET_PORT_MAC_ADDR DPNI_CMD(0x263)
  5957. +
  5958. +#define DPNI_CMDID_GET_BUFFER_LAYOUT DPNI_CMD(0x264)
  5959. +#define DPNI_CMDID_SET_BUFFER_LAYOUT DPNI_CMD(0x265)
  5960. +
  5961. +#define DPNI_CMDID_SET_TX_CONFIRMATION_MODE DPNI_CMD(0x266)
  5962. +#define DPNI_CMDID_SET_CONGESTION_NOTIFICATION DPNI_CMD(0x267)
  5963. +#define DPNI_CMDID_GET_CONGESTION_NOTIFICATION DPNI_CMD(0x268)
  5964. +#define DPNI_CMDID_SET_EARLY_DROP DPNI_CMD(0x269)
  5965. +#define DPNI_CMDID_GET_EARLY_DROP DPNI_CMD(0x26A)
  5966. +#define DPNI_CMDID_GET_OFFLOAD DPNI_CMD(0x26B)
  5967. +#define DPNI_CMDID_SET_OFFLOAD DPNI_CMD(0x26C)
  5968. +
  5969. +/* Macros for accessing command fields smaller than 1byte */
  5970. +#define DPNI_MASK(field) \
  5971. + GENMASK(DPNI_##field##_SHIFT + DPNI_##field##_SIZE - 1, \
  5972. + DPNI_##field##_SHIFT)
  5973. +
  5974. +#define dpni_set_field(var, field, val) \
  5975. + ((var) |= (((val) << DPNI_##field##_SHIFT) & DPNI_MASK(field)))
  5976. +#define dpni_get_field(var, field) \
  5977. + (((var) & DPNI_MASK(field)) >> DPNI_##field##_SHIFT)
  5978. +
  5979. +struct dpni_cmd_open {
  5980. + __le32 dpni_id;
  5981. +};
  5982. +
  5983. +#define DPNI_BACKUP_POOL(val, order) (((val) & 0x1) << (order))
  5984. +struct dpni_cmd_set_pools {
  5985. + /* cmd word 0 */
  5986. + u8 num_dpbp;
  5987. + u8 backup_pool_mask;
  5988. + __le16 pad;
  5989. + /* cmd word 0..4 */
  5990. + __le32 dpbp_id[DPNI_MAX_DPBP];
  5991. + /* cmd word 4..6 */
  5992. + __le16 buffer_size[DPNI_MAX_DPBP];
  5993. +};
  5994. +
  5995. +/* The enable indication is always the least significant bit */
  5996. +#define DPNI_ENABLE_SHIFT 0
  5997. +#define DPNI_ENABLE_SIZE 1
  5998. +
  5999. +struct dpni_rsp_is_enabled {
  6000. + u8 enabled;
  6001. +};
  6002. +
  6003. +struct dpni_rsp_get_irq {
  6004. + /* response word 0 */
  6005. + __le32 irq_val;
  6006. + __le32 pad;
  6007. + /* response word 1 */
  6008. + __le64 irq_addr;
  6009. + /* response word 2 */
  6010. + __le32 irq_num;
  6011. + __le32 type;
  6012. +};
  6013. +
  6014. +struct dpni_cmd_set_irq_enable {
  6015. + u8 enable;
  6016. + u8 pad[3];
  6017. + u8 irq_index;
  6018. +};
  6019. +
  6020. +struct dpni_cmd_get_irq_enable {
  6021. + __le32 pad;
  6022. + u8 irq_index;
  6023. +};
  6024. +
  6025. +struct dpni_rsp_get_irq_enable {
  6026. + u8 enabled;
  6027. +};
  6028. +
  6029. +struct dpni_cmd_set_irq_mask {
  6030. + __le32 mask;
  6031. + u8 irq_index;
  6032. +};
  6033. +
  6034. +struct dpni_cmd_get_irq_mask {
  6035. + __le32 pad;
  6036. + u8 irq_index;
  6037. +};
  6038. +
  6039. +struct dpni_rsp_get_irq_mask {
  6040. + __le32 mask;
  6041. +};
  6042. +
  6043. +struct dpni_cmd_get_irq_status {
  6044. + __le32 status;
  6045. + u8 irq_index;
  6046. +};
  6047. +
  6048. +struct dpni_rsp_get_irq_status {
  6049. + __le32 status;
  6050. +};
  6051. +
  6052. +struct dpni_cmd_clear_irq_status {
  6053. + __le32 status;
  6054. + u8 irq_index;
  6055. +};
  6056. +
  6057. +struct dpni_rsp_get_attr {
  6058. + /* response word 0 */
  6059. + __le32 options;
  6060. + u8 num_queues;
  6061. + u8 num_tcs;
  6062. + u8 mac_filter_entries;
  6063. + u8 pad0;
  6064. + /* response word 1 */
  6065. + u8 vlan_filter_entries;
  6066. + u8 pad1;
  6067. + u8 qos_entries;
  6068. + u8 pad2;
  6069. + __le16 fs_entries;
  6070. + __le16 pad3;
  6071. + /* response word 2 */
  6072. + u8 qos_key_size;
  6073. + u8 fs_key_size;
  6074. + __le16 wriop_version;
  6075. +};
  6076. +
  6077. +#define DPNI_ERROR_ACTION_SHIFT 0
  6078. +#define DPNI_ERROR_ACTION_SIZE 4
  6079. +#define DPNI_FRAME_ANN_SHIFT 4
  6080. +#define DPNI_FRAME_ANN_SIZE 1
  6081. +
  6082. +struct dpni_cmd_set_errors_behavior {
  6083. + __le32 errors;
  6084. + /* from least significant bit: error_action:4, set_frame_annotation:1 */
  6085. + u8 flags;
  6086. +};
  6087. +
  6088. +/* There are 3 separate commands for configuring Rx, Tx and Tx confirmation
  6089. + * buffer layouts, but they all share the same parameters.
  6090. + * If one of the functions changes, below structure needs to be split.
  6091. + */
  6092. +
  6093. +#define DPNI_PASS_TS_SHIFT 0
  6094. +#define DPNI_PASS_TS_SIZE 1
  6095. +#define DPNI_PASS_PR_SHIFT 1
  6096. +#define DPNI_PASS_PR_SIZE 1
  6097. +#define DPNI_PASS_FS_SHIFT 2
  6098. +#define DPNI_PASS_FS_SIZE 1
  6099. +
  6100. +struct dpni_cmd_get_buffer_layout {
  6101. + u8 qtype;
  6102. +};
  6103. +
  6104. +struct dpni_rsp_get_buffer_layout {
  6105. + /* response word 0 */
  6106. + u8 pad0[6];
  6107. + /* from LSB: pass_timestamp:1, parser_result:1, frame_status:1 */
  6108. + u8 flags;
  6109. + u8 pad1;
  6110. + /* response word 1 */
  6111. + __le16 private_data_size;
  6112. + __le16 data_align;
  6113. + __le16 head_room;
  6114. + __le16 tail_room;
  6115. +};
  6116. +
  6117. +struct dpni_cmd_set_buffer_layout {
  6118. + /* cmd word 0 */
  6119. + u8 qtype;
  6120. + u8 pad0[3];
  6121. + __le16 options;
  6122. + /* from LSB: pass_timestamp:1, parser_result:1, frame_status:1 */
  6123. + u8 flags;
  6124. + u8 pad1;
  6125. + /* cmd word 1 */
  6126. + __le16 private_data_size;
  6127. + __le16 data_align;
  6128. + __le16 head_room;
  6129. + __le16 tail_room;
  6130. +};
  6131. +
  6132. +struct dpni_cmd_set_offload {
  6133. + u8 pad[3];
  6134. + u8 dpni_offload;
  6135. + __le32 config;
  6136. +};
  6137. +
  6138. +struct dpni_cmd_get_offload {
  6139. + u8 pad[3];
  6140. + u8 dpni_offload;
  6141. +};
  6142. +
  6143. +struct dpni_rsp_get_offload {
  6144. + __le32 pad;
  6145. + __le32 config;
  6146. +};
  6147. +
  6148. +struct dpni_cmd_get_qdid {
  6149. + u8 qtype;
  6150. +};
  6151. +
  6152. +struct dpni_rsp_get_qdid {
  6153. + __le16 qdid;
  6154. +};
  6155. +
  6156. +struct dpni_rsp_get_tx_data_offset {
  6157. + __le16 data_offset;
  6158. +};
  6159. +
  6160. +struct dpni_cmd_get_statistics {
  6161. + u8 page_number;
  6162. +};
  6163. +
  6164. +struct dpni_rsp_get_statistics {
  6165. + __le64 counter[DPNI_STATISTICS_CNT];
  6166. +};
  6167. +
  6168. +struct dpni_cmd_set_link_cfg {
  6169. + /* cmd word 0 */
  6170. + __le64 pad0;
  6171. + /* cmd word 1 */
  6172. + __le32 rate;
  6173. + __le32 pad1;
  6174. + /* cmd word 2 */
  6175. + __le64 options;
  6176. +};
  6177. +
  6178. +#define DPNI_LINK_STATE_SHIFT 0
  6179. +#define DPNI_LINK_STATE_SIZE 1
  6180. +
  6181. +struct dpni_rsp_get_link_state {
  6182. + /* response word 0 */
  6183. + __le32 pad0;
  6184. + /* from LSB: up:1 */
  6185. + u8 flags;
  6186. + u8 pad1[3];
  6187. + /* response word 1 */
  6188. + __le32 rate;
  6189. + __le32 pad2;
  6190. + /* response word 2 */
  6191. + __le64 options;
  6192. +};
  6193. +
  6194. +struct dpni_cmd_set_tx_shaping {
  6195. + /* cmd word 0 */
  6196. + __le16 max_burst_size;
  6197. + __le16 pad0[3];
  6198. + /* cmd word 1 */
  6199. + __le32 rate_limit;
  6200. +};
  6201. +
  6202. +struct dpni_cmd_set_max_frame_length {
  6203. + __le16 max_frame_length;
  6204. +};
  6205. +
  6206. +struct dpni_rsp_get_max_frame_length {
  6207. + __le16 max_frame_length;
  6208. +};
  6209. +
  6210. +struct dpni_cmd_set_multicast_promisc {
  6211. + u8 enable;
  6212. +};
  6213. +
  6214. +struct dpni_rsp_get_multicast_promisc {
  6215. + u8 enabled;
  6216. +};
  6217. +
  6218. +struct dpni_cmd_set_unicast_promisc {
  6219. + u8 enable;
  6220. +};
  6221. +
  6222. +struct dpni_rsp_get_unicast_promisc {
  6223. + u8 enabled;
  6224. +};
  6225. +
  6226. +struct dpni_cmd_set_primary_mac_addr {
  6227. + __le16 pad;
  6228. + u8 mac_addr[6];
  6229. +};
  6230. +
  6231. +struct dpni_rsp_get_primary_mac_addr {
  6232. + __le16 pad;
  6233. + u8 mac_addr[6];
  6234. +};
  6235. +
  6236. +struct dpni_rsp_get_port_mac_addr {
  6237. + __le16 pad;
  6238. + u8 mac_addr[6];
  6239. +};
  6240. +
  6241. +struct dpni_cmd_add_mac_addr {
  6242. + __le16 pad;
  6243. + u8 mac_addr[6];
  6244. +};
  6245. +
  6246. +struct dpni_cmd_remove_mac_addr {
  6247. + __le16 pad;
  6248. + u8 mac_addr[6];
  6249. +};
  6250. +
  6251. +#define DPNI_UNICAST_FILTERS_SHIFT 0
  6252. +#define DPNI_UNICAST_FILTERS_SIZE 1
  6253. +#define DPNI_MULTICAST_FILTERS_SHIFT 1
  6254. +#define DPNI_MULTICAST_FILTERS_SIZE 1
  6255. +
  6256. +struct dpni_cmd_clear_mac_filters {
  6257. + /* from LSB: unicast:1, multicast:1 */
  6258. + u8 flags;
  6259. +};
  6260. +
  6261. +#define DPNI_DIST_MODE_SHIFT 0
  6262. +#define DPNI_DIST_MODE_SIZE 4
  6263. +#define DPNI_MISS_ACTION_SHIFT 4
  6264. +#define DPNI_MISS_ACTION_SIZE 4
  6265. +
  6266. +struct dpni_cmd_set_rx_tc_dist {
  6267. + /* cmd word 0 */
  6268. + __le16 dist_size;
  6269. + u8 tc_id;
  6270. + /* from LSB: dist_mode:4, miss_action:4 */
  6271. + u8 flags;
  6272. + __le16 pad0;
  6273. + __le16 default_flow_id;
  6274. + /* cmd word 1..5 */
  6275. + __le64 pad1[5];
  6276. + /* cmd word 6 */
  6277. + __le64 key_cfg_iova;
  6278. +};
  6279. +
  6280. +/* dpni_set_rx_tc_dist extension (structure of the DMA-able memory at
  6281. + * key_cfg_iova)
  6282. + */
  6283. +struct dpni_mask_cfg {
  6284. + u8 mask;
  6285. + u8 offset;
  6286. +};
  6287. +
  6288. +#define DPNI_EFH_TYPE_SHIFT 0
  6289. +#define DPNI_EFH_TYPE_SIZE 4
  6290. +#define DPNI_EXTRACT_TYPE_SHIFT 0
  6291. +#define DPNI_EXTRACT_TYPE_SIZE 4
  6292. +
  6293. +struct dpni_dist_extract {
  6294. + /* word 0 */
  6295. + u8 prot;
  6296. + /* EFH type stored in the 4 least significant bits */
  6297. + u8 efh_type;
  6298. + u8 size;
  6299. + u8 offset;
  6300. + __le32 field;
  6301. + /* word 1 */
  6302. + u8 hdr_index;
  6303. + u8 constant;
  6304. + u8 num_of_repeats;
  6305. + u8 num_of_byte_masks;
  6306. + /* Extraction type is stored in the 4 LSBs */
  6307. + u8 extract_type;
  6308. + u8 pad[3];
  6309. + /* word 2 */
  6310. + struct dpni_mask_cfg masks[4];
  6311. +};
  6312. +
  6313. +struct dpni_ext_set_rx_tc_dist {
  6314. + /* extension word 0 */
  6315. + u8 num_extracts;
  6316. + u8 pad[7];
  6317. + /* words 1..25 */
  6318. + struct dpni_dist_extract extracts[DPKG_MAX_NUM_OF_EXTRACTS];
  6319. +};
  6320. +
  6321. +struct dpni_cmd_get_queue {
  6322. + u8 qtype;
  6323. + u8 tc;
  6324. + u8 index;
  6325. +};
  6326. +
  6327. +#define DPNI_DEST_TYPE_SHIFT 0
  6328. +#define DPNI_DEST_TYPE_SIZE 4
  6329. +#define DPNI_STASH_CTRL_SHIFT 6
  6330. +#define DPNI_STASH_CTRL_SIZE 1
  6331. +#define DPNI_HOLD_ACTIVE_SHIFT 7
  6332. +#define DPNI_HOLD_ACTIVE_SIZE 1
  6333. +
  6334. +struct dpni_rsp_get_queue {
  6335. + /* response word 0 */
  6336. + __le64 pad0;
  6337. + /* response word 1 */
  6338. + __le32 dest_id;
  6339. + __le16 pad1;
  6340. + u8 dest_prio;
  6341. + /* From LSB: dest_type:4, pad:2, flc_stash_ctrl:1, hold_active:1 */
  6342. + u8 flags;
  6343. + /* response word 2 */
  6344. + __le64 flc;
  6345. + /* response word 3 */
  6346. + __le64 user_context;
  6347. + /* response word 4 */
  6348. + __le32 fqid;
  6349. + __le16 qdbin;
  6350. +};
  6351. +
  6352. +struct dpni_cmd_set_queue {
  6353. + /* cmd word 0 */
  6354. + u8 qtype;
  6355. + u8 tc;
  6356. + u8 index;
  6357. + u8 options;
  6358. + __le32 pad0;
  6359. + /* cmd word 1 */
  6360. + __le32 dest_id;
  6361. + __le16 pad1;
  6362. + u8 dest_prio;
  6363. + u8 flags;
  6364. + /* cmd word 2 */
  6365. + __le64 flc;
  6366. + /* cmd word 3 */
  6367. + __le64 user_context;
  6368. +};
  6369. +
  6370. +struct dpni_cmd_add_fs_entry {
  6371. + /* cmd word 0 */
  6372. + u16 options;
  6373. + u8 tc_id;
  6374. + u8 key_size;
  6375. + u16 index;
  6376. + u16 flow_id;
  6377. + /* cmd word 1 */
  6378. + u64 key_iova;
  6379. + /* cmd word 2 */
  6380. + u64 mask_iova;
  6381. + /* cmd word 3 */
  6382. + u64 flc;
  6383. +};
  6384. +
  6385. +struct dpni_cmd_remove_fs_entry {
  6386. + /* cmd word 0 */
  6387. + __le16 pad0;
  6388. + u8 tc_id;
  6389. + u8 key_size;
  6390. + __le32 pad1;
  6391. + /* cmd word 1 */
  6392. + u64 key_iova;
  6393. + /* cmd word 2 */
  6394. + u64 mask_iova;
  6395. +};
  6396. +
  6397. +struct dpni_cmd_set_taildrop {
  6398. + /* cmd word 0 */
  6399. + u8 congestion_point;
  6400. + u8 qtype;
  6401. + u8 tc;
  6402. + u8 index;
  6403. + __le32 pad0;
  6404. + /* cmd word 1 */
  6405. + /* Only least significant bit is relevant */
  6406. + u8 enable;
  6407. + u8 pad1;
  6408. + u8 units;
  6409. + u8 pad2;
  6410. + __le32 threshold;
  6411. +};
  6412. +
  6413. +struct dpni_cmd_get_taildrop {
  6414. + u8 congestion_point;
  6415. + u8 qtype;
  6416. + u8 tc;
  6417. + u8 index;
  6418. +};
  6419. +
  6420. +struct dpni_rsp_get_taildrop {
  6421. + /* cmd word 0 */
  6422. + __le64 pad0;
  6423. + /* cmd word 1 */
  6424. + /* only least significant bit is relevant */
  6425. + u8 enable;
  6426. + u8 pad1;
  6427. + u8 units;
  6428. + u8 pad2;
  6429. + __le32 threshold;
  6430. +};
  6431. +
  6432. +#define DPNI_DEST_TYPE_SHIFT 0
  6433. +#define DPNI_DEST_TYPE_SIZE 4
  6434. +#define DPNI_CONG_UNITS_SHIFT 4
  6435. +#define DPNI_CONG_UNITS_SIZE 2
  6436. +
  6437. +struct dpni_cmd_set_congestion_notification {
  6438. + /* cmd word 0 */
  6439. + u8 qtype;
  6440. + u8 tc;
  6441. + u8 pad[6];
  6442. + /* cmd word 1 */
  6443. + u32 dest_id;
  6444. + u16 notification_mode;
  6445. + u8 dest_priority;
  6446. + /* from LSB: dest_type: 4 units:2 */
  6447. + u8 type_units;
  6448. + /* cmd word 2 */
  6449. + u64 message_iova;
  6450. + /* cmd word 3 */
  6451. + u64 message_ctx;
  6452. + /* cmd word 4 */
  6453. + u32 threshold_entry;
  6454. + u32 threshold_exit;
  6455. +};
  6456. +
  6457. +#endif /* _FSL_DPNI_CMD_H */
  6458. --- /dev/null
  6459. +++ b/drivers/staging/fsl-dpaa2/ethernet/dpni.c
  6460. @@ -0,0 +1,1770 @@
  6461. +/* Copyright 2013-2016 Freescale Semiconductor Inc.
  6462. + * Copyright 2016 NXP
  6463. + *
  6464. + * Redistribution and use in source and binary forms, with or without
  6465. + * modification, are permitted provided that the following conditions are met:
  6466. + * * Redistributions of source code must retain the above copyright
  6467. + * notice, this list of conditions and the following disclaimer.
  6468. + * * Redistributions in binary form must reproduce the above copyright
  6469. + * notice, this list of conditions and the following disclaimer in the
  6470. + * documentation and/or other materials provided with the distribution.
  6471. + * * Neither the name of the above-listed copyright holders nor the
  6472. + * names of any contributors may be used to endorse or promote products
  6473. + * derived from this software without specific prior written permission.
  6474. + *
  6475. + *
  6476. + * ALTERNATIVELY, this software may be distributed under the terms of the
  6477. + * GNU General Public License ("GPL") as published by the Free Software
  6478. + * Foundation, either version 2 of that License or (at your option) any
  6479. + * later version.
  6480. + *
  6481. + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  6482. + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  6483. + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  6484. + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
  6485. + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  6486. + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  6487. + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  6488. + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  6489. + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  6490. + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  6491. + * POSSIBILITY OF SUCH DAMAGE.
  6492. + */
  6493. +#include "../../fsl-mc/include/mc-sys.h"
  6494. +#include "../../fsl-mc/include/mc-cmd.h"
  6495. +#include "dpni.h"
  6496. +#include "dpni-cmd.h"
  6497. +
  6498. +/**
  6499. + * dpni_prepare_key_cfg() - function prepare extract parameters
  6500. + * @cfg: defining a full Key Generation profile (rule)
  6501. + * @key_cfg_buf: Zeroed 256 bytes of memory before mapping it to DMA
  6502. + *
  6503. + * This function has to be called before the following functions:
  6504. + * - dpni_set_rx_tc_dist()
  6505. + * - dpni_set_qos_table()
  6506. + */
  6507. +int dpni_prepare_key_cfg(const struct dpkg_profile_cfg *cfg, u8 *key_cfg_buf)
  6508. +{
  6509. + int i, j;
  6510. + struct dpni_ext_set_rx_tc_dist *dpni_ext;
  6511. + struct dpni_dist_extract *extr;
  6512. +
  6513. + if (cfg->num_extracts > DPKG_MAX_NUM_OF_EXTRACTS)
  6514. + return -EINVAL;
  6515. +
  6516. + dpni_ext = (struct dpni_ext_set_rx_tc_dist *)key_cfg_buf;
  6517. + dpni_ext->num_extracts = cfg->num_extracts;
  6518. +
  6519. + for (i = 0; i < cfg->num_extracts; i++) {
  6520. + extr = &dpni_ext->extracts[i];
  6521. +
  6522. + switch (cfg->extracts[i].type) {
  6523. + case DPKG_EXTRACT_FROM_HDR:
  6524. + extr->prot = cfg->extracts[i].extract.from_hdr.prot;
  6525. + dpni_set_field(extr->efh_type, EFH_TYPE,
  6526. + cfg->extracts[i].extract.from_hdr.type);
  6527. + extr->size = cfg->extracts[i].extract.from_hdr.size;
  6528. + extr->offset = cfg->extracts[i].extract.from_hdr.offset;
  6529. + extr->field = cpu_to_le32(
  6530. + cfg->extracts[i].extract.from_hdr.field);
  6531. + extr->hdr_index =
  6532. + cfg->extracts[i].extract.from_hdr.hdr_index;
  6533. + break;
  6534. + case DPKG_EXTRACT_FROM_DATA:
  6535. + extr->size = cfg->extracts[i].extract.from_data.size;
  6536. + extr->offset =
  6537. + cfg->extracts[i].extract.from_data.offset;
  6538. + break;
  6539. + case DPKG_EXTRACT_FROM_PARSE:
  6540. + extr->size = cfg->extracts[i].extract.from_parse.size;
  6541. + extr->offset =
  6542. + cfg->extracts[i].extract.from_parse.offset;
  6543. + break;
  6544. + default:
  6545. + return -EINVAL;
  6546. + }
  6547. +
  6548. + extr->num_of_byte_masks = cfg->extracts[i].num_of_byte_masks;
  6549. + dpni_set_field(extr->extract_type, EXTRACT_TYPE,
  6550. + cfg->extracts[i].type);
  6551. +
  6552. + for (j = 0; j < DPKG_NUM_OF_MASKS; j++) {
  6553. + extr->masks[j].mask = cfg->extracts[i].masks[j].mask;
  6554. + extr->masks[j].offset =
  6555. + cfg->extracts[i].masks[j].offset;
  6556. + }
  6557. + }
  6558. +
  6559. + return 0;
  6560. +}
  6561. +
  6562. +/**
  6563. + * dpni_open() - Open a control session for the specified object
  6564. + * @mc_io: Pointer to MC portal's I/O object
  6565. + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
  6566. + * @dpni_id: DPNI unique ID
  6567. + * @token: Returned token; use in subsequent API calls
  6568. + *
  6569. + * This function can be used to open a control session for an
  6570. + * already created object; an object may have been declared in
  6571. + * the DPL or by calling the dpni_create() function.
  6572. + * This function returns a unique authentication token,
  6573. + * associated with the specific object ID and the specific MC
  6574. + * portal; this token must be used in all subsequent commands for
  6575. + * this specific object.
  6576. + *
  6577. + * Return: '0' on Success; Error code otherwise.
  6578. + */
  6579. +int dpni_open(struct fsl_mc_io *mc_io,
  6580. + u32 cmd_flags,
  6581. + int dpni_id,
  6582. + u16 *token)
  6583. +{
  6584. + struct mc_command cmd = { 0 };
  6585. + struct dpni_cmd_open *cmd_params;
  6586. +
  6587. + int err;
  6588. +
  6589. + /* prepare command */
  6590. + cmd.header = mc_encode_cmd_header(DPNI_CMDID_OPEN,
  6591. + cmd_flags,
  6592. + 0);
  6593. + cmd_params = (struct dpni_cmd_open *)cmd.params;
  6594. + cmd_params->dpni_id = cpu_to_le32(dpni_id);
  6595. +
  6596. + /* send command to mc*/
  6597. + err = mc_send_command(mc_io, &cmd);
  6598. + if (err)
  6599. + return err;
  6600. +
  6601. + /* retrieve response parameters */
  6602. + *token = mc_cmd_hdr_read_token(&cmd);
  6603. +
  6604. + return 0;
  6605. +}
  6606. +
  6607. +/**
  6608. + * dpni_close() - Close the control session of the object
  6609. + * @mc_io: Pointer to MC portal's I/O object
  6610. + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
  6611. + * @token: Token of DPNI object
  6612. + *
  6613. + * After this function is called, no further operations are
  6614. + * allowed on the object without opening a new control session.
  6615. + *
  6616. + * Return: '0' on Success; Error code otherwise.
  6617. + */
  6618. +int dpni_close(struct fsl_mc_io *mc_io,
  6619. + u32 cmd_flags,
  6620. + u16 token)
  6621. +{
  6622. + struct mc_command cmd = { 0 };
  6623. +
  6624. + /* prepare command */
  6625. + cmd.header = mc_encode_cmd_header(DPNI_CMDID_CLOSE,
  6626. + cmd_flags,
  6627. + token);
  6628. +
  6629. + /* send command to mc*/
  6630. + return mc_send_command(mc_io, &cmd);
  6631. +}
  6632. +
  6633. +/**
  6634. + * dpni_set_pools() - Set buffer pools configuration
  6635. + * @mc_io: Pointer to MC portal's I/O object
  6636. + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
  6637. + * @token: Token of DPNI object
  6638. + * @cfg: Buffer pools configuration
  6639. + *
  6640. + * mandatory for DPNI operation
  6641. + * warning:Allowed only when DPNI is disabled
  6642. + *
  6643. + * Return: '0' on Success; Error code otherwise.
  6644. + */
  6645. +int dpni_set_pools(struct fsl_mc_io *mc_io,
  6646. + u32 cmd_flags,
  6647. + u16 token,
  6648. + const struct dpni_pools_cfg *cfg)
  6649. +{
  6650. + struct mc_command cmd = { 0 };
  6651. + struct dpni_cmd_set_pools *cmd_params;
  6652. + int i;
  6653. +
  6654. + /* prepare command */
  6655. + cmd.header = mc_encode_cmd_header(DPNI_CMDID_SET_POOLS,
  6656. + cmd_flags,
  6657. + token);
  6658. + cmd_params = (struct dpni_cmd_set_pools *)cmd.params;
  6659. + cmd_params->num_dpbp = cfg->num_dpbp;
  6660. + for (i = 0; i < DPNI_MAX_DPBP; i++) {
  6661. + cmd_params->dpbp_id[i] = cpu_to_le32(cfg->pools[i].dpbp_id);
  6662. + cmd_params->buffer_size[i] =
  6663. + cpu_to_le16(cfg->pools[i].buffer_size);
  6664. + cmd_params->backup_pool_mask |=
  6665. + DPNI_BACKUP_POOL(cfg->pools[i].backup_pool, i);
  6666. + }
  6667. +
  6668. + /* send command to mc*/
  6669. + return mc_send_command(mc_io, &cmd);
  6670. +}
  6671. +
  6672. +/**
  6673. + * dpni_enable() - Enable the DPNI, allow sending and receiving frames.
  6674. + * @mc_io: Pointer to MC portal's I/O object
  6675. + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
  6676. + * @token: Token of DPNI object
  6677. + *
  6678. + * Return: '0' on Success; Error code otherwise.
  6679. + */
  6680. +int dpni_enable(struct fsl_mc_io *mc_io,
  6681. + u32 cmd_flags,
  6682. + u16 token)
  6683. +{
  6684. + struct mc_command cmd = { 0 };
  6685. +
  6686. + /* prepare command */
  6687. + cmd.header = mc_encode_cmd_header(DPNI_CMDID_ENABLE,
  6688. + cmd_flags,
  6689. + token);
  6690. +
  6691. + /* send command to mc*/
  6692. + return mc_send_command(mc_io, &cmd);
  6693. +}
  6694. +
  6695. +/**
  6696. + * dpni_disable() - Disable the DPNI, stop sending and receiving frames.
  6697. + * @mc_io: Pointer to MC portal's I/O object
  6698. + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
  6699. + * @token: Token of DPNI object
  6700. + *
  6701. + * Return: '0' on Success; Error code otherwise.
  6702. + */
  6703. +int dpni_disable(struct fsl_mc_io *mc_io,
  6704. + u32 cmd_flags,
  6705. + u16 token)
  6706. +{
  6707. + struct mc_command cmd = { 0 };
  6708. +
  6709. + /* prepare command */
  6710. + cmd.header = mc_encode_cmd_header(DPNI_CMDID_DISABLE,
  6711. + cmd_flags,
  6712. + token);
  6713. +
  6714. + /* send command to mc*/
  6715. + return mc_send_command(mc_io, &cmd);
  6716. +}
  6717. +
  6718. +/**
  6719. + * dpni_is_enabled() - Check if the DPNI is enabled.
  6720. + * @mc_io: Pointer to MC portal's I/O object
  6721. + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
  6722. + * @token: Token of DPNI object
  6723. + * @en: Returns '1' if object is enabled; '0' otherwise
  6724. + *
  6725. + * Return: '0' on Success; Error code otherwise.
  6726. + */
  6727. +int dpni_is_enabled(struct fsl_mc_io *mc_io,
  6728. + u32 cmd_flags,
  6729. + u16 token,
  6730. + int *en)
  6731. +{
  6732. + struct mc_command cmd = { 0 };
  6733. + struct dpni_rsp_is_enabled *rsp_params;
  6734. + int err;
  6735. +
  6736. + /* prepare command */
  6737. + cmd.header = mc_encode_cmd_header(DPNI_CMDID_IS_ENABLED,
  6738. + cmd_flags,
  6739. + token);
  6740. +
  6741. + /* send command to mc*/
  6742. + err = mc_send_command(mc_io, &cmd);
  6743. + if (err)
  6744. + return err;
  6745. +
  6746. + /* retrieve response parameters */
  6747. + rsp_params = (struct dpni_rsp_is_enabled *)cmd.params;
  6748. + *en = dpni_get_field(rsp_params->enabled, ENABLE);
  6749. +
  6750. + return 0;
  6751. +}
  6752. +
  6753. +/**
  6754. + * dpni_reset() - Reset the DPNI, returns the object to initial state.
  6755. + * @mc_io: Pointer to MC portal's I/O object
  6756. + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
  6757. + * @token: Token of DPNI object
  6758. + *
  6759. + * Return: '0' on Success; Error code otherwise.
  6760. + */
  6761. +int dpni_reset(struct fsl_mc_io *mc_io,
  6762. + u32 cmd_flags,
  6763. + u16 token)
  6764. +{
  6765. + struct mc_command cmd = { 0 };
  6766. +
  6767. + /* prepare command */
  6768. + cmd.header = mc_encode_cmd_header(DPNI_CMDID_RESET,
  6769. + cmd_flags,
  6770. + token);
  6771. +
  6772. + /* send command to mc*/
  6773. + return mc_send_command(mc_io, &cmd);
  6774. +}
  6775. +
  6776. +/**
  6777. + * dpni_set_irq_enable() - Set overall interrupt state.
  6778. + * @mc_io: Pointer to MC portal's I/O object
  6779. + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
  6780. + * @token: Token of DPNI object
  6781. + * @irq_index: The interrupt index to configure
  6782. + * @en: Interrupt state: - enable = 1, disable = 0
  6783. + *
  6784. + * Allows GPP software to control when interrupts are generated.
  6785. + * Each interrupt can have up to 32 causes. The enable/disable control's the
  6786. + * overall interrupt state. if the interrupt is disabled no causes will cause
  6787. + * an interrupt.
  6788. + *
  6789. + * Return: '0' on Success; Error code otherwise.
  6790. + */
  6791. +int dpni_set_irq_enable(struct fsl_mc_io *mc_io,
  6792. + u32 cmd_flags,
  6793. + u16 token,
  6794. + u8 irq_index,
  6795. + u8 en)
  6796. +{
  6797. + struct mc_command cmd = { 0 };
  6798. + struct dpni_cmd_set_irq_enable *cmd_params;
  6799. +
  6800. + /* prepare command */
  6801. + cmd.header = mc_encode_cmd_header(DPNI_CMDID_SET_IRQ_ENABLE,
  6802. + cmd_flags,
  6803. + token);
  6804. + cmd_params = (struct dpni_cmd_set_irq_enable *)cmd.params;
  6805. + dpni_set_field(cmd_params->enable, ENABLE, en);
  6806. + cmd_params->irq_index = irq_index;
  6807. +
  6808. + /* send command to mc*/
  6809. + return mc_send_command(mc_io, &cmd);
  6810. +}
  6811. +
  6812. +/**
  6813. + * dpni_get_irq_enable() - Get overall interrupt state
  6814. + * @mc_io: Pointer to MC portal's I/O object
  6815. + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
  6816. + * @token: Token of DPNI object
  6817. + * @irq_index: The interrupt index to configure
  6818. + * @en: Returned interrupt state - enable = 1, disable = 0
  6819. + *
  6820. + * Return: '0' on Success; Error code otherwise.
  6821. + */
  6822. +int dpni_get_irq_enable(struct fsl_mc_io *mc_io,
  6823. + u32 cmd_flags,
  6824. + u16 token,
  6825. + u8 irq_index,
  6826. + u8 *en)
  6827. +{
  6828. + struct mc_command cmd = { 0 };
  6829. + struct dpni_cmd_get_irq_enable *cmd_params;
  6830. + struct dpni_rsp_get_irq_enable *rsp_params;
  6831. +
  6832. + int err;
  6833. +
  6834. + /* prepare command */
  6835. + cmd.header = mc_encode_cmd_header(DPNI_CMDID_GET_IRQ_ENABLE,
  6836. + cmd_flags,
  6837. + token);
  6838. + cmd_params = (struct dpni_cmd_get_irq_enable *)cmd.params;
  6839. + cmd_params->irq_index = irq_index;
  6840. +
  6841. + /* send command to mc*/
  6842. + err = mc_send_command(mc_io, &cmd);
  6843. + if (err)
  6844. + return err;
  6845. +
  6846. + /* retrieve response parameters */
  6847. + rsp_params = (struct dpni_rsp_get_irq_enable *)cmd.params;
  6848. + *en = dpni_get_field(rsp_params->enabled, ENABLE);
  6849. +
  6850. + return 0;
  6851. +}
  6852. +
  6853. +/**
  6854. + * dpni_set_irq_mask() - Set interrupt mask.
  6855. + * @mc_io: Pointer to MC portal's I/O object
  6856. + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
  6857. + * @token: Token of DPNI object
  6858. + * @irq_index: The interrupt index to configure
  6859. + * @mask: event mask to trigger interrupt;
  6860. + * each bit:
  6861. + * 0 = ignore event
  6862. + * 1 = consider event for asserting IRQ
  6863. + *
  6864. + * Every interrupt can have up to 32 causes and the interrupt model supports
  6865. + * masking/unmasking each cause independently
  6866. + *
  6867. + * Return: '0' on Success; Error code otherwise.
  6868. + */
  6869. +int dpni_set_irq_mask(struct fsl_mc_io *mc_io,
  6870. + u32 cmd_flags,
  6871. + u16 token,
  6872. + u8 irq_index,
  6873. + u32 mask)
  6874. +{
  6875. + struct mc_command cmd = { 0 };
  6876. + struct dpni_cmd_set_irq_mask *cmd_params;
  6877. +
  6878. + /* prepare command */
  6879. + cmd.header = mc_encode_cmd_header(DPNI_CMDID_SET_IRQ_MASK,
  6880. + cmd_flags,
  6881. + token);
  6882. + cmd_params = (struct dpni_cmd_set_irq_mask *)cmd.params;
  6883. + cmd_params->mask = cpu_to_le32(mask);
  6884. + cmd_params->irq_index = irq_index;
  6885. +
  6886. + /* send command to mc*/
  6887. + return mc_send_command(mc_io, &cmd);
  6888. +}
  6889. +
  6890. +/**
  6891. + * dpni_get_irq_mask() - Get interrupt mask.
  6892. + * @mc_io: Pointer to MC portal's I/O object
  6893. + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
  6894. + * @token: Token of DPNI object
  6895. + * @irq_index: The interrupt index to configure
  6896. + * @mask: Returned event mask to trigger interrupt
  6897. + *
  6898. + * Every interrupt can have up to 32 causes and the interrupt model supports
  6899. + * masking/unmasking each cause independently
  6900. + *
  6901. + * Return: '0' on Success; Error code otherwise.
  6902. + */
  6903. +int dpni_get_irq_mask(struct fsl_mc_io *mc_io,
  6904. + u32 cmd_flags,
  6905. + u16 token,
  6906. + u8 irq_index,
  6907. + u32 *mask)
  6908. +{
  6909. + struct mc_command cmd = { 0 };
  6910. + struct dpni_cmd_get_irq_mask *cmd_params;
  6911. + struct dpni_rsp_get_irq_mask *rsp_params;
  6912. + int err;
  6913. +
  6914. + /* prepare command */
  6915. + cmd.header = mc_encode_cmd_header(DPNI_CMDID_GET_IRQ_MASK,
  6916. + cmd_flags,
  6917. + token);
  6918. + cmd_params = (struct dpni_cmd_get_irq_mask *)cmd.params;
  6919. + cmd_params->irq_index = irq_index;
  6920. +
  6921. + /* send command to mc*/
  6922. + err = mc_send_command(mc_io, &cmd);
  6923. + if (err)
  6924. + return err;
  6925. +
  6926. + /* retrieve response parameters */
  6927. + rsp_params = (struct dpni_rsp_get_irq_mask *)cmd.params;
  6928. + *mask = le32_to_cpu(rsp_params->mask);
  6929. +
  6930. + return 0;
  6931. +}
  6932. +
  6933. +/**
  6934. + * dpni_get_irq_status() - Get the current status of any pending interrupts.
  6935. + * @mc_io: Pointer to MC portal's I/O object
  6936. + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
  6937. + * @token: Token of DPNI object
  6938. + * @irq_index: The interrupt index to configure
  6939. + * @status: Returned interrupts status - one bit per cause:
  6940. + * 0 = no interrupt pending
  6941. + * 1 = interrupt pending
  6942. + *
  6943. + * Return: '0' on Success; Error code otherwise.
  6944. + */
  6945. +int dpni_get_irq_status(struct fsl_mc_io *mc_io,
  6946. + u32 cmd_flags,
  6947. + u16 token,
  6948. + u8 irq_index,
  6949. + u32 *status)
  6950. +{
  6951. + struct mc_command cmd = { 0 };
  6952. + struct dpni_cmd_get_irq_status *cmd_params;
  6953. + struct dpni_rsp_get_irq_status *rsp_params;
  6954. + int err;
  6955. +
  6956. + /* prepare command */
  6957. + cmd.header = mc_encode_cmd_header(DPNI_CMDID_GET_IRQ_STATUS,
  6958. + cmd_flags,
  6959. + token);
  6960. + cmd_params = (struct dpni_cmd_get_irq_status *)cmd.params;
  6961. + cmd_params->status = cpu_to_le32(*status);
  6962. + cmd_params->irq_index = irq_index;
  6963. +
  6964. + /* send command to mc*/
  6965. + err = mc_send_command(mc_io, &cmd);
  6966. + if (err)
  6967. + return err;
  6968. +
  6969. + /* retrieve response parameters */
  6970. + rsp_params = (struct dpni_rsp_get_irq_status *)cmd.params;
  6971. + *status = le32_to_cpu(rsp_params->status);
  6972. +
  6973. + return 0;
  6974. +}
  6975. +
  6976. +/**
  6977. + * dpni_clear_irq_status() - Clear a pending interrupt's status
  6978. + * @mc_io: Pointer to MC portal's I/O object
  6979. + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
  6980. + * @token: Token of DPNI object
  6981. + * @irq_index: The interrupt index to configure
  6982. + * @status: bits to clear (W1C) - one bit per cause:
  6983. + * 0 = don't change
  6984. + * 1 = clear status bit
  6985. + *
  6986. + * Return: '0' on Success; Error code otherwise.
  6987. + */
  6988. +int dpni_clear_irq_status(struct fsl_mc_io *mc_io,
  6989. + u32 cmd_flags,
  6990. + u16 token,
  6991. + u8 irq_index,
  6992. + u32 status)
  6993. +{
  6994. + struct mc_command cmd = { 0 };
  6995. + struct dpni_cmd_clear_irq_status *cmd_params;
  6996. +
  6997. + /* prepare command */
  6998. + cmd.header = mc_encode_cmd_header(DPNI_CMDID_CLEAR_IRQ_STATUS,
  6999. + cmd_flags,
  7000. + token);
  7001. + cmd_params = (struct dpni_cmd_clear_irq_status *)cmd.params;
  7002. + cmd_params->irq_index = irq_index;
  7003. + cmd_params->status = cpu_to_le32(status);
  7004. +
  7005. + /* send command to mc*/
  7006. + return mc_send_command(mc_io, &cmd);
  7007. +}
  7008. +
  7009. +/**
  7010. + * dpni_get_attributes() - Retrieve DPNI attributes.
  7011. + * @mc_io: Pointer to MC portal's I/O object
  7012. + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
  7013. + * @token: Token of DPNI object
  7014. + * @attr: Object's attributes
  7015. + *
  7016. + * Return: '0' on Success; Error code otherwise.
  7017. + */
  7018. +int dpni_get_attributes(struct fsl_mc_io *mc_io,
  7019. + u32 cmd_flags,
  7020. + u16 token,
  7021. + struct dpni_attr *attr)
  7022. +{
  7023. + struct mc_command cmd = { 0 };
  7024. + struct dpni_rsp_get_attr *rsp_params;
  7025. +
  7026. + int err;
  7027. +
  7028. + /* prepare command */
  7029. + cmd.header = mc_encode_cmd_header(DPNI_CMDID_GET_ATTR,
  7030. + cmd_flags,
  7031. + token);
  7032. +
  7033. + /* send command to mc*/
  7034. + err = mc_send_command(mc_io, &cmd);
  7035. + if (err)
  7036. + return err;
  7037. +
  7038. + /* retrieve response parameters */
  7039. + rsp_params = (struct dpni_rsp_get_attr *)cmd.params;
  7040. + attr->options = le32_to_cpu(rsp_params->options);
  7041. + attr->num_queues = rsp_params->num_queues;
  7042. + attr->num_tcs = rsp_params->num_tcs;
  7043. + attr->mac_filter_entries = rsp_params->mac_filter_entries;
  7044. + attr->vlan_filter_entries = rsp_params->vlan_filter_entries;
  7045. + attr->qos_entries = rsp_params->qos_entries;
  7046. + attr->fs_entries = le16_to_cpu(rsp_params->fs_entries);
  7047. + attr->qos_key_size = rsp_params->qos_key_size;
  7048. + attr->fs_key_size = rsp_params->fs_key_size;
  7049. + attr->wriop_version = le16_to_cpu(rsp_params->wriop_version);
  7050. +
  7051. + return 0;
  7052. +}
  7053. +
  7054. +/**
  7055. + * dpni_set_errors_behavior() - Set errors behavior
  7056. + * @mc_io: Pointer to MC portal's I/O object
  7057. + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
  7058. + * @token: Token of DPNI object
  7059. + * @cfg: Errors configuration
  7060. + *
  7061. + * this function may be called numerous times with different
  7062. + * error masks
  7063. + *
  7064. + * Return: '0' on Success; Error code otherwise.
  7065. + */
  7066. +int dpni_set_errors_behavior(struct fsl_mc_io *mc_io,
  7067. + u32 cmd_flags,
  7068. + u16 token,
  7069. + struct dpni_error_cfg *cfg)
  7070. +{
  7071. + struct mc_command cmd = { 0 };
  7072. + struct dpni_cmd_set_errors_behavior *cmd_params;
  7073. +
  7074. + /* prepare command */
  7075. + cmd.header = mc_encode_cmd_header(DPNI_CMDID_SET_ERRORS_BEHAVIOR,
  7076. + cmd_flags,
  7077. + token);
  7078. + cmd_params = (struct dpni_cmd_set_errors_behavior *)cmd.params;
  7079. + cmd_params->errors = cpu_to_le32(cfg->errors);
  7080. + dpni_set_field(cmd_params->flags, ERROR_ACTION, cfg->error_action);
  7081. + dpni_set_field(cmd_params->flags, FRAME_ANN, cfg->set_frame_annotation);
  7082. +
  7083. + /* send command to mc*/
  7084. + return mc_send_command(mc_io, &cmd);
  7085. +}
  7086. +
  7087. +/**
  7088. + * dpni_get_buffer_layout() - Retrieve buffer layout attributes.
  7089. + * @mc_io: Pointer to MC portal's I/O object
  7090. + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
  7091. + * @token: Token of DPNI object
  7092. + * @qtype: Type of queue to retrieve configuration for
  7093. + * @layout: Returns buffer layout attributes
  7094. + *
  7095. + * Return: '0' on Success; Error code otherwise.
  7096. + */
  7097. +int dpni_get_buffer_layout(struct fsl_mc_io *mc_io,
  7098. + u32 cmd_flags,
  7099. + u16 token,
  7100. + enum dpni_queue_type qtype,
  7101. + struct dpni_buffer_layout *layout)
  7102. +{
  7103. + struct mc_command cmd = { 0 };
  7104. + struct dpni_cmd_get_buffer_layout *cmd_params;
  7105. + struct dpni_rsp_get_buffer_layout *rsp_params;
  7106. + int err;
  7107. +
  7108. + /* prepare command */
  7109. + cmd.header = mc_encode_cmd_header(DPNI_CMDID_GET_BUFFER_LAYOUT,
  7110. + cmd_flags,
  7111. + token);
  7112. + cmd_params = (struct dpni_cmd_get_buffer_layout *)cmd.params;
  7113. + cmd_params->qtype = qtype;
  7114. +
  7115. + /* send command to mc*/
  7116. + err = mc_send_command(mc_io, &cmd);
  7117. + if (err)
  7118. + return err;
  7119. +
  7120. + /* retrieve response parameters */
  7121. + rsp_params = (struct dpni_rsp_get_buffer_layout *)cmd.params;
  7122. + layout->pass_timestamp = dpni_get_field(rsp_params->flags, PASS_TS);
  7123. + layout->pass_parser_result = dpni_get_field(rsp_params->flags, PASS_PR);
  7124. + layout->pass_frame_status = dpni_get_field(rsp_params->flags, PASS_FS);
  7125. + layout->private_data_size = le16_to_cpu(rsp_params->private_data_size);
  7126. + layout->data_align = le16_to_cpu(rsp_params->data_align);
  7127. + layout->data_head_room = le16_to_cpu(rsp_params->head_room);
  7128. + layout->data_tail_room = le16_to_cpu(rsp_params->tail_room);
  7129. +
  7130. + return 0;
  7131. +}
  7132. +
  7133. +/**
  7134. + * dpni_set_buffer_layout() - Set buffer layout configuration.
  7135. + * @mc_io: Pointer to MC portal's I/O object
  7136. + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
  7137. + * @token: Token of DPNI object
  7138. + * @qtype: Type of queue this configuration applies to
  7139. + * @layout: Buffer layout configuration
  7140. + *
  7141. + * Return: '0' on Success; Error code otherwise.
  7142. + *
  7143. + * @warning Allowed only when DPNI is disabled
  7144. + */
  7145. +int dpni_set_buffer_layout(struct fsl_mc_io *mc_io,
  7146. + u32 cmd_flags,
  7147. + u16 token,
  7148. + enum dpni_queue_type qtype,
  7149. + const struct dpni_buffer_layout *layout)
  7150. +{
  7151. + struct mc_command cmd = { 0 };
  7152. + struct dpni_cmd_set_buffer_layout *cmd_params;
  7153. +
  7154. + /* prepare command */
  7155. + cmd.header = mc_encode_cmd_header(DPNI_CMDID_SET_BUFFER_LAYOUT,
  7156. + cmd_flags,
  7157. + token);
  7158. + cmd_params = (struct dpni_cmd_set_buffer_layout *)cmd.params;
  7159. + cmd_params->qtype = qtype;
  7160. + cmd_params->options = cpu_to_le16(layout->options);
  7161. + dpni_set_field(cmd_params->flags, PASS_TS, layout->pass_timestamp);
  7162. + dpni_set_field(cmd_params->flags, PASS_PR, layout->pass_parser_result);
  7163. + dpni_set_field(cmd_params->flags, PASS_FS, layout->pass_frame_status);
  7164. + cmd_params->private_data_size = cpu_to_le16(layout->private_data_size);
  7165. + cmd_params->data_align = cpu_to_le16(layout->data_align);
  7166. + cmd_params->head_room = cpu_to_le16(layout->data_head_room);
  7167. + cmd_params->tail_room = cpu_to_le16(layout->data_tail_room);
  7168. +
  7169. + /* send command to mc*/
  7170. + return mc_send_command(mc_io, &cmd);
  7171. +}
  7172. +
  7173. +/**
  7174. + * dpni_set_offload() - Set DPNI offload configuration.
  7175. + * @mc_io: Pointer to MC portal's I/O object
  7176. + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
  7177. + * @token: Token of DPNI object
  7178. + * @type: Type of DPNI offload
  7179. + * @config: Offload configuration.
  7180. + * For checksum offloads, non-zero value enables the offload
  7181. + *
  7182. + * Return: '0' on Success; Error code otherwise.
  7183. + *
  7184. + * @warning Allowed only when DPNI is disabled
  7185. + */
  7186. +
  7187. +int dpni_set_offload(struct fsl_mc_io *mc_io,
  7188. + u32 cmd_flags,
  7189. + u16 token,
  7190. + enum dpni_offload type,
  7191. + u32 config)
  7192. +{
  7193. + struct mc_command cmd = { 0 };
  7194. + struct dpni_cmd_set_offload *cmd_params;
  7195. +
  7196. + cmd.header = mc_encode_cmd_header(DPNI_CMDID_SET_OFFLOAD,
  7197. + cmd_flags,
  7198. + token);
  7199. + cmd_params = (struct dpni_cmd_set_offload *)cmd.params;
  7200. + cmd_params->dpni_offload = type;
  7201. + cmd_params->config = cpu_to_le32(config);
  7202. +
  7203. + return mc_send_command(mc_io, &cmd);
  7204. +}
  7205. +
  7206. +int dpni_get_offload(struct fsl_mc_io *mc_io,
  7207. + u32 cmd_flags,
  7208. + u16 token,
  7209. + enum dpni_offload type,
  7210. + u32 *config)
  7211. +{
  7212. + struct mc_command cmd = { 0 };
  7213. + struct dpni_cmd_get_offload *cmd_params;
  7214. + struct dpni_rsp_get_offload *rsp_params;
  7215. + int err;
  7216. +
  7217. + /* prepare command */
  7218. + cmd.header = mc_encode_cmd_header(DPNI_CMDID_GET_OFFLOAD,
  7219. + cmd_flags,
  7220. + token);
  7221. + cmd_params = (struct dpni_cmd_get_offload *)cmd.params;
  7222. + cmd_params->dpni_offload = type;
  7223. +
  7224. + /* send command to mc*/
  7225. + err = mc_send_command(mc_io, &cmd);
  7226. + if (err)
  7227. + return err;
  7228. +
  7229. + /* retrieve response parameters */
  7230. + rsp_params = (struct dpni_rsp_get_offload *)cmd.params;
  7231. + *config = le32_to_cpu(rsp_params->config);
  7232. +
  7233. + return 0;
  7234. +}
  7235. +
  7236. +/**
  7237. + * dpni_get_qdid() - Get the Queuing Destination ID (QDID) that should be used
  7238. + * for enqueue operations
  7239. + * @mc_io: Pointer to MC portal's I/O object
  7240. + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
  7241. + * @token: Token of DPNI object
  7242. + * @qtype: Type of queue to receive QDID for
  7243. + * @qdid: Returned virtual QDID value that should be used as an argument
  7244. + * in all enqueue operations
  7245. + *
  7246. + * Return: '0' on Success; Error code otherwise.
  7247. + */
  7248. +int dpni_get_qdid(struct fsl_mc_io *mc_io,
  7249. + u32 cmd_flags,
  7250. + u16 token,
  7251. + enum dpni_queue_type qtype,
  7252. + u16 *qdid)
  7253. +{
  7254. + struct mc_command cmd = { 0 };
  7255. + struct dpni_cmd_get_qdid *cmd_params;
  7256. + struct dpni_rsp_get_qdid *rsp_params;
  7257. + int err;
  7258. +
  7259. + /* prepare command */
  7260. + cmd.header = mc_encode_cmd_header(DPNI_CMDID_GET_QDID,
  7261. + cmd_flags,
  7262. + token);
  7263. + cmd_params = (struct dpni_cmd_get_qdid *)cmd.params;
  7264. + cmd_params->qtype = qtype;
  7265. +
  7266. + /* send command to mc*/
  7267. + err = mc_send_command(mc_io, &cmd);
  7268. + if (err)
  7269. + return err;
  7270. +
  7271. + /* retrieve response parameters */
  7272. + rsp_params = (struct dpni_rsp_get_qdid *)cmd.params;
  7273. + *qdid = le16_to_cpu(rsp_params->qdid);
  7274. +
  7275. + return 0;
  7276. +}
  7277. +
  7278. +/**
  7279. + * dpni_get_tx_data_offset() - Get the Tx data offset (from start of buffer)
  7280. + * @mc_io: Pointer to MC portal's I/O object
  7281. + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
  7282. + * @token: Token of DPNI object
  7283. + * @data_offset: Tx data offset (from start of buffer)
  7284. + *
  7285. + * Return: '0' on Success; Error code otherwise.
  7286. + */
  7287. +int dpni_get_tx_data_offset(struct fsl_mc_io *mc_io,
  7288. + u32 cmd_flags,
  7289. + u16 token,
  7290. + u16 *data_offset)
  7291. +{
  7292. + struct mc_command cmd = { 0 };
  7293. + struct dpni_rsp_get_tx_data_offset *rsp_params;
  7294. + int err;
  7295. +
  7296. + /* prepare command */
  7297. + cmd.header = mc_encode_cmd_header(DPNI_CMDID_GET_TX_DATA_OFFSET,
  7298. + cmd_flags,
  7299. + token);
  7300. +
  7301. + /* send command to mc*/
  7302. + err = mc_send_command(mc_io, &cmd);
  7303. + if (err)
  7304. + return err;
  7305. +
  7306. + /* retrieve response parameters */
  7307. + rsp_params = (struct dpni_rsp_get_tx_data_offset *)cmd.params;
  7308. + *data_offset = le16_to_cpu(rsp_params->data_offset);
  7309. +
  7310. + return 0;
  7311. +}
  7312. +
  7313. +/**
  7314. + * dpni_set_link_cfg() - set the link configuration.
  7315. + * @mc_io: Pointer to MC portal's I/O object
  7316. + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
  7317. + * @token: Token of DPNI object
  7318. + * @cfg: Link configuration
  7319. + *
  7320. + * Return: '0' on Success; Error code otherwise.
  7321. + */
  7322. +int dpni_set_link_cfg(struct fsl_mc_io *mc_io,
  7323. + u32 cmd_flags,
  7324. + u16 token,
  7325. + const struct dpni_link_cfg *cfg)
  7326. +{
  7327. + struct mc_command cmd = { 0 };
  7328. + struct dpni_cmd_set_link_cfg *cmd_params;
  7329. +
  7330. + /* prepare command */
  7331. + cmd.header = mc_encode_cmd_header(DPNI_CMDID_SET_LINK_CFG,
  7332. + cmd_flags,
  7333. + token);
  7334. + cmd_params = (struct dpni_cmd_set_link_cfg *)cmd.params;
  7335. + cmd_params->rate = cpu_to_le32(cfg->rate);
  7336. + cmd_params->options = cpu_to_le64(cfg->options);
  7337. +
  7338. + /* send command to mc*/
  7339. + return mc_send_command(mc_io, &cmd);
  7340. +}
  7341. +
  7342. +/**
  7343. + * dpni_get_link_state() - Return the link state (either up or down)
  7344. + * @mc_io: Pointer to MC portal's I/O object
  7345. + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
  7346. + * @token: Token of DPNI object
  7347. + * @state: Returned link state;
  7348. + *
  7349. + * Return: '0' on Success; Error code otherwise.
  7350. + */
  7351. +int dpni_get_link_state(struct fsl_mc_io *mc_io,
  7352. + u32 cmd_flags,
  7353. + u16 token,
  7354. + struct dpni_link_state *state)
  7355. +{
  7356. + struct mc_command cmd = { 0 };
  7357. + struct dpni_rsp_get_link_state *rsp_params;
  7358. + int err;
  7359. +
  7360. + /* prepare command */
  7361. + cmd.header = mc_encode_cmd_header(DPNI_CMDID_GET_LINK_STATE,
  7362. + cmd_flags,
  7363. + token);
  7364. +
  7365. + /* send command to mc*/
  7366. + err = mc_send_command(mc_io, &cmd);
  7367. + if (err)
  7368. + return err;
  7369. +
  7370. + /* retrieve response parameters */
  7371. + rsp_params = (struct dpni_rsp_get_link_state *)cmd.params;
  7372. + state->up = dpni_get_field(rsp_params->flags, LINK_STATE);
  7373. + state->rate = le32_to_cpu(rsp_params->rate);
  7374. + state->options = le64_to_cpu(rsp_params->options);
  7375. +
  7376. + return 0;
  7377. +}
  7378. +
  7379. +/**
  7380. + * dpni_set_tx_shaping() - Set the transmit shaping
  7381. + * @mc_io: Pointer to MC portal's I/O object
  7382. + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
  7383. + * @token: Token of DPNI object
  7384. + * @tx_shaper: tx shaping configuration
  7385. + *
  7386. + * Return: '0' on Success; Error code otherwise.
  7387. + */
  7388. +int dpni_set_tx_shaping(struct fsl_mc_io *mc_io,
  7389. + u32 cmd_flags,
  7390. + u16 token,
  7391. + const struct dpni_tx_shaping_cfg *tx_shaper)
  7392. +{
  7393. + struct mc_command cmd = { 0 };
  7394. + struct dpni_cmd_set_tx_shaping *cmd_params;
  7395. +
  7396. + /* prepare command */
  7397. + cmd.header = mc_encode_cmd_header(DPNI_CMDID_SET_TX_SHAPING,
  7398. + cmd_flags,
  7399. + token);
  7400. + cmd_params = (struct dpni_cmd_set_tx_shaping *)cmd.params;
  7401. + cmd_params->max_burst_size = cpu_to_le16(tx_shaper->max_burst_size);
  7402. + cmd_params->rate_limit = cpu_to_le32(tx_shaper->rate_limit);
  7403. +
  7404. + /* send command to mc*/
  7405. + return mc_send_command(mc_io, &cmd);
  7406. +}
  7407. +
  7408. +/**
  7409. + * dpni_set_max_frame_length() - Set the maximum received frame length.
  7410. + * @mc_io: Pointer to MC portal's I/O object
  7411. + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
  7412. + * @token: Token of DPNI object
  7413. + * @max_frame_length: Maximum received frame length (in
  7414. + * bytes); frame is discarded if its
  7415. + * length exceeds this value
  7416. + *
  7417. + * Return: '0' on Success; Error code otherwise.
  7418. + */
  7419. +int dpni_set_max_frame_length(struct fsl_mc_io *mc_io,
  7420. + u32 cmd_flags,
  7421. + u16 token,
  7422. + u16 max_frame_length)
  7423. +{
  7424. + struct mc_command cmd = { 0 };
  7425. + struct dpni_cmd_set_max_frame_length *cmd_params;
  7426. +
  7427. + /* prepare command */
  7428. + cmd.header = mc_encode_cmd_header(DPNI_CMDID_SET_MAX_FRAME_LENGTH,
  7429. + cmd_flags,
  7430. + token);
  7431. + cmd_params = (struct dpni_cmd_set_max_frame_length *)cmd.params;
  7432. + cmd_params->max_frame_length = cpu_to_le16(max_frame_length);
  7433. +
  7434. + /* send command to mc*/
  7435. + return mc_send_command(mc_io, &cmd);
  7436. +}
  7437. +
  7438. +/**
  7439. + * dpni_get_max_frame_length() - Get the maximum received frame length.
  7440. + * @mc_io: Pointer to MC portal's I/O object
  7441. + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
  7442. + * @token: Token of DPNI object
  7443. + * @max_frame_length: Maximum received frame length (in
  7444. + * bytes); frame is discarded if its
  7445. + * length exceeds this value
  7446. + *
  7447. + * Return: '0' on Success; Error code otherwise.
  7448. + */
  7449. +int dpni_get_max_frame_length(struct fsl_mc_io *mc_io,
  7450. + u32 cmd_flags,
  7451. + u16 token,
  7452. + u16 *max_frame_length)
  7453. +{
  7454. + struct mc_command cmd = { 0 };
  7455. + struct dpni_rsp_get_max_frame_length *rsp_params;
  7456. + int err;
  7457. +
  7458. + /* prepare command */
  7459. + cmd.header = mc_encode_cmd_header(DPNI_CMDID_GET_MAX_FRAME_LENGTH,
  7460. + cmd_flags,
  7461. + token);
  7462. +
  7463. + /* send command to mc*/
  7464. + err = mc_send_command(mc_io, &cmd);
  7465. + if (err)
  7466. + return err;
  7467. +
  7468. + /* retrieve response parameters */
  7469. + rsp_params = (struct dpni_rsp_get_max_frame_length *)cmd.params;
  7470. + *max_frame_length = le16_to_cpu(rsp_params->max_frame_length);
  7471. +
  7472. + return 0;
  7473. +}
  7474. +
  7475. +/**
  7476. + * dpni_set_multicast_promisc() - Enable/disable multicast promiscuous mode
  7477. + * @mc_io: Pointer to MC portal's I/O object
  7478. + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
  7479. + * @token: Token of DPNI object
  7480. + * @en: Set to '1' to enable; '0' to disable
  7481. + *
  7482. + * Return: '0' on Success; Error code otherwise.
  7483. + */
  7484. +int dpni_set_multicast_promisc(struct fsl_mc_io *mc_io,
  7485. + u32 cmd_flags,
  7486. + u16 token,
  7487. + int en)
  7488. +{
  7489. + struct mc_command cmd = { 0 };
  7490. + struct dpni_cmd_set_multicast_promisc *cmd_params;
  7491. +
  7492. + /* prepare command */
  7493. + cmd.header = mc_encode_cmd_header(DPNI_CMDID_SET_MCAST_PROMISC,
  7494. + cmd_flags,
  7495. + token);
  7496. + cmd_params = (struct dpni_cmd_set_multicast_promisc *)cmd.params;
  7497. + dpni_set_field(cmd_params->enable, ENABLE, en);
  7498. +
  7499. + /* send command to mc*/
  7500. + return mc_send_command(mc_io, &cmd);
  7501. +}
  7502. +
  7503. +/**
  7504. + * dpni_get_multicast_promisc() - Get multicast promiscuous mode
  7505. + * @mc_io: Pointer to MC portal's I/O object
  7506. + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
  7507. + * @token: Token of DPNI object
  7508. + * @en: Returns '1' if enabled; '0' otherwise
  7509. + *
  7510. + * Return: '0' on Success; Error code otherwise.
  7511. + */
  7512. +int dpni_get_multicast_promisc(struct fsl_mc_io *mc_io,
  7513. + u32 cmd_flags,
  7514. + u16 token,
  7515. + int *en)
  7516. +{
  7517. + struct mc_command cmd = { 0 };
  7518. + struct dpni_rsp_get_multicast_promisc *rsp_params;
  7519. + int err;
  7520. +
  7521. + /* prepare command */
  7522. + cmd.header = mc_encode_cmd_header(DPNI_CMDID_GET_MCAST_PROMISC,
  7523. + cmd_flags,
  7524. + token);
  7525. +
  7526. + /* send command to mc*/
  7527. + err = mc_send_command(mc_io, &cmd);
  7528. + if (err)
  7529. + return err;
  7530. +
  7531. + /* retrieve response parameters */
  7532. + rsp_params = (struct dpni_rsp_get_multicast_promisc *)cmd.params;
  7533. + *en = dpni_get_field(rsp_params->enabled, ENABLE);
  7534. +
  7535. + return 0;
  7536. +}
  7537. +
  7538. +/**
  7539. + * dpni_set_unicast_promisc() - Enable/disable unicast promiscuous mode
  7540. + * @mc_io: Pointer to MC portal's I/O object
  7541. + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
  7542. + * @token: Token of DPNI object
  7543. + * @en: Set to '1' to enable; '0' to disable
  7544. + *
  7545. + * Return: '0' on Success; Error code otherwise.
  7546. + */
  7547. +int dpni_set_unicast_promisc(struct fsl_mc_io *mc_io,
  7548. + u32 cmd_flags,
  7549. + u16 token,
  7550. + int en)
  7551. +{
  7552. + struct mc_command cmd = { 0 };
  7553. + struct dpni_cmd_set_unicast_promisc *cmd_params;
  7554. +
  7555. + /* prepare command */
  7556. + cmd.header = mc_encode_cmd_header(DPNI_CMDID_SET_UNICAST_PROMISC,
  7557. + cmd_flags,
  7558. + token);
  7559. + cmd_params = (struct dpni_cmd_set_unicast_promisc *)cmd.params;
  7560. + dpni_set_field(cmd_params->enable, ENABLE, en);
  7561. +
  7562. + /* send command to mc*/
  7563. + return mc_send_command(mc_io, &cmd);
  7564. +}
  7565. +
  7566. +/**
  7567. + * dpni_get_unicast_promisc() - Get unicast promiscuous mode
  7568. + * @mc_io: Pointer to MC portal's I/O object
  7569. + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
  7570. + * @token: Token of DPNI object
  7571. + * @en: Returns '1' if enabled; '0' otherwise
  7572. + *
  7573. + * Return: '0' on Success; Error code otherwise.
  7574. + */
  7575. +int dpni_get_unicast_promisc(struct fsl_mc_io *mc_io,
  7576. + u32 cmd_flags,
  7577. + u16 token,
  7578. + int *en)
  7579. +{
  7580. + struct mc_command cmd = { 0 };
  7581. + struct dpni_rsp_get_unicast_promisc *rsp_params;
  7582. + int err;
  7583. +
  7584. + /* prepare command */
  7585. + cmd.header = mc_encode_cmd_header(DPNI_CMDID_GET_UNICAST_PROMISC,
  7586. + cmd_flags,
  7587. + token);
  7588. +
  7589. + /* send command to mc*/
  7590. + err = mc_send_command(mc_io, &cmd);
  7591. + if (err)
  7592. + return err;
  7593. +
  7594. + /* retrieve response parameters */
  7595. + rsp_params = (struct dpni_rsp_get_unicast_promisc *)cmd.params;
  7596. + *en = dpni_get_field(rsp_params->enabled, ENABLE);
  7597. +
  7598. + return 0;
  7599. +}
  7600. +
  7601. +/**
  7602. + * dpni_set_primary_mac_addr() - Set the primary MAC address
  7603. + * @mc_io: Pointer to MC portal's I/O object
  7604. + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
  7605. + * @token: Token of DPNI object
  7606. + * @mac_addr: MAC address to set as primary address
  7607. + *
  7608. + * Return: '0' on Success; Error code otherwise.
  7609. + */
  7610. +int dpni_set_primary_mac_addr(struct fsl_mc_io *mc_io,
  7611. + u32 cmd_flags,
  7612. + u16 token,
  7613. + const u8 mac_addr[6])
  7614. +{
  7615. + struct mc_command cmd = { 0 };
  7616. + struct dpni_cmd_set_primary_mac_addr *cmd_params;
  7617. + int i;
  7618. +
  7619. + /* prepare command */
  7620. + cmd.header = mc_encode_cmd_header(DPNI_CMDID_SET_PRIM_MAC,
  7621. + cmd_flags,
  7622. + token);
  7623. + cmd_params = (struct dpni_cmd_set_primary_mac_addr *)cmd.params;
  7624. + for (i = 0; i < 6; i++)
  7625. + cmd_params->mac_addr[i] = mac_addr[5 - i];
  7626. +
  7627. + /* send command to mc*/
  7628. + return mc_send_command(mc_io, &cmd);
  7629. +}
  7630. +
  7631. +/**
  7632. + * dpni_get_primary_mac_addr() - Get the primary MAC address
  7633. + * @mc_io: Pointer to MC portal's I/O object
  7634. + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
  7635. + * @token: Token of DPNI object
  7636. + * @mac_addr: Returned MAC address
  7637. + *
  7638. + * Return: '0' on Success; Error code otherwise.
  7639. + */
  7640. +int dpni_get_primary_mac_addr(struct fsl_mc_io *mc_io,
  7641. + u32 cmd_flags,
  7642. + u16 token,
  7643. + u8 mac_addr[6])
  7644. +{
  7645. + struct mc_command cmd = { 0 };
  7646. + struct dpni_rsp_get_primary_mac_addr *rsp_params;
  7647. + int i, err;
  7648. +
  7649. + /* prepare command */
  7650. + cmd.header = mc_encode_cmd_header(DPNI_CMDID_GET_PRIM_MAC,
  7651. + cmd_flags,
  7652. + token);
  7653. +
  7654. + /* send command to mc*/
  7655. + err = mc_send_command(mc_io, &cmd);
  7656. + if (err)
  7657. + return err;
  7658. +
  7659. + /* retrieve response parameters */
  7660. + rsp_params = (struct dpni_rsp_get_primary_mac_addr *)cmd.params;
  7661. + for (i = 0; i < 6; i++)
  7662. + mac_addr[5 - i] = rsp_params->mac_addr[i];
  7663. +
  7664. + return 0;
  7665. +}
  7666. +
  7667. +/**
  7668. + * dpni_get_port_mac_addr() - Retrieve MAC address associated to the physical
  7669. + * port the DPNI is attached to
  7670. + * @mc_io: Pointer to MC portal's I/O object
  7671. + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
  7672. + * @token: Token of DPNI object
  7673. + * @mac_addr: MAC address of the physical port, if any, otherwise 0
  7674. + *
  7675. + * The primary MAC address is not cleared by this operation.
  7676. + *
  7677. + * Return: '0' on Success; Error code otherwise.
  7678. + */
  7679. +int dpni_get_port_mac_addr(struct fsl_mc_io *mc_io,
  7680. + u32 cmd_flags,
  7681. + u16 token,
  7682. + u8 mac_addr[6])
  7683. +{
  7684. + struct mc_command cmd = { 0 };
  7685. + struct dpni_rsp_get_port_mac_addr *rsp_params;
  7686. + int i, err;
  7687. +
  7688. + /* prepare command */
  7689. + cmd.header = mc_encode_cmd_header(DPNI_CMDID_GET_PORT_MAC_ADDR,
  7690. + cmd_flags,
  7691. + token);
  7692. +
  7693. + /* send command to mc*/
  7694. + err = mc_send_command(mc_io, &cmd);
  7695. + if (err)
  7696. + return err;
  7697. +
  7698. + /* retrieve response parameters */
  7699. + rsp_params = (struct dpni_rsp_get_port_mac_addr *)cmd.params;
  7700. + for (i = 0; i < 6; i++)
  7701. + mac_addr[5 - i] = rsp_params->mac_addr[i];
  7702. +
  7703. + return 0;
  7704. +}
  7705. +
  7706. +/**
  7707. + * dpni_add_mac_addr() - Add MAC address filter
  7708. + * @mc_io: Pointer to MC portal's I/O object
  7709. + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
  7710. + * @token: Token of DPNI object
  7711. + * @mac_addr: MAC address to add
  7712. + *
  7713. + * Return: '0' on Success; Error code otherwise.
  7714. + */
  7715. +int dpni_add_mac_addr(struct fsl_mc_io *mc_io,
  7716. + u32 cmd_flags,
  7717. + u16 token,
  7718. + const u8 mac_addr[6])
  7719. +{
  7720. + struct mc_command cmd = { 0 };
  7721. + struct dpni_cmd_add_mac_addr *cmd_params;
  7722. + int i;
  7723. +
  7724. + /* prepare command */
  7725. + cmd.header = mc_encode_cmd_header(DPNI_CMDID_ADD_MAC_ADDR,
  7726. + cmd_flags,
  7727. + token);
  7728. + cmd_params = (struct dpni_cmd_add_mac_addr *)cmd.params;
  7729. + for (i = 0; i < 6; i++)
  7730. + cmd_params->mac_addr[i] = mac_addr[5 - i];
  7731. +
  7732. + /* send command to mc*/
  7733. + return mc_send_command(mc_io, &cmd);
  7734. +}
  7735. +
  7736. +/**
  7737. + * dpni_remove_mac_addr() - Remove MAC address filter
  7738. + * @mc_io: Pointer to MC portal's I/O object
  7739. + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
  7740. + * @token: Token of DPNI object
  7741. + * @mac_addr: MAC address to remove
  7742. + *
  7743. + * Return: '0' on Success; Error code otherwise.
  7744. + */
  7745. +int dpni_remove_mac_addr(struct fsl_mc_io *mc_io,
  7746. + u32 cmd_flags,
  7747. + u16 token,
  7748. + const u8 mac_addr[6])
  7749. +{
  7750. + struct mc_command cmd = { 0 };
  7751. + struct dpni_cmd_remove_mac_addr *cmd_params;
  7752. + int i;
  7753. +
  7754. + /* prepare command */
  7755. + cmd.header = mc_encode_cmd_header(DPNI_CMDID_REMOVE_MAC_ADDR,
  7756. + cmd_flags,
  7757. + token);
  7758. + cmd_params = (struct dpni_cmd_remove_mac_addr *)cmd.params;
  7759. + for (i = 0; i < 6; i++)
  7760. + cmd_params->mac_addr[i] = mac_addr[5 - i];
  7761. +
  7762. + /* send command to mc*/
  7763. + return mc_send_command(mc_io, &cmd);
  7764. +}
  7765. +
  7766. +/**
  7767. + * dpni_clear_mac_filters() - Clear all unicast and/or multicast MAC filters
  7768. + * @mc_io: Pointer to MC portal's I/O object
  7769. + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
  7770. + * @token: Token of DPNI object
  7771. + * @unicast: Set to '1' to clear unicast addresses
  7772. + * @multicast: Set to '1' to clear multicast addresses
  7773. + *
  7774. + * The primary MAC address is not cleared by this operation.
  7775. + *
  7776. + * Return: '0' on Success; Error code otherwise.
  7777. + */
  7778. +int dpni_clear_mac_filters(struct fsl_mc_io *mc_io,
  7779. + u32 cmd_flags,
  7780. + u16 token,
  7781. + int unicast,
  7782. + int multicast)
  7783. +{
  7784. + struct mc_command cmd = { 0 };
  7785. + struct dpni_cmd_clear_mac_filters *cmd_params;
  7786. +
  7787. + /* prepare command */
  7788. + cmd.header = mc_encode_cmd_header(DPNI_CMDID_CLR_MAC_FILTERS,
  7789. + cmd_flags,
  7790. + token);
  7791. + cmd_params = (struct dpni_cmd_clear_mac_filters *)cmd.params;
  7792. + dpni_set_field(cmd_params->flags, UNICAST_FILTERS, unicast);
  7793. + dpni_set_field(cmd_params->flags, MULTICAST_FILTERS, multicast);
  7794. +
  7795. + /* send command to mc*/
  7796. + return mc_send_command(mc_io, &cmd);
  7797. +}
  7798. +
  7799. +/**
  7800. + * dpni_set_rx_tc_dist() - Set Rx traffic class distribution configuration
  7801. + * @mc_io: Pointer to MC portal's I/O object
  7802. + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
  7803. + * @token: Token of DPNI object
  7804. + * @tc_id: Traffic class selection (0-7)
  7805. + * @cfg: Traffic class distribution configuration
  7806. + *
  7807. + * warning: if 'dist_mode != DPNI_DIST_MODE_NONE', call dpni_prepare_key_cfg()
  7808. + * first to prepare the key_cfg_iova parameter
  7809. + *
  7810. + * Return: '0' on Success; error code otherwise.
  7811. + */
  7812. +int dpni_set_rx_tc_dist(struct fsl_mc_io *mc_io,
  7813. + u32 cmd_flags,
  7814. + u16 token,
  7815. + u8 tc_id,
  7816. + const struct dpni_rx_tc_dist_cfg *cfg)
  7817. +{
  7818. + struct mc_command cmd = { 0 };
  7819. + struct dpni_cmd_set_rx_tc_dist *cmd_params;
  7820. +
  7821. + /* prepare command */
  7822. + cmd.header = mc_encode_cmd_header(DPNI_CMDID_SET_RX_TC_DIST,
  7823. + cmd_flags,
  7824. + token);
  7825. + cmd_params = (struct dpni_cmd_set_rx_tc_dist *)cmd.params;
  7826. + cmd_params->dist_size = cpu_to_le16(cfg->dist_size);
  7827. + cmd_params->tc_id = tc_id;
  7828. + dpni_set_field(cmd_params->flags, DIST_MODE, cfg->dist_mode);
  7829. + dpni_set_field(cmd_params->flags, MISS_ACTION, cfg->fs_cfg.miss_action);
  7830. + cmd_params->default_flow_id = cpu_to_le16(cfg->fs_cfg.default_flow_id);
  7831. + cmd_params->key_cfg_iova = cpu_to_le64(cfg->key_cfg_iova);
  7832. +
  7833. + /* send command to mc*/
  7834. + return mc_send_command(mc_io, &cmd);
  7835. +}
  7836. +
  7837. +/**
  7838. + * dpni_add_fs_entry() - Add Flow Steering entry for a specific traffic class
  7839. + * (to select a flow ID)
  7840. + * @mc_io: Pointer to MC portal's I/O object
  7841. + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
  7842. + * @token: Token of DPNI object
  7843. + * @tc_id: Traffic class selection (0-7)
  7844. + * @index: Location in the QoS table where to insert the entry.
  7845. + * Only relevant if MASKING is enabled for QoS
  7846. + * classification on this DPNI, it is ignored for exact match.
  7847. + * @cfg: Flow steering rule to add
  7848. + * @action: Action to be taken as result of a classification hit
  7849. + *
  7850. + * Return: '0' on Success; Error code otherwise.
  7851. + */
  7852. +int dpni_add_fs_entry(struct fsl_mc_io *mc_io,
  7853. + u32 cmd_flags,
  7854. + u16 token,
  7855. + u8 tc_id,
  7856. + u16 index,
  7857. + const struct dpni_rule_cfg *cfg,
  7858. + const struct dpni_fs_action_cfg *action)
  7859. +{
  7860. + struct dpni_cmd_add_fs_entry *cmd_params;
  7861. + struct mc_command cmd = { 0 };
  7862. +
  7863. + /* prepare command */
  7864. + cmd.header = mc_encode_cmd_header(DPNI_CMDID_ADD_FS_ENT,
  7865. + cmd_flags,
  7866. + token);
  7867. + cmd_params = (struct dpni_cmd_add_fs_entry *)cmd.params;
  7868. + cmd_params->tc_id = tc_id;
  7869. + cmd_params->key_size = cfg->key_size;
  7870. + cmd_params->index = cpu_to_le16(index);
  7871. + cmd_params->key_iova = cpu_to_le64(cfg->key_iova);
  7872. + cmd_params->mask_iova = cpu_to_le64(cfg->mask_iova);
  7873. + cmd_params->options = cpu_to_le16(action->options);
  7874. + cmd_params->flow_id = cpu_to_le16(action->flow_id);
  7875. + cmd_params->flc = cpu_to_le64(action->flc);
  7876. +
  7877. + /* send command to mc*/
  7878. + return mc_send_command(mc_io, &cmd);
  7879. +}
  7880. +
  7881. +/**
  7882. + * dpni_remove_fs_entry() - Remove Flow Steering entry from a specific
  7883. + * traffic class
  7884. + * @mc_io: Pointer to MC portal's I/O object
  7885. + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
  7886. + * @token: Token of DPNI object
  7887. + * @tc_id: Traffic class selection (0-7)
  7888. + * @cfg: Flow steering rule to remove
  7889. + *
  7890. + * Return: '0' on Success; Error code otherwise.
  7891. + */
  7892. +int dpni_remove_fs_entry(struct fsl_mc_io *mc_io,
  7893. + u32 cmd_flags,
  7894. + u16 token,
  7895. + u8 tc_id,
  7896. + const struct dpni_rule_cfg *cfg)
  7897. +{
  7898. + struct dpni_cmd_remove_fs_entry *cmd_params;
  7899. + struct mc_command cmd = { 0 };
  7900. +
  7901. + /* prepare command */
  7902. + cmd.header = mc_encode_cmd_header(DPNI_CMDID_REMOVE_FS_ENT,
  7903. + cmd_flags,
  7904. + token);
  7905. + cmd_params = (struct dpni_cmd_remove_fs_entry *)cmd.params;
  7906. + cmd_params->tc_id = tc_id;
  7907. + cmd_params->key_size = cfg->key_size;
  7908. + cmd_params->key_iova = cpu_to_le64(cfg->key_iova);
  7909. + cmd_params->mask_iova = cpu_to_le64(cfg->mask_iova);
  7910. +
  7911. + /* send command to mc*/
  7912. + return mc_send_command(mc_io, &cmd);
  7913. +}
  7914. +
  7915. +/**
  7916. + * dpni_set_congestion_notification() - Set traffic class congestion
  7917. + * notification configuration
  7918. + * @mc_io: Pointer to MC portal's I/O object
  7919. + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
  7920. + * @token: Token of DPNI object
  7921. + * @qtype: Type of queue - Rx, Tx and Tx confirm types are supported
  7922. + * @tc_id: Traffic class selection (0-7)
  7923. + * @cfg: congestion notification configuration
  7924. + *
  7925. + * Return: '0' on Success; error code otherwise.
  7926. + */
  7927. +int dpni_set_congestion_notification(struct fsl_mc_io *mc_io,
  7928. + u32 cmd_flags,
  7929. + u16 token,
  7930. + enum dpni_queue_type qtype,
  7931. + u8 tc_id,
  7932. + const struct dpni_congestion_notification_cfg *cfg)
  7933. +{
  7934. + struct dpni_cmd_set_congestion_notification *cmd_params;
  7935. + struct mc_command cmd = { 0 };
  7936. +
  7937. + /* prepare command */
  7938. + cmd.header = mc_encode_cmd_header(
  7939. + DPNI_CMDID_SET_CONGESTION_NOTIFICATION,
  7940. + cmd_flags,
  7941. + token);
  7942. + cmd_params = (struct dpni_cmd_set_congestion_notification *)cmd.params;
  7943. + cmd_params->qtype = qtype;
  7944. + cmd_params->tc = tc_id;
  7945. + cmd_params->dest_id = cpu_to_le32(cfg->dest_cfg.dest_id);
  7946. + cmd_params->notification_mode = cpu_to_le16(cfg->notification_mode);
  7947. + cmd_params->dest_priority = cfg->dest_cfg.priority;
  7948. + dpni_set_field(cmd_params->type_units, DEST_TYPE,
  7949. + cfg->dest_cfg.dest_type);
  7950. + dpni_set_field(cmd_params->type_units, CONG_UNITS, cfg->units);
  7951. + cmd_params->message_iova = cpu_to_le64(cfg->message_iova);
  7952. + cmd_params->message_ctx = cpu_to_le64(cfg->message_ctx);
  7953. + cmd_params->threshold_entry = cpu_to_le32(cfg->threshold_entry);
  7954. + cmd_params->threshold_exit = cpu_to_le32(cfg->threshold_exit);
  7955. +
  7956. + /* send command to mc*/
  7957. + return mc_send_command(mc_io, &cmd);
  7958. +}
  7959. +
  7960. +/**
  7961. + * dpni_set_queue() - Set queue parameters
  7962. + * @mc_io: Pointer to MC portal's I/O object
  7963. + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
  7964. + * @token: Token of DPNI object
  7965. + * @qtype: Type of queue - all queue types are supported, although
  7966. + * the command is ignored for Tx
  7967. + * @tc: Traffic class, in range 0 to NUM_TCS - 1
  7968. + * @index: Selects the specific queue out of the set allocated for the
  7969. + * same TC. Value must be in range 0 to NUM_QUEUES - 1
  7970. + * @options: A combination of DPNI_QUEUE_OPT_ values that control what
  7971. + * configuration options are set on the queue
  7972. + * @queue: Queue structure
  7973. + *
  7974. + * Return: '0' on Success; Error code otherwise.
  7975. + */
  7976. +int dpni_set_queue(struct fsl_mc_io *mc_io,
  7977. + u32 cmd_flags,
  7978. + u16 token,
  7979. + enum dpni_queue_type qtype,
  7980. + u8 tc,
  7981. + u8 index,
  7982. + u8 options,
  7983. + const struct dpni_queue *queue)
  7984. +{
  7985. + struct mc_command cmd = { 0 };
  7986. + struct dpni_cmd_set_queue *cmd_params;
  7987. +
  7988. + /* prepare command */
  7989. + cmd.header = mc_encode_cmd_header(DPNI_CMDID_SET_QUEUE,
  7990. + cmd_flags,
  7991. + token);
  7992. + cmd_params = (struct dpni_cmd_set_queue *)cmd.params;
  7993. + cmd_params->qtype = qtype;
  7994. + cmd_params->tc = tc;
  7995. + cmd_params->index = index;
  7996. + cmd_params->options = options;
  7997. + cmd_params->dest_id = cpu_to_le32(queue->destination.id);
  7998. + cmd_params->dest_prio = queue->destination.priority;
  7999. + dpni_set_field(cmd_params->flags, DEST_TYPE, queue->destination.type);
  8000. + dpni_set_field(cmd_params->flags, STASH_CTRL, queue->flc.stash_control);
  8001. + dpni_set_field(cmd_params->flags, HOLD_ACTIVE,
  8002. + queue->destination.hold_active);
  8003. + cmd_params->flc = cpu_to_le64(queue->flc.value);
  8004. + cmd_params->user_context = cpu_to_le64(queue->user_context);
  8005. +
  8006. + /* send command to mc */
  8007. + return mc_send_command(mc_io, &cmd);
  8008. +}
  8009. +
  8010. +/**
  8011. + * dpni_get_queue() - Get queue parameters
  8012. + * @mc_io: Pointer to MC portal's I/O object
  8013. + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
  8014. + * @token: Token of DPNI object
  8015. + * @qtype: Type of queue - all queue types are supported
  8016. + * @tc: Traffic class, in range 0 to NUM_TCS - 1
  8017. + * @index: Selects the specific queue out of the set allocated for the
  8018. + * same TC. Value must be in range 0 to NUM_QUEUES - 1
  8019. + * @queue: Queue configuration structure
  8020. + * @qid: Queue identification
  8021. + *
  8022. + * Return: '0' on Success; Error code otherwise.
  8023. + */
  8024. +int dpni_get_queue(struct fsl_mc_io *mc_io,
  8025. + u32 cmd_flags,
  8026. + u16 token,
  8027. + enum dpni_queue_type qtype,
  8028. + u8 tc,
  8029. + u8 index,
  8030. + struct dpni_queue *queue,
  8031. + struct dpni_queue_id *qid)
  8032. +{
  8033. + struct mc_command cmd = { 0 };
  8034. + struct dpni_cmd_get_queue *cmd_params;
  8035. + struct dpni_rsp_get_queue *rsp_params;
  8036. + int err;
  8037. +
  8038. + /* prepare command */
  8039. + cmd.header = mc_encode_cmd_header(DPNI_CMDID_GET_QUEUE,
  8040. + cmd_flags,
  8041. + token);
  8042. + cmd_params = (struct dpni_cmd_get_queue *)cmd.params;
  8043. + cmd_params->qtype = qtype;
  8044. + cmd_params->tc = tc;
  8045. + cmd_params->index = index;
  8046. +
  8047. + /* send command to mc */
  8048. + err = mc_send_command(mc_io, &cmd);
  8049. + if (err)
  8050. + return err;
  8051. +
  8052. + /* retrieve response parameters */
  8053. + rsp_params = (struct dpni_rsp_get_queue *)cmd.params;
  8054. + queue->destination.id = le32_to_cpu(rsp_params->dest_id);
  8055. + queue->destination.priority = rsp_params->dest_prio;
  8056. + queue->destination.type = dpni_get_field(rsp_params->flags,
  8057. + DEST_TYPE);
  8058. + queue->flc.stash_control = dpni_get_field(rsp_params->flags,
  8059. + STASH_CTRL);
  8060. + queue->destination.hold_active = dpni_get_field(rsp_params->flags,
  8061. + HOLD_ACTIVE);
  8062. + queue->flc.value = le64_to_cpu(rsp_params->flc);
  8063. + queue->user_context = le64_to_cpu(rsp_params->user_context);
  8064. + qid->fqid = le32_to_cpu(rsp_params->fqid);
  8065. + qid->qdbin = le16_to_cpu(rsp_params->qdbin);
  8066. +
  8067. + return 0;
  8068. +}
  8069. +
  8070. +/**
  8071. + * dpni_get_statistics() - Get DPNI statistics
  8072. + * @mc_io: Pointer to MC portal's I/O object
  8073. + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
  8074. + * @token: Token of DPNI object
  8075. + * @page: Selects the statistics page to retrieve, see
  8076. + * DPNI_GET_STATISTICS output. Pages are numbered 0 to 2.
  8077. + * @stat: Structure containing the statistics
  8078. + *
  8079. + * Return: '0' on Success; Error code otherwise.
  8080. + */
  8081. +int dpni_get_statistics(struct fsl_mc_io *mc_io,
  8082. + u32 cmd_flags,
  8083. + u16 token,
  8084. + u8 page,
  8085. + union dpni_statistics *stat)
  8086. +{
  8087. + struct mc_command cmd = { 0 };
  8088. + struct dpni_cmd_get_statistics *cmd_params;
  8089. + struct dpni_rsp_get_statistics *rsp_params;
  8090. + int i, err;
  8091. +
  8092. + /* prepare command */
  8093. + cmd.header = mc_encode_cmd_header(DPNI_CMDID_GET_STATISTICS,
  8094. + cmd_flags,
  8095. + token);
  8096. + cmd_params = (struct dpni_cmd_get_statistics *)cmd.params;
  8097. + cmd_params->page_number = page;
  8098. +
  8099. + /* send command to mc */
  8100. + err = mc_send_command(mc_io, &cmd);
  8101. + if (err)
  8102. + return err;
  8103. +
  8104. + /* retrieve response parameters */
  8105. + rsp_params = (struct dpni_rsp_get_statistics *)cmd.params;
  8106. + for (i = 0; i < DPNI_STATISTICS_CNT; i++)
  8107. + stat->raw.counter[i] = le64_to_cpu(rsp_params->counter[i]);
  8108. +
  8109. + return 0;
  8110. +}
  8111. +
  8112. +/**
  8113. + * dpni_reset_statistics() - Clears DPNI statistics
  8114. + * @mc_io: Pointer to MC portal's I/O object
  8115. + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
  8116. + * @token: Token of DPNI object
  8117. + *
  8118. + * Return: '0' on Success; Error code otherwise.
  8119. + */
  8120. +int dpni_reset_statistics(struct fsl_mc_io *mc_io,
  8121. + u32 cmd_flags,
  8122. + u16 token)
  8123. +{
  8124. + struct mc_command cmd = { 0 };
  8125. +
  8126. + /* prepare command */
  8127. + cmd.header = mc_encode_cmd_header(DPNI_CMDID_RESET_STATISTICS,
  8128. + cmd_flags,
  8129. + token);
  8130. +
  8131. + /* send command to mc*/
  8132. + return mc_send_command(mc_io, &cmd);
  8133. +}
  8134. +
  8135. +/**
  8136. + * dpni_set_taildrop() - Set taildrop per queue or TC
  8137. + * @mc_io: Pointer to MC portal's I/O object
  8138. + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
  8139. + * @token: Token of DPNI object
  8140. + * @cg_point: Congestion point
  8141. + * @q_type: Queue type on which the taildrop is configured.
  8142. + * Only Rx queues are supported for now
  8143. + * @tc: Traffic class to apply this taildrop to
  8144. + * @q_index: Index of the queue if the DPNI supports multiple queues for
  8145. + * traffic distribution. Ignored if CONGESTION_POINT is not 0.
  8146. + * @taildrop: Taildrop structure
  8147. + *
  8148. + * Return: '0' on Success; Error code otherwise.
  8149. + */
  8150. +int dpni_set_taildrop(struct fsl_mc_io *mc_io,
  8151. + u32 cmd_flags,
  8152. + u16 token,
  8153. + enum dpni_congestion_point cg_point,
  8154. + enum dpni_queue_type qtype,
  8155. + u8 tc,
  8156. + u8 index,
  8157. + struct dpni_taildrop *taildrop)
  8158. +{
  8159. + struct mc_command cmd = { 0 };
  8160. + struct dpni_cmd_set_taildrop *cmd_params;
  8161. +
  8162. + /* prepare command */
  8163. + cmd.header = mc_encode_cmd_header(DPNI_CMDID_SET_TAILDROP,
  8164. + cmd_flags,
  8165. + token);
  8166. + cmd_params = (struct dpni_cmd_set_taildrop *)cmd.params;
  8167. + cmd_params->congestion_point = cg_point;
  8168. + cmd_params->qtype = qtype;
  8169. + cmd_params->tc = tc;
  8170. + cmd_params->index = index;
  8171. + dpni_set_field(cmd_params->enable, ENABLE, taildrop->enable);
  8172. + cmd_params->units = taildrop->units;
  8173. + cmd_params->threshold = cpu_to_le32(taildrop->threshold);
  8174. +
  8175. + /* send command to mc */
  8176. + return mc_send_command(mc_io, &cmd);
  8177. +}
  8178. +
  8179. +/**
  8180. + * dpni_get_taildrop() - Get taildrop information
  8181. + * @mc_io: Pointer to MC portal's I/O object
  8182. + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
  8183. + * @token: Token of DPNI object
  8184. + * @cg_point: Congestion point
  8185. + * @q_type: Queue type on which the taildrop is configured.
  8186. + * Only Rx queues are supported for now
  8187. + * @tc: Traffic class to apply this taildrop to
  8188. + * @q_index: Index of the queue if the DPNI supports multiple queues for
  8189. + * traffic distribution. Ignored if CONGESTION_POINT is not 0.
  8190. + * @taildrop: Taildrop structure
  8191. + *
  8192. + * Return: '0' on Success; Error code otherwise.
  8193. + */
  8194. +int dpni_get_taildrop(struct fsl_mc_io *mc_io,
  8195. + u32 cmd_flags,
  8196. + u16 token,
  8197. + enum dpni_congestion_point cg_point,
  8198. + enum dpni_queue_type qtype,
  8199. + u8 tc,
  8200. + u8 index,
  8201. + struct dpni_taildrop *taildrop)
  8202. +{
  8203. + struct mc_command cmd = { 0 };
  8204. + struct dpni_cmd_get_taildrop *cmd_params;
  8205. + struct dpni_rsp_get_taildrop *rsp_params;
  8206. + int err;
  8207. +
  8208. + /* prepare command */
  8209. + cmd.header = mc_encode_cmd_header(DPNI_CMDID_GET_TAILDROP,
  8210. + cmd_flags,
  8211. + token);
  8212. + cmd_params = (struct dpni_cmd_get_taildrop *)cmd.params;
  8213. + cmd_params->congestion_point = cg_point;
  8214. + cmd_params->qtype = qtype;
  8215. + cmd_params->tc = tc;
  8216. + cmd_params->index = index;
  8217. +
  8218. + /* send command to mc */
  8219. + err = mc_send_command(mc_io, &cmd);
  8220. + if (err)
  8221. + return err;
  8222. +
  8223. + /* retrieve response parameters */
  8224. + rsp_params = (struct dpni_rsp_get_taildrop *)cmd.params;
  8225. + taildrop->enable = dpni_get_field(rsp_params->enable, ENABLE);
  8226. + taildrop->units = rsp_params->units;
  8227. + taildrop->threshold = le32_to_cpu(rsp_params->threshold);
  8228. +
  8229. + return 0;
  8230. +}
  8231. --- /dev/null
  8232. +++ b/drivers/staging/fsl-dpaa2/ethernet/dpni.h
  8233. @@ -0,0 +1,989 @@
  8234. +/* Copyright 2013-2016 Freescale Semiconductor Inc.
  8235. + * Copyright 2016 NXP
  8236. + *
  8237. + * Redistribution and use in source and binary forms, with or without
  8238. + * modification, are permitted provided that the following conditions are met:
  8239. + * * Redistributions of source code must retain the above copyright
  8240. + * notice, this list of conditions and the following disclaimer.
  8241. + * * Redistributions in binary form must reproduce the above copyright
  8242. + * notice, this list of conditions and the following disclaimer in the
  8243. + * documentation and/or other materials provided with the distribution.
  8244. + * * Neither the name of the above-listed copyright holders nor the
  8245. + * names of any contributors may be used to endorse or promote products
  8246. + * derived from this software without specific prior written permission.
  8247. + *
  8248. + *
  8249. + * ALTERNATIVELY, this software may be distributed under the terms of the
  8250. + * GNU General Public License ("GPL") as published by the Free Software
  8251. + * Foundation, either version 2 of that License or (at your option) any
  8252. + * later version.
  8253. + *
  8254. + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  8255. + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  8256. + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  8257. + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
  8258. + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  8259. + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  8260. + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  8261. + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  8262. + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  8263. + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  8264. + * POSSIBILITY OF SUCH DAMAGE.
  8265. + */
  8266. +#ifndef __FSL_DPNI_H
  8267. +#define __FSL_DPNI_H
  8268. +
  8269. +#include "dpkg.h"
  8270. +
  8271. +struct fsl_mc_io;
  8272. +
  8273. +/**
  8274. + * Data Path Network Interface API
  8275. + * Contains initialization APIs and runtime control APIs for DPNI
  8276. + */
  8277. +
  8278. +/** General DPNI macros */
  8279. +
  8280. +/**
  8281. + * Maximum number of traffic classes
  8282. + */
  8283. +#define DPNI_MAX_TC 8
  8284. +/**
  8285. + * Maximum number of buffer pools per DPNI
  8286. + */
  8287. +#define DPNI_MAX_DPBP 8
  8288. +
  8289. +/**
  8290. + * All traffic classes considered; see dpni_set_queue()
  8291. + */
  8292. +#define DPNI_ALL_TCS (u8)(-1)
  8293. +/**
  8294. + * All flows within traffic class considered; see dpni_set_queue()
  8295. + */
  8296. +#define DPNI_ALL_TC_FLOWS (u16)(-1)
  8297. +/**
  8298. + * Generate new flow ID; see dpni_set_queue()
  8299. + */
  8300. +#define DPNI_NEW_FLOW_ID (u16)(-1)
  8301. +
  8302. +/**
  8303. + * Tx traffic is always released to a buffer pool on transmit, there are no
  8304. + * resources allocated to have the frames confirmed back to the source after
  8305. + * transmission.
  8306. + */
  8307. +#define DPNI_OPT_TX_FRM_RELEASE 0x000001
  8308. +/**
  8309. + * Disables support for MAC address filtering for addresses other than primary
  8310. + * MAC address. This affects both unicast and multicast. Promiscuous mode can
  8311. + * still be enabled/disabled for both unicast and multicast. If promiscuous mode
  8312. + * is disabled, only traffic matching the primary MAC address will be accepted.
  8313. + */
  8314. +#define DPNI_OPT_NO_MAC_FILTER 0x000002
  8315. +/**
  8316. + * Allocate policers for this DPNI. They can be used to rate-limit traffic per
  8317. + * traffic class (TC) basis.
  8318. + */
  8319. +#define DPNI_OPT_HAS_POLICING 0x000004
  8320. +/**
  8321. + * Congestion can be managed in several ways, allowing the buffer pool to
  8322. + * deplete on ingress, taildrop on each queue or use congestion groups for sets
  8323. + * of queues. If set, it configures a single congestion groups across all TCs.
  8324. + * If reset, a congestion group is allocated for each TC. Only relevant if the
  8325. + * DPNI has multiple traffic classes.
  8326. + */
  8327. +#define DPNI_OPT_SHARED_CONGESTION 0x000008
  8328. +/**
  8329. + * Enables TCAM for Flow Steering and QoS look-ups. If not specified, all
  8330. + * look-ups are exact match. Note that TCAM is not available on LS1088 and its
  8331. + * variants. Setting this bit on these SoCs will trigger an error.
  8332. + */
  8333. +#define DPNI_OPT_HAS_KEY_MASKING 0x000010
  8334. +/**
  8335. + * Disables the flow steering table.
  8336. + */
  8337. +#define DPNI_OPT_NO_FS 0x000020
  8338. +
  8339. +int dpni_open(struct fsl_mc_io *mc_io,
  8340. + u32 cmd_flags,
  8341. + int dpni_id,
  8342. + u16 *token);
  8343. +
  8344. +int dpni_close(struct fsl_mc_io *mc_io,
  8345. + u32 cmd_flags,
  8346. + u16 token);
  8347. +
  8348. +/**
  8349. + * struct dpni_pools_cfg - Structure representing buffer pools configuration
  8350. + * @num_dpbp: Number of DPBPs
  8351. + * @pools: Array of buffer pools parameters; The number of valid entries
  8352. + * must match 'num_dpbp' value
  8353. + */
  8354. +struct dpni_pools_cfg {
  8355. + u8 num_dpbp;
  8356. + /**
  8357. + * struct pools - Buffer pools parameters
  8358. + * @dpbp_id: DPBP object ID
  8359. + * @buffer_size: Buffer size
  8360. + * @backup_pool: Backup pool
  8361. + */
  8362. + struct {
  8363. + int dpbp_id;
  8364. + u16 buffer_size;
  8365. + int backup_pool;
  8366. + } pools[DPNI_MAX_DPBP];
  8367. +};
  8368. +
  8369. +int dpni_set_pools(struct fsl_mc_io *mc_io,
  8370. + u32 cmd_flags,
  8371. + u16 token,
  8372. + const struct dpni_pools_cfg *cfg);
  8373. +
  8374. +int dpni_enable(struct fsl_mc_io *mc_io,
  8375. + u32 cmd_flags,
  8376. + u16 token);
  8377. +
  8378. +int dpni_disable(struct fsl_mc_io *mc_io,
  8379. + u32 cmd_flags,
  8380. + u16 token);
  8381. +
  8382. +int dpni_is_enabled(struct fsl_mc_io *mc_io,
  8383. + u32 cmd_flags,
  8384. + u16 token,
  8385. + int *en);
  8386. +
  8387. +int dpni_reset(struct fsl_mc_io *mc_io,
  8388. + u32 cmd_flags,
  8389. + u16 token);
  8390. +
  8391. +/**
  8392. + * DPNI IRQ Index and Events
  8393. + */
  8394. +
  8395. +/**
  8396. + * IRQ index
  8397. + */
  8398. +#define DPNI_IRQ_INDEX 0
  8399. +/**
  8400. + * IRQ event - indicates a change in link state
  8401. + */
  8402. +#define DPNI_IRQ_EVENT_LINK_CHANGED 0x00000001
  8403. +
  8404. +int dpni_set_irq_enable(struct fsl_mc_io *mc_io,
  8405. + u32 cmd_flags,
  8406. + u16 token,
  8407. + u8 irq_index,
  8408. + u8 en);
  8409. +
  8410. +int dpni_get_irq_enable(struct fsl_mc_io *mc_io,
  8411. + u32 cmd_flags,
  8412. + u16 token,
  8413. + u8 irq_index,
  8414. + u8 *en);
  8415. +
  8416. +int dpni_set_irq_mask(struct fsl_mc_io *mc_io,
  8417. + u32 cmd_flags,
  8418. + u16 token,
  8419. + u8 irq_index,
  8420. + u32 mask);
  8421. +
  8422. +int dpni_get_irq_mask(struct fsl_mc_io *mc_io,
  8423. + u32 cmd_flags,
  8424. + u16 token,
  8425. + u8 irq_index,
  8426. + u32 *mask);
  8427. +
  8428. +int dpni_get_irq_status(struct fsl_mc_io *mc_io,
  8429. + u32 cmd_flags,
  8430. + u16 token,
  8431. + u8 irq_index,
  8432. + u32 *status);
  8433. +
  8434. +int dpni_clear_irq_status(struct fsl_mc_io *mc_io,
  8435. + u32 cmd_flags,
  8436. + u16 token,
  8437. + u8 irq_index,
  8438. + u32 status);
  8439. +
  8440. +/**
  8441. + * struct dpni_attr - Structure representing DPNI attributes
  8442. + * @options: Any combination of the following options:
  8443. + * DPNI_OPT_TX_FRM_RELEASE
  8444. + * DPNI_OPT_NO_MAC_FILTER
  8445. + * DPNI_OPT_HAS_POLICING
  8446. + * DPNI_OPT_SHARED_CONGESTION
  8447. + * DPNI_OPT_HAS_KEY_MASKING
  8448. + * DPNI_OPT_NO_FS
  8449. + * @num_queues: Number of Tx and Rx queues used for traffic distribution.
  8450. + * @num_tcs: Number of traffic classes (TCs), reserved for the DPNI.
  8451. + * @mac_filter_entries: Number of entries in the MAC address filtering table.
  8452. + * @vlan_filter_entries: Number of entries in the VLAN address filtering table.
  8453. + * @qos_entries: Number of entries in the QoS classification table.
  8454. + * @fs_entries: Number of entries in the flow steering table.
  8455. + * @qos_key_size: Size, in bytes, of the QoS look-up key. Defining a key larger
  8456. + * than this when adding QoS entries will result in an error.
  8457. + * @fs_key_size: Size, in bytes, of the flow steering look-up key. Defining a
  8458. + * key larger than this when composing the hash + FS key will
  8459. + * result in an error.
  8460. + * @wriop_version: Version of WRIOP HW block. The 3 version values are stored
  8461. + * on 6, 5, 5 bits respectively.
  8462. + */
  8463. +struct dpni_attr {
  8464. + u32 options;
  8465. + u8 num_queues;
  8466. + u8 num_tcs;
  8467. + u8 mac_filter_entries;
  8468. + u8 vlan_filter_entries;
  8469. + u8 qos_entries;
  8470. + u16 fs_entries;
  8471. + u8 qos_key_size;
  8472. + u8 fs_key_size;
  8473. + u16 wriop_version;
  8474. +};
  8475. +
  8476. +int dpni_get_attributes(struct fsl_mc_io *mc_io,
  8477. + u32 cmd_flags,
  8478. + u16 token,
  8479. + struct dpni_attr *attr);
  8480. +
  8481. +/**
  8482. + * DPNI errors
  8483. + */
  8484. +
  8485. +/**
  8486. + * Extract out of frame header error
  8487. + */
  8488. +#define DPNI_ERROR_EOFHE 0x00020000
  8489. +/**
  8490. + * Frame length error
  8491. + */
  8492. +#define DPNI_ERROR_FLE 0x00002000
  8493. +/**
  8494. + * Frame physical error
  8495. + */
  8496. +#define DPNI_ERROR_FPE 0x00001000
  8497. +/**
  8498. + * Parsing header error
  8499. + */
  8500. +#define DPNI_ERROR_PHE 0x00000020
  8501. +/**
  8502. + * Parser L3 checksum error
  8503. + */
  8504. +#define DPNI_ERROR_L3CE 0x00000004
  8505. +/**
  8506. + * Parser L3 checksum error
  8507. + */
  8508. +#define DPNI_ERROR_L4CE 0x00000001
  8509. +
  8510. +/**
  8511. + * enum dpni_error_action - Defines DPNI behavior for errors
  8512. + * @DPNI_ERROR_ACTION_DISCARD: Discard the frame
  8513. + * @DPNI_ERROR_ACTION_CONTINUE: Continue with the normal flow
  8514. + * @DPNI_ERROR_ACTION_SEND_TO_ERROR_QUEUE: Send the frame to the error queue
  8515. + */
  8516. +enum dpni_error_action {
  8517. + DPNI_ERROR_ACTION_DISCARD = 0,
  8518. + DPNI_ERROR_ACTION_CONTINUE = 1,
  8519. + DPNI_ERROR_ACTION_SEND_TO_ERROR_QUEUE = 2
  8520. +};
  8521. +
  8522. +/**
  8523. + * struct dpni_error_cfg - Structure representing DPNI errors treatment
  8524. + * @errors: Errors mask; use 'DPNI_ERROR__<X>
  8525. + * @error_action: The desired action for the errors mask
  8526. + * @set_frame_annotation: Set to '1' to mark the errors in frame annotation
  8527. + * status (FAS); relevant only for the non-discard action
  8528. + */
  8529. +struct dpni_error_cfg {
  8530. + u32 errors;
  8531. + enum dpni_error_action error_action;
  8532. + int set_frame_annotation;
  8533. +};
  8534. +
  8535. +int dpni_set_errors_behavior(struct fsl_mc_io *mc_io,
  8536. + u32 cmd_flags,
  8537. + u16 token,
  8538. + struct dpni_error_cfg *cfg);
  8539. +
  8540. +/**
  8541. + * DPNI buffer layout modification options
  8542. + */
  8543. +
  8544. +/**
  8545. + * Select to modify the time-stamp setting
  8546. + */
  8547. +#define DPNI_BUF_LAYOUT_OPT_TIMESTAMP 0x00000001
  8548. +/**
  8549. + * Select to modify the parser-result setting; not applicable for Tx
  8550. + */
  8551. +#define DPNI_BUF_LAYOUT_OPT_PARSER_RESULT 0x00000002
  8552. +/**
  8553. + * Select to modify the frame-status setting
  8554. + */
  8555. +#define DPNI_BUF_LAYOUT_OPT_FRAME_STATUS 0x00000004
  8556. +/**
  8557. + * Select to modify the private-data-size setting
  8558. + */
  8559. +#define DPNI_BUF_LAYOUT_OPT_PRIVATE_DATA_SIZE 0x00000008
  8560. +/**
  8561. + * Select to modify the data-alignment setting
  8562. + */
  8563. +#define DPNI_BUF_LAYOUT_OPT_DATA_ALIGN 0x00000010
  8564. +/**
  8565. + * Select to modify the data-head-room setting
  8566. + */
  8567. +#define DPNI_BUF_LAYOUT_OPT_DATA_HEAD_ROOM 0x00000020
  8568. +/**
  8569. + * Select to modify the data-tail-room setting
  8570. + */
  8571. +#define DPNI_BUF_LAYOUT_OPT_DATA_TAIL_ROOM 0x00000040
  8572. +
  8573. +/**
  8574. + * struct dpni_buffer_layout - Structure representing DPNI buffer layout
  8575. + * @options: Flags representing the suggested modifications to the buffer
  8576. + * layout; Use any combination of 'DPNI_BUF_LAYOUT_OPT_<X>' flags
  8577. + * @pass_timestamp: Pass timestamp value
  8578. + * @pass_parser_result: Pass parser results
  8579. + * @pass_frame_status: Pass frame status
  8580. + * @private_data_size: Size kept for private data (in bytes)
  8581. + * @data_align: Data alignment
  8582. + * @data_head_room: Data head room
  8583. + * @data_tail_room: Data tail room
  8584. + */
  8585. +struct dpni_buffer_layout {
  8586. + u32 options;
  8587. + int pass_timestamp;
  8588. + int pass_parser_result;
  8589. + int pass_frame_status;
  8590. + u16 private_data_size;
  8591. + u16 data_align;
  8592. + u16 data_head_room;
  8593. + u16 data_tail_room;
  8594. +};
  8595. +
  8596. +/**
  8597. + * enum dpni_queue_type - Identifies a type of queue targeted by the command
  8598. + * @DPNI_QUEUE_RX: Rx queue
  8599. + * @DPNI_QUEUE_TX: Tx queue
  8600. + * @DPNI_QUEUE_TX_CONFIRM: Tx confirmation queue
  8601. + * @DPNI_QUEUE_RX_ERR: Rx error queue
  8602. + */enum dpni_queue_type {
  8603. + DPNI_QUEUE_RX,
  8604. + DPNI_QUEUE_TX,
  8605. + DPNI_QUEUE_TX_CONFIRM,
  8606. + DPNI_QUEUE_RX_ERR,
  8607. +};
  8608. +
  8609. +int dpni_get_buffer_layout(struct fsl_mc_io *mc_io,
  8610. + u32 cmd_flags,
  8611. + u16 token,
  8612. + enum dpni_queue_type qtype,
  8613. + struct dpni_buffer_layout *layout);
  8614. +
  8615. +int dpni_set_buffer_layout(struct fsl_mc_io *mc_io,
  8616. + u32 cmd_flags,
  8617. + u16 token,
  8618. + enum dpni_queue_type qtype,
  8619. + const struct dpni_buffer_layout *layout);
  8620. +
  8621. +/**
  8622. + * enum dpni_offload - Identifies a type of offload targeted by the command
  8623. + * @DPNI_OFF_RX_L3_CSUM: Rx L3 checksum validation
  8624. + * @DPNI_OFF_RX_L4_CSUM: Rx L4 checksum validation
  8625. + * @DPNI_OFF_TX_L3_CSUM: Tx L3 checksum generation
  8626. + * @DPNI_OFF_TX_L4_CSUM: Tx L4 checksum generation
  8627. + */
  8628. +enum dpni_offload {
  8629. + DPNI_OFF_RX_L3_CSUM,
  8630. + DPNI_OFF_RX_L4_CSUM,
  8631. + DPNI_OFF_TX_L3_CSUM,
  8632. + DPNI_OFF_TX_L4_CSUM,
  8633. +};
  8634. +
  8635. +int dpni_set_offload(struct fsl_mc_io *mc_io,
  8636. + u32 cmd_flags,
  8637. + u16 token,
  8638. + enum dpni_offload type,
  8639. + u32 config);
  8640. +
  8641. +int dpni_get_offload(struct fsl_mc_io *mc_io,
  8642. + u32 cmd_flags,
  8643. + u16 token,
  8644. + enum dpni_offload type,
  8645. + u32 *config);
  8646. +
  8647. +int dpni_get_qdid(struct fsl_mc_io *mc_io,
  8648. + u32 cmd_flags,
  8649. + u16 token,
  8650. + enum dpni_queue_type qtype,
  8651. + u16 *qdid);
  8652. +
  8653. +int dpni_get_tx_data_offset(struct fsl_mc_io *mc_io,
  8654. + u32 cmd_flags,
  8655. + u16 token,
  8656. + u16 *data_offset);
  8657. +
  8658. +#define DPNI_STATISTICS_CNT 7
  8659. +
  8660. +union dpni_statistics {
  8661. + /**
  8662. + * struct page_0 - Page_0 statistics structure
  8663. + * @ingress_all_frames: Ingress frame count
  8664. + * @ingress_all_bytes: Ingress byte count
  8665. + * @ingress_multicast_frames: Ingress multicast frame count
  8666. + * @ingress_multicast_bytes: Ingress multicast byte count
  8667. + * @ingress_broadcast_frames: Ingress broadcast frame count
  8668. + * @ingress_broadcast_bytes: Ingress broadcast byte count
  8669. + */
  8670. + struct {
  8671. + u64 ingress_all_frames;
  8672. + u64 ingress_all_bytes;
  8673. + u64 ingress_multicast_frames;
  8674. + u64 ingress_multicast_bytes;
  8675. + u64 ingress_broadcast_frames;
  8676. + u64 ingress_broadcast_bytes;
  8677. + } page_0;
  8678. + /**
  8679. + * struct page_1 - Page_1 statistics structure
  8680. + * @egress_all_frames: Egress frame count
  8681. + * @egress_all_bytes: Egress byte count
  8682. + * @egress_multicast_frames: Egress multicast frame count
  8683. + * @egress_multicast_bytes: Egress multicast byte count
  8684. + * @egress_broadcast_frames: Egress broadcast frame count
  8685. + * @egress_broadcast_bytes: Egress broadcast byte count
  8686. + */
  8687. + struct {
  8688. + u64 egress_all_frames;
  8689. + u64 egress_all_bytes;
  8690. + u64 egress_multicast_frames;
  8691. + u64 egress_multicast_bytes;
  8692. + u64 egress_broadcast_frames;
  8693. + u64 egress_broadcast_bytes;
  8694. + } page_1;
  8695. + /**
  8696. + * struct page_2 - Page_2 statistics structure
  8697. + * @ingress_filtered_frames: Ingress filtered frame count
  8698. + * @ingress_discarded_frames: Ingress discarded frame count
  8699. + * @ingress_nobuffer_discards: Ingress discarded frame count
  8700. + * due to lack of buffers
  8701. + * @egress_discarded_frames: Egress discarded frame count
  8702. + * @egress_confirmed_frames: Egress confirmed frame count
  8703. + */
  8704. + struct {
  8705. + u64 ingress_filtered_frames;
  8706. + u64 ingress_discarded_frames;
  8707. + u64 ingress_nobuffer_discards;
  8708. + u64 egress_discarded_frames;
  8709. + u64 egress_confirmed_frames;
  8710. + } page_2;
  8711. + /**
  8712. + * struct raw - raw statistics structure
  8713. + */
  8714. + struct {
  8715. + u64 counter[DPNI_STATISTICS_CNT];
  8716. + } raw;
  8717. +};
  8718. +
  8719. +int dpni_get_statistics(struct fsl_mc_io *mc_io,
  8720. + u32 cmd_flags,
  8721. + u16 token,
  8722. + u8 page,
  8723. + union dpni_statistics *stat);
  8724. +
  8725. +int dpni_reset_statistics(struct fsl_mc_io *mc_io,
  8726. + u32 cmd_flags,
  8727. + u16 token);
  8728. +
  8729. +/**
  8730. + * Enable auto-negotiation
  8731. + */
  8732. +#define DPNI_LINK_OPT_AUTONEG 0x0000000000000001ULL
  8733. +/**
  8734. + * Enable half-duplex mode
  8735. + */
  8736. +#define DPNI_LINK_OPT_HALF_DUPLEX 0x0000000000000002ULL
  8737. +/**
  8738. + * Enable pause frames
  8739. + */
  8740. +#define DPNI_LINK_OPT_PAUSE 0x0000000000000004ULL
  8741. +/**
  8742. + * Enable a-symmetric pause frames
  8743. + */
  8744. +#define DPNI_LINK_OPT_ASYM_PAUSE 0x0000000000000008ULL
  8745. +
  8746. +/**
  8747. + * struct - Structure representing DPNI link configuration
  8748. + * @rate: Rate
  8749. + * @options: Mask of available options; use 'DPNI_LINK_OPT_<X>' values
  8750. + */
  8751. +struct dpni_link_cfg {
  8752. + u32 rate;
  8753. + u64 options;
  8754. +};
  8755. +
  8756. +int dpni_set_link_cfg(struct fsl_mc_io *mc_io,
  8757. + u32 cmd_flags,
  8758. + u16 token,
  8759. + const struct dpni_link_cfg *cfg);
  8760. +
  8761. +/**
  8762. + * struct dpni_link_state - Structure representing DPNI link state
  8763. + * @rate: Rate
  8764. + * @options: Mask of available options; use 'DPNI_LINK_OPT_<X>' values
  8765. + * @up: Link state; '0' for down, '1' for up
  8766. + */
  8767. +struct dpni_link_state {
  8768. + u32 rate;
  8769. + u64 options;
  8770. + int up;
  8771. +};
  8772. +
  8773. +int dpni_get_link_state(struct fsl_mc_io *mc_io,
  8774. + u32 cmd_flags,
  8775. + u16 token,
  8776. + struct dpni_link_state *state);
  8777. +
  8778. +/**
  8779. + * struct dpni_tx_shaping - Structure representing DPNI tx shaping configuration
  8780. + * @rate_limit: rate in Mbps
  8781. + * @max_burst_size: burst size in bytes (up to 64KB)
  8782. + */
  8783. +struct dpni_tx_shaping_cfg {
  8784. + u32 rate_limit;
  8785. + u16 max_burst_size;
  8786. +};
  8787. +
  8788. +int dpni_set_tx_shaping(struct fsl_mc_io *mc_io,
  8789. + u32 cmd_flags,
  8790. + u16 token,
  8791. + const struct dpni_tx_shaping_cfg *tx_shaper);
  8792. +
  8793. +int dpni_set_max_frame_length(struct fsl_mc_io *mc_io,
  8794. + u32 cmd_flags,
  8795. + u16 token,
  8796. + u16 max_frame_length);
  8797. +
  8798. +int dpni_get_max_frame_length(struct fsl_mc_io *mc_io,
  8799. + u32 cmd_flags,
  8800. + u16 token,
  8801. + u16 *max_frame_length);
  8802. +
  8803. +int dpni_set_multicast_promisc(struct fsl_mc_io *mc_io,
  8804. + u32 cmd_flags,
  8805. + u16 token,
  8806. + int en);
  8807. +
  8808. +int dpni_get_multicast_promisc(struct fsl_mc_io *mc_io,
  8809. + u32 cmd_flags,
  8810. + u16 token,
  8811. + int *en);
  8812. +
  8813. +int dpni_set_unicast_promisc(struct fsl_mc_io *mc_io,
  8814. + u32 cmd_flags,
  8815. + u16 token,
  8816. + int en);
  8817. +
  8818. +int dpni_get_unicast_promisc(struct fsl_mc_io *mc_io,
  8819. + u32 cmd_flags,
  8820. + u16 token,
  8821. + int *en);
  8822. +
  8823. +int dpni_set_primary_mac_addr(struct fsl_mc_io *mc_io,
  8824. + u32 cmd_flags,
  8825. + u16 token,
  8826. + const u8 mac_addr[6]);
  8827. +
  8828. +int dpni_get_primary_mac_addr(struct fsl_mc_io *mc_io,
  8829. + u32 cmd_flags,
  8830. + u16 token,
  8831. + u8 mac_addr[6]);
  8832. +
  8833. +int dpni_get_port_mac_addr(struct fsl_mc_io *mc_io,
  8834. + u32 cm_flags,
  8835. + u16 token,
  8836. + u8 mac_addr[6]);
  8837. +
  8838. +int dpni_add_mac_addr(struct fsl_mc_io *mc_io,
  8839. + u32 cmd_flags,
  8840. + u16 token,
  8841. + const u8 mac_addr[6]);
  8842. +
  8843. +int dpni_remove_mac_addr(struct fsl_mc_io *mc_io,
  8844. + u32 cmd_flags,
  8845. + u16 token,
  8846. + const u8 mac_addr[6]);
  8847. +
  8848. +int dpni_clear_mac_filters(struct fsl_mc_io *mc_io,
  8849. + u32 cmd_flags,
  8850. + u16 token,
  8851. + int unicast,
  8852. + int multicast);
  8853. +
  8854. +/**
  8855. + * enum dpni_dist_mode - DPNI distribution mode
  8856. + * @DPNI_DIST_MODE_NONE: No distribution
  8857. + * @DPNI_DIST_MODE_HASH: Use hash distribution; only relevant if
  8858. + * the 'DPNI_OPT_DIST_HASH' option was set at DPNI creation
  8859. + * @DPNI_DIST_MODE_FS: Use explicit flow steering; only relevant if
  8860. + * the 'DPNI_OPT_DIST_FS' option was set at DPNI creation
  8861. + */
  8862. +enum dpni_dist_mode {
  8863. + DPNI_DIST_MODE_NONE = 0,
  8864. + DPNI_DIST_MODE_HASH = 1,
  8865. + DPNI_DIST_MODE_FS = 2
  8866. +};
  8867. +
  8868. +/**
  8869. + * enum dpni_fs_miss_action - DPNI Flow Steering miss action
  8870. + * @DPNI_FS_MISS_DROP: In case of no-match, drop the frame
  8871. + * @DPNI_FS_MISS_EXPLICIT_FLOWID: In case of no-match, use explicit flow-id
  8872. + * @DPNI_FS_MISS_HASH: In case of no-match, distribute using hash
  8873. + */
  8874. +enum dpni_fs_miss_action {
  8875. + DPNI_FS_MISS_DROP = 0,
  8876. + DPNI_FS_MISS_EXPLICIT_FLOWID = 1,
  8877. + DPNI_FS_MISS_HASH = 2
  8878. +};
  8879. +
  8880. +/**
  8881. + * struct dpni_fs_tbl_cfg - Flow Steering table configuration
  8882. + * @miss_action: Miss action selection
  8883. + * @default_flow_id: Used when 'miss_action = DPNI_FS_MISS_EXPLICIT_FLOWID'
  8884. + */
  8885. +struct dpni_fs_tbl_cfg {
  8886. + enum dpni_fs_miss_action miss_action;
  8887. + u16 default_flow_id;
  8888. +};
  8889. +
  8890. +int dpni_prepare_key_cfg(const struct dpkg_profile_cfg *cfg,
  8891. + u8 *key_cfg_buf);
  8892. +
  8893. +/**
  8894. + * struct dpni_rx_tc_dist_cfg - Rx traffic class distribution configuration
  8895. + * @dist_size: Set the distribution size;
  8896. + * supported values: 1,2,3,4,6,7,8,12,14,16,24,28,32,48,56,64,96,
  8897. + * 112,128,192,224,256,384,448,512,768,896,1024
  8898. + * @dist_mode: Distribution mode
  8899. + * @key_cfg_iova: I/O virtual address of 256 bytes DMA-able memory filled with
  8900. + * the extractions to be used for the distribution key by calling
  8901. + * dpni_prepare_key_cfg() relevant only when
  8902. + * 'dist_mode != DPNI_DIST_MODE_NONE', otherwise it can be '0'
  8903. + * @fs_cfg: Flow Steering table configuration; only relevant if
  8904. + * 'dist_mode = DPNI_DIST_MODE_FS'
  8905. + */
  8906. +struct dpni_rx_tc_dist_cfg {
  8907. + u16 dist_size;
  8908. + enum dpni_dist_mode dist_mode;
  8909. + u64 key_cfg_iova;
  8910. + struct dpni_fs_tbl_cfg fs_cfg;
  8911. +};
  8912. +
  8913. +int dpni_set_rx_tc_dist(struct fsl_mc_io *mc_io,
  8914. + u32 cmd_flags,
  8915. + u16 token,
  8916. + u8 tc_id,
  8917. + const struct dpni_rx_tc_dist_cfg *cfg);
  8918. +
  8919. +/**
  8920. + * enum dpni_dest - DPNI destination types
  8921. + * @DPNI_DEST_NONE: Unassigned destination; The queue is set in parked mode and
  8922. + * does not generate FQDAN notifications; user is expected to
  8923. + * dequeue from the queue based on polling or other user-defined
  8924. + * method
  8925. + * @DPNI_DEST_DPIO: The queue is set in schedule mode and generates FQDAN
  8926. + * notifications to the specified DPIO; user is expected to dequeue
  8927. + * from the queue only after notification is received
  8928. + * @DPNI_DEST_DPCON: The queue is set in schedule mode and does not generate
  8929. + * FQDAN notifications, but is connected to the specified DPCON
  8930. + * object; user is expected to dequeue from the DPCON channel
  8931. + */
  8932. +enum dpni_dest {
  8933. + DPNI_DEST_NONE = 0,
  8934. + DPNI_DEST_DPIO = 1,
  8935. + DPNI_DEST_DPCON = 2
  8936. +};
  8937. +
  8938. +/**
  8939. + * struct dpni_queue - Queue structure
  8940. + * @user_context: User data, presented to the user along with any frames from
  8941. + * this queue. Not relevant for Tx queues.
  8942. + */
  8943. +struct dpni_queue {
  8944. +/**
  8945. + * struct destination - Destination structure
  8946. + * @id: ID of the destination, only relevant if DEST_TYPE is > 0.
  8947. + * Identifies either a DPIO or a DPCON object. Not relevant for
  8948. + * Tx queues.
  8949. + * @type: May be one of the following:
  8950. + * 0 - No destination, queue can be manually queried, but will not
  8951. + * push traffic or notifications to a DPIO;
  8952. + * 1 - The destination is a DPIO. When traffic becomes available in
  8953. + * the queue a FQDAN (FQ data available notification) will be
  8954. + * generated to selected DPIO;
  8955. + * 2 - The destination is a DPCON. The queue is associated with a
  8956. + * DPCON object for the purpose of scheduling between multiple
  8957. + * queues. The DPCON may be independently configured to
  8958. + * generate notifications. Not relevant for Tx queues.
  8959. + * @hold_active: Hold active, maintains a queue scheduled for longer
  8960. + * in a DPIO during dequeue to reduce spread of traffic.
  8961. + * Only relevant if queues are not affined to a single DPIO.
  8962. + */
  8963. + struct {
  8964. + u16 id;
  8965. + enum dpni_dest type;
  8966. + char hold_active;
  8967. + u8 priority;
  8968. + } destination;
  8969. + u64 user_context;
  8970. + struct {
  8971. + u64 value;
  8972. + char stash_control;
  8973. + } flc;
  8974. +};
  8975. +
  8976. +/**
  8977. + * struct dpni_queue_id - Queue identification, used for enqueue commands
  8978. + * or queue control
  8979. + * @fqid: FQID used for enqueueing to and/or configuration of this specific FQ
  8980. + * @qdbin: Queueing bin, used to enqueue using QDID, DQBIN, QPRI. Only relevant
  8981. + * for Tx queues.
  8982. + */
  8983. +struct dpni_queue_id {
  8984. + u32 fqid;
  8985. + u16 qdbin;
  8986. +};
  8987. +
  8988. +/**
  8989. + * Set User Context
  8990. + */
  8991. +#define DPNI_QUEUE_OPT_USER_CTX 0x00000001
  8992. +#define DPNI_QUEUE_OPT_DEST 0x00000002
  8993. +#define DPNI_QUEUE_OPT_FLC 0x00000004
  8994. +#define DPNI_QUEUE_OPT_HOLD_ACTIVE 0x00000008
  8995. +
  8996. +int dpni_set_queue(struct fsl_mc_io *mc_io,
  8997. + u32 cmd_flags,
  8998. + u16 token,
  8999. + enum dpni_queue_type qtype,
  9000. + u8 tc,
  9001. + u8 index,
  9002. + u8 options,
  9003. + const struct dpni_queue *queue);
  9004. +
  9005. +int dpni_get_queue(struct fsl_mc_io *mc_io,
  9006. + u32 cmd_flags,
  9007. + u16 token,
  9008. + enum dpni_queue_type qtype,
  9009. + u8 tc,
  9010. + u8 index,
  9011. + struct dpni_queue *queue,
  9012. + struct dpni_queue_id *qid);
  9013. +
  9014. +/**
  9015. + * enum dpni_congestion_unit - DPNI congestion units
  9016. + * @DPNI_CONGESTION_UNIT_BYTES: bytes units
  9017. + * @DPNI_CONGESTION_UNIT_FRAMES: frames units
  9018. + */
  9019. +enum dpni_congestion_unit {
  9020. + DPNI_CONGESTION_UNIT_BYTES = 0,
  9021. + DPNI_CONGESTION_UNIT_FRAMES
  9022. +};
  9023. +
  9024. +/**
  9025. + * enum dpni_congestion_point - Structure representing congestion point
  9026. + * @DPNI_CP_QUEUE: Set taildrop per queue, identified by QUEUE_TYPE, TC and
  9027. + * QUEUE_INDEX
  9028. + * @DPNI_CP_GROUP: Set taildrop per queue group. Depending on options used to
  9029. + * define the DPNI this can be either per TC (default) or per
  9030. + * interface (DPNI_OPT_SHARED_CONGESTION set at DPNI create).
  9031. + * QUEUE_INDEX is ignored if this type is used.
  9032. + */
  9033. +enum dpni_congestion_point {
  9034. + DPNI_CP_QUEUE,
  9035. + DPNI_CP_GROUP,
  9036. +};
  9037. +
  9038. +/**
  9039. + * struct dpni_dest_cfg - Structure representing DPNI destination parameters
  9040. + * @dest_type: Destination type
  9041. + * @dest_id: Either DPIO ID or DPCON ID, depending on the destination type
  9042. + * @priority: Priority selection within the DPIO or DPCON channel; valid values
  9043. + * are 0-1 or 0-7, depending on the number of priorities in that
  9044. + * channel; not relevant for 'DPNI_DEST_NONE' option
  9045. + */
  9046. +struct dpni_dest_cfg {
  9047. + enum dpni_dest dest_type;
  9048. + int dest_id;
  9049. + u8 priority;
  9050. +};
  9051. +
  9052. +/* DPNI congestion options */
  9053. +
  9054. +/**
  9055. + * CSCN message is written to message_iova once entering a
  9056. + * congestion state (see 'threshold_entry')
  9057. + */
  9058. +#define DPNI_CONG_OPT_WRITE_MEM_ON_ENTER 0x00000001
  9059. +/**
  9060. + * CSCN message is written to message_iova once exiting a
  9061. + * congestion state (see 'threshold_exit')
  9062. + */
  9063. +#define DPNI_CONG_OPT_WRITE_MEM_ON_EXIT 0x00000002
  9064. +/**
  9065. + * CSCN write will attempt to allocate into a cache (coherent write);
  9066. + * valid only if 'DPNI_CONG_OPT_WRITE_MEM_<X>' is selected
  9067. + */
  9068. +#define DPNI_CONG_OPT_COHERENT_WRITE 0x00000004
  9069. +/**
  9070. + * if 'dest_cfg.dest_type != DPNI_DEST_NONE' CSCN message is sent to
  9071. + * DPIO/DPCON's WQ channel once entering a congestion state
  9072. + * (see 'threshold_entry')
  9073. + */
  9074. +#define DPNI_CONG_OPT_NOTIFY_DEST_ON_ENTER 0x00000008
  9075. +/**
  9076. + * if 'dest_cfg.dest_type != DPNI_DEST_NONE' CSCN message is sent to
  9077. + * DPIO/DPCON's WQ channel once exiting a congestion state
  9078. + * (see 'threshold_exit')
  9079. + */
  9080. +#define DPNI_CONG_OPT_NOTIFY_DEST_ON_EXIT 0x00000010
  9081. +/**
  9082. + * if 'dest_cfg.dest_type != DPNI_DEST_NONE' when the CSCN is written to the
  9083. + * sw-portal's DQRR, the DQRI interrupt is asserted immediately (if enabled)
  9084. + */
  9085. +#define DPNI_CONG_OPT_INTR_COALESCING_DISABLED 0x00000020
  9086. +
  9087. +/**
  9088. + * struct dpni_congestion_notification_cfg - congestion notification
  9089. + * configuration
  9090. + * @units: units type
  9091. + * @threshold_entry: above this threshold we enter a congestion state.
  9092. + * set it to '0' to disable it
  9093. + * @threshold_exit: below this threshold we exit the congestion state.
  9094. + * @message_ctx: The context that will be part of the CSCN message
  9095. + * @message_iova: I/O virtual address (must be in DMA-able memory),
  9096. + * must be 16B aligned; valid only if 'DPNI_CONG_OPT_WRITE_MEM_<X>' is
  9097. + * contained in 'options'
  9098. + * @dest_cfg: CSCN can be send to either DPIO or DPCON WQ channel
  9099. + * @notification_mode: Mask of available options; use 'DPNI_CONG_OPT_<X>' values
  9100. + */
  9101. +
  9102. +struct dpni_congestion_notification_cfg {
  9103. + enum dpni_congestion_unit units;
  9104. + u32 threshold_entry;
  9105. + u32 threshold_exit;
  9106. + u64 message_ctx;
  9107. + u64 message_iova;
  9108. + struct dpni_dest_cfg dest_cfg;
  9109. + u16 notification_mode;
  9110. +};
  9111. +
  9112. +int dpni_set_congestion_notification(struct fsl_mc_io *mc_io,
  9113. + u32 cmd_flags,
  9114. + u16 token,
  9115. + enum dpni_queue_type qtype,
  9116. + u8 tc_id,
  9117. + const struct dpni_congestion_notification_cfg *cfg);
  9118. +
  9119. +/**
  9120. + * struct dpni_taildrop - Structure representing the taildrop
  9121. + * @enable: Indicates whether the taildrop is active or not.
  9122. + * @units: Indicates the unit of THRESHOLD. Queue taildrop only supports
  9123. + * byte units, this field is ignored and assumed = 0 if
  9124. + * CONGESTION_POINT is 0.
  9125. + * @threshold: Threshold value, in units identified by UNITS field. Value 0
  9126. + * cannot be used as a valid taildrop threshold, THRESHOLD must
  9127. + * be > 0 if the taildrop is enabled.
  9128. + */
  9129. +struct dpni_taildrop {
  9130. + char enable;
  9131. + enum dpni_congestion_unit units;
  9132. + u32 threshold;
  9133. +};
  9134. +
  9135. +int dpni_set_taildrop(struct fsl_mc_io *mc_io,
  9136. + u32 cmd_flags,
  9137. + u16 token,
  9138. + enum dpni_congestion_point cg_point,
  9139. + enum dpni_queue_type q_type,
  9140. + u8 tc,
  9141. + u8 q_index,
  9142. + struct dpni_taildrop *taildrop);
  9143. +
  9144. +int dpni_get_taildrop(struct fsl_mc_io *mc_io,
  9145. + u32 cmd_flags,
  9146. + u16 token,
  9147. + enum dpni_congestion_point cg_point,
  9148. + enum dpni_queue_type q_type,
  9149. + u8 tc,
  9150. + u8 q_index,
  9151. + struct dpni_taildrop *taildrop);
  9152. +
  9153. +/**
  9154. + * struct dpni_rule_cfg - Rule configuration for table lookup
  9155. + * @key_iova: I/O virtual address of the key (must be in DMA-able memory)
  9156. + * @mask_iova: I/O virtual address of the mask (must be in DMA-able memory)
  9157. + * @key_size: key and mask size (in bytes)
  9158. + */
  9159. +struct dpni_rule_cfg {
  9160. + u64 key_iova;
  9161. + u64 mask_iova;
  9162. + u8 key_size;
  9163. +};
  9164. +
  9165. +/**
  9166. + * Discard matching traffic. If set, this takes precedence over any other
  9167. + * configuration and matching traffic is always discarded.
  9168. + */
  9169. + #define DPNI_FS_OPT_DISCARD 0x1
  9170. +
  9171. +/**
  9172. + * Set FLC value. If set, flc member of truct dpni_fs_action_cfg is used to
  9173. + * override the FLC value set per queue.
  9174. + * For more details check the Frame Descriptor section in the hardware
  9175. + * documentation.
  9176. + */
  9177. +#define DPNI_FS_OPT_SET_FLC 0x2
  9178. +
  9179. +/*
  9180. + * Indicates whether the 6 lowest significant bits of FLC are used for stash
  9181. + * control. If set, the 6 least significant bits in value are interpreted as
  9182. + * follows:
  9183. + * - bits 0-1: indicates the number of 64 byte units of context that are
  9184. + * stashed. FLC value is interpreted as a memory address in this case,
  9185. + * excluding the 6 LS bits.
  9186. + * - bits 2-3: indicates the number of 64 byte units of frame annotation
  9187. + * to be stashed. Annotation is placed at FD[ADDR].
  9188. + * - bits 4-5: indicates the number of 64 byte units of frame data to be
  9189. + * stashed. Frame data is placed at FD[ADDR] + FD[OFFSET].
  9190. + * This flag is ignored if DPNI_FS_OPT_SET_FLC is not specified.
  9191. + */
  9192. +#define DPNI_FS_OPT_SET_STASH_CONTROL 0x4
  9193. +
  9194. +/**
  9195. + * struct dpni_fs_action_cfg - Action configuration for table look-up
  9196. + * @flc: FLC value for traffic matching this rule. Please check the Frame
  9197. + * Descriptor section in the hardware documentation for more information.
  9198. + * @flow_id: Identifies the Rx queue used for matching traffic. Supported
  9199. + * values are in range 0 to num_queue-1.
  9200. + * @options: Any combination of DPNI_FS_OPT_ values.
  9201. + */
  9202. +struct dpni_fs_action_cfg {
  9203. + u64 flc;
  9204. + u16 flow_id;
  9205. + u16 options;
  9206. +};
  9207. +
  9208. +int dpni_add_fs_entry(struct fsl_mc_io *mc_io,
  9209. + u32 cmd_flags,
  9210. + u16 token,
  9211. + u8 tc_id,
  9212. + u16 index,
  9213. + const struct dpni_rule_cfg *cfg,
  9214. + const struct dpni_fs_action_cfg *action);
  9215. +
  9216. +int dpni_remove_fs_entry(struct fsl_mc_io *mc_io,
  9217. + u32 cmd_flags,
  9218. + u16 token,
  9219. + u8 tc_id,
  9220. + const struct dpni_rule_cfg *cfg);
  9221. +
  9222. +#endif /* __FSL_DPNI_H */
  9223. --- /dev/null
  9224. +++ b/drivers/staging/fsl-dpaa2/ethernet/net.h
  9225. @@ -0,0 +1,480 @@
  9226. +/* Copyright 2013-2015 Freescale Semiconductor Inc.
  9227. + *
  9228. + * Redistribution and use in source and binary forms, with or without
  9229. + * modification, are permitted provided that the following conditions are met:
  9230. + * * Redistributions of source code must retain the above copyright
  9231. + * notice, this list of conditions and the following disclaimer.
  9232. + * * Redistributions in binary form must reproduce the above copyright
  9233. + * notice, this list of conditions and the following disclaimer in the
  9234. + * documentation and/or other materials provided with the distribution.
  9235. + * * Neither the name of the above-listed copyright holders nor the
  9236. + * names of any contributors may be used to endorse or promote products
  9237. + * derived from this software without specific prior written permission.
  9238. + *
  9239. + *
  9240. + * ALTERNATIVELY, this software may be distributed under the terms of the
  9241. + * GNU General Public License ("GPL") as published by the Free Software
  9242. + * Foundation, either version 2 of that License or (at your option) any
  9243. + * later version.
  9244. + *
  9245. + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  9246. + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  9247. + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  9248. + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
  9249. + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  9250. + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  9251. + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  9252. + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  9253. + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  9254. + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  9255. + * POSSIBILITY OF SUCH DAMAGE.
  9256. + */
  9257. +#ifndef __FSL_NET_H
  9258. +#define __FSL_NET_H
  9259. +
  9260. +#define LAST_HDR_INDEX 0xFFFFFFFF
  9261. +
  9262. +/*****************************************************************************/
  9263. +/* Protocol fields */
  9264. +/*****************************************************************************/
  9265. +
  9266. +/************************* Ethernet fields *********************************/
  9267. +#define NH_FLD_ETH_DA (1)
  9268. +#define NH_FLD_ETH_SA (NH_FLD_ETH_DA << 1)
  9269. +#define NH_FLD_ETH_LENGTH (NH_FLD_ETH_DA << 2)
  9270. +#define NH_FLD_ETH_TYPE (NH_FLD_ETH_DA << 3)
  9271. +#define NH_FLD_ETH_FINAL_CKSUM (NH_FLD_ETH_DA << 4)
  9272. +#define NH_FLD_ETH_PADDING (NH_FLD_ETH_DA << 5)
  9273. +#define NH_FLD_ETH_ALL_FIELDS ((NH_FLD_ETH_DA << 6) - 1)
  9274. +
  9275. +#define NH_FLD_ETH_ADDR_SIZE 6
  9276. +
  9277. +/*************************** VLAN fields ***********************************/
  9278. +#define NH_FLD_VLAN_VPRI (1)
  9279. +#define NH_FLD_VLAN_CFI (NH_FLD_VLAN_VPRI << 1)
  9280. +#define NH_FLD_VLAN_VID (NH_FLD_VLAN_VPRI << 2)
  9281. +#define NH_FLD_VLAN_LENGTH (NH_FLD_VLAN_VPRI << 3)
  9282. +#define NH_FLD_VLAN_TYPE (NH_FLD_VLAN_VPRI << 4)
  9283. +#define NH_FLD_VLAN_ALL_FIELDS ((NH_FLD_VLAN_VPRI << 5) - 1)
  9284. +
  9285. +#define NH_FLD_VLAN_TCI (NH_FLD_VLAN_VPRI | \
  9286. + NH_FLD_VLAN_CFI | \
  9287. + NH_FLD_VLAN_VID)
  9288. +
  9289. +/************************ IP (generic) fields ******************************/
  9290. +#define NH_FLD_IP_VER (1)
  9291. +#define NH_FLD_IP_DSCP (NH_FLD_IP_VER << 2)
  9292. +#define NH_FLD_IP_ECN (NH_FLD_IP_VER << 3)
  9293. +#define NH_FLD_IP_PROTO (NH_FLD_IP_VER << 4)
  9294. +#define NH_FLD_IP_SRC (NH_FLD_IP_VER << 5)
  9295. +#define NH_FLD_IP_DST (NH_FLD_IP_VER << 6)
  9296. +#define NH_FLD_IP_TOS_TC (NH_FLD_IP_VER << 7)
  9297. +#define NH_FLD_IP_ID (NH_FLD_IP_VER << 8)
  9298. +#define NH_FLD_IP_ALL_FIELDS ((NH_FLD_IP_VER << 9) - 1)
  9299. +
  9300. +#define NH_FLD_IP_PROTO_SIZE 1
  9301. +
  9302. +/***************************** IPV4 fields *********************************/
  9303. +#define NH_FLD_IPV4_VER (1)
  9304. +#define NH_FLD_IPV4_HDR_LEN (NH_FLD_IPV4_VER << 1)
  9305. +#define NH_FLD_IPV4_TOS (NH_FLD_IPV4_VER << 2)
  9306. +#define NH_FLD_IPV4_TOTAL_LEN (NH_FLD_IPV4_VER << 3)
  9307. +#define NH_FLD_IPV4_ID (NH_FLD_IPV4_VER << 4)
  9308. +#define NH_FLD_IPV4_FLAG_D (NH_FLD_IPV4_VER << 5)
  9309. +#define NH_FLD_IPV4_FLAG_M (NH_FLD_IPV4_VER << 6)
  9310. +#define NH_FLD_IPV4_OFFSET (NH_FLD_IPV4_VER << 7)
  9311. +#define NH_FLD_IPV4_TTL (NH_FLD_IPV4_VER << 8)
  9312. +#define NH_FLD_IPV4_PROTO (NH_FLD_IPV4_VER << 9)
  9313. +#define NH_FLD_IPV4_CKSUM (NH_FLD_IPV4_VER << 10)
  9314. +#define NH_FLD_IPV4_SRC_IP (NH_FLD_IPV4_VER << 11)
  9315. +#define NH_FLD_IPV4_DST_IP (NH_FLD_IPV4_VER << 12)
  9316. +#define NH_FLD_IPV4_OPTS (NH_FLD_IPV4_VER << 13)
  9317. +#define NH_FLD_IPV4_OPTS_COUNT (NH_FLD_IPV4_VER << 14)
  9318. +#define NH_FLD_IPV4_ALL_FIELDS ((NH_FLD_IPV4_VER << 15) - 1)
  9319. +
  9320. +#define NH_FLD_IPV4_ADDR_SIZE 4
  9321. +#define NH_FLD_IPV4_PROTO_SIZE 1
  9322. +
  9323. +/***************************** IPV6 fields *********************************/
  9324. +#define NH_FLD_IPV6_VER (1)
  9325. +#define NH_FLD_IPV6_TC (NH_FLD_IPV6_VER << 1)
  9326. +#define NH_FLD_IPV6_SRC_IP (NH_FLD_IPV6_VER << 2)
  9327. +#define NH_FLD_IPV6_DST_IP (NH_FLD_IPV6_VER << 3)
  9328. +#define NH_FLD_IPV6_NEXT_HDR (NH_FLD_IPV6_VER << 4)
  9329. +#define NH_FLD_IPV6_FL (NH_FLD_IPV6_VER << 5)
  9330. +#define NH_FLD_IPV6_HOP_LIMIT (NH_FLD_IPV6_VER << 6)
  9331. +#define NH_FLD_IPV6_ID (NH_FLD_IPV6_VER << 7)
  9332. +#define NH_FLD_IPV6_ALL_FIELDS ((NH_FLD_IPV6_VER << 8) - 1)
  9333. +
  9334. +#define NH_FLD_IPV6_ADDR_SIZE 16
  9335. +#define NH_FLD_IPV6_NEXT_HDR_SIZE 1
  9336. +
  9337. +/***************************** ICMP fields *********************************/
  9338. +#define NH_FLD_ICMP_TYPE (1)
  9339. +#define NH_FLD_ICMP_CODE (NH_FLD_ICMP_TYPE << 1)
  9340. +#define NH_FLD_ICMP_CKSUM (NH_FLD_ICMP_TYPE << 2)
  9341. +#define NH_FLD_ICMP_ID (NH_FLD_ICMP_TYPE << 3)
  9342. +#define NH_FLD_ICMP_SQ_NUM (NH_FLD_ICMP_TYPE << 4)
  9343. +#define NH_FLD_ICMP_ALL_FIELDS ((NH_FLD_ICMP_TYPE << 5) - 1)
  9344. +
  9345. +#define NH_FLD_ICMP_CODE_SIZE 1
  9346. +#define NH_FLD_ICMP_TYPE_SIZE 1
  9347. +
  9348. +/***************************** IGMP fields *********************************/
  9349. +#define NH_FLD_IGMP_VERSION (1)
  9350. +#define NH_FLD_IGMP_TYPE (NH_FLD_IGMP_VERSION << 1)
  9351. +#define NH_FLD_IGMP_CKSUM (NH_FLD_IGMP_VERSION << 2)
  9352. +#define NH_FLD_IGMP_DATA (NH_FLD_IGMP_VERSION << 3)
  9353. +#define NH_FLD_IGMP_ALL_FIELDS ((NH_FLD_IGMP_VERSION << 4) - 1)
  9354. +
  9355. +/***************************** TCP fields **********************************/
  9356. +#define NH_FLD_TCP_PORT_SRC (1)
  9357. +#define NH_FLD_TCP_PORT_DST (NH_FLD_TCP_PORT_SRC << 1)
  9358. +#define NH_FLD_TCP_SEQ (NH_FLD_TCP_PORT_SRC << 2)
  9359. +#define NH_FLD_TCP_ACK (NH_FLD_TCP_PORT_SRC << 3)
  9360. +#define NH_FLD_TCP_OFFSET (NH_FLD_TCP_PORT_SRC << 4)
  9361. +#define NH_FLD_TCP_FLAGS (NH_FLD_TCP_PORT_SRC << 5)
  9362. +#define NH_FLD_TCP_WINDOW (NH_FLD_TCP_PORT_SRC << 6)
  9363. +#define NH_FLD_TCP_CKSUM (NH_FLD_TCP_PORT_SRC << 7)
  9364. +#define NH_FLD_TCP_URGPTR (NH_FLD_TCP_PORT_SRC << 8)
  9365. +#define NH_FLD_TCP_OPTS (NH_FLD_TCP_PORT_SRC << 9)
  9366. +#define NH_FLD_TCP_OPTS_COUNT (NH_FLD_TCP_PORT_SRC << 10)
  9367. +#define NH_FLD_TCP_ALL_FIELDS ((NH_FLD_TCP_PORT_SRC << 11) - 1)
  9368. +
  9369. +#define NH_FLD_TCP_PORT_SIZE 2
  9370. +
  9371. +/***************************** UDP fields **********************************/
  9372. +#define NH_FLD_UDP_PORT_SRC (1)
  9373. +#define NH_FLD_UDP_PORT_DST (NH_FLD_UDP_PORT_SRC << 1)
  9374. +#define NH_FLD_UDP_LEN (NH_FLD_UDP_PORT_SRC << 2)
  9375. +#define NH_FLD_UDP_CKSUM (NH_FLD_UDP_PORT_SRC << 3)
  9376. +#define NH_FLD_UDP_ALL_FIELDS ((NH_FLD_UDP_PORT_SRC << 4) - 1)
  9377. +
  9378. +#define NH_FLD_UDP_PORT_SIZE 2
  9379. +
  9380. +/*************************** UDP-lite fields *******************************/
  9381. +#define NH_FLD_UDP_LITE_PORT_SRC (1)
  9382. +#define NH_FLD_UDP_LITE_PORT_DST (NH_FLD_UDP_LITE_PORT_SRC << 1)
  9383. +#define NH_FLD_UDP_LITE_ALL_FIELDS \
  9384. + ((NH_FLD_UDP_LITE_PORT_SRC << 2) - 1)
  9385. +
  9386. +#define NH_FLD_UDP_LITE_PORT_SIZE 2
  9387. +
  9388. +/*************************** UDP-encap-ESP fields **************************/
  9389. +#define NH_FLD_UDP_ENC_ESP_PORT_SRC (1)
  9390. +#define NH_FLD_UDP_ENC_ESP_PORT_DST (NH_FLD_UDP_ENC_ESP_PORT_SRC << 1)
  9391. +#define NH_FLD_UDP_ENC_ESP_LEN (NH_FLD_UDP_ENC_ESP_PORT_SRC << 2)
  9392. +#define NH_FLD_UDP_ENC_ESP_CKSUM (NH_FLD_UDP_ENC_ESP_PORT_SRC << 3)
  9393. +#define NH_FLD_UDP_ENC_ESP_SPI (NH_FLD_UDP_ENC_ESP_PORT_SRC << 4)
  9394. +#define NH_FLD_UDP_ENC_ESP_SEQUENCE_NUM (NH_FLD_UDP_ENC_ESP_PORT_SRC << 5)
  9395. +#define NH_FLD_UDP_ENC_ESP_ALL_FIELDS \
  9396. + ((NH_FLD_UDP_ENC_ESP_PORT_SRC << 6) - 1)
  9397. +
  9398. +#define NH_FLD_UDP_ENC_ESP_PORT_SIZE 2
  9399. +#define NH_FLD_UDP_ENC_ESP_SPI_SIZE 4
  9400. +
  9401. +/***************************** SCTP fields *********************************/
  9402. +#define NH_FLD_SCTP_PORT_SRC (1)
  9403. +#define NH_FLD_SCTP_PORT_DST (NH_FLD_SCTP_PORT_SRC << 1)
  9404. +#define NH_FLD_SCTP_VER_TAG (NH_FLD_SCTP_PORT_SRC << 2)
  9405. +#define NH_FLD_SCTP_CKSUM (NH_FLD_SCTP_PORT_SRC << 3)
  9406. +#define NH_FLD_SCTP_ALL_FIELDS ((NH_FLD_SCTP_PORT_SRC << 4) - 1)
  9407. +
  9408. +#define NH_FLD_SCTP_PORT_SIZE 2
  9409. +
  9410. +/***************************** DCCP fields *********************************/
  9411. +#define NH_FLD_DCCP_PORT_SRC (1)
  9412. +#define NH_FLD_DCCP_PORT_DST (NH_FLD_DCCP_PORT_SRC << 1)
  9413. +#define NH_FLD_DCCP_ALL_FIELDS ((NH_FLD_DCCP_PORT_SRC << 2) - 1)
  9414. +
  9415. +#define NH_FLD_DCCP_PORT_SIZE 2
  9416. +
  9417. +/***************************** IPHC fields *********************************/
  9418. +#define NH_FLD_IPHC_CID (1)
  9419. +#define NH_FLD_IPHC_CID_TYPE (NH_FLD_IPHC_CID << 1)
  9420. +#define NH_FLD_IPHC_HCINDEX (NH_FLD_IPHC_CID << 2)
  9421. +#define NH_FLD_IPHC_GEN (NH_FLD_IPHC_CID << 3)
  9422. +#define NH_FLD_IPHC_D_BIT (NH_FLD_IPHC_CID << 4)
  9423. +#define NH_FLD_IPHC_ALL_FIELDS ((NH_FLD_IPHC_CID << 5) - 1)
  9424. +
  9425. +/***************************** SCTP fields *********************************/
  9426. +#define NH_FLD_SCTP_CHUNK_DATA_TYPE (1)
  9427. +#define NH_FLD_SCTP_CHUNK_DATA_FLAGS (NH_FLD_SCTP_CHUNK_DATA_TYPE << 1)
  9428. +#define NH_FLD_SCTP_CHUNK_DATA_LENGTH (NH_FLD_SCTP_CHUNK_DATA_TYPE << 2)
  9429. +#define NH_FLD_SCTP_CHUNK_DATA_TSN (NH_FLD_SCTP_CHUNK_DATA_TYPE << 3)
  9430. +#define NH_FLD_SCTP_CHUNK_DATA_STREAM_ID (NH_FLD_SCTP_CHUNK_DATA_TYPE << 4)
  9431. +#define NH_FLD_SCTP_CHUNK_DATA_STREAM_SQN (NH_FLD_SCTP_CHUNK_DATA_TYPE << 5)
  9432. +#define NH_FLD_SCTP_CHUNK_DATA_PAYLOAD_PID (NH_FLD_SCTP_CHUNK_DATA_TYPE << 6)
  9433. +#define NH_FLD_SCTP_CHUNK_DATA_UNORDERED (NH_FLD_SCTP_CHUNK_DATA_TYPE << 7)
  9434. +#define NH_FLD_SCTP_CHUNK_DATA_BEGGINING (NH_FLD_SCTP_CHUNK_DATA_TYPE << 8)
  9435. +#define NH_FLD_SCTP_CHUNK_DATA_END (NH_FLD_SCTP_CHUNK_DATA_TYPE << 9)
  9436. +#define NH_FLD_SCTP_CHUNK_DATA_ALL_FIELDS \
  9437. + ((NH_FLD_SCTP_CHUNK_DATA_TYPE << 10) - 1)
  9438. +
  9439. +/*************************** L2TPV2 fields *********************************/
  9440. +#define NH_FLD_L2TPV2_TYPE_BIT (1)
  9441. +#define NH_FLD_L2TPV2_LENGTH_BIT (NH_FLD_L2TPV2_TYPE_BIT << 1)
  9442. +#define NH_FLD_L2TPV2_SEQUENCE_BIT (NH_FLD_L2TPV2_TYPE_BIT << 2)
  9443. +#define NH_FLD_L2TPV2_OFFSET_BIT (NH_FLD_L2TPV2_TYPE_BIT << 3)
  9444. +#define NH_FLD_L2TPV2_PRIORITY_BIT (NH_FLD_L2TPV2_TYPE_BIT << 4)
  9445. +#define NH_FLD_L2TPV2_VERSION (NH_FLD_L2TPV2_TYPE_BIT << 5)
  9446. +#define NH_FLD_L2TPV2_LEN (NH_FLD_L2TPV2_TYPE_BIT << 6)
  9447. +#define NH_FLD_L2TPV2_TUNNEL_ID (NH_FLD_L2TPV2_TYPE_BIT << 7)
  9448. +#define NH_FLD_L2TPV2_SESSION_ID (NH_FLD_L2TPV2_TYPE_BIT << 8)
  9449. +#define NH_FLD_L2TPV2_NS (NH_FLD_L2TPV2_TYPE_BIT << 9)
  9450. +#define NH_FLD_L2TPV2_NR (NH_FLD_L2TPV2_TYPE_BIT << 10)
  9451. +#define NH_FLD_L2TPV2_OFFSET_SIZE (NH_FLD_L2TPV2_TYPE_BIT << 11)
  9452. +#define NH_FLD_L2TPV2_FIRST_BYTE (NH_FLD_L2TPV2_TYPE_BIT << 12)
  9453. +#define NH_FLD_L2TPV2_ALL_FIELDS \
  9454. + ((NH_FLD_L2TPV2_TYPE_BIT << 13) - 1)
  9455. +
  9456. +/*************************** L2TPV3 fields *********************************/
  9457. +#define NH_FLD_L2TPV3_CTRL_TYPE_BIT (1)
  9458. +#define NH_FLD_L2TPV3_CTRL_LENGTH_BIT (NH_FLD_L2TPV3_CTRL_TYPE_BIT << 1)
  9459. +#define NH_FLD_L2TPV3_CTRL_SEQUENCE_BIT (NH_FLD_L2TPV3_CTRL_TYPE_BIT << 2)
  9460. +#define NH_FLD_L2TPV3_CTRL_VERSION (NH_FLD_L2TPV3_CTRL_TYPE_BIT << 3)
  9461. +#define NH_FLD_L2TPV3_CTRL_LENGTH (NH_FLD_L2TPV3_CTRL_TYPE_BIT << 4)
  9462. +#define NH_FLD_L2TPV3_CTRL_CONTROL (NH_FLD_L2TPV3_CTRL_TYPE_BIT << 5)
  9463. +#define NH_FLD_L2TPV3_CTRL_SENT (NH_FLD_L2TPV3_CTRL_TYPE_BIT << 6)
  9464. +#define NH_FLD_L2TPV3_CTRL_RECV (NH_FLD_L2TPV3_CTRL_TYPE_BIT << 7)
  9465. +#define NH_FLD_L2TPV3_CTRL_FIRST_BYTE (NH_FLD_L2TPV3_CTRL_TYPE_BIT << 8)
  9466. +#define NH_FLD_L2TPV3_CTRL_ALL_FIELDS \
  9467. + ((NH_FLD_L2TPV3_CTRL_TYPE_BIT << 9) - 1)
  9468. +
  9469. +#define NH_FLD_L2TPV3_SESS_TYPE_BIT (1)
  9470. +#define NH_FLD_L2TPV3_SESS_VERSION (NH_FLD_L2TPV3_SESS_TYPE_BIT << 1)
  9471. +#define NH_FLD_L2TPV3_SESS_ID (NH_FLD_L2TPV3_SESS_TYPE_BIT << 2)
  9472. +#define NH_FLD_L2TPV3_SESS_COOKIE (NH_FLD_L2TPV3_SESS_TYPE_BIT << 3)
  9473. +#define NH_FLD_L2TPV3_SESS_ALL_FIELDS \
  9474. + ((NH_FLD_L2TPV3_SESS_TYPE_BIT << 4) - 1)
  9475. +
  9476. +/**************************** PPP fields ***********************************/
  9477. +#define NH_FLD_PPP_PID (1)
  9478. +#define NH_FLD_PPP_COMPRESSED (NH_FLD_PPP_PID << 1)
  9479. +#define NH_FLD_PPP_ALL_FIELDS ((NH_FLD_PPP_PID << 2) - 1)
  9480. +
  9481. +/************************** PPPoE fields ***********************************/
  9482. +#define NH_FLD_PPPOE_VER (1)
  9483. +#define NH_FLD_PPPOE_TYPE (NH_FLD_PPPOE_VER << 1)
  9484. +#define NH_FLD_PPPOE_CODE (NH_FLD_PPPOE_VER << 2)
  9485. +#define NH_FLD_PPPOE_SID (NH_FLD_PPPOE_VER << 3)
  9486. +#define NH_FLD_PPPOE_LEN (NH_FLD_PPPOE_VER << 4)
  9487. +#define NH_FLD_PPPOE_SESSION (NH_FLD_PPPOE_VER << 5)
  9488. +#define NH_FLD_PPPOE_PID (NH_FLD_PPPOE_VER << 6)
  9489. +#define NH_FLD_PPPOE_ALL_FIELDS ((NH_FLD_PPPOE_VER << 7) - 1)
  9490. +
  9491. +/************************* PPP-Mux fields **********************************/
  9492. +#define NH_FLD_PPPMUX_PID (1)
  9493. +#define NH_FLD_PPPMUX_CKSUM (NH_FLD_PPPMUX_PID << 1)
  9494. +#define NH_FLD_PPPMUX_COMPRESSED (NH_FLD_PPPMUX_PID << 2)
  9495. +#define NH_FLD_PPPMUX_ALL_FIELDS ((NH_FLD_PPPMUX_PID << 3) - 1)
  9496. +
  9497. +/*********************** PPP-Mux sub-frame fields **************************/
  9498. +#define NH_FLD_PPPMUX_SUBFRM_PFF (1)
  9499. +#define NH_FLD_PPPMUX_SUBFRM_LXT (NH_FLD_PPPMUX_SUBFRM_PFF << 1)
  9500. +#define NH_FLD_PPPMUX_SUBFRM_LEN (NH_FLD_PPPMUX_SUBFRM_PFF << 2)
  9501. +#define NH_FLD_PPPMUX_SUBFRM_PID (NH_FLD_PPPMUX_SUBFRM_PFF << 3)
  9502. +#define NH_FLD_PPPMUX_SUBFRM_USE_PID (NH_FLD_PPPMUX_SUBFRM_PFF << 4)
  9503. +#define NH_FLD_PPPMUX_SUBFRM_ALL_FIELDS \
  9504. + ((NH_FLD_PPPMUX_SUBFRM_PFF << 5) - 1)
  9505. +
  9506. +/*************************** LLC fields ************************************/
  9507. +#define NH_FLD_LLC_DSAP (1)
  9508. +#define NH_FLD_LLC_SSAP (NH_FLD_LLC_DSAP << 1)
  9509. +#define NH_FLD_LLC_CTRL (NH_FLD_LLC_DSAP << 2)
  9510. +#define NH_FLD_LLC_ALL_FIELDS ((NH_FLD_LLC_DSAP << 3) - 1)
  9511. +
  9512. +/*************************** NLPID fields **********************************/
  9513. +#define NH_FLD_NLPID_NLPID (1)
  9514. +#define NH_FLD_NLPID_ALL_FIELDS ((NH_FLD_NLPID_NLPID << 1) - 1)
  9515. +
  9516. +/*************************** SNAP fields ***********************************/
  9517. +#define NH_FLD_SNAP_OUI (1)
  9518. +#define NH_FLD_SNAP_PID (NH_FLD_SNAP_OUI << 1)
  9519. +#define NH_FLD_SNAP_ALL_FIELDS ((NH_FLD_SNAP_OUI << 2) - 1)
  9520. +
  9521. +/*************************** LLC SNAP fields *******************************/
  9522. +#define NH_FLD_LLC_SNAP_TYPE (1)
  9523. +#define NH_FLD_LLC_SNAP_ALL_FIELDS ((NH_FLD_LLC_SNAP_TYPE << 1) - 1)
  9524. +
  9525. +#define NH_FLD_ARP_HTYPE (1)
  9526. +#define NH_FLD_ARP_PTYPE (NH_FLD_ARP_HTYPE << 1)
  9527. +#define NH_FLD_ARP_HLEN (NH_FLD_ARP_HTYPE << 2)
  9528. +#define NH_FLD_ARP_PLEN (NH_FLD_ARP_HTYPE << 3)
  9529. +#define NH_FLD_ARP_OPER (NH_FLD_ARP_HTYPE << 4)
  9530. +#define NH_FLD_ARP_SHA (NH_FLD_ARP_HTYPE << 5)
  9531. +#define NH_FLD_ARP_SPA (NH_FLD_ARP_HTYPE << 6)
  9532. +#define NH_FLD_ARP_THA (NH_FLD_ARP_HTYPE << 7)
  9533. +#define NH_FLD_ARP_TPA (NH_FLD_ARP_HTYPE << 8)
  9534. +#define NH_FLD_ARP_ALL_FIELDS ((NH_FLD_ARP_HTYPE << 9) - 1)
  9535. +
  9536. +/*************************** RFC2684 fields ********************************/
  9537. +#define NH_FLD_RFC2684_LLC (1)
  9538. +#define NH_FLD_RFC2684_NLPID (NH_FLD_RFC2684_LLC << 1)
  9539. +#define NH_FLD_RFC2684_OUI (NH_FLD_RFC2684_LLC << 2)
  9540. +#define NH_FLD_RFC2684_PID (NH_FLD_RFC2684_LLC << 3)
  9541. +#define NH_FLD_RFC2684_VPN_OUI (NH_FLD_RFC2684_LLC << 4)
  9542. +#define NH_FLD_RFC2684_VPN_IDX (NH_FLD_RFC2684_LLC << 5)
  9543. +#define NH_FLD_RFC2684_ALL_FIELDS ((NH_FLD_RFC2684_LLC << 6) - 1)
  9544. +
  9545. +/*************************** User defined fields ***************************/
  9546. +#define NH_FLD_USER_DEFINED_SRCPORT (1)
  9547. +#define NH_FLD_USER_DEFINED_PCDID (NH_FLD_USER_DEFINED_SRCPORT << 1)
  9548. +#define NH_FLD_USER_DEFINED_ALL_FIELDS \
  9549. + ((NH_FLD_USER_DEFINED_SRCPORT << 2) - 1)
  9550. +
  9551. +/*************************** Payload fields ********************************/
  9552. +#define NH_FLD_PAYLOAD_BUFFER (1)
  9553. +#define NH_FLD_PAYLOAD_SIZE (NH_FLD_PAYLOAD_BUFFER << 1)
  9554. +#define NH_FLD_MAX_FRM_SIZE (NH_FLD_PAYLOAD_BUFFER << 2)
  9555. +#define NH_FLD_MIN_FRM_SIZE (NH_FLD_PAYLOAD_BUFFER << 3)
  9556. +#define NH_FLD_PAYLOAD_TYPE (NH_FLD_PAYLOAD_BUFFER << 4)
  9557. +#define NH_FLD_FRAME_SIZE (NH_FLD_PAYLOAD_BUFFER << 5)
  9558. +#define NH_FLD_PAYLOAD_ALL_FIELDS ((NH_FLD_PAYLOAD_BUFFER << 6) - 1)
  9559. +
  9560. +/*************************** GRE fields ************************************/
  9561. +#define NH_FLD_GRE_TYPE (1)
  9562. +#define NH_FLD_GRE_ALL_FIELDS ((NH_FLD_GRE_TYPE << 1) - 1)
  9563. +
  9564. +/*************************** MINENCAP fields *******************************/
  9565. +#define NH_FLD_MINENCAP_SRC_IP (1)
  9566. +#define NH_FLD_MINENCAP_DST_IP (NH_FLD_MINENCAP_SRC_IP << 1)
  9567. +#define NH_FLD_MINENCAP_TYPE (NH_FLD_MINENCAP_SRC_IP << 2)
  9568. +#define NH_FLD_MINENCAP_ALL_FIELDS \
  9569. + ((NH_FLD_MINENCAP_SRC_IP << 3) - 1)
  9570. +
  9571. +/*************************** IPSEC AH fields *******************************/
  9572. +#define NH_FLD_IPSEC_AH_SPI (1)
  9573. +#define NH_FLD_IPSEC_AH_NH (NH_FLD_IPSEC_AH_SPI << 1)
  9574. +#define NH_FLD_IPSEC_AH_ALL_FIELDS ((NH_FLD_IPSEC_AH_SPI << 2) - 1)
  9575. +
  9576. +/*************************** IPSEC ESP fields ******************************/
  9577. +#define NH_FLD_IPSEC_ESP_SPI (1)
  9578. +#define NH_FLD_IPSEC_ESP_SEQUENCE_NUM (NH_FLD_IPSEC_ESP_SPI << 1)
  9579. +#define NH_FLD_IPSEC_ESP_ALL_FIELDS ((NH_FLD_IPSEC_ESP_SPI << 2) - 1)
  9580. +
  9581. +#define NH_FLD_IPSEC_ESP_SPI_SIZE 4
  9582. +
  9583. +/*************************** MPLS fields ***********************************/
  9584. +#define NH_FLD_MPLS_LABEL_STACK (1)
  9585. +#define NH_FLD_MPLS_LABEL_STACK_ALL_FIELDS \
  9586. + ((NH_FLD_MPLS_LABEL_STACK << 1) - 1)
  9587. +
  9588. +/*************************** MACSEC fields *********************************/
  9589. +#define NH_FLD_MACSEC_SECTAG (1)
  9590. +#define NH_FLD_MACSEC_ALL_FIELDS ((NH_FLD_MACSEC_SECTAG << 1) - 1)
  9591. +
  9592. +/*************************** GTP fields ************************************/
  9593. +#define NH_FLD_GTP_TEID (1)
  9594. +
  9595. +/* Protocol options */
  9596. +
  9597. +/* Ethernet options */
  9598. +#define NH_OPT_ETH_BROADCAST 1
  9599. +#define NH_OPT_ETH_MULTICAST 2
  9600. +#define NH_OPT_ETH_UNICAST 3
  9601. +#define NH_OPT_ETH_BPDU 4
  9602. +
  9603. +#define NH_ETH_IS_MULTICAST_ADDR(addr) (addr[0] & 0x01)
  9604. +/* also applicable for broadcast */
  9605. +
  9606. +/* VLAN options */
  9607. +#define NH_OPT_VLAN_CFI 1
  9608. +
  9609. +/* IPV4 options */
  9610. +#define NH_OPT_IPV4_UNICAST 1
  9611. +#define NH_OPT_IPV4_MULTICAST 2
  9612. +#define NH_OPT_IPV4_BROADCAST 3
  9613. +#define NH_OPT_IPV4_OPTION 4
  9614. +#define NH_OPT_IPV4_FRAG 5
  9615. +#define NH_OPT_IPV4_INITIAL_FRAG 6
  9616. +
  9617. +/* IPV6 options */
  9618. +#define NH_OPT_IPV6_UNICAST 1
  9619. +#define NH_OPT_IPV6_MULTICAST 2
  9620. +#define NH_OPT_IPV6_OPTION 3
  9621. +#define NH_OPT_IPV6_FRAG 4
  9622. +#define NH_OPT_IPV6_INITIAL_FRAG 5
  9623. +
  9624. +/* General IP options (may be used for any version) */
  9625. +#define NH_OPT_IP_FRAG 1
  9626. +#define NH_OPT_IP_INITIAL_FRAG 2
  9627. +#define NH_OPT_IP_OPTION 3
  9628. +
  9629. +/* Minenc. options */
  9630. +#define NH_OPT_MINENCAP_SRC_ADDR_PRESENT 1
  9631. +
  9632. +/* GRE. options */
  9633. +#define NH_OPT_GRE_ROUTING_PRESENT 1
  9634. +
  9635. +/* TCP options */
  9636. +#define NH_OPT_TCP_OPTIONS 1
  9637. +#define NH_OPT_TCP_CONTROL_HIGH_BITS 2
  9638. +#define NH_OPT_TCP_CONTROL_LOW_BITS 3
  9639. +
  9640. +/* CAPWAP options */
  9641. +#define NH_OPT_CAPWAP_DTLS 1
  9642. +
  9643. +enum net_prot {
  9644. + NET_PROT_NONE = 0,
  9645. + NET_PROT_PAYLOAD,
  9646. + NET_PROT_ETH,
  9647. + NET_PROT_VLAN,
  9648. + NET_PROT_IPV4,
  9649. + NET_PROT_IPV6,
  9650. + NET_PROT_IP,
  9651. + NET_PROT_TCP,
  9652. + NET_PROT_UDP,
  9653. + NET_PROT_UDP_LITE,
  9654. + NET_PROT_IPHC,
  9655. + NET_PROT_SCTP,
  9656. + NET_PROT_SCTP_CHUNK_DATA,
  9657. + NET_PROT_PPPOE,
  9658. + NET_PROT_PPP,
  9659. + NET_PROT_PPPMUX,
  9660. + NET_PROT_PPPMUX_SUBFRM,
  9661. + NET_PROT_L2TPV2,
  9662. + NET_PROT_L2TPV3_CTRL,
  9663. + NET_PROT_L2TPV3_SESS,
  9664. + NET_PROT_LLC,
  9665. + NET_PROT_LLC_SNAP,
  9666. + NET_PROT_NLPID,
  9667. + NET_PROT_SNAP,
  9668. + NET_PROT_MPLS,
  9669. + NET_PROT_IPSEC_AH,
  9670. + NET_PROT_IPSEC_ESP,
  9671. + NET_PROT_UDP_ENC_ESP, /* RFC 3948 */
  9672. + NET_PROT_MACSEC,
  9673. + NET_PROT_GRE,
  9674. + NET_PROT_MINENCAP,
  9675. + NET_PROT_DCCP,
  9676. + NET_PROT_ICMP,
  9677. + NET_PROT_IGMP,
  9678. + NET_PROT_ARP,
  9679. + NET_PROT_CAPWAP_DATA,
  9680. + NET_PROT_CAPWAP_CTRL,
  9681. + NET_PROT_RFC2684,
  9682. + NET_PROT_ICMPV6,
  9683. + NET_PROT_FCOE,
  9684. + NET_PROT_FIP,
  9685. + NET_PROT_ISCSI,
  9686. + NET_PROT_GTP,
  9687. + NET_PROT_USER_DEFINED_L2,
  9688. + NET_PROT_USER_DEFINED_L3,
  9689. + NET_PROT_USER_DEFINED_L4,
  9690. + NET_PROT_USER_DEFINED_L5,
  9691. + NET_PROT_USER_DEFINED_SHIM1,
  9692. + NET_PROT_USER_DEFINED_SHIM2,
  9693. +
  9694. + NET_PROT_DUMMY_LAST
  9695. +};
  9696. +
  9697. +/*! IEEE8021.Q */
  9698. +#define NH_IEEE8021Q_ETYPE 0x8100
  9699. +#define NH_IEEE8021Q_HDR(etype, pcp, dei, vlan_id) \
  9700. + ((((u32)((etype) & 0xFFFF)) << 16) | \
  9701. + (((u32)((pcp) & 0x07)) << 13) | \
  9702. + (((u32)((dei) & 0x01)) << 12) | \
  9703. + (((u32)((vlan_id) & 0xFFF))))
  9704. +
  9705. +#endif /* __FSL_NET_H */
  9706. --- /dev/null
  9707. +++ b/drivers/staging/fsl-dpaa2/ethsw/Kconfig
  9708. @@ -0,0 +1,6 @@
  9709. +config FSL_DPAA2_ETHSW
  9710. + tristate "DPAA2 Ethernet Switch"
  9711. + depends on FSL_MC_BUS && FSL_DPAA2
  9712. + default y
  9713. + ---help---
  9714. + Prototype driver for DPAA2 Ethernet Switch.
  9715. --- /dev/null
  9716. +++ b/drivers/staging/fsl-dpaa2/ethsw/Makefile
  9717. @@ -0,0 +1,10 @@
  9718. +
  9719. +obj-$(CONFIG_FSL_DPAA2_ETHSW) += dpaa2-ethsw.o
  9720. +
  9721. +dpaa2-ethsw-objs := switch.o dpsw.o
  9722. +
  9723. +all:
  9724. + make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules
  9725. +
  9726. +clean:
  9727. + make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean
  9728. --- /dev/null
  9729. +++ b/drivers/staging/fsl-dpaa2/ethsw/dpsw-cmd.h
  9730. @@ -0,0 +1,851 @@
  9731. +/* Copyright 2013-2016 Freescale Semiconductor Inc.
  9732. + *
  9733. + * Redistribution and use in source and binary forms, with or without
  9734. + * modification, are permitted provided that the following conditions are met:
  9735. + * * Redistributions of source code must retain the above copyright
  9736. + * notice, this list of conditions and the following disclaimer.
  9737. + * * Redistributions in binary form must reproduce the above copyright
  9738. + * notice, this list of conditions and the following disclaimer in the
  9739. + * documentation and/or other materials provided with the distribution.
  9740. + * * Neither the name of the above-listed copyright holders nor the
  9741. + * names of any contributors may be used to endorse or promote products
  9742. + * derived from this software without specific prior written permission.
  9743. + *
  9744. + *
  9745. + * ALTERNATIVELY, this software may be distributed under the terms of the
  9746. + * GNU General Public License ("GPL") as published by the Free Software
  9747. + * Foundation, either version 2 of that License or (at your option) any
  9748. + * later version.
  9749. + *
  9750. + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  9751. + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  9752. + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  9753. + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
  9754. + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  9755. + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  9756. + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  9757. + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  9758. + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  9759. + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  9760. + * POSSIBILITY OF SUCH DAMAGE.
  9761. + */
  9762. +#ifndef __FSL_DPSW_CMD_H
  9763. +#define __FSL_DPSW_CMD_H
  9764. +
  9765. +/* DPSW Version */
  9766. +#define DPSW_VER_MAJOR 8
  9767. +#define DPSW_VER_MINOR 0
  9768. +
  9769. +#define DPSW_CMD_BASE_VERSION 1
  9770. +#define DPSW_CMD_ID_OFFSET 4
  9771. +
  9772. +#define DPSW_CMD_ID(id) (((id) << DPSW_CMD_ID_OFFSET) | DPSW_CMD_BASE_VERSION)
  9773. +
  9774. +/* Command IDs */
  9775. +#define DPSW_CMDID_CLOSE DPSW_CMD_ID(0x800)
  9776. +#define DPSW_CMDID_OPEN DPSW_CMD_ID(0x802)
  9777. +
  9778. +#define DPSW_CMDID_GET_API_VERSION DPSW_CMD_ID(0xa02)
  9779. +
  9780. +#define DPSW_CMDID_ENABLE DPSW_CMD_ID(0x002)
  9781. +#define DPSW_CMDID_DISABLE DPSW_CMD_ID(0x003)
  9782. +#define DPSW_CMDID_GET_ATTR DPSW_CMD_ID(0x004)
  9783. +#define DPSW_CMDID_RESET DPSW_CMD_ID(0x005)
  9784. +#define DPSW_CMDID_IS_ENABLED DPSW_CMD_ID(0x006)
  9785. +
  9786. +#define DPSW_CMDID_SET_IRQ DPSW_CMD_ID(0x010)
  9787. +#define DPSW_CMDID_GET_IRQ DPSW_CMD_ID(0x011)
  9788. +#define DPSW_CMDID_SET_IRQ_ENABLE DPSW_CMD_ID(0x012)
  9789. +#define DPSW_CMDID_GET_IRQ_ENABLE DPSW_CMD_ID(0x013)
  9790. +#define DPSW_CMDID_SET_IRQ_MASK DPSW_CMD_ID(0x014)
  9791. +#define DPSW_CMDID_GET_IRQ_MASK DPSW_CMD_ID(0x015)
  9792. +#define DPSW_CMDID_GET_IRQ_STATUS DPSW_CMD_ID(0x016)
  9793. +#define DPSW_CMDID_CLEAR_IRQ_STATUS DPSW_CMD_ID(0x017)
  9794. +
  9795. +#define DPSW_CMDID_SET_REFLECTION_IF DPSW_CMD_ID(0x022)
  9796. +
  9797. +#define DPSW_CMDID_ADD_CUSTOM_TPID DPSW_CMD_ID(0x024)
  9798. +
  9799. +#define DPSW_CMDID_REMOVE_CUSTOM_TPID DPSW_CMD_ID(0x026)
  9800. +
  9801. +#define DPSW_CMDID_IF_SET_TCI DPSW_CMD_ID(0x030)
  9802. +#define DPSW_CMDID_IF_SET_STP DPSW_CMD_ID(0x031)
  9803. +#define DPSW_CMDID_IF_SET_ACCEPTED_FRAMES DPSW_CMD_ID(0x032)
  9804. +#define DPSW_CMDID_SET_IF_ACCEPT_ALL_VLAN DPSW_CMD_ID(0x033)
  9805. +#define DPSW_CMDID_IF_GET_COUNTER DPSW_CMD_ID(0x034)
  9806. +#define DPSW_CMDID_IF_SET_COUNTER DPSW_CMD_ID(0x035)
  9807. +#define DPSW_CMDID_IF_SET_TX_SELECTION DPSW_CMD_ID(0x036)
  9808. +#define DPSW_CMDID_IF_ADD_REFLECTION DPSW_CMD_ID(0x037)
  9809. +#define DPSW_CMDID_IF_REMOVE_REFLECTION DPSW_CMD_ID(0x038)
  9810. +#define DPSW_CMDID_IF_SET_FLOODING_METERING DPSW_CMD_ID(0x039)
  9811. +#define DPSW_CMDID_IF_SET_METERING DPSW_CMD_ID(0x03A)
  9812. +#define DPSW_CMDID_IF_SET_EARLY_DROP DPSW_CMD_ID(0x03B)
  9813. +
  9814. +#define DPSW_CMDID_IF_ENABLE DPSW_CMD_ID(0x03D)
  9815. +#define DPSW_CMDID_IF_DISABLE DPSW_CMD_ID(0x03E)
  9816. +
  9817. +#define DPSW_CMDID_IF_GET_ATTR DPSW_CMD_ID(0x042)
  9818. +
  9819. +#define DPSW_CMDID_IF_SET_MAX_FRAME_LENGTH DPSW_CMD_ID(0x044)
  9820. +#define DPSW_CMDID_IF_GET_MAX_FRAME_LENGTH DPSW_CMD_ID(0x045)
  9821. +#define DPSW_CMDID_IF_GET_LINK_STATE DPSW_CMD_ID(0x046)
  9822. +#define DPSW_CMDID_IF_SET_FLOODING DPSW_CMD_ID(0x047)
  9823. +#define DPSW_CMDID_IF_SET_BROADCAST DPSW_CMD_ID(0x048)
  9824. +#define DPSW_CMDID_IF_SET_MULTICAST DPSW_CMD_ID(0x049)
  9825. +#define DPSW_CMDID_IF_GET_TCI DPSW_CMD_ID(0x04A)
  9826. +
  9827. +#define DPSW_CMDID_IF_SET_LINK_CFG DPSW_CMD_ID(0x04C)
  9828. +
  9829. +#define DPSW_CMDID_VLAN_ADD DPSW_CMD_ID(0x060)
  9830. +#define DPSW_CMDID_VLAN_ADD_IF DPSW_CMD_ID(0x061)
  9831. +#define DPSW_CMDID_VLAN_ADD_IF_UNTAGGED DPSW_CMD_ID(0x062)
  9832. +#define DPSW_CMDID_VLAN_ADD_IF_FLOODING DPSW_CMD_ID(0x063)
  9833. +#define DPSW_CMDID_VLAN_REMOVE_IF DPSW_CMD_ID(0x064)
  9834. +#define DPSW_CMDID_VLAN_REMOVE_IF_UNTAGGED DPSW_CMD_ID(0x065)
  9835. +#define DPSW_CMDID_VLAN_REMOVE_IF_FLOODING DPSW_CMD_ID(0x066)
  9836. +#define DPSW_CMDID_VLAN_REMOVE DPSW_CMD_ID(0x067)
  9837. +#define DPSW_CMDID_VLAN_GET_IF DPSW_CMD_ID(0x068)
  9838. +#define DPSW_CMDID_VLAN_GET_IF_FLOODING DPSW_CMD_ID(0x069)
  9839. +#define DPSW_CMDID_VLAN_GET_IF_UNTAGGED DPSW_CMD_ID(0x06A)
  9840. +#define DPSW_CMDID_VLAN_GET_ATTRIBUTES DPSW_CMD_ID(0x06B)
  9841. +
  9842. +#define DPSW_CMDID_FDB_GET_MULTICAST DPSW_CMD_ID(0x080)
  9843. +#define DPSW_CMDID_FDB_GET_UNICAST DPSW_CMD_ID(0x081)
  9844. +#define DPSW_CMDID_FDB_ADD DPSW_CMD_ID(0x082)
  9845. +#define DPSW_CMDID_FDB_REMOVE DPSW_CMD_ID(0x083)
  9846. +#define DPSW_CMDID_FDB_ADD_UNICAST DPSW_CMD_ID(0x084)
  9847. +#define DPSW_CMDID_FDB_REMOVE_UNICAST DPSW_CMD_ID(0x085)
  9848. +#define DPSW_CMDID_FDB_ADD_MULTICAST DPSW_CMD_ID(0x086)
  9849. +#define DPSW_CMDID_FDB_REMOVE_MULTICAST DPSW_CMD_ID(0x087)
  9850. +#define DPSW_CMDID_FDB_SET_LEARNING_MODE DPSW_CMD_ID(0x088)
  9851. +#define DPSW_CMDID_FDB_GET_ATTR DPSW_CMD_ID(0x089)
  9852. +
  9853. +#define DPSW_CMDID_ACL_ADD DPSW_CMD_ID(0x090)
  9854. +#define DPSW_CMDID_ACL_REMOVE DPSW_CMD_ID(0x091)
  9855. +#define DPSW_CMDID_ACL_ADD_ENTRY DPSW_CMD_ID(0x092)
  9856. +#define DPSW_CMDID_ACL_REMOVE_ENTRY DPSW_CMD_ID(0x093)
  9857. +#define DPSW_CMDID_ACL_ADD_IF DPSW_CMD_ID(0x094)
  9858. +#define DPSW_CMDID_ACL_REMOVE_IF DPSW_CMD_ID(0x095)
  9859. +#define DPSW_CMDID_ACL_GET_ATTR DPSW_CMD_ID(0x096)
  9860. +
  9861. +#define DPSW_CMDID_CTRL_IF_GET_ATTR DPSW_CMD_ID(0x0A0)
  9862. +#define DPSW_CMDID_CTRL_IF_SET_POOLS DPSW_CMD_ID(0x0A1)
  9863. +#define DPSW_CMDID_CTRL_IF_ENABLE DPSW_CMD_ID(0x0A2)
  9864. +#define DPSW_CMDID_CTRL_IF_DISABLE DPSW_CMD_ID(0x0A3)
  9865. +
  9866. +/* Macros for accessing command fields smaller than 1byte */
  9867. +#define DPSW_MASK(field) \
  9868. + GENMASK(DPSW_##field##_SHIFT + DPSW_##field##_SIZE - 1, \
  9869. + DPSW_##field##_SHIFT)
  9870. +#define dpsw_set_field(var, field, val) \
  9871. + ((var) |= (((val) << DPSW_##field##_SHIFT) & DPSW_MASK(field)))
  9872. +#define dpsw_get_field(var, field) \
  9873. + (((var) & DPSW_MASK(field)) >> DPSW_##field##_SHIFT)
  9874. +#define dpsw_get_bit(var, bit) \
  9875. + (((var) >> (bit)) & GENMASK(0, 0))
  9876. +
  9877. +static inline u64 dpsw_set_bit(u64 var, unsigned int bit, u8 val)
  9878. +{
  9879. + var |= (u64)val << bit & GENMASK(bit, bit);
  9880. + return var;
  9881. +}
  9882. +
  9883. +struct dpsw_cmd_open {
  9884. + __le32 dpsw_id;
  9885. +};
  9886. +
  9887. +#define DPSW_COMPONENT_TYPE_SHIFT 0
  9888. +#define DPSW_COMPONENT_TYPE_SIZE 4
  9889. +
  9890. +struct dpsw_cmd_create {
  9891. + /* cmd word 0 */
  9892. + __le16 num_ifs;
  9893. + u8 max_fdbs;
  9894. + u8 max_meters_per_if;
  9895. + /* from LSB: only the first 4 bits */
  9896. + u8 component_type;
  9897. + u8 pad[3];
  9898. + /* cmd word 1 */
  9899. + __le16 max_vlans;
  9900. + __le16 max_fdb_entries;
  9901. + __le16 fdb_aging_time;
  9902. + __le16 max_fdb_mc_groups;
  9903. + /* cmd word 2 */
  9904. + __le64 options;
  9905. +};
  9906. +
  9907. +struct dpsw_cmd_destroy {
  9908. + __le32 dpsw_id;
  9909. +};
  9910. +
  9911. +#define DPSW_ENABLE_SHIFT 0
  9912. +#define DPSW_ENABLE_SIZE 1
  9913. +
  9914. +struct dpsw_rsp_is_enabled {
  9915. + /* from LSB: enable:1 */
  9916. + u8 enabled;
  9917. +};
  9918. +
  9919. +struct dpsw_cmd_set_irq {
  9920. + /* cmd word 0 */
  9921. + u8 irq_index;
  9922. + u8 pad[3];
  9923. + __le32 irq_val;
  9924. + /* cmd word 1 */
  9925. + __le64 irq_addr;
  9926. + /* cmd word 2 */
  9927. + __le32 irq_num;
  9928. +};
  9929. +
  9930. +struct dpsw_cmd_get_irq {
  9931. + __le32 pad;
  9932. + u8 irq_index;
  9933. +};
  9934. +
  9935. +struct dpsw_rsp_get_irq {
  9936. + /* cmd word 0 */
  9937. + __le32 irq_val;
  9938. + __le32 pad;
  9939. + /* cmd word 1 */
  9940. + __le64 irq_addr;
  9941. + /* cmd word 2 */
  9942. + __le32 irq_num;
  9943. + __le32 irq_type;
  9944. +};
  9945. +
  9946. +struct dpsw_cmd_set_irq_enable {
  9947. + u8 enable_state;
  9948. + u8 pad[3];
  9949. + u8 irq_index;
  9950. +};
  9951. +
  9952. +struct dpsw_cmd_get_irq_enable {
  9953. + __le32 pad;
  9954. + u8 irq_index;
  9955. +};
  9956. +
  9957. +struct dpsw_rsp_get_irq_enable {
  9958. + u8 enable_state;
  9959. +};
  9960. +
  9961. +struct dpsw_cmd_set_irq_mask {
  9962. + __le32 mask;
  9963. + u8 irq_index;
  9964. +};
  9965. +
  9966. +struct dpsw_cmd_get_irq_mask {
  9967. + __le32 pad;
  9968. + u8 irq_index;
  9969. +};
  9970. +
  9971. +struct dpsw_rsp_get_irq_mask {
  9972. + __le32 mask;
  9973. +};
  9974. +
  9975. +struct dpsw_cmd_get_irq_status {
  9976. + __le32 status;
  9977. + u8 irq_index;
  9978. +};
  9979. +
  9980. +struct dpsw_rsp_get_irq_status {
  9981. + __le32 status;
  9982. +};
  9983. +
  9984. +struct dpsw_cmd_clear_irq_status {
  9985. + __le32 status;
  9986. + u8 irq_index;
  9987. +};
  9988. +
  9989. +#define DPSW_COMPONENT_TYPE_SHIFT 0
  9990. +#define DPSW_COMPONENT_TYPE_SIZE 4
  9991. +
  9992. +struct dpsw_rsp_get_attr {
  9993. + /* cmd word 0 */
  9994. + __le16 num_ifs;
  9995. + u8 max_fdbs;
  9996. + u8 num_fdbs;
  9997. + __le16 max_vlans;
  9998. + __le16 num_vlans;
  9999. + /* cmd word 1 */
  10000. + __le16 max_fdb_entries;
  10001. + __le16 fdb_aging_time;
  10002. + __le32 dpsw_id;
  10003. + /* cmd word 2 */
  10004. + __le16 mem_size;
  10005. + __le16 max_fdb_mc_groups;
  10006. + u8 max_meters_per_if;
  10007. + /* from LSB only the ffirst 4 bits */
  10008. + u8 component_type;
  10009. + __le16 pad;
  10010. + /* cmd word 3 */
  10011. + __le64 options;
  10012. +};
  10013. +
  10014. +struct dpsw_cmd_set_reflection_if {
  10015. + __le16 if_id;
  10016. +};
  10017. +
  10018. +struct dpsw_cmd_if_set_flooding {
  10019. + __le16 if_id;
  10020. + /* from LSB: enable:1 */
  10021. + u8 enable;
  10022. +};
  10023. +
  10024. +struct dpsw_cmd_if_set_broadcast {
  10025. + __le16 if_id;
  10026. + /* from LSB: enable:1 */
  10027. + u8 enable;
  10028. +};
  10029. +
  10030. +struct dpsw_cmd_if_set_multicast {
  10031. + __le16 if_id;
  10032. + /* from LSB: enable:1 */
  10033. + u8 enable;
  10034. +};
  10035. +
  10036. +#define DPSW_VLAN_ID_SHIFT 0
  10037. +#define DPSW_VLAN_ID_SIZE 12
  10038. +#define DPSW_DEI_SHIFT 12
  10039. +#define DPSW_DEI_SIZE 1
  10040. +#define DPSW_PCP_SHIFT 13
  10041. +#define DPSW_PCP_SIZE 3
  10042. +
  10043. +struct dpsw_cmd_if_set_tci {
  10044. + __le16 if_id;
  10045. + /* from LSB: VLAN_ID:12 DEI:1 PCP:3 */
  10046. + __le16 conf;
  10047. +};
  10048. +
  10049. +struct dpsw_cmd_if_get_tci {
  10050. + __le16 if_id;
  10051. +};
  10052. +
  10053. +struct dpsw_rsp_if_get_tci {
  10054. + __le16 pad;
  10055. + __le16 vlan_id;
  10056. + u8 dei;
  10057. + u8 pcp;
  10058. +};
  10059. +
  10060. +#define DPSW_STATE_SHIFT 0
  10061. +#define DPSW_STATE_SIZE 4
  10062. +
  10063. +struct dpsw_cmd_if_set_stp {
  10064. + __le16 if_id;
  10065. + __le16 vlan_id;
  10066. + /* only the first LSB 4 bits */
  10067. + u8 state;
  10068. +};
  10069. +
  10070. +#define DPSW_FRAME_TYPE_SHIFT 0
  10071. +#define DPSW_FRAME_TYPE_SIZE 4
  10072. +#define DPSW_UNACCEPTED_ACT_SHIFT 4
  10073. +#define DPSW_UNACCEPTED_ACT_SIZE 4
  10074. +
  10075. +struct dpsw_cmd_if_set_accepted_frames {
  10076. + __le16 if_id;
  10077. + /* from LSB: type:4 unaccepted_act:4 */
  10078. + u8 unaccepted;
  10079. +};
  10080. +
  10081. +#define DPSW_ACCEPT_ALL_SHIFT 0
  10082. +#define DPSW_ACCEPT_ALL_SIZE 1
  10083. +
  10084. +struct dpsw_cmd_if_set_accept_all_vlan {
  10085. + __le16 if_id;
  10086. + /* only the least significant bit */
  10087. + u8 accept_all;
  10088. +};
  10089. +
  10090. +#define DPSW_COUNTER_TYPE_SHIFT 0
  10091. +#define DPSW_COUNTER_TYPE_SIZE 5
  10092. +
  10093. +struct dpsw_cmd_if_get_counter {
  10094. + __le16 if_id;
  10095. + /* from LSB: type:5 */
  10096. + u8 type;
  10097. +};
  10098. +
  10099. +struct dpsw_rsp_if_get_counter {
  10100. + __le64 pad;
  10101. + __le64 counter;
  10102. +};
  10103. +
  10104. +struct dpsw_cmd_if_set_counter {
  10105. + /* cmd word 0 */
  10106. + __le16 if_id;
  10107. + /* from LSB: type:5 */
  10108. + u8 type;
  10109. + /* cmd word 1 */
  10110. + __le64 counter;
  10111. +};
  10112. +
  10113. +#define DPSW_PRIORITY_SELECTOR_SHIFT 0
  10114. +#define DPSW_PRIORITY_SELECTOR_SIZE 3
  10115. +#define DPSW_SCHED_MODE_SHIFT 0
  10116. +#define DPSW_SCHED_MODE_SIZE 4
  10117. +
  10118. +struct dpsw_cmd_if_set_tx_selection {
  10119. + __le16 if_id;
  10120. + /* from LSB: priority_selector:3 */
  10121. + u8 priority_selector;
  10122. + u8 pad[5];
  10123. + u8 tc_id[8];
  10124. +
  10125. + struct dpsw_tc_sched {
  10126. + __le16 delta_bandwidth;
  10127. + u8 mode;
  10128. + u8 pad;
  10129. + } tc_sched[8];
  10130. +};
  10131. +
  10132. +#define DPSW_FILTER_SHIFT 0
  10133. +#define DPSW_FILTER_SIZE 2
  10134. +
  10135. +struct dpsw_cmd_if_reflection {
  10136. + __le16 if_id;
  10137. + __le16 vlan_id;
  10138. + /* only 2 bits from the LSB */
  10139. + u8 filter;
  10140. +};
  10141. +
  10142. +#define DPSW_MODE_SHIFT 0
  10143. +#define DPSW_MODE_SIZE 4
  10144. +#define DPSW_UNITS_SHIFT 4
  10145. +#define DPSW_UNITS_SIZE 4
  10146. +
  10147. +struct dpsw_cmd_if_set_flooding_metering {
  10148. + /* cmd word 0 */
  10149. + __le16 if_id;
  10150. + u8 pad;
  10151. + /* from LSB: mode:4 units:4 */
  10152. + u8 mode_units;
  10153. + __le32 cir;
  10154. + /* cmd word 1 */
  10155. + __le32 eir;
  10156. + __le32 cbs;
  10157. + /* cmd word 2 */
  10158. + __le32 ebs;
  10159. +};
  10160. +
  10161. +struct dpsw_cmd_if_set_metering {
  10162. + /* cmd word 0 */
  10163. + __le16 if_id;
  10164. + u8 tc_id;
  10165. + /* from LSB: mode:4 units:4 */
  10166. + u8 mode_units;
  10167. + __le32 cir;
  10168. + /* cmd word 1 */
  10169. + __le32 eir;
  10170. + __le32 cbs;
  10171. + /* cmd word 2 */
  10172. + __le32 ebs;
  10173. +};
  10174. +
  10175. +#define DPSW_EARLY_DROP_MODE_SHIFT 0
  10176. +#define DPSW_EARLY_DROP_MODE_SIZE 2
  10177. +#define DPSW_EARLY_DROP_UNIT_SHIFT 2
  10178. +#define DPSW_EARLY_DROP_UNIT_SIZE 2
  10179. +
  10180. +struct dpsw_prep_early_drop {
  10181. + /* from LSB: mode:2 units:2 */
  10182. + u8 conf;
  10183. + u8 pad0[3];
  10184. + __le32 tail_drop_threshold;
  10185. + u8 green_drop_probability;
  10186. + u8 pad1[7];
  10187. + __le64 green_max_threshold;
  10188. + __le64 green_min_threshold;
  10189. + __le64 pad2;
  10190. + u8 yellow_drop_probability;
  10191. + u8 pad3[7];
  10192. + __le64 yellow_max_threshold;
  10193. + __le64 yellow_min_threshold;
  10194. +};
  10195. +
  10196. +struct dpsw_cmd_if_set_early_drop {
  10197. + /* cmd word 0 */
  10198. + u8 pad0;
  10199. + u8 tc_id;
  10200. + __le16 if_id;
  10201. + __le32 pad1;
  10202. + /* cmd word 1 */
  10203. + __le64 early_drop_iova;
  10204. +};
  10205. +
  10206. +struct dpsw_cmd_custom_tpid {
  10207. + __le16 pad;
  10208. + __le16 tpid;
  10209. +};
  10210. +
  10211. +struct dpsw_cmd_if {
  10212. + __le16 if_id;
  10213. +};
  10214. +
  10215. +#define DPSW_ADMIT_UNTAGGED_SHIFT 0
  10216. +#define DPSW_ADMIT_UNTAGGED_SIZE 4
  10217. +#define DPSW_ENABLED_SHIFT 5
  10218. +#define DPSW_ENABLED_SIZE 1
  10219. +#define DPSW_ACCEPT_ALL_VLAN_SHIFT 6
  10220. +#define DPSW_ACCEPT_ALL_VLAN_SIZE 1
  10221. +
  10222. +struct dpsw_rsp_if_get_attr {
  10223. + /* cmd word 0 */
  10224. + /* from LSB: admit_untagged:4 enabled:1 accept_all_vlan:1 */
  10225. + u8 conf;
  10226. + u8 pad1;
  10227. + u8 num_tcs;
  10228. + u8 pad2;
  10229. + __le16 qdid;
  10230. + /* cmd word 1 */
  10231. + __le32 options;
  10232. + __le32 pad3;
  10233. + /* cmd word 2 */
  10234. + __le32 rate;
  10235. +};
  10236. +
  10237. +struct dpsw_cmd_if_set_max_frame_length {
  10238. + __le16 if_id;
  10239. + __le16 frame_length;
  10240. +};
  10241. +
  10242. +struct dpsw_cmd_if_get_max_frame_length {
  10243. + __le16 if_id;
  10244. +};
  10245. +
  10246. +struct dpsw_rsp_if_get_max_frame_length {
  10247. + __le16 pad;
  10248. + __le16 frame_length;
  10249. +};
  10250. +
  10251. +struct dpsw_cmd_if_set_link_cfg {
  10252. + /* cmd word 0 */
  10253. + __le16 if_id;
  10254. + u8 pad[6];
  10255. + /* cmd word 1 */
  10256. + __le32 rate;
  10257. + __le32 pad1;
  10258. + /* cmd word 2 */
  10259. + __le64 options;
  10260. +};
  10261. +
  10262. +struct dpsw_cmd_if_get_link_state {
  10263. + __le16 if_id;
  10264. +};
  10265. +
  10266. +#define DPSW_UP_SHIFT 0
  10267. +#define DPSW_UP_SIZE 1
  10268. +
  10269. +struct dpsw_rsp_if_get_link_state {
  10270. + /* cmd word 0 */
  10271. + __le32 pad0;
  10272. + u8 up;
  10273. + u8 pad1[3];
  10274. + /* cmd word 1 */
  10275. + __le32 rate;
  10276. + __le32 pad2;
  10277. + /* cmd word 2 */
  10278. + __le64 options;
  10279. +};
  10280. +
  10281. +struct dpsw_vlan_add {
  10282. + __le16 fdb_id;
  10283. + __le16 vlan_id;
  10284. +};
  10285. +
  10286. +struct dpsw_cmd_vlan_manage_if {
  10287. + /* cmd word 0 */
  10288. + __le16 pad0;
  10289. + __le16 vlan_id;
  10290. + __le32 pad1;
  10291. + /* cmd word 1 */
  10292. + __le64 if_id[4];
  10293. +};
  10294. +
  10295. +struct dpsw_cmd_vlan_remove {
  10296. + __le16 pad;
  10297. + __le16 vlan_id;
  10298. +};
  10299. +
  10300. +struct dpsw_cmd_vlan_get_attr {
  10301. + __le16 vlan_id;
  10302. +};
  10303. +
  10304. +struct dpsw_rsp_vlan_get_attr {
  10305. + /* cmd word 0 */
  10306. + __le64 pad;
  10307. + /* cmd word 1 */
  10308. + __le16 fdb_id;
  10309. + __le16 num_ifs;
  10310. + __le16 num_untagged_ifs;
  10311. + __le16 num_flooding_ifs;
  10312. +};
  10313. +
  10314. +struct dpsw_cmd_vlan_get_if {
  10315. + __le16 vlan_id;
  10316. +};
  10317. +
  10318. +struct dpsw_rsp_vlan_get_if {
  10319. + /* cmd word 0 */
  10320. + __le16 pad0;
  10321. + __le16 num_ifs;
  10322. + u8 pad1[4];
  10323. + /* cmd word 1 */
  10324. + __le64 if_id[4];
  10325. +};
  10326. +
  10327. +struct dpsw_cmd_vlan_get_if_untagged {
  10328. + __le16 vlan_id;
  10329. +};
  10330. +
  10331. +struct dpsw_rsp_vlan_get_if_untagged {
  10332. + /* cmd word 0 */
  10333. + __le16 pad0;
  10334. + __le16 num_ifs;
  10335. + u8 pad1[4];
  10336. + /* cmd word 1 */
  10337. + __le64 if_id[4];
  10338. +};
  10339. +
  10340. +struct dpsw_cmd_vlan_get_if_flooding {
  10341. + __le16 vlan_id;
  10342. +};
  10343. +
  10344. +struct dpsw_rsp_vlan_get_if_flooding {
  10345. + /* cmd word 0 */
  10346. + __le16 pad0;
  10347. + __le16 num_ifs;
  10348. + u8 pad1[4];
  10349. + /* cmd word 1 */
  10350. + __le64 if_id[4];
  10351. +};
  10352. +
  10353. +struct dpsw_cmd_fdb_add {
  10354. + __le32 pad;
  10355. + __le16 fdb_aging_time;
  10356. + __le16 num_fdb_entries;
  10357. +};
  10358. +
  10359. +struct dpsw_rsp_fdb_add {
  10360. + __le16 fdb_id;
  10361. +};
  10362. +
  10363. +struct dpsw_cmd_fdb_remove {
  10364. + __le16 fdb_id;
  10365. +};
  10366. +
  10367. +#define DPSW_ENTRY_TYPE_SHIFT 0
  10368. +#define DPSW_ENTRY_TYPE_SIZE 4
  10369. +
  10370. +struct dpsw_cmd_fdb_add_unicast {
  10371. + /* cmd word 0 */
  10372. + __le16 fdb_id;
  10373. + u8 mac_addr[6];
  10374. + /* cmd word 1 */
  10375. + u8 if_egress;
  10376. + u8 pad;
  10377. + /* only the first 4 bits from LSB */
  10378. + u8 type;
  10379. +};
  10380. +
  10381. +struct dpsw_cmd_fdb_get_unicast {
  10382. + __le16 fdb_id;
  10383. + u8 mac_addr[6];
  10384. +};
  10385. +
  10386. +struct dpsw_rsp_fdb_get_unicast {
  10387. + __le64 pad;
  10388. + __le16 if_egress;
  10389. + /* only first 4 bits from LSB */
  10390. + u8 type;
  10391. +};
  10392. +
  10393. +struct dpsw_cmd_fdb_remove_unicast {
  10394. + /* cmd word 0 */
  10395. + __le16 fdb_id;
  10396. + u8 mac_addr[6];
  10397. + /* cmd word 1 */
  10398. + __le16 if_egress;
  10399. + /* only the first 4 bits from LSB */
  10400. + u8 type;
  10401. +};
  10402. +
  10403. +struct dpsw_cmd_fdb_add_multicast {
  10404. + /* cmd word 0 */
  10405. + __le16 fdb_id;
  10406. + __le16 num_ifs;
  10407. + /* only the first 4 bits from LSB */
  10408. + u8 type;
  10409. + u8 pad[3];
  10410. + /* cmd word 1 */
  10411. + u8 mac_addr[6];
  10412. + __le16 pad2;
  10413. + /* cmd word 2 */
  10414. + __le64 if_id[4];
  10415. +};
  10416. +
  10417. +struct dpsw_cmd_fdb_get_multicast {
  10418. + __le16 fdb_id;
  10419. + u8 mac_addr[6];
  10420. +};
  10421. +
  10422. +struct dpsw_rsp_fdb_get_multicast {
  10423. + /* cmd word 0 */
  10424. + __le64 pad0;
  10425. + /* cmd word 1 */
  10426. + __le16 num_ifs;
  10427. + /* only the first 4 bits from LSB */
  10428. + u8 type;
  10429. + u8 pad1[5];
  10430. + /* cmd word 2 */
  10431. + __le64 if_id[4];
  10432. +};
  10433. +
  10434. +struct dpsw_cmd_fdb_remove_multicast {
  10435. + /* cmd word 0 */
  10436. + __le16 fdb_id;
  10437. + __le16 num_ifs;
  10438. + /* only the first 4 bits from LSB */
  10439. + u8 type;
  10440. + u8 pad[3];
  10441. + /* cmd word 1 */
  10442. + u8 mac_addr[6];
  10443. + __le16 pad2;
  10444. + /* cmd word 2 */
  10445. + __le64 if_id[4];
  10446. +};
  10447. +
  10448. +#define DPSW_LEARNING_MODE_SHIFT 0
  10449. +#define DPSW_LEARNING_MODE_SIZE 4
  10450. +
  10451. +struct dpsw_cmd_fdb_set_learning_mode {
  10452. + __le16 fdb_id;
  10453. + /* only the first 4 bits from LSB */
  10454. + u8 mode;
  10455. +};
  10456. +
  10457. +struct dpsw_cmd_fdb_get_attr {
  10458. + __le16 fdb_id;
  10459. +};
  10460. +
  10461. +struct dpsw_rsp_fdb_get_attr {
  10462. + /* cmd word 0 */
  10463. + __le16 pad;
  10464. + __le16 max_fdb_entries;
  10465. + __le16 fdb_aging_time;
  10466. + __le16 num_fdb_mc_groups;
  10467. + /* cmd word 1 */
  10468. + __le16 max_fdb_mc_groups;
  10469. + /* only the first 4 bits from LSB */
  10470. + u8 learning_mode;
  10471. +};
  10472. +
  10473. +struct dpsw_cmd_acl_add {
  10474. + __le16 pad;
  10475. + __le16 max_entries;
  10476. +};
  10477. +
  10478. +struct dpsw_rsp_acl_add {
  10479. + __le16 acl_id;
  10480. +};
  10481. +
  10482. +struct dpsw_cmd_acl_remove {
  10483. + __le16 acl_id;
  10484. +};
  10485. +
  10486. +struct dpsw_prep_acl_entry {
  10487. + u8 match_l2_dest_mac[6];
  10488. + __le16 match_l2_tpid;
  10489. +
  10490. + u8 match_l2_source_mac[6];
  10491. + __le16 match_l2_vlan_id;
  10492. +
  10493. + __le32 match_l3_dest_ip;
  10494. + __le32 match_l3_source_ip;
  10495. +
  10496. + __le16 match_l4_dest_port;
  10497. + __le16 match_l4_source_port;
  10498. + __le16 match_l2_ether_type;
  10499. + u8 match_l2_pcp_dei;
  10500. + u8 match_l3_dscp;
  10501. +
  10502. + u8 mask_l2_dest_mac[6];
  10503. + __le16 mask_l2_tpid;
  10504. +
  10505. + u8 mask_l2_source_mac[6];
  10506. + __le16 mask_l2_vlan_id;
  10507. +
  10508. + __le32 mask_l3_dest_ip;
  10509. + __le32 mask_l3_source_ip;
  10510. +
  10511. + __le16 mask_l4_dest_port;
  10512. + __le16 mask_l4_source_port;
  10513. + __le16 mask_l2_ether_type;
  10514. + u8 mask_l2_pcp_dei;
  10515. + u8 mask_l3_dscp;
  10516. +
  10517. + u8 match_l3_protocol;
  10518. + u8 mask_l3_protocol;
  10519. +};
  10520. +
  10521. +#define DPSW_RESULT_ACTION_SHIFT 0
  10522. +#define DPSW_RESULT_ACTION_SIZE 4
  10523. +
  10524. +struct dpsw_cmd_acl_entry {
  10525. + __le16 acl_id;
  10526. + __le16 result_if_id;
  10527. + __le32 precedence;
  10528. + /* from LSB only the first 4 bits */
  10529. + u8 result_action;
  10530. + u8 pad[7];
  10531. + __le64 pad2[4];
  10532. + __le64 key_iova;
  10533. +};
  10534. +
  10535. +struct dpsw_cmd_acl_if {
  10536. + /* cmd word 0 */
  10537. + __le16 acl_id;
  10538. + __le16 num_ifs;
  10539. + __le32 pad;
  10540. + /* cmd word 1 */
  10541. + __le64 if_id[4];
  10542. +};
  10543. +
  10544. +struct dpsw_cmd_acl_get_attr {
  10545. + __le16 acl_id;
  10546. +};
  10547. +
  10548. +struct dpsw_rsp_acl_get_attr {
  10549. + /* cmd word 0 */
  10550. + __le64 pad;
  10551. + /* cmd word 1 */
  10552. + __le16 max_entries;
  10553. + __le16 num_entries;
  10554. + __le16 num_ifs;
  10555. +};
  10556. +
  10557. +struct dpsw_rsp_ctrl_if_get_attr {
  10558. + /* cmd word 0 */
  10559. + __le64 pad;
  10560. + /* cmd word 1 */
  10561. + __le32 rx_fqid;
  10562. + __le32 rx_err_fqid;
  10563. + /* cmd word 2 */
  10564. + __le32 tx_err_conf_fqid;
  10565. +};
  10566. +
  10567. +struct dpsw_cmd_ctrl_if_set_pools {
  10568. + u8 num_dpbp;
  10569. + /* from LSB: POOL0_BACKUP_POOL:1 ... POOL7_BACKUP_POOL */
  10570. + u8 backup_pool;
  10571. + __le16 pad;
  10572. + __le32 dpbp_id[8];
  10573. + __le16 buffer_size[8];
  10574. +};
  10575. +
  10576. +struct dpsw_rsp_get_api_version {
  10577. + __le16 version_major;
  10578. + __le16 version_minor;
  10579. +};
  10580. +
  10581. +#endif /* __FSL_DPSW_CMD_H */
  10582. --- /dev/null
  10583. +++ b/drivers/staging/fsl-dpaa2/ethsw/dpsw.c
  10584. @@ -0,0 +1,2762 @@
  10585. +/* Copyright 2013-2015 Freescale Semiconductor Inc.
  10586. + *
  10587. + * Redistribution and use in source and binary forms, with or without
  10588. + * modification, are permitted provided that the following conditions are met:
  10589. + * * Redistributions of source code must retain the above copyright
  10590. + * notice, this list of conditions and the following disclaimer.
  10591. + * * Redistributions in binary form must reproduce the above copyright
  10592. + * notice, this list of conditions and the following disclaimer in the
  10593. + * documentation and/or other materials provided with the distribution.
  10594. + * * Neither the name of the above-listed copyright holders nor the
  10595. + * names of any contributors may be used to endorse or promote products
  10596. + * derived from this software without specific prior written permission.
  10597. + *
  10598. + *
  10599. + * ALTERNATIVELY, this software may be distributed under the terms of the
  10600. + * GNU General Public License ("GPL") as published by the Free Software
  10601. + * Foundation, either version 2 of that License or (at your option) any
  10602. + * later version.
  10603. + *
  10604. + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  10605. + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  10606. + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  10607. + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
  10608. + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  10609. + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  10610. + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  10611. + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  10612. + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  10613. + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  10614. + * POSSIBILITY OF SUCH DAMAGE.
  10615. + */
  10616. +#include "../../fsl-mc/include/mc-sys.h"
  10617. +#include "../../fsl-mc/include/mc-cmd.h"
  10618. +#include "dpsw.h"
  10619. +#include "dpsw-cmd.h"
  10620. +
  10621. +static void build_if_id_bitmap(__le64 *bmap,
  10622. + const u16 *id,
  10623. + const u16 num_ifs) {
  10624. + int i;
  10625. +
  10626. + for (i = 0; (i < num_ifs) && (i < DPSW_MAX_IF); i++)
  10627. + bmap[id[i] / 64] = dpsw_set_bit(bmap[id[i] / 64],
  10628. + (id[i] % 64),
  10629. + 1);
  10630. +}
  10631. +
  10632. +static void read_if_id_bitmap(u16 *if_id,
  10633. + u16 *num_ifs,
  10634. + __le64 *bmap) {
  10635. + int bitmap[DPSW_MAX_IF] = { 0 };
  10636. + int i, j = 0;
  10637. + int count = 0;
  10638. +
  10639. + for (i = 0; i < DPSW_MAX_IF; i++) {
  10640. + bitmap[i] = dpsw_get_bit(le64_to_cpu(bmap[i / 64]),
  10641. + i % 64);
  10642. + count += bitmap[i];
  10643. + }
  10644. +
  10645. + *num_ifs = (u16)count;
  10646. +
  10647. + for (i = 0; (i < DPSW_MAX_IF) && (j < count); i++) {
  10648. + if (bitmap[i]) {
  10649. + if_id[j] = (u16)i;
  10650. + j++;
  10651. + }
  10652. + }
  10653. +}
  10654. +
  10655. +/**
  10656. + * dpsw_open() - Open a control session for the specified object
  10657. + * @mc_io: Pointer to MC portal's I/O object
  10658. + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
  10659. + * @dpsw_id: DPSW unique ID
  10660. + * @token: Returned token; use in subsequent API calls
  10661. + *
  10662. + * This function can be used to open a control session for an
  10663. + * already created object; an object may have been declared in
  10664. + * the DPL or by calling the dpsw_create() function.
  10665. + * This function returns a unique authentication token,
  10666. + * associated with the specific object ID and the specific MC
  10667. + * portal; this token must be used in all subsequent commands for
  10668. + * this specific object
  10669. + *
  10670. + * Return: '0' on Success; Error code otherwise.
  10671. + */
  10672. +int dpsw_open(struct fsl_mc_io *mc_io,
  10673. + u32 cmd_flags,
  10674. + int dpsw_id,
  10675. + u16 *token)
  10676. +{
  10677. + struct mc_command cmd = { 0 };
  10678. + struct dpsw_cmd_open *cmd_params;
  10679. + int err;
  10680. +
  10681. + /* prepare command */
  10682. + cmd.header = mc_encode_cmd_header(DPSW_CMDID_OPEN,
  10683. + cmd_flags,
  10684. + 0);
  10685. + cmd_params = (struct dpsw_cmd_open *)cmd.params;
  10686. + cmd_params->dpsw_id = cpu_to_le32(dpsw_id);
  10687. +
  10688. + /* send command to mc*/
  10689. + err = mc_send_command(mc_io, &cmd);
  10690. + if (err)
  10691. + return err;
  10692. +
  10693. + /* retrieve response parameters */
  10694. + *token = mc_cmd_hdr_read_token(&cmd);
  10695. +
  10696. + return 0;
  10697. +}
  10698. +
  10699. +/**
  10700. + * dpsw_close() - Close the control session of the object
  10701. + * @mc_io: Pointer to MC portal's I/O object
  10702. + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
  10703. + * @token: Token of DPSW object
  10704. + *
  10705. + * After this function is called, no further operations are
  10706. + * allowed on the object without opening a new control session.
  10707. + *
  10708. + * Return: '0' on Success; Error code otherwise.
  10709. + */
  10710. +int dpsw_close(struct fsl_mc_io *mc_io,
  10711. + u32 cmd_flags,
  10712. + u16 token)
  10713. +{
  10714. + struct mc_command cmd = { 0 };
  10715. +
  10716. + /* prepare command */
  10717. + cmd.header = mc_encode_cmd_header(DPSW_CMDID_CLOSE,
  10718. + cmd_flags,
  10719. + token);
  10720. +
  10721. + /* send command to mc*/
  10722. + return mc_send_command(mc_io, &cmd);
  10723. +}
  10724. +
  10725. +/**
  10726. + * dpsw_enable() - Enable DPSW functionality
  10727. + * @mc_io: Pointer to MC portal's I/O object
  10728. + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
  10729. + * @token: Token of DPSW object
  10730. + *
  10731. + * Return: Completion status. '0' on Success; Error code otherwise.
  10732. + */
  10733. +int dpsw_enable(struct fsl_mc_io *mc_io,
  10734. + u32 cmd_flags,
  10735. + u16 token)
  10736. +{
  10737. + struct mc_command cmd = { 0 };
  10738. +
  10739. + /* prepare command */
  10740. + cmd.header = mc_encode_cmd_header(DPSW_CMDID_ENABLE,
  10741. + cmd_flags,
  10742. + token);
  10743. +
  10744. + /* send command to mc*/
  10745. + return mc_send_command(mc_io, &cmd);
  10746. +}
  10747. +
  10748. +/**
  10749. + * dpsw_disable() - Disable DPSW functionality
  10750. + * @mc_io: Pointer to MC portal's I/O object
  10751. + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
  10752. + * @token: Token of DPSW object
  10753. + *
  10754. + * Return: Completion status. '0' on Success; Error code otherwise.
  10755. + */
  10756. +int dpsw_disable(struct fsl_mc_io *mc_io,
  10757. + u32 cmd_flags,
  10758. + u16 token)
  10759. +{
  10760. + struct mc_command cmd = { 0 };
  10761. +
  10762. + /* prepare command */
  10763. + cmd.header = mc_encode_cmd_header(DPSW_CMDID_DISABLE,
  10764. + cmd_flags,
  10765. + token);
  10766. +
  10767. + /* send command to mc*/
  10768. + return mc_send_command(mc_io, &cmd);
  10769. +}
  10770. +
  10771. +/**
  10772. + * dpsw_is_enabled() - Check if the DPSW is enabled
  10773. + *
  10774. + * @mc_io: Pointer to MC portal's I/O object
  10775. + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
  10776. + * @token: Token of DPSW object
  10777. + * @en: Returns '1' if object is enabled; '0' otherwise
  10778. + *
  10779. + * Return: '0' on Success; Error code otherwise
  10780. + */
  10781. +int dpsw_is_enabled(struct fsl_mc_io *mc_io,
  10782. + u32 cmd_flags,
  10783. + u16 token,
  10784. + int *en)
  10785. +{
  10786. + struct mc_command cmd = { 0 };
  10787. + struct dpsw_rsp_is_enabled *cmd_rsp;
  10788. + int err;
  10789. +
  10790. + /* prepare command */
  10791. + cmd.header = mc_encode_cmd_header(DPSW_CMDID_IS_ENABLED, cmd_flags,
  10792. + token);
  10793. +
  10794. + /* send command to mc*/
  10795. + err = mc_send_command(mc_io, &cmd);
  10796. + if (err)
  10797. + return err;
  10798. +
  10799. + /* retrieve response parameters */
  10800. + cmd_rsp = (struct dpsw_rsp_is_enabled *)cmd.params;
  10801. + *en = dpsw_get_field(cmd_rsp->enabled, ENABLE);
  10802. +
  10803. + return 0;
  10804. +}
  10805. +
  10806. +/**
  10807. + * dpsw_reset() - Reset the DPSW, returns the object to initial state.
  10808. + * @mc_io: Pointer to MC portal's I/O object
  10809. + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
  10810. + * @token: Token of DPSW object
  10811. + *
  10812. + * Return: '0' on Success; Error code otherwise.
  10813. + */
  10814. +int dpsw_reset(struct fsl_mc_io *mc_io,
  10815. + u32 cmd_flags,
  10816. + u16 token)
  10817. +{
  10818. + struct mc_command cmd = { 0 };
  10819. +
  10820. + /* prepare command */
  10821. + cmd.header = mc_encode_cmd_header(DPSW_CMDID_RESET,
  10822. + cmd_flags,
  10823. + token);
  10824. +
  10825. + /* send command to mc*/
  10826. + return mc_send_command(mc_io, &cmd);
  10827. +}
  10828. +
  10829. +/**
  10830. + * dpsw_set_irq() - Set IRQ information for the DPSW to trigger an interrupt.
  10831. + * @mc_io: Pointer to MC portal's I/O object
  10832. + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
  10833. + * @token: Token of DPSW object
  10834. + * @irq_index: Identifies the interrupt index to configure
  10835. + * @irq_cfg: IRQ configuration
  10836. + *
  10837. + * Return: '0' on Success; Error code otherwise.
  10838. + */
  10839. +int dpsw_set_irq(struct fsl_mc_io *mc_io,
  10840. + u32 cmd_flags,
  10841. + u16 token,
  10842. + u8 irq_index,
  10843. + struct dpsw_irq_cfg *irq_cfg)
  10844. +{
  10845. + struct mc_command cmd = { 0 };
  10846. + struct dpsw_cmd_set_irq *cmd_params;
  10847. +
  10848. + /* prepare command */
  10849. + cmd.header = mc_encode_cmd_header(DPSW_CMDID_SET_IRQ,
  10850. + cmd_flags,
  10851. + token);
  10852. + cmd_params = (struct dpsw_cmd_set_irq *)cmd.params;
  10853. + cmd_params->irq_index = irq_index;
  10854. + cmd_params->irq_val = cpu_to_le32(irq_cfg->val);
  10855. + cmd_params->irq_addr = cpu_to_le64(irq_cfg->addr);
  10856. + cmd_params->irq_num = cpu_to_le32(irq_cfg->irq_num);
  10857. +
  10858. + /* send command to mc*/
  10859. + return mc_send_command(mc_io, &cmd);
  10860. +}
  10861. +
  10862. +/**
  10863. + * dpsw_get_irq() - Get IRQ information from the DPSW
  10864. + *
  10865. + * @mc_io: Pointer to MC portal's I/O object
  10866. + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
  10867. + * @token: Token of DPSW object
  10868. + * @irq_index: The interrupt index to configure
  10869. + * @type: Interrupt type: 0 represents message interrupt
  10870. + * type (both irq_addr and irq_val are valid)
  10871. + * @irq_cfg: IRQ attributes
  10872. + *
  10873. + * Return: '0' on Success; Error code otherwise.
  10874. + */
  10875. +int dpsw_get_irq(struct fsl_mc_io *mc_io,
  10876. + u32 cmd_flags,
  10877. + u16 token,
  10878. + u8 irq_index,
  10879. + int *type,
  10880. + struct dpsw_irq_cfg *irq_cfg)
  10881. +{
  10882. + struct mc_command cmd = { 0 };
  10883. + struct dpsw_cmd_get_irq *cmd_params;
  10884. + struct dpsw_rsp_get_irq *rsp_params;
  10885. + int err;
  10886. +
  10887. + /* prepare command */
  10888. + cmd.header = mc_encode_cmd_header(DPSW_CMDID_GET_IRQ,
  10889. + cmd_flags,
  10890. + token);
  10891. + cmd_params = (struct dpsw_cmd_get_irq *)cmd.params;
  10892. + cmd_params->irq_index = irq_index;
  10893. +
  10894. + /* send command to mc*/
  10895. + err = mc_send_command(mc_io, &cmd);
  10896. + if (err)
  10897. + return err;
  10898. +
  10899. + /* retrieve response parameters */
  10900. + rsp_params = (struct dpsw_rsp_get_irq *)cmd.params;
  10901. + irq_cfg->addr = le64_to_cpu(rsp_params->irq_addr);
  10902. + irq_cfg->val = le32_to_cpu(rsp_params->irq_val);
  10903. + irq_cfg->irq_num = le32_to_cpu(rsp_params->irq_num);
  10904. + *type = le32_to_cpu(rsp_params->irq_type);
  10905. +
  10906. + return 0;
  10907. +}
  10908. +
  10909. +/**
  10910. + * dpsw_set_irq_enable() - Set overall interrupt state.
  10911. + * @mc_io: Pointer to MC portal's I/O object
  10912. + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
  10913. + * @token: Token of DPCI object
  10914. + * @irq_index: The interrupt index to configure
  10915. + * @en: Interrupt state - enable = 1, disable = 0
  10916. + *
  10917. + * Allows GPP software to control when interrupts are generated.
  10918. + * Each interrupt can have up to 32 causes. The enable/disable control's the
  10919. + * overall interrupt state. if the interrupt is disabled no causes will cause
  10920. + * an interrupt
  10921. + *
  10922. + * Return: '0' on Success; Error code otherwise.
  10923. + */
  10924. +int dpsw_set_irq_enable(struct fsl_mc_io *mc_io,
  10925. + u32 cmd_flags,
  10926. + u16 token,
  10927. + u8 irq_index,
  10928. + u8 en)
  10929. +{
  10930. + struct mc_command cmd = { 0 };
  10931. + struct dpsw_cmd_set_irq_enable *cmd_params;
  10932. +
  10933. + /* prepare command */
  10934. + cmd.header = mc_encode_cmd_header(DPSW_CMDID_SET_IRQ_ENABLE,
  10935. + cmd_flags,
  10936. + token);
  10937. + cmd_params = (struct dpsw_cmd_set_irq_enable *)cmd.params;
  10938. + dpsw_set_field(cmd_params->enable_state, ENABLE, en);
  10939. + cmd_params->irq_index = irq_index;
  10940. +
  10941. + /* send command to mc*/
  10942. + return mc_send_command(mc_io, &cmd);
  10943. +}
  10944. +
  10945. +/**
  10946. + * dpsw_set_irq_mask() - Set interrupt mask.
  10947. + * @mc_io: Pointer to MC portal's I/O object
  10948. + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
  10949. + * @token: Token of DPCI object
  10950. + * @irq_index: The interrupt index to configure
  10951. + * @mask: Event mask to trigger interrupt;
  10952. + * each bit:
  10953. + * 0 = ignore event
  10954. + * 1 = consider event for asserting IRQ
  10955. + *
  10956. + * Every interrupt can have up to 32 causes and the interrupt model supports
  10957. + * masking/unmasking each cause independently
  10958. + *
  10959. + * Return: '0' on Success; Error code otherwise.
  10960. + */
  10961. +int dpsw_set_irq_mask(struct fsl_mc_io *mc_io,
  10962. + u32 cmd_flags,
  10963. + u16 token,
  10964. + u8 irq_index,
  10965. + u32 mask)
  10966. +{
  10967. + struct mc_command cmd = { 0 };
  10968. + struct dpsw_cmd_set_irq_mask *cmd_params;
  10969. +
  10970. + /* prepare command */
  10971. + cmd.header = mc_encode_cmd_header(DPSW_CMDID_SET_IRQ_MASK,
  10972. + cmd_flags,
  10973. + token);
  10974. + cmd_params = (struct dpsw_cmd_set_irq_mask *)cmd.params;
  10975. + cmd_params->mask = cpu_to_le32(mask);
  10976. + cmd_params->irq_index = irq_index;
  10977. +
  10978. + /* send command to mc*/
  10979. + return mc_send_command(mc_io, &cmd);
  10980. +}
  10981. +
  10982. +/**
  10983. + * dpsw_get_irq_status() - Get the current status of any pending interrupts
  10984. + * @mc_io: Pointer to MC portal's I/O object
  10985. + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
  10986. + * @token: Token of DPSW object
  10987. + * @irq_index: The interrupt index to configure
  10988. + * @status: Returned interrupts status - one bit per cause:
  10989. + * 0 = no interrupt pending
  10990. + * 1 = interrupt pending
  10991. + *
  10992. + * Return: '0' on Success; Error code otherwise.
  10993. + */
  10994. +int dpsw_get_irq_status(struct fsl_mc_io *mc_io,
  10995. + u32 cmd_flags,
  10996. + u16 token,
  10997. + u8 irq_index,
  10998. + u32 *status)
  10999. +{
  11000. + struct mc_command cmd = { 0 };
  11001. + struct dpsw_cmd_get_irq_status *cmd_params;
  11002. + struct dpsw_rsp_get_irq_status *rsp_params;
  11003. + int err;
  11004. +
  11005. + /* prepare command */
  11006. + cmd.header = mc_encode_cmd_header(DPSW_CMDID_GET_IRQ_STATUS,
  11007. + cmd_flags,
  11008. + token);
  11009. + cmd_params = (struct dpsw_cmd_get_irq_status *)cmd.params;
  11010. + cmd_params->status = cpu_to_le32(*status);
  11011. + cmd_params->irq_index = irq_index;
  11012. +
  11013. + /* send command to mc*/
  11014. + err = mc_send_command(mc_io, &cmd);
  11015. + if (err)
  11016. + return err;
  11017. +
  11018. + /* retrieve response parameters */
  11019. + rsp_params = (struct dpsw_rsp_get_irq_status *)cmd.params;
  11020. + *status = le32_to_cpu(rsp_params->status);
  11021. +
  11022. + return 0;
  11023. +}
  11024. +
  11025. +/**
  11026. + * dpsw_clear_irq_status() - Clear a pending interrupt's status
  11027. + * @mc_io: Pointer to MC portal's I/O object
  11028. + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
  11029. + * @token: Token of DPCI object
  11030. + * @irq_index: The interrupt index to configure
  11031. + * @status: bits to clear (W1C) - one bit per cause:
  11032. + * 0 = don't change
  11033. + * 1 = clear status bit
  11034. + *
  11035. + * Return: '0' on Success; Error code otherwise.
  11036. + */
  11037. +int dpsw_clear_irq_status(struct fsl_mc_io *mc_io,
  11038. + u32 cmd_flags,
  11039. + u16 token,
  11040. + u8 irq_index,
  11041. + u32 status)
  11042. +{
  11043. + struct mc_command cmd = { 0 };
  11044. + struct dpsw_cmd_clear_irq_status *cmd_params;
  11045. +
  11046. + /* prepare command */
  11047. + cmd.header = mc_encode_cmd_header(DPSW_CMDID_CLEAR_IRQ_STATUS,
  11048. + cmd_flags,
  11049. + token);
  11050. + cmd_params = (struct dpsw_cmd_clear_irq_status *)cmd.params;
  11051. + cmd_params->status = cpu_to_le32(status);
  11052. + cmd_params->irq_index = irq_index;
  11053. +
  11054. + /* send command to mc*/
  11055. + return mc_send_command(mc_io, &cmd);
  11056. +}
  11057. +
  11058. +/**
  11059. + * dpsw_get_attributes() - Retrieve DPSW attributes
  11060. + * @mc_io: Pointer to MC portal's I/O object
  11061. + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
  11062. + * @token: Token of DPSW object
  11063. + * @attr: Returned DPSW attributes
  11064. + *
  11065. + * Return: Completion status. '0' on Success; Error code otherwise.
  11066. + */
  11067. +int dpsw_get_attributes(struct fsl_mc_io *mc_io,
  11068. + u32 cmd_flags,
  11069. + u16 token,
  11070. + struct dpsw_attr *attr)
  11071. +{
  11072. + struct mc_command cmd = { 0 };
  11073. + struct dpsw_rsp_get_attr *rsp_params;
  11074. + int err;
  11075. +
  11076. + /* prepare command */
  11077. + cmd.header = mc_encode_cmd_header(DPSW_CMDID_GET_ATTR,
  11078. + cmd_flags,
  11079. + token);
  11080. +
  11081. + /* send command to mc*/
  11082. + err = mc_send_command(mc_io, &cmd);
  11083. + if (err)
  11084. + return err;
  11085. +
  11086. + /* retrieve response parameters */
  11087. + rsp_params = (struct dpsw_rsp_get_attr *)cmd.params;
  11088. + attr->num_ifs = le16_to_cpu(rsp_params->num_ifs);
  11089. + attr->max_fdbs = rsp_params->max_fdbs;
  11090. + attr->num_fdbs = rsp_params->num_fdbs;
  11091. + attr->max_vlans = le16_to_cpu(rsp_params->max_vlans);
  11092. + attr->num_vlans = le16_to_cpu(rsp_params->num_vlans);
  11093. + attr->max_fdb_entries = le16_to_cpu(rsp_params->max_fdb_entries);
  11094. + attr->fdb_aging_time = le16_to_cpu(rsp_params->fdb_aging_time);
  11095. + attr->id = le32_to_cpu(rsp_params->dpsw_id);
  11096. + attr->mem_size = le16_to_cpu(rsp_params->mem_size);
  11097. + attr->max_fdb_mc_groups = le16_to_cpu(rsp_params->max_fdb_mc_groups);
  11098. + attr->max_meters_per_if = rsp_params->max_meters_per_if;
  11099. + attr->options = le64_to_cpu(rsp_params->options);
  11100. + attr->component_type = dpsw_get_field(rsp_params->component_type,
  11101. + COMPONENT_TYPE);
  11102. +
  11103. + return 0;
  11104. +}
  11105. +
  11106. +/**
  11107. + * dpsw_set_reflection_if() - Set target interface for reflected interfaces.
  11108. + * @mc_io: Pointer to MC portal's I/O object
  11109. + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
  11110. + * @token: Token of DPSW object
  11111. + * @if_id: Interface Id
  11112. + *
  11113. + * Only one reflection receive interface is allowed per switch
  11114. + *
  11115. + * Return: Completion status. '0' on Success; Error code otherwise.
  11116. + */
  11117. +int dpsw_set_reflection_if(struct fsl_mc_io *mc_io,
  11118. + u32 cmd_flags,
  11119. + u16 token,
  11120. + u16 if_id)
  11121. +{
  11122. + struct mc_command cmd = { 0 };
  11123. + struct dpsw_cmd_set_reflection_if *cmd_params;
  11124. +
  11125. + /* prepare command */
  11126. + cmd.header = mc_encode_cmd_header(DPSW_CMDID_SET_REFLECTION_IF,
  11127. + cmd_flags,
  11128. + token);
  11129. + cmd_params = (struct dpsw_cmd_set_reflection_if *)cmd.params;
  11130. + cmd_params->if_id = cpu_to_le16(if_id);
  11131. +
  11132. + /* send command to mc*/
  11133. + return mc_send_command(mc_io, &cmd);
  11134. +}
  11135. +
  11136. +/**
  11137. + * dpsw_if_set_link_cfg() - Set the link configuration.
  11138. + * @mc_io: Pointer to MC portal's I/O object
  11139. + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
  11140. + * @token: Token of DPSW object
  11141. + * @if_id: Interface id
  11142. + * @cfg: Link configuration
  11143. + *
  11144. + * Return: '0' on Success; Error code otherwise.
  11145. + */
  11146. +int dpsw_if_set_link_cfg(struct fsl_mc_io *mc_io,
  11147. + u32 cmd_flags,
  11148. + u16 token,
  11149. + u16 if_id,
  11150. + struct dpsw_link_cfg *cfg)
  11151. +{
  11152. + struct mc_command cmd = { 0 };
  11153. + struct dpsw_cmd_if_set_link_cfg *cmd_params;
  11154. +
  11155. + /* prepare command */
  11156. + cmd.header = mc_encode_cmd_header(DPSW_CMDID_IF_SET_LINK_CFG,
  11157. + cmd_flags,
  11158. + token);
  11159. + cmd_params = (struct dpsw_cmd_if_set_link_cfg *)cmd.params;
  11160. + cmd_params->if_id = cpu_to_le16(if_id);
  11161. + cmd_params->rate = cpu_to_le32(cfg->rate);
  11162. + cmd_params->options = cpu_to_le64(cfg->options);
  11163. +
  11164. + /* send command to mc*/
  11165. + return mc_send_command(mc_io, &cmd);
  11166. +}
  11167. +
  11168. +/**
  11169. + * dpsw_if_get_link_state - Return the link state
  11170. + * @mc_io: Pointer to MC portal's I/O object
  11171. + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
  11172. + * @token: Token of DPSW object
  11173. + * @if_id: Interface id
  11174. + * @state: Link state 1 - linkup, 0 - link down or disconnected
  11175. + *
  11176. + * @Return '0' on Success; Error code otherwise.
  11177. + */
  11178. +int dpsw_if_get_link_state(struct fsl_mc_io *mc_io,
  11179. + u32 cmd_flags,
  11180. + u16 token,
  11181. + u16 if_id,
  11182. + struct dpsw_link_state *state)
  11183. +{
  11184. + struct mc_command cmd = { 0 };
  11185. + struct dpsw_cmd_if_get_link_state *cmd_params;
  11186. + struct dpsw_rsp_if_get_link_state *rsp_params;
  11187. + int err;
  11188. +
  11189. + /* prepare command */
  11190. + cmd.header = mc_encode_cmd_header(DPSW_CMDID_IF_GET_LINK_STATE,
  11191. + cmd_flags,
  11192. + token);
  11193. + cmd_params = (struct dpsw_cmd_if_get_link_state *)cmd.params;
  11194. + cmd_params->if_id = cpu_to_le16(if_id);
  11195. +
  11196. + /* send command to mc*/
  11197. + err = mc_send_command(mc_io, &cmd);
  11198. + if (err)
  11199. + return err;
  11200. +
  11201. + /* retrieve response parameters */
  11202. + rsp_params = (struct dpsw_rsp_if_get_link_state *)cmd.params;
  11203. + state->rate = le32_to_cpu(rsp_params->rate);
  11204. + state->options = le64_to_cpu(rsp_params->options);
  11205. + state->up = dpsw_get_field(rsp_params->up, UP);
  11206. +
  11207. + return 0;
  11208. +}
  11209. +
  11210. +/**
  11211. + * dpsw_if_set_flooding() - Enable Disable flooding for particular interface
  11212. + * @mc_io: Pointer to MC portal's I/O object
  11213. + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
  11214. + * @token: Token of DPSW object
  11215. + * @if_id: Interface Identifier
  11216. + * @en: 1 - enable, 0 - disable
  11217. + *
  11218. + * Return: Completion status. '0' on Success; Error code otherwise.
  11219. + */
  11220. +int dpsw_if_set_flooding(struct fsl_mc_io *mc_io,
  11221. + u32 cmd_flags,
  11222. + u16 token,
  11223. + u16 if_id,
  11224. + int en)
  11225. +{
  11226. + struct mc_command cmd = { 0 };
  11227. + struct dpsw_cmd_if_set_flooding *cmd_params;
  11228. +
  11229. + /* prepare command */
  11230. + cmd.header = mc_encode_cmd_header(DPSW_CMDID_IF_SET_FLOODING,
  11231. + cmd_flags,
  11232. + token);
  11233. + cmd_params = (struct dpsw_cmd_if_set_flooding *)cmd.params;
  11234. + cmd_params->if_id = cpu_to_le16(if_id);
  11235. + dpsw_set_field(cmd_params->enable, ENABLE, en);
  11236. +
  11237. + /* send command to mc*/
  11238. + return mc_send_command(mc_io, &cmd);
  11239. +}
  11240. +
  11241. +/**
  11242. + * dpsw_if_set_broadcast() - Enable/disable broadcast for particular interface
  11243. + * @mc_io: Pointer to MC portal's I/O object
  11244. + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
  11245. + * @token: Token of DPSW object
  11246. + * @if_id: Interface Identifier
  11247. + * @en: 1 - enable, 0 - disable
  11248. + *
  11249. + * Return: Completion status. '0' on Success; Error code otherwise.
  11250. + */
  11251. +int dpsw_if_set_broadcast(struct fsl_mc_io *mc_io,
  11252. + u32 cmd_flags,
  11253. + u16 token,
  11254. + u16 if_id,
  11255. + int en)
  11256. +{
  11257. + struct mc_command cmd = { 0 };
  11258. + struct dpsw_cmd_if_set_broadcast *cmd_params;
  11259. +
  11260. + /* prepare command */
  11261. + cmd.header = mc_encode_cmd_header(DPSW_CMDID_IF_SET_BROADCAST,
  11262. + cmd_flags,
  11263. + token);
  11264. + cmd_params = (struct dpsw_cmd_if_set_broadcast *)cmd.params;
  11265. + cmd_params->if_id = cpu_to_le16(if_id);
  11266. + dpsw_set_field(cmd_params->enable, ENABLE, en);
  11267. +
  11268. + /* send command to mc*/
  11269. + return mc_send_command(mc_io, &cmd);
  11270. +}
  11271. +
  11272. +/**
  11273. + * dpsw_if_set_multicast() - Enable/disable multicast for particular interface
  11274. + * @mc_io: Pointer to MC portal's I/O object
  11275. + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
  11276. + * @token: Token of DPSW object
  11277. + * @if_id: Interface Identifier
  11278. + * @en: 1 - enable, 0 - disable
  11279. + *
  11280. + * Return: Completion status. '0' on Success; Error code otherwise.
  11281. + */
  11282. +int dpsw_if_set_multicast(struct fsl_mc_io *mc_io,
  11283. + u32 cmd_flags,
  11284. + u16 token,
  11285. + u16 if_id,
  11286. + int en)
  11287. +{
  11288. + struct mc_command cmd = { 0 };
  11289. + struct dpsw_cmd_if_set_multicast *cmd_params;
  11290. +
  11291. + /* prepare command */
  11292. + cmd.header = mc_encode_cmd_header(DPSW_CMDID_IF_SET_MULTICAST,
  11293. + cmd_flags,
  11294. + token);
  11295. + cmd_params = (struct dpsw_cmd_if_set_multicast *)cmd.params;
  11296. + cmd_params->if_id = cpu_to_le16(if_id);
  11297. + dpsw_set_field(cmd_params->enable, ENABLE, en);
  11298. +
  11299. + /* send command to mc*/
  11300. + return mc_send_command(mc_io, &cmd);
  11301. +}
  11302. +
  11303. +/**
  11304. + * dpsw_if_set_tci() - Set default VLAN Tag Control Information (TCI)
  11305. + * @mc_io: Pointer to MC portal's I/O object
  11306. + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
  11307. + * @token: Token of DPSW object
  11308. + * @if_id: Interface Identifier
  11309. + * @cfg: Tag Control Information Configuration
  11310. + *
  11311. + * Return: Completion status. '0' on Success; Error code otherwise.
  11312. + */
  11313. +int dpsw_if_set_tci(struct fsl_mc_io *mc_io,
  11314. + u32 cmd_flags,
  11315. + u16 token,
  11316. + u16 if_id,
  11317. + const struct dpsw_tci_cfg *cfg)
  11318. +{
  11319. + struct mc_command cmd = { 0 };
  11320. + struct dpsw_cmd_if_set_tci *cmd_params;
  11321. +
  11322. + /* prepare command */
  11323. + cmd.header = mc_encode_cmd_header(DPSW_CMDID_IF_SET_TCI,
  11324. + cmd_flags,
  11325. + token);
  11326. + cmd_params = (struct dpsw_cmd_if_set_tci *)cmd.params;
  11327. + cmd_params->if_id = cpu_to_le16(if_id);
  11328. + dpsw_set_field(cmd_params->conf, VLAN_ID, cfg->vlan_id);
  11329. + dpsw_set_field(cmd_params->conf, DEI, cfg->dei);
  11330. + dpsw_set_field(cmd_params->conf, PCP, cfg->pcp);
  11331. + cmd_params->conf = cpu_to_le16(cmd_params->conf);
  11332. +
  11333. + /* send command to mc*/
  11334. + return mc_send_command(mc_io, &cmd);
  11335. +}
  11336. +
  11337. +/**
  11338. + * dpsw_if_get_tci() - Get default VLAN Tag Control Information (TCI)
  11339. + * @mc_io: Pointer to MC portal's I/O object
  11340. + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
  11341. + * @token: Token of DPSW object
  11342. + * @if_id: Interface Identifier
  11343. + * @cfg: Tag Control Information Configuration
  11344. + *
  11345. + * Return: Completion status. '0' on Success; Error code otherwise.
  11346. + */
  11347. +int dpsw_if_get_tci(struct fsl_mc_io *mc_io,
  11348. + u32 cmd_flags,
  11349. + u16 token,
  11350. + u16 if_id,
  11351. + struct dpsw_tci_cfg *cfg)
  11352. +{
  11353. + struct mc_command cmd = { 0 };
  11354. + struct dpsw_cmd_if_get_tci *cmd_params;
  11355. + struct dpsw_rsp_if_get_tci *rsp_params;
  11356. + int err;
  11357. +
  11358. + /* prepare command */
  11359. + cmd.header = mc_encode_cmd_header(DPSW_CMDID_IF_GET_TCI,
  11360. + cmd_flags,
  11361. + token);
  11362. + cmd_params = (struct dpsw_cmd_if_get_tci *)cmd.params;
  11363. + cmd_params->if_id = cpu_to_le16(if_id);
  11364. +
  11365. + /* send command to mc*/
  11366. + err = mc_send_command(mc_io, &cmd);
  11367. + if (err)
  11368. + return err;
  11369. +
  11370. + /* retrieve response parameters */
  11371. + rsp_params = (struct dpsw_rsp_if_get_tci *)cmd.params;
  11372. + cfg->pcp = rsp_params->pcp;
  11373. + cfg->dei = rsp_params->dei;
  11374. + cfg->vlan_id = le16_to_cpu(rsp_params->vlan_id);
  11375. +
  11376. + return 0;
  11377. +}
  11378. +
  11379. +/**
  11380. + * dpsw_if_set_stp() - Function sets Spanning Tree Protocol (STP) state.
  11381. + * @mc_io: Pointer to MC portal's I/O object
  11382. + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
  11383. + * @token: Token of DPSW object
  11384. + * @if_id: Interface Identifier
  11385. + * @cfg: STP State configuration parameters
  11386. + *
  11387. + * The following STP states are supported -
  11388. + * blocking, listening, learning, forwarding and disabled.
  11389. + *
  11390. + * Return: Completion status. '0' on Success; Error code otherwise.
  11391. + */
  11392. +int dpsw_if_set_stp(struct fsl_mc_io *mc_io,
  11393. + u32 cmd_flags,
  11394. + u16 token,
  11395. + u16 if_id,
  11396. + const struct dpsw_stp_cfg *cfg)
  11397. +{
  11398. + struct mc_command cmd = { 0 };
  11399. + struct dpsw_cmd_if_set_stp *cmd_params;
  11400. +
  11401. + /* prepare command */
  11402. + cmd.header = mc_encode_cmd_header(DPSW_CMDID_IF_SET_STP,
  11403. + cmd_flags,
  11404. + token);
  11405. + cmd_params = (struct dpsw_cmd_if_set_stp *)cmd.params;
  11406. + cmd_params->if_id = cpu_to_le16(if_id);
  11407. + cmd_params->vlan_id = cpu_to_le16(cfg->vlan_id);
  11408. + dpsw_set_field(cmd_params->state, STATE, cfg->state);
  11409. +
  11410. + /* send command to mc*/
  11411. + return mc_send_command(mc_io, &cmd);
  11412. +}
  11413. +
  11414. +/**
  11415. + * dpsw_if_set_accepted_frames()
  11416. + * @mc_io: Pointer to MC portal's I/O object
  11417. + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
  11418. + * @token: Token of DPSW object
  11419. + * @if_id: Interface Identifier
  11420. + * @cfg: Frame types configuration
  11421. + *
  11422. + * When is admit_only_vlan_tagged- the device will discard untagged
  11423. + * frames or Priority-Tagged frames received on this interface.
  11424. + * When admit_only_untagged- untagged frames or Priority-Tagged
  11425. + * frames received on this interface will be accepted and assigned
  11426. + * to a VID based on the PVID and VID Set for this interface.
  11427. + * When admit_all - the device will accept VLAN tagged, untagged
  11428. + * and priority tagged frames.
  11429. + * The default is admit_all
  11430. + *
  11431. + * Return: Completion status. '0' on Success; Error code otherwise.
  11432. + */
  11433. +int dpsw_if_set_accepted_frames(struct fsl_mc_io *mc_io,
  11434. + u32 cmd_flags,
  11435. + u16 token,
  11436. + u16 if_id,
  11437. + const struct dpsw_accepted_frames_cfg *cfg)
  11438. +{
  11439. + struct mc_command cmd = { 0 };
  11440. + struct dpsw_cmd_if_set_accepted_frames *cmd_params;
  11441. +
  11442. + /* prepare command */
  11443. + cmd.header = mc_encode_cmd_header(DPSW_CMDID_IF_SET_ACCEPTED_FRAMES,
  11444. + cmd_flags,
  11445. + token);
  11446. + cmd_params = (struct dpsw_cmd_if_set_accepted_frames *)cmd.params;
  11447. + cmd_params->if_id = cpu_to_le16(if_id);
  11448. + dpsw_set_field(cmd_params->unaccepted, FRAME_TYPE, cfg->type);
  11449. + dpsw_set_field(cmd_params->unaccepted, UNACCEPTED_ACT,
  11450. + cfg->unaccept_act);
  11451. +
  11452. + /* send command to mc*/
  11453. + return mc_send_command(mc_io, &cmd);
  11454. +}
  11455. +
  11456. +/**
  11457. + * dpsw_if_set_accept_all_vlan()
  11458. + * @mc_io: Pointer to MC portal's I/O object
  11459. + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
  11460. + * @token: Token of DPSW object
  11461. + * @if_id: Interface Identifier
  11462. + * @accept_all: Accept or drop frames having different VLAN
  11463. + *
  11464. + * When this is accept (FALSE), the device will discard incoming
  11465. + * frames for VLANs that do not include this interface in its
  11466. + * Member set. When accept (TRUE), the interface will accept all incoming frames
  11467. + *
  11468. + * Return: Completion status. '0' on Success; Error code otherwise.
  11469. + */
  11470. +int dpsw_if_set_accept_all_vlan(struct fsl_mc_io *mc_io,
  11471. + u32 cmd_flags,
  11472. + u16 token,
  11473. + u16 if_id,
  11474. + int accept_all)
  11475. +{
  11476. + struct mc_command cmd = { 0 };
  11477. + struct dpsw_cmd_if_set_accept_all_vlan *cmd_params;
  11478. +
  11479. + /* prepare command */
  11480. + cmd.header = mc_encode_cmd_header(DPSW_CMDID_SET_IF_ACCEPT_ALL_VLAN,
  11481. + cmd_flags,
  11482. + token);
  11483. + cmd_params = (struct dpsw_cmd_if_set_accept_all_vlan *)cmd.params;
  11484. + cmd_params->if_id = cpu_to_le16(if_id);
  11485. + dpsw_set_field(cmd_params->accept_all, ACCEPT_ALL, accept_all);
  11486. +
  11487. + /* send command to mc*/
  11488. + return mc_send_command(mc_io, &cmd);
  11489. +}
  11490. +
  11491. +/**
  11492. + * dpsw_if_get_counter() - Get specific counter of particular interface
  11493. + * @mc_io: Pointer to MC portal's I/O object
  11494. + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
  11495. + * @token: Token of DPSW object
  11496. + * @if_id: Interface Identifier
  11497. + * @type: Counter type
  11498. + * @counter: return value
  11499. + *
  11500. + * Return: Completion status. '0' on Success; Error code otherwise.
  11501. + */
  11502. +int dpsw_if_get_counter(struct fsl_mc_io *mc_io,
  11503. + u32 cmd_flags,
  11504. + u16 token,
  11505. + u16 if_id,
  11506. + enum dpsw_counter type,
  11507. + u64 *counter)
  11508. +{
  11509. + struct mc_command cmd = { 0 };
  11510. + struct dpsw_cmd_if_get_counter *cmd_params;
  11511. + struct dpsw_rsp_if_get_counter *rsp_params;
  11512. + int err;
  11513. +
  11514. + /* prepare command */
  11515. + cmd.header = mc_encode_cmd_header(DPSW_CMDID_IF_GET_COUNTER,
  11516. + cmd_flags,
  11517. + token);
  11518. + cmd_params = (struct dpsw_cmd_if_get_counter *)cmd.params;
  11519. + cmd_params->if_id = cpu_to_le16(if_id);
  11520. + dpsw_set_field(cmd_params->type, COUNTER_TYPE, type);
  11521. +
  11522. + /* send command to mc*/
  11523. + err = mc_send_command(mc_io, &cmd);
  11524. + if (err)
  11525. + return err;
  11526. +
  11527. + /* retrieve response parameters */
  11528. + rsp_params = (struct dpsw_rsp_if_get_counter *)cmd.params;
  11529. + *counter = le64_to_cpu(rsp_params->counter);
  11530. +
  11531. + return 0;
  11532. +}
  11533. +
  11534. +/**
  11535. + * dpsw_if_set_counter() - Set specific counter of particular interface
  11536. + * @mc_io: Pointer to MC portal's I/O object
  11537. + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
  11538. + * @token: Token of DPSW object
  11539. + * @if_id: Interface Identifier
  11540. + * @type: Counter type
  11541. + * @counter: New counter value
  11542. + *
  11543. + * Return: Completion status. '0' on Success; Error code otherwise.
  11544. + */
  11545. +int dpsw_if_set_counter(struct fsl_mc_io *mc_io,
  11546. + u32 cmd_flags,
  11547. + u16 token,
  11548. + u16 if_id,
  11549. + enum dpsw_counter type,
  11550. + u64 counter)
  11551. +{
  11552. + struct mc_command cmd = { 0 };
  11553. + struct dpsw_cmd_if_set_counter *cmd_params;
  11554. +
  11555. + /* prepare command */
  11556. + cmd.header = mc_encode_cmd_header(DPSW_CMDID_IF_SET_COUNTER,
  11557. + cmd_flags,
  11558. + token);
  11559. + cmd_params = (struct dpsw_cmd_if_set_counter *)cmd.params;
  11560. + cmd_params->if_id = cpu_to_le16(if_id);
  11561. + cmd_params->counter = cpu_to_le64(counter);
  11562. + dpsw_set_field(cmd_params->type, COUNTER_TYPE, type);
  11563. +
  11564. + /* send command to mc*/
  11565. + return mc_send_command(mc_io, &cmd);
  11566. +}
  11567. +
  11568. +/**
  11569. + * dpsw_if_set_tx_selection() - Function is used for mapping variety
  11570. + * of frame fields
  11571. + * @mc_io: Pointer to MC portal's I/O object
  11572. + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
  11573. + * @token: Token of DPSW object
  11574. + * @if_id: Interface Identifier
  11575. + * @cfg: Traffic class mapping configuration
  11576. + *
  11577. + * Function is used for mapping variety of frame fields (DSCP, PCP)
  11578. + * to Traffic Class. Traffic class is a number
  11579. + * in the range from 0 to 7
  11580. + *
  11581. + * Return: Completion status. '0' on Success; Error code otherwise.
  11582. + */
  11583. +int dpsw_if_set_tx_selection(struct fsl_mc_io *mc_io,
  11584. + u32 cmd_flags,
  11585. + u16 token,
  11586. + u16 if_id,
  11587. + const struct dpsw_tx_selection_cfg *cfg)
  11588. +{
  11589. + struct dpsw_cmd_if_set_tx_selection *cmd_params;
  11590. + struct mc_command cmd = { 0 };
  11591. + int i;
  11592. +
  11593. + /* prepare command */
  11594. + cmd.header = mc_encode_cmd_header(DPSW_CMDID_IF_SET_TX_SELECTION,
  11595. + cmd_flags,
  11596. + token);
  11597. + cmd_params = (struct dpsw_cmd_if_set_tx_selection *)cmd.params;
  11598. + cmd_params->if_id = cpu_to_le16(if_id);
  11599. + dpsw_set_field(cmd_params->priority_selector, PRIORITY_SELECTOR,
  11600. + cfg->priority_selector);
  11601. +
  11602. + for (i = 0; i < 8; i++) {
  11603. + cmd_params->tc_sched[i].delta_bandwidth =
  11604. + cpu_to_le16(cfg->tc_sched[i].delta_bandwidth);
  11605. + dpsw_set_field(cmd_params->tc_sched[i].mode, SCHED_MODE,
  11606. + cfg->tc_sched[i].mode);
  11607. + cmd_params->tc_id[i] = cfg->tc_id[i];
  11608. + }
  11609. +
  11610. + /* send command to mc*/
  11611. + return mc_send_command(mc_io, &cmd);
  11612. +}
  11613. +
  11614. +/**
  11615. + * dpsw_if_add_reflection() - Identify interface to be reflected or mirrored
  11616. + * @mc_io: Pointer to MC portal's I/O object
  11617. + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
  11618. + * @token: Token of DPSW object
  11619. + * @if_id: Interface Identifier
  11620. + * @cfg: Reflection configuration
  11621. + *
  11622. + * Return: Completion status. '0' on Success; Error code otherwise.
  11623. + */
  11624. +int dpsw_if_add_reflection(struct fsl_mc_io *mc_io,
  11625. + u32 cmd_flags,
  11626. + u16 token,
  11627. + u16 if_id,
  11628. + const struct dpsw_reflection_cfg *cfg)
  11629. +{
  11630. + struct mc_command cmd = { 0 };
  11631. + struct dpsw_cmd_if_reflection *cmd_params;
  11632. +
  11633. + /* prepare command */
  11634. + cmd.header = mc_encode_cmd_header(DPSW_CMDID_IF_ADD_REFLECTION,
  11635. + cmd_flags,
  11636. + token);
  11637. + cmd_params = (struct dpsw_cmd_if_reflection *)cmd.params;
  11638. + cmd_params->if_id = cpu_to_le16(if_id);
  11639. + cmd_params->vlan_id = cpu_to_le16(cfg->vlan_id);
  11640. + dpsw_set_field(cmd_params->filter, FILTER, cfg->filter);
  11641. +
  11642. + /* send command to mc*/
  11643. + return mc_send_command(mc_io, &cmd);
  11644. +}
  11645. +
  11646. +/**
  11647. + * dpsw_if_remove_reflection() - Remove interface to be reflected or mirrored
  11648. + * @mc_io: Pointer to MC portal's I/O object
  11649. + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
  11650. + * @token: Token of DPSW object
  11651. + * @if_id: Interface Identifier
  11652. + * @cfg: Reflection configuration
  11653. + *
  11654. + * Return: Completion status. '0' on Success; Error code otherwise.
  11655. + */
  11656. +int dpsw_if_remove_reflection(struct fsl_mc_io *mc_io,
  11657. + u32 cmd_flags,
  11658. + u16 token,
  11659. + u16 if_id,
  11660. + const struct dpsw_reflection_cfg *cfg)
  11661. +{
  11662. + struct mc_command cmd = { 0 };
  11663. + struct dpsw_cmd_if_reflection *cmd_params;
  11664. +
  11665. + /* prepare command */
  11666. + cmd.header = mc_encode_cmd_header(DPSW_CMDID_IF_REMOVE_REFLECTION,
  11667. + cmd_flags,
  11668. + token);
  11669. + cmd_params = (struct dpsw_cmd_if_reflection *)cmd.params;
  11670. + cmd_params->if_id = cpu_to_le16(if_id);
  11671. + cmd_params->vlan_id = cpu_to_le16(cfg->vlan_id);
  11672. + dpsw_set_field(cmd_params->filter, FILTER, cfg->filter);
  11673. +
  11674. + /* send command to mc*/
  11675. + return mc_send_command(mc_io, &cmd);
  11676. +}
  11677. +
  11678. +/**
  11679. + * dpsw_if_set_flooding_metering() - Set flooding metering
  11680. + * @mc_io: Pointer to MC portal's I/O object
  11681. + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
  11682. + * @token: Token of DPSW object
  11683. + * @if_id: Interface Identifier
  11684. + * @cfg: Metering parameters
  11685. + *
  11686. + * Return: Completion status. '0' on Success; Error code otherwise.
  11687. + */
  11688. +int dpsw_if_set_flooding_metering(struct fsl_mc_io *mc_io,
  11689. + u32 cmd_flags,
  11690. + u16 token,
  11691. + u16 if_id,
  11692. + const struct dpsw_metering_cfg *cfg)
  11693. +{
  11694. + struct mc_command cmd = { 0 };
  11695. + struct dpsw_cmd_if_set_flooding_metering *cmd_params;
  11696. +
  11697. + /* prepare command */
  11698. + cmd.header = mc_encode_cmd_header(DPSW_CMDID_IF_SET_FLOODING_METERING,
  11699. + cmd_flags,
  11700. + token);
  11701. + cmd_params = (struct dpsw_cmd_if_set_flooding_metering *)cmd.params;
  11702. + cmd_params->if_id = cpu_to_le16(if_id);
  11703. + dpsw_set_field(cmd_params->mode_units, MODE, cfg->mode);
  11704. + dpsw_set_field(cmd_params->mode_units, UNITS, cfg->units);
  11705. + cmd_params->cir = cpu_to_le32(cfg->cir);
  11706. + cmd_params->eir = cpu_to_le32(cfg->eir);
  11707. + cmd_params->cbs = cpu_to_le32(cfg->cbs);
  11708. + cmd_params->ebs = cpu_to_le32(cfg->ebs);
  11709. +
  11710. + /* send command to mc*/
  11711. + return mc_send_command(mc_io, &cmd);
  11712. +}
  11713. +
  11714. +/**
  11715. + * dpsw_if_set_metering() - Set interface metering for flooding
  11716. + * @mc_io: Pointer to MC portal's I/O object
  11717. + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
  11718. + * @token: Token of DPSW object
  11719. + * @if_id: Interface Identifier
  11720. + * @tc_id: Traffic class ID
  11721. + * @cfg: Metering parameters
  11722. + *
  11723. + * Return: Completion status. '0' on Success; Error code otherwise.
  11724. + */
  11725. +int dpsw_if_set_metering(struct fsl_mc_io *mc_io,
  11726. + u32 cmd_flags,
  11727. + u16 token,
  11728. + u16 if_id,
  11729. + u8 tc_id,
  11730. + const struct dpsw_metering_cfg *cfg)
  11731. +{
  11732. + struct mc_command cmd = { 0 };
  11733. + struct dpsw_cmd_if_set_metering *cmd_params;
  11734. +
  11735. + /* prepare command */
  11736. + cmd.header = mc_encode_cmd_header(DPSW_CMDID_IF_SET_METERING,
  11737. + cmd_flags,
  11738. + token);
  11739. + cmd_params = (struct dpsw_cmd_if_set_metering *)cmd.params;
  11740. + cmd_params->if_id = cpu_to_le16(if_id);
  11741. + cmd_params->tc_id = tc_id;
  11742. + dpsw_set_field(cmd_params->mode_units, MODE, cfg->mode);
  11743. + dpsw_set_field(cmd_params->mode_units, UNITS, cfg->units);
  11744. + cmd_params->cir = cpu_to_le32(cfg->cir);
  11745. + cmd_params->eir = cpu_to_le32(cfg->eir);
  11746. + cmd_params->cbs = cpu_to_le32(cfg->cbs);
  11747. + cmd_params->ebs = cpu_to_le32(cfg->ebs);
  11748. +
  11749. + /* send command to mc*/
  11750. + return mc_send_command(mc_io, &cmd);
  11751. +}
  11752. +
  11753. +/**
  11754. + * dpsw_prepare_early_drop() - Prepare an early drop for setting in to interface
  11755. + * @cfg: Early-drop configuration
  11756. + * @early_drop_buf: Zeroed 256 bytes of memory before mapping it to DMA
  11757. + *
  11758. + * This function has to be called before dpsw_if_tc_set_early_drop
  11759. + *
  11760. + */
  11761. +void dpsw_prepare_early_drop(const struct dpsw_early_drop_cfg *cfg,
  11762. + u8 *early_drop_buf)
  11763. +{
  11764. + struct dpsw_prep_early_drop *ext_params;
  11765. +
  11766. + ext_params = (struct dpsw_prep_early_drop *)early_drop_buf;
  11767. + dpsw_set_field(ext_params->conf, EARLY_DROP_MODE, cfg->drop_mode);
  11768. + dpsw_set_field(ext_params->conf, EARLY_DROP_UNIT, cfg->units);
  11769. + ext_params->tail_drop_threshold = cpu_to_le32(cfg->tail_drop_threshold);
  11770. + ext_params->green_drop_probability = cfg->green.drop_probability;
  11771. + ext_params->green_max_threshold = cpu_to_le64(cfg->green.max_threshold);
  11772. + ext_params->green_min_threshold = cpu_to_le64(cfg->green.min_threshold);
  11773. + ext_params->yellow_drop_probability = cfg->yellow.drop_probability;
  11774. + ext_params->yellow_max_threshold =
  11775. + cpu_to_le64(cfg->yellow.max_threshold);
  11776. + ext_params->yellow_min_threshold =
  11777. + cpu_to_le64(cfg->yellow.min_threshold);
  11778. +}
  11779. +
  11780. +/**
  11781. + * dpsw_if_set_early_drop() - Set interface traffic class early-drop
  11782. + * configuration
  11783. + * @mc_io: Pointer to MC portal's I/O object
  11784. + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
  11785. + * @token: Token of DPSW object
  11786. + * @if_id: Interface Identifier
  11787. + * @tc_id: Traffic class selection (0-7)
  11788. + * @early_drop_iova: I/O virtual address of 64 bytes;
  11789. + * Must be cacheline-aligned and DMA-able memory
  11790. + *
  11791. + * warning: Before calling this function, call dpsw_prepare_if_tc_early_drop()
  11792. + * to prepare the early_drop_iova parameter
  11793. + *
  11794. + * Return: '0' on Success; error code otherwise.
  11795. + */
  11796. +int dpsw_if_set_early_drop(struct fsl_mc_io *mc_io,
  11797. + u32 cmd_flags,
  11798. + u16 token,
  11799. + u16 if_id,
  11800. + u8 tc_id,
  11801. + u64 early_drop_iova)
  11802. +{
  11803. + struct mc_command cmd = { 0 };
  11804. + struct dpsw_cmd_if_set_early_drop *cmd_params;
  11805. +
  11806. + /* prepare command */
  11807. + cmd.header = mc_encode_cmd_header(DPSW_CMDID_IF_SET_EARLY_DROP,
  11808. + cmd_flags,
  11809. + token);
  11810. + cmd_params = (struct dpsw_cmd_if_set_early_drop *)cmd.params;
  11811. + cmd_params->tc_id = tc_id;
  11812. + cmd_params->if_id = cpu_to_le16(if_id);
  11813. + cmd_params->early_drop_iova = cpu_to_le64(early_drop_iova);
  11814. +
  11815. + /* send command to mc*/
  11816. + return mc_send_command(mc_io, &cmd);
  11817. +}
  11818. +
  11819. +/**
  11820. + * dpsw_add_custom_tpid() - API Configures a distinct Ethernet type value
  11821. + * @mc_io: Pointer to MC portal's I/O object
  11822. + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
  11823. + * @token: Token of DPSW object
  11824. + * @cfg: Tag Protocol identifier
  11825. + *
  11826. + * API Configures a distinct Ethernet type value (or TPID value)
  11827. + * to indicate a VLAN tag in addition to the common
  11828. + * TPID values 0x8100 and 0x88A8.
  11829. + * Two additional TPID's are supported
  11830. + *
  11831. + * Return: Completion status. '0' on Success; Error code otherwise.
  11832. + */
  11833. +int dpsw_add_custom_tpid(struct fsl_mc_io *mc_io,
  11834. + u32 cmd_flags,
  11835. + u16 token,
  11836. + const struct dpsw_custom_tpid_cfg *cfg)
  11837. +{
  11838. + struct mc_command cmd = { 0 };
  11839. + struct dpsw_cmd_custom_tpid *cmd_params;
  11840. +
  11841. + /* prepare command */
  11842. + cmd.header = mc_encode_cmd_header(DPSW_CMDID_ADD_CUSTOM_TPID,
  11843. + cmd_flags,
  11844. + token);
  11845. + cmd_params = (struct dpsw_cmd_custom_tpid *)cmd.params;
  11846. + cmd_params->tpid = cpu_to_le16(cfg->tpid);
  11847. +
  11848. + /* send command to mc*/
  11849. + return mc_send_command(mc_io, &cmd);
  11850. +}
  11851. +
  11852. +/**
  11853. + * dpsw_remove_custom_tpid - API removes a distinct Ethernet type value
  11854. + * @mc_io: Pointer to MC portal's I/O object
  11855. + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
  11856. + * @token: Token of DPSW object
  11857. + * @cfg: Tag Protocol identifier
  11858. + *
  11859. + * Return: Completion status. '0' on Success; Error code otherwise.
  11860. + */
  11861. +int dpsw_remove_custom_tpid(struct fsl_mc_io *mc_io,
  11862. + u32 cmd_flags,
  11863. + u16 token,
  11864. + const struct dpsw_custom_tpid_cfg *cfg)
  11865. +{
  11866. + struct mc_command cmd = { 0 };
  11867. + struct dpsw_cmd_custom_tpid *cmd_params;
  11868. +
  11869. + /* prepare command */
  11870. + cmd.header = mc_encode_cmd_header(DPSW_CMDID_REMOVE_CUSTOM_TPID,
  11871. + cmd_flags,
  11872. + token);
  11873. + cmd_params = (struct dpsw_cmd_custom_tpid *)cmd.params;
  11874. + cmd_params->tpid = cpu_to_le16(cfg->tpid);
  11875. +
  11876. + /* send command to mc*/
  11877. + return mc_send_command(mc_io, &cmd);
  11878. +}
  11879. +
  11880. +/**
  11881. + * dpsw_if_enable() - Enable Interface
  11882. + * @mc_io: Pointer to MC portal's I/O object
  11883. + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
  11884. + * @token: Token of DPSW object
  11885. + * @if_id: Interface Identifier
  11886. + *
  11887. + * Return: Completion status. '0' on Success; Error code otherwise.
  11888. + */
  11889. +int dpsw_if_enable(struct fsl_mc_io *mc_io,
  11890. + u32 cmd_flags,
  11891. + u16 token,
  11892. + u16 if_id)
  11893. +{
  11894. + struct mc_command cmd = { 0 };
  11895. + struct dpsw_cmd_if *cmd_params;
  11896. +
  11897. + /* prepare command */
  11898. + cmd.header = mc_encode_cmd_header(DPSW_CMDID_IF_ENABLE,
  11899. + cmd_flags,
  11900. + token);
  11901. + cmd_params = (struct dpsw_cmd_if *)cmd.params;
  11902. + cmd_params->if_id = cpu_to_le16(if_id);
  11903. +
  11904. + /* send command to mc*/
  11905. + return mc_send_command(mc_io, &cmd);
  11906. +}
  11907. +
  11908. +/**
  11909. + * dpsw_if_disable() - Disable Interface
  11910. + * @mc_io: Pointer to MC portal's I/O object
  11911. + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
  11912. + * @token: Token of DPSW object
  11913. + * @if_id: Interface Identifier
  11914. + *
  11915. + * Return: Completion status. '0' on Success; Error code otherwise.
  11916. + */
  11917. +int dpsw_if_disable(struct fsl_mc_io *mc_io,
  11918. + u32 cmd_flags,
  11919. + u16 token,
  11920. + u16 if_id)
  11921. +{
  11922. + struct mc_command cmd = { 0 };
  11923. + struct dpsw_cmd_if *cmd_params;
  11924. +
  11925. + /* prepare command */
  11926. + cmd.header = mc_encode_cmd_header(DPSW_CMDID_IF_DISABLE,
  11927. + cmd_flags,
  11928. + token);
  11929. + cmd_params = (struct dpsw_cmd_if *)cmd.params;
  11930. + cmd_params->if_id = cpu_to_le16(if_id);
  11931. +
  11932. + /* send command to mc*/
  11933. + return mc_send_command(mc_io, &cmd);
  11934. +}
  11935. +
  11936. +/**
  11937. + * dpsw_if_get_attributes() - Function obtains attributes of interface
  11938. + * @mc_io: Pointer to MC portal's I/O object
  11939. + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
  11940. + * @token: Token of DPSW object
  11941. + * @if_id: Interface Identifier
  11942. + * @attr: Returned interface attributes
  11943. + *
  11944. + * Return: Completion status. '0' on Success; Error code otherwise.
  11945. + */
  11946. +int dpsw_if_get_attributes(struct fsl_mc_io *mc_io,
  11947. + u32 cmd_flags,
  11948. + u16 token,
  11949. + u16 if_id,
  11950. + struct dpsw_if_attr *attr)
  11951. +{
  11952. + struct dpsw_rsp_if_get_attr *rsp_params;
  11953. + struct dpsw_cmd_if *cmd_params;
  11954. + struct mc_command cmd = { 0 };
  11955. + int err;
  11956. +
  11957. + /* prepare command */
  11958. + cmd.header = mc_encode_cmd_header(DPSW_CMDID_IF_GET_ATTR,
  11959. + cmd_flags,
  11960. + token);
  11961. + cmd_params = (struct dpsw_cmd_if *)cmd.params;
  11962. + cmd_params->if_id = cpu_to_le16(if_id);
  11963. +
  11964. + /* send command to mc*/
  11965. + err = mc_send_command(mc_io, &cmd);
  11966. + if (err)
  11967. + return err;
  11968. +
  11969. + /* retrieve response parameters */
  11970. + rsp_params = (struct dpsw_rsp_if_get_attr *)cmd.params;
  11971. + attr->num_tcs = rsp_params->num_tcs;
  11972. + attr->rate = le32_to_cpu(rsp_params->rate);
  11973. + attr->options = le32_to_cpu(rsp_params->options);
  11974. + attr->enabled = dpsw_get_field(rsp_params->conf, ENABLED);
  11975. + attr->accept_all_vlan = dpsw_get_field(rsp_params->conf,
  11976. + ACCEPT_ALL_VLAN);
  11977. + attr->admit_untagged = dpsw_get_field(rsp_params->conf, ADMIT_UNTAGGED);
  11978. + attr->qdid = le16_to_cpu(rsp_params->qdid);
  11979. +
  11980. + return 0;
  11981. +}
  11982. +
  11983. +/**
  11984. + * dpsw_if_set_max_frame_length() - Set Maximum Receive frame length.
  11985. + * @mc_io: Pointer to MC portal's I/O object
  11986. + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
  11987. + * @token: Token of DPSW object
  11988. + * @if_id: Interface Identifier
  11989. + * @frame_length: Maximum Frame Length
  11990. + *
  11991. + * Return: Completion status. '0' on Success; Error code otherwise.
  11992. + */
  11993. +int dpsw_if_set_max_frame_length(struct fsl_mc_io *mc_io,
  11994. + u32 cmd_flags,
  11995. + u16 token,
  11996. + u16 if_id,
  11997. + u16 frame_length)
  11998. +{
  11999. + struct mc_command cmd = { 0 };
  12000. + struct dpsw_cmd_if_set_max_frame_length *cmd_params;
  12001. +
  12002. + /* prepare command */
  12003. + cmd.header = mc_encode_cmd_header(DPSW_CMDID_IF_SET_MAX_FRAME_LENGTH,
  12004. + cmd_flags,
  12005. + token);
  12006. + cmd_params = (struct dpsw_cmd_if_set_max_frame_length *)cmd.params;
  12007. + cmd_params->if_id = cpu_to_le16(if_id);
  12008. + cmd_params->frame_length = cpu_to_le16(frame_length);
  12009. +
  12010. + /* send command to mc*/
  12011. + return mc_send_command(mc_io, &cmd);
  12012. +}
  12013. +
  12014. +/**
  12015. + * dpsw_if_get_max_frame_length() - Get Maximum Receive frame length.
  12016. + * @mc_io: Pointer to MC portal's I/O object
  12017. + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
  12018. + * @token: Token of DPSW object
  12019. + * @if_id: Interface Identifier
  12020. + * @frame_length: Returned maximum Frame Length
  12021. + *
  12022. + * Return: Completion status. '0' on Success; Error code otherwise.
  12023. + */
  12024. +int dpsw_if_get_max_frame_length(struct fsl_mc_io *mc_io,
  12025. + u32 cmd_flags,
  12026. + u16 token,
  12027. + u16 if_id,
  12028. + u16 *frame_length)
  12029. +{
  12030. + struct mc_command cmd = { 0 };
  12031. + struct dpsw_cmd_if_get_max_frame_length *cmd_params;
  12032. + struct dpsw_rsp_if_get_max_frame_length *rsp_params;
  12033. + int err;
  12034. +
  12035. + /* prepare command */
  12036. + cmd.header = mc_encode_cmd_header(DPSW_CMDID_IF_GET_MAX_FRAME_LENGTH,
  12037. + cmd_flags,
  12038. + token);
  12039. + cmd_params = (struct dpsw_cmd_if_get_max_frame_length *)cmd.params;
  12040. + cmd_params->if_id = cpu_to_le16(if_id);
  12041. +
  12042. + /* send command to mc*/
  12043. + err = mc_send_command(mc_io, &cmd);
  12044. + if (err)
  12045. + return err;
  12046. +
  12047. + rsp_params = (struct dpsw_rsp_if_get_max_frame_length *)cmd.params;
  12048. + *frame_length = le16_to_cpu(rsp_params->frame_length);
  12049. +
  12050. + return 0;
  12051. +}
  12052. +
  12053. +/**
  12054. + * dpsw_vlan_add() - Adding new VLAN to DPSW.
  12055. + * @mc_io: Pointer to MC portal's I/O object
  12056. + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
  12057. + * @token: Token of DPSW object
  12058. + * @vlan_id: VLAN Identifier
  12059. + * @cfg: VLAN configuration
  12060. + *
  12061. + * Only VLAN ID and FDB ID are required parameters here.
  12062. + * 12 bit VLAN ID is defined in IEEE802.1Q.
  12063. + * Adding a duplicate VLAN ID is not allowed.
  12064. + * FDB ID can be shared across multiple VLANs. Shared learning
  12065. + * is obtained by calling dpsw_vlan_add for multiple VLAN IDs
  12066. + * with same fdb_id
  12067. + *
  12068. + * Return: Completion status. '0' on Success; Error code otherwise.
  12069. + */
  12070. +int dpsw_vlan_add(struct fsl_mc_io *mc_io,
  12071. + u32 cmd_flags,
  12072. + u16 token,
  12073. + u16 vlan_id,
  12074. + const struct dpsw_vlan_cfg *cfg)
  12075. +{
  12076. + struct mc_command cmd = { 0 };
  12077. + struct dpsw_vlan_add *cmd_params;
  12078. +
  12079. + /* prepare command */
  12080. + cmd.header = mc_encode_cmd_header(DPSW_CMDID_VLAN_ADD,
  12081. + cmd_flags,
  12082. + token);
  12083. + cmd_params = (struct dpsw_vlan_add *)cmd.params;
  12084. + cmd_params->fdb_id = cpu_to_le16(cfg->fdb_id);
  12085. + cmd_params->vlan_id = cpu_to_le16(vlan_id);
  12086. +
  12087. + /* send command to mc*/
  12088. + return mc_send_command(mc_io, &cmd);
  12089. +}
  12090. +
  12091. +/**
  12092. + * dpsw_vlan_add_if() - Adding a set of interfaces to an existing VLAN.
  12093. + * @mc_io: Pointer to MC portal's I/O object
  12094. + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
  12095. + * @token: Token of DPSW object
  12096. + * @vlan_id: VLAN Identifier
  12097. + * @cfg: Set of interfaces to add
  12098. + *
  12099. + * It adds only interfaces not belonging to this VLAN yet,
  12100. + * otherwise an error is generated and an entire command is
  12101. + * ignored. This function can be called numerous times always
  12102. + * providing required interfaces delta.
  12103. + *
  12104. + * Return: Completion status. '0' on Success; Error code otherwise.
  12105. + */
  12106. +int dpsw_vlan_add_if(struct fsl_mc_io *mc_io,
  12107. + u32 cmd_flags,
  12108. + u16 token,
  12109. + u16 vlan_id,
  12110. + const struct dpsw_vlan_if_cfg *cfg)
  12111. +{
  12112. + struct mc_command cmd = { 0 };
  12113. + struct dpsw_cmd_vlan_manage_if *cmd_params;
  12114. +
  12115. + /* prepare command */
  12116. + cmd.header = mc_encode_cmd_header(DPSW_CMDID_VLAN_ADD_IF,
  12117. + cmd_flags,
  12118. + token);
  12119. + cmd_params = (struct dpsw_cmd_vlan_manage_if *)cmd.params;
  12120. + cmd_params->vlan_id = cpu_to_le16(vlan_id);
  12121. + build_if_id_bitmap(cmd_params->if_id, cfg->if_id, cfg->num_ifs);
  12122. +
  12123. + /* send command to mc*/
  12124. + return mc_send_command(mc_io, &cmd);
  12125. +}
  12126. +
  12127. +/**
  12128. + * dpsw_vlan_add_if_untagged() - Defining a set of interfaces that should be
  12129. + * transmitted as untagged.
  12130. + * @mc_io: Pointer to MC portal's I/O object
  12131. + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
  12132. + * @token: Token of DPSW object
  12133. + * @vlan_id: VLAN Identifier
  12134. + * @cfg: Set of interfaces that should be transmitted as untagged
  12135. + *
  12136. + * These interfaces should already belong to this VLAN.
  12137. + * By default all interfaces are transmitted as tagged.
  12138. + * Providing un-existing interface or untagged interface that is
  12139. + * configured untagged already generates an error and the entire
  12140. + * command is ignored.
  12141. + *
  12142. + * Return: Completion status. '0' on Success; Error code otherwise.
  12143. + */
  12144. +int dpsw_vlan_add_if_untagged(struct fsl_mc_io *mc_io,
  12145. + u32 cmd_flags,
  12146. + u16 token,
  12147. + u16 vlan_id,
  12148. + const struct dpsw_vlan_if_cfg *cfg)
  12149. +{
  12150. + struct mc_command cmd = { 0 };
  12151. + struct dpsw_cmd_vlan_manage_if *cmd_params;
  12152. +
  12153. + /* prepare command */
  12154. + cmd.header = mc_encode_cmd_header(DPSW_CMDID_VLAN_ADD_IF_UNTAGGED,
  12155. + cmd_flags,
  12156. + token);
  12157. + cmd_params = (struct dpsw_cmd_vlan_manage_if *)cmd.params;
  12158. + cmd_params->vlan_id = cpu_to_le16(vlan_id);
  12159. + build_if_id_bitmap(cmd_params->if_id, cfg->if_id, cfg->num_ifs);
  12160. +
  12161. + /* send command to mc*/
  12162. + return mc_send_command(mc_io, &cmd);
  12163. +}
  12164. +
  12165. +/**
  12166. + * dpsw_vlan_add_if_flooding() - Define a set of interfaces that should be
  12167. + * included in flooding when frame with unknown destination
  12168. + * unicast MAC arrived.
  12169. + * @mc_io: Pointer to MC portal's I/O object
  12170. + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
  12171. + * @token: Token of DPSW object
  12172. + * @vlan_id: VLAN Identifier
  12173. + * @cfg: Set of interfaces that should be used for flooding
  12174. + *
  12175. + * These interfaces should belong to this VLAN. By default all
  12176. + * interfaces are included into flooding list. Providing
  12177. + * un-existing interface or an interface that already in the
  12178. + * flooding list generates an error and the entire command is
  12179. + * ignored.
  12180. + *
  12181. + * Return: Completion status. '0' on Success; Error code otherwise.
  12182. + */
  12183. +int dpsw_vlan_add_if_flooding(struct fsl_mc_io *mc_io,
  12184. + u32 cmd_flags,
  12185. + u16 token,
  12186. + u16 vlan_id,
  12187. + const struct dpsw_vlan_if_cfg *cfg)
  12188. +{
  12189. + struct mc_command cmd = { 0 };
  12190. + struct dpsw_cmd_vlan_manage_if *cmd_params;
  12191. +
  12192. + /* prepare command */
  12193. + cmd.header = mc_encode_cmd_header(DPSW_CMDID_VLAN_ADD_IF_FLOODING,
  12194. + cmd_flags,
  12195. + token);
  12196. + cmd_params = (struct dpsw_cmd_vlan_manage_if *)cmd.params;
  12197. + cmd_params->vlan_id = cpu_to_le16(vlan_id);
  12198. + build_if_id_bitmap(cmd_params->if_id, cfg->if_id, cfg->num_ifs);
  12199. +
  12200. + /* send command to mc*/
  12201. + return mc_send_command(mc_io, &cmd);
  12202. +}
  12203. +
  12204. +/**
  12205. + * dpsw_vlan_remove_if() - Remove interfaces from an existing VLAN.
  12206. + * @mc_io: Pointer to MC portal's I/O object
  12207. + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
  12208. + * @token: Token of DPSW object
  12209. + * @vlan_id: VLAN Identifier
  12210. + * @cfg: Set of interfaces that should be removed
  12211. + *
  12212. + * Interfaces must belong to this VLAN, otherwise an error
  12213. + * is returned and an the command is ignored
  12214. + *
  12215. + * Return: Completion status. '0' on Success; Error code otherwise.
  12216. + */
  12217. +int dpsw_vlan_remove_if(struct fsl_mc_io *mc_io,
  12218. + u32 cmd_flags,
  12219. + u16 token,
  12220. + u16 vlan_id,
  12221. + const struct dpsw_vlan_if_cfg *cfg)
  12222. +{
  12223. + struct mc_command cmd = { 0 };
  12224. + struct dpsw_cmd_vlan_manage_if *cmd_params;
  12225. +
  12226. + /* prepare command */
  12227. + cmd.header = mc_encode_cmd_header(DPSW_CMDID_VLAN_REMOVE_IF,
  12228. + cmd_flags,
  12229. + token);
  12230. + cmd_params = (struct dpsw_cmd_vlan_manage_if *)cmd.params;
  12231. + cmd_params->vlan_id = cpu_to_le16(vlan_id);
  12232. + build_if_id_bitmap(cmd_params->if_id, cfg->if_id, cfg->num_ifs);
  12233. +
  12234. + /* send command to mc*/
  12235. + return mc_send_command(mc_io, &cmd);
  12236. +}
  12237. +
  12238. +/**
  12239. + * dpsw_vlan_remove_if_untagged() - Define a set of interfaces that should be
  12240. + * converted from transmitted as untagged to transmit as tagged.
  12241. + * @mc_io: Pointer to MC portal's I/O object
  12242. + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
  12243. + * @token: Token of DPSW object
  12244. + * @vlan_id: VLAN Identifier
  12245. + * @cfg: Set of interfaces that should be removed
  12246. + *
  12247. + * Interfaces provided by API have to belong to this VLAN and
  12248. + * configured untagged, otherwise an error is returned and the
  12249. + * command is ignored
  12250. + *
  12251. + * Return: Completion status. '0' on Success; Error code otherwise.
  12252. + */
  12253. +int dpsw_vlan_remove_if_untagged(struct fsl_mc_io *mc_io,
  12254. + u32 cmd_flags,
  12255. + u16 token,
  12256. + u16 vlan_id,
  12257. + const struct dpsw_vlan_if_cfg *cfg)
  12258. +{
  12259. + struct mc_command cmd = { 0 };
  12260. + struct dpsw_cmd_vlan_manage_if *cmd_params;
  12261. +
  12262. + /* prepare command */
  12263. + cmd.header = mc_encode_cmd_header(DPSW_CMDID_VLAN_REMOVE_IF_UNTAGGED,
  12264. + cmd_flags,
  12265. + token);
  12266. + cmd_params = (struct dpsw_cmd_vlan_manage_if *)cmd.params;
  12267. + cmd_params->vlan_id = cpu_to_le16(vlan_id);
  12268. + build_if_id_bitmap(cmd_params->if_id, cfg->if_id, cfg->num_ifs);
  12269. +
  12270. + /* send command to mc*/
  12271. + return mc_send_command(mc_io, &cmd);
  12272. +}
  12273. +
  12274. +/**
  12275. + * dpsw_vlan_remove_if_flooding() - Define a set of interfaces that should be
  12276. + * removed from the flooding list.
  12277. + * @mc_io: Pointer to MC portal's I/O object
  12278. + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
  12279. + * @token: Token of DPSW object
  12280. + * @vlan_id: VLAN Identifier
  12281. + * @cfg: Set of interfaces used for flooding
  12282. + *
  12283. + * Return: Completion status. '0' on Success; Error code otherwise.
  12284. + */
  12285. +int dpsw_vlan_remove_if_flooding(struct fsl_mc_io *mc_io,
  12286. + u32 cmd_flags,
  12287. + u16 token,
  12288. + u16 vlan_id,
  12289. + const struct dpsw_vlan_if_cfg *cfg)
  12290. +{
  12291. + struct mc_command cmd = { 0 };
  12292. + struct dpsw_cmd_vlan_manage_if *cmd_params;
  12293. +
  12294. + /* prepare command */
  12295. + cmd.header = mc_encode_cmd_header(DPSW_CMDID_VLAN_REMOVE_IF_FLOODING,
  12296. + cmd_flags,
  12297. + token);
  12298. + cmd_params = (struct dpsw_cmd_vlan_manage_if *)cmd.params;
  12299. + cmd_params->vlan_id = cpu_to_le16(vlan_id);
  12300. + build_if_id_bitmap(cmd_params->if_id, cfg->if_id, cfg->num_ifs);
  12301. +
  12302. + /* send command to mc*/
  12303. + return mc_send_command(mc_io, &cmd);
  12304. +}
  12305. +
  12306. +/**
  12307. + * dpsw_vlan_remove() - Remove an entire VLAN
  12308. + * @mc_io: Pointer to MC portal's I/O object
  12309. + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
  12310. + * @token: Token of DPSW object
  12311. + * @vlan_id: VLAN Identifier
  12312. + *
  12313. + * Return: Completion status. '0' on Success; Error code otherwise.
  12314. + */
  12315. +int dpsw_vlan_remove(struct fsl_mc_io *mc_io,
  12316. + u32 cmd_flags,
  12317. + u16 token,
  12318. + u16 vlan_id)
  12319. +{
  12320. + struct mc_command cmd = { 0 };
  12321. + struct dpsw_cmd_vlan_remove *cmd_params;
  12322. +
  12323. + /* prepare command */
  12324. + cmd.header = mc_encode_cmd_header(DPSW_CMDID_VLAN_REMOVE,
  12325. + cmd_flags,
  12326. + token);
  12327. + cmd_params = (struct dpsw_cmd_vlan_remove *)cmd.params;
  12328. + cmd_params->vlan_id = cpu_to_le16(vlan_id);
  12329. +
  12330. + /* send command to mc*/
  12331. + return mc_send_command(mc_io, &cmd);
  12332. +}
  12333. +
  12334. +/**
  12335. + * dpsw_vlan_get_attributes() - Get VLAN attributes
  12336. + * @mc_io: Pointer to MC portal's I/O object
  12337. + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
  12338. + * @token: Token of DPSW object
  12339. + * @vlan_id: VLAN Identifier
  12340. + * @attr: Returned DPSW attributes
  12341. + *
  12342. + * Return: Completion status. '0' on Success; Error code otherwise.
  12343. + */
  12344. +int dpsw_vlan_get_attributes(struct fsl_mc_io *mc_io,
  12345. + u32 cmd_flags,
  12346. + u16 token,
  12347. + u16 vlan_id,
  12348. + struct dpsw_vlan_attr *attr)
  12349. +{
  12350. + struct mc_command cmd = { 0 };
  12351. + struct dpsw_cmd_vlan_get_attr *cmd_params;
  12352. + struct dpsw_rsp_vlan_get_attr *rsp_params;
  12353. + int err;
  12354. +
  12355. + /* prepare command */
  12356. + cmd.header = mc_encode_cmd_header(DPSW_CMDID_VLAN_GET_ATTRIBUTES,
  12357. + cmd_flags,
  12358. + token);
  12359. + cmd_params = (struct dpsw_cmd_vlan_get_attr *)cmd.params;
  12360. + cmd_params->vlan_id = cpu_to_le16(vlan_id);
  12361. +
  12362. + /* send command to mc*/
  12363. + err = mc_send_command(mc_io, &cmd);
  12364. + if (err)
  12365. + return err;
  12366. +
  12367. + /* retrieve response parameters */
  12368. + rsp_params = (struct dpsw_rsp_vlan_get_attr *)cmd.params;
  12369. + attr->fdb_id = le16_to_cpu(rsp_params->fdb_id);
  12370. + attr->num_ifs = le16_to_cpu(rsp_params->num_ifs);
  12371. + attr->num_untagged_ifs = le16_to_cpu(rsp_params->num_untagged_ifs);
  12372. + attr->num_flooding_ifs = le16_to_cpu(rsp_params->num_flooding_ifs);
  12373. +
  12374. + return 0;
  12375. +}
  12376. +
  12377. +/**
  12378. + * dpsw_vlan_get_if() - Get interfaces belong to this VLAN
  12379. + * @mc_io: Pointer to MC portal's I/O object
  12380. + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
  12381. + * @token: Token of DPSW object
  12382. + * @vlan_id: VLAN Identifier
  12383. + * @cfg: Returned set of interfaces belong to this VLAN
  12384. + *
  12385. + * Return: Completion status. '0' on Success; Error code otherwise.
  12386. + */
  12387. +int dpsw_vlan_get_if(struct fsl_mc_io *mc_io,
  12388. + u32 cmd_flags,
  12389. + u16 token,
  12390. + u16 vlan_id,
  12391. + struct dpsw_vlan_if_cfg *cfg)
  12392. +{
  12393. + struct mc_command cmd = { 0 };
  12394. + struct dpsw_cmd_vlan_get_if *cmd_params;
  12395. + struct dpsw_rsp_vlan_get_if *rsp_params;
  12396. + int err;
  12397. +
  12398. + /* prepare command */
  12399. + cmd.header = mc_encode_cmd_header(DPSW_CMDID_VLAN_GET_IF,
  12400. + cmd_flags,
  12401. + token);
  12402. + cmd_params = (struct dpsw_cmd_vlan_get_if *)cmd.params;
  12403. + cmd_params->vlan_id = cpu_to_le16(vlan_id);
  12404. +
  12405. + /* send command to mc*/
  12406. + err = mc_send_command(mc_io, &cmd);
  12407. + if (err)
  12408. + return err;
  12409. +
  12410. + /* retrieve response parameters */
  12411. + rsp_params = (struct dpsw_rsp_vlan_get_if *)cmd.params;
  12412. + cfg->num_ifs = le16_to_cpu(rsp_params->num_ifs);
  12413. + read_if_id_bitmap(cfg->if_id, &cfg->num_ifs, rsp_params->if_id);
  12414. +
  12415. + return 0;
  12416. +}
  12417. +
  12418. +/**
  12419. + * dpsw_vlan_get_if_flooding() - Get interfaces used in flooding for this VLAN
  12420. + * @mc_io: Pointer to MC portal's I/O object
  12421. + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
  12422. + * @token: Token of DPSW object
  12423. + * @vlan_id: VLAN Identifier
  12424. + * @cfg: Returned set of flooding interfaces
  12425. + *
  12426. + * Return: Completion status. '0' on Success; Error code otherwise.
  12427. + */
  12428. +
  12429. +int dpsw_vlan_get_if_flooding(struct fsl_mc_io *mc_io,
  12430. + u32 cmd_flags,
  12431. + u16 token,
  12432. + u16 vlan_id,
  12433. + struct dpsw_vlan_if_cfg *cfg)
  12434. +{
  12435. + struct mc_command cmd = { 0 };
  12436. + struct dpsw_cmd_vlan_get_if_flooding *cmd_params;
  12437. + struct dpsw_rsp_vlan_get_if_flooding *rsp_params;
  12438. + int err;
  12439. +
  12440. + /* prepare command */
  12441. + cmd.header = mc_encode_cmd_header(DPSW_CMDID_VLAN_GET_IF_FLOODING,
  12442. + cmd_flags,
  12443. + token);
  12444. + cmd_params = (struct dpsw_cmd_vlan_get_if_flooding *)cmd.params;
  12445. + cmd_params->vlan_id = cpu_to_le16(vlan_id);
  12446. +
  12447. + /* send command to mc*/
  12448. + err = mc_send_command(mc_io, &cmd);
  12449. + if (err)
  12450. + return err;
  12451. +
  12452. + /* retrieve response parameters */
  12453. + rsp_params = (struct dpsw_rsp_vlan_get_if_flooding *)cmd.params;
  12454. + cfg->num_ifs = le16_to_cpu(rsp_params->num_ifs);
  12455. + read_if_id_bitmap(cfg->if_id, &cfg->num_ifs, rsp_params->if_id);
  12456. +
  12457. + return 0;
  12458. +}
  12459. +
  12460. +/**
  12461. + * dpsw_vlan_get_if_untagged() - Get interfaces that should be transmitted as
  12462. + * untagged
  12463. + * @mc_io: Pointer to MC portal's I/O object
  12464. + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
  12465. + * @token: Token of DPSW object
  12466. + * @vlan_id: VLAN Identifier
  12467. + * @cfg: Returned set of untagged interfaces
  12468. + *
  12469. + * Return: Completion status. '0' on Success; Error code otherwise.
  12470. + */
  12471. +int dpsw_vlan_get_if_untagged(struct fsl_mc_io *mc_io,
  12472. + u32 cmd_flags,
  12473. + u16 token,
  12474. + u16 vlan_id,
  12475. + struct dpsw_vlan_if_cfg *cfg)
  12476. +{
  12477. + struct mc_command cmd = { 0 };
  12478. + struct dpsw_cmd_vlan_get_if_untagged *cmd_params;
  12479. + struct dpsw_rsp_vlan_get_if_untagged *rsp_params;
  12480. + int err;
  12481. +
  12482. + /* prepare command */
  12483. + cmd.header = mc_encode_cmd_header(DPSW_CMDID_VLAN_GET_IF_UNTAGGED,
  12484. + cmd_flags,
  12485. + token);
  12486. + cmd_params = (struct dpsw_cmd_vlan_get_if_untagged *)cmd.params;
  12487. + cmd_params->vlan_id = cpu_to_le16(vlan_id);
  12488. +
  12489. + /* send command to mc*/
  12490. + err = mc_send_command(mc_io, &cmd);
  12491. + if (err)
  12492. + return err;
  12493. +
  12494. + /* retrieve response parameters */
  12495. + rsp_params = (struct dpsw_rsp_vlan_get_if_untagged *)cmd.params;
  12496. + cfg->num_ifs = le16_to_cpu(rsp_params->num_ifs);
  12497. + read_if_id_bitmap(cfg->if_id, &cfg->num_ifs, rsp_params->if_id);
  12498. +
  12499. + return 0;
  12500. +}
  12501. +
  12502. +/**
  12503. + * dpsw_fdb_add() - Add FDB to switch and Returns handle to FDB table for
  12504. + * the reference
  12505. + * @mc_io: Pointer to MC portal's I/O object
  12506. + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
  12507. + * @token: Token of DPSW object
  12508. + * @fdb_id: Returned Forwarding Database Identifier
  12509. + * @cfg: FDB Configuration
  12510. + *
  12511. + * Return: Completion status. '0' on Success; Error code otherwise.
  12512. + */
  12513. +int dpsw_fdb_add(struct fsl_mc_io *mc_io,
  12514. + u32 cmd_flags,
  12515. + u16 token,
  12516. + u16 *fdb_id,
  12517. + const struct dpsw_fdb_cfg *cfg)
  12518. +{
  12519. + struct mc_command cmd = { 0 };
  12520. + struct dpsw_cmd_fdb_add *cmd_params;
  12521. + struct dpsw_rsp_fdb_add *rsp_params;
  12522. + int err;
  12523. +
  12524. + /* prepare command */
  12525. + cmd.header = mc_encode_cmd_header(DPSW_CMDID_FDB_ADD,
  12526. + cmd_flags,
  12527. + token);
  12528. + cmd_params = (struct dpsw_cmd_fdb_add *)cmd.params;
  12529. + cmd_params->fdb_aging_time = cpu_to_le16(cfg->fdb_aging_time);
  12530. + cmd_params->num_fdb_entries = cpu_to_le16(cfg->num_fdb_entries);
  12531. +
  12532. + /* send command to mc*/
  12533. + err = mc_send_command(mc_io, &cmd);
  12534. + if (err)
  12535. + return err;
  12536. +
  12537. + /* retrieve response parameters */
  12538. + rsp_params = (struct dpsw_rsp_fdb_add *)cmd.params;
  12539. + *fdb_id = le16_to_cpu(rsp_params->fdb_id);
  12540. +
  12541. + return 0;
  12542. +}
  12543. +
  12544. +/**
  12545. + * dpsw_fdb_remove() - Remove FDB from switch
  12546. + * @mc_io: Pointer to MC portal's I/O object
  12547. + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
  12548. + * @token: Token of DPSW object
  12549. + * @fdb_id: Forwarding Database Identifier
  12550. + *
  12551. + * Return: Completion status. '0' on Success; Error code otherwise.
  12552. + */
  12553. +int dpsw_fdb_remove(struct fsl_mc_io *mc_io,
  12554. + u32 cmd_flags,
  12555. + u16 token,
  12556. + u16 fdb_id)
  12557. +{
  12558. + struct mc_command cmd = { 0 };
  12559. + struct dpsw_cmd_fdb_remove *cmd_params;
  12560. +
  12561. + /* prepare command */
  12562. + cmd.header = mc_encode_cmd_header(DPSW_CMDID_FDB_REMOVE,
  12563. + cmd_flags,
  12564. + token);
  12565. + cmd_params = (struct dpsw_cmd_fdb_remove *)cmd.params;
  12566. + cmd_params->fdb_id = cpu_to_le16(fdb_id);
  12567. +
  12568. + /* send command to mc*/
  12569. + return mc_send_command(mc_io, &cmd);
  12570. +}
  12571. +
  12572. +/**
  12573. + * dpsw_fdb_add_unicast() - Function adds an unicast entry into MAC lookup table
  12574. + * @mc_io: Pointer to MC portal's I/O object
  12575. + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
  12576. + * @token: Token of DPSW object
  12577. + * @fdb_id: Forwarding Database Identifier
  12578. + * @cfg: Unicast entry configuration
  12579. + *
  12580. + * Return: Completion status. '0' on Success; Error code otherwise.
  12581. + */
  12582. +int dpsw_fdb_add_unicast(struct fsl_mc_io *mc_io,
  12583. + u32 cmd_flags,
  12584. + u16 token,
  12585. + u16 fdb_id,
  12586. + const struct dpsw_fdb_unicast_cfg *cfg)
  12587. +{
  12588. + struct mc_command cmd = { 0 };
  12589. + struct dpsw_cmd_fdb_add_unicast *cmd_params;
  12590. + int i;
  12591. +
  12592. + /* prepare command */
  12593. + cmd.header = mc_encode_cmd_header(DPSW_CMDID_FDB_ADD_UNICAST,
  12594. + cmd_flags,
  12595. + token);
  12596. + cmd_params = (struct dpsw_cmd_fdb_add_unicast *)cmd.params;
  12597. + cmd_params->fdb_id = cpu_to_le16(fdb_id);
  12598. + cmd_params->if_egress = cpu_to_le16(cfg->if_egress);
  12599. + for (i = 0; i < 6; i++)
  12600. + cmd_params->mac_addr[i] = cfg->mac_addr[5 - i];
  12601. + dpsw_set_field(cmd_params->type, ENTRY_TYPE, cfg->type);
  12602. +
  12603. + /* send command to mc*/
  12604. + return mc_send_command(mc_io, &cmd);
  12605. +}
  12606. +
  12607. +/**
  12608. + * dpsw_fdb_get_unicast() - Get unicast entry from MAC lookup table by
  12609. + * unicast Ethernet address
  12610. + * @mc_io: Pointer to MC portal's I/O object
  12611. + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
  12612. + * @token: Token of DPSW object
  12613. + * @fdb_id: Forwarding Database Identifier
  12614. + * @cfg: Returned unicast entry configuration
  12615. + *
  12616. + * Return: Completion status. '0' on Success; Error code otherwise.
  12617. + */
  12618. +int dpsw_fdb_get_unicast(struct fsl_mc_io *mc_io,
  12619. + u32 cmd_flags,
  12620. + u16 token,
  12621. + u16 fdb_id,
  12622. + struct dpsw_fdb_unicast_cfg *cfg)
  12623. +{
  12624. + struct mc_command cmd = { 0 };
  12625. + struct dpsw_cmd_fdb_get_unicast *cmd_params;
  12626. + struct dpsw_rsp_fdb_get_unicast *rsp_params;
  12627. + int err, i;
  12628. +
  12629. + /* prepare command */
  12630. + cmd.header = mc_encode_cmd_header(DPSW_CMDID_FDB_GET_UNICAST,
  12631. + cmd_flags,
  12632. + token);
  12633. + cmd_params = (struct dpsw_cmd_fdb_get_unicast *)cmd.params;
  12634. + cmd_params->fdb_id = cpu_to_le16(fdb_id);
  12635. + for (i = 0; i < 6; i++)
  12636. + cmd_params->mac_addr[i] = cfg->mac_addr[5 - i];
  12637. +
  12638. + /* send command to mc*/
  12639. + err = mc_send_command(mc_io, &cmd);
  12640. + if (err)
  12641. + return err;
  12642. +
  12643. + /* retrieve response parameters */
  12644. + rsp_params = (struct dpsw_rsp_fdb_get_unicast *)cmd.params;
  12645. + cfg->if_egress = le16_to_cpu(rsp_params->if_egress);
  12646. + cfg->type = dpsw_get_field(rsp_params->type, ENTRY_TYPE);
  12647. +
  12648. + return 0;
  12649. +}
  12650. +
  12651. +/**
  12652. + * dpsw_fdb_remove_unicast() - removes an entry from MAC lookup table
  12653. + * @mc_io: Pointer to MC portal's I/O object
  12654. + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
  12655. + * @token: Token of DPSW object
  12656. + * @fdb_id: Forwarding Database Identifier
  12657. + * @cfg: Unicast entry configuration
  12658. + *
  12659. + * Return: Completion status. '0' on Success; Error code otherwise.
  12660. + */
  12661. +int dpsw_fdb_remove_unicast(struct fsl_mc_io *mc_io,
  12662. + u32 cmd_flags,
  12663. + u16 token,
  12664. + u16 fdb_id,
  12665. + const struct dpsw_fdb_unicast_cfg *cfg)
  12666. +{
  12667. + struct mc_command cmd = { 0 };
  12668. + struct dpsw_cmd_fdb_remove_unicast *cmd_params;
  12669. + int i;
  12670. +
  12671. + /* prepare command */
  12672. + cmd.header = mc_encode_cmd_header(DPSW_CMDID_FDB_REMOVE_UNICAST,
  12673. + cmd_flags,
  12674. + token);
  12675. + cmd_params = (struct dpsw_cmd_fdb_remove_unicast *)cmd.params;
  12676. + cmd_params->fdb_id = cpu_to_le16(fdb_id);
  12677. + for (i = 0; i < 6; i++)
  12678. + cmd_params->mac_addr[i] = cfg->mac_addr[5 - i];
  12679. + cmd_params->if_egress = cpu_to_le16(cfg->if_egress);
  12680. + dpsw_set_field(cmd_params->type, ENTRY_TYPE, cfg->type);
  12681. +
  12682. + /* send command to mc*/
  12683. + return mc_send_command(mc_io, &cmd);
  12684. +}
  12685. +
  12686. +/**
  12687. + * dpsw_fdb_add_multicast() - Add a set of egress interfaces to multi-cast group
  12688. + * @mc_io: Pointer to MC portal's I/O object
  12689. + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
  12690. + * @token: Token of DPSW object
  12691. + * @fdb_id: Forwarding Database Identifier
  12692. + * @cfg: Multicast entry configuration
  12693. + *
  12694. + * If group doesn't exist, it will be created.
  12695. + * It adds only interfaces not belonging to this multicast group
  12696. + * yet, otherwise error will be generated and the command is
  12697. + * ignored.
  12698. + * This function may be called numerous times always providing
  12699. + * required interfaces delta.
  12700. + *
  12701. + * Return: Completion status. '0' on Success; Error code otherwise.
  12702. + */
  12703. +int dpsw_fdb_add_multicast(struct fsl_mc_io *mc_io,
  12704. + u32 cmd_flags,
  12705. + u16 token,
  12706. + u16 fdb_id,
  12707. + const struct dpsw_fdb_multicast_cfg *cfg)
  12708. +{
  12709. + struct mc_command cmd = { 0 };
  12710. + struct dpsw_cmd_fdb_add_multicast *cmd_params;
  12711. + int i;
  12712. +
  12713. + /* prepare command */
  12714. + cmd.header = mc_encode_cmd_header(DPSW_CMDID_FDB_ADD_MULTICAST,
  12715. + cmd_flags,
  12716. + token);
  12717. + cmd_params = (struct dpsw_cmd_fdb_add_multicast *)cmd.params;
  12718. + cmd_params->fdb_id = cpu_to_le16(fdb_id);
  12719. + cmd_params->num_ifs = cpu_to_le16(cfg->num_ifs);
  12720. + dpsw_set_field(cmd_params->type, ENTRY_TYPE, cfg->type);
  12721. + build_if_id_bitmap(cmd_params->if_id, cfg->if_id, cfg->num_ifs);
  12722. + for (i = 0; i < 6; i++)
  12723. + cmd_params->mac_addr[i] = cfg->mac_addr[5 - i];
  12724. +
  12725. + /* send command to mc*/
  12726. + return mc_send_command(mc_io, &cmd);
  12727. +}
  12728. +
  12729. +/**
  12730. + * dpsw_fdb_get_multicast() - Reading multi-cast group by multi-cast Ethernet
  12731. + * address.
  12732. + * @mc_io: Pointer to MC portal's I/O object
  12733. + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
  12734. + * @token: Token of DPSW object
  12735. + * @fdb_id: Forwarding Database Identifier
  12736. + * @cfg: Returned multicast entry configuration
  12737. + *
  12738. + * Return: Completion status. '0' on Success; Error code otherwise.
  12739. + */
  12740. +int dpsw_fdb_get_multicast(struct fsl_mc_io *mc_io,
  12741. + u32 cmd_flags,
  12742. + u16 token,
  12743. + u16 fdb_id,
  12744. + struct dpsw_fdb_multicast_cfg *cfg)
  12745. +{
  12746. + struct mc_command cmd = { 0 };
  12747. + struct dpsw_cmd_fdb_get_multicast *cmd_params;
  12748. + struct dpsw_rsp_fdb_get_multicast *rsp_params;
  12749. + int err, i;
  12750. +
  12751. + /* prepare command */
  12752. + cmd.header = mc_encode_cmd_header(DPSW_CMDID_FDB_GET_MULTICAST,
  12753. + cmd_flags,
  12754. + token);
  12755. + cmd_params = (struct dpsw_cmd_fdb_get_multicast *)cmd.params;
  12756. + cmd_params->fdb_id = cpu_to_le16(fdb_id);
  12757. + for (i = 0; i < 6; i++)
  12758. + cmd_params->mac_addr[i] = cfg->mac_addr[5 - i];
  12759. +
  12760. + /* send command to mc*/
  12761. + err = mc_send_command(mc_io, &cmd);
  12762. + if (err)
  12763. + return err;
  12764. +
  12765. + /* retrieve response parameters */
  12766. + rsp_params = (struct dpsw_rsp_fdb_get_multicast *)cmd.params;
  12767. + cfg->num_ifs = le16_to_cpu(rsp_params->num_ifs);
  12768. + cfg->type = dpsw_get_field(rsp_params->type, ENTRY_TYPE);
  12769. + read_if_id_bitmap(cfg->if_id, &cfg->num_ifs, rsp_params->if_id);
  12770. +
  12771. + return 0;
  12772. +}
  12773. +
  12774. +/**
  12775. + * dpsw_fdb_remove_multicast() - Removing interfaces from an existing multicast
  12776. + * group.
  12777. + * @mc_io: Pointer to MC portal's I/O object
  12778. + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
  12779. + * @token: Token of DPSW object
  12780. + * @fdb_id: Forwarding Database Identifier
  12781. + * @cfg: Multicast entry configuration
  12782. + *
  12783. + * Interfaces provided by this API have to exist in the group,
  12784. + * otherwise an error will be returned and an entire command
  12785. + * ignored. If there is no interface left in the group,
  12786. + * an entire group is deleted
  12787. + *
  12788. + * Return: Completion status. '0' on Success; Error code otherwise.
  12789. + */
  12790. +int dpsw_fdb_remove_multicast(struct fsl_mc_io *mc_io,
  12791. + u32 cmd_flags,
  12792. + u16 token,
  12793. + u16 fdb_id,
  12794. + const struct dpsw_fdb_multicast_cfg *cfg)
  12795. +{
  12796. + struct mc_command cmd = { 0 };
  12797. + struct dpsw_cmd_fdb_remove_multicast *cmd_params;
  12798. + int i;
  12799. +
  12800. + /* prepare command */
  12801. + cmd.header = mc_encode_cmd_header(DPSW_CMDID_FDB_REMOVE_MULTICAST,
  12802. + cmd_flags,
  12803. + token);
  12804. + cmd_params = (struct dpsw_cmd_fdb_remove_multicast *)cmd.params;
  12805. + cmd_params->fdb_id = cpu_to_le16(fdb_id);
  12806. + cmd_params->num_ifs = cpu_to_le16(cfg->num_ifs);
  12807. + dpsw_set_field(cmd_params->type, ENTRY_TYPE, cfg->type);
  12808. + build_if_id_bitmap(cmd_params->if_id, cfg->if_id, cfg->num_ifs);
  12809. + for (i = 0; i < 6; i++)
  12810. + cmd_params->mac_addr[i] = cfg->mac_addr[5 - i];
  12811. +
  12812. + /* send command to mc*/
  12813. + return mc_send_command(mc_io, &cmd);
  12814. +}
  12815. +
  12816. +/**
  12817. + * dpsw_fdb_set_learning_mode() - Define FDB learning mode
  12818. + * @mc_io: Pointer to MC portal's I/O object
  12819. + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
  12820. + * @token: Token of DPSW object
  12821. + * @fdb_id: Forwarding Database Identifier
  12822. + * @mode: Learning mode
  12823. + *
  12824. + * Return: Completion status. '0' on Success; Error code otherwise.
  12825. + */
  12826. +int dpsw_fdb_set_learning_mode(struct fsl_mc_io *mc_io,
  12827. + u32 cmd_flags,
  12828. + u16 token,
  12829. + u16 fdb_id,
  12830. + enum dpsw_fdb_learning_mode mode)
  12831. +{
  12832. + struct mc_command cmd = { 0 };
  12833. + struct dpsw_cmd_fdb_set_learning_mode *cmd_params;
  12834. +
  12835. + /* prepare command */
  12836. + cmd.header = mc_encode_cmd_header(DPSW_CMDID_FDB_SET_LEARNING_MODE,
  12837. + cmd_flags,
  12838. + token);
  12839. + cmd_params = (struct dpsw_cmd_fdb_set_learning_mode *)cmd.params;
  12840. + cmd_params->fdb_id = cpu_to_le16(fdb_id);
  12841. + dpsw_set_field(cmd_params->mode, LEARNING_MODE, mode);
  12842. +
  12843. + /* send command to mc*/
  12844. + return mc_send_command(mc_io, &cmd);
  12845. +}
  12846. +
  12847. +/**
  12848. + * dpsw_fdb_get_attributes() - Get FDB attributes
  12849. + * @mc_io: Pointer to MC portal's I/O object
  12850. + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
  12851. + * @token: Token of DPSW object
  12852. + * @fdb_id: Forwarding Database Identifier
  12853. + * @attr: Returned FDB attributes
  12854. + *
  12855. + * Return: Completion status. '0' on Success; Error code otherwise.
  12856. + */
  12857. +int dpsw_fdb_get_attributes(struct fsl_mc_io *mc_io,
  12858. + u32 cmd_flags,
  12859. + u16 token,
  12860. + u16 fdb_id,
  12861. + struct dpsw_fdb_attr *attr)
  12862. +{
  12863. + struct mc_command cmd = { 0 };
  12864. + struct dpsw_cmd_fdb_get_attr *cmd_params;
  12865. + struct dpsw_rsp_fdb_get_attr *rsp_params;
  12866. + int err;
  12867. +
  12868. + /* prepare command */
  12869. + cmd.header = mc_encode_cmd_header(DPSW_CMDID_FDB_GET_ATTR,
  12870. + cmd_flags,
  12871. + token);
  12872. + cmd_params = (struct dpsw_cmd_fdb_get_attr *)cmd.params;
  12873. + cmd_params->fdb_id = cpu_to_le16(fdb_id);
  12874. +
  12875. + /* send command to mc*/
  12876. + err = mc_send_command(mc_io, &cmd);
  12877. + if (err)
  12878. + return err;
  12879. +
  12880. + /* retrieve response parameters */
  12881. + rsp_params = (struct dpsw_rsp_fdb_get_attr *)cmd.params;
  12882. + attr->max_fdb_entries = le16_to_cpu(rsp_params->max_fdb_entries);
  12883. + attr->fdb_aging_time = le16_to_cpu(rsp_params->fdb_aging_time);
  12884. + attr->learning_mode = dpsw_get_field(rsp_params->learning_mode,
  12885. + LEARNING_MODE);
  12886. + attr->num_fdb_mc_groups = le16_to_cpu(rsp_params->num_fdb_mc_groups);
  12887. + attr->max_fdb_mc_groups = le16_to_cpu(rsp_params->max_fdb_mc_groups);
  12888. +
  12889. + return 0;
  12890. +}
  12891. +
  12892. +/**
  12893. + * dpsw_acl_add() - Adds ACL to L2 switch.
  12894. + * @mc_io: Pointer to MC portal's I/O object
  12895. + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
  12896. + * @token: Token of DPSW object
  12897. + * @acl_id: Returned ACL ID, for the future reference
  12898. + * @cfg: ACL configuration
  12899. + *
  12900. + * Create Access Control List. Multiple ACLs can be created and
  12901. + * co-exist in L2 switch
  12902. + *
  12903. + * Return: '0' on Success; Error code otherwise.
  12904. + */
  12905. +int dpsw_acl_add(struct fsl_mc_io *mc_io,
  12906. + u32 cmd_flags,
  12907. + u16 token,
  12908. + u16 *acl_id,
  12909. + const struct dpsw_acl_cfg *cfg)
  12910. +{
  12911. + struct mc_command cmd = { 0 };
  12912. + struct dpsw_cmd_acl_add *cmd_params;
  12913. + struct dpsw_rsp_acl_add *rsp_params;
  12914. + int err;
  12915. +
  12916. + /* prepare command */
  12917. + cmd.header = mc_encode_cmd_header(DPSW_CMDID_ACL_ADD,
  12918. + cmd_flags,
  12919. + token);
  12920. + cmd_params = (struct dpsw_cmd_acl_add *)cmd.params;
  12921. + cmd_params->max_entries = cpu_to_le16(cfg->max_entries);
  12922. +
  12923. + /* send command to mc*/
  12924. + err = mc_send_command(mc_io, &cmd);
  12925. + if (err)
  12926. + return err;
  12927. +
  12928. + /* retrieve response parameters */
  12929. + rsp_params = (struct dpsw_rsp_acl_add *)cmd.params;
  12930. + *acl_id = le16_to_cpu(rsp_params->acl_id);
  12931. +
  12932. + return 0;
  12933. +}
  12934. +
  12935. +/**
  12936. + * dpsw_acl_remove() - Removes ACL from L2 switch.
  12937. + * @mc_io: Pointer to MC portal's I/O object
  12938. + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
  12939. + * @token: Token of DPSW object
  12940. + * @acl_id: ACL ID
  12941. + *
  12942. + * Return: '0' on Success; Error code otherwise.
  12943. + */
  12944. +int dpsw_acl_remove(struct fsl_mc_io *mc_io,
  12945. + u32 cmd_flags,
  12946. + u16 token,
  12947. + u16 acl_id)
  12948. +{
  12949. + struct mc_command cmd = { 0 };
  12950. + struct dpsw_cmd_acl_remove *cmd_params;
  12951. +
  12952. + /* prepare command */
  12953. + cmd.header = mc_encode_cmd_header(DPSW_CMDID_ACL_REMOVE,
  12954. + cmd_flags,
  12955. + token);
  12956. + cmd_params = (struct dpsw_cmd_acl_remove *)cmd.params;
  12957. + cmd_params->acl_id = cpu_to_le16(acl_id);
  12958. +
  12959. + /* send command to mc*/
  12960. + return mc_send_command(mc_io, &cmd);
  12961. +}
  12962. +
  12963. +/**
  12964. + * dpsw_acl_prepare_entry_cfg() - Set an entry to ACL.
  12965. + * @key: Key
  12966. + * @entry_cfg_buf: Zeroed 256 bytes of memory before mapping it to DMA
  12967. + *
  12968. + * This function has to be called before adding or removing acl_entry
  12969. + *
  12970. + */
  12971. +void dpsw_acl_prepare_entry_cfg(const struct dpsw_acl_key *key,
  12972. + u8 *entry_cfg_buf)
  12973. +{
  12974. + struct dpsw_prep_acl_entry *ext_params;
  12975. + int i;
  12976. +
  12977. + ext_params = (struct dpsw_prep_acl_entry *)entry_cfg_buf;
  12978. +
  12979. + for (i = 0; i < 6; i++) {
  12980. + ext_params->match_l2_dest_mac[i] =
  12981. + key->match.l2_dest_mac[5 - i];
  12982. + ext_params->match_l2_source_mac[i] =
  12983. + key->match.l2_source_mac[5 - i];
  12984. + ext_params->mask_l2_dest_mac[i] =
  12985. + key->mask.l2_dest_mac[5 - i];
  12986. + ext_params->mask_l2_source_mac[i] =
  12987. + key->mask.l2_source_mac[5 - i];
  12988. + }
  12989. +
  12990. + ext_params->match_l2_tpid = cpu_to_le16(key->match.l2_tpid);
  12991. + ext_params->match_l2_vlan_id = cpu_to_le16(key->match.l2_vlan_id);
  12992. + ext_params->match_l3_dest_ip = cpu_to_le32(key->match.l3_dest_ip);
  12993. + ext_params->match_l3_source_ip = cpu_to_le32(key->match.l3_source_ip);
  12994. + ext_params->match_l4_dest_port = cpu_to_le16(key->match.l4_dest_port);
  12995. + ext_params->match_l2_ether_type = cpu_to_le16(key->match.l2_ether_type);
  12996. + ext_params->match_l2_pcp_dei = key->match.l2_pcp_dei;
  12997. + ext_params->match_l3_dscp = key->match.l3_dscp;
  12998. + ext_params->match_l4_source_port =
  12999. + cpu_to_le16(key->match.l4_source_port);
  13000. +
  13001. + ext_params->mask_l2_tpid = cpu_to_le16(key->mask.l2_tpid);
  13002. + ext_params->mask_l2_vlan_id = cpu_to_le16(key->mask.l2_vlan_id);
  13003. + ext_params->mask_l3_dest_ip = cpu_to_le32(key->mask.l3_dest_ip);
  13004. + ext_params->mask_l3_source_ip = cpu_to_le32(key->mask.l3_source_ip);
  13005. + ext_params->mask_l4_dest_port = cpu_to_le16(key->mask.l4_dest_port);
  13006. + ext_params->mask_l4_source_port = cpu_to_le16(key->mask.l4_source_port);
  13007. + ext_params->mask_l2_ether_type = cpu_to_le16(key->mask.l2_ether_type);
  13008. + ext_params->mask_l2_pcp_dei = key->mask.l2_pcp_dei;
  13009. + ext_params->mask_l3_dscp = key->mask.l3_dscp;
  13010. + ext_params->match_l3_protocol = key->match.l3_protocol;
  13011. + ext_params->mask_l3_protocol = key->mask.l3_protocol;
  13012. +}
  13013. +
  13014. +/**
  13015. + * dpsw_acl_add_entry() - Adds an entry to ACL.
  13016. + * @mc_io: Pointer to MC portal's I/O object
  13017. + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
  13018. + * @token: Token of DPSW object
  13019. + * @acl_id: ACL ID
  13020. + * @cfg: Entry configuration
  13021. + *
  13022. + * warning: This function has to be called after dpsw_acl_set_entry_cfg()
  13023. + *
  13024. + * Return: '0' on Success; Error code otherwise.
  13025. + */
  13026. +int dpsw_acl_add_entry(struct fsl_mc_io *mc_io,
  13027. + u32 cmd_flags,
  13028. + u16 token,
  13029. + u16 acl_id,
  13030. + const struct dpsw_acl_entry_cfg *cfg)
  13031. +{
  13032. + struct mc_command cmd = { 0 };
  13033. + struct dpsw_cmd_acl_entry *cmd_params;
  13034. +
  13035. + /* prepare command */
  13036. + cmd.header = mc_encode_cmd_header(DPSW_CMDID_ACL_ADD_ENTRY,
  13037. + cmd_flags,
  13038. + token);
  13039. + cmd_params = (struct dpsw_cmd_acl_entry *)cmd.params;
  13040. + cmd_params->acl_id = cpu_to_le16(acl_id);
  13041. + cmd_params->result_if_id = cpu_to_le16(cfg->result.if_id);
  13042. + cmd_params->precedence = cpu_to_le32(cfg->precedence);
  13043. + dpsw_set_field(cmd_params->result_action, RESULT_ACTION,
  13044. + cfg->result.action);
  13045. + cmd_params->key_iova = cpu_to_le64(cfg->key_iova);
  13046. +
  13047. + /* send command to mc*/
  13048. + return mc_send_command(mc_io, &cmd);
  13049. +}
  13050. +
  13051. +/**
  13052. + * dpsw_acl_remove_entry() - Removes an entry from ACL.
  13053. + * @mc_io: Pointer to MC portal's I/O object
  13054. + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
  13055. + * @token: Token of DPSW object
  13056. + * @acl_id: ACL ID
  13057. + * @cfg: Entry configuration
  13058. + *
  13059. + * warning: This function has to be called after dpsw_acl_set_entry_cfg()
  13060. + *
  13061. + * Return: '0' on Success; Error code otherwise.
  13062. + */
  13063. +int dpsw_acl_remove_entry(struct fsl_mc_io *mc_io,
  13064. + u32 cmd_flags,
  13065. + u16 token,
  13066. + u16 acl_id,
  13067. + const struct dpsw_acl_entry_cfg *cfg)
  13068. +{
  13069. + struct mc_command cmd = { 0 };
  13070. + struct dpsw_cmd_acl_entry *cmd_params;
  13071. +
  13072. + /* prepare command */
  13073. + cmd.header = mc_encode_cmd_header(DPSW_CMDID_ACL_REMOVE_ENTRY,
  13074. + cmd_flags,
  13075. + token);
  13076. + cmd_params = (struct dpsw_cmd_acl_entry *)cmd.params;
  13077. + cmd_params->acl_id = cpu_to_le16(acl_id);
  13078. + cmd_params->result_if_id = cpu_to_le16(cfg->result.if_id);
  13079. + cmd_params->precedence = cpu_to_le32(cfg->precedence);
  13080. + dpsw_set_field(cmd_params->result_action, RESULT_ACTION,
  13081. + cfg->result.action);
  13082. + cmd_params->key_iova = cpu_to_le64(cfg->key_iova);
  13083. +
  13084. + /* send command to mc*/
  13085. + return mc_send_command(mc_io, &cmd);
  13086. +}
  13087. +
  13088. +/**
  13089. + * dpsw_acl_add_if() - Associate interface/interfaces with ACL.
  13090. + * @mc_io: Pointer to MC portal's I/O object
  13091. + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
  13092. + * @token: Token of DPSW object
  13093. + * @acl_id: ACL ID
  13094. + * @cfg: Interfaces list
  13095. + *
  13096. + * Return: '0' on Success; Error code otherwise.
  13097. + */
  13098. +int dpsw_acl_add_if(struct fsl_mc_io *mc_io,
  13099. + u32 cmd_flags,
  13100. + u16 token,
  13101. + u16 acl_id,
  13102. + const struct dpsw_acl_if_cfg *cfg)
  13103. +{
  13104. + struct mc_command cmd = { 0 };
  13105. + struct dpsw_cmd_acl_if *cmd_params;
  13106. +
  13107. + /* prepare command */
  13108. + cmd.header = mc_encode_cmd_header(DPSW_CMDID_ACL_ADD_IF,
  13109. + cmd_flags,
  13110. + token);
  13111. + cmd_params = (struct dpsw_cmd_acl_if *)cmd.params;
  13112. + cmd_params->acl_id = cpu_to_le16(acl_id);
  13113. + cmd_params->num_ifs = cpu_to_le16(cfg->num_ifs);
  13114. + build_if_id_bitmap(cmd_params->if_id, cfg->if_id, cfg->num_ifs);
  13115. +
  13116. + /* send command to mc*/
  13117. + return mc_send_command(mc_io, &cmd);
  13118. +}
  13119. +
  13120. +/**
  13121. + * dpsw_acl_remove_if() - De-associate interface/interfaces from ACL.
  13122. + * @mc_io: Pointer to MC portal's I/O object
  13123. + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
  13124. + * @token: Token of DPSW object
  13125. + * @acl_id: ACL ID
  13126. + * @cfg: Interfaces list
  13127. + *
  13128. + * Return: '0' on Success; Error code otherwise.
  13129. + */
  13130. +int dpsw_acl_remove_if(struct fsl_mc_io *mc_io,
  13131. + u32 cmd_flags,
  13132. + u16 token,
  13133. + u16 acl_id,
  13134. + const struct dpsw_acl_if_cfg *cfg)
  13135. +{
  13136. + struct mc_command cmd = { 0 };
  13137. + struct dpsw_cmd_acl_if *cmd_params;
  13138. +
  13139. + /* prepare command */
  13140. + cmd.header = mc_encode_cmd_header(DPSW_CMDID_ACL_REMOVE_IF,
  13141. + cmd_flags,
  13142. + token);
  13143. + cmd_params = (struct dpsw_cmd_acl_if *)cmd.params;
  13144. + cmd_params->acl_id = cpu_to_le16(acl_id);
  13145. + cmd_params->num_ifs = cpu_to_le16(cfg->num_ifs);
  13146. + build_if_id_bitmap(cmd_params->if_id, cfg->if_id, cfg->num_ifs);
  13147. +
  13148. + /* send command to mc*/
  13149. + return mc_send_command(mc_io, &cmd);
  13150. +}
  13151. +
  13152. +/**
  13153. + * dpsw_acl_get_attributes() - Get specific counter of particular interface
  13154. + * @mc_io: Pointer to MC portal's I/O object
  13155. + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
  13156. + * @token: Token of DPSW object
  13157. + * @acl_id: ACL Identifier
  13158. + * @attr: Returned ACL attributes
  13159. + *
  13160. + * Return: '0' on Success; Error code otherwise.
  13161. + */
  13162. +int dpsw_acl_get_attributes(struct fsl_mc_io *mc_io,
  13163. + u32 cmd_flags,
  13164. + u16 token,
  13165. + u16 acl_id,
  13166. + struct dpsw_acl_attr *attr)
  13167. +{
  13168. + struct mc_command cmd = { 0 };
  13169. + struct dpsw_cmd_acl_get_attr *cmd_params;
  13170. + struct dpsw_rsp_acl_get_attr *rsp_params;
  13171. + int err;
  13172. +
  13173. + /* prepare command */
  13174. + cmd.header = mc_encode_cmd_header(DPSW_CMDID_ACL_GET_ATTR,
  13175. + cmd_flags,
  13176. + token);
  13177. + cmd_params = (struct dpsw_cmd_acl_get_attr *)cmd.params;
  13178. + cmd_params->acl_id = cpu_to_le16(acl_id);
  13179. +
  13180. + /* send command to mc*/
  13181. + err = mc_send_command(mc_io, &cmd);
  13182. + if (err)
  13183. + return err;
  13184. +
  13185. + /* retrieve response parameters */
  13186. + rsp_params = (struct dpsw_rsp_acl_get_attr *)cmd.params;
  13187. + attr->max_entries = le16_to_cpu(rsp_params->max_entries);
  13188. + attr->num_entries = le16_to_cpu(rsp_params->num_entries);
  13189. + attr->num_ifs = le16_to_cpu(rsp_params->num_ifs);
  13190. +
  13191. + return 0;
  13192. +}
  13193. +
  13194. +/**
  13195. + * dpsw_ctrl_if_get_attributes() - Obtain control interface attributes
  13196. + * @mc_io: Pointer to MC portal's I/O object
  13197. + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
  13198. + * @token: Token of DPSW object
  13199. + * @attr: Returned control interface attributes
  13200. + *
  13201. + * Return: '0' on Success; Error code otherwise.
  13202. + */
  13203. +int dpsw_ctrl_if_get_attributes(struct fsl_mc_io *mc_io,
  13204. + u32 cmd_flags,
  13205. + u16 token,
  13206. + struct dpsw_ctrl_if_attr *attr)
  13207. +{
  13208. + struct mc_command cmd = { 0 };
  13209. + struct dpsw_rsp_ctrl_if_get_attr *rsp_params;
  13210. + int err;
  13211. +
  13212. + /* prepare command */
  13213. + cmd.header = mc_encode_cmd_header(DPSW_CMDID_CTRL_IF_GET_ATTR,
  13214. + cmd_flags,
  13215. + token);
  13216. +
  13217. + /* send command to mc*/
  13218. + err = mc_send_command(mc_io, &cmd);
  13219. + if (err)
  13220. + return err;
  13221. +
  13222. + /* retrieve response parameters */
  13223. + rsp_params = (struct dpsw_rsp_ctrl_if_get_attr *)cmd.params;
  13224. + attr->rx_fqid = le32_to_cpu(rsp_params->rx_fqid);
  13225. + attr->rx_err_fqid = le32_to_cpu(rsp_params->rx_err_fqid);
  13226. + attr->tx_err_conf_fqid = le32_to_cpu(rsp_params->tx_err_conf_fqid);
  13227. +
  13228. + return 0;
  13229. +}
  13230. +
  13231. +/**
  13232. + * dpsw_ctrl_if_set_pools() - Set control interface buffer pools
  13233. + * @mc_io: Pointer to MC portal's I/O object
  13234. + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
  13235. + * @token: Token of DPSW object
  13236. + * @cfg: Buffer pools configuration
  13237. + *
  13238. + * Return: '0' on Success; Error code otherwise.
  13239. + */
  13240. +int dpsw_ctrl_if_set_pools(struct fsl_mc_io *mc_io,
  13241. + u32 cmd_flags,
  13242. + u16 token,
  13243. + const struct dpsw_ctrl_if_pools_cfg *pools)
  13244. +{
  13245. + struct mc_command cmd = { 0 };
  13246. + struct dpsw_cmd_ctrl_if_set_pools *cmd_params;
  13247. + int i;
  13248. +
  13249. + /* prepare command */
  13250. + cmd.header = mc_encode_cmd_header(DPSW_CMDID_CTRL_IF_SET_POOLS,
  13251. + cmd_flags,
  13252. + token);
  13253. + cmd_params = (struct dpsw_cmd_ctrl_if_set_pools *)cmd.params;
  13254. + cmd_params->num_dpbp = pools->num_dpbp;
  13255. + for (i = 0; i < 8; i++) {
  13256. + cmd_params->backup_pool = dpsw_set_bit(cmd_params->backup_pool,
  13257. + i,
  13258. + pools->pools[i].backup_pool);
  13259. + cmd_params->buffer_size[i] =
  13260. + cpu_to_le16(pools->pools[i].buffer_size);
  13261. + cmd_params->dpbp_id[i] =
  13262. + cpu_to_le32(pools->pools[i].dpbp_id);
  13263. + }
  13264. +
  13265. + /* send command to mc*/
  13266. + return mc_send_command(mc_io, &cmd);
  13267. +}
  13268. +
  13269. +/**
  13270. + * dpsw_ctrl_if_enable() - Enable control interface
  13271. + * @mc_io: Pointer to MC portal's I/O object
  13272. + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
  13273. + * @token: Token of DPSW object
  13274. + *
  13275. + * Return: '0' on Success; Error code otherwise.
  13276. + */
  13277. +int dpsw_ctrl_if_enable(struct fsl_mc_io *mc_io,
  13278. + u32 cmd_flags,
  13279. + u16 token)
  13280. +{
  13281. + struct mc_command cmd = { 0 };
  13282. +
  13283. + /* prepare command */
  13284. + cmd.header = mc_encode_cmd_header(DPSW_CMDID_CTRL_IF_ENABLE,
  13285. + cmd_flags,
  13286. + token);
  13287. +
  13288. + /* send command to mc*/
  13289. + return mc_send_command(mc_io, &cmd);
  13290. +}
  13291. +
  13292. +/**
  13293. + * dpsw_ctrl_if_disable() - Function disables control interface
  13294. + * @mc_io: Pointer to MC portal's I/O object
  13295. + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
  13296. + * @token: Token of DPSW object
  13297. + *
  13298. + * Return: '0' on Success; Error code otherwise.
  13299. + */
  13300. +int dpsw_ctrl_if_disable(struct fsl_mc_io *mc_io,
  13301. + u32 cmd_flags,
  13302. + u16 token)
  13303. +{
  13304. + struct mc_command cmd = { 0 };
  13305. +
  13306. + /* prepare command */
  13307. + cmd.header = mc_encode_cmd_header(DPSW_CMDID_CTRL_IF_DISABLE,
  13308. + cmd_flags,
  13309. + token);
  13310. +
  13311. + /* send command to mc*/
  13312. + return mc_send_command(mc_io, &cmd);
  13313. +}
  13314. +
  13315. +/**
  13316. + * dpsw_get_api_version() - Get Data Path Switch API version
  13317. + * @mc_io: Pointer to MC portal's I/O object
  13318. + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
  13319. + * @major_ver: Major version of data path switch API
  13320. + * @minor_ver: Minor version of data path switch API
  13321. + *
  13322. + * Return: '0' on Success; Error code otherwise.
  13323. + */
  13324. +int dpsw_get_api_version(struct fsl_mc_io *mc_io,
  13325. + u32 cmd_flags,
  13326. + u16 *major_ver,
  13327. + u16 *minor_ver)
  13328. +{
  13329. + struct mc_command cmd = { 0 };
  13330. + struct dpsw_rsp_get_api_version *rsp_params;
  13331. + int err;
  13332. +
  13333. + cmd.header = mc_encode_cmd_header(DPSW_CMDID_GET_API_VERSION,
  13334. + cmd_flags,
  13335. + 0);
  13336. +
  13337. + err = mc_send_command(mc_io, &cmd);
  13338. + if (err)
  13339. + return err;
  13340. +
  13341. + rsp_params = (struct dpsw_rsp_get_api_version *)cmd.params;
  13342. + *major_ver = le16_to_cpu(rsp_params->version_major);
  13343. + *minor_ver = le16_to_cpu(rsp_params->version_minor);
  13344. +
  13345. + return 0;
  13346. +}
  13347. --- /dev/null
  13348. +++ b/drivers/staging/fsl-dpaa2/ethsw/dpsw.h
  13349. @@ -0,0 +1,1269 @@
  13350. +/* Copyright 2013-2015 Freescale Semiconductor Inc.
  13351. + *
  13352. + * Redistribution and use in source and binary forms, with or without
  13353. + * modification, are permitted provided that the following conditions are met:
  13354. + * * Redistributions of source code must retain the above copyright
  13355. + * notice, this list of conditions and the following disclaimer.
  13356. + * * Redistributions in binary form must reproduce the above copyright
  13357. + * notice, this list of conditions and the following disclaimer in the
  13358. + * documentation and/or other materials provided with the distribution.
  13359. + * * Neither the name of the above-listed copyright holders nor the
  13360. + * names of any contributors may be used to endorse or promote products
  13361. + * derived from this software without specific prior written permission.
  13362. + *
  13363. + *
  13364. + * ALTERNATIVELY, this software may be distributed under the terms of the
  13365. + * GNU General Public License ("GPL") as published by the Free Software
  13366. + * Foundation, either version 2 of that License or (at your option) any
  13367. + * later version.
  13368. + *
  13369. + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  13370. + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  13371. + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  13372. + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
  13373. + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  13374. + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  13375. + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  13376. + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  13377. + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  13378. + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  13379. + * POSSIBILITY OF SUCH DAMAGE.
  13380. + */
  13381. +#ifndef __FSL_DPSW_H
  13382. +#define __FSL_DPSW_H
  13383. +
  13384. +/* Data Path L2-Switch API
  13385. + * Contains API for handling DPSW topology and functionality
  13386. + */
  13387. +
  13388. +struct fsl_mc_io;
  13389. +
  13390. +/**
  13391. + * DPSW general definitions
  13392. + */
  13393. +
  13394. +/**
  13395. + * Maximum number of traffic class priorities
  13396. + */
  13397. +#define DPSW_MAX_PRIORITIES 8
  13398. +/**
  13399. + * Maximum number of interfaces
  13400. + */
  13401. +#define DPSW_MAX_IF 64
  13402. +
  13403. +int dpsw_open(struct fsl_mc_io *mc_io,
  13404. + u32 cmd_flags,
  13405. + int dpsw_id,
  13406. + u16 *token);
  13407. +
  13408. +int dpsw_close(struct fsl_mc_io *mc_io,
  13409. + u32 cmd_flags,
  13410. + u16 token);
  13411. +
  13412. +/**
  13413. + * DPSW options
  13414. + */
  13415. +
  13416. +/**
  13417. + * Disable flooding
  13418. + */
  13419. +#define DPSW_OPT_FLOODING_DIS 0x0000000000000001ULL
  13420. +/**
  13421. + * Disable Multicast
  13422. + */
  13423. +#define DPSW_OPT_MULTICAST_DIS 0x0000000000000004ULL
  13424. +/**
  13425. + * Support control interface
  13426. + */
  13427. +#define DPSW_OPT_CTRL_IF_DIS 0x0000000000000010ULL
  13428. +/**
  13429. + * Disable flooding metering
  13430. + */
  13431. +#define DPSW_OPT_FLOODING_METERING_DIS 0x0000000000000020ULL
  13432. +/**
  13433. + * Enable metering
  13434. + */
  13435. +#define DPSW_OPT_METERING_EN 0x0000000000000040ULL
  13436. +
  13437. +/**
  13438. + * enum dpsw_component_type - component type of a bridge
  13439. + * @DPSW_COMPONENT_TYPE_C_VLAN: A C-VLAN component of an
  13440. + * enterprise VLAN bridge or of a Provider Bridge used
  13441. + * to process C-tagged frames
  13442. + * @DPSW_COMPONENT_TYPE_S_VLAN: An S-VLAN component of a
  13443. + * Provider Bridge
  13444. + *
  13445. + */
  13446. +enum dpsw_component_type {
  13447. + DPSW_COMPONENT_TYPE_C_VLAN = 0,
  13448. + DPSW_COMPONENT_TYPE_S_VLAN
  13449. +};
  13450. +
  13451. +/**
  13452. + * struct dpsw_cfg - DPSW configuration
  13453. + * @num_ifs: Number of external and internal interfaces
  13454. + * @adv: Advanced parameters; default is all zeros;
  13455. + * use this structure to change default settings
  13456. + */
  13457. +struct dpsw_cfg {
  13458. + u16 num_ifs;
  13459. + /**
  13460. + * struct adv - Advanced parameters
  13461. + * @options: Enable/Disable DPSW features (bitmap)
  13462. + * @max_vlans: Maximum Number of VLAN's; 0 - indicates default 16
  13463. + * @max_meters_per_if: Number of meters per interface
  13464. + * @max_fdbs: Maximum Number of FDB's; 0 - indicates default 16
  13465. + * @max_fdb_entries: Number of FDB entries for default FDB table;
  13466. + * 0 - indicates default 1024 entries.
  13467. + * @fdb_aging_time: Default FDB aging time for default FDB table;
  13468. + * 0 - indicates default 300 seconds
  13469. + * @max_fdb_mc_groups: Number of multicast groups in each FDB table;
  13470. + * 0 - indicates default 32
  13471. + * @component_type: Indicates the component type of this bridge
  13472. + */
  13473. + struct {
  13474. + u64 options;
  13475. + u16 max_vlans;
  13476. + u8 max_meters_per_if;
  13477. + u8 max_fdbs;
  13478. + u16 max_fdb_entries;
  13479. + u16 fdb_aging_time;
  13480. + u16 max_fdb_mc_groups;
  13481. + enum dpsw_component_type component_type;
  13482. + } adv;
  13483. +};
  13484. +
  13485. +int dpsw_create(struct fsl_mc_io *mc_io,
  13486. + u16 dprc_token,
  13487. + u32 cmd_flags,
  13488. + const struct dpsw_cfg *cfg,
  13489. + u32 *obj_id);
  13490. +
  13491. +int dpsw_destroy(struct fsl_mc_io *mc_io,
  13492. + u16 dprc_token,
  13493. + u32 cmd_flags,
  13494. + u32 object_id);
  13495. +
  13496. +int dpsw_enable(struct fsl_mc_io *mc_io,
  13497. + u32 cmd_flags,
  13498. + u16 token);
  13499. +
  13500. +int dpsw_disable(struct fsl_mc_io *mc_io,
  13501. + u32 cmd_flags,
  13502. + u16 token);
  13503. +
  13504. +int dpsw_is_enabled(struct fsl_mc_io *mc_io,
  13505. + u32 cmd_flags,
  13506. + u16 token,
  13507. + int *en);
  13508. +
  13509. +int dpsw_reset(struct fsl_mc_io *mc_io,
  13510. + u32 cmd_flags,
  13511. + u16 token);
  13512. +
  13513. +/**
  13514. + * DPSW IRQ Index and Events
  13515. + */
  13516. +
  13517. +#define DPSW_IRQ_INDEX_IF 0x0000
  13518. +#define DPSW_IRQ_INDEX_L2SW 0x0001
  13519. +
  13520. +/**
  13521. + * IRQ event - Indicates that the link state changed
  13522. + */
  13523. +#define DPSW_IRQ_EVENT_LINK_CHANGED 0x0001
  13524. +
  13525. +/**
  13526. + * struct dpsw_irq_cfg - IRQ configuration
  13527. + * @addr: Address that must be written to signal a message-based interrupt
  13528. + * @val: Value to write into irq_addr address
  13529. + * @irq_num: A user defined number associated with this IRQ
  13530. + */
  13531. +struct dpsw_irq_cfg {
  13532. + u64 addr;
  13533. + u32 val;
  13534. + int irq_num;
  13535. +};
  13536. +
  13537. +int dpsw_set_irq(struct fsl_mc_io *mc_io,
  13538. + u32 cmd_flags,
  13539. + u16 token,
  13540. + u8 irq_index,
  13541. + struct dpsw_irq_cfg *irq_cfg);
  13542. +
  13543. +int dpsw_get_irq(struct fsl_mc_io *mc_io,
  13544. + u32 cmd_flags,
  13545. + u16 token,
  13546. + u8 irq_index,
  13547. + int *type,
  13548. + struct dpsw_irq_cfg *irq_cfg);
  13549. +
  13550. +int dpsw_set_irq_enable(struct fsl_mc_io *mc_io,
  13551. + u32 cmd_flags,
  13552. + u16 token,
  13553. + u8 irq_index,
  13554. + u8 en);
  13555. +
  13556. +int dpsw_get_irq_enable(struct fsl_mc_io *mc_io,
  13557. + u32 cmd_flags,
  13558. + u16 token,
  13559. + u8 irq_index,
  13560. + u8 *en);
  13561. +
  13562. +int dpsw_set_irq_mask(struct fsl_mc_io *mc_io,
  13563. + u32 cmd_flags,
  13564. + u16 token,
  13565. + u8 irq_index,
  13566. + u32 mask);
  13567. +
  13568. +int dpsw_get_irq_mask(struct fsl_mc_io *mc_io,
  13569. + u32 cmd_flags,
  13570. + u16 token,
  13571. + u8 irq_index,
  13572. + u32 *mask);
  13573. +
  13574. +int dpsw_get_irq_status(struct fsl_mc_io *mc_io,
  13575. + u32 cmd_flags,
  13576. + u16 token,
  13577. + u8 irq_index,
  13578. + u32 *status);
  13579. +
  13580. +int dpsw_clear_irq_status(struct fsl_mc_io *mc_io,
  13581. + u32 cmd_flags,
  13582. + u16 token,
  13583. + u8 irq_index,
  13584. + u32 status);
  13585. +
  13586. +/**
  13587. + * struct dpsw_attr - Structure representing DPSW attributes
  13588. + * @id: DPSW object ID
  13589. + * @options: Enable/Disable DPSW features
  13590. + * @max_vlans: Maximum Number of VLANs
  13591. + * @max_meters_per_if: Number of meters per interface
  13592. + * @max_fdbs: Maximum Number of FDBs
  13593. + * @max_fdb_entries: Number of FDB entries for default FDB table;
  13594. + * 0 - indicates default 1024 entries.
  13595. + * @fdb_aging_time: Default FDB aging time for default FDB table;
  13596. + * 0 - indicates default 300 seconds
  13597. + * @max_fdb_mc_groups: Number of multicast groups in each FDB table;
  13598. + * 0 - indicates default 32
  13599. + * @mem_size: DPSW frame storage memory size
  13600. + * @num_ifs: Number of interfaces
  13601. + * @num_vlans: Current number of VLANs
  13602. + * @num_fdbs: Current number of FDBs
  13603. + * @component_type: Component type of this bridge
  13604. + */
  13605. +struct dpsw_attr {
  13606. + int id;
  13607. + u64 options;
  13608. + u16 max_vlans;
  13609. + u8 max_meters_per_if;
  13610. + u8 max_fdbs;
  13611. + u16 max_fdb_entries;
  13612. + u16 fdb_aging_time;
  13613. + u16 max_fdb_mc_groups;
  13614. + u16 num_ifs;
  13615. + u16 mem_size;
  13616. + u16 num_vlans;
  13617. + u8 num_fdbs;
  13618. + enum dpsw_component_type component_type;
  13619. +};
  13620. +
  13621. +int dpsw_get_attributes(struct fsl_mc_io *mc_io,
  13622. + u32 cmd_flags,
  13623. + u16 token,
  13624. + struct dpsw_attr *attr);
  13625. +
  13626. +int dpsw_set_reflection_if(struct fsl_mc_io *mc_io,
  13627. + u32 cmd_flags,
  13628. + u16 token,
  13629. + u16 if_id);
  13630. +
  13631. +/**
  13632. + * enum dpsw_action - Action selection for special/control frames
  13633. + * @DPSW_ACTION_DROP: Drop frame
  13634. + * @DPSW_ACTION_REDIRECT: Redirect frame to control port
  13635. + */
  13636. +enum dpsw_action {
  13637. + DPSW_ACTION_DROP = 0,
  13638. + DPSW_ACTION_REDIRECT = 1
  13639. +};
  13640. +
  13641. +/**
  13642. + * Enable auto-negotiation
  13643. + */
  13644. +#define DPSW_LINK_OPT_AUTONEG 0x0000000000000001ULL
  13645. +/**
  13646. + * Enable half-duplex mode
  13647. + */
  13648. +#define DPSW_LINK_OPT_HALF_DUPLEX 0x0000000000000002ULL
  13649. +/**
  13650. + * Enable pause frames
  13651. + */
  13652. +#define DPSW_LINK_OPT_PAUSE 0x0000000000000004ULL
  13653. +/**
  13654. + * Enable a-symmetric pause frames
  13655. + */
  13656. +#define DPSW_LINK_OPT_ASYM_PAUSE 0x0000000000000008ULL
  13657. +
  13658. +/**
  13659. + * struct dpsw_link_cfg - Structure representing DPSW link configuration
  13660. + * @rate: Rate
  13661. + * @options: Mask of available options; use 'DPSW_LINK_OPT_<X>' values
  13662. + */
  13663. +struct dpsw_link_cfg {
  13664. + u32 rate;
  13665. + u64 options;
  13666. +};
  13667. +
  13668. +int dpsw_if_set_link_cfg(struct fsl_mc_io *mc_io,
  13669. + u32 cmd_flags,
  13670. + u16 token,
  13671. + u16 if_id,
  13672. + struct dpsw_link_cfg *cfg);
  13673. +/**
  13674. + * struct dpsw_link_state - Structure representing DPSW link state
  13675. + * @rate: Rate
  13676. + * @options: Mask of available options; use 'DPSW_LINK_OPT_<X>' values
  13677. + * @up: 0 - covers two cases: down and disconnected, 1 - up
  13678. + */
  13679. +struct dpsw_link_state {
  13680. + u32 rate;
  13681. + u64 options;
  13682. + int up;
  13683. +};
  13684. +
  13685. +int dpsw_if_get_link_state(struct fsl_mc_io *mc_io,
  13686. + u32 cmd_flags,
  13687. + u16 token,
  13688. + u16 if_id,
  13689. + struct dpsw_link_state *state);
  13690. +
  13691. +int dpsw_if_set_flooding(struct fsl_mc_io *mc_io,
  13692. + u32 cmd_flags,
  13693. + u16 token,
  13694. + u16 if_id,
  13695. + int en);
  13696. +
  13697. +int dpsw_if_set_broadcast(struct fsl_mc_io *mc_io,
  13698. + u32 cmd_flags,
  13699. + u16 token,
  13700. + u16 if_id,
  13701. + int en);
  13702. +
  13703. +int dpsw_if_set_multicast(struct fsl_mc_io *mc_io,
  13704. + u32 cmd_flags,
  13705. + u16 token,
  13706. + u16 if_id,
  13707. + int en);
  13708. +
  13709. +/**
  13710. + * struct dpsw_tci_cfg - Tag Contorl Information (TCI) configuration
  13711. + * @pcp: Priority Code Point (PCP): a 3-bit field which refers
  13712. + * to the IEEE 802.1p priority
  13713. + * @dei: Drop Eligible Indicator (DEI): a 1-bit field. May be used
  13714. + * separately or in conjunction with PCP to indicate frames
  13715. + * eligible to be dropped in the presence of congestion
  13716. + * @vlan_id: VLAN Identifier (VID): a 12-bit field specifying the VLAN
  13717. + * to which the frame belongs. The hexadecimal values
  13718. + * of 0x000 and 0xFFF are reserved;
  13719. + * all other values may be used as VLAN identifiers,
  13720. + * allowing up to 4,094 VLANs
  13721. + */
  13722. +struct dpsw_tci_cfg {
  13723. + u8 pcp;
  13724. + u8 dei;
  13725. + u16 vlan_id;
  13726. +};
  13727. +
  13728. +int dpsw_if_set_tci(struct fsl_mc_io *mc_io,
  13729. + u32 cmd_flags,
  13730. + u16 token,
  13731. + u16 if_id,
  13732. + const struct dpsw_tci_cfg *cfg);
  13733. +
  13734. +int dpsw_if_get_tci(struct fsl_mc_io *mc_io,
  13735. + u32 cmd_flags,
  13736. + u16 token,
  13737. + u16 if_id,
  13738. + struct dpsw_tci_cfg *cfg);
  13739. +
  13740. +/**
  13741. + * enum dpsw_stp_state - Spanning Tree Protocol (STP) states
  13742. + * @DPSW_STP_STATE_BLOCKING: Blocking state
  13743. + * @DPSW_STP_STATE_LISTENING: Listening state
  13744. + * @DPSW_STP_STATE_LEARNING: Learning state
  13745. + * @DPSW_STP_STATE_FORWARDING: Forwarding state
  13746. + *
  13747. + */
  13748. +enum dpsw_stp_state {
  13749. + DPSW_STP_STATE_BLOCKING = 0,
  13750. + DPSW_STP_STATE_LISTENING = 1,
  13751. + DPSW_STP_STATE_LEARNING = 2,
  13752. + DPSW_STP_STATE_FORWARDING = 3
  13753. +};
  13754. +
  13755. +/**
  13756. + * struct dpsw_stp_cfg - Spanning Tree Protocol (STP) Configuration
  13757. + * @vlan_id: VLAN ID STP state
  13758. + * @state: STP state
  13759. + */
  13760. +struct dpsw_stp_cfg {
  13761. + u16 vlan_id;
  13762. + enum dpsw_stp_state state;
  13763. +};
  13764. +
  13765. +int dpsw_if_set_stp(struct fsl_mc_io *mc_io,
  13766. + u32 cmd_flags,
  13767. + u16 token,
  13768. + u16 if_id,
  13769. + const struct dpsw_stp_cfg *cfg);
  13770. +
  13771. +/**
  13772. + * enum dpsw_accepted_frames - Types of frames to accept
  13773. + * @DPSW_ADMIT_ALL: The device accepts VLAN tagged, untagged and
  13774. + * priority tagged frames
  13775. + * @DPSW_ADMIT_ONLY_VLAN_TAGGED: The device discards untagged frames or
  13776. + * Priority-Tagged frames received on this interface.
  13777. + *
  13778. + */
  13779. +enum dpsw_accepted_frames {
  13780. + DPSW_ADMIT_ALL = 1,
  13781. + DPSW_ADMIT_ONLY_VLAN_TAGGED = 3
  13782. +};
  13783. +
  13784. +/**
  13785. + * struct dpsw_accepted_frames_cfg - Types of frames to accept configuration
  13786. + * @type: Defines ingress accepted frames
  13787. + * @unaccept_act: When a frame is not accepted, it may be discarded or
  13788. + * redirected to control interface depending on this mode
  13789. + */
  13790. +struct dpsw_accepted_frames_cfg {
  13791. + enum dpsw_accepted_frames type;
  13792. + enum dpsw_action unaccept_act;
  13793. +};
  13794. +
  13795. +int dpsw_if_set_accepted_frames(struct fsl_mc_io *mc_io,
  13796. + u32 cmd_flags,
  13797. + u16 token,
  13798. + u16 if_id,
  13799. + const struct dpsw_accepted_frames_cfg *cfg);
  13800. +
  13801. +int dpsw_if_set_accept_all_vlan(struct fsl_mc_io *mc_io,
  13802. + u32 cmd_flags,
  13803. + u16 token,
  13804. + u16 if_id,
  13805. + int accept_all);
  13806. +
  13807. +/**
  13808. + * enum dpsw_counter - Counters types
  13809. + * @DPSW_CNT_ING_FRAME: Counts ingress frames
  13810. + * @DPSW_CNT_ING_BYTE: Counts ingress bytes
  13811. + * @DPSW_CNT_ING_FLTR_FRAME: Counts filtered ingress frames
  13812. + * @DPSW_CNT_ING_FRAME_DISCARD: Counts discarded ingress frame
  13813. + * @DPSW_CNT_ING_MCAST_FRAME: Counts ingress multicast frames
  13814. + * @DPSW_CNT_ING_MCAST_BYTE: Counts ingress multicast bytes
  13815. + * @DPSW_CNT_ING_BCAST_FRAME: Counts ingress broadcast frames
  13816. + * @DPSW_CNT_ING_BCAST_BYTES: Counts ingress broadcast bytes
  13817. + * @DPSW_CNT_EGR_FRAME: Counts egress frames
  13818. + * @DPSW_CNT_EGR_BYTE: Counts eEgress bytes
  13819. + * @DPSW_CNT_EGR_FRAME_DISCARD: Counts discarded egress frames
  13820. + * @DPSW_CNT_EGR_STP_FRAME_DISCARD: Counts egress STP discarded frames
  13821. + */
  13822. +enum dpsw_counter {
  13823. + DPSW_CNT_ING_FRAME = 0x0,
  13824. + DPSW_CNT_ING_BYTE = 0x1,
  13825. + DPSW_CNT_ING_FLTR_FRAME = 0x2,
  13826. + DPSW_CNT_ING_FRAME_DISCARD = 0x3,
  13827. + DPSW_CNT_ING_MCAST_FRAME = 0x4,
  13828. + DPSW_CNT_ING_MCAST_BYTE = 0x5,
  13829. + DPSW_CNT_ING_BCAST_FRAME = 0x6,
  13830. + DPSW_CNT_ING_BCAST_BYTES = 0x7,
  13831. + DPSW_CNT_EGR_FRAME = 0x8,
  13832. + DPSW_CNT_EGR_BYTE = 0x9,
  13833. + DPSW_CNT_EGR_FRAME_DISCARD = 0xa,
  13834. + DPSW_CNT_EGR_STP_FRAME_DISCARD = 0xb
  13835. +};
  13836. +
  13837. +int dpsw_if_get_counter(struct fsl_mc_io *mc_io,
  13838. + u32 cmd_flags,
  13839. + u16 token,
  13840. + u16 if_id,
  13841. + enum dpsw_counter type,
  13842. + u64 *counter);
  13843. +
  13844. +int dpsw_if_set_counter(struct fsl_mc_io *mc_io,
  13845. + u32 cmd_flags,
  13846. + u16 token,
  13847. + u16 if_id,
  13848. + enum dpsw_counter type,
  13849. + u64 counter);
  13850. +
  13851. +/**
  13852. + * Maximum number of TC
  13853. + */
  13854. +#define DPSW_MAX_TC 8
  13855. +
  13856. +/**
  13857. + * enum dpsw_priority_selector - User priority
  13858. + * @DPSW_UP_PCP: Priority Code Point (PCP): a 3-bit field which
  13859. + * refers to the IEEE 802.1p priority.
  13860. + * @DPSW_UP_DSCP: Differentiated services Code Point (DSCP): 6 bit
  13861. + * field from IP header
  13862. + *
  13863. + */
  13864. +enum dpsw_priority_selector {
  13865. + DPSW_UP_PCP = 0,
  13866. + DPSW_UP_DSCP = 1
  13867. +};
  13868. +
  13869. +/**
  13870. + * enum dpsw_schedule_mode - Traffic classes scheduling
  13871. + * @DPSW_SCHED_STRICT_PRIORITY: schedule strict priority
  13872. + * @DPSW_SCHED_WEIGHTED: schedule based on token bucket created algorithm
  13873. + */
  13874. +enum dpsw_schedule_mode {
  13875. + DPSW_SCHED_STRICT_PRIORITY,
  13876. + DPSW_SCHED_WEIGHTED
  13877. +};
  13878. +
  13879. +/**
  13880. + * struct dpsw_tx_schedule_cfg - traffic class configuration
  13881. + * @mode: Strict or weight-based scheduling
  13882. + * @delta_bandwidth: weighted Bandwidth in range from 100 to 10000
  13883. + */
  13884. +struct dpsw_tx_schedule_cfg {
  13885. + enum dpsw_schedule_mode mode;
  13886. + u16 delta_bandwidth;
  13887. +};
  13888. +
  13889. +/**
  13890. + * struct dpsw_tx_selection_cfg - Mapping user priority into traffic
  13891. + * class configuration
  13892. + * @priority_selector: Source for user priority regeneration
  13893. + * @tc_id: The Regenerated User priority that the incoming
  13894. + * User Priority is mapped to for this interface
  13895. + * @tc_sched: Traffic classes configuration
  13896. + */
  13897. +struct dpsw_tx_selection_cfg {
  13898. + enum dpsw_priority_selector priority_selector;
  13899. + u8 tc_id[DPSW_MAX_PRIORITIES];
  13900. + struct dpsw_tx_schedule_cfg tc_sched[DPSW_MAX_TC];
  13901. +};
  13902. +
  13903. +int dpsw_if_set_tx_selection(struct fsl_mc_io *mc_io,
  13904. + u32 cmd_flags,
  13905. + u16 token,
  13906. + u16 if_id,
  13907. + const struct dpsw_tx_selection_cfg *cfg);
  13908. +
  13909. +/**
  13910. + * enum dpsw_reflection_filter - Filter type for frames to reflect
  13911. + * @DPSW_REFLECTION_FILTER_INGRESS_ALL: Reflect all frames
  13912. + * @DPSW_REFLECTION_FILTER_INGRESS_VLAN: Reflect only frames belong to
  13913. + * particular VLAN defined by vid parameter
  13914. + *
  13915. + */
  13916. +enum dpsw_reflection_filter {
  13917. + DPSW_REFLECTION_FILTER_INGRESS_ALL = 0,
  13918. + DPSW_REFLECTION_FILTER_INGRESS_VLAN = 1
  13919. +};
  13920. +
  13921. +/**
  13922. + * struct dpsw_reflection_cfg - Structure representing reflection information
  13923. + * @filter: Filter type for frames to reflect
  13924. + * @vlan_id: Vlan Id to reflect; valid only when filter type is
  13925. + * DPSW_INGRESS_VLAN
  13926. + */
  13927. +struct dpsw_reflection_cfg {
  13928. + enum dpsw_reflection_filter filter;
  13929. + u16 vlan_id;
  13930. +};
  13931. +
  13932. +int dpsw_if_add_reflection(struct fsl_mc_io *mc_io,
  13933. + u32 cmd_flags,
  13934. + u16 token,
  13935. + u16 if_id,
  13936. + const struct dpsw_reflection_cfg *cfg);
  13937. +
  13938. +int dpsw_if_remove_reflection(struct fsl_mc_io *mc_io,
  13939. + u32 cmd_flags,
  13940. + u16 token,
  13941. + u16 if_id,
  13942. + const struct dpsw_reflection_cfg *cfg);
  13943. +
  13944. +/**
  13945. + * enum dpsw_metering_mode - Metering modes
  13946. + * @DPSW_METERING_MODE_NONE: metering disabled
  13947. + * @DPSW_METERING_MODE_RFC2698: RFC 2698
  13948. + * @DPSW_METERING_MODE_RFC4115: RFC 4115
  13949. + */
  13950. +enum dpsw_metering_mode {
  13951. + DPSW_METERING_MODE_NONE = 0,
  13952. + DPSW_METERING_MODE_RFC2698,
  13953. + DPSW_METERING_MODE_RFC4115
  13954. +};
  13955. +
  13956. +/**
  13957. + * enum dpsw_metering_unit - Metering count
  13958. + * @DPSW_METERING_UNIT_BYTES: count bytes
  13959. + * @DPSW_METERING_UNIT_FRAMES: count frames
  13960. + */
  13961. +enum dpsw_metering_unit {
  13962. + DPSW_METERING_UNIT_BYTES = 0,
  13963. + DPSW_METERING_UNIT_FRAMES
  13964. +};
  13965. +
  13966. +/**
  13967. + * struct dpsw_metering_cfg - Metering configuration
  13968. + * @mode: metering modes
  13969. + * @units: Bytes or frame units
  13970. + * @cir: Committed information rate (CIR) in Kbits/s
  13971. + * @eir: Peak information rate (PIR) Kbit/s rfc2698
  13972. + * Excess information rate (EIR) Kbit/s rfc4115
  13973. + * @cbs: Committed burst size (CBS) in bytes
  13974. + * @ebs: Peak burst size (PBS) in bytes for rfc2698
  13975. + * Excess bust size (EBS) in bytes rfc4115
  13976. + *
  13977. + */
  13978. +struct dpsw_metering_cfg {
  13979. + enum dpsw_metering_mode mode;
  13980. + enum dpsw_metering_unit units;
  13981. + u32 cir;
  13982. + u32 eir;
  13983. + u32 cbs;
  13984. + u32 ebs;
  13985. +};
  13986. +
  13987. +int dpsw_if_set_flooding_metering(struct fsl_mc_io *mc_io,
  13988. + u32 cmd_flags,
  13989. + u16 token,
  13990. + u16 if_id,
  13991. + const struct dpsw_metering_cfg *cfg);
  13992. +
  13993. +int dpsw_if_set_metering(struct fsl_mc_io *mc_io,
  13994. + u32 cmd_flags,
  13995. + u16 token,
  13996. + u16 if_id,
  13997. + u8 tc_id,
  13998. + const struct dpsw_metering_cfg *cfg);
  13999. +
  14000. +/**
  14001. + * enum dpsw_early_drop_unit - DPSW early drop unit
  14002. + * @DPSW_EARLY_DROP_UNIT_BYTE: count bytes
  14003. + * @DPSW_EARLY_DROP_UNIT_FRAMES: count frames
  14004. + */
  14005. +enum dpsw_early_drop_unit {
  14006. + DPSW_EARLY_DROP_UNIT_BYTE = 0,
  14007. + DPSW_EARLY_DROP_UNIT_FRAMES
  14008. +};
  14009. +
  14010. +/**
  14011. + * enum dpsw_early_drop_mode - DPSW early drop mode
  14012. + * @DPSW_EARLY_DROP_MODE_NONE: early drop is disabled
  14013. + * @DPSW_EARLY_DROP_MODE_TAIL: early drop in taildrop mode
  14014. + * @DPSW_EARLY_DROP_MODE_WRED: early drop in WRED mode
  14015. + */
  14016. +enum dpsw_early_drop_mode {
  14017. + DPSW_EARLY_DROP_MODE_NONE = 0,
  14018. + DPSW_EARLY_DROP_MODE_TAIL,
  14019. + DPSW_EARLY_DROP_MODE_WRED
  14020. +};
  14021. +
  14022. +/**
  14023. + * struct dpsw_wred_cfg - WRED configuration
  14024. + * @max_threshold: maximum threshold that packets may be discarded. Above this
  14025. + * threshold all packets are discarded; must be less than 2^39;
  14026. + * approximated to be expressed as (x+256)*2^(y-1) due to HW
  14027. + * implementation.
  14028. + * @min_threshold: minimum threshold that packets may be discarded at
  14029. + * @drop_probability: probability that a packet will be discarded (1-100,
  14030. + * associated with the maximum threshold)
  14031. + */
  14032. +struct dpsw_wred_cfg {
  14033. + u64 min_threshold;
  14034. + u64 max_threshold;
  14035. + u8 drop_probability;
  14036. +};
  14037. +
  14038. +/**
  14039. + * struct dpsw_early_drop_cfg - early-drop configuration
  14040. + * @drop_mode: drop mode
  14041. + * @units: count units
  14042. + * @yellow: WRED - 'yellow' configuration
  14043. + * @green: WRED - 'green' configuration
  14044. + * @tail_drop_threshold: tail drop threshold
  14045. + */
  14046. +struct dpsw_early_drop_cfg {
  14047. + enum dpsw_early_drop_mode drop_mode;
  14048. + enum dpsw_early_drop_unit units;
  14049. + struct dpsw_wred_cfg yellow;
  14050. + struct dpsw_wred_cfg green;
  14051. + u32 tail_drop_threshold;
  14052. +};
  14053. +
  14054. +void dpsw_prepare_early_drop(const struct dpsw_early_drop_cfg *cfg,
  14055. + u8 *early_drop_buf);
  14056. +
  14057. +int dpsw_if_set_early_drop(struct fsl_mc_io *mc_io,
  14058. + u32 cmd_flags,
  14059. + u16 token,
  14060. + u16 if_id,
  14061. + u8 tc_id,
  14062. + u64 early_drop_iova);
  14063. +
  14064. +/**
  14065. + * struct dpsw_custom_tpid_cfg - Structure representing tag Protocol identifier
  14066. + * @tpid: An additional tag protocol identifier
  14067. + */
  14068. +struct dpsw_custom_tpid_cfg {
  14069. + u16 tpid;
  14070. +};
  14071. +
  14072. +int dpsw_add_custom_tpid(struct fsl_mc_io *mc_io,
  14073. + u32 cmd_flags,
  14074. + u16 token,
  14075. + const struct dpsw_custom_tpid_cfg *cfg);
  14076. +
  14077. +int dpsw_remove_custom_tpid(struct fsl_mc_io *mc_io,
  14078. + u32 cmd_flags,
  14079. + u16 token,
  14080. + const struct dpsw_custom_tpid_cfg *cfg);
  14081. +
  14082. +int dpsw_if_enable(struct fsl_mc_io *mc_io,
  14083. + u32 cmd_flags,
  14084. + u16 token,
  14085. + u16 if_id);
  14086. +
  14087. +int dpsw_if_disable(struct fsl_mc_io *mc_io,
  14088. + u32 cmd_flags,
  14089. + u16 token,
  14090. + u16 if_id);
  14091. +
  14092. +/**
  14093. + * struct dpsw_if_attr - Structure representing DPSW interface attributes
  14094. + * @num_tcs: Number of traffic classes
  14095. + * @rate: Transmit rate in bits per second
  14096. + * @options: Interface configuration options (bitmap)
  14097. + * @enabled: Indicates if interface is enabled
  14098. + * @accept_all_vlan: The device discards/accepts incoming frames
  14099. + * for VLANs that do not include this interface
  14100. + * @admit_untagged: When set to 'DPSW_ADMIT_ONLY_VLAN_TAGGED', the device
  14101. + * discards untagged frames or priority-tagged frames received on
  14102. + * this interface;
  14103. + * When set to 'DPSW_ADMIT_ALL', untagged frames or priority-
  14104. + * tagged frames received on this interface are accepted
  14105. + * @qdid: control frames transmit qdid
  14106. + */
  14107. +struct dpsw_if_attr {
  14108. + u8 num_tcs;
  14109. + u32 rate;
  14110. + u32 options;
  14111. + int enabled;
  14112. + int accept_all_vlan;
  14113. + enum dpsw_accepted_frames admit_untagged;
  14114. + u16 qdid;
  14115. +};
  14116. +
  14117. +int dpsw_if_get_attributes(struct fsl_mc_io *mc_io,
  14118. + u32 cmd_flags,
  14119. + u16 token,
  14120. + u16 if_id,
  14121. + struct dpsw_if_attr *attr);
  14122. +
  14123. +int dpsw_if_set_max_frame_length(struct fsl_mc_io *mc_io,
  14124. + u32 cmd_flags,
  14125. + u16 token,
  14126. + u16 if_id,
  14127. + u16 frame_length);
  14128. +
  14129. +int dpsw_if_get_max_frame_length(struct fsl_mc_io *mc_io,
  14130. + u32 cmd_flags,
  14131. + u16 token,
  14132. + u16 if_id,
  14133. + u16 *frame_length);
  14134. +
  14135. +/**
  14136. + * struct dpsw_vlan_cfg - VLAN Configuration
  14137. + * @fdb_id: Forwarding Data Base
  14138. + */
  14139. +struct dpsw_vlan_cfg {
  14140. + u16 fdb_id;
  14141. +};
  14142. +
  14143. +int dpsw_vlan_add(struct fsl_mc_io *mc_io,
  14144. + u32 cmd_flags,
  14145. + u16 token,
  14146. + u16 vlan_id,
  14147. + const struct dpsw_vlan_cfg *cfg);
  14148. +
  14149. +/**
  14150. + * struct dpsw_vlan_if_cfg - Set of VLAN Interfaces
  14151. + * @num_ifs: The number of interfaces that are assigned to the egress
  14152. + * list for this VLAN
  14153. + * @if_id: The set of interfaces that are
  14154. + * assigned to the egress list for this VLAN
  14155. + */
  14156. +struct dpsw_vlan_if_cfg {
  14157. + u16 num_ifs;
  14158. + u16 if_id[DPSW_MAX_IF];
  14159. +};
  14160. +
  14161. +int dpsw_vlan_add_if(struct fsl_mc_io *mc_io,
  14162. + u32 cmd_flags,
  14163. + u16 token,
  14164. + u16 vlan_id,
  14165. + const struct dpsw_vlan_if_cfg *cfg);
  14166. +
  14167. +int dpsw_vlan_add_if_untagged(struct fsl_mc_io *mc_io,
  14168. + u32 cmd_flags,
  14169. + u16 token,
  14170. + u16 vlan_id,
  14171. + const struct dpsw_vlan_if_cfg *cfg);
  14172. +
  14173. +int dpsw_vlan_add_if_flooding(struct fsl_mc_io *mc_io,
  14174. + u32 cmd_flags,
  14175. + u16 token,
  14176. + u16 vlan_id,
  14177. + const struct dpsw_vlan_if_cfg *cfg);
  14178. +
  14179. +int dpsw_vlan_remove_if(struct fsl_mc_io *mc_io,
  14180. + u32 cmd_flags,
  14181. + u16 token,
  14182. + u16 vlan_id,
  14183. + const struct dpsw_vlan_if_cfg *cfg);
  14184. +
  14185. +int dpsw_vlan_remove_if_untagged(struct fsl_mc_io *mc_io,
  14186. + u32 cmd_flags,
  14187. + u16 token,
  14188. + u16 vlan_id,
  14189. + const struct dpsw_vlan_if_cfg *cfg);
  14190. +
  14191. +int dpsw_vlan_remove_if_flooding(struct fsl_mc_io *mc_io,
  14192. + u32 cmd_flags,
  14193. + u16 token,
  14194. + u16 vlan_id,
  14195. + const struct dpsw_vlan_if_cfg *cfg);
  14196. +
  14197. +int dpsw_vlan_remove(struct fsl_mc_io *mc_io,
  14198. + u32 cmd_flags,
  14199. + u16 token,
  14200. + u16 vlan_id);
  14201. +
  14202. +/**
  14203. + * struct dpsw_vlan_attr - VLAN attributes
  14204. + * @fdb_id: Associated FDB ID
  14205. + * @num_ifs: Number of interfaces
  14206. + * @num_untagged_ifs: Number of untagged interfaces
  14207. + * @num_flooding_ifs: Number of flooding interfaces
  14208. + */
  14209. +struct dpsw_vlan_attr {
  14210. + u16 fdb_id;
  14211. + u16 num_ifs;
  14212. + u16 num_untagged_ifs;
  14213. + u16 num_flooding_ifs;
  14214. +};
  14215. +
  14216. +int dpsw_vlan_get_attributes(struct fsl_mc_io *mc_io,
  14217. + u32 cmd_flags,
  14218. + u16 token,
  14219. + u16 vlan_id,
  14220. + struct dpsw_vlan_attr *attr);
  14221. +
  14222. +int dpsw_vlan_get_if(struct fsl_mc_io *mc_io,
  14223. + u32 cmd_flags,
  14224. + u16 token,
  14225. + u16 vlan_id,
  14226. + struct dpsw_vlan_if_cfg *cfg);
  14227. +
  14228. +int dpsw_vlan_get_if_flooding(struct fsl_mc_io *mc_io,
  14229. + u32 cmd_flags,
  14230. + u16 token,
  14231. + u16 vlan_id,
  14232. + struct dpsw_vlan_if_cfg *cfg);
  14233. +
  14234. +int dpsw_vlan_get_if_untagged(struct fsl_mc_io *mc_io,
  14235. + u32 cmd_flags,
  14236. + u16 token,
  14237. + u16 vlan_id,
  14238. + struct dpsw_vlan_if_cfg *cfg);
  14239. +
  14240. +/**
  14241. + * struct dpsw_fdb_cfg - FDB Configuration
  14242. + * @num_fdb_entries: Number of FDB entries
  14243. + * @fdb_aging_time: Aging time in seconds
  14244. + */
  14245. +struct dpsw_fdb_cfg {
  14246. + u16 num_fdb_entries;
  14247. + u16 fdb_aging_time;
  14248. +};
  14249. +
  14250. +int dpsw_fdb_add(struct fsl_mc_io *mc_io,
  14251. + u32 cmd_flags,
  14252. + u16 token,
  14253. + u16 *fdb_id,
  14254. + const struct dpsw_fdb_cfg *cfg);
  14255. +
  14256. +int dpsw_fdb_remove(struct fsl_mc_io *mc_io,
  14257. + u32 cmd_flags,
  14258. + u16 token,
  14259. + u16 fdb_id);
  14260. +
  14261. +/**
  14262. + * enum dpsw_fdb_entry_type - FDB Entry type - Static/Dynamic
  14263. + * @DPSW_FDB_ENTRY_STATIC: Static entry
  14264. + * @DPSW_FDB_ENTRY_DINAMIC: Dynamic entry
  14265. + */
  14266. +enum dpsw_fdb_entry_type {
  14267. + DPSW_FDB_ENTRY_STATIC = 0,
  14268. + DPSW_FDB_ENTRY_DINAMIC = 1
  14269. +};
  14270. +
  14271. +/**
  14272. + * struct dpsw_fdb_unicast_cfg - Unicast entry configuration
  14273. + * @type: Select static or dynamic entry
  14274. + * @mac_addr: MAC address
  14275. + * @if_egress: Egress interface ID
  14276. + */
  14277. +struct dpsw_fdb_unicast_cfg {
  14278. + enum dpsw_fdb_entry_type type;
  14279. + u8 mac_addr[6];
  14280. + u16 if_egress;
  14281. +};
  14282. +
  14283. +int dpsw_fdb_add_unicast(struct fsl_mc_io *mc_io,
  14284. + u32 cmd_flags,
  14285. + u16 token,
  14286. + u16 fdb_id,
  14287. + const struct dpsw_fdb_unicast_cfg *cfg);
  14288. +
  14289. +int dpsw_fdb_get_unicast(struct fsl_mc_io *mc_io,
  14290. + u32 cmd_flags,
  14291. + u16 token,
  14292. + u16 fdb_id,
  14293. + struct dpsw_fdb_unicast_cfg *cfg);
  14294. +
  14295. +int dpsw_fdb_remove_unicast(struct fsl_mc_io *mc_io,
  14296. + u32 cmd_flags,
  14297. + u16 token,
  14298. + u16 fdb_id,
  14299. + const struct dpsw_fdb_unicast_cfg *cfg);
  14300. +
  14301. +/**
  14302. + * struct dpsw_fdb_multicast_cfg - Multi-cast entry configuration
  14303. + * @type: Select static or dynamic entry
  14304. + * @mac_addr: MAC address
  14305. + * @num_ifs: Number of external and internal interfaces
  14306. + * @if_id: Egress interface IDs
  14307. + */
  14308. +struct dpsw_fdb_multicast_cfg {
  14309. + enum dpsw_fdb_entry_type type;
  14310. + u8 mac_addr[6];
  14311. + u16 num_ifs;
  14312. + u16 if_id[DPSW_MAX_IF];
  14313. +};
  14314. +
  14315. +int dpsw_fdb_add_multicast(struct fsl_mc_io *mc_io,
  14316. + u32 cmd_flags,
  14317. + u16 token,
  14318. + u16 fdb_id,
  14319. + const struct dpsw_fdb_multicast_cfg *cfg);
  14320. +
  14321. +int dpsw_fdb_get_multicast(struct fsl_mc_io *mc_io,
  14322. + u32 cmd_flags,
  14323. + u16 token,
  14324. + u16 fdb_id,
  14325. + struct dpsw_fdb_multicast_cfg *cfg);
  14326. +
  14327. +int dpsw_fdb_remove_multicast(struct fsl_mc_io *mc_io,
  14328. + u32 cmd_flags,
  14329. + u16 token,
  14330. + u16 fdb_id,
  14331. + const struct dpsw_fdb_multicast_cfg *cfg);
  14332. +
  14333. +/**
  14334. + * enum dpsw_fdb_learning_mode - Auto-learning modes
  14335. + * @DPSW_FDB_LEARNING_MODE_DIS: Disable Auto-learning
  14336. + * @DPSW_FDB_LEARNING_MODE_HW: Enable HW auto-Learning
  14337. + * @DPSW_FDB_LEARNING_MODE_NON_SECURE: Enable None secure learning by CPU
  14338. + * @DPSW_FDB_LEARNING_MODE_SECURE: Enable secure learning by CPU
  14339. + *
  14340. + * NONE - SECURE LEARNING
  14341. + * SMAC found DMAC found CTLU Action
  14342. + * v v Forward frame to
  14343. + * 1. DMAC destination
  14344. + * - v Forward frame to
  14345. + * 1. DMAC destination
  14346. + * 2. Control interface
  14347. + * v - Forward frame to
  14348. + * 1. Flooding list of interfaces
  14349. + * - - Forward frame to
  14350. + * 1. Flooding list of interfaces
  14351. + * 2. Control interface
  14352. + * SECURE LEARING
  14353. + * SMAC found DMAC found CTLU Action
  14354. + * v v Forward frame to
  14355. + * 1. DMAC destination
  14356. + * - v Forward frame to
  14357. + * 1. Control interface
  14358. + * v - Forward frame to
  14359. + * 1. Flooding list of interfaces
  14360. + * - - Forward frame to
  14361. + * 1. Control interface
  14362. + */
  14363. +enum dpsw_fdb_learning_mode {
  14364. + DPSW_FDB_LEARNING_MODE_DIS = 0,
  14365. + DPSW_FDB_LEARNING_MODE_HW = 1,
  14366. + DPSW_FDB_LEARNING_MODE_NON_SECURE = 2,
  14367. + DPSW_FDB_LEARNING_MODE_SECURE = 3
  14368. +};
  14369. +
  14370. +int dpsw_fdb_set_learning_mode(struct fsl_mc_io *mc_io,
  14371. + u32 cmd_flags,
  14372. + u16 token,
  14373. + u16 fdb_id,
  14374. + enum dpsw_fdb_learning_mode mode);
  14375. +
  14376. +/**
  14377. + * struct dpsw_fdb_attr - FDB Attributes
  14378. + * @max_fdb_entries: Number of FDB entries
  14379. + * @fdb_aging_time: Aging time in seconds
  14380. + * @learning_mode: Learning mode
  14381. + * @num_fdb_mc_groups: Current number of multicast groups
  14382. + * @max_fdb_mc_groups: Maximum number of multicast groups
  14383. + */
  14384. +struct dpsw_fdb_attr {
  14385. + u16 max_fdb_entries;
  14386. + u16 fdb_aging_time;
  14387. + enum dpsw_fdb_learning_mode learning_mode;
  14388. + u16 num_fdb_mc_groups;
  14389. + u16 max_fdb_mc_groups;
  14390. +};
  14391. +
  14392. +int dpsw_fdb_get_attributes(struct fsl_mc_io *mc_io,
  14393. + u32 cmd_flags,
  14394. + u16 token,
  14395. + u16 fdb_id,
  14396. + struct dpsw_fdb_attr *attr);
  14397. +
  14398. +/**
  14399. + * struct dpsw_acl_cfg - ACL Configuration
  14400. + * @max_entries: Number of FDB entries
  14401. + */
  14402. +struct dpsw_acl_cfg {
  14403. + u16 max_entries;
  14404. +};
  14405. +
  14406. +/**
  14407. + * struct dpsw_acl_fields - ACL fields.
  14408. + * @l2_dest_mac: Destination MAC address: BPDU, Multicast, Broadcast, Unicast,
  14409. + * slow protocols, MVRP, STP
  14410. + * @l2_source_mac: Source MAC address
  14411. + * @l2_tpid: Layer 2 (Ethernet) protocol type, used to identify the following
  14412. + * protocols: MPLS, PTP, PFC, ARP, Jumbo frames, LLDP, IEEE802.1ae,
  14413. + * Q-in-Q, IPv4, IPv6, PPPoE
  14414. + * @l2_pcp_dei: indicate which protocol is encapsulated in the payload
  14415. + * @l2_vlan_id: layer 2 VLAN ID
  14416. + * @l2_ether_type: layer 2 Ethernet type
  14417. + * @l3_dscp: Layer 3 differentiated services code point
  14418. + * @l3_protocol: Tells the Network layer at the destination host, to which
  14419. + * Protocol this packet belongs to. The following protocol are
  14420. + * supported: ICMP, IGMP, IPv4 (encapsulation), TCP, IPv6
  14421. + * (encapsulation), GRE, PTP
  14422. + * @l3_source_ip: Source IPv4 IP
  14423. + * @l3_dest_ip: Destination IPv4 IP
  14424. + * @l4_source_port: Source TCP/UDP Port
  14425. + * @l4_dest_port: Destination TCP/UDP Port
  14426. + */
  14427. +struct dpsw_acl_fields {
  14428. + u8 l2_dest_mac[6];
  14429. + u8 l2_source_mac[6];
  14430. + u16 l2_tpid;
  14431. + u8 l2_pcp_dei;
  14432. + u16 l2_vlan_id;
  14433. + u16 l2_ether_type;
  14434. + u8 l3_dscp;
  14435. + u8 l3_protocol;
  14436. + u32 l3_source_ip;
  14437. + u32 l3_dest_ip;
  14438. + u16 l4_source_port;
  14439. + u16 l4_dest_port;
  14440. +};
  14441. +
  14442. +/**
  14443. + * struct dpsw_acl_key - ACL key
  14444. + * @match: Match fields
  14445. + * @mask: Mask: b'1 - valid, b'0 don't care
  14446. + */
  14447. +struct dpsw_acl_key {
  14448. + struct dpsw_acl_fields match;
  14449. + struct dpsw_acl_fields mask;
  14450. +};
  14451. +
  14452. +/**
  14453. + * enum dpsw_acl_action
  14454. + * @DPSW_ACL_ACTION_DROP: Drop frame
  14455. + * @DPSW_ACL_ACTION_REDIRECT: Redirect to certain port
  14456. + * @DPSW_ACL_ACTION_ACCEPT: Accept frame
  14457. + * @DPSW_ACL_ACTION_REDIRECT_TO_CTRL_IF: Redirect to control interface
  14458. + */
  14459. +enum dpsw_acl_action {
  14460. + DPSW_ACL_ACTION_DROP,
  14461. + DPSW_ACL_ACTION_REDIRECT,
  14462. + DPSW_ACL_ACTION_ACCEPT,
  14463. + DPSW_ACL_ACTION_REDIRECT_TO_CTRL_IF
  14464. +};
  14465. +
  14466. +/**
  14467. + * struct dpsw_acl_result - ACL action
  14468. + * @action: Action should be taken when ACL entry hit
  14469. + * @if_id: Interface IDs to redirect frame. Valid only if redirect selected for
  14470. + * action
  14471. + */
  14472. +struct dpsw_acl_result {
  14473. + enum dpsw_acl_action action;
  14474. + u16 if_id;
  14475. +};
  14476. +
  14477. +/**
  14478. + * struct dpsw_acl_entry_cfg - ACL entry
  14479. + * @key_iova: I/O virtual address of DMA-able memory filled with key after call
  14480. + * to dpsw_acl_prepare_entry_cfg()
  14481. + * @result: Required action when entry hit occurs
  14482. + * @precedence: Precedence inside ACL 0 is lowest; This priority can not change
  14483. + * during the lifetime of a Policy. It is user responsibility to
  14484. + * space the priorities according to consequent rule additions.
  14485. + */
  14486. +struct dpsw_acl_entry_cfg {
  14487. + u64 key_iova;
  14488. + struct dpsw_acl_result result;
  14489. + int precedence;
  14490. +};
  14491. +
  14492. +int dpsw_acl_add(struct fsl_mc_io *mc_io,
  14493. + u32 cmd_flags,
  14494. + u16 token,
  14495. + u16 *acl_id,
  14496. + const struct dpsw_acl_cfg *cfg);
  14497. +
  14498. +int dpsw_acl_remove(struct fsl_mc_io *mc_io,
  14499. + u32 cmd_flags,
  14500. + u16 token,
  14501. + u16 acl_id);
  14502. +
  14503. +void dpsw_acl_prepare_entry_cfg(const struct dpsw_acl_key *key,
  14504. + uint8_t *entry_cfg_buf);
  14505. +
  14506. +int dpsw_acl_add_entry(struct fsl_mc_io *mc_io,
  14507. + u32 cmd_flags,
  14508. + u16 token,
  14509. + u16 acl_id,
  14510. + const struct dpsw_acl_entry_cfg *cfg);
  14511. +
  14512. +int dpsw_acl_remove_entry(struct fsl_mc_io *mc_io,
  14513. + u32 cmd_flags,
  14514. + u16 token,
  14515. + u16 acl_id,
  14516. + const struct dpsw_acl_entry_cfg *cfg);
  14517. +
  14518. +/**
  14519. + * struct dpsw_acl_if_cfg - List of interfaces to Associate with ACL
  14520. + * @num_ifs: Number of interfaces
  14521. + * @if_id: List of interfaces
  14522. + */
  14523. +struct dpsw_acl_if_cfg {
  14524. + u16 num_ifs;
  14525. + u16 if_id[DPSW_MAX_IF];
  14526. +};
  14527. +
  14528. +int dpsw_acl_add_if(struct fsl_mc_io *mc_io,
  14529. + u32 cmd_flags,
  14530. + u16 token,
  14531. + u16 acl_id,
  14532. + const struct dpsw_acl_if_cfg *cfg);
  14533. +
  14534. +int dpsw_acl_remove_if(struct fsl_mc_io *mc_io,
  14535. + u32 cmd_flags,
  14536. + u16 token,
  14537. + u16 acl_id,
  14538. + const struct dpsw_acl_if_cfg *cfg);
  14539. +
  14540. +/**
  14541. + * struct dpsw_acl_attr - ACL Attributes
  14542. + * @max_entries: Max number of ACL entries
  14543. + * @num_entries: Number of used ACL entries
  14544. + * @num_ifs: Number of interfaces associated with ACL
  14545. + */
  14546. +struct dpsw_acl_attr {
  14547. + u16 max_entries;
  14548. + u16 num_entries;
  14549. + u16 num_ifs;
  14550. +};
  14551. +
  14552. +int dpsw_acl_get_attributes(struct fsl_mc_io *mc_io,
  14553. + u32 cmd_flags,
  14554. + u16 token,
  14555. + u16 acl_id,
  14556. + struct dpsw_acl_attr *attr);
  14557. +/**
  14558. + * struct dpsw_ctrl_if_attr - Control interface attributes
  14559. + * @rx_fqid: Receive FQID
  14560. + * @rx_err_fqid: Receive error FQID
  14561. + * @tx_err_conf_fqid: Transmit error and confirmation FQID
  14562. + */
  14563. +struct dpsw_ctrl_if_attr {
  14564. + u32 rx_fqid;
  14565. + u32 rx_err_fqid;
  14566. + u32 tx_err_conf_fqid;
  14567. +};
  14568. +
  14569. +int dpsw_ctrl_if_get_attributes(struct fsl_mc_io *mc_io,
  14570. + u32 cmd_flags,
  14571. + u16 token,
  14572. + struct dpsw_ctrl_if_attr *attr);
  14573. +
  14574. +/**
  14575. + * Maximum number of DPBP
  14576. + */
  14577. +#define DPSW_MAX_DPBP 8
  14578. +
  14579. +/**
  14580. + * struct dpsw_ctrl_if_pools_cfg - Control interface buffer pools configuration
  14581. + * @num_dpbp: Number of DPBPs
  14582. + * @pools: Array of buffer pools parameters; The number of valid entries
  14583. + * must match 'num_dpbp' value
  14584. + */
  14585. +struct dpsw_ctrl_if_pools_cfg {
  14586. + u8 num_dpbp;
  14587. + /**
  14588. + * struct pools - Buffer pools parameters
  14589. + * @dpbp_id: DPBP object ID
  14590. + * @buffer_size: Buffer size
  14591. + * @backup_pool: Backup pool
  14592. + */
  14593. + struct {
  14594. + int dpbp_id;
  14595. + u16 buffer_size;
  14596. + int backup_pool;
  14597. + } pools[DPSW_MAX_DPBP];
  14598. +};
  14599. +
  14600. +int dpsw_ctrl_if_set_pools(struct fsl_mc_io *mc_io,
  14601. + u32 cmd_flags,
  14602. + u16 token,
  14603. + const struct dpsw_ctrl_if_pools_cfg *cfg);
  14604. +
  14605. +int dpsw_ctrl_if_enable(struct fsl_mc_io *mc_io,
  14606. + u32 cmd_flags,
  14607. + u16 token);
  14608. +
  14609. +int dpsw_ctrl_if_disable(struct fsl_mc_io *mc_io,
  14610. + u32 cmd_flags,
  14611. + u16 token);
  14612. +
  14613. +int dpsw_get_api_version(struct fsl_mc_io *mc_io,
  14614. + u32 cmd_flags,
  14615. + u16 *major_ver,
  14616. + u16 *minor_ver);
  14617. +
  14618. +#endif /* __FSL_DPSW_H */
  14619. --- /dev/null
  14620. +++ b/drivers/staging/fsl-dpaa2/ethsw/switch.c
  14621. @@ -0,0 +1,1857 @@
  14622. +/* Copyright 2014-2015 Freescale Semiconductor Inc.
  14623. + *
  14624. + * Redistribution and use in source and binary forms, with or without
  14625. + * modification, are permitted provided that the following conditions are met:
  14626. + * * Redistributions of source code must retain the above copyright
  14627. + * notice, this list of conditions and the following disclaimer.
  14628. + * * Redistributions in binary form must reproduce the above copyright
  14629. + * notice, this list of conditions and the following disclaimer in the
  14630. + * documentation and/or other materials provided with the distribution.
  14631. + * * Neither the name of Freescale Semiconductor nor the
  14632. + * names of its contributors may be used to endorse or promote products
  14633. + * derived from this software without specific prior written permission.
  14634. + *
  14635. + *
  14636. + * ALTERNATIVELY, this software may be distributed under the terms of the
  14637. + * GNU General Public License ("GPL") as published by the Free Software
  14638. + * Foundation, either version 2 of that License or (at your option) any
  14639. + * later version.
  14640. + *
  14641. + * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
  14642. + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  14643. + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  14644. + * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
  14645. + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  14646. + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  14647. + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  14648. + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  14649. + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  14650. + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  14651. + */
  14652. +
  14653. +#include <linux/module.h>
  14654. +#include <linux/msi.h>
  14655. +
  14656. +#include <linux/netdevice.h>
  14657. +#include <linux/etherdevice.h>
  14658. +#include <linux/rtnetlink.h>
  14659. +#include <linux/if_vlan.h>
  14660. +
  14661. +#include <uapi/linux/if_bridge.h>
  14662. +#include <net/netlink.h>
  14663. +
  14664. +#include "../../fsl-mc/include/mc.h"
  14665. +#include "dpsw.h"
  14666. +#include "dpsw-cmd.h"
  14667. +
  14668. +static const char ethsw_drv_version[] = "0.1";
  14669. +
  14670. +/* Minimal supported DPSE version */
  14671. +#define DPSW_MIN_VER_MAJOR 8
  14672. +#define DPSW_MIN_VER_MINOR 0
  14673. +
  14674. +/* IRQ index */
  14675. +#define DPSW_MAX_IRQ_NUM 2
  14676. +
  14677. +#define ETHSW_VLAN_MEMBER 1
  14678. +#define ETHSW_VLAN_UNTAGGED 2
  14679. +#define ETHSW_VLAN_PVID 4
  14680. +#define ETHSW_VLAN_GLOBAL 8
  14681. +
  14682. +/* Maximum Frame Length supported by HW (currently 10k) */
  14683. +#define DPAA2_MFL (10 * 1024)
  14684. +#define ETHSW_MAX_FRAME_LENGTH (DPAA2_MFL - VLAN_ETH_HLEN - ETH_FCS_LEN)
  14685. +#define ETHSW_L2_MAX_FRM(mtu) ((mtu) + VLAN_ETH_HLEN + ETH_FCS_LEN)
  14686. +
  14687. +struct ethsw_port_priv {
  14688. + struct net_device *netdev;
  14689. + struct list_head list;
  14690. + u16 port_index;
  14691. + struct ethsw_dev_priv *ethsw_priv;
  14692. + u8 stp_state;
  14693. +
  14694. + char vlans[VLAN_VID_MASK + 1];
  14695. +
  14696. +};
  14697. +
  14698. +struct ethsw_dev_priv {
  14699. + struct net_device *netdev;
  14700. + struct fsl_mc_io *mc_io;
  14701. + u16 dpsw_handle;
  14702. + struct dpsw_attr sw_attr;
  14703. + int dev_id;
  14704. + /*TODO: redundant, we can use the slave dev list */
  14705. + struct list_head port_list;
  14706. +
  14707. + bool flood;
  14708. + bool learning;
  14709. +
  14710. + char vlans[VLAN_VID_MASK + 1];
  14711. +};
  14712. +
  14713. +static int ethsw_port_stop(struct net_device *netdev);
  14714. +static int ethsw_port_open(struct net_device *netdev);
  14715. +
  14716. +static inline void __get_priv(struct net_device *netdev,
  14717. + struct ethsw_dev_priv **priv,
  14718. + struct ethsw_port_priv **port_priv)
  14719. +{
  14720. + struct ethsw_dev_priv *_priv = NULL;
  14721. + struct ethsw_port_priv *_port_priv = NULL;
  14722. +
  14723. + if (netdev->flags & IFF_MASTER) {
  14724. + _priv = netdev_priv(netdev);
  14725. + } else {
  14726. + _port_priv = netdev_priv(netdev);
  14727. + _priv = _port_priv->ethsw_priv;
  14728. + }
  14729. +
  14730. + if (priv)
  14731. + *priv = _priv;
  14732. + if (port_priv)
  14733. + *port_priv = _port_priv;
  14734. +}
  14735. +
  14736. +/* -------------------------------------------------------------------------- */
  14737. +/* ethsw netdevice ops */
  14738. +
  14739. +static netdev_tx_t ethsw_dropframe(struct sk_buff *skb, struct net_device *dev)
  14740. +{
  14741. + /* we don't support I/O for now, drop the frame */
  14742. + dev_kfree_skb_any(skb);
  14743. + return NETDEV_TX_OK;
  14744. +}
  14745. +
  14746. +static int ethsw_open(struct net_device *netdev)
  14747. +{
  14748. + struct ethsw_dev_priv *priv = netdev_priv(netdev);
  14749. + struct list_head *pos;
  14750. + struct ethsw_port_priv *port_priv = NULL;
  14751. + int err;
  14752. +
  14753. + err = dpsw_enable(priv->mc_io, 0, priv->dpsw_handle);
  14754. + if (err) {
  14755. + netdev_err(netdev, "dpsw_enable err %d\n", err);
  14756. + return err;
  14757. + }
  14758. +
  14759. + list_for_each(pos, &priv->port_list) {
  14760. + port_priv = list_entry(pos, struct ethsw_port_priv, list);
  14761. + err = dev_open(port_priv->netdev);
  14762. + if (err)
  14763. + netdev_err(port_priv->netdev, "dev_open err %d\n", err);
  14764. + }
  14765. +
  14766. + return 0;
  14767. +}
  14768. +
  14769. +static int ethsw_stop(struct net_device *netdev)
  14770. +{
  14771. + struct ethsw_dev_priv *priv = netdev_priv(netdev);
  14772. + struct list_head *pos;
  14773. + struct ethsw_port_priv *port_priv = NULL;
  14774. + int err;
  14775. +
  14776. + err = dpsw_disable(priv->mc_io, 0, priv->dpsw_handle);
  14777. + if (err) {
  14778. + netdev_err(netdev, "dpsw_disable err %d\n", err);
  14779. + return err;
  14780. + }
  14781. +
  14782. + list_for_each(pos, &priv->port_list) {
  14783. + port_priv = list_entry(pos, struct ethsw_port_priv, list);
  14784. + err = dev_close(port_priv->netdev);
  14785. + if (err)
  14786. + netdev_err(port_priv->netdev,
  14787. + "dev_close err %d\n", err);
  14788. + }
  14789. +
  14790. + return 0;
  14791. +}
  14792. +
  14793. +static int ethsw_add_vlan(struct net_device *netdev, u16 vid)
  14794. +{
  14795. + struct ethsw_dev_priv *priv = netdev_priv(netdev);
  14796. + int err;
  14797. +
  14798. + struct dpsw_vlan_cfg vcfg = {
  14799. + /* TODO: add support for VLAN private FDBs */
  14800. + .fdb_id = 0,
  14801. + };
  14802. + if (priv->vlans[vid]) {
  14803. + netdev_err(netdev, "VLAN already configured\n");
  14804. + return -EEXIST;
  14805. + }
  14806. +
  14807. + err = dpsw_vlan_add(priv->mc_io, 0, priv->dpsw_handle, vid, &vcfg);
  14808. + if (err) {
  14809. + netdev_err(netdev, "dpsw_vlan_add err %d\n", err);
  14810. + return err;
  14811. + }
  14812. + priv->vlans[vid] = ETHSW_VLAN_MEMBER;
  14813. +
  14814. + return 0;
  14815. +}
  14816. +
  14817. +static int ethsw_port_add_vlan(struct net_device *netdev, u16 vid, u16 flags)
  14818. +{
  14819. + struct ethsw_port_priv *port_priv = netdev_priv(netdev);
  14820. + struct ethsw_dev_priv *priv = port_priv->ethsw_priv;
  14821. + int err;
  14822. +
  14823. + struct dpsw_vlan_if_cfg vcfg = {
  14824. + .num_ifs = 1,
  14825. + .if_id[0] = port_priv->port_index,
  14826. + };
  14827. +
  14828. + if (port_priv->vlans[vid]) {
  14829. + netdev_err(netdev, "VLAN already configured\n");
  14830. + return -EEXIST;
  14831. + }
  14832. +
  14833. + if (flags & BRIDGE_VLAN_INFO_PVID && netif_oper_up(netdev)) {
  14834. + netdev_err(netdev, "interface must be down to change PVID!\n");
  14835. + return -EBUSY;
  14836. + }
  14837. +
  14838. + err = dpsw_vlan_add_if(priv->mc_io, 0, priv->dpsw_handle, vid, &vcfg);
  14839. + if (err) {
  14840. + netdev_err(netdev, "dpsw_vlan_add_if err %d\n", err);
  14841. + return err;
  14842. + }
  14843. + port_priv->vlans[vid] = ETHSW_VLAN_MEMBER;
  14844. +
  14845. + if (flags & BRIDGE_VLAN_INFO_UNTAGGED) {
  14846. + err = dpsw_vlan_add_if_untagged(priv->mc_io, 0,
  14847. + priv->dpsw_handle, vid, &vcfg);
  14848. + if (err) {
  14849. + netdev_err(netdev, "dpsw_vlan_add_if_untagged err %d\n",
  14850. + err);
  14851. + return err;
  14852. + }
  14853. + port_priv->vlans[vid] |= ETHSW_VLAN_UNTAGGED;
  14854. + }
  14855. +
  14856. + if (flags & BRIDGE_VLAN_INFO_PVID) {
  14857. + struct dpsw_tci_cfg tci_cfg = {
  14858. + /* TODO: at least add better defaults if these cannot
  14859. + * be configured
  14860. + */
  14861. + .pcp = 0,
  14862. + .dei = 0,
  14863. + .vlan_id = vid,
  14864. + };
  14865. +
  14866. + err = dpsw_if_set_tci(priv->mc_io, 0, priv->dpsw_handle,
  14867. + port_priv->port_index, &tci_cfg);
  14868. + if (err) {
  14869. + netdev_err(netdev, "dpsw_if_set_tci err %d\n", err);
  14870. + return err;
  14871. + }
  14872. + port_priv->vlans[vid] |= ETHSW_VLAN_PVID;
  14873. + }
  14874. +
  14875. + return 0;
  14876. +}
  14877. +
  14878. +static const struct nla_policy ifla_br_policy[IFLA_MAX + 1] = {
  14879. + [IFLA_BRIDGE_FLAGS] = { .type = NLA_U16 },
  14880. + [IFLA_BRIDGE_MODE] = { .type = NLA_U16 },
  14881. + [IFLA_BRIDGE_VLAN_INFO] = { .type = NLA_BINARY,
  14882. + .len = sizeof(struct bridge_vlan_info), },
  14883. +};
  14884. +
  14885. +static int ethsw_setlink_af_spec(struct net_device *netdev,
  14886. + struct nlattr **tb)
  14887. +{
  14888. + struct bridge_vlan_info *vinfo;
  14889. + struct ethsw_dev_priv *priv = NULL;
  14890. + struct ethsw_port_priv *port_priv = NULL;
  14891. + int err = 0;
  14892. +
  14893. + if (!tb[IFLA_BRIDGE_VLAN_INFO]) {
  14894. + netdev_err(netdev, "no VLAN INFO in nlmsg\n");
  14895. + return -EOPNOTSUPP;
  14896. + }
  14897. +
  14898. + vinfo = nla_data(tb[IFLA_BRIDGE_VLAN_INFO]);
  14899. +
  14900. + if (!vinfo->vid || vinfo->vid > VLAN_VID_MASK)
  14901. + return -EINVAL;
  14902. +
  14903. + __get_priv(netdev, &priv, &port_priv);
  14904. +
  14905. + if (!port_priv || !priv->vlans[vinfo->vid]) {
  14906. + /* command targets switch device or this is a new VLAN */
  14907. + err = ethsw_add_vlan(priv->netdev, vinfo->vid);
  14908. + if (err)
  14909. + return err;
  14910. +
  14911. + /* command targets switch device; mark it*/
  14912. + if (!port_priv)
  14913. + priv->vlans[vinfo->vid] |= ETHSW_VLAN_GLOBAL;
  14914. + }
  14915. +
  14916. + if (port_priv) {
  14917. + /* command targets switch port */
  14918. + err = ethsw_port_add_vlan(netdev, vinfo->vid, vinfo->flags);
  14919. + if (err)
  14920. + return err;
  14921. + }
  14922. +
  14923. + return 0;
  14924. +}
  14925. +
  14926. +static const struct nla_policy ifla_brport_policy[IFLA_BRPORT_MAX + 1] = {
  14927. + [IFLA_BRPORT_STATE] = { .type = NLA_U8 },
  14928. + [IFLA_BRPORT_COST] = { .type = NLA_U32 },
  14929. + [IFLA_BRPORT_PRIORITY] = { .type = NLA_U16 },
  14930. + [IFLA_BRPORT_MODE] = { .type = NLA_U8 },
  14931. + [IFLA_BRPORT_GUARD] = { .type = NLA_U8 },
  14932. + [IFLA_BRPORT_PROTECT] = { .type = NLA_U8 },
  14933. + [IFLA_BRPORT_LEARNING] = { .type = NLA_U8 },
  14934. + [IFLA_BRPORT_UNICAST_FLOOD] = { .type = NLA_U8 },
  14935. +};
  14936. +
  14937. +static int ethsw_set_learning(struct net_device *netdev, u8 flag)
  14938. +{
  14939. + struct ethsw_dev_priv *priv = netdev_priv(netdev);
  14940. + enum dpsw_fdb_learning_mode learn_mode;
  14941. + int err;
  14942. +
  14943. + if (flag)
  14944. + learn_mode = DPSW_FDB_LEARNING_MODE_HW;
  14945. + else
  14946. + learn_mode = DPSW_FDB_LEARNING_MODE_DIS;
  14947. +
  14948. + err = dpsw_fdb_set_learning_mode(priv->mc_io, 0, priv->dpsw_handle,
  14949. + 0, learn_mode);
  14950. + if (err) {
  14951. + netdev_err(netdev, "dpsw_fdb_set_learning_mode err %d\n", err);
  14952. + return err;
  14953. + }
  14954. + priv->learning = !!flag;
  14955. +
  14956. + return 0;
  14957. +}
  14958. +
  14959. +static int ethsw_port_set_flood(struct net_device *netdev, u8 flag)
  14960. +{
  14961. + struct ethsw_port_priv *port_priv = netdev_priv(netdev);
  14962. + struct ethsw_dev_priv *priv = port_priv->ethsw_priv;
  14963. + int err;
  14964. +
  14965. + err = dpsw_if_set_flooding(priv->mc_io, 0, priv->dpsw_handle,
  14966. + port_priv->port_index, (int)flag);
  14967. + if (err) {
  14968. + netdev_err(netdev, "dpsw_fdb_set_learning_mode err %d\n", err);
  14969. + return err;
  14970. + }
  14971. + priv->flood = !!flag;
  14972. +
  14973. + return 0;
  14974. +}
  14975. +
  14976. +static int ethsw_port_set_state(struct net_device *netdev, u8 state)
  14977. +{
  14978. + struct ethsw_port_priv *port_priv = netdev_priv(netdev);
  14979. + struct ethsw_dev_priv *priv = port_priv->ethsw_priv;
  14980. + u8 old_state = port_priv->stp_state;
  14981. + int err;
  14982. +
  14983. + struct dpsw_stp_cfg stp_cfg = {
  14984. + .vlan_id = 1,
  14985. + .state = state,
  14986. + };
  14987. + /* TODO: check port state, interface may be down */
  14988. +
  14989. + if (state > BR_STATE_BLOCKING)
  14990. + return -EINVAL;
  14991. +
  14992. + if (state == port_priv->stp_state)
  14993. + return 0;
  14994. +
  14995. + if (state == BR_STATE_DISABLED) {
  14996. + port_priv->stp_state = state;
  14997. +
  14998. + err = ethsw_port_stop(netdev);
  14999. + if (err)
  15000. + goto error;
  15001. + } else {
  15002. + err = dpsw_if_set_stp(priv->mc_io, 0, priv->dpsw_handle,
  15003. + port_priv->port_index, &stp_cfg);
  15004. + if (err) {
  15005. + netdev_err(netdev, "dpsw_if_set_stp err %d\n", err);
  15006. + return err;
  15007. + }
  15008. +
  15009. + port_priv->stp_state = state;
  15010. +
  15011. + if (old_state == BR_STATE_DISABLED) {
  15012. + err = ethsw_port_open(netdev);
  15013. + if (err)
  15014. + goto error;
  15015. + }
  15016. + }
  15017. +
  15018. + return 0;
  15019. +error:
  15020. + port_priv->stp_state = old_state;
  15021. + return err;
  15022. +}
  15023. +
  15024. +static int ethsw_setlink_protinfo(struct net_device *netdev,
  15025. + struct nlattr **tb)
  15026. +{
  15027. + struct ethsw_dev_priv *priv;
  15028. + struct ethsw_port_priv *port_priv = NULL;
  15029. + int err = 0;
  15030. +
  15031. + __get_priv(netdev, &priv, &port_priv);
  15032. +
  15033. + if (tb[IFLA_BRPORT_LEARNING]) {
  15034. + u8 flag = nla_get_u8(tb[IFLA_BRPORT_LEARNING]);
  15035. +
  15036. + if (port_priv)
  15037. + netdev_warn(netdev,
  15038. + "learning set on whole switch dev\n");
  15039. +
  15040. + err = ethsw_set_learning(priv->netdev, flag);
  15041. + if (err)
  15042. + return err;
  15043. +
  15044. + } else if (tb[IFLA_BRPORT_UNICAST_FLOOD] && port_priv) {
  15045. + u8 flag = nla_get_u8(tb[IFLA_BRPORT_UNICAST_FLOOD]);
  15046. +
  15047. + err = ethsw_port_set_flood(port_priv->netdev, flag);
  15048. + if (err)
  15049. + return err;
  15050. +
  15051. + } else if (tb[IFLA_BRPORT_STATE] && port_priv) {
  15052. + u8 state = nla_get_u8(tb[IFLA_BRPORT_STATE]);
  15053. +
  15054. + err = ethsw_port_set_state(port_priv->netdev, state);
  15055. + if (err)
  15056. + return err;
  15057. +
  15058. + } else {
  15059. + return -EOPNOTSUPP;
  15060. + }
  15061. +
  15062. + return 0;
  15063. +}
  15064. +
  15065. +static int ethsw_setlink(struct net_device *netdev,
  15066. + struct nlmsghdr *nlh,
  15067. + u16 flags)
  15068. +{
  15069. + struct nlattr *attr;
  15070. + struct nlattr *tb[(IFLA_BRIDGE_MAX > IFLA_BRPORT_MAX) ?
  15071. + IFLA_BRIDGE_MAX : IFLA_BRPORT_MAX + 1];
  15072. + int err = 0;
  15073. +
  15074. + attr = nlmsg_find_attr(nlh, sizeof(struct ifinfomsg), IFLA_AF_SPEC);
  15075. + if (attr) {
  15076. + err = nla_parse_nested(tb, IFLA_BRIDGE_MAX, attr,
  15077. + ifla_br_policy);
  15078. + if (err) {
  15079. + netdev_err(netdev,
  15080. + "nla_parse_nested for br_policy err %d\n",
  15081. + err);
  15082. + return err;
  15083. + }
  15084. +
  15085. + err = ethsw_setlink_af_spec(netdev, tb);
  15086. + return err;
  15087. + }
  15088. +
  15089. + attr = nlmsg_find_attr(nlh, sizeof(struct ifinfomsg), IFLA_PROTINFO);
  15090. + if (attr) {
  15091. + err = nla_parse_nested(tb, IFLA_BRPORT_MAX, attr,
  15092. + ifla_brport_policy);
  15093. + if (err) {
  15094. + netdev_err(netdev,
  15095. + "nla_parse_nested for brport_policy err %d\n",
  15096. + err);
  15097. + return err;
  15098. + }
  15099. +
  15100. + err = ethsw_setlink_protinfo(netdev, tb);
  15101. + return err;
  15102. + }
  15103. +
  15104. + netdev_err(netdev, "nlmsg_find_attr found no AF_SPEC/PROTINFO\n");
  15105. + return -EOPNOTSUPP;
  15106. +}
  15107. +
  15108. +static int __nla_put_netdev(struct sk_buff *skb, struct net_device *netdev,
  15109. + struct ethsw_dev_priv *priv)
  15110. +{
  15111. + u8 operstate = netif_running(netdev) ? netdev->operstate : IF_OPER_DOWN;
  15112. + int iflink;
  15113. + int err;
  15114. +
  15115. + err = nla_put_string(skb, IFLA_IFNAME, netdev->name);
  15116. + if (err)
  15117. + goto nla_put_err;
  15118. + err = nla_put_u32(skb, IFLA_MASTER, priv->netdev->ifindex);
  15119. + if (err)
  15120. + goto nla_put_err;
  15121. + err = nla_put_u32(skb, IFLA_MTU, netdev->mtu);
  15122. + if (err)
  15123. + goto nla_put_err;
  15124. + err = nla_put_u8(skb, IFLA_OPERSTATE, operstate);
  15125. + if (err)
  15126. + goto nla_put_err;
  15127. + if (netdev->addr_len) {
  15128. + err = nla_put(skb, IFLA_ADDRESS, netdev->addr_len,
  15129. + netdev->dev_addr);
  15130. + if (err)
  15131. + goto nla_put_err;
  15132. + }
  15133. +
  15134. + iflink = dev_get_iflink(netdev);
  15135. + if (netdev->ifindex != iflink) {
  15136. + err = nla_put_u32(skb, IFLA_LINK, iflink);
  15137. + if (err)
  15138. + goto nla_put_err;
  15139. + }
  15140. +
  15141. + return 0;
  15142. +
  15143. +nla_put_err:
  15144. + netdev_err(netdev, "nla_put_ err %d\n", err);
  15145. + return err;
  15146. +}
  15147. +
  15148. +static int __nla_put_port(struct sk_buff *skb, struct net_device *netdev,
  15149. + struct ethsw_port_priv *port_priv)
  15150. +{
  15151. + struct nlattr *nest;
  15152. + int err;
  15153. +
  15154. + u8 stp_state = port_priv->stp_state;
  15155. +
  15156. + if (port_priv->stp_state == DPSW_STP_STATE_BLOCKING)
  15157. + stp_state = BR_STATE_BLOCKING;
  15158. +
  15159. + nest = nla_nest_start(skb, IFLA_PROTINFO | NLA_F_NESTED);
  15160. + if (!nest) {
  15161. + netdev_err(netdev, "nla_nest_start failed\n");
  15162. + return -ENOMEM;
  15163. + }
  15164. +
  15165. + err = nla_put_u8(skb, IFLA_BRPORT_STATE, stp_state);
  15166. + if (err)
  15167. + goto nla_put_err;
  15168. + err = nla_put_u16(skb, IFLA_BRPORT_PRIORITY, 0);
  15169. + if (err)
  15170. + goto nla_put_err;
  15171. + err = nla_put_u32(skb, IFLA_BRPORT_COST, 0);
  15172. + if (err)
  15173. + goto nla_put_err;
  15174. + err = nla_put_u8(skb, IFLA_BRPORT_MODE, 0);
  15175. + if (err)
  15176. + goto nla_put_err;
  15177. + err = nla_put_u8(skb, IFLA_BRPORT_GUARD, 0);
  15178. + if (err)
  15179. + goto nla_put_err;
  15180. + err = nla_put_u8(skb, IFLA_BRPORT_PROTECT, 0);
  15181. + if (err)
  15182. + goto nla_put_err;
  15183. + err = nla_put_u8(skb, IFLA_BRPORT_FAST_LEAVE, 0);
  15184. + if (err)
  15185. + goto nla_put_err;
  15186. + err = nla_put_u8(skb, IFLA_BRPORT_LEARNING,
  15187. + port_priv->ethsw_priv->learning);
  15188. + if (err)
  15189. + goto nla_put_err;
  15190. + err = nla_put_u8(skb, IFLA_BRPORT_UNICAST_FLOOD,
  15191. + port_priv->ethsw_priv->flood);
  15192. + if (err)
  15193. + goto nla_put_err;
  15194. + nla_nest_end(skb, nest);
  15195. +
  15196. + return 0;
  15197. +
  15198. +nla_put_err:
  15199. + netdev_err(netdev, "nla_put_ err %d\n", err);
  15200. + nla_nest_cancel(skb, nest);
  15201. + return err;
  15202. +}
  15203. +
  15204. +static int __nla_put_vlan(struct sk_buff *skb, struct net_device *netdev,
  15205. + struct ethsw_dev_priv *priv,
  15206. + struct ethsw_port_priv *port_priv)
  15207. +{
  15208. + struct nlattr *nest;
  15209. + struct bridge_vlan_info vinfo;
  15210. + const char *vlans;
  15211. + u16 i;
  15212. + int err;
  15213. +
  15214. + nest = nla_nest_start(skb, IFLA_AF_SPEC);
  15215. + if (!nest) {
  15216. + netdev_err(netdev, "nla_nest_start failed");
  15217. + return -ENOMEM;
  15218. + }
  15219. +
  15220. + if (port_priv)
  15221. + vlans = port_priv->vlans;
  15222. + else
  15223. + vlans = priv->vlans;
  15224. +
  15225. + for (i = 0; i < VLAN_VID_MASK + 1; i++) {
  15226. + vinfo.flags = 0;
  15227. + vinfo.vid = i;
  15228. +
  15229. + if (vlans[i] & ETHSW_VLAN_UNTAGGED)
  15230. + vinfo.flags |= BRIDGE_VLAN_INFO_UNTAGGED;
  15231. +
  15232. + if (vlans[i] & ETHSW_VLAN_PVID)
  15233. + vinfo.flags |= BRIDGE_VLAN_INFO_PVID;
  15234. +
  15235. + if (vlans[i] & ETHSW_VLAN_MEMBER) {
  15236. + err = nla_put(skb, IFLA_BRIDGE_VLAN_INFO,
  15237. + sizeof(vinfo), &vinfo);
  15238. + if (err)
  15239. + goto nla_put_err;
  15240. + }
  15241. + }
  15242. +
  15243. + nla_nest_end(skb, nest);
  15244. +
  15245. + return 0;
  15246. +nla_put_err:
  15247. + netdev_err(netdev, "nla_put_ err %d\n", err);
  15248. + nla_nest_cancel(skb, nest);
  15249. + return err;
  15250. +}
  15251. +
  15252. +static int ethsw_getlink(struct sk_buff *skb, u32 pid, u32 seq,
  15253. + struct net_device *netdev, u32 filter_mask,
  15254. + int nlflags)
  15255. +{
  15256. + struct ethsw_dev_priv *priv;
  15257. + struct ethsw_port_priv *port_priv = NULL;
  15258. + struct ifinfomsg *hdr;
  15259. + struct nlmsghdr *nlh;
  15260. + int err;
  15261. +
  15262. + __get_priv(netdev, &priv, &port_priv);
  15263. +
  15264. + nlh = nlmsg_put(skb, pid, seq, RTM_NEWLINK, sizeof(*hdr), NLM_F_MULTI);
  15265. + if (!nlh)
  15266. + return -EMSGSIZE;
  15267. +
  15268. + hdr = nlmsg_data(nlh);
  15269. + memset(hdr, 0, sizeof(*hdr));
  15270. + hdr->ifi_family = AF_BRIDGE;
  15271. + hdr->ifi_type = netdev->type;
  15272. + hdr->ifi_index = netdev->ifindex;
  15273. + hdr->ifi_flags = dev_get_flags(netdev);
  15274. +
  15275. + err = __nla_put_netdev(skb, netdev, priv);
  15276. + if (err)
  15277. + goto nla_put_err;
  15278. +
  15279. + if (port_priv) {
  15280. + err = __nla_put_port(skb, netdev, port_priv);
  15281. + if (err)
  15282. + goto nla_put_err;
  15283. + }
  15284. +
  15285. + /* Check if the VID information is requested */
  15286. + if (filter_mask & RTEXT_FILTER_BRVLAN) {
  15287. + err = __nla_put_vlan(skb, netdev, priv, port_priv);
  15288. + if (err)
  15289. + goto nla_put_err;
  15290. + }
  15291. +
  15292. + nlmsg_end(skb, nlh);
  15293. + return skb->len;
  15294. +
  15295. +nla_put_err:
  15296. + nlmsg_cancel(skb, nlh);
  15297. + return -EMSGSIZE;
  15298. +}
  15299. +
  15300. +static int ethsw_dellink_switch(struct ethsw_dev_priv *priv, u16 vid)
  15301. +{
  15302. + struct list_head *pos;
  15303. + struct ethsw_port_priv *ppriv_local = NULL;
  15304. + int err = 0;
  15305. +
  15306. + if (!priv->vlans[vid])
  15307. + return -ENOENT;
  15308. +
  15309. + err = dpsw_vlan_remove(priv->mc_io, 0, priv->dpsw_handle, vid);
  15310. + if (err) {
  15311. + netdev_err(priv->netdev, "dpsw_vlan_remove err %d\n", err);
  15312. + return err;
  15313. + }
  15314. + priv->vlans[vid] = 0;
  15315. +
  15316. + list_for_each(pos, &priv->port_list) {
  15317. + ppriv_local = list_entry(pos, struct ethsw_port_priv,
  15318. + list);
  15319. + ppriv_local->vlans[vid] = 0;
  15320. + }
  15321. +
  15322. + return 0;
  15323. +}
  15324. +
  15325. +static int ethsw_dellink_port(struct ethsw_dev_priv *priv,
  15326. + struct ethsw_port_priv *port_priv,
  15327. + u16 vid)
  15328. +{
  15329. + struct list_head *pos;
  15330. + struct ethsw_port_priv *ppriv_local = NULL;
  15331. + struct dpsw_vlan_if_cfg vcfg = {
  15332. + .num_ifs = 1,
  15333. + .if_id[0] = port_priv->port_index,
  15334. + };
  15335. + unsigned int count = 0;
  15336. + int err = 0;
  15337. +
  15338. + if (!port_priv->vlans[vid])
  15339. + return -ENOENT;
  15340. +
  15341. + /* VLAN will be deleted from switch if global flag is not set
  15342. + * and is configured on only one port
  15343. + */
  15344. + if (!(priv->vlans[vid] & ETHSW_VLAN_GLOBAL)) {
  15345. + list_for_each(pos, &priv->port_list) {
  15346. + ppriv_local = list_entry(pos, struct ethsw_port_priv,
  15347. + list);
  15348. + if (ppriv_local->vlans[vid] & ETHSW_VLAN_MEMBER)
  15349. + count++;
  15350. + }
  15351. +
  15352. + if (count == 1)
  15353. + return ethsw_dellink_switch(priv, vid);
  15354. + }
  15355. +
  15356. + err = dpsw_vlan_remove_if(priv->mc_io, 0, priv->dpsw_handle,
  15357. + vid, &vcfg);
  15358. + if (err) {
  15359. + netdev_err(priv->netdev, "dpsw_vlan_remove_if err %d\n", err);
  15360. + return err;
  15361. + }
  15362. + port_priv->vlans[vid] = 0;
  15363. + return 0;
  15364. +}
  15365. +
  15366. +static int ethsw_dellink(struct net_device *netdev,
  15367. + struct nlmsghdr *nlh,
  15368. + u16 flags)
  15369. +{
  15370. + struct nlattr *tb[IFLA_BRIDGE_MAX + 1];
  15371. + struct nlattr *spec;
  15372. + struct bridge_vlan_info *vinfo;
  15373. + struct ethsw_dev_priv *priv;
  15374. + struct ethsw_port_priv *port_priv = NULL;
  15375. + int err = 0;
  15376. +
  15377. + spec = nlmsg_find_attr(nlh, sizeof(struct ifinfomsg), IFLA_AF_SPEC);
  15378. + if (!spec)
  15379. + return 0;
  15380. +
  15381. + err = nla_parse_nested(tb, IFLA_BRIDGE_MAX, spec, ifla_br_policy);
  15382. + if (err)
  15383. + return err;
  15384. +
  15385. + if (!tb[IFLA_BRIDGE_VLAN_INFO])
  15386. + return -EOPNOTSUPP;
  15387. +
  15388. + vinfo = nla_data(tb[IFLA_BRIDGE_VLAN_INFO]);
  15389. +
  15390. + if (!vinfo->vid || vinfo->vid > VLAN_VID_MASK)
  15391. + return -EINVAL;
  15392. +
  15393. + __get_priv(netdev, &priv, &port_priv);
  15394. +
  15395. + /* decide if command targets switch device or port */
  15396. + if (!port_priv)
  15397. + err = ethsw_dellink_switch(priv, vinfo->vid);
  15398. + else
  15399. + err = ethsw_dellink_port(priv, port_priv, vinfo->vid);
  15400. +
  15401. + return err;
  15402. +}
  15403. +
  15404. +static const struct net_device_ops ethsw_ops = {
  15405. + .ndo_open = &ethsw_open,
  15406. + .ndo_stop = &ethsw_stop,
  15407. +
  15408. + .ndo_bridge_setlink = &ethsw_setlink,
  15409. + .ndo_bridge_getlink = &ethsw_getlink,
  15410. + .ndo_bridge_dellink = &ethsw_dellink,
  15411. +
  15412. + .ndo_start_xmit = &ethsw_dropframe,
  15413. +};
  15414. +
  15415. +/*--------------------------------------------------------------------------- */
  15416. +/* switch port netdevice ops */
  15417. +
  15418. +static int _ethsw_port_carrier_state_sync(struct net_device *netdev)
  15419. +{
  15420. + struct ethsw_port_priv *port_priv = netdev_priv(netdev);
  15421. + struct dpsw_link_state state;
  15422. + int err;
  15423. +
  15424. + err = dpsw_if_get_link_state(port_priv->ethsw_priv->mc_io, 0,
  15425. + port_priv->ethsw_priv->dpsw_handle,
  15426. + port_priv->port_index, &state);
  15427. + if (unlikely(err)) {
  15428. + netdev_err(netdev, "dpsw_if_get_link_state() err %d\n", err);
  15429. + return err;
  15430. + }
  15431. +
  15432. + WARN_ONCE(state.up > 1, "Garbage read into link_state");
  15433. +
  15434. + if (state.up)
  15435. + netif_carrier_on(port_priv->netdev);
  15436. + else
  15437. + netif_carrier_off(port_priv->netdev);
  15438. +
  15439. + return 0;
  15440. +}
  15441. +
  15442. +static int ethsw_port_open(struct net_device *netdev)
  15443. +{
  15444. + struct ethsw_port_priv *port_priv = netdev_priv(netdev);
  15445. + int err;
  15446. +
  15447. + err = dpsw_if_enable(port_priv->ethsw_priv->mc_io, 0,
  15448. + port_priv->ethsw_priv->dpsw_handle,
  15449. + port_priv->port_index);
  15450. + if (err) {
  15451. + netdev_err(netdev, "dpsw_if_enable err %d\n", err);
  15452. + return err;
  15453. + }
  15454. +
  15455. + /* sync carrier state */
  15456. + err = _ethsw_port_carrier_state_sync(netdev);
  15457. + if (err) {
  15458. + netdev_err(netdev, "_ethsw_port_carrier_state_sync err %d\n",
  15459. + err);
  15460. + goto err_carrier_sync;
  15461. + }
  15462. +
  15463. + return 0;
  15464. +
  15465. +err_carrier_sync:
  15466. + dpsw_if_disable(port_priv->ethsw_priv->mc_io, 0,
  15467. + port_priv->ethsw_priv->dpsw_handle,
  15468. + port_priv->port_index);
  15469. + return err;
  15470. +}
  15471. +
  15472. +static int ethsw_port_stop(struct net_device *netdev)
  15473. +{
  15474. + struct ethsw_port_priv *port_priv = netdev_priv(netdev);
  15475. + int err;
  15476. +
  15477. + err = dpsw_if_disable(port_priv->ethsw_priv->mc_io, 0,
  15478. + port_priv->ethsw_priv->dpsw_handle,
  15479. + port_priv->port_index);
  15480. + if (err) {
  15481. + netdev_err(netdev, "dpsw_if_disable err %d\n", err);
  15482. + return err;
  15483. + }
  15484. +
  15485. + return 0;
  15486. +}
  15487. +
  15488. +static int ethsw_port_fdb_add_uc(struct net_device *netdev,
  15489. + const unsigned char *addr)
  15490. +{
  15491. + struct ethsw_port_priv *port_priv = netdev_priv(netdev);
  15492. + struct dpsw_fdb_unicast_cfg entry = {0};
  15493. + int err;
  15494. +
  15495. + entry.if_egress = port_priv->port_index;
  15496. + entry.type = DPSW_FDB_ENTRY_STATIC;
  15497. + ether_addr_copy(entry.mac_addr, addr);
  15498. +
  15499. + err = dpsw_fdb_add_unicast(port_priv->ethsw_priv->mc_io, 0,
  15500. + port_priv->ethsw_priv->dpsw_handle,
  15501. + 0, &entry);
  15502. + if (err)
  15503. + netdev_err(netdev, "dpsw_fdb_add_unicast err %d\n", err);
  15504. + return err;
  15505. +}
  15506. +
  15507. +static int ethsw_port_fdb_del_uc(struct net_device *netdev,
  15508. + const unsigned char *addr)
  15509. +{
  15510. + struct ethsw_port_priv *port_priv = netdev_priv(netdev);
  15511. + struct dpsw_fdb_unicast_cfg entry = {0};
  15512. + int err;
  15513. +
  15514. + entry.if_egress = port_priv->port_index;
  15515. + entry.type = DPSW_FDB_ENTRY_STATIC;
  15516. + ether_addr_copy(entry.mac_addr, addr);
  15517. +
  15518. + err = dpsw_fdb_remove_unicast(port_priv->ethsw_priv->mc_io, 0,
  15519. + port_priv->ethsw_priv->dpsw_handle,
  15520. + 0, &entry);
  15521. + if (err)
  15522. + netdev_err(netdev, "dpsw_fdb_remove_unicast err %d\n", err);
  15523. + return err;
  15524. +}
  15525. +
  15526. +static int ethsw_port_fdb_add_mc(struct net_device *netdev,
  15527. + const unsigned char *addr)
  15528. +{
  15529. + struct ethsw_port_priv *port_priv = netdev_priv(netdev);
  15530. + struct dpsw_fdb_multicast_cfg entry = {0};
  15531. + int err;
  15532. +
  15533. + ether_addr_copy(entry.mac_addr, addr);
  15534. + entry.type = DPSW_FDB_ENTRY_STATIC;
  15535. + entry.num_ifs = 1;
  15536. + entry.if_id[0] = port_priv->port_index;
  15537. +
  15538. + err = dpsw_fdb_add_multicast(port_priv->ethsw_priv->mc_io, 0,
  15539. + port_priv->ethsw_priv->dpsw_handle,
  15540. + 0, &entry);
  15541. + if (err)
  15542. + netdev_err(netdev, "dpsw_fdb_add_multicast err %d\n", err);
  15543. + return err;
  15544. +}
  15545. +
  15546. +static int ethsw_port_fdb_del_mc(struct net_device *netdev,
  15547. + const unsigned char *addr)
  15548. +{
  15549. + struct ethsw_port_priv *port_priv = netdev_priv(netdev);
  15550. + struct dpsw_fdb_multicast_cfg entry = {0};
  15551. + int err;
  15552. +
  15553. + ether_addr_copy(entry.mac_addr, addr);
  15554. + entry.type = DPSW_FDB_ENTRY_STATIC;
  15555. + entry.num_ifs = 1;
  15556. + entry.if_id[0] = port_priv->port_index;
  15557. +
  15558. + err = dpsw_fdb_remove_multicast(port_priv->ethsw_priv->mc_io, 0,
  15559. + port_priv->ethsw_priv->dpsw_handle,
  15560. + 0, &entry);
  15561. + if (err)
  15562. + netdev_err(netdev, "dpsw_fdb_remove_multicast err %d\n", err);
  15563. + return err;
  15564. +}
  15565. +
  15566. +static int _lookup_address(struct net_device *netdev, int is_uc,
  15567. + const unsigned char *addr)
  15568. +{
  15569. + struct netdev_hw_addr *ha;
  15570. + struct netdev_hw_addr_list *list = (is_uc) ? &netdev->uc : &netdev->mc;
  15571. +
  15572. + netif_addr_lock_bh(netdev);
  15573. + list_for_each_entry(ha, &list->list, list) {
  15574. + if (ether_addr_equal(ha->addr, addr)) {
  15575. + netif_addr_unlock_bh(netdev);
  15576. + return 1;
  15577. + }
  15578. + }
  15579. + netif_addr_unlock_bh(netdev);
  15580. + return 0;
  15581. +}
  15582. +
  15583. +static int ethsw_port_fdb_add(struct ndmsg *ndm, struct nlattr *tb[],
  15584. + struct net_device *netdev,
  15585. + const unsigned char *addr, u16 vid,
  15586. + u16 flags)
  15587. +{
  15588. + struct list_head *pos;
  15589. + struct ethsw_port_priv *port_priv = netdev_priv(netdev);
  15590. + struct ethsw_dev_priv *priv = port_priv->ethsw_priv;
  15591. + int err;
  15592. +
  15593. + /* TODO: add replace support when added to iproute bridge */
  15594. + if (!(flags & NLM_F_REQUEST)) {
  15595. + netdev_err(netdev,
  15596. + "ethsw_port_fdb_add unexpected flags value %08x\n",
  15597. + flags);
  15598. + return -EINVAL;
  15599. + }
  15600. +
  15601. + if (is_unicast_ether_addr(addr)) {
  15602. + /* if entry cannot be replaced, return error if exists */
  15603. + if (flags & NLM_F_EXCL || flags & NLM_F_APPEND) {
  15604. + list_for_each(pos, &priv->port_list) {
  15605. + port_priv = list_entry(pos,
  15606. + struct ethsw_port_priv,
  15607. + list);
  15608. + if (_lookup_address(port_priv->netdev,
  15609. + 1, addr))
  15610. + return -EEXIST;
  15611. + }
  15612. + }
  15613. +
  15614. + err = ethsw_port_fdb_add_uc(netdev, addr);
  15615. + if (err) {
  15616. + netdev_err(netdev, "ethsw_port_fdb_add_uc err %d\n",
  15617. + err);
  15618. + return err;
  15619. + }
  15620. +
  15621. + /* we might have replaced an existing entry for a different
  15622. + * switch port, make sure the address doesn't linger in any
  15623. + * port address list
  15624. + */
  15625. + list_for_each(pos, &priv->port_list) {
  15626. + port_priv = list_entry(pos, struct ethsw_port_priv,
  15627. + list);
  15628. + dev_uc_del(port_priv->netdev, addr);
  15629. + }
  15630. +
  15631. + err = dev_uc_add(netdev, addr);
  15632. + if (err) {
  15633. + netdev_err(netdev, "dev_uc_add err %d\n", err);
  15634. + return err;
  15635. + }
  15636. + } else {
  15637. + struct dpsw_fdb_multicast_cfg entry = {
  15638. + .type = DPSW_FDB_ENTRY_STATIC,
  15639. + .num_ifs = 0,
  15640. + };
  15641. +
  15642. + /* check if address is already set on this port */
  15643. + if (_lookup_address(netdev, 0, addr))
  15644. + return -EEXIST;
  15645. +
  15646. + /* check if the address exists on other port */
  15647. + ether_addr_copy(entry.mac_addr, addr);
  15648. + err = dpsw_fdb_get_multicast(priv->mc_io, 0, priv->dpsw_handle,
  15649. + 0, &entry);
  15650. + if (!err) {
  15651. + /* entry exists, can we replace it? */
  15652. + if (flags & NLM_F_EXCL)
  15653. + return -EEXIST;
  15654. + } else if (err != -ENAVAIL) {
  15655. + netdev_err(netdev, "dpsw_fdb_get_unicast err %d\n",
  15656. + err);
  15657. + return err;
  15658. + }
  15659. +
  15660. + err = ethsw_port_fdb_add_mc(netdev, addr);
  15661. + if (err) {
  15662. + netdev_err(netdev, "ethsw_port_fdb_add_mc err %d\n",
  15663. + err);
  15664. + return err;
  15665. + }
  15666. +
  15667. + err = dev_mc_add(netdev, addr);
  15668. + if (err) {
  15669. + netdev_err(netdev, "dev_mc_add err %d\n", err);
  15670. + return err;
  15671. + }
  15672. + }
  15673. +
  15674. + return 0;
  15675. +}
  15676. +
  15677. +static int ethsw_port_fdb_del(struct ndmsg *ndm, struct nlattr *tb[],
  15678. + struct net_device *netdev,
  15679. + const unsigned char *addr, u16 vid)
  15680. +{
  15681. + int err;
  15682. +
  15683. + if (is_unicast_ether_addr(addr)) {
  15684. + err = ethsw_port_fdb_del_uc(netdev, addr);
  15685. + if (err) {
  15686. + netdev_err(netdev, "ethsw_port_fdb_del_uc err %d\n",
  15687. + err);
  15688. + return err;
  15689. + }
  15690. +
  15691. + /* also delete if configured on port */
  15692. + err = dev_uc_del(netdev, addr);
  15693. + if (err && err != -ENOENT) {
  15694. + netdev_err(netdev, "dev_uc_del err %d\n", err);
  15695. + return err;
  15696. + }
  15697. + } else {
  15698. + if (!_lookup_address(netdev, 0, addr))
  15699. + return -ENOENT;
  15700. +
  15701. + err = dev_mc_del(netdev, addr);
  15702. + if (err) {
  15703. + netdev_err(netdev, "dev_mc_del err %d\n", err);
  15704. + return err;
  15705. + }
  15706. +
  15707. + err = ethsw_port_fdb_del_mc(netdev, addr);
  15708. + if (err) {
  15709. + netdev_err(netdev, "ethsw_port_fdb_del_mc err %d\n",
  15710. + err);
  15711. + return err;
  15712. + }
  15713. + }
  15714. +
  15715. + return 0;
  15716. +}
  15717. +
  15718. +void ethsw_port_get_stats(struct net_device *netdev,
  15719. + struct rtnl_link_stats64 *storage)
  15720. +{
  15721. + struct ethsw_port_priv *port_priv = netdev_priv(netdev);
  15722. + u64 tmp;
  15723. + int err;
  15724. +
  15725. + err = dpsw_if_get_counter(port_priv->ethsw_priv->mc_io, 0,
  15726. + port_priv->ethsw_priv->dpsw_handle,
  15727. + port_priv->port_index,
  15728. + DPSW_CNT_ING_FRAME, &storage->rx_packets);
  15729. + if (err)
  15730. + goto error;
  15731. +
  15732. + err = dpsw_if_get_counter(port_priv->ethsw_priv->mc_io, 0,
  15733. + port_priv->ethsw_priv->dpsw_handle,
  15734. + port_priv->port_index,
  15735. + DPSW_CNT_EGR_FRAME, &storage->tx_packets);
  15736. + if (err)
  15737. + goto error;
  15738. +
  15739. + err = dpsw_if_get_counter(port_priv->ethsw_priv->mc_io, 0,
  15740. + port_priv->ethsw_priv->dpsw_handle,
  15741. + port_priv->port_index,
  15742. + DPSW_CNT_ING_BYTE, &storage->rx_bytes);
  15743. + if (err)
  15744. + goto error;
  15745. +
  15746. + err = dpsw_if_get_counter(port_priv->ethsw_priv->mc_io, 0,
  15747. + port_priv->ethsw_priv->dpsw_handle,
  15748. + port_priv->port_index,
  15749. + DPSW_CNT_EGR_BYTE, &storage->tx_bytes);
  15750. + if (err)
  15751. + goto error;
  15752. +
  15753. + err = dpsw_if_get_counter(port_priv->ethsw_priv->mc_io, 0,
  15754. + port_priv->ethsw_priv->dpsw_handle,
  15755. + port_priv->port_index,
  15756. + DPSW_CNT_ING_FRAME_DISCARD,
  15757. + &storage->rx_dropped);
  15758. + if (err)
  15759. + goto error;
  15760. +
  15761. + err = dpsw_if_get_counter(port_priv->ethsw_priv->mc_io, 0,
  15762. + port_priv->ethsw_priv->dpsw_handle,
  15763. + port_priv->port_index,
  15764. + DPSW_CNT_ING_FLTR_FRAME,
  15765. + &tmp);
  15766. + if (err)
  15767. + goto error;
  15768. + storage->rx_dropped += tmp;
  15769. +
  15770. + err = dpsw_if_get_counter(port_priv->ethsw_priv->mc_io, 0,
  15771. + port_priv->ethsw_priv->dpsw_handle,
  15772. + port_priv->port_index,
  15773. + DPSW_CNT_EGR_FRAME_DISCARD,
  15774. + &storage->tx_dropped);
  15775. + if (err)
  15776. + goto error;
  15777. +
  15778. + return;
  15779. +
  15780. +error:
  15781. + netdev_err(netdev, "dpsw_if_get_counter err %d\n", err);
  15782. +}
  15783. +
  15784. +static int ethsw_port_change_mtu(struct net_device *netdev, int mtu)
  15785. +{
  15786. + struct ethsw_port_priv *port_priv = netdev_priv(netdev);
  15787. + int err;
  15788. +
  15789. + if (mtu < ETH_ZLEN || mtu > ETHSW_MAX_FRAME_LENGTH) {
  15790. + netdev_err(netdev, "Invalid MTU %d. Valid range is: %d..%d\n",
  15791. + mtu, ETH_ZLEN, ETHSW_MAX_FRAME_LENGTH);
  15792. + return -EINVAL;
  15793. + }
  15794. +
  15795. + err = dpsw_if_set_max_frame_length(port_priv->ethsw_priv->mc_io,
  15796. + 0,
  15797. + port_priv->ethsw_priv->dpsw_handle,
  15798. + port_priv->port_index,
  15799. + (u16)ETHSW_L2_MAX_FRM(mtu));
  15800. + if (err) {
  15801. + netdev_err(netdev,
  15802. + "dpsw_if_set_max_frame_length() err %d\n", err);
  15803. + return err;
  15804. + }
  15805. +
  15806. + netdev->mtu = mtu;
  15807. + return 0;
  15808. +}
  15809. +
  15810. +static const struct net_device_ops ethsw_port_ops = {
  15811. + .ndo_open = &ethsw_port_open,
  15812. + .ndo_stop = &ethsw_port_stop,
  15813. +
  15814. + .ndo_fdb_add = &ethsw_port_fdb_add,
  15815. + .ndo_fdb_del = &ethsw_port_fdb_del,
  15816. + .ndo_fdb_dump = &ndo_dflt_fdb_dump,
  15817. +
  15818. + .ndo_get_stats64 = &ethsw_port_get_stats,
  15819. + .ndo_change_mtu = &ethsw_port_change_mtu,
  15820. +
  15821. + .ndo_start_xmit = &ethsw_dropframe,
  15822. +};
  15823. +
  15824. +static void ethsw_get_drvinfo(struct net_device *netdev,
  15825. + struct ethtool_drvinfo *drvinfo)
  15826. +{
  15827. + struct ethsw_port_priv *port_priv = netdev_priv(netdev);
  15828. + u16 version_major, version_minor;
  15829. + int err;
  15830. +
  15831. + strlcpy(drvinfo->driver, KBUILD_MODNAME, sizeof(drvinfo->driver));
  15832. + strlcpy(drvinfo->version, ethsw_drv_version, sizeof(drvinfo->version));
  15833. +
  15834. + err = dpsw_get_api_version(port_priv->ethsw_priv->mc_io, 0,
  15835. + &version_major,
  15836. + &version_minor);
  15837. + if (err)
  15838. + strlcpy(drvinfo->fw_version, "N/A",
  15839. + sizeof(drvinfo->fw_version));
  15840. + else
  15841. + snprintf(drvinfo->fw_version, sizeof(drvinfo->fw_version),
  15842. + "%u.%u", version_major, version_minor);
  15843. +
  15844. + strlcpy(drvinfo->bus_info, dev_name(netdev->dev.parent->parent),
  15845. + sizeof(drvinfo->bus_info));
  15846. +}
  15847. +
  15848. +static int ethsw_get_settings(struct net_device *netdev,
  15849. + struct ethtool_cmd *cmd)
  15850. +{
  15851. + struct ethsw_port_priv *port_priv = netdev_priv(netdev);
  15852. + struct dpsw_link_state state = {0};
  15853. + int err = 0;
  15854. +
  15855. + err = dpsw_if_get_link_state(port_priv->ethsw_priv->mc_io, 0,
  15856. + port_priv->ethsw_priv->dpsw_handle,
  15857. + port_priv->port_index,
  15858. + &state);
  15859. + if (err) {
  15860. + netdev_err(netdev, "ERROR %d getting link state", err);
  15861. + goto out;
  15862. + }
  15863. +
  15864. + /* At the moment, we have no way of interrogating the DPMAC
  15865. + * from the DPSW side or there may not exist a DPMAC at all.
  15866. + * Report only autoneg state, duplexity and speed.
  15867. + */
  15868. + if (state.options & DPSW_LINK_OPT_AUTONEG)
  15869. + cmd->autoneg = AUTONEG_ENABLE;
  15870. + if (!(state.options & DPSW_LINK_OPT_HALF_DUPLEX))
  15871. + cmd->autoneg = DUPLEX_FULL;
  15872. + ethtool_cmd_speed_set(cmd, state.rate);
  15873. +
  15874. +out:
  15875. + return err;
  15876. +}
  15877. +
  15878. +static int ethsw_set_settings(struct net_device *netdev,
  15879. + struct ethtool_cmd *cmd)
  15880. +{
  15881. + struct ethsw_port_priv *port_priv = netdev_priv(netdev);
  15882. + struct dpsw_link_state state = {0};
  15883. + struct dpsw_link_cfg cfg = {0};
  15884. + int err = 0;
  15885. +
  15886. + netdev_dbg(netdev, "Setting link parameters...");
  15887. +
  15888. + err = dpsw_if_get_link_state(port_priv->ethsw_priv->mc_io, 0,
  15889. + port_priv->ethsw_priv->dpsw_handle,
  15890. + port_priv->port_index,
  15891. + &state);
  15892. + if (err) {
  15893. + netdev_err(netdev, "ERROR %d getting link state", err);
  15894. + goto out;
  15895. + }
  15896. +
  15897. + /* Due to a temporary MC limitation, the DPSW port must be down
  15898. + * in order to be able to change link settings. Taking steps to let
  15899. + * the user know that.
  15900. + */
  15901. + if (netif_running(netdev)) {
  15902. + netdev_info(netdev,
  15903. + "Sorry, interface must be brought down first.\n");
  15904. + return -EACCES;
  15905. + }
  15906. +
  15907. + cfg.options = state.options;
  15908. + cfg.rate = ethtool_cmd_speed(cmd);
  15909. + if (cmd->autoneg == AUTONEG_ENABLE)
  15910. + cfg.options |= DPSW_LINK_OPT_AUTONEG;
  15911. + else
  15912. + cfg.options &= ~DPSW_LINK_OPT_AUTONEG;
  15913. + if (cmd->duplex == DUPLEX_HALF)
  15914. + cfg.options |= DPSW_LINK_OPT_HALF_DUPLEX;
  15915. + else
  15916. + cfg.options &= ~DPSW_LINK_OPT_HALF_DUPLEX;
  15917. +
  15918. + err = dpsw_if_set_link_cfg(port_priv->ethsw_priv->mc_io, 0,
  15919. + port_priv->ethsw_priv->dpsw_handle,
  15920. + port_priv->port_index,
  15921. + &cfg);
  15922. + if (err)
  15923. + /* ethtool will be loud enough if we return an error; no point
  15924. + * in putting our own error message on the console by default
  15925. + */
  15926. + netdev_dbg(netdev, "ERROR %d setting link cfg", err);
  15927. +
  15928. +out:
  15929. + return err;
  15930. +}
  15931. +
  15932. +static struct {
  15933. + enum dpsw_counter id;
  15934. + char name[ETH_GSTRING_LEN];
  15935. +} ethsw_ethtool_counters[] = {
  15936. + {DPSW_CNT_ING_FRAME, "rx frames"},
  15937. + {DPSW_CNT_ING_BYTE, "rx bytes"},
  15938. + {DPSW_CNT_ING_FLTR_FRAME, "rx filtered frames"},
  15939. + {DPSW_CNT_ING_FRAME_DISCARD, "rx discarded frames"},
  15940. + {DPSW_CNT_ING_BCAST_FRAME, "rx b-cast frames"},
  15941. + {DPSW_CNT_ING_BCAST_BYTES, "rx b-cast bytes"},
  15942. + {DPSW_CNT_ING_MCAST_FRAME, "rx m-cast frames"},
  15943. + {DPSW_CNT_ING_MCAST_BYTE, "rx m-cast bytes"},
  15944. + {DPSW_CNT_EGR_FRAME, "tx frames"},
  15945. + {DPSW_CNT_EGR_BYTE, "tx bytes"},
  15946. + {DPSW_CNT_EGR_FRAME_DISCARD, "tx discarded frames"},
  15947. +
  15948. +};
  15949. +
  15950. +static int ethsw_ethtool_get_sset_count(struct net_device *dev, int sset)
  15951. +{
  15952. + switch (sset) {
  15953. + case ETH_SS_STATS:
  15954. + return ARRAY_SIZE(ethsw_ethtool_counters);
  15955. + default:
  15956. + return -EOPNOTSUPP;
  15957. + }
  15958. +}
  15959. +
  15960. +static void ethsw_ethtool_get_strings(struct net_device *netdev,
  15961. + u32 stringset, u8 *data)
  15962. +{
  15963. + u32 i;
  15964. +
  15965. + switch (stringset) {
  15966. + case ETH_SS_STATS:
  15967. + for (i = 0; i < ARRAY_SIZE(ethsw_ethtool_counters); i++)
  15968. + memcpy(data + i * ETH_GSTRING_LEN,
  15969. + ethsw_ethtool_counters[i].name, ETH_GSTRING_LEN);
  15970. + break;
  15971. + }
  15972. +}
  15973. +
  15974. +static void ethsw_ethtool_get_stats(struct net_device *netdev,
  15975. + struct ethtool_stats *stats,
  15976. + u64 *data)
  15977. +{
  15978. + struct ethsw_port_priv *port_priv = netdev_priv(netdev);
  15979. + u32 i;
  15980. + int err;
  15981. +
  15982. + for (i = 0; i < ARRAY_SIZE(ethsw_ethtool_counters); i++) {
  15983. + err = dpsw_if_get_counter(port_priv->ethsw_priv->mc_io, 0,
  15984. + port_priv->ethsw_priv->dpsw_handle,
  15985. + port_priv->port_index,
  15986. + ethsw_ethtool_counters[i].id,
  15987. + &data[i]);
  15988. + if (err)
  15989. + netdev_err(netdev, "dpsw_if_get_counter[%s] err %d\n",
  15990. + ethsw_ethtool_counters[i].name, err);
  15991. + }
  15992. +}
  15993. +
  15994. +static const struct ethtool_ops ethsw_port_ethtool_ops = {
  15995. + .get_drvinfo = &ethsw_get_drvinfo,
  15996. + .get_link = &ethtool_op_get_link,
  15997. + .get_settings = &ethsw_get_settings,
  15998. + .set_settings = &ethsw_set_settings,
  15999. + .get_strings = &ethsw_ethtool_get_strings,
  16000. + .get_ethtool_stats = &ethsw_ethtool_get_stats,
  16001. + .get_sset_count = &ethsw_ethtool_get_sset_count,
  16002. +};
  16003. +
  16004. +/* -------------------------------------------------------------------------- */
  16005. +/* ethsw driver functions */
  16006. +
  16007. +static int ethsw_links_state_update(struct ethsw_dev_priv *priv)
  16008. +{
  16009. + struct list_head *pos;
  16010. + struct ethsw_port_priv *port_priv;
  16011. + int err;
  16012. +
  16013. + list_for_each(pos, &priv->port_list) {
  16014. + port_priv = list_entry(pos, struct ethsw_port_priv,
  16015. + list);
  16016. +
  16017. + err = _ethsw_port_carrier_state_sync(port_priv->netdev);
  16018. + if (err)
  16019. + netdev_err(port_priv->netdev,
  16020. + "_ethsw_port_carrier_state_sync err %d\n",
  16021. + err);
  16022. + }
  16023. +
  16024. + return 0;
  16025. +}
  16026. +
  16027. +static irqreturn_t ethsw_irq0_handler(int irq_num, void *arg)
  16028. +{
  16029. + return IRQ_WAKE_THREAD;
  16030. +}
  16031. +
  16032. +static irqreturn_t _ethsw_irq0_handler_thread(int irq_num, void *arg)
  16033. +{
  16034. + struct device *dev = (struct device *)arg;
  16035. + struct net_device *netdev = dev_get_drvdata(dev);
  16036. + struct ethsw_dev_priv *priv = netdev_priv(netdev);
  16037. +
  16038. + struct fsl_mc_io *io = priv->mc_io;
  16039. + u16 token = priv->dpsw_handle;
  16040. + int irq_index = DPSW_IRQ_INDEX_IF;
  16041. +
  16042. + /* Mask the events and the if_id reserved bits to be cleared on read */
  16043. + u32 status = DPSW_IRQ_EVENT_LINK_CHANGED | 0xFFFF0000;
  16044. + int err;
  16045. +
  16046. + err = dpsw_get_irq_status(io, 0, token, irq_index, &status);
  16047. + if (unlikely(err)) {
  16048. + netdev_err(netdev, "Can't get irq status (err %d)", err);
  16049. +
  16050. + err = dpsw_clear_irq_status(io, 0, token, irq_index,
  16051. + 0xFFFFFFFF);
  16052. + if (unlikely(err))
  16053. + netdev_err(netdev, "Can't clear irq status (err %d)",
  16054. + err);
  16055. + goto out;
  16056. + }
  16057. +
  16058. + if (status & DPSW_IRQ_EVENT_LINK_CHANGED) {
  16059. + err = ethsw_links_state_update(priv);
  16060. + if (unlikely(err))
  16061. + goto out;
  16062. + }
  16063. +
  16064. +out:
  16065. + return IRQ_HANDLED;
  16066. +}
  16067. +
  16068. +static int ethsw_setup_irqs(struct fsl_mc_device *sw_dev)
  16069. +{
  16070. + struct device *dev = &sw_dev->dev;
  16071. + struct net_device *netdev = dev_get_drvdata(dev);
  16072. + struct ethsw_dev_priv *priv = netdev_priv(netdev);
  16073. + int err = 0;
  16074. + struct fsl_mc_device_irq *irq;
  16075. + const int irq_index = DPSW_IRQ_INDEX_IF;
  16076. + u32 mask = DPSW_IRQ_EVENT_LINK_CHANGED;
  16077. +
  16078. + err = fsl_mc_allocate_irqs(sw_dev);
  16079. + if (unlikely(err)) {
  16080. + dev_err(dev, "MC irqs allocation failed\n");
  16081. + return err;
  16082. + }
  16083. +
  16084. + if (WARN_ON(sw_dev->obj_desc.irq_count != DPSW_MAX_IRQ_NUM)) {
  16085. + err = -EINVAL;
  16086. + goto free_irq;
  16087. + }
  16088. +
  16089. + err = dpsw_set_irq_enable(priv->mc_io, 0, priv->dpsw_handle,
  16090. + irq_index, 0);
  16091. + if (unlikely(err)) {
  16092. + dev_err(dev, "dpsw_set_irq_enable err %d\n", err);
  16093. + goto free_irq;
  16094. + }
  16095. +
  16096. + irq = sw_dev->irqs[irq_index];
  16097. +
  16098. + err = devm_request_threaded_irq(dev, irq->msi_desc->irq,
  16099. + ethsw_irq0_handler,
  16100. + _ethsw_irq0_handler_thread,
  16101. + IRQF_NO_SUSPEND | IRQF_ONESHOT,
  16102. + dev_name(dev), dev);
  16103. + if (unlikely(err)) {
  16104. + dev_err(dev, "devm_request_threaded_irq(): %d", err);
  16105. + goto free_irq;
  16106. + }
  16107. +
  16108. + err = dpsw_set_irq_mask(priv->mc_io, 0, priv->dpsw_handle,
  16109. + irq_index, mask);
  16110. + if (unlikely(err)) {
  16111. + dev_err(dev, "dpsw_set_irq_mask(): %d", err);
  16112. + goto free_devm_irq;
  16113. + }
  16114. +
  16115. + err = dpsw_set_irq_enable(priv->mc_io, 0, priv->dpsw_handle,
  16116. + irq_index, 1);
  16117. + if (unlikely(err)) {
  16118. + dev_err(dev, "dpsw_set_irq_enable(): %d", err);
  16119. + goto free_devm_irq;
  16120. + }
  16121. +
  16122. + return 0;
  16123. +
  16124. +free_devm_irq:
  16125. + devm_free_irq(dev, irq->msi_desc->irq, dev);
  16126. +free_irq:
  16127. + fsl_mc_free_irqs(sw_dev);
  16128. + return err;
  16129. +}
  16130. +
  16131. +static void ethsw_teardown_irqs(struct fsl_mc_device *sw_dev)
  16132. +{
  16133. + struct device *dev = &sw_dev->dev;
  16134. + struct net_device *netdev = dev_get_drvdata(dev);
  16135. + struct ethsw_dev_priv *priv = netdev_priv(netdev);
  16136. +
  16137. + dpsw_set_irq_enable(priv->mc_io, 0, priv->dpsw_handle,
  16138. + DPSW_IRQ_INDEX_IF, 0);
  16139. + devm_free_irq(dev,
  16140. + sw_dev->irqs[DPSW_IRQ_INDEX_IF]->msi_desc->irq,
  16141. + dev);
  16142. + fsl_mc_free_irqs(sw_dev);
  16143. +}
  16144. +
  16145. +static int __cold
  16146. +ethsw_init(struct fsl_mc_device *sw_dev)
  16147. +{
  16148. + struct device *dev = &sw_dev->dev;
  16149. + struct ethsw_dev_priv *priv;
  16150. + struct net_device *netdev;
  16151. + int err = 0;
  16152. + u16 i;
  16153. + u16 version_major, version_minor;
  16154. + const struct dpsw_stp_cfg stp_cfg = {
  16155. + .vlan_id = 1,
  16156. + .state = DPSW_STP_STATE_FORWARDING,
  16157. + };
  16158. +
  16159. + netdev = dev_get_drvdata(dev);
  16160. + priv = netdev_priv(netdev);
  16161. +
  16162. + priv->dev_id = sw_dev->obj_desc.id;
  16163. +
  16164. + err = dpsw_open(priv->mc_io, 0, priv->dev_id, &priv->dpsw_handle);
  16165. + if (err) {
  16166. + dev_err(dev, "dpsw_open err %d\n", err);
  16167. + goto err_exit;
  16168. + }
  16169. + if (!priv->dpsw_handle) {
  16170. + dev_err(dev, "dpsw_open returned null handle but no error\n");
  16171. + err = -EFAULT;
  16172. + goto err_exit;
  16173. + }
  16174. +
  16175. + err = dpsw_get_attributes(priv->mc_io, 0, priv->dpsw_handle,
  16176. + &priv->sw_attr);
  16177. + if (err) {
  16178. + dev_err(dev, "dpsw_get_attributes err %d\n", err);
  16179. + goto err_close;
  16180. + }
  16181. +
  16182. + err = dpsw_get_api_version(priv->mc_io, 0,
  16183. + &version_major,
  16184. + &version_minor);
  16185. + if (err) {
  16186. + dev_err(dev, "dpsw_get_api_version err %d\n", err);
  16187. + goto err_close;
  16188. + }
  16189. +
  16190. + /* Minimum supported DPSW version check */
  16191. + if (version_major < DPSW_MIN_VER_MAJOR ||
  16192. + (version_major == DPSW_MIN_VER_MAJOR &&
  16193. + version_minor < DPSW_MIN_VER_MINOR)) {
  16194. + dev_err(dev, "DPSW version %d:%d not supported. Use %d.%d or greater.\n",
  16195. + version_major,
  16196. + version_minor,
  16197. + DPSW_MIN_VER_MAJOR, DPSW_MIN_VER_MINOR);
  16198. + err = -ENOTSUPP;
  16199. + goto err_close;
  16200. + }
  16201. +
  16202. + err = dpsw_reset(priv->mc_io, 0, priv->dpsw_handle);
  16203. + if (err) {
  16204. + dev_err(dev, "dpsw_reset err %d\n", err);
  16205. + goto err_close;
  16206. + }
  16207. +
  16208. + err = dpsw_fdb_set_learning_mode(priv->mc_io, 0, priv->dpsw_handle, 0,
  16209. + DPSW_FDB_LEARNING_MODE_HW);
  16210. + if (err) {
  16211. + dev_err(dev, "dpsw_fdb_set_learning_mode err %d\n", err);
  16212. + goto err_close;
  16213. + }
  16214. +
  16215. + for (i = 0; i < priv->sw_attr.num_ifs; i++) {
  16216. + err = dpsw_if_set_stp(priv->mc_io, 0, priv->dpsw_handle, i,
  16217. + &stp_cfg);
  16218. + if (err) {
  16219. + dev_err(dev, "dpsw_if_set_stp err %d for port %d\n",
  16220. + err, i);
  16221. + goto err_close;
  16222. + }
  16223. +
  16224. + err = dpsw_if_set_broadcast(priv->mc_io, 0,
  16225. + priv->dpsw_handle, i, 1);
  16226. + if (err) {
  16227. + dev_err(dev,
  16228. + "dpsw_if_set_broadcast err %d for port %d\n",
  16229. + err, i);
  16230. + goto err_close;
  16231. + }
  16232. + }
  16233. +
  16234. + return 0;
  16235. +
  16236. +err_close:
  16237. + dpsw_close(priv->mc_io, 0, priv->dpsw_handle);
  16238. +err_exit:
  16239. + return err;
  16240. +}
  16241. +
  16242. +static int __cold
  16243. +ethsw_takedown(struct fsl_mc_device *sw_dev)
  16244. +{
  16245. + struct device *dev = &sw_dev->dev;
  16246. + struct net_device *netdev;
  16247. + struct ethsw_dev_priv *priv;
  16248. + int err;
  16249. +
  16250. + netdev = dev_get_drvdata(dev);
  16251. + priv = netdev_priv(netdev);
  16252. +
  16253. + err = dpsw_close(priv->mc_io, 0, priv->dpsw_handle);
  16254. + if (err)
  16255. + dev_warn(dev, "dpsw_close err %d\n", err);
  16256. +
  16257. + return 0;
  16258. +}
  16259. +
  16260. +static int __cold
  16261. +ethsw_remove(struct fsl_mc_device *sw_dev)
  16262. +{
  16263. + struct device *dev;
  16264. + struct net_device *netdev;
  16265. + struct ethsw_dev_priv *priv;
  16266. + struct ethsw_port_priv *port_priv;
  16267. + struct list_head *pos;
  16268. +
  16269. + dev = &sw_dev->dev;
  16270. + netdev = dev_get_drvdata(dev);
  16271. + priv = netdev_priv(netdev);
  16272. +
  16273. + list_for_each(pos, &priv->port_list) {
  16274. + port_priv = list_entry(pos, struct ethsw_port_priv, list);
  16275. +
  16276. + rtnl_lock();
  16277. + netdev_upper_dev_unlink(port_priv->netdev, netdev);
  16278. + rtnl_unlock();
  16279. +
  16280. + unregister_netdev(port_priv->netdev);
  16281. + free_netdev(port_priv->netdev);
  16282. + }
  16283. +
  16284. + ethsw_teardown_irqs(sw_dev);
  16285. +
  16286. + unregister_netdev(netdev);
  16287. +
  16288. + ethsw_takedown(sw_dev);
  16289. + fsl_mc_portal_free(priv->mc_io);
  16290. +
  16291. + dev_set_drvdata(dev, NULL);
  16292. + free_netdev(netdev);
  16293. +
  16294. + return 0;
  16295. +}
  16296. +
  16297. +static int __cold
  16298. +ethsw_probe(struct fsl_mc_device *sw_dev)
  16299. +{
  16300. + struct device *dev;
  16301. + struct net_device *netdev = NULL;
  16302. + struct ethsw_dev_priv *priv = NULL;
  16303. + int err = 0;
  16304. + u16 i;
  16305. + const char def_mcast[ETH_ALEN] = {
  16306. + 0x01, 0x00, 0x5e, 0x00, 0x00, 0x01,
  16307. + };
  16308. + char port_name[IFNAMSIZ];
  16309. +
  16310. + dev = &sw_dev->dev;
  16311. +
  16312. + /* register switch device, it's for management only - no I/O */
  16313. + netdev = alloc_etherdev(sizeof(*priv));
  16314. + if (!netdev) {
  16315. + dev_err(dev, "alloc_etherdev error\n");
  16316. + return -ENOMEM;
  16317. + }
  16318. + netdev->netdev_ops = &ethsw_ops;
  16319. +
  16320. + SET_NETDEV_DEV(netdev, dev);
  16321. + dev_set_drvdata(dev, netdev);
  16322. +
  16323. + priv = netdev_priv(netdev);
  16324. + priv->netdev = netdev;
  16325. +
  16326. + err = fsl_mc_portal_allocate(sw_dev, 0, &priv->mc_io);
  16327. + if (err) {
  16328. + dev_err(dev, "fsl_mc_portal_allocate err %d\n", err);
  16329. + goto err_free_netdev;
  16330. + }
  16331. + if (!priv->mc_io) {
  16332. + dev_err(dev, "fsl_mc_portal_allocate returned null handle but no error\n");
  16333. + err = -EFAULT;
  16334. + goto err_free_netdev;
  16335. + }
  16336. +
  16337. + err = ethsw_init(sw_dev);
  16338. + if (err) {
  16339. + dev_err(dev, "switch init err %d\n", err);
  16340. + goto err_free_cmdport;
  16341. + }
  16342. +
  16343. + netdev->flags = netdev->flags | IFF_PROMISC | IFF_MASTER;
  16344. +
  16345. + /* TODO: should we hold rtnl_lock here? We can't register_netdev under
  16346. + * lock
  16347. + */
  16348. + dev_alloc_name(netdev, "sw%d");
  16349. + err = register_netdev(netdev);
  16350. + if (err < 0) {
  16351. + dev_err(dev, "register_netdev error %d\n", err);
  16352. + goto err_takedown;
  16353. + }
  16354. + if (err)
  16355. + dev_info(dev, "register_netdev res %d\n", err);
  16356. +
  16357. + /* VLAN 1 is implicitly configured on the switch */
  16358. + priv->vlans[1] = ETHSW_VLAN_MEMBER;
  16359. + /* Flooding, learning are implicitly enabled */
  16360. + priv->learning = true;
  16361. + priv->flood = true;
  16362. +
  16363. + /* register switch ports */
  16364. + snprintf(port_name, IFNAMSIZ, "%sp%%d", netdev->name);
  16365. +
  16366. + INIT_LIST_HEAD(&priv->port_list);
  16367. + for (i = 0; i < priv->sw_attr.num_ifs; i++) {
  16368. + struct net_device *port_netdev;
  16369. + struct ethsw_port_priv *port_priv;
  16370. +
  16371. + port_netdev = alloc_etherdev(sizeof(struct ethsw_port_priv));
  16372. + if (!port_netdev) {
  16373. + dev_err(dev, "alloc_etherdev error\n");
  16374. + goto err_takedown;
  16375. + }
  16376. +
  16377. + port_priv = netdev_priv(port_netdev);
  16378. + port_priv->netdev = port_netdev;
  16379. + port_priv->ethsw_priv = priv;
  16380. +
  16381. + port_priv->port_index = i;
  16382. + port_priv->stp_state = BR_STATE_FORWARDING;
  16383. + /* VLAN 1 is configured by default on all switch ports */
  16384. + port_priv->vlans[1] = ETHSW_VLAN_MEMBER | ETHSW_VLAN_UNTAGGED |
  16385. + ETHSW_VLAN_PVID;
  16386. +
  16387. + SET_NETDEV_DEV(port_netdev, dev);
  16388. + port_netdev->netdev_ops = &ethsw_port_ops;
  16389. + port_netdev->ethtool_ops = &ethsw_port_ethtool_ops;
  16390. +
  16391. + port_netdev->flags = port_netdev->flags |
  16392. + IFF_PROMISC | IFF_SLAVE;
  16393. +
  16394. + dev_alloc_name(port_netdev, port_name);
  16395. + err = register_netdev(port_netdev);
  16396. + if (err < 0) {
  16397. + dev_err(dev, "register_netdev error %d\n", err);
  16398. + free_netdev(port_netdev);
  16399. + goto err_takedown;
  16400. + }
  16401. +
  16402. + rtnl_lock();
  16403. +
  16404. + err = netdev_master_upper_dev_link(port_netdev, netdev,
  16405. + NULL, NULL);
  16406. + if (err) {
  16407. + dev_err(dev, "netdev_master_upper_dev_link error %d\n",
  16408. + err);
  16409. + unregister_netdev(port_netdev);
  16410. + free_netdev(port_netdev);
  16411. + rtnl_unlock();
  16412. + goto err_takedown;
  16413. + }
  16414. +
  16415. + rtmsg_ifinfo(RTM_NEWLINK, port_netdev, IFF_SLAVE, GFP_KERNEL);
  16416. +
  16417. + rtnl_unlock();
  16418. +
  16419. + list_add(&port_priv->list, &priv->port_list);
  16420. +
  16421. + /* TODO: implmenet set_rm_mode instead of this */
  16422. + err = ethsw_port_fdb_add_mc(port_netdev, def_mcast);
  16423. + if (err)
  16424. + dev_warn(&netdev->dev,
  16425. + "ethsw_port_fdb_add_mc err %d\n", err);
  16426. + }
  16427. +
  16428. + /* the switch starts up enabled */
  16429. + rtnl_lock();
  16430. + err = dev_open(netdev);
  16431. + rtnl_unlock();
  16432. + if (err)
  16433. + dev_warn(dev, "dev_open err %d\n", err);
  16434. +
  16435. + /* setup irqs */
  16436. + err = ethsw_setup_irqs(sw_dev);
  16437. + if (unlikely(err)) {
  16438. + dev_warn(dev, "ethsw_setup_irqs err %d\n", err);
  16439. + goto err_takedown;
  16440. + }
  16441. +
  16442. + dev_info(&netdev->dev,
  16443. + "probed %d port switch\n", priv->sw_attr.num_ifs);
  16444. + return 0;
  16445. +
  16446. +err_takedown:
  16447. + ethsw_remove(sw_dev);
  16448. +err_free_cmdport:
  16449. + fsl_mc_portal_free(priv->mc_io);
  16450. +err_free_netdev:
  16451. + dev_set_drvdata(dev, NULL);
  16452. + free_netdev(netdev);
  16453. +
  16454. + return err;
  16455. +}
  16456. +
  16457. +static const struct fsl_mc_device_id ethsw_match_id_table[] = {
  16458. + {
  16459. + .vendor = FSL_MC_VENDOR_FREESCALE,
  16460. + .obj_type = "dpsw",
  16461. + },
  16462. + {}
  16463. +};
  16464. +
  16465. +static struct fsl_mc_driver eth_sw_drv = {
  16466. + .driver = {
  16467. + .name = KBUILD_MODNAME,
  16468. + .owner = THIS_MODULE,
  16469. + },
  16470. + .probe = ethsw_probe,
  16471. + .remove = ethsw_remove,
  16472. + .match_id_table = ethsw_match_id_table,
  16473. +};
  16474. +
  16475. +module_fsl_mc_driver(eth_sw_drv);
  16476. +
  16477. +MODULE_LICENSE("GPL");
  16478. +MODULE_DESCRIPTION("DPAA2 Ethernet Switch Driver (prototype)");
  16479. --- /dev/null
  16480. +++ b/drivers/staging/fsl-dpaa2/evb/Kconfig
  16481. @@ -0,0 +1,7 @@
  16482. +config FSL_DPAA2_EVB
  16483. + tristate "DPAA2 Edge Virtual Bridge"
  16484. + depends on FSL_MC_BUS && FSL_DPAA2
  16485. + select VLAN_8021Q
  16486. + default y
  16487. + ---help---
  16488. + Prototype driver for DPAA2 Edge Virtual Bridge.
  16489. --- /dev/null
  16490. +++ b/drivers/staging/fsl-dpaa2/evb/Makefile
  16491. @@ -0,0 +1,10 @@
  16492. +
  16493. +obj-$(CONFIG_FSL_DPAA2_EVB) += dpaa2-evb.o
  16494. +
  16495. +dpaa2-evb-objs := evb.o dpdmux.o
  16496. +
  16497. +all:
  16498. + make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules
  16499. +
  16500. +clean:
  16501. + make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean
  16502. --- /dev/null
  16503. +++ b/drivers/staging/fsl-dpaa2/evb/dpdmux-cmd.h
  16504. @@ -0,0 +1,279 @@
  16505. +/* Copyright 2013-2016 Freescale Semiconductor Inc.
  16506. + *
  16507. + * Redistribution and use in source and binary forms, with or without
  16508. + * modification, are permitted provided that the following conditions are met:
  16509. + * * Redistributions of source code must retain the above copyright
  16510. + * notice, this list of conditions and the following disclaimer.
  16511. + * * Redistributions in binary form must reproduce the above copyright
  16512. + * notice, this list of conditions and the following disclaimer in the
  16513. + * documentation and/or other materials provided with the distribution.
  16514. + * * Neither the name of the above-listed copyright holders nor the
  16515. + * names of any contributors may be used to endorse or promote products
  16516. + * derived from this software without specific prior written permission.
  16517. + *
  16518. + *
  16519. + * ALTERNATIVELY, this software may be distributed under the terms of the
  16520. + * GNU General Public License ("GPL") as published by the Free Software
  16521. + * Foundation, either version 2 of that License or (at your option) any
  16522. + * later version.
  16523. + *
  16524. + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  16525. + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  16526. + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  16527. + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
  16528. + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  16529. + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  16530. + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  16531. + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  16532. + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  16533. + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  16534. + * POSSIBILITY OF SUCH DAMAGE.
  16535. + */
  16536. +#ifndef _FSL_DPDMUX_CMD_H
  16537. +#define _FSL_DPDMUX_CMD_H
  16538. +
  16539. +/* DPDMUX Version */
  16540. +#define DPDMUX_VER_MAJOR 6
  16541. +#define DPDMUX_VER_MINOR 1
  16542. +
  16543. +#define DPDMUX_CMD_BASE_VER 1
  16544. +#define DPDMUX_CMD_ID_OFFSET 4
  16545. +
  16546. +#define DPDMUX_CMD(id) (((id) << DPDMUX_CMD_ID_OFFSET) | DPDMUX_CMD_BASE_VER)
  16547. +
  16548. +/* Command IDs */
  16549. +#define DPDMUX_CMDID_CLOSE DPDMUX_CMD(0x800)
  16550. +#define DPDMUX_CMDID_OPEN DPDMUX_CMD(0x806)
  16551. +#define DPDMUX_CMDID_CREATE DPDMUX_CMD(0x906)
  16552. +#define DPDMUX_CMDID_DESTROY DPDMUX_CMD(0x986)
  16553. +#define DPDMUX_CMDID_GET_API_VERSION DPDMUX_CMD(0xa06)
  16554. +
  16555. +#define DPDMUX_CMDID_ENABLE DPDMUX_CMD(0x002)
  16556. +#define DPDMUX_CMDID_DISABLE DPDMUX_CMD(0x003)
  16557. +#define DPDMUX_CMDID_GET_ATTR DPDMUX_CMD(0x004)
  16558. +#define DPDMUX_CMDID_RESET DPDMUX_CMD(0x005)
  16559. +#define DPDMUX_CMDID_IS_ENABLED DPDMUX_CMD(0x006)
  16560. +
  16561. +#define DPDMUX_CMDID_SET_IRQ_ENABLE DPDMUX_CMD(0x012)
  16562. +#define DPDMUX_CMDID_GET_IRQ_ENABLE DPDMUX_CMD(0x013)
  16563. +#define DPDMUX_CMDID_SET_IRQ_MASK DPDMUX_CMD(0x014)
  16564. +#define DPDMUX_CMDID_GET_IRQ_MASK DPDMUX_CMD(0x015)
  16565. +#define DPDMUX_CMDID_GET_IRQ_STATUS DPDMUX_CMD(0x016)
  16566. +#define DPDMUX_CMDID_CLEAR_IRQ_STATUS DPDMUX_CMD(0x017)
  16567. +
  16568. +#define DPDMUX_CMDID_SET_MAX_FRAME_LENGTH DPDMUX_CMD(0x0a1)
  16569. +
  16570. +#define DPDMUX_CMDID_UL_RESET_COUNTERS DPDMUX_CMD(0x0a3)
  16571. +
  16572. +#define DPDMUX_CMDID_IF_SET_ACCEPTED_FRAMES DPDMUX_CMD(0x0a7)
  16573. +#define DPDMUX_CMDID_IF_GET_ATTR DPDMUX_CMD(0x0a8)
  16574. +#define DPDMUX_CMDID_IF_ENABLE DPDMUX_CMD(0x0a9)
  16575. +#define DPDMUX_CMDID_IF_DISABLE DPDMUX_CMD(0x0aa)
  16576. +
  16577. +#define DPDMUX_CMDID_IF_ADD_L2_RULE DPDMUX_CMD(0x0b0)
  16578. +#define DPDMUX_CMDID_IF_REMOVE_L2_RULE DPDMUX_CMD(0x0b1)
  16579. +#define DPDMUX_CMDID_IF_GET_COUNTER DPDMUX_CMD(0x0b2)
  16580. +#define DPDMUX_CMDID_IF_SET_LINK_CFG DPDMUX_CMD(0x0b3)
  16581. +#define DPDMUX_CMDID_IF_GET_LINK_STATE DPDMUX_CMD(0x0b4)
  16582. +
  16583. +#define DPDMUX_CMDID_SET_CUSTOM_KEY DPDMUX_CMD(0x0b5)
  16584. +#define DPDMUX_CMDID_ADD_CUSTOM_CLS_ENTRY DPDMUX_CMD(0x0b6)
  16585. +#define DPDMUX_CMDID_REMOVE_CUSTOM_CLS_ENTRY DPDMUX_CMD(0x0b7)
  16586. +
  16587. +#define DPDMUX_MASK(field) \
  16588. + GENMASK(DPDMUX_##field##_SHIFT + DPDMUX_##field##_SIZE - 1, \
  16589. + DPDMUX_##field##_SHIFT)
  16590. +#define dpdmux_set_field(var, field, val) \
  16591. + ((var) |= (((val) << DPDMUX_##field##_SHIFT) & DPDMUX_MASK(field)))
  16592. +#define dpdmux_get_field(var, field) \
  16593. + (((var) & DPDMUX_MASK(field)) >> DPDMUX_##field##_SHIFT)
  16594. +
  16595. +struct dpdmux_cmd_open {
  16596. + u32 dpdmux_id;
  16597. +};
  16598. +
  16599. +struct dpdmux_cmd_create {
  16600. + u8 method;
  16601. + u8 manip;
  16602. + u16 num_ifs;
  16603. + u32 pad;
  16604. +
  16605. + u16 adv_max_dmat_entries;
  16606. + u16 adv_max_mc_groups;
  16607. + u16 adv_max_vlan_ids;
  16608. + u16 pad1;
  16609. +
  16610. + u64 options;
  16611. +};
  16612. +
  16613. +struct dpdmux_cmd_destroy {
  16614. + u32 dpdmux_id;
  16615. +};
  16616. +
  16617. +#define DPDMUX_ENABLE_SHIFT 0
  16618. +#define DPDMUX_ENABLE_SIZE 1
  16619. +
  16620. +struct dpdmux_rsp_is_enabled {
  16621. + u8 en;
  16622. +};
  16623. +
  16624. +struct dpdmux_cmd_set_irq_enable {
  16625. + u8 enable;
  16626. + u8 pad[3];
  16627. + u8 irq_index;
  16628. +};
  16629. +
  16630. +struct dpdmux_cmd_get_irq_enable {
  16631. + u32 pad;
  16632. + u8 irq_index;
  16633. +};
  16634. +
  16635. +struct dpdmux_rsp_get_irq_enable {
  16636. + u8 enable;
  16637. +};
  16638. +
  16639. +struct dpdmux_cmd_set_irq_mask {
  16640. + u32 mask;
  16641. + u8 irq_index;
  16642. +};
  16643. +
  16644. +struct dpdmux_cmd_get_irq_mask {
  16645. + u32 pad;
  16646. + u8 irq_index;
  16647. +};
  16648. +
  16649. +struct dpdmux_rsp_get_irq_mask {
  16650. + u32 mask;
  16651. +};
  16652. +
  16653. +struct dpdmux_cmd_get_irq_status {
  16654. + u32 status;
  16655. + u8 irq_index;
  16656. +};
  16657. +
  16658. +struct dpdmux_rsp_get_irq_status {
  16659. + u32 status;
  16660. +};
  16661. +
  16662. +struct dpdmux_cmd_clear_irq_status {
  16663. + u32 status;
  16664. + u8 irq_index;
  16665. +};
  16666. +
  16667. +struct dpdmux_rsp_get_attr {
  16668. + u8 method;
  16669. + u8 manip;
  16670. + u16 num_ifs;
  16671. + u16 mem_size;
  16672. + u16 pad;
  16673. +
  16674. + u64 pad1;
  16675. +
  16676. + u32 id;
  16677. + u32 pad2;
  16678. +
  16679. + u64 options;
  16680. +};
  16681. +
  16682. +struct dpdmux_cmd_set_max_frame_length {
  16683. + u16 max_frame_length;
  16684. +};
  16685. +
  16686. +#define DPDMUX_ACCEPTED_FRAMES_TYPE_SHIFT 0
  16687. +#define DPDMUX_ACCEPTED_FRAMES_TYPE_SIZE 4
  16688. +#define DPDMUX_UNACCEPTED_FRAMES_ACTION_SHIFT 4
  16689. +#define DPDMUX_UNACCEPTED_FRAMES_ACTION_SIZE 4
  16690. +
  16691. +struct dpdmux_cmd_if_set_accepted_frames {
  16692. + u16 if_id;
  16693. + u8 frames_options;
  16694. +};
  16695. +
  16696. +struct dpdmux_cmd_if {
  16697. + u16 if_id;
  16698. +};
  16699. +
  16700. +struct dpdmux_rsp_if_get_attr {
  16701. + u8 pad[3];
  16702. + u8 enabled;
  16703. + u8 pad1[3];
  16704. + u8 accepted_frames_type;
  16705. + u32 rate;
  16706. +};
  16707. +
  16708. +struct dpdmux_cmd_if_l2_rule {
  16709. + u16 if_id;
  16710. + u8 mac_addr5;
  16711. + u8 mac_addr4;
  16712. + u8 mac_addr3;
  16713. + u8 mac_addr2;
  16714. + u8 mac_addr1;
  16715. + u8 mac_addr0;
  16716. +
  16717. + u32 pad;
  16718. + u16 vlan_id;
  16719. +};
  16720. +
  16721. +struct dpdmux_cmd_if_get_counter {
  16722. + u16 if_id;
  16723. + u8 counter_type;
  16724. +};
  16725. +
  16726. +struct dpdmux_rsp_if_get_counter {
  16727. + u64 pad;
  16728. + u64 counter;
  16729. +};
  16730. +
  16731. +struct dpdmux_cmd_if_set_link_cfg {
  16732. + u16 if_id;
  16733. + u16 pad[3];
  16734. +
  16735. + u32 rate;
  16736. + u32 pad1;
  16737. +
  16738. + u64 options;
  16739. +};
  16740. +
  16741. +struct dpdmux_cmd_if_get_link_state {
  16742. + u16 if_id;
  16743. +};
  16744. +
  16745. +struct dpdmux_rsp_if_get_link_state {
  16746. + u32 pad;
  16747. + u8 up;
  16748. + u8 pad1[3];
  16749. +
  16750. + u32 rate;
  16751. + u32 pad2;
  16752. +
  16753. + u64 options;
  16754. +};
  16755. +
  16756. +struct dpdmux_rsp_get_api_version {
  16757. + u16 major;
  16758. + u16 minor;
  16759. +};
  16760. +
  16761. +struct dpdmux_set_custom_key {
  16762. + u64 pad[6];
  16763. + u64 key_cfg_iova;
  16764. +};
  16765. +
  16766. +struct dpdmux_cmd_add_custom_cls_entry {
  16767. + u8 pad[3];
  16768. + u8 key_size;
  16769. + u16 pad1;
  16770. + u16 dest_if;
  16771. + u64 key_iova;
  16772. + u64 mask_iova;
  16773. +};
  16774. +
  16775. +struct dpdmux_cmd_remove_custom_cls_entry {
  16776. + u8 pad[3];
  16777. + u8 key_size;
  16778. + u32 pad1;
  16779. + u64 key_iova;
  16780. + u64 mask_iova;
  16781. +};
  16782. +
  16783. +#endif /* _FSL_DPDMUX_CMD_H */
  16784. --- /dev/null
  16785. +++ b/drivers/staging/fsl-dpaa2/evb/dpdmux.c
  16786. @@ -0,0 +1,1112 @@
  16787. +/* Copyright 2013-2016 Freescale Semiconductor Inc.
  16788. + *
  16789. + * Redistribution and use in source and binary forms, with or without
  16790. + * modification, are permitted provided that the following conditions are met:
  16791. + * * Redistributions of source code must retain the above copyright
  16792. + * notice, this list of conditions and the following disclaimer.
  16793. + * * Redistributions in binary form must reproduce the above copyright
  16794. + * notice, this list of conditions and the following disclaimer in the
  16795. + * documentation and/or other materials provided with the distribution.
  16796. + * * Neither the name of the above-listed copyright holders nor the
  16797. + * names of any contributors may be used to endorse or promote products
  16798. + * derived from this software without specific prior written permission.
  16799. + *
  16800. + *
  16801. + * ALTERNATIVELY, this software may be distributed under the terms of the
  16802. + * GNU General Public License ("GPL") as published by the Free Software
  16803. + * Foundation, either version 2 of that License or (at your option) any
  16804. + * later version.
  16805. + *
  16806. + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  16807. + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  16808. + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  16809. + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
  16810. + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  16811. + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  16812. + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  16813. + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  16814. + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  16815. + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  16816. + * POSSIBILITY OF SUCH DAMAGE.
  16817. + */
  16818. +#include "../../fsl-mc/include/mc-sys.h"
  16819. +#include "../../fsl-mc/include/mc-cmd.h"
  16820. +#include "dpdmux.h"
  16821. +#include "dpdmux-cmd.h"
  16822. +
  16823. +/**
  16824. + * dpdmux_open() - Open a control session for the specified object
  16825. + * @mc_io: Pointer to MC portal's I/O object
  16826. + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
  16827. + * @dpdmux_id: DPDMUX unique ID
  16828. + * @token: Returned token; use in subsequent API calls
  16829. + *
  16830. + * This function can be used to open a control session for an
  16831. + * already created object; an object may have been declared in
  16832. + * the DPL or by calling the dpdmux_create() function.
  16833. + * This function returns a unique authentication token,
  16834. + * associated with the specific object ID and the specific MC
  16835. + * portal; this token must be used in all subsequent commands for
  16836. + * this specific object.
  16837. + *
  16838. + * Return: '0' on Success; Error code otherwise.
  16839. + */
  16840. +int dpdmux_open(struct fsl_mc_io *mc_io,
  16841. + u32 cmd_flags,
  16842. + int dpdmux_id,
  16843. + u16 *token)
  16844. +{
  16845. + struct mc_command cmd = { 0 };
  16846. + struct dpdmux_cmd_open *cmd_params;
  16847. + int err;
  16848. +
  16849. + /* prepare command */
  16850. + cmd.header = mc_encode_cmd_header(DPDMUX_CMDID_OPEN,
  16851. + cmd_flags,
  16852. + 0);
  16853. + cmd_params = (struct dpdmux_cmd_open *)cmd.params;
  16854. + cmd_params->dpdmux_id = cpu_to_le32(dpdmux_id);
  16855. +
  16856. + /* send command to mc*/
  16857. + err = mc_send_command(mc_io, &cmd);
  16858. + if (err)
  16859. + return err;
  16860. +
  16861. + /* retrieve response parameters */
  16862. + *token = mc_cmd_hdr_read_token(&cmd);
  16863. +
  16864. + return 0;
  16865. +}
  16866. +
  16867. +/**
  16868. + * dpdmux_close() - Close the control session of the object
  16869. + * @mc_io: Pointer to MC portal's I/O object
  16870. + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
  16871. + * @token: Token of DPDMUX object
  16872. + *
  16873. + * After this function is called, no further operations are
  16874. + * allowed on the object without opening a new control session.
  16875. + *
  16876. + * Return: '0' on Success; Error code otherwise.
  16877. + */
  16878. +int dpdmux_close(struct fsl_mc_io *mc_io,
  16879. + u32 cmd_flags,
  16880. + u16 token)
  16881. +{
  16882. + struct mc_command cmd = { 0 };
  16883. +
  16884. + /* prepare command */
  16885. + cmd.header = mc_encode_cmd_header(DPDMUX_CMDID_CLOSE,
  16886. + cmd_flags,
  16887. + token);
  16888. +
  16889. + /* send command to mc*/
  16890. + return mc_send_command(mc_io, &cmd);
  16891. +}
  16892. +
  16893. +/**
  16894. + * dpdmux_create() - Create the DPDMUX object
  16895. + * @mc_io: Pointer to MC portal's I/O object
  16896. + * @dprc_token: Parent container token; '0' for default container
  16897. + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
  16898. + * @cfg: Configuration structure
  16899. + * @obj_id: returned object id
  16900. + *
  16901. + * Create the DPDMUX object, allocate required resources and
  16902. + * perform required initialization.
  16903. + *
  16904. + * The object can be created either by declaring it in the
  16905. + * DPL file, or by calling this function.
  16906. + *
  16907. + * The function accepts an authentication token of a parent
  16908. + * container that this object should be assigned to. The token
  16909. + * can be '0' so the object will be assigned to the default container.
  16910. + * The newly created object can be opened with the returned
  16911. + * object id and using the container's associated tokens and MC portals.
  16912. + *
  16913. + * Return: '0' on Success; Error code otherwise.
  16914. + */
  16915. +int dpdmux_create(struct fsl_mc_io *mc_io,
  16916. + u16 dprc_token,
  16917. + u32 cmd_flags,
  16918. + const struct dpdmux_cfg *cfg,
  16919. + u32 *obj_id)
  16920. +{
  16921. + struct mc_command cmd = { 0 };
  16922. + struct dpdmux_cmd_create *cmd_params;
  16923. + int err;
  16924. +
  16925. + /* prepare command */
  16926. + cmd.header = mc_encode_cmd_header(DPDMUX_CMDID_CREATE,
  16927. + cmd_flags,
  16928. + dprc_token);
  16929. + cmd_params = (struct dpdmux_cmd_create *)cmd.params;
  16930. + cmd_params->method = cfg->method;
  16931. + cmd_params->manip = cfg->manip;
  16932. + cmd_params->num_ifs = cpu_to_le16(cfg->num_ifs);
  16933. + cmd_params->adv_max_dmat_entries =
  16934. + cpu_to_le16(cfg->adv.max_dmat_entries);
  16935. + cmd_params->adv_max_mc_groups = cpu_to_le16(cfg->adv.max_mc_groups);
  16936. + cmd_params->adv_max_vlan_ids = cpu_to_le16(cfg->adv.max_vlan_ids);
  16937. + cmd_params->options = cpu_to_le64(cfg->adv.options);
  16938. +
  16939. + /* send command to mc*/
  16940. + err = mc_send_command(mc_io, &cmd);
  16941. + if (err)
  16942. + return err;
  16943. +
  16944. + /* retrieve response parameters */
  16945. + *obj_id = mc_cmd_hdr_read_token(&cmd);
  16946. +
  16947. + return 0;
  16948. +}
  16949. +
  16950. +/**
  16951. + * dpdmux_destroy() - Destroy the DPDMUX object and release all its resources.
  16952. + * @mc_io: Pointer to MC portal's I/O object
  16953. + * @dprc_token: Parent container token; '0' for default container
  16954. + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
  16955. + * @object_id: The object id; it must be a valid id within the container that
  16956. + * created this object;
  16957. + *
  16958. + * The function accepts the authentication token of the parent container that
  16959. + * created the object (not the one that currently owns the object). The object
  16960. + * is searched within parent using the provided 'object_id'.
  16961. + * All tokens to the object must be closed before calling destroy.
  16962. + *
  16963. + * Return: '0' on Success; error code otherwise.
  16964. + */
  16965. +int dpdmux_destroy(struct fsl_mc_io *mc_io,
  16966. + u16 dprc_token,
  16967. + u32 cmd_flags,
  16968. + u32 object_id)
  16969. +{
  16970. + struct mc_command cmd = { 0 };
  16971. + struct dpdmux_cmd_destroy *cmd_params;
  16972. +
  16973. + /* prepare command */
  16974. + cmd.header = mc_encode_cmd_header(DPDMUX_CMDID_DESTROY,
  16975. + cmd_flags,
  16976. + dprc_token);
  16977. + cmd_params = (struct dpdmux_cmd_destroy *)cmd.params;
  16978. + cmd_params->dpdmux_id = cpu_to_le32(object_id);
  16979. +
  16980. + /* send command to mc*/
  16981. + return mc_send_command(mc_io, &cmd);
  16982. +}
  16983. +
  16984. +/**
  16985. + * dpdmux_enable() - Enable DPDMUX functionality
  16986. + * @mc_io: Pointer to MC portal's I/O object
  16987. + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
  16988. + * @token: Token of DPDMUX object
  16989. + *
  16990. + * Return: '0' on Success; Error code otherwise.
  16991. + */
  16992. +int dpdmux_enable(struct fsl_mc_io *mc_io,
  16993. + u32 cmd_flags,
  16994. + u16 token)
  16995. +{
  16996. + struct mc_command cmd = { 0 };
  16997. +
  16998. + /* prepare command */
  16999. + cmd.header = mc_encode_cmd_header(DPDMUX_CMDID_ENABLE,
  17000. + cmd_flags,
  17001. + token);
  17002. +
  17003. + /* send command to mc*/
  17004. + return mc_send_command(mc_io, &cmd);
  17005. +}
  17006. +
  17007. +/**
  17008. + * dpdmux_disable() - Disable DPDMUX functionality
  17009. + * @mc_io: Pointer to MC portal's I/O object
  17010. + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
  17011. + * @token: Token of DPDMUX object
  17012. + *
  17013. + * Return: '0' on Success; Error code otherwise.
  17014. + */
  17015. +int dpdmux_disable(struct fsl_mc_io *mc_io,
  17016. + u32 cmd_flags,
  17017. + u16 token)
  17018. +{
  17019. + struct mc_command cmd = { 0 };
  17020. +
  17021. + /* prepare command */
  17022. + cmd.header = mc_encode_cmd_header(DPDMUX_CMDID_DISABLE,
  17023. + cmd_flags,
  17024. + token);
  17025. +
  17026. + /* send command to mc*/
  17027. + return mc_send_command(mc_io, &cmd);
  17028. +}
  17029. +
  17030. +/**
  17031. + * dpdmux_is_enabled() - Check if the DPDMUX is enabled.
  17032. + * @mc_io: Pointer to MC portal's I/O object
  17033. + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
  17034. + * @token: Token of DPDMUX object
  17035. + * @en: Returns '1' if object is enabled; '0' otherwise
  17036. + *
  17037. + * Return: '0' on Success; Error code otherwise.
  17038. + */
  17039. +int dpdmux_is_enabled(struct fsl_mc_io *mc_io,
  17040. + u32 cmd_flags,
  17041. + u16 token,
  17042. + int *en)
  17043. +{
  17044. + struct mc_command cmd = { 0 };
  17045. + struct dpdmux_rsp_is_enabled *rsp_params;
  17046. + int err;
  17047. +
  17048. + /* prepare command */
  17049. + cmd.header = mc_encode_cmd_header(DPDMUX_CMDID_IS_ENABLED,
  17050. + cmd_flags,
  17051. + token);
  17052. +
  17053. + /* send command to mc*/
  17054. + err = mc_send_command(mc_io, &cmd);
  17055. + if (err)
  17056. + return err;
  17057. +
  17058. + /* retrieve response parameters */
  17059. + rsp_params = (struct dpdmux_rsp_is_enabled *)cmd.params;
  17060. + *en = dpdmux_get_field(rsp_params->en, ENABLE);
  17061. +
  17062. + return 0;
  17063. +}
  17064. +
  17065. +/**
  17066. + * dpdmux_reset() - Reset the DPDMUX, returns the object to initial state.
  17067. + * @mc_io: Pointer to MC portal's I/O object
  17068. + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
  17069. + * @token: Token of DPDMUX object
  17070. + *
  17071. + * Return: '0' on Success; Error code otherwise.
  17072. + */
  17073. +int dpdmux_reset(struct fsl_mc_io *mc_io,
  17074. + u32 cmd_flags,
  17075. + u16 token)
  17076. +{
  17077. + struct mc_command cmd = { 0 };
  17078. +
  17079. + /* prepare command */
  17080. + cmd.header = mc_encode_cmd_header(DPDMUX_CMDID_RESET,
  17081. + cmd_flags,
  17082. + token);
  17083. +
  17084. + /* send command to mc*/
  17085. + return mc_send_command(mc_io, &cmd);
  17086. +}
  17087. +
  17088. +/**
  17089. + * dpdmux_set_irq_enable() - Set overall interrupt state.
  17090. + * @mc_io: Pointer to MC portal's I/O object
  17091. + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
  17092. + * @token: Token of DPDMUX object
  17093. + * @irq_index: The interrupt index to configure
  17094. + * @en: Interrupt state - enable = 1, disable = 0
  17095. + *
  17096. + * Allows GPP software to control when interrupts are generated.
  17097. + * Each interrupt can have up to 32 causes. The enable/disable control's the
  17098. + * overall interrupt state. if the interrupt is disabled no causes will cause
  17099. + * an interrupt.
  17100. + *
  17101. + * Return: '0' on Success; Error code otherwise.
  17102. + */
  17103. +int dpdmux_set_irq_enable(struct fsl_mc_io *mc_io,
  17104. + u32 cmd_flags,
  17105. + u16 token,
  17106. + u8 irq_index,
  17107. + u8 en)
  17108. +{
  17109. + struct mc_command cmd = { 0 };
  17110. + struct dpdmux_cmd_set_irq_enable *cmd_params;
  17111. +
  17112. + /* prepare command */
  17113. + cmd.header = mc_encode_cmd_header(DPDMUX_CMDID_SET_IRQ_ENABLE,
  17114. + cmd_flags,
  17115. + token);
  17116. + cmd_params = (struct dpdmux_cmd_set_irq_enable *)cmd.params;
  17117. + cmd_params->enable = en;
  17118. + cmd_params->irq_index = irq_index;
  17119. +
  17120. + /* send command to mc*/
  17121. + return mc_send_command(mc_io, &cmd);
  17122. +}
  17123. +
  17124. +/**
  17125. + * dpdmux_get_irq_enable() - Get overall interrupt state.
  17126. + * @mc_io: Pointer to MC portal's I/O object
  17127. + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
  17128. + * @token: Token of DPDMUX object
  17129. + * @irq_index: The interrupt index to configure
  17130. + * @en: Returned interrupt state - enable = 1, disable = 0
  17131. + *
  17132. + * Return: '0' on Success; Error code otherwise.
  17133. + */
  17134. +int dpdmux_get_irq_enable(struct fsl_mc_io *mc_io,
  17135. + u32 cmd_flags,
  17136. + u16 token,
  17137. + u8 irq_index,
  17138. + u8 *en)
  17139. +{
  17140. + struct mc_command cmd = { 0 };
  17141. + struct dpdmux_cmd_get_irq_enable *cmd_params;
  17142. + struct dpdmux_rsp_get_irq_enable *rsp_params;
  17143. + int err;
  17144. +
  17145. + /* prepare command */
  17146. + cmd.header = mc_encode_cmd_header(DPDMUX_CMDID_GET_IRQ_ENABLE,
  17147. + cmd_flags,
  17148. + token);
  17149. + cmd_params = (struct dpdmux_cmd_get_irq_enable *)cmd.params;
  17150. + cmd_params->irq_index = irq_index;
  17151. +
  17152. + /* send command to mc*/
  17153. + err = mc_send_command(mc_io, &cmd);
  17154. + if (err)
  17155. + return err;
  17156. +
  17157. + /* retrieve response parameters */
  17158. + rsp_params = (struct dpdmux_rsp_get_irq_enable *)cmd.params;
  17159. + *en = rsp_params->enable;
  17160. +
  17161. + return 0;
  17162. +}
  17163. +
  17164. +/**
  17165. + * dpdmux_set_irq_mask() - Set interrupt mask.
  17166. + * @mc_io: Pointer to MC portal's I/O object
  17167. + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
  17168. + * @token: Token of DPDMUX object
  17169. + * @irq_index: The interrupt index to configure
  17170. + * @mask: event mask to trigger interrupt;
  17171. + * each bit:
  17172. + * 0 = ignore event
  17173. + * 1 = consider event for asserting IRQ
  17174. + *
  17175. + * Every interrupt can have up to 32 causes and the interrupt model supports
  17176. + * masking/unmasking each cause independently
  17177. + *
  17178. + * Return: '0' on Success; Error code otherwise.
  17179. + */
  17180. +int dpdmux_set_irq_mask(struct fsl_mc_io *mc_io,
  17181. + u32 cmd_flags,
  17182. + u16 token,
  17183. + u8 irq_index,
  17184. + u32 mask)
  17185. +{
  17186. + struct mc_command cmd = { 0 };
  17187. + struct dpdmux_cmd_set_irq_mask *cmd_params;
  17188. +
  17189. + /* prepare command */
  17190. + cmd.header = mc_encode_cmd_header(DPDMUX_CMDID_SET_IRQ_MASK,
  17191. + cmd_flags,
  17192. + token);
  17193. + cmd_params = (struct dpdmux_cmd_set_irq_mask *)cmd.params;
  17194. + cmd_params->mask = cpu_to_le32(mask);
  17195. + cmd_params->irq_index = irq_index;
  17196. +
  17197. + /* send command to mc*/
  17198. + return mc_send_command(mc_io, &cmd);
  17199. +}
  17200. +
  17201. +/**
  17202. + * dpdmux_get_irq_mask() - Get interrupt mask.
  17203. + * @mc_io: Pointer to MC portal's I/O object
  17204. + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
  17205. + * @token: Token of DPDMUX object
  17206. + * @irq_index: The interrupt index to configure
  17207. + * @mask: Returned event mask to trigger interrupt
  17208. + *
  17209. + * Every interrupt can have up to 32 causes and the interrupt model supports
  17210. + * masking/unmasking each cause independently
  17211. + *
  17212. + * Return: '0' on Success; Error code otherwise.
  17213. + */
  17214. +int dpdmux_get_irq_mask(struct fsl_mc_io *mc_io,
  17215. + u32 cmd_flags,
  17216. + u16 token,
  17217. + u8 irq_index,
  17218. + u32 *mask)
  17219. +{
  17220. + struct mc_command cmd = { 0 };
  17221. + struct dpdmux_cmd_get_irq_mask *cmd_params;
  17222. + struct dpdmux_rsp_get_irq_mask *rsp_params;
  17223. + int err;
  17224. +
  17225. + /* prepare command */
  17226. + cmd.header = mc_encode_cmd_header(DPDMUX_CMDID_GET_IRQ_MASK,
  17227. + cmd_flags,
  17228. + token);
  17229. + cmd_params = (struct dpdmux_cmd_get_irq_mask *)cmd.params;
  17230. + cmd_params->irq_index = irq_index;
  17231. +
  17232. + /* send command to mc*/
  17233. + err = mc_send_command(mc_io, &cmd);
  17234. + if (err)
  17235. + return err;
  17236. +
  17237. + /* retrieve response parameters */
  17238. + rsp_params = (struct dpdmux_rsp_get_irq_mask *)cmd.params;
  17239. + *mask = le32_to_cpu(rsp_params->mask);
  17240. +
  17241. + return 0;
  17242. +}
  17243. +
  17244. +/**
  17245. + * dpdmux_get_irq_status() - Get the current status of any pending interrupts.
  17246. + * @mc_io: Pointer to MC portal's I/O object
  17247. + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
  17248. + * @token: Token of DPDMUX object
  17249. + * @irq_index: The interrupt index to configure
  17250. + * @status: Returned interrupts status - one bit per cause:
  17251. + * 0 = no interrupt pending
  17252. + * 1 = interrupt pending
  17253. + *
  17254. + * Return: '0' on Success; Error code otherwise.
  17255. + */
  17256. +int dpdmux_get_irq_status(struct fsl_mc_io *mc_io,
  17257. + u32 cmd_flags,
  17258. + u16 token,
  17259. + u8 irq_index,
  17260. + u32 *status)
  17261. +{
  17262. + struct mc_command cmd = { 0 };
  17263. + struct dpdmux_cmd_get_irq_status *cmd_params;
  17264. + struct dpdmux_rsp_get_irq_status *rsp_params;
  17265. + int err;
  17266. +
  17267. + /* prepare command */
  17268. + cmd.header = mc_encode_cmd_header(DPDMUX_CMDID_GET_IRQ_STATUS,
  17269. + cmd_flags,
  17270. + token);
  17271. + cmd_params = (struct dpdmux_cmd_get_irq_status *)cmd.params;
  17272. + cmd_params->status = cpu_to_le32(*status);
  17273. + cmd_params->irq_index = irq_index;
  17274. +
  17275. + /* send command to mc*/
  17276. + err = mc_send_command(mc_io, &cmd);
  17277. + if (err)
  17278. + return err;
  17279. +
  17280. + /* retrieve response parameters */
  17281. + rsp_params = (struct dpdmux_rsp_get_irq_status *)cmd.params;
  17282. + *status = le32_to_cpu(rsp_params->status);
  17283. +
  17284. + return 0;
  17285. +}
  17286. +
  17287. +/**
  17288. + * dpdmux_clear_irq_status() - Clear a pending interrupt's status
  17289. + * @mc_io: Pointer to MC portal's I/O object
  17290. + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
  17291. + * @token: Token of DPDMUX object
  17292. + * @irq_index: The interrupt index to configure
  17293. + * @status: bits to clear (W1C) - one bit per cause:
  17294. + * 0 = don't change
  17295. + * 1 = clear status bit
  17296. + *
  17297. + * Return: '0' on Success; Error code otherwise.
  17298. + */
  17299. +int dpdmux_clear_irq_status(struct fsl_mc_io *mc_io,
  17300. + u32 cmd_flags,
  17301. + u16 token,
  17302. + u8 irq_index,
  17303. + u32 status)
  17304. +{
  17305. + struct mc_command cmd = { 0 };
  17306. + struct dpdmux_cmd_clear_irq_status *cmd_params;
  17307. +
  17308. + /* prepare command */
  17309. + cmd.header = mc_encode_cmd_header(DPDMUX_CMDID_CLEAR_IRQ_STATUS,
  17310. + cmd_flags,
  17311. + token);
  17312. + cmd_params = (struct dpdmux_cmd_clear_irq_status *)cmd.params;
  17313. + cmd_params->status = cpu_to_le32(status);
  17314. + cmd_params->irq_index = irq_index;
  17315. +
  17316. + /* send command to mc*/
  17317. + return mc_send_command(mc_io, &cmd);
  17318. +}
  17319. +
  17320. +/**
  17321. + * dpdmux_get_attributes() - Retrieve DPDMUX attributes
  17322. + * @mc_io: Pointer to MC portal's I/O object
  17323. + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
  17324. + * @token: Token of DPDMUX object
  17325. + * @attr: Returned object's attributes
  17326. + *
  17327. + * Return: '0' on Success; Error code otherwise.
  17328. + */
  17329. +int dpdmux_get_attributes(struct fsl_mc_io *mc_io,
  17330. + u32 cmd_flags,
  17331. + u16 token,
  17332. + struct dpdmux_attr *attr)
  17333. +{
  17334. + struct mc_command cmd = { 0 };
  17335. + struct dpdmux_rsp_get_attr *rsp_params;
  17336. + int err;
  17337. +
  17338. + /* prepare command */
  17339. + cmd.header = mc_encode_cmd_header(DPDMUX_CMDID_GET_ATTR,
  17340. + cmd_flags,
  17341. + token);
  17342. +
  17343. + /* send command to mc*/
  17344. + err = mc_send_command(mc_io, &cmd);
  17345. + if (err)
  17346. + return err;
  17347. +
  17348. + /* retrieve response parameters */
  17349. + rsp_params = (struct dpdmux_rsp_get_attr *)cmd.params;
  17350. + attr->id = le32_to_cpu(rsp_params->id);
  17351. + attr->options = le64_to_cpu(rsp_params->options);
  17352. + attr->method = rsp_params->method;
  17353. + attr->manip = rsp_params->manip;
  17354. + attr->num_ifs = le16_to_cpu(rsp_params->num_ifs);
  17355. + attr->mem_size = le16_to_cpu(rsp_params->mem_size);
  17356. +
  17357. + return 0;
  17358. +}
  17359. +
  17360. +/**
  17361. + * dpdmux_if_enable() - Enable Interface
  17362. + * @mc_io: Pointer to MC portal's I/O object
  17363. + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
  17364. + * @token: Token of DPDMUX object
  17365. + * @if_id: Interface Identifier
  17366. + *
  17367. + * Return: Completion status. '0' on Success; Error code otherwise.
  17368. + */
  17369. +int dpdmux_if_enable(struct fsl_mc_io *mc_io,
  17370. + u32 cmd_flags,
  17371. + u16 token,
  17372. + u16 if_id)
  17373. +{
  17374. + struct dpdmux_cmd_if *cmd_params;
  17375. + struct mc_command cmd = { 0 };
  17376. +
  17377. + /* prepare command */
  17378. + cmd.header = mc_encode_cmd_header(DPDMUX_CMDID_IF_ENABLE,
  17379. + cmd_flags,
  17380. + token);
  17381. + cmd_params = (struct dpdmux_cmd_if *)cmd.params;
  17382. + cmd_params->if_id = cpu_to_le16(if_id);
  17383. +
  17384. + /* send command to mc*/
  17385. + return mc_send_command(mc_io, &cmd);
  17386. +}
  17387. +
  17388. +/**
  17389. + * dpdmux_if_disable() - Disable Interface
  17390. + * @mc_io: Pointer to MC portal's I/O object
  17391. + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
  17392. + * @token: Token of DPDMUX object
  17393. + * @if_id: Interface Identifier
  17394. + *
  17395. + * Return: Completion status. '0' on Success; Error code otherwise.
  17396. + */
  17397. +int dpdmux_if_disable(struct fsl_mc_io *mc_io,
  17398. + u32 cmd_flags,
  17399. + u16 token,
  17400. + u16 if_id)
  17401. +{
  17402. + struct dpdmux_cmd_if *cmd_params;
  17403. + struct mc_command cmd = { 0 };
  17404. +
  17405. + /* prepare command */
  17406. + cmd.header = mc_encode_cmd_header(DPDMUX_CMDID_IF_DISABLE,
  17407. + cmd_flags,
  17408. + token);
  17409. + cmd_params = (struct dpdmux_cmd_if *)cmd.params;
  17410. + cmd_params->if_id = cpu_to_le16(if_id);
  17411. +
  17412. + /* send command to mc*/
  17413. + return mc_send_command(mc_io, &cmd);
  17414. +}
  17415. +
  17416. +/**
  17417. + * dpdmux_set_max_frame_length() - Set the maximum frame length in DPDMUX
  17418. + * @mc_io: Pointer to MC portal's I/O object
  17419. + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
  17420. + * @token: Token of DPDMUX object
  17421. + * @max_frame_length: The required maximum frame length
  17422. + *
  17423. + * Update the maximum frame length on all DMUX interfaces.
  17424. + * In case of VEPA, the maximum frame length on all dmux interfaces
  17425. + * will be updated with the minimum value of the mfls of the connected
  17426. + * dpnis and the actual value of dmux mfl.
  17427. + *
  17428. + * Return: '0' on Success; Error code otherwise.
  17429. + */
  17430. +int dpdmux_set_max_frame_length(struct fsl_mc_io *mc_io,
  17431. + u32 cmd_flags,
  17432. + u16 token,
  17433. + u16 max_frame_length)
  17434. +{
  17435. + struct mc_command cmd = { 0 };
  17436. + struct dpdmux_cmd_set_max_frame_length *cmd_params;
  17437. +
  17438. + /* prepare command */
  17439. + cmd.header = mc_encode_cmd_header(DPDMUX_CMDID_SET_MAX_FRAME_LENGTH,
  17440. + cmd_flags,
  17441. + token);
  17442. + cmd_params = (struct dpdmux_cmd_set_max_frame_length *)cmd.params;
  17443. + cmd_params->max_frame_length = cpu_to_le16(max_frame_length);
  17444. +
  17445. + /* send command to mc*/
  17446. + return mc_send_command(mc_io, &cmd);
  17447. +}
  17448. +
  17449. +/**
  17450. + * dpdmux_ul_reset_counters() - Function resets the uplink counter
  17451. + * @mc_io: Pointer to MC portal's I/O object
  17452. + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
  17453. + * @token: Token of DPDMUX object
  17454. + *
  17455. + * Return: '0' on Success; Error code otherwise.
  17456. + */
  17457. +int dpdmux_ul_reset_counters(struct fsl_mc_io *mc_io,
  17458. + u32 cmd_flags,
  17459. + u16 token)
  17460. +{
  17461. + struct mc_command cmd = { 0 };
  17462. +
  17463. + /* prepare command */
  17464. + cmd.header = mc_encode_cmd_header(DPDMUX_CMDID_UL_RESET_COUNTERS,
  17465. + cmd_flags,
  17466. + token);
  17467. +
  17468. + /* send command to mc*/
  17469. + return mc_send_command(mc_io, &cmd);
  17470. +}
  17471. +
  17472. +/**
  17473. + * dpdmux_if_set_accepted_frames() - Set the accepted frame types
  17474. + * @mc_io: Pointer to MC portal's I/O object
  17475. + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
  17476. + * @token: Token of DPDMUX object
  17477. + * @if_id: Interface ID (0 for uplink, or 1-num_ifs);
  17478. + * @cfg: Frame types configuration
  17479. + *
  17480. + * if 'DPDMUX_ADMIT_ONLY_VLAN_TAGGED' is set - untagged frames or
  17481. + * priority-tagged frames are discarded.
  17482. + * if 'DPDMUX_ADMIT_ONLY_UNTAGGED' is set - untagged frames or
  17483. + * priority-tagged frames are accepted.
  17484. + * if 'DPDMUX_ADMIT_ALL' is set (default mode) - all VLAN tagged,
  17485. + * untagged and priority-tagged frame are accepted;
  17486. + *
  17487. + * Return: '0' on Success; Error code otherwise.
  17488. + */
  17489. +int dpdmux_if_set_accepted_frames(struct fsl_mc_io *mc_io,
  17490. + u32 cmd_flags,
  17491. + u16 token,
  17492. + u16 if_id,
  17493. + const struct dpdmux_accepted_frames *cfg)
  17494. +{
  17495. + struct mc_command cmd = { 0 };
  17496. + struct dpdmux_cmd_if_set_accepted_frames *cmd_params;
  17497. +
  17498. + /* prepare command */
  17499. + cmd.header = mc_encode_cmd_header(DPDMUX_CMDID_IF_SET_ACCEPTED_FRAMES,
  17500. + cmd_flags,
  17501. + token);
  17502. + cmd_params = (struct dpdmux_cmd_if_set_accepted_frames *)cmd.params;
  17503. + cmd_params->if_id = cpu_to_le16(if_id);
  17504. + dpdmux_set_field(cmd_params->frames_options, ACCEPTED_FRAMES_TYPE,
  17505. + cfg->type);
  17506. + dpdmux_set_field(cmd_params->frames_options, UNACCEPTED_FRAMES_ACTION,
  17507. + cfg->unaccept_act);
  17508. +
  17509. + /* send command to mc*/
  17510. + return mc_send_command(mc_io, &cmd);
  17511. +}
  17512. +
  17513. +/**
  17514. + * dpdmux_if_get_attributes() - Obtain DPDMUX interface attributes
  17515. + * @mc_io: Pointer to MC portal's I/O object
  17516. + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
  17517. + * @token: Token of DPDMUX object
  17518. + * @if_id: Interface ID (0 for uplink, or 1-num_ifs);
  17519. + * @attr: Interface attributes
  17520. + *
  17521. + * Return: '0' on Success; Error code otherwise.
  17522. + */
  17523. +int dpdmux_if_get_attributes(struct fsl_mc_io *mc_io,
  17524. + u32 cmd_flags,
  17525. + u16 token,
  17526. + u16 if_id,
  17527. + struct dpdmux_if_attr *attr)
  17528. +{
  17529. + struct mc_command cmd = { 0 };
  17530. + struct dpdmux_cmd_if *cmd_params;
  17531. + struct dpdmux_rsp_if_get_attr *rsp_params;
  17532. + int err;
  17533. +
  17534. + /* prepare command */
  17535. + cmd.header = mc_encode_cmd_header(DPDMUX_CMDID_IF_GET_ATTR,
  17536. + cmd_flags,
  17537. + token);
  17538. + cmd_params = (struct dpdmux_cmd_if *)cmd.params;
  17539. + cmd_params->if_id = cpu_to_le16(if_id);
  17540. +
  17541. + /* send command to mc*/
  17542. + err = mc_send_command(mc_io, &cmd);
  17543. + if (err)
  17544. + return err;
  17545. +
  17546. + /* retrieve response parameters */
  17547. + rsp_params = (struct dpdmux_rsp_if_get_attr *)cmd.params;
  17548. + attr->rate = le32_to_cpu(rsp_params->rate);
  17549. + attr->enabled = dpdmux_get_field(rsp_params->enabled, ENABLE);
  17550. + attr->accept_frame_type =
  17551. + dpdmux_get_field(rsp_params->accepted_frames_type,
  17552. + ACCEPTED_FRAMES_TYPE);
  17553. +
  17554. + return 0;
  17555. +}
  17556. +
  17557. +/**
  17558. + * dpdmux_if_remove_l2_rule() - Remove L2 rule from DPDMUX table
  17559. + * @mc_io: Pointer to MC portal's I/O object
  17560. + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
  17561. + * @token: Token of DPDMUX object
  17562. + * @if_id: Destination interface ID
  17563. + * @rule: L2 rule
  17564. + *
  17565. + * Function removes a L2 rule from DPDMUX table
  17566. + * or adds an interface to an existing multicast address
  17567. + *
  17568. + * Return: '0' on Success; Error code otherwise.
  17569. + */
  17570. +int dpdmux_if_remove_l2_rule(struct fsl_mc_io *mc_io,
  17571. + u32 cmd_flags,
  17572. + u16 token,
  17573. + u16 if_id,
  17574. + const struct dpdmux_l2_rule *rule)
  17575. +{
  17576. + struct mc_command cmd = { 0 };
  17577. + struct dpdmux_cmd_if_l2_rule *cmd_params;
  17578. +
  17579. + /* prepare command */
  17580. + cmd.header = mc_encode_cmd_header(DPDMUX_CMDID_IF_REMOVE_L2_RULE,
  17581. + cmd_flags,
  17582. + token);
  17583. + cmd_params = (struct dpdmux_cmd_if_l2_rule *)cmd.params;
  17584. + cmd_params->if_id = cpu_to_le16(if_id);
  17585. + cmd_params->vlan_id = cpu_to_le16(rule->vlan_id);
  17586. + cmd_params->mac_addr5 = rule->mac_addr[5];
  17587. + cmd_params->mac_addr4 = rule->mac_addr[4];
  17588. + cmd_params->mac_addr3 = rule->mac_addr[3];
  17589. + cmd_params->mac_addr2 = rule->mac_addr[2];
  17590. + cmd_params->mac_addr1 = rule->mac_addr[1];
  17591. + cmd_params->mac_addr0 = rule->mac_addr[0];
  17592. +
  17593. + /* send command to mc*/
  17594. + return mc_send_command(mc_io, &cmd);
  17595. +}
  17596. +
  17597. +/**
  17598. + * dpdmux_if_add_l2_rule() - Add L2 rule into DPDMUX table
  17599. + * @mc_io: Pointer to MC portal's I/O object
  17600. + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
  17601. + * @token: Token of DPDMUX object
  17602. + * @if_id: Destination interface ID
  17603. + * @rule: L2 rule
  17604. + *
  17605. + * Function adds a L2 rule into DPDMUX table
  17606. + * or adds an interface to an existing multicast address
  17607. + *
  17608. + * Return: '0' on Success; Error code otherwise.
  17609. + */
  17610. +int dpdmux_if_add_l2_rule(struct fsl_mc_io *mc_io,
  17611. + u32 cmd_flags,
  17612. + u16 token,
  17613. + u16 if_id,
  17614. + const struct dpdmux_l2_rule *rule)
  17615. +{
  17616. + struct mc_command cmd = { 0 };
  17617. + struct dpdmux_cmd_if_l2_rule *cmd_params;
  17618. +
  17619. + /* prepare command */
  17620. + cmd.header = mc_encode_cmd_header(DPDMUX_CMDID_IF_ADD_L2_RULE,
  17621. + cmd_flags,
  17622. + token);
  17623. + cmd_params = (struct dpdmux_cmd_if_l2_rule *)cmd.params;
  17624. + cmd_params->if_id = cpu_to_le16(if_id);
  17625. + cmd_params->vlan_id = cpu_to_le16(rule->vlan_id);
  17626. + cmd_params->mac_addr5 = rule->mac_addr[5];
  17627. + cmd_params->mac_addr4 = rule->mac_addr[4];
  17628. + cmd_params->mac_addr3 = rule->mac_addr[3];
  17629. + cmd_params->mac_addr2 = rule->mac_addr[2];
  17630. + cmd_params->mac_addr1 = rule->mac_addr[1];
  17631. + cmd_params->mac_addr0 = rule->mac_addr[0];
  17632. +
  17633. + /* send command to mc*/
  17634. + return mc_send_command(mc_io, &cmd);
  17635. +}
  17636. +
  17637. +/**
  17638. + * dpdmux_if_get_counter() - Functions obtains specific counter of an interface
  17639. + * @mc_io: Pointer to MC portal's I/O object
  17640. + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
  17641. + * @token: Token of DPDMUX object
  17642. + * @if_id: Interface Id
  17643. + * @counter_type: counter type
  17644. + * @counter: Returned specific counter information
  17645. + *
  17646. + * Return: '0' on Success; Error code otherwise.
  17647. + */
  17648. +int dpdmux_if_get_counter(struct fsl_mc_io *mc_io,
  17649. + u32 cmd_flags,
  17650. + u16 token,
  17651. + u16 if_id,
  17652. + enum dpdmux_counter_type counter_type,
  17653. + u64 *counter)
  17654. +{
  17655. + struct mc_command cmd = { 0 };
  17656. + struct dpdmux_cmd_if_get_counter *cmd_params;
  17657. + struct dpdmux_rsp_if_get_counter *rsp_params;
  17658. + int err;
  17659. +
  17660. + /* prepare command */
  17661. + cmd.header = mc_encode_cmd_header(DPDMUX_CMDID_IF_GET_COUNTER,
  17662. + cmd_flags,
  17663. + token);
  17664. + cmd_params = (struct dpdmux_cmd_if_get_counter *)cmd.params;
  17665. + cmd_params->if_id = cpu_to_le16(if_id);
  17666. + cmd_params->counter_type = counter_type;
  17667. +
  17668. + /* send command to mc*/
  17669. + err = mc_send_command(mc_io, &cmd);
  17670. + if (err)
  17671. + return err;
  17672. +
  17673. + /* retrieve response parameters */
  17674. + rsp_params = (struct dpdmux_rsp_if_get_counter *)cmd.params;
  17675. + *counter = le64_to_cpu(rsp_params->counter);
  17676. +
  17677. + return 0;
  17678. +}
  17679. +
  17680. +/**
  17681. + * dpdmux_if_set_link_cfg() - set the link configuration.
  17682. + * @mc_io: Pointer to MC portal's I/O object
  17683. + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
  17684. + * @token: Token of DPSW object
  17685. + * @if_id: interface id
  17686. + * @cfg: Link configuration
  17687. + *
  17688. + * Return: '0' on Success; Error code otherwise.
  17689. + */
  17690. +int dpdmux_if_set_link_cfg(struct fsl_mc_io *mc_io,
  17691. + u32 cmd_flags,
  17692. + u16 token,
  17693. + u16 if_id,
  17694. + struct dpdmux_link_cfg *cfg)
  17695. +{
  17696. + struct mc_command cmd = { 0 };
  17697. + struct dpdmux_cmd_if_set_link_cfg *cmd_params;
  17698. +
  17699. + /* prepare command */
  17700. + cmd.header = mc_encode_cmd_header(DPDMUX_CMDID_IF_SET_LINK_CFG,
  17701. + cmd_flags,
  17702. + token);
  17703. + cmd_params = (struct dpdmux_cmd_if_set_link_cfg *)cmd.params;
  17704. + cmd_params->if_id = cpu_to_le16(if_id);
  17705. + cmd_params->rate = cpu_to_le32(cfg->rate);
  17706. + cmd_params->options = cpu_to_le64(cfg->options);
  17707. +
  17708. + /* send command to mc*/
  17709. + return mc_send_command(mc_io, &cmd);
  17710. +}
  17711. +
  17712. +/**
  17713. + * dpdmux_if_get_link_state - Return the link state
  17714. + * @mc_io: Pointer to MC portal's I/O object
  17715. + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
  17716. + * @token: Token of DPSW object
  17717. + * @if_id: interface id
  17718. + * @state: link state
  17719. + *
  17720. + * @returns '0' on Success; Error code otherwise.
  17721. + */
  17722. +int dpdmux_if_get_link_state(struct fsl_mc_io *mc_io,
  17723. + u32 cmd_flags,
  17724. + u16 token,
  17725. + u16 if_id,
  17726. + struct dpdmux_link_state *state)
  17727. +{
  17728. + struct mc_command cmd = { 0 };
  17729. + struct dpdmux_cmd_if_get_link_state *cmd_params;
  17730. + struct dpdmux_rsp_if_get_link_state *rsp_params;
  17731. + int err;
  17732. +
  17733. + /* prepare command */
  17734. + cmd.header = mc_encode_cmd_header(DPDMUX_CMDID_IF_GET_LINK_STATE,
  17735. + cmd_flags,
  17736. + token);
  17737. + cmd_params = (struct dpdmux_cmd_if_get_link_state *)cmd.params;
  17738. + cmd_params->if_id = cpu_to_le16(if_id);
  17739. +
  17740. + /* send command to mc*/
  17741. + err = mc_send_command(mc_io, &cmd);
  17742. + if (err)
  17743. + return err;
  17744. +
  17745. + /* retrieve response parameters */
  17746. + rsp_params = (struct dpdmux_rsp_if_get_link_state *)cmd.params;
  17747. + state->rate = le32_to_cpu(rsp_params->rate);
  17748. + state->options = le64_to_cpu(rsp_params->options);
  17749. + state->up = dpdmux_get_field(rsp_params->up, ENABLE);
  17750. +
  17751. + return 0;
  17752. +}
  17753. +
  17754. +/**
  17755. + * dpdmux_set_custom_key - Set a custom classification key.
  17756. + *
  17757. + * This API is only available for DPDMUX instance created with
  17758. + * DPDMUX_METHOD_CUSTOM. This API must be called before populating the
  17759. + * classification table using dpdmux_add_custom_cls_entry.
  17760. + *
  17761. + * Calls to dpdmux_set_custom_key remove all existing classification entries
  17762. + * that may have been added previously using dpdmux_add_custom_cls_entry.
  17763. + *
  17764. + * @mc_io: Pointer to MC portal's I/O object
  17765. + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
  17766. + * @token: Token of DPSW object
  17767. + * @if_id: interface id
  17768. + * @key_cfg_iova: DMA address of a configuration structure set up using
  17769. + * dpkg_prepare_key_cfg. Maximum key size is 24 bytes.
  17770. + *
  17771. + * @returns '0' on Success; Error code otherwise.
  17772. + */
  17773. +int dpdmux_set_custom_key(struct fsl_mc_io *mc_io,
  17774. + u32 cmd_flags,
  17775. + u16 token,
  17776. + u64 key_cfg_iova)
  17777. +{
  17778. + struct dpdmux_set_custom_key *cmd_params;
  17779. + struct mc_command cmd = { 0 };
  17780. +
  17781. + /* prepare command */
  17782. + cmd.header = mc_encode_cmd_header(DPDMUX_CMDID_SET_CUSTOM_KEY,
  17783. + cmd_flags,
  17784. + token);
  17785. + cmd_params = (struct dpdmux_set_custom_key *)cmd.params;
  17786. + cmd_params->key_cfg_iova = cpu_to_le64(key_cfg_iova);
  17787. +
  17788. + /* send command to mc*/
  17789. + return mc_send_command(mc_io, &cmd);
  17790. +}
  17791. +
  17792. +/**
  17793. + * dpdmux_add_custom_cls_entry - Adds a custom classification entry.
  17794. + *
  17795. + * This API is only available for DPDMUX instances created with
  17796. + * DPDMUX_METHOD_CUSTOM. Before calling this function a classification key
  17797. + * composition rule must be set up using dpdmux_set_custom_key.
  17798. + *
  17799. + * @mc_io: Pointer to MC portal's I/O object
  17800. + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
  17801. + * @token: Token of DPSW object
  17802. + * @rule: Classification rule to insert. Rules cannot be duplicated, if a
  17803. + * matching rule already exists, the action will be replaced.
  17804. + * @action: Action to perform for matching traffic.
  17805. + *
  17806. + * @returns '0' on Success; Error code otherwise.
  17807. + */
  17808. +int dpdmux_add_custom_cls_entry(struct fsl_mc_io *mc_io,
  17809. + u32 cmd_flags,
  17810. + u16 token,
  17811. + struct dpdmux_rule_cfg *rule,
  17812. + struct dpdmux_cls_action *action)
  17813. +{
  17814. + struct dpdmux_cmd_add_custom_cls_entry *cmd_params;
  17815. + struct mc_command cmd = { 0 };
  17816. +
  17817. + /* prepare command */
  17818. + cmd.header = mc_encode_cmd_header(DPDMUX_CMDID_ADD_CUSTOM_CLS_ENTRY,
  17819. + cmd_flags,
  17820. + token);
  17821. +
  17822. + cmd_params = (struct dpdmux_cmd_add_custom_cls_entry *)cmd.params;
  17823. + cmd_params->key_size = rule->key_size;
  17824. + cmd_params->dest_if = cpu_to_le16(action->dest_if);
  17825. + cmd_params->key_iova = cpu_to_le64(rule->key_iova);
  17826. + cmd_params->mask_iova = cpu_to_le64(rule->mask_iova);
  17827. +
  17828. + /* send command to mc*/
  17829. + return mc_send_command(mc_io, &cmd);
  17830. +}
  17831. +
  17832. +/**
  17833. + * dpdmux_remove_custom_cls_entry - Removes a custom classification entry.
  17834. + *
  17835. + * This API is only available for DPDMUX instances created with
  17836. + * DPDMUX_METHOD_CUSTOM. The API can be used to remove classification
  17837. + * entries previously inserted using dpdmux_add_custom_cls_entry.
  17838. + *
  17839. + * @mc_io: Pointer to MC portal's I/O object
  17840. + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
  17841. + * @token: Token of DPSW object
  17842. + * @rule: Classification rule to remove
  17843. + *
  17844. + * @returns '0' on Success; Error code otherwise.
  17845. + */
  17846. +int dpdmux_remove_custom_cls_entry(struct fsl_mc_io *mc_io,
  17847. + u32 cmd_flags,
  17848. + u16 token,
  17849. + struct dpdmux_rule_cfg *rule)
  17850. +{
  17851. + struct dpdmux_cmd_remove_custom_cls_entry *cmd_params;
  17852. + struct mc_command cmd = { 0 };
  17853. +
  17854. + /* prepare command */
  17855. + cmd.header = mc_encode_cmd_header(DPDMUX_CMDID_REMOVE_CUSTOM_CLS_ENTRY,
  17856. + cmd_flags,
  17857. + token);
  17858. + cmd_params = (struct dpdmux_cmd_remove_custom_cls_entry *)cmd.params;
  17859. + cmd_params->key_size = rule->key_size;
  17860. + cmd_params->key_iova = cpu_to_le64(rule->key_iova);
  17861. + cmd_params->mask_iova = cpu_to_le64(rule->mask_iova);
  17862. +
  17863. + /* send command to mc*/
  17864. + return mc_send_command(mc_io, &cmd);
  17865. +}
  17866. +
  17867. +/**
  17868. + * dpdmux_get_api_version() - Get Data Path Demux API version
  17869. + * @mc_io: Pointer to MC portal's I/O object
  17870. + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
  17871. + * @major_ver: Major version of data path demux API
  17872. + * @minor_ver: Minor version of data path demux API
  17873. + *
  17874. + * Return: '0' on Success; Error code otherwise.
  17875. + */
  17876. +int dpdmux_get_api_version(struct fsl_mc_io *mc_io,
  17877. + u32 cmd_flags,
  17878. + u16 *major_ver,
  17879. + u16 *minor_ver)
  17880. +{
  17881. + struct mc_command cmd = { 0 };
  17882. + struct dpdmux_rsp_get_api_version *rsp_params;
  17883. + int err;
  17884. +
  17885. + cmd.header = mc_encode_cmd_header(DPDMUX_CMDID_GET_API_VERSION,
  17886. + cmd_flags,
  17887. + 0);
  17888. +
  17889. + err = mc_send_command(mc_io, &cmd);
  17890. + if (err)
  17891. + return err;
  17892. +
  17893. + rsp_params = (struct dpdmux_rsp_get_api_version *)cmd.params;
  17894. + *major_ver = le16_to_cpu(rsp_params->major);
  17895. + *minor_ver = le16_to_cpu(rsp_params->minor);
  17896. +
  17897. + return 0;
  17898. +}
  17899. --- /dev/null
  17900. +++ b/drivers/staging/fsl-dpaa2/evb/dpdmux.h
  17901. @@ -0,0 +1,453 @@
  17902. +/* Copyright 2013-2015 Freescale Semiconductor Inc.
  17903. + *
  17904. + * Redistribution and use in source and binary forms, with or without
  17905. + * modification, are permitted provided that the following conditions are met:
  17906. + * * Redistributions of source code must retain the above copyright
  17907. + * notice, this list of conditions and the following disclaimer.
  17908. + * * Redistributions in binary form must reproduce the above copyright
  17909. + * notice, this list of conditions and the following disclaimer in the
  17910. + * documentation and/or other materials provided with the distribution.
  17911. + * * Neither the name of the above-listed copyright holders nor the
  17912. + * names of any contributors may be used to endorse or promote products
  17913. + * derived from this software without specific prior written permission.
  17914. + *
  17915. + *
  17916. + * ALTERNATIVELY, this software may be distributed under the terms of the
  17917. + * GNU General Public License ("GPL") as published by the Free Software
  17918. + * Foundation, either version 2 of that License or (at your option) any
  17919. + * later version.
  17920. + *
  17921. + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  17922. + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  17923. + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  17924. + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
  17925. + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  17926. + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  17927. + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  17928. + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  17929. + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  17930. + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  17931. + * POSSIBILITY OF SUCH DAMAGE.
  17932. + */
  17933. +#ifndef __FSL_DPDMUX_H
  17934. +#define __FSL_DPDMUX_H
  17935. +
  17936. +struct fsl_mc_io;
  17937. +
  17938. +/* Data Path Demux API
  17939. + * Contains API for handling DPDMUX topology and functionality
  17940. + */
  17941. +
  17942. +int dpdmux_open(struct fsl_mc_io *mc_io,
  17943. + u32 cmd_flags,
  17944. + int dpdmux_id,
  17945. + u16 *token);
  17946. +
  17947. +int dpdmux_close(struct fsl_mc_io *mc_io,
  17948. + u32 cmd_flags,
  17949. + u16 token);
  17950. +
  17951. +/**
  17952. + * DPDMUX general options
  17953. + */
  17954. +
  17955. +/**
  17956. + * Enable bridging between internal interfaces
  17957. + */
  17958. +#define DPDMUX_OPT_BRIDGE_EN 0x0000000000000002ULL
  17959. +
  17960. +/**
  17961. + * Mask support for classification
  17962. + */
  17963. +#define DPDMUX_OPT_CLS_MASK_SUPPORT 0x0000000000000020ULL
  17964. +
  17965. +#define DPDMUX_IRQ_INDEX_IF 0x0000
  17966. +#define DPDMUX_IRQ_INDEX 0x0001
  17967. +
  17968. +/**
  17969. + * IRQ event - Indicates that the link state changed
  17970. + */
  17971. +#define DPDMUX_IRQ_EVENT_LINK_CHANGED 0x0001
  17972. +
  17973. +/**
  17974. + * enum dpdmux_manip - DPDMUX manipulation operations
  17975. + * @DPDMUX_MANIP_NONE: No manipulation on frames
  17976. + * @DPDMUX_MANIP_ADD_REMOVE_S_VLAN: Add S-VLAN on egress, remove it on ingress
  17977. + */
  17978. +enum dpdmux_manip {
  17979. + DPDMUX_MANIP_NONE = 0x0,
  17980. + DPDMUX_MANIP_ADD_REMOVE_S_VLAN = 0x1
  17981. +};
  17982. +
  17983. +/**
  17984. + * enum dpdmux_method - DPDMUX method options
  17985. + * @DPDMUX_METHOD_NONE: no DPDMUX method
  17986. + * @DPDMUX_METHOD_C_VLAN_MAC: DPDMUX based on C-VLAN and MAC address
  17987. + * @DPDMUX_METHOD_MAC: DPDMUX based on MAC address
  17988. + * @DPDMUX_METHOD_C_VLAN: DPDMUX based on C-VLAN
  17989. + * @DPDMUX_METHOD_S_VLAN: DPDMUX based on S-VLAN
  17990. + */
  17991. +enum dpdmux_method {
  17992. + DPDMUX_METHOD_NONE = 0x0,
  17993. + DPDMUX_METHOD_C_VLAN_MAC = 0x1,
  17994. + DPDMUX_METHOD_MAC = 0x2,
  17995. + DPDMUX_METHOD_C_VLAN = 0x3,
  17996. + DPDMUX_METHOD_S_VLAN = 0x4,
  17997. + DPDMUX_METHOD_CUSTOM = 0x5
  17998. +};
  17999. +
  18000. +/**
  18001. + * struct dpdmux_cfg - DPDMUX configuration parameters
  18002. + * @method: Defines the operation method for the DPDMUX address table
  18003. + * @manip: Required manipulation operation
  18004. + * @num_ifs: Number of interfaces (excluding the uplink interface)
  18005. + * @adv: Advanced parameters; default is all zeros;
  18006. + * use this structure to change default settings
  18007. + */
  18008. +struct dpdmux_cfg {
  18009. + enum dpdmux_method method;
  18010. + enum dpdmux_manip manip;
  18011. + u16 num_ifs;
  18012. + /**
  18013. + * struct adv - Advanced parameters
  18014. + * @options: DPDMUX options - combination of 'DPDMUX_OPT_<X>' flags
  18015. + * @max_dmat_entries: Maximum entries in DPDMUX address table
  18016. + * 0 - indicates default: 64 entries per interface.
  18017. + * @max_mc_groups: Number of multicast groups in DPDMUX table
  18018. + * 0 - indicates default: 32 multicast groups
  18019. + * @max_vlan_ids: max vlan ids allowed in the system -
  18020. + * relevant only case of working in mac+vlan method.
  18021. + * 0 - indicates default 16 vlan ids.
  18022. + */
  18023. + struct {
  18024. + u64 options;
  18025. + u16 max_dmat_entries;
  18026. + u16 max_mc_groups;
  18027. + u16 max_vlan_ids;
  18028. + } adv;
  18029. +};
  18030. +
  18031. +int dpdmux_create(struct fsl_mc_io *mc_io,
  18032. + u16 dprc_token,
  18033. + u32 cmd_flags,
  18034. + const struct dpdmux_cfg *cfg,
  18035. + u32 *obj_id);
  18036. +
  18037. +int dpdmux_destroy(struct fsl_mc_io *mc_io,
  18038. + u16 dprc_token,
  18039. + u32 cmd_flags,
  18040. + u32 object_id);
  18041. +
  18042. +int dpdmux_enable(struct fsl_mc_io *mc_io,
  18043. + u32 cmd_flags,
  18044. + u16 token);
  18045. +
  18046. +int dpdmux_disable(struct fsl_mc_io *mc_io,
  18047. + u32 cmd_flags,
  18048. + u16 token);
  18049. +
  18050. +int dpdmux_is_enabled(struct fsl_mc_io *mc_io,
  18051. + u32 cmd_flags,
  18052. + u16 token,
  18053. + int *en);
  18054. +
  18055. +int dpdmux_reset(struct fsl_mc_io *mc_io,
  18056. + u32 cmd_flags,
  18057. + u16 token);
  18058. +
  18059. +int dpdmux_set_irq_enable(struct fsl_mc_io *mc_io,
  18060. + u32 cmd_flags,
  18061. + u16 token,
  18062. + u8 irq_index,
  18063. + u8 en);
  18064. +
  18065. +int dpdmux_get_irq_enable(struct fsl_mc_io *mc_io,
  18066. + u32 cmd_flags,
  18067. + u16 token,
  18068. + u8 irq_index,
  18069. + u8 *en);
  18070. +
  18071. +int dpdmux_set_irq_mask(struct fsl_mc_io *mc_io,
  18072. + u32 cmd_flags,
  18073. + u16 token,
  18074. + u8 irq_index,
  18075. + u32 mask);
  18076. +
  18077. +int dpdmux_get_irq_mask(struct fsl_mc_io *mc_io,
  18078. + u32 cmd_flags,
  18079. + u16 token,
  18080. + u8 irq_index,
  18081. + u32 *mask);
  18082. +
  18083. +int dpdmux_get_irq_status(struct fsl_mc_io *mc_io,
  18084. + u32 cmd_flags,
  18085. + u16 token,
  18086. + u8 irq_index,
  18087. + u32 *status);
  18088. +
  18089. +int dpdmux_clear_irq_status(struct fsl_mc_io *mc_io,
  18090. + u32 cmd_flags,
  18091. + u16 token,
  18092. + u8 irq_index,
  18093. + u32 status);
  18094. +
  18095. +/**
  18096. + * struct dpdmux_attr - Structure representing DPDMUX attributes
  18097. + * @id: DPDMUX object ID
  18098. + * @options: Configuration options (bitmap)
  18099. + * @method: DPDMUX address table method
  18100. + * @manip: DPDMUX manipulation type
  18101. + * @num_ifs: Number of interfaces (excluding the uplink interface)
  18102. + * @mem_size: DPDMUX frame storage memory size
  18103. + */
  18104. +struct dpdmux_attr {
  18105. + int id;
  18106. + u64 options;
  18107. + enum dpdmux_method method;
  18108. + enum dpdmux_manip manip;
  18109. + u16 num_ifs;
  18110. + u16 mem_size;
  18111. +};
  18112. +
  18113. +int dpdmux_get_attributes(struct fsl_mc_io *mc_io,
  18114. + u32 cmd_flags,
  18115. + u16 token,
  18116. + struct dpdmux_attr *attr);
  18117. +
  18118. +int dpdmux_set_max_frame_length(struct fsl_mc_io *mc_io,
  18119. + u32 cmd_flags,
  18120. + u16 token,
  18121. + u16 max_frame_length);
  18122. +
  18123. +/**
  18124. + * enum dpdmux_counter_type - Counter types
  18125. + * @DPDMUX_CNT_ING_FRAME: Counts ingress frames
  18126. + * @DPDMUX_CNT_ING_BYTE: Counts ingress bytes
  18127. + * @DPDMUX_CNT_ING_FLTR_FRAME: Counts filtered ingress frames
  18128. + * @DPDMUX_CNT_ING_FRAME_DISCARD: Counts discarded ingress frames
  18129. + * @DPDMUX_CNT_ING_MCAST_FRAME: Counts ingress multicast frames
  18130. + * @DPDMUX_CNT_ING_MCAST_BYTE: Counts ingress multicast bytes
  18131. + * @DPDMUX_CNT_ING_BCAST_FRAME: Counts ingress broadcast frames
  18132. + * @DPDMUX_CNT_ING_BCAST_BYTES: Counts ingress broadcast bytes
  18133. + * @DPDMUX_CNT_EGR_FRAME: Counts egress frames
  18134. + * @DPDMUX_CNT_EGR_BYTE: Counts egress bytes
  18135. + * @DPDMUX_CNT_EGR_FRAME_DISCARD: Counts discarded egress frames
  18136. + */
  18137. +enum dpdmux_counter_type {
  18138. + DPDMUX_CNT_ING_FRAME = 0x0,
  18139. + DPDMUX_CNT_ING_BYTE = 0x1,
  18140. + DPDMUX_CNT_ING_FLTR_FRAME = 0x2,
  18141. + DPDMUX_CNT_ING_FRAME_DISCARD = 0x3,
  18142. + DPDMUX_CNT_ING_MCAST_FRAME = 0x4,
  18143. + DPDMUX_CNT_ING_MCAST_BYTE = 0x5,
  18144. + DPDMUX_CNT_ING_BCAST_FRAME = 0x6,
  18145. + DPDMUX_CNT_ING_BCAST_BYTES = 0x7,
  18146. + DPDMUX_CNT_EGR_FRAME = 0x8,
  18147. + DPDMUX_CNT_EGR_BYTE = 0x9,
  18148. + DPDMUX_CNT_EGR_FRAME_DISCARD = 0xa
  18149. +};
  18150. +
  18151. +/**
  18152. + * enum dpdmux_accepted_frames_type - DPDMUX frame types
  18153. + * @DPDMUX_ADMIT_ALL: The device accepts VLAN tagged, untagged and
  18154. + * priority-tagged frames
  18155. + * @DPDMUX_ADMIT_ONLY_VLAN_TAGGED: The device discards untagged frames or
  18156. + * priority-tagged frames that are received on this
  18157. + * interface
  18158. + * @DPDMUX_ADMIT_ONLY_UNTAGGED: Untagged frames or priority-tagged frames
  18159. + * received on this interface are accepted
  18160. + */
  18161. +enum dpdmux_accepted_frames_type {
  18162. + DPDMUX_ADMIT_ALL = 0,
  18163. + DPDMUX_ADMIT_ONLY_VLAN_TAGGED = 1,
  18164. + DPDMUX_ADMIT_ONLY_UNTAGGED = 2
  18165. +};
  18166. +
  18167. +/**
  18168. + * enum dpdmux_action - DPDMUX action for un-accepted frames
  18169. + * @DPDMUX_ACTION_DROP: Drop un-accepted frames
  18170. + * @DPDMUX_ACTION_REDIRECT_TO_CTRL: Redirect un-accepted frames to the
  18171. + * control interface
  18172. + */
  18173. +enum dpdmux_action {
  18174. + DPDMUX_ACTION_DROP = 0,
  18175. + DPDMUX_ACTION_REDIRECT_TO_CTRL = 1
  18176. +};
  18177. +
  18178. +/**
  18179. + * struct dpdmux_accepted_frames - Frame types configuration
  18180. + * @type: Defines ingress accepted frames
  18181. + * @unaccept_act: Defines action on frames not accepted
  18182. + */
  18183. +struct dpdmux_accepted_frames {
  18184. + enum dpdmux_accepted_frames_type type;
  18185. + enum dpdmux_action unaccept_act;
  18186. +};
  18187. +
  18188. +int dpdmux_if_set_accepted_frames(struct fsl_mc_io *mc_io,
  18189. + u32 cmd_flags,
  18190. + u16 token,
  18191. + u16 if_id,
  18192. + const struct dpdmux_accepted_frames *cfg);
  18193. +
  18194. +/**
  18195. + * struct dpdmux_if_attr - Structure representing frame types configuration
  18196. + * @rate: Configured interface rate (in bits per second)
  18197. + * @enabled: Indicates if interface is enabled
  18198. + * @accept_frame_type: Indicates type of accepted frames for the interface
  18199. + */
  18200. +struct dpdmux_if_attr {
  18201. + u32 rate;
  18202. + int enabled;
  18203. + enum dpdmux_accepted_frames_type accept_frame_type;
  18204. +};
  18205. +
  18206. +int dpdmux_if_get_attributes(struct fsl_mc_io *mc_io,
  18207. + u32 cmd_flags,
  18208. + u16 token,
  18209. + u16 if_id,
  18210. + struct dpdmux_if_attr *attr);
  18211. +
  18212. +int dpdmux_if_enable(struct fsl_mc_io *mc_io,
  18213. + u32 cmd_flags,
  18214. + u16 token,
  18215. + u16 if_id);
  18216. +
  18217. +int dpdmux_if_disable(struct fsl_mc_io *mc_io,
  18218. + u32 cmd_flags,
  18219. + u16 token,
  18220. + u16 if_id);
  18221. +
  18222. +/**
  18223. + * struct dpdmux_l2_rule - Structure representing L2 rule
  18224. + * @mac_addr: MAC address
  18225. + * @vlan_id: VLAN ID
  18226. + */
  18227. +struct dpdmux_l2_rule {
  18228. + u8 mac_addr[6];
  18229. + u16 vlan_id;
  18230. +};
  18231. +
  18232. +int dpdmux_if_remove_l2_rule(struct fsl_mc_io *mc_io,
  18233. + u32 cmd_flags,
  18234. + u16 token,
  18235. + u16 if_id,
  18236. + const struct dpdmux_l2_rule *rule);
  18237. +
  18238. +int dpdmux_if_add_l2_rule(struct fsl_mc_io *mc_io,
  18239. + u32 cmd_flags,
  18240. + u16 token,
  18241. + u16 if_id,
  18242. + const struct dpdmux_l2_rule *rule);
  18243. +
  18244. +int dpdmux_if_get_counter(struct fsl_mc_io *mc_io,
  18245. + u32 cmd_flags,
  18246. + u16 token,
  18247. + u16 if_id,
  18248. + enum dpdmux_counter_type counter_type,
  18249. + u64 *counter);
  18250. +
  18251. +int dpdmux_ul_reset_counters(struct fsl_mc_io *mc_io,
  18252. + u32 cmd_flags,
  18253. + u16 token);
  18254. +
  18255. +/**
  18256. + * Enable auto-negotiation
  18257. + */
  18258. +#define DPDMUX_LINK_OPT_AUTONEG 0x0000000000000001ULL
  18259. +/**
  18260. + * Enable half-duplex mode
  18261. + */
  18262. +#define DPDMUX_LINK_OPT_HALF_DUPLEX 0x0000000000000002ULL
  18263. +/**
  18264. + * Enable pause frames
  18265. + */
  18266. +#define DPDMUX_LINK_OPT_PAUSE 0x0000000000000004ULL
  18267. +/**
  18268. + * Enable a-symmetric pause frames
  18269. + */
  18270. +#define DPDMUX_LINK_OPT_ASYM_PAUSE 0x0000000000000008ULL
  18271. +
  18272. +/**
  18273. + * struct dpdmux_link_cfg - Structure representing DPDMUX link configuration
  18274. + * @rate: Rate
  18275. + * @options: Mask of available options; use 'DPDMUX_LINK_OPT_<X>' values
  18276. + */
  18277. +struct dpdmux_link_cfg {
  18278. + u32 rate;
  18279. + u64 options;
  18280. +};
  18281. +
  18282. +int dpdmux_if_set_link_cfg(struct fsl_mc_io *mc_io,
  18283. + u32 cmd_flags,
  18284. + u16 token,
  18285. + u16 if_id,
  18286. + struct dpdmux_link_cfg *cfg);
  18287. +/**
  18288. + * struct dpdmux_link_state - Structure representing DPDMUX link state
  18289. + * @rate: Rate
  18290. + * @options: Mask of available options; use 'DPDMUX_LINK_OPT_<X>' values
  18291. + * @up: 0 - down, 1 - up
  18292. + */
  18293. +struct dpdmux_link_state {
  18294. + u32 rate;
  18295. + u64 options;
  18296. + int up;
  18297. +};
  18298. +
  18299. +int dpdmux_if_get_link_state(struct fsl_mc_io *mc_io,
  18300. + u32 cmd_flags,
  18301. + u16 token,
  18302. + u16 if_id,
  18303. + struct dpdmux_link_state *state);
  18304. +
  18305. +int dpdmux_set_custom_key(struct fsl_mc_io *mc_io,
  18306. + u32 cmd_flags,
  18307. + u16 token,
  18308. + u64 key_cfg_iova);
  18309. +
  18310. +/**
  18311. + * struct dpdmux_rule_cfg - Custom classification rule.
  18312. + *
  18313. + * @key_iova: DMA address of buffer storing the look-up value
  18314. + * @mask_iova: DMA address of the mask used for TCAM classification
  18315. + * @key_size: size, in bytes, of the look-up value. This must match the size
  18316. + * of the look-up key defined using dpdmux_set_custom_key, otherwise the
  18317. + * entry will never be hit
  18318. + */
  18319. +struct dpdmux_rule_cfg {
  18320. + u64 key_iova;
  18321. + u64 mask_iova;
  18322. + u8 key_size;
  18323. +};
  18324. +
  18325. +/**
  18326. + * struct dpdmux_cls_action - Action to execute for frames matching the
  18327. + * classification entry
  18328. + *
  18329. + * @dest_if: Interface to forward the frames to. Port numbering is similar to
  18330. + * the one used to connect interfaces:
  18331. + * - 0 is the uplink port,
  18332. + * - all others are downlink ports.
  18333. + */
  18334. +struct dpdmux_cls_action {
  18335. + u16 dest_if;
  18336. +};
  18337. +
  18338. +int dpdmux_add_custom_cls_entry(struct fsl_mc_io *mc_io,
  18339. + u32 cmd_flags,
  18340. + u16 token,
  18341. + struct dpdmux_rule_cfg *rule,
  18342. + struct dpdmux_cls_action *action);
  18343. +
  18344. +int dpdmux_remove_custom_cls_entry(struct fsl_mc_io *mc_io,
  18345. + u32 cmd_flags,
  18346. + u16 token,
  18347. + struct dpdmux_rule_cfg *rule);
  18348. +
  18349. +int dpdmux_get_api_version(struct fsl_mc_io *mc_io,
  18350. + u32 cmd_flags,
  18351. + u16 *major_ver,
  18352. + u16 *minor_ver);
  18353. +
  18354. +#endif /* __FSL_DPDMUX_H */
  18355. --- /dev/null
  18356. +++ b/drivers/staging/fsl-dpaa2/evb/evb.c
  18357. @@ -0,0 +1,1350 @@
  18358. +/* Copyright 2015 Freescale Semiconductor Inc.
  18359. + *
  18360. + * Redistribution and use in source and binary forms, with or without
  18361. + * modification, are permitted provided that the following conditions are met:
  18362. + * * Redistributions of source code must retain the above copyright
  18363. + * notice, this list of conditions and the following disclaimer.
  18364. + * * Redistributions in binary form must reproduce the above copyright
  18365. + * notice, this list of conditions and the following disclaimer in the
  18366. + * documentation and/or other materials provided with the distribution.
  18367. + * * Neither the name of Freescale Semiconductor nor the
  18368. + * names of its contributors may be used to endorse or promote products
  18369. + * derived from this software without specific prior written permission.
  18370. + *
  18371. + *
  18372. + * ALTERNATIVELY, this software may be distributed under the terms of the
  18373. + * GNU General Public License ("GPL") as published by the Free Software
  18374. + * Foundation, either version 2 of that License or (at your option) any
  18375. + * later version.
  18376. + *
  18377. + * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
  18378. + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  18379. + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  18380. + * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
  18381. + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  18382. + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  18383. + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  18384. + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  18385. + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  18386. + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  18387. + */
  18388. +#include <linux/module.h>
  18389. +#include <linux/msi.h>
  18390. +#include <linux/netdevice.h>
  18391. +#include <linux/etherdevice.h>
  18392. +#include <linux/rtnetlink.h>
  18393. +#include <linux/if_vlan.h>
  18394. +
  18395. +#include <uapi/linux/if_bridge.h>
  18396. +#include <net/netlink.h>
  18397. +
  18398. +#include "../../fsl-mc/include/mc.h"
  18399. +
  18400. +#include "dpdmux.h"
  18401. +#include "dpdmux-cmd.h"
  18402. +
  18403. +static const char evb_drv_version[] = "0.1";
  18404. +
  18405. +/* Minimal supported DPDMUX version */
  18406. +#define DPDMUX_MIN_VER_MAJOR 6
  18407. +#define DPDMUX_MIN_VER_MINOR 0
  18408. +
  18409. +/* IRQ index */
  18410. +#define DPDMUX_MAX_IRQ_NUM 2
  18411. +
  18412. +/* MAX FRAME LENGTH (currently 10k) */
  18413. +#define EVB_MAX_FRAME_LENGTH (10 * 1024)
  18414. +/* MIN FRAME LENGTH (64 bytes + 4 bytes CRC) */
  18415. +#define EVB_MIN_FRAME_LENGTH 68
  18416. +
  18417. +struct evb_port_priv {
  18418. + struct net_device *netdev;
  18419. + struct list_head list;
  18420. + u16 port_index;
  18421. + struct evb_priv *evb_priv;
  18422. + u8 vlans[VLAN_VID_MASK + 1];
  18423. +};
  18424. +
  18425. +struct evb_priv {
  18426. + /* keep first */
  18427. + struct evb_port_priv uplink;
  18428. +
  18429. + struct fsl_mc_io *mc_io;
  18430. + struct list_head port_list;
  18431. + struct dpdmux_attr attr;
  18432. + u16 mux_handle;
  18433. + int dev_id;
  18434. +};
  18435. +
  18436. +static int _evb_port_carrier_state_sync(struct net_device *netdev)
  18437. +{
  18438. + struct evb_port_priv *port_priv = netdev_priv(netdev);
  18439. + struct dpdmux_link_state state;
  18440. + int err;
  18441. +
  18442. + err = dpdmux_if_get_link_state(port_priv->evb_priv->mc_io, 0,
  18443. + port_priv->evb_priv->mux_handle,
  18444. + port_priv->port_index, &state);
  18445. + if (unlikely(err)) {
  18446. + netdev_err(netdev, "dpdmux_if_get_link_state() err %d\n", err);
  18447. + return err;
  18448. + }
  18449. +
  18450. + WARN_ONCE(state.up > 1, "Garbage read into link_state");
  18451. +
  18452. + if (state.up)
  18453. + netif_carrier_on(port_priv->netdev);
  18454. + else
  18455. + netif_carrier_off(port_priv->netdev);
  18456. +
  18457. + return 0;
  18458. +}
  18459. +
  18460. +static int evb_port_open(struct net_device *netdev)
  18461. +{
  18462. + int err;
  18463. +
  18464. + /* FIXME: enable port when support added */
  18465. +
  18466. + err = _evb_port_carrier_state_sync(netdev);
  18467. + if (err) {
  18468. + netdev_err(netdev, "ethsw_port_carrier_state_sync err %d\n",
  18469. + err);
  18470. + return err;
  18471. + }
  18472. +
  18473. + return 0;
  18474. +}
  18475. +
  18476. +static netdev_tx_t evb_dropframe(struct sk_buff *skb, struct net_device *dev)
  18477. +{
  18478. + /* we don't support I/O for now, drop the frame */
  18479. + dev_kfree_skb_any(skb);
  18480. + return NETDEV_TX_OK;
  18481. +}
  18482. +
  18483. +static int evb_links_state_update(struct evb_priv *priv)
  18484. +{
  18485. + struct evb_port_priv *port_priv;
  18486. + struct list_head *pos;
  18487. + int err;
  18488. +
  18489. + list_for_each(pos, &priv->port_list) {
  18490. + port_priv = list_entry(pos, struct evb_port_priv, list);
  18491. +
  18492. + err = _evb_port_carrier_state_sync(port_priv->netdev);
  18493. + if (err)
  18494. + netdev_err(port_priv->netdev,
  18495. + "_evb_port_carrier_state_sync err %d\n",
  18496. + err);
  18497. + }
  18498. +
  18499. + return 0;
  18500. +}
  18501. +
  18502. +static irqreturn_t evb_irq0_handler(int irq_num, void *arg)
  18503. +{
  18504. + return IRQ_WAKE_THREAD;
  18505. +}
  18506. +
  18507. +static irqreturn_t _evb_irq0_handler_thread(int irq_num, void *arg)
  18508. +{
  18509. + struct device *dev = (struct device *)arg;
  18510. + struct fsl_mc_device *evb_dev = to_fsl_mc_device(dev);
  18511. + struct net_device *netdev = dev_get_drvdata(dev);
  18512. + struct evb_priv *priv = netdev_priv(netdev);
  18513. + struct fsl_mc_io *io = priv->mc_io;
  18514. + u16 token = priv->mux_handle;
  18515. + int irq_index = DPDMUX_IRQ_INDEX_IF;
  18516. +
  18517. + /* Mask the events and the if_id reserved bits to be cleared on read */
  18518. + u32 status = DPDMUX_IRQ_EVENT_LINK_CHANGED | 0xFFFF0000;
  18519. + int err;
  18520. +
  18521. + /* Sanity check */
  18522. + if (WARN_ON(!evb_dev || !evb_dev->irqs || !evb_dev->irqs[irq_index]))
  18523. + goto out;
  18524. + if (WARN_ON(evb_dev->irqs[irq_index]->msi_desc->irq != (u32)irq_num))
  18525. + goto out;
  18526. +
  18527. + err = dpdmux_get_irq_status(io, 0, token, irq_index, &status);
  18528. + if (unlikely(err)) {
  18529. + netdev_err(netdev, "Can't get irq status (err %d)", err);
  18530. + err = dpdmux_clear_irq_status(io, 0, token, irq_index,
  18531. + 0xFFFFFFFF);
  18532. + if (unlikely(err))
  18533. + netdev_err(netdev, "Can't clear irq status (err %d)",
  18534. + err);
  18535. + goto out;
  18536. + }
  18537. +
  18538. + if (status & DPDMUX_IRQ_EVENT_LINK_CHANGED) {
  18539. + err = evb_links_state_update(priv);
  18540. + if (unlikely(err))
  18541. + goto out;
  18542. + }
  18543. +
  18544. +out:
  18545. + return IRQ_HANDLED;
  18546. +}
  18547. +
  18548. +static int evb_setup_irqs(struct fsl_mc_device *evb_dev)
  18549. +{
  18550. + struct device *dev = &evb_dev->dev;
  18551. + struct net_device *netdev = dev_get_drvdata(dev);
  18552. + struct evb_priv *priv = netdev_priv(netdev);
  18553. + int err = 0;
  18554. + struct fsl_mc_device_irq *irq;
  18555. + const int irq_index = DPDMUX_IRQ_INDEX_IF;
  18556. + u32 mask = DPDMUX_IRQ_EVENT_LINK_CHANGED;
  18557. +
  18558. + err = fsl_mc_allocate_irqs(evb_dev);
  18559. + if (unlikely(err)) {
  18560. + dev_err(dev, "MC irqs allocation failed\n");
  18561. + return err;
  18562. + }
  18563. +
  18564. + if (WARN_ON(evb_dev->obj_desc.irq_count != DPDMUX_MAX_IRQ_NUM)) {
  18565. + err = -EINVAL;
  18566. + goto free_irq;
  18567. + }
  18568. +
  18569. + err = dpdmux_set_irq_enable(priv->mc_io, 0, priv->mux_handle,
  18570. + irq_index, 0);
  18571. + if (unlikely(err)) {
  18572. + dev_err(dev, "dpdmux_set_irq_enable err %d\n", err);
  18573. + goto free_irq;
  18574. + }
  18575. +
  18576. + irq = evb_dev->irqs[irq_index];
  18577. +
  18578. + err = devm_request_threaded_irq(dev, irq->msi_desc->irq,
  18579. + evb_irq0_handler,
  18580. + _evb_irq0_handler_thread,
  18581. + IRQF_NO_SUSPEND | IRQF_ONESHOT,
  18582. + dev_name(dev), dev);
  18583. + if (unlikely(err)) {
  18584. + dev_err(dev, "devm_request_threaded_irq(): %d", err);
  18585. + goto free_irq;
  18586. + }
  18587. +
  18588. + err = dpdmux_set_irq_mask(priv->mc_io, 0, priv->mux_handle,
  18589. + irq_index, mask);
  18590. + if (unlikely(err)) {
  18591. + dev_err(dev, "dpdmux_set_irq_mask(): %d", err);
  18592. + goto free_devm_irq;
  18593. + }
  18594. +
  18595. + err = dpdmux_set_irq_enable(priv->mc_io, 0, priv->mux_handle,
  18596. + irq_index, 1);
  18597. + if (unlikely(err)) {
  18598. + dev_err(dev, "dpdmux_set_irq_enable(): %d", err);
  18599. + goto free_devm_irq;
  18600. + }
  18601. +
  18602. + return 0;
  18603. +
  18604. +free_devm_irq:
  18605. + devm_free_irq(dev, irq->msi_desc->irq, dev);
  18606. +free_irq:
  18607. + fsl_mc_free_irqs(evb_dev);
  18608. + return err;
  18609. +}
  18610. +
  18611. +static void evb_teardown_irqs(struct fsl_mc_device *evb_dev)
  18612. +{
  18613. + struct device *dev = &evb_dev->dev;
  18614. + struct net_device *netdev = dev_get_drvdata(dev);
  18615. + struct evb_priv *priv = netdev_priv(netdev);
  18616. +
  18617. + dpdmux_set_irq_enable(priv->mc_io, 0, priv->mux_handle,
  18618. + DPDMUX_IRQ_INDEX_IF, 0);
  18619. +
  18620. + devm_free_irq(dev,
  18621. + evb_dev->irqs[DPDMUX_IRQ_INDEX_IF]->msi_desc->irq,
  18622. + dev);
  18623. + fsl_mc_free_irqs(evb_dev);
  18624. +}
  18625. +
  18626. +static int evb_port_add_rule(struct net_device *netdev,
  18627. + const unsigned char *addr, u16 vid)
  18628. +{
  18629. + struct evb_port_priv *port_priv = netdev_priv(netdev);
  18630. + struct dpdmux_l2_rule rule = { .vlan_id = vid };
  18631. + int err;
  18632. +
  18633. + if (addr)
  18634. + ether_addr_copy(rule.mac_addr, addr);
  18635. +
  18636. + err = dpdmux_if_add_l2_rule(port_priv->evb_priv->mc_io,
  18637. + 0,
  18638. + port_priv->evb_priv->mux_handle,
  18639. + port_priv->port_index, &rule);
  18640. + if (unlikely(err))
  18641. + netdev_err(netdev, "dpdmux_if_add_l2_rule err %d\n", err);
  18642. + return err;
  18643. +}
  18644. +
  18645. +static int evb_port_del_rule(struct net_device *netdev,
  18646. + const unsigned char *addr, u16 vid)
  18647. +{
  18648. + struct evb_port_priv *port_priv = netdev_priv(netdev);
  18649. + struct dpdmux_l2_rule rule = { .vlan_id = vid };
  18650. + int err;
  18651. +
  18652. + if (addr)
  18653. + ether_addr_copy(rule.mac_addr, addr);
  18654. +
  18655. + err = dpdmux_if_remove_l2_rule(port_priv->evb_priv->mc_io,
  18656. + 0,
  18657. + port_priv->evb_priv->mux_handle,
  18658. + port_priv->port_index, &rule);
  18659. + if (unlikely(err))
  18660. + netdev_err(netdev, "dpdmux_if_remove_l2_rule err %d\n", err);
  18661. + return err;
  18662. +}
  18663. +
  18664. +static bool _lookup_address(struct net_device *netdev,
  18665. + const unsigned char *addr)
  18666. +{
  18667. + struct netdev_hw_addr *ha;
  18668. + struct netdev_hw_addr_list *list = (is_unicast_ether_addr(addr)) ?
  18669. + &netdev->uc : &netdev->mc;
  18670. +
  18671. + netif_addr_lock_bh(netdev);
  18672. + list_for_each_entry(ha, &list->list, list) {
  18673. + if (ether_addr_equal(ha->addr, addr)) {
  18674. + netif_addr_unlock_bh(netdev);
  18675. + return true;
  18676. + }
  18677. + }
  18678. + netif_addr_unlock_bh(netdev);
  18679. + return false;
  18680. +}
  18681. +
  18682. +static inline int evb_port_fdb_prep(struct nlattr *tb[],
  18683. + struct net_device *netdev,
  18684. + const unsigned char *addr, u16 *vid,
  18685. + bool del)
  18686. +{
  18687. + struct evb_port_priv *port_priv = netdev_priv(netdev);
  18688. + struct evb_priv *evb_priv = port_priv->evb_priv;
  18689. +
  18690. + *vid = 0;
  18691. +
  18692. + if (evb_priv->attr.method != DPDMUX_METHOD_MAC &&
  18693. + evb_priv->attr.method != DPDMUX_METHOD_C_VLAN_MAC) {
  18694. + netdev_err(netdev,
  18695. + "EVB mode does not support MAC classification\n");
  18696. + return -EOPNOTSUPP;
  18697. + }
  18698. +
  18699. + /* check if the address is configured on this port */
  18700. + if (_lookup_address(netdev, addr)) {
  18701. + if (!del)
  18702. + return -EEXIST;
  18703. + } else {
  18704. + if (del)
  18705. + return -ENOENT;
  18706. + }
  18707. +
  18708. + if (tb[NDA_VLAN] && evb_priv->attr.method == DPDMUX_METHOD_C_VLAN_MAC) {
  18709. + if (nla_len(tb[NDA_VLAN]) != sizeof(unsigned short)) {
  18710. + netdev_err(netdev, "invalid vlan size %d\n",
  18711. + nla_len(tb[NDA_VLAN]));
  18712. + return -EINVAL;
  18713. + }
  18714. +
  18715. + *vid = nla_get_u16(tb[NDA_VLAN]);
  18716. +
  18717. + if (!*vid || *vid >= VLAN_VID_MASK) {
  18718. + netdev_err(netdev, "invalid vid value 0x%04x\n", *vid);
  18719. + return -EINVAL;
  18720. + }
  18721. + } else if (evb_priv->attr.method == DPDMUX_METHOD_C_VLAN_MAC) {
  18722. + netdev_err(netdev,
  18723. + "EVB mode requires explicit VLAN configuration\n");
  18724. + return -EINVAL;
  18725. + } else if (tb[NDA_VLAN]) {
  18726. + netdev_warn(netdev, "VLAN not supported, argument ignored\n");
  18727. + }
  18728. +
  18729. + return 0;
  18730. +}
  18731. +
  18732. +static int evb_port_fdb_add(struct ndmsg *ndm, struct nlattr *tb[],
  18733. + struct net_device *netdev,
  18734. + const unsigned char *addr, u16 vid, u16 flags)
  18735. +{
  18736. + u16 _vid;
  18737. + int err;
  18738. +
  18739. + /* TODO: add replace support when added to iproute bridge */
  18740. + if (!(flags & NLM_F_REQUEST)) {
  18741. + netdev_err(netdev,
  18742. + "evb_port_fdb_add unexpected flags value %08x\n",
  18743. + flags);
  18744. + return -EINVAL;
  18745. + }
  18746. +
  18747. + err = evb_port_fdb_prep(tb, netdev, addr, &_vid, 0);
  18748. + if (unlikely(err))
  18749. + return err;
  18750. +
  18751. + err = evb_port_add_rule(netdev, addr, _vid);
  18752. + if (unlikely(err))
  18753. + return err;
  18754. +
  18755. + if (is_unicast_ether_addr(addr)) {
  18756. + err = dev_uc_add(netdev, addr);
  18757. + if (unlikely(err)) {
  18758. + netdev_err(netdev, "dev_uc_add err %d\n", err);
  18759. + return err;
  18760. + }
  18761. + } else {
  18762. + err = dev_mc_add(netdev, addr);
  18763. + if (unlikely(err)) {
  18764. + netdev_err(netdev, "dev_mc_add err %d\n", err);
  18765. + return err;
  18766. + }
  18767. + }
  18768. +
  18769. + return 0;
  18770. +}
  18771. +
  18772. +static int evb_port_fdb_del(struct ndmsg *ndm, struct nlattr *tb[],
  18773. + struct net_device *netdev,
  18774. + const unsigned char *addr, u16 vid)
  18775. +{
  18776. + u16 _vid;
  18777. + int err;
  18778. +
  18779. + err = evb_port_fdb_prep(tb, netdev, addr, &_vid, 1);
  18780. + if (unlikely(err))
  18781. + return err;
  18782. +
  18783. + err = evb_port_del_rule(netdev, addr, _vid);
  18784. + if (unlikely(err))
  18785. + return err;
  18786. +
  18787. + if (is_unicast_ether_addr(addr)) {
  18788. + err = dev_uc_del(netdev, addr);
  18789. + if (unlikely(err)) {
  18790. + netdev_err(netdev, "dev_uc_del err %d\n", err);
  18791. + return err;
  18792. + }
  18793. + } else {
  18794. + err = dev_mc_del(netdev, addr);
  18795. + if (unlikely(err)) {
  18796. + netdev_err(netdev, "dev_mc_del err %d\n", err);
  18797. + return err;
  18798. + }
  18799. + }
  18800. +
  18801. + return 0;
  18802. +}
  18803. +
  18804. +static int evb_change_mtu(struct net_device *netdev,
  18805. + int mtu)
  18806. +{
  18807. + struct evb_port_priv *port_priv = netdev_priv(netdev);
  18808. + struct evb_priv *evb_priv = port_priv->evb_priv;
  18809. + struct list_head *pos;
  18810. + int err = 0;
  18811. +
  18812. + /* This operation is not permitted on downlinks */
  18813. + if (port_priv->port_index > 0)
  18814. + return -EPERM;
  18815. +
  18816. + if (mtu < EVB_MIN_FRAME_LENGTH || mtu > EVB_MAX_FRAME_LENGTH) {
  18817. + netdev_err(netdev, "Invalid MTU %d. Valid range is: %d..%d\n",
  18818. + mtu, EVB_MIN_FRAME_LENGTH, EVB_MAX_FRAME_LENGTH);
  18819. + return -EINVAL;
  18820. + }
  18821. +
  18822. + err = dpdmux_set_max_frame_length(evb_priv->mc_io,
  18823. + 0,
  18824. + evb_priv->mux_handle,
  18825. + (uint16_t)mtu);
  18826. +
  18827. + if (unlikely(err)) {
  18828. + netdev_err(netdev, "dpdmux_ul_set_max_frame_length err %d\n",
  18829. + err);
  18830. + return err;
  18831. + }
  18832. +
  18833. + /* Update the max frame length for downlinks */
  18834. + list_for_each(pos, &evb_priv->port_list) {
  18835. + port_priv = list_entry(pos, struct evb_port_priv, list);
  18836. + port_priv->netdev->mtu = mtu;
  18837. + }
  18838. +
  18839. + netdev->mtu = mtu;
  18840. + return 0;
  18841. +}
  18842. +
  18843. +static const struct nla_policy ifla_br_policy[IFLA_MAX + 1] = {
  18844. + [IFLA_BRIDGE_FLAGS] = { .type = NLA_U16 },
  18845. + [IFLA_BRIDGE_MODE] = { .type = NLA_U16 },
  18846. + [IFLA_BRIDGE_VLAN_INFO] = { .type = NLA_BINARY,
  18847. + .len = sizeof(struct bridge_vlan_info), },
  18848. +};
  18849. +
  18850. +static int evb_setlink_af_spec(struct net_device *netdev,
  18851. + struct nlattr **tb)
  18852. +{
  18853. + struct bridge_vlan_info *vinfo;
  18854. + struct evb_port_priv *port_priv = netdev_priv(netdev);
  18855. + int err = 0;
  18856. +
  18857. + if (!tb[IFLA_BRIDGE_VLAN_INFO]) {
  18858. + netdev_err(netdev, "no VLAN INFO in nlmsg\n");
  18859. + return -EOPNOTSUPP;
  18860. + }
  18861. +
  18862. + vinfo = nla_data(tb[IFLA_BRIDGE_VLAN_INFO]);
  18863. +
  18864. + if (!vinfo->vid || vinfo->vid > VLAN_VID_MASK)
  18865. + return -EINVAL;
  18866. +
  18867. + err = evb_port_add_rule(netdev, NULL, vinfo->vid);
  18868. + if (unlikely(err))
  18869. + return err;
  18870. +
  18871. + port_priv->vlans[vinfo->vid] = 1;
  18872. +
  18873. + return 0;
  18874. +}
  18875. +
  18876. +static int evb_setlink(struct net_device *netdev,
  18877. + struct nlmsghdr *nlh,
  18878. + u16 flags)
  18879. +{
  18880. + struct evb_port_priv *port_priv = netdev_priv(netdev);
  18881. + struct evb_priv *evb_priv = port_priv->evb_priv;
  18882. + struct nlattr *attr;
  18883. + struct nlattr *tb[(IFLA_BRIDGE_MAX > IFLA_BRPORT_MAX) ?
  18884. + IFLA_BRIDGE_MAX : IFLA_BRPORT_MAX + 1];
  18885. + int err = 0;
  18886. +
  18887. + if (evb_priv->attr.method != DPDMUX_METHOD_C_VLAN &&
  18888. + evb_priv->attr.method != DPDMUX_METHOD_S_VLAN) {
  18889. + netdev_err(netdev,
  18890. + "EVB mode does not support VLAN only classification\n");
  18891. + return -EOPNOTSUPP;
  18892. + }
  18893. +
  18894. + attr = nlmsg_find_attr(nlh, sizeof(struct ifinfomsg), IFLA_AF_SPEC);
  18895. + if (attr) {
  18896. + err = nla_parse_nested(tb, IFLA_BRIDGE_MAX, attr,
  18897. + ifla_br_policy);
  18898. + if (unlikely(err)) {
  18899. + netdev_err(netdev,
  18900. + "nla_parse_nested for br_policy err %d\n",
  18901. + err);
  18902. + return err;
  18903. + }
  18904. +
  18905. + err = evb_setlink_af_spec(netdev, tb);
  18906. + return err;
  18907. + }
  18908. +
  18909. + netdev_err(netdev, "nlmsg_find_attr found no AF_SPEC\n");
  18910. + return -EOPNOTSUPP;
  18911. +}
  18912. +
  18913. +static int __nla_put_netdev(struct sk_buff *skb, struct net_device *netdev)
  18914. +{
  18915. + struct evb_port_priv *port_priv = netdev_priv(netdev);
  18916. + struct evb_priv *evb_priv = port_priv->evb_priv;
  18917. + u8 operstate = netif_running(netdev) ?
  18918. + netdev->operstate : IF_OPER_DOWN;
  18919. + int iflink;
  18920. + int err;
  18921. +
  18922. + err = nla_put_string(skb, IFLA_IFNAME, netdev->name);
  18923. + if (unlikely(err))
  18924. + goto nla_put_err;
  18925. + err = nla_put_u32(skb, IFLA_MASTER, evb_priv->uplink.netdev->ifindex);
  18926. + if (unlikely(err))
  18927. + goto nla_put_err;
  18928. + err = nla_put_u32(skb, IFLA_MTU, netdev->mtu);
  18929. + if (unlikely(err))
  18930. + goto nla_put_err;
  18931. + err = nla_put_u8(skb, IFLA_OPERSTATE, operstate);
  18932. + if (unlikely(err))
  18933. + goto nla_put_err;
  18934. + if (netdev->addr_len) {
  18935. + err = nla_put(skb, IFLA_ADDRESS, netdev->addr_len,
  18936. + netdev->dev_addr);
  18937. + if (unlikely(err))
  18938. + goto nla_put_err;
  18939. + }
  18940. +
  18941. + iflink = dev_get_iflink(netdev);
  18942. + if (netdev->ifindex != iflink) {
  18943. + err = nla_put_u32(skb, IFLA_LINK, iflink);
  18944. + if (unlikely(err))
  18945. + goto nla_put_err;
  18946. + }
  18947. +
  18948. + return 0;
  18949. +
  18950. +nla_put_err:
  18951. + netdev_err(netdev, "nla_put_ err %d\n", err);
  18952. + return err;
  18953. +}
  18954. +
  18955. +static int __nla_put_port(struct sk_buff *skb, struct net_device *netdev)
  18956. +{
  18957. + struct nlattr *nest;
  18958. + int err;
  18959. +
  18960. + nest = nla_nest_start(skb, IFLA_PROTINFO | NLA_F_NESTED);
  18961. + if (!nest) {
  18962. + netdev_err(netdev, "nla_nest_start failed\n");
  18963. + return -ENOMEM;
  18964. + }
  18965. +
  18966. + err = nla_put_u8(skb, IFLA_BRPORT_STATE, BR_STATE_FORWARDING);
  18967. + if (unlikely(err))
  18968. + goto nla_put_err;
  18969. + err = nla_put_u16(skb, IFLA_BRPORT_PRIORITY, 0);
  18970. + if (unlikely(err))
  18971. + goto nla_put_err;
  18972. + err = nla_put_u32(skb, IFLA_BRPORT_COST, 0);
  18973. + if (unlikely(err))
  18974. + goto nla_put_err;
  18975. + err = nla_put_u8(skb, IFLA_BRPORT_MODE, 0);
  18976. + if (unlikely(err))
  18977. + goto nla_put_err;
  18978. + err = nla_put_u8(skb, IFLA_BRPORT_GUARD, 0);
  18979. + if (unlikely(err))
  18980. + goto nla_put_err;
  18981. + err = nla_put_u8(skb, IFLA_BRPORT_PROTECT, 0);
  18982. + if (unlikely(err))
  18983. + goto nla_put_err;
  18984. + err = nla_put_u8(skb, IFLA_BRPORT_FAST_LEAVE, 0);
  18985. + if (unlikely(err))
  18986. + goto nla_put_err;
  18987. + err = nla_put_u8(skb, IFLA_BRPORT_LEARNING, 0);
  18988. + if (unlikely(err))
  18989. + goto nla_put_err;
  18990. + err = nla_put_u8(skb, IFLA_BRPORT_UNICAST_FLOOD, 1);
  18991. + if (unlikely(err))
  18992. + goto nla_put_err;
  18993. + nla_nest_end(skb, nest);
  18994. +
  18995. + return 0;
  18996. +
  18997. +nla_put_err:
  18998. + netdev_err(netdev, "nla_put_ err %d\n", err);
  18999. + nla_nest_cancel(skb, nest);
  19000. + return err;
  19001. +}
  19002. +
  19003. +static int __nla_put_vlan(struct sk_buff *skb, struct net_device *netdev)
  19004. +{
  19005. + struct evb_port_priv *port_priv = netdev_priv(netdev);
  19006. + struct nlattr *nest;
  19007. + struct bridge_vlan_info vinfo;
  19008. + const u8 *vlans = port_priv->vlans;
  19009. + u16 i;
  19010. + int err;
  19011. +
  19012. + nest = nla_nest_start(skb, IFLA_AF_SPEC);
  19013. + if (!nest) {
  19014. + netdev_err(netdev, "nla_nest_start failed");
  19015. + return -ENOMEM;
  19016. + }
  19017. +
  19018. + for (i = 0; i < VLAN_VID_MASK + 1; i++) {
  19019. + if (!vlans[i])
  19020. + continue;
  19021. +
  19022. + vinfo.flags = 0;
  19023. + vinfo.vid = i;
  19024. +
  19025. + err = nla_put(skb, IFLA_BRIDGE_VLAN_INFO,
  19026. + sizeof(vinfo), &vinfo);
  19027. + if (unlikely(err))
  19028. + goto nla_put_err;
  19029. + }
  19030. +
  19031. + nla_nest_end(skb, nest);
  19032. +
  19033. + return 0;
  19034. +
  19035. +nla_put_err:
  19036. + netdev_err(netdev, "nla_put_ err %d\n", err);
  19037. + nla_nest_cancel(skb, nest);
  19038. + return err;
  19039. +}
  19040. +
  19041. +static int evb_getlink(struct sk_buff *skb, u32 pid, u32 seq,
  19042. + struct net_device *netdev, u32 filter_mask, int nlflags)
  19043. +{
  19044. + struct evb_port_priv *port_priv = netdev_priv(netdev);
  19045. + struct evb_priv *evb_priv = port_priv->evb_priv;
  19046. + struct ifinfomsg *hdr;
  19047. + struct nlmsghdr *nlh;
  19048. + int err;
  19049. +
  19050. + if (evb_priv->attr.method != DPDMUX_METHOD_C_VLAN &&
  19051. + evb_priv->attr.method != DPDMUX_METHOD_S_VLAN) {
  19052. + return 0;
  19053. + }
  19054. +
  19055. + nlh = nlmsg_put(skb, pid, seq, RTM_NEWLINK, sizeof(*hdr), NLM_F_MULTI);
  19056. + if (!nlh)
  19057. + return -EMSGSIZE;
  19058. +
  19059. + hdr = nlmsg_data(nlh);
  19060. + memset(hdr, 0, sizeof(*hdr));
  19061. + hdr->ifi_family = AF_BRIDGE;
  19062. + hdr->ifi_type = netdev->type;
  19063. + hdr->ifi_index = netdev->ifindex;
  19064. + hdr->ifi_flags = dev_get_flags(netdev);
  19065. +
  19066. + err = __nla_put_netdev(skb, netdev);
  19067. + if (unlikely(err))
  19068. + goto nla_put_err;
  19069. +
  19070. + err = __nla_put_port(skb, netdev);
  19071. + if (unlikely(err))
  19072. + goto nla_put_err;
  19073. +
  19074. + /* Check if the VID information is requested */
  19075. + if (filter_mask & RTEXT_FILTER_BRVLAN) {
  19076. + err = __nla_put_vlan(skb, netdev);
  19077. + if (unlikely(err))
  19078. + goto nla_put_err;
  19079. + }
  19080. +
  19081. + nlmsg_end(skb, nlh);
  19082. + return skb->len;
  19083. +
  19084. +nla_put_err:
  19085. + nlmsg_cancel(skb, nlh);
  19086. + return -EMSGSIZE;
  19087. +}
  19088. +
  19089. +static int evb_dellink(struct net_device *netdev,
  19090. + struct nlmsghdr *nlh,
  19091. + u16 flags)
  19092. +{
  19093. + struct nlattr *tb[IFLA_BRIDGE_MAX + 1];
  19094. + struct nlattr *spec;
  19095. + struct bridge_vlan_info *vinfo;
  19096. + struct evb_port_priv *port_priv = netdev_priv(netdev);
  19097. + int err = 0;
  19098. +
  19099. + spec = nlmsg_find_attr(nlh, sizeof(struct ifinfomsg), IFLA_AF_SPEC);
  19100. + if (!spec)
  19101. + return 0;
  19102. +
  19103. + err = nla_parse_nested(tb, IFLA_BRIDGE_MAX, spec, ifla_br_policy);
  19104. + if (unlikely(err))
  19105. + return err;
  19106. +
  19107. + if (!tb[IFLA_BRIDGE_VLAN_INFO])
  19108. + return -EOPNOTSUPP;
  19109. +
  19110. + vinfo = nla_data(tb[IFLA_BRIDGE_VLAN_INFO]);
  19111. +
  19112. + if (!vinfo->vid || vinfo->vid > VLAN_VID_MASK)
  19113. + return -EINVAL;
  19114. +
  19115. + err = evb_port_del_rule(netdev, NULL, vinfo->vid);
  19116. + if (unlikely(err)) {
  19117. + netdev_err(netdev, "evb_port_del_rule err %d\n", err);
  19118. + return err;
  19119. + }
  19120. + port_priv->vlans[vinfo->vid] = 0;
  19121. +
  19122. + return 0;
  19123. +}
  19124. +
  19125. +void evb_port_get_stats(struct net_device *netdev,
  19126. + struct rtnl_link_stats64 *storage)
  19127. +{
  19128. + struct evb_port_priv *port_priv = netdev_priv(netdev);
  19129. + u64 tmp;
  19130. + int err;
  19131. +
  19132. + err = dpdmux_if_get_counter(port_priv->evb_priv->mc_io,
  19133. + 0,
  19134. + port_priv->evb_priv->mux_handle,
  19135. + port_priv->port_index,
  19136. + DPDMUX_CNT_ING_FRAME, &storage->rx_packets);
  19137. + if (unlikely(err))
  19138. + goto error;
  19139. +
  19140. + err = dpdmux_if_get_counter(port_priv->evb_priv->mc_io,
  19141. + 0,
  19142. + port_priv->evb_priv->mux_handle,
  19143. + port_priv->port_index,
  19144. + DPDMUX_CNT_ING_BYTE, &storage->rx_bytes);
  19145. + if (unlikely(err))
  19146. + goto error;
  19147. +
  19148. + err = dpdmux_if_get_counter(port_priv->evb_priv->mc_io,
  19149. + 0,
  19150. + port_priv->evb_priv->mux_handle,
  19151. + port_priv->port_index,
  19152. + DPDMUX_CNT_ING_FLTR_FRAME, &tmp);
  19153. + if (unlikely(err))
  19154. + goto error;
  19155. +
  19156. + err = dpdmux_if_get_counter(port_priv->evb_priv->mc_io,
  19157. + 0,
  19158. + port_priv->evb_priv->mux_handle,
  19159. + port_priv->port_index,
  19160. + DPDMUX_CNT_ING_FRAME_DISCARD,
  19161. + &storage->rx_dropped);
  19162. + if (unlikely(err)) {
  19163. + storage->rx_dropped = tmp;
  19164. + goto error;
  19165. + }
  19166. + storage->rx_dropped += tmp;
  19167. +
  19168. + err = dpdmux_if_get_counter(port_priv->evb_priv->mc_io,
  19169. + 0,
  19170. + port_priv->evb_priv->mux_handle,
  19171. + port_priv->port_index,
  19172. + DPDMUX_CNT_ING_MCAST_FRAME,
  19173. + &storage->multicast);
  19174. + if (unlikely(err))
  19175. + goto error;
  19176. +
  19177. + err = dpdmux_if_get_counter(port_priv->evb_priv->mc_io,
  19178. + 0,
  19179. + port_priv->evb_priv->mux_handle,
  19180. + port_priv->port_index,
  19181. + DPDMUX_CNT_EGR_FRAME, &storage->tx_packets);
  19182. + if (unlikely(err))
  19183. + goto error;
  19184. +
  19185. + err = dpdmux_if_get_counter(port_priv->evb_priv->mc_io,
  19186. + 0,
  19187. + port_priv->evb_priv->mux_handle,
  19188. + port_priv->port_index,
  19189. + DPDMUX_CNT_EGR_BYTE, &storage->tx_bytes);
  19190. + if (unlikely(err))
  19191. + goto error;
  19192. +
  19193. + err = dpdmux_if_get_counter(port_priv->evb_priv->mc_io,
  19194. + 0,
  19195. + port_priv->evb_priv->mux_handle,
  19196. + port_priv->port_index,
  19197. + DPDMUX_CNT_EGR_FRAME_DISCARD,
  19198. + &storage->tx_dropped);
  19199. + if (unlikely(err))
  19200. + goto error;
  19201. +
  19202. + return;
  19203. +
  19204. +error:
  19205. + netdev_err(netdev, "dpdmux_if_get_counter err %d\n", err);
  19206. +}
  19207. +
  19208. +static const struct net_device_ops evb_port_ops = {
  19209. + .ndo_open = &evb_port_open,
  19210. +
  19211. + .ndo_start_xmit = &evb_dropframe,
  19212. +
  19213. + .ndo_fdb_add = &evb_port_fdb_add,
  19214. + .ndo_fdb_del = &evb_port_fdb_del,
  19215. +
  19216. + .ndo_get_stats64 = &evb_port_get_stats,
  19217. + .ndo_change_mtu = &evb_change_mtu,
  19218. +};
  19219. +
  19220. +static void evb_get_drvinfo(struct net_device *netdev,
  19221. + struct ethtool_drvinfo *drvinfo)
  19222. +{
  19223. + struct evb_port_priv *port_priv = netdev_priv(netdev);
  19224. + u16 version_major, version_minor;
  19225. + int err;
  19226. +
  19227. + strlcpy(drvinfo->driver, KBUILD_MODNAME, sizeof(drvinfo->driver));
  19228. + strlcpy(drvinfo->version, evb_drv_version, sizeof(drvinfo->version));
  19229. +
  19230. + err = dpdmux_get_api_version(port_priv->evb_priv->mc_io, 0,
  19231. + &version_major,
  19232. + &version_minor);
  19233. + if (err)
  19234. + strlcpy(drvinfo->fw_version, "N/A",
  19235. + sizeof(drvinfo->fw_version));
  19236. + else
  19237. + snprintf(drvinfo->fw_version, sizeof(drvinfo->fw_version),
  19238. + "%u.%u", version_major, version_minor);
  19239. +
  19240. + strlcpy(drvinfo->bus_info, dev_name(netdev->dev.parent->parent),
  19241. + sizeof(drvinfo->bus_info));
  19242. +}
  19243. +
  19244. +static int evb_get_settings(struct net_device *netdev,
  19245. + struct ethtool_cmd *cmd)
  19246. +{
  19247. + struct evb_port_priv *port_priv = netdev_priv(netdev);
  19248. + struct dpdmux_link_state state = {0};
  19249. + int err = 0;
  19250. +
  19251. + err = dpdmux_if_get_link_state(port_priv->evb_priv->mc_io, 0,
  19252. + port_priv->evb_priv->mux_handle,
  19253. + port_priv->port_index,
  19254. + &state);
  19255. + if (err) {
  19256. + netdev_err(netdev, "ERROR %d getting link state", err);
  19257. + goto out;
  19258. + }
  19259. +
  19260. + /* At the moment, we have no way of interrogating the DPMAC
  19261. + * from the DPDMUX side or there may not exist a DPMAC at all.
  19262. + * Report only autoneg state, duplexity and speed.
  19263. + */
  19264. + if (state.options & DPDMUX_LINK_OPT_AUTONEG)
  19265. + cmd->autoneg = AUTONEG_ENABLE;
  19266. + if (!(state.options & DPDMUX_LINK_OPT_HALF_DUPLEX))
  19267. + cmd->duplex = DUPLEX_FULL;
  19268. + ethtool_cmd_speed_set(cmd, state.rate);
  19269. +
  19270. +out:
  19271. + return err;
  19272. +}
  19273. +
  19274. +static int evb_set_settings(struct net_device *netdev,
  19275. + struct ethtool_cmd *cmd)
  19276. +{
  19277. + struct evb_port_priv *port_priv = netdev_priv(netdev);
  19278. + struct dpdmux_link_state state = {0};
  19279. + struct dpdmux_link_cfg cfg = {0};
  19280. + int err = 0;
  19281. +
  19282. + netdev_dbg(netdev, "Setting link parameters...");
  19283. +
  19284. + err = dpdmux_if_get_link_state(port_priv->evb_priv->mc_io, 0,
  19285. + port_priv->evb_priv->mux_handle,
  19286. + port_priv->port_index,
  19287. + &state);
  19288. + if (err) {
  19289. + netdev_err(netdev, "ERROR %d getting link state", err);
  19290. + goto out;
  19291. + }
  19292. +
  19293. + /* Due to a temporary MC limitation, the DPDMUX port must be down
  19294. + * in order to be able to change link settings. Taking steps to let
  19295. + * the user know that.
  19296. + */
  19297. + if (netif_running(netdev)) {
  19298. + netdev_info(netdev,
  19299. + "Sorry, interface must be brought down first.\n");
  19300. + return -EACCES;
  19301. + }
  19302. +
  19303. + cfg.options = state.options;
  19304. + cfg.rate = ethtool_cmd_speed(cmd);
  19305. + if (cmd->autoneg == AUTONEG_ENABLE)
  19306. + cfg.options |= DPDMUX_LINK_OPT_AUTONEG;
  19307. + else
  19308. + cfg.options &= ~DPDMUX_LINK_OPT_AUTONEG;
  19309. + if (cmd->duplex == DUPLEX_HALF)
  19310. + cfg.options |= DPDMUX_LINK_OPT_HALF_DUPLEX;
  19311. + else
  19312. + cfg.options &= ~DPDMUX_LINK_OPT_HALF_DUPLEX;
  19313. +
  19314. + err = dpdmux_if_set_link_cfg(port_priv->evb_priv->mc_io, 0,
  19315. + port_priv->evb_priv->mux_handle,
  19316. + port_priv->port_index,
  19317. + &cfg);
  19318. + if (err)
  19319. + /* ethtool will be loud enough if we return an error; no point
  19320. + * in putting our own error message on the console by default
  19321. + */
  19322. + netdev_dbg(netdev, "ERROR %d setting link cfg", err);
  19323. +
  19324. +out:
  19325. + return err;
  19326. +}
  19327. +
  19328. +static struct {
  19329. + enum dpdmux_counter_type id;
  19330. + char name[ETH_GSTRING_LEN];
  19331. +} evb_ethtool_counters[] = {
  19332. + {DPDMUX_CNT_ING_FRAME, "rx frames"},
  19333. + {DPDMUX_CNT_ING_BYTE, "rx bytes"},
  19334. + {DPDMUX_CNT_ING_FLTR_FRAME, "rx filtered frames"},
  19335. + {DPDMUX_CNT_ING_FRAME_DISCARD, "rx discarded frames"},
  19336. + {DPDMUX_CNT_ING_BCAST_FRAME, "rx b-cast frames"},
  19337. + {DPDMUX_CNT_ING_BCAST_BYTES, "rx b-cast bytes"},
  19338. + {DPDMUX_CNT_ING_MCAST_FRAME, "rx m-cast frames"},
  19339. + {DPDMUX_CNT_ING_MCAST_BYTE, "rx m-cast bytes"},
  19340. + {DPDMUX_CNT_EGR_FRAME, "tx frames"},
  19341. + {DPDMUX_CNT_EGR_BYTE, "tx bytes"},
  19342. + {DPDMUX_CNT_EGR_FRAME_DISCARD, "tx discarded frames"},
  19343. +};
  19344. +
  19345. +static int evb_ethtool_get_sset_count(struct net_device *dev, int sset)
  19346. +{
  19347. + switch (sset) {
  19348. + case ETH_SS_STATS:
  19349. + return ARRAY_SIZE(evb_ethtool_counters);
  19350. + default:
  19351. + return -EOPNOTSUPP;
  19352. + }
  19353. +}
  19354. +
  19355. +static void evb_ethtool_get_strings(struct net_device *netdev,
  19356. + u32 stringset, u8 *data)
  19357. +{
  19358. + u32 i;
  19359. +
  19360. + switch (stringset) {
  19361. + case ETH_SS_STATS:
  19362. + for (i = 0; i < ARRAY_SIZE(evb_ethtool_counters); i++)
  19363. + memcpy(data + i * ETH_GSTRING_LEN,
  19364. + evb_ethtool_counters[i].name, ETH_GSTRING_LEN);
  19365. + break;
  19366. + }
  19367. +}
  19368. +
  19369. +static void evb_ethtool_get_stats(struct net_device *netdev,
  19370. + struct ethtool_stats *stats,
  19371. + u64 *data)
  19372. +{
  19373. + struct evb_port_priv *port_priv = netdev_priv(netdev);
  19374. + u32 i;
  19375. + int err;
  19376. +
  19377. + for (i = 0; i < ARRAY_SIZE(evb_ethtool_counters); i++) {
  19378. + err = dpdmux_if_get_counter(port_priv->evb_priv->mc_io,
  19379. + 0,
  19380. + port_priv->evb_priv->mux_handle,
  19381. + port_priv->port_index,
  19382. + evb_ethtool_counters[i].id,
  19383. + &data[i]);
  19384. + if (err)
  19385. + netdev_err(netdev, "dpdmux_if_get_counter[%s] err %d\n",
  19386. + evb_ethtool_counters[i].name, err);
  19387. + }
  19388. +}
  19389. +
  19390. +static const struct ethtool_ops evb_port_ethtool_ops = {
  19391. + .get_drvinfo = &evb_get_drvinfo,
  19392. + .get_link = &ethtool_op_get_link,
  19393. + .get_settings = &evb_get_settings,
  19394. + .set_settings = &evb_set_settings,
  19395. + .get_strings = &evb_ethtool_get_strings,
  19396. + .get_ethtool_stats = &evb_ethtool_get_stats,
  19397. + .get_sset_count = &evb_ethtool_get_sset_count,
  19398. +};
  19399. +
  19400. +static int evb_open(struct net_device *netdev)
  19401. +{
  19402. + struct evb_priv *priv = netdev_priv(netdev);
  19403. + int err = 0;
  19404. +
  19405. + err = dpdmux_enable(priv->mc_io, 0, priv->mux_handle);
  19406. + if (unlikely(err))
  19407. + netdev_err(netdev, "dpdmux_enable err %d\n", err);
  19408. +
  19409. + return err;
  19410. +}
  19411. +
  19412. +static int evb_close(struct net_device *netdev)
  19413. +{
  19414. + struct evb_priv *priv = netdev_priv(netdev);
  19415. + int err = 0;
  19416. +
  19417. + err = dpdmux_disable(priv->mc_io, 0, priv->mux_handle);
  19418. + if (unlikely(err))
  19419. + netdev_err(netdev, "dpdmux_disable err %d\n", err);
  19420. +
  19421. + return err;
  19422. +}
  19423. +
  19424. +static const struct net_device_ops evb_ops = {
  19425. + .ndo_start_xmit = &evb_dropframe,
  19426. + .ndo_open = &evb_open,
  19427. + .ndo_stop = &evb_close,
  19428. +
  19429. + .ndo_bridge_setlink = &evb_setlink,
  19430. + .ndo_bridge_getlink = &evb_getlink,
  19431. + .ndo_bridge_dellink = &evb_dellink,
  19432. +
  19433. + .ndo_get_stats64 = &evb_port_get_stats,
  19434. + .ndo_change_mtu = &evb_change_mtu,
  19435. +};
  19436. +
  19437. +static int evb_takedown(struct fsl_mc_device *evb_dev)
  19438. +{
  19439. + struct device *dev = &evb_dev->dev;
  19440. + struct net_device *netdev = dev_get_drvdata(dev);
  19441. + struct evb_priv *priv = netdev_priv(netdev);
  19442. + int err;
  19443. +
  19444. + err = dpdmux_close(priv->mc_io, 0, priv->mux_handle);
  19445. + if (unlikely(err))
  19446. + dev_warn(dev, "dpdmux_close err %d\n", err);
  19447. +
  19448. + return 0;
  19449. +}
  19450. +
  19451. +static int evb_init(struct fsl_mc_device *evb_dev)
  19452. +{
  19453. + struct device *dev = &evb_dev->dev;
  19454. + struct net_device *netdev = dev_get_drvdata(dev);
  19455. + struct evb_priv *priv = netdev_priv(netdev);
  19456. + u16 version_major;
  19457. + u16 version_minor;
  19458. + int err = 0;
  19459. +
  19460. + priv->dev_id = evb_dev->obj_desc.id;
  19461. +
  19462. + err = dpdmux_open(priv->mc_io, 0, priv->dev_id, &priv->mux_handle);
  19463. + if (unlikely(err)) {
  19464. + dev_err(dev, "dpdmux_open err %d\n", err);
  19465. + goto err_exit;
  19466. + }
  19467. + if (!priv->mux_handle) {
  19468. + dev_err(dev, "dpdmux_open returned null handle but no error\n");
  19469. + err = -EFAULT;
  19470. + goto err_exit;
  19471. + }
  19472. +
  19473. + err = dpdmux_get_attributes(priv->mc_io, 0, priv->mux_handle,
  19474. + &priv->attr);
  19475. + if (unlikely(err)) {
  19476. + dev_err(dev, "dpdmux_get_attributes err %d\n", err);
  19477. + goto err_close;
  19478. + }
  19479. +
  19480. + err = dpdmux_get_api_version(priv->mc_io, 0,
  19481. + &version_major,
  19482. + &version_minor);
  19483. + if (unlikely(err)) {
  19484. + dev_err(dev, "dpdmux_get_api_version err %d\n", err);
  19485. + goto err_close;
  19486. + }
  19487. +
  19488. + /* Minimum supported DPDMUX version check */
  19489. + if (version_major < DPDMUX_MIN_VER_MAJOR ||
  19490. + (version_major == DPDMUX_MIN_VER_MAJOR &&
  19491. + version_minor < DPDMUX_MIN_VER_MINOR)) {
  19492. + dev_err(dev, "DPDMUX version %d.%d not supported. Use %d.%d or greater.\n",
  19493. + version_major, version_minor,
  19494. + DPDMUX_MIN_VER_MAJOR, DPDMUX_MIN_VER_MAJOR);
  19495. + err = -ENOTSUPP;
  19496. + goto err_close;
  19497. + }
  19498. +
  19499. + err = dpdmux_reset(priv->mc_io, 0, priv->mux_handle);
  19500. + if (unlikely(err)) {
  19501. + dev_err(dev, "dpdmux_reset err %d\n", err);
  19502. + goto err_close;
  19503. + }
  19504. +
  19505. + return 0;
  19506. +
  19507. +err_close:
  19508. + dpdmux_close(priv->mc_io, 0, priv->mux_handle);
  19509. +err_exit:
  19510. + return err;
  19511. +}
  19512. +
  19513. +static int evb_remove(struct fsl_mc_device *evb_dev)
  19514. +{
  19515. + struct device *dev = &evb_dev->dev;
  19516. + struct net_device *netdev = dev_get_drvdata(dev);
  19517. + struct evb_priv *priv = netdev_priv(netdev);
  19518. + struct evb_port_priv *port_priv;
  19519. + struct list_head *pos;
  19520. +
  19521. + list_for_each(pos, &priv->port_list) {
  19522. + port_priv = list_entry(pos, struct evb_port_priv, list);
  19523. +
  19524. + rtnl_lock();
  19525. + netdev_upper_dev_unlink(port_priv->netdev, netdev);
  19526. + rtnl_unlock();
  19527. +
  19528. + unregister_netdev(port_priv->netdev);
  19529. + free_netdev(port_priv->netdev);
  19530. + }
  19531. +
  19532. + evb_teardown_irqs(evb_dev);
  19533. +
  19534. + unregister_netdev(netdev);
  19535. +
  19536. + evb_takedown(evb_dev);
  19537. + fsl_mc_portal_free(priv->mc_io);
  19538. +
  19539. + dev_set_drvdata(dev, NULL);
  19540. + free_netdev(netdev);
  19541. +
  19542. + return 0;
  19543. +}
  19544. +
  19545. +static int evb_probe(struct fsl_mc_device *evb_dev)
  19546. +{
  19547. + struct device *dev;
  19548. + struct evb_priv *priv = NULL;
  19549. + struct net_device *netdev = NULL;
  19550. + char port_name[IFNAMSIZ];
  19551. + int i;
  19552. + int err = 0;
  19553. +
  19554. + dev = &evb_dev->dev;
  19555. +
  19556. + /* register switch device, it's for management only - no I/O */
  19557. + netdev = alloc_etherdev(sizeof(*priv));
  19558. + if (!netdev) {
  19559. + dev_err(dev, "alloc_etherdev error\n");
  19560. + return -ENOMEM;
  19561. + }
  19562. + netdev->netdev_ops = &evb_ops;
  19563. +
  19564. + dev_set_drvdata(dev, netdev);
  19565. +
  19566. + priv = netdev_priv(netdev);
  19567. +
  19568. + err = fsl_mc_portal_allocate(evb_dev, 0, &priv->mc_io);
  19569. + if (unlikely(err)) {
  19570. + dev_err(dev, "fsl_mc_portal_allocate err %d\n", err);
  19571. + goto err_free_netdev;
  19572. + }
  19573. + if (!priv->mc_io) {
  19574. + dev_err(dev, "fsl_mc_portal_allocate returned null handle but no error\n");
  19575. + err = -EFAULT;
  19576. + goto err_free_netdev;
  19577. + }
  19578. +
  19579. + err = evb_init(evb_dev);
  19580. + if (unlikely(err)) {
  19581. + dev_err(dev, "evb init err %d\n", err);
  19582. + goto err_free_cmdport;
  19583. + }
  19584. +
  19585. + INIT_LIST_HEAD(&priv->port_list);
  19586. + netdev->flags |= IFF_PROMISC | IFF_MASTER;
  19587. +
  19588. + dev_alloc_name(netdev, "evb%d");
  19589. +
  19590. + /* register switch ports */
  19591. + snprintf(port_name, IFNAMSIZ, "%sp%%d", netdev->name);
  19592. +
  19593. + /* only register downlinks? */
  19594. + for (i = 0; i < priv->attr.num_ifs + 1; i++) {
  19595. + struct net_device *port_netdev;
  19596. + struct evb_port_priv *port_priv;
  19597. +
  19598. + if (i) {
  19599. + port_netdev =
  19600. + alloc_etherdev(sizeof(struct evb_port_priv));
  19601. + if (!port_netdev) {
  19602. + dev_err(dev, "alloc_etherdev error\n");
  19603. + goto err_takedown;
  19604. + }
  19605. +
  19606. + port_priv = netdev_priv(port_netdev);
  19607. +
  19608. + port_netdev->flags |= IFF_PROMISC | IFF_SLAVE;
  19609. +
  19610. + dev_alloc_name(port_netdev, port_name);
  19611. + } else {
  19612. + port_netdev = netdev;
  19613. + port_priv = &priv->uplink;
  19614. + }
  19615. +
  19616. + port_priv->netdev = port_netdev;
  19617. + port_priv->evb_priv = priv;
  19618. + port_priv->port_index = i;
  19619. +
  19620. + SET_NETDEV_DEV(port_netdev, dev);
  19621. +
  19622. + if (i) {
  19623. + port_netdev->netdev_ops = &evb_port_ops;
  19624. +
  19625. + err = register_netdev(port_netdev);
  19626. + if (err < 0) {
  19627. + dev_err(dev, "register_netdev err %d\n", err);
  19628. + free_netdev(port_netdev);
  19629. + goto err_takedown;
  19630. + }
  19631. +
  19632. + rtnl_lock();
  19633. + err = netdev_master_upper_dev_link(port_netdev, netdev,
  19634. + NULL, NULL);
  19635. + if (unlikely(err)) {
  19636. + dev_err(dev, "netdev_master_upper_dev_link err %d\n",
  19637. + err);
  19638. + unregister_netdev(port_netdev);
  19639. + free_netdev(port_netdev);
  19640. + rtnl_unlock();
  19641. + goto err_takedown;
  19642. + }
  19643. + rtmsg_ifinfo(RTM_NEWLINK, port_netdev,
  19644. + IFF_SLAVE, GFP_KERNEL);
  19645. + rtnl_unlock();
  19646. +
  19647. + list_add(&port_priv->list, &priv->port_list);
  19648. + } else {
  19649. + err = register_netdev(netdev);
  19650. +
  19651. + if (err < 0) {
  19652. + dev_err(dev, "register_netdev error %d\n", err);
  19653. + goto err_takedown;
  19654. + }
  19655. + }
  19656. +
  19657. + port_netdev->ethtool_ops = &evb_port_ethtool_ops;
  19658. +
  19659. + /* ports are up from init */
  19660. + rtnl_lock();
  19661. + err = dev_open(port_netdev);
  19662. + rtnl_unlock();
  19663. + if (unlikely(err))
  19664. + dev_warn(dev, "dev_open err %d\n", err);
  19665. + }
  19666. +
  19667. + /* setup irqs */
  19668. + err = evb_setup_irqs(evb_dev);
  19669. + if (unlikely(err)) {
  19670. + dev_warn(dev, "evb_setup_irqs err %d\n", err);
  19671. + goto err_takedown;
  19672. + }
  19673. +
  19674. + dev_info(dev, "probed evb device with %d ports\n",
  19675. + priv->attr.num_ifs);
  19676. + return 0;
  19677. +
  19678. +err_takedown:
  19679. + evb_remove(evb_dev);
  19680. +err_free_cmdport:
  19681. + fsl_mc_portal_free(priv->mc_io);
  19682. +err_free_netdev:
  19683. + return err;
  19684. +}
  19685. +
  19686. +static const struct fsl_mc_device_id evb_match_id_table[] = {
  19687. + {
  19688. + .vendor = FSL_MC_VENDOR_FREESCALE,
  19689. + .obj_type = "dpdmux",
  19690. + },
  19691. + {}
  19692. +};
  19693. +
  19694. +static struct fsl_mc_driver evb_drv = {
  19695. + .driver = {
  19696. + .name = KBUILD_MODNAME,
  19697. + .owner = THIS_MODULE,
  19698. + },
  19699. + .probe = evb_probe,
  19700. + .remove = evb_remove,
  19701. + .match_id_table = evb_match_id_table,
  19702. +};
  19703. +
  19704. +module_fsl_mc_driver(evb_drv);
  19705. +
  19706. +MODULE_LICENSE("GPL");
  19707. +MODULE_DESCRIPTION("Layerscape DPAA Edge Virtual Bridge driver (prototype)");
  19708. --- /dev/null
  19709. +++ b/drivers/staging/fsl-dpaa2/mac/Kconfig
  19710. @@ -0,0 +1,23 @@
  19711. +config FSL_DPAA2_MAC
  19712. + tristate "DPAA2 MAC / PHY interface"
  19713. + depends on FSL_MC_BUS && FSL_DPAA2
  19714. + select MDIO_BUS_MUX_MMIOREG
  19715. + select FSL_XGMAC_MDIO
  19716. + select FIXED_PHY
  19717. + ---help---
  19718. + Prototype driver for DPAA2 MAC / PHY interface object.
  19719. + This driver works as a proxy between phylib including phy drivers and
  19720. + the MC firmware. It receives updates on link state changes from PHY
  19721. + lib and forwards them to MC and receives interrupt from MC whenever
  19722. + a request is made to change the link state.
  19723. +
  19724. +
  19725. +config FSL_DPAA2_MAC_NETDEVS
  19726. + bool "Expose net interfaces for PHYs"
  19727. + default n
  19728. + depends on FSL_DPAA2_MAC
  19729. + ---help---
  19730. + Exposes macX net interfaces which allow direct control over MACs and
  19731. + PHYs.
  19732. + .
  19733. + Leave disabled if unsure.
  19734. --- /dev/null
  19735. +++ b/drivers/staging/fsl-dpaa2/mac/Makefile
  19736. @@ -0,0 +1,10 @@
  19737. +
  19738. +obj-$(CONFIG_FSL_DPAA2_MAC) += dpaa2-mac.o
  19739. +
  19740. +dpaa2-mac-objs := mac.o dpmac.o
  19741. +
  19742. +all:
  19743. + make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules
  19744. +
  19745. +clean:
  19746. + make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean
  19747. --- /dev/null
  19748. +++ b/drivers/staging/fsl-dpaa2/mac/dpmac-cmd.h
  19749. @@ -0,0 +1,172 @@
  19750. +/* Copyright 2013-2016 Freescale Semiconductor Inc.
  19751. + *
  19752. + * Redistribution and use in source and binary forms, with or without
  19753. + * modification, are permitted provided that the following conditions are met:
  19754. + * * Redistributions of source code must retain the above copyright
  19755. + * notice, this list of conditions and the following disclaimer.
  19756. + * * Redistributions in binary form must reproduce the above copyright
  19757. + * notice, this list of conditions and the following disclaimer in the
  19758. + * documentation and/or other materials provided with the distribution.
  19759. + * * Neither the name of the above-listed copyright holders nor the
  19760. + * names of any contributors may be used to endorse or promote products
  19761. + * derived from this software without specific prior written permission.
  19762. + *
  19763. + *
  19764. + * ALTERNATIVELY, this software may be distributed under the terms of the
  19765. + * GNU General Public License ("GPL") as published by the Free Software
  19766. + * Foundation, either version 2 of that License or (at your option) any
  19767. + * later version.
  19768. + *
  19769. + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  19770. + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  19771. + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  19772. + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
  19773. + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  19774. + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  19775. + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  19776. + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  19777. + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  19778. + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  19779. + * POSSIBILITY OF SUCH DAMAGE.
  19780. + */
  19781. +#ifndef _FSL_DPMAC_CMD_H
  19782. +#define _FSL_DPMAC_CMD_H
  19783. +
  19784. +/* DPMAC Version */
  19785. +#define DPMAC_VER_MAJOR 4
  19786. +#define DPMAC_VER_MINOR 2
  19787. +#define DPMAC_CMD_BASE_VERSION 1
  19788. +#define DPMAC_CMD_ID_OFFSET 4
  19789. +
  19790. +#define DPMAC_CMD(id) (((id) << DPMAC_CMD_ID_OFFSET) | DPMAC_CMD_BASE_VERSION)
  19791. +
  19792. +/* Command IDs */
  19793. +#define DPMAC_CMDID_CLOSE DPMAC_CMD(0x800)
  19794. +#define DPMAC_CMDID_OPEN DPMAC_CMD(0x80c)
  19795. +#define DPMAC_CMDID_CREATE DPMAC_CMD(0x90c)
  19796. +#define DPMAC_CMDID_DESTROY DPMAC_CMD(0x98c)
  19797. +#define DPMAC_CMDID_GET_API_VERSION DPMAC_CMD(0xa0c)
  19798. +
  19799. +#define DPMAC_CMDID_GET_ATTR DPMAC_CMD(0x004)
  19800. +#define DPMAC_CMDID_RESET DPMAC_CMD(0x005)
  19801. +
  19802. +#define DPMAC_CMDID_SET_IRQ_ENABLE DPMAC_CMD(0x012)
  19803. +#define DPMAC_CMDID_GET_IRQ_ENABLE DPMAC_CMD(0x013)
  19804. +#define DPMAC_CMDID_SET_IRQ_MASK DPMAC_CMD(0x014)
  19805. +#define DPMAC_CMDID_GET_IRQ_MASK DPMAC_CMD(0x015)
  19806. +#define DPMAC_CMDID_GET_IRQ_STATUS DPMAC_CMD(0x016)
  19807. +#define DPMAC_CMDID_CLEAR_IRQ_STATUS DPMAC_CMD(0x017)
  19808. +
  19809. +#define DPMAC_CMDID_GET_LINK_CFG DPMAC_CMD(0x0c2)
  19810. +#define DPMAC_CMDID_SET_LINK_STATE DPMAC_CMD(0x0c3)
  19811. +#define DPMAC_CMDID_GET_COUNTER DPMAC_CMD(0x0c4)
  19812. +
  19813. +#define DPMAC_CMDID_SET_PORT_MAC_ADDR DPMAC_CMD(0x0c5)
  19814. +
  19815. +/* Macros for accessing command fields smaller than 1byte */
  19816. +#define DPMAC_MASK(field) \
  19817. + GENMASK(DPMAC_##field##_SHIFT + DPMAC_##field##_SIZE - 1, \
  19818. + DPMAC_##field##_SHIFT)
  19819. +#define dpmac_set_field(var, field, val) \
  19820. + ((var) |= (((val) << DPMAC_##field##_SHIFT) & DPMAC_MASK(field)))
  19821. +#define dpmac_get_field(var, field) \
  19822. + (((var) & DPMAC_MASK(field)) >> DPMAC_##field##_SHIFT)
  19823. +
  19824. +struct dpmac_cmd_open {
  19825. + u32 dpmac_id;
  19826. +};
  19827. +
  19828. +struct dpmac_cmd_create {
  19829. + u32 mac_id;
  19830. +};
  19831. +
  19832. +struct dpmac_cmd_destroy {
  19833. + u32 dpmac_id;
  19834. +};
  19835. +
  19836. +struct dpmac_cmd_set_irq_enable {
  19837. + u8 enable;
  19838. + u8 pad[3];
  19839. + u8 irq_index;
  19840. +};
  19841. +
  19842. +struct dpmac_cmd_get_irq_enable {
  19843. + u32 pad;
  19844. + u8 irq_index;
  19845. +};
  19846. +
  19847. +struct dpmac_rsp_get_irq_enable {
  19848. + u8 enabled;
  19849. +};
  19850. +
  19851. +struct dpmac_cmd_set_irq_mask {
  19852. + u32 mask;
  19853. + u8 irq_index;
  19854. +};
  19855. +
  19856. +struct dpmac_cmd_get_irq_mask {
  19857. + u32 pad;
  19858. + u8 irq_index;
  19859. +};
  19860. +
  19861. +struct dpmac_rsp_get_irq_mask {
  19862. + u32 mask;
  19863. +};
  19864. +
  19865. +struct dpmac_cmd_get_irq_status {
  19866. + u32 status;
  19867. + u8 irq_index;
  19868. +};
  19869. +
  19870. +struct dpmac_rsp_get_irq_status {
  19871. + u32 status;
  19872. +};
  19873. +
  19874. +struct dpmac_cmd_clear_irq_status {
  19875. + u32 status;
  19876. + u8 irq_index;
  19877. +};
  19878. +
  19879. +struct dpmac_rsp_get_attributes {
  19880. + u8 eth_if;
  19881. + u8 link_type;
  19882. + u16 id;
  19883. + u32 max_rate;
  19884. +};
  19885. +
  19886. +struct dpmac_rsp_get_link_cfg {
  19887. + u64 options;
  19888. + u32 rate;
  19889. +};
  19890. +
  19891. +#define DPMAC_STATE_SIZE 1
  19892. +#define DPMAC_STATE_SHIFT 0
  19893. +
  19894. +struct dpmac_cmd_set_link_state {
  19895. + u64 options;
  19896. + u32 rate;
  19897. + u32 pad;
  19898. + /* only least significant bit is valid */
  19899. + u8 up;
  19900. +};
  19901. +
  19902. +struct dpmac_cmd_get_counter {
  19903. + u8 type;
  19904. +};
  19905. +
  19906. +struct dpmac_rsp_get_counter {
  19907. + u64 pad;
  19908. + u64 counter;
  19909. +};
  19910. +
  19911. +struct dpmac_rsp_get_api_version {
  19912. + u16 major;
  19913. + u16 minor;
  19914. +};
  19915. +
  19916. +struct dpmac_cmd_set_port_mac_addr {
  19917. + u8 pad[2];
  19918. + u8 addr[6];
  19919. +};
  19920. +
  19921. +#endif /* _FSL_DPMAC_CMD_H */
  19922. --- /dev/null
  19923. +++ b/drivers/staging/fsl-dpaa2/mac/dpmac.c
  19924. @@ -0,0 +1,620 @@
  19925. +/* Copyright 2013-2016 Freescale Semiconductor Inc.
  19926. + *
  19927. + * Redistribution and use in source and binary forms, with or without
  19928. + * modification, are permitted provided that the following conditions are met:
  19929. + * * Redistributions of source code must retain the above copyright
  19930. + * notice, this list of conditions and the following disclaimer.
  19931. + * * Redistributions in binary form must reproduce the above copyright
  19932. + * notice, this list of conditions and the following disclaimer in the
  19933. + * documentation and/or other materials provided with the distribution.
  19934. + * * Neither the name of the above-listed copyright holders nor the
  19935. + * names of any contributors may be used to endorse or promote products
  19936. + * derived from this software without specific prior written permission.
  19937. + *
  19938. + *
  19939. + * ALTERNATIVELY, this software may be distributed under the terms of the
  19940. + * GNU General Public License ("GPL") as published by the Free Software
  19941. + * Foundation, either version 2 of that License or (at your option) any
  19942. + * later version.
  19943. + *
  19944. + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  19945. + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  19946. + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  19947. + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
  19948. + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  19949. + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  19950. + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  19951. + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  19952. + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  19953. + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  19954. + * POSSIBILITY OF SUCH DAMAGE.
  19955. + */
  19956. +#include "../../fsl-mc/include/mc-sys.h"
  19957. +#include "../../fsl-mc/include/mc-cmd.h"
  19958. +#include "dpmac.h"
  19959. +#include "dpmac-cmd.h"
  19960. +
  19961. +/**
  19962. + * dpmac_open() - Open a control session for the specified object.
  19963. + * @mc_io: Pointer to MC portal's I/O object
  19964. + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
  19965. + * @dpmac_id: DPMAC unique ID
  19966. + * @token: Returned token; use in subsequent API calls
  19967. + *
  19968. + * This function can be used to open a control session for an
  19969. + * already created object; an object may have been declared in
  19970. + * the DPL or by calling the dpmac_create function.
  19971. + * This function returns a unique authentication token,
  19972. + * associated with the specific object ID and the specific MC
  19973. + * portal; this token must be used in all subsequent commands for
  19974. + * this specific object
  19975. + *
  19976. + * Return: '0' on Success; Error code otherwise.
  19977. + */
  19978. +int dpmac_open(struct fsl_mc_io *mc_io,
  19979. + u32 cmd_flags,
  19980. + int dpmac_id,
  19981. + u16 *token)
  19982. +{
  19983. + struct dpmac_cmd_open *cmd_params;
  19984. + struct mc_command cmd = { 0 };
  19985. + int err;
  19986. +
  19987. + /* prepare command */
  19988. + cmd.header = mc_encode_cmd_header(DPMAC_CMDID_OPEN,
  19989. + cmd_flags,
  19990. + 0);
  19991. + cmd_params = (struct dpmac_cmd_open *)cmd.params;
  19992. + cmd_params->dpmac_id = cpu_to_le32(dpmac_id);
  19993. +
  19994. + /* send command to mc*/
  19995. + err = mc_send_command(mc_io, &cmd);
  19996. + if (err)
  19997. + return err;
  19998. +
  19999. + /* retrieve response parameters */
  20000. + *token = mc_cmd_hdr_read_token(&cmd);
  20001. +
  20002. + return err;
  20003. +}
  20004. +
  20005. +/**
  20006. + * dpmac_close() - Close the control session of the object
  20007. + * @mc_io: Pointer to MC portal's I/O object
  20008. + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
  20009. + * @token: Token of DPMAC object
  20010. + *
  20011. + * After this function is called, no further operations are
  20012. + * allowed on the object without opening a new control session.
  20013. + *
  20014. + * Return: '0' on Success; Error code otherwise.
  20015. + */
  20016. +int dpmac_close(struct fsl_mc_io *mc_io,
  20017. + u32 cmd_flags,
  20018. + u16 token)
  20019. +{
  20020. + struct mc_command cmd = { 0 };
  20021. +
  20022. + /* prepare command */
  20023. + cmd.header = mc_encode_cmd_header(DPMAC_CMDID_CLOSE, cmd_flags,
  20024. + token);
  20025. +
  20026. + /* send command to mc*/
  20027. + return mc_send_command(mc_io, &cmd);
  20028. +}
  20029. +
  20030. +/**
  20031. + * dpmac_create() - Create the DPMAC object.
  20032. + * @mc_io: Pointer to MC portal's I/O object
  20033. + * @dprc_token: Parent container token; '0' for default container
  20034. + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
  20035. + * @cfg: Configuration structure
  20036. + * @obj_id: Returned object id
  20037. + *
  20038. + * Create the DPMAC object, allocate required resources and
  20039. + * perform required initialization.
  20040. + *
  20041. + * The function accepts an authentication token of a parent
  20042. + * container that this object should be assigned to. The token
  20043. + * can be '0' so the object will be assigned to the default container.
  20044. + * The newly created object can be opened with the returned
  20045. + * object id and using the container's associated tokens and MC portals.
  20046. + *
  20047. + * Return: '0' on Success; Error code otherwise.
  20048. + */
  20049. +int dpmac_create(struct fsl_mc_io *mc_io,
  20050. + u16 dprc_token,
  20051. + u32 cmd_flags,
  20052. + const struct dpmac_cfg *cfg,
  20053. + u32 *obj_id)
  20054. +{
  20055. + struct dpmac_cmd_create *cmd_params;
  20056. + struct mc_command cmd = { 0 };
  20057. + int err;
  20058. +
  20059. + /* prepare command */
  20060. + cmd.header = mc_encode_cmd_header(DPMAC_CMDID_CREATE,
  20061. + cmd_flags,
  20062. + dprc_token);
  20063. + cmd_params = (struct dpmac_cmd_create *)cmd.params;
  20064. + cmd_params->mac_id = cpu_to_le32(cfg->mac_id);
  20065. +
  20066. + /* send command to mc*/
  20067. + err = mc_send_command(mc_io, &cmd);
  20068. + if (err)
  20069. + return err;
  20070. +
  20071. + /* retrieve response parameters */
  20072. + *obj_id = mc_cmd_read_object_id(&cmd);
  20073. +
  20074. + return 0;
  20075. +}
  20076. +
  20077. +/**
  20078. + * dpmac_destroy() - Destroy the DPMAC object and release all its resources.
  20079. + * @mc_io: Pointer to MC portal's I/O object
  20080. + * @dprc_token: Parent container token; '0' for default container
  20081. + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
  20082. + * @object_id: The object id; it must be a valid id within the container that
  20083. + * created this object;
  20084. + *
  20085. + * The function accepts the authentication token of the parent container that
  20086. + * created the object (not the one that currently owns the object). The object
  20087. + * is searched within parent using the provided 'object_id'.
  20088. + * All tokens to the object must be closed before calling destroy.
  20089. + *
  20090. + * Return: '0' on Success; error code otherwise.
  20091. + */
  20092. +int dpmac_destroy(struct fsl_mc_io *mc_io,
  20093. + u16 dprc_token,
  20094. + u32 cmd_flags,
  20095. + u32 object_id)
  20096. +{
  20097. + struct dpmac_cmd_destroy *cmd_params;
  20098. + struct mc_command cmd = { 0 };
  20099. +
  20100. + /* prepare command */
  20101. + cmd.header = mc_encode_cmd_header(DPMAC_CMDID_DESTROY,
  20102. + cmd_flags,
  20103. + dprc_token);
  20104. + cmd_params = (struct dpmac_cmd_destroy *)cmd.params;
  20105. + cmd_params->dpmac_id = cpu_to_le32(object_id);
  20106. +
  20107. + /* send command to mc*/
  20108. + return mc_send_command(mc_io, &cmd);
  20109. +}
  20110. +
  20111. +/**
  20112. + * dpmac_set_irq_enable() - Set overall interrupt state.
  20113. + * @mc_io: Pointer to MC portal's I/O object
  20114. + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
  20115. + * @token: Token of DPMAC object
  20116. + * @irq_index: The interrupt index to configure
  20117. + * @en: Interrupt state - enable = 1, disable = 0
  20118. + *
  20119. + * Allows GPP software to control when interrupts are generated.
  20120. + * Each interrupt can have up to 32 causes. The enable/disable control's the
  20121. + * overall interrupt state. if the interrupt is disabled no causes will cause
  20122. + * an interrupt.
  20123. + *
  20124. + * Return: '0' on Success; Error code otherwise.
  20125. + */
  20126. +int dpmac_set_irq_enable(struct fsl_mc_io *mc_io,
  20127. + u32 cmd_flags,
  20128. + u16 token,
  20129. + u8 irq_index,
  20130. + u8 en)
  20131. +{
  20132. + struct dpmac_cmd_set_irq_enable *cmd_params;
  20133. + struct mc_command cmd = { 0 };
  20134. +
  20135. + /* prepare command */
  20136. + cmd.header = mc_encode_cmd_header(DPMAC_CMDID_SET_IRQ_ENABLE,
  20137. + cmd_flags,
  20138. + token);
  20139. + cmd_params = (struct dpmac_cmd_set_irq_enable *)cmd.params;
  20140. + cmd_params->irq_index = irq_index;
  20141. + cmd_params->enable = en;
  20142. +
  20143. + /* send command to mc*/
  20144. + return mc_send_command(mc_io, &cmd);
  20145. +}
  20146. +
  20147. +/**
  20148. + * dpmac_get_irq_enable() - Get overall interrupt state
  20149. + * @mc_io: Pointer to MC portal's I/O object
  20150. + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
  20151. + * @token: Token of DPMAC object
  20152. + * @irq_index: The interrupt index to configure
  20153. + * @en: Returned interrupt state - enable = 1, disable = 0
  20154. + *
  20155. + * Return: '0' on Success; Error code otherwise.
  20156. + */
  20157. +int dpmac_get_irq_enable(struct fsl_mc_io *mc_io,
  20158. + u32 cmd_flags,
  20159. + u16 token,
  20160. + u8 irq_index,
  20161. + u8 *en)
  20162. +{
  20163. + struct dpmac_cmd_get_irq_enable *cmd_params;
  20164. + struct dpmac_rsp_get_irq_enable *rsp_params;
  20165. + struct mc_command cmd = { 0 };
  20166. + int err;
  20167. +
  20168. + /* prepare command */
  20169. + cmd.header = mc_encode_cmd_header(DPMAC_CMDID_GET_IRQ_ENABLE,
  20170. + cmd_flags,
  20171. + token);
  20172. + cmd_params = (struct dpmac_cmd_get_irq_enable *)cmd.params;
  20173. + cmd_params->irq_index = irq_index;
  20174. +
  20175. + /* send command to mc*/
  20176. + err = mc_send_command(mc_io, &cmd);
  20177. + if (err)
  20178. + return err;
  20179. +
  20180. + /* retrieve response parameters */
  20181. + rsp_params = (struct dpmac_rsp_get_irq_enable *)cmd.params;
  20182. + *en = rsp_params->enabled;
  20183. +
  20184. + return 0;
  20185. +}
  20186. +
  20187. +/**
  20188. + * dpmac_set_irq_mask() - Set interrupt mask.
  20189. + * @mc_io: Pointer to MC portal's I/O object
  20190. + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
  20191. + * @token: Token of DPMAC object
  20192. + * @irq_index: The interrupt index to configure
  20193. + * @mask: Event mask to trigger interrupt;
  20194. + * each bit:
  20195. + * 0 = ignore event
  20196. + * 1 = consider event for asserting IRQ
  20197. + *
  20198. + * Every interrupt can have up to 32 causes and the interrupt model supports
  20199. + * masking/unmasking each cause independently
  20200. + *
  20201. + * Return: '0' on Success; Error code otherwise.
  20202. + */
  20203. +int dpmac_set_irq_mask(struct fsl_mc_io *mc_io,
  20204. + u32 cmd_flags,
  20205. + u16 token,
  20206. + u8 irq_index,
  20207. + u32 mask)
  20208. +{
  20209. + struct dpmac_cmd_set_irq_mask *cmd_params;
  20210. + struct mc_command cmd = { 0 };
  20211. +
  20212. + /* prepare command */
  20213. + cmd.header = mc_encode_cmd_header(DPMAC_CMDID_SET_IRQ_MASK,
  20214. + cmd_flags,
  20215. + token);
  20216. + cmd_params = (struct dpmac_cmd_set_irq_mask *)cmd.params;
  20217. + cmd_params->mask = cpu_to_le32(mask);
  20218. + cmd_params->irq_index = irq_index;
  20219. +
  20220. + /* send command to mc*/
  20221. + return mc_send_command(mc_io, &cmd);
  20222. +}
  20223. +
  20224. +/**
  20225. + * dpmac_get_irq_mask() - Get interrupt mask.
  20226. + * @mc_io: Pointer to MC portal's I/O object
  20227. + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
  20228. + * @token: Token of DPMAC object
  20229. + * @irq_index: The interrupt index to configure
  20230. + * @mask: Returned event mask to trigger interrupt
  20231. + *
  20232. + * Every interrupt can have up to 32 causes and the interrupt model supports
  20233. + * masking/unmasking each cause independently
  20234. + *
  20235. + * Return: '0' on Success; Error code otherwise.
  20236. + */
  20237. +int dpmac_get_irq_mask(struct fsl_mc_io *mc_io,
  20238. + u32 cmd_flags,
  20239. + u16 token,
  20240. + u8 irq_index,
  20241. + u32 *mask)
  20242. +{
  20243. + struct dpmac_cmd_get_irq_mask *cmd_params;
  20244. + struct dpmac_rsp_get_irq_mask *rsp_params;
  20245. + struct mc_command cmd = { 0 };
  20246. + int err;
  20247. +
  20248. + /* prepare command */
  20249. + cmd.header = mc_encode_cmd_header(DPMAC_CMDID_GET_IRQ_MASK,
  20250. + cmd_flags,
  20251. + token);
  20252. + cmd_params = (struct dpmac_cmd_get_irq_mask *)cmd.params;
  20253. + cmd_params->irq_index = irq_index;
  20254. +
  20255. + /* send command to mc*/
  20256. + err = mc_send_command(mc_io, &cmd);
  20257. + if (err)
  20258. + return err;
  20259. +
  20260. + /* retrieve response parameters */
  20261. + rsp_params = (struct dpmac_rsp_get_irq_mask *)cmd.params;
  20262. + *mask = le32_to_cpu(rsp_params->mask);
  20263. +
  20264. + return 0;
  20265. +}
  20266. +
  20267. +/**
  20268. + * dpmac_get_irq_status() - Get the current status of any pending interrupts.
  20269. + *
  20270. + * @mc_io: Pointer to MC portal's I/O object
  20271. + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
  20272. + * @token: Token of DPMAC object
  20273. + * @irq_index: The interrupt index to configure
  20274. + * @status: Returned interrupts status - one bit per cause:
  20275. + * 0 = no interrupt pending
  20276. + * 1 = interrupt pending
  20277. + *
  20278. + * Return: '0' on Success; Error code otherwise.
  20279. + */
  20280. +int dpmac_get_irq_status(struct fsl_mc_io *mc_io,
  20281. + u32 cmd_flags,
  20282. + u16 token,
  20283. + u8 irq_index,
  20284. + u32 *status)
  20285. +{
  20286. + struct dpmac_cmd_get_irq_status *cmd_params;
  20287. + struct dpmac_rsp_get_irq_status *rsp_params;
  20288. + struct mc_command cmd = { 0 };
  20289. + int err;
  20290. +
  20291. + /* prepare command */
  20292. + cmd.header = mc_encode_cmd_header(DPMAC_CMDID_GET_IRQ_STATUS,
  20293. + cmd_flags,
  20294. + token);
  20295. + cmd_params = (struct dpmac_cmd_get_irq_status *)cmd.params;
  20296. + cmd_params->status = cpu_to_le32(*status);
  20297. + cmd_params->irq_index = irq_index;
  20298. +
  20299. + /* send command to mc*/
  20300. + err = mc_send_command(mc_io, &cmd);
  20301. + if (err)
  20302. + return err;
  20303. +
  20304. + /* retrieve response parameters */
  20305. + rsp_params = (struct dpmac_rsp_get_irq_status *)cmd.params;
  20306. + *status = le32_to_cpu(rsp_params->status);
  20307. +
  20308. + return 0;
  20309. +}
  20310. +
  20311. +/**
  20312. + * dpmac_clear_irq_status() - Clear a pending interrupt's status
  20313. + *
  20314. + * @mc_io: Pointer to MC portal's I/O object
  20315. + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
  20316. + * @token: Token of DPMAC object
  20317. + * @irq_index: The interrupt index to configure
  20318. + * @status: Bits to clear (W1C) - one bit per cause:
  20319. + * 0 = don't change
  20320. + * 1 = clear status bit
  20321. + *
  20322. + * Return: '0' on Success; Error code otherwise.
  20323. + */
  20324. +int dpmac_clear_irq_status(struct fsl_mc_io *mc_io,
  20325. + u32 cmd_flags,
  20326. + u16 token,
  20327. + u8 irq_index,
  20328. + u32 status)
  20329. +{
  20330. + struct dpmac_cmd_clear_irq_status *cmd_params;
  20331. + struct mc_command cmd = { 0 };
  20332. +
  20333. + /* prepare command */
  20334. + cmd.header = mc_encode_cmd_header(DPMAC_CMDID_CLEAR_IRQ_STATUS,
  20335. + cmd_flags,
  20336. + token);
  20337. + cmd_params = (struct dpmac_cmd_clear_irq_status *)cmd.params;
  20338. + cmd_params->status = cpu_to_le32(status);
  20339. + cmd_params->irq_index = irq_index;
  20340. +
  20341. + /* send command to mc*/
  20342. + return mc_send_command(mc_io, &cmd);
  20343. +}
  20344. +
  20345. +/**
  20346. + * dpmac_get_attributes - Retrieve DPMAC attributes.
  20347. + *
  20348. + * @mc_io: Pointer to MC portal's I/O object
  20349. + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
  20350. + * @token: Token of DPMAC object
  20351. + * @attr: Returned object's attributes
  20352. + *
  20353. + * Return: '0' on Success; Error code otherwise.
  20354. + */
  20355. +int dpmac_get_attributes(struct fsl_mc_io *mc_io,
  20356. + u32 cmd_flags,
  20357. + u16 token,
  20358. + struct dpmac_attr *attr)
  20359. +{
  20360. + struct dpmac_rsp_get_attributes *rsp_params;
  20361. + struct mc_command cmd = { 0 };
  20362. + int err;
  20363. +
  20364. + /* prepare command */
  20365. + cmd.header = mc_encode_cmd_header(DPMAC_CMDID_GET_ATTR,
  20366. + cmd_flags,
  20367. + token);
  20368. +
  20369. + /* send command to mc*/
  20370. + err = mc_send_command(mc_io, &cmd);
  20371. + if (err)
  20372. + return err;
  20373. +
  20374. + /* retrieve response parameters */
  20375. + rsp_params = (struct dpmac_rsp_get_attributes *)cmd.params;
  20376. + attr->eth_if = rsp_params->eth_if;
  20377. + attr->link_type = rsp_params->link_type;
  20378. + attr->id = le16_to_cpu(rsp_params->id);
  20379. + attr->max_rate = le32_to_cpu(rsp_params->max_rate);
  20380. +
  20381. + return 0;
  20382. +}
  20383. +
  20384. +/**
  20385. + * dpmac_get_link_cfg() - Get Ethernet link configuration
  20386. + * @mc_io: Pointer to opaque I/O object
  20387. + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
  20388. + * @token: Token of DPMAC object
  20389. + * @cfg: Returned structure with the link configuration
  20390. + *
  20391. + * Return: '0' on Success; Error code otherwise.
  20392. + */
  20393. +int dpmac_get_link_cfg(struct fsl_mc_io *mc_io,
  20394. + u32 cmd_flags,
  20395. + u16 token,
  20396. + struct dpmac_link_cfg *cfg)
  20397. +{
  20398. + struct dpmac_rsp_get_link_cfg *rsp_params;
  20399. + struct mc_command cmd = { 0 };
  20400. + int err = 0;
  20401. +
  20402. + /* prepare command */
  20403. + cmd.header = mc_encode_cmd_header(DPMAC_CMDID_GET_LINK_CFG,
  20404. + cmd_flags,
  20405. + token);
  20406. +
  20407. + /* send command to mc*/
  20408. + err = mc_send_command(mc_io, &cmd);
  20409. + if (err)
  20410. + return err;
  20411. +
  20412. + rsp_params = (struct dpmac_rsp_get_link_cfg *)cmd.params;
  20413. + cfg->options = le64_to_cpu(rsp_params->options);
  20414. + cfg->rate = le32_to_cpu(rsp_params->rate);
  20415. +
  20416. + return 0;
  20417. +}
  20418. +
  20419. +/**
  20420. + * dpmac_set_link_state() - Set the Ethernet link status
  20421. + * @mc_io: Pointer to opaque I/O object
  20422. + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
  20423. + * @token: Token of DPMAC object
  20424. + * @link_state: Link state configuration
  20425. + *
  20426. + * Return: '0' on Success; Error code otherwise.
  20427. + */
  20428. +int dpmac_set_link_state(struct fsl_mc_io *mc_io,
  20429. + u32 cmd_flags,
  20430. + u16 token,
  20431. + struct dpmac_link_state *link_state)
  20432. +{
  20433. + struct dpmac_cmd_set_link_state *cmd_params;
  20434. + struct mc_command cmd = { 0 };
  20435. +
  20436. + /* prepare command */
  20437. + cmd.header = mc_encode_cmd_header(DPMAC_CMDID_SET_LINK_STATE,
  20438. + cmd_flags,
  20439. + token);
  20440. + cmd_params = (struct dpmac_cmd_set_link_state *)cmd.params;
  20441. + cmd_params->options = cpu_to_le64(link_state->options);
  20442. + cmd_params->rate = cpu_to_le32(link_state->rate);
  20443. + cmd_params->up = dpmac_get_field(link_state->up, STATE);
  20444. +
  20445. + /* send command to mc*/
  20446. + return mc_send_command(mc_io, &cmd);
  20447. +}
  20448. +
  20449. +/**
  20450. + * dpmac_get_counter() - Read a specific DPMAC counter
  20451. + * @mc_io: Pointer to opaque I/O object
  20452. + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
  20453. + * @token: Token of DPMAC object
  20454. + * @type: The requested counter
  20455. + * @counter: Returned counter value
  20456. + *
  20457. + * Return: The requested counter; '0' otherwise.
  20458. + */
  20459. +int dpmac_get_counter(struct fsl_mc_io *mc_io,
  20460. + u32 cmd_flags,
  20461. + u16 token,
  20462. + enum dpmac_counter type,
  20463. + u64 *counter)
  20464. +{
  20465. + struct dpmac_cmd_get_counter *dpmac_cmd;
  20466. + struct dpmac_rsp_get_counter *dpmac_rsp;
  20467. + struct mc_command cmd = { 0 };
  20468. + int err = 0;
  20469. +
  20470. + /* prepare command */
  20471. + cmd.header = mc_encode_cmd_header(DPMAC_CMDID_GET_COUNTER,
  20472. + cmd_flags,
  20473. + token);
  20474. + dpmac_cmd = (struct dpmac_cmd_get_counter *)cmd.params;
  20475. + dpmac_cmd->type = type;
  20476. +
  20477. + /* send command to mc*/
  20478. + err = mc_send_command(mc_io, &cmd);
  20479. + if (err)
  20480. + return err;
  20481. +
  20482. + dpmac_rsp = (struct dpmac_rsp_get_counter *)cmd.params;
  20483. + *counter = le64_to_cpu(dpmac_rsp->counter);
  20484. +
  20485. + return 0;
  20486. +}
  20487. +
  20488. +/* untested */
  20489. +int dpmac_set_port_mac_addr(struct fsl_mc_io *mc_io,
  20490. + u32 cmd_flags,
  20491. + u16 token,
  20492. + const u8 addr[6])
  20493. +{
  20494. + struct dpmac_cmd_set_port_mac_addr *dpmac_cmd;
  20495. + struct mc_command cmd = { 0 };
  20496. +
  20497. + /* prepare command */
  20498. + cmd.header = mc_encode_cmd_header(DPMAC_CMDID_SET_PORT_MAC_ADDR,
  20499. + cmd_flags,
  20500. + token);
  20501. + dpmac_cmd = (struct dpmac_cmd_set_port_mac_addr *)cmd.params;
  20502. + dpmac_cmd->addr[0] = addr[5];
  20503. + dpmac_cmd->addr[1] = addr[4];
  20504. + dpmac_cmd->addr[2] = addr[3];
  20505. + dpmac_cmd->addr[3] = addr[2];
  20506. + dpmac_cmd->addr[4] = addr[1];
  20507. + dpmac_cmd->addr[5] = addr[0];
  20508. +
  20509. + /* send command to mc*/
  20510. + return mc_send_command(mc_io, &cmd);
  20511. +}
  20512. +
  20513. +/**
  20514. + * dpmac_get_api_version() - Get Data Path MAC version
  20515. + * @mc_io: Pointer to MC portal's I/O object
  20516. + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
  20517. + * @major_ver: Major version of data path mac API
  20518. + * @minor_ver: Minor version of data path mac API
  20519. + *
  20520. + * Return: '0' on Success; Error code otherwise.
  20521. + */
  20522. +int dpmac_get_api_version(struct fsl_mc_io *mc_io,
  20523. + u32 cmd_flags,
  20524. + u16 *major_ver,
  20525. + u16 *minor_ver)
  20526. +{
  20527. + struct dpmac_rsp_get_api_version *rsp_params;
  20528. + struct mc_command cmd = { 0 };
  20529. + int err;
  20530. +
  20531. + cmd.header = mc_encode_cmd_header(DPMAC_CMDID_GET_API_VERSION,
  20532. + cmd_flags,
  20533. + 0);
  20534. +
  20535. + err = mc_send_command(mc_io, &cmd);
  20536. + if (err)
  20537. + return err;
  20538. +
  20539. + rsp_params = (struct dpmac_rsp_get_api_version *)cmd.params;
  20540. + *major_ver = le16_to_cpu(rsp_params->major);
  20541. + *minor_ver = le16_to_cpu(rsp_params->minor);
  20542. +
  20543. + return 0;
  20544. +}
  20545. --- /dev/null
  20546. +++ b/drivers/staging/fsl-dpaa2/mac/dpmac.h
  20547. @@ -0,0 +1,342 @@
  20548. +/* Copyright 2013-2016 Freescale Semiconductor Inc.
  20549. + *
  20550. + * Redistribution and use in source and binary forms, with or without
  20551. + * modification, are permitted provided that the following conditions are met:
  20552. + * * Redistributions of source code must retain the above copyright
  20553. + * notice, this list of conditions and the following disclaimer.
  20554. + * * Redistributions in binary form must reproduce the above copyright
  20555. + * notice, this list of conditions and the following disclaimer in the
  20556. + * documentation and/or other materials provided with the distribution.
  20557. + * * Neither the name of the above-listed copyright holders nor the
  20558. + * names of any contributors may be used to endorse or promote products
  20559. + * derived from this software without specific prior written permission.
  20560. + *
  20561. + *
  20562. + * ALTERNATIVELY, this software may be distributed under the terms of the
  20563. + * GNU General Public License ("GPL") as published by the Free Software
  20564. + * Foundation, either version 2 of that License or (at your option) any
  20565. + * later version.
  20566. + *
  20567. + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  20568. + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  20569. + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  20570. + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
  20571. + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  20572. + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  20573. + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  20574. + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  20575. + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  20576. + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  20577. + * POSSIBILITY OF SUCH DAMAGE.
  20578. + */
  20579. +#ifndef __FSL_DPMAC_H
  20580. +#define __FSL_DPMAC_H
  20581. +
  20582. +/* Data Path MAC API
  20583. + * Contains initialization APIs and runtime control APIs for DPMAC
  20584. + */
  20585. +
  20586. +struct fsl_mc_io;
  20587. +
  20588. +int dpmac_open(struct fsl_mc_io *mc_io,
  20589. + u32 cmd_flags,
  20590. + int dpmac_id,
  20591. + u16 *token);
  20592. +
  20593. +int dpmac_close(struct fsl_mc_io *mc_io,
  20594. + u32 cmd_flags,
  20595. + u16 token);
  20596. +
  20597. +/**
  20598. + * enum dpmac_link_type - DPMAC link type
  20599. + * @DPMAC_LINK_TYPE_NONE: No link
  20600. + * @DPMAC_LINK_TYPE_FIXED: Link is fixed type
  20601. + * @DPMAC_LINK_TYPE_PHY: Link by PHY ID
  20602. + * @DPMAC_LINK_TYPE_BACKPLANE: Backplane link type
  20603. + */
  20604. +enum dpmac_link_type {
  20605. + DPMAC_LINK_TYPE_NONE,
  20606. + DPMAC_LINK_TYPE_FIXED,
  20607. + DPMAC_LINK_TYPE_PHY,
  20608. + DPMAC_LINK_TYPE_BACKPLANE
  20609. +};
  20610. +
  20611. +/**
  20612. + * enum dpmac_eth_if - DPMAC Ethrnet interface
  20613. + * @DPMAC_ETH_IF_MII: MII interface
  20614. + * @DPMAC_ETH_IF_RMII: RMII interface
  20615. + * @DPMAC_ETH_IF_SMII: SMII interface
  20616. + * @DPMAC_ETH_IF_GMII: GMII interface
  20617. + * @DPMAC_ETH_IF_RGMII: RGMII interface
  20618. + * @DPMAC_ETH_IF_SGMII: SGMII interface
  20619. + * @DPMAC_ETH_IF_QSGMII: QSGMII interface
  20620. + * @DPMAC_ETH_IF_XAUI: XAUI interface
  20621. + * @DPMAC_ETH_IF_XFI: XFI interface
  20622. + */
  20623. +enum dpmac_eth_if {
  20624. + DPMAC_ETH_IF_MII,
  20625. + DPMAC_ETH_IF_RMII,
  20626. + DPMAC_ETH_IF_SMII,
  20627. + DPMAC_ETH_IF_GMII,
  20628. + DPMAC_ETH_IF_RGMII,
  20629. + DPMAC_ETH_IF_SGMII,
  20630. + DPMAC_ETH_IF_QSGMII,
  20631. + DPMAC_ETH_IF_XAUI,
  20632. + DPMAC_ETH_IF_XFI
  20633. +};
  20634. +
  20635. +/**
  20636. + * struct dpmac_cfg - Structure representing DPMAC configuration
  20637. + * @mac_id: Represents the Hardware MAC ID; in case of multiple WRIOP,
  20638. + * the MAC IDs are continuous.
  20639. + * For example: 2 WRIOPs, 16 MACs in each:
  20640. + * MAC IDs for the 1st WRIOP: 1-16,
  20641. + * MAC IDs for the 2nd WRIOP: 17-32.
  20642. + */
  20643. +struct dpmac_cfg {
  20644. + u16 mac_id;
  20645. +};
  20646. +
  20647. +int dpmac_create(struct fsl_mc_io *mc_io,
  20648. + u16 dprc_token,
  20649. + u32 cmd_flags,
  20650. + const struct dpmac_cfg *cfg,
  20651. + u32 *obj_id);
  20652. +
  20653. +int dpmac_destroy(struct fsl_mc_io *mc_io,
  20654. + u16 dprc_token,
  20655. + u32 cmd_flags,
  20656. + u32 object_id);
  20657. +
  20658. +/**
  20659. + * DPMAC IRQ Index and Events
  20660. + */
  20661. +
  20662. +/**
  20663. + * IRQ index
  20664. + */
  20665. +#define DPMAC_IRQ_INDEX 0
  20666. +/**
  20667. + * IRQ event - indicates a change in link state
  20668. + */
  20669. +#define DPMAC_IRQ_EVENT_LINK_CFG_REQ 0x00000001
  20670. +/**
  20671. + * IRQ event - Indicates that the link state changed
  20672. + */
  20673. +#define DPMAC_IRQ_EVENT_LINK_CHANGED 0x00000002
  20674. +
  20675. +int dpmac_set_irq_enable(struct fsl_mc_io *mc_io,
  20676. + u32 cmd_flags,
  20677. + u16 token,
  20678. + u8 irq_index,
  20679. + u8 en);
  20680. +
  20681. +int dpmac_get_irq_enable(struct fsl_mc_io *mc_io,
  20682. + u32 cmd_flags,
  20683. + u16 token,
  20684. + u8 irq_index,
  20685. + u8 *en);
  20686. +
  20687. +int dpmac_set_irq_mask(struct fsl_mc_io *mc_io,
  20688. + u32 cmd_flags,
  20689. + u16 token,
  20690. + u8 irq_index,
  20691. + u32 mask);
  20692. +
  20693. +int dpmac_get_irq_mask(struct fsl_mc_io *mc_io,
  20694. + u32 cmd_flags,
  20695. + u16 token,
  20696. + u8 irq_index,
  20697. + u32 *mask);
  20698. +
  20699. +int dpmac_get_irq_status(struct fsl_mc_io *mc_io,
  20700. + u32 cmd_flags,
  20701. + u16 token,
  20702. + u8 irq_index,
  20703. + u32 *status);
  20704. +
  20705. +int dpmac_clear_irq_status(struct fsl_mc_io *mc_io,
  20706. + u32 cmd_flags,
  20707. + u16 token,
  20708. + u8 irq_index,
  20709. + u32 status);
  20710. +
  20711. +/**
  20712. + * struct dpmac_attr - Structure representing DPMAC attributes
  20713. + * @id: DPMAC object ID
  20714. + * @max_rate: Maximum supported rate - in Mbps
  20715. + * @eth_if: Ethernet interface
  20716. + * @link_type: link type
  20717. + */
  20718. +struct dpmac_attr {
  20719. + u16 id;
  20720. + u32 max_rate;
  20721. + enum dpmac_eth_if eth_if;
  20722. + enum dpmac_link_type link_type;
  20723. +};
  20724. +
  20725. +int dpmac_get_attributes(struct fsl_mc_io *mc_io,
  20726. + u32 cmd_flags,
  20727. + u16 token,
  20728. + struct dpmac_attr *attr);
  20729. +
  20730. +/**
  20731. + * DPMAC link configuration/state options
  20732. + */
  20733. +
  20734. +/**
  20735. + * Enable auto-negotiation
  20736. + */
  20737. +#define DPMAC_LINK_OPT_AUTONEG 0x0000000000000001ULL
  20738. +/**
  20739. + * Enable half-duplex mode
  20740. + */
  20741. +#define DPMAC_LINK_OPT_HALF_DUPLEX 0x0000000000000002ULL
  20742. +/**
  20743. + * Enable pause frames
  20744. + */
  20745. +#define DPMAC_LINK_OPT_PAUSE 0x0000000000000004ULL
  20746. +/**
  20747. + * Enable a-symmetric pause frames
  20748. + */
  20749. +#define DPMAC_LINK_OPT_ASYM_PAUSE 0x0000000000000008ULL
  20750. +
  20751. +/**
  20752. + * struct dpmac_link_cfg - Structure representing DPMAC link configuration
  20753. + * @rate: Link's rate - in Mbps
  20754. + * @options: Enable/Disable DPMAC link cfg features (bitmap)
  20755. + */
  20756. +struct dpmac_link_cfg {
  20757. + u32 rate;
  20758. + u64 options;
  20759. +};
  20760. +
  20761. +int dpmac_get_link_cfg(struct fsl_mc_io *mc_io,
  20762. + u32 cmd_flags,
  20763. + u16 token,
  20764. + struct dpmac_link_cfg *cfg);
  20765. +
  20766. +/**
  20767. + * struct dpmac_link_state - DPMAC link configuration request
  20768. + * @rate: Rate in Mbps
  20769. + * @options: Enable/Disable DPMAC link cfg features (bitmap)
  20770. + * @up: Link state
  20771. + */
  20772. +struct dpmac_link_state {
  20773. + u32 rate;
  20774. + u64 options;
  20775. + int up;
  20776. +};
  20777. +
  20778. +int dpmac_set_link_state(struct fsl_mc_io *mc_io,
  20779. + u32 cmd_flags,
  20780. + u16 token,
  20781. + struct dpmac_link_state *link_state);
  20782. +
  20783. +/**
  20784. + * enum dpmac_counter - DPMAC counter types
  20785. + * @DPMAC_CNT_ING_FRAME_64: counts 64-bytes frames, good or bad.
  20786. + * @DPMAC_CNT_ING_FRAME_127: counts 65- to 127-bytes frames, good or bad.
  20787. + * @DPMAC_CNT_ING_FRAME_255: counts 128- to 255-bytes frames, good or bad.
  20788. + * @DPMAC_CNT_ING_FRAME_511: counts 256- to 511-bytes frames, good or bad.
  20789. + * @DPMAC_CNT_ING_FRAME_1023: counts 512- to 1023-bytes frames, good or bad.
  20790. + * @DPMAC_CNT_ING_FRAME_1518: counts 1024- to 1518-bytes frames, good or bad.
  20791. + * @DPMAC_CNT_ING_FRAME_1519_MAX: counts 1519-bytes frames and larger
  20792. + * (up to max frame length specified),
  20793. + * good or bad.
  20794. + * @DPMAC_CNT_ING_FRAG: counts frames which are shorter than 64 bytes received
  20795. + * with a wrong CRC
  20796. + * @DPMAC_CNT_ING_JABBER: counts frames longer than the maximum frame length
  20797. + * specified, with a bad frame check sequence.
  20798. + * @DPMAC_CNT_ING_FRAME_DISCARD: counts dropped frames due to internal errors.
  20799. + * Occurs when a receive FIFO overflows.
  20800. + * Includes also frames truncated as a result of
  20801. + * the receive FIFO overflow.
  20802. + * @DPMAC_CNT_ING_ALIGN_ERR: counts frames with an alignment error
  20803. + * (optional used for wrong SFD).
  20804. + * @DPMAC_CNT_EGR_UNDERSIZED: counts frames transmitted that was less than 64
  20805. + * bytes long with a good CRC.
  20806. + * @DPMAC_CNT_ING_OVERSIZED: counts frames longer than the maximum frame length
  20807. + * specified, with a good frame check sequence.
  20808. + * @DPMAC_CNT_ING_VALID_PAUSE_FRAME: counts valid pause frames (regular and PFC)
  20809. + * @DPMAC_CNT_EGR_VALID_PAUSE_FRAME: counts valid pause frames transmitted
  20810. + * (regular and PFC).
  20811. + * @DPMAC_CNT_ING_BYTE: counts bytes received except preamble for all valid
  20812. + * frames and valid pause frames.
  20813. + * @DPMAC_CNT_ING_MCAST_FRAME: counts received multicast frames.
  20814. + * @DPMAC_CNT_ING_BCAST_FRAME: counts received broadcast frames.
  20815. + * @DPMAC_CNT_ING_ALL_FRAME: counts each good or bad frames received.
  20816. + * @DPMAC_CNT_ING_UCAST_FRAME: counts received unicast frames.
  20817. + * @DPMAC_CNT_ING_ERR_FRAME: counts frames received with an error
  20818. + * (except for undersized/fragment frame).
  20819. + * @DPMAC_CNT_EGR_BYTE: counts bytes transmitted except preamble for all valid
  20820. + * frames and valid pause frames transmitted.
  20821. + * @DPMAC_CNT_EGR_MCAST_FRAME: counts transmitted multicast frames.
  20822. + * @DPMAC_CNT_EGR_BCAST_FRAME: counts transmitted broadcast frames.
  20823. + * @DPMAC_CNT_EGR_UCAST_FRAME: counts transmitted unicast frames.
  20824. + * @DPMAC_CNT_EGR_ERR_FRAME: counts frames transmitted with an error.
  20825. + * @DPMAC_CNT_ING_GOOD_FRAME: counts frames received without error, including
  20826. + * pause frames.
  20827. + * @DPMAC_CNT_ENG_GOOD_FRAME: counts frames transmitted without error, including
  20828. + * pause frames.
  20829. + */
  20830. +enum dpmac_counter {
  20831. + DPMAC_CNT_ING_FRAME_64,
  20832. + DPMAC_CNT_ING_FRAME_127,
  20833. + DPMAC_CNT_ING_FRAME_255,
  20834. + DPMAC_CNT_ING_FRAME_511,
  20835. + DPMAC_CNT_ING_FRAME_1023,
  20836. + DPMAC_CNT_ING_FRAME_1518,
  20837. + DPMAC_CNT_ING_FRAME_1519_MAX,
  20838. + DPMAC_CNT_ING_FRAG,
  20839. + DPMAC_CNT_ING_JABBER,
  20840. + DPMAC_CNT_ING_FRAME_DISCARD,
  20841. + DPMAC_CNT_ING_ALIGN_ERR,
  20842. + DPMAC_CNT_EGR_UNDERSIZED,
  20843. + DPMAC_CNT_ING_OVERSIZED,
  20844. + DPMAC_CNT_ING_VALID_PAUSE_FRAME,
  20845. + DPMAC_CNT_EGR_VALID_PAUSE_FRAME,
  20846. + DPMAC_CNT_ING_BYTE,
  20847. + DPMAC_CNT_ING_MCAST_FRAME,
  20848. + DPMAC_CNT_ING_BCAST_FRAME,
  20849. + DPMAC_CNT_ING_ALL_FRAME,
  20850. + DPMAC_CNT_ING_UCAST_FRAME,
  20851. + DPMAC_CNT_ING_ERR_FRAME,
  20852. + DPMAC_CNT_EGR_BYTE,
  20853. + DPMAC_CNT_EGR_MCAST_FRAME,
  20854. + DPMAC_CNT_EGR_BCAST_FRAME,
  20855. + DPMAC_CNT_EGR_UCAST_FRAME,
  20856. + DPMAC_CNT_EGR_ERR_FRAME,
  20857. + DPMAC_CNT_ING_GOOD_FRAME,
  20858. + DPMAC_CNT_ENG_GOOD_FRAME
  20859. +};
  20860. +
  20861. +int dpmac_get_counter(struct fsl_mc_io *mc_io,
  20862. + u32 cmd_flags,
  20863. + u16 token,
  20864. + enum dpmac_counter type,
  20865. + u64 *counter);
  20866. +
  20867. +/**
  20868. + * dpmac_set_port_mac_addr() - Set a MAC address associated with the physical
  20869. + * port. This is not used for filtering, MAC is always in
  20870. + * promiscuous mode, it is passed to DPNIs through DPNI API for
  20871. + * application used.
  20872. + * @mc_io: Pointer to opaque I/O object
  20873. + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
  20874. + * @token: Token of DPMAC object
  20875. + * @addr: MAC address to set
  20876. + *
  20877. + * Return: The requested counter; '0' otherwise.
  20878. + */
  20879. +int dpmac_set_port_mac_addr(struct fsl_mc_io *mc_io,
  20880. + u32 cmd_flags,
  20881. + u16 token,
  20882. + const u8 addr[6]);
  20883. +
  20884. +int dpmac_get_api_version(struct fsl_mc_io *mc_io,
  20885. + u32 cmd_flags,
  20886. + u16 *major_ver,
  20887. + u16 *minor_ver);
  20888. +
  20889. +#endif /* __FSL_DPMAC_H */
  20890. --- /dev/null
  20891. +++ b/drivers/staging/fsl-dpaa2/mac/mac.c
  20892. @@ -0,0 +1,666 @@
  20893. +/* Copyright 2015 Freescale Semiconductor Inc.
  20894. + *
  20895. + * Redistribution and use in source and binary forms, with or without
  20896. + * modification, are permitted provided that the following conditions are met:
  20897. + * * Redistributions of source code must retain the above copyright
  20898. + * notice, this list of conditions and the following disclaimer.
  20899. + * * Redistributions in binary form must reproduce the above copyright
  20900. + * notice, this list of conditions and the following disclaimer in the
  20901. + * documentation and/or other materials provided with the distribution.
  20902. + * * Neither the name of Freescale Semiconductor nor the
  20903. + * names of its contributors may be used to endorse or promote products
  20904. + * derived from this software without specific prior written permission.
  20905. + *
  20906. + *
  20907. + * ALTERNATIVELY, this software may be distributed under the terms of the
  20908. + * GNU General Public License ("GPL") as published by the Free Software
  20909. + * Foundation, either version 2 of that License or (at your option) any
  20910. + * later version.
  20911. + *
  20912. + * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
  20913. + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  20914. + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  20915. + * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
  20916. + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  20917. + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  20918. + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  20919. + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  20920. + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  20921. + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  20922. + */
  20923. +
  20924. +#include <linux/module.h>
  20925. +
  20926. +#include <linux/netdevice.h>
  20927. +#include <linux/etherdevice.h>
  20928. +#include <linux/msi.h>
  20929. +#include <linux/rtnetlink.h>
  20930. +#include <linux/if_vlan.h>
  20931. +
  20932. +#include <uapi/linux/if_bridge.h>
  20933. +#include <net/netlink.h>
  20934. +
  20935. +#include <linux/of.h>
  20936. +#include <linux/of_mdio.h>
  20937. +#include <linux/of_net.h>
  20938. +#include <linux/phy.h>
  20939. +#include <linux/phy_fixed.h>
  20940. +
  20941. +#include "../../fsl-mc/include/mc.h"
  20942. +#include "../../fsl-mc/include/mc-sys.h"
  20943. +
  20944. +#include "dpmac.h"
  20945. +#include "dpmac-cmd.h"
  20946. +
  20947. +struct dpaa2_mac_priv {
  20948. + struct net_device *netdev;
  20949. + struct fsl_mc_device *mc_dev;
  20950. + struct dpmac_attr attr;
  20951. + struct dpmac_link_state old_state;
  20952. +};
  20953. +
  20954. +/* TODO: fix the 10G modes, mapping can't be right:
  20955. + * XGMII is paralel
  20956. + * XAUI is serial, using 8b/10b encoding
  20957. + * XFI is also serial but using 64b/66b encoding
  20958. + * they can't all map to XGMII...
  20959. + *
  20960. + * This must be kept in sync with enum dpmac_eth_if.
  20961. + */
  20962. +static phy_interface_t dpaa2_mac_iface_mode[] = {
  20963. + PHY_INTERFACE_MODE_MII, /* DPMAC_ETH_IF_MII */
  20964. + PHY_INTERFACE_MODE_RMII, /* DPMAC_ETH_IF_RMII */
  20965. + PHY_INTERFACE_MODE_SMII, /* DPMAC_ETH_IF_SMII */
  20966. + PHY_INTERFACE_MODE_GMII, /* DPMAC_ETH_IF_GMII */
  20967. + PHY_INTERFACE_MODE_RGMII, /* DPMAC_ETH_IF_RGMII */
  20968. + PHY_INTERFACE_MODE_SGMII, /* DPMAC_ETH_IF_SGMII */
  20969. + PHY_INTERFACE_MODE_QSGMII, /* DPMAC_ETH_IF_QSGMII */
  20970. + PHY_INTERFACE_MODE_XGMII, /* DPMAC_ETH_IF_XAUI */
  20971. + PHY_INTERFACE_MODE_XGMII, /* DPMAC_ETH_IF_XFI */
  20972. +};
  20973. +
  20974. +static void dpaa2_mac_link_changed(struct net_device *netdev)
  20975. +{
  20976. + struct phy_device *phydev;
  20977. + struct dpmac_link_state state = { 0 };
  20978. + struct dpaa2_mac_priv *priv = netdev_priv(netdev);
  20979. + int err;
  20980. +
  20981. + /* the PHY just notified us of link state change */
  20982. + phydev = netdev->phydev;
  20983. +
  20984. + state.up = !!phydev->link;
  20985. + if (phydev->link) {
  20986. + state.rate = phydev->speed;
  20987. +
  20988. + if (!phydev->duplex)
  20989. + state.options |= DPMAC_LINK_OPT_HALF_DUPLEX;
  20990. + if (phydev->autoneg)
  20991. + state.options |= DPMAC_LINK_OPT_AUTONEG;
  20992. +
  20993. + netif_carrier_on(netdev);
  20994. + } else {
  20995. + netif_carrier_off(netdev);
  20996. + }
  20997. +
  20998. + if (priv->old_state.up != state.up ||
  20999. + priv->old_state.rate != state.rate ||
  21000. + priv->old_state.options != state.options) {
  21001. + priv->old_state = state;
  21002. + phy_print_status(phydev);
  21003. + }
  21004. +
  21005. + /* We must interrogate MC at all times, because we don't know
  21006. + * when and whether a potential DPNI may have read the link state.
  21007. + */
  21008. + err = dpmac_set_link_state(priv->mc_dev->mc_io, 0,
  21009. + priv->mc_dev->mc_handle, &state);
  21010. + if (unlikely(err))
  21011. + dev_err(&priv->mc_dev->dev, "dpmac_set_link_state: %d\n", err);
  21012. +}
  21013. +
  21014. +#ifdef CONFIG_FSL_DPAA2_MAC_NETDEVS
  21015. +static netdev_tx_t dpaa2_mac_drop_frame(struct sk_buff *skb,
  21016. + struct net_device *dev)
  21017. +{
  21018. + /* we don't support I/O for now, drop the frame */
  21019. + dev_kfree_skb_any(skb);
  21020. + return NETDEV_TX_OK;
  21021. +}
  21022. +
  21023. +static int dpaa2_mac_open(struct net_device *netdev)
  21024. +{
  21025. + /* start PHY state machine */
  21026. + phy_start(netdev->phydev);
  21027. +
  21028. + return 0;
  21029. +}
  21030. +
  21031. +static int dpaa2_mac_stop(struct net_device *netdev)
  21032. +{
  21033. + if (!netdev->phydev)
  21034. + goto done;
  21035. +
  21036. + /* stop PHY state machine */
  21037. + phy_stop(netdev->phydev);
  21038. +
  21039. + /* signal link down to firmware */
  21040. + netdev->phydev->link = 0;
  21041. + dpaa2_mac_link_changed(netdev);
  21042. +
  21043. +done:
  21044. + return 0;
  21045. +}
  21046. +
  21047. +static int dpaa2_mac_get_settings(struct net_device *netdev,
  21048. + struct ethtool_cmd *cmd)
  21049. +{
  21050. + return phy_ethtool_gset(netdev->phydev, cmd);
  21051. +}
  21052. +
  21053. +static int dpaa2_mac_set_settings(struct net_device *netdev,
  21054. + struct ethtool_cmd *cmd)
  21055. +{
  21056. + return phy_ethtool_sset(netdev->phydev, cmd);
  21057. +}
  21058. +
  21059. +static void dpaa2_mac_get_stats(struct net_device *netdev,
  21060. + struct rtnl_link_stats64 *storage)
  21061. +{
  21062. + struct dpaa2_mac_priv *priv = netdev_priv(netdev);
  21063. + u64 tmp;
  21064. + int err;
  21065. +
  21066. + err = dpmac_get_counter(priv->mc_dev->mc_io, 0, priv->mc_dev->mc_handle,
  21067. + DPMAC_CNT_EGR_MCAST_FRAME,
  21068. + &storage->tx_packets);
  21069. + if (err)
  21070. + goto error;
  21071. + err = dpmac_get_counter(priv->mc_dev->mc_io, 0, priv->mc_dev->mc_handle,
  21072. + DPMAC_CNT_EGR_BCAST_FRAME, &tmp);
  21073. + if (err)
  21074. + goto error;
  21075. + storage->tx_packets += tmp;
  21076. + err = dpmac_get_counter(priv->mc_dev->mc_io, 0, priv->mc_dev->mc_handle,
  21077. + DPMAC_CNT_EGR_UCAST_FRAME, &tmp);
  21078. + if (err)
  21079. + goto error;
  21080. + storage->tx_packets += tmp;
  21081. +
  21082. + err = dpmac_get_counter(priv->mc_dev->mc_io, 0, priv->mc_dev->mc_handle,
  21083. + DPMAC_CNT_EGR_UNDERSIZED, &storage->tx_dropped);
  21084. + if (err)
  21085. + goto error;
  21086. + err = dpmac_get_counter(priv->mc_dev->mc_io, 0, priv->mc_dev->mc_handle,
  21087. + DPMAC_CNT_EGR_BYTE, &storage->tx_bytes);
  21088. + if (err)
  21089. + goto error;
  21090. + err = dpmac_get_counter(priv->mc_dev->mc_io, 0, priv->mc_dev->mc_handle,
  21091. + DPMAC_CNT_EGR_ERR_FRAME, &storage->tx_errors);
  21092. + if (err)
  21093. + goto error;
  21094. +
  21095. + err = dpmac_get_counter(priv->mc_dev->mc_io, 0, priv->mc_dev->mc_handle,
  21096. + DPMAC_CNT_ING_ALL_FRAME, &storage->rx_packets);
  21097. + if (err)
  21098. + goto error;
  21099. + err = dpmac_get_counter(priv->mc_dev->mc_io, 0, priv->mc_dev->mc_handle,
  21100. + DPMAC_CNT_ING_MCAST_FRAME, &storage->multicast);
  21101. + if (err)
  21102. + goto error;
  21103. + err = dpmac_get_counter(priv->mc_dev->mc_io, 0, priv->mc_dev->mc_handle,
  21104. + DPMAC_CNT_ING_FRAME_DISCARD,
  21105. + &storage->rx_dropped);
  21106. + if (err)
  21107. + goto error;
  21108. + err = dpmac_get_counter(priv->mc_dev->mc_io, 0, priv->mc_dev->mc_handle,
  21109. + DPMAC_CNT_ING_ALIGN_ERR, &storage->rx_errors);
  21110. + if (err)
  21111. + goto error;
  21112. + err = dpmac_get_counter(priv->mc_dev->mc_io, 0, priv->mc_dev->mc_handle,
  21113. + DPMAC_CNT_ING_OVERSIZED, &tmp);
  21114. + if (err)
  21115. + goto error;
  21116. + storage->rx_errors += tmp;
  21117. + err = dpmac_get_counter(priv->mc_dev->mc_io, 0, priv->mc_dev->mc_handle,
  21118. + DPMAC_CNT_ING_BYTE, &storage->rx_bytes);
  21119. + if (err)
  21120. + goto error;
  21121. +
  21122. + return;
  21123. +error:
  21124. + netdev_err(netdev, "dpmac_get_counter err %d\n", err);
  21125. +}
  21126. +
  21127. +static struct {
  21128. + enum dpmac_counter id;
  21129. + char name[ETH_GSTRING_LEN];
  21130. +} dpaa2_mac_counters[] = {
  21131. + {DPMAC_CNT_ING_ALL_FRAME, "rx all frames"},
  21132. + {DPMAC_CNT_ING_GOOD_FRAME, "rx frames ok"},
  21133. + {DPMAC_CNT_ING_ERR_FRAME, "rx frame errors"},
  21134. + {DPMAC_CNT_ING_FRAME_DISCARD, "rx frame discards"},
  21135. + {DPMAC_CNT_ING_UCAST_FRAME, "rx u-cast"},
  21136. + {DPMAC_CNT_ING_BCAST_FRAME, "rx b-cast"},
  21137. + {DPMAC_CNT_ING_MCAST_FRAME, "rx m-cast"},
  21138. + {DPMAC_CNT_ING_FRAME_64, "rx 64 bytes"},
  21139. + {DPMAC_CNT_ING_FRAME_127, "rx 65-127 bytes"},
  21140. + {DPMAC_CNT_ING_FRAME_255, "rx 128-255 bytes"},
  21141. + {DPMAC_CNT_ING_FRAME_511, "rx 256-511 bytes"},
  21142. + {DPMAC_CNT_ING_FRAME_1023, "rx 512-1023 bytes"},
  21143. + {DPMAC_CNT_ING_FRAME_1518, "rx 1024-1518 bytes"},
  21144. + {DPMAC_CNT_ING_FRAME_1519_MAX, "rx 1519-max bytes"},
  21145. + {DPMAC_CNT_ING_FRAG, "rx frags"},
  21146. + {DPMAC_CNT_ING_JABBER, "rx jabber"},
  21147. + {DPMAC_CNT_ING_ALIGN_ERR, "rx align errors"},
  21148. + {DPMAC_CNT_ING_OVERSIZED, "rx oversized"},
  21149. + {DPMAC_CNT_ING_VALID_PAUSE_FRAME, "rx pause"},
  21150. + {DPMAC_CNT_ING_BYTE, "rx bytes"},
  21151. + {DPMAC_CNT_ENG_GOOD_FRAME, "tx frames ok"},
  21152. + {DPMAC_CNT_EGR_UCAST_FRAME, "tx u-cast"},
  21153. + {DPMAC_CNT_EGR_MCAST_FRAME, "tx m-cast"},
  21154. + {DPMAC_CNT_EGR_BCAST_FRAME, "tx b-cast"},
  21155. + {DPMAC_CNT_EGR_ERR_FRAME, "tx frame errors"},
  21156. + {DPMAC_CNT_EGR_UNDERSIZED, "tx undersized"},
  21157. + {DPMAC_CNT_EGR_VALID_PAUSE_FRAME, "tx b-pause"},
  21158. + {DPMAC_CNT_EGR_BYTE, "tx bytes"},
  21159. +
  21160. +};
  21161. +
  21162. +static void dpaa2_mac_get_strings(struct net_device *netdev,
  21163. + u32 stringset, u8 *data)
  21164. +{
  21165. + int i;
  21166. +
  21167. + switch (stringset) {
  21168. + case ETH_SS_STATS:
  21169. + for (i = 0; i < ARRAY_SIZE(dpaa2_mac_counters); i++)
  21170. + memcpy(data + i * ETH_GSTRING_LEN,
  21171. + dpaa2_mac_counters[i].name,
  21172. + ETH_GSTRING_LEN);
  21173. + break;
  21174. + }
  21175. +}
  21176. +
  21177. +static void dpaa2_mac_get_ethtool_stats(struct net_device *netdev,
  21178. + struct ethtool_stats *stats,
  21179. + u64 *data)
  21180. +{
  21181. + struct dpaa2_mac_priv *priv = netdev_priv(netdev);
  21182. + int i;
  21183. + int err;
  21184. +
  21185. + for (i = 0; i < ARRAY_SIZE(dpaa2_mac_counters); i++) {
  21186. + err = dpmac_get_counter(priv->mc_dev->mc_io,
  21187. + 0,
  21188. + priv->mc_dev->mc_handle,
  21189. + dpaa2_mac_counters[i].id, &data[i]);
  21190. + if (err)
  21191. + netdev_err(netdev, "dpmac_get_counter[%s] err %d\n",
  21192. + dpaa2_mac_counters[i].name, err);
  21193. + }
  21194. +}
  21195. +
  21196. +static int dpaa2_mac_get_sset_count(struct net_device *dev, int sset)
  21197. +{
  21198. + switch (sset) {
  21199. + case ETH_SS_STATS:
  21200. + return ARRAY_SIZE(dpaa2_mac_counters);
  21201. + default:
  21202. + return -EOPNOTSUPP;
  21203. + }
  21204. +}
  21205. +
  21206. +static const struct net_device_ops dpaa2_mac_ndo_ops = {
  21207. + .ndo_start_xmit = &dpaa2_mac_drop_frame,
  21208. + .ndo_open = &dpaa2_mac_open,
  21209. + .ndo_stop = &dpaa2_mac_stop,
  21210. + .ndo_get_stats64 = &dpaa2_mac_get_stats,
  21211. +};
  21212. +
  21213. +static const struct ethtool_ops dpaa2_mac_ethtool_ops = {
  21214. + .get_settings = &dpaa2_mac_get_settings,
  21215. + .set_settings = &dpaa2_mac_set_settings,
  21216. + .get_strings = &dpaa2_mac_get_strings,
  21217. + .get_ethtool_stats = &dpaa2_mac_get_ethtool_stats,
  21218. + .get_sset_count = &dpaa2_mac_get_sset_count,
  21219. +};
  21220. +#endif /* CONFIG_FSL_DPAA2_MAC_NETDEVS */
  21221. +
  21222. +static void configure_link(struct dpaa2_mac_priv *priv,
  21223. + struct dpmac_link_cfg *cfg)
  21224. +{
  21225. + struct phy_device *phydev = priv->netdev->phydev;
  21226. +
  21227. + if (unlikely(!phydev))
  21228. + return;
  21229. +
  21230. + phydev->speed = cfg->rate;
  21231. + phydev->duplex = !!(cfg->options & DPMAC_LINK_OPT_HALF_DUPLEX);
  21232. +
  21233. + if (cfg->options & DPMAC_LINK_OPT_AUTONEG) {
  21234. + phydev->autoneg = 1;
  21235. + phydev->advertising |= ADVERTISED_Autoneg;
  21236. + } else {
  21237. + phydev->autoneg = 0;
  21238. + phydev->advertising &= ~ADVERTISED_Autoneg;
  21239. + }
  21240. +
  21241. + phy_start_aneg(phydev);
  21242. +}
  21243. +
  21244. +static irqreturn_t dpaa2_mac_irq_handler(int irq_num, void *arg)
  21245. +{
  21246. + struct device *dev = (struct device *)arg;
  21247. + struct fsl_mc_device *mc_dev = to_fsl_mc_device(dev);
  21248. + struct dpaa2_mac_priv *priv = dev_get_drvdata(dev);
  21249. + struct dpmac_link_cfg link_cfg;
  21250. + u32 status;
  21251. + int err;
  21252. +
  21253. + err = dpmac_get_irq_status(mc_dev->mc_io, 0, mc_dev->mc_handle,
  21254. + DPMAC_IRQ_INDEX, &status);
  21255. + if (unlikely(err || !status))
  21256. + return IRQ_NONE;
  21257. +
  21258. + /* DPNI-initiated link configuration; 'ifconfig up' also calls this */
  21259. + if (status & DPMAC_IRQ_EVENT_LINK_CFG_REQ) {
  21260. + err = dpmac_get_link_cfg(mc_dev->mc_io, 0, mc_dev->mc_handle,
  21261. + &link_cfg);
  21262. + if (unlikely(err))
  21263. + goto out;
  21264. +
  21265. + configure_link(priv, &link_cfg);
  21266. + }
  21267. +
  21268. +out:
  21269. + dpmac_clear_irq_status(mc_dev->mc_io, 0, mc_dev->mc_handle,
  21270. + DPMAC_IRQ_INDEX, status);
  21271. +
  21272. + return IRQ_HANDLED;
  21273. +}
  21274. +
  21275. +static int setup_irqs(struct fsl_mc_device *mc_dev)
  21276. +{
  21277. + int err = 0;
  21278. + struct fsl_mc_device_irq *irq;
  21279. +
  21280. + err = fsl_mc_allocate_irqs(mc_dev);
  21281. + if (err) {
  21282. + dev_err(&mc_dev->dev, "fsl_mc_allocate_irqs err %d\n", err);
  21283. + return err;
  21284. + }
  21285. +
  21286. + irq = mc_dev->irqs[0];
  21287. + err = devm_request_threaded_irq(&mc_dev->dev, irq->msi_desc->irq,
  21288. + NULL, &dpaa2_mac_irq_handler,
  21289. + IRQF_NO_SUSPEND | IRQF_ONESHOT,
  21290. + dev_name(&mc_dev->dev), &mc_dev->dev);
  21291. + if (err) {
  21292. + dev_err(&mc_dev->dev, "devm_request_threaded_irq err %d\n",
  21293. + err);
  21294. + goto free_irq;
  21295. + }
  21296. +
  21297. + err = dpmac_set_irq_mask(mc_dev->mc_io, 0, mc_dev->mc_handle,
  21298. + DPMAC_IRQ_INDEX, DPMAC_IRQ_EVENT_LINK_CFG_REQ);
  21299. + if (err) {
  21300. + dev_err(&mc_dev->dev, "dpmac_set_irq_mask err %d\n", err);
  21301. + goto free_irq;
  21302. + }
  21303. + err = dpmac_set_irq_enable(mc_dev->mc_io, 0, mc_dev->mc_handle,
  21304. + DPMAC_IRQ_INDEX, 1);
  21305. + if (err) {
  21306. + dev_err(&mc_dev->dev, "dpmac_set_irq_enable err %d\n", err);
  21307. + goto free_irq;
  21308. + }
  21309. +
  21310. + return 0;
  21311. +
  21312. +free_irq:
  21313. + fsl_mc_free_irqs(mc_dev);
  21314. +
  21315. + return err;
  21316. +}
  21317. +
  21318. +static void teardown_irqs(struct fsl_mc_device *mc_dev)
  21319. +{
  21320. + int err;
  21321. +
  21322. + err = dpmac_set_irq_enable(mc_dev->mc_io, 0, mc_dev->mc_handle,
  21323. + DPMAC_IRQ_INDEX, 0);
  21324. + if (err)
  21325. + dev_err(&mc_dev->dev, "dpmac_set_irq_enable err %d\n", err);
  21326. +
  21327. + fsl_mc_free_irqs(mc_dev);
  21328. +}
  21329. +
  21330. +static struct device_node *find_dpmac_node(struct device *dev, u16 dpmac_id)
  21331. +{
  21332. + struct device_node *dpmacs, *dpmac = NULL;
  21333. + struct device_node *mc_node = dev->of_node;
  21334. + u32 id;
  21335. + int err;
  21336. +
  21337. + dpmacs = of_find_node_by_name(mc_node, "dpmacs");
  21338. + if (!dpmacs) {
  21339. + dev_err(dev, "No dpmacs subnode in device-tree\n");
  21340. + return NULL;
  21341. + }
  21342. +
  21343. + while ((dpmac = of_get_next_child(dpmacs, dpmac))) {
  21344. + err = of_property_read_u32(dpmac, "reg", &id);
  21345. + if (err)
  21346. + continue;
  21347. + if (id == dpmac_id)
  21348. + return dpmac;
  21349. + }
  21350. +
  21351. + return NULL;
  21352. +}
  21353. +
  21354. +static int dpaa2_mac_probe(struct fsl_mc_device *mc_dev)
  21355. +{
  21356. + struct device *dev;
  21357. + struct dpaa2_mac_priv *priv = NULL;
  21358. + struct device_node *phy_node, *dpmac_node;
  21359. + struct net_device *netdev;
  21360. + phy_interface_t if_mode;
  21361. + int err = 0;
  21362. +
  21363. + dev = &mc_dev->dev;
  21364. +
  21365. + /* prepare a net_dev structure to make the phy lib API happy */
  21366. + netdev = alloc_etherdev(sizeof(*priv));
  21367. + if (!netdev) {
  21368. + dev_err(dev, "alloc_etherdev error\n");
  21369. + err = -ENOMEM;
  21370. + goto err_exit;
  21371. + }
  21372. + priv = netdev_priv(netdev);
  21373. + priv->mc_dev = mc_dev;
  21374. + priv->netdev = netdev;
  21375. +
  21376. + SET_NETDEV_DEV(netdev, dev);
  21377. +
  21378. +#ifdef CONFIG_FSL_DPAA2_MAC_NETDEVS
  21379. + snprintf(netdev->name, IFNAMSIZ, "mac%d", mc_dev->obj_desc.id);
  21380. +#endif
  21381. +
  21382. + dev_set_drvdata(dev, priv);
  21383. +
  21384. + err = fsl_mc_portal_allocate(mc_dev, 0, &mc_dev->mc_io);
  21385. + if (err || !mc_dev->mc_io) {
  21386. + dev_err(dev, "fsl_mc_portal_allocate error: %d\n", err);
  21387. + err = -ENODEV;
  21388. + goto err_free_netdev;
  21389. + }
  21390. +
  21391. + err = dpmac_open(mc_dev->mc_io, 0, mc_dev->obj_desc.id,
  21392. + &mc_dev->mc_handle);
  21393. + if (err || !mc_dev->mc_handle) {
  21394. + dev_err(dev, "dpmac_open error: %d\n", err);
  21395. + err = -ENODEV;
  21396. + goto err_free_mcp;
  21397. + }
  21398. +
  21399. + err = dpmac_get_attributes(mc_dev->mc_io, 0,
  21400. + mc_dev->mc_handle, &priv->attr);
  21401. + if (err) {
  21402. + dev_err(dev, "dpmac_get_attributes err %d\n", err);
  21403. + err = -EINVAL;
  21404. + goto err_close;
  21405. + }
  21406. +
  21407. + /* Look up the DPMAC node in the device-tree. */
  21408. + dpmac_node = find_dpmac_node(dev, priv->attr.id);
  21409. + if (!dpmac_node) {
  21410. + dev_err(dev, "No dpmac@%d subnode found.\n", priv->attr.id);
  21411. + err = -ENODEV;
  21412. + goto err_close;
  21413. + }
  21414. +
  21415. + err = setup_irqs(mc_dev);
  21416. + if (err) {
  21417. + err = -EFAULT;
  21418. + goto err_close;
  21419. + }
  21420. +
  21421. +#ifdef CONFIG_FSL_DPAA2_MAC_NETDEVS
  21422. + /* OPTIONAL, register netdev just to make it visible to the user */
  21423. + netdev->netdev_ops = &dpaa2_mac_ndo_ops;
  21424. + netdev->ethtool_ops = &dpaa2_mac_ethtool_ops;
  21425. +
  21426. + /* phy starts up enabled so netdev should be up too */
  21427. + netdev->flags |= IFF_UP;
  21428. +
  21429. + err = register_netdev(priv->netdev);
  21430. + if (err < 0) {
  21431. + dev_err(dev, "register_netdev error %d\n", err);
  21432. + err = -ENODEV;
  21433. + goto err_free_irq;
  21434. + }
  21435. +#endif /* CONFIG_FSL_DPAA2_MAC_NETDEVS */
  21436. +
  21437. + /* probe the PHY as a fixed-link if the link type declared in DPC
  21438. + * explicitly mandates this
  21439. + */
  21440. +
  21441. + phy_node = of_parse_phandle(dpmac_node, "phy-handle", 0);
  21442. + if (!phy_node) {
  21443. + goto probe_fixed_link;
  21444. + }
  21445. +
  21446. + if (priv->attr.eth_if < ARRAY_SIZE(dpaa2_mac_iface_mode)) {
  21447. + if_mode = dpaa2_mac_iface_mode[priv->attr.eth_if];
  21448. + dev_dbg(dev, "\tusing if mode %s for eth_if %d\n",
  21449. + phy_modes(if_mode), priv->attr.eth_if);
  21450. + } else {
  21451. + dev_warn(dev, "Unexpected interface mode %d, will probe as fixed link\n",
  21452. + priv->attr.eth_if);
  21453. + goto probe_fixed_link;
  21454. + }
  21455. +
  21456. + /* try to connect to the PHY */
  21457. + netdev->phydev = of_phy_connect(netdev, phy_node,
  21458. + &dpaa2_mac_link_changed, 0, if_mode);
  21459. + if (!netdev->phydev) {
  21460. + /* No need for dev_err(); the kernel's loud enough as it is. */
  21461. + dev_dbg(dev, "Can't of_phy_connect() now.\n");
  21462. + /* We might be waiting for the MDIO MUX to probe, so defer
  21463. + * our own probing.
  21464. + */
  21465. + err = -EPROBE_DEFER;
  21466. + goto err_defer;
  21467. + }
  21468. + dev_info(dev, "Connected to %s PHY.\n", phy_modes(if_mode));
  21469. +
  21470. +probe_fixed_link:
  21471. + if (!netdev->phydev) {
  21472. + struct fixed_phy_status status = {
  21473. + .link = 1,
  21474. + /* fixed-phys don't support 10Gbps speed for now */
  21475. + .speed = 1000,
  21476. + .duplex = 1,
  21477. + };
  21478. +
  21479. + /* try to register a fixed link phy */
  21480. + netdev->phydev = fixed_phy_register(PHY_POLL, &status, -1,
  21481. + NULL);
  21482. + if (!netdev->phydev || IS_ERR(netdev->phydev)) {
  21483. + dev_err(dev, "error trying to register fixed PHY\n");
  21484. + /* So we don't crash unregister_netdev() later on */
  21485. + netdev->phydev = NULL;
  21486. + err = -EFAULT;
  21487. + goto err_no_phy;
  21488. + }
  21489. + dev_info(dev, "Registered fixed PHY.\n");
  21490. + }
  21491. +
  21492. + /* start PHY state machine */
  21493. +#ifdef CONFIG_FSL_DPAA2_MAC_NETDEVS
  21494. + dpaa2_mac_open(netdev);
  21495. +#else /* CONFIG_FSL_DPAA2_MAC_NETDEVS */
  21496. + phy_start(netdev->phydev);
  21497. +#endif /* CONFIG_FSL_DPAA2_MAC_NETDEVS */
  21498. + return 0;
  21499. +
  21500. +err_defer:
  21501. +err_no_phy:
  21502. +#ifdef CONFIG_FSL_DPAA2_MAC_NETDEVS
  21503. + unregister_netdev(netdev);
  21504. +err_free_irq:
  21505. +#endif
  21506. + teardown_irqs(mc_dev);
  21507. +err_close:
  21508. + dpmac_close(mc_dev->mc_io, 0, mc_dev->mc_handle);
  21509. +err_free_mcp:
  21510. + fsl_mc_portal_free(mc_dev->mc_io);
  21511. +err_free_netdev:
  21512. + free_netdev(netdev);
  21513. +err_exit:
  21514. + return err;
  21515. +}
  21516. +
  21517. +static int dpaa2_mac_remove(struct fsl_mc_device *mc_dev)
  21518. +{
  21519. + struct device *dev = &mc_dev->dev;
  21520. + struct dpaa2_mac_priv *priv = dev_get_drvdata(dev);
  21521. +
  21522. +#ifdef CONFIG_FSL_DPAA2_MAC_NETDEVS
  21523. + unregister_netdev(priv->netdev);
  21524. +#endif
  21525. + teardown_irqs(priv->mc_dev);
  21526. + dpmac_close(priv->mc_dev->mc_io, 0, priv->mc_dev->mc_handle);
  21527. + fsl_mc_portal_free(priv->mc_dev->mc_io);
  21528. + free_netdev(priv->netdev);
  21529. +
  21530. + dev_set_drvdata(dev, NULL);
  21531. + kfree(priv);
  21532. +
  21533. + return 0;
  21534. +}
  21535. +
  21536. +static const struct fsl_mc_device_id dpaa2_mac_match_id_table[] = {
  21537. + {
  21538. + .vendor = FSL_MC_VENDOR_FREESCALE,
  21539. + .obj_type = "dpmac",
  21540. + },
  21541. + { .vendor = 0x0 }
  21542. +};
  21543. +MODULE_DEVICE_TABLE(fslmc, dpaa2_mac_match_id_table);
  21544. +
  21545. +static struct fsl_mc_driver dpaa2_mac_drv = {
  21546. + .driver = {
  21547. + .name = KBUILD_MODNAME,
  21548. + .owner = THIS_MODULE,
  21549. + },
  21550. + .probe = dpaa2_mac_probe,
  21551. + .remove = dpaa2_mac_remove,
  21552. + .match_id_table = dpaa2_mac_match_id_table,
  21553. +};
  21554. +
  21555. +module_fsl_mc_driver(dpaa2_mac_drv);
  21556. +
  21557. +MODULE_LICENSE("GPL");
  21558. +MODULE_DESCRIPTION("DPAA2 PHY proxy interface driver");
  21559. --- /dev/null
  21560. +++ b/drivers/staging/fsl-dpaa2/rtc/Makefile
  21561. @@ -0,0 +1,10 @@
  21562. +
  21563. +obj-$(CONFIG_PTP_1588_CLOCK_DPAA2) += dpaa2-rtc.o
  21564. +
  21565. +dpaa2-rtc-objs := rtc.o dprtc.o
  21566. +
  21567. +all:
  21568. + make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules
  21569. +
  21570. +clean:
  21571. + make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean
  21572. --- /dev/null
  21573. +++ b/drivers/staging/fsl-dpaa2/rtc/dprtc-cmd.h
  21574. @@ -0,0 +1,160 @@
  21575. +/* Copyright 2013-2016 Freescale Semiconductor Inc.
  21576. + *
  21577. + * Redistribution and use in source and binary forms, with or without
  21578. + * modification, are permitted provided that the following conditions are met:
  21579. + * * Redistributions of source code must retain the above copyright
  21580. + * notice, this list of conditions and the following disclaimer.
  21581. + * * Redistributions in binary form must reproduce the above copyright
  21582. + * notice, this list of conditions and the following disclaimer in the
  21583. + * documentation and/or other materials provided with the distribution.
  21584. + * * Neither the name of the above-listed copyright holders nor the
  21585. + * names of any contributors may be used to endorse or promote products
  21586. + * derived from this software without specific prior written permission.
  21587. + *
  21588. + *
  21589. + * ALTERNATIVELY, this software may be distributed under the terms of the
  21590. + * GNU General Public License ("GPL") as published by the Free Software
  21591. + * Foundation, either version 2 of that License or (at your option) any
  21592. + * later version.
  21593. + *
  21594. + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  21595. + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  21596. + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  21597. + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
  21598. + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  21599. + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  21600. + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  21601. + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  21602. + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  21603. + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  21604. + * POSSIBILITY OF SUCH DAMAGE.
  21605. + */
  21606. +#ifndef _FSL_DPRTC_CMD_H
  21607. +#define _FSL_DPRTC_CMD_H
  21608. +
  21609. +/* DPRTC Version */
  21610. +#define DPRTC_VER_MAJOR 2
  21611. +#define DPRTC_VER_MINOR 0
  21612. +
  21613. +/* Command versioning */
  21614. +#define DPRTC_CMD_BASE_VERSION 1
  21615. +#define DPRTC_CMD_ID_OFFSET 4
  21616. +
  21617. +#define DPRTC_CMD(id) (((id) << DPRTC_CMD_ID_OFFSET) | DPRTC_CMD_BASE_VERSION)
  21618. +
  21619. +/* Command IDs */
  21620. +#define DPRTC_CMDID_CLOSE DPRTC_CMD(0x800)
  21621. +#define DPRTC_CMDID_OPEN DPRTC_CMD(0x810)
  21622. +#define DPRTC_CMDID_CREATE DPRTC_CMD(0x910)
  21623. +#define DPRTC_CMDID_DESTROY DPRTC_CMD(0x990)
  21624. +#define DPRTC_CMDID_GET_API_VERSION DPRTC_CMD(0xa10)
  21625. +
  21626. +#define DPRTC_CMDID_ENABLE DPRTC_CMD(0x002)
  21627. +#define DPRTC_CMDID_DISABLE DPRTC_CMD(0x003)
  21628. +#define DPRTC_CMDID_GET_ATTR DPRTC_CMD(0x004)
  21629. +#define DPRTC_CMDID_RESET DPRTC_CMD(0x005)
  21630. +#define DPRTC_CMDID_IS_ENABLED DPRTC_CMD(0x006)
  21631. +
  21632. +#define DPRTC_CMDID_SET_IRQ_ENABLE DPRTC_CMD(0x012)
  21633. +#define DPRTC_CMDID_GET_IRQ_ENABLE DPRTC_CMD(0x013)
  21634. +#define DPRTC_CMDID_SET_IRQ_MASK DPRTC_CMD(0x014)
  21635. +#define DPRTC_CMDID_GET_IRQ_MASK DPRTC_CMD(0x015)
  21636. +#define DPRTC_CMDID_GET_IRQ_STATUS DPRTC_CMD(0x016)
  21637. +#define DPRTC_CMDID_CLEAR_IRQ_STATUS DPRTC_CMD(0x017)
  21638. +
  21639. +#define DPRTC_CMDID_SET_CLOCK_OFFSET DPRTC_CMD(0x1d0)
  21640. +#define DPRTC_CMDID_SET_FREQ_COMPENSATION DPRTC_CMD(0x1d1)
  21641. +#define DPRTC_CMDID_GET_FREQ_COMPENSATION DPRTC_CMD(0x1d2)
  21642. +#define DPRTC_CMDID_GET_TIME DPRTC_CMD(0x1d3)
  21643. +#define DPRTC_CMDID_SET_TIME DPRTC_CMD(0x1d4)
  21644. +#define DPRTC_CMDID_SET_ALARM DPRTC_CMD(0x1d5)
  21645. +#define DPRTC_CMDID_SET_PERIODIC_PULSE DPRTC_CMD(0x1d6)
  21646. +#define DPRTC_CMDID_CLEAR_PERIODIC_PULSE DPRTC_CMD(0x1d7)
  21647. +#define DPRTC_CMDID_SET_EXT_TRIGGER DPRTC_CMD(0x1d8)
  21648. +#define DPRTC_CMDID_CLEAR_EXT_TRIGGER DPRTC_CMD(0x1d9)
  21649. +#define DPRTC_CMDID_GET_EXT_TRIGGER_TIMESTAMP DPRTC_CMD(0x1dA)
  21650. +
  21651. +/* Macros for accessing command fields smaller than 1byte */
  21652. +#define DPRTC_MASK(field) \
  21653. + GENMASK(DPRTC_##field##_SHIFT + DPRTC_##field##_SIZE - 1, \
  21654. + DPRTC_##field##_SHIFT)
  21655. +#define dprtc_get_field(var, field) \
  21656. + (((var) & DPRTC_MASK(field)) >> DPRTC_##field##_SHIFT)
  21657. +
  21658. +#pragma pack(push, 1)
  21659. +struct dprtc_cmd_open {
  21660. + uint32_t dprtc_id;
  21661. +};
  21662. +
  21663. +struct dprtc_cmd_destroy {
  21664. + uint32_t object_id;
  21665. +};
  21666. +
  21667. +#define DPRTC_ENABLE_SHIFT 0
  21668. +#define DPRTC_ENABLE_SIZE 1
  21669. +
  21670. +struct dprtc_rsp_is_enabled {
  21671. + uint8_t en;
  21672. +};
  21673. +
  21674. +struct dprtc_cmd_get_irq {
  21675. + uint32_t pad;
  21676. + uint8_t irq_index;
  21677. +};
  21678. +
  21679. +struct dprtc_cmd_set_irq_enable {
  21680. + uint8_t en;
  21681. + uint8_t pad[3];
  21682. + uint8_t irq_index;
  21683. +};
  21684. +
  21685. +struct dprtc_rsp_get_irq_enable {
  21686. + uint8_t en;
  21687. +};
  21688. +
  21689. +struct dprtc_cmd_set_irq_mask {
  21690. + uint32_t mask;
  21691. + uint8_t irq_index;
  21692. +};
  21693. +
  21694. +struct dprtc_rsp_get_irq_mask {
  21695. + uint32_t mask;
  21696. +};
  21697. +
  21698. +struct dprtc_cmd_get_irq_status {
  21699. + uint32_t status;
  21700. + uint8_t irq_index;
  21701. +};
  21702. +
  21703. +struct dprtc_rsp_get_irq_status {
  21704. + uint32_t status;
  21705. +};
  21706. +
  21707. +struct dprtc_cmd_clear_irq_status {
  21708. + uint32_t status;
  21709. + uint8_t irq_index;
  21710. +};
  21711. +
  21712. +struct dprtc_rsp_get_attributes {
  21713. + uint32_t pad;
  21714. + uint32_t id;
  21715. +};
  21716. +
  21717. +struct dprtc_cmd_set_clock_offset {
  21718. + uint64_t offset;
  21719. +};
  21720. +
  21721. +struct dprtc_get_freq_compensation {
  21722. + uint32_t freq_compensation;
  21723. +};
  21724. +
  21725. +struct dprtc_time {
  21726. + uint64_t time;
  21727. +};
  21728. +
  21729. +struct dprtc_rsp_get_api_version {
  21730. + uint16_t major;
  21731. + uint16_t minor;
  21732. +};
  21733. +#pragma pack(pop)
  21734. +#endif /* _FSL_DPRTC_CMD_H */
  21735. --- /dev/null
  21736. +++ b/drivers/staging/fsl-dpaa2/rtc/dprtc.c
  21737. @@ -0,0 +1,746 @@
  21738. +/* Copyright 2013-2016 Freescale Semiconductor Inc.
  21739. + *
  21740. + * Redistribution and use in source and binary forms, with or without
  21741. + * modification, are permitted provided that the following conditions are met:
  21742. + * * Redistributions of source code must retain the above copyright
  21743. + * notice, this list of conditions and the following disclaimer.
  21744. + * * Redistributions in binary form must reproduce the above copyright
  21745. + * notice, this list of conditions and the following disclaimer in the
  21746. + * documentation and/or other materials provided with the distribution.
  21747. + * * Neither the name of the above-listed copyright holders nor the
  21748. + * names of any contributors may be used to endorse or promote products
  21749. + * derived from this software without specific prior written permission.
  21750. + *
  21751. + *
  21752. + * ALTERNATIVELY, this software may be distributed under the terms of the
  21753. + * GNU General Public License ("GPL") as published by the Free Software
  21754. + * Foundation, either version 2 of that License or (at your option) any
  21755. + * later version.
  21756. + *
  21757. + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  21758. + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  21759. + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  21760. + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
  21761. + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  21762. + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  21763. + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  21764. + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  21765. + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  21766. + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  21767. + * POSSIBILITY OF SUCH DAMAGE.
  21768. + */
  21769. +#include "../../fsl-mc/include/mc-sys.h"
  21770. +#include "../../fsl-mc/include/mc-cmd.h"
  21771. +#include "dprtc.h"
  21772. +#include "dprtc-cmd.h"
  21773. +
  21774. +/**
  21775. + * dprtc_open() - Open a control session for the specified object.
  21776. + * @mc_io: Pointer to MC portal's I/O object
  21777. + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
  21778. + * @dprtc_id: DPRTC unique ID
  21779. + * @token: Returned token; use in subsequent API calls
  21780. + *
  21781. + * This function can be used to open a control session for an
  21782. + * already created object; an object may have been declared in
  21783. + * the DPL or by calling the dprtc_create function.
  21784. + * This function returns a unique authentication token,
  21785. + * associated with the specific object ID and the specific MC
  21786. + * portal; this token must be used in all subsequent commands for
  21787. + * this specific object
  21788. + *
  21789. + * Return: '0' on Success; Error code otherwise.
  21790. + */
  21791. +int dprtc_open(struct fsl_mc_io *mc_io,
  21792. + uint32_t cmd_flags,
  21793. + int dprtc_id,
  21794. + uint16_t *token)
  21795. +{
  21796. + struct dprtc_cmd_open *cmd_params;
  21797. + struct mc_command cmd = { 0 };
  21798. + int err;
  21799. +
  21800. + /* prepare command */
  21801. + cmd.header = mc_encode_cmd_header(DPRTC_CMDID_OPEN,
  21802. + cmd_flags,
  21803. + 0);
  21804. + cmd_params = (struct dprtc_cmd_open *)cmd.params;
  21805. + cmd_params->dprtc_id = cpu_to_le32(dprtc_id);
  21806. +
  21807. + /* send command to mc*/
  21808. + err = mc_send_command(mc_io, &cmd);
  21809. + if (err)
  21810. + return err;
  21811. +
  21812. + /* retrieve response parameters */
  21813. + *token = mc_cmd_hdr_read_token(&cmd);
  21814. +
  21815. + return err;
  21816. +}
  21817. +
  21818. +/**
  21819. + * dprtc_close() - Close the control session of the object
  21820. + * @mc_io: Pointer to MC portal's I/O object
  21821. + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
  21822. + * @token: Token of DPRTC object
  21823. + *
  21824. + * After this function is called, no further operations are
  21825. + * allowed on the object without opening a new control session.
  21826. + *
  21827. + * Return: '0' on Success; Error code otherwise.
  21828. + */
  21829. +int dprtc_close(struct fsl_mc_io *mc_io,
  21830. + uint32_t cmd_flags,
  21831. + uint16_t token)
  21832. +{
  21833. + struct mc_command cmd = { 0 };
  21834. +
  21835. + /* prepare command */
  21836. + cmd.header = mc_encode_cmd_header(DPRTC_CMDID_CLOSE, cmd_flags,
  21837. + token);
  21838. +
  21839. + /* send command to mc*/
  21840. + return mc_send_command(mc_io, &cmd);
  21841. +}
  21842. +
  21843. +/**
  21844. + * dprtc_create() - Create the DPRTC object.
  21845. + * @mc_io: Pointer to MC portal's I/O object
  21846. + * @dprc_token: Parent container token; '0' for default container
  21847. + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
  21848. + * @cfg: Configuration structure
  21849. + * @obj_id: Returned object id
  21850. + *
  21851. + * Create the DPRTC object, allocate required resources and
  21852. + * perform required initialization.
  21853. + *
  21854. + * The function accepts an authentication token of a parent
  21855. + * container that this object should be assigned to. The token
  21856. + * can be '0' so the object will be assigned to the default container.
  21857. + * The newly created object can be opened with the returned
  21858. + * object id and using the container's associated tokens and MC portals.
  21859. + *
  21860. + * Return: '0' on Success; Error code otherwise.
  21861. + */
  21862. +int dprtc_create(struct fsl_mc_io *mc_io,
  21863. + uint16_t dprc_token,
  21864. + uint32_t cmd_flags,
  21865. + const struct dprtc_cfg *cfg,
  21866. + uint32_t *obj_id)
  21867. +{
  21868. + struct mc_command cmd = { 0 };
  21869. + int err;
  21870. +
  21871. + (void)(cfg); /* unused */
  21872. +
  21873. + /* prepare command */
  21874. + cmd.header = mc_encode_cmd_header(DPRTC_CMDID_CREATE,
  21875. + cmd_flags,
  21876. + dprc_token);
  21877. +
  21878. + /* send command to mc*/
  21879. + err = mc_send_command(mc_io, &cmd);
  21880. + if (err)
  21881. + return err;
  21882. +
  21883. + /* retrieve response parameters */
  21884. + *obj_id = mc_cmd_read_object_id(&cmd);
  21885. +
  21886. + return 0;
  21887. +}
  21888. +
  21889. +/**
  21890. + * dprtc_destroy() - Destroy the DPRTC object and release all its resources.
  21891. + * @mc_io: Pointer to MC portal's I/O object
  21892. + * @dprc_token: Parent container token; '0' for default container
  21893. + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
  21894. + * @object_id: The object id; it must be a valid id within the container that
  21895. + * created this object;
  21896. + *
  21897. + * The function accepts the authentication token of the parent container that
  21898. + * created the object (not the one that currently owns the object). The object
  21899. + * is searched within parent using the provided 'object_id'.
  21900. + * All tokens to the object must be closed before calling destroy.
  21901. + *
  21902. + * Return: '0' on Success; error code otherwise.
  21903. + */
  21904. +int dprtc_destroy(struct fsl_mc_io *mc_io,
  21905. + uint16_t dprc_token,
  21906. + uint32_t cmd_flags,
  21907. + uint32_t object_id)
  21908. +{
  21909. + struct dprtc_cmd_destroy *cmd_params;
  21910. + struct mc_command cmd = { 0 };
  21911. +
  21912. + /* prepare command */
  21913. + cmd.header = mc_encode_cmd_header(DPRTC_CMDID_DESTROY,
  21914. + cmd_flags,
  21915. + dprc_token);
  21916. + cmd_params = (struct dprtc_cmd_destroy *)cmd.params;
  21917. + cmd_params->object_id = cpu_to_le32(object_id);
  21918. +
  21919. + /* send command to mc*/
  21920. + return mc_send_command(mc_io, &cmd);
  21921. +}
  21922. +
  21923. +int dprtc_enable(struct fsl_mc_io *mc_io,
  21924. + uint32_t cmd_flags,
  21925. + uint16_t token)
  21926. +{
  21927. + struct mc_command cmd = { 0 };
  21928. +
  21929. + /* prepare command */
  21930. + cmd.header = mc_encode_cmd_header(DPRTC_CMDID_ENABLE, cmd_flags,
  21931. + token);
  21932. +
  21933. + /* send command to mc*/
  21934. + return mc_send_command(mc_io, &cmd);
  21935. +}
  21936. +
  21937. +int dprtc_disable(struct fsl_mc_io *mc_io,
  21938. + uint32_t cmd_flags,
  21939. + uint16_t token)
  21940. +{
  21941. + struct mc_command cmd = { 0 };
  21942. +
  21943. + /* prepare command */
  21944. + cmd.header = mc_encode_cmd_header(DPRTC_CMDID_DISABLE,
  21945. + cmd_flags,
  21946. + token);
  21947. +
  21948. + /* send command to mc*/
  21949. + return mc_send_command(mc_io, &cmd);
  21950. +}
  21951. +
  21952. +int dprtc_is_enabled(struct fsl_mc_io *mc_io,
  21953. + uint32_t cmd_flags,
  21954. + uint16_t token,
  21955. + int *en)
  21956. +{
  21957. + struct dprtc_rsp_is_enabled *rsp_params;
  21958. + struct mc_command cmd = { 0 };
  21959. + int err;
  21960. +
  21961. + /* prepare command */
  21962. + cmd.header = mc_encode_cmd_header(DPRTC_CMDID_IS_ENABLED, cmd_flags,
  21963. + token);
  21964. +
  21965. + /* send command to mc*/
  21966. + err = mc_send_command(mc_io, &cmd);
  21967. + if (err)
  21968. + return err;
  21969. +
  21970. + /* retrieve response parameters */
  21971. + rsp_params = (struct dprtc_rsp_is_enabled *)cmd.params;
  21972. + *en = dprtc_get_field(rsp_params->en, ENABLE);
  21973. +
  21974. + return 0;
  21975. +}
  21976. +
  21977. +int dprtc_reset(struct fsl_mc_io *mc_io,
  21978. + uint32_t cmd_flags,
  21979. + uint16_t token)
  21980. +{
  21981. + struct mc_command cmd = { 0 };
  21982. +
  21983. + /* prepare command */
  21984. + cmd.header = mc_encode_cmd_header(DPRTC_CMDID_RESET,
  21985. + cmd_flags,
  21986. + token);
  21987. +
  21988. + /* send command to mc*/
  21989. + return mc_send_command(mc_io, &cmd);
  21990. +}
  21991. +
  21992. +/**
  21993. + * dprtc_set_irq_enable() - Set overall interrupt state.
  21994. + * @mc_io: Pointer to MC portal's I/O object
  21995. + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
  21996. + * @token: Token of DPRTC object
  21997. + * @irq_index: The interrupt index to configure
  21998. + * @en: Interrupt state - enable = 1, disable = 0
  21999. + *
  22000. + * Allows GPP software to control when interrupts are generated.
  22001. + * Each interrupt can have up to 32 causes. The enable/disable control's the
  22002. + * overall interrupt state. if the interrupt is disabled no causes will cause
  22003. + * an interrupt.
  22004. + *
  22005. + * Return: '0' on Success; Error code otherwise.
  22006. + */
  22007. +int dprtc_set_irq_enable(struct fsl_mc_io *mc_io,
  22008. + uint32_t cmd_flags,
  22009. + uint16_t token,
  22010. + uint8_t irq_index,
  22011. + uint8_t en)
  22012. +{
  22013. + struct dprtc_cmd_set_irq_enable *cmd_params;
  22014. + struct mc_command cmd = { 0 };
  22015. +
  22016. + /* prepare command */
  22017. + cmd.header = mc_encode_cmd_header(DPRTC_CMDID_SET_IRQ_ENABLE,
  22018. + cmd_flags,
  22019. + token);
  22020. + cmd_params = (struct dprtc_cmd_set_irq_enable *)cmd.params;
  22021. + cmd_params->irq_index = irq_index;
  22022. + cmd_params->en = en;
  22023. +
  22024. + /* send command to mc*/
  22025. + return mc_send_command(mc_io, &cmd);
  22026. +}
  22027. +
  22028. +/**
  22029. + * dprtc_get_irq_enable() - Get overall interrupt state
  22030. + * @mc_io: Pointer to MC portal's I/O object
  22031. + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
  22032. + * @token: Token of DPRTC object
  22033. + * @irq_index: The interrupt index to configure
  22034. + * @en: Returned interrupt state - enable = 1, disable = 0
  22035. + *
  22036. + * Return: '0' on Success; Error code otherwise.
  22037. + */
  22038. +int dprtc_get_irq_enable(struct fsl_mc_io *mc_io,
  22039. + uint32_t cmd_flags,
  22040. + uint16_t token,
  22041. + uint8_t irq_index,
  22042. + uint8_t *en)
  22043. +{
  22044. + struct dprtc_rsp_get_irq_enable *rsp_params;
  22045. + struct dprtc_cmd_get_irq *cmd_params;
  22046. + struct mc_command cmd = { 0 };
  22047. + int err;
  22048. +
  22049. + /* prepare command */
  22050. + cmd.header = mc_encode_cmd_header(DPRTC_CMDID_GET_IRQ_ENABLE,
  22051. + cmd_flags,
  22052. + token);
  22053. + cmd_params = (struct dprtc_cmd_get_irq *)cmd.params;
  22054. + cmd_params->irq_index = irq_index;
  22055. +
  22056. + /* send command to mc*/
  22057. + err = mc_send_command(mc_io, &cmd);
  22058. + if (err)
  22059. + return err;
  22060. +
  22061. + /* retrieve response parameters */
  22062. + rsp_params = (struct dprtc_rsp_get_irq_enable *)cmd.params;
  22063. + *en = rsp_params->en;
  22064. +
  22065. + return 0;
  22066. +}
  22067. +
  22068. +/**
  22069. + * dprtc_set_irq_mask() - Set interrupt mask.
  22070. + * @mc_io: Pointer to MC portal's I/O object
  22071. + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
  22072. + * @token: Token of DPRTC object
  22073. + * @irq_index: The interrupt index to configure
  22074. + * @mask: Event mask to trigger interrupt;
  22075. + * each bit:
  22076. + * 0 = ignore event
  22077. + * 1 = consider event for asserting IRQ
  22078. + *
  22079. + * Every interrupt can have up to 32 causes and the interrupt model supports
  22080. + * masking/unmasking each cause independently
  22081. + *
  22082. + * Return: '0' on Success; Error code otherwise.
  22083. + */
  22084. +int dprtc_set_irq_mask(struct fsl_mc_io *mc_io,
  22085. + uint32_t cmd_flags,
  22086. + uint16_t token,
  22087. + uint8_t irq_index,
  22088. + uint32_t mask)
  22089. +{
  22090. + struct dprtc_cmd_set_irq_mask *cmd_params;
  22091. + struct mc_command cmd = { 0 };
  22092. +
  22093. + /* prepare command */
  22094. + cmd.header = mc_encode_cmd_header(DPRTC_CMDID_SET_IRQ_MASK,
  22095. + cmd_flags,
  22096. + token);
  22097. + cmd_params = (struct dprtc_cmd_set_irq_mask *)cmd.params;
  22098. + cmd_params->mask = cpu_to_le32(mask);
  22099. + cmd_params->irq_index = irq_index;
  22100. +
  22101. + /* send command to mc*/
  22102. + return mc_send_command(mc_io, &cmd);
  22103. +}
  22104. +
  22105. +/**
  22106. + * dprtc_get_irq_mask() - Get interrupt mask.
  22107. + * @mc_io: Pointer to MC portal's I/O object
  22108. + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
  22109. + * @token: Token of DPRTC object
  22110. + * @irq_index: The interrupt index to configure
  22111. + * @mask: Returned event mask to trigger interrupt
  22112. + *
  22113. + * Every interrupt can have up to 32 causes and the interrupt model supports
  22114. + * masking/unmasking each cause independently
  22115. + *
  22116. + * Return: '0' on Success; Error code otherwise.
  22117. + */
  22118. +int dprtc_get_irq_mask(struct fsl_mc_io *mc_io,
  22119. + uint32_t cmd_flags,
  22120. + uint16_t token,
  22121. + uint8_t irq_index,
  22122. + uint32_t *mask)
  22123. +{
  22124. + struct dprtc_rsp_get_irq_mask *rsp_params;
  22125. + struct dprtc_cmd_get_irq *cmd_params;
  22126. + struct mc_command cmd = { 0 };
  22127. + int err;
  22128. +
  22129. + /* prepare command */
  22130. + cmd.header = mc_encode_cmd_header(DPRTC_CMDID_GET_IRQ_MASK,
  22131. + cmd_flags,
  22132. + token);
  22133. + cmd_params = (struct dprtc_cmd_get_irq *)cmd.params;
  22134. + cmd_params->irq_index = irq_index;
  22135. +
  22136. + /* send command to mc*/
  22137. + err = mc_send_command(mc_io, &cmd);
  22138. + if (err)
  22139. + return err;
  22140. +
  22141. + /* retrieve response parameters */
  22142. + rsp_params = (struct dprtc_rsp_get_irq_mask *)cmd.params;
  22143. + *mask = le32_to_cpu(rsp_params->mask);
  22144. +
  22145. + return 0;
  22146. +}
  22147. +
  22148. +/**
  22149. + * dprtc_get_irq_status() - Get the current status of any pending interrupts.
  22150. + *
  22151. + * @mc_io: Pointer to MC portal's I/O object
  22152. + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
  22153. + * @token: Token of DPRTC object
  22154. + * @irq_index: The interrupt index to configure
  22155. + * @status: Returned interrupts status - one bit per cause:
  22156. + * 0 = no interrupt pending
  22157. + * 1 = interrupt pending
  22158. + *
  22159. + * Return: '0' on Success; Error code otherwise.
  22160. + */
  22161. +int dprtc_get_irq_status(struct fsl_mc_io *mc_io,
  22162. + uint32_t cmd_flags,
  22163. + uint16_t token,
  22164. + uint8_t irq_index,
  22165. + uint32_t *status)
  22166. +{
  22167. + struct dprtc_cmd_get_irq_status *cmd_params;
  22168. + struct dprtc_rsp_get_irq_status *rsp_params;
  22169. + struct mc_command cmd = { 0 };
  22170. + int err;
  22171. +
  22172. + /* prepare command */
  22173. + cmd.header = mc_encode_cmd_header(DPRTC_CMDID_GET_IRQ_STATUS,
  22174. + cmd_flags,
  22175. + token);
  22176. + cmd_params = (struct dprtc_cmd_get_irq_status *)cmd.params;
  22177. + cmd_params->status = cpu_to_le32(*status);
  22178. + cmd_params->irq_index = irq_index;
  22179. +
  22180. + /* send command to mc*/
  22181. + err = mc_send_command(mc_io, &cmd);
  22182. + if (err)
  22183. + return err;
  22184. +
  22185. + /* retrieve response parameters */
  22186. + rsp_params = (struct dprtc_rsp_get_irq_status *)cmd.params;
  22187. + *status = rsp_params->status;
  22188. +
  22189. + return 0;
  22190. +}
  22191. +
  22192. +/**
  22193. + * dprtc_clear_irq_status() - Clear a pending interrupt's status
  22194. + *
  22195. + * @mc_io: Pointer to MC portal's I/O object
  22196. + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
  22197. + * @token: Token of DPRTC object
  22198. + * @irq_index: The interrupt index to configure
  22199. + * @status: Bits to clear (W1C) - one bit per cause:
  22200. + * 0 = don't change
  22201. + * 1 = clear status bit
  22202. + *
  22203. + * Return: '0' on Success; Error code otherwise.
  22204. + */
  22205. +int dprtc_clear_irq_status(struct fsl_mc_io *mc_io,
  22206. + uint32_t cmd_flags,
  22207. + uint16_t token,
  22208. + uint8_t irq_index,
  22209. + uint32_t status)
  22210. +{
  22211. + struct dprtc_cmd_clear_irq_status *cmd_params;
  22212. + struct mc_command cmd = { 0 };
  22213. +
  22214. + /* prepare command */
  22215. + cmd.header = mc_encode_cmd_header(DPRTC_CMDID_CLEAR_IRQ_STATUS,
  22216. + cmd_flags,
  22217. + token);
  22218. + cmd_params = (struct dprtc_cmd_clear_irq_status *)cmd.params;
  22219. + cmd_params->irq_index = irq_index;
  22220. + cmd_params->status = cpu_to_le32(status);
  22221. +
  22222. + /* send command to mc*/
  22223. + return mc_send_command(mc_io, &cmd);
  22224. +}
  22225. +
  22226. +/**
  22227. + * dprtc_get_attributes - Retrieve DPRTC attributes.
  22228. + *
  22229. + * @mc_io: Pointer to MC portal's I/O object
  22230. + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
  22231. + * @token: Token of DPRTC object
  22232. + * @attr: Returned object's attributes
  22233. + *
  22234. + * Return: '0' on Success; Error code otherwise.
  22235. + */
  22236. +int dprtc_get_attributes(struct fsl_mc_io *mc_io,
  22237. + uint32_t cmd_flags,
  22238. + uint16_t token,
  22239. + struct dprtc_attr *attr)
  22240. +{
  22241. + struct dprtc_rsp_get_attributes *rsp_params;
  22242. + struct mc_command cmd = { 0 };
  22243. + int err;
  22244. +
  22245. + /* prepare command */
  22246. + cmd.header = mc_encode_cmd_header(DPRTC_CMDID_GET_ATTR,
  22247. + cmd_flags,
  22248. + token);
  22249. +
  22250. + /* send command to mc*/
  22251. + err = mc_send_command(mc_io, &cmd);
  22252. + if (err)
  22253. + return err;
  22254. +
  22255. + /* retrieve response parameters */
  22256. + rsp_params = (struct dprtc_rsp_get_attributes *)cmd.params;
  22257. + attr->id = le32_to_cpu(rsp_params->id);
  22258. +
  22259. + return 0;
  22260. +}
  22261. +
  22262. +/**
  22263. + * dprtc_set_clock_offset() - Sets the clock's offset
  22264. + * (usually relative to another clock).
  22265. + *
  22266. + * @mc_io: Pointer to MC portal's I/O object
  22267. + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
  22268. + * @token: Token of DPRTC object
  22269. + * @offset: New clock offset (in nanoseconds).
  22270. + *
  22271. + * Return: '0' on Success; Error code otherwise.
  22272. + */
  22273. +int dprtc_set_clock_offset(struct fsl_mc_io *mc_io,
  22274. + uint32_t cmd_flags,
  22275. + uint16_t token,
  22276. + int64_t offset)
  22277. +{
  22278. + struct dprtc_cmd_set_clock_offset *cmd_params;
  22279. + struct mc_command cmd = { 0 };
  22280. +
  22281. + /* prepare command */
  22282. + cmd.header = mc_encode_cmd_header(DPRTC_CMDID_SET_CLOCK_OFFSET,
  22283. + cmd_flags,
  22284. + token);
  22285. + cmd_params = (struct dprtc_cmd_set_clock_offset *)cmd.params;
  22286. + cmd_params->offset = cpu_to_le64(offset);
  22287. +
  22288. + /* send command to mc*/
  22289. + return mc_send_command(mc_io, &cmd);
  22290. +}
  22291. +
  22292. +/**
  22293. + * dprtc_set_freq_compensation() - Sets a new frequency compensation value.
  22294. + *
  22295. + * @mc_io: Pointer to MC portal's I/O object
  22296. + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
  22297. + * @token: Token of DPRTC object
  22298. + * @freq_compensation: The new frequency compensation value to set.
  22299. + *
  22300. + * Return: '0' on Success; Error code otherwise.
  22301. + */
  22302. +int dprtc_set_freq_compensation(struct fsl_mc_io *mc_io,
  22303. + uint32_t cmd_flags,
  22304. + uint16_t token,
  22305. + uint32_t freq_compensation)
  22306. +{
  22307. + struct dprtc_get_freq_compensation *cmd_params;
  22308. + struct mc_command cmd = { 0 };
  22309. +
  22310. + /* prepare command */
  22311. + cmd.header = mc_encode_cmd_header(DPRTC_CMDID_SET_FREQ_COMPENSATION,
  22312. + cmd_flags,
  22313. + token);
  22314. + cmd_params = (struct dprtc_get_freq_compensation *)cmd.params;
  22315. + cmd_params->freq_compensation = cpu_to_le32(freq_compensation);
  22316. +
  22317. + /* send command to mc*/
  22318. + return mc_send_command(mc_io, &cmd);
  22319. +}
  22320. +
  22321. +/**
  22322. + * dprtc_get_freq_compensation() - Retrieves the frequency compensation value
  22323. + *
  22324. + * @mc_io: Pointer to MC portal's I/O object
  22325. + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
  22326. + * @token: Token of DPRTC object
  22327. + * @freq_compensation: Frequency compensation value
  22328. + *
  22329. + * Return: '0' on Success; Error code otherwise.
  22330. + */
  22331. +int dprtc_get_freq_compensation(struct fsl_mc_io *mc_io,
  22332. + uint32_t cmd_flags,
  22333. + uint16_t token,
  22334. + uint32_t *freq_compensation)
  22335. +{
  22336. + struct dprtc_get_freq_compensation *rsp_params;
  22337. + struct mc_command cmd = { 0 };
  22338. + int err;
  22339. +
  22340. + /* prepare command */
  22341. + cmd.header = mc_encode_cmd_header(DPRTC_CMDID_GET_FREQ_COMPENSATION,
  22342. + cmd_flags,
  22343. + token);
  22344. +
  22345. + /* send command to mc*/
  22346. + err = mc_send_command(mc_io, &cmd);
  22347. + if (err)
  22348. + return err;
  22349. +
  22350. + /* retrieve response parameters */
  22351. + rsp_params = (struct dprtc_get_freq_compensation *)cmd.params;
  22352. + *freq_compensation = le32_to_cpu(rsp_params->freq_compensation);
  22353. +
  22354. + return 0;
  22355. +}
  22356. +
  22357. +/**
  22358. + * dprtc_get_time() - Returns the current RTC time.
  22359. + *
  22360. + * @mc_io: Pointer to MC portal's I/O object
  22361. + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
  22362. + * @token: Token of DPRTC object
  22363. + * @time: Current RTC time.
  22364. + *
  22365. + * Return: '0' on Success; Error code otherwise.
  22366. + */
  22367. +int dprtc_get_time(struct fsl_mc_io *mc_io,
  22368. + uint32_t cmd_flags,
  22369. + uint16_t token,
  22370. + uint64_t *time)
  22371. +{
  22372. + struct dprtc_time *rsp_params;
  22373. + struct mc_command cmd = { 0 };
  22374. + int err;
  22375. +
  22376. + /* prepare command */
  22377. + cmd.header = mc_encode_cmd_header(DPRTC_CMDID_GET_TIME,
  22378. + cmd_flags,
  22379. + token);
  22380. +
  22381. + /* send command to mc*/
  22382. + err = mc_send_command(mc_io, &cmd);
  22383. + if (err)
  22384. + return err;
  22385. +
  22386. + /* retrieve response parameters */
  22387. + rsp_params = (struct dprtc_time *)cmd.params;
  22388. + *time = le64_to_cpu(rsp_params->time);
  22389. +
  22390. + return 0;
  22391. +}
  22392. +
  22393. +/**
  22394. + * dprtc_set_time() - Updates current RTC time.
  22395. + *
  22396. + * @mc_io: Pointer to MC portal's I/O object
  22397. + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
  22398. + * @token: Token of DPRTC object
  22399. + * @time: New RTC time.
  22400. + *
  22401. + * Return: '0' on Success; Error code otherwise.
  22402. + */
  22403. +int dprtc_set_time(struct fsl_mc_io *mc_io,
  22404. + uint32_t cmd_flags,
  22405. + uint16_t token,
  22406. + uint64_t time)
  22407. +{
  22408. + struct dprtc_time *cmd_params;
  22409. + struct mc_command cmd = { 0 };
  22410. +
  22411. + /* prepare command */
  22412. + cmd.header = mc_encode_cmd_header(DPRTC_CMDID_SET_TIME,
  22413. + cmd_flags,
  22414. + token);
  22415. + cmd_params = (struct dprtc_time *)cmd.params;
  22416. + cmd_params->time = cpu_to_le64(time);
  22417. +
  22418. + /* send command to mc*/
  22419. + return mc_send_command(mc_io, &cmd);
  22420. +}
  22421. +
  22422. +/**
  22423. + * dprtc_set_alarm() - Defines and sets alarm.
  22424. + *
  22425. + * @mc_io: Pointer to MC portal's I/O object
  22426. + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
  22427. + * @token: Token of DPRTC object
  22428. + * @time: In nanoseconds, the time when the alarm
  22429. + * should go off - must be a multiple of
  22430. + * 1 microsecond
  22431. + *
  22432. + * Return: '0' on Success; Error code otherwise.
  22433. + */
  22434. +int dprtc_set_alarm(struct fsl_mc_io *mc_io,
  22435. + uint32_t cmd_flags,
  22436. + uint16_t token, uint64_t time)
  22437. +{
  22438. + struct dprtc_time *cmd_params;
  22439. + struct mc_command cmd = { 0 };
  22440. +
  22441. + /* prepare command */
  22442. + cmd.header = mc_encode_cmd_header(DPRTC_CMDID_SET_ALARM,
  22443. + cmd_flags,
  22444. + token);
  22445. + cmd_params = (struct dprtc_time *)cmd.params;
  22446. + cmd_params->time = cpu_to_le64(time);
  22447. +
  22448. + /* send command to mc*/
  22449. + return mc_send_command(mc_io, &cmd);
  22450. +}
  22451. +
  22452. +/**
  22453. + * dprtc_get_api_version() - Get Data Path Real Time Counter API version
  22454. + * @mc_io: Pointer to MC portal's I/O object
  22455. + * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
  22456. + * @major_ver: Major version of data path real time counter API
  22457. + * @minor_ver: Minor version of data path real time counter API
  22458. + *
  22459. + * Return: '0' on Success; Error code otherwise.
  22460. + */
  22461. +int dprtc_get_api_version(struct fsl_mc_io *mc_io,
  22462. + uint32_t cmd_flags,
  22463. + uint16_t *major_ver,
  22464. + uint16_t *minor_ver)
  22465. +{
  22466. + struct dprtc_rsp_get_api_version *rsp_params;
  22467. + struct mc_command cmd = { 0 };
  22468. + int err;
  22469. +
  22470. + cmd.header = mc_encode_cmd_header(DPRTC_CMDID_GET_API_VERSION,
  22471. + cmd_flags,
  22472. + 0);
  22473. +
  22474. + err = mc_send_command(mc_io, &cmd);
  22475. + if (err)
  22476. + return err;
  22477. +
  22478. + rsp_params = (struct dprtc_rsp_get_api_version *)cmd.params;
  22479. + *major_ver = le16_to_cpu(rsp_params->major);
  22480. + *minor_ver = le16_to_cpu(rsp_params->minor);
  22481. +
  22482. + return 0;
  22483. +}
  22484. --- /dev/null
  22485. +++ b/drivers/staging/fsl-dpaa2/rtc/dprtc.h
  22486. @@ -0,0 +1,172 @@
  22487. +/* Copyright 2013-2016 Freescale Semiconductor Inc.
  22488. + *
  22489. + * Redistribution and use in source and binary forms, with or without
  22490. + * modification, are permitted provided that the following conditions are met:
  22491. + * * Redistributions of source code must retain the above copyright
  22492. + * notice, this list of conditions and the following disclaimer.
  22493. + * * Redistributions in binary form must reproduce the above copyright
  22494. + * notice, this list of conditions and the following disclaimer in the
  22495. + * documentation and/or other materials provided with the distribution.
  22496. + * * Neither the name of the above-listed copyright holders nor the
  22497. + * names of any contributors may be used to endorse or promote products
  22498. + * derived from this software without specific prior written permission.
  22499. + *
  22500. + *
  22501. + * ALTERNATIVELY, this software may be distributed under the terms of the
  22502. + * GNU General Public License ("GPL") as published by the Free Software
  22503. + * Foundation, either version 2 of that License or (at your option) any
  22504. + * later version.
  22505. + *
  22506. + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  22507. + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  22508. + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  22509. + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
  22510. + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  22511. + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  22512. + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  22513. + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  22514. + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  22515. + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  22516. + * POSSIBILITY OF SUCH DAMAGE.
  22517. + */
  22518. +#ifndef __FSL_DPRTC_H
  22519. +#define __FSL_DPRTC_H
  22520. +
  22521. +/* Data Path Real Time Counter API
  22522. + * Contains initialization APIs and runtime control APIs for RTC
  22523. + */
  22524. +
  22525. +struct fsl_mc_io;
  22526. +
  22527. +/**
  22528. + * Number of irq's
  22529. + */
  22530. +#define DPRTC_MAX_IRQ_NUM 1
  22531. +#define DPRTC_IRQ_INDEX 0
  22532. +
  22533. +/**
  22534. + * Interrupt event masks:
  22535. + */
  22536. +
  22537. +/**
  22538. + * Interrupt event mask indicating alarm event had occurred
  22539. + */
  22540. +#define DPRTC_EVENT_ALARM 0x40000000
  22541. +/**
  22542. + * Interrupt event mask indicating periodic pulse event had occurred
  22543. + */
  22544. +#define DPRTC_EVENT_PPS 0x08000000
  22545. +
  22546. +int dprtc_open(struct fsl_mc_io *mc_io,
  22547. + uint32_t cmd_flags,
  22548. + int dprtc_id,
  22549. + uint16_t *token);
  22550. +
  22551. +int dprtc_close(struct fsl_mc_io *mc_io,
  22552. + uint32_t cmd_flags,
  22553. + uint16_t token);
  22554. +
  22555. +/**
  22556. + * struct dprtc_cfg - Structure representing DPRTC configuration
  22557. + * @options: place holder
  22558. + */
  22559. +struct dprtc_cfg {
  22560. + uint32_t options;
  22561. +};
  22562. +
  22563. +int dprtc_create(struct fsl_mc_io *mc_io,
  22564. + uint16_t dprc_token,
  22565. + uint32_t cmd_flags,
  22566. + const struct dprtc_cfg *cfg,
  22567. + uint32_t *obj_id);
  22568. +
  22569. +int dprtc_destroy(struct fsl_mc_io *mc_io,
  22570. + uint16_t dprc_token,
  22571. + uint32_t cmd_flags,
  22572. + uint32_t object_id);
  22573. +
  22574. +int dprtc_set_clock_offset(struct fsl_mc_io *mc_io,
  22575. + uint32_t cmd_flags,
  22576. + uint16_t token,
  22577. + int64_t offset);
  22578. +
  22579. +int dprtc_set_freq_compensation(struct fsl_mc_io *mc_io,
  22580. + uint32_t cmd_flags,
  22581. + uint16_t token,
  22582. + uint32_t freq_compensation);
  22583. +
  22584. +int dprtc_get_freq_compensation(struct fsl_mc_io *mc_io,
  22585. + uint32_t cmd_flags,
  22586. + uint16_t token,
  22587. + uint32_t *freq_compensation);
  22588. +
  22589. +int dprtc_get_time(struct fsl_mc_io *mc_io,
  22590. + uint32_t cmd_flags,
  22591. + uint16_t token,
  22592. + uint64_t *time);
  22593. +
  22594. +int dprtc_set_time(struct fsl_mc_io *mc_io,
  22595. + uint32_t cmd_flags,
  22596. + uint16_t token,
  22597. + uint64_t time);
  22598. +
  22599. +int dprtc_set_alarm(struct fsl_mc_io *mc_io,
  22600. + uint32_t cmd_flags,
  22601. + uint16_t token,
  22602. + uint64_t time);
  22603. +
  22604. +int dprtc_set_irq_enable(struct fsl_mc_io *mc_io,
  22605. + uint32_t cmd_flags,
  22606. + uint16_t token,
  22607. + uint8_t irq_index,
  22608. + uint8_t en);
  22609. +
  22610. +int dprtc_get_irq_enable(struct fsl_mc_io *mc_io,
  22611. + uint32_t cmd_flags,
  22612. + uint16_t token,
  22613. + uint8_t irq_index,
  22614. + uint8_t *en);
  22615. +
  22616. +int dprtc_set_irq_mask(struct fsl_mc_io *mc_io,
  22617. + uint32_t cmd_flags,
  22618. + uint16_t token,
  22619. + uint8_t irq_index,
  22620. + uint32_t mask);
  22621. +
  22622. +int dprtc_get_irq_mask(struct fsl_mc_io *mc_io,
  22623. + uint32_t cmd_flags,
  22624. + uint16_t token,
  22625. + uint8_t irq_index,
  22626. + uint32_t *mask);
  22627. +
  22628. +int dprtc_get_irq_status(struct fsl_mc_io *mc_io,
  22629. + uint32_t cmd_flags,
  22630. + uint16_t token,
  22631. + uint8_t irq_index,
  22632. + uint32_t *status);
  22633. +
  22634. +int dprtc_clear_irq_status(struct fsl_mc_io *mc_io,
  22635. + uint32_t cmd_flags,
  22636. + uint16_t token,
  22637. + uint8_t irq_index,
  22638. + uint32_t status);
  22639. +
  22640. +/**
  22641. + * struct dprtc_attr - Structure representing DPRTC attributes
  22642. + * @id: DPRTC object ID
  22643. + */
  22644. +struct dprtc_attr {
  22645. + int id;
  22646. +};
  22647. +
  22648. +int dprtc_get_attributes(struct fsl_mc_io *mc_io,
  22649. + uint32_t cmd_flags,
  22650. + uint16_t token,
  22651. + struct dprtc_attr *attr);
  22652. +
  22653. +int dprtc_get_api_version(struct fsl_mc_io *mc_io,
  22654. + uint32_t cmd_flags,
  22655. + uint16_t *major_ver,
  22656. + uint16_t *minor_ver);
  22657. +
  22658. +#endif /* __FSL_DPRTC_H */
  22659. --- /dev/null
  22660. +++ b/drivers/staging/fsl-dpaa2/rtc/rtc.c
  22661. @@ -0,0 +1,243 @@
  22662. +/* Copyright 2013-2015 Freescale Semiconductor Inc.
  22663. + *
  22664. + * Redistribution and use in source and binary forms, with or without
  22665. + * modification, are permitted provided that the following conditions are met:
  22666. + * * Redistributions of source code must retain the above copyright
  22667. + * notice, this list of conditions and the following disclaimer.
  22668. + * * Redistributions in binary form must reproduce the above copyright
  22669. + * notice, this list of conditions and the following disclaimer in the
  22670. + * documentation and/or other materials provided with the distribution.
  22671. + * * Neither the name of the above-listed copyright holders nor the
  22672. + * names of any contributors may be used to endorse or promote products
  22673. + * derived from this software without specific prior written permission.
  22674. + *
  22675. + *
  22676. + * ALTERNATIVELY, this software may be distributed under the terms of the
  22677. + * GNU General Public License ("GPL") as published by the Free Software
  22678. + * Foundation, either version 2 of that License or (at your option) any
  22679. + * later version.
  22680. + *
  22681. + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  22682. + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  22683. + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  22684. + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
  22685. + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  22686. + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  22687. + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  22688. + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  22689. + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  22690. + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  22691. + * POSSIBILITY OF SUCH DAMAGE.
  22692. + */
  22693. +
  22694. +#include <linux/module.h>
  22695. +#include <linux/ptp_clock_kernel.h>
  22696. +
  22697. +#include "../../fsl-mc/include/mc.h"
  22698. +#include "../../fsl-mc/include/mc-sys.h"
  22699. +
  22700. +#include "dprtc.h"
  22701. +#include "dprtc-cmd.h"
  22702. +
  22703. +#define N_EXT_TS 2
  22704. +
  22705. +struct ptp_clock *clock;
  22706. +struct fsl_mc_device *rtc_mc_dev;
  22707. +u32 freqCompensation;
  22708. +
  22709. +/* PTP clock operations */
  22710. +static int ptp_dpaa2_adjfreq(struct ptp_clock_info *ptp, s32 ppb)
  22711. +{
  22712. + u64 adj;
  22713. + u32 diff, tmr_add;
  22714. + int neg_adj = 0;
  22715. + int err = 0;
  22716. + struct fsl_mc_device *mc_dev = rtc_mc_dev;
  22717. + struct device *dev = &mc_dev->dev;
  22718. +
  22719. + if (ppb < 0) {
  22720. + neg_adj = 1;
  22721. + ppb = -ppb;
  22722. + }
  22723. +
  22724. + tmr_add = freqCompensation;
  22725. + adj = tmr_add;
  22726. + adj *= ppb;
  22727. + diff = div_u64(adj, 1000000000ULL);
  22728. +
  22729. + tmr_add = neg_adj ? tmr_add - diff : tmr_add + diff;
  22730. +
  22731. + err = dprtc_set_freq_compensation(mc_dev->mc_io, 0,
  22732. + mc_dev->mc_handle, tmr_add);
  22733. + if (err)
  22734. + dev_err(dev, "dprtc_set_freq_compensation err %d\n", err);
  22735. + return 0;
  22736. +}
  22737. +
  22738. +static int ptp_dpaa2_adjtime(struct ptp_clock_info *ptp, s64 delta)
  22739. +{
  22740. + s64 now;
  22741. + int err = 0;
  22742. + struct fsl_mc_device *mc_dev = rtc_mc_dev;
  22743. + struct device *dev = &mc_dev->dev;
  22744. +
  22745. + err = dprtc_get_time(mc_dev->mc_io, 0, mc_dev->mc_handle, &now);
  22746. + if (err) {
  22747. + dev_err(dev, "dprtc_get_time err %d\n", err);
  22748. + return 0;
  22749. + }
  22750. +
  22751. + now += delta;
  22752. +
  22753. + err = dprtc_set_time(mc_dev->mc_io, 0, mc_dev->mc_handle, now);
  22754. + if (err) {
  22755. + dev_err(dev, "dprtc_set_time err %d\n", err);
  22756. + return 0;
  22757. + }
  22758. + return 0;
  22759. +}
  22760. +
  22761. +static int ptp_dpaa2_gettime(struct ptp_clock_info *ptp, struct timespec *ts)
  22762. +{
  22763. + u64 ns;
  22764. + u32 remainder;
  22765. + int err = 0;
  22766. + struct fsl_mc_device *mc_dev = rtc_mc_dev;
  22767. + struct device *dev = &mc_dev->dev;
  22768. +
  22769. + err = dprtc_get_time(mc_dev->mc_io, 0, mc_dev->mc_handle, &ns);
  22770. + if (err) {
  22771. + dev_err(dev, "dprtc_get_time err %d\n", err);
  22772. + return 0;
  22773. + }
  22774. +
  22775. + ts->tv_sec = div_u64_rem(ns, 1000000000, &remainder);
  22776. + ts->tv_nsec = remainder;
  22777. + return 0;
  22778. +}
  22779. +
  22780. +static int ptp_dpaa2_settime(struct ptp_clock_info *ptp,
  22781. + const struct timespec *ts)
  22782. +{
  22783. + u64 ns;
  22784. + int err = 0;
  22785. + struct fsl_mc_device *mc_dev = rtc_mc_dev;
  22786. + struct device *dev = &mc_dev->dev;
  22787. +
  22788. + ns = ts->tv_sec * 1000000000ULL;
  22789. + ns += ts->tv_nsec;
  22790. +
  22791. + err = dprtc_set_time(mc_dev->mc_io, 0, mc_dev->mc_handle, ns);
  22792. + if (err)
  22793. + dev_err(dev, "dprtc_set_time err %d\n", err);
  22794. + return 0;
  22795. +}
  22796. +
  22797. +static struct ptp_clock_info ptp_dpaa2_caps = {
  22798. + .owner = THIS_MODULE,
  22799. + .name = "dpaa2 clock",
  22800. + .max_adj = 512000,
  22801. + .n_alarm = 0,
  22802. + .n_ext_ts = N_EXT_TS,
  22803. + .n_per_out = 0,
  22804. + .n_pins = 0,
  22805. + .pps = 1,
  22806. + .adjfreq = ptp_dpaa2_adjfreq,
  22807. + .adjtime = ptp_dpaa2_adjtime,
  22808. + .gettime64 = ptp_dpaa2_gettime,
  22809. + .settime64 = ptp_dpaa2_settime,
  22810. +};
  22811. +
  22812. +static int rtc_probe(struct fsl_mc_device *mc_dev)
  22813. +{
  22814. + struct device *dev;
  22815. + int err = 0;
  22816. + int dpaa2_phc_index;
  22817. + u32 tmr_add = 0;
  22818. +
  22819. + if (!mc_dev)
  22820. + return -EFAULT;
  22821. +
  22822. + dev = &mc_dev->dev;
  22823. +
  22824. + err = fsl_mc_portal_allocate(mc_dev, 0, &mc_dev->mc_io);
  22825. + if (unlikely(err)) {
  22826. + dev_err(dev, "fsl_mc_portal_allocate err %d\n", err);
  22827. + goto err_exit;
  22828. + }
  22829. + if (!mc_dev->mc_io) {
  22830. + dev_err(dev,
  22831. + "fsl_mc_portal_allocate returned null handle but no error\n");
  22832. + err = -EFAULT;
  22833. + goto err_exit;
  22834. + }
  22835. +
  22836. + err = dprtc_open(mc_dev->mc_io, 0, mc_dev->obj_desc.id,
  22837. + &mc_dev->mc_handle);
  22838. + if (err) {
  22839. + dev_err(dev, "dprtc_open err %d\n", err);
  22840. + goto err_free_mcp;
  22841. + }
  22842. + if (!mc_dev->mc_handle) {
  22843. + dev_err(dev, "dprtc_open returned null handle but no error\n");
  22844. + err = -EFAULT;
  22845. + goto err_free_mcp;
  22846. + }
  22847. +
  22848. + rtc_mc_dev = mc_dev;
  22849. +
  22850. + err = dprtc_get_freq_compensation(mc_dev->mc_io, 0,
  22851. + mc_dev->mc_handle, &tmr_add);
  22852. + if (err) {
  22853. + dev_err(dev, "dprtc_get_freq_compensation err %d\n", err);
  22854. + goto err_close;
  22855. + }
  22856. + freqCompensation = tmr_add;
  22857. +
  22858. + clock = ptp_clock_register(&ptp_dpaa2_caps, dev);
  22859. + if (IS_ERR(clock)) {
  22860. + err = PTR_ERR(clock);
  22861. + goto err_close;
  22862. + }
  22863. + dpaa2_phc_index = ptp_clock_index(clock);
  22864. +
  22865. + return 0;
  22866. +err_close:
  22867. + dprtc_close(mc_dev->mc_io, 0, mc_dev->mc_handle);
  22868. +err_free_mcp:
  22869. + fsl_mc_portal_free(mc_dev->mc_io);
  22870. +err_exit:
  22871. + return err;
  22872. +}
  22873. +
  22874. +static int rtc_remove(struct fsl_mc_device *mc_dev)
  22875. +{
  22876. + ptp_clock_unregister(clock);
  22877. + dprtc_close(mc_dev->mc_io, 0, mc_dev->mc_handle);
  22878. + fsl_mc_portal_free(mc_dev->mc_io);
  22879. +
  22880. + return 0;
  22881. +}
  22882. +
  22883. +static const struct fsl_mc_device_id rtc_match_id_table[] = {
  22884. + {
  22885. + .vendor = FSL_MC_VENDOR_FREESCALE,
  22886. + .obj_type = "dprtc",
  22887. + },
  22888. + {}
  22889. +};
  22890. +
  22891. +static struct fsl_mc_driver rtc_drv = {
  22892. + .driver = {
  22893. + .name = KBUILD_MODNAME,
  22894. + .owner = THIS_MODULE,
  22895. + },
  22896. + .probe = rtc_probe,
  22897. + .remove = rtc_remove,
  22898. + .match_id_table = rtc_match_id_table,
  22899. +};
  22900. +
  22901. +module_fsl_mc_driver(rtc_drv);
  22902. +
  22903. +MODULE_LICENSE("GPL");
  22904. +MODULE_DESCRIPTION("DPAA2 RTC (PTP 1588 clock) driver (prototype)");