dhd_sdio.c 263 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832383338343835383638373838383938403841384238433844384538463847384838493850385138523853385438553856385738583859386038613862386338643865386638673868386938703871387238733874387538763877387838793880388138823883388438853886388738883889389038913892389338943895389638973898389939003901390239033904390539063907390839093910391139123913391439153916391739183919392039213922392339243925392639273928392939303931393239333934393539363937393839393940394139423943394439453946394739483949395039513952395339543955395639573958395939603961396239633964396539663967396839693970397139723973397439753976397739783979398039813982398339843985398639873988398939903991399239933994399539963997399839994000400140024003400440054006400740084009401040114012401340144015401640174018401940204021402240234024402540264027402840294030403140324033403440354036403740384039404040414042404340444045404640474048404940504051405240534054405540564057405840594060406140624063406440654066406740684069407040714072407340744075407640774078407940804081408240834084408540864087408840894090409140924093409440954096409740984099410041014102410341044105410641074108410941104111411241134114411541164117411841194120412141224123412441254126412741284129413041314132413341344135413641374138413941404141414241434144414541464147414841494150415141524153415441554156415741584159416041614162416341644165416641674168416941704171417241734174417541764177417841794180418141824183418441854186418741884189419041914192419341944195419641974198419942004201420242034204420542064207420842094210421142124213421442154216421742184219422042214222422342244225422642274228422942304231423242334234423542364237423842394240424142424243424442454246424742484249425042514252425342544255425642574258425942604261426242634264426542664267426842694270427142724273427442754276427742784279428042814282428342844285428642874288428942904291429242934294429542964297429842994300430143024303430443054306430743084309431043114312431343144315431643174318431943204321432243234324432543264327432843294330433143324333433443354336433743384339434043414342434343444345434643474348434943504351435243534354435543564357435843594360436143624363436443654366436743684369437043714372437343744375437643774378437943804381438243834384438543864387438843894390439143924393439443954396439743984399440044014402440344044405440644074408440944104411441244134414441544164417441844194420442144224423442444254426442744284429443044314432443344344435443644374438443944404441444244434444444544464447444844494450445144524453445444554456445744584459446044614462446344644465446644674468446944704471447244734474447544764477447844794480448144824483448444854486448744884489449044914492449344944495449644974498449945004501450245034504450545064507450845094510451145124513451445154516451745184519452045214522452345244525452645274528452945304531453245334534453545364537453845394540454145424543454445454546454745484549455045514552455345544555455645574558455945604561456245634564456545664567456845694570457145724573457445754576457745784579458045814582458345844585458645874588458945904591459245934594459545964597459845994600460146024603460446054606460746084609461046114612461346144615461646174618461946204621462246234624462546264627462846294630463146324633463446354636463746384639464046414642464346444645464646474648464946504651465246534654465546564657465846594660466146624663466446654666466746684669467046714672467346744675467646774678467946804681468246834684468546864687468846894690469146924693469446954696469746984699470047014702470347044705470647074708470947104711471247134714471547164717471847194720472147224723472447254726472747284729473047314732473347344735473647374738473947404741474247434744474547464747474847494750475147524753475447554756475747584759476047614762476347644765476647674768476947704771477247734774477547764777477847794780478147824783478447854786478747884789479047914792479347944795479647974798479948004801480248034804480548064807480848094810481148124813481448154816481748184819482048214822482348244825482648274828482948304831483248334834483548364837483848394840484148424843484448454846484748484849485048514852485348544855485648574858485948604861486248634864486548664867486848694870487148724873487448754876487748784879488048814882488348844885488648874888488948904891489248934894489548964897489848994900490149024903490449054906490749084909491049114912491349144915491649174918491949204921492249234924492549264927492849294930493149324933493449354936493749384939494049414942494349444945494649474948494949504951495249534954495549564957495849594960496149624963496449654966496749684969497049714972497349744975497649774978497949804981498249834984498549864987498849894990499149924993499449954996499749984999500050015002500350045005500650075008500950105011501250135014501550165017501850195020502150225023502450255026502750285029503050315032503350345035503650375038503950405041504250435044504550465047504850495050505150525053505450555056505750585059506050615062506350645065506650675068506950705071507250735074507550765077507850795080508150825083508450855086508750885089509050915092509350945095509650975098509951005101510251035104510551065107510851095110511151125113511451155116511751185119512051215122512351245125512651275128512951305131513251335134513551365137513851395140514151425143514451455146514751485149515051515152515351545155515651575158515951605161516251635164516551665167516851695170517151725173517451755176517751785179518051815182518351845185518651875188518951905191519251935194519551965197519851995200520152025203520452055206520752085209521052115212521352145215521652175218521952205221522252235224522552265227522852295230523152325233523452355236523752385239524052415242524352445245524652475248524952505251525252535254525552565257525852595260526152625263526452655266526752685269527052715272527352745275527652775278527952805281528252835284528552865287528852895290529152925293529452955296529752985299530053015302530353045305530653075308530953105311531253135314531553165317531853195320532153225323532453255326532753285329533053315332533353345335533653375338533953405341534253435344534553465347534853495350535153525353535453555356535753585359536053615362536353645365536653675368536953705371537253735374537553765377537853795380538153825383538453855386538753885389539053915392539353945395539653975398539954005401540254035404540554065407540854095410541154125413541454155416541754185419542054215422542354245425542654275428542954305431543254335434543554365437543854395440544154425443544454455446544754485449545054515452545354545455545654575458545954605461546254635464546554665467546854695470547154725473547454755476547754785479548054815482548354845485548654875488548954905491549254935494549554965497549854995500550155025503550455055506550755085509551055115512551355145515551655175518551955205521552255235524552555265527552855295530553155325533553455355536553755385539554055415542554355445545554655475548554955505551555255535554555555565557555855595560556155625563556455655566556755685569557055715572557355745575557655775578557955805581558255835584558555865587558855895590559155925593559455955596559755985599560056015602560356045605560656075608560956105611561256135614561556165617561856195620562156225623562456255626562756285629563056315632563356345635563656375638563956405641564256435644564556465647564856495650565156525653565456555656565756585659566056615662566356645665566656675668566956705671567256735674567556765677567856795680568156825683568456855686568756885689569056915692569356945695569656975698569957005701570257035704570557065707570857095710571157125713571457155716571757185719572057215722572357245725572657275728572957305731573257335734573557365737573857395740574157425743574457455746574757485749575057515752575357545755575657575758575957605761576257635764576557665767576857695770577157725773577457755776577757785779578057815782578357845785578657875788578957905791579257935794579557965797579857995800580158025803580458055806580758085809581058115812581358145815581658175818581958205821582258235824582558265827582858295830583158325833583458355836583758385839584058415842584358445845584658475848584958505851585258535854585558565857585858595860586158625863586458655866586758685869587058715872587358745875587658775878587958805881588258835884588558865887588858895890589158925893589458955896589758985899590059015902590359045905590659075908590959105911591259135914591559165917591859195920592159225923592459255926592759285929593059315932593359345935593659375938593959405941594259435944594559465947594859495950595159525953595459555956595759585959596059615962596359645965596659675968596959705971597259735974597559765977597859795980598159825983598459855986598759885989599059915992599359945995599659975998599960006001600260036004600560066007600860096010601160126013601460156016601760186019602060216022602360246025602660276028602960306031603260336034603560366037603860396040604160426043604460456046604760486049605060516052605360546055605660576058605960606061606260636064606560666067606860696070607160726073607460756076607760786079608060816082608360846085608660876088608960906091609260936094609560966097609860996100610161026103610461056106610761086109611061116112611361146115611661176118611961206121612261236124612561266127612861296130613161326133613461356136613761386139614061416142614361446145614661476148614961506151615261536154615561566157615861596160616161626163616461656166616761686169617061716172617361746175617661776178617961806181618261836184618561866187618861896190619161926193619461956196619761986199620062016202620362046205620662076208620962106211621262136214621562166217621862196220622162226223622462256226622762286229623062316232623362346235623662376238623962406241624262436244624562466247624862496250625162526253625462556256625762586259626062616262626362646265626662676268626962706271627262736274627562766277627862796280628162826283628462856286628762886289629062916292629362946295629662976298629963006301630263036304630563066307630863096310631163126313631463156316631763186319632063216322632363246325632663276328632963306331633263336334633563366337633863396340634163426343634463456346634763486349635063516352635363546355635663576358635963606361636263636364636563666367636863696370637163726373637463756376637763786379638063816382638363846385638663876388638963906391639263936394639563966397639863996400640164026403640464056406640764086409641064116412641364146415641664176418641964206421642264236424642564266427642864296430643164326433643464356436643764386439644064416442644364446445644664476448644964506451645264536454645564566457645864596460646164626463646464656466646764686469647064716472647364746475647664776478647964806481648264836484648564866487648864896490649164926493649464956496649764986499650065016502650365046505650665076508650965106511651265136514651565166517651865196520652165226523652465256526652765286529653065316532653365346535653665376538653965406541654265436544654565466547654865496550655165526553655465556556655765586559656065616562656365646565656665676568656965706571657265736574657565766577657865796580658165826583658465856586658765886589659065916592659365946595659665976598659966006601660266036604660566066607660866096610661166126613661466156616661766186619662066216622662366246625662666276628662966306631663266336634663566366637663866396640664166426643664466456646664766486649665066516652665366546655665666576658665966606661666266636664666566666667666866696670667166726673667466756676667766786679668066816682668366846685668666876688668966906691669266936694669566966697669866996700670167026703670467056706670767086709671067116712671367146715671667176718671967206721672267236724672567266727672867296730673167326733673467356736673767386739674067416742674367446745674667476748674967506751675267536754675567566757675867596760676167626763676467656766676767686769677067716772677367746775677667776778677967806781678267836784678567866787678867896790679167926793679467956796679767986799680068016802680368046805680668076808680968106811681268136814681568166817681868196820682168226823682468256826682768286829683068316832683368346835683668376838683968406841684268436844684568466847684868496850685168526853685468556856685768586859686068616862686368646865686668676868686968706871687268736874687568766877687868796880688168826883688468856886688768886889689068916892689368946895689668976898689969006901690269036904690569066907690869096910691169126913691469156916691769186919692069216922692369246925692669276928692969306931693269336934693569366937693869396940694169426943694469456946694769486949695069516952695369546955695669576958695969606961696269636964696569666967696869696970697169726973697469756976697769786979698069816982698369846985698669876988698969906991699269936994699569966997699869997000700170027003700470057006700770087009701070117012701370147015701670177018701970207021702270237024702570267027702870297030703170327033703470357036703770387039704070417042704370447045704670477048704970507051705270537054705570567057705870597060706170627063706470657066706770687069707070717072707370747075707670777078707970807081708270837084708570867087708870897090709170927093709470957096709770987099710071017102710371047105710671077108710971107111711271137114711571167117711871197120712171227123712471257126712771287129713071317132713371347135713671377138713971407141714271437144714571467147714871497150715171527153715471557156715771587159716071617162716371647165716671677168716971707171717271737174717571767177717871797180718171827183718471857186718771887189719071917192719371947195719671977198719972007201720272037204720572067207720872097210721172127213721472157216721772187219722072217222722372247225722672277228722972307231723272337234723572367237723872397240724172427243724472457246724772487249725072517252725372547255725672577258725972607261726272637264726572667267726872697270727172727273727472757276727772787279728072817282728372847285728672877288728972907291729272937294729572967297729872997300730173027303730473057306730773087309731073117312731373147315731673177318731973207321732273237324732573267327732873297330733173327333733473357336733773387339734073417342734373447345734673477348734973507351735273537354735573567357735873597360736173627363736473657366736773687369737073717372737373747375737673777378737973807381738273837384738573867387738873897390739173927393739473957396739773987399740074017402740374047405740674077408740974107411741274137414741574167417741874197420742174227423742474257426742774287429743074317432743374347435743674377438743974407441744274437444744574467447744874497450745174527453745474557456745774587459746074617462746374647465746674677468746974707471747274737474747574767477747874797480748174827483748474857486748774887489749074917492749374947495749674977498749975007501750275037504750575067507750875097510751175127513751475157516751775187519752075217522752375247525752675277528752975307531753275337534753575367537753875397540754175427543754475457546754775487549755075517552755375547555755675577558755975607561756275637564756575667567756875697570757175727573757475757576757775787579758075817582758375847585758675877588758975907591759275937594759575967597759875997600760176027603760476057606760776087609761076117612761376147615761676177618761976207621762276237624762576267627762876297630763176327633763476357636763776387639764076417642764376447645764676477648764976507651765276537654765576567657765876597660766176627663766476657666766776687669767076717672767376747675767676777678767976807681768276837684768576867687768876897690769176927693769476957696769776987699770077017702770377047705770677077708770977107711771277137714771577167717771877197720772177227723772477257726772777287729773077317732773377347735773677377738773977407741774277437744774577467747774877497750775177527753775477557756775777587759776077617762776377647765776677677768776977707771777277737774777577767777777877797780778177827783778477857786778777887789779077917792779377947795779677977798779978007801780278037804780578067807780878097810781178127813781478157816781778187819782078217822782378247825782678277828782978307831783278337834783578367837783878397840784178427843784478457846784778487849785078517852785378547855785678577858785978607861786278637864786578667867786878697870787178727873787478757876787778787879788078817882788378847885788678877888788978907891789278937894789578967897789878997900790179027903790479057906790779087909791079117912791379147915791679177918791979207921792279237924792579267927792879297930793179327933793479357936793779387939794079417942794379447945794679477948794979507951795279537954795579567957795879597960796179627963796479657966796779687969797079717972797379747975797679777978797979807981798279837984798579867987798879897990799179927993799479957996799779987999800080018002800380048005800680078008800980108011801280138014801580168017801880198020802180228023802480258026802780288029803080318032803380348035803680378038803980408041804280438044804580468047804880498050805180528053805480558056805780588059806080618062806380648065806680678068806980708071807280738074807580768077807880798080808180828083808480858086808780888089809080918092809380948095809680978098809981008101810281038104810581068107810881098110811181128113811481158116811781188119812081218122812381248125812681278128812981308131813281338134813581368137813881398140814181428143814481458146814781488149815081518152815381548155815681578158815981608161816281638164816581668167816881698170817181728173817481758176817781788179818081818182818381848185818681878188818981908191819281938194819581968197819881998200820182028203820482058206820782088209821082118212821382148215821682178218821982208221822282238224822582268227822882298230823182328233823482358236823782388239824082418242824382448245824682478248824982508251825282538254825582568257825882598260826182628263826482658266826782688269827082718272827382748275827682778278827982808281828282838284828582868287828882898290829182928293829482958296829782988299830083018302830383048305830683078308830983108311831283138314831583168317831883198320832183228323832483258326832783288329833083318332833383348335833683378338833983408341834283438344834583468347834883498350835183528353835483558356835783588359836083618362836383648365836683678368836983708371837283738374837583768377837883798380838183828383838483858386838783888389839083918392839383948395839683978398839984008401840284038404840584068407840884098410841184128413841484158416841784188419842084218422842384248425842684278428842984308431843284338434843584368437843884398440844184428443844484458446844784488449845084518452845384548455845684578458845984608461846284638464846584668467846884698470847184728473847484758476847784788479848084818482848384848485848684878488848984908491849284938494849584968497849884998500850185028503850485058506850785088509851085118512851385148515851685178518851985208521852285238524852585268527852885298530853185328533853485358536853785388539854085418542854385448545854685478548854985508551855285538554855585568557855885598560856185628563856485658566856785688569857085718572857385748575857685778578857985808581858285838584858585868587858885898590859185928593859485958596859785988599860086018602860386048605860686078608860986108611861286138614861586168617861886198620862186228623862486258626862786288629863086318632863386348635863686378638863986408641864286438644864586468647864886498650865186528653865486558656865786588659866086618662866386648665866686678668866986708671867286738674867586768677867886798680868186828683868486858686868786888689869086918692869386948695869686978698869987008701870287038704870587068707870887098710871187128713871487158716871787188719872087218722872387248725872687278728872987308731873287338734873587368737873887398740874187428743874487458746874787488749875087518752875387548755875687578758875987608761876287638764876587668767876887698770877187728773877487758776877787788779878087818782878387848785878687878788878987908791879287938794879587968797879887998800880188028803880488058806880788088809881088118812881388148815881688178818881988208821882288238824882588268827882888298830883188328833883488358836883788388839884088418842884388448845884688478848884988508851885288538854885588568857885888598860886188628863886488658866886788688869887088718872887388748875887688778878887988808881888288838884888588868887888888898890889188928893889488958896889788988899890089018902890389048905890689078908890989108911891289138914891589168917891889198920892189228923892489258926892789288929893089318932893389348935893689378938893989408941894289438944894589468947894889498950895189528953895489558956895789588959896089618962896389648965896689678968896989708971897289738974897589768977897889798980898189828983898489858986898789888989899089918992899389948995899689978998899990009001900290039004900590069007900890099010901190129013901490159016901790189019902090219022902390249025902690279028902990309031903290339034903590369037903890399040904190429043904490459046904790489049905090519052905390549055905690579058905990609061906290639064906590669067906890699070907190729073907490759076907790789079908090819082908390849085908690879088908990909091909290939094909590969097909890999100910191029103910491059106910791089109911091119112911391149115911691179118911991209121912291239124912591269127912891299130913191329133913491359136913791389139914091419142914391449145914691479148914991509151915291539154915591569157915891599160916191629163916491659166916791689169917091719172917391749175917691779178917991809181918291839184918591869187918891899190919191929193919491959196919791989199920092019202920392049205920692079208920992109211921292139214921592169217921892199220922192229223922492259226922792289229923092319232923392349235923692379238923992409241924292439244924592469247924892499250925192529253925492559256925792589259926092619262926392649265926692679268926992709271927292739274927592769277927892799280928192829283928492859286928792889289929092919292929392949295929692979298929993009301930293039304930593069307930893099310931193129313931493159316931793189319932093219322932393249325932693279328932993309331933293339334933593369337933893399340934193429343934493459346934793489349935093519352935393549355935693579358935993609361936293639364936593669367936893699370937193729373937493759376937793789379938093819382938393849385938693879388
  1. /*
  2. * DHD Bus Module for SDIO
  3. *
  4. * Copyright (C) 1999-2015, Broadcom Corporation
  5. *
  6. * Unless you and Broadcom execute a separate written software license
  7. * agreement governing use of this software, this software is licensed to you
  8. * under the terms of the GNU General Public License version 2 (the "GPL"),
  9. * available at http://www.broadcom.com/licenses/GPLv2.php, with the
  10. * following added to such license:
  11. *
  12. * As a special exception, the copyright holders of this software give you
  13. * permission to link this software with independent modules, and to copy and
  14. * distribute the resulting executable under terms of your choice, provided that
  15. * you also meet, for each linked independent module, the terms and conditions of
  16. * the license of that module. An independent module is a module which is not
  17. * derived from this software. The special exception does not apply to any
  18. * modifications of the software.
  19. *
  20. * Notwithstanding the above, under no circumstances may you combine this
  21. * software in any way with any other Broadcom software provided under a license
  22. * other than the GPL, without Broadcom's express prior written consent.
  23. *
  24. * $Id: dhd_sdio.c 604396 2015-12-07 06:50:33Z $
  25. */
  26. #include <typedefs.h>
  27. #include <osl.h>
  28. #include <bcmsdh.h>
  29. #ifdef BCMEMBEDIMAGE
  30. #include BCMEMBEDIMAGE
  31. #endif /* BCMEMBEDIMAGE */
  32. #include <bcmdefs.h>
  33. #include <bcmutils.h>
  34. #include <bcmendian.h>
  35. #include <bcmdevs.h>
  36. #include <siutils.h>
  37. #include <hndpmu.h>
  38. #include <hndsoc.h>
  39. #include <bcmsdpcm.h>
  40. #if defined(DHD_DEBUG)
  41. #include <hndrte_armtrap.h>
  42. #include <hndrte_cons.h>
  43. #endif /* defined(DHD_DEBUG) */
  44. #include <sbchipc.h>
  45. #include <sbhnddma.h>
  46. #include <sdio.h>
  47. #ifdef BCMSPI
  48. #include <spid.h>
  49. #endif /* BCMSPI */
  50. #include <sbsdio.h>
  51. #include <sbsdpcmdev.h>
  52. #include <bcmsdpcm.h>
  53. #include <bcmsdbus.h>
  54. #include <proto/ethernet.h>
  55. #include <proto/802.1d.h>
  56. #include <proto/802.11.h>
  57. #include <dngl_stats.h>
  58. #include <dhd.h>
  59. #include <dhd_bus.h>
  60. #include <dhd_proto.h>
  61. #include <dhd_dbg.h>
  62. #include <dhdioctl.h>
  63. #include <sdiovar.h>
  64. #ifdef PROP_TXSTATUS
  65. #include <dhd_wlfc.h>
  66. #endif
  67. #ifdef DHDTCPACK_SUPPRESS
  68. #include <dhd_ip.h>
  69. #endif
  70. bool dhd_mp_halting(dhd_pub_t *dhdp);
  71. extern void bcmsdh_waitfor_iodrain(void *sdh);
  72. extern void bcmsdh_reject_ioreqs(void *sdh, bool reject);
  73. extern bool bcmsdh_fatal_error(void *sdh);
  74. #ifndef DHDSDIO_MEM_DUMP_FNAME
  75. #define DHDSDIO_MEM_DUMP_FNAME "mem_dump"
  76. #endif
  77. #define QLEN (1024) /* bulk rx and tx queue lengths */
  78. #define FCHI (QLEN - 10)
  79. #define FCLOW (FCHI / 2)
  80. #define PRIOMASK 7
  81. #define TXRETRIES 2 /* # of retries for tx frames */
  82. #define READ_FRM_CNT_RETRIES 3
  83. #ifndef DHD_RXBOUND
  84. #define DHD_RXBOUND 50 /* Default for max rx frames in one scheduling */
  85. #endif
  86. #ifndef DHD_TXBOUND
  87. #define DHD_TXBOUND 20 /* Default for max tx frames in one scheduling */
  88. #endif
  89. #define DHD_TXMINMAX 1 /* Max tx frames if rx still pending */
  90. #define MEMBLOCK 2048 /* Block size used for downloading of dongle image */
  91. #define MAX_NVRAMBUF_SIZE 4096 /* max nvram buf size */
  92. #define MAX_DATA_BUF (64 * 1024) /* Must be large enough to hold biggest possible glom */
  93. #ifndef DHD_FIRSTREAD
  94. #define DHD_FIRSTREAD 32
  95. #endif
  96. #if !ISPOWEROF2(DHD_FIRSTREAD)
  97. #error DHD_FIRSTREAD is not a power of 2!
  98. #endif
  99. /* Total length of frame header for dongle protocol */
  100. #define SDPCM_HDRLEN (SDPCM_FRAMETAG_LEN + SDPCM_SWHEADER_LEN)
  101. #define SDPCM_HDRLEN_TXGLOM (SDPCM_HDRLEN + SDPCM_HWEXT_LEN)
  102. #define MAX_TX_PKTCHAIN_CNT SDPCM_MAXGLOM_SIZE
  103. #ifdef SDTEST
  104. #define SDPCM_RESERVE (SDPCM_HDRLEN + SDPCM_TEST_HDRLEN + DHD_SDALIGN)
  105. #else
  106. #define SDPCM_RESERVE (SDPCM_HDRLEN + DHD_SDALIGN)
  107. #endif
  108. /* Space for header read, limit for data packets */
  109. #ifndef MAX_HDR_READ
  110. #define MAX_HDR_READ 32
  111. #endif
  112. #if !ISPOWEROF2(MAX_HDR_READ)
  113. #error MAX_HDR_READ is not a power of 2!
  114. #endif
  115. #define MAX_RX_DATASZ 2048
  116. /* Maximum milliseconds to wait for F2 to come up */
  117. #define DHD_WAIT_F2RDY 3000
  118. /* Bump up limit on waiting for HT to account for first startup;
  119. * if the image is doing a CRC calculation before programming the PMU
  120. * for HT availability, it could take a couple hundred ms more, so
  121. * max out at a 1 second (1000000us).
  122. */
  123. #if (PMU_MAX_TRANSITION_DLY <= 1000000)
  124. #undef PMU_MAX_TRANSITION_DLY
  125. #define PMU_MAX_TRANSITION_DLY 1000000
  126. #endif
  127. /* hooks for limiting threshold custom tx num in rx processing */
  128. #define DEFAULT_TXINRX_THRES 0
  129. #ifndef CUSTOM_TXINRX_THRES
  130. #define CUSTOM_TXINRX_THRES DEFAULT_TXINRX_THRES
  131. #endif
  132. /* Value for ChipClockCSR during initial setup */
  133. #define DHD_INIT_CLKCTL1 (SBSDIO_FORCE_HW_CLKREQ_OFF | SBSDIO_ALP_AVAIL_REQ)
  134. #define DHD_INIT_CLKCTL2 (SBSDIO_FORCE_HW_CLKREQ_OFF | SBSDIO_FORCE_ALP)
  135. /* Flags for SDH calls */
  136. #define F2SYNC (SDIO_REQ_4BYTE | SDIO_REQ_FIXED)
  137. /* Packet free applicable unconditionally for sdio and sdspi. Conditional if
  138. * bufpool was present for gspi bus.
  139. */
  140. #define PKTFREE2() if ((bus->bus != SPI_BUS) || bus->usebufpool) \
  141. PKTFREE(bus->dhd->osh, pkt, FALSE);
  142. DHD_SPINWAIT_SLEEP_INIT(sdioh_spinwait_sleep);
  143. #if defined(MULTIPLE_SUPPLICANT)
  144. #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25))
  145. DEFINE_MUTEX(_dhd_sdio_mutex_lock_);
  146. #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)) */
  147. #endif
  148. #if defined(SUPPORT_MULTIPLE_BOARD_REV_FROM_HW)
  149. extern unsigned int system_hw_rev;
  150. #endif /* SUPPORT_MULTIPLE_BOARD_REV_FROM_HW */
  151. #ifdef DHD_DEBUG
  152. /* Device console log buffer state */
  153. #define CONSOLE_LINE_MAX 192
  154. #define CONSOLE_BUFFER_MAX 2024
  155. typedef struct dhd_console {
  156. uint count; /* Poll interval msec counter */
  157. uint log_addr; /* Log struct address (fixed) */
  158. hndrte_log_t log; /* Log struct (host copy) */
  159. uint bufsize; /* Size of log buffer */
  160. uint8 *buf; /* Log buffer (host copy) */
  161. uint last; /* Last buffer read index */
  162. } dhd_console_t;
  163. #endif /* DHD_DEBUG */
  164. #define REMAP_ENAB(bus) ((bus)->remap)
  165. #define REMAP_ISADDR(bus, a) (((a) >= ((bus)->orig_ramsize)) && ((a) < ((bus)->ramsize)))
  166. #define KSO_ENAB(bus) ((bus)->kso)
  167. #define SR_ENAB(bus) ((bus)->_srenab)
  168. #define SLPAUTO_ENAB(bus) ((SR_ENAB(bus)) && ((bus)->_slpauto))
  169. #define MIN_RSRC_ADDR (SI_ENUM_BASE + 0x618)
  170. #define MIN_RSRC_SR 0x3
  171. #define CORE_CAPEXT_ADDR (SI_ENUM_BASE + 0x64c)
  172. #define CORE_CAPEXT_SR_SUPPORTED_MASK (1 << 1)
  173. #define RCTL_MACPHY_DISABLE_MASK (1 << 26)
  174. #define RCTL_LOGIC_DISABLE_MASK (1 << 27)
  175. #define OOB_WAKEUP_ENAB(bus) ((bus)->_oobwakeup)
  176. #define GPIO_DEV_SRSTATE 16 /* Host gpio17 mapped to device gpio0 SR state */
  177. #define GPIO_DEV_SRSTATE_TIMEOUT 320000 /* 320ms */
  178. #define GPIO_DEV_WAKEUP 17 /* Host gpio17 mapped to device gpio1 wakeup */
  179. #define CC_CHIPCTRL2_GPIO1_WAKEUP (1 << 0)
  180. #define CC_CHIPCTRL3_SR_ENG_ENABLE (1 << 2)
  181. #define OVERFLOW_BLKSZ512_WM 96
  182. #define OVERFLOW_BLKSZ512_MES 80
  183. #define CC_PMUCC3 (0x3)
  184. /* Private data for SDIO bus interaction */
  185. typedef struct dhd_bus {
  186. dhd_pub_t *dhd;
  187. bcmsdh_info_t *sdh; /* Handle for BCMSDH calls */
  188. si_t *sih; /* Handle for SI calls */
  189. char *vars; /* Variables (from CIS and/or other) */
  190. uint varsz; /* Size of variables buffer */
  191. uint32 sbaddr; /* Current SB window pointer (-1, invalid) */
  192. sdpcmd_regs_t *regs; /* Registers for SDIO core */
  193. uint sdpcmrev; /* SDIO core revision */
  194. uint armrev; /* CPU core revision */
  195. uint ramrev; /* SOCRAM core revision */
  196. uint32 ramsize; /* Size of RAM in SOCRAM (bytes) */
  197. uint32 orig_ramsize; /* Size of RAM in SOCRAM (bytes) */
  198. uint32 srmemsize; /* Size of SRMEM */
  199. uint32 bus; /* gSPI or SDIO bus */
  200. uint32 bus_num; /* bus number */
  201. uint32 slot_num; /* slot ID */
  202. uint32 hostintmask; /* Copy of Host Interrupt Mask */
  203. uint32 intstatus; /* Intstatus bits (events) pending */
  204. bool dpc_sched; /* Indicates DPC schedule (intrpt rcvd) */
  205. bool fcstate; /* State of dongle flow-control */
  206. uint16 cl_devid; /* cached devid for dhdsdio_probe_attach() */
  207. char *fw_path; /* module_param: path to firmware image */
  208. char *nv_path; /* module_param: path to nvram vars file */
  209. const char *nvram_params; /* user specified nvram params. */
  210. uint blocksize; /* Block size of SDIO transfers */
  211. uint roundup; /* Max roundup limit */
  212. struct pktq txq; /* Queue length used for flow-control */
  213. uint8 flowcontrol; /* per prio flow control bitmask */
  214. uint8 tx_seq; /* Transmit sequence number (next) */
  215. uint8 tx_max; /* Maximum transmit sequence allowed */
  216. uint8 hdrbuf[MAX_HDR_READ + DHD_SDALIGN];
  217. uint8 *rxhdr; /* Header of current rx frame (in hdrbuf) */
  218. uint16 nextlen; /* Next Read Len from last header */
  219. uint8 rx_seq; /* Receive sequence number (expected) */
  220. bool rxskip; /* Skip receive (awaiting NAK ACK) */
  221. void *glomd; /* Packet containing glomming descriptor */
  222. void *glom; /* Packet chain for glommed superframe */
  223. uint glomerr; /* Glom packet read errors */
  224. uint8 *rxbuf; /* Buffer for receiving control packets */
  225. uint rxblen; /* Allocated length of rxbuf */
  226. uint8 *rxctl; /* Aligned pointer into rxbuf */
  227. uint8 *databuf; /* Buffer for receiving big glom packet */
  228. uint8 *dataptr; /* Aligned pointer into databuf */
  229. uint rxlen; /* Length of valid data in buffer */
  230. uint8 sdpcm_ver; /* Bus protocol reported by dongle */
  231. bool intr; /* Use interrupts */
  232. bool poll; /* Use polling */
  233. bool ipend; /* Device interrupt is pending */
  234. bool intdis; /* Interrupts disabled by isr */
  235. uint intrcount; /* Count of device interrupt callbacks */
  236. uint lastintrs; /* Count as of last watchdog timer */
  237. uint spurious; /* Count of spurious interrupts */
  238. uint pollrate; /* Ticks between device polls */
  239. uint polltick; /* Tick counter */
  240. uint pollcnt; /* Count of active polls */
  241. #ifdef DHD_DEBUG
  242. dhd_console_t console; /* Console output polling support */
  243. uint console_addr; /* Console address from shared struct */
  244. #endif /* DHD_DEBUG */
  245. uint regfails; /* Count of R_REG/W_REG failures */
  246. uint clkstate; /* State of sd and backplane clock(s) */
  247. bool activity; /* Activity flag for clock down */
  248. int32 idletime; /* Control for activity timeout */
  249. int32 idlecount; /* Activity timeout counter */
  250. int32 idleclock; /* How to set bus driver when idle */
  251. int32 sd_divisor; /* Speed control to bus driver */
  252. int32 sd_mode; /* Mode control to bus driver */
  253. int32 sd_rxchain; /* If bcmsdh api accepts PKT chains */
  254. bool use_rxchain; /* If dhd should use PKT chains */
  255. bool sleeping; /* Is SDIO bus sleeping? */
  256. #if defined(SUPPORT_P2P_GO_PS)
  257. wait_queue_head_t bus_sleep;
  258. #endif /* LINUX && SUPPORT_P2P_GO_PS */
  259. uint rxflow_mode; /* Rx flow control mode */
  260. bool rxflow; /* Is rx flow control on */
  261. uint prev_rxlim_hit; /* Is prev rx limit exceeded (per dpc schedule) */
  262. bool alp_only; /* Don't use HT clock (ALP only) */
  263. /* Field to decide if rx of control frames happen in rxbuf or lb-pool */
  264. bool usebufpool;
  265. int32 txinrx_thres; /* num of in-queued pkts */
  266. int32 dotxinrx; /* tx first in dhdsdio_readframes */
  267. #ifdef SDTEST
  268. /* external loopback */
  269. bool ext_loop;
  270. uint8 loopid;
  271. /* pktgen configuration */
  272. uint pktgen_freq; /* Ticks between bursts */
  273. uint pktgen_count; /* Packets to send each burst */
  274. uint pktgen_print; /* Bursts between count displays */
  275. uint pktgen_total; /* Stop after this many */
  276. uint pktgen_minlen; /* Minimum packet data len */
  277. uint pktgen_maxlen; /* Maximum packet data len */
  278. uint pktgen_mode; /* Configured mode: tx, rx, or echo */
  279. uint pktgen_stop; /* Number of tx failures causing stop */
  280. /* active pktgen fields */
  281. uint pktgen_tick; /* Tick counter for bursts */
  282. uint pktgen_ptick; /* Burst counter for printing */
  283. uint pktgen_sent; /* Number of test packets generated */
  284. uint pktgen_rcvd; /* Number of test packets received */
  285. uint pktgen_prev_time; /* Time at which previous stats where printed */
  286. uint pktgen_prev_sent; /* Number of test packets generated when
  287. * previous stats were printed
  288. */
  289. uint pktgen_prev_rcvd; /* Number of test packets received when
  290. * previous stats were printed
  291. */
  292. uint pktgen_fail; /* Number of failed send attempts */
  293. uint16 pktgen_len; /* Length of next packet to send */
  294. #define PKTGEN_RCV_IDLE (0)
  295. #define PKTGEN_RCV_ONGOING (1)
  296. uint16 pktgen_rcv_state; /* receive state */
  297. uint pktgen_rcvd_rcvsession; /* test pkts rcvd per rcv session. */
  298. #endif /* SDTEST */
  299. /* Some additional counters */
  300. uint tx_sderrs; /* Count of tx attempts with sd errors */
  301. uint fcqueued; /* Tx packets that got queued */
  302. uint rxrtx; /* Count of rtx requests (NAK to dongle) */
  303. uint rx_toolong; /* Receive frames too long to receive */
  304. uint rxc_errors; /* SDIO errors when reading control frames */
  305. uint rx_hdrfail; /* SDIO errors on header reads */
  306. uint rx_badhdr; /* Bad received headers (roosync?) */
  307. uint rx_badseq; /* Mismatched rx sequence number */
  308. uint fc_rcvd; /* Number of flow-control events received */
  309. uint fc_xoff; /* Number which turned on flow-control */
  310. uint fc_xon; /* Number which turned off flow-control */
  311. uint rxglomfail; /* Failed deglom attempts */
  312. uint rxglomframes; /* Number of glom frames (superframes) */
  313. uint rxglompkts; /* Number of packets from glom frames */
  314. uint f2rxhdrs; /* Number of header reads */
  315. uint f2rxdata; /* Number of frame data reads */
  316. uint f2txdata; /* Number of f2 frame writes */
  317. uint f1regdata; /* Number of f1 register accesses */
  318. #ifdef BCMSPI
  319. bool dwordmode;
  320. #endif /* BCMSPI */
  321. #ifdef DHDENABLE_TAILPAD
  322. uint tx_tailpad_chain; /* Number of tail padding by chaining pad_pkt */
  323. uint tx_tailpad_pktget; /* Number of tail padding by new PKTGET */
  324. #endif
  325. uint8 *ctrl_frame_buf;
  326. uint32 ctrl_frame_len;
  327. bool ctrl_frame_stat;
  328. #ifndef BCMSPI
  329. uint32 rxint_mode; /* rx interrupt mode */
  330. #endif /* BCMSPI */
  331. bool remap; /* Contiguous 1MB RAM: 512K socram + 512K devram
  332. * Available with socram rev 16
  333. * Remap region not DMA-able
  334. */
  335. bool kso;
  336. bool _slpauto;
  337. bool _oobwakeup;
  338. bool _srenab;
  339. bool readframes;
  340. bool reqbussleep;
  341. uint32 resetinstr;
  342. uint32 dongle_ram_base;
  343. void *glom_pkt_arr[SDPCM_MAXGLOM_SIZE]; /* Array of pkts for glomming */
  344. uint32 txglom_cnt; /* Number of pkts in the glom array */
  345. uint32 txglom_total_len; /* Total length of pkts in glom array */
  346. bool txglom_enable; /* Flag to indicate whether tx glom is enabled/disabled */
  347. uint32 txglomsize; /* Glom size limitation */
  348. void *pad_pkt;
  349. } dhd_bus_t;
  350. /* clkstate */
  351. #define CLK_NONE 0
  352. #define CLK_SDONLY 1
  353. #define CLK_PENDING 2 /* Not used yet */
  354. #define CLK_AVAIL 3
  355. #define DHD_NOPMU(dhd) (FALSE)
  356. #ifdef DHD_DEBUG
  357. static int qcount[NUMPRIO];
  358. static int tx_packets[NUMPRIO];
  359. #endif /* DHD_DEBUG */
  360. /* Deferred transmit */
  361. const uint dhd_deferred_tx = 1;
  362. extern uint dhd_watchdog_ms;
  363. #ifdef BCMSPI_ANDROID
  364. extern uint *dhd_spi_lockcount;
  365. #endif /* BCMSPI_ANDROID */
  366. extern void dhd_os_wd_timer(void *bus, uint wdtick);
  367. /* Tx/Rx bounds */
  368. uint dhd_txbound;
  369. uint dhd_rxbound;
  370. uint dhd_txminmax = DHD_TXMINMAX;
  371. /* override the RAM size if possible */
  372. #define DONGLE_MIN_RAMSIZE (128 *1024)
  373. int dhd_dongle_ramsize;
  374. uint dhd_doflow = TRUE;
  375. uint dhd_dpcpoll = FALSE;
  376. module_param(dhd_doflow, uint, 0644);
  377. module_param(dhd_dpcpoll, uint, 0644);
  378. static bool dhd_alignctl;
  379. static bool sd1idle;
  380. static bool retrydata;
  381. #define RETRYCHAN(chan) (((chan) == SDPCM_EVENT_CHANNEL) || retrydata)
  382. #ifdef BCMSPI
  383. /* At a watermark around 8 the spid hits underflow error. */
  384. static uint watermark = 32;
  385. static uint mesbusyctrl = 0;
  386. #else
  387. static uint watermark = 8;
  388. static uint mesbusyctrl = 0;
  389. #endif /* BCMSPI */
  390. static const uint firstread = DHD_FIRSTREAD;
  391. /* Retry count for register access failures */
  392. static const uint retry_limit = 2;
  393. /* Force even SD lengths (some host controllers mess up on odd bytes) */
  394. static bool forcealign;
  395. #define ALIGNMENT 4
  396. #if defined(OOB_INTR_ONLY) && defined(HW_OOB)
  397. extern void bcmsdh_enable_hw_oob_intr(void *sdh, bool enable);
  398. #endif
  399. #if defined(OOB_INTR_ONLY) && defined(SDIO_ISR_THREAD)
  400. #error OOB_INTR_ONLY is NOT working with SDIO_ISR_THREAD
  401. #endif /* defined(OOB_INTR_ONLY) && defined(SDIO_ISR_THREAD) */
  402. #define PKTALIGN(osh, p, len, align) \
  403. do { \
  404. uintptr datalign; \
  405. datalign = (uintptr)PKTDATA((osh), (p)); \
  406. datalign = ROUNDUP(datalign, (align)) - datalign; \
  407. ASSERT(datalign < (align)); \
  408. ASSERT(PKTLEN((osh), (p)) >= ((len) + datalign)); \
  409. if (datalign) \
  410. PKTPULL((osh), (p), (uint)datalign); \
  411. PKTSETLEN((osh), (p), (len)); \
  412. } while (0)
  413. /* Limit on rounding up frames */
  414. static const uint max_roundup = 512;
  415. /* Try doing readahead */
  416. static bool dhd_readahead;
  417. /* To check if there's window offered */
  418. #define DATAOK(bus) \
  419. (((uint8)(bus->tx_max - bus->tx_seq) > 1) && \
  420. (((uint8)(bus->tx_max - bus->tx_seq) & 0x80) == 0))
  421. /* To check if there's window offered for ctrl frame */
  422. #define TXCTLOK(bus) \
  423. (((uint8)(bus->tx_max - bus->tx_seq) != 0) && \
  424. (((uint8)(bus->tx_max - bus->tx_seq) & 0x80) == 0))
  425. /* Number of pkts available in dongle for data RX */
  426. #define DATABUFCNT(bus) \
  427. ((uint8)(bus->tx_max - bus->tx_seq) - 1)
  428. /* Macros to get register read/write status */
  429. /* NOTE: these assume a local dhdsdio_bus_t *bus! */
  430. #define R_SDREG(regvar, regaddr, retryvar) \
  431. do { \
  432. retryvar = 0; \
  433. do { \
  434. regvar = R_REG(bus->dhd->osh, regaddr); \
  435. } while (bcmsdh_regfail(bus->sdh) && (++retryvar <= retry_limit)); \
  436. if (retryvar) { \
  437. bus->regfails += (retryvar-1); \
  438. if (retryvar > retry_limit) { \
  439. DHD_ERROR(("%s: FAILED" #regvar "READ, LINE %d\n", \
  440. __FUNCTION__, __LINE__)); \
  441. regvar = 0; \
  442. } \
  443. } \
  444. } while (0)
  445. #define W_SDREG(regval, regaddr, retryvar) \
  446. do { \
  447. retryvar = 0; \
  448. do { \
  449. W_REG(bus->dhd->osh, regaddr, regval); \
  450. } while (bcmsdh_regfail(bus->sdh) && (++retryvar <= retry_limit)); \
  451. if (retryvar) { \
  452. bus->regfails += (retryvar-1); \
  453. if (retryvar > retry_limit) \
  454. DHD_ERROR(("%s: FAILED REGISTER WRITE, LINE %d\n", \
  455. __FUNCTION__, __LINE__)); \
  456. } \
  457. } while (0)
  458. #define BUS_WAKE(bus) \
  459. do { \
  460. bus->idlecount = 0; \
  461. if ((bus)->sleeping) \
  462. dhdsdio_bussleep((bus), FALSE); \
  463. } while (0);
  464. /*
  465. * pktavail interrupts from dongle to host can be managed in 3 different ways
  466. * whenever there is a packet available in dongle to transmit to host.
  467. *
  468. * Mode 0: Dongle writes the software host mailbox and host is interrupted.
  469. * Mode 1: (sdiod core rev >= 4)
  470. * Device sets a new bit in the intstatus whenever there is a packet
  471. * available in fifo. Host can't clear this specific status bit until all the
  472. * packets are read from the FIFO. No need to ack dongle intstatus.
  473. * Mode 2: (sdiod core rev >= 4)
  474. * Device sets a bit in the intstatus, and host acks this by writing
  475. * one to this bit. Dongle won't generate anymore packet interrupts
  476. * until host reads all the packets from the dongle and reads a zero to
  477. * figure that there are no more packets. No need to disable host ints.
  478. * Need to ack the intstatus.
  479. */
  480. #define SDIO_DEVICE_HMB_RXINT 0 /* default old way */
  481. #define SDIO_DEVICE_RXDATAINT_MODE_0 1 /* from sdiod rev 4 */
  482. #define SDIO_DEVICE_RXDATAINT_MODE_1 2 /* from sdiod rev 4 */
  483. #ifdef BCMSPI
  484. #define FRAME_AVAIL_MASK(bus) I_HMB_FRAME_IND
  485. #define DHD_BUS SPI_BUS
  486. /* check packet-available-interrupt in piggybacked dstatus */
  487. #define PKT_AVAILABLE(bus, intstatus) (bcmsdh_get_dstatus(bus->sdh) & STATUS_F2_PKT_AVAILABLE)
  488. #define HOSTINTMASK (I_HMB_FC_CHANGE | I_HMB_HOST_INT)
  489. #define GSPI_PR55150_BAILOUT \
  490. do { \
  491. uint32 dstatussw = bcmsdh_get_dstatus((void *)bus->sdh); \
  492. uint32 dstatushw = bcmsdh_cfg_read_word(bus->sdh, SDIO_FUNC_0, SPID_STATUS_REG, NULL); \
  493. uint32 intstatuserr = 0; \
  494. uint retries = 0; \
  495. \
  496. R_SDREG(intstatuserr, &bus->regs->intstatus, retries); \
  497. printf("dstatussw = 0x%x, dstatushw = 0x%x, intstatus = 0x%x\n", \
  498. dstatussw, dstatushw, intstatuserr); \
  499. \
  500. bus->nextlen = 0; \
  501. *finished = TRUE; \
  502. } while (0)
  503. #else /* BCMSDIO */
  504. #define FRAME_AVAIL_MASK(bus) \
  505. ((bus->rxint_mode == SDIO_DEVICE_HMB_RXINT) ? I_HMB_FRAME_IND : I_XMTDATA_AVAIL)
  506. #define DHD_BUS SDIO_BUS
  507. #define PKT_AVAILABLE(bus, intstatus) ((intstatus) & (FRAME_AVAIL_MASK(bus)))
  508. #define HOSTINTMASK (I_HMB_SW_MASK | I_CHIPACTIVE)
  509. #define GSPI_PR55150_BAILOUT
  510. #endif /* BCMSPI */
  511. #ifdef SDTEST
  512. static void dhdsdio_testrcv(dhd_bus_t *bus, void *pkt, uint seq);
  513. static void dhdsdio_sdtest_set(dhd_bus_t *bus, uint count);
  514. #endif
  515. #ifdef DHD_DEBUG
  516. static int dhdsdio_checkdied(dhd_bus_t *bus, char *data, uint size);
  517. static int dhd_serialconsole(dhd_bus_t *bus, bool get, bool enable, int *bcmerror);
  518. #endif /* DHD_DEBUG */
  519. static int dhdsdio_devcap_set(dhd_bus_t *bus, uint8 cap);
  520. static int dhdsdio_download_state(dhd_bus_t *bus, bool enter);
  521. static void dhdsdio_release(dhd_bus_t *bus, osl_t *osh);
  522. static void dhdsdio_release_malloc(dhd_bus_t *bus, osl_t *osh);
  523. static void dhdsdio_disconnect(void *ptr);
  524. static bool dhdsdio_chipmatch(uint16 chipid);
  525. static bool dhdsdio_probe_attach(dhd_bus_t *bus, osl_t *osh, void *sdh,
  526. void * regsva, uint16 devid);
  527. static bool dhdsdio_probe_malloc(dhd_bus_t *bus, osl_t *osh, void *sdh);
  528. static bool dhdsdio_probe_init(dhd_bus_t *bus, osl_t *osh, void *sdh);
  529. static void dhdsdio_release_dongle(dhd_bus_t *bus, osl_t *osh, bool dongle_isolation,
  530. bool reset_flag);
  531. static void dhd_dongle_setramsize(struct dhd_bus *bus, int mem_size);
  532. static int dhd_bcmsdh_recv_buf(dhd_bus_t *bus, uint32 addr, uint fn, uint flags,
  533. uint8 *buf, uint nbytes,
  534. void *pkt, bcmsdh_cmplt_fn_t complete, void *handle);
  535. static int dhd_bcmsdh_send_buf(dhd_bus_t *bus, uint32 addr, uint fn, uint flags,
  536. uint8 *buf, uint nbytes,
  537. void *pkt, bcmsdh_cmplt_fn_t complete, void *handle, int max_retry);
  538. static int dhdsdio_txpkt(dhd_bus_t *bus, uint chan, void** pkts, int num_pkt, bool free_pkt);
  539. static int dhdsdio_txpkt_preprocess(dhd_bus_t *bus, void *pkt, int chan, int txseq,
  540. int prev_chain_total_len, bool last_chained_pkt,
  541. int *pad_pkt_len, void **new_pkt);
  542. static int dhdsdio_txpkt_postprocess(dhd_bus_t *bus, void *pkt);
  543. static int dhdsdio_download_firmware(dhd_bus_t *bus, osl_t *osh, void *sdh);
  544. static int _dhdsdio_download_firmware(dhd_bus_t *bus);
  545. static int dhdsdio_download_code_file(dhd_bus_t *bus, char *image_path);
  546. static int dhdsdio_download_nvram(dhd_bus_t *bus);
  547. #ifdef BCMEMBEDIMAGE
  548. static int dhdsdio_download_code_array(dhd_bus_t *bus);
  549. #endif
  550. static int dhdsdio_bussleep(dhd_bus_t *bus, bool sleep);
  551. static int dhdsdio_clkctl(dhd_bus_t *bus, uint target, bool pendok);
  552. static uint8 dhdsdio_sleepcsr_get(dhd_bus_t *bus);
  553. #ifdef SUPPORT_MULTIPLE_BOARD_REV_FROM_DT
  554. int dhd_get_system_rev(void);
  555. #endif /* SUPPORT_MULTIPLE_BOARD_REV_FROM_DT */
  556. #ifdef WLMEDIA_HTSF
  557. #include <htsf.h>
  558. extern uint32 dhd_get_htsf(void *dhd, int ifidx);
  559. #endif /* WLMEDIA_HTSF */
  560. static void
  561. dhdsdio_tune_fifoparam(struct dhd_bus *bus)
  562. {
  563. int err;
  564. uint8 devctl, wm, mes;
  565. if (bus->sih->buscorerev >= 15) {
  566. /* See .ppt in PR for these recommended values */
  567. if (bus->blocksize == 512) {
  568. wm = OVERFLOW_BLKSZ512_WM;
  569. mes = OVERFLOW_BLKSZ512_MES;
  570. } else {
  571. mes = bus->blocksize/4;
  572. wm = bus->blocksize/4;
  573. }
  574. watermark = wm;
  575. mesbusyctrl = mes;
  576. } else {
  577. DHD_INFO(("skip fifotune: SdioRev(%d) is lower than minimal requested ver\n",
  578. bus->sih->buscorerev));
  579. return;
  580. }
  581. /* Update watermark */
  582. if (wm > 0) {
  583. bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1, SBSDIO_WATERMARK, wm, &err);
  584. devctl = bcmsdh_cfg_read(bus->sdh, SDIO_FUNC_1, SBSDIO_DEVICE_CTL, &err);
  585. devctl |= SBSDIO_DEVCTL_F2WM_ENAB;
  586. bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1, SBSDIO_DEVICE_CTL, devctl, &err);
  587. }
  588. /* Update MES */
  589. if (mes > 0) {
  590. bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_MESBUSYCTRL,
  591. (mes | SBSDIO_MESBUSYCTRL_ENAB), &err);
  592. }
  593. DHD_INFO(("Apply overflow WAR: 0x%02x 0x%02x 0x%02x\n",
  594. bcmsdh_cfg_read(bus->sdh, SDIO_FUNC_1, SBSDIO_DEVICE_CTL, &err),
  595. bcmsdh_cfg_read(bus->sdh, SDIO_FUNC_1, SBSDIO_WATERMARK, &err),
  596. bcmsdh_cfg_read(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_MESBUSYCTRL, &err)));
  597. }
  598. static void
  599. dhd_dongle_setramsize(struct dhd_bus *bus, int mem_size)
  600. {
  601. int32 min_size = DONGLE_MIN_RAMSIZE;
  602. /* Restrict the ramsize to user specified limit */
  603. DHD_ERROR(("user: Restrict the dongle ram size to %d, min accepted %d\n",
  604. dhd_dongle_ramsize, min_size));
  605. if ((dhd_dongle_ramsize > min_size) &&
  606. (dhd_dongle_ramsize < (int32)bus->orig_ramsize))
  607. bus->ramsize = dhd_dongle_ramsize;
  608. }
  609. static int
  610. dhdsdio_set_siaddr_window(dhd_bus_t *bus, uint32 address)
  611. {
  612. int err = 0;
  613. bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_SBADDRLOW,
  614. (address >> 8) & SBSDIO_SBADDRLOW_MASK, &err);
  615. if (!err)
  616. bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_SBADDRMID,
  617. (address >> 16) & SBSDIO_SBADDRMID_MASK, &err);
  618. if (!err)
  619. bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_SBADDRHIGH,
  620. (address >> 24) & SBSDIO_SBADDRHIGH_MASK, &err);
  621. return err;
  622. }
  623. #ifdef BCMSPI
  624. static void
  625. dhdsdio_wkwlan(dhd_bus_t *bus, bool on)
  626. {
  627. int err;
  628. uint32 regdata;
  629. bcmsdh_info_t *sdh = bus->sdh;
  630. if (bus->sih->buscoretype == SDIOD_CORE_ID) {
  631. /* wake up wlan function :WAKE_UP goes as ht_avail_request and alp_avail_request */
  632. regdata = bcmsdh_cfg_read_word(sdh, SDIO_FUNC_0, SPID_CONFIG, NULL);
  633. DHD_INFO(("F0 REG0 rd = 0x%x\n", regdata));
  634. if (on == TRUE)
  635. regdata |= WAKE_UP;
  636. else
  637. regdata &= ~WAKE_UP;
  638. bcmsdh_cfg_write_word(sdh, SDIO_FUNC_0, SPID_CONFIG, regdata, &err);
  639. }
  640. }
  641. #endif /* BCMSPI */
  642. #ifdef USE_OOB_GPIO1
  643. static int
  644. dhdsdio_oobwakeup_init(dhd_bus_t *bus)
  645. {
  646. uint32 val, addr, data;
  647. bcmsdh_gpioouten(bus->sdh, GPIO_DEV_WAKEUP);
  648. addr = SI_ENUM_BASE + OFFSETOF(chipcregs_t, chipcontrol_addr);
  649. data = SI_ENUM_BASE + OFFSETOF(chipcregs_t, chipcontrol_data);
  650. /* Set device for gpio1 wakeup */
  651. bcmsdh_reg_write(bus->sdh, addr, 4, 2);
  652. val = bcmsdh_reg_read(bus->sdh, data, 4);
  653. val |= CC_CHIPCTRL2_GPIO1_WAKEUP;
  654. bcmsdh_reg_write(bus->sdh, data, 4, val);
  655. bus->_oobwakeup = TRUE;
  656. return 0;
  657. }
  658. #endif /* USE_OOB_GPIO1 */
  659. #ifndef BCMSPI
  660. /*
  661. * Query if FW is in SR mode
  662. */
  663. static bool
  664. dhdsdio_sr_cap(dhd_bus_t *bus)
  665. {
  666. bool cap = FALSE;
  667. uint32 core_capext, addr, data;
  668. if (bus->sih->chip == BCM43430_CHIP_ID) {
  669. /* check if fw initialized sr engine */
  670. addr = SI_ENUM_BASE + OFFSETOF(chipcregs_t, sr_control1);
  671. if (bcmsdh_reg_read(bus->sdh, addr, 4) != 0)
  672. cap = TRUE;
  673. return cap;
  674. }
  675. if (bus->sih->chip == BCM4324_CHIP_ID) {
  676. addr = SI_ENUM_BASE + OFFSETOF(chipcregs_t, chipcontrol_addr);
  677. data = SI_ENUM_BASE + OFFSETOF(chipcregs_t, chipcontrol_data);
  678. bcmsdh_reg_write(bus->sdh, addr, 4, 3);
  679. core_capext = bcmsdh_reg_read(bus->sdh, data, 4);
  680. } else if (bus->sih->chip == BCM4330_CHIP_ID) {
  681. core_capext = FALSE;
  682. } else if ((bus->sih->chip == BCM4335_CHIP_ID) ||
  683. (bus->sih->chip == BCM4339_CHIP_ID) ||
  684. (bus->sih->chip == BCM43349_CHIP_ID) ||
  685. (bus->sih->chip == BCM4345_CHIP_ID) ||
  686. (bus->sih->chip == BCM43454_CHIP_ID) ||
  687. (bus->sih->chip == BCM4354_CHIP_ID) ||
  688. (bus->sih->chip == BCM4356_CHIP_ID) ||
  689. (bus->sih->chip == BCM4350_CHIP_ID)) {
  690. core_capext = TRUE;
  691. } else {
  692. core_capext = bcmsdh_reg_read(bus->sdh, CORE_CAPEXT_ADDR, 4);
  693. core_capext = (core_capext & CORE_CAPEXT_SR_SUPPORTED_MASK);
  694. }
  695. if (!(core_capext))
  696. return FALSE;
  697. if (bus->sih->chip == BCM4324_CHIP_ID) {
  698. /* FIX: Should change to query SR control register instead */
  699. cap = TRUE;
  700. } else if ((bus->sih->chip == BCM4335_CHIP_ID) ||
  701. (bus->sih->chip == BCM4339_CHIP_ID) ||
  702. (bus->sih->chip == BCM43349_CHIP_ID) ||
  703. (bus->sih->chip == BCM4345_CHIP_ID) ||
  704. (bus->sih->chip == BCM43454_CHIP_ID) ||
  705. (bus->sih->chip == BCM4354_CHIP_ID) ||
  706. (bus->sih->chip == BCM4356_CHIP_ID) ||
  707. (bus->sih->chip == BCM4350_CHIP_ID)) {
  708. uint32 enabval = 0;
  709. addr = SI_ENUM_BASE + OFFSETOF(chipcregs_t, chipcontrol_addr);
  710. data = SI_ENUM_BASE + OFFSETOF(chipcregs_t, chipcontrol_data);
  711. bcmsdh_reg_write(bus->sdh, addr, 4, CC_PMUCC3);
  712. enabval = bcmsdh_reg_read(bus->sdh, data, 4);
  713. if ((bus->sih->chip == BCM4350_CHIP_ID) ||
  714. (bus->sih->chip == BCM4345_CHIP_ID) ||
  715. (bus->sih->chip == BCM43454_CHIP_ID) ||
  716. (bus->sih->chip == BCM4356_CHIP_ID) ||
  717. (bus->sih->chip == BCM4354_CHIP_ID))
  718. enabval &= CC_CHIPCTRL3_SR_ENG_ENABLE;
  719. if (enabval)
  720. cap = TRUE;
  721. } else {
  722. data = bcmsdh_reg_read(bus->sdh,
  723. SI_ENUM_BASE + OFFSETOF(chipcregs_t, retention_ctl), 4);
  724. if ((data & (RCTL_MACPHY_DISABLE_MASK | RCTL_LOGIC_DISABLE_MASK)) == 0)
  725. cap = TRUE;
  726. }
  727. return cap;
  728. }
  729. static int
  730. dhdsdio_srwar_init(dhd_bus_t *bus)
  731. {
  732. bcmsdh_gpio_init(bus->sdh);
  733. #ifdef USE_OOB_GPIO1
  734. dhdsdio_oobwakeup_init(bus);
  735. #endif
  736. return 0;
  737. }
  738. static int
  739. dhdsdio_sr_init(dhd_bus_t *bus)
  740. {
  741. uint8 val;
  742. int err = 0;
  743. if ((bus->sih->chip == BCM4334_CHIP_ID) && (bus->sih->chiprev == 2))
  744. dhdsdio_srwar_init(bus);
  745. val = bcmsdh_cfg_read(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_WAKEUPCTRL, NULL);
  746. val |= 1 << SBSDIO_FUNC1_WCTRL_HTWAIT_SHIFT;
  747. bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_WAKEUPCTRL,
  748. 1 << SBSDIO_FUNC1_WCTRL_HTWAIT_SHIFT, &err);
  749. val = bcmsdh_cfg_read(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_WAKEUPCTRL, NULL);
  750. #ifdef USE_CMD14
  751. /* Add CMD14 Support */
  752. dhdsdio_devcap_set(bus,
  753. (SDIOD_CCCR_BRCM_CARDCAP_CMD14_SUPPORT | SDIOD_CCCR_BRCM_CARDCAP_CMD14_EXT));
  754. #endif /* USE_CMD14 */
  755. dhdsdio_devcap_set(bus, SDIOD_CCCR_BRCM_CARDCAP_CMD_NODEC);
  756. bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1,
  757. SBSDIO_FUNC1_CHIPCLKCSR, SBSDIO_FORCE_HT, &err);
  758. bus->_slpauto = dhd_slpauto ? TRUE : FALSE;
  759. bus->_srenab = TRUE;
  760. return 0;
  761. }
  762. #endif /* BCMSPI */
  763. /*
  764. * FIX: Be sure KSO bit is enabled
  765. * Currently, it's defaulting to 0 which should be 1.
  766. */
  767. static int
  768. dhdsdio_clk_kso_init(dhd_bus_t *bus)
  769. {
  770. uint8 val;
  771. int err = 0;
  772. /* set flag */
  773. bus->kso = TRUE;
  774. /*
  775. * Enable KeepSdioOn (KSO) bit for normal operation
  776. * Default is 0 (4334A0) so set it. Fixed in B0.
  777. */
  778. val = bcmsdh_cfg_read(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_SLEEPCSR, NULL);
  779. if (!(val & SBSDIO_FUNC1_SLEEPCSR_KSO_MASK)) {
  780. val |= (SBSDIO_FUNC1_SLEEPCSR_KSO_EN << SBSDIO_FUNC1_SLEEPCSR_KSO_SHIFT);
  781. bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_SLEEPCSR, val, &err);
  782. if (err)
  783. DHD_ERROR(("%s: SBSDIO_FUNC1_SLEEPCSR err: 0x%x\n", __FUNCTION__, err));
  784. }
  785. return 0;
  786. }
  787. #define KSO_DBG(x)
  788. #define KSO_WAIT_US 50
  789. #define KSO_WAIT_MS 1
  790. #define KSO_SLEEP_RETRY_COUNT 20
  791. #define ERROR_BCME_NODEVICE_MAX 1
  792. #if defined(CUSTOMER_HW4)
  793. #define MAX_KSO_ATTEMPTS 64
  794. #else
  795. #define MAX_KSO_ATTEMPTS (PMU_MAX_TRANSITION_DLY/KSO_WAIT_US)
  796. #endif /* CUSTOMER_HW4 */
  797. static int
  798. dhdsdio_clk_kso_enab(dhd_bus_t *bus, bool on)
  799. {
  800. uint8 wr_val = 0, rd_val, cmp_val, bmask;
  801. int err = 0;
  802. int try_cnt = 0;
  803. KSO_DBG(("%s> op:%s\n", __FUNCTION__, (on ? "KSO_SET" : "KSO_CLR")));
  804. wr_val |= (on << SBSDIO_FUNC1_SLEEPCSR_KSO_SHIFT);
  805. bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_SLEEPCSR, wr_val, &err);
  806. if (on) {
  807. cmp_val = SBSDIO_FUNC1_SLEEPCSR_KSO_MASK | SBSDIO_FUNC1_SLEEPCSR_DEVON_MASK;
  808. bmask = cmp_val;
  809. OSL_SLEEP(3);
  810. } else {
  811. /* Put device to sleep, turn off KSO */
  812. cmp_val = 0;
  813. bmask = SBSDIO_FUNC1_SLEEPCSR_KSO_MASK;
  814. }
  815. do {
  816. rd_val = bcmsdh_cfg_read(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_SLEEPCSR, &err);
  817. if (((rd_val & bmask) == cmp_val) && !err)
  818. break;
  819. KSO_DBG(("%s> KSO wr/rd retry:%d, ERR:%x \n", __FUNCTION__, try_cnt, err));
  820. if (((try_cnt + 1) % KSO_SLEEP_RETRY_COUNT) == 0) {
  821. OSL_SLEEP(KSO_WAIT_MS);
  822. } else
  823. OSL_DELAY(KSO_WAIT_US);
  824. bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_SLEEPCSR, wr_val, &err);
  825. } while (try_cnt++ < MAX_KSO_ATTEMPTS);
  826. if (try_cnt > 2)
  827. KSO_DBG(("%s> op:%s, try_cnt:%d, rd_val:%x, ERR:%x \n",
  828. __FUNCTION__, (on ? "KSO_SET" : "KSO_CLR"), try_cnt, rd_val, err));
  829. if (try_cnt > MAX_KSO_ATTEMPTS) {
  830. DHD_ERROR(("%s> op:%s, ERROR: try_cnt:%d, rd_val:%x, ERR:%x \n",
  831. __FUNCTION__, (on ? "KSO_SET" : "KSO_CLR"), try_cnt, rd_val, err));
  832. }
  833. return err;
  834. }
  835. static int
  836. dhdsdio_clk_kso_iovar(dhd_bus_t *bus, bool on)
  837. {
  838. int err = 0;
  839. if (on == FALSE) {
  840. BUS_WAKE(bus);
  841. dhdsdio_clkctl(bus, CLK_AVAIL, FALSE);
  842. DHD_ERROR(("%s: KSO disable clk: 0x%x\n", __FUNCTION__,
  843. bcmsdh_cfg_read(bus->sdh, SDIO_FUNC_1,
  844. SBSDIO_FUNC1_CHIPCLKCSR, &err)));
  845. dhdsdio_clk_kso_enab(bus, FALSE);
  846. } else {
  847. DHD_ERROR(("%s: KSO enable\n", __FUNCTION__));
  848. /* Make sure we have SD bus access */
  849. if (bus->clkstate == CLK_NONE) {
  850. DHD_ERROR(("%s: Request SD clk\n", __FUNCTION__));
  851. dhdsdio_clkctl(bus, CLK_SDONLY, FALSE);
  852. }
  853. dhdsdio_clk_kso_enab(bus, TRUE);
  854. DHD_ERROR(("%s: sleepcsr: 0x%x\n", __FUNCTION__,
  855. dhdsdio_sleepcsr_get(bus)));
  856. }
  857. bus->kso = on;
  858. BCM_REFERENCE(err);
  859. return 0;
  860. }
  861. static uint8
  862. dhdsdio_sleepcsr_get(dhd_bus_t *bus)
  863. {
  864. int err = 0;
  865. uint8 val = 0;
  866. val = bcmsdh_cfg_read(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_SLEEPCSR, &err);
  867. if (err)
  868. DHD_TRACE(("Failed to read SLEEPCSR: %d\n", err));
  869. return val;
  870. }
  871. uint8
  872. dhdsdio_devcap_get(dhd_bus_t *bus)
  873. {
  874. return bcmsdh_cfg_read(bus->sdh, SDIO_FUNC_0, SDIOD_CCCR_BRCM_CARDCAP, NULL);
  875. }
  876. static int
  877. dhdsdio_devcap_set(dhd_bus_t *bus, uint8 cap)
  878. {
  879. int err = 0;
  880. bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_0, SDIOD_CCCR_BRCM_CARDCAP, cap, &err);
  881. if (err)
  882. DHD_ERROR(("%s: devcap set err: 0x%x\n", __FUNCTION__, err));
  883. return 0;
  884. }
  885. static int
  886. dhdsdio_clk_devsleep_iovar(dhd_bus_t *bus, bool on)
  887. {
  888. int err = 0, retry;
  889. uint8 val;
  890. retry = 0;
  891. if (on == TRUE) {
  892. /* Enter Sleep */
  893. /* Be sure we request clk before going to sleep
  894. * so we can wake-up with clk request already set
  895. * else device can go back to sleep immediately
  896. */
  897. if (!SLPAUTO_ENAB(bus))
  898. dhdsdio_clkctl(bus, CLK_AVAIL, FALSE);
  899. else {
  900. val = bcmsdh_cfg_read(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR, &err);
  901. if ((val & SBSDIO_CSR_MASK) == 0) {
  902. DHD_ERROR(("%s: No clock before enter sleep:0x%x\n",
  903. __FUNCTION__, val));
  904. /* Reset clock request */
  905. bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR,
  906. SBSDIO_ALP_AVAIL_REQ, &err);
  907. DHD_ERROR(("%s: clock before sleep:0x%x\n", __FUNCTION__,
  908. bcmsdh_cfg_read(bus->sdh, SDIO_FUNC_1,
  909. SBSDIO_FUNC1_CHIPCLKCSR, &err)));
  910. }
  911. }
  912. DHD_TRACE(("%s: clk before sleep: 0x%x\n", __FUNCTION__,
  913. bcmsdh_cfg_read(bus->sdh, SDIO_FUNC_1,
  914. SBSDIO_FUNC1_CHIPCLKCSR, &err)));
  915. #ifdef USE_CMD14
  916. err = bcmsdh_sleep(bus->sdh, TRUE);
  917. #else
  918. err = dhdsdio_clk_kso_enab(bus, FALSE);
  919. if (OOB_WAKEUP_ENAB(bus))
  920. {
  921. err = bcmsdh_gpioout(bus->sdh, GPIO_DEV_WAKEUP, FALSE); /* GPIO_1 is off */
  922. }
  923. #endif /* USE_CMD14 */
  924. } else {
  925. /* Exit Sleep */
  926. /* Make sure we have SD bus access */
  927. if (bus->clkstate == CLK_NONE) {
  928. DHD_TRACE(("%s: Request SD clk\n", __FUNCTION__));
  929. dhdsdio_clkctl(bus, CLK_SDONLY, FALSE);
  930. }
  931. if ((bus->sih->chip == BCM4334_CHIP_ID) && (bus->sih->chiprev == 2)) {
  932. SPINWAIT_SLEEP(sdioh_spinwait_sleep,
  933. (bcmsdh_gpioin(bus->sdh, GPIO_DEV_SRSTATE) != TRUE),
  934. GPIO_DEV_SRSTATE_TIMEOUT);
  935. if (bcmsdh_gpioin(bus->sdh, GPIO_DEV_SRSTATE) == FALSE) {
  936. DHD_ERROR(("ERROR: GPIO_DEV_SRSTATE still low!\n"));
  937. }
  938. }
  939. #ifdef USE_CMD14
  940. err = bcmsdh_sleep(bus->sdh, FALSE);
  941. if (SLPAUTO_ENAB(bus) && (err != 0)) {
  942. OSL_DELAY(10000);
  943. DHD_TRACE(("%s: Resync device sleep\n", __FUNCTION__));
  944. /* Toggle sleep to resync with host and device */
  945. err = bcmsdh_sleep(bus->sdh, TRUE);
  946. OSL_DELAY(10000);
  947. err = bcmsdh_sleep(bus->sdh, FALSE);
  948. if (err) {
  949. OSL_DELAY(10000);
  950. DHD_ERROR(("%s: CMD14 exit failed again!\n", __FUNCTION__));
  951. /* Toggle sleep to resync with host and device */
  952. err = bcmsdh_sleep(bus->sdh, TRUE);
  953. OSL_DELAY(10000);
  954. err = bcmsdh_sleep(bus->sdh, FALSE);
  955. if (err) {
  956. DHD_ERROR(("%s: CMD14 exit failed twice!\n", __FUNCTION__));
  957. DHD_ERROR(("%s: FATAL: Device non-response!\n",
  958. __FUNCTION__));
  959. err = 0;
  960. }
  961. }
  962. }
  963. #else
  964. if (OOB_WAKEUP_ENAB(bus))
  965. {
  966. err = bcmsdh_gpioout(bus->sdh, GPIO_DEV_WAKEUP, TRUE); /* GPIO_1 is on */
  967. }
  968. do {
  969. err = dhdsdio_clk_kso_enab(bus, TRUE);
  970. if (err)
  971. OSL_SLEEP(10);
  972. } while ((err != 0) && (++retry < 3));
  973. if (err != 0) {
  974. DHD_ERROR(("ERROR: kso set failed retry: %d\n", retry));
  975. err = 0; /* continue anyway */
  976. }
  977. #endif /* !USE_CMD14 */
  978. if (err == 0) {
  979. uint8 csr;
  980. /* Wait for device ready during transition to wake-up */
  981. SPINWAIT_SLEEP(sdioh_spinwait_sleep,
  982. (((csr = dhdsdio_sleepcsr_get(bus)) &
  983. SBSDIO_FUNC1_SLEEPCSR_DEVON_MASK) !=
  984. (SBSDIO_FUNC1_SLEEPCSR_DEVON_MASK)), (20000));
  985. DHD_TRACE(("%s: ExitSleep sleepcsr: 0x%x\n", __FUNCTION__, csr));
  986. if (!(csr & SBSDIO_FUNC1_SLEEPCSR_DEVON_MASK)) {
  987. DHD_ERROR(("%s:ERROR: ExitSleep device NOT Ready! 0x%x\n",
  988. __FUNCTION__, csr));
  989. err = BCME_NODEVICE;
  990. }
  991. SPINWAIT_SLEEP(sdioh_spinwait_sleep,
  992. (((csr = bcmsdh_cfg_read(bus->sdh, SDIO_FUNC_1,
  993. SBSDIO_FUNC1_CHIPCLKCSR, &err)) & SBSDIO_HT_AVAIL) !=
  994. (SBSDIO_HT_AVAIL)), (10000));
  995. DHD_TRACE(("%s: SBSDIO_FUNC1_CHIPCLKCSR : 0x%x\n", __FUNCTION__, csr));
  996. if (!err && ((csr & SBSDIO_HT_AVAIL) != SBSDIO_HT_AVAIL)) {
  997. DHD_ERROR(("%s:ERROR: device NOT Ready! 0x%x\n",
  998. __FUNCTION__, csr));
  999. err = BCME_NODEVICE;
  1000. }
  1001. }
  1002. }
  1003. /* Update if successful */
  1004. if (err == 0)
  1005. bus->kso = on ? FALSE : TRUE;
  1006. else {
  1007. DHD_ERROR(("%s: Sleep request failed: kso:%d on:%d err:%d\n",
  1008. __FUNCTION__, bus->kso, on, err));
  1009. if (!on && retry > 2)
  1010. bus->kso = FALSE;
  1011. }
  1012. return err;
  1013. }
  1014. /* Turn backplane clock on or off */
  1015. static int
  1016. dhdsdio_htclk(dhd_bus_t *bus, bool on, bool pendok)
  1017. {
  1018. #define HT_AVAIL_ERROR_MAX 10
  1019. static int ht_avail_error = 0;
  1020. int err;
  1021. uint8 clkctl, clkreq, devctl;
  1022. bcmsdh_info_t *sdh;
  1023. DHD_TRACE(("%s: Enter\n", __FUNCTION__));
  1024. clkctl = 0;
  1025. sdh = bus->sdh;
  1026. if (!KSO_ENAB(bus))
  1027. return BCME_OK;
  1028. if (SLPAUTO_ENAB(bus)) {
  1029. bus->clkstate = (on ? CLK_AVAIL : CLK_SDONLY);
  1030. return BCME_OK;
  1031. }
  1032. if (on) {
  1033. /* Request HT Avail */
  1034. clkreq = bus->alp_only ? SBSDIO_ALP_AVAIL_REQ : SBSDIO_HT_AVAIL_REQ;
  1035. #ifdef BCMSPI
  1036. dhdsdio_wkwlan(bus, TRUE);
  1037. #endif /* BCMSPI */
  1038. bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR, clkreq, &err);
  1039. if (err) {
  1040. ht_avail_error++;
  1041. if (ht_avail_error < HT_AVAIL_ERROR_MAX) {
  1042. DHD_ERROR(("%s: HT Avail request error: %d\n", __FUNCTION__, err));
  1043. }
  1044. #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)
  1045. else if (ht_avail_error == HT_AVAIL_ERROR_MAX) {
  1046. bus->dhd->hang_reason = HANG_REASON_HT_AVAIL_ERROR;
  1047. dhd_os_send_hang_message(bus->dhd);
  1048. }
  1049. #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27) */
  1050. return BCME_ERROR;
  1051. } else {
  1052. ht_avail_error = 0;
  1053. }
  1054. /* Check current status */
  1055. clkctl = bcmsdh_cfg_read(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR, &err);
  1056. if (err) {
  1057. DHD_ERROR(("%s: HT Avail read error: %d\n", __FUNCTION__, err));
  1058. return BCME_ERROR;
  1059. }
  1060. #if !defined(OOB_INTR_ONLY)
  1061. /* Go to pending and await interrupt if appropriate */
  1062. if (!SBSDIO_CLKAV(clkctl, bus->alp_only) && pendok) {
  1063. /* Allow only clock-available interrupt */
  1064. devctl = bcmsdh_cfg_read(sdh, SDIO_FUNC_1, SBSDIO_DEVICE_CTL, &err);
  1065. if (err) {
  1066. DHD_ERROR(("%s: Devctl access error setting CA: %d\n",
  1067. __FUNCTION__, err));
  1068. return BCME_ERROR;
  1069. }
  1070. devctl |= SBSDIO_DEVCTL_CA_INT_ONLY;
  1071. bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_DEVICE_CTL, devctl, &err);
  1072. DHD_INFO(("CLKCTL: set PENDING\n"));
  1073. bus->clkstate = CLK_PENDING;
  1074. return BCME_OK;
  1075. } else
  1076. #endif /* !defined (OOB_INTR_ONLY) */
  1077. {
  1078. if (bus->clkstate == CLK_PENDING) {
  1079. /* Cancel CA-only interrupt filter */
  1080. devctl = bcmsdh_cfg_read(sdh, SDIO_FUNC_1, SBSDIO_DEVICE_CTL, &err);
  1081. devctl &= ~SBSDIO_DEVCTL_CA_INT_ONLY;
  1082. bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_DEVICE_CTL, devctl, &err);
  1083. }
  1084. }
  1085. /* Otherwise, wait here (polling) for HT Avail */
  1086. if (!SBSDIO_CLKAV(clkctl, bus->alp_only)) {
  1087. SPINWAIT_SLEEP(sdioh_spinwait_sleep,
  1088. ((clkctl = bcmsdh_cfg_read(sdh, SDIO_FUNC_1,
  1089. SBSDIO_FUNC1_CHIPCLKCSR, &err)),
  1090. !SBSDIO_CLKAV(clkctl, bus->alp_only)), PMU_MAX_TRANSITION_DLY);
  1091. }
  1092. if (err) {
  1093. DHD_ERROR(("%s: HT Avail request error: %d\n", __FUNCTION__, err));
  1094. return BCME_ERROR;
  1095. }
  1096. if (!SBSDIO_CLKAV(clkctl, bus->alp_only)) {
  1097. DHD_ERROR(("%s: HT Avail timeout (%d): clkctl 0x%02x\n",
  1098. __FUNCTION__, PMU_MAX_TRANSITION_DLY, clkctl));
  1099. return BCME_ERROR;
  1100. }
  1101. /* Mark clock available */
  1102. bus->clkstate = CLK_AVAIL;
  1103. DHD_INFO(("CLKCTL: turned ON\n"));
  1104. #if defined(DHD_DEBUG)
  1105. if (bus->alp_only == TRUE) {
  1106. #if !defined(BCMLXSDMMC)
  1107. if (!SBSDIO_ALPONLY(clkctl)) {
  1108. DHD_ERROR(("%s: HT Clock, when ALP Only\n", __FUNCTION__));
  1109. }
  1110. #endif /* !defined(BCMLXSDMMC) */
  1111. } else {
  1112. if (SBSDIO_ALPONLY(clkctl)) {
  1113. DHD_ERROR(("%s: HT Clock should be on.\n", __FUNCTION__));
  1114. }
  1115. }
  1116. #endif /* defined (DHD_DEBUG) */
  1117. bus->activity = TRUE;
  1118. #ifdef DHD_USE_IDLECOUNT
  1119. bus->idlecount = 0;
  1120. #endif /* DHD_USE_IDLECOUNT */
  1121. } else {
  1122. clkreq = 0;
  1123. if (bus->clkstate == CLK_PENDING) {
  1124. /* Cancel CA-only interrupt filter */
  1125. devctl = bcmsdh_cfg_read(sdh, SDIO_FUNC_1, SBSDIO_DEVICE_CTL, &err);
  1126. devctl &= ~SBSDIO_DEVCTL_CA_INT_ONLY;
  1127. bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_DEVICE_CTL, devctl, &err);
  1128. }
  1129. bus->clkstate = CLK_SDONLY;
  1130. if (!SR_ENAB(bus)) {
  1131. bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR, clkreq, &err);
  1132. DHD_INFO(("CLKCTL: turned OFF\n"));
  1133. if (err) {
  1134. DHD_ERROR(("%s: Failed access turning clock off: %d\n",
  1135. __FUNCTION__, err));
  1136. return BCME_ERROR;
  1137. }
  1138. }
  1139. #ifdef BCMSPI
  1140. dhdsdio_wkwlan(bus, FALSE);
  1141. #endif /* BCMSPI */
  1142. }
  1143. return BCME_OK;
  1144. }
  1145. /* Change idle/active SD state */
  1146. static int
  1147. dhdsdio_sdclk(dhd_bus_t *bus, bool on)
  1148. {
  1149. #ifndef BCMSPI
  1150. int err;
  1151. int32 iovalue;
  1152. DHD_TRACE(("%s: Enter\n", __FUNCTION__));
  1153. if (on) {
  1154. if (bus->idleclock == DHD_IDLE_STOP) {
  1155. /* Turn on clock and restore mode */
  1156. iovalue = 1;
  1157. err = bcmsdh_iovar_op(bus->sdh, "sd_clock", NULL, 0,
  1158. &iovalue, sizeof(iovalue), TRUE);
  1159. if (err) {
  1160. DHD_ERROR(("%s: error enabling sd_clock: %d\n",
  1161. __FUNCTION__, err));
  1162. return BCME_ERROR;
  1163. }
  1164. iovalue = bus->sd_mode;
  1165. err = bcmsdh_iovar_op(bus->sdh, "sd_mode", NULL, 0,
  1166. &iovalue, sizeof(iovalue), TRUE);
  1167. if (err) {
  1168. DHD_ERROR(("%s: error changing sd_mode: %d\n",
  1169. __FUNCTION__, err));
  1170. return BCME_ERROR;
  1171. }
  1172. } else if (bus->idleclock != DHD_IDLE_ACTIVE) {
  1173. /* Restore clock speed */
  1174. iovalue = bus->sd_divisor;
  1175. err = bcmsdh_iovar_op(bus->sdh, "sd_divisor", NULL, 0,
  1176. &iovalue, sizeof(iovalue), TRUE);
  1177. if (err) {
  1178. DHD_ERROR(("%s: error restoring sd_divisor: %d\n",
  1179. __FUNCTION__, err));
  1180. return BCME_ERROR;
  1181. }
  1182. }
  1183. bus->clkstate = CLK_SDONLY;
  1184. } else {
  1185. /* Stop or slow the SD clock itself */
  1186. if ((bus->sd_divisor == -1) || (bus->sd_mode == -1)) {
  1187. DHD_TRACE(("%s: can't idle clock, divisor %d mode %d\n",
  1188. __FUNCTION__, bus->sd_divisor, bus->sd_mode));
  1189. return BCME_ERROR;
  1190. }
  1191. if (bus->idleclock == DHD_IDLE_STOP) {
  1192. if (sd1idle) {
  1193. /* Change to SD1 mode and turn off clock */
  1194. iovalue = 1;
  1195. err = bcmsdh_iovar_op(bus->sdh, "sd_mode", NULL, 0,
  1196. &iovalue, sizeof(iovalue), TRUE);
  1197. if (err) {
  1198. DHD_ERROR(("%s: error changing sd_clock: %d\n",
  1199. __FUNCTION__, err));
  1200. return BCME_ERROR;
  1201. }
  1202. }
  1203. iovalue = 0;
  1204. err = bcmsdh_iovar_op(bus->sdh, "sd_clock", NULL, 0,
  1205. &iovalue, sizeof(iovalue), TRUE);
  1206. if (err) {
  1207. DHD_ERROR(("%s: error disabling sd_clock: %d\n",
  1208. __FUNCTION__, err));
  1209. return BCME_ERROR;
  1210. }
  1211. } else if (bus->idleclock != DHD_IDLE_ACTIVE) {
  1212. /* Set divisor to idle value */
  1213. iovalue = bus->idleclock;
  1214. err = bcmsdh_iovar_op(bus->sdh, "sd_divisor", NULL, 0,
  1215. &iovalue, sizeof(iovalue), TRUE);
  1216. if (err) {
  1217. DHD_ERROR(("%s: error changing sd_divisor: %d\n",
  1218. __FUNCTION__, err));
  1219. return BCME_ERROR;
  1220. }
  1221. }
  1222. bus->clkstate = CLK_NONE;
  1223. }
  1224. #endif /* BCMSPI */
  1225. return BCME_OK;
  1226. }
  1227. /* Transition SD and backplane clock readiness */
  1228. static int
  1229. dhdsdio_clkctl(dhd_bus_t *bus, uint target, bool pendok)
  1230. {
  1231. int ret = BCME_OK;
  1232. #ifdef DHD_DEBUG
  1233. uint oldstate = bus->clkstate;
  1234. #endif /* DHD_DEBUG */
  1235. DHD_TRACE(("%s: Enter\n", __FUNCTION__));
  1236. /* Early exit if we're already there */
  1237. if (bus->clkstate == target) {
  1238. if (target == CLK_AVAIL) {
  1239. dhd_os_wd_timer(bus->dhd, dhd_watchdog_ms);
  1240. bus->activity = TRUE;
  1241. #ifdef DHD_USE_IDLECOUNT
  1242. bus->idlecount = 0;
  1243. #endif /* DHD_USE_IDLECOUNT */
  1244. }
  1245. return ret;
  1246. }
  1247. switch (target) {
  1248. case CLK_AVAIL:
  1249. /* Make sure SD clock is available */
  1250. if (bus->clkstate == CLK_NONE)
  1251. dhdsdio_sdclk(bus, TRUE);
  1252. /* Now request HT Avail on the backplane */
  1253. ret = dhdsdio_htclk(bus, TRUE, pendok);
  1254. if (ret == BCME_OK) {
  1255. dhd_os_wd_timer(bus->dhd, dhd_watchdog_ms);
  1256. bus->activity = TRUE;
  1257. #ifdef DHD_USE_IDLECOUNT
  1258. bus->idlecount = 0;
  1259. #endif /* DHD_USE_IDLECOUNT */
  1260. }
  1261. break;
  1262. case CLK_SDONLY:
  1263. /* Remove HT request, or bring up SD clock */
  1264. if (bus->clkstate == CLK_NONE)
  1265. ret = dhdsdio_sdclk(bus, TRUE);
  1266. else if (bus->clkstate == CLK_AVAIL)
  1267. ret = dhdsdio_htclk(bus, FALSE, FALSE);
  1268. else
  1269. DHD_ERROR(("dhdsdio_clkctl: request for %d -> %d\n",
  1270. bus->clkstate, target));
  1271. if (ret == BCME_OK) {
  1272. dhd_os_wd_timer(bus->dhd, dhd_watchdog_ms);
  1273. }
  1274. break;
  1275. case CLK_NONE:
  1276. /* Make sure to remove HT request */
  1277. if (bus->clkstate == CLK_AVAIL)
  1278. ret = dhdsdio_htclk(bus, FALSE, FALSE);
  1279. /* Now remove the SD clock */
  1280. ret = dhdsdio_sdclk(bus, FALSE);
  1281. #ifdef DHD_DEBUG
  1282. if (dhd_console_ms == 0)
  1283. #endif /* DHD_DEBUG */
  1284. if (bus->poll == 0)
  1285. dhd_os_wd_timer(bus->dhd, 0);
  1286. break;
  1287. }
  1288. #ifdef DHD_DEBUG
  1289. DHD_INFO(("dhdsdio_clkctl: %d -> %d\n", oldstate, bus->clkstate));
  1290. #endif /* DHD_DEBUG */
  1291. return ret;
  1292. }
  1293. static int
  1294. dhdsdio_bussleep(dhd_bus_t *bus, bool sleep)
  1295. {
  1296. int err = 0;
  1297. bcmsdh_info_t *sdh = bus->sdh;
  1298. sdpcmd_regs_t *regs = bus->regs;
  1299. uint retries = 0;
  1300. DHD_INFO(("dhdsdio_bussleep: request %s (currently %s)\n",
  1301. (sleep ? "SLEEP" : "WAKE"),
  1302. (bus->sleeping ? "SLEEP" : "WAKE")));
  1303. if (bus->dhd->hang_was_sent)
  1304. return BCME_ERROR;
  1305. /* Done if we're already in the requested state */
  1306. if (sleep == bus->sleeping)
  1307. return BCME_OK;
  1308. /* Going to sleep: set the alarm and turn off the lights... */
  1309. if (sleep) {
  1310. /* Don't sleep if something is pending */
  1311. #ifdef CUSTOMER_HW4
  1312. if (bus->dpc_sched || bus->rxskip || pktq_len(&bus->txq) || bus->readframes ||
  1313. bus->ctrl_frame_stat)
  1314. #else
  1315. if (bus->dpc_sched || bus->rxskip || pktq_len(&bus->txq))
  1316. #endif /* CUSTOMER_HW4 */
  1317. return BCME_BUSY;
  1318. if (!SLPAUTO_ENAB(bus)) {
  1319. /* Disable SDIO interrupts (no longer interested) */
  1320. bcmsdh_intr_disable(bus->sdh);
  1321. /* Make sure the controller has the bus up */
  1322. dhdsdio_clkctl(bus, CLK_AVAIL, FALSE);
  1323. /* Tell device to start using OOB wakeup */
  1324. W_SDREG(SMB_USE_OOB, &regs->tosbmailbox, retries);
  1325. if (retries > retry_limit)
  1326. DHD_ERROR(("CANNOT SIGNAL CHIP, WILL NOT WAKE UP!!\n"));
  1327. /* Turn off our contribution to the HT clock request */
  1328. dhdsdio_clkctl(bus, CLK_SDONLY, FALSE);
  1329. bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR,
  1330. SBSDIO_FORCE_HW_CLKREQ_OFF, NULL);
  1331. /* Isolate the bus */
  1332. if (bus->sih->chip != BCM4329_CHIP_ID &&
  1333. bus->sih->chip != BCM4319_CHIP_ID) {
  1334. bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_DEVICE_CTL,
  1335. SBSDIO_DEVCTL_PADS_ISO, NULL);
  1336. }
  1337. } else {
  1338. /* Leave interrupts enabled since device can exit sleep and
  1339. * interrupt host
  1340. */
  1341. err = dhdsdio_clk_devsleep_iovar(bus, TRUE /* sleep */);
  1342. }
  1343. /* Change state */
  1344. bus->sleeping = TRUE;
  1345. #if defined(SUPPORT_P2P_GO_PS)
  1346. wake_up(&bus->bus_sleep);
  1347. #endif /* LINUX && SUPPORT_P2P_GO_PS */
  1348. } else {
  1349. /* Waking up: bus power up is ok, set local state */
  1350. if (!SLPAUTO_ENAB(bus)) {
  1351. bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR, 0, &err);
  1352. /* Force pad isolation off if possible (in case power never toggled) */
  1353. bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_DEVICE_CTL, 0, NULL);
  1354. /* Make sure the controller has the bus up */
  1355. dhdsdio_clkctl(bus, CLK_AVAIL, FALSE);
  1356. /* Send misc interrupt to indicate OOB not needed */
  1357. W_SDREG(0, &regs->tosbmailboxdata, retries);
  1358. if (retries <= retry_limit)
  1359. W_SDREG(SMB_DEV_INT, &regs->tosbmailbox, retries);
  1360. if (retries > retry_limit)
  1361. DHD_ERROR(("CANNOT SIGNAL CHIP TO CLEAR OOB!!\n"));
  1362. /* Make sure we have SD bus access */
  1363. dhdsdio_clkctl(bus, CLK_SDONLY, FALSE);
  1364. /* Enable interrupts again */
  1365. if (bus->intr && (bus->dhd->busstate == DHD_BUS_DATA)) {
  1366. bus->intdis = FALSE;
  1367. bcmsdh_intr_enable(bus->sdh);
  1368. }
  1369. } else {
  1370. err = dhdsdio_clk_devsleep_iovar(bus, FALSE /* wake */);
  1371. }
  1372. if (err == 0) {
  1373. /* Change state */
  1374. bus->sleeping = FALSE;
  1375. }
  1376. }
  1377. return err;
  1378. }
  1379. #if defined(CUSTOMER_HW4) && defined(USE_DYNAMIC_F2_BLKSIZE)
  1380. int dhdsdio_func_blocksize(dhd_pub_t *dhd, int function_num, int block_size)
  1381. {
  1382. int func_blk_size = function_num;
  1383. int bcmerr = 0;
  1384. int result;
  1385. bcmerr = dhd_bus_iovar_op(dhd, "sd_blocksize", &func_blk_size,
  1386. sizeof(int), &result, sizeof(int), IOV_GET);
  1387. if (bcmerr != BCME_OK) {
  1388. DHD_ERROR(("%s: Get F%d Block size error\n", __FUNCTION__, function_num));
  1389. return BCME_ERROR;
  1390. }
  1391. if (result != block_size) {
  1392. DHD_TRACE_HW4(("%s: F%d Block size set from %d to %d\n",
  1393. __FUNCTION__, function_num, result, block_size));
  1394. func_blk_size = function_num << 16 | block_size;
  1395. bcmerr = dhd_bus_iovar_op(dhd, "sd_blocksize", NULL,
  1396. 0, &func_blk_size, sizeof(int32), IOV_SET);
  1397. if (bcmerr != BCME_OK) {
  1398. DHD_ERROR(("%s: Set F2 Block size error\n", __FUNCTION__));
  1399. return BCME_ERROR;
  1400. }
  1401. }
  1402. return BCME_OK;
  1403. }
  1404. #endif /* CUSTOMER_HW4 && USE_DYNAMIC_F2_BLKSIZE */
  1405. #if defined(OOB_INTR_ONLY) || defined(BCMSPI_ANDROID)
  1406. void
  1407. dhd_enable_oob_intr(struct dhd_bus *bus, bool enable)
  1408. {
  1409. #if defined(BCMSPI_ANDROID)
  1410. bcmsdh_intr_enable(bus->sdh);
  1411. #elif defined(HW_OOB)
  1412. bcmsdh_enable_hw_oob_intr(bus->sdh, enable);
  1413. #else
  1414. sdpcmd_regs_t *regs = bus->regs;
  1415. uint retries = 0;
  1416. dhdsdio_clkctl(bus, CLK_AVAIL, FALSE);
  1417. if (enable == TRUE) {
  1418. /* Tell device to start using OOB wakeup */
  1419. W_SDREG(SMB_USE_OOB, &regs->tosbmailbox, retries);
  1420. if (retries > retry_limit)
  1421. DHD_ERROR(("CANNOT SIGNAL CHIP, WILL NOT WAKE UP!!\n"));
  1422. } else {
  1423. /* Send misc interrupt to indicate OOB not needed */
  1424. W_SDREG(0, &regs->tosbmailboxdata, retries);
  1425. if (retries <= retry_limit)
  1426. W_SDREG(SMB_DEV_INT, &regs->tosbmailbox, retries);
  1427. }
  1428. /* Turn off our contribution to the HT clock request */
  1429. dhdsdio_clkctl(bus, CLK_SDONLY, FALSE);
  1430. #endif /* !defined(HW_OOB) */
  1431. }
  1432. #endif /* defined(OOB_INTR_ONLY) || defined(BCMSPI_ANDROID) */
  1433. int
  1434. dhd_bus_txdata(struct dhd_bus *bus, void *pkt)
  1435. {
  1436. int ret = BCME_ERROR;
  1437. osl_t *osh;
  1438. uint datalen, prec;
  1439. #if defined(DHD_TX_DUMP)
  1440. uint8 *dump_data;
  1441. #endif /* DHD_TX_DUMP */
  1442. DHD_TRACE(("%s: Enter\n", __FUNCTION__));
  1443. osh = bus->dhd->osh;
  1444. datalen = PKTLEN(osh, pkt);
  1445. #ifdef SDTEST
  1446. /* Push the test header if doing loopback */
  1447. if (bus->ext_loop) {
  1448. uint8* data;
  1449. PKTPUSH(osh, pkt, SDPCM_TEST_HDRLEN);
  1450. data = PKTDATA(osh, pkt);
  1451. *data++ = SDPCM_TEST_ECHOREQ;
  1452. *data++ = (uint8)bus->loopid++;
  1453. *data++ = (datalen >> 0);
  1454. *data++ = (datalen >> 8);
  1455. datalen += SDPCM_TEST_HDRLEN;
  1456. }
  1457. #else /* SDTEST */
  1458. BCM_REFERENCE(datalen);
  1459. #endif /* SDTEST */
  1460. #if defined(DHD_TX_DUMP) && defined(DHD_TX_FULL_DUMP)
  1461. dump_data = PKTDATA(osh, pkt);
  1462. dump_data += 4; /* skip 4 bytes header */
  1463. {
  1464. int i;
  1465. DHD_ERROR(("TX DUMP\n"));
  1466. for (i = 0; i < (datalen - 4); i++) {
  1467. DHD_ERROR(("%02X ", dump_data[i]));
  1468. if ((i & 15) == 15)
  1469. printk("\n");
  1470. }
  1471. DHD_ERROR(("\n"));
  1472. }
  1473. #endif /* DHD_TX_DUMP && DHD_TX_FULL_DUMP */
  1474. prec = PRIO2PREC((PKTPRIO(pkt) & PRIOMASK));
  1475. /* Check for existing queue, current flow-control, pending event, or pending clock */
  1476. if (dhd_deferred_tx || bus->fcstate || pktq_len(&bus->txq) || bus->dpc_sched ||
  1477. (!DATAOK(bus)) || (bus->flowcontrol & NBITVAL(prec)) ||
  1478. (bus->clkstate != CLK_AVAIL)) {
  1479. bool deq_ret;
  1480. int pkq_len;
  1481. DHD_TRACE(("%s: deferring pktq len %d\n", __FUNCTION__, pktq_len(&bus->txq)));
  1482. bus->fcqueued++;
  1483. /* Priority based enq */
  1484. dhd_os_sdlock_txq(bus->dhd);
  1485. deq_ret = dhd_prec_enq(bus->dhd, &bus->txq, pkt, prec);
  1486. dhd_os_sdunlock_txq(bus->dhd);
  1487. if (!deq_ret) {
  1488. #ifdef PROP_TXSTATUS
  1489. if (DHD_PKTTAG_WLFCPKT(PKTTAG(pkt)) == 0)
  1490. #endif /* PROP_TXSTATUS */
  1491. {
  1492. #ifdef DHDTCPACK_SUPPRESS
  1493. if (dhd_tcpack_check_xmit(bus->dhd, pkt) == BCME_ERROR) {
  1494. DHD_ERROR(("%s %d: tcpack_suppress ERROR!!! Stop using\n",
  1495. __FUNCTION__, __LINE__));
  1496. dhd_tcpack_suppress_set(bus->dhd, TCPACK_SUP_OFF);
  1497. }
  1498. #endif /* DHDTCPACK_SUPPRESS */
  1499. dhd_txcomplete(bus->dhd, pkt, FALSE);
  1500. PKTFREE(osh, pkt, TRUE);
  1501. }
  1502. ret = BCME_NORESOURCE;
  1503. } else
  1504. ret = BCME_OK;
  1505. dhd_os_sdlock_txq(bus->dhd);
  1506. pkq_len = pktq_len(&bus->txq);
  1507. dhd_os_sdunlock_txq(bus->dhd);
  1508. if (pkq_len >= FCHI) {
  1509. bool wlfc_enabled = FALSE;
  1510. #ifdef PROP_TXSTATUS
  1511. wlfc_enabled = (dhd_wlfc_flowcontrol(bus->dhd, ON, FALSE) !=
  1512. WLFC_UNSUPPORTED);
  1513. #endif
  1514. if (!wlfc_enabled && dhd_doflow) {
  1515. dhd_txflowcontrol(bus->dhd, ALL_INTERFACES, ON);
  1516. }
  1517. }
  1518. #ifdef DHD_DEBUG
  1519. dhd_os_sdlock_txq(bus->dhd);
  1520. if (pktq_plen(&bus->txq, prec) > qcount[prec])
  1521. qcount[prec] = pktq_plen(&bus->txq, prec);
  1522. dhd_os_sdunlock_txq(bus->dhd);
  1523. #endif
  1524. /* Schedule DPC if needed to send queued packet(s) */
  1525. if (dhd_deferred_tx && !bus->dpc_sched) {
  1526. bus->dpc_sched = TRUE;
  1527. dhd_sched_dpc(bus->dhd);
  1528. }
  1529. } else {
  1530. int chan = SDPCM_DATA_CHANNEL;
  1531. #ifdef SDTEST
  1532. chan = (bus->ext_loop ? SDPCM_TEST_CHANNEL : SDPCM_DATA_CHANNEL);
  1533. #endif
  1534. /* Lock: we're about to use shared data/code (and SDIO) */
  1535. dhd_os_sdlock(bus->dhd);
  1536. /* Otherwise, send it now */
  1537. BUS_WAKE(bus);
  1538. /* Make sure back plane ht clk is on, no pending allowed */
  1539. dhdsdio_clkctl(bus, CLK_AVAIL, TRUE);
  1540. ret = dhdsdio_txpkt(bus, chan, &pkt, 1, TRUE);
  1541. if (ret != BCME_OK)
  1542. bus->dhd->tx_errors++;
  1543. else
  1544. bus->dhd->dstats.tx_bytes += datalen;
  1545. if ((bus->idletime == DHD_IDLE_IMMEDIATE) && !bus->dpc_sched) {
  1546. bus->activity = FALSE;
  1547. dhdsdio_clkctl(bus, CLK_NONE, TRUE);
  1548. }
  1549. dhd_os_sdunlock(bus->dhd);
  1550. }
  1551. return ret;
  1552. }
  1553. /* align packet data pointer and packet length to n-byte boundary, process packet headers,
  1554. * a new packet may be allocated if there is not enough head and/or tail from for padding.
  1555. * the caller is responsible for updating the glom size in the head packet (when glom is
  1556. * used)
  1557. *
  1558. * pad_pkt_len: returns the length of extra padding needed from the padding packet, this parameter
  1559. * is taken in tx glom mode only
  1560. *
  1561. * new_pkt: out, pointer of the new packet allocated due to insufficient head room for alignment
  1562. * padding, NULL if not needed, the caller is responsible for freeing the new packet
  1563. *
  1564. * return: positive value - length of the packet, including head and tail padding
  1565. * negative value - errors
  1566. */
  1567. static int dhdsdio_txpkt_preprocess(dhd_bus_t *bus, void *pkt, int chan, int txseq,
  1568. int prev_chain_total_len, bool last_chained_pkt,
  1569. int *pad_pkt_len, void **new_pkt)
  1570. {
  1571. osl_t *osh;
  1572. uint8 *frame;
  1573. int pkt_len;
  1574. int modulo;
  1575. int head_padding;
  1576. int tail_padding = 0;
  1577. uint32 swheader;
  1578. uint32 swhdr_offset;
  1579. bool alloc_new_pkt = FALSE;
  1580. uint8 sdpcm_hdrlen = bus->txglom_enable ? SDPCM_HDRLEN_TXGLOM : SDPCM_HDRLEN;
  1581. *new_pkt = NULL;
  1582. osh = bus->dhd->osh;
  1583. #ifdef DHDTCPACK_SUPPRESS
  1584. if (dhd_tcpack_check_xmit(bus->dhd, pkt) == BCME_ERROR) {
  1585. DHD_ERROR(("%s %d: tcpack_suppress ERROR!!! Stop using it\n",
  1586. __FUNCTION__, __LINE__));
  1587. dhd_tcpack_suppress_set(bus->dhd, TCPACK_SUP_OFF);
  1588. }
  1589. #endif /* DHDTCPACK_SUPPRESS */
  1590. /* Add space for the SDPCM hardware/software headers */
  1591. PKTPUSH(osh, pkt, sdpcm_hdrlen);
  1592. ASSERT(ISALIGNED((uintptr)PKTDATA(osh, pkt), 2));
  1593. frame = (uint8*)PKTDATA(osh, pkt);
  1594. pkt_len = (uint16)PKTLEN(osh, pkt);
  1595. #ifdef WLMEDIA_HTSF
  1596. frame = (uint8*)PKTDATA(osh, pkt);
  1597. if (PKTLEN(osh, pkt) >= 100) {
  1598. htsf_ts = (htsfts_t*) (frame + HTSF_HOSTOFFSET + 12);
  1599. if (htsf_ts->magic == HTSFMAGIC) {
  1600. htsf_ts->c20 = get_cycles();
  1601. htsf_ts->t20 = dhd_get_htsf(bus->dhd->info, 0);
  1602. }
  1603. }
  1604. #endif /* WLMEDIA_HTSF */
  1605. #ifdef DHD_DEBUG
  1606. if (PKTPRIO(pkt) < ARRAYSIZE(tx_packets))
  1607. tx_packets[PKTPRIO(pkt)]++;
  1608. #endif /* DHD_DEBUG */
  1609. /* align the data pointer, allocate a new packet if there is not enough space (new
  1610. * packet data pointer will be aligned thus no padding will be needed)
  1611. */
  1612. head_padding = (ulong)frame % DHD_SDALIGN;
  1613. if (PKTHEADROOM(osh, pkt) < head_padding) {
  1614. head_padding = 0;
  1615. alloc_new_pkt = TRUE;
  1616. } else {
  1617. uint cur_chain_total_len;
  1618. int chain_tail_padding = 0;
  1619. /* All packets need to be aligned by DHD_SDALIGN */
  1620. modulo = (pkt_len + head_padding) % DHD_SDALIGN;
  1621. tail_padding = modulo > 0 ? (DHD_SDALIGN - modulo) : 0;
  1622. /* Total pkt chain length needs to be aligned by block size,
  1623. * unless it is a single pkt chain with total length less than one block size,
  1624. * which we prefer sending by byte mode.
  1625. *
  1626. * Do the chain alignment here if
  1627. * 1. This is the last pkt of the chain of multiple pkts or a single pkt.
  1628. * 2-1. This chain is of multiple pkts, or
  1629. * 2-2. This is a single pkt whose size is longer than one block size.
  1630. */
  1631. cur_chain_total_len = prev_chain_total_len +
  1632. (head_padding + pkt_len + tail_padding);
  1633. if (last_chained_pkt && bus->blocksize != 0 &&
  1634. (cur_chain_total_len > (int)bus->blocksize || prev_chain_total_len > 0)) {
  1635. modulo = cur_chain_total_len % bus->blocksize;
  1636. chain_tail_padding = modulo > 0 ? (bus->blocksize - modulo) : 0;
  1637. }
  1638. #ifdef DHDENABLE_TAILPAD
  1639. if (PKTTAILROOM(osh, pkt) < tail_padding) {
  1640. /* We don't have tail room to align by DHD_SDALIGN */
  1641. alloc_new_pkt = TRUE;
  1642. bus->tx_tailpad_pktget++;
  1643. } else if (PKTTAILROOM(osh, pkt) < tail_padding + chain_tail_padding) {
  1644. /* We have tail room for tail_padding of this pkt itself, but not for
  1645. * total pkt chain alignment by block size.
  1646. * Use the padding packet to avoid memory copy if applicable,
  1647. * otherwise, just allocate a new pkt.
  1648. */
  1649. if (bus->pad_pkt) {
  1650. *pad_pkt_len = chain_tail_padding;
  1651. bus->tx_tailpad_chain++;
  1652. } else {
  1653. alloc_new_pkt = TRUE;
  1654. bus->tx_tailpad_pktget++;
  1655. }
  1656. } else
  1657. /* This last pkt's tailroom is sufficient to hold both tail_padding
  1658. * of the pkt itself and chain_tail_padding of total pkt chain
  1659. */
  1660. #endif /* DHDENABLE_TAILPAD */
  1661. tail_padding += chain_tail_padding;
  1662. }
  1663. DHD_INFO(("%s sdhdr len + orig_pkt_len %d h_pad %d t_pad %d pad_pkt_len %d\n",
  1664. __FUNCTION__, pkt_len, head_padding, tail_padding, *pad_pkt_len));
  1665. if (alloc_new_pkt) {
  1666. void *tmp_pkt;
  1667. int newpkt_size;
  1668. int cur_total_len;
  1669. ASSERT(*pad_pkt_len == 0);
  1670. DHD_INFO(("%s allocating new packet for padding\n", __FUNCTION__));
  1671. /* head pointer is aligned now, no padding needed */
  1672. head_padding = 0;
  1673. /* update the tail padding as it depends on the head padding, since a new packet is
  1674. * allocated, the head padding is non longer needed and packet length is chagned
  1675. */
  1676. cur_total_len = prev_chain_total_len + pkt_len;
  1677. if (last_chained_pkt && bus->blocksize != 0 &&
  1678. (cur_total_len > (int)bus->blocksize || prev_chain_total_len > 0)) {
  1679. modulo = cur_total_len % bus->blocksize;
  1680. tail_padding = modulo > 0 ? (bus->blocksize - modulo) : 0;
  1681. }
  1682. else {
  1683. modulo = pkt_len % DHD_SDALIGN;
  1684. tail_padding = modulo > 0 ? (DHD_SDALIGN - modulo) : 0;
  1685. }
  1686. newpkt_size = PKTLEN(osh, pkt) + bus->blocksize + DHD_SDALIGN;
  1687. bus->dhd->tx_realloc++;
  1688. tmp_pkt = PKTGET(osh, newpkt_size, TRUE);
  1689. if (tmp_pkt == NULL) {
  1690. DHD_ERROR(("failed to alloc new %d byte packet\n", newpkt_size));
  1691. return BCME_NOMEM;
  1692. }
  1693. PKTALIGN(osh, tmp_pkt, PKTLEN(osh, pkt), DHD_SDALIGN);
  1694. bcopy(PKTDATA(osh, pkt), PKTDATA(osh, tmp_pkt), PKTLEN(osh, pkt));
  1695. *new_pkt = tmp_pkt;
  1696. pkt = tmp_pkt;
  1697. }
  1698. if (head_padding)
  1699. PKTPUSH(osh, pkt, head_padding);
  1700. frame = (uint8*)PKTDATA(osh, pkt);
  1701. bzero(frame, head_padding + sdpcm_hdrlen);
  1702. pkt_len = (uint16)PKTLEN(osh, pkt);
  1703. /* the header has the followming format
  1704. * 4-byte HW frame tag: length, ~length (for glom this is the total length)
  1705. *
  1706. * 8-byte HW extesion flags (glom mode only) as the following:
  1707. * 2-byte packet length, excluding HW tag and padding
  1708. * 2-byte frame channel and frame flags (e.g. next frame following)
  1709. * 2-byte header length
  1710. * 2-byte tail padding size
  1711. *
  1712. * 8-byte SW frame tags as the following
  1713. * 4-byte flags: host tx seq, channel, data offset
  1714. * 4-byte flags: TBD
  1715. */
  1716. swhdr_offset = SDPCM_FRAMETAG_LEN;
  1717. /* hardware frame tag:
  1718. *
  1719. * in tx-glom mode, dongle only checks the hardware frame tag in the first
  1720. * packet and sees it as the total lenght of the glom (including tail padding),
  1721. * for each packet in the glom, the packet length needs to be updated, (see
  1722. * below PKTSETLEN)
  1723. *
  1724. * in non tx-glom mode, PKTLEN still need to include tail padding as to be
  1725. * referred to in sdioh_request_buffer(). The tail length will be excluded in
  1726. * dhdsdio_txpkt_postprocess().
  1727. */
  1728. *(uint16*)frame = (uint16)htol16(pkt_len);
  1729. *(((uint16*)frame) + 1) = (uint16)htol16(~pkt_len);
  1730. pkt_len += tail_padding;
  1731. /* hardware extesion flags */
  1732. if (bus->txglom_enable) {
  1733. uint32 hwheader1;
  1734. uint32 hwheader2;
  1735. swhdr_offset += SDPCM_HWEXT_LEN;
  1736. hwheader1 = (pkt_len - SDPCM_FRAMETAG_LEN - tail_padding) |
  1737. (last_chained_pkt << 24);
  1738. hwheader2 = (tail_padding) << 16;
  1739. htol32_ua_store(hwheader1, frame + SDPCM_FRAMETAG_LEN);
  1740. htol32_ua_store(hwheader2, frame + SDPCM_FRAMETAG_LEN + 4);
  1741. }
  1742. PKTSETLEN((osh), (pkt), (pkt_len));
  1743. /* software frame tags */
  1744. swheader = ((chan << SDPCM_CHANNEL_SHIFT) & SDPCM_CHANNEL_MASK)
  1745. | (txseq % SDPCM_SEQUENCE_WRAP) |
  1746. (((head_padding + sdpcm_hdrlen) << SDPCM_DOFFSET_SHIFT) & SDPCM_DOFFSET_MASK);
  1747. htol32_ua_store(swheader, frame + swhdr_offset);
  1748. htol32_ua_store(0, frame + swhdr_offset + sizeof(swheader));
  1749. return pkt_len;
  1750. }
  1751. static int dhdsdio_txpkt_postprocess(dhd_bus_t *bus, void *pkt)
  1752. {
  1753. osl_t *osh;
  1754. uint8 *frame;
  1755. int data_offset;
  1756. int tail_padding;
  1757. int swhdr_offset = SDPCM_FRAMETAG_LEN + (bus->txglom_enable ? SDPCM_HWEXT_LEN : 0);
  1758. (void)osh;
  1759. osh = bus->dhd->osh;
  1760. /* restore pkt buffer pointer, but keeps the header pushed by dhd_prot_hdrpush */
  1761. frame = (uint8*)PKTDATA(osh, pkt);
  1762. DHD_INFO(("%s PKTLEN before postprocess %d",
  1763. __FUNCTION__, PKTLEN(osh, pkt)));
  1764. /* PKTLEN still includes tail_padding, so exclude it.
  1765. * We shall have head_padding + original pkt_len for PKTLEN afterwards.
  1766. */
  1767. if (bus->txglom_enable) {
  1768. /* txglom pkts have tail_padding length in HW ext header */
  1769. tail_padding = ltoh32_ua(frame + SDPCM_FRAMETAG_LEN + 4) >> 16;
  1770. PKTSETLEN(osh, pkt, PKTLEN(osh, pkt) - tail_padding);
  1771. DHD_INFO((" txglom pkt: tail_padding %d PKTLEN %d\n",
  1772. tail_padding, PKTLEN(osh, pkt)));
  1773. } else {
  1774. /* non-txglom pkts have head_padding + original pkt length in HW frame tag.
  1775. * We cannot refer to this field for txglom pkts as the first pkt of the chain will
  1776. * have the field for the total length of the chain.
  1777. */
  1778. PKTSETLEN(osh, pkt, *(uint16*)frame);
  1779. DHD_INFO((" non-txglom pkt: HW frame tag len %d after PKTLEN %d\n",
  1780. *(uint16*)frame, PKTLEN(osh, pkt)));
  1781. }
  1782. data_offset = ltoh32_ua(frame + swhdr_offset);
  1783. data_offset = (data_offset & SDPCM_DOFFSET_MASK) >> SDPCM_DOFFSET_SHIFT;
  1784. /* Get rid of sdpcm header + head_padding */
  1785. PKTPULL(osh, pkt, data_offset);
  1786. DHD_INFO(("%s data_offset %d, PKTLEN %d\n",
  1787. __FUNCTION__, data_offset, PKTLEN(osh, pkt)));
  1788. return BCME_OK;
  1789. }
  1790. static int dhdsdio_txpkt(dhd_bus_t *bus, uint chan, void** pkts, int num_pkt, bool free_pkt)
  1791. {
  1792. int i;
  1793. int ret = 0;
  1794. osl_t *osh;
  1795. bcmsdh_info_t *sdh;
  1796. void *pkt = NULL;
  1797. void *pkt_chain;
  1798. int total_len = 0;
  1799. void *head_pkt = NULL;
  1800. void *prev_pkt = NULL;
  1801. int pad_pkt_len = 0;
  1802. int new_pkt_num = 0;
  1803. void *new_pkts[MAX_TX_PKTCHAIN_CNT];
  1804. bool wlfc_enabled = FALSE;
  1805. if (bus->dhd->dongle_reset)
  1806. return BCME_NOTREADY;
  1807. sdh = bus->sdh;
  1808. osh = bus->dhd->osh;
  1809. /* init new_pkts[0] to make some compiler happy, not necessary as we check new_pkt_num */
  1810. new_pkts[0] = NULL;
  1811. for (i = 0; i < num_pkt; i++) {
  1812. int pkt_len;
  1813. bool last_pkt;
  1814. void *new_pkt = NULL;
  1815. pkt = pkts[i];
  1816. ASSERT(pkt);
  1817. last_pkt = (i == num_pkt - 1);
  1818. pkt_len = dhdsdio_txpkt_preprocess(bus, pkt, chan, bus->tx_seq + i,
  1819. total_len, last_pkt, &pad_pkt_len, &new_pkt);
  1820. if (pkt_len <= 0)
  1821. goto done;
  1822. if (new_pkt) {
  1823. pkt = new_pkt;
  1824. new_pkts[new_pkt_num++] = new_pkt;
  1825. }
  1826. total_len += pkt_len;
  1827. PKTSETNEXT(osh, pkt, NULL);
  1828. /* insert the packet into the list */
  1829. head_pkt ? PKTSETNEXT(osh, prev_pkt, pkt) : (head_pkt = pkt);
  1830. prev_pkt = pkt;
  1831. }
  1832. /* Update the HW frame tag (total length) in the first pkt of the glom */
  1833. if (bus->txglom_enable) {
  1834. uint8 *frame;
  1835. total_len += pad_pkt_len;
  1836. frame = (uint8*)PKTDATA(osh, head_pkt);
  1837. *(uint16*)frame = (uint16)htol16(total_len);
  1838. *(((uint16*)frame) + 1) = (uint16)htol16(~total_len);
  1839. }
  1840. /* if a padding packet if needed, insert it to the end of the link list */
  1841. if (pad_pkt_len) {
  1842. PKTSETLEN(osh, bus->pad_pkt, pad_pkt_len);
  1843. PKTSETNEXT(osh, pkt, bus->pad_pkt);
  1844. }
  1845. /* dhd_bcmsdh_send_buf ignores the buffer pointer if he packet
  1846. * parameter is not NULL, for non packet chian we pass NULL pkt pointer
  1847. * so it will take the aligned length and buffer pointer.
  1848. */
  1849. pkt_chain = PKTNEXT(osh, head_pkt) ? head_pkt : NULL;
  1850. ret = dhd_bcmsdh_send_buf(bus, bcmsdh_cur_sbwad(sdh), SDIO_FUNC_2, F2SYNC,
  1851. PKTDATA(osh, head_pkt), total_len, pkt_chain, NULL, NULL, TXRETRIES);
  1852. if (ret == BCME_OK)
  1853. bus->tx_seq = (bus->tx_seq + num_pkt) % SDPCM_SEQUENCE_WRAP;
  1854. /* if a padding packet was needed, remove it from the link list as it not a data pkt */
  1855. if (pad_pkt_len && pkt)
  1856. PKTSETNEXT(osh, pkt, NULL);
  1857. done:
  1858. pkt = head_pkt;
  1859. while (pkt) {
  1860. void *pkt_next = PKTNEXT(osh, pkt);
  1861. PKTSETNEXT(osh, pkt, NULL);
  1862. dhdsdio_txpkt_postprocess(bus, pkt);
  1863. pkt = pkt_next;
  1864. }
  1865. /* new packets might be allocated due to insufficient room for padding, but we
  1866. * still have to indicate the original packets to upper layer
  1867. */
  1868. for (i = 0; i < num_pkt; i++) {
  1869. pkt = pkts[i];
  1870. wlfc_enabled = FALSE;
  1871. #ifdef PROP_TXSTATUS
  1872. if (DHD_PKTTAG_WLFCPKT(PKTTAG(pkt))) {
  1873. wlfc_enabled = (dhd_wlfc_txcomplete(bus->dhd, pkt, ret == 0) !=
  1874. WLFC_UNSUPPORTED);
  1875. }
  1876. #endif /* PROP_TXSTATUS */
  1877. if (!wlfc_enabled) {
  1878. PKTSETNEXT(osh, pkt, NULL);
  1879. dhd_txcomplete(bus->dhd, pkt, ret != 0);
  1880. if (free_pkt)
  1881. PKTFREE(osh, pkt, TRUE);
  1882. }
  1883. }
  1884. for (i = 0; i < new_pkt_num; i++)
  1885. PKTFREE(osh, new_pkts[i], TRUE);
  1886. return ret;
  1887. }
  1888. static uint
  1889. dhdsdio_sendfromq(dhd_bus_t *bus, uint maxframes)
  1890. {
  1891. uint cnt = 0;
  1892. uint8 tx_prec_map;
  1893. uint16 txpktqlen = 0;
  1894. uint32 intstatus = 0;
  1895. uint retries = 0;
  1896. osl_t *osh;
  1897. uint datalen = 0;
  1898. dhd_pub_t *dhd = bus->dhd;
  1899. sdpcmd_regs_t *regs = bus->regs;
  1900. DHD_TRACE(("%s: Enter\n", __FUNCTION__));
  1901. if (!KSO_ENAB(bus)) {
  1902. DHD_ERROR(("%s: Device asleep\n", __FUNCTION__));
  1903. return BCME_NODEVICE;
  1904. }
  1905. osh = dhd->osh;
  1906. tx_prec_map = ~bus->flowcontrol;
  1907. #ifdef DHD_LOSSLESS_ROAMING
  1908. tx_prec_map &= dhd->dequeue_prec_map;
  1909. #endif
  1910. for (cnt = 0; (cnt < maxframes) && DATAOK(bus);) {
  1911. int i;
  1912. int num_pkt = 1;
  1913. void *pkts[MAX_TX_PKTCHAIN_CNT];
  1914. int prec_out;
  1915. dhd_os_sdlock_txq(bus->dhd);
  1916. if (bus->txglom_enable) {
  1917. num_pkt = MIN((uint32)DATABUFCNT(bus), (uint32)bus->txglomsize);
  1918. num_pkt = MIN(num_pkt, ARRAYSIZE(pkts));
  1919. }
  1920. num_pkt = MIN(num_pkt, pktq_mlen(&bus->txq, tx_prec_map));
  1921. for (i = 0; i < num_pkt; i++) {
  1922. pkts[i] = pktq_mdeq(&bus->txq, tx_prec_map, &prec_out);
  1923. if (!pkts[i]) {
  1924. DHD_ERROR(("%s: pktg_mlen non-zero when no pkt\n",
  1925. __FUNCTION__));
  1926. ASSERT(0);
  1927. break;
  1928. }
  1929. PKTORPHAN(pkts[i]);
  1930. datalen += PKTLEN(osh, pkts[i]);
  1931. }
  1932. dhd_os_sdunlock_txq(bus->dhd);
  1933. if (i == 0)
  1934. break;
  1935. if (dhdsdio_txpkt(bus, SDPCM_DATA_CHANNEL, pkts, i, TRUE) != BCME_OK)
  1936. dhd->tx_errors++;
  1937. else
  1938. dhd->dstats.tx_bytes += datalen;
  1939. cnt += i;
  1940. /* In poll mode, need to check for other events */
  1941. if (!bus->intr && cnt)
  1942. {
  1943. /* Check device status, signal pending interrupt */
  1944. R_SDREG(intstatus, &regs->intstatus, retries);
  1945. bus->f2txdata++;
  1946. if (bcmsdh_regfail(bus->sdh))
  1947. break;
  1948. if (intstatus & bus->hostintmask)
  1949. bus->ipend = TRUE;
  1950. }
  1951. }
  1952. dhd_os_sdlock_txq(bus->dhd);
  1953. txpktqlen = pktq_len(&bus->txq);
  1954. dhd_os_sdunlock_txq(bus->dhd);
  1955. /* Do flow-control if needed */
  1956. if (dhd->up && (dhd->busstate == DHD_BUS_DATA) && (txpktqlen < FCLOW)) {
  1957. bool wlfc_enabled = FALSE;
  1958. #ifdef PROP_TXSTATUS
  1959. wlfc_enabled = (dhd_wlfc_flowcontrol(dhd, OFF, TRUE) != WLFC_UNSUPPORTED);
  1960. #endif
  1961. if (!wlfc_enabled && dhd_doflow && dhd->txoff) {
  1962. dhd_txflowcontrol(dhd, ALL_INTERFACES, OFF);
  1963. }
  1964. }
  1965. return cnt;
  1966. }
  1967. static void
  1968. dhdsdio_sendpendctl(dhd_bus_t *bus)
  1969. {
  1970. bcmsdh_info_t *sdh = bus->sdh;
  1971. int ret;
  1972. uint8* frame_seq = bus->ctrl_frame_buf + SDPCM_FRAMETAG_LEN;
  1973. if (bus->txglom_enable)
  1974. frame_seq += SDPCM_HWEXT_LEN;
  1975. if (*frame_seq != bus->tx_seq) {
  1976. DHD_INFO(("%s IOCTL frame seq lag detected!"
  1977. " frm_seq:%d != bus->tx_seq:%d, corrected\n",
  1978. __FUNCTION__, *frame_seq, bus->tx_seq));
  1979. *frame_seq = bus->tx_seq;
  1980. }
  1981. ret = dhd_bcmsdh_send_buf(bus, bcmsdh_cur_sbwad(sdh), SDIO_FUNC_2, F2SYNC,
  1982. (uint8 *)bus->ctrl_frame_buf, (uint32)bus->ctrl_frame_len,
  1983. NULL, NULL, NULL, 1);
  1984. if (ret == BCME_OK)
  1985. bus->tx_seq = (bus->tx_seq + 1) % SDPCM_SEQUENCE_WRAP;
  1986. bus->ctrl_frame_stat = FALSE;
  1987. dhd_wait_event_wakeup(bus->dhd);
  1988. }
  1989. int
  1990. dhd_bus_txctl(struct dhd_bus *bus, uchar *msg, uint msglen)
  1991. {
  1992. static int err_nodevice = 0;
  1993. uint8 *frame;
  1994. uint16 len;
  1995. uint32 swheader;
  1996. bcmsdh_info_t *sdh = bus->sdh;
  1997. uint8 doff = 0;
  1998. int ret = -1;
  1999. uint8 sdpcm_hdrlen = bus->txglom_enable ? SDPCM_HDRLEN_TXGLOM : SDPCM_HDRLEN;
  2000. DHD_TRACE(("%s: Enter\n", __FUNCTION__));
  2001. if (bus->dhd->dongle_reset)
  2002. return -EIO;
  2003. /* Back the pointer to make a room for bus header */
  2004. frame = msg - sdpcm_hdrlen;
  2005. len = (msglen += sdpcm_hdrlen);
  2006. /* Add alignment padding (optional for ctl frames) */
  2007. if (dhd_alignctl) {
  2008. if ((doff = ((uintptr)frame % DHD_SDALIGN))) {
  2009. frame -= doff;
  2010. len += doff;
  2011. msglen += doff;
  2012. bzero(frame, doff + sdpcm_hdrlen);
  2013. }
  2014. ASSERT(doff < DHD_SDALIGN);
  2015. }
  2016. doff += sdpcm_hdrlen;
  2017. #ifndef BCMSPI
  2018. /* Round send length to next SDIO block */
  2019. if (bus->roundup && bus->blocksize && (len > bus->blocksize)) {
  2020. uint16 pad = bus->blocksize - (len % bus->blocksize);
  2021. if ((pad <= bus->roundup) && (pad < bus->blocksize))
  2022. len += pad;
  2023. } else if (len % DHD_SDALIGN) {
  2024. len += DHD_SDALIGN - (len % DHD_SDALIGN);
  2025. }
  2026. #endif /* BCMSPI */
  2027. /* Satisfy length-alignment requirements */
  2028. if (forcealign && (len & (ALIGNMENT - 1)))
  2029. len = ROUNDUP(len, ALIGNMENT);
  2030. ASSERT(ISALIGNED((uintptr)frame, 2));
  2031. /* Need to lock here to protect txseq and SDIO tx calls */
  2032. dhd_os_sdlock(bus->dhd);
  2033. BUS_WAKE(bus);
  2034. /* Make sure backplane clock is on */
  2035. dhdsdio_clkctl(bus, CLK_AVAIL, FALSE);
  2036. /* Hardware tag: 2 byte len followed by 2 byte ~len check (all LE) */
  2037. *(uint16*)frame = htol16((uint16)msglen);
  2038. *(((uint16*)frame) + 1) = htol16(~msglen);
  2039. if (bus->txglom_enable) {
  2040. uint32 hwheader1, hwheader2;
  2041. /* Software tag: channel, sequence number, data offset */
  2042. swheader = ((SDPCM_CONTROL_CHANNEL << SDPCM_CHANNEL_SHIFT) & SDPCM_CHANNEL_MASK)
  2043. | bus->tx_seq
  2044. | ((doff << SDPCM_DOFFSET_SHIFT) & SDPCM_DOFFSET_MASK);
  2045. htol32_ua_store(swheader, frame + SDPCM_FRAMETAG_LEN + SDPCM_HWEXT_LEN);
  2046. htol32_ua_store(0, frame + SDPCM_FRAMETAG_LEN
  2047. + SDPCM_HWEXT_LEN + sizeof(swheader));
  2048. hwheader1 = (msglen - SDPCM_FRAMETAG_LEN) | (1 << 24);
  2049. hwheader2 = (len - (msglen)) << 16;
  2050. htol32_ua_store(hwheader1, frame + SDPCM_FRAMETAG_LEN);
  2051. htol32_ua_store(hwheader2, frame + SDPCM_FRAMETAG_LEN + 4);
  2052. *(uint16*)frame = htol16(len);
  2053. *(((uint16*)frame) + 1) = htol16(~(len));
  2054. } else {
  2055. /* Software tag: channel, sequence number, data offset */
  2056. swheader = ((SDPCM_CONTROL_CHANNEL << SDPCM_CHANNEL_SHIFT) & SDPCM_CHANNEL_MASK)
  2057. | bus->tx_seq | ((doff << SDPCM_DOFFSET_SHIFT) & SDPCM_DOFFSET_MASK);
  2058. htol32_ua_store(swheader, frame + SDPCM_FRAMETAG_LEN);
  2059. htol32_ua_store(0, frame + SDPCM_FRAMETAG_LEN + sizeof(swheader));
  2060. }
  2061. if (!TXCTLOK(bus)) {
  2062. DHD_INFO(("%s: No bus credit bus->tx_max %d, bus->tx_seq %d\n",
  2063. __FUNCTION__, bus->tx_max, bus->tx_seq));
  2064. bus->ctrl_frame_stat = TRUE;
  2065. /* Send from dpc */
  2066. bus->ctrl_frame_buf = frame;
  2067. bus->ctrl_frame_len = len;
  2068. if (!bus->dpc_sched) {
  2069. bus->dpc_sched = TRUE;
  2070. dhd_sched_dpc(bus->dhd);
  2071. }
  2072. if (bus->ctrl_frame_stat) {
  2073. dhd_wait_for_event(bus->dhd, &bus->ctrl_frame_stat);
  2074. }
  2075. if (bus->ctrl_frame_stat == FALSE) {
  2076. DHD_INFO(("%s: ctrl_frame_stat == FALSE\n", __FUNCTION__));
  2077. ret = 0;
  2078. } else {
  2079. bus->dhd->txcnt_timeout++;
  2080. if (!bus->dhd->hang_was_sent) {
  2081. #ifdef CUSTOMER_HW4
  2082. uint32 status, retry = 0;
  2083. R_SDREG(status, &bus->regs->intstatus, retry);
  2084. DHD_TRACE_HW4(("%s: txcnt_timeout, INT status=0x%08X\n",
  2085. __FUNCTION__, status));
  2086. DHD_TRACE_HW4(("%s : tx_max : %d, tx_seq : %d, clkstate : %d \n",
  2087. __FUNCTION__, bus->tx_max, bus->tx_seq, bus->clkstate));
  2088. #endif /* CUSTOMER_HW4 */
  2089. DHD_ERROR(("%s: ctrl_frame_stat == TRUE txcnt_timeout=%d\n",
  2090. __FUNCTION__, bus->dhd->txcnt_timeout));
  2091. }
  2092. ret = -1;
  2093. bus->ctrl_frame_stat = FALSE;
  2094. goto done;
  2095. }
  2096. }
  2097. bus->dhd->txcnt_timeout = 0;
  2098. bus->ctrl_frame_stat = TRUE;
  2099. if (ret == -1) {
  2100. #ifdef DHD_DEBUG
  2101. if (DHD_BYTES_ON() && DHD_CTL_ON()) {
  2102. prhex("Tx Frame", frame, len);
  2103. } else if (DHD_HDRS_ON()) {
  2104. prhex("TxHdr", frame, MIN(len, 16));
  2105. }
  2106. #endif
  2107. ret = dhd_bcmsdh_send_buf(bus, bcmsdh_cur_sbwad(sdh), SDIO_FUNC_2, F2SYNC,
  2108. frame, len, NULL, NULL, NULL, TXRETRIES);
  2109. if (ret == BCME_OK)
  2110. bus->tx_seq = (bus->tx_seq + 1) % SDPCM_SEQUENCE_WRAP;
  2111. }
  2112. bus->ctrl_frame_stat = FALSE;
  2113. done:
  2114. if ((bus->idletime == DHD_IDLE_IMMEDIATE) && !bus->dpc_sched) {
  2115. bus->activity = FALSE;
  2116. dhdsdio_clkctl(bus, CLK_NONE, TRUE);
  2117. }
  2118. dhd_os_sdunlock(bus->dhd);
  2119. if (ret)
  2120. bus->dhd->tx_ctlerrs++;
  2121. else
  2122. bus->dhd->tx_ctlpkts++;
  2123. if (bus->dhd->txcnt_timeout >= MAX_CNTL_TX_TIMEOUT)
  2124. return -ETIMEDOUT;
  2125. if (ret == BCME_NODEVICE)
  2126. err_nodevice++;
  2127. else
  2128. err_nodevice = 0;
  2129. return ret ? err_nodevice >= ERROR_BCME_NODEVICE_MAX ? -ETIMEDOUT : -EIO : 0;
  2130. }
  2131. int
  2132. dhd_bus_rxctl(struct dhd_bus *bus, uchar *msg, uint msglen)
  2133. {
  2134. int timeleft;
  2135. uint rxlen = 0;
  2136. bool pending;
  2137. DHD_TRACE(("%s: Enter\n", __FUNCTION__));
  2138. if (bus->dhd->dongle_reset)
  2139. return -EIO;
  2140. /* Wait until control frame is available */
  2141. timeleft = dhd_os_ioctl_resp_wait(bus->dhd, &bus->rxlen, &pending);
  2142. dhd_os_sdlock(bus->dhd);
  2143. rxlen = bus->rxlen;
  2144. bcopy(bus->rxctl, msg, MIN(msglen, rxlen));
  2145. bus->rxlen = 0;
  2146. dhd_os_sdunlock(bus->dhd);
  2147. if (rxlen) {
  2148. DHD_CTL(("%s: resumed on rxctl frame, got %d expected %d\n",
  2149. __FUNCTION__, rxlen, msglen));
  2150. } else if (timeleft == 0) {
  2151. #ifdef DHD_DEBUG
  2152. uint32 status, retry = 0;
  2153. R_SDREG(status, &bus->regs->intstatus, retry);
  2154. DHD_ERROR(("%s: resumed on timeout, INT status=0x%08X\n",
  2155. __FUNCTION__, status));
  2156. #else
  2157. DHD_ERROR(("%s: resumed on timeout\n", __FUNCTION__));
  2158. #endif /* DHD_DEBUG */
  2159. #ifdef DHD_DEBUG
  2160. dhd_os_sdlock(bus->dhd);
  2161. dhdsdio_checkdied(bus, NULL, 0);
  2162. dhd_os_sdunlock(bus->dhd);
  2163. #endif /* DHD_DEBUG */
  2164. } else if (pending == TRUE) {
  2165. /* signal pending */
  2166. DHD_ERROR(("%s: signal pending\n", __FUNCTION__));
  2167. return -EINTR;
  2168. } else {
  2169. DHD_CTL(("%s: resumed for unknown reason?\n", __FUNCTION__));
  2170. #ifdef DHD_DEBUG
  2171. dhd_os_sdlock(bus->dhd);
  2172. dhdsdio_checkdied(bus, NULL, 0);
  2173. dhd_os_sdunlock(bus->dhd);
  2174. #endif /* DHD_DEBUG */
  2175. }
  2176. if (timeleft == 0) {
  2177. if (rxlen == 0)
  2178. bus->dhd->rxcnt_timeout++;
  2179. DHD_ERROR(("%s: rxcnt_timeout=%d, rxlen=%d\n", __FUNCTION__,
  2180. bus->dhd->rxcnt_timeout, rxlen));
  2181. }
  2182. else
  2183. bus->dhd->rxcnt_timeout = 0;
  2184. if (rxlen)
  2185. bus->dhd->rx_ctlpkts++;
  2186. else
  2187. bus->dhd->rx_ctlerrs++;
  2188. if (bus->dhd->rxcnt_timeout >= MAX_CNTL_RX_TIMEOUT)
  2189. return -ETIMEDOUT;
  2190. if (bus->dhd->dongle_trap_occured)
  2191. return -EREMOTEIO;
  2192. return rxlen ? (int)rxlen : -EIO;
  2193. }
  2194. /* IOVar table */
  2195. enum {
  2196. IOV_INTR = 1,
  2197. IOV_POLLRATE,
  2198. IOV_SDREG,
  2199. IOV_SBREG,
  2200. IOV_SDCIS,
  2201. IOV_MEMBYTES,
  2202. IOV_RAMSIZE,
  2203. IOV_RAMSTART,
  2204. #ifdef DHD_DEBUG
  2205. IOV_CHECKDIED,
  2206. IOV_SERIALCONS,
  2207. #endif /* DHD_DEBUG */
  2208. IOV_SET_DOWNLOAD_STATE,
  2209. IOV_SOCRAM_STATE,
  2210. IOV_FORCEEVEN,
  2211. IOV_SDIOD_DRIVE,
  2212. IOV_READAHEAD,
  2213. IOV_SDRXCHAIN,
  2214. IOV_ALIGNCTL,
  2215. IOV_SDALIGN,
  2216. IOV_DEVRESET,
  2217. IOV_CPU,
  2218. #if defined(USE_SDIOFIFO_IOVAR)
  2219. IOV_WATERMARK,
  2220. IOV_MESBUSYCTRL,
  2221. #endif /* USE_SDIOFIFO_IOVAR */
  2222. #ifdef SDTEST
  2223. IOV_PKTGEN,
  2224. IOV_EXTLOOP,
  2225. #endif /* SDTEST */
  2226. IOV_SPROM,
  2227. IOV_TXBOUND,
  2228. IOV_RXBOUND,
  2229. IOV_TXMINMAX,
  2230. IOV_IDLETIME,
  2231. IOV_IDLECLOCK,
  2232. IOV_SD1IDLE,
  2233. IOV_SLEEP,
  2234. IOV_DONGLEISOLATION,
  2235. IOV_KSO,
  2236. IOV_DEVSLEEP,
  2237. IOV_DEVCAP,
  2238. IOV_VARS,
  2239. #ifdef SOFTAP
  2240. IOV_FWPATH,
  2241. #endif
  2242. IOV_TXGLOMSIZE,
  2243. IOV_TXGLOMMODE,
  2244. IOV_HANGREPORT,
  2245. IOV_TXINRX_THRES
  2246. };
  2247. const bcm_iovar_t dhdsdio_iovars[] = {
  2248. {"intr", IOV_INTR, 0, IOVT_BOOL, 0 },
  2249. {"sleep", IOV_SLEEP, 0, IOVT_BOOL, 0 },
  2250. {"pollrate", IOV_POLLRATE, 0, IOVT_UINT32, 0 },
  2251. {"idletime", IOV_IDLETIME, 0, IOVT_INT32, 0 },
  2252. {"idleclock", IOV_IDLECLOCK, 0, IOVT_INT32, 0 },
  2253. {"sd1idle", IOV_SD1IDLE, 0, IOVT_BOOL, 0 },
  2254. {"membytes", IOV_MEMBYTES, 0, IOVT_BUFFER, 2 * sizeof(int) },
  2255. {"ramsize", IOV_RAMSIZE, 0, IOVT_UINT32, 0 },
  2256. {"ramstart", IOV_RAMSTART, 0, IOVT_UINT32, 0 },
  2257. {"dwnldstate", IOV_SET_DOWNLOAD_STATE, 0, IOVT_BOOL, 0 },
  2258. {"socram_state", IOV_SOCRAM_STATE, 0, IOVT_BOOL, 0 },
  2259. {"vars", IOV_VARS, 0, IOVT_BUFFER, 0 },
  2260. {"sdiod_drive", IOV_SDIOD_DRIVE, 0, IOVT_UINT32, 0 },
  2261. {"readahead", IOV_READAHEAD, 0, IOVT_BOOL, 0 },
  2262. {"sdrxchain", IOV_SDRXCHAIN, 0, IOVT_BOOL, 0 },
  2263. {"alignctl", IOV_ALIGNCTL, 0, IOVT_BOOL, 0 },
  2264. {"sdalign", IOV_SDALIGN, 0, IOVT_BOOL, 0 },
  2265. {"devreset", IOV_DEVRESET, 0, IOVT_BOOL, 0 },
  2266. #ifdef DHD_DEBUG
  2267. {"sdreg", IOV_SDREG, 0, IOVT_BUFFER, sizeof(sdreg_t) },
  2268. {"sbreg", IOV_SBREG, 0, IOVT_BUFFER, sizeof(sdreg_t) },
  2269. {"sd_cis", IOV_SDCIS, 0, IOVT_BUFFER, DHD_IOCTL_MAXLEN },
  2270. {"forcealign", IOV_FORCEEVEN, 0, IOVT_BOOL, 0 },
  2271. {"txbound", IOV_TXBOUND, 0, IOVT_UINT32, 0 },
  2272. {"rxbound", IOV_RXBOUND, 0, IOVT_UINT32, 0 },
  2273. {"txminmax", IOV_TXMINMAX, 0, IOVT_UINT32, 0 },
  2274. {"cpu", IOV_CPU, 0, IOVT_BOOL, 0 },
  2275. #ifdef DHD_DEBUG
  2276. {"checkdied", IOV_CHECKDIED, 0, IOVT_BUFFER, 0 },
  2277. {"serial", IOV_SERIALCONS, 0, IOVT_UINT32, 0 },
  2278. #endif /* DHD_DEBUG */
  2279. #endif /* DHD_DEBUG */
  2280. #ifdef SDTEST
  2281. {"extloop", IOV_EXTLOOP, 0, IOVT_BOOL, 0 },
  2282. {"pktgen", IOV_PKTGEN, 0, IOVT_BUFFER, sizeof(dhd_pktgen_t) },
  2283. #endif /* SDTEST */
  2284. #if defined(USE_SDIOFIFO_IOVAR)
  2285. {"watermark", IOV_WATERMARK, 0, IOVT_UINT32, 0 },
  2286. {"mesbusyctrl", IOV_MESBUSYCTRL, 0, IOVT_UINT32, 0 },
  2287. #endif /* USE_SDIOFIFO_IOVAR */
  2288. {"devcap", IOV_DEVCAP, 0, IOVT_UINT32, 0 },
  2289. {"dngl_isolation", IOV_DONGLEISOLATION, 0, IOVT_UINT32, 0 },
  2290. {"kso", IOV_KSO, 0, IOVT_UINT32, 0 },
  2291. {"devsleep", IOV_DEVSLEEP, 0, IOVT_UINT32, 0 },
  2292. #ifdef SOFTAP
  2293. {"fwpath", IOV_FWPATH, 0, IOVT_BUFFER, 0 },
  2294. #endif
  2295. {"txglomsize", IOV_TXGLOMSIZE, 0, IOVT_UINT32, 0 },
  2296. {"fw_hang_report", IOV_HANGREPORT, 0, IOVT_BOOL, 0 },
  2297. {"txinrx_thres", IOV_TXINRX_THRES, 0, IOVT_INT32, 0 },
  2298. {NULL, 0, 0, 0, 0 }
  2299. };
  2300. static void
  2301. dhd_dump_pct(struct bcmstrbuf *strbuf, char *desc, uint num, uint div)
  2302. {
  2303. uint q1, q2;
  2304. if (!div) {
  2305. bcm_bprintf(strbuf, "%s N/A", desc);
  2306. } else {
  2307. q1 = num / div;
  2308. q2 = (100 * (num - (q1 * div))) / div;
  2309. bcm_bprintf(strbuf, "%s %d.%02d", desc, q1, q2);
  2310. }
  2311. }
  2312. void
  2313. dhd_bus_dump(dhd_pub_t *dhdp, struct bcmstrbuf *strbuf)
  2314. {
  2315. dhd_bus_t *bus = dhdp->bus;
  2316. bcm_bprintf(strbuf, "Bus SDIO structure:\n");
  2317. bcm_bprintf(strbuf, "hostintmask 0x%08x intstatus 0x%08x sdpcm_ver %d\n",
  2318. bus->hostintmask, bus->intstatus, bus->sdpcm_ver);
  2319. bcm_bprintf(strbuf, "fcstate %d qlen %u tx_seq %d, max %d, rxskip %d rxlen %u rx_seq %d\n",
  2320. bus->fcstate, pktq_len(&bus->txq), bus->tx_seq, bus->tx_max, bus->rxskip,
  2321. bus->rxlen, bus->rx_seq);
  2322. bcm_bprintf(strbuf, "intr %d intrcount %u lastintrs %u spurious %u\n",
  2323. bus->intr, bus->intrcount, bus->lastintrs, bus->spurious);
  2324. bcm_bprintf(strbuf, "pollrate %u pollcnt %u regfails %u\n",
  2325. bus->pollrate, bus->pollcnt, bus->regfails);
  2326. bcm_bprintf(strbuf, "\nAdditional counters:\n");
  2327. #ifdef DHDENABLE_TAILPAD
  2328. bcm_bprintf(strbuf, "tx_tailpad_chain %u tx_tailpad_pktget %u\n",
  2329. bus->tx_tailpad_chain, bus->tx_tailpad_pktget);
  2330. #endif
  2331. bcm_bprintf(strbuf, "tx_sderrs %u fcqueued %u rxrtx %u rx_toolong %u rxc_errors %u\n",
  2332. bus->tx_sderrs, bus->fcqueued, bus->rxrtx, bus->rx_toolong,
  2333. bus->rxc_errors);
  2334. bcm_bprintf(strbuf, "rx_hdrfail %u badhdr %u badseq %u\n",
  2335. bus->rx_hdrfail, bus->rx_badhdr, bus->rx_badseq);
  2336. bcm_bprintf(strbuf, "fc_rcvd %u, fc_xoff %u, fc_xon %u\n",
  2337. bus->fc_rcvd, bus->fc_xoff, bus->fc_xon);
  2338. bcm_bprintf(strbuf, "rxglomfail %u, rxglomframes %u, rxglompkts %u\n",
  2339. bus->rxglomfail, bus->rxglomframes, bus->rxglompkts);
  2340. bcm_bprintf(strbuf, "f2rx (hdrs/data) %u (%u/%u), f2tx %u f1regs %u\n",
  2341. (bus->f2rxhdrs + bus->f2rxdata), bus->f2rxhdrs, bus->f2rxdata,
  2342. bus->f2txdata, bus->f1regdata);
  2343. {
  2344. dhd_dump_pct(strbuf, "\nRx: pkts/f2rd", bus->dhd->rx_packets,
  2345. (bus->f2rxhdrs + bus->f2rxdata));
  2346. dhd_dump_pct(strbuf, ", pkts/f1sd", bus->dhd->rx_packets, bus->f1regdata);
  2347. dhd_dump_pct(strbuf, ", pkts/sd", bus->dhd->rx_packets,
  2348. (bus->f2rxhdrs + bus->f2rxdata + bus->f1regdata));
  2349. dhd_dump_pct(strbuf, ", pkts/int", bus->dhd->rx_packets, bus->intrcount);
  2350. bcm_bprintf(strbuf, "\n");
  2351. dhd_dump_pct(strbuf, "Rx: glom pct", (100 * bus->rxglompkts),
  2352. bus->dhd->rx_packets);
  2353. dhd_dump_pct(strbuf, ", pkts/glom", bus->rxglompkts, bus->rxglomframes);
  2354. bcm_bprintf(strbuf, "\n");
  2355. dhd_dump_pct(strbuf, "Tx: pkts/f2wr", bus->dhd->tx_packets, bus->f2txdata);
  2356. dhd_dump_pct(strbuf, ", pkts/f1sd", bus->dhd->tx_packets, bus->f1regdata);
  2357. dhd_dump_pct(strbuf, ", pkts/sd", bus->dhd->tx_packets,
  2358. (bus->f2txdata + bus->f1regdata));
  2359. dhd_dump_pct(strbuf, ", pkts/int", bus->dhd->tx_packets, bus->intrcount);
  2360. bcm_bprintf(strbuf, "\n");
  2361. dhd_dump_pct(strbuf, "Total: pkts/f2rw",
  2362. (bus->dhd->tx_packets + bus->dhd->rx_packets),
  2363. (bus->f2txdata + bus->f2rxhdrs + bus->f2rxdata));
  2364. dhd_dump_pct(strbuf, ", pkts/f1sd",
  2365. (bus->dhd->tx_packets + bus->dhd->rx_packets), bus->f1regdata);
  2366. dhd_dump_pct(strbuf, ", pkts/sd",
  2367. (bus->dhd->tx_packets + bus->dhd->rx_packets),
  2368. (bus->f2txdata + bus->f2rxhdrs + bus->f2rxdata + bus->f1regdata));
  2369. dhd_dump_pct(strbuf, ", pkts/int",
  2370. (bus->dhd->tx_packets + bus->dhd->rx_packets), bus->intrcount);
  2371. bcm_bprintf(strbuf, "\n\n");
  2372. }
  2373. #ifdef SDTEST
  2374. if (bus->pktgen_count) {
  2375. bcm_bprintf(strbuf, "pktgen config and count:\n");
  2376. bcm_bprintf(strbuf, "freq %u count %u print %u total %u min %u len %u\n",
  2377. bus->pktgen_freq, bus->pktgen_count, bus->pktgen_print,
  2378. bus->pktgen_total, bus->pktgen_minlen, bus->pktgen_maxlen);
  2379. bcm_bprintf(strbuf, "send attempts %u rcvd %u fail %u\n",
  2380. bus->pktgen_sent, bus->pktgen_rcvd, bus->pktgen_fail);
  2381. }
  2382. #endif /* SDTEST */
  2383. #ifdef DHD_DEBUG
  2384. bcm_bprintf(strbuf, "dpc_sched %d host interrupt%spending\n",
  2385. bus->dpc_sched, (bcmsdh_intr_pending(bus->sdh) ? " " : " not "));
  2386. bcm_bprintf(strbuf, "blocksize %u roundup %u\n", bus->blocksize, bus->roundup);
  2387. #endif /* DHD_DEBUG */
  2388. bcm_bprintf(strbuf, "clkstate %d activity %d idletime %d idlecount %d sleeping %d\n",
  2389. bus->clkstate, bus->activity, bus->idletime, bus->idlecount, bus->sleeping);
  2390. }
  2391. void
  2392. dhd_bus_clearcounts(dhd_pub_t *dhdp)
  2393. {
  2394. dhd_bus_t *bus = (dhd_bus_t *)dhdp->bus;
  2395. bus->intrcount = bus->lastintrs = bus->spurious = bus->regfails = 0;
  2396. bus->rxrtx = bus->rx_toolong = bus->rxc_errors = 0;
  2397. bus->rx_hdrfail = bus->rx_badhdr = bus->rx_badseq = 0;
  2398. #ifdef DHDENABLE_TAILPAD
  2399. bus->tx_tailpad_chain = bus->tx_tailpad_pktget = 0;
  2400. #endif
  2401. bus->tx_sderrs = bus->fc_rcvd = bus->fc_xoff = bus->fc_xon = 0;
  2402. bus->rxglomfail = bus->rxglomframes = bus->rxglompkts = 0;
  2403. bus->f2rxhdrs = bus->f2rxdata = bus->f2txdata = bus->f1regdata = 0;
  2404. }
  2405. #ifdef SDTEST
  2406. static int
  2407. dhdsdio_pktgen_get(dhd_bus_t *bus, uint8 *arg)
  2408. {
  2409. dhd_pktgen_t pktgen;
  2410. pktgen.version = DHD_PKTGEN_VERSION;
  2411. pktgen.freq = bus->pktgen_freq;
  2412. pktgen.count = bus->pktgen_count;
  2413. pktgen.print = bus->pktgen_print;
  2414. pktgen.total = bus->pktgen_total;
  2415. pktgen.minlen = bus->pktgen_minlen;
  2416. pktgen.maxlen = bus->pktgen_maxlen;
  2417. pktgen.numsent = bus->pktgen_sent;
  2418. pktgen.numrcvd = bus->pktgen_rcvd;
  2419. pktgen.numfail = bus->pktgen_fail;
  2420. pktgen.mode = bus->pktgen_mode;
  2421. pktgen.stop = bus->pktgen_stop;
  2422. bcopy(&pktgen, arg, sizeof(pktgen));
  2423. return 0;
  2424. }
  2425. static int
  2426. dhdsdio_pktgen_set(dhd_bus_t *bus, uint8 *arg)
  2427. {
  2428. dhd_pktgen_t pktgen;
  2429. uint oldcnt, oldmode;
  2430. bcopy(arg, &pktgen, sizeof(pktgen));
  2431. if (pktgen.version != DHD_PKTGEN_VERSION)
  2432. return BCME_BADARG;
  2433. oldcnt = bus->pktgen_count;
  2434. oldmode = bus->pktgen_mode;
  2435. bus->pktgen_freq = pktgen.freq;
  2436. bus->pktgen_count = pktgen.count;
  2437. bus->pktgen_print = pktgen.print;
  2438. bus->pktgen_total = pktgen.total;
  2439. bus->pktgen_minlen = pktgen.minlen;
  2440. bus->pktgen_maxlen = pktgen.maxlen;
  2441. bus->pktgen_mode = pktgen.mode;
  2442. bus->pktgen_stop = pktgen.stop;
  2443. bus->pktgen_tick = bus->pktgen_ptick = 0;
  2444. bus->pktgen_prev_time = jiffies;
  2445. bus->pktgen_len = MAX(bus->pktgen_len, bus->pktgen_minlen);
  2446. bus->pktgen_len = MIN(bus->pktgen_len, bus->pktgen_maxlen);
  2447. /* Clear counts for a new pktgen (mode change, or was stopped) */
  2448. if (bus->pktgen_count && (!oldcnt || oldmode != bus->pktgen_mode)) {
  2449. bus->pktgen_sent = bus->pktgen_prev_sent = bus->pktgen_rcvd = 0;
  2450. bus->pktgen_prev_rcvd = bus->pktgen_fail = 0;
  2451. }
  2452. return 0;
  2453. }
  2454. #endif /* SDTEST */
  2455. static void
  2456. dhdsdio_devram_remap(dhd_bus_t *bus, bool val)
  2457. {
  2458. uint8 enable, protect, remap;
  2459. si_socdevram(bus->sih, FALSE, &enable, &protect, &remap);
  2460. remap = val ? TRUE : FALSE;
  2461. si_socdevram(bus->sih, TRUE, &enable, &protect, &remap);
  2462. }
  2463. static int
  2464. dhdsdio_membytes(dhd_bus_t *bus, bool write, uint32 address, uint8 *data, uint size)
  2465. {
  2466. int bcmerror = 0;
  2467. uint32 sdaddr;
  2468. uint dsize;
  2469. /* In remap mode, adjust address beyond socram and redirect
  2470. * to devram at SOCDEVRAM_BP_ADDR since remap address > orig_ramsize
  2471. * is not backplane accessible
  2472. */
  2473. if (REMAP_ENAB(bus) && REMAP_ISADDR(bus, address)) {
  2474. address -= bus->orig_ramsize;
  2475. address += SOCDEVRAM_BP_ADDR;
  2476. }
  2477. /* Determine initial transfer parameters */
  2478. sdaddr = address & SBSDIO_SB_OFT_ADDR_MASK;
  2479. if ((sdaddr + size) & SBSDIO_SBWINDOW_MASK)
  2480. dsize = (SBSDIO_SB_OFT_ADDR_LIMIT - sdaddr);
  2481. else
  2482. dsize = size;
  2483. /* Set the backplane window to include the start address */
  2484. if ((bcmerror = dhdsdio_set_siaddr_window(bus, address))) {
  2485. DHD_ERROR(("%s: window change failed\n", __FUNCTION__));
  2486. goto xfer_done;
  2487. }
  2488. /* Do the transfer(s) */
  2489. while (size) {
  2490. DHD_INFO(("%s: %s %d bytes at offset 0x%08x in window 0x%08x\n",
  2491. __FUNCTION__, (write ? "write" : "read"), dsize, sdaddr,
  2492. (address & SBSDIO_SBWINDOW_MASK)));
  2493. if ((bcmerror = bcmsdh_rwdata(bus->sdh, write, sdaddr, data, dsize))) {
  2494. DHD_ERROR(("%s: membytes transfer failed\n", __FUNCTION__));
  2495. break;
  2496. }
  2497. /* Adjust for next transfer (if any) */
  2498. if ((size -= dsize)) {
  2499. data += dsize;
  2500. address += dsize;
  2501. if ((bcmerror = dhdsdio_set_siaddr_window(bus, address))) {
  2502. DHD_ERROR(("%s: window change failed\n", __FUNCTION__));
  2503. break;
  2504. }
  2505. sdaddr = 0;
  2506. dsize = MIN(SBSDIO_SB_OFT_ADDR_LIMIT, size);
  2507. }
  2508. }
  2509. xfer_done:
  2510. /* Return the window to backplane enumeration space for core access */
  2511. if (dhdsdio_set_siaddr_window(bus, bcmsdh_cur_sbwad(bus->sdh))) {
  2512. DHD_ERROR(("%s: FAILED to set window back to 0x%x\n", __FUNCTION__,
  2513. bcmsdh_cur_sbwad(bus->sdh)));
  2514. }
  2515. return bcmerror;
  2516. }
  2517. #ifdef DHD_DEBUG
  2518. static int
  2519. dhdsdio_readshared(dhd_bus_t *bus, sdpcm_shared_t *sh)
  2520. {
  2521. uint32 addr;
  2522. int rv, i;
  2523. uint32 shaddr = 0;
  2524. if (CHIPID(bus->sih->chip) == BCM43430_CHIP_ID && !dhdsdio_sr_cap(bus))
  2525. bus->srmemsize = 0;
  2526. shaddr = bus->dongle_ram_base + bus->ramsize - 4;
  2527. i = 0;
  2528. do {
  2529. /* Read last word in memory to determine address of sdpcm_shared structure */
  2530. if ((rv = dhdsdio_membytes(bus, FALSE, shaddr, (uint8 *)&addr, 4)) < 0)
  2531. return rv;
  2532. addr = ltoh32(addr);
  2533. DHD_INFO(("sdpcm_shared address 0x%08X\n", addr));
  2534. /*
  2535. * Check if addr is valid.
  2536. * NVRAM length at the end of memory should have been overwritten.
  2537. */
  2538. if (addr == 0 || ((~addr >> 16) & 0xffff) == (addr & 0xffff)) {
  2539. if ((bus->srmemsize > 0) && (i++ == 0)) {
  2540. shaddr -= bus->srmemsize;
  2541. } else {
  2542. DHD_ERROR(("%s: address (0x%08x) of sdpcm_shared invalid\n",
  2543. __FUNCTION__, addr));
  2544. return BCME_ERROR;
  2545. }
  2546. } else
  2547. break;
  2548. } while (i < 2);
  2549. /* Read hndrte_shared structure */
  2550. if ((rv = dhdsdio_membytes(bus, FALSE, addr, (uint8 *)sh, sizeof(sdpcm_shared_t))) < 0)
  2551. return rv;
  2552. /* Endianness */
  2553. sh->flags = ltoh32(sh->flags);
  2554. sh->trap_addr = ltoh32(sh->trap_addr);
  2555. sh->assert_exp_addr = ltoh32(sh->assert_exp_addr);
  2556. sh->assert_file_addr = ltoh32(sh->assert_file_addr);
  2557. sh->assert_line = ltoh32(sh->assert_line);
  2558. sh->console_addr = ltoh32(sh->console_addr);
  2559. sh->msgtrace_addr = ltoh32(sh->msgtrace_addr);
  2560. if ((sh->flags & SDPCM_SHARED_VERSION_MASK) == 3 && SDPCM_SHARED_VERSION == 1)
  2561. return BCME_OK;
  2562. if ((sh->flags & SDPCM_SHARED_VERSION_MASK) != SDPCM_SHARED_VERSION) {
  2563. DHD_ERROR(("%s: sdpcm_shared version %d in dhd "
  2564. "is different than sdpcm_shared version %d in dongle\n",
  2565. __FUNCTION__, SDPCM_SHARED_VERSION,
  2566. sh->flags & SDPCM_SHARED_VERSION_MASK));
  2567. return BCME_ERROR;
  2568. }
  2569. return BCME_OK;
  2570. }
  2571. #define CONSOLE_LINE_MAX 192
  2572. static int
  2573. dhdsdio_readconsole(dhd_bus_t *bus)
  2574. {
  2575. dhd_console_t *c = &bus->console;
  2576. uint8 line[CONSOLE_LINE_MAX], ch;
  2577. uint32 n, idx, addr;
  2578. int rv;
  2579. /* Don't do anything until FWREADY updates console address */
  2580. if (bus->console_addr == 0)
  2581. return 0;
  2582. if (!KSO_ENAB(bus))
  2583. return 0;
  2584. /* Read console log struct */
  2585. addr = bus->console_addr + OFFSETOF(hndrte_cons_t, log);
  2586. if ((rv = dhdsdio_membytes(bus, FALSE, addr, (uint8 *)&c->log, sizeof(c->log))) < 0)
  2587. return rv;
  2588. /* Allocate console buffer (one time only) */
  2589. if (c->buf == NULL) {
  2590. c->bufsize = ltoh32(c->log.buf_size);
  2591. if ((c->buf = MALLOC(bus->dhd->osh, c->bufsize)) == NULL)
  2592. return BCME_NOMEM;
  2593. }
  2594. idx = ltoh32(c->log.idx);
  2595. /* Protect against corrupt value */
  2596. if (idx > c->bufsize)
  2597. return BCME_ERROR;
  2598. /* Skip reading the console buffer if the index pointer has not moved */
  2599. if (idx == c->last)
  2600. return BCME_OK;
  2601. /* Read the console buffer */
  2602. addr = ltoh32(c->log.buf);
  2603. if ((rv = dhdsdio_membytes(bus, FALSE, addr, c->buf, c->bufsize)) < 0)
  2604. return rv;
  2605. while (c->last != idx) {
  2606. for (n = 0; n < CONSOLE_LINE_MAX - 2; n++) {
  2607. if (c->last == idx) {
  2608. /* This would output a partial line. Instead, back up
  2609. * the buffer pointer and output this line next time around.
  2610. */
  2611. if (c->last >= n)
  2612. c->last -= n;
  2613. else
  2614. c->last = c->bufsize - n;
  2615. goto break2;
  2616. }
  2617. ch = c->buf[c->last];
  2618. c->last = (c->last + 1) % c->bufsize;
  2619. if (ch == '\n')
  2620. break;
  2621. line[n] = ch;
  2622. }
  2623. if (n > 0) {
  2624. if (line[n - 1] == '\r')
  2625. n--;
  2626. line[n] = 0;
  2627. printf("CONSOLE: %s\n", line);
  2628. #ifdef LOG_INTO_TCPDUMP
  2629. dhd_sendup_log(bus->dhd, line, n);
  2630. #endif /* LOG_INTO_TCPDUMP */
  2631. }
  2632. }
  2633. break2:
  2634. return BCME_OK;
  2635. }
  2636. static int
  2637. dhdsdio_checkdied(dhd_bus_t *bus, char *data, uint size)
  2638. {
  2639. int bcmerror = 0;
  2640. uint msize = 512;
  2641. char *mbuffer = NULL;
  2642. char *console_buffer = NULL;
  2643. uint maxstrlen = 256;
  2644. char *str = NULL;
  2645. trap_t tr;
  2646. sdpcm_shared_t sdpcm_shared;
  2647. struct bcmstrbuf strbuf;
  2648. uint32 console_ptr, console_size, console_index;
  2649. uint8 line[CONSOLE_LINE_MAX], ch;
  2650. uint32 n, i, addr;
  2651. int rv;
  2652. DHD_TRACE(("%s: Enter\n", __FUNCTION__));
  2653. if (DHD_NOCHECKDIED_ON())
  2654. return 0;
  2655. if (data == NULL) {
  2656. /*
  2657. * Called after a rx ctrl timeout. "data" is NULL.
  2658. * allocate memory to trace the trap or assert.
  2659. */
  2660. size = msize;
  2661. mbuffer = data = MALLOC(bus->dhd->osh, msize);
  2662. if (mbuffer == NULL) {
  2663. DHD_ERROR(("%s: MALLOC(%d) failed \n", __FUNCTION__, msize));
  2664. bcmerror = BCME_NOMEM;
  2665. goto done;
  2666. }
  2667. }
  2668. if ((str = MALLOC(bus->dhd->osh, maxstrlen)) == NULL) {
  2669. DHD_ERROR(("%s: MALLOC(%d) failed \n", __FUNCTION__, maxstrlen));
  2670. bcmerror = BCME_NOMEM;
  2671. goto done;
  2672. }
  2673. if ((bcmerror = dhdsdio_readshared(bus, &sdpcm_shared)) < 0)
  2674. goto done;
  2675. bcm_binit(&strbuf, data, size);
  2676. bcm_bprintf(&strbuf, "msgtrace address : 0x%08X\nconsole address : 0x%08X\n",
  2677. sdpcm_shared.msgtrace_addr, sdpcm_shared.console_addr);
  2678. if ((sdpcm_shared.flags & SDPCM_SHARED_ASSERT_BUILT) == 0) {
  2679. /* NOTE: Misspelled assert is intentional - DO NOT FIX.
  2680. * (Avoids conflict with real asserts for programmatic parsing of output.)
  2681. */
  2682. bcm_bprintf(&strbuf, "Assrt not built in dongle\n");
  2683. }
  2684. if ((sdpcm_shared.flags & (SDPCM_SHARED_ASSERT|SDPCM_SHARED_TRAP)) == 0) {
  2685. /* NOTE: Misspelled assert is intentional - DO NOT FIX.
  2686. * (Avoids conflict with real asserts for programmatic parsing of output.)
  2687. */
  2688. bcm_bprintf(&strbuf, "No trap%s in dongle",
  2689. (sdpcm_shared.flags & SDPCM_SHARED_ASSERT_BUILT)
  2690. ?"/assrt" :"");
  2691. } else {
  2692. if (sdpcm_shared.flags & SDPCM_SHARED_ASSERT) {
  2693. /* Download assert */
  2694. bcm_bprintf(&strbuf, "Dongle assert");
  2695. if (sdpcm_shared.assert_exp_addr != 0) {
  2696. str[0] = '\0';
  2697. if ((bcmerror = dhdsdio_membytes(bus, FALSE,
  2698. sdpcm_shared.assert_exp_addr,
  2699. (uint8 *)str, maxstrlen)) < 0)
  2700. goto done;
  2701. str[maxstrlen - 1] = '\0';
  2702. bcm_bprintf(&strbuf, " expr \"%s\"", str);
  2703. }
  2704. if (sdpcm_shared.assert_file_addr != 0) {
  2705. str[0] = '\0';
  2706. if ((bcmerror = dhdsdio_membytes(bus, FALSE,
  2707. sdpcm_shared.assert_file_addr,
  2708. (uint8 *)str, maxstrlen)) < 0)
  2709. goto done;
  2710. str[maxstrlen - 1] = '\0';
  2711. bcm_bprintf(&strbuf, " file \"%s\"", str);
  2712. }
  2713. bcm_bprintf(&strbuf, " line %d ", sdpcm_shared.assert_line);
  2714. }
  2715. if (sdpcm_shared.flags & SDPCM_SHARED_TRAP) {
  2716. bus->dhd->dongle_trap_occured = TRUE;
  2717. if ((bcmerror = dhdsdio_membytes(bus, FALSE,
  2718. sdpcm_shared.trap_addr,
  2719. (uint8*)&tr, sizeof(trap_t))) < 0)
  2720. goto done;
  2721. bcm_bprintf(&strbuf,
  2722. "Dongle trap type 0x%x @ epc 0x%x, cpsr 0x%x, spsr 0x%x, sp 0x%x,"
  2723. "lp 0x%x, rpc 0x%x Trap offset 0x%x, "
  2724. "r0 0x%x, r1 0x%x, r2 0x%x, r3 0x%x, "
  2725. "r4 0x%x, r5 0x%x, r6 0x%x, r7 0x%x\n\n",
  2726. ltoh32(tr.type), ltoh32(tr.epc), ltoh32(tr.cpsr), ltoh32(tr.spsr),
  2727. ltoh32(tr.r13), ltoh32(tr.r14), ltoh32(tr.pc),
  2728. ltoh32(sdpcm_shared.trap_addr),
  2729. ltoh32(tr.r0), ltoh32(tr.r1), ltoh32(tr.r2), ltoh32(tr.r3),
  2730. ltoh32(tr.r4), ltoh32(tr.r5), ltoh32(tr.r6), ltoh32(tr.r7));
  2731. addr = sdpcm_shared.console_addr + OFFSETOF(hndrte_cons_t, log);
  2732. if ((rv = dhdsdio_membytes(bus, FALSE, addr,
  2733. (uint8 *)&console_ptr, sizeof(console_ptr))) < 0)
  2734. goto printbuf;
  2735. addr = sdpcm_shared.console_addr + OFFSETOF(hndrte_cons_t, log.buf_size);
  2736. if ((rv = dhdsdio_membytes(bus, FALSE, addr,
  2737. (uint8 *)&console_size, sizeof(console_size))) < 0)
  2738. goto printbuf;
  2739. addr = sdpcm_shared.console_addr + OFFSETOF(hndrte_cons_t, log.idx);
  2740. if ((rv = dhdsdio_membytes(bus, FALSE, addr,
  2741. (uint8 *)&console_index, sizeof(console_index))) < 0)
  2742. goto printbuf;
  2743. console_ptr = ltoh32(console_ptr);
  2744. console_size = ltoh32(console_size);
  2745. console_index = ltoh32(console_index);
  2746. if (console_size > CONSOLE_BUFFER_MAX ||
  2747. !(console_buffer = MALLOC(bus->dhd->osh, console_size)))
  2748. goto printbuf;
  2749. if ((rv = dhdsdio_membytes(bus, FALSE, console_ptr,
  2750. (uint8 *)console_buffer, console_size)) < 0)
  2751. goto printbuf;
  2752. for (i = 0, n = 0; i < console_size; i += n + 1) {
  2753. for (n = 0; n < CONSOLE_LINE_MAX - 2; n++) {
  2754. ch = console_buffer[(console_index + i + n) % console_size];
  2755. if (ch == '\n')
  2756. break;
  2757. line[n] = ch;
  2758. }
  2759. if (n > 0) {
  2760. if (line[n - 1] == '\r')
  2761. n--;
  2762. line[n] = 0;
  2763. /* Don't use DHD_ERROR macro since we print
  2764. * a lot of information quickly. The macro
  2765. * will truncate a lot of the printfs
  2766. */
  2767. if (dhd_msg_level & DHD_ERROR_VAL)
  2768. printf("CONSOLE: %s\n", line);
  2769. }
  2770. }
  2771. }
  2772. }
  2773. printbuf:
  2774. if (sdpcm_shared.flags & (SDPCM_SHARED_ASSERT | SDPCM_SHARED_TRAP)) {
  2775. DHD_ERROR(("%s: %s\n", __FUNCTION__, strbuf.origbuf));
  2776. }
  2777. done:
  2778. if (mbuffer)
  2779. MFREE(bus->dhd->osh, mbuffer, msize);
  2780. if (str)
  2781. MFREE(bus->dhd->osh, str, maxstrlen);
  2782. if (console_buffer)
  2783. MFREE(bus->dhd->osh, console_buffer, console_size);
  2784. return bcmerror;
  2785. }
  2786. #endif /* #ifdef DHD_DEBUG */
  2787. int
  2788. dhdsdio_downloadvars(dhd_bus_t *bus, void *arg, int len)
  2789. {
  2790. int bcmerror = BCME_OK;
  2791. #ifdef KEEP_JP_REGREV
  2792. char *tmpbuf;
  2793. uint tmpidx;
  2794. #endif /* KEEP_JP_REGREV */
  2795. DHD_TRACE(("%s: Enter\n", __FUNCTION__));
  2796. /* Basic sanity checks */
  2797. if (bus->dhd->up) {
  2798. bcmerror = BCME_NOTDOWN;
  2799. goto err;
  2800. }
  2801. if (!len) {
  2802. bcmerror = BCME_BUFTOOSHORT;
  2803. goto err;
  2804. }
  2805. /* Free the old ones and replace with passed variables */
  2806. if (bus->vars)
  2807. MFREE(bus->dhd->osh, bus->vars, bus->varsz);
  2808. bus->vars = MALLOC(bus->dhd->osh, len);
  2809. bus->varsz = bus->vars ? len : 0;
  2810. if (bus->vars == NULL) {
  2811. bcmerror = BCME_NOMEM;
  2812. goto err;
  2813. }
  2814. /* Copy the passed variables, which should include the terminating double-null */
  2815. bcopy(arg, bus->vars, bus->varsz);
  2816. #ifdef KEEP_JP_REGREV
  2817. if (bus->vars != NULL && bus->varsz > 0) {
  2818. char *pos = NULL;
  2819. tmpbuf = MALLOCZ(bus->dhd->osh, bus->varsz + 1);
  2820. if (tmpbuf == NULL) {
  2821. goto err;
  2822. }
  2823. memcpy(tmpbuf, bus->vars, bus->varsz);
  2824. for (tmpidx = 0; tmpidx < bus->varsz; tmpidx++) {
  2825. if (tmpbuf[tmpidx] == 0) {
  2826. tmpbuf[tmpidx] = '\n';
  2827. }
  2828. }
  2829. bus->dhd->vars_ccode[0] = 0;
  2830. bus->dhd->vars_regrev = 0;
  2831. if ((pos = strstr(tmpbuf, "ccode"))) {
  2832. sscanf(pos, "ccode=%s\n", bus->dhd->vars_ccode);
  2833. }
  2834. if ((pos = strstr(tmpbuf, "regrev"))) {
  2835. sscanf(pos, "regrev=%u\n", &(bus->dhd->vars_regrev));
  2836. }
  2837. MFREE(bus->dhd->osh, tmpbuf, bus->varsz + 1);
  2838. }
  2839. #endif /* KEEP_JP_REGREV */
  2840. err:
  2841. return bcmerror;
  2842. }
  2843. #ifdef DHD_DEBUG
  2844. #define CC_PLL_CHIPCTRL_SERIAL_ENAB (1 << 24)
  2845. #define CC_CHIPCTRL_JTAG_SEL (1 << 3)
  2846. #define CC_CHIPCTRL_GPIO_SEL (0x3)
  2847. #define CC_PLL_CHIPCTRL_SERIAL_ENAB_4334 (1 << 28)
  2848. static int
  2849. dhd_serialconsole(dhd_bus_t *bus, bool set, bool enable, int *bcmerror)
  2850. {
  2851. int int_val;
  2852. uint32 addr, data, uart_enab = 0;
  2853. uint32 jtag_sel = CC_CHIPCTRL_JTAG_SEL;
  2854. uint32 gpio_sel = CC_CHIPCTRL_GPIO_SEL;
  2855. addr = SI_ENUM_BASE + OFFSETOF(chipcregs_t, chipcontrol_addr);
  2856. data = SI_ENUM_BASE + OFFSETOF(chipcregs_t, chipcontrol_data);
  2857. *bcmerror = 0;
  2858. bcmsdh_reg_write(bus->sdh, addr, 4, 1);
  2859. if (bcmsdh_regfail(bus->sdh)) {
  2860. *bcmerror = BCME_SDIO_ERROR;
  2861. return -1;
  2862. }
  2863. int_val = bcmsdh_reg_read(bus->sdh, data, 4);
  2864. if (bcmsdh_regfail(bus->sdh)) {
  2865. *bcmerror = BCME_SDIO_ERROR;
  2866. return -1;
  2867. }
  2868. if (bus->sih->chip == BCM4330_CHIP_ID) {
  2869. uart_enab = CC_PLL_CHIPCTRL_SERIAL_ENAB;
  2870. }
  2871. else if (bus->sih->chip == BCM4334_CHIP_ID ||
  2872. bus->sih->chip == BCM43340_CHIP_ID ||
  2873. bus->sih->chip == BCM43341_CHIP_ID ||
  2874. bus->sih->chip == BCM43342_CHIP_ID ||
  2875. 0) {
  2876. if (enable) {
  2877. /* Moved to PMU chipcontrol 1 from 4330 */
  2878. int_val &= ~gpio_sel;
  2879. int_val |= jtag_sel;
  2880. } else {
  2881. int_val |= gpio_sel;
  2882. int_val &= ~jtag_sel;
  2883. }
  2884. uart_enab = CC_PLL_CHIPCTRL_SERIAL_ENAB_4334;
  2885. }
  2886. if (!set)
  2887. return (int_val & uart_enab);
  2888. if (enable)
  2889. int_val |= uart_enab;
  2890. else
  2891. int_val &= ~uart_enab;
  2892. bcmsdh_reg_write(bus->sdh, data, 4, int_val);
  2893. if (bcmsdh_regfail(bus->sdh)) {
  2894. *bcmerror = BCME_SDIO_ERROR;
  2895. return -1;
  2896. }
  2897. if (bus->sih->chip == BCM4330_CHIP_ID) {
  2898. uint32 chipcontrol;
  2899. addr = SI_ENUM_BASE + OFFSETOF(chipcregs_t, chipcontrol);
  2900. chipcontrol = bcmsdh_reg_read(bus->sdh, addr, 4);
  2901. chipcontrol &= ~jtag_sel;
  2902. if (enable) {
  2903. chipcontrol |= jtag_sel;
  2904. chipcontrol &= ~gpio_sel;
  2905. }
  2906. bcmsdh_reg_write(bus->sdh, addr, 4, chipcontrol);
  2907. }
  2908. return (int_val & uart_enab);
  2909. }
  2910. #endif
  2911. static int
  2912. dhdsdio_doiovar(dhd_bus_t *bus, const bcm_iovar_t *vi, uint32 actionid, const char *name,
  2913. void *params, int plen, void *arg, int len, int val_size)
  2914. {
  2915. int bcmerror = 0;
  2916. int32 int_val = 0;
  2917. bool bool_val = 0;
  2918. DHD_TRACE(("%s: Enter, action %d name %s params %p plen %d arg %p len %d val_size %d\n",
  2919. __FUNCTION__, actionid, name, params, plen, arg, len, val_size));
  2920. if ((bcmerror = bcm_iovar_lencheck(vi, arg, len, IOV_ISSET(actionid))) != 0)
  2921. goto exit;
  2922. if (plen >= (int)sizeof(int_val))
  2923. bcopy(params, &int_val, sizeof(int_val));
  2924. bool_val = (int_val != 0) ? TRUE : FALSE;
  2925. /* Some ioctls use the bus */
  2926. dhd_os_sdlock(bus->dhd);
  2927. /* Check if dongle is in reset. If so, only allow DEVRESET iovars */
  2928. if (bus->dhd->dongle_reset && !(actionid == IOV_SVAL(IOV_DEVRESET) ||
  2929. actionid == IOV_GVAL(IOV_DEVRESET))) {
  2930. bcmerror = BCME_NOTREADY;
  2931. goto exit;
  2932. }
  2933. /*
  2934. * Special handling for keepSdioOn: New SDIO Wake-up Mechanism
  2935. */
  2936. if ((vi->varid == IOV_KSO) && (IOV_ISSET(actionid))) {
  2937. dhdsdio_clk_kso_iovar(bus, bool_val);
  2938. goto exit;
  2939. } else if ((vi->varid == IOV_DEVSLEEP) && (IOV_ISSET(actionid))) {
  2940. {
  2941. dhdsdio_clk_devsleep_iovar(bus, bool_val);
  2942. if (!SLPAUTO_ENAB(bus) && (bool_val == FALSE) && (bus->ipend)) {
  2943. DHD_ERROR(("INT pending in devsleep 1, dpc_sched: %d\n",
  2944. bus->dpc_sched));
  2945. if (!bus->dpc_sched) {
  2946. bus->dpc_sched = TRUE;
  2947. dhd_sched_dpc(bus->dhd);
  2948. }
  2949. }
  2950. }
  2951. goto exit;
  2952. }
  2953. /* Handle sleep stuff before any clock mucking */
  2954. if (vi->varid == IOV_SLEEP) {
  2955. if (IOV_ISSET(actionid)) {
  2956. bcmerror = dhdsdio_bussleep(bus, bool_val);
  2957. } else {
  2958. int_val = (int32)bus->sleeping;
  2959. bcopy(&int_val, arg, val_size);
  2960. }
  2961. goto exit;
  2962. }
  2963. /* Request clock to allow SDIO accesses */
  2964. if (!bus->dhd->dongle_reset) {
  2965. BUS_WAKE(bus);
  2966. dhdsdio_clkctl(bus, CLK_AVAIL, FALSE);
  2967. }
  2968. switch (actionid) {
  2969. case IOV_GVAL(IOV_INTR):
  2970. int_val = (int32)bus->intr;
  2971. bcopy(&int_val, arg, val_size);
  2972. break;
  2973. case IOV_SVAL(IOV_INTR):
  2974. bus->intr = bool_val;
  2975. bus->intdis = FALSE;
  2976. if (bus->dhd->up) {
  2977. if (bus->intr) {
  2978. DHD_INTR(("%s: enable SDIO device interrupts\n", __FUNCTION__));
  2979. bcmsdh_intr_enable(bus->sdh);
  2980. } else {
  2981. DHD_INTR(("%s: disable SDIO interrupts\n", __FUNCTION__));
  2982. bcmsdh_intr_disable(bus->sdh);
  2983. }
  2984. }
  2985. break;
  2986. case IOV_GVAL(IOV_POLLRATE):
  2987. int_val = (int32)bus->pollrate;
  2988. bcopy(&int_val, arg, val_size);
  2989. break;
  2990. case IOV_SVAL(IOV_POLLRATE):
  2991. bus->pollrate = (uint)int_val;
  2992. bus->poll = (bus->pollrate != 0);
  2993. break;
  2994. case IOV_GVAL(IOV_IDLETIME):
  2995. int_val = bus->idletime;
  2996. bcopy(&int_val, arg, val_size);
  2997. break;
  2998. case IOV_SVAL(IOV_IDLETIME):
  2999. if ((int_val < 0) && (int_val != DHD_IDLE_IMMEDIATE)) {
  3000. bcmerror = BCME_BADARG;
  3001. } else {
  3002. bus->idletime = int_val;
  3003. }
  3004. break;
  3005. case IOV_GVAL(IOV_IDLECLOCK):
  3006. int_val = (int32)bus->idleclock;
  3007. bcopy(&int_val, arg, val_size);
  3008. break;
  3009. case IOV_SVAL(IOV_IDLECLOCK):
  3010. bus->idleclock = int_val;
  3011. break;
  3012. case IOV_GVAL(IOV_SD1IDLE):
  3013. int_val = (int32)sd1idle;
  3014. bcopy(&int_val, arg, val_size);
  3015. break;
  3016. case IOV_SVAL(IOV_SD1IDLE):
  3017. sd1idle = bool_val;
  3018. break;
  3019. case IOV_SVAL(IOV_MEMBYTES):
  3020. case IOV_GVAL(IOV_MEMBYTES):
  3021. {
  3022. uint32 address;
  3023. uint size, dsize;
  3024. uint8 *data;
  3025. bool set = (actionid == IOV_SVAL(IOV_MEMBYTES));
  3026. ASSERT(plen >= 2*sizeof(int));
  3027. address = (uint32)int_val;
  3028. bcopy((char *)params + sizeof(int_val), &int_val, sizeof(int_val));
  3029. size = (uint)int_val;
  3030. /* Do some validation */
  3031. dsize = set ? plen - (2 * sizeof(int)) : len;
  3032. if (dsize < size) {
  3033. DHD_ERROR(("%s: error on %s membytes, addr 0x%08x size %d dsize %d\n",
  3034. __FUNCTION__, (set ? "set" : "get"), address, size, dsize));
  3035. bcmerror = BCME_BADARG;
  3036. break;
  3037. }
  3038. DHD_INFO(("%s: Request to %s %d bytes at address 0x%08x\n", __FUNCTION__,
  3039. (set ? "write" : "read"), size, address));
  3040. /* check if CR4 */
  3041. if (si_setcore(bus->sih, ARMCR4_CORE_ID, 0)) {
  3042. /*
  3043. * If address is start of RAM (i.e. a downloaded image),
  3044. * store the reset instruction to be written in 0
  3045. */
  3046. if (set && address == bus->dongle_ram_base) {
  3047. bus->resetinstr = *(((uint32*)params) + 2);
  3048. }
  3049. } else {
  3050. /* If we know about SOCRAM, check for a fit */
  3051. if ((bus->orig_ramsize) &&
  3052. ((address > bus->orig_ramsize) || (address + size > bus->orig_ramsize)))
  3053. {
  3054. uint8 enable, protect, remap;
  3055. si_socdevram(bus->sih, FALSE, &enable, &protect, &remap);
  3056. if (!enable || protect) {
  3057. DHD_ERROR(("%s: ramsize 0x%08x doesn't have %d bytes at 0x%08x\n",
  3058. __FUNCTION__, bus->orig_ramsize, size, address));
  3059. DHD_ERROR(("%s: socram enable %d, protect %d\n",
  3060. __FUNCTION__, enable, protect));
  3061. bcmerror = BCME_BADARG;
  3062. break;
  3063. }
  3064. if (!REMAP_ENAB(bus) && (address >= SOCDEVRAM_ARM_ADDR)) {
  3065. uint32 devramsize = si_socdevram_size(bus->sih);
  3066. if ((address < SOCDEVRAM_ARM_ADDR) ||
  3067. (address + size > (SOCDEVRAM_ARM_ADDR + devramsize))) {
  3068. DHD_ERROR(("%s: bad address 0x%08x, size 0x%08x\n",
  3069. __FUNCTION__, address, size));
  3070. DHD_ERROR(("%s: socram range 0x%08x,size 0x%08x\n",
  3071. __FUNCTION__, SOCDEVRAM_ARM_ADDR, devramsize));
  3072. bcmerror = BCME_BADARG;
  3073. break;
  3074. }
  3075. /* move it such that address is real now */
  3076. address -= SOCDEVRAM_ARM_ADDR;
  3077. address += SOCDEVRAM_BP_ADDR;
  3078. DHD_INFO(("%s: Request to %s %d bytes @ Mapped address 0x%08x\n",
  3079. __FUNCTION__, (set ? "write" : "read"), size, address));
  3080. } else if (REMAP_ENAB(bus) && REMAP_ISADDR(bus, address) && remap) {
  3081. /* Can not access remap region while devram remap bit is set
  3082. * ROM content would be returned in this case
  3083. */
  3084. DHD_ERROR(("%s: Need to disable remap for address 0x%08x\n",
  3085. __FUNCTION__, address));
  3086. bcmerror = BCME_ERROR;
  3087. break;
  3088. }
  3089. }
  3090. }
  3091. /* Generate the actual data pointer */
  3092. data = set ? (uint8*)params + 2 * sizeof(int): (uint8*)arg;
  3093. /* Call to do the transfer */
  3094. bcmerror = dhdsdio_membytes(bus, set, address, data, size);
  3095. break;
  3096. }
  3097. case IOV_GVAL(IOV_RAMSIZE):
  3098. int_val = (int32)bus->ramsize;
  3099. bcopy(&int_val, arg, val_size);
  3100. break;
  3101. case IOV_GVAL(IOV_RAMSTART):
  3102. int_val = (int32)bus->dongle_ram_base;
  3103. bcopy(&int_val, arg, val_size);
  3104. break;
  3105. case IOV_GVAL(IOV_SDIOD_DRIVE):
  3106. int_val = (int32)dhd_sdiod_drive_strength;
  3107. bcopy(&int_val, arg, val_size);
  3108. break;
  3109. case IOV_SVAL(IOV_SDIOD_DRIVE):
  3110. dhd_sdiod_drive_strength = int_val;
  3111. si_sdiod_drive_strength_init(bus->sih, bus->dhd->osh, dhd_sdiod_drive_strength);
  3112. break;
  3113. case IOV_SVAL(IOV_SET_DOWNLOAD_STATE):
  3114. bcmerror = dhdsdio_download_state(bus, bool_val);
  3115. break;
  3116. case IOV_SVAL(IOV_SOCRAM_STATE):
  3117. bcmerror = dhdsdio_download_state(bus, bool_val);
  3118. break;
  3119. case IOV_SVAL(IOV_VARS):
  3120. bcmerror = dhdsdio_downloadvars(bus, arg, len);
  3121. break;
  3122. case IOV_GVAL(IOV_READAHEAD):
  3123. int_val = (int32)dhd_readahead;
  3124. bcopy(&int_val, arg, val_size);
  3125. break;
  3126. case IOV_SVAL(IOV_READAHEAD):
  3127. if (bool_val && !dhd_readahead)
  3128. bus->nextlen = 0;
  3129. dhd_readahead = bool_val;
  3130. break;
  3131. case IOV_GVAL(IOV_SDRXCHAIN):
  3132. int_val = (int32)bus->use_rxchain;
  3133. bcopy(&int_val, arg, val_size);
  3134. break;
  3135. case IOV_SVAL(IOV_SDRXCHAIN):
  3136. if (bool_val && !bus->sd_rxchain)
  3137. bcmerror = BCME_UNSUPPORTED;
  3138. else
  3139. bus->use_rxchain = bool_val;
  3140. break;
  3141. #ifndef BCMSPI
  3142. case IOV_GVAL(IOV_ALIGNCTL):
  3143. int_val = (int32)dhd_alignctl;
  3144. bcopy(&int_val, arg, val_size);
  3145. break;
  3146. case IOV_SVAL(IOV_ALIGNCTL):
  3147. dhd_alignctl = bool_val;
  3148. break;
  3149. #endif /* BCMSPI */
  3150. case IOV_GVAL(IOV_SDALIGN):
  3151. int_val = DHD_SDALIGN;
  3152. bcopy(&int_val, arg, val_size);
  3153. break;
  3154. #ifdef DHD_DEBUG
  3155. case IOV_GVAL(IOV_VARS):
  3156. if (bus->varsz < (uint)len)
  3157. bcopy(bus->vars, arg, bus->varsz);
  3158. else
  3159. bcmerror = BCME_BUFTOOSHORT;
  3160. break;
  3161. #endif /* DHD_DEBUG */
  3162. #ifdef DHD_DEBUG
  3163. case IOV_GVAL(IOV_SDREG):
  3164. {
  3165. sdreg_t *sd_ptr;
  3166. uint32 addr, size;
  3167. sd_ptr = (sdreg_t *)params;
  3168. addr = (uint32)((ulong)bus->regs + sd_ptr->offset);
  3169. size = sd_ptr->func;
  3170. int_val = (int32)bcmsdh_reg_read(bus->sdh, addr, size);
  3171. if (bcmsdh_regfail(bus->sdh))
  3172. bcmerror = BCME_SDIO_ERROR;
  3173. bcopy(&int_val, arg, sizeof(int32));
  3174. break;
  3175. }
  3176. case IOV_SVAL(IOV_SDREG):
  3177. {
  3178. sdreg_t *sd_ptr;
  3179. uint32 addr, size;
  3180. sd_ptr = (sdreg_t *)params;
  3181. addr = (uint32)((ulong)bus->regs + sd_ptr->offset);
  3182. size = sd_ptr->func;
  3183. bcmsdh_reg_write(bus->sdh, addr, size, sd_ptr->value);
  3184. if (bcmsdh_regfail(bus->sdh))
  3185. bcmerror = BCME_SDIO_ERROR;
  3186. break;
  3187. }
  3188. /* Same as above, but offset is not backplane (not SDIO core) */
  3189. case IOV_GVAL(IOV_SBREG):
  3190. {
  3191. sdreg_t sdreg;
  3192. uint32 addr, size;
  3193. bcopy(params, &sdreg, sizeof(sdreg));
  3194. addr = SI_ENUM_BASE + sdreg.offset;
  3195. size = sdreg.func;
  3196. int_val = (int32)bcmsdh_reg_read(bus->sdh, addr, size);
  3197. if (bcmsdh_regfail(bus->sdh))
  3198. bcmerror = BCME_SDIO_ERROR;
  3199. bcopy(&int_val, arg, sizeof(int32));
  3200. break;
  3201. }
  3202. case IOV_SVAL(IOV_SBREG):
  3203. {
  3204. sdreg_t sdreg;
  3205. uint32 addr, size;
  3206. bcopy(params, &sdreg, sizeof(sdreg));
  3207. addr = SI_ENUM_BASE + sdreg.offset;
  3208. size = sdreg.func;
  3209. bcmsdh_reg_write(bus->sdh, addr, size, sdreg.value);
  3210. if (bcmsdh_regfail(bus->sdh))
  3211. bcmerror = BCME_SDIO_ERROR;
  3212. break;
  3213. }
  3214. case IOV_GVAL(IOV_SDCIS):
  3215. {
  3216. *(char *)arg = 0;
  3217. bcmstrcat(arg, "\nFunc 0\n");
  3218. bcmsdh_cis_read(bus->sdh, 0x10, (uint8 *)arg + strlen(arg), SBSDIO_CIS_SIZE_LIMIT);
  3219. bcmstrcat(arg, "\nFunc 1\n");
  3220. bcmsdh_cis_read(bus->sdh, 0x11, (uint8 *)arg + strlen(arg), SBSDIO_CIS_SIZE_LIMIT);
  3221. bcmstrcat(arg, "\nFunc 2\n");
  3222. bcmsdh_cis_read(bus->sdh, 0x12, (uint8 *)arg + strlen(arg), SBSDIO_CIS_SIZE_LIMIT);
  3223. break;
  3224. }
  3225. case IOV_GVAL(IOV_FORCEEVEN):
  3226. int_val = (int32)forcealign;
  3227. bcopy(&int_val, arg, val_size);
  3228. break;
  3229. case IOV_SVAL(IOV_FORCEEVEN):
  3230. forcealign = bool_val;
  3231. break;
  3232. case IOV_GVAL(IOV_TXBOUND):
  3233. int_val = (int32)dhd_txbound;
  3234. bcopy(&int_val, arg, val_size);
  3235. break;
  3236. case IOV_SVAL(IOV_TXBOUND):
  3237. dhd_txbound = (uint)int_val;
  3238. break;
  3239. case IOV_GVAL(IOV_RXBOUND):
  3240. int_val = (int32)dhd_rxbound;
  3241. bcopy(&int_val, arg, val_size);
  3242. break;
  3243. case IOV_SVAL(IOV_RXBOUND):
  3244. dhd_rxbound = (uint)int_val;
  3245. break;
  3246. case IOV_GVAL(IOV_TXMINMAX):
  3247. int_val = (int32)dhd_txminmax;
  3248. bcopy(&int_val, arg, val_size);
  3249. break;
  3250. case IOV_SVAL(IOV_TXMINMAX):
  3251. dhd_txminmax = (uint)int_val;
  3252. break;
  3253. case IOV_GVAL(IOV_SERIALCONS):
  3254. int_val = dhd_serialconsole(bus, FALSE, 0, &bcmerror);
  3255. if (bcmerror != 0)
  3256. break;
  3257. bcopy(&int_val, arg, val_size);
  3258. break;
  3259. case IOV_SVAL(IOV_SERIALCONS):
  3260. dhd_serialconsole(bus, TRUE, bool_val, &bcmerror);
  3261. break;
  3262. #endif /* DHD_DEBUG */
  3263. #ifdef SDTEST
  3264. case IOV_GVAL(IOV_EXTLOOP):
  3265. int_val = (int32)bus->ext_loop;
  3266. bcopy(&int_val, arg, val_size);
  3267. break;
  3268. case IOV_SVAL(IOV_EXTLOOP):
  3269. bus->ext_loop = bool_val;
  3270. break;
  3271. case IOV_GVAL(IOV_PKTGEN):
  3272. bcmerror = dhdsdio_pktgen_get(bus, arg);
  3273. break;
  3274. case IOV_SVAL(IOV_PKTGEN):
  3275. bcmerror = dhdsdio_pktgen_set(bus, arg);
  3276. break;
  3277. #endif /* SDTEST */
  3278. #if defined(USE_SDIOFIFO_IOVAR)
  3279. case IOV_GVAL(IOV_WATERMARK):
  3280. int_val = (int32)watermark;
  3281. bcopy(&int_val, arg, val_size);
  3282. break;
  3283. case IOV_SVAL(IOV_WATERMARK):
  3284. watermark = (uint)int_val;
  3285. watermark = (watermark > SBSDIO_WATERMARK_MASK) ? SBSDIO_WATERMARK_MASK : watermark;
  3286. DHD_ERROR(("Setting watermark as 0x%x.\n", watermark));
  3287. bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1, SBSDIO_WATERMARK, (uint8)watermark, NULL);
  3288. break;
  3289. case IOV_GVAL(IOV_MESBUSYCTRL):
  3290. int_val = (int32)mesbusyctrl;
  3291. bcopy(&int_val, arg, val_size);
  3292. break;
  3293. case IOV_SVAL(IOV_MESBUSYCTRL):
  3294. mesbusyctrl = (uint)int_val;
  3295. mesbusyctrl = (mesbusyctrl > SBSDIO_MESBUSYCTRL_MASK)
  3296. ? SBSDIO_MESBUSYCTRL_MASK : mesbusyctrl;
  3297. DHD_ERROR(("Setting mesbusyctrl as 0x%x.\n", mesbusyctrl));
  3298. bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_MESBUSYCTRL,
  3299. ((uint8)mesbusyctrl | 0x80), NULL);
  3300. break;
  3301. #endif
  3302. case IOV_GVAL(IOV_DONGLEISOLATION):
  3303. int_val = bus->dhd->dongle_isolation;
  3304. bcopy(&int_val, arg, val_size);
  3305. break;
  3306. case IOV_SVAL(IOV_DONGLEISOLATION):
  3307. bus->dhd->dongle_isolation = bool_val;
  3308. break;
  3309. case IOV_SVAL(IOV_DEVRESET):
  3310. DHD_TRACE(("%s: Called set IOV_DEVRESET=%d dongle_reset=%d busstate=%d\n",
  3311. __FUNCTION__, bool_val, bus->dhd->dongle_reset,
  3312. bus->dhd->busstate));
  3313. ASSERT(bus->dhd->osh);
  3314. /* ASSERT(bus->cl_devid); */
  3315. dhd_bus_devreset(bus->dhd, (uint8)bool_val);
  3316. break;
  3317. /*
  3318. * softap firmware is updated through module parameter or android private command
  3319. */
  3320. case IOV_GVAL(IOV_DEVRESET):
  3321. DHD_TRACE(("%s: Called get IOV_DEVRESET\n", __FUNCTION__));
  3322. /* Get its status */
  3323. int_val = (bool) bus->dhd->dongle_reset;
  3324. bcopy(&int_val, arg, val_size);
  3325. break;
  3326. case IOV_GVAL(IOV_KSO):
  3327. int_val = dhdsdio_sleepcsr_get(bus);
  3328. bcopy(&int_val, arg, val_size);
  3329. break;
  3330. case IOV_GVAL(IOV_DEVCAP):
  3331. int_val = dhdsdio_devcap_get(bus);
  3332. bcopy(&int_val, arg, val_size);
  3333. break;
  3334. case IOV_SVAL(IOV_DEVCAP):
  3335. dhdsdio_devcap_set(bus, (uint8) int_val);
  3336. break;
  3337. case IOV_GVAL(IOV_TXGLOMSIZE):
  3338. int_val = (int32)bus->txglomsize;
  3339. bcopy(&int_val, arg, val_size);
  3340. break;
  3341. case IOV_SVAL(IOV_TXGLOMSIZE):
  3342. if (int_val > SDPCM_MAXGLOM_SIZE) {
  3343. bcmerror = BCME_ERROR;
  3344. } else {
  3345. bus->txglomsize = (uint)int_val;
  3346. }
  3347. break;
  3348. case IOV_SVAL(IOV_HANGREPORT):
  3349. bus->dhd->hang_report = bool_val;
  3350. DHD_ERROR(("%s: Set hang_report as %d\n", __FUNCTION__, bus->dhd->hang_report));
  3351. break;
  3352. case IOV_GVAL(IOV_HANGREPORT):
  3353. int_val = (int32)bus->dhd->hang_report;
  3354. bcopy(&int_val, arg, val_size);
  3355. break;
  3356. case IOV_GVAL(IOV_TXINRX_THRES):
  3357. int_val = bus->txinrx_thres;
  3358. bcopy(&int_val, arg, val_size);
  3359. break;
  3360. case IOV_SVAL(IOV_TXINRX_THRES):
  3361. if (int_val < 0) {
  3362. bcmerror = BCME_BADARG;
  3363. } else {
  3364. bus->txinrx_thres = int_val;
  3365. }
  3366. break;
  3367. default:
  3368. bcmerror = BCME_UNSUPPORTED;
  3369. break;
  3370. }
  3371. exit:
  3372. if ((bus->idletime == DHD_IDLE_IMMEDIATE) && !bus->dpc_sched) {
  3373. bus->activity = FALSE;
  3374. dhdsdio_clkctl(bus, CLK_NONE, TRUE);
  3375. }
  3376. dhd_os_sdunlock(bus->dhd);
  3377. return bcmerror;
  3378. }
  3379. static int
  3380. dhdsdio_write_vars(dhd_bus_t *bus)
  3381. {
  3382. int bcmerror = 0;
  3383. uint32 varsize, phys_size;
  3384. uint32 varaddr;
  3385. uint8 *vbuffer;
  3386. uint32 varsizew;
  3387. #ifdef DHD_DEBUG
  3388. uint8 *nvram_ularray;
  3389. #endif /* DHD_DEBUG */
  3390. /* Even if there are no vars are to be written, we still need to set the ramsize. */
  3391. varsize = bus->varsz ? ROUNDUP(bus->varsz, 4) : 0;
  3392. varaddr = (bus->ramsize - 4) - varsize;
  3393. varaddr += bus->dongle_ram_base;
  3394. if (bus->vars) {
  3395. if ((bus->sih->buscoretype == SDIOD_CORE_ID) && (bus->sdpcmrev == 7)) {
  3396. if (((varaddr & 0x3C) == 0x3C) && (varsize > 4)) {
  3397. DHD_ERROR(("PR85623WAR in place\n"));
  3398. varsize += 4;
  3399. varaddr -= 4;
  3400. }
  3401. }
  3402. vbuffer = (uint8 *)MALLOC(bus->dhd->osh, varsize);
  3403. if (!vbuffer)
  3404. return BCME_NOMEM;
  3405. bzero(vbuffer, varsize);
  3406. bcopy(bus->vars, vbuffer, bus->varsz);
  3407. /* Write the vars list */
  3408. bcmerror = dhdsdio_membytes(bus, TRUE, varaddr, vbuffer, varsize);
  3409. #ifdef DHD_DEBUG
  3410. /* Verify NVRAM bytes */
  3411. DHD_INFO(("Compare NVRAM dl & ul; varsize=%d\n", varsize));
  3412. nvram_ularray = (uint8*)MALLOC(bus->dhd->osh, varsize);
  3413. if (!nvram_ularray) {
  3414. MFREE(bus->dhd->osh, vbuffer, varsize);
  3415. return BCME_NOMEM;
  3416. }
  3417. /* Upload image to verify downloaded contents. */
  3418. memset(nvram_ularray, 0xaa, varsize);
  3419. /* Read the vars list to temp buffer for comparison */
  3420. bcmerror = dhdsdio_membytes(bus, FALSE, varaddr, nvram_ularray, varsize);
  3421. if (bcmerror) {
  3422. DHD_ERROR(("%s: error %d on reading %d nvram bytes at 0x%08x\n",
  3423. __FUNCTION__, bcmerror, varsize, varaddr));
  3424. }
  3425. /* Compare the org NVRAM with the one read from RAM */
  3426. if (memcmp(vbuffer, nvram_ularray, varsize)) {
  3427. DHD_ERROR(("%s: Downloaded NVRAM image is corrupted.\n", __FUNCTION__));
  3428. } else
  3429. DHD_ERROR(("%s: Download, Upload and compare of NVRAM succeeded.\n",
  3430. __FUNCTION__));
  3431. MFREE(bus->dhd->osh, nvram_ularray, varsize);
  3432. #endif /* DHD_DEBUG */
  3433. MFREE(bus->dhd->osh, vbuffer, varsize);
  3434. }
  3435. phys_size = REMAP_ENAB(bus) ? bus->ramsize : bus->orig_ramsize;
  3436. phys_size += bus->dongle_ram_base;
  3437. /* adjust to the user specified RAM */
  3438. DHD_INFO(("Physical memory size: %d, usable memory size: %d\n",
  3439. phys_size, bus->ramsize));
  3440. DHD_INFO(("Vars are at %d, orig varsize is %d\n",
  3441. varaddr, varsize));
  3442. varsize = ((phys_size - 4) - varaddr);
  3443. /*
  3444. * Determine the length token:
  3445. * Varsize, converted to words, in lower 16-bits, checksum in upper 16-bits.
  3446. */
  3447. if (bcmerror) {
  3448. varsizew = 0;
  3449. } else {
  3450. varsizew = varsize / 4;
  3451. varsizew = (~varsizew << 16) | (varsizew & 0x0000FFFF);
  3452. varsizew = htol32(varsizew);
  3453. }
  3454. DHD_INFO(("New varsize is %d, length token=0x%08x\n", varsize, varsizew));
  3455. /* Write the length token to the last word */
  3456. bcmerror = dhdsdio_membytes(bus, TRUE, (phys_size - 4),
  3457. (uint8*)&varsizew, 4);
  3458. return bcmerror;
  3459. }
  3460. static int
  3461. dhdsdio_download_state(dhd_bus_t *bus, bool enter)
  3462. {
  3463. uint retries;
  3464. int bcmerror = 0;
  3465. int foundcr4 = 0;
  3466. if (!bus->sih)
  3467. return BCME_ERROR;
  3468. /* To enter download state, disable ARM and reset SOCRAM.
  3469. * To exit download state, simply reset ARM (default is RAM boot).
  3470. */
  3471. if (enter) {
  3472. bus->alp_only = TRUE;
  3473. if (!(si_setcore(bus->sih, ARM7S_CORE_ID, 0)) &&
  3474. !(si_setcore(bus->sih, ARMCM3_CORE_ID, 0))) {
  3475. if (si_setcore(bus->sih, ARMCR4_CORE_ID, 0)) {
  3476. foundcr4 = 1;
  3477. } else {
  3478. DHD_ERROR(("%s: Failed to find ARM core!\n", __FUNCTION__));
  3479. bcmerror = BCME_ERROR;
  3480. goto fail;
  3481. }
  3482. }
  3483. if (!foundcr4) {
  3484. si_core_disable(bus->sih, 0);
  3485. if (bcmsdh_regfail(bus->sdh)) {
  3486. bcmerror = BCME_SDIO_ERROR;
  3487. goto fail;
  3488. }
  3489. if (!(si_setcore(bus->sih, SOCRAM_CORE_ID, 0))) {
  3490. DHD_ERROR(("%s: Failed to find SOCRAM core!\n", __FUNCTION__));
  3491. bcmerror = BCME_ERROR;
  3492. goto fail;
  3493. }
  3494. si_core_reset(bus->sih, 0, 0);
  3495. if (bcmsdh_regfail(bus->sdh)) {
  3496. DHD_ERROR(("%s: Failure trying reset SOCRAM core?\n",
  3497. __FUNCTION__));
  3498. bcmerror = BCME_SDIO_ERROR;
  3499. goto fail;
  3500. }
  3501. /* Disable remap for download */
  3502. if (REMAP_ENAB(bus) && si_socdevram_remap_isenb(bus->sih))
  3503. dhdsdio_devram_remap(bus, FALSE);
  3504. if (CHIPID(bus->sih->chip) == BCM43430_CHIP_ID) {
  3505. /* Disabling Remap for SRAM_3 */
  3506. si_socram_set_bankpda(bus->sih, 0x3, 0x0);
  3507. }
  3508. /* Clear the top bit of memory */
  3509. if (bus->ramsize) {
  3510. uint32 zeros = 0;
  3511. if (dhdsdio_membytes(bus, TRUE, bus->ramsize - 4,
  3512. (uint8*)&zeros, 4) < 0) {
  3513. bcmerror = BCME_SDIO_ERROR;
  3514. goto fail;
  3515. }
  3516. }
  3517. } else {
  3518. /* For CR4,
  3519. * Halt ARM
  3520. * Remove ARM reset
  3521. * Read RAM base address [0x18_0000]
  3522. * [next] Download firmware
  3523. * [done at else] Populate the reset vector
  3524. * [done at else] Remove ARM halt
  3525. */
  3526. /* Halt ARM & remove reset */
  3527. si_core_reset(bus->sih, SICF_CPUHALT, SICF_CPUHALT);
  3528. }
  3529. } else {
  3530. if (!si_setcore(bus->sih, ARMCR4_CORE_ID, 0)) {
  3531. if (!(si_setcore(bus->sih, SOCRAM_CORE_ID, 0))) {
  3532. DHD_ERROR(("%s: Failed to find SOCRAM core!\n", __FUNCTION__));
  3533. bcmerror = BCME_ERROR;
  3534. goto fail;
  3535. }
  3536. if (!si_iscoreup(bus->sih)) {
  3537. DHD_ERROR(("%s: SOCRAM core is down after reset?\n", __FUNCTION__));
  3538. bcmerror = BCME_ERROR;
  3539. goto fail;
  3540. }
  3541. if ((bcmerror = dhdsdio_write_vars(bus))) {
  3542. DHD_ERROR(("%s: could not write vars to RAM\n", __FUNCTION__));
  3543. goto fail;
  3544. }
  3545. /* Enable remap before ARM reset but after vars.
  3546. * No backplane access in remap mode
  3547. */
  3548. if (REMAP_ENAB(bus) && !si_socdevram_remap_isenb(bus->sih))
  3549. dhdsdio_devram_remap(bus, TRUE);
  3550. if (!si_setcore(bus->sih, PCMCIA_CORE_ID, 0) &&
  3551. !si_setcore(bus->sih, SDIOD_CORE_ID, 0)) {
  3552. DHD_ERROR(("%s: Can't change back to SDIO core?\n", __FUNCTION__));
  3553. bcmerror = BCME_ERROR;
  3554. goto fail;
  3555. }
  3556. W_SDREG(0xFFFFFFFF, &bus->regs->intstatus, retries);
  3557. if (!(si_setcore(bus->sih, ARM7S_CORE_ID, 0)) &&
  3558. !(si_setcore(bus->sih, ARMCM3_CORE_ID, 0))) {
  3559. DHD_ERROR(("%s: Failed to find ARM core!\n", __FUNCTION__));
  3560. bcmerror = BCME_ERROR;
  3561. goto fail;
  3562. }
  3563. } else {
  3564. /* cr4 has no socram, but tcm's */
  3565. /* write vars */
  3566. if ((bcmerror = dhdsdio_write_vars(bus))) {
  3567. DHD_ERROR(("%s: could not write vars to RAM\n", __FUNCTION__));
  3568. goto fail;
  3569. }
  3570. if (!si_setcore(bus->sih, PCMCIA_CORE_ID, 0) &&
  3571. !si_setcore(bus->sih, SDIOD_CORE_ID, 0)) {
  3572. DHD_ERROR(("%s: Can't change back to SDIO core?\n", __FUNCTION__));
  3573. bcmerror = BCME_ERROR;
  3574. goto fail;
  3575. }
  3576. W_SDREG(0xFFFFFFFF, &bus->regs->intstatus, retries);
  3577. /* switch back to arm core again */
  3578. if (!(si_setcore(bus->sih, ARMCR4_CORE_ID, 0))) {
  3579. DHD_ERROR(("%s: Failed to find ARM CR4 core!\n", __FUNCTION__));
  3580. bcmerror = BCME_ERROR;
  3581. goto fail;
  3582. }
  3583. /* write address 0 with reset instruction */
  3584. bcmerror = dhdsdio_membytes(bus, TRUE, 0,
  3585. (uint8 *)&bus->resetinstr, sizeof(bus->resetinstr));
  3586. /* now remove reset and halt and continue to run CR4 */
  3587. }
  3588. si_core_reset(bus->sih, 0, 0);
  3589. if (bcmsdh_regfail(bus->sdh)) {
  3590. DHD_ERROR(("%s: Failure trying to reset ARM core?\n", __FUNCTION__));
  3591. bcmerror = BCME_SDIO_ERROR;
  3592. goto fail;
  3593. }
  3594. /* Allow HT Clock now that the ARM is running. */
  3595. bus->alp_only = FALSE;
  3596. bus->dhd->busstate = DHD_BUS_LOAD;
  3597. }
  3598. fail:
  3599. /* Always return to SDIOD core */
  3600. if (!si_setcore(bus->sih, PCMCIA_CORE_ID, 0))
  3601. si_setcore(bus->sih, SDIOD_CORE_ID, 0);
  3602. return bcmerror;
  3603. }
  3604. int
  3605. dhd_bus_iovar_op(dhd_pub_t *dhdp, const char *name,
  3606. void *params, int plen, void *arg, int len, bool set)
  3607. {
  3608. dhd_bus_t *bus = dhdp->bus;
  3609. const bcm_iovar_t *vi = NULL;
  3610. int bcmerror = 0;
  3611. int val_size;
  3612. uint32 actionid;
  3613. DHD_TRACE(("%s: Enter\n", __FUNCTION__));
  3614. ASSERT(name);
  3615. ASSERT(len >= 0);
  3616. /* Get MUST have return space */
  3617. ASSERT(set || (arg && len));
  3618. /* Set does NOT take qualifiers */
  3619. ASSERT(!set || (!params && !plen));
  3620. /* Look up var locally; if not found pass to host driver */
  3621. if ((vi = bcm_iovar_lookup(dhdsdio_iovars, name)) == NULL) {
  3622. dhd_os_sdlock(bus->dhd);
  3623. BUS_WAKE(bus);
  3624. /* Turn on clock in case SD command needs backplane */
  3625. dhdsdio_clkctl(bus, CLK_AVAIL, FALSE);
  3626. bcmerror = bcmsdh_iovar_op(bus->sdh, name, params, plen, arg, len, set);
  3627. /* Check for bus configuration changes of interest */
  3628. /* If it was divisor change, read the new one */
  3629. if (set && strcmp(name, "sd_divisor") == 0) {
  3630. if (bcmsdh_iovar_op(bus->sdh, "sd_divisor", NULL, 0,
  3631. &bus->sd_divisor, sizeof(int32), FALSE) != BCME_OK) {
  3632. bus->sd_divisor = -1;
  3633. DHD_ERROR(("%s: fail on %s get\n", __FUNCTION__, name));
  3634. } else {
  3635. DHD_INFO(("%s: noted %s update, value now %d\n",
  3636. __FUNCTION__, name, bus->sd_divisor));
  3637. }
  3638. }
  3639. /* If it was a mode change, read the new one */
  3640. if (set && strcmp(name, "sd_mode") == 0) {
  3641. if (bcmsdh_iovar_op(bus->sdh, "sd_mode", NULL, 0,
  3642. &bus->sd_mode, sizeof(int32), FALSE) != BCME_OK) {
  3643. bus->sd_mode = -1;
  3644. DHD_ERROR(("%s: fail on %s get\n", __FUNCTION__, name));
  3645. } else {
  3646. DHD_INFO(("%s: noted %s update, value now %d\n",
  3647. __FUNCTION__, name, bus->sd_mode));
  3648. }
  3649. }
  3650. /* Similar check for blocksize change */
  3651. if (set && strcmp(name, "sd_blocksize") == 0) {
  3652. int32 fnum = 2;
  3653. if (bcmsdh_iovar_op(bus->sdh, "sd_blocksize", &fnum, sizeof(int32),
  3654. &bus->blocksize, sizeof(int32), FALSE) != BCME_OK) {
  3655. bus->blocksize = 0;
  3656. DHD_ERROR(("%s: fail on %s get\n", __FUNCTION__, "sd_blocksize"));
  3657. } else {
  3658. DHD_INFO(("%s: noted %s update, value now %d\n",
  3659. __FUNCTION__, "sd_blocksize", bus->blocksize));
  3660. dhdsdio_tune_fifoparam(bus);
  3661. }
  3662. }
  3663. bus->roundup = MIN(max_roundup, bus->blocksize);
  3664. if ((bus->idletime == DHD_IDLE_IMMEDIATE) && !bus->dpc_sched) {
  3665. bus->activity = FALSE;
  3666. dhdsdio_clkctl(bus, CLK_NONE, TRUE);
  3667. }
  3668. dhd_os_sdunlock(bus->dhd);
  3669. goto exit;
  3670. }
  3671. DHD_CTL(("%s: %s %s, len %d plen %d\n", __FUNCTION__,
  3672. name, (set ? "set" : "get"), len, plen));
  3673. /* set up 'params' pointer in case this is a set command so that
  3674. * the convenience int and bool code can be common to set and get
  3675. */
  3676. if (params == NULL) {
  3677. params = arg;
  3678. plen = len;
  3679. }
  3680. if (vi->type == IOVT_VOID)
  3681. val_size = 0;
  3682. else if (vi->type == IOVT_BUFFER)
  3683. val_size = len;
  3684. else
  3685. /* all other types are integer sized */
  3686. val_size = sizeof(int);
  3687. actionid = set ? IOV_SVAL(vi->varid) : IOV_GVAL(vi->varid);
  3688. bcmerror = dhdsdio_doiovar(bus, vi, actionid, name, params, plen, arg, len, val_size);
  3689. exit:
  3690. return bcmerror;
  3691. }
  3692. void
  3693. dhd_bus_stop(struct dhd_bus *bus, bool enforce_mutex)
  3694. {
  3695. osl_t *osh;
  3696. uint32 local_hostintmask;
  3697. uint8 saveclk;
  3698. uint retries;
  3699. int err;
  3700. bool wlfc_enabled = FALSE;
  3701. if (!bus->dhd)
  3702. return;
  3703. osh = bus->dhd->osh;
  3704. DHD_TRACE(("%s: Enter\n", __FUNCTION__));
  3705. bcmsdh_waitlockfree(bus->sdh);
  3706. if (enforce_mutex)
  3707. dhd_os_sdlock(bus->dhd);
  3708. if ((bus->dhd->busstate == DHD_BUS_DOWN) || bus->dhd->hang_was_sent) {
  3709. /* if Firmware already hangs disbale any interrupt */
  3710. bus->dhd->busstate = DHD_BUS_DOWN;
  3711. bus->hostintmask = 0;
  3712. bcmsdh_intr_disable(bus->sdh);
  3713. } else {
  3714. BUS_WAKE(bus);
  3715. /* Change our idea of bus state */
  3716. bus->dhd->busstate = DHD_BUS_DOWN;
  3717. if (KSO_ENAB(bus)) {
  3718. /* Enable clock for device interrupts */
  3719. dhdsdio_clkctl(bus, CLK_AVAIL, FALSE);
  3720. /* Disable and clear interrupts at the chip level also */
  3721. W_SDREG(0, &bus->regs->hostintmask, retries);
  3722. local_hostintmask = bus->hostintmask;
  3723. bus->hostintmask = 0;
  3724. /* Force clocks on backplane to be sure F2 interrupt propagates */
  3725. saveclk = bcmsdh_cfg_read(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR, &err);
  3726. if (!err) {
  3727. bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR,
  3728. (saveclk | SBSDIO_FORCE_HT), &err);
  3729. }
  3730. if (err) {
  3731. DHD_ERROR(("%s: Failed to force clock for F2: err %d\n",
  3732. __FUNCTION__, err));
  3733. }
  3734. /* Turn off the bus (F2), free any pending packets */
  3735. DHD_INTR(("%s: disable SDIO interrupts\n", __FUNCTION__));
  3736. bcmsdh_intr_disable(bus->sdh);
  3737. #ifndef BCMSPI
  3738. bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_0, SDIOD_CCCR_IOEN, SDIO_FUNC_ENABLE_1, NULL);
  3739. #endif /* !BCMSPI */
  3740. /* Clear any pending interrupts now that F2 is disabled */
  3741. W_SDREG(local_hostintmask, &bus->regs->intstatus, retries);
  3742. }
  3743. /* Turn off the backplane clock (only) */
  3744. dhdsdio_clkctl(bus, CLK_SDONLY, FALSE);
  3745. }
  3746. #ifdef PROP_TXSTATUS
  3747. wlfc_enabled = (dhd_wlfc_cleanup_txq(bus->dhd, NULL, 0) != WLFC_UNSUPPORTED);
  3748. #endif
  3749. if (!wlfc_enabled) {
  3750. #ifdef DHDTCPACK_SUPPRESS
  3751. /* Clean tcp_ack_info_tbl in order to prevent access to flushed pkt,
  3752. * when there is a newly coming packet from network stack.
  3753. */
  3754. dhd_tcpack_info_tbl_clean(bus->dhd);
  3755. #endif /* DHDTCPACK_SUPPRESS */
  3756. /* Clear the data packet queues */
  3757. pktq_flush(osh, &bus->txq, TRUE, NULL, 0);
  3758. }
  3759. /* Clear any held glomming stuff */
  3760. if (bus->glomd)
  3761. PKTFREE(osh, bus->glomd, FALSE);
  3762. if (bus->glom)
  3763. PKTFREE(osh, bus->glom, FALSE);
  3764. bus->glom = bus->glomd = NULL;
  3765. /* Clear rx control and wake any waiters */
  3766. bus->rxlen = 0;
  3767. dhd_os_ioctl_resp_wake(bus->dhd);
  3768. /* Reset some F2 state stuff */
  3769. bus->rxskip = FALSE;
  3770. bus->tx_seq = bus->rx_seq = 0;
  3771. bus->tx_max = 4;
  3772. if (enforce_mutex)
  3773. dhd_os_sdunlock(bus->dhd);
  3774. }
  3775. #if defined(BCMSDIOH_TXGLOM) && defined(BCMSDIOH_STD)
  3776. extern uint sd_txglom;
  3777. #endif
  3778. void
  3779. dhd_txglom_enable(dhd_pub_t *dhdp, bool enable)
  3780. {
  3781. /* can't enable host txglom by default, some platforms have no
  3782. * (or crappy) ADMA support and txglom will cause kernel assertions (e.g.
  3783. * panda board)
  3784. */
  3785. dhd_bus_t *bus = dhdp->bus;
  3786. #ifdef BCMSDIOH_TXGLOM
  3787. char buf[256];
  3788. uint32 rxglom;
  3789. int32 ret;
  3790. DHD_TRACE(("%s: Enter\n", __FUNCTION__));
  3791. #ifdef BCMSDIOH_STD
  3792. if (enable)
  3793. enable = sd_txglom;
  3794. #endif /* BCMSDIOH_STD */
  3795. if (enable) {
  3796. rxglom = 1;
  3797. memset(buf, 0, sizeof(buf));
  3798. bcm_mkiovar("bus:rxglom", (void *)&rxglom, 4, buf, sizeof(buf));
  3799. ret = dhd_wl_ioctl_cmd(dhdp, WLC_SET_VAR, buf, sizeof(buf), TRUE, 0);
  3800. if (ret >= 0)
  3801. bus->txglom_enable = TRUE;
  3802. else {
  3803. #ifdef BCMSDIOH_STD
  3804. sd_txglom = 0;
  3805. #endif /* BCMSDIOH_STD */
  3806. bus->txglom_enable = FALSE;
  3807. }
  3808. } else
  3809. #endif /* BCMSDIOH_TXGLOM */
  3810. bus->txglom_enable = FALSE;
  3811. }
  3812. int
  3813. dhd_bus_init(dhd_pub_t *dhdp, bool enforce_mutex)
  3814. {
  3815. dhd_bus_t *bus = dhdp->bus;
  3816. dhd_timeout_t tmo;
  3817. uint retries = 0;
  3818. uint8 ready, enable;
  3819. int err, ret = 0;
  3820. #ifdef BCMSPI
  3821. uint32 dstatus = 0; /* gSPI device-status bits */
  3822. #else /* BCMSPI */
  3823. uint8 saveclk;
  3824. #endif /* BCMSPI */
  3825. DHD_TRACE(("%s: Enter\n", __FUNCTION__));
  3826. ASSERT(bus->dhd);
  3827. if (!bus->dhd)
  3828. return 0;
  3829. if (enforce_mutex)
  3830. dhd_os_sdlock(bus->dhd);
  3831. /* Make sure backplane clock is on, needed to generate F2 interrupt */
  3832. dhdsdio_clkctl(bus, CLK_AVAIL, FALSE);
  3833. if (bus->clkstate != CLK_AVAIL) {
  3834. DHD_ERROR(("%s: clock state is wrong. state = %d\n", __FUNCTION__, bus->clkstate));
  3835. ret = -1;
  3836. goto exit;
  3837. }
  3838. #ifdef BCMSPI
  3839. /* fake "ready" for spi, wake-wlan would have already enabled F1 and F2 */
  3840. ready = (SDIO_FUNC_ENABLE_1 | SDIO_FUNC_ENABLE_2);
  3841. enable = 0;
  3842. /* Give the dongle some time to do its thing and set IOR2 */
  3843. dhd_timeout_start(&tmo, WAIT_F2RXFIFORDY * WAIT_F2RXFIFORDY_DELAY * 1000);
  3844. while (!enable && !dhd_timeout_expired(&tmo)) {
  3845. dstatus = bcmsdh_cfg_read_word(bus->sdh, SDIO_FUNC_0, SPID_STATUS_REG, NULL);
  3846. if (dstatus & STATUS_F2_RX_READY)
  3847. enable = TRUE;
  3848. }
  3849. if (enable) {
  3850. DHD_ERROR(("Took %u usec before dongle is ready\n", tmo.elapsed));
  3851. enable = ready;
  3852. } else {
  3853. DHD_ERROR(("dstatus when timed out on f2-fifo not ready = 0x%x\n", dstatus));
  3854. DHD_ERROR(("Waited %u usec, dongle is not ready\n", tmo.elapsed));
  3855. ret = -1;
  3856. goto exit;
  3857. }
  3858. #else /* !BCMSPI */
  3859. /* Force clocks on backplane to be sure F2 interrupt propagates */
  3860. saveclk = bcmsdh_cfg_read(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR, &err);
  3861. if (!err) {
  3862. bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR,
  3863. (saveclk | SBSDIO_FORCE_HT), &err);
  3864. }
  3865. if (err) {
  3866. DHD_ERROR(("%s: Failed to force clock for F2: err %d\n", __FUNCTION__, err));
  3867. ret = -1;
  3868. goto exit;
  3869. }
  3870. /* Enable function 2 (frame transfers) */
  3871. W_SDREG((SDPCM_PROT_VERSION << SMB_DATA_VERSION_SHIFT),
  3872. &bus->regs->tosbmailboxdata, retries);
  3873. enable = (SDIO_FUNC_ENABLE_1 | SDIO_FUNC_ENABLE_2);
  3874. bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_0, SDIOD_CCCR_IOEN, enable, NULL);
  3875. /* Give the dongle some time to do its thing and set IOR2 */
  3876. dhd_timeout_start(&tmo, DHD_WAIT_F2RDY * 1000);
  3877. ready = 0;
  3878. while (ready != enable && !dhd_timeout_expired(&tmo))
  3879. ready = bcmsdh_cfg_read(bus->sdh, SDIO_FUNC_0, SDIOD_CCCR_IORDY, NULL);
  3880. #endif /* !BCMSPI */
  3881. DHD_ERROR(("%s: enable 0x%02x, ready 0x%02x (waited %uus)\n",
  3882. __FUNCTION__, enable, ready, tmo.elapsed));
  3883. /* If F2 successfully enabled, set core and enable interrupts */
  3884. if (ready == enable) {
  3885. /* Make sure we're talking to the core. */
  3886. if (!(bus->regs = si_setcore(bus->sih, PCMCIA_CORE_ID, 0)))
  3887. bus->regs = si_setcore(bus->sih, SDIOD_CORE_ID, 0);
  3888. ASSERT(bus->regs != NULL);
  3889. /* Set up the interrupt mask and enable interrupts */
  3890. bus->hostintmask = HOSTINTMASK;
  3891. /* corerev 4 could use the newer interrupt logic to detect the frames */
  3892. #ifndef BCMSPI
  3893. if ((bus->sih->buscoretype == SDIOD_CORE_ID) && (bus->sdpcmrev == 4) &&
  3894. (bus->rxint_mode != SDIO_DEVICE_HMB_RXINT)) {
  3895. bus->hostintmask &= ~I_HMB_FRAME_IND;
  3896. bus->hostintmask |= I_XMTDATA_AVAIL;
  3897. }
  3898. #endif /* BCMSPI */
  3899. W_SDREG(bus->hostintmask, &bus->regs->hostintmask, retries);
  3900. if (bus->sih->buscorerev < 15) {
  3901. bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1, SBSDIO_WATERMARK,
  3902. (uint8)watermark, &err);
  3903. }
  3904. /* Set bus state according to enable result */
  3905. dhdp->busstate = DHD_BUS_DATA;
  3906. /* bcmsdh_intr_unmask(bus->sdh); */
  3907. bus->intdis = FALSE;
  3908. if (bus->intr) {
  3909. DHD_INTR(("%s: enable SDIO device interrupts\n", __FUNCTION__));
  3910. #ifndef BCMSPI_ANDROID
  3911. bcmsdh_intr_enable(bus->sdh);
  3912. #endif /* !BCMSPI_ANDROID */
  3913. } else {
  3914. DHD_INTR(("%s: disable SDIO interrupts\n", __FUNCTION__));
  3915. bcmsdh_intr_disable(bus->sdh);
  3916. }
  3917. }
  3918. #ifndef BCMSPI
  3919. else {
  3920. /* Disable F2 again */
  3921. enable = SDIO_FUNC_ENABLE_1;
  3922. bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_0, SDIOD_CCCR_IOEN, enable, NULL);
  3923. }
  3924. if (dhdsdio_sr_cap(bus)) {
  3925. dhdsdio_sr_init(bus);
  3926. /* Masking the chip active interrupt permanantly */
  3927. bus->hostintmask &= ~I_CHIPACTIVE;
  3928. W_SDREG(bus->hostintmask, &bus->regs->hostintmask, retries);
  3929. DHD_INFO(("%s: disable I_CHIPACTIVE in hostintmask[0x%08x]\n",
  3930. __FUNCTION__, bus->hostintmask));
  3931. }
  3932. else
  3933. bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1,
  3934. SBSDIO_FUNC1_CHIPCLKCSR, saveclk, &err);
  3935. #endif /* !BCMSPI */
  3936. /* If we didn't come up, turn off backplane clock */
  3937. if (dhdp->busstate != DHD_BUS_DATA)
  3938. dhdsdio_clkctl(bus, CLK_NONE, FALSE);
  3939. #if defined(CUSTOMER_HW4) && defined(BCMHOST_XTAL_PU_TIME_MOD)
  3940. #ifdef BCM4330_CHIP
  3941. bcmsdh_reg_write(bus->sdh, 0x18000620, 2, 11);
  3942. bcmsdh_reg_write(bus->sdh, 0x18000628, 4, 0x0000F801);
  3943. #endif
  3944. #ifdef BCM4334_CHIP
  3945. bcmsdh_reg_write(bus->sdh, 0x18000620, 2, 11);
  3946. bcmsdh_reg_write(bus->sdh, 0x18000628, 4, 0x00F80001);
  3947. #endif
  3948. #ifdef BCM43430_CHIP
  3949. bcmsdh_reg_write(bus->sdh, 0x18000620, 2, 12);
  3950. bcmsdh_reg_write(bus->sdh, 0x18000628, 4, 0x00A60001);
  3951. #endif
  3952. #endif /* defined(CUSTOMER_HW4) && defined(BCMHOST_XTAL_PU_TIME_MOD */
  3953. exit:
  3954. if (enforce_mutex)
  3955. dhd_os_sdunlock(bus->dhd);
  3956. return ret;
  3957. }
  3958. static void
  3959. dhdsdio_rxfail(dhd_bus_t *bus, bool abort, bool rtx)
  3960. {
  3961. bcmsdh_info_t *sdh = bus->sdh;
  3962. sdpcmd_regs_t *regs = bus->regs;
  3963. uint retries = 0;
  3964. uint16 lastrbc;
  3965. uint8 hi, lo;
  3966. int err;
  3967. DHD_ERROR(("%s: %sterminate frame%s\n", __FUNCTION__,
  3968. (abort ? "abort command, " : ""), (rtx ? ", send NAK" : "")));
  3969. if (!KSO_ENAB(bus)) {
  3970. DHD_ERROR(("%s: Device asleep\n", __FUNCTION__));
  3971. return;
  3972. }
  3973. if (abort) {
  3974. bcmsdh_abort(sdh, SDIO_FUNC_2);
  3975. }
  3976. bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_FRAMECTRL, SFC_RF_TERM, &err);
  3977. if (err) {
  3978. DHD_ERROR(("%s: SBSDIO_FUNC1_FRAMECTRL cmd err\n", __FUNCTION__));
  3979. goto fail;
  3980. }
  3981. bus->f1regdata++;
  3982. /* Wait until the packet has been flushed (device/FIFO stable) */
  3983. for (lastrbc = retries = 0xffff; retries > 0; retries--) {
  3984. hi = bcmsdh_cfg_read(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_RFRAMEBCHI, NULL);
  3985. lo = bcmsdh_cfg_read(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_RFRAMEBCLO, &err);
  3986. if (err) {
  3987. DHD_ERROR(("%s: SBSDIO_FUNC1_RFAMEBCLO cmd err\n", __FUNCTION__));
  3988. goto fail;
  3989. }
  3990. bus->f1regdata += 2;
  3991. if ((hi == 0) && (lo == 0))
  3992. break;
  3993. if ((hi > (lastrbc >> 8)) && (lo > (lastrbc & 0x00ff))) {
  3994. DHD_ERROR(("%s: count growing: last 0x%04x now 0x%04x\n",
  3995. __FUNCTION__, lastrbc, ((hi << 8) + lo)));
  3996. }
  3997. lastrbc = (hi << 8) + lo;
  3998. }
  3999. if (!retries) {
  4000. DHD_ERROR(("%s: count never zeroed: last 0x%04x\n", __FUNCTION__, lastrbc));
  4001. } else {
  4002. DHD_INFO(("%s: flush took %d iterations\n", __FUNCTION__, (0xffff - retries)));
  4003. }
  4004. if (rtx) {
  4005. bus->rxrtx++;
  4006. W_SDREG(SMB_NAK, &regs->tosbmailbox, retries);
  4007. bus->f1regdata++;
  4008. if (retries <= retry_limit) {
  4009. bus->rxskip = TRUE;
  4010. }
  4011. }
  4012. /* Clear partial in any case */
  4013. bus->nextlen = 0;
  4014. fail:
  4015. /* If we can't reach the device, signal failure */
  4016. if (err || bcmsdh_regfail(sdh))
  4017. bus->dhd->busstate = DHD_BUS_DOWN;
  4018. }
  4019. static void
  4020. dhdsdio_read_control(dhd_bus_t *bus, uint8 *hdr, uint len, uint doff)
  4021. {
  4022. bcmsdh_info_t *sdh = bus->sdh;
  4023. uint rdlen, pad;
  4024. int sdret;
  4025. DHD_TRACE(("%s: Enter\n", __FUNCTION__));
  4026. /* Control data already received in aligned rxctl */
  4027. if ((bus->bus == SPI_BUS) && (!bus->usebufpool))
  4028. goto gotpkt;
  4029. ASSERT(bus->rxbuf);
  4030. /* Set rxctl for frame (w/optional alignment) */
  4031. bus->rxctl = bus->rxbuf;
  4032. if (dhd_alignctl) {
  4033. bus->rxctl += firstread;
  4034. if ((pad = ((uintptr)bus->rxctl % DHD_SDALIGN)))
  4035. bus->rxctl += (DHD_SDALIGN - pad);
  4036. bus->rxctl -= firstread;
  4037. }
  4038. ASSERT(bus->rxctl >= bus->rxbuf);
  4039. /* Copy the already-read portion over */
  4040. bcopy(hdr, bus->rxctl, firstread);
  4041. if (len <= firstread)
  4042. goto gotpkt;
  4043. /* Copy the full data pkt in gSPI case and process ioctl. */
  4044. if (bus->bus == SPI_BUS) {
  4045. bcopy(hdr, bus->rxctl, len);
  4046. goto gotpkt;
  4047. }
  4048. /* Raise rdlen to next SDIO block to avoid tail command */
  4049. rdlen = len - firstread;
  4050. if (bus->roundup && bus->blocksize && (rdlen > bus->blocksize)) {
  4051. pad = bus->blocksize - (rdlen % bus->blocksize);
  4052. if ((pad <= bus->roundup) && (pad < bus->blocksize) &&
  4053. ((len + pad) < bus->dhd->maxctl))
  4054. rdlen += pad;
  4055. } else if (rdlen % DHD_SDALIGN) {
  4056. rdlen += DHD_SDALIGN - (rdlen % DHD_SDALIGN);
  4057. }
  4058. /* Satisfy length-alignment requirements */
  4059. if (forcealign && (rdlen & (ALIGNMENT - 1)))
  4060. rdlen = ROUNDUP(rdlen, ALIGNMENT);
  4061. /* Drop if the read is too big or it exceeds our maximum */
  4062. if ((rdlen + firstread) > bus->dhd->maxctl) {
  4063. DHD_ERROR(("%s: %d-byte control read exceeds %d-byte buffer\n",
  4064. __FUNCTION__, rdlen, bus->dhd->maxctl));
  4065. bus->dhd->rx_errors++;
  4066. dhdsdio_rxfail(bus, FALSE, FALSE);
  4067. goto done;
  4068. }
  4069. if ((len - doff) > bus->dhd->maxctl) {
  4070. DHD_ERROR(("%s: %d-byte ctl frame (%d-byte ctl data) exceeds %d-byte limit\n",
  4071. __FUNCTION__, len, (len - doff), bus->dhd->maxctl));
  4072. bus->dhd->rx_errors++; bus->rx_toolong++;
  4073. dhdsdio_rxfail(bus, FALSE, FALSE);
  4074. goto done;
  4075. }
  4076. /* Read remainder of frame body into the rxctl buffer */
  4077. sdret = dhd_bcmsdh_recv_buf(bus, bcmsdh_cur_sbwad(sdh), SDIO_FUNC_2, F2SYNC,
  4078. (bus->rxctl + firstread), rdlen, NULL, NULL, NULL);
  4079. bus->f2rxdata++;
  4080. ASSERT(sdret != BCME_PENDING);
  4081. /* Control frame failures need retransmission */
  4082. if (sdret < 0) {
  4083. DHD_ERROR(("%s: read %d control bytes failed: %d\n", __FUNCTION__, rdlen, sdret));
  4084. bus->rxc_errors++; /* dhd.rx_ctlerrs is higher level */
  4085. dhdsdio_rxfail(bus, TRUE, TRUE);
  4086. goto done;
  4087. }
  4088. gotpkt:
  4089. #ifdef DHD_DEBUG
  4090. if (DHD_BYTES_ON() && DHD_CTL_ON()) {
  4091. prhex("RxCtrl", bus->rxctl, len);
  4092. }
  4093. #endif
  4094. /* Point to valid data and indicate its length */
  4095. bus->rxctl += doff;
  4096. bus->rxlen = len - doff;
  4097. done:
  4098. /* Awake any waiters */
  4099. dhd_os_ioctl_resp_wake(bus->dhd);
  4100. }
  4101. int
  4102. dhd_process_pkt_reorder_info(dhd_pub_t *dhd, uchar *reorder_info_buf, uint reorder_info_len,
  4103. void **pkt, uint32 *pkt_count);
  4104. static uint8
  4105. dhdsdio_rxglom(dhd_bus_t *bus, uint8 rxseq)
  4106. {
  4107. uint16 dlen, totlen;
  4108. uint8 *dptr, num = 0;
  4109. uint16 sublen, check;
  4110. void *pfirst, *plast, *pnext;
  4111. void * list_tail[DHD_MAX_IFS] = { NULL };
  4112. void * list_head[DHD_MAX_IFS] = { NULL };
  4113. uint8 idx;
  4114. osl_t *osh = bus->dhd->osh;
  4115. int errcode;
  4116. uint8 chan, seq, doff, sfdoff;
  4117. uint8 txmax;
  4118. uchar reorder_info_buf[WLHOST_REORDERDATA_TOTLEN];
  4119. uint reorder_info_len;
  4120. int ifidx = 0;
  4121. bool usechain = bus->use_rxchain;
  4122. /* If packets, issue read(s) and send up packet chain */
  4123. /* Return sequence numbers consumed? */
  4124. DHD_TRACE(("dhdsdio_rxglom: start: glomd %p glom %p\n", bus->glomd, bus->glom));
  4125. /* If there's a descriptor, generate the packet chain */
  4126. if (bus->glomd) {
  4127. dhd_os_sdlock_rxq(bus->dhd);
  4128. pfirst = plast = pnext = NULL;
  4129. dlen = (uint16)PKTLEN(osh, bus->glomd);
  4130. dptr = PKTDATA(osh, bus->glomd);
  4131. if (!dlen || (dlen & 1)) {
  4132. DHD_ERROR(("%s: bad glomd len (%d), ignore descriptor\n",
  4133. __FUNCTION__, dlen));
  4134. dlen = 0;
  4135. }
  4136. for (totlen = num = 0; dlen; num++) {
  4137. /* Get (and move past) next length */
  4138. sublen = ltoh16_ua(dptr);
  4139. dlen -= sizeof(uint16);
  4140. dptr += sizeof(uint16);
  4141. if ((sublen < SDPCM_HDRLEN) ||
  4142. ((num == 0) && (sublen < (2 * SDPCM_HDRLEN)))) {
  4143. DHD_ERROR(("%s: descriptor len %d bad: %d\n",
  4144. __FUNCTION__, num, sublen));
  4145. pnext = NULL;
  4146. break;
  4147. }
  4148. if (sublen % DHD_SDALIGN) {
  4149. DHD_ERROR(("%s: sublen %d not a multiple of %d\n",
  4150. __FUNCTION__, sublen, DHD_SDALIGN));
  4151. usechain = FALSE;
  4152. }
  4153. totlen += sublen;
  4154. /* For last frame, adjust read len so total is a block multiple */
  4155. if (!dlen) {
  4156. sublen += (ROUNDUP(totlen, bus->blocksize) - totlen);
  4157. totlen = ROUNDUP(totlen, bus->blocksize);
  4158. }
  4159. /* Allocate/chain packet for next subframe */
  4160. if ((pnext = PKTGET(osh, sublen + DHD_SDALIGN, FALSE)) == NULL) {
  4161. DHD_ERROR(("%s: PKTGET failed, num %d len %d\n",
  4162. __FUNCTION__, num, sublen));
  4163. break;
  4164. }
  4165. ASSERT(!PKTLINK(pnext));
  4166. if (!pfirst) {
  4167. ASSERT(!plast);
  4168. pfirst = plast = pnext;
  4169. } else {
  4170. ASSERT(plast);
  4171. PKTSETNEXT(osh, plast, pnext);
  4172. plast = pnext;
  4173. }
  4174. /* Adhere to start alignment requirements */
  4175. PKTALIGN(osh, pnext, sublen, DHD_SDALIGN);
  4176. }
  4177. /* If all allocations succeeded, save packet chain in bus structure */
  4178. if (pnext) {
  4179. DHD_GLOM(("%s: allocated %d-byte packet chain for %d subframes\n",
  4180. __FUNCTION__, totlen, num));
  4181. if (DHD_GLOM_ON() && bus->nextlen) {
  4182. if (totlen != bus->nextlen) {
  4183. DHD_GLOM(("%s: glomdesc mismatch: nextlen %d glomdesc %d "
  4184. "rxseq %d\n", __FUNCTION__, bus->nextlen,
  4185. totlen, rxseq));
  4186. }
  4187. }
  4188. bus->glom = pfirst;
  4189. pfirst = pnext = NULL;
  4190. } else {
  4191. if (pfirst)
  4192. PKTFREE(osh, pfirst, FALSE);
  4193. bus->glom = NULL;
  4194. num = 0;
  4195. }
  4196. /* Done with descriptor packet */
  4197. PKTFREE(osh, bus->glomd, FALSE);
  4198. bus->glomd = NULL;
  4199. bus->nextlen = 0;
  4200. dhd_os_sdunlock_rxq(bus->dhd);
  4201. }
  4202. /* Ok -- either we just generated a packet chain, or had one from before */
  4203. if (bus->glom) {
  4204. if (DHD_GLOM_ON()) {
  4205. DHD_GLOM(("%s: attempt superframe read, packet chain:\n", __FUNCTION__));
  4206. for (pnext = bus->glom; pnext; pnext = PKTNEXT(osh, pnext)) {
  4207. DHD_GLOM((" %p: %p len 0x%04x (%d)\n",
  4208. pnext, (uint8*)PKTDATA(osh, pnext),
  4209. PKTLEN(osh, pnext), PKTLEN(osh, pnext)));
  4210. }
  4211. }
  4212. pfirst = bus->glom;
  4213. dlen = (uint16)pkttotlen(osh, pfirst);
  4214. /* Do an SDIO read for the superframe. Configurable iovar to
  4215. * read directly into the chained packet, or allocate a large
  4216. * packet and and copy into the chain.
  4217. */
  4218. if (usechain) {
  4219. errcode = dhd_bcmsdh_recv_buf(bus,
  4220. bcmsdh_cur_sbwad(bus->sdh), SDIO_FUNC_2,
  4221. F2SYNC, (uint8*)PKTDATA(osh, pfirst),
  4222. dlen, pfirst, NULL, NULL);
  4223. } else if (bus->dataptr) {
  4224. errcode = dhd_bcmsdh_recv_buf(bus,
  4225. bcmsdh_cur_sbwad(bus->sdh), SDIO_FUNC_2,
  4226. F2SYNC, bus->dataptr,
  4227. dlen, NULL, NULL, NULL);
  4228. sublen = (uint16)pktfrombuf(osh, pfirst, 0, dlen, bus->dataptr);
  4229. if (sublen != dlen) {
  4230. DHD_ERROR(("%s: FAILED TO COPY, dlen %d sublen %d\n",
  4231. __FUNCTION__, dlen, sublen));
  4232. errcode = -1;
  4233. }
  4234. pnext = NULL;
  4235. } else {
  4236. DHD_ERROR(("COULDN'T ALLOC %d-BYTE GLOM, FORCE FAILURE\n", dlen));
  4237. errcode = -1;
  4238. }
  4239. bus->f2rxdata++;
  4240. ASSERT(errcode != BCME_PENDING);
  4241. /* On failure, kill the superframe, allow a couple retries */
  4242. if (errcode < 0) {
  4243. DHD_ERROR(("%s: glom read of %d bytes failed: %d\n",
  4244. __FUNCTION__, dlen, errcode));
  4245. bus->dhd->rx_errors++;
  4246. if (bus->glomerr++ < 3) {
  4247. dhdsdio_rxfail(bus, TRUE, TRUE);
  4248. } else {
  4249. bus->glomerr = 0;
  4250. dhdsdio_rxfail(bus, TRUE, FALSE);
  4251. dhd_os_sdlock_rxq(bus->dhd);
  4252. PKTFREE(osh, bus->glom, FALSE);
  4253. dhd_os_sdunlock_rxq(bus->dhd);
  4254. bus->rxglomfail++;
  4255. bus->glom = NULL;
  4256. }
  4257. return 0;
  4258. }
  4259. #ifdef DHD_DEBUG
  4260. if (DHD_GLOM_ON()) {
  4261. prhex("SUPERFRAME", PKTDATA(osh, pfirst),
  4262. MIN(PKTLEN(osh, pfirst), 48));
  4263. }
  4264. #endif
  4265. /* Validate the superframe header */
  4266. dptr = (uint8 *)PKTDATA(osh, pfirst);
  4267. sublen = ltoh16_ua(dptr);
  4268. check = ltoh16_ua(dptr + sizeof(uint16));
  4269. chan = SDPCM_PACKET_CHANNEL(&dptr[SDPCM_FRAMETAG_LEN]);
  4270. seq = SDPCM_PACKET_SEQUENCE(&dptr[SDPCM_FRAMETAG_LEN]);
  4271. bus->nextlen = dptr[SDPCM_FRAMETAG_LEN + SDPCM_NEXTLEN_OFFSET];
  4272. if ((bus->nextlen << 4) > MAX_RX_DATASZ) {
  4273. DHD_INFO(("%s: got frame w/nextlen too large (%d) seq %d\n",
  4274. __FUNCTION__, bus->nextlen, seq));
  4275. bus->nextlen = 0;
  4276. }
  4277. doff = SDPCM_DOFFSET_VALUE(&dptr[SDPCM_FRAMETAG_LEN]);
  4278. txmax = SDPCM_WINDOW_VALUE(&dptr[SDPCM_FRAMETAG_LEN]);
  4279. errcode = 0;
  4280. if ((uint16)~(sublen^check)) {
  4281. DHD_ERROR(("%s (superframe): HW hdr error: len/check 0x%04x/0x%04x\n",
  4282. __FUNCTION__, sublen, check));
  4283. errcode = -1;
  4284. } else if (ROUNDUP(sublen, bus->blocksize) != dlen) {
  4285. DHD_ERROR(("%s (superframe): len 0x%04x, rounded 0x%04x, expect 0x%04x\n",
  4286. __FUNCTION__, sublen, ROUNDUP(sublen, bus->blocksize), dlen));
  4287. errcode = -1;
  4288. } else if (SDPCM_PACKET_CHANNEL(&dptr[SDPCM_FRAMETAG_LEN]) != SDPCM_GLOM_CHANNEL) {
  4289. DHD_ERROR(("%s (superframe): bad channel %d\n", __FUNCTION__,
  4290. SDPCM_PACKET_CHANNEL(&dptr[SDPCM_FRAMETAG_LEN])));
  4291. errcode = -1;
  4292. } else if (SDPCM_GLOMDESC(&dptr[SDPCM_FRAMETAG_LEN])) {
  4293. DHD_ERROR(("%s (superframe): got second descriptor?\n", __FUNCTION__));
  4294. errcode = -1;
  4295. } else if ((doff < SDPCM_HDRLEN) ||
  4296. (doff > (PKTLEN(osh, pfirst) - SDPCM_HDRLEN))) {
  4297. DHD_ERROR(("%s (superframe): Bad data offset %d: HW %d pkt %d min %d\n",
  4298. __FUNCTION__, doff, sublen, PKTLEN(osh, pfirst),
  4299. SDPCM_HDRLEN));
  4300. errcode = -1;
  4301. }
  4302. /* Check sequence number of superframe SW header */
  4303. if (rxseq != seq) {
  4304. DHD_INFO(("%s: (superframe) rx_seq %d, expected %d\n",
  4305. __FUNCTION__, seq, rxseq));
  4306. bus->rx_badseq++;
  4307. rxseq = seq;
  4308. }
  4309. /* Check window for sanity */
  4310. if ((uint8)(txmax - bus->tx_seq) > 0x70) {
  4311. DHD_ERROR(("%s: got unlikely tx max %d with tx_seq %d\n",
  4312. __FUNCTION__, txmax, bus->tx_seq));
  4313. txmax = bus->tx_max;
  4314. }
  4315. bus->tx_max = txmax;
  4316. /* Remove superframe header, remember offset */
  4317. PKTPULL(osh, pfirst, doff);
  4318. sfdoff = doff;
  4319. /* Validate all the subframe headers */
  4320. for (num = 0, pnext = pfirst; pnext && !errcode;
  4321. num++, pnext = PKTNEXT(osh, pnext)) {
  4322. dptr = (uint8 *)PKTDATA(osh, pnext);
  4323. dlen = (uint16)PKTLEN(osh, pnext);
  4324. sublen = ltoh16_ua(dptr);
  4325. check = ltoh16_ua(dptr + sizeof(uint16));
  4326. chan = SDPCM_PACKET_CHANNEL(&dptr[SDPCM_FRAMETAG_LEN]);
  4327. doff = SDPCM_DOFFSET_VALUE(&dptr[SDPCM_FRAMETAG_LEN]);
  4328. #ifdef DHD_DEBUG
  4329. if (DHD_GLOM_ON()) {
  4330. prhex("subframe", dptr, 32);
  4331. }
  4332. #endif
  4333. if ((uint16)~(sublen^check)) {
  4334. DHD_ERROR(("%s (subframe %d): HW hdr error: "
  4335. "len/check 0x%04x/0x%04x\n",
  4336. __FUNCTION__, num, sublen, check));
  4337. errcode = -1;
  4338. } else if ((sublen > dlen) || (sublen < SDPCM_HDRLEN)) {
  4339. DHD_ERROR(("%s (subframe %d): length mismatch: "
  4340. "len 0x%04x, expect 0x%04x\n",
  4341. __FUNCTION__, num, sublen, dlen));
  4342. errcode = -1;
  4343. } else if ((chan != SDPCM_DATA_CHANNEL) &&
  4344. (chan != SDPCM_EVENT_CHANNEL)) {
  4345. DHD_ERROR(("%s (subframe %d): bad channel %d\n",
  4346. __FUNCTION__, num, chan));
  4347. errcode = -1;
  4348. } else if ((doff < SDPCM_HDRLEN) || (doff > sublen)) {
  4349. DHD_ERROR(("%s (subframe %d): Bad data offset %d: HW %d min %d\n",
  4350. __FUNCTION__, num, doff, sublen, SDPCM_HDRLEN));
  4351. errcode = -1;
  4352. }
  4353. }
  4354. if (errcode) {
  4355. /* Terminate frame on error, request a couple retries */
  4356. if (bus->glomerr++ < 3) {
  4357. /* Restore superframe header space */
  4358. PKTPUSH(osh, pfirst, sfdoff);
  4359. dhdsdio_rxfail(bus, TRUE, TRUE);
  4360. } else {
  4361. bus->glomerr = 0;
  4362. dhdsdio_rxfail(bus, TRUE, FALSE);
  4363. dhd_os_sdlock_rxq(bus->dhd);
  4364. PKTFREE(osh, bus->glom, FALSE);
  4365. dhd_os_sdunlock_rxq(bus->dhd);
  4366. bus->rxglomfail++;
  4367. bus->glom = NULL;
  4368. }
  4369. bus->nextlen = 0;
  4370. return 0;
  4371. }
  4372. /* Basic SD framing looks ok - process each packet (header) */
  4373. bus->glom = NULL;
  4374. plast = NULL;
  4375. dhd_os_sdlock_rxq(bus->dhd);
  4376. for (num = 0; pfirst; rxseq++, pfirst = pnext) {
  4377. pnext = PKTNEXT(osh, pfirst);
  4378. PKTSETNEXT(osh, pfirst, NULL);
  4379. dptr = (uint8 *)PKTDATA(osh, pfirst);
  4380. sublen = ltoh16_ua(dptr);
  4381. chan = SDPCM_PACKET_CHANNEL(&dptr[SDPCM_FRAMETAG_LEN]);
  4382. seq = SDPCM_PACKET_SEQUENCE(&dptr[SDPCM_FRAMETAG_LEN]);
  4383. doff = SDPCM_DOFFSET_VALUE(&dptr[SDPCM_FRAMETAG_LEN]);
  4384. DHD_GLOM(("%s: Get subframe %d, %p(%p/%d), sublen %d chan %d seq %d\n",
  4385. __FUNCTION__, num, pfirst, PKTDATA(osh, pfirst),
  4386. PKTLEN(osh, pfirst), sublen, chan, seq));
  4387. ASSERT((chan == SDPCM_DATA_CHANNEL) || (chan == SDPCM_EVENT_CHANNEL));
  4388. if (rxseq != seq) {
  4389. DHD_GLOM(("%s: rx_seq %d, expected %d\n",
  4390. __FUNCTION__, seq, rxseq));
  4391. bus->rx_badseq++;
  4392. rxseq = seq;
  4393. }
  4394. #ifdef DHD_DEBUG
  4395. if (DHD_BYTES_ON() && DHD_DATA_ON()) {
  4396. prhex("Rx Subframe Data", dptr, dlen);
  4397. }
  4398. #endif
  4399. PKTSETLEN(osh, pfirst, sublen);
  4400. PKTPULL(osh, pfirst, doff);
  4401. reorder_info_len = sizeof(reorder_info_buf);
  4402. if (PKTLEN(osh, pfirst) == 0) {
  4403. PKTFREE(bus->dhd->osh, pfirst, FALSE);
  4404. continue;
  4405. } else if (dhd_prot_hdrpull(bus->dhd, &ifidx, pfirst, reorder_info_buf,
  4406. &reorder_info_len) != 0) {
  4407. DHD_ERROR(("%s: rx protocol error\n", __FUNCTION__));
  4408. bus->dhd->rx_errors++;
  4409. PKTFREE(osh, pfirst, FALSE);
  4410. continue;
  4411. }
  4412. if (reorder_info_len) {
  4413. uint32 free_buf_count;
  4414. void *ppfirst;
  4415. ppfirst = pfirst;
  4416. /* Reordering info from the firmware */
  4417. dhd_process_pkt_reorder_info(bus->dhd, reorder_info_buf,
  4418. reorder_info_len, &ppfirst, &free_buf_count);
  4419. if (free_buf_count == 0) {
  4420. continue;
  4421. }
  4422. else {
  4423. void *temp;
  4424. /* go to the end of the chain and attach the pnext there */
  4425. temp = ppfirst;
  4426. while (PKTNEXT(osh, temp) != NULL) {
  4427. temp = PKTNEXT(osh, temp);
  4428. }
  4429. pfirst = temp;
  4430. if (list_tail[ifidx] == NULL)
  4431. list_head[ifidx] = ppfirst;
  4432. else
  4433. PKTSETNEXT(osh, list_tail[ifidx], ppfirst);
  4434. list_tail[ifidx] = pfirst;
  4435. }
  4436. num += (uint8)free_buf_count;
  4437. }
  4438. else {
  4439. /* this packet will go up, link back into chain and count it */
  4440. if (list_tail[ifidx] == NULL) {
  4441. list_head[ifidx] = list_tail[ifidx] = pfirst;
  4442. }
  4443. else {
  4444. PKTSETNEXT(osh, list_tail[ifidx], pfirst);
  4445. list_tail[ifidx] = pfirst;
  4446. }
  4447. num++;
  4448. }
  4449. #ifdef DHD_DEBUG
  4450. if (DHD_GLOM_ON()) {
  4451. DHD_GLOM(("%s subframe %d to stack, %p(%p/%d) nxt/lnk %p/%p\n",
  4452. __FUNCTION__, num, pfirst,
  4453. PKTDATA(osh, pfirst), PKTLEN(osh, pfirst),
  4454. PKTNEXT(osh, pfirst), PKTLINK(pfirst)));
  4455. prhex("", (uint8 *)PKTDATA(osh, pfirst),
  4456. MIN(PKTLEN(osh, pfirst), 32));
  4457. }
  4458. #endif /* DHD_DEBUG */
  4459. }
  4460. dhd_os_sdunlock_rxq(bus->dhd);
  4461. for (idx = 0; idx < DHD_MAX_IFS; idx++) {
  4462. if (list_head[idx]) {
  4463. void *temp;
  4464. uint8 cnt = 0;
  4465. temp = list_head[idx];
  4466. do {
  4467. temp = PKTNEXT(osh, temp);
  4468. cnt++;
  4469. } while (temp);
  4470. if (cnt) {
  4471. dhd_os_sdunlock(bus->dhd);
  4472. dhd_rx_frame(bus->dhd, idx, list_head[idx], cnt, 0);
  4473. dhd_os_sdlock(bus->dhd);
  4474. }
  4475. }
  4476. }
  4477. bus->rxglomframes++;
  4478. bus->rxglompkts += num;
  4479. }
  4480. return num;
  4481. }
  4482. /* Return TRUE if there may be more frames to read */
  4483. static uint
  4484. dhdsdio_readframes(dhd_bus_t *bus, uint maxframes, bool *finished)
  4485. {
  4486. osl_t *osh = bus->dhd->osh;
  4487. bcmsdh_info_t *sdh = bus->sdh;
  4488. uint16 len, check; /* Extracted hardware header fields */
  4489. uint8 chan, seq, doff; /* Extracted software header fields */
  4490. uint8 fcbits; /* Extracted fcbits from software header */
  4491. uint8 delta;
  4492. void *pkt; /* Packet for event or data frames */
  4493. uint16 pad; /* Number of pad bytes to read */
  4494. uint16 rdlen; /* Total number of bytes to read */
  4495. uint8 rxseq; /* Next sequence number to expect */
  4496. uint rxleft = 0; /* Remaining number of frames allowed */
  4497. int sdret; /* Return code from bcmsdh calls */
  4498. uint8 txmax; /* Maximum tx sequence offered */
  4499. #ifdef BCMSPI
  4500. uint32 dstatus = 0; /* gSPI device status bits of */
  4501. #endif /* BCMSPI */
  4502. bool len_consistent; /* Result of comparing readahead len and len from hw-hdr */
  4503. uint8 *rxbuf;
  4504. int ifidx = 0;
  4505. uint rxcount = 0; /* Total frames read */
  4506. uchar reorder_info_buf[WLHOST_REORDERDATA_TOTLEN];
  4507. uint reorder_info_len;
  4508. uint pkt_count;
  4509. #if defined(DHD_DEBUG) || defined(SDTEST)
  4510. bool sdtest = FALSE; /* To limit message spew from test mode */
  4511. #endif
  4512. DHD_TRACE(("%s: Enter\n", __FUNCTION__));
  4513. bus->readframes = TRUE;
  4514. if (!KSO_ENAB(bus)) {
  4515. DHD_ERROR(("%s: KSO off\n", __FUNCTION__));
  4516. bus->readframes = FALSE;
  4517. return 0;
  4518. }
  4519. ASSERT(maxframes);
  4520. #ifdef SDTEST
  4521. /* Allow pktgen to override maxframes */
  4522. if (bus->pktgen_count && (bus->pktgen_mode == DHD_PKTGEN_RECV)) {
  4523. maxframes = bus->pktgen_count;
  4524. sdtest = TRUE;
  4525. }
  4526. #endif
  4527. /* Not finished unless we encounter no more frames indication */
  4528. *finished = FALSE;
  4529. #ifdef BCMSPI
  4530. /* Get pktlen from gSPI device F0 reg. */
  4531. if (bus->bus == SPI_BUS) {
  4532. /* Peek in dstatus bits and find out size to do rx-read. */
  4533. dstatus = bcmsdh_get_dstatus(bus->sdh);
  4534. if (dstatus == 0)
  4535. DHD_ERROR(("%s:ZERO spi dstatus, a case observed in PR61352 hit !!!\n",
  4536. __FUNCTION__));
  4537. DHD_TRACE(("Device status from regread = 0x%x\n", dstatus));
  4538. DHD_TRACE(("Device status from bit-reconstruction = 0x%x\n",
  4539. bcmsdh_get_dstatus((void *)bus->sdh)));
  4540. if ((dstatus & STATUS_F2_PKT_AVAILABLE) && (((dstatus & STATUS_UNDERFLOW)) == 0)) {
  4541. bus->nextlen = ((dstatus & STATUS_F2_PKT_LEN_MASK) >>
  4542. STATUS_F2_PKT_LEN_SHIFT);
  4543. /* '0' size with pkt-available interrupt is eqvt to 2048 bytes */
  4544. bus->nextlen = (bus->nextlen == 0) ? SPI_MAX_PKT_LEN : bus->nextlen;
  4545. if (bus->dwordmode)
  4546. bus->nextlen = bus->nextlen << 2;
  4547. DHD_TRACE(("Entering %s: length to be read from gSPI = %d\n",
  4548. __FUNCTION__, bus->nextlen));
  4549. } else {
  4550. if (dstatus & STATUS_F2_PKT_AVAILABLE)
  4551. DHD_ERROR(("Underflow during %s.\n", __FUNCTION__));
  4552. else
  4553. DHD_ERROR(("False pkt-available intr.\n"));
  4554. *finished = TRUE;
  4555. return (maxframes - rxleft);
  4556. }
  4557. }
  4558. #endif /* BCMSPI */
  4559. for (rxseq = bus->rx_seq, rxleft = maxframes;
  4560. !bus->rxskip && rxleft && bus->dhd->busstate != DHD_BUS_DOWN;
  4561. rxseq++, rxleft--) {
  4562. #ifdef DHDTCPACK_SUP_DBG
  4563. if (bus->dhd->tcpack_sup_mode != TCPACK_SUP_DELAYTX) {
  4564. if (bus->dotxinrx == FALSE)
  4565. DHD_ERROR(("%s %d: dotxinrx FALSE with tcpack_sub_mode %d\n",
  4566. __FUNCTION__, __LINE__, bus->dhd->tcpack_sup_mode));
  4567. }
  4568. #ifdef DEBUG_COUNTER
  4569. else if (pktq_mlen(&bus->txq, ~bus->flowcontrol) > 0) {
  4570. tack_tbl.cnt[bus->dotxinrx ? 6 : 7]++;
  4571. }
  4572. #endif /* DEBUG_COUNTER */
  4573. #endif /* DHDTCPACK_SUP_DBG */
  4574. /* tx more to improve rx performance */
  4575. if (TXCTLOK(bus) && bus->ctrl_frame_stat && (bus->clkstate == CLK_AVAIL)) {
  4576. dhdsdio_sendpendctl(bus);
  4577. } else if (bus->dotxinrx && (bus->clkstate == CLK_AVAIL) &&
  4578. !bus->fcstate && DATAOK(bus) &&
  4579. (pktq_mlen(&bus->txq, ~bus->flowcontrol) > bus->txinrx_thres)) {
  4580. dhdsdio_sendfromq(bus, dhd_txbound);
  4581. #ifdef DHDTCPACK_SUPPRESS
  4582. /* In TCPACK_SUP_DELAYTX mode, do txinrx only if
  4583. * 1. Any DATA packet to TX
  4584. * 2. TCPACK to TCPDATA PSH packets.
  4585. * in bus txq.
  4586. */
  4587. bus->dotxinrx = (bus->dhd->tcpack_sup_mode == TCPACK_SUP_DELAYTX) ?
  4588. FALSE : TRUE;
  4589. #endif
  4590. }
  4591. /* Handle glomming separately */
  4592. if (bus->glom || bus->glomd) {
  4593. uint8 cnt;
  4594. DHD_GLOM(("%s: calling rxglom: glomd %p, glom %p\n",
  4595. __FUNCTION__, bus->glomd, bus->glom));
  4596. cnt = dhdsdio_rxglom(bus, rxseq);
  4597. DHD_GLOM(("%s: rxglom returned %d\n", __FUNCTION__, cnt));
  4598. rxseq += cnt - 1;
  4599. rxleft = (rxleft > cnt) ? (rxleft - cnt) : 1;
  4600. continue;
  4601. }
  4602. /* Try doing single read if we can */
  4603. if (dhd_readahead && bus->nextlen) {
  4604. uint16 nextlen = bus->nextlen;
  4605. bus->nextlen = 0;
  4606. if (bus->bus == SPI_BUS) {
  4607. rdlen = len = nextlen;
  4608. }
  4609. else {
  4610. rdlen = len = nextlen << 4;
  4611. /* Pad read to blocksize for efficiency */
  4612. if (bus->roundup && bus->blocksize && (rdlen > bus->blocksize)) {
  4613. pad = bus->blocksize - (rdlen % bus->blocksize);
  4614. if ((pad <= bus->roundup) && (pad < bus->blocksize) &&
  4615. ((rdlen + pad + firstread) < MAX_RX_DATASZ))
  4616. rdlen += pad;
  4617. } else if (rdlen % DHD_SDALIGN) {
  4618. rdlen += DHD_SDALIGN - (rdlen % DHD_SDALIGN);
  4619. }
  4620. }
  4621. /* We use bus->rxctl buffer in WinXP for initial control pkt receives.
  4622. * Later we use buffer-poll for data as well as control packets.
  4623. * This is required because dhd receives full frame in gSPI unlike SDIO.
  4624. * After the frame is received we have to distinguish whether it is data
  4625. * or non-data frame.
  4626. */
  4627. /* Allocate a packet buffer */
  4628. dhd_os_sdlock_rxq(bus->dhd);
  4629. if (!(pkt = PKTGET(osh, rdlen + DHD_SDALIGN, FALSE))) {
  4630. if (bus->bus == SPI_BUS) {
  4631. bus->usebufpool = FALSE;
  4632. bus->rxctl = bus->rxbuf;
  4633. if (dhd_alignctl) {
  4634. bus->rxctl += firstread;
  4635. if ((pad = ((uintptr)bus->rxctl % DHD_SDALIGN)))
  4636. bus->rxctl += (DHD_SDALIGN - pad);
  4637. bus->rxctl -= firstread;
  4638. }
  4639. ASSERT(bus->rxctl >= bus->rxbuf);
  4640. rxbuf = bus->rxctl;
  4641. /* Read the entire frame */
  4642. sdret = dhd_bcmsdh_recv_buf(bus,
  4643. bcmsdh_cur_sbwad(sdh),
  4644. SDIO_FUNC_2,
  4645. F2SYNC, rxbuf, rdlen,
  4646. NULL, NULL, NULL);
  4647. bus->f2rxdata++;
  4648. ASSERT(sdret != BCME_PENDING);
  4649. #ifdef BCMSPI
  4650. if (bcmsdh_get_dstatus((void *)bus->sdh) &
  4651. STATUS_UNDERFLOW) {
  4652. bus->nextlen = 0;
  4653. *finished = TRUE;
  4654. DHD_ERROR(("%s: read %d control bytes failed "
  4655. "due to spi underflow\n",
  4656. __FUNCTION__, rdlen));
  4657. /* dhd.rx_ctlerrs is higher level */
  4658. bus->rxc_errors++;
  4659. dhd_os_sdunlock_rxq(bus->dhd);
  4660. continue;
  4661. }
  4662. #endif /* BCMSPI */
  4663. /* Control frame failures need retransmission */
  4664. if (sdret < 0) {
  4665. DHD_ERROR(("%s: read %d control bytes failed: %d\n",
  4666. __FUNCTION__, rdlen, sdret));
  4667. /* dhd.rx_ctlerrs is higher level */
  4668. bus->rxc_errors++;
  4669. dhd_os_sdunlock_rxq(bus->dhd);
  4670. dhdsdio_rxfail(bus, TRUE,
  4671. (bus->bus == SPI_BUS) ? FALSE : TRUE);
  4672. continue;
  4673. }
  4674. } else {
  4675. /* Give up on data, request rtx of events */
  4676. DHD_ERROR(("%s (nextlen): PKTGET failed: len %d rdlen %d "
  4677. "expected rxseq %d\n",
  4678. __FUNCTION__, len, rdlen, rxseq));
  4679. /* Just go try again w/normal header read */
  4680. dhd_os_sdunlock_rxq(bus->dhd);
  4681. continue;
  4682. }
  4683. } else {
  4684. if (bus->bus == SPI_BUS)
  4685. bus->usebufpool = TRUE;
  4686. ASSERT(!PKTLINK(pkt));
  4687. PKTALIGN(osh, pkt, rdlen, DHD_SDALIGN);
  4688. rxbuf = (uint8 *)PKTDATA(osh, pkt);
  4689. /* Read the entire frame */
  4690. sdret = dhd_bcmsdh_recv_buf(bus, bcmsdh_cur_sbwad(sdh),
  4691. SDIO_FUNC_2,
  4692. F2SYNC, rxbuf, rdlen,
  4693. pkt, NULL, NULL);
  4694. bus->f2rxdata++;
  4695. ASSERT(sdret != BCME_PENDING);
  4696. #ifdef BCMSPI
  4697. if (bcmsdh_get_dstatus((void *)bus->sdh) & STATUS_UNDERFLOW) {
  4698. bus->nextlen = 0;
  4699. *finished = TRUE;
  4700. DHD_ERROR(("%s (nextlen): read %d bytes failed due "
  4701. "to spi underflow\n",
  4702. __FUNCTION__, rdlen));
  4703. PKTFREE(bus->dhd->osh, pkt, FALSE);
  4704. bus->dhd->rx_errors++;
  4705. dhd_os_sdunlock_rxq(bus->dhd);
  4706. continue;
  4707. }
  4708. #endif /* BCMSPI */
  4709. if (sdret < 0) {
  4710. DHD_ERROR(("%s (nextlen): read %d bytes failed: %d\n",
  4711. __FUNCTION__, rdlen, sdret));
  4712. PKTFREE(bus->dhd->osh, pkt, FALSE);
  4713. bus->dhd->rx_errors++;
  4714. dhd_os_sdunlock_rxq(bus->dhd);
  4715. /* Force retry w/normal header read. Don't attempt NAK for
  4716. * gSPI
  4717. */
  4718. dhdsdio_rxfail(bus, TRUE,
  4719. (bus->bus == SPI_BUS) ? FALSE : TRUE);
  4720. continue;
  4721. }
  4722. }
  4723. dhd_os_sdunlock_rxq(bus->dhd);
  4724. /* Now check the header */
  4725. bcopy(rxbuf, bus->rxhdr, SDPCM_HDRLEN);
  4726. /* Extract hardware header fields */
  4727. len = ltoh16_ua(bus->rxhdr);
  4728. check = ltoh16_ua(bus->rxhdr + sizeof(uint16));
  4729. /* All zeros means readahead info was bad */
  4730. if (!(len|check)) {
  4731. DHD_INFO(("%s (nextlen): read zeros in HW header???\n",
  4732. __FUNCTION__));
  4733. dhd_os_sdlock_rxq(bus->dhd);
  4734. PKTFREE2();
  4735. dhd_os_sdunlock_rxq(bus->dhd);
  4736. GSPI_PR55150_BAILOUT;
  4737. continue;
  4738. }
  4739. /* Validate check bytes */
  4740. if ((uint16)~(len^check)) {
  4741. DHD_ERROR(("%s (nextlen): HW hdr error: nextlen/len/check"
  4742. " 0x%04x/0x%04x/0x%04x\n", __FUNCTION__, nextlen,
  4743. len, check));
  4744. dhd_os_sdlock_rxq(bus->dhd);
  4745. PKTFREE2();
  4746. dhd_os_sdunlock_rxq(bus->dhd);
  4747. bus->rx_badhdr++;
  4748. dhdsdio_rxfail(bus, FALSE, FALSE);
  4749. GSPI_PR55150_BAILOUT;
  4750. continue;
  4751. }
  4752. /* Validate frame length */
  4753. if (len < SDPCM_HDRLEN) {
  4754. DHD_ERROR(("%s (nextlen): HW hdr length invalid: %d\n",
  4755. __FUNCTION__, len));
  4756. dhd_os_sdlock_rxq(bus->dhd);
  4757. PKTFREE2();
  4758. dhd_os_sdunlock_rxq(bus->dhd);
  4759. GSPI_PR55150_BAILOUT;
  4760. continue;
  4761. }
  4762. /* Check for consistency with readahead info */
  4763. #ifdef BCMSPI
  4764. if (bus->bus == SPI_BUS) {
  4765. if (bus->dwordmode) {
  4766. uint16 spilen;
  4767. if ((bus->sih->chip == BCM4329_CHIP_ID) &&
  4768. (bus->sih->chiprev == 2))
  4769. spilen = ROUNDUP(len, 16);
  4770. else
  4771. spilen = ROUNDUP(len, 4);
  4772. len_consistent = (nextlen != spilen);
  4773. } else
  4774. len_consistent = (nextlen != len);
  4775. } else
  4776. #endif /* BCMSPI */
  4777. len_consistent = (nextlen != (ROUNDUP(len, 16) >> 4));
  4778. if (len_consistent) {
  4779. /* Mismatch, force retry w/normal header (may be >4K) */
  4780. DHD_ERROR(("%s (nextlen): mismatch, nextlen %d len %d rnd %d; "
  4781. "expected rxseq %d\n",
  4782. __FUNCTION__, nextlen, len, ROUNDUP(len, 16), rxseq));
  4783. dhd_os_sdlock_rxq(bus->dhd);
  4784. PKTFREE2();
  4785. dhd_os_sdunlock_rxq(bus->dhd);
  4786. dhdsdio_rxfail(bus, TRUE, (bus->bus == SPI_BUS) ? FALSE : TRUE);
  4787. GSPI_PR55150_BAILOUT;
  4788. continue;
  4789. }
  4790. /* Extract software header fields */
  4791. chan = SDPCM_PACKET_CHANNEL(&bus->rxhdr[SDPCM_FRAMETAG_LEN]);
  4792. seq = SDPCM_PACKET_SEQUENCE(&bus->rxhdr[SDPCM_FRAMETAG_LEN]);
  4793. doff = SDPCM_DOFFSET_VALUE(&bus->rxhdr[SDPCM_FRAMETAG_LEN]);
  4794. txmax = SDPCM_WINDOW_VALUE(&bus->rxhdr[SDPCM_FRAMETAG_LEN]);
  4795. #ifdef BCMSPI
  4796. /* Save the readahead length if there is one */
  4797. if (bus->bus == SPI_BUS) {
  4798. /* Use reconstructed dstatus bits and find out readahead size */
  4799. dstatus = bcmsdh_get_dstatus((void *)bus->sdh);
  4800. DHD_INFO(("Device status from bit-reconstruction = 0x%x\n",
  4801. bcmsdh_get_dstatus((void *)bus->sdh)));
  4802. if (dstatus & STATUS_F2_PKT_AVAILABLE) {
  4803. bus->nextlen = ((dstatus & STATUS_F2_PKT_LEN_MASK) >>
  4804. STATUS_F2_PKT_LEN_SHIFT);
  4805. bus->nextlen = (bus->nextlen == 0) ?
  4806. SPI_MAX_PKT_LEN : bus->nextlen;
  4807. if (bus->dwordmode)
  4808. bus->nextlen = bus->nextlen << 2;
  4809. DHD_INFO(("readahead len from gSPI = %d \n",
  4810. bus->nextlen));
  4811. bus->dhd->rx_readahead_cnt ++;
  4812. } else {
  4813. bus->nextlen = 0;
  4814. *finished = TRUE;
  4815. }
  4816. } else {
  4817. #endif /* BCMSPI */
  4818. bus->nextlen =
  4819. bus->rxhdr[SDPCM_FRAMETAG_LEN + SDPCM_NEXTLEN_OFFSET];
  4820. if ((bus->nextlen << 4) > MAX_RX_DATASZ) {
  4821. DHD_INFO(("%s (nextlen): got frame w/nextlen too large"
  4822. " (%d), seq %d\n", __FUNCTION__, bus->nextlen,
  4823. seq));
  4824. bus->nextlen = 0;
  4825. }
  4826. bus->dhd->rx_readahead_cnt ++;
  4827. #ifdef BCMSPI
  4828. }
  4829. #endif /* BCMSPI */
  4830. /* Handle Flow Control */
  4831. fcbits = SDPCM_FCMASK_VALUE(&bus->rxhdr[SDPCM_FRAMETAG_LEN]);
  4832. delta = 0;
  4833. if (~bus->flowcontrol & fcbits) {
  4834. bus->fc_xoff++;
  4835. delta = 1;
  4836. }
  4837. if (bus->flowcontrol & ~fcbits) {
  4838. bus->fc_xon++;
  4839. delta = 1;
  4840. }
  4841. if (delta) {
  4842. bus->fc_rcvd++;
  4843. bus->flowcontrol = fcbits;
  4844. }
  4845. /* Check and update sequence number */
  4846. if (rxseq != seq) {
  4847. DHD_INFO(("%s (nextlen): rx_seq %d, expected %d\n",
  4848. __FUNCTION__, seq, rxseq));
  4849. bus->rx_badseq++;
  4850. rxseq = seq;
  4851. }
  4852. /* Check window for sanity */
  4853. if ((uint8)(txmax - bus->tx_seq) > 0x70) {
  4854. #ifdef BCMSPI
  4855. if ((bus->bus == SPI_BUS) && !(dstatus & STATUS_F2_RX_READY)) {
  4856. DHD_ERROR(("%s: got unlikely tx max %d with tx_seq %d\n",
  4857. __FUNCTION__, txmax, bus->tx_seq));
  4858. txmax = bus->tx_seq + 2;
  4859. } else {
  4860. #endif /* BCMSPI */
  4861. DHD_ERROR(("%s: got unlikely tx max %d with tx_seq %d\n",
  4862. __FUNCTION__, txmax, bus->tx_seq));
  4863. txmax = bus->tx_max;
  4864. #ifdef BCMSPI
  4865. }
  4866. #endif /* BCMSPI */
  4867. }
  4868. bus->tx_max = txmax;
  4869. #ifdef DHD_DEBUG
  4870. if (DHD_BYTES_ON() && DHD_DATA_ON()) {
  4871. prhex("Rx Data", rxbuf, len);
  4872. } else if (DHD_HDRS_ON()) {
  4873. prhex("RxHdr", bus->rxhdr, SDPCM_HDRLEN);
  4874. }
  4875. #endif
  4876. if (chan == SDPCM_CONTROL_CHANNEL) {
  4877. if (bus->bus == SPI_BUS) {
  4878. dhdsdio_read_control(bus, rxbuf, len, doff);
  4879. if (bus->usebufpool) {
  4880. dhd_os_sdlock_rxq(bus->dhd);
  4881. PKTFREE(bus->dhd->osh, pkt, FALSE);
  4882. dhd_os_sdunlock_rxq(bus->dhd);
  4883. }
  4884. continue;
  4885. } else {
  4886. DHD_ERROR(("%s (nextlen): readahead on control"
  4887. " packet %d?\n", __FUNCTION__, seq));
  4888. /* Force retry w/normal header read */
  4889. bus->nextlen = 0;
  4890. dhdsdio_rxfail(bus, FALSE, TRUE);
  4891. dhd_os_sdlock_rxq(bus->dhd);
  4892. PKTFREE2();
  4893. dhd_os_sdunlock_rxq(bus->dhd);
  4894. continue;
  4895. }
  4896. }
  4897. if ((bus->bus == SPI_BUS) && !bus->usebufpool) {
  4898. DHD_ERROR(("Received %d bytes on %d channel. Running out of "
  4899. "rx pktbuf's or not yet malloced.\n", len, chan));
  4900. continue;
  4901. }
  4902. /* Validate data offset */
  4903. if ((doff < SDPCM_HDRLEN) || (doff > len)) {
  4904. DHD_ERROR(("%s (nextlen): bad data offset %d: HW len %d min %d\n",
  4905. __FUNCTION__, doff, len, SDPCM_HDRLEN));
  4906. dhd_os_sdlock_rxq(bus->dhd);
  4907. PKTFREE2();
  4908. dhd_os_sdunlock_rxq(bus->dhd);
  4909. ASSERT(0);
  4910. dhdsdio_rxfail(bus, FALSE, FALSE);
  4911. continue;
  4912. }
  4913. /* All done with this one -- now deliver the packet */
  4914. goto deliver;
  4915. }
  4916. /* gSPI frames should not be handled in fractions */
  4917. if (bus->bus == SPI_BUS) {
  4918. break;
  4919. }
  4920. /* Read frame header (hardware and software) */
  4921. sdret = dhd_bcmsdh_recv_buf(bus, bcmsdh_cur_sbwad(sdh), SDIO_FUNC_2, F2SYNC,
  4922. bus->rxhdr, firstread, NULL, NULL, NULL);
  4923. bus->f2rxhdrs++;
  4924. ASSERT(sdret != BCME_PENDING);
  4925. if (sdret < 0) {
  4926. DHD_ERROR(("%s: RXHEADER FAILED: %d\n", __FUNCTION__, sdret));
  4927. bus->rx_hdrfail++;
  4928. dhdsdio_rxfail(bus, TRUE, TRUE);
  4929. continue;
  4930. }
  4931. #ifdef DHD_DEBUG
  4932. if (DHD_BYTES_ON() || DHD_HDRS_ON()) {
  4933. prhex("RxHdr", bus->rxhdr, SDPCM_HDRLEN);
  4934. }
  4935. #endif
  4936. /* Extract hardware header fields */
  4937. len = ltoh16_ua(bus->rxhdr);
  4938. check = ltoh16_ua(bus->rxhdr + sizeof(uint16));
  4939. /* All zeros means no more frames */
  4940. if (!(len|check)) {
  4941. *finished = TRUE;
  4942. break;
  4943. }
  4944. /* Validate check bytes */
  4945. if ((uint16)~(len^check)) {
  4946. DHD_ERROR(("%s: HW hdr error: len/check 0x%04x/0x%04x\n",
  4947. __FUNCTION__, len, check));
  4948. bus->rx_badhdr++;
  4949. dhdsdio_rxfail(bus, FALSE, FALSE);
  4950. continue;
  4951. }
  4952. /* Validate frame length */
  4953. if (len < SDPCM_HDRLEN) {
  4954. DHD_ERROR(("%s: HW hdr length invalid: %d\n", __FUNCTION__, len));
  4955. continue;
  4956. }
  4957. /* Extract software header fields */
  4958. chan = SDPCM_PACKET_CHANNEL(&bus->rxhdr[SDPCM_FRAMETAG_LEN]);
  4959. seq = SDPCM_PACKET_SEQUENCE(&bus->rxhdr[SDPCM_FRAMETAG_LEN]);
  4960. doff = SDPCM_DOFFSET_VALUE(&bus->rxhdr[SDPCM_FRAMETAG_LEN]);
  4961. txmax = SDPCM_WINDOW_VALUE(&bus->rxhdr[SDPCM_FRAMETAG_LEN]);
  4962. /* Validate data offset */
  4963. if ((doff < SDPCM_HDRLEN) || (doff > len)) {
  4964. DHD_ERROR(("%s: Bad data offset %d: HW len %d, min %d seq %d\n",
  4965. __FUNCTION__, doff, len, SDPCM_HDRLEN, seq));
  4966. bus->rx_badhdr++;
  4967. ASSERT(0);
  4968. dhdsdio_rxfail(bus, FALSE, FALSE);
  4969. continue;
  4970. }
  4971. /* Save the readahead length if there is one */
  4972. bus->nextlen = bus->rxhdr[SDPCM_FRAMETAG_LEN + SDPCM_NEXTLEN_OFFSET];
  4973. if ((bus->nextlen << 4) > MAX_RX_DATASZ) {
  4974. DHD_INFO(("%s (nextlen): got frame w/nextlen too large (%d), seq %d\n",
  4975. __FUNCTION__, bus->nextlen, seq));
  4976. bus->nextlen = 0;
  4977. }
  4978. /* Handle Flow Control */
  4979. fcbits = SDPCM_FCMASK_VALUE(&bus->rxhdr[SDPCM_FRAMETAG_LEN]);
  4980. delta = 0;
  4981. if (~bus->flowcontrol & fcbits) {
  4982. bus->fc_xoff++;
  4983. delta = 1;
  4984. }
  4985. if (bus->flowcontrol & ~fcbits) {
  4986. bus->fc_xon++;
  4987. delta = 1;
  4988. }
  4989. if (delta) {
  4990. bus->fc_rcvd++;
  4991. bus->flowcontrol = fcbits;
  4992. }
  4993. /* Check and update sequence number */
  4994. if (rxseq != seq) {
  4995. DHD_INFO(("%s: rx_seq %d, expected %d\n", __FUNCTION__, seq, rxseq));
  4996. bus->rx_badseq++;
  4997. rxseq = seq;
  4998. }
  4999. /* Check window for sanity */
  5000. if ((uint8)(txmax - bus->tx_seq) > 0x70) {
  5001. DHD_ERROR(("%s: got unlikely tx max %d with tx_seq %d\n",
  5002. __FUNCTION__, txmax, bus->tx_seq));
  5003. txmax = bus->tx_max;
  5004. }
  5005. bus->tx_max = txmax;
  5006. /* Call a separate function for control frames */
  5007. if (chan == SDPCM_CONTROL_CHANNEL) {
  5008. dhdsdio_read_control(bus, bus->rxhdr, len, doff);
  5009. continue;
  5010. }
  5011. ASSERT((chan == SDPCM_DATA_CHANNEL) || (chan == SDPCM_EVENT_CHANNEL) ||
  5012. (chan == SDPCM_TEST_CHANNEL) || (chan == SDPCM_GLOM_CHANNEL));
  5013. /* Length to read */
  5014. rdlen = (len > firstread) ? (len - firstread) : 0;
  5015. /* May pad read to blocksize for efficiency */
  5016. if (bus->roundup && bus->blocksize && (rdlen > bus->blocksize)) {
  5017. pad = bus->blocksize - (rdlen % bus->blocksize);
  5018. if ((pad <= bus->roundup) && (pad < bus->blocksize) &&
  5019. ((rdlen + pad + firstread) < MAX_RX_DATASZ))
  5020. rdlen += pad;
  5021. } else if (rdlen % DHD_SDALIGN) {
  5022. rdlen += DHD_SDALIGN - (rdlen % DHD_SDALIGN);
  5023. }
  5024. /* Satisfy length-alignment requirements */
  5025. if (forcealign && (rdlen & (ALIGNMENT - 1)))
  5026. rdlen = ROUNDUP(rdlen, ALIGNMENT);
  5027. if ((rdlen + firstread) > MAX_RX_DATASZ) {
  5028. /* Too long -- skip this frame */
  5029. DHD_ERROR(("%s: too long: len %d rdlen %d\n", __FUNCTION__, len, rdlen));
  5030. bus->dhd->rx_errors++; bus->rx_toolong++;
  5031. dhdsdio_rxfail(bus, FALSE, FALSE);
  5032. continue;
  5033. }
  5034. dhd_os_sdlock_rxq(bus->dhd);
  5035. if (!(pkt = PKTGET(osh, (rdlen + firstread + DHD_SDALIGN), FALSE))) {
  5036. /* Give up on data, request rtx of events */
  5037. DHD_ERROR(("%s: PKTGET failed: rdlen %d chan %d\n",
  5038. __FUNCTION__, rdlen, chan));
  5039. bus->dhd->rx_dropped++;
  5040. dhd_os_sdunlock_rxq(bus->dhd);
  5041. dhdsdio_rxfail(bus, FALSE, RETRYCHAN(chan));
  5042. continue;
  5043. }
  5044. dhd_os_sdunlock_rxq(bus->dhd);
  5045. ASSERT(!PKTLINK(pkt));
  5046. /* Leave room for what we already read, and align remainder */
  5047. ASSERT(firstread < (PKTLEN(osh, pkt)));
  5048. PKTPULL(osh, pkt, firstread);
  5049. PKTALIGN(osh, pkt, rdlen, DHD_SDALIGN);
  5050. /* Read the remaining frame data */
  5051. sdret = dhd_bcmsdh_recv_buf(bus, bcmsdh_cur_sbwad(sdh), SDIO_FUNC_2, F2SYNC,
  5052. ((uint8 *)PKTDATA(osh, pkt)), rdlen, pkt, NULL, NULL);
  5053. bus->f2rxdata++;
  5054. ASSERT(sdret != BCME_PENDING);
  5055. if (sdret < 0) {
  5056. DHD_ERROR(("%s: read %d %s bytes failed: %d\n", __FUNCTION__, rdlen,
  5057. ((chan == SDPCM_EVENT_CHANNEL) ? "event" :
  5058. ((chan == SDPCM_DATA_CHANNEL) ? "data" : "test")), sdret));
  5059. dhd_os_sdlock_rxq(bus->dhd);
  5060. PKTFREE(bus->dhd->osh, pkt, FALSE);
  5061. dhd_os_sdunlock_rxq(bus->dhd);
  5062. bus->dhd->rx_errors++;
  5063. dhdsdio_rxfail(bus, TRUE, RETRYCHAN(chan));
  5064. continue;
  5065. }
  5066. /* Copy the already-read portion */
  5067. PKTPUSH(osh, pkt, firstread);
  5068. bcopy(bus->rxhdr, PKTDATA(osh, pkt), firstread);
  5069. #ifdef DHD_DEBUG
  5070. if (DHD_BYTES_ON() && DHD_DATA_ON()) {
  5071. prhex("Rx Data", PKTDATA(osh, pkt), len);
  5072. }
  5073. #endif
  5074. deliver:
  5075. /* Save superframe descriptor and allocate packet frame */
  5076. if (chan == SDPCM_GLOM_CHANNEL) {
  5077. if (SDPCM_GLOMDESC(&bus->rxhdr[SDPCM_FRAMETAG_LEN])) {
  5078. DHD_GLOM(("%s: got glom descriptor, %d bytes:\n",
  5079. __FUNCTION__, len));
  5080. #ifdef DHD_DEBUG
  5081. if (DHD_GLOM_ON()) {
  5082. prhex("Glom Data", PKTDATA(osh, pkt), len);
  5083. }
  5084. #endif
  5085. PKTSETLEN(osh, pkt, len);
  5086. ASSERT(doff == SDPCM_HDRLEN);
  5087. PKTPULL(osh, pkt, SDPCM_HDRLEN);
  5088. bus->glomd = pkt;
  5089. } else {
  5090. DHD_ERROR(("%s: glom superframe w/o descriptor!\n", __FUNCTION__));
  5091. dhdsdio_rxfail(bus, FALSE, FALSE);
  5092. }
  5093. continue;
  5094. }
  5095. /* Fill in packet len and prio, deliver upward */
  5096. PKTSETLEN(osh, pkt, len);
  5097. PKTPULL(osh, pkt, doff);
  5098. #ifdef SDTEST
  5099. /* Test channel packets are processed separately */
  5100. if (chan == SDPCM_TEST_CHANNEL) {
  5101. dhdsdio_testrcv(bus, pkt, seq);
  5102. continue;
  5103. }
  5104. #endif /* SDTEST */
  5105. if (PKTLEN(osh, pkt) == 0) {
  5106. dhd_os_sdlock_rxq(bus->dhd);
  5107. PKTFREE(bus->dhd->osh, pkt, FALSE);
  5108. dhd_os_sdunlock_rxq(bus->dhd);
  5109. continue;
  5110. } else if (dhd_prot_hdrpull(bus->dhd, &ifidx, pkt, reorder_info_buf,
  5111. &reorder_info_len) != 0) {
  5112. DHD_ERROR(("%s: rx protocol error\n", __FUNCTION__));
  5113. dhd_os_sdlock_rxq(bus->dhd);
  5114. PKTFREE(bus->dhd->osh, pkt, FALSE);
  5115. dhd_os_sdunlock_rxq(bus->dhd);
  5116. bus->dhd->rx_errors++;
  5117. continue;
  5118. }
  5119. if (reorder_info_len) {
  5120. /* Reordering info from the firmware */
  5121. dhd_process_pkt_reorder_info(bus->dhd, reorder_info_buf, reorder_info_len,
  5122. &pkt, &pkt_count);
  5123. if (pkt_count == 0)
  5124. continue;
  5125. }
  5126. else
  5127. pkt_count = 1;
  5128. /* Unlock during rx call */
  5129. dhd_os_sdunlock(bus->dhd);
  5130. dhd_rx_frame(bus->dhd, ifidx, pkt, pkt_count, chan);
  5131. dhd_os_sdlock(bus->dhd);
  5132. }
  5133. rxcount = maxframes - rxleft;
  5134. #ifdef DHD_DEBUG
  5135. /* Message if we hit the limit */
  5136. if (!rxleft && !sdtest)
  5137. DHD_DATA(("%s: hit rx limit of %d frames\n", __FUNCTION__, maxframes));
  5138. else
  5139. #endif /* DHD_DEBUG */
  5140. DHD_DATA(("%s: processed %d frames\n", __FUNCTION__, rxcount));
  5141. /* Back off rxseq if awaiting rtx, update rx_seq */
  5142. if (bus->rxskip)
  5143. rxseq--;
  5144. bus->rx_seq = rxseq;
  5145. if (bus->reqbussleep)
  5146. {
  5147. dhdsdio_bussleep(bus, TRUE);
  5148. bus->reqbussleep = FALSE;
  5149. }
  5150. bus->readframes = FALSE;
  5151. return rxcount;
  5152. }
  5153. static uint32
  5154. dhdsdio_hostmail(dhd_bus_t *bus)
  5155. {
  5156. sdpcmd_regs_t *regs = bus->regs;
  5157. uint32 intstatus = 0;
  5158. uint32 hmb_data;
  5159. uint8 fcbits;
  5160. uint retries = 0;
  5161. DHD_TRACE(("%s: Enter\n", __FUNCTION__));
  5162. /* Read mailbox data and ack that we did so */
  5163. R_SDREG(hmb_data, &regs->tohostmailboxdata, retries);
  5164. if (retries <= retry_limit)
  5165. W_SDREG(SMB_INT_ACK, &regs->tosbmailbox, retries);
  5166. bus->f1regdata += 2;
  5167. /* Dongle recomposed rx frames, accept them again */
  5168. if (hmb_data & HMB_DATA_NAKHANDLED) {
  5169. DHD_INFO(("Dongle reports NAK handled, expect rtx of %d\n", bus->rx_seq));
  5170. if (!bus->rxskip) {
  5171. DHD_ERROR(("%s: unexpected NAKHANDLED!\n", __FUNCTION__));
  5172. }
  5173. bus->rxskip = FALSE;
  5174. intstatus |= FRAME_AVAIL_MASK(bus);
  5175. }
  5176. /*
  5177. * DEVREADY does not occur with gSPI.
  5178. */
  5179. if (hmb_data & (HMB_DATA_DEVREADY | HMB_DATA_FWREADY)) {
  5180. bus->sdpcm_ver = (hmb_data & HMB_DATA_VERSION_MASK) >> HMB_DATA_VERSION_SHIFT;
  5181. if (bus->sdpcm_ver != SDPCM_PROT_VERSION)
  5182. DHD_ERROR(("Version mismatch, dongle reports %d, expecting %d\n",
  5183. bus->sdpcm_ver, SDPCM_PROT_VERSION));
  5184. else
  5185. DHD_INFO(("Dongle ready, protocol version %d\n", bus->sdpcm_ver));
  5186. #ifndef BCMSPI
  5187. /* make sure for the SDIO_DEVICE_RXDATAINT_MODE_1 corecontrol is proper */
  5188. if ((bus->sih->buscoretype == SDIOD_CORE_ID) && (bus->sdpcmrev >= 4) &&
  5189. (bus->rxint_mode == SDIO_DEVICE_RXDATAINT_MODE_1)) {
  5190. uint32 val;
  5191. val = R_REG(bus->dhd->osh, &bus->regs->corecontrol);
  5192. val &= ~CC_XMTDATAAVAIL_MODE;
  5193. val |= CC_XMTDATAAVAIL_CTRL;
  5194. W_REG(bus->dhd->osh, &bus->regs->corecontrol, val);
  5195. val = R_REG(bus->dhd->osh, &bus->regs->corecontrol);
  5196. }
  5197. #endif /* BCMSPI */
  5198. #ifdef DHD_DEBUG
  5199. /* Retrieve console state address now that firmware should have updated it */
  5200. {
  5201. sdpcm_shared_t shared;
  5202. if (dhdsdio_readshared(bus, &shared) == 0)
  5203. bus->console_addr = shared.console_addr;
  5204. }
  5205. #endif /* DHD_DEBUG */
  5206. }
  5207. /*
  5208. * Flow Control has been moved into the RX headers and this out of band
  5209. * method isn't used any more. Leave this here for possibly remaining backward
  5210. * compatible with older dongles
  5211. */
  5212. if (hmb_data & HMB_DATA_FC) {
  5213. fcbits = (hmb_data & HMB_DATA_FCDATA_MASK) >> HMB_DATA_FCDATA_SHIFT;
  5214. if (fcbits & ~bus->flowcontrol)
  5215. bus->fc_xoff++;
  5216. if (bus->flowcontrol & ~fcbits)
  5217. bus->fc_xon++;
  5218. bus->fc_rcvd++;
  5219. bus->flowcontrol = fcbits;
  5220. }
  5221. #ifdef DHD_DEBUG
  5222. /* At least print a message if FW halted */
  5223. if (hmb_data & HMB_DATA_FWHALT) {
  5224. DHD_ERROR(("INTERNAL ERROR: FIRMWARE HALTED : set BUS DOWN\n"));
  5225. dhdsdio_checkdied(bus, NULL, 0);
  5226. bus->dhd->busstate = DHD_BUS_DOWN;
  5227. }
  5228. #endif /* DHD_DEBUG */
  5229. /* Shouldn't be any others */
  5230. if (hmb_data & ~(HMB_DATA_DEVREADY |
  5231. HMB_DATA_FWHALT |
  5232. HMB_DATA_NAKHANDLED |
  5233. HMB_DATA_FC |
  5234. HMB_DATA_FWREADY |
  5235. HMB_DATA_FCDATA_MASK |
  5236. HMB_DATA_VERSION_MASK)) {
  5237. DHD_ERROR(("Unknown mailbox data content: 0x%02x\n", hmb_data));
  5238. }
  5239. return intstatus;
  5240. }
  5241. static bool
  5242. dhdsdio_dpc(dhd_bus_t *bus)
  5243. {
  5244. bcmsdh_info_t *sdh = bus->sdh;
  5245. sdpcmd_regs_t *regs = bus->regs;
  5246. uint32 intstatus, newstatus = 0;
  5247. uint retries = 0;
  5248. uint rxlimit = dhd_rxbound; /* Rx frames to read before resched */
  5249. uint txlimit = dhd_txbound; /* Tx frames to send before resched */
  5250. uint framecnt = 0; /* Temporary counter of tx/rx frames */
  5251. bool rxdone = TRUE; /* Flag for no more read data */
  5252. bool resched = FALSE; /* Flag indicating resched wanted */
  5253. #if defined(CUSTOMER_HW4)
  5254. bool is_resched_by_readframe = FALSE;
  5255. #endif
  5256. DHD_TRACE(("%s: Enter\n", __FUNCTION__));
  5257. dhd_os_sdlock(bus->dhd);
  5258. if (bus->dhd->busstate == DHD_BUS_DOWN) {
  5259. DHD_ERROR(("%s: Bus down, ret\n", __FUNCTION__));
  5260. bus->intstatus = 0;
  5261. dhd_os_sdunlock(bus->dhd);
  5262. return 0;
  5263. }
  5264. /* Start with leftover status bits */
  5265. intstatus = bus->intstatus;
  5266. if (!SLPAUTO_ENAB(bus) && !KSO_ENAB(bus)) {
  5267. DHD_ERROR(("%s: Device asleep\n", __FUNCTION__));
  5268. goto exit;
  5269. }
  5270. /* If waiting for HTAVAIL, check status */
  5271. if (!SLPAUTO_ENAB(bus) && (bus->clkstate == CLK_PENDING)) {
  5272. int err;
  5273. uint8 clkctl, devctl = 0;
  5274. #ifdef DHD_DEBUG
  5275. /* Check for inconsistent device control */
  5276. devctl = bcmsdh_cfg_read(sdh, SDIO_FUNC_1, SBSDIO_DEVICE_CTL, &err);
  5277. if (err) {
  5278. DHD_ERROR(("%s: error reading DEVCTL: %d\n", __FUNCTION__, err));
  5279. bus->dhd->busstate = DHD_BUS_DOWN;
  5280. } else {
  5281. ASSERT(devctl & SBSDIO_DEVCTL_CA_INT_ONLY);
  5282. }
  5283. #endif /* DHD_DEBUG */
  5284. /* Read CSR, if clock on switch to AVAIL, else ignore */
  5285. clkctl = bcmsdh_cfg_read(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR, &err);
  5286. if (err) {
  5287. DHD_ERROR(("%s: error reading CSR: %d\n", __FUNCTION__, err));
  5288. bus->dhd->busstate = DHD_BUS_DOWN;
  5289. }
  5290. DHD_INFO(("DPC: PENDING, devctl 0x%02x clkctl 0x%02x\n", devctl, clkctl));
  5291. if (SBSDIO_HTAV(clkctl)) {
  5292. devctl = bcmsdh_cfg_read(sdh, SDIO_FUNC_1, SBSDIO_DEVICE_CTL, &err);
  5293. if (err) {
  5294. DHD_ERROR(("%s: error reading DEVCTL: %d\n",
  5295. __FUNCTION__, err));
  5296. bus->dhd->busstate = DHD_BUS_DOWN;
  5297. }
  5298. devctl &= ~SBSDIO_DEVCTL_CA_INT_ONLY;
  5299. bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_DEVICE_CTL, devctl, &err);
  5300. if (err) {
  5301. DHD_ERROR(("%s: error writing DEVCTL: %d\n",
  5302. __FUNCTION__, err));
  5303. bus->dhd->busstate = DHD_BUS_DOWN;
  5304. }
  5305. bus->clkstate = CLK_AVAIL;
  5306. } else {
  5307. goto clkwait;
  5308. }
  5309. }
  5310. BUS_WAKE(bus);
  5311. /* Make sure backplane clock is on */
  5312. dhdsdio_clkctl(bus, CLK_AVAIL, TRUE);
  5313. if (bus->clkstate != CLK_AVAIL)
  5314. goto clkwait;
  5315. /* Pending interrupt indicates new device status */
  5316. if (bus->ipend) {
  5317. bus->ipend = FALSE;
  5318. R_SDREG(newstatus, &regs->intstatus, retries);
  5319. bus->f1regdata++;
  5320. if (bcmsdh_regfail(bus->sdh))
  5321. newstatus = 0;
  5322. newstatus &= bus->hostintmask;
  5323. bus->fcstate = !!(newstatus & I_HMB_FC_STATE);
  5324. if (newstatus) {
  5325. bus->f1regdata++;
  5326. #ifndef BCMSPI
  5327. if ((bus->rxint_mode == SDIO_DEVICE_RXDATAINT_MODE_0) &&
  5328. (newstatus == I_XMTDATA_AVAIL)) {
  5329. }
  5330. else
  5331. #endif /* BCMSPI */
  5332. W_SDREG(newstatus, &regs->intstatus, retries);
  5333. }
  5334. }
  5335. /* Merge new bits with previous */
  5336. intstatus |= newstatus;
  5337. bus->intstatus = 0;
  5338. /* Handle flow-control change: read new state in case our ack
  5339. * crossed another change interrupt. If change still set, assume
  5340. * FC ON for safety, let next loop through do the debounce.
  5341. */
  5342. if (intstatus & I_HMB_FC_CHANGE) {
  5343. intstatus &= ~I_HMB_FC_CHANGE;
  5344. W_SDREG(I_HMB_FC_CHANGE, &regs->intstatus, retries);
  5345. R_SDREG(newstatus, &regs->intstatus, retries);
  5346. bus->f1regdata += 2;
  5347. bus->fcstate = !!(newstatus & (I_HMB_FC_STATE | I_HMB_FC_CHANGE));
  5348. intstatus |= (newstatus & bus->hostintmask);
  5349. }
  5350. /* Just being here means nothing more to do for chipactive */
  5351. if (intstatus & I_CHIPACTIVE) {
  5352. /* ASSERT(bus->clkstate == CLK_AVAIL); */
  5353. intstatus &= ~I_CHIPACTIVE;
  5354. }
  5355. /* Handle host mailbox indication */
  5356. if (intstatus & I_HMB_HOST_INT) {
  5357. intstatus &= ~I_HMB_HOST_INT;
  5358. intstatus |= dhdsdio_hostmail(bus);
  5359. }
  5360. /* Generally don't ask for these, can get CRC errors... */
  5361. if (intstatus & I_WR_OOSYNC) {
  5362. DHD_ERROR(("Dongle reports WR_OOSYNC\n"));
  5363. intstatus &= ~I_WR_OOSYNC;
  5364. }
  5365. if (intstatus & I_RD_OOSYNC) {
  5366. DHD_ERROR(("Dongle reports RD_OOSYNC\n"));
  5367. intstatus &= ~I_RD_OOSYNC;
  5368. }
  5369. if (intstatus & I_SBINT) {
  5370. DHD_ERROR(("Dongle reports SBINT\n"));
  5371. intstatus &= ~I_SBINT;
  5372. }
  5373. /* Would be active due to wake-wlan in gSPI */
  5374. if (intstatus & I_CHIPACTIVE) {
  5375. DHD_INFO(("Dongle reports CHIPACTIVE\n"));
  5376. intstatus &= ~I_CHIPACTIVE;
  5377. }
  5378. if (intstatus & I_HMB_FC_STATE) {
  5379. DHD_INFO(("Dongle reports HMB_FC_STATE\n"));
  5380. intstatus &= ~I_HMB_FC_STATE;
  5381. }
  5382. /* Ignore frame indications if rxskip is set */
  5383. if (bus->rxskip) {
  5384. intstatus &= ~FRAME_AVAIL_MASK(bus);
  5385. }
  5386. /* On frame indication, read available frames */
  5387. if (PKT_AVAILABLE(bus, intstatus)) {
  5388. framecnt = dhdsdio_readframes(bus, rxlimit, &rxdone);
  5389. if (rxdone || bus->rxskip)
  5390. intstatus &= ~FRAME_AVAIL_MASK(bus);
  5391. rxlimit -= MIN(framecnt, rxlimit);
  5392. }
  5393. /* Keep still-pending events for next scheduling */
  5394. bus->intstatus = intstatus;
  5395. clkwait:
  5396. /* Re-enable interrupts to detect new device events (mailbox, rx frame)
  5397. * or clock availability. (Allows tx loop to check ipend if desired.)
  5398. * (Unless register access seems hosed, as we may not be able to ACK...)
  5399. */
  5400. if (bus->intr && bus->intdis && !bcmsdh_regfail(sdh)) {
  5401. DHD_INTR(("%s: enable SDIO interrupts, rxdone %d framecnt %d\n",
  5402. __FUNCTION__, rxdone, framecnt));
  5403. bus->intdis = FALSE;
  5404. #if defined(OOB_INTR_ONLY)
  5405. bcmsdh_oob_intr_set(bus->sdh, TRUE);
  5406. #endif /* defined(OOB_INTR_ONLY) */
  5407. bcmsdh_intr_enable(sdh);
  5408. #ifdef BCMSPI_ANDROID
  5409. if (*dhd_spi_lockcount == 0)
  5410. bcmsdh_oob_intr_set(bus->sdh, TRUE);
  5411. #endif /* BCMSPI_ANDROID */
  5412. }
  5413. #if defined(OOB_INTR_ONLY) && !defined(HW_OOB)
  5414. /* In case of SW-OOB(using edge trigger),
  5415. * Check interrupt status in the dongle again after enable irq on the host.
  5416. * and rechedule dpc if interrupt is pended in the dongle.
  5417. * There is a chance to miss OOB interrupt while irq is disabled on the host.
  5418. * No need to do this with HW-OOB(level trigger)
  5419. */
  5420. R_SDREG(newstatus, &regs->intstatus, retries);
  5421. if (bcmsdh_regfail(bus->sdh))
  5422. newstatus = 0;
  5423. if (newstatus & bus->hostintmask) {
  5424. bus->ipend = TRUE;
  5425. resched = TRUE;
  5426. }
  5427. #endif /* defined(OOB_INTR_ONLY) && !defined(HW_OOB) */
  5428. #ifdef PROP_TXSTATUS
  5429. dhd_wlfc_commit_packets(bus->dhd, (f_commitpkt_t)dhd_bus_txdata, (void *)bus, NULL, FALSE);
  5430. #endif
  5431. if (TXCTLOK(bus) && bus->ctrl_frame_stat && (bus->clkstate == CLK_AVAIL))
  5432. dhdsdio_sendpendctl(bus);
  5433. /* Send queued frames (limit 1 if rx may still be pending) */
  5434. else if ((bus->clkstate == CLK_AVAIL) && !bus->fcstate &&
  5435. pktq_mlen(&bus->txq, ~bus->flowcontrol) && txlimit && DATAOK(bus)) {
  5436. framecnt = rxdone ? txlimit : MIN(txlimit, dhd_txminmax);
  5437. framecnt = dhdsdio_sendfromq(bus, framecnt);
  5438. txlimit -= framecnt;
  5439. }
  5440. /* Resched the DPC if ctrl cmd is pending on bus credit */
  5441. if (bus->ctrl_frame_stat)
  5442. resched = TRUE;
  5443. /* Resched if events or tx frames are pending, else await next interrupt */
  5444. /* On failed register access, all bets are off: no resched or interrupts */
  5445. if ((bus->dhd->busstate == DHD_BUS_DOWN) || bcmsdh_regfail(sdh)) {
  5446. if ((bus->sih && bus->sih->buscorerev >= 12) && !(dhdsdio_sleepcsr_get(bus) &
  5447. SBSDIO_FUNC1_SLEEPCSR_KSO_MASK)) {
  5448. /* Bus failed because of KSO */
  5449. DHD_ERROR(("%s: Bus failed due to KSO\n", __FUNCTION__));
  5450. bus->kso = FALSE;
  5451. } else {
  5452. DHD_ERROR(("%s: failed backplane access over SDIO, halting operation\n",
  5453. __FUNCTION__));
  5454. bus->dhd->busstate = DHD_BUS_DOWN;
  5455. bus->intstatus = 0;
  5456. }
  5457. } else if (bus->clkstate == CLK_PENDING) {
  5458. /* Awaiting I_CHIPACTIVE; don't resched */
  5459. } else if (bus->intstatus || bus->ipend ||
  5460. (!bus->fcstate && pktq_mlen(&bus->txq, ~bus->flowcontrol) && DATAOK(bus)) ||
  5461. PKT_AVAILABLE(bus, bus->intstatus)) { /* Read multiple frames */
  5462. resched = TRUE;
  5463. }
  5464. bus->dpc_sched = resched;
  5465. /* If we're done for now, turn off clock request. */
  5466. if ((bus->idletime == DHD_IDLE_IMMEDIATE) && (bus->clkstate != CLK_PENDING)) {
  5467. bus->activity = FALSE;
  5468. dhdsdio_clkctl(bus, CLK_NONE, FALSE);
  5469. }
  5470. exit:
  5471. if (!resched && dhd_dpcpoll) {
  5472. if (dhdsdio_readframes(bus, dhd_rxbound, &rxdone) != 0)
  5473. resched = TRUE;
  5474. #if defined(CUSTOMER_HW4)
  5475. is_resched_by_readframe = TRUE;
  5476. #endif
  5477. }
  5478. dhd_os_sdunlock(bus->dhd);
  5479. #if defined(CUSTOMER_HW4)
  5480. if (bus->dhd->dhd_bug_on) {
  5481. DHD_INFO(("%s: resched = %d ctrl_frame_stat = %d intstatus 0x%08x"
  5482. " ipend = %d pktq_mlen = %d is_resched_by_readframe = %d \n",
  5483. __FUNCTION__, resched, bus->ctrl_frame_stat,
  5484. bus->intstatus, bus->ipend,
  5485. pktq_mlen(&bus->txq, ~bus->flowcontrol), is_resched_by_readframe));
  5486. bus->dhd->dhd_bug_on = FALSE;
  5487. }
  5488. #endif
  5489. return resched;
  5490. }
  5491. bool
  5492. dhd_bus_dpc(struct dhd_bus *bus)
  5493. {
  5494. bool resched;
  5495. /* Call the DPC directly. */
  5496. DHD_TRACE(("Calling dhdsdio_dpc() from %s\n", __FUNCTION__));
  5497. resched = dhdsdio_dpc(bus);
  5498. return resched;
  5499. }
  5500. void
  5501. dhdsdio_isr(void *arg)
  5502. {
  5503. dhd_bus_t *bus = (dhd_bus_t*)arg;
  5504. bcmsdh_info_t *sdh;
  5505. DHD_TRACE(("%s: Enter\n", __FUNCTION__));
  5506. if (!bus) {
  5507. DHD_ERROR(("%s : bus is null pointer , exit \n", __FUNCTION__));
  5508. return;
  5509. }
  5510. sdh = bus->sdh;
  5511. if (bus->dhd->busstate == DHD_BUS_DOWN) {
  5512. DHD_ERROR(("%s : bus is down. we have nothing to do\n", __FUNCTION__));
  5513. return;
  5514. }
  5515. DHD_TRACE(("%s: Enter\n", __FUNCTION__));
  5516. /* Count the interrupt call */
  5517. bus->intrcount++;
  5518. bus->ipend = TRUE;
  5519. /* Shouldn't get this interrupt if we're sleeping? */
  5520. if (!SLPAUTO_ENAB(bus)) {
  5521. if (bus->sleeping) {
  5522. DHD_ERROR(("INTERRUPT WHILE SLEEPING??\n"));
  5523. return;
  5524. } else if (!KSO_ENAB(bus)) {
  5525. DHD_ERROR(("ISR in devsleep 1\n"));
  5526. }
  5527. }
  5528. /* Disable additional interrupts (is this needed now)? */
  5529. if (bus->intr) {
  5530. DHD_INTR(("%s: disable SDIO interrupts\n", __FUNCTION__));
  5531. } else {
  5532. DHD_ERROR(("dhdsdio_isr() w/o interrupt configured!\n"));
  5533. }
  5534. #ifdef BCMSPI_ANDROID
  5535. bcmsdh_oob_intr_set(bus->sdh, FALSE);
  5536. #endif /* BCMSPI_ANDROID */
  5537. bcmsdh_intr_disable(sdh);
  5538. bus->intdis = TRUE;
  5539. #if defined(SDIO_ISR_THREAD)
  5540. DHD_TRACE(("Calling dhdsdio_dpc() from %s\n", __FUNCTION__));
  5541. DHD_OS_WAKE_LOCK(bus->dhd);
  5542. dhdsdio_dpc(bus);
  5543. DHD_OS_WAKE_UNLOCK(bus->dhd);
  5544. #else
  5545. bus->dpc_sched = TRUE;
  5546. dhd_sched_dpc(bus->dhd);
  5547. #endif /* defined(SDIO_ISR_THREAD) */
  5548. }
  5549. #ifdef SDTEST
  5550. static void
  5551. dhdsdio_pktgen_init(dhd_bus_t *bus)
  5552. {
  5553. /* Default to specified length, or full range */
  5554. if (dhd_pktgen_len) {
  5555. bus->pktgen_maxlen = MIN(dhd_pktgen_len, MAX_PKTGEN_LEN);
  5556. bus->pktgen_minlen = bus->pktgen_maxlen;
  5557. } else {
  5558. bus->pktgen_maxlen = MAX_PKTGEN_LEN;
  5559. bus->pktgen_minlen = 0;
  5560. }
  5561. bus->pktgen_len = (uint16)bus->pktgen_minlen;
  5562. /* Default to per-watchdog burst with 10s print time */
  5563. bus->pktgen_freq = 1;
  5564. bus->pktgen_print = dhd_watchdog_ms ? (10000 / dhd_watchdog_ms) : 0;
  5565. bus->pktgen_count = (dhd_pktgen * dhd_watchdog_ms + 999) / 1000;
  5566. /* Default to echo mode */
  5567. bus->pktgen_mode = DHD_PKTGEN_ECHO;
  5568. bus->pktgen_stop = 1;
  5569. }
  5570. static void
  5571. dhdsdio_pktgen(dhd_bus_t *bus)
  5572. {
  5573. void *pkt;
  5574. uint8 *data;
  5575. uint pktcount;
  5576. uint fillbyte;
  5577. osl_t *osh = bus->dhd->osh;
  5578. uint16 len;
  5579. ulong time_lapse;
  5580. uint sent_pkts;
  5581. uint rcvd_pkts;
  5582. /* Display current count if appropriate */
  5583. if (bus->pktgen_print && (++bus->pktgen_ptick >= bus->pktgen_print)) {
  5584. bus->pktgen_ptick = 0;
  5585. printf("%s: send attempts %d, rcvd %d, errors %d\n",
  5586. __FUNCTION__, bus->pktgen_sent, bus->pktgen_rcvd, bus->pktgen_fail);
  5587. /* Print throughput stats only for constant length packet runs */
  5588. if (bus->pktgen_minlen == bus->pktgen_maxlen) {
  5589. time_lapse = jiffies - bus->pktgen_prev_time;
  5590. bus->pktgen_prev_time = jiffies;
  5591. sent_pkts = bus->pktgen_sent - bus->pktgen_prev_sent;
  5592. bus->pktgen_prev_sent = bus->pktgen_sent;
  5593. rcvd_pkts = bus->pktgen_rcvd - bus->pktgen_prev_rcvd;
  5594. bus->pktgen_prev_rcvd = bus->pktgen_rcvd;
  5595. printf("%s: Tx Throughput %d kbps, Rx Throughput %d kbps\n",
  5596. __FUNCTION__,
  5597. (sent_pkts * bus->pktgen_len / jiffies_to_msecs(time_lapse)) * 8,
  5598. (rcvd_pkts * bus->pktgen_len / jiffies_to_msecs(time_lapse)) * 8);
  5599. }
  5600. }
  5601. /* For recv mode, just make sure dongle has started sending */
  5602. if (bus->pktgen_mode == DHD_PKTGEN_RECV) {
  5603. if (bus->pktgen_rcv_state == PKTGEN_RCV_IDLE) {
  5604. bus->pktgen_rcv_state = PKTGEN_RCV_ONGOING;
  5605. dhdsdio_sdtest_set(bus, bus->pktgen_total);
  5606. }
  5607. return;
  5608. }
  5609. /* Otherwise, generate or request the specified number of packets */
  5610. for (pktcount = 0; pktcount < bus->pktgen_count; pktcount++) {
  5611. /* Stop if total has been reached */
  5612. if (bus->pktgen_total && (bus->pktgen_sent >= bus->pktgen_total)) {
  5613. bus->pktgen_count = 0;
  5614. break;
  5615. }
  5616. /* Allocate an appropriate-sized packet */
  5617. if (bus->pktgen_mode == DHD_PKTGEN_RXBURST) {
  5618. len = SDPCM_TEST_PKT_CNT_FLD_LEN;
  5619. } else {
  5620. len = bus->pktgen_len;
  5621. }
  5622. if (!(pkt = PKTGET(osh, (len + SDPCM_HDRLEN + SDPCM_TEST_HDRLEN + DHD_SDALIGN),
  5623. TRUE))) {;
  5624. DHD_ERROR(("%s: PKTGET failed!\n", __FUNCTION__));
  5625. break;
  5626. }
  5627. PKTALIGN(osh, pkt, (len + SDPCM_HDRLEN + SDPCM_TEST_HDRLEN), DHD_SDALIGN);
  5628. data = (uint8*)PKTDATA(osh, pkt) + SDPCM_HDRLEN;
  5629. /* Write test header cmd and extra based on mode */
  5630. switch (bus->pktgen_mode) {
  5631. case DHD_PKTGEN_ECHO:
  5632. *data++ = SDPCM_TEST_ECHOREQ;
  5633. *data++ = (uint8)bus->pktgen_sent;
  5634. break;
  5635. case DHD_PKTGEN_SEND:
  5636. *data++ = SDPCM_TEST_DISCARD;
  5637. *data++ = (uint8)bus->pktgen_sent;
  5638. break;
  5639. case DHD_PKTGEN_RXBURST:
  5640. *data++ = SDPCM_TEST_BURST;
  5641. *data++ = (uint8)bus->pktgen_count; /* Just for backward compatability */
  5642. break;
  5643. default:
  5644. DHD_ERROR(("Unrecognized pktgen mode %d\n", bus->pktgen_mode));
  5645. PKTFREE(osh, pkt, TRUE);
  5646. bus->pktgen_count = 0;
  5647. return;
  5648. }
  5649. /* Write test header length field */
  5650. *data++ = (bus->pktgen_len >> 0);
  5651. *data++ = (bus->pktgen_len >> 8);
  5652. /* Write frame count in a 4 byte field adjucent to SDPCM test header for
  5653. * burst mode
  5654. */
  5655. if (bus->pktgen_mode == DHD_PKTGEN_RXBURST) {
  5656. *data++ = (uint8)(bus->pktgen_count >> 0);
  5657. *data++ = (uint8)(bus->pktgen_count >> 8);
  5658. *data++ = (uint8)(bus->pktgen_count >> 16);
  5659. *data++ = (uint8)(bus->pktgen_count >> 24);
  5660. } else {
  5661. /* Then fill in the remainder -- N/A for burst */
  5662. for (fillbyte = 0; fillbyte < len; fillbyte++)
  5663. *data++ = SDPCM_TEST_FILL(fillbyte, (uint8)bus->pktgen_sent);
  5664. }
  5665. #ifdef DHD_DEBUG
  5666. if (DHD_BYTES_ON() && DHD_DATA_ON()) {
  5667. data = (uint8*)PKTDATA(osh, pkt) + SDPCM_HDRLEN;
  5668. prhex("dhdsdio_pktgen: Tx Data", data, PKTLEN(osh, pkt) - SDPCM_HDRLEN);
  5669. }
  5670. #endif
  5671. /* Send it */
  5672. if (dhdsdio_txpkt(bus, SDPCM_TEST_CHANNEL, &pkt, 1, TRUE) != BCME_OK) {
  5673. bus->pktgen_fail++;
  5674. if (bus->pktgen_stop && bus->pktgen_stop == bus->pktgen_fail)
  5675. bus->pktgen_count = 0;
  5676. }
  5677. bus->pktgen_sent++;
  5678. /* Bump length if not fixed, wrap at max */
  5679. if (++bus->pktgen_len > bus->pktgen_maxlen)
  5680. bus->pktgen_len = (uint16)bus->pktgen_minlen;
  5681. /* Special case for burst mode: just send one request! */
  5682. if (bus->pktgen_mode == DHD_PKTGEN_RXBURST)
  5683. break;
  5684. }
  5685. }
  5686. static void
  5687. dhdsdio_sdtest_set(dhd_bus_t *bus, uint count)
  5688. {
  5689. void *pkt;
  5690. uint8 *data;
  5691. osl_t *osh = bus->dhd->osh;
  5692. /* Allocate the packet */
  5693. if (!(pkt = PKTGET(osh, SDPCM_HDRLEN + SDPCM_TEST_HDRLEN +
  5694. SDPCM_TEST_PKT_CNT_FLD_LEN + DHD_SDALIGN, TRUE))) {
  5695. DHD_ERROR(("%s: PKTGET failed!\n", __FUNCTION__));
  5696. return;
  5697. }
  5698. PKTALIGN(osh, pkt, (SDPCM_HDRLEN + SDPCM_TEST_HDRLEN +
  5699. SDPCM_TEST_PKT_CNT_FLD_LEN), DHD_SDALIGN);
  5700. data = (uint8*)PKTDATA(osh, pkt) + SDPCM_HDRLEN;
  5701. /* Fill in the test header */
  5702. *data++ = SDPCM_TEST_SEND;
  5703. *data++ = (count > 0)?TRUE:FALSE;
  5704. *data++ = (bus->pktgen_maxlen >> 0);
  5705. *data++ = (bus->pktgen_maxlen >> 8);
  5706. *data++ = (uint8)(count >> 0);
  5707. *data++ = (uint8)(count >> 8);
  5708. *data++ = (uint8)(count >> 16);
  5709. *data++ = (uint8)(count >> 24);
  5710. /* Send it */
  5711. if (dhdsdio_txpkt(bus, SDPCM_TEST_CHANNEL, &pkt, 1, TRUE) != BCME_OK)
  5712. bus->pktgen_fail++;
  5713. }
  5714. static void
  5715. dhdsdio_testrcv(dhd_bus_t *bus, void *pkt, uint seq)
  5716. {
  5717. osl_t *osh = bus->dhd->osh;
  5718. uint8 *data;
  5719. uint pktlen;
  5720. uint8 cmd;
  5721. uint8 extra;
  5722. uint16 len;
  5723. uint16 offset;
  5724. /* Check for min length */
  5725. if ((pktlen = PKTLEN(osh, pkt)) < SDPCM_TEST_HDRLEN) {
  5726. DHD_ERROR(("dhdsdio_restrcv: toss runt frame, pktlen %d\n", pktlen));
  5727. PKTFREE(osh, pkt, FALSE);
  5728. return;
  5729. }
  5730. /* Extract header fields */
  5731. data = PKTDATA(osh, pkt);
  5732. cmd = *data++;
  5733. extra = *data++;
  5734. len = *data++; len += *data++ << 8;
  5735. DHD_TRACE(("%s:cmd:%d, xtra:%d,len:%d\n", __FUNCTION__, cmd, extra, len));
  5736. /* Check length for relevant commands */
  5737. if (cmd == SDPCM_TEST_DISCARD || cmd == SDPCM_TEST_ECHOREQ || cmd == SDPCM_TEST_ECHORSP) {
  5738. if (pktlen != len + SDPCM_TEST_HDRLEN) {
  5739. DHD_ERROR(("dhdsdio_testrcv: frame length mismatch, pktlen %d seq %d"
  5740. " cmd %d extra %d len %d\n", pktlen, seq, cmd, extra, len));
  5741. PKTFREE(osh, pkt, FALSE);
  5742. return;
  5743. }
  5744. }
  5745. /* Process as per command */
  5746. switch (cmd) {
  5747. case SDPCM_TEST_ECHOREQ:
  5748. /* Rx->Tx turnaround ok (even on NDIS w/current implementation) */
  5749. *(uint8 *)(PKTDATA(osh, pkt)) = SDPCM_TEST_ECHORSP;
  5750. if (dhdsdio_txpkt(bus, SDPCM_TEST_CHANNEL, &pkt, 1, TRUE) == BCME_OK) {
  5751. bus->pktgen_sent++;
  5752. } else {
  5753. bus->pktgen_fail++;
  5754. PKTFREE(osh, pkt, FALSE);
  5755. }
  5756. bus->pktgen_rcvd++;
  5757. break;
  5758. case SDPCM_TEST_ECHORSP:
  5759. if (bus->ext_loop) {
  5760. PKTFREE(osh, pkt, FALSE);
  5761. bus->pktgen_rcvd++;
  5762. break;
  5763. }
  5764. for (offset = 0; offset < len; offset++, data++) {
  5765. if (*data != SDPCM_TEST_FILL(offset, extra)) {
  5766. DHD_ERROR(("dhdsdio_testrcv: echo data mismatch: "
  5767. "offset %d (len %d) expect 0x%02x rcvd 0x%02x\n",
  5768. offset, len, SDPCM_TEST_FILL(offset, extra), *data));
  5769. break;
  5770. }
  5771. }
  5772. PKTFREE(osh, pkt, FALSE);
  5773. bus->pktgen_rcvd++;
  5774. break;
  5775. case SDPCM_TEST_DISCARD:
  5776. {
  5777. int i = 0;
  5778. uint8 *prn = data;
  5779. uint8 testval = extra;
  5780. for (i = 0; i < len; i++) {
  5781. if (*prn != testval) {
  5782. DHD_ERROR(("DIErr@Pkt#:%d,Ix:%d, expected:0x%x, got:0x%x\n",
  5783. i, bus->pktgen_rcvd_rcvsession, testval, *prn));
  5784. prn++; testval++;
  5785. }
  5786. }
  5787. }
  5788. PKTFREE(osh, pkt, FALSE);
  5789. bus->pktgen_rcvd++;
  5790. break;
  5791. case SDPCM_TEST_BURST:
  5792. case SDPCM_TEST_SEND:
  5793. default:
  5794. DHD_INFO(("dhdsdio_testrcv: unsupported or unknown command, pktlen %d seq %d"
  5795. " cmd %d extra %d len %d\n", pktlen, seq, cmd, extra, len));
  5796. PKTFREE(osh, pkt, FALSE);
  5797. break;
  5798. }
  5799. /* For recv mode, stop at limit (and tell dongle to stop sending) */
  5800. if (bus->pktgen_mode == DHD_PKTGEN_RECV) {
  5801. if (bus->pktgen_rcv_state != PKTGEN_RCV_IDLE) {
  5802. bus->pktgen_rcvd_rcvsession++;
  5803. if (bus->pktgen_total &&
  5804. (bus->pktgen_rcvd_rcvsession >= bus->pktgen_total)) {
  5805. bus->pktgen_count = 0;
  5806. DHD_ERROR(("Pktgen:rcv test complete!\n"));
  5807. bus->pktgen_rcv_state = PKTGEN_RCV_IDLE;
  5808. dhdsdio_sdtest_set(bus, FALSE);
  5809. bus->pktgen_rcvd_rcvsession = 0;
  5810. }
  5811. }
  5812. }
  5813. }
  5814. #endif /* SDTEST */
  5815. int dhd_bus_oob_intr_register(dhd_pub_t *dhdp)
  5816. {
  5817. int err = 0;
  5818. #if defined(OOB_INTR_ONLY) || defined(BCMSPI_ANDROID)
  5819. err = bcmsdh_oob_intr_register(dhdp->bus->sdh, dhdsdio_isr, dhdp->bus);
  5820. #endif
  5821. return err;
  5822. }
  5823. void dhd_bus_oob_intr_unregister(dhd_pub_t *dhdp)
  5824. {
  5825. #if defined(OOB_INTR_ONLY) || defined(BCMSPI_ANDROID)
  5826. bcmsdh_oob_intr_unregister(dhdp->bus->sdh);
  5827. #endif
  5828. }
  5829. void dhd_bus_oob_intr_set(dhd_pub_t *dhdp, bool enable)
  5830. {
  5831. #if defined(OOB_INTR_ONLY) || defined(BCMSPI_ANDROID)
  5832. bcmsdh_oob_intr_set(dhdp->bus->sdh, enable);
  5833. #endif
  5834. }
  5835. void dhd_bus_dev_pm_stay_awake(dhd_pub_t *dhdpub)
  5836. {
  5837. bcmsdh_dev_pm_stay_awake(dhdpub->bus->sdh);
  5838. }
  5839. void dhd_bus_dev_pm_relax(dhd_pub_t *dhdpub)
  5840. {
  5841. bcmsdh_dev_relax(dhdpub->bus->sdh);
  5842. }
  5843. bool dhd_bus_dev_pm_enabled(dhd_pub_t *dhdpub)
  5844. {
  5845. bool enabled = FALSE;
  5846. enabled = bcmsdh_dev_pm_enabled(dhdpub->bus->sdh);
  5847. return enabled;
  5848. }
  5849. extern bool
  5850. dhd_bus_watchdog(dhd_pub_t *dhdp)
  5851. {
  5852. dhd_bus_t *bus;
  5853. DHD_TIMER(("%s: Enter\n", __FUNCTION__));
  5854. bus = dhdp->bus;
  5855. if (bus->dhd->dongle_reset)
  5856. return FALSE;
  5857. if (bus->dhd->hang_was_sent) {
  5858. dhd_os_wd_timer(bus->dhd, 0);
  5859. return FALSE;
  5860. }
  5861. /* Ignore the timer if simulating bus down */
  5862. if (!SLPAUTO_ENAB(bus) && bus->sleeping)
  5863. return FALSE;
  5864. if (dhdp->busstate == DHD_BUS_DOWN)
  5865. return FALSE;
  5866. /* Poll period: check device if appropriate. */
  5867. if (!SLPAUTO_ENAB(bus) && (bus->poll && (++bus->polltick >= bus->pollrate))) {
  5868. uint32 intstatus = 0;
  5869. /* Reset poll tick */
  5870. bus->polltick = 0;
  5871. /* Check device if no interrupts */
  5872. if (!bus->intr || (bus->intrcount == bus->lastintrs)) {
  5873. #ifndef BCMSPI
  5874. if (!bus->dpc_sched) {
  5875. uint8 devpend;
  5876. devpend = bcmsdh_cfg_read(bus->sdh, SDIO_FUNC_0,
  5877. SDIOD_CCCR_INTPEND, NULL);
  5878. intstatus = devpend & (INTR_STATUS_FUNC1 | INTR_STATUS_FUNC2);
  5879. }
  5880. #else
  5881. if (!bus->dpc_sched) {
  5882. uint32 devpend;
  5883. devpend = bcmsdh_cfg_read_word(bus->sdh, SDIO_FUNC_0,
  5884. SPID_STATUS_REG, NULL);
  5885. intstatus = devpend & STATUS_F2_PKT_AVAILABLE;
  5886. }
  5887. #endif /* !BCMSPI */
  5888. /* If there is something, make like the ISR and schedule the DPC */
  5889. if (intstatus) {
  5890. bus->pollcnt++;
  5891. bus->ipend = TRUE;
  5892. if (bus->intr) {
  5893. bcmsdh_intr_disable(bus->sdh);
  5894. }
  5895. bus->dpc_sched = TRUE;
  5896. dhd_sched_dpc(bus->dhd);
  5897. }
  5898. }
  5899. /* Update interrupt tracking */
  5900. bus->lastintrs = bus->intrcount;
  5901. }
  5902. #ifdef DHD_DEBUG
  5903. /* Poll for console output periodically */
  5904. if (dhdp->busstate == DHD_BUS_DATA && dhd_console_ms != 0) {
  5905. bus->console.count += dhd_watchdog_ms;
  5906. if (bus->console.count >= dhd_console_ms) {
  5907. bus->console.count -= dhd_console_ms;
  5908. /* Make sure backplane clock is on */
  5909. if (SLPAUTO_ENAB(bus))
  5910. dhdsdio_bussleep(bus, FALSE);
  5911. else
  5912. dhdsdio_clkctl(bus, CLK_AVAIL, FALSE);
  5913. if (dhdsdio_readconsole(bus) < 0)
  5914. dhd_console_ms = 0; /* On error, stop trying */
  5915. }
  5916. }
  5917. #endif /* DHD_DEBUG */
  5918. #ifdef SDTEST
  5919. /* Generate packets if configured */
  5920. if (bus->pktgen_count && (++bus->pktgen_tick >= bus->pktgen_freq)) {
  5921. /* Make sure backplane clock is on */
  5922. if (SLPAUTO_ENAB(bus))
  5923. dhdsdio_bussleep(bus, FALSE);
  5924. else
  5925. dhdsdio_clkctl(bus, CLK_AVAIL, FALSE);
  5926. bus->pktgen_tick = 0;
  5927. dhdsdio_pktgen(bus);
  5928. }
  5929. #endif
  5930. /* On idle timeout clear activity flag and/or turn off clock */
  5931. #ifdef DHD_USE_IDLECOUNT
  5932. if (bus->activity)
  5933. bus->activity = FALSE;
  5934. else {
  5935. bus->idlecount++;
  5936. if ((bus->idletime > 0) && (bus->idlecount >= bus->idletime)) {
  5937. DHD_TIMER(("%s: DHD Idle state!!\n", __FUNCTION__));
  5938. if (SLPAUTO_ENAB(bus)) {
  5939. if (dhdsdio_bussleep(bus, TRUE) != BCME_BUSY)
  5940. dhd_os_wd_timer(bus->dhd, 0);
  5941. } else
  5942. dhdsdio_clkctl(bus, CLK_NONE, FALSE);
  5943. bus->idlecount = 0;
  5944. }
  5945. }
  5946. #else
  5947. if ((bus->idletime > 0) && (bus->clkstate == CLK_AVAIL)) {
  5948. if (++bus->idlecount >= bus->idletime) {
  5949. bus->idlecount = 0;
  5950. if (bus->activity) {
  5951. bus->activity = FALSE;
  5952. if (SLPAUTO_ENAB(bus)) {
  5953. if (!bus->readframes)
  5954. dhdsdio_bussleep(bus, TRUE);
  5955. else
  5956. bus->reqbussleep = TRUE;
  5957. }
  5958. else
  5959. dhdsdio_clkctl(bus, CLK_NONE, FALSE);
  5960. }
  5961. }
  5962. }
  5963. #endif /* DHD_USE_IDLECOUNT */
  5964. return bus->ipend;
  5965. }
  5966. #ifdef DHD_DEBUG
  5967. extern int
  5968. dhd_bus_console_in(dhd_pub_t *dhdp, uchar *msg, uint msglen)
  5969. {
  5970. dhd_bus_t *bus = dhdp->bus;
  5971. uint32 addr, val;
  5972. int rv;
  5973. void *pkt;
  5974. /* Address could be zero if CONSOLE := 0 in dongle Makefile */
  5975. if (bus->console_addr == 0)
  5976. return BCME_UNSUPPORTED;
  5977. /* Exclusive bus access */
  5978. dhd_os_sdlock(bus->dhd);
  5979. /* Don't allow input if dongle is in reset */
  5980. if (bus->dhd->dongle_reset) {
  5981. dhd_os_sdunlock(bus->dhd);
  5982. return BCME_NOTREADY;
  5983. }
  5984. /* Request clock to allow SDIO accesses */
  5985. BUS_WAKE(bus);
  5986. /* No pend allowed since txpkt is called later, ht clk has to be on */
  5987. dhdsdio_clkctl(bus, CLK_AVAIL, FALSE);
  5988. /* Zero cbuf_index */
  5989. addr = bus->console_addr + OFFSETOF(hndrte_cons_t, cbuf_idx);
  5990. val = htol32(0);
  5991. if ((rv = dhdsdio_membytes(bus, TRUE, addr, (uint8 *)&val, sizeof(val))) < 0)
  5992. goto done;
  5993. /* Write message into cbuf */
  5994. addr = bus->console_addr + OFFSETOF(hndrte_cons_t, cbuf);
  5995. if ((rv = dhdsdio_membytes(bus, TRUE, addr, (uint8 *)msg, msglen)) < 0)
  5996. goto done;
  5997. /* Write length into vcons_in */
  5998. addr = bus->console_addr + OFFSETOF(hndrte_cons_t, vcons_in);
  5999. val = htol32(msglen);
  6000. if ((rv = dhdsdio_membytes(bus, TRUE, addr, (uint8 *)&val, sizeof(val))) < 0)
  6001. goto done;
  6002. /* Bump dongle by sending an empty packet on the event channel.
  6003. * sdpcm_sendup (RX) checks for virtual console input.
  6004. */
  6005. if ((pkt = PKTGET(bus->dhd->osh, 4 + SDPCM_RESERVE, TRUE)) != NULL)
  6006. rv = dhdsdio_txpkt(bus, SDPCM_EVENT_CHANNEL, &pkt, 1, TRUE);
  6007. done:
  6008. if ((bus->idletime == DHD_IDLE_IMMEDIATE) && !bus->dpc_sched) {
  6009. bus->activity = FALSE;
  6010. dhdsdio_clkctl(bus, CLK_NONE, TRUE);
  6011. }
  6012. dhd_os_sdunlock(bus->dhd);
  6013. return rv;
  6014. }
  6015. #endif /* DHD_DEBUG */
  6016. #ifdef DHD_DEBUG
  6017. static void
  6018. dhd_dump_cis(uint fn, uint8 *cis)
  6019. {
  6020. uint byte, tag, tdata;
  6021. DHD_INFO(("Function %d CIS:\n", fn));
  6022. for (tdata = byte = 0; byte < SBSDIO_CIS_SIZE_LIMIT; byte++) {
  6023. if ((byte % 16) == 0)
  6024. DHD_INFO((" "));
  6025. DHD_INFO(("%02x ", cis[byte]));
  6026. if ((byte % 16) == 15)
  6027. DHD_INFO(("\n"));
  6028. if (!tdata--) {
  6029. tag = cis[byte];
  6030. if (tag == 0xff)
  6031. break;
  6032. else if (!tag)
  6033. tdata = 0;
  6034. else if ((byte + 1) < SBSDIO_CIS_SIZE_LIMIT)
  6035. tdata = cis[byte + 1] + 1;
  6036. else
  6037. DHD_INFO(("]"));
  6038. }
  6039. }
  6040. if ((byte % 16) != 15)
  6041. DHD_INFO(("\n"));
  6042. }
  6043. #endif /* DHD_DEBUG */
  6044. static bool
  6045. dhdsdio_chipmatch(uint16 chipid)
  6046. {
  6047. if (chipid == BCM4325_CHIP_ID)
  6048. return TRUE;
  6049. if (chipid == BCM4329_CHIP_ID)
  6050. return TRUE;
  6051. if (chipid == BCM4315_CHIP_ID)
  6052. return TRUE;
  6053. if (chipid == BCM4319_CHIP_ID)
  6054. return TRUE;
  6055. if (chipid == BCM4336_CHIP_ID)
  6056. return TRUE;
  6057. if (chipid == BCM4330_CHIP_ID)
  6058. return TRUE;
  6059. if (chipid == BCM43237_CHIP_ID)
  6060. return TRUE;
  6061. if (chipid == BCM43362_CHIP_ID)
  6062. return TRUE;
  6063. if (chipid == BCM4314_CHIP_ID)
  6064. return TRUE;
  6065. if (chipid == BCM43242_CHIP_ID)
  6066. return TRUE;
  6067. if (chipid == BCM43340_CHIP_ID)
  6068. return TRUE;
  6069. if (chipid == BCM43341_CHIP_ID)
  6070. return TRUE;
  6071. if (chipid == BCM43143_CHIP_ID)
  6072. return TRUE;
  6073. if (chipid == BCM43342_CHIP_ID)
  6074. return TRUE;
  6075. if (chipid == BCM4334_CHIP_ID)
  6076. return TRUE;
  6077. if (chipid == BCM43239_CHIP_ID)
  6078. return TRUE;
  6079. if (chipid == BCM4324_CHIP_ID)
  6080. return TRUE;
  6081. if (chipid == BCM4335_CHIP_ID)
  6082. return TRUE;
  6083. if (chipid == BCM4339_CHIP_ID)
  6084. return TRUE;
  6085. if (chipid == BCM43349_CHIP_ID)
  6086. return TRUE;
  6087. if (chipid == BCM4345_CHIP_ID || chipid == BCM43454_CHIP_ID)
  6088. return TRUE;
  6089. if (chipid == BCM4350_CHIP_ID)
  6090. return TRUE;
  6091. if (chipid == BCM4354_CHIP_ID)
  6092. return TRUE;
  6093. if (chipid == BCM4356_CHIP_ID)
  6094. return TRUE;
  6095. if (chipid == BCM43430_CHIP_ID)
  6096. return TRUE;
  6097. return FALSE;
  6098. }
  6099. static void *
  6100. dhdsdio_probe(uint16 venid, uint16 devid, uint16 bus_no, uint16 slot,
  6101. uint16 func, uint bustype, void *regsva, osl_t * osh, void *sdh)
  6102. {
  6103. int ret;
  6104. dhd_bus_t *bus;
  6105. #if defined(MULTIPLE_SUPPLICANT)
  6106. #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25))
  6107. if (mutex_is_locked(&_dhd_sdio_mutex_lock_) == 0) {
  6108. DHD_ERROR(("%s : no mutex held. set lock\n", __FUNCTION__));
  6109. }
  6110. else {
  6111. DHD_ERROR(("%s : mutex is locked!. wait for unlocking\n", __FUNCTION__));
  6112. }
  6113. mutex_lock(&_dhd_sdio_mutex_lock_);
  6114. #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)) */
  6115. #endif
  6116. /* Init global variables at run-time, not as part of the declaration.
  6117. * This is required to support init/de-init of the driver. Initialization
  6118. * of globals as part of the declaration results in non-deterministic
  6119. * behavior since the value of the globals may be different on the
  6120. * first time that the driver is initialized vs subsequent initializations.
  6121. */
  6122. dhd_txbound = DHD_TXBOUND;
  6123. dhd_rxbound = DHD_RXBOUND;
  6124. #ifdef BCMSPI
  6125. dhd_alignctl = FALSE;
  6126. #else
  6127. dhd_alignctl = TRUE;
  6128. #endif /* BCMSPI */
  6129. sd1idle = TRUE;
  6130. dhd_readahead = TRUE;
  6131. retrydata = FALSE;
  6132. #if defined(DISABLE_FLOW_CONTROL)
  6133. dhd_doflow = FALSE;
  6134. #else
  6135. #if !defined(PLATFORM_MPS) && !defined(CUSTOMER_HW4)
  6136. dhd_doflow = FALSE;
  6137. #else
  6138. dhd_doflow = TRUE;
  6139. #endif /* OEM_ANDROID */
  6140. #endif /* DISABLE_FLOW_CONTROL */
  6141. dhd_dongle_ramsize = 0;
  6142. dhd_txminmax = DHD_TXMINMAX;
  6143. #ifdef BCMSPI
  6144. forcealign = FALSE;
  6145. #else
  6146. forcealign = TRUE;
  6147. #endif /* !BCMSPI */
  6148. DHD_TRACE(("%s: Enter\n", __FUNCTION__));
  6149. DHD_INFO(("%s: venid 0x%04x devid 0x%04x\n", __FUNCTION__, venid, devid));
  6150. /* We make assumptions about address window mappings */
  6151. ASSERT((uintptr)regsva == SI_ENUM_BASE);
  6152. /* BCMSDH passes venid and devid based on CIS parsing -- but low-power start
  6153. * means early parse could fail, so here we should get either an ID
  6154. * we recognize OR (-1) indicating we must request power first.
  6155. */
  6156. /* Check the Vendor ID */
  6157. switch (venid) {
  6158. case 0x0000:
  6159. case VENDOR_BROADCOM:
  6160. break;
  6161. default:
  6162. DHD_ERROR(("%s: unknown vendor: 0x%04x\n",
  6163. __FUNCTION__, venid));
  6164. goto forcereturn;
  6165. }
  6166. /* Check the Device ID and make sure it's one that we support */
  6167. switch (devid) {
  6168. case BCM4325_D11DUAL_ID: /* 4325 802.11a/g id */
  6169. case BCM4325_D11G_ID: /* 4325 802.11g 2.4Ghz band id */
  6170. case BCM4325_D11A_ID: /* 4325 802.11a 5Ghz band id */
  6171. DHD_INFO(("%s: found 4325 Dongle\n", __FUNCTION__));
  6172. break;
  6173. case BCM4329_D11N_ID: /* 4329 802.11n dualband device */
  6174. case BCM4329_D11N2G_ID: /* 4329 802.11n 2.4G device */
  6175. case BCM4329_D11N5G_ID: /* 4329 802.11n 5G device */
  6176. case 0x4329:
  6177. DHD_INFO(("%s: found 4329 Dongle\n", __FUNCTION__));
  6178. break;
  6179. case BCM4315_D11DUAL_ID: /* 4315 802.11a/g id */
  6180. case BCM4315_D11G_ID: /* 4315 802.11g id */
  6181. case BCM4315_D11A_ID: /* 4315 802.11a id */
  6182. DHD_INFO(("%s: found 4315 Dongle\n", __FUNCTION__));
  6183. break;
  6184. case BCM4319_D11N_ID: /* 4319 802.11n id */
  6185. case BCM4319_D11N2G_ID: /* 4319 802.11n2g id */
  6186. case BCM4319_D11N5G_ID: /* 4319 802.11n5g id */
  6187. DHD_INFO(("%s: found 4319 Dongle\n", __FUNCTION__));
  6188. break;
  6189. case 0:
  6190. DHD_INFO(("%s: allow device id 0, will check chip internals\n",
  6191. __FUNCTION__));
  6192. break;
  6193. default:
  6194. DHD_ERROR(("%s: skipping 0x%04x/0x%04x, not a dongle\n",
  6195. __FUNCTION__, venid, devid));
  6196. goto forcereturn;
  6197. }
  6198. if (osh == NULL) {
  6199. DHD_ERROR(("%s: osh is NULL!\n", __FUNCTION__));
  6200. goto forcereturn;
  6201. }
  6202. /* Allocate private bus interface state */
  6203. if (!(bus = MALLOC(osh, sizeof(dhd_bus_t)))) {
  6204. DHD_ERROR(("%s: MALLOC of dhd_bus_t failed\n", __FUNCTION__));
  6205. goto fail;
  6206. }
  6207. bzero(bus, sizeof(dhd_bus_t));
  6208. bus->sdh = sdh;
  6209. bus->cl_devid = (uint16)devid;
  6210. bus->bus = DHD_BUS;
  6211. bus->bus_num = bus_no;
  6212. bus->slot_num = slot;
  6213. bus->tx_seq = SDPCM_SEQUENCE_WRAP - 1;
  6214. bus->usebufpool = FALSE; /* Use bufpool if allocated, else use locally malloced rxbuf */
  6215. #if defined(SUPPORT_P2P_GO_PS)
  6216. init_waitqueue_head(&bus->bus_sleep);
  6217. #endif /* LINUX && SUPPORT_P2P_GO_PS */
  6218. /* attempt to attach to the dongle */
  6219. if (!(dhdsdio_probe_attach(bus, osh, sdh, regsva, devid))) {
  6220. DHD_ERROR(("%s: dhdsdio_probe_attach failed\n", __FUNCTION__));
  6221. goto fail;
  6222. }
  6223. /* Attach to the dhd/OS/network interface */
  6224. if (!(bus->dhd = dhd_attach(osh, bus, SDPCM_RESERVE))) {
  6225. DHD_ERROR(("%s: dhd_attach failed\n", __FUNCTION__));
  6226. goto fail;
  6227. }
  6228. /* Allocate buffers */
  6229. if (!(dhdsdio_probe_malloc(bus, osh, sdh))) {
  6230. DHD_ERROR(("%s: dhdsdio_probe_malloc failed\n", __FUNCTION__));
  6231. goto fail;
  6232. }
  6233. if (!(dhdsdio_probe_init(bus, osh, sdh))) {
  6234. DHD_ERROR(("%s: dhdsdio_probe_init failed\n", __FUNCTION__));
  6235. goto fail;
  6236. }
  6237. if (bus->intr) {
  6238. /* Register interrupt callback, but mask it (not operational yet). */
  6239. DHD_INTR(("%s: disable SDIO interrupts (not interested yet)\n", __FUNCTION__));
  6240. bcmsdh_intr_disable(sdh);
  6241. if ((ret = bcmsdh_intr_reg(sdh, dhdsdio_isr, bus)) != 0) {
  6242. DHD_ERROR(("%s: FAILED: bcmsdh_intr_reg returned %d\n",
  6243. __FUNCTION__, ret));
  6244. goto fail;
  6245. }
  6246. DHD_INTR(("%s: registered SDIO interrupt function ok\n", __FUNCTION__));
  6247. } else {
  6248. DHD_INFO(("%s: SDIO interrupt function is NOT registered due to polling mode\n",
  6249. __FUNCTION__));
  6250. }
  6251. DHD_INFO(("%s: completed!!\n", __FUNCTION__));
  6252. /* if firmware path present try to download and bring up bus */
  6253. bus->dhd->hang_report = TRUE;
  6254. if (dhd_download_fw_on_driverload) {
  6255. if ((ret = dhd_bus_start(bus->dhd)) != 0) {
  6256. DHD_ERROR(("%s: dhd_bus_start failed\n", __FUNCTION__));
  6257. goto fail;
  6258. }
  6259. }
  6260. #ifdef CUSTOMER_HW4
  6261. else {
  6262. /* Set ramdom MAC address during boot time */
  6263. get_random_bytes(&bus->dhd->mac.octet[3], 3);
  6264. /* Adding BRCM OUI */
  6265. bus->dhd->mac.octet[0] = 0;
  6266. bus->dhd->mac.octet[1] = 0x90;
  6267. bus->dhd->mac.octet[2] = 0x4C;
  6268. }
  6269. #endif /* CUSTOMER_HW4 */
  6270. /* Ok, have the per-port tell the stack we're open for business */
  6271. if (dhd_register_if(bus->dhd, 0, TRUE) != 0) {
  6272. DHD_ERROR(("%s: Net attach failed!!\n", __FUNCTION__));
  6273. goto fail;
  6274. }
  6275. #if defined(MULTIPLE_SUPPLICANT)
  6276. #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25))
  6277. mutex_unlock(&_dhd_sdio_mutex_lock_);
  6278. DHD_ERROR(("%s : the lock is released.\n", __FUNCTION__));
  6279. #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) */
  6280. #endif
  6281. return bus;
  6282. fail:
  6283. dhdsdio_release(bus, osh);
  6284. forcereturn:
  6285. #if defined(MULTIPLE_SUPPLICANT)
  6286. #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25))
  6287. mutex_unlock(&_dhd_sdio_mutex_lock_);
  6288. DHD_ERROR(("%s : the lock is released.\n", __FUNCTION__));
  6289. #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) */
  6290. #endif
  6291. return NULL;
  6292. }
  6293. #ifdef REGON_BP_HANG_FIX
  6294. static int dhd_sdio_backplane_reset(struct dhd_bus *bus)
  6295. {
  6296. uint32 temp = 0;
  6297. DHD_ERROR(("Resetting the backplane to avoid failure in firmware download..\n"));
  6298. temp = bcmsdh_reg_read(bus->sdh, 0x180021e0, 4);
  6299. DHD_INFO(("SDIO Clk Control Reg = %x\n", temp));
  6300. /* Force HT req from PMU */
  6301. bcmsdh_reg_write(bus->sdh, 0x18000644, 4, 0x6000005);
  6302. /* Increase the clock stretch duration. */
  6303. bcmsdh_reg_write(bus->sdh, 0x18000630, 4, 0xC8FFC8);
  6304. /* Setting ALP clock request in SDIOD clock control status register */
  6305. bcmsdh_reg_write(bus->sdh, 0x180021e0, 4, 0x41);
  6306. /* Allowing clock from SR engine to SR memory */
  6307. bcmsdh_reg_write(bus->sdh, 0x18004400, 4, 0xf92f1);
  6308. /* Disabling SR Engine before SR binary download. */
  6309. bcmsdh_reg_write(bus->sdh, 0x18000650, 4, 0x3);
  6310. bcmsdh_reg_write(bus->sdh, 0x18000654, 4, 0x0);
  6311. /* Enabling clock from backplane to SR memory */
  6312. bcmsdh_reg_write(bus->sdh, 0x18004400, 4, 0xf9af1);
  6313. /* Initializing SR memory address register in SOCRAM */
  6314. bcmsdh_reg_write(bus->sdh, 0x18004408, 4, 0x0);
  6315. /* Downloading the SR binary */
  6316. bcmsdh_reg_write(bus->sdh, 0x1800440c, 4, 0x00000000);
  6317. bcmsdh_reg_write(bus->sdh, 0x1800440c, 4, 0x00000000);
  6318. bcmsdh_reg_write(bus->sdh, 0x1800440c, 4, 0x00000000);
  6319. bcmsdh_reg_write(bus->sdh, 0x1800440c, 4, 0x00000000);
  6320. bcmsdh_reg_write(bus->sdh, 0x1800440c, 4, 0x00000000);
  6321. bcmsdh_reg_write(bus->sdh, 0x1800440c, 4, 0x00000000);
  6322. bcmsdh_reg_write(bus->sdh, 0x1800440c, 4, 0x00000000);
  6323. bcmsdh_reg_write(bus->sdh, 0x1800440c, 4, 0xc0002000);
  6324. bcmsdh_reg_write(bus->sdh, 0x1800440c, 4, 0x00000000);
  6325. bcmsdh_reg_write(bus->sdh, 0x1800440c, 4, 0x00000000);
  6326. bcmsdh_reg_write(bus->sdh, 0x1800440c, 4, 0x00000000);
  6327. bcmsdh_reg_write(bus->sdh, 0x1800440c, 4, 0x00000000);
  6328. bcmsdh_reg_write(bus->sdh, 0x1800440c, 4, 0x00000000);
  6329. bcmsdh_reg_write(bus->sdh, 0x1800440c, 4, 0x00000000);
  6330. bcmsdh_reg_write(bus->sdh, 0x1800440c, 4, 0x00000000);
  6331. bcmsdh_reg_write(bus->sdh, 0x1800440c, 4, 0x00000000);
  6332. bcmsdh_reg_write(bus->sdh, 0x1800440c, 4, 0x00000000);
  6333. bcmsdh_reg_write(bus->sdh, 0x1800440c, 4, 0x00000000);
  6334. bcmsdh_reg_write(bus->sdh, 0x1800440c, 4, 0x00000000);
  6335. bcmsdh_reg_write(bus->sdh, 0x1800440c, 4, 0x00000000);
  6336. bcmsdh_reg_write(bus->sdh, 0x1800440c, 4, 0x00000000);
  6337. bcmsdh_reg_write(bus->sdh, 0x1800440c, 4, 0x00000000);
  6338. bcmsdh_reg_write(bus->sdh, 0x1800440c, 4, 0x00000000);
  6339. bcmsdh_reg_write(bus->sdh, 0x1800440c, 4, 0x00000000);
  6340. bcmsdh_reg_write(bus->sdh, 0x1800440c, 4, 0x00000000);
  6341. bcmsdh_reg_write(bus->sdh, 0x1800440c, 4, 0x00000000);
  6342. bcmsdh_reg_write(bus->sdh, 0x1800440c, 4, 0x00000000);
  6343. bcmsdh_reg_write(bus->sdh, 0x1800440c, 4, 0x00000000);
  6344. bcmsdh_reg_write(bus->sdh, 0x1800440c, 4, 0x00000000);
  6345. bcmsdh_reg_write(bus->sdh, 0x1800440c, 4, 0x00000000);
  6346. bcmsdh_reg_write(bus->sdh, 0x1800440c, 4, 0x00000000);
  6347. bcmsdh_reg_write(bus->sdh, 0x1800440c, 4, 0x00000000);
  6348. bcmsdh_reg_write(bus->sdh, 0x1800440c, 4, 0x80008000);
  6349. bcmsdh_reg_write(bus->sdh, 0x1800440c, 4, 0x1051f080);
  6350. bcmsdh_reg_write(bus->sdh, 0x1800440c, 4, 0x80008000);
  6351. bcmsdh_reg_write(bus->sdh, 0x1800440c, 4, 0x1050f080);
  6352. bcmsdh_reg_write(bus->sdh, 0x1800440c, 4, 0x80008000);
  6353. bcmsdh_reg_write(bus->sdh, 0x1800440c, 4, 0x1050f080);
  6354. bcmsdh_reg_write(bus->sdh, 0x1800440c, 4, 0x80008000);
  6355. bcmsdh_reg_write(bus->sdh, 0x1800440c, 4, 0x1050f080);
  6356. bcmsdh_reg_write(bus->sdh, 0x1800440c, 4, 0x00000004);
  6357. bcmsdh_reg_write(bus->sdh, 0x1800440c, 4, 0x30a00000);
  6358. bcmsdh_reg_write(bus->sdh, 0x1800440c, 4, 0x00000604);
  6359. bcmsdh_reg_write(bus->sdh, 0x1800440c, 4, 0x30a00000);
  6360. bcmsdh_reg_write(bus->sdh, 0x1800440c, 4, 0x00001604);
  6361. bcmsdh_reg_write(bus->sdh, 0x1800440c, 4, 0x30a00000);
  6362. bcmsdh_reg_write(bus->sdh, 0x1800440c, 4, 0x00001404);
  6363. bcmsdh_reg_write(bus->sdh, 0x1800440c, 4, 0x30a08c80);
  6364. bcmsdh_reg_write(bus->sdh, 0x1800440c, 4, 0x00010001);
  6365. bcmsdh_reg_write(bus->sdh, 0x1800440c, 4, 0x14a00000);
  6366. bcmsdh_reg_write(bus->sdh, 0x1800440c, 4, 0x00011404);
  6367. bcmsdh_reg_write(bus->sdh, 0x1800440c, 4, 0x30a00000);
  6368. bcmsdh_reg_write(bus->sdh, 0x1800440c, 4, 0x00002000);
  6369. bcmsdh_reg_write(bus->sdh, 0x1800440c, 4, 0x04a00000);
  6370. bcmsdh_reg_write(bus->sdh, 0x1800440c, 4, 0x00002000);
  6371. bcmsdh_reg_write(bus->sdh, 0x1800440c, 4, 0xf8000000);
  6372. bcmsdh_reg_write(bus->sdh, 0x1800440c, 4, 0x00002000);
  6373. bcmsdh_reg_write(bus->sdh, 0x1800440c, 4, 0x04a00000);
  6374. bcmsdh_reg_write(bus->sdh, 0x1800440c, 4, 0x00002000);
  6375. bcmsdh_reg_write(bus->sdh, 0x1800440c, 4, 0xf8000000);
  6376. bcmsdh_reg_write(bus->sdh, 0x1800440c, 4, 0x00011604);
  6377. bcmsdh_reg_write(bus->sdh, 0x1800440c, 4, 0x30a00000);
  6378. bcmsdh_reg_write(bus->sdh, 0x1800440c, 4, 0x00010604);
  6379. bcmsdh_reg_write(bus->sdh, 0x1800440c, 4, 0x30a00000);
  6380. bcmsdh_reg_write(bus->sdh, 0x1800440c, 4, 0x00010004);
  6381. bcmsdh_reg_write(bus->sdh, 0x1800440c, 4, 0x30a00000);
  6382. bcmsdh_reg_write(bus->sdh, 0x1800440c, 4, 0x00010000);
  6383. bcmsdh_reg_write(bus->sdh, 0x1800440c, 4, 0x14a00000);
  6384. bcmsdh_reg_write(bus->sdh, 0x1800440c, 4, 0x00000004);
  6385. bcmsdh_reg_write(bus->sdh, 0x1800440c, 4, 0x30a00000);
  6386. bcmsdh_reg_write(bus->sdh, 0x1800440c, 4, 0x00010001);
  6387. bcmsdh_reg_write(bus->sdh, 0x1800440c, 4, 0x14a00000);
  6388. bcmsdh_reg_write(bus->sdh, 0x1800440c, 4, 0x00010004);
  6389. bcmsdh_reg_write(bus->sdh, 0x1800440c, 4, 0x30a00000);
  6390. bcmsdh_reg_write(bus->sdh, 0x1800440c, 4, 0x00010000);
  6391. bcmsdh_reg_write(bus->sdh, 0x1800440c, 4, 0x30a00000);
  6392. bcmsdh_reg_write(bus->sdh, 0x1800440c, 4, 0x00010000);
  6393. bcmsdh_reg_write(bus->sdh, 0x1800440c, 4, 0x14a00000);
  6394. bcmsdh_reg_write(bus->sdh, 0x1800440c, 4, 0x00000000);
  6395. bcmsdh_reg_write(bus->sdh, 0x1800440c, 4, 0x30a00000);
  6396. bcmsdh_reg_write(bus->sdh, 0x1800440c, 4, 0x00000008);
  6397. bcmsdh_reg_write(bus->sdh, 0x1800440c, 4, 0x04a00000);
  6398. bcmsdh_reg_write(bus->sdh, 0x1800440c, 4, 0x00000008);
  6399. bcmsdh_reg_write(bus->sdh, 0x1800440c, 4, 0xfc000000);
  6400. /* SR Binary Download complete */
  6401. /* Allowing clock from SR engine to SR memory */
  6402. bcmsdh_reg_write(bus->sdh, 0x18004400, 4, 0xf92f1);
  6403. /* Turning ON SR Engine to initiate backplane reset Repeated ?? Maharana */
  6404. bcmsdh_reg_write(bus->sdh, 0x18000650, 4, 0x3);
  6405. bcmsdh_reg_write(bus->sdh, 0x18000654, 4, 0x0);
  6406. bcmsdh_reg_write(bus->sdh, 0x18000650, 4, 0x3);
  6407. bcmsdh_reg_write(bus->sdh, 0x18000654, 4, 0x2);
  6408. bcmsdh_reg_write(bus->sdh, 0x18000650, 4, 0x3);
  6409. bcmsdh_reg_write(bus->sdh, 0x18000654, 4, 0x3);
  6410. bcmsdh_reg_write(bus->sdh, 0x18000650, 4, 0x3);
  6411. bcmsdh_reg_write(bus->sdh, 0x18000654, 4, 0x37);
  6412. bcmsdh_reg_write(bus->sdh, 0x18000650, 4, 0x3);
  6413. temp = bcmsdh_reg_read(bus->sdh, 0x18000654, 4);
  6414. DHD_INFO(("0x18000654 = %x\n", temp));
  6415. bcmsdh_reg_write(bus->sdh, 0x18000654, 4, 0x800037);
  6416. OSL_DELAY(100000);
  6417. /* Rolling back the original values for clock stretch and PMU timers */
  6418. bcmsdh_reg_write(bus->sdh, 0x18000644, 4, 0x0);
  6419. bcmsdh_reg_write(bus->sdh, 0x18000630, 4, 0xC800C8);
  6420. /* Removing ALP clock request in SDIOD clock control status register */
  6421. bcmsdh_reg_write(bus->sdh, 0x180021e0, 4, 0x40);
  6422. OSL_DELAY(10000);
  6423. return TRUE;
  6424. }
  6425. static int dhdsdio_sdio_hang_war(struct dhd_bus *bus)
  6426. {
  6427. uint32 temp = 0, temp2 = 0, counter = 0, BT_pwr_up = 0, BT_ready = 0;
  6428. /* Removing reset of D11 Core */
  6429. bcmsdh_reg_write(bus->sdh, 0x18101408, 4, 0x3);
  6430. bcmsdh_reg_write(bus->sdh, 0x18101800, 4, 0x0);
  6431. bcmsdh_reg_write(bus->sdh, 0x18101408, 4, 0x1);
  6432. /* Reading CLB XTAL BT cntrl register */
  6433. bcmsdh_reg_write(bus->sdh, 0x180013D8, 2, 0xD1);
  6434. bcmsdh_reg_write(bus->sdh, 0x180013DA, 2, 0x12);
  6435. bcmsdh_reg_write(bus->sdh, 0x180013D8, 2, 0x2D0);
  6436. /* Read if BT is powered up */
  6437. temp = bcmsdh_reg_read(bus->sdh, 0x180013DA, 2);
  6438. /* Read BT_ready from WLAN wireless register */
  6439. temp2 = bcmsdh_reg_read(bus->sdh, 0x1800002C, 4);
  6440. /*
  6441. Check if the BT is powered up and ready. The duration between BT being powered up
  6442. and BT becoming ready is the problematic window for WLAN. If we move ahead at this
  6443. time then we may encounter a corrupted backplane later. So we wait for BT to be ready
  6444. and then proceed after checking the health of the backplane. If the backplane shows
  6445. indications of failure then we have to do a full reset of the backplane using SR engine
  6446. and then proceed.
  6447. */
  6448. (temp & 0xF0) ? (BT_pwr_up = 1):(BT_pwr_up = 0);
  6449. (temp2 & (1<<17)) ? (BT_ready = 1):(BT_ready = 0);
  6450. DHD_ERROR(("WARNING: Checking if BT is ready BT_pwr_up = %x"
  6451. "BT_ready = %x \n", BT_pwr_up, BT_ready));
  6452. while (BT_pwr_up && !BT_ready)
  6453. {
  6454. OSL_DELAY(1000);
  6455. bcmsdh_reg_write(bus->sdh, 0x180013D8, 2, 0x2D0);
  6456. temp = bcmsdh_reg_read(bus->sdh, 0x180013DA, 2);
  6457. temp2 = bcmsdh_reg_read(bus->sdh, 0x1800002C, 4);
  6458. (temp & 0xF0) ? (BT_pwr_up = 1):(BT_pwr_up = 0);
  6459. (temp2 & (1<<17)) ? (BT_ready = 1):(BT_ready = 0);
  6460. counter++;
  6461. if (counter == 5000)
  6462. {
  6463. DHD_ERROR(("WARNING: Going ahead after 5 secs with"
  6464. "risk of failure because BT ready is not yet set\n"));
  6465. break;
  6466. }
  6467. }
  6468. DHD_ERROR(("\nWARNING: WL Proceeding BT_pwr_up = %x BT_ready = %x"
  6469. "\n", BT_pwr_up, BT_ready));
  6470. counter = 0;
  6471. OSL_DELAY(10000);
  6472. /*
  6473. Get the information of who accessed the crucial backplane entities
  6474. by reading read and write access registers
  6475. */
  6476. DHD_TRACE(("%d: Read Value @ 0x18104808 = %x."
  6477. "\n", __LINE__, bcmsdh_reg_read(bus->sdh, 0x18104808, 4)));
  6478. DHD_TRACE(("%d: Read Value @ 0x1810480C = %x."
  6479. "\n", __LINE__, bcmsdh_reg_read(bus->sdh, 0x1810480C, 4)));
  6480. DHD_TRACE(("%d: Read Value @ 0x18106808 = %x."
  6481. "\n", __LINE__, bcmsdh_reg_read(bus->sdh, 0x18106808, 4)));
  6482. DHD_TRACE(("%d: Read Value @ 0x1810680C = %x."
  6483. "\n", __LINE__, bcmsdh_reg_read(bus->sdh, 0x1810680C, 4)));
  6484. DHD_TRACE(("%d: Read Value @ 0x18107808 = %x."
  6485. "\n", __LINE__, bcmsdh_reg_read(bus->sdh, 0x18107808, 4)));
  6486. DHD_TRACE(("%d: Read Value @ 0x1810780C = %x."
  6487. "\n", __LINE__, bcmsdh_reg_read(bus->sdh, 0x1810780C, 4)));
  6488. DHD_TRACE(("%d: Read Value @ 0x18108808 = %x."
  6489. "\n", __LINE__, bcmsdh_reg_read(bus->sdh, 0x18108808, 4)));
  6490. DHD_TRACE(("%d: Read Value @ 0x1810880C = %x."
  6491. "\n", __LINE__, bcmsdh_reg_read(bus->sdh, 0x1810880C, 4)));
  6492. DHD_TRACE(("%d: Read Value @ 0x18109808 = %x."
  6493. "\n", __LINE__, bcmsdh_reg_read(bus->sdh, 0x18109808, 4)));
  6494. DHD_TRACE(("%d: Read Value @ 0x1810980C = %x."
  6495. "\n", __LINE__, bcmsdh_reg_read(bus->sdh, 0x1810980C, 4)));
  6496. DHD_TRACE(("%d: Read Value @ 0x1810C808 = %x."
  6497. "\n", __LINE__, bcmsdh_reg_read(bus->sdh, 0x1810c808, 4)));
  6498. DHD_TRACE(("%d: Read Value @ 0x1810C80C = %x."
  6499. "\n", __LINE__, bcmsdh_reg_read(bus->sdh, 0x1810c80C, 4)));
  6500. counter = 0;
  6501. while ((bcmsdh_reg_read(bus->sdh, 0x18104808, 4) == 5) ||
  6502. (bcmsdh_reg_read(bus->sdh, 0x1810480C, 4) == 5) ||
  6503. (bcmsdh_reg_read(bus->sdh, 0x18106808, 4) == 5) ||
  6504. (bcmsdh_reg_read(bus->sdh, 0x1810680C, 4) == 5) ||
  6505. (bcmsdh_reg_read(bus->sdh, 0x1810780C, 4) == 5) ||
  6506. (bcmsdh_reg_read(bus->sdh, 0x1810780C, 4) == 5) ||
  6507. (bcmsdh_reg_read(bus->sdh, 0x1810880C, 4) == 5) ||
  6508. (bcmsdh_reg_read(bus->sdh, 0x1810880C, 4) == 5) ||
  6509. (bcmsdh_reg_read(bus->sdh, 0x1810980C, 4) == 5) ||
  6510. (bcmsdh_reg_read(bus->sdh, 0x1810980C, 4) == 5) ||
  6511. (bcmsdh_reg_read(bus->sdh, 0x1810C80C, 4) == 5) ||
  6512. (bcmsdh_reg_read(bus->sdh, 0x1810C80C, 4) == 5))
  6513. {
  6514. if (++counter > 10)
  6515. {
  6516. DHD_ERROR(("Unable to recover the backkplane corruption"
  6517. "..Tried %d times.. Exiting\n", counter));
  6518. break;
  6519. }
  6520. OSL_DELAY(10000);
  6521. dhd_sdio_backplane_reset(bus);
  6522. /*
  6523. Get the information of who accessed the crucial backplane
  6524. entities by reading read and write access registers
  6525. */
  6526. DHD_ERROR(("%d: Read Value @ 0x18104808 = %x."
  6527. "\n", __LINE__, bcmsdh_reg_read(bus->sdh, 0x18104808, 4)));
  6528. DHD_ERROR(("%d: Read Value @ 0x1810480C = %x."
  6529. "\n", __LINE__, bcmsdh_reg_read(bus->sdh, 0x1810480C, 4)));
  6530. DHD_ERROR(("%d: Read Value @ 0x18106808 = %x."
  6531. "\n", __LINE__, bcmsdh_reg_read(bus->sdh, 0x18106808, 4)));
  6532. DHD_ERROR(("%d: Read Value @ 0x1810680C = %x."
  6533. "\n", __LINE__, bcmsdh_reg_read(bus->sdh, 0x1810680C, 4)));
  6534. DHD_ERROR(("%d: Read Value @ 0x18107808 = %x."
  6535. "\n", __LINE__, bcmsdh_reg_read(bus->sdh, 0x18107808, 4)));
  6536. DHD_ERROR(("%d: Read Value @ 0x1810780C = %x."
  6537. "\n", __LINE__, bcmsdh_reg_read(bus->sdh, 0x1810780C, 4)));
  6538. DHD_ERROR(("%d: Read Value @ 0x18108808 = %x."
  6539. "\n", __LINE__, bcmsdh_reg_read(bus->sdh, 0x18108808, 4)));
  6540. DHD_ERROR(("%d: Read Value @ 0x1810880C = %x."
  6541. "\n", __LINE__, bcmsdh_reg_read(bus->sdh, 0x1810880C, 4)));
  6542. DHD_ERROR(("%d: Read Value @ 0x18109808 = %x."
  6543. "\n", __LINE__, bcmsdh_reg_read(bus->sdh, 0x18109808, 4)));
  6544. DHD_ERROR(("%d: Read Value @ 0x1810980C = %x."
  6545. "\n", __LINE__, bcmsdh_reg_read(bus->sdh, 0x1810980C, 4)));
  6546. DHD_ERROR(("%d: Read Value @ 0x1810C808 = %x."
  6547. "\n", __LINE__, bcmsdh_reg_read(bus->sdh, 0x1810c808, 4)));
  6548. DHD_ERROR(("%d: Read Value @ 0x1810C80C = %x."
  6549. "\n", __LINE__, bcmsdh_reg_read(bus->sdh, 0x1810c80C, 4)));
  6550. }
  6551. /* Set the WL ready to indicate BT that we are done with backplane reset */
  6552. DHD_ERROR(("Setting up AXI_OK\n"));
  6553. bcmsdh_reg_write(bus->sdh, 0x18000658, 4, 0x3);
  6554. temp = bcmsdh_reg_read(bus->sdh, 0x1800065c, 4);
  6555. temp |= 0x80000000;
  6556. bcmsdh_reg_write(bus->sdh, 0x1800065c, 4, temp);
  6557. return TRUE;
  6558. }
  6559. #endif /* REGON_BP_HANG_FIX */
  6560. static bool
  6561. dhdsdio_probe_attach(struct dhd_bus *bus, osl_t *osh, void *sdh, void *regsva,
  6562. uint16 devid)
  6563. {
  6564. #ifndef BCMSPI
  6565. int err = 0;
  6566. uint8 clkctl = 0;
  6567. #endif /* !BCMSPI */
  6568. bus->alp_only = TRUE;
  6569. bus->sih = NULL;
  6570. /* Return the window to backplane enumeration space for core access */
  6571. if (dhdsdio_set_siaddr_window(bus, SI_ENUM_BASE)) {
  6572. DHD_ERROR(("%s: FAILED to return to SI_ENUM_BASE\n", __FUNCTION__));
  6573. }
  6574. #ifndef BCMSPI /* wake-wlan in gSPI will bring up the htavail/alpavail clocks. */
  6575. /* Force PLL off until si_attach() programs PLL control regs */
  6576. bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR, DHD_INIT_CLKCTL1, &err);
  6577. if (!err)
  6578. clkctl = bcmsdh_cfg_read(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR, &err);
  6579. if (err || ((clkctl & ~SBSDIO_AVBITS) != DHD_INIT_CLKCTL1)) {
  6580. DHD_ERROR(("dhdsdio_probe: ChipClkCSR access: err %d wrote 0x%02x read 0x%02x\n",
  6581. err, DHD_INIT_CLKCTL1, clkctl));
  6582. goto fail;
  6583. }
  6584. #endif /* !BCMSPI */
  6585. #ifdef DHD_DEBUG
  6586. if (DHD_INFO_ON()) {
  6587. uint fn, numfn;
  6588. uint8 *cis[SDIOD_MAX_IOFUNCS];
  6589. int err = 0;
  6590. #ifndef BCMSPI
  6591. numfn = bcmsdh_query_iofnum(sdh);
  6592. ASSERT(numfn <= SDIOD_MAX_IOFUNCS);
  6593. /* Make sure ALP is available before trying to read CIS */
  6594. SPINWAIT(((clkctl = bcmsdh_cfg_read(sdh, SDIO_FUNC_1,
  6595. SBSDIO_FUNC1_CHIPCLKCSR, NULL)),
  6596. !SBSDIO_ALPAV(clkctl)), PMU_MAX_TRANSITION_DLY);
  6597. /* Now request ALP be put on the bus */
  6598. bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR,
  6599. DHD_INIT_CLKCTL2, &err);
  6600. OSL_DELAY(65);
  6601. #else
  6602. numfn = 0; /* internally func is hardcoded to 1 as gSPI has cis on F1 only */
  6603. #endif /* !BCMSPI */
  6604. for (fn = 0; fn <= numfn; fn++) {
  6605. if (!(cis[fn] = MALLOC(osh, SBSDIO_CIS_SIZE_LIMIT))) {
  6606. DHD_INFO(("dhdsdio_probe: fn %d cis malloc failed\n", fn));
  6607. break;
  6608. }
  6609. bzero(cis[fn], SBSDIO_CIS_SIZE_LIMIT);
  6610. if ((err = bcmsdh_cis_read(sdh, fn, cis[fn], SBSDIO_CIS_SIZE_LIMIT))) {
  6611. DHD_INFO(("dhdsdio_probe: fn %d cis read err %d\n", fn, err));
  6612. MFREE(osh, cis[fn], SBSDIO_CIS_SIZE_LIMIT);
  6613. break;
  6614. }
  6615. dhd_dump_cis(fn, cis[fn]);
  6616. }
  6617. while (fn-- > 0) {
  6618. ASSERT(cis[fn]);
  6619. MFREE(osh, cis[fn], SBSDIO_CIS_SIZE_LIMIT);
  6620. }
  6621. if (err) {
  6622. DHD_ERROR(("dhdsdio_probe: failure reading or parsing CIS\n"));
  6623. goto fail;
  6624. }
  6625. }
  6626. #endif /* DHD_DEBUG */
  6627. /* si_attach() will provide an SI handle and scan the backplane */
  6628. if (!(bus->sih = si_attach((uint)devid, osh, regsva, DHD_BUS, sdh,
  6629. &bus->vars, &bus->varsz))) {
  6630. DHD_ERROR(("%s: si_attach failed!\n", __FUNCTION__));
  6631. goto fail;
  6632. }
  6633. #ifdef DHD_DEBUG
  6634. DHD_ERROR(("F1 signature OK, socitype:0x%x chip:0x%4x rev:0x%x pkg:0x%x\n",
  6635. bus->sih->socitype, bus->sih->chip, bus->sih->chiprev, bus->sih->chippkg));
  6636. #endif /* DHD_DEBUG */
  6637. #ifdef REGON_BP_HANG_FIX
  6638. /* WAR - for 43241 B0-B1-B2. B3 onwards do not need this */
  6639. if (((uint16)bus->sih->chip == BCM4324_CHIP_ID) && (bus->sih->chiprev < 3))
  6640. dhdsdio_sdio_hang_war(bus);
  6641. #endif /* REGON_BP_HANG_FIX */
  6642. bcmsdh_chipinfo(sdh, bus->sih->chip, bus->sih->chiprev);
  6643. if (!dhdsdio_chipmatch((uint16)bus->sih->chip)) {
  6644. DHD_ERROR(("%s: unsupported chip: 0x%04x\n",
  6645. __FUNCTION__, bus->sih->chip));
  6646. goto fail;
  6647. }
  6648. if (bus->sih->buscorerev >= 12)
  6649. dhdsdio_clk_kso_init(bus);
  6650. else
  6651. bus->kso = TRUE;
  6652. if (CST4330_CHIPMODE_SDIOD(bus->sih->chipst)) {
  6653. }
  6654. si_sdiod_drive_strength_init(bus->sih, osh, dhd_sdiod_drive_strength);
  6655. /* Get info on the ARM and SOCRAM cores... */
  6656. if (!DHD_NOPMU(bus)) {
  6657. if ((si_setcore(bus->sih, ARM7S_CORE_ID, 0)) ||
  6658. (si_setcore(bus->sih, ARMCM3_CORE_ID, 0)) ||
  6659. (si_setcore(bus->sih, ARMCR4_CORE_ID, 0))) {
  6660. bus->armrev = si_corerev(bus->sih);
  6661. } else {
  6662. DHD_ERROR(("%s: failed to find ARM core!\n", __FUNCTION__));
  6663. goto fail;
  6664. }
  6665. if (!si_setcore(bus->sih, ARMCR4_CORE_ID, 0)) {
  6666. if (!(bus->orig_ramsize = si_socram_size(bus->sih))) {
  6667. DHD_ERROR(("%s: failed to find SOCRAM memory!\n", __FUNCTION__));
  6668. goto fail;
  6669. }
  6670. } else {
  6671. /* cr4 has a different way to find the RAM size from TCM's */
  6672. if (!(bus->orig_ramsize = si_tcm_size(bus->sih))) {
  6673. DHD_ERROR(("%s: failed to find CR4-TCM memory!\n", __FUNCTION__));
  6674. goto fail;
  6675. }
  6676. /* also populate base address */
  6677. switch ((uint16)bus->sih->chip) {
  6678. case BCM4335_CHIP_ID:
  6679. case BCM4339_CHIP_ID:
  6680. case BCM43349_CHIP_ID:
  6681. bus->dongle_ram_base = CR4_4335_RAM_BASE;
  6682. break;
  6683. case BCM4350_CHIP_ID:
  6684. case BCM4354_CHIP_ID:
  6685. case BCM4356_CHIP_ID:
  6686. bus->dongle_ram_base = CR4_4350_RAM_BASE;
  6687. break;
  6688. case BCM4360_CHIP_ID:
  6689. bus->dongle_ram_base = CR4_4360_RAM_BASE;
  6690. break;
  6691. case BCM4345_CHIP_ID:
  6692. case BCM43454_CHIP_ID:
  6693. bus->dongle_ram_base = (bus->sih->chiprev < 6) /* from 4345C0 */
  6694. ? CR4_4345_LT_C0_RAM_BASE : CR4_4345_GE_C0_RAM_BASE;
  6695. break;
  6696. default:
  6697. bus->dongle_ram_base = 0;
  6698. DHD_ERROR(("%s: WARNING: Using default ram base at 0x%x\n",
  6699. __FUNCTION__, bus->dongle_ram_base));
  6700. }
  6701. }
  6702. bus->ramsize = bus->orig_ramsize;
  6703. if (dhd_dongle_ramsize)
  6704. dhd_dongle_setramsize(bus, dhd_dongle_ramsize);
  6705. DHD_ERROR(("DHD: dongle ram size is set to %d(orig %d) at 0x%x\n",
  6706. bus->ramsize, bus->orig_ramsize, bus->dongle_ram_base));
  6707. bus->srmemsize = si_socram_srmem_size(bus->sih);
  6708. }
  6709. /* ...but normally deal with the SDPCMDEV core */
  6710. if (!(bus->regs = si_setcore(bus->sih, PCMCIA_CORE_ID, 0)) &&
  6711. !(bus->regs = si_setcore(bus->sih, SDIOD_CORE_ID, 0))) {
  6712. DHD_ERROR(("%s: failed to find SDIODEV core!\n", __FUNCTION__));
  6713. goto fail;
  6714. }
  6715. bus->sdpcmrev = si_corerev(bus->sih);
  6716. /* Set core control so an SDIO reset does a backplane reset */
  6717. OR_REG(osh, &bus->regs->corecontrol, CC_BPRESEN);
  6718. #ifndef BCMSPI
  6719. bus->rxint_mode = SDIO_DEVICE_HMB_RXINT;
  6720. if ((bus->sih->buscoretype == SDIOD_CORE_ID) && (bus->sdpcmrev >= 4) &&
  6721. (bus->rxint_mode == SDIO_DEVICE_RXDATAINT_MODE_1))
  6722. {
  6723. uint32 val;
  6724. val = R_REG(osh, &bus->regs->corecontrol);
  6725. val &= ~CC_XMTDATAAVAIL_MODE;
  6726. val |= CC_XMTDATAAVAIL_CTRL;
  6727. W_REG(osh, &bus->regs->corecontrol, val);
  6728. }
  6729. #endif /* BCMSPI */
  6730. pktq_init(&bus->txq, (PRIOMASK + 1), QLEN);
  6731. /* Locate an appropriately-aligned portion of hdrbuf */
  6732. bus->rxhdr = (uint8 *)ROUNDUP((uintptr)&bus->hdrbuf[0], DHD_SDALIGN);
  6733. /* Set the poll and/or interrupt flags */
  6734. bus->intr = (bool)dhd_intr;
  6735. if ((bus->poll = (bool)dhd_poll))
  6736. bus->pollrate = 1;
  6737. /* Setting default Glom size */
  6738. bus->txglomsize = SDPCM_DEFGLOM_SIZE;
  6739. return TRUE;
  6740. fail:
  6741. if (bus->sih != NULL) {
  6742. si_detach(bus->sih);
  6743. bus->sih = NULL;
  6744. }
  6745. return FALSE;
  6746. }
  6747. static bool
  6748. dhdsdio_probe_malloc(dhd_bus_t *bus, osl_t *osh, void *sdh)
  6749. {
  6750. DHD_TRACE(("%s: Enter\n", __FUNCTION__));
  6751. if (bus->dhd->maxctl) {
  6752. bus->rxblen = ROUNDUP((bus->dhd->maxctl+SDPCM_HDRLEN), ALIGNMENT) + DHD_SDALIGN;
  6753. if (!(bus->rxbuf = DHD_OS_PREALLOC(bus->dhd, DHD_PREALLOC_RXBUF, bus->rxblen))) {
  6754. DHD_ERROR(("%s: MALLOC of %d-byte rxbuf failed\n",
  6755. __FUNCTION__, bus->rxblen));
  6756. goto fail;
  6757. }
  6758. }
  6759. /* Allocate buffer to receive glomed packet */
  6760. if (!(bus->databuf = DHD_OS_PREALLOC(bus->dhd, DHD_PREALLOC_DATABUF, MAX_DATA_BUF))) {
  6761. DHD_ERROR(("%s: MALLOC of %d-byte databuf failed\n",
  6762. __FUNCTION__, MAX_DATA_BUF));
  6763. /* release rxbuf which was already located as above */
  6764. if (bus->rxbuf) {
  6765. DHD_OS_PREFREE(bus->dhd, DHD_PREALLOC_RXBUF, bus->rxbuf, bus->rxblen);
  6766. }
  6767. goto fail;
  6768. }
  6769. /* Align the buffer */
  6770. if ((uintptr)bus->databuf % DHD_SDALIGN)
  6771. bus->dataptr = bus->databuf + (DHD_SDALIGN - ((uintptr)bus->databuf % DHD_SDALIGN));
  6772. else
  6773. bus->dataptr = bus->databuf;
  6774. return TRUE;
  6775. fail:
  6776. return FALSE;
  6777. }
  6778. static bool
  6779. dhdsdio_probe_init(dhd_bus_t *bus, osl_t *osh, void *sdh)
  6780. {
  6781. int32 fnum;
  6782. DHD_TRACE(("%s: Enter\n", __FUNCTION__));
  6783. bus->_srenab = FALSE;
  6784. #ifdef SDTEST
  6785. dhdsdio_pktgen_init(bus);
  6786. #endif /* SDTEST */
  6787. #ifndef BCMSPI
  6788. /* Disable F2 to clear any intermediate frame state on the dongle */
  6789. bcmsdh_cfg_write(sdh, SDIO_FUNC_0, SDIOD_CCCR_IOEN, SDIO_FUNC_ENABLE_1, NULL);
  6790. #endif /* !BCMSPI */
  6791. bus->dhd->busstate = DHD_BUS_DOWN;
  6792. bus->sleeping = FALSE;
  6793. bus->rxflow = FALSE;
  6794. bus->prev_rxlim_hit = 0;
  6795. #ifndef BCMSPI
  6796. /* Done with backplane-dependent accesses, can drop clock... */
  6797. bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR, 0, NULL);
  6798. #endif /* !BCMSPI */
  6799. /* ...and initialize clock/power states */
  6800. bus->clkstate = CLK_SDONLY;
  6801. bus->idletime = (int32)dhd_idletime;
  6802. bus->idleclock = DHD_IDLE_ACTIVE;
  6803. /* Query the SD clock speed */
  6804. if (bcmsdh_iovar_op(sdh, "sd_divisor", NULL, 0,
  6805. &bus->sd_divisor, sizeof(int32), FALSE) != BCME_OK) {
  6806. DHD_ERROR(("%s: fail on %s get\n", __FUNCTION__, "sd_divisor"));
  6807. bus->sd_divisor = -1;
  6808. } else {
  6809. DHD_INFO(("%s: Initial value for %s is %d\n",
  6810. __FUNCTION__, "sd_divisor", bus->sd_divisor));
  6811. }
  6812. /* Query the SD bus mode */
  6813. if (bcmsdh_iovar_op(sdh, "sd_mode", NULL, 0,
  6814. &bus->sd_mode, sizeof(int32), FALSE) != BCME_OK) {
  6815. DHD_ERROR(("%s: fail on %s get\n", __FUNCTION__, "sd_mode"));
  6816. bus->sd_mode = -1;
  6817. } else {
  6818. DHD_INFO(("%s: Initial value for %s is %d\n",
  6819. __FUNCTION__, "sd_mode", bus->sd_mode));
  6820. }
  6821. /* Query the F2 block size, set roundup accordingly */
  6822. fnum = 2;
  6823. if (bcmsdh_iovar_op(sdh, "sd_blocksize", &fnum, sizeof(int32),
  6824. &bus->blocksize, sizeof(int32), FALSE) != BCME_OK) {
  6825. bus->blocksize = 0;
  6826. DHD_ERROR(("%s: fail on %s get\n", __FUNCTION__, "sd_blocksize"));
  6827. } else {
  6828. DHD_INFO(("%s: Initial value for %s is %d\n",
  6829. __FUNCTION__, "sd_blocksize", bus->blocksize));
  6830. dhdsdio_tune_fifoparam(bus);
  6831. }
  6832. bus->roundup = MIN(max_roundup, bus->blocksize);
  6833. if (bus->pad_pkt)
  6834. PKTFREE(osh, bus->pad_pkt, FALSE);
  6835. bus->pad_pkt = PKTGET(osh, SDIO_MAX_BLOCK_SIZE, FALSE);
  6836. if (bus->pad_pkt == NULL)
  6837. DHD_ERROR(("failed to allocate padding packet\n"));
  6838. else {
  6839. int alignment_offset = 0;
  6840. uintptr pktprt = (uintptr)PKTDATA(osh, bus->pad_pkt);
  6841. if (!(pktprt&1) && (pktprt = (pktprt % DHD_SDALIGN)))
  6842. PKTPUSH(osh, bus->pad_pkt, alignment_offset);
  6843. PKTSETNEXT(osh, bus->pad_pkt, NULL);
  6844. }
  6845. /* Query if bus module supports packet chaining, default to use if supported */
  6846. if (bcmsdh_iovar_op(sdh, "sd_rxchain", NULL, 0,
  6847. &bus->sd_rxchain, sizeof(int32), FALSE) != BCME_OK) {
  6848. bus->sd_rxchain = FALSE;
  6849. } else {
  6850. DHD_INFO(("%s: bus module (through bcmsdh API) %s chaining\n",
  6851. __FUNCTION__, (bus->sd_rxchain ? "supports" : "does not support")));
  6852. }
  6853. bus->use_rxchain = (bool)bus->sd_rxchain;
  6854. bus->txinrx_thres = CUSTOM_TXINRX_THRES;
  6855. /* TX first in dhdsdio_readframes() */
  6856. bus->dotxinrx = TRUE;
  6857. return TRUE;
  6858. }
  6859. int
  6860. dhd_bus_download_firmware(struct dhd_bus *bus, osl_t *osh,
  6861. char *pfw_path, char *pnv_path)
  6862. {
  6863. int ret;
  6864. bus->fw_path = pfw_path;
  6865. bus->nv_path = pnv_path;
  6866. ret = dhdsdio_download_firmware(bus, osh, bus->sdh);
  6867. #if defined(BCMSPI) && defined(GSPI_DWORD_MODE)
  6868. /* Enable the dwordmode in gSPI before first F2 transaction */
  6869. if ((bus->sih->chip == BCM4329_CHIP_ID) && (bus->sih->chiprev > 1)) {
  6870. bcmsdh_dwordmode(bus->sdh, TRUE);
  6871. bus->dwordmode = TRUE;
  6872. }
  6873. #endif /* defined(BCMSPI) && defined(GSPI_DWORD_MODE) */
  6874. return ret;
  6875. }
  6876. static int
  6877. dhdsdio_download_firmware(struct dhd_bus *bus, osl_t *osh, void *sdh)
  6878. {
  6879. int ret;
  6880. #if defined(SUPPORT_MULTIPLE_REVISION)
  6881. if (concate_revision(bus, bus->fw_path, strlen(bus->fw_path) + 1,
  6882. bus->nv_path, strlen(bus->nv_path)+ 1) != 0) {
  6883. DHD_ERROR(("%s: fail to concatnate revison \n",
  6884. __FUNCTION__));
  6885. return BCME_BADARG;
  6886. }
  6887. #endif /* SUPPORT_MULTIPLE_REVISION */
  6888. DHD_TRACE_HW4(("%s: firmware path=%s, nvram path=%s\n",
  6889. __FUNCTION__, bus->fw_path, bus->nv_path));
  6890. DHD_OS_WAKE_LOCK(bus->dhd);
  6891. /* Download the firmware */
  6892. dhdsdio_clkctl(bus, CLK_AVAIL, FALSE);
  6893. ret = _dhdsdio_download_firmware(bus);
  6894. dhdsdio_clkctl(bus, CLK_SDONLY, FALSE);
  6895. DHD_OS_WAKE_UNLOCK(bus->dhd);
  6896. return ret;
  6897. }
  6898. /* Detach and free everything */
  6899. static void
  6900. dhdsdio_release(dhd_bus_t *bus, osl_t *osh)
  6901. {
  6902. bool dongle_isolation = FALSE;
  6903. DHD_TRACE(("%s: Enter\n", __FUNCTION__));
  6904. if (bus) {
  6905. ASSERT(osh);
  6906. if (bus->dhd) {
  6907. dongle_isolation = bus->dhd->dongle_isolation;
  6908. dhd_detach(bus->dhd);
  6909. }
  6910. /* De-register interrupt handler */
  6911. bcmsdh_intr_disable(bus->sdh);
  6912. bcmsdh_intr_dereg(bus->sdh);
  6913. if (bus->dhd) {
  6914. dhdsdio_release_dongle(bus, osh, dongle_isolation, TRUE);
  6915. dhd_free(bus->dhd);
  6916. bus->dhd = NULL;
  6917. }
  6918. dhdsdio_release_malloc(bus, osh);
  6919. #ifdef DHD_DEBUG
  6920. if (bus->console.buf != NULL)
  6921. MFREE(osh, bus->console.buf, bus->console.bufsize);
  6922. #endif
  6923. if (bus->pad_pkt)
  6924. PKTFREE(osh, bus->pad_pkt, FALSE);
  6925. MFREE(osh, bus, sizeof(dhd_bus_t));
  6926. }
  6927. DHD_TRACE(("%s: Disconnected\n", __FUNCTION__));
  6928. }
  6929. static void
  6930. dhdsdio_release_malloc(dhd_bus_t *bus, osl_t *osh)
  6931. {
  6932. DHD_TRACE(("%s: Enter\n", __FUNCTION__));
  6933. if (bus->dhd && bus->dhd->dongle_reset)
  6934. return;
  6935. if (bus->rxbuf) {
  6936. #ifndef CONFIG_DHD_USE_STATIC_BUF
  6937. MFREE(osh, bus->rxbuf, bus->rxblen);
  6938. #endif
  6939. bus->rxctl = bus->rxbuf = NULL;
  6940. bus->rxlen = 0;
  6941. }
  6942. if (bus->databuf) {
  6943. #ifndef CONFIG_DHD_USE_STATIC_BUF
  6944. MFREE(osh, bus->databuf, MAX_DATA_BUF);
  6945. #endif
  6946. bus->databuf = NULL;
  6947. }
  6948. if (bus->vars && bus->varsz) {
  6949. MFREE(osh, bus->vars, bus->varsz);
  6950. bus->vars = NULL;
  6951. }
  6952. }
  6953. static void
  6954. dhdsdio_release_dongle(dhd_bus_t *bus, osl_t *osh, bool dongle_isolation, bool reset_flag)
  6955. {
  6956. DHD_TRACE(("%s: Enter bus->dhd %p bus->dhd->dongle_reset %d \n", __FUNCTION__,
  6957. bus->dhd, bus->dhd->dongle_reset));
  6958. if ((bus->dhd && bus->dhd->dongle_reset) && reset_flag)
  6959. return;
  6960. if (bus->sih) {
  6961. #if !defined(BCMLXSDMMC)
  6962. if (bus->dhd) {
  6963. dhdsdio_clkctl(bus, CLK_AVAIL, FALSE);
  6964. }
  6965. if (KSO_ENAB(bus) && (dongle_isolation == FALSE))
  6966. si_watchdog(bus->sih, 4);
  6967. #endif /* !defined(BCMLXSDMMC) */
  6968. if (bus->dhd) {
  6969. dhdsdio_clkctl(bus, CLK_NONE, FALSE);
  6970. }
  6971. si_detach(bus->sih);
  6972. bus->sih = NULL;
  6973. if (bus->vars && bus->varsz)
  6974. MFREE(osh, bus->vars, bus->varsz);
  6975. bus->vars = NULL;
  6976. }
  6977. DHD_TRACE(("%s: Disconnected\n", __FUNCTION__));
  6978. }
  6979. static void
  6980. dhdsdio_disconnect(void *ptr)
  6981. {
  6982. dhd_bus_t *bus = (dhd_bus_t *)ptr;
  6983. DHD_TRACE(("%s: Enter\n", __FUNCTION__));
  6984. #if defined(MULTIPLE_SUPPLICANT)
  6985. #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25))
  6986. if (mutex_is_locked(&_dhd_sdio_mutex_lock_) == 0) {
  6987. DHD_ERROR(("%s : no mutex held. set lock\n", __FUNCTION__));
  6988. }
  6989. else {
  6990. DHD_ERROR(("%s : mutex is locked!. wait for unlocking\n", __FUNCTION__));
  6991. }
  6992. mutex_lock(&_dhd_sdio_mutex_lock_);
  6993. #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)) */
  6994. #endif
  6995. if (bus) {
  6996. ASSERT(bus->dhd);
  6997. dhdsdio_release(bus, bus->dhd->osh);
  6998. }
  6999. #if defined(MULTIPLE_SUPPLICANT)
  7000. #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25))
  7001. mutex_unlock(&_dhd_sdio_mutex_lock_);
  7002. DHD_ERROR(("%s : the lock is released.\n", __FUNCTION__));
  7003. #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)) */
  7004. #endif /* LINUX */
  7005. DHD_TRACE(("%s: Disconnected\n", __FUNCTION__));
  7006. }
  7007. static int
  7008. dhdsdio_suspend(void *context)
  7009. {
  7010. int ret = 0;
  7011. dhd_bus_t *bus = (dhd_bus_t*)context;
  7012. #ifdef SUPPORT_P2P_GO_PS
  7013. int wait_time = 0;
  7014. if (bus->idletime > 0) {
  7015. wait_time = msecs_to_jiffies(bus->idletime * dhd_watchdog_ms);
  7016. }
  7017. #endif /* SUPPORT_P2P_GO_PS */
  7018. ret = dhd_os_check_wakelock(bus->dhd);
  7019. #ifdef SUPPORT_P2P_GO_PS
  7020. if ((!ret) && (bus->dhd->up) && (bus->dhd->op_mode != DHD_FLAG_HOSTAP_MODE)) {
  7021. if (wait_event_timeout(bus->bus_sleep, bus->sleeping, wait_time) == 0) {
  7022. if (!bus->sleeping) {
  7023. return 1;
  7024. }
  7025. }
  7026. }
  7027. #endif /* SUPPORT_P2P_GO_PS */
  7028. return ret;
  7029. }
  7030. static int
  7031. dhdsdio_resume(void *context)
  7032. {
  7033. #if defined(OOB_INTR_ONLY) || defined(BCMSPI_ANDROID)
  7034. dhd_bus_t *bus = (dhd_bus_t*)context;
  7035. if (dhd_os_check_if_up(bus->dhd))
  7036. bcmsdh_oob_intr_set(bus->sdh, TRUE);
  7037. #endif /* defined(OOB_INTR_ONLY) || defined(BCMSPI_ANDROID) */
  7038. return 0;
  7039. }
  7040. /* Register/Unregister functions are called by the main DHD entry
  7041. * point (e.g. module insertion) to link with the bus driver, in
  7042. * order to look for or await the device.
  7043. */
  7044. static bcmsdh_driver_t dhd_sdio = {
  7045. dhdsdio_probe,
  7046. dhdsdio_disconnect,
  7047. dhdsdio_suspend,
  7048. dhdsdio_resume
  7049. };
  7050. int
  7051. dhd_bus_register(void)
  7052. {
  7053. DHD_TRACE(("%s: Enter\n", __FUNCTION__));
  7054. return bcmsdh_register(&dhd_sdio);
  7055. }
  7056. void
  7057. dhd_bus_unregister(void)
  7058. {
  7059. DHD_TRACE(("%s: Enter\n", __FUNCTION__));
  7060. bcmsdh_unregister();
  7061. }
  7062. #if defined(BCMLXSDMMC)
  7063. /* Register a dummy SDIO client driver in order to be notified of new SDIO device */
  7064. int dhd_bus_reg_sdio_notify(void* semaphore)
  7065. {
  7066. return bcmsdh_reg_sdio_notify(semaphore);
  7067. }
  7068. void dhd_bus_unreg_sdio_notify(void)
  7069. {
  7070. bcmsdh_unreg_sdio_notify();
  7071. }
  7072. #endif /* defined(BCMLXSDMMC) */
  7073. #ifdef BCMEMBEDIMAGE
  7074. static int
  7075. dhdsdio_download_code_array(struct dhd_bus *bus)
  7076. {
  7077. int bcmerror = -1;
  7078. int offset = 0;
  7079. unsigned char *ularray = NULL;
  7080. DHD_INFO(("%s: download embedded firmware...\n", __FUNCTION__));
  7081. /* Download image */
  7082. while ((offset + MEMBLOCK) < sizeof(dlarray)) {
  7083. /* check if CR4 */
  7084. if (si_setcore(bus->sih, ARMCR4_CORE_ID, 0)) {
  7085. /* if address is 0, store the reset instruction to be written in 0 */
  7086. if (offset == 0) {
  7087. bus->resetinstr = *(((uint32*)dlarray));
  7088. /* Add start of RAM address to the address given by user */
  7089. offset += bus->dongle_ram_base;
  7090. }
  7091. }
  7092. bcmerror = dhdsdio_membytes(bus, TRUE, offset,
  7093. (uint8 *) (dlarray + offset), MEMBLOCK);
  7094. if (bcmerror) {
  7095. DHD_ERROR(("%s: error %d on writing %d membytes at 0x%08x\n",
  7096. __FUNCTION__, bcmerror, MEMBLOCK, offset));
  7097. goto err;
  7098. }
  7099. offset += MEMBLOCK;
  7100. }
  7101. if (offset < sizeof(dlarray)) {
  7102. bcmerror = dhdsdio_membytes(bus, TRUE, offset,
  7103. (uint8 *) (dlarray + offset), sizeof(dlarray) - offset);
  7104. if (bcmerror) {
  7105. DHD_ERROR(("%s: error %d on writing %d membytes at 0x%08x\n",
  7106. __FUNCTION__, bcmerror, sizeof(dlarray) - offset, offset));
  7107. goto err;
  7108. }
  7109. }
  7110. #ifdef DHD_DEBUG
  7111. /* Upload and compare the downloaded code */
  7112. {
  7113. ularray = MALLOC(bus->dhd->osh, bus->ramsize);
  7114. /* Upload image to verify downloaded contents. */
  7115. offset = 0;
  7116. memset(ularray, 0xaa, bus->ramsize);
  7117. while ((offset + MEMBLOCK) < sizeof(dlarray)) {
  7118. bcmerror = dhdsdio_membytes(bus, FALSE, offset, ularray + offset, MEMBLOCK);
  7119. if (bcmerror) {
  7120. DHD_ERROR(("%s: error %d on reading %d membytes at 0x%08x\n",
  7121. __FUNCTION__, bcmerror, MEMBLOCK, offset));
  7122. goto err;
  7123. }
  7124. offset += MEMBLOCK;
  7125. }
  7126. if (offset < sizeof(dlarray)) {
  7127. bcmerror = dhdsdio_membytes(bus, FALSE, offset,
  7128. ularray + offset, sizeof(dlarray) - offset);
  7129. if (bcmerror) {
  7130. DHD_ERROR(("%s: error %d on reading %d membytes at 0x%08x\n",
  7131. __FUNCTION__, bcmerror, sizeof(dlarray) - offset, offset));
  7132. goto err;
  7133. }
  7134. }
  7135. if (memcmp(dlarray, ularray, sizeof(dlarray))) {
  7136. DHD_ERROR(("%s: Downloaded image is corrupted (%s, %s, %s).\n",
  7137. __FUNCTION__, dlimagename, dlimagever, dlimagedate));
  7138. goto err;
  7139. } else
  7140. DHD_ERROR(("%s: Download, Upload and compare succeeded (%s, %s, %s).\n",
  7141. __FUNCTION__, dlimagename, dlimagever, dlimagedate));
  7142. }
  7143. #endif /* DHD_DEBUG */
  7144. err:
  7145. if (ularray)
  7146. MFREE(bus->dhd->osh, ularray, bus->ramsize);
  7147. return bcmerror;
  7148. }
  7149. #endif /* BCMEMBEDIMAGE */
  7150. static int
  7151. dhdsdio_download_code_file(struct dhd_bus *bus, char *pfw_path)
  7152. {
  7153. int bcmerror = -1;
  7154. int offset = 0;
  7155. int len;
  7156. void *image = NULL;
  7157. uint8 *memblock = NULL, *memptr;
  7158. DHD_INFO(("%s: download firmware %s\n", __FUNCTION__, pfw_path));
  7159. image = dhd_os_open_image(pfw_path);
  7160. if (image == NULL)
  7161. goto err;
  7162. memptr = memblock = MALLOC(bus->dhd->osh, MEMBLOCK + DHD_SDALIGN);
  7163. if (memblock == NULL) {
  7164. DHD_ERROR(("%s: Failed to allocate memory %d bytes\n", __FUNCTION__, MEMBLOCK));
  7165. goto err;
  7166. }
  7167. if ((uint32)(uintptr)memblock % DHD_SDALIGN)
  7168. memptr += (DHD_SDALIGN - ((uint32)(uintptr)memblock % DHD_SDALIGN));
  7169. /* Download image */
  7170. while ((len = dhd_os_get_image_block((char*)memptr, MEMBLOCK, image))) {
  7171. if (len < 0) {
  7172. DHD_ERROR(("%s: dhd_os_get_image_block failed (%d)\n", __FUNCTION__, len));
  7173. bcmerror = BCME_ERROR;
  7174. goto err;
  7175. }
  7176. /* check if CR4 */
  7177. if (si_setcore(bus->sih, ARMCR4_CORE_ID, 0)) {
  7178. /* if address is 0, store the reset instruction to be written in 0 */
  7179. if (offset == 0) {
  7180. bus->resetinstr = *(((uint32*)memptr));
  7181. /* Add start of RAM address to the address given by user */
  7182. offset += bus->dongle_ram_base;
  7183. }
  7184. }
  7185. bcmerror = dhdsdio_membytes(bus, TRUE, offset, memptr, len);
  7186. if (bcmerror) {
  7187. DHD_ERROR(("%s: error %d on writing %d membytes at 0x%08x\n",
  7188. __FUNCTION__, bcmerror, MEMBLOCK, offset));
  7189. goto err;
  7190. }
  7191. offset += MEMBLOCK;
  7192. }
  7193. err:
  7194. if (memblock)
  7195. MFREE(bus->dhd->osh, memblock, MEMBLOCK + DHD_SDALIGN);
  7196. if (image)
  7197. dhd_os_close_image(image);
  7198. return bcmerror;
  7199. }
  7200. /*
  7201. EXAMPLE: nvram_array
  7202. nvram_arry format:
  7203. name=value
  7204. Use carriage return at the end of each assignment, and an empty string with
  7205. carriage return at the end of array.
  7206. For example:
  7207. unsigned char nvram_array[] = {"name1=value1\n", "name2=value2\n", "\n"};
  7208. Hex values start with 0x, and mac addr format: xx:xx:xx:xx:xx:xx.
  7209. Search "EXAMPLE: nvram_array" to see how the array is activated.
  7210. */
  7211. void
  7212. dhd_bus_set_nvram_params(struct dhd_bus * bus, const char *nvram_params)
  7213. {
  7214. bus->nvram_params = nvram_params;
  7215. }
  7216. static int
  7217. dhdsdio_download_nvram(struct dhd_bus *bus)
  7218. {
  7219. int bcmerror = -1;
  7220. uint len;
  7221. void * image = NULL;
  7222. char * memblock = NULL;
  7223. char *bufp;
  7224. char *pnv_path;
  7225. bool nvram_file_exists;
  7226. pnv_path = bus->nv_path;
  7227. nvram_file_exists = ((pnv_path != NULL) && (pnv_path[0] != '\0'));
  7228. if (!nvram_file_exists && (bus->nvram_params == NULL))
  7229. return (0);
  7230. if (nvram_file_exists) {
  7231. image = dhd_os_open_image(pnv_path);
  7232. if (image == NULL)
  7233. goto err;
  7234. }
  7235. memblock = MALLOC(bus->dhd->osh, MAX_NVRAMBUF_SIZE);
  7236. if (memblock == NULL) {
  7237. DHD_ERROR(("%s: Failed to allocate memory %d bytes\n",
  7238. __FUNCTION__, MAX_NVRAMBUF_SIZE));
  7239. goto err;
  7240. }
  7241. /* Download variables */
  7242. if (nvram_file_exists) {
  7243. len = dhd_os_get_image_block(memblock, MAX_NVRAMBUF_SIZE, image);
  7244. }
  7245. else {
  7246. len = strlen(bus->nvram_params);
  7247. ASSERT(len <= MAX_NVRAMBUF_SIZE);
  7248. memcpy(memblock, bus->nvram_params, len);
  7249. }
  7250. if (len > 0 && len < MAX_NVRAMBUF_SIZE) {
  7251. bufp = (char *)memblock;
  7252. bufp[len] = 0;
  7253. len = process_nvram_vars(bufp, len);
  7254. if (len % 4) {
  7255. len += 4 - (len % 4);
  7256. }
  7257. bufp += len;
  7258. *bufp++ = 0;
  7259. if (len)
  7260. bcmerror = dhdsdio_downloadvars(bus, memblock, len + 1);
  7261. if (bcmerror) {
  7262. DHD_ERROR(("%s: error downloading vars: %d\n",
  7263. __FUNCTION__, bcmerror));
  7264. }
  7265. }
  7266. else {
  7267. DHD_ERROR(("%s: error reading nvram file: %d\n",
  7268. __FUNCTION__, len));
  7269. bcmerror = BCME_SDIO_ERROR;
  7270. }
  7271. err:
  7272. if (memblock)
  7273. MFREE(bus->dhd->osh, memblock, MAX_NVRAMBUF_SIZE);
  7274. if (image)
  7275. dhd_os_close_image(image);
  7276. return bcmerror;
  7277. }
  7278. static int
  7279. _dhdsdio_download_firmware(struct dhd_bus *bus)
  7280. {
  7281. int bcmerror = -1;
  7282. bool embed = FALSE; /* download embedded firmware */
  7283. bool dlok = FALSE; /* download firmware succeeded */
  7284. /* Out immediately if no image to download */
  7285. if ((bus->fw_path == NULL) || (bus->fw_path[0] == '\0')) {
  7286. #ifdef BCMEMBEDIMAGE
  7287. embed = TRUE;
  7288. #else
  7289. return 0;
  7290. #endif
  7291. }
  7292. /* Keep arm in reset */
  7293. if (dhdsdio_download_state(bus, TRUE)) {
  7294. DHD_ERROR(("%s: error placing ARM core in reset\n", __FUNCTION__));
  7295. goto err;
  7296. }
  7297. /* External image takes precedence if specified */
  7298. if ((bus->fw_path != NULL) && (bus->fw_path[0] != '\0')) {
  7299. if (dhdsdio_download_code_file(bus, bus->fw_path)) {
  7300. DHD_ERROR(("%s: dongle image file download failed\n", __FUNCTION__));
  7301. #ifdef BCMEMBEDIMAGE
  7302. embed = TRUE;
  7303. #else
  7304. goto err;
  7305. #endif
  7306. }
  7307. else {
  7308. embed = FALSE;
  7309. dlok = TRUE;
  7310. }
  7311. }
  7312. #ifdef BCMEMBEDIMAGE
  7313. if (embed) {
  7314. if (dhdsdio_download_code_array(bus)) {
  7315. DHD_ERROR(("%s: dongle image array download failed\n", __FUNCTION__));
  7316. goto err;
  7317. }
  7318. else {
  7319. dlok = TRUE;
  7320. }
  7321. }
  7322. #else
  7323. BCM_REFERENCE(embed);
  7324. #endif
  7325. if (!dlok) {
  7326. DHD_ERROR(("%s: dongle image download failed\n", __FUNCTION__));
  7327. goto err;
  7328. }
  7329. /* EXAMPLE: nvram_array */
  7330. /* If a valid nvram_arry is specified as above, it can be passed down to dongle */
  7331. /* dhd_bus_set_nvram_params(bus, (char *)&nvram_array); */
  7332. /* External nvram takes precedence if specified */
  7333. if (dhdsdio_download_nvram(bus)) {
  7334. DHD_ERROR(("%s: dongle nvram file download failed\n", __FUNCTION__));
  7335. goto err;
  7336. }
  7337. /* Take arm out of reset */
  7338. if (dhdsdio_download_state(bus, FALSE)) {
  7339. DHD_ERROR(("%s: error getting out of ARM core reset\n", __FUNCTION__));
  7340. goto err;
  7341. }
  7342. bcmerror = 0;
  7343. err:
  7344. return bcmerror;
  7345. }
  7346. static int
  7347. dhd_bcmsdh_recv_buf(dhd_bus_t *bus, uint32 addr, uint fn, uint flags, uint8 *buf, uint nbytes,
  7348. void *pkt, bcmsdh_cmplt_fn_t complete, void *handle)
  7349. {
  7350. int status;
  7351. if (!KSO_ENAB(bus)) {
  7352. DHD_ERROR(("%s: Device asleep\n", __FUNCTION__));
  7353. return BCME_NODEVICE;
  7354. }
  7355. status = bcmsdh_recv_buf(bus->sdh, addr, fn, flags, buf, nbytes, pkt, complete, handle);
  7356. return status;
  7357. }
  7358. static int
  7359. dhd_bcmsdh_send_buf(dhd_bus_t *bus, uint32 addr, uint fn, uint flags, uint8 *buf, uint nbytes,
  7360. void *pkt, bcmsdh_cmplt_fn_t complete, void *handle, int max_retry)
  7361. {
  7362. int ret;
  7363. int i = 0;
  7364. int retries = 0;
  7365. bcmsdh_info_t *sdh;
  7366. if (!KSO_ENAB(bus)) {
  7367. DHD_ERROR(("%s: Device asleep\n", __FUNCTION__));
  7368. return BCME_NODEVICE;
  7369. }
  7370. sdh = bus->sdh;
  7371. do {
  7372. ret = bcmsdh_send_buf(bus->sdh, addr, fn, flags, buf, nbytes,
  7373. pkt, complete, handle);
  7374. bus->f2txdata++;
  7375. ASSERT(ret != BCME_PENDING);
  7376. if (ret == BCME_NODEVICE) {
  7377. DHD_ERROR(("%s: Device asleep already\n", __FUNCTION__));
  7378. } else if (ret < 0) {
  7379. /* On failure, abort the command and terminate the frame */
  7380. DHD_ERROR(("%s: sdio error %d, abort command and terminate frame.\n",
  7381. __FUNCTION__, ret));
  7382. bus->tx_sderrs++;
  7383. bus->f1regdata++;
  7384. bus->dhd->tx_errors++;
  7385. bcmsdh_abort(sdh, SDIO_FUNC_2);
  7386. bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_FRAMECTRL,
  7387. SFC_WF_TERM, NULL);
  7388. for (i = 0; i < READ_FRM_CNT_RETRIES; i++) {
  7389. uint8 hi, lo;
  7390. hi = bcmsdh_cfg_read(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_WFRAMEBCHI,
  7391. NULL);
  7392. lo = bcmsdh_cfg_read(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_WFRAMEBCLO,
  7393. NULL);
  7394. bus->f1regdata += 2;
  7395. if ((hi == 0) && (lo == 0))
  7396. break;
  7397. }
  7398. }
  7399. } while ((ret < 0) && retrydata && ++retries < max_retry);
  7400. return ret;
  7401. }
  7402. uint
  7403. dhd_bus_chip(struct dhd_bus *bus)
  7404. {
  7405. ASSERT(bus->sih != NULL);
  7406. return bus->sih->chip;
  7407. }
  7408. uint
  7409. dhd_bus_chiprev(struct dhd_bus *bus)
  7410. {
  7411. ASSERT(bus);
  7412. ASSERT(bus->sih != NULL);
  7413. return bus->sih->chiprev;
  7414. }
  7415. void *
  7416. dhd_bus_pub(struct dhd_bus *bus)
  7417. {
  7418. return bus->dhd;
  7419. }
  7420. void *
  7421. dhd_bus_sih(struct dhd_bus *bus)
  7422. {
  7423. return (void *)bus->sih;
  7424. }
  7425. void *
  7426. dhd_bus_txq(struct dhd_bus *bus)
  7427. {
  7428. return &bus->txq;
  7429. }
  7430. void
  7431. dhd_bus_set_dotxinrx(struct dhd_bus *bus, bool val)
  7432. {
  7433. bus->dotxinrx = val;
  7434. }
  7435. int
  7436. dhd_bus_devreset(dhd_pub_t *dhdp, uint8 flag)
  7437. {
  7438. int bcmerror = 0;
  7439. dhd_bus_t *bus;
  7440. bus = dhdp->bus;
  7441. if (flag == TRUE) {
  7442. if (!bus->dhd->dongle_reset) {
  7443. dhd_os_sdlock(dhdp);
  7444. dhd_os_wd_timer(dhdp, 0);
  7445. #if !defined(IGNORE_ETH0_DOWN)
  7446. /* Force flow control as protection when stop come before ifconfig_down */
  7447. dhd_txflowcontrol(bus->dhd, ALL_INTERFACES, ON);
  7448. #endif /* !defined(IGNORE_ETH0_DOWN) */
  7449. /* Expect app to have torn down any connection before calling */
  7450. /* Stop the bus, disable F2 */
  7451. dhd_bus_stop(bus, FALSE);
  7452. #if defined(OOB_INTR_ONLY) || defined(BCMSPI_ANDROID)
  7453. /* Clean up any pending IRQ */
  7454. dhd_enable_oob_intr(bus, FALSE);
  7455. bcmsdh_oob_intr_set(bus->sdh, FALSE);
  7456. bcmsdh_oob_intr_unregister(bus->sdh);
  7457. #endif /* defined(OOB_INTR_ONLY) || defined(BCMSPI_ANDROID) */
  7458. /* Clean tx/rx buffer pointers, detach from the dongle */
  7459. dhdsdio_release_dongle(bus, bus->dhd->osh, TRUE, TRUE);
  7460. bus->dhd->dongle_reset = TRUE;
  7461. bus->dhd->up = FALSE;
  7462. dhd_txglom_enable(dhdp, FALSE);
  7463. dhd_os_sdunlock(dhdp);
  7464. DHD_TRACE(("%s: WLAN OFF DONE\n", __FUNCTION__));
  7465. /* App can now remove power from device */
  7466. } else
  7467. bcmerror = BCME_SDIO_ERROR;
  7468. } else {
  7469. /* App must have restored power to device before calling */
  7470. DHD_TRACE(("\n\n%s: == WLAN ON ==\n", __FUNCTION__));
  7471. if (bus->dhd->dongle_reset) {
  7472. /* Turn on WLAN */
  7473. dhd_os_sdlock(dhdp);
  7474. /* Reset SD client */
  7475. bcmsdh_reset(bus->sdh);
  7476. /* Attempt to re-attach & download */
  7477. if (dhdsdio_probe_attach(bus, bus->dhd->osh, bus->sdh,
  7478. (uint32 *)SI_ENUM_BASE,
  7479. bus->cl_devid)) {
  7480. /* Attempt to download binary to the dongle */
  7481. if (dhdsdio_probe_init(bus, bus->dhd->osh, bus->sdh) &&
  7482. dhdsdio_download_firmware(bus, bus->dhd->osh, bus->sdh) >= 0) {
  7483. /* Re-init bus, enable F2 transfer */
  7484. bcmerror = dhd_bus_init((dhd_pub_t *) bus->dhd, FALSE);
  7485. if (bcmerror == BCME_OK) {
  7486. #if defined(OOB_INTR_ONLY) || defined(BCMSPI_ANDROID)
  7487. dhd_enable_oob_intr(bus, TRUE);
  7488. bcmsdh_oob_intr_register(bus->sdh,
  7489. dhdsdio_isr, bus);
  7490. bcmsdh_oob_intr_set(bus->sdh, TRUE);
  7491. #endif /* defined(OOB_INTR_ONLY) || defined(BCMSPI_ANDROID) */
  7492. bus->dhd->dongle_reset = FALSE;
  7493. bus->dhd->up = TRUE;
  7494. #if !defined(IGNORE_ETH0_DOWN)
  7495. /* Restore flow control */
  7496. dhd_txflowcontrol(bus->dhd, ALL_INTERFACES, OFF);
  7497. #endif
  7498. dhd_os_wd_timer(dhdp, dhd_watchdog_ms);
  7499. DHD_TRACE(("%s: WLAN ON DONE\n", __FUNCTION__));
  7500. } else {
  7501. dhd_bus_stop(bus, FALSE);
  7502. dhdsdio_release_dongle(bus, bus->dhd->osh,
  7503. TRUE, FALSE);
  7504. }
  7505. } else
  7506. bcmerror = BCME_SDIO_ERROR;
  7507. } else
  7508. bcmerror = BCME_SDIO_ERROR;
  7509. dhd_os_sdunlock(dhdp);
  7510. } else {
  7511. bcmerror = BCME_SDIO_ERROR;
  7512. DHD_INFO(("%s called when dongle is not in reset\n",
  7513. __FUNCTION__));
  7514. DHD_INFO(("Will call dhd_bus_start instead\n"));
  7515. dhd_bus_resume(dhdp, 1);
  7516. if ((bcmerror = dhd_bus_start(dhdp)) != 0)
  7517. DHD_ERROR(("%s: dhd_bus_start fail with %d\n",
  7518. __FUNCTION__, bcmerror));
  7519. }
  7520. }
  7521. return bcmerror;
  7522. }
  7523. int dhd_bus_suspend(dhd_pub_t *dhdpub)
  7524. {
  7525. return bcmsdh_stop(dhdpub->bus->sdh);
  7526. }
  7527. int dhd_bus_resume(dhd_pub_t *dhdpub, int stage)
  7528. {
  7529. return bcmsdh_start(dhdpub->bus->sdh, stage);
  7530. }
  7531. /* Get Chip ID version */
  7532. uint dhd_bus_chip_id(dhd_pub_t *dhdp)
  7533. {
  7534. dhd_bus_t *bus = dhdp->bus;
  7535. return bus->sih->chip;
  7536. }
  7537. /* Get Chip Rev ID version */
  7538. uint dhd_bus_chiprev_id(dhd_pub_t *dhdp)
  7539. {
  7540. dhd_bus_t *bus = dhdp->bus;
  7541. return bus->sih->chiprev;
  7542. }
  7543. /* Get Chip Pkg ID version */
  7544. uint dhd_bus_chippkg_id(dhd_pub_t *dhdp)
  7545. {
  7546. dhd_bus_t *bus = dhdp->bus;
  7547. return bus->sih->chippkg;
  7548. }
  7549. int dhd_bus_get_ids(struct dhd_bus *bus, uint32 *bus_type, uint32 *bus_num, uint32 *slot_num)
  7550. {
  7551. *bus_type = bus->bus;
  7552. *bus_num = bus->bus_num;
  7553. *slot_num = bus->slot_num;
  7554. return 0;
  7555. }
  7556. int
  7557. dhd_bus_membytes(dhd_pub_t *dhdp, bool set, uint32 address, uint8 *data, uint size)
  7558. {
  7559. dhd_bus_t *bus;
  7560. bus = dhdp->bus;
  7561. return dhdsdio_membytes(bus, set, address, data, size);
  7562. }
  7563. #if defined(SUPPORT_MULTIPLE_REVISION)
  7564. /* Just print chip revision for BCM4330 */
  7565. static int
  7566. concate_revision_bcm4330(dhd_bus_t *bus)
  7567. {
  7568. uint chipver;
  7569. chipver = bus->sih->chiprev;
  7570. if (chipver == 3)
  7571. DHD_ERROR(("---- CHIP bcm4330 B1 ----\n"));
  7572. else if (chipver == 4)
  7573. DHD_ERROR(("---- CHIP bcm4330 B2 ----\n"));
  7574. else
  7575. DHD_ERROR(("----- Invalid chip version -----\n"));
  7576. return 0;
  7577. }
  7578. static int
  7579. concate_revision_bcm4334(dhd_bus_t *bus,
  7580. char *fw_path, int fw_path_len, char *nv_path, int nv_path_len)
  7581. {
  7582. #define REV_ID_ADDR 0x1E008F90
  7583. #define BCM4334_B1_UNIQUE 0x30312E36
  7584. uint chipver;
  7585. uint32 unique_id;
  7586. uint8 data[4];
  7587. #if defined(SUPPORT_MULTIPLE_CHIPS)
  7588. char chipver_tag[10] = "_4334";
  7589. #else
  7590. char chipver_tag[4] = "";
  7591. #endif /* defined(SUPPORT_MULTIPLE_CHIPS) */
  7592. DHD_TRACE(("%s: BCM4334 Multiple Revision Check\n", __FUNCTION__));
  7593. if (bus->sih->chip != BCM4334_CHIP_ID) {
  7594. DHD_ERROR(("%s:Chip is not BCM4334\n", __FUNCTION__));
  7595. return -1;
  7596. }
  7597. chipver = bus->sih->chiprev;
  7598. if (chipver == 0x2) {
  7599. dhdsdio_membytes(bus, FALSE, REV_ID_ADDR, data, 4);
  7600. unique_id = load32_ua(data);
  7601. if (unique_id == BCM4334_B1_UNIQUE)
  7602. chipver = 0x01;
  7603. }
  7604. DHD_ERROR(("CHIP VER = [0x%x]\n", chipver));
  7605. if (chipver == 1) {
  7606. DHD_ERROR(("----- CHIP bcm4334_B0 -----\n"));
  7607. strcat(chipver_tag, "_b0");
  7608. } else if (chipver == 2) {
  7609. DHD_ERROR(("----- CHIP bcm4334_B1 -----\n"));
  7610. strcat(chipver_tag, "_b1");
  7611. } else if (chipver == 3) {
  7612. DHD_ERROR(("----- CHIP bcm4334_B2 -----\n"));
  7613. strcat(chipver_tag, "_b2");
  7614. }
  7615. else {
  7616. DHD_ERROR(("----- Invalid chip version -----\n"));
  7617. return -1;
  7618. }
  7619. strcat(fw_path, chipver_tag);
  7620. #if defined(SUPPORT_MULTIPLE_CHIPS)
  7621. strcat(nv_path, chipver_tag);
  7622. #endif /* defined(SUPPORT_MULTIPLE_CHIPS) */
  7623. #undef REV_ID_ADDR
  7624. #undef BCM4334_B1_UNIQUE
  7625. return 0;
  7626. }
  7627. static int
  7628. concate_revision_bcm4335
  7629. (dhd_bus_t *bus, char *fw_path, int fw_path_len, char *nv_path, int nv_path_len)
  7630. {
  7631. uint chipver;
  7632. #if defined(SUPPORT_MULTIPLE_CHIPS)
  7633. char chipver_tag[10] = "_4335";
  7634. #else
  7635. char chipver_tag[4] = {0, };
  7636. #endif /* defined(SUPPORT_MULTIPLE_CHIPS) */
  7637. DHD_TRACE(("%s: BCM4335 Multiple Revision Check\n", __FUNCTION__));
  7638. if (bus->sih->chip != BCM4335_CHIP_ID) {
  7639. DHD_ERROR(("%s:Chip is not BCM4335\n", __FUNCTION__));
  7640. return -1;
  7641. }
  7642. chipver = bus->sih->chiprev;
  7643. DHD_ERROR(("CHIP VER = [0x%x]\n", chipver));
  7644. if (chipver == 0x0) {
  7645. DHD_ERROR(("----- CHIP bcm4335_A0 -----\n"));
  7646. strcat(chipver_tag, "_a0");
  7647. } else if (chipver == 0x1) {
  7648. DHD_ERROR(("----- CHIP bcm4335_B0 -----\n"));
  7649. #if defined(SUPPORT_MULTIPLE_CHIPS)
  7650. strcat(chipver_tag, "_b0");
  7651. #endif /* defined(SUPPORT_MULTIPLE_CHIPS) */
  7652. }
  7653. strcat(fw_path, chipver_tag);
  7654. strcat(nv_path, chipver_tag);
  7655. return 0;
  7656. }
  7657. static int
  7658. concate_revision_bcm4339
  7659. (dhd_bus_t *bus, char *fw_path, int fw_path_len, char *nv_path, int nv_path_len)
  7660. {
  7661. uint chipver;
  7662. #if defined(SUPPORT_MULTIPLE_CHIPS)
  7663. char chipver_tag[10] = "_4339";
  7664. #else
  7665. char chipver_tag[4] = {0, };
  7666. #endif /* defined(SUPPORT_MULTIPLE_CHIPS) */
  7667. DHD_TRACE(("%s: BCM4339 Multiple Revision Check\n", __FUNCTION__));
  7668. if (bus->sih->chip != BCM4339_CHIP_ID) {
  7669. DHD_ERROR(("%s:Chip is not BCM4339\n", __FUNCTION__));
  7670. return -1;
  7671. }
  7672. chipver = bus->sih->chiprev;
  7673. DHD_ERROR(("CHIP VER = [0x%x]\n", chipver));
  7674. if (chipver == 0x1) {
  7675. DHD_ERROR(("----- CHIP bcm4339_A0 -----\n"));
  7676. strcat(chipver_tag, "_a0");
  7677. } else {
  7678. DHD_ERROR(("----- CHIP bcm4339 unknown revision %d -----\n",
  7679. chipver));
  7680. }
  7681. strcat(fw_path, chipver_tag);
  7682. strcat(nv_path, chipver_tag);
  7683. return 0;
  7684. }
  7685. static int
  7686. concate_revision_bcm43349
  7687. (dhd_bus_t *bus, char *fw_path, int fw_path_len, char *nv_path, int nv_path_len)
  7688. {
  7689. uint chipver;
  7690. #if defined(SUPPORT_MULTIPLE_CHIPS)
  7691. char chipver_tag[10] = "_43349";
  7692. #else
  7693. char chipver_tag[4] = {0, };
  7694. #endif /* defined(SUPPORT_MULTIPLE_CHIPS) */
  7695. DHD_TRACE(("%s: BCM43349 Multiple Revision Check\n", __FUNCTION__));
  7696. if (bus->sih->chip != BCM43349_CHIP_ID) {
  7697. DHD_ERROR(("%s:Chip is not BCM43349\n", __FUNCTION__));
  7698. return -1;
  7699. }
  7700. chipver = bus->sih->chiprev;
  7701. DHD_ERROR(("CHIP VER = [0x%x]\n", chipver));
  7702. if (chipver == 0x1) {
  7703. DHD_ERROR(("----- CHIP bcm43349_A0 -----\n"));
  7704. strcat(chipver_tag, "_a0");
  7705. } else {
  7706. DHD_ERROR(("----- CHIP bcm43349 unknown revision %d -----\n",
  7707. chipver));
  7708. }
  7709. strcat(fw_path, chipver_tag);
  7710. strcat(nv_path, chipver_tag);
  7711. return 0;
  7712. }
  7713. static int concate_revision_bcm43241(dhd_bus_t *bus,
  7714. char *fw_path, int fw_path_len, char *nv_path, int nv_path_len)
  7715. {
  7716. uint32 chip_id, chip_ver;
  7717. #if defined(SUPPORT_MULTIPLE_CHIPS)
  7718. char chipver_tag[10] = "_43241";
  7719. #else
  7720. char chipver_tag[4] = {0, };
  7721. #endif /* defined(SUPPORT_MULTIPLE_CHIPS) */
  7722. DHD_TRACE(("%s: BCM43241 Multiple Revision Check\n", __FUNCTION__));
  7723. chip_id = bus->sih->chip;
  7724. chip_ver = bus->sih->chiprev;
  7725. if (chip_ver == 2) {
  7726. DHD_ERROR(("----- CHIP bcm43241_B0 -----\n"));
  7727. strcat(chipver_tag, "_b0");
  7728. } else if (chip_ver == 5) {
  7729. DHD_ERROR(("----- CHIP bcm43241_B4 -----\n"));
  7730. strcat(chipver_tag, "_b4");
  7731. } else {
  7732. DHD_ERROR(("----- Invalid chip version -----\n"));
  7733. return -1;
  7734. }
  7735. strcat(fw_path, chipver_tag);
  7736. strcat(nv_path, chipver_tag);
  7737. return 0;
  7738. }
  7739. static int concate_revision_bcm4350(dhd_bus_t *bus,
  7740. char *fw_path, int fw_path_len, char *nv_path, int nv_path_len)
  7741. {
  7742. uint32 chip_id, chip_ver;
  7743. #if defined(SUPPORT_MULTIPLE_CHIPS)
  7744. char chipver_tag[10] = {0, };
  7745. #else
  7746. char chipver_tag[4] = {0, };
  7747. #endif /* defined(SUPPORT_MULTIPLE_CHIPS) */
  7748. chip_id = bus->sih->chip;
  7749. chip_ver = bus->sih->chiprev;
  7750. #if defined(SUPPORT_MULTIPLE_CHIPS)
  7751. if (chip_ver == 3)
  7752. strcat(chipver_tag, "_4354");
  7753. else
  7754. strcat(chipver_tag, "_4350");
  7755. #endif
  7756. if (chip_ver == 3) {
  7757. DHD_ERROR(("----- CHIP 4354 A0 -----\n"));
  7758. strcat(chipver_tag, "_a0");
  7759. } else {
  7760. DHD_ERROR(("----- Unknown chip version, ver=%x -----\n", chip_ver));
  7761. }
  7762. strcat(fw_path, chipver_tag);
  7763. strcat(nv_path, chipver_tag);
  7764. return 0;
  7765. }
  7766. static int concate_revision_bcm4354(dhd_bus_t *bus,
  7767. char *fw_path, int fw_path_len, char *nv_path, int nv_path_len)
  7768. {
  7769. uint32 chip_id, chip_ver;
  7770. #if defined(SUPPORT_MULTIPLE_CHIPS)
  7771. char chipver_tag[10] = "_4354";
  7772. #else
  7773. #if !defined(CUSTOMER_HW4)
  7774. char chipver_tag[4] = {0, };
  7775. #endif /* !CUSTOMER_HW4 */
  7776. #endif /* SUPPORT_MULTIPLE_CHIPS */
  7777. chip_id = bus->sih->chip;
  7778. chip_ver = bus->sih->chiprev;
  7779. #if !defined(SUPPORT_MULTIPLE_CHIPS) && defined(CUSTOMER_HW4)
  7780. DHD_INFO(("----- CHIP 4354, ver=%x -----\n", chip_ver));
  7781. #else
  7782. if (chip_ver == 1) {
  7783. DHD_ERROR(("----- CHIP 4354 A1 -----\n"));
  7784. strcat(chipver_tag, "_a1");
  7785. } else {
  7786. DHD_ERROR(("----- Unknown chip version, ver=%x -----\n", chip_ver));
  7787. }
  7788. strcat(fw_path, chipver_tag);
  7789. strcat(nv_path, chipver_tag);
  7790. #endif /* !SUPPORT_MULTIPLE_CHIPS && CUSTOMER_HW4 */
  7791. return 0;
  7792. }
  7793. static int concate_revision_bcm4356(dhd_bus_t *bus,
  7794. char *fw_path, int fw_path_len, char *nv_path, int nv_path_len)
  7795. {
  7796. uint32 chip_id, chip_ver;
  7797. #if defined(SUPPORT_MULTIPLE_CHIPS)
  7798. char chipver_tag[10] = "_4356";
  7799. #else
  7800. char chipver_tag[4] = {0, };
  7801. #endif /* SUPPORT_MULTIPLE_CHIPS */
  7802. chip_id = bus->sih->chip;
  7803. chip_ver = bus->sih->chiprev;
  7804. if (chip_ver == 0x2) {
  7805. DHD_ERROR(("----- CHIP 4356 A2 -----\n"));
  7806. strcat(chipver_tag, "_a2");
  7807. } else {
  7808. DHD_ERROR(("----- Unknown chip version, ver=%x -----\n", chip_ver));
  7809. }
  7810. strcat(fw_path, chipver_tag);
  7811. strcat(nv_path, chipver_tag);
  7812. return 0;
  7813. }
  7814. static int concate_revision_bcm43341(dhd_bus_t *bus,
  7815. char *fw_path, int fw_path_len, char *nv_path, int nv_path_len)
  7816. {
  7817. uint chipver;
  7818. #if defined(SUPPORT_MULTIPLE_CHIPS)
  7819. char chipver_tag[10] = "_43341";
  7820. #else
  7821. char chipver_tag[4] = {0, };
  7822. #endif /* defined(SUPPORT_MULTIPLE_CHIPS) */
  7823. DHD_TRACE(("%s: BCM43341 Multiple Revision Check\n", __FUNCTION__));
  7824. if (bus->sih->chip != BCM43341_CHIP_ID) {
  7825. DHD_ERROR(("%s:Chip is not BCM43341\n", __FUNCTION__));
  7826. return -1;
  7827. }
  7828. chipver = bus->sih->chiprev;
  7829. DHD_ERROR(("CHIP VER = [0x%x]\n", chipver));
  7830. if (chipver == 0x1) {
  7831. DHD_ERROR(("----- CHIP bcm43341_A0 -----\n"));
  7832. strcat(chipver_tag, "_a0");
  7833. } else if (chipver == 0x2) {
  7834. DHD_ERROR(("----- CHIP bcm43341_B0 -----\n"));
  7835. strcat(chipver_tag, "_b0");
  7836. } else {
  7837. DHD_ERROR(("----- CHIP bcm43341 unknown revision %d -----\n",
  7838. chipver));
  7839. }
  7840. strcat(fw_path, chipver_tag);
  7841. strcat(nv_path, chipver_tag);
  7842. return 0;
  7843. }
  7844. static int
  7845. concate_revision_bcm43454(dhd_bus_t *bus,
  7846. char *fw_path, int fw_path_len, char *nv_path, int nv_path_len)
  7847. {
  7848. char chipver_tag[10] = {0, };
  7849. #ifdef SUPPORT_MULTIPLE_BOARD_REV_FROM_DT
  7850. int base_system_rev_for_nv = 0;
  7851. #endif /* SUPPORT_MULTIPLE_BOARD_REV_FROM_DT */
  7852. DHD_TRACE(("%s: BCM43454 Multiple Revision Check\n", __FUNCTION__));
  7853. if (bus->sih->chip != BCM43454_CHIP_ID) {
  7854. DHD_ERROR(("%s:Chip is not BCM43454!\n", __FUNCTION__));
  7855. return -1;
  7856. }
  7857. #ifdef SUPPORT_MULTIPLE_BOARD_REV_FROM_DT
  7858. base_system_rev_for_nv = dhd_get_system_rev();
  7859. if (base_system_rev_for_nv > 0) {
  7860. DHD_ERROR(("----- Board Rev [%d] -----\n", base_system_rev_for_nv));
  7861. sprintf(chipver_tag, "_r%02d", base_system_rev_for_nv);
  7862. }
  7863. #endif /* SUPPORT_MULTIPLE_BOARD_REV_FROM_DT */
  7864. #ifdef SUPPORT_MULTIPLE_BOARD_REV_FROM_HW
  7865. DHD_ERROR(("----- Rev [%d] Fot MULTIPLE Board. -----\n", system_hw_rev));
  7866. if ((system_hw_rev >= 8) && (system_hw_rev <= 11)) {
  7867. DHD_ERROR(("This HW is Rev 08 ~ 11. this is For FD-HW\n"));
  7868. strcat(chipver_tag, "_FD");
  7869. }
  7870. #endif /* SUPPORT_MULTIPLE_BOARD_REV_FROM_HW */
  7871. strcat(nv_path, chipver_tag);
  7872. return 0;
  7873. }
  7874. static int
  7875. concate_revision_bcm43455(dhd_bus_t *bus,
  7876. char *fw_path, int fw_path_len, char *nv_path, int nv_path_len)
  7877. {
  7878. char chipver_tag[10] = {0, };
  7879. #ifdef SUPPORT_MULTIPLE_BOARD_REV_FROM_DT
  7880. int base_system_rev_for_nv = 0;
  7881. #endif /* SUPPORT_MULTIPLE_BOARD_REV_FROM_DT */
  7882. DHD_TRACE(("%s: BCM43455 Multiple Revision Check\n", __FUNCTION__));
  7883. if (bus->sih->chip != BCM4345_CHIP_ID) {
  7884. DHD_ERROR(("%s:Chip is not BCM43455!\n", __FUNCTION__));
  7885. return -1;
  7886. }
  7887. #ifdef SUPPORT_MULTIPLE_BOARD_REV_FROM_DT
  7888. base_system_rev_for_nv = dhd_get_system_rev();
  7889. if (base_system_rev_for_nv > 0) {
  7890. DHD_ERROR(("----- Board Rev [%d]-----\n", base_system_rev_for_nv));
  7891. sprintf(chipver_tag, "_r%02d", base_system_rev_for_nv);
  7892. }
  7893. #endif /* SUPPORT_MULTIPLE_BOARD_REV_FROM_DT */
  7894. strcat(nv_path, chipver_tag);
  7895. return 0;
  7896. }
  7897. int
  7898. concate_revision(dhd_bus_t *bus, char *fw_path, int fw_path_len, char *nv_path, int nv_path_len)
  7899. {
  7900. int res = 0;
  7901. if (!bus || !bus->sih) {
  7902. DHD_ERROR(("%s:Bus is Invalid\n", __FUNCTION__));
  7903. return -1;
  7904. }
  7905. #if defined(PLATFORM_MPS)
  7906. /* get the base name (prefix) for firmware & nvram from the platform */
  7907. wifi_get_fw_nv_path(fw_path, nv_path);
  7908. #endif
  7909. switch (bus->sih->chip) {
  7910. case BCM4330_CHIP_ID:
  7911. res = concate_revision_bcm4330(bus);
  7912. break;
  7913. case BCM4334_CHIP_ID:
  7914. res = concate_revision_bcm4334(bus, fw_path, fw_path_len,
  7915. nv_path, nv_path_len);
  7916. break;
  7917. case BCM4335_CHIP_ID:
  7918. res = concate_revision_bcm4335(bus, fw_path, fw_path_len,
  7919. nv_path, nv_path_len);
  7920. break;
  7921. case BCM4339_CHIP_ID:
  7922. res = concate_revision_bcm4339(bus, fw_path, fw_path_len,
  7923. nv_path, nv_path_len);
  7924. break;
  7925. case BCM43349_CHIP_ID:
  7926. res = concate_revision_bcm43349(bus, fw_path, fw_path_len,
  7927. nv_path, nv_path_len);
  7928. break;
  7929. case BCM4324_CHIP_ID:
  7930. res = concate_revision_bcm43241(bus, fw_path, fw_path_len, nv_path, nv_path_len);
  7931. break;
  7932. case BCM4350_CHIP_ID:
  7933. res = concate_revision_bcm4350(bus, fw_path, fw_path_len, nv_path, nv_path_len);
  7934. break;
  7935. case BCM4354_CHIP_ID:
  7936. res = concate_revision_bcm4354(bus, fw_path, fw_path_len, nv_path, nv_path_len);
  7937. break;
  7938. case BCM4356_CHIP_ID:
  7939. res = concate_revision_bcm4356(bus, fw_path, fw_path_len, nv_path, nv_path_len);
  7940. break;
  7941. case BCM43341_CHIP_ID:
  7942. res = concate_revision_bcm43341(bus, fw_path, fw_path_len, nv_path, nv_path_len);
  7943. break;
  7944. case BCM43454_CHIP_ID:
  7945. res = concate_revision_bcm43454(bus, fw_path, fw_path_len, nv_path, nv_path_len);
  7946. break;
  7947. case BCM4345_CHIP_ID:
  7948. res = concate_revision_bcm43455(bus, fw_path, fw_path_len, nv_path, nv_path_len);
  7949. break;
  7950. default:
  7951. DHD_ERROR(("REVISION SPECIFIC feature is not required\n"));
  7952. return res;
  7953. }
  7954. if (res == 0) {
  7955. }
  7956. return res;
  7957. }
  7958. #endif /* SUPPORT_MULTIPLE_REVISION */
  7959. void
  7960. dhd_bus_update_fw_nv_path(struct dhd_bus *bus, char *pfw_path, char *pnv_path)
  7961. {
  7962. bus->fw_path = pfw_path;
  7963. bus->nv_path = pnv_path;
  7964. }
  7965. int
  7966. dhd_enableOOB(dhd_pub_t *dhd, bool sleep)
  7967. {
  7968. dhd_bus_t *bus = dhd->bus;
  7969. sdpcmd_regs_t *regs = bus->regs;
  7970. uint retries = 0;
  7971. if (sleep) {
  7972. dhdsdio_clkctl(bus, CLK_AVAIL, FALSE);
  7973. /* Tell device to start using OOB wakeup */
  7974. W_SDREG(SMB_USE_OOB, &regs->tosbmailbox, retries);
  7975. if (retries > retry_limit) {
  7976. DHD_ERROR(("CANNOT SIGNAL CHIP, WILL NOT WAKE UP!!\n"));
  7977. return BCME_BUSY;
  7978. }
  7979. /* Turn off our contribution to the HT clock request */
  7980. dhdsdio_clkctl(bus, CLK_SDONLY, FALSE);
  7981. } else {
  7982. /* Make sure the controller has the bus up */
  7983. dhdsdio_clkctl(bus, CLK_AVAIL, FALSE);
  7984. /* Send misc interrupt to indicate OOB not needed */
  7985. W_SDREG(0, &regs->tosbmailboxdata, retries);
  7986. if (retries <= retry_limit)
  7987. W_SDREG(SMB_DEV_INT, &regs->tosbmailbox, retries);
  7988. if (retries > retry_limit)
  7989. DHD_ERROR(("CANNOT SIGNAL CHIP TO CLEAR OOB!!\n"));
  7990. /* Make sure we have SD bus access */
  7991. dhdsdio_clkctl(bus, CLK_SDONLY, FALSE);
  7992. }
  7993. return BCME_OK;
  7994. }
  7995. void
  7996. dhd_bus_pktq_flush(dhd_pub_t *dhdp)
  7997. {
  7998. dhd_bus_t *bus = dhdp->bus;
  7999. bool wlfc_enabled = FALSE;
  8000. #ifdef PROP_TXSTATUS
  8001. wlfc_enabled = (dhd_wlfc_cleanup_txq(dhdp, NULL, 0) != WLFC_UNSUPPORTED);
  8002. #endif
  8003. if (!wlfc_enabled) {
  8004. #ifdef DHDTCPACK_SUPPRESS
  8005. /* Clean tcp_ack_info_tbl in order to prevent access to flushed pkt,
  8006. * when there is a newly coming packet from network stack.
  8007. */
  8008. dhd_tcpack_info_tbl_clean(bus->dhd);
  8009. #endif /* DHDTCPACK_SUPPRESS */
  8010. /* Clear the data packet queues */
  8011. pktq_flush(dhdp->osh, &bus->txq, TRUE, NULL, 0);
  8012. }
  8013. }
  8014. int
  8015. dhd_sr_config(dhd_pub_t *dhd, bool on)
  8016. {
  8017. dhd_bus_t *bus = dhd->bus;
  8018. if (!bus->_srenab)
  8019. return -1;
  8020. return dhdsdio_clk_devsleep_iovar(bus, on);
  8021. }
  8022. uint16
  8023. dhd_get_chipid(dhd_pub_t *dhd)
  8024. {
  8025. dhd_bus_t *bus = dhd->bus;
  8026. if (bus && bus->sih)
  8027. return (uint16)bus->sih->chip;
  8028. else
  8029. return 0;
  8030. }
  8031. #ifdef DEBUGGER
  8032. uint32 dhd_sdio_reg_read(void *h, uint32 addr)
  8033. {
  8034. uint32 rval;
  8035. struct dhd_bus *bus = (struct dhd_bus *) h;
  8036. dhd_os_sdlock(bus->dhd);
  8037. BUS_WAKE(bus);
  8038. dhdsdio_clkctl(bus, CLK_AVAIL, FALSE);
  8039. rval = bcmsdh_reg_read(bus->sdh, addr, 4);
  8040. dhd_os_sdunlock(bus->dhd);
  8041. return rval;
  8042. }
  8043. void dhd_sdio_reg_write(void *h, uint32 addr, uint32 val)
  8044. {
  8045. struct dhd_bus *bus = (struct dhd_bus *) h;
  8046. dhd_os_sdlock(bus->dhd);
  8047. BUS_WAKE(bus);
  8048. dhdsdio_clkctl(bus, CLK_AVAIL, FALSE);
  8049. bcmsdh_reg_write(bus->sdh, addr, 4, val);
  8050. dhd_os_sdunlock(bus->dhd);
  8051. }
  8052. #endif /* DEBUGGER */