stp_sdio.c 103 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363
  1. /*! \file "stp_sdio.c"
  2. * \brief
  3. *
  4. * detailed description
  5. */
  6. /*******************************************************************************
  7. * C O M P I L E R F L A G S
  8. ********************************************************************************
  9. */
  10. #define STP_SDIO_DBG_SUPPORT 1
  11. #define STP_SDIO_RXDBG 1 /* depends on STP_SDIO_DBG_SUPPORT */
  12. #define STP_SDIO_TXDBG 1 /* depends on STP_SDIO_DBG_SUPPORT */
  13. #define STP_SDIO_TXPERFDBG 1 /* depends on STP_SDIO_DBG_SUPPORT */
  14. #define STP_SDIO_OWNBACKDBG 1 /* depends on STP_SDIO_DBG_SUPPORT */
  15. #define STP_SDIO_NEW_IRQ_HANDLER 1
  16. /*******************************************************************************
  17. * E X T E R N A L R E F E R E N C E S
  18. ********************************************************************************
  19. */
  20. #include <linux/mm.h>
  21. #include <linux/device.h>
  22. #include <linux/module.h>
  23. #include <linux/init.h>
  24. #include <linux/interrupt.h>
  25. #include <linux/sched.h>
  26. #include <linux/delay.h>
  27. #include <linux/completion.h>
  28. #include <linux/time.h>
  29. #include "osal.h"
  30. #include "stp_exp.h"
  31. #include "hif_sdio.h"
  32. #include "stp_sdio.h"
  33. #include "wmt_lib.h"
  34. #include "wmt_exp.h"
  35. /*******************************************************************************
  36. * C O N S T A N T S
  37. ********************************************************************************
  38. */
  39. #ifdef DFT_TAG
  40. #undef DFT_TAG
  41. #endif
  42. #define DFT_TAG "[STP SDIO]"
  43. #define STPSDIO_LOG_LOUD 5
  44. #define STPSDIO_LOG_DBG 4
  45. #define STPSDIO_LOG_HINT 3
  46. #define STPSDIO_LOG_INFO 2
  47. #define STPSDIO_LOG_WARN 1
  48. #define STPSDIO_LOG_ERR 0
  49. /*******************************************************************************
  50. * D A T A T Y P E S
  51. ********************************************************************************
  52. */
  53. #if STP_SDIO_DBG_SUPPORT && STP_SDIO_RXDBG
  54. #define STP_SDIO_RXDBG_COUNT (0x10UL)
  55. #define STP_SDIO_RXDBG_COUNT_MASK (STP_SDIO_RXDBG_COUNT - 1)
  56. struct stp_sdio_rxdbg {
  57. UINT32 ts;
  58. UINT32 bus_rxlen;
  59. UINT32 chisr_rxlen;
  60. UINT8 rx_pkt_buf[STP_SDIO_RX_BUF_SIZE];
  61. };
  62. #endif
  63. #if STP_SDIO_DBG_SUPPORT && STP_SDIO_TXDBG
  64. #define STP_SDIO_TXDBG_COUNT (0x10UL)
  65. #define STP_SDIO_TXDBG_COUNT_MASK (STP_SDIO_TXDBG_COUNT - 1)
  66. struct stp_sdio_txdbg {
  67. UINT32 ts;
  68. UINT32 bus_txlen;
  69. UINT32 four_byte_align_len;
  70. UINT8 tx_pkt_buf[STP_SDIO_TX_ENTRY_SIZE];
  71. };
  72. #define STP_SDIO_TXDBG_MAX_SIZE (0x20)
  73. #endif
  74. /*******************************************************************************
  75. * F U N C T I O N D E C L A R A T I O N S
  76. ********************************************************************************
  77. */
  78. static INT32 stp_sdio_irq(const MTK_WCN_HIF_SDIO_CLTCTX clt_ctx);
  79. static INT32
  80. stp_sdio_probe(const MTK_WCN_HIF_SDIO_CLTCTX clt_ctx,
  81. const MTK_WCN_HIF_SDIO_FUNCINFO *sdio_func_infop);
  82. static INT32 stp_sdio_remove(const MTK_WCN_HIF_SDIO_CLTCTX clt_ctx);
  83. #if STP_SDIO_DBG_SUPPORT && (STP_SDIO_TXDBG || STP_SDIO_TXPERFDBG)
  84. static VOID stp_sdio_txdbg_dump(VOID);
  85. #endif
  86. static VOID stp_sdio_rx_wkr(struct work_struct *work);
  87. static VOID stp_sdio_tx_wkr(struct work_struct *work);
  88. #if STP_SDIO_OWN_THREAD
  89. static INT32 _stp_sdio_wait_for_msg(PVOID pvData);
  90. static VOID stp_sdio_tx_rx_handling(PVOID pData);
  91. #endif
  92. static INT32 stp_sdio_host_info_deinit(PPUINT8 ppTxBuf, PPUINT8 ppRxBuf);
  93. static INT32 stp_sdio_host_info_init(PPUINT8 ppTxBuf, PPUINT8 ppRxBuf);
  94. static INT32 stp_sdio_host_info_op(INT32 opId);
  95. static INT32 stp_sdio_rc_reg_readl_retry(MTK_WCN_HIF_SDIO_CLTCTX clt_ctx, UINT32 offset,
  96. UINT32 retry_limit, INT32 *p_ret);
  97. /*******************************************************************************
  98. * P R I V A T E D A T A
  99. ********************************************************************************
  100. */
  101. /* Supported SDIO device table */
  102. static const MTK_WCN_HIF_SDIO_FUNCINFO mtk_stp_sdio_id_tbl[] = {
  103. /* MT6618 *//* Not an SDIO standard class device */
  104. {MTK_WCN_HIF_SDIO_FUNC(0x037A, 0x018B, 1, STP_SDIO_BLK_SIZE)},
  105. {MTK_WCN_HIF_SDIO_FUNC(0x037A, 0x018C, 1, STP_SDIO_BLK_SIZE)}, /* 2-function */
  106. /* MT6619 *//* Not an SDIO standard class device */
  107. {MTK_WCN_HIF_SDIO_FUNC(0x037A, 0x6619, 1, STP_SDIO_BLK_SIZE)},
  108. /* MT6620 *//* Not an SDIO standard class device */
  109. {MTK_WCN_HIF_SDIO_FUNC(0x037A, 0x020B, 1, STP_SDIO_BLK_SIZE)},
  110. {MTK_WCN_HIF_SDIO_FUNC(0x037A, 0x020C, 1, STP_SDIO_BLK_SIZE)}, /* 2-function */
  111. /* MT6628 *//* Not an SDIO standard class device */
  112. {MTK_WCN_HIF_SDIO_FUNC(0x037A, 0x6628, 2, STP_SDIO_BLK_SIZE)}, /* 2-function */
  113. /* MT6630 *//* Not an SDIO standard class device */
  114. {MTK_WCN_HIF_SDIO_FUNC(0x037A, 0x6630, 2, STP_SDIO_BLK_SIZE)}, /* 2-function */
  115. { /* end: all zeroes */ },
  116. };
  117. wait_queue_head_t g_ownback_done;
  118. INT32 is_wait_ownback = 0;
  119. /* static void (*cmb_bgf_eirq_cb)(void) = NULL; */
  120. /* STP SDIO client information for hif sdio driver registration */
  121. const MTK_WCN_HIF_SDIO_CLTINFO g_stp_sdio_cltinfo = {
  122. .func_tbl = mtk_stp_sdio_id_tbl,
  123. .func_tbl_size = (sizeof(mtk_stp_sdio_id_tbl) / sizeof(MTK_WCN_HIF_SDIO_FUNCINFO) - 1),
  124. .hif_clt_irq = stp_sdio_irq,
  125. .hif_clt_probe = stp_sdio_probe,
  126. .hif_clt_remove = stp_sdio_remove,
  127. };
  128. /* STP SDIO host array for multiple hosts maintenance */
  129. MTK_WCN_STP_SDIO_HIF_INFO g_stp_sdio_host_info; /*[STP_SDIO_HOST_COUNT]; */
  130. /* STP SDIO host information pointer (for stp if_tx() function) */
  131. MTK_WCN_STP_SDIO_HIF_INFO *const gp_info = &g_stp_sdio_host_info;
  132. /* STP-SDIO probe count (not support multiple probe and hosts) */
  133. UINT32 g_stp_sdio_host_count;
  134. #if STP_SDIO_DBG_SUPPORT && STP_SDIO_RXDBG
  135. #define STP_SDIO_RXDBG_PROCNAME "driver/stp_sdio_rxdbg"
  136. static struct proc_dir_entry *gStpSdioRxDbgEntry;
  137. static INT32 stp_sdio_rxdbg_cnt;
  138. static struct stp_sdio_rxdbg stp_sdio_rxdbg_buffer[STP_SDIO_RXDBG_COUNT];
  139. static struct timeval old = {0};
  140. #define TX_NO_ACK_TIMEOUT_ASSERT 5 /* tx no ack timeout assert, unit:second*/
  141. #if USE_NEW_PROC_FS_FLAG
  142. static ssize_t stp_sdio_rxdbg_read(struct file *filp, char __user *buf, size_t count, loff_t *f_pos);
  143. static ssize_t stp_sdio_rxdbg_write(struct file *filp, const char __user *buf, size_t count,
  144. loff_t *f_pos);
  145. static const struct file_operations stp_sdio_rxdbg_fops = {
  146. .read = stp_sdio_rxdbg_read,
  147. .write = stp_sdio_rxdbg_write,
  148. };
  149. #endif
  150. #endif
  151. #if STP_SDIO_DBG_SUPPORT && STP_SDIO_OWNBACKDBG
  152. #define STP_SDIO_OWNDBG_PROCNAME "driver/stp_sdio_own"
  153. static struct proc_dir_entry *gStpSdioOwnEntry;
  154. #if USE_NEW_PROC_FS_FLAG
  155. static ssize_t stp_sdio_own_read(struct file *filp, char __user *buf, size_t count, loff_t *f_pos);
  156. static ssize_t stp_sdio_own_write(struct file *filp, const char __user *buf, size_t count,
  157. loff_t *f_pos);
  158. static const struct file_operations stp_sdio_own_fops = {
  159. .read = stp_sdio_own_read,
  160. .write = stp_sdio_own_write,
  161. };
  162. #endif
  163. #endif
  164. #if STP_SDIO_DBG_SUPPORT && (STP_SDIO_TXDBG || STP_SDIO_TXPERFDBG)
  165. #define STP_SDIO_TXDBG_PROCNAME "driver/stp_sdio_txdbg"
  166. static struct proc_dir_entry *gStpSdioTxDbgEntry;
  167. #if USE_NEW_PROC_FS_FLAG
  168. static ssize_t stp_sdio_txdbg_read(struct file *filp, char __user *buf, size_t count, loff_t *f_pos);
  169. static ssize_t stp_sdio_txdbg_write(struct file *filp, const char __user *buf, size_t count,
  170. loff_t *f_pos);
  171. static const struct file_operations stp_sdio_txdbg_fops = {
  172. .read = stp_sdio_txdbg_read,
  173. .write = stp_sdio_txdbg_write,
  174. };
  175. #endif
  176. #if STP_SDIO_TXDBG
  177. static INT32 stp_sdio_txdbg_cnt;
  178. static struct stp_sdio_txdbg stp_sdio_txdbg_buffer[STP_SDIO_TXDBG_COUNT];
  179. #endif
  180. #if STP_SDIO_TXPERFDBG
  181. /* a record for tx worker loop counter */
  182. static UINT32 stp_sdio_txperf_worker_cnt;
  183. /* a record for left fifo size in hw when tx wait */
  184. static UINT32 stp_sdio_txperf_fifo_left;
  185. /* a record for data length when tx wait */
  186. static UINT32 stp_sdio_txperf_to_send;
  187. /* a record for tx wait fifo limit counter */
  188. static UINT32 stp_sdio_txperf_fifo_lmt_cnt;
  189. /* a record for left txed pkt number in tx worker */
  190. static UINT32 stp_sdio_txperf_txed_pkt_num;
  191. /* a record for tx wait pkt_num limit counter */
  192. static UINT32 stp_sdio_txperf_pkt_num_lmt_cnt;
  193. #endif
  194. #endif
  195. /*******************************************************************************
  196. * P U B L I C D A T A
  197. ********************************************************************************
  198. */
  199. MODULE_LICENSE("GPL");
  200. MODULE_AUTHOR("MediaTek Inc WCN_SE_CS3");
  201. MODULE_DESCRIPTION("Read-Copy Update tracing for hierarchical implementation");
  202. UINT32 gStpSdioDbgLvl = STPSDIO_LOG_INFO;
  203. /*******************************************************************************
  204. * M A C R O S
  205. ********************************************************************************
  206. */
  207. #define STPSDIO_LOUD_FUNC(fmt, arg...) \
  208. do { \
  209. if (gStpSdioDbgLvl >= STPSDIO_LOG_LOUD) \
  210. pr_err(DFT_TAG "[L]%s:" fmt, __func__ , ##arg); \
  211. } while (0)
  212. #define STPSDIO_DBG_FUNC(fmt, arg...) \
  213. do { \
  214. if (gStpSdioDbgLvl >= STPSDIO_LOG_DBG) \
  215. pr_err(DFT_TAG "[D]%s:" fmt, __func__ , ##arg); \
  216. } while (0)
  217. #define STPSDIO_HINT_FUNC(fmt, arg...) \
  218. do { \
  219. if (gStpSdioDbgLvl >= STPSDIO_LOG_HINT) \
  220. pr_err(DFT_TAG "[I]%s:" fmt, __func__ , ##arg); \
  221. } while (0)
  222. #define STPSDIO_INFO_FUNC(fmt, arg...) \
  223. do { \
  224. if (gStpSdioDbgLvl >= STPSDIO_LOG_INFO) \
  225. pr_err(DFT_TAG "[I]%s:" fmt, __func__ , ##arg); \
  226. } while (0)
  227. #define STPSDIO_WARN_FUNC(fmt, arg...) \
  228. do { \
  229. if (gStpSdioDbgLvl >= STPSDIO_LOG_WARN) \
  230. pr_err(DFT_TAG "[W]%s:" fmt, __func__ , ##arg); \
  231. } while (0)
  232. #define STPSDIO_ERR_FUNC(fmt, arg...) \
  233. do { \
  234. if (gStpSdioDbgLvl >= STPSDIO_LOG_ERR) \
  235. pr_err(DFT_TAG "[E]%s(%d):" fmt, __func__ , __LINE__, ##arg); \
  236. } while (0)
  237. #define STPSDIO_TRC_FUNC(f) \
  238. do { \
  239. if (gStpSdioDbgLvl >= STPSDIO_LOG_DBG) \
  240. pr_err(DFT_TAG "<%s> <%d>\n", __func__, __LINE__); \
  241. } while (0)
  242. /*******************************************************************************
  243. * F U N C T I O N S
  244. ********************************************************************************
  245. */
  246. INT32 stp_sdio_host_info_op(INT32 opId)
  247. {
  248. INT32 iRet = 0;
  249. #if KMALLOC_UPDATE
  250. static PUINT8 p_tx_buffer;
  251. static PUINT8 p_rx_buffer;
  252. if (NULL == p_tx_buffer) {
  253. p_tx_buffer = kmalloc(STP_SDIO_TX_BUF_CNT * STP_SDIO_TX_ENTRY_SIZE, GFP_ATOMIC);
  254. if (NULL == p_tx_buffer) {
  255. STPSDIO_ERR_FUNC
  256. ("memory allocate for g_stp_sdio_host_info.pkt_buf.tx_buf fail!\n");
  257. iRet = -1;
  258. } else {
  259. STPSDIO_INFO_FUNC
  260. ("memory allocate for g_stp_sdio_host_info.pkt_buf.tx_buf succeed!\n");
  261. iRet = 0;
  262. }
  263. } else {
  264. STPSDIO_INFO_FUNC
  265. ("memory already allocated for g_stp_sdio_host_info.pkt_buf.tx_buf!\n");
  266. iRet = 0;
  267. }
  268. if (NULL == p_rx_buffer) {
  269. p_rx_buffer = kmalloc(STP_SDIO_RX_BUF_SIZE, GFP_ATOMIC);
  270. if (NULL == p_rx_buffer) {
  271. STPSDIO_ERR_FUNC
  272. ("memory allocate for g_stp_sdio_host_info.pkt_buf.rx_buf fail!\n");
  273. iRet = -1;
  274. } else {
  275. STPSDIO_INFO_FUNC
  276. ("memory allocate for g_stp_sdio_host_info.pkt_buf.rx_buf succeed!\n");
  277. iRet = 0;
  278. }
  279. } else {
  280. STPSDIO_INFO_FUNC
  281. ("memory already allocated for g_stp_sdio_host_info.pkt_buf.rx_buf!\n");
  282. iRet = 0;
  283. }
  284. #endif
  285. if (0 == iRet && 0 == opId)
  286. iRet = stp_sdio_host_info_deinit(&p_tx_buffer, &p_rx_buffer);
  287. else if (0 == iRet)
  288. iRet = stp_sdio_host_info_init(&p_tx_buffer, &p_rx_buffer);
  289. else
  290. STPSDIO_ERR_FUNC("iRet (%d)!\n", iRet);
  291. return iRet;
  292. }
  293. INT32 stp_sdio_host_info_init(PPUINT8 ppTxBuf, PPUINT8 ppRxBuf)
  294. {
  295. /* Init host count */
  296. memset(&g_stp_sdio_host_info, 0, sizeof(g_stp_sdio_host_info));
  297. #if KMALLOC_UPDATE
  298. g_stp_sdio_host_info.pkt_buf.tx_buf = *ppTxBuf;
  299. g_stp_sdio_host_info.pkt_buf.rx_buf = *ppRxBuf;
  300. #endif
  301. return 0;
  302. }
  303. INT32 stp_sdio_host_info_deinit(PPUINT8 ppTxBuf, PPUINT8 ppRxBuf)
  304. {
  305. STPSDIO_DBG_FUNC("clear g_stp_sdio_host_count end\n");
  306. #if KMALLOC_UPDATE
  307. if (NULL != *ppTxBuf) {
  308. kfree(*ppTxBuf);
  309. *ppTxBuf = NULL;
  310. }
  311. if (NULL != *ppRxBuf) {
  312. kfree(*ppRxBuf);
  313. *ppRxBuf = NULL;
  314. }
  315. #endif
  316. return 0;
  317. }
  318. INT32 _stp_sdio_issue_fake_coredump(UINT8 *str)
  319. {
  320. #define MAX_STRING_LENGTH 64
  321. UINT8 AssertStr[4 + MAX_STRING_LENGTH + 1 + 2] = { 0 };
  322. UINT32 length = strlen(str) >= MAX_STRING_LENGTH ? MAX_STRING_LENGTH : strlen(str);
  323. /*pack str into STP SDIO packet format */
  324. /*STP header */
  325. AssertStr[0] = 0x80;
  326. AssertStr[1] = 0x50;
  327. AssertStr[2] = (length + 1) & 0xff;
  328. AssertStr[3] = 0x0;
  329. /*STP content */
  330. memcpy(&AssertStr[4], str, length);
  331. /*string end character */
  332. AssertStr[4 + length] = '\n';
  333. /*STP CRC */
  334. AssertStr[4 + length + 1] = 0x0;
  335. AssertStr[4 + length + 2] = 0x0;
  336. /*send to STP layer coredump content */
  337. mtk_wcn_stp_parser_data(&AssertStr[0], 4 + length + 1 + 2);
  338. /*send coredump end content */
  339. length = strlen("coredump end");
  340. AssertStr[0] = 0x80;
  341. AssertStr[1] = 0x50;
  342. AssertStr[2] = (length + 2) & 0xff;
  343. AssertStr[3] = 0x0;
  344. memcpy(&AssertStr[4], "coredump end", length);
  345. /*string end character */
  346. AssertStr[4 + length] = '\r';
  347. AssertStr[4 + length + 1] = '\n';
  348. /*STP CRC */
  349. AssertStr[4 + length + 2] = 0x0;
  350. AssertStr[4 + length + 3] = 0x0;
  351. mtk_wcn_stp_parser_data(&AssertStr[0], 4 + length + 2 + 2);
  352. STPSDIO_ERR_FUNC("trigger fake coredump with str:[%s] finished\n", str);
  353. return 0;
  354. }
  355. /*!
  356. * \brief
  357. *
  358. * \details
  359. *
  360. * \retval 0 success
  361. * \retval !=0 fail
  362. */
  363. static SDIO_PS_OP stp_sdio_get_own_state(VOID)
  364. {
  365. SDIO_PS_OP ret = OWN_SET;
  366. INT32 i_ret = 0;
  367. UINT32 chlcpr_value = 0x0;
  368. MTK_WCN_HIF_SDIO_CLTCTX clt_ctx;
  369. clt_ctx = gp_info->sdio_cltctx;
  370. i_ret = mtk_wcn_hif_sdio_readl(clt_ctx, CHLPCR, &chlcpr_value);
  371. if (i_ret) {
  372. ret = OWN_SET;
  373. STPSDIO_ERR_FUNC("read CHLPCR fail(%d), return\n", ret);
  374. return ret;
  375. }
  376. if ((chlcpr_value & C_FW_COM_DRV_OWN) == C_FW_COM_DRV_OWN)
  377. ret = OWN_CLR;
  378. else
  379. ret = OWN_SET;
  380. return ret;
  381. }
  382. /*!
  383. * \brief
  384. *
  385. * \details
  386. *
  387. * \retval 0 success
  388. * \retval !=0 fail
  389. */
  390. static INT32 stp_sdio_do_own_clr(INT32 wait)
  391. {
  392. #define CLR_OWN_RETRY 50
  393. INT32 ret = -1;
  394. UINT32 time_out;
  395. INT32 retry;
  396. UINT32 chlcpr_value = 0x0;
  397. UINT32 delay_us = 500;
  398. MTK_WCN_HIF_SDIO_CLTCTX clt_ctx;
  399. clt_ctx = gp_info->sdio_cltctx;
  400. retry = 40;
  401. /* <1> request firmware-own back */
  402. STPSDIO_DBG_FUNC("Do FW-Own back!(Wakeup)\n");
  403. if (wait) {
  404. /* TODO:[FixMe][George] why use both polling & interrupt methods here??? */
  405. init_waitqueue_head(&g_ownback_done);
  406. is_wait_ownback = 1;
  407. }
  408. /* need to wait for the ownback completion */
  409. /* [COHEC_00006052] SW work-around solution:
  410. using CMD52 write instead of CMD53 write for CCIR, CHLPCR, CSDIOCSR */
  411. while (retry-- > 0) {
  412. #if COHEC_00006052
  413. ret =
  414. mtk_wcn_hif_sdio_writeb(clt_ctx, (UINT32) (CHLPCR + 0x1),
  415. (UINT8) (C_FW_OWN_REQ_CLR >> 8));
  416. #else
  417. ret = mtk_wcn_hif_sdio_writel(clt_ctx, CHLPCR, C_FW_OWN_REQ_CLR);
  418. #endif /* COHEC_00006052 */
  419. if (ret) {
  420. STPSDIO_ERR_FUNC("request firmware own back fail(%d)\n", ret);
  421. osal_dbg_assert_aee("<HIF_SDIO> sdio_write ERROR",
  422. "write CHLPCR by SDIO report error");
  423. if (0 == retry)
  424. goto out;
  425. } else
  426. break;
  427. };
  428. retry = 1200;/*wait for 1200*500 = 600 000 us*/
  429. do {
  430. ret = mtk_wcn_hif_sdio_readl(clt_ctx, CHLPCR, &chlcpr_value);
  431. if (ret) {
  432. /* 4 <1.1> get CHISR Rx error handling */
  433. STPSDIO_ERR_FUNC("get CHLPCR information rx error!(%d)\n", ret);
  434. goto out;
  435. }
  436. if ((chlcpr_value & C_FW_COM_DRV_OWN) == C_FW_COM_DRV_OWN) {
  437. /* 4 <2> handle ownership back interrupt */
  438. STPSDIO_DBG_FUNC("firmware ownback is polled!(%d)\n",
  439. CLR_OWN_RETRY - retry);
  440. /* udelay(2000); */
  441. break;
  442. }
  443. STPSDIO_DBG_FUNC("firmware ownback is no polled, wait for (%d us) and retry\n", delay_us);
  444. udelay(delay_us);
  445. if (0 == (retry - 1)%40)
  446. STPSDIO_ERR_FUNC("own back failed in %d us, something might goes wrong\n", 40*delay_us);
  447. if (0 == (retry - 1)%200) {
  448. #if COHEC_00006052
  449. ret = mtk_wcn_hif_sdio_writeb(clt_ctx, (UINT32)(CHLPCR+0x1), (UINT8)(C_FW_OWN_REQ_CLR>>8));
  450. #else
  451. ret = mtk_wcn_hif_sdio_writel(clt_ctx, CHLPCR, C_FW_OWN_REQ_CLR);
  452. #endif /* COHEC_00006052 */
  453. if (ret)
  454. STPSDIO_ERR_FUNC("request firmware own back fail(%d)\n", ret);
  455. STPSDIO_ERR_FUNC("own back failed in %d us, write again\n", 200*delay_us);
  456. }
  457. } while (retry-- > 0);
  458. if (wait) {
  459. /* <2> wait own_back bit is set. */
  460. time_out = wait_event_timeout(g_ownback_done,
  461. is_wait_ownback == 0, (1000 / (1000 / HZ)));
  462. if (time_out != 0) {
  463. STPSDIO_INFO_FUNC("Do FW-Own back!(Wakeup) succeed\n");
  464. ret = 0;
  465. } else {
  466. STPSDIO_ERR_FUNC("Do FW-Own back!(Wakeup) fail\n");
  467. ret = -1;
  468. }
  469. } else {
  470. ret = retry > 0 ? 0 : -1;
  471. }
  472. out:
  473. return ret;
  474. }
  475. #if 0
  476. /*!
  477. * \brief
  478. *
  479. * \details
  480. *
  481. * \retval 0 success
  482. * \retval !=0 fail
  483. */
  484. static INT32 stp_sdio_do_own_set(VOID)
  485. {
  486. #define SET_OWN_RETRY 10
  487. INT32 ret = -1;
  488. UINT32 chlcpr_value = 0x0;
  489. UINT32 retry = SET_OWN_RETRY;
  490. UINT32 delay_us = 500;
  491. UINT32 tx_fifo_clear_cnt = 0;
  492. MTK_WCN_HIF_SDIO_CLTCTX clt_ctx;
  493. MTK_WCN_STP_SDIO_HIF_INFO *p_info;
  494. UINT32 comp_count = 0;
  495. #define SAFE_CNT_TO_SET_OWN 5
  496. clt_ctx = gp_info->sdio_cltctx;
  497. p_info = gp_info;
  498. while (retry) {
  499. #if STP_SDIO_NEW_TXRING
  500. #else
  501. spin_lock_irqsave(&gp_info->pkt_buf.rd_idx_lock, gp_info->pkt_buf.rd_irq_flag);
  502. comp_count = atomic_read(&p_info->firmware_info.tx_comp_num);
  503. if ((comp_count == p_info->firmware_info.tx_packet_num)
  504. && (0 == p_info->rx_pkt_len)) {
  505. spin_unlock_irqrestore(&gp_info->pkt_buf.rd_idx_lock,
  506. gp_info->pkt_buf.rd_irq_flag);
  507. msleep(20);
  508. tx_fifo_clear_cnt++;
  509. /* atomic_sub(comp_count, &p_info->firmware_info.tx_comp_num); */
  510. /* update tx to firemware information */
  511. } else {
  512. spin_unlock_irqrestore(&gp_info->pkt_buf.rd_idx_lock,
  513. gp_info->pkt_buf.rd_irq_flag);
  514. retry--;
  515. tx_fifo_clear_cnt = 0;
  516. msleep(20);
  517. }
  518. #endif
  519. if (tx_fifo_clear_cnt == SAFE_CNT_TO_SET_OWN) {
  520. STPSDIO_DBG_FUNC("set own (sleep) is permitted!\n");
  521. break;
  522. }
  523. }
  524. if (!retry) {
  525. STPSDIO_WARN_FUNC("set own (sleep) is not permitted, bus is busy.\n");
  526. return -2;
  527. }
  528. /* <1> request firmware-own back */
  529. STPSDIO_INFO_FUNC("set firmware own! (sleeping)\n");
  530. ret = mtk_wcn_hif_sdio_writel(clt_ctx, CHLPCR, C_FW_OWN_REQ_SET);
  531. if (ret) {
  532. STPSDIO_ERR_FUNC("set firmware own! (sleeping) fail\n");
  533. goto out;
  534. }
  535. /* <2> wait own_back bit is set. */
  536. retry = 10;
  537. do {
  538. ret = mtk_wcn_hif_sdio_readl(clt_ctx, CHLPCR, &chlcpr_value);
  539. if (ret) {
  540. /* 4 <1.1> get CHISR Rx error handling */
  541. STPSDIO_ERR_FUNC("get CHISR information rx error!(%d)\n", ret);
  542. goto out;
  543. }
  544. if ((chlcpr_value & C_FW_COM_DRV_OWN) == 0) {
  545. /* 4 <2> handle ownership back interrupt */
  546. STPSDIO_INFO_FUNC("set firmware own succeful, retry:%d\n",
  547. SET_OWN_RETRY - retry);
  548. } else {
  549. STPSDIO_INFO_FUNC("set firmware own! wait for (%d us) and retry\n",
  550. delay_us);
  551. udelay(delay_us);
  552. }
  553. } while (retry-- > 0);
  554. ret = (retry > 0) ? 0 : -1;
  555. out:
  556. return ret;
  557. }
  558. #endif
  559. /*!
  560. * \brief
  561. *
  562. * \details
  563. *
  564. * \param[IN] op code for SDIO PS and OWN control
  565. *
  566. * \retval 0 success
  567. * \retval !=0 fail
  568. */
  569. INT32 stp_sdio_own_ctrl(SDIO_PS_OP op)
  570. {
  571. INT32 ret = -1;
  572. P_OSAL_SIGNAL pOsalSignal = NULL;
  573. if (0 == g_stp_sdio_host_count) {
  574. STPSDIO_WARN_FUNC("g_stp_sdio_host_count is 0, do nothing!\n");
  575. return 0;
  576. }
  577. pOsalSignal = &gp_info->isr_check_complete;
  578. pOsalSignal->timeoutValue = 100;
  579. osal_signal_init(pOsalSignal);
  580. switch (op) {
  581. case OWN_SET:
  582. /* ret = stp_sdio_do_own_set(); */
  583. gp_info->wakeup_flag = 0;
  584. gp_info->sleep_flag = 1;
  585. osal_trigger_event(&gp_info->tx_rx_event);
  586. STPSDIO_LOUD_FUNC("before op(%d)\n", op);
  587. osal_wait_for_signal(pOsalSignal);
  588. STPSDIO_LOUD_FUNC("after op(%d)\n", op);
  589. ret = 0;
  590. break;
  591. case OWN_CLR:
  592. /* ret = stp_sdio_do_own_clr(1); */
  593. gp_info->sleep_flag = 0;
  594. gp_info->wakeup_flag = 1;
  595. osal_trigger_event(&gp_info->tx_rx_event);
  596. STPSDIO_LOUD_FUNC("before op(%d)\n", op);
  597. osal_wait_for_signal(pOsalSignal);
  598. STPSDIO_LOUD_FUNC("after op(%d)\n", op);
  599. ret = 0;
  600. break;
  601. case OWN_STATE:
  602. /* ret = stp_sdio_get_own_state(); */
  603. STPSDIO_INFO_FUNC("omit op(%d)\n", op);
  604. ret = 0;
  605. break;
  606. default:
  607. STPSDIO_WARN_FUNC("omit op(%d)\n", op);
  608. ret = -1;
  609. break;
  610. }
  611. osal_signal_deinit(pOsalSignal);
  612. return ret;
  613. }
  614. #if STP_SDIO_OWN_THREAD
  615. static INT32 _stp_sdio_wait_for_msg(PVOID pvData)
  616. {
  617. MTK_WCN_STP_SDIO_HIF_INFO *pInfo = (MTK_WCN_STP_SDIO_HIF_INFO *) pvData;
  618. #if STP_SDIO_NEW_TXRING
  619. STPSDIO_LOUD_FUNC
  620. ("len(%u), wr_cnt(%u), rd_cnt(%u), irq_pending(%u), sleep(%u), wakeup(%u)\n",
  621. pInfo->rx_pkt_len, pInfo->pkt_buf.wr_cnt, pInfo->pkt_buf.rd_cnt, pInfo->irq_pending,
  622. pInfo->sleep_flag, pInfo->wakeup_flag);
  623. return (0 != pInfo->rx_pkt_len)
  624. || (pInfo->pkt_buf.wr_cnt != pInfo->pkt_buf.rd_cnt)
  625. || (0 != pInfo->irq_pending)
  626. || (0 != pInfo->sleep_flag)
  627. || (0 != pInfo->wakeup_flag)
  628. || (osal_thread_should_stop(&pInfo->tx_rx_thread));
  629. #else
  630. STPSDIO_LOUD_FUNC
  631. ("len(%u), rd_idx(%u), wr_idx(%u), irq_pending(%u), sleep(%u), wakeup(%u)\n",
  632. pInfo->rx_pkt_len, pInfo->pkt_buf.rd_idx, pInfo->pkt_buf.wr_idx, pInfo->irq_pending,
  633. pInfo->sleep_flag, pInfo->wakeup_flag);
  634. return (pInfo->rx_pkt_len != 0)
  635. || (pInfo->pkt_buf.rd_idx != pInfo->pkt_buf.wr_idx)
  636. || (0 != pInfo->irq_pending)
  637. || (0 != pInfo->sleep_flag)
  638. || (0 != pInfo->wakeup_flag)
  639. || (osal_thread_should_stop(&pInfo->tx_rx_thread));
  640. #endif
  641. }
  642. static VOID stp_sdio_tx_rx_handling(PVOID pData)
  643. {
  644. MTK_WCN_STP_SDIO_HIF_INFO *pInfo = (MTK_WCN_STP_SDIO_HIF_INFO *) pData;
  645. UINT32 iRet = 0;
  646. UINT32 chisr = 0;
  647. UINT32 chlcpr_value = 0;
  648. UINT32 tx_comp = 0;
  649. MTK_WCN_HIF_SDIO_CLTCTX clt_ctx;
  650. UINT32 while_loop_counter = 0;
  651. UINT32 own_fail_counter = 0;
  652. UINT32 val = 0;
  653. STPSDIO_INFO_FUNC("stp_tx_rx_thread start running...\n");
  654. if (NULL == pInfo) {
  655. STPSDIO_WARN_FUNC("sanity check fail, (pInfo == NULL)\n");
  656. return;
  657. }
  658. clt_ctx = pInfo->sdio_cltctx;
  659. STPSDIO_INFO_FUNC("stp_tx_rx_thread runns\n");
  660. while (!osal_thread_should_stop(&pInfo->tx_rx_thread)) {
  661. while_loop_counter++;
  662. /* <0> get CHLPCR information */
  663. if (OWN_SET == stp_sdio_get_own_state()) {
  664. STPSDIO_DBG_FUNC("OWN on fw side!\n");
  665. mtk_wcn_hif_sdio_dis_deep_sleep(clt_ctx);
  666. if (0 == stp_sdio_do_own_clr(0)) {
  667. STPSDIO_DBG_FUNC("set OWN to driver side ok!\n");
  668. pInfo->awake_flag = 1;
  669. own_fail_counter = 0;
  670. } else {
  671. if ((0 != pInfo->sleep_flag) || (0 != pInfo->wakeup_flag)) {
  672. pInfo->wakeup_flag = 0;
  673. pInfo->sleep_flag = 0;
  674. STPSDIO_WARN_FUNC("clr fw own fail,signal for sleep/wakeup to return\n");
  675. osal_raise_signal(&pInfo->isr_check_complete);
  676. }
  677. if (0 == (own_fail_counter % 50)) {
  678. STPSDIO_ERR_FUNC("set OWN to driver side error!\n");
  679. /*trigger whole chip reset by send fake coredump content */
  680. if (0 == own_fail_counter) {
  681. mtk_wcn_stp_read_fw_cpupcr();
  682. _stp_sdio_issue_fake_coredump
  683. ("ABT: STP-SDIO clear f/w own failed");
  684. }
  685. }
  686. own_fail_counter++;
  687. }
  688. } else {
  689. STPSDIO_DBG_FUNC("OWN on driver side!\n");
  690. pInfo->awake_flag = 1;
  691. }
  692. if ((0 != pInfo->wakeup_flag) && (0 != pInfo->awake_flag)) {
  693. while_loop_counter = 0;
  694. STPSDIO_DBG_FUNC("clr firmware own! (wakeup) ok\n");
  695. pInfo->wakeup_flag = 0;
  696. osal_raise_signal(&pInfo->isr_check_complete);
  697. }
  698. if ((0 != pInfo->irq_pending) && (1 == pInfo->awake_flag)) {
  699. while_loop_counter = 0;
  700. /* <1> get CHISR information */
  701. iRet = mtk_wcn_hif_sdio_readl(clt_ctx, CHISR, &chisr);
  702. if (iRet) {
  703. /* 4 <1.1> get CHISR Rx error handling */
  704. /* TODO: error handling! */
  705. STPSDIO_ERR_FUNC("get CHISR information rx error, ret:%d\n", iRet);
  706. if (-5 == iRet) {
  707. chisr =
  708. stp_sdio_rc_reg_readl_retry(clt_ctx, CSR, 100, &iRet);
  709. pInfo->irq_pending = 0;
  710. }
  711. } else
  712. pInfo->irq_pending = 0;
  713. if (0 != pInfo->dump_flag)
  714. STPSDIO_ERR_FUNC("CHISR(0x%08x)\n", chisr);
  715. else
  716. STPSDIO_DBG_FUNC("CHISR(0x%08x)\n", chisr);
  717. if (0x0 == chisr) {
  718. gStpSdioDbgLvl = STPSDIO_LOG_DBG;
  719. STPSDIO_ERR_FUNC("******CHISR == 0*****\n");
  720. mtk_wcn_hif_sdio_readl(clt_ctx, CCIR, &val);
  721. STPSDIO_ERR_FUNC("******CCIR == 0x%x*****\n", val);
  722. mtk_wcn_hif_sdio_readl(clt_ctx, CHLPCR, &val);
  723. STPSDIO_ERR_FUNC("******CHLPCR == 0x%x*****\n", val);
  724. mtk_wcn_hif_sdio_readl(clt_ctx, CSDIOCSR, &val);
  725. STPSDIO_ERR_FUNC("******CSDIOCSR == 0x%x*****\n", val);
  726. mtk_wcn_hif_sdio_readl(clt_ctx, CHCR, &val);
  727. STPSDIO_ERR_FUNC("******CHCR == 0x%x*****\n", val);
  728. mtk_wcn_hif_sdio_readl(clt_ctx, CHISR, &val);
  729. STPSDIO_ERR_FUNC("******CHISR == 0x%x*****\n", val);
  730. mtk_wcn_hif_sdio_readl(clt_ctx, CHIER, &val);
  731. STPSDIO_ERR_FUNC("******CHIER == 0x%x*****\n", val);
  732. mtk_wcn_hif_sdio_readl(clt_ctx, CTFSR, &val);
  733. STPSDIO_ERR_FUNC("******CTFSR == 0x%x*****\n", val);
  734. mtk_wcn_hif_sdio_readl(clt_ctx, CRPLR, &val);
  735. STPSDIO_ERR_FUNC("******CRPLR == 0x%x*****\n", val);
  736. } else
  737. gStpSdioDbgLvl = STPSDIO_LOG_INFO;
  738. if (chisr & FW_OWN_BACK_INT)
  739. STPSDIO_HINT_FUNC("FW_OWN_BACK_INT\n");
  740. /* <4> handle Tx interrupt */
  741. if ((chisr & TX_EMPTY) || (chisr & TX_UNDER_THOLD)) {
  742. while_loop_counter = 0;
  743. STPSDIO_DBG_FUNC("Tx interrupt\n");
  744. /* get complete count */
  745. tx_comp = (chisr & TX_COMPLETE_COUNT) >> 4;
  746. tx_comp =
  747. atomic_add_return(tx_comp, &pInfo->firmware_info.tx_comp_num);
  748. if (tx_comp > STP_SDIO_TX_PKT_MAX_CNT)
  749. STPSDIO_ERR_FUNC
  750. ("Abnormal accumulated comp count(%d) chisr(0x%x)\n",
  751. tx_comp, chisr);
  752. }
  753. if (1 == pInfo->awake_flag)
  754. stp_sdio_tx_wkr(&pInfo->tx_work);
  755. if (chisr & RX_DONE) {
  756. /* STPSDIO_INFO_FUNC("RX_DONE_INT\n"); */
  757. if (pInfo->rx_pkt_len)
  758. STPSDIO_ERR_FUNC("rx worker is not finished yet!\n");
  759. /* get Rx packet length */
  760. pInfo->rx_pkt_len = (chisr & RX_PKT_LEN) >> 16;
  761. STPSDIO_HINT_FUNC("rx_pkt_len(%d)\n", pInfo->rx_pkt_len);
  762. /* sanity check */
  763. if ((0 == pInfo->rx_pkt_len)
  764. || (STP_SDIO_RX_FIFO_SIZE < pInfo->rx_pkt_len)) {
  765. STPSDIO_ERR_FUNC
  766. ("abnormal rx_pkt_len(%d) in CHISR(0x%08x) skip rx_worker\n",
  767. pInfo->rx_pkt_len, chisr);
  768. pInfo->rx_pkt_len = 0;
  769. } else {
  770. /* Before host driver read all rx data, chip/fw will not send more data
  771. * to host. No need to mask rx interrupt. schedule rx worker to get data
  772. * back and handle it.
  773. */
  774. if (pInfo->rx_pkt_len & 0x3)
  775. STPSDIO_WARN_FUNC("rx len not 4 bytes, CHISR(0x%08x), rx len (%d).\n",
  776. chisr, pInfo->rx_pkt_len);
  777. }
  778. /*Rx job */
  779. stp_sdio_rx_wkr(&pInfo->rx_work);
  780. mtk_wcn_stp_wmt_sdio_host_awake();
  781. }
  782. }
  783. /* We schedule Tx job here without condition */
  784. /*Tx job */
  785. if (1 == pInfo->awake_flag)
  786. stp_sdio_tx_wkr(&pInfo->tx_work);
  787. /*Enable IRQ */
  788. /*Disable Common interrupt output in CHLPCR */
  789. STPSDIO_DBG_FUNC("enable COM IRQ\n");
  790. /* need to wait for the ownback completion */
  791. /* [COHEC_00006052] SW work-around solution:
  792. using CMD52 write instead of CMD53 write for CCIR, CHLPCR, CSDIOCSR */
  793. #if COHEC_00006052
  794. iRet = mtk_wcn_hif_sdio_writeb(clt_ctx, CHLPCR, C_FW_INT_EN_SET);
  795. #else
  796. iRet = mtk_wcn_hif_sdio_writel(clt_ctx, CHLPCR, C_FW_INT_EN_SET);
  797. #endif /* COHEC_00006052 */
  798. if (iRet) {
  799. STPSDIO_ERR_FUNC("enable IRQ fail. iRet:%d\n", iRet);
  800. } else {
  801. STPSDIO_HINT_FUNC("enable COM IRQ\n");
  802. iRet = mtk_wcn_hif_sdio_readl(clt_ctx, CHLPCR, &chlcpr_value);
  803. if (iRet) {
  804. STPSDIO_ERR_FUNC("read CHLPCR fail. iRet:%d\n", iRet);
  805. } else {
  806. if (chlcpr_value & C_FW_INT_EN_SET) {
  807. STPSDIO_HINT_FUNC("enable COM IRQ okay (0x%x)\n",
  808. chlcpr_value);
  809. /* INTR_STATUS CHECK */
  810. /*
  811. iRet = mtk_wcn_hif_sdio_writel(clt_ctx, CHCR, 0x00000002); // W1C
  812. iRet = mtk_wcn_hif_sdio_readl(clt_ctx, CHISR, &chisr);
  813. STPSDIO_INFO_FUNC("Query CHISR(0x%08x)\n", chisr);
  814. iRet = mtk_wcn_hif_sdio_writel(clt_ctx, CHCR, 0x00000000); // W1C
  815. */
  816. }
  817. #if 0
  818. else {
  819. STPSDIO_ERR_FUNC
  820. ("**************Fatal Error, enable COM IRQ fail*********\n");
  821. }
  822. #endif
  823. }
  824. }
  825. if ((0 != pInfo->sleep_flag) && (0 == pInfo->wakeup_flag) && mtk_wcn_stp_is_ready()
  826. && (0 == pInfo->irq_pending)
  827. && (0 == pInfo->firmware_info.tx_packet_num)
  828. && (0 == pInfo->rx_pkt_len)
  829. && !mtk_wcn_stp_coredump_start_get() /* f/w assert disable sdio sleep */
  830. ) {
  831. /* pInfo->awake_flag = 0; */
  832. /* STPSDIO_INFO_FUNC("set firmware own! (sleeping)\n"); */
  833. /* [COHEC_00006052] SW work-around solution:
  834. using CMD52 write instead of CMD53 write for CCIR, CHLPCR, CSDIOCSR */
  835. while_loop_counter = 0;
  836. #if COHEC_00006052
  837. iRet =
  838. mtk_wcn_hif_sdio_writeb(clt_ctx, (UINT32) (CHLPCR + 0x01),
  839. (UINT8) (C_FW_OWN_REQ_SET >> 8));
  840. #else
  841. iRet = mtk_wcn_hif_sdio_writel(clt_ctx, CHLPCR, C_FW_OWN_REQ_SET);
  842. #endif /* COHEC_00006052 */
  843. if (iRet) {
  844. STPSDIO_ERR_FUNC("set firmware own! (sleeping) fail\n");
  845. } else {
  846. iRet = mtk_wcn_hif_sdio_readl(clt_ctx, CHLPCR, &chlcpr_value);
  847. if (iRet) {
  848. STPSDIO_ERR_FUNC
  849. ("get firmware own! (sleeping) fail iRet:%d\n", iRet);
  850. } else {
  851. if (!(chlcpr_value & C_FW_COM_DRV_OWN)) {
  852. while_loop_counter = 0;
  853. STPSDIO_DBG_FUNC
  854. ("set firmware own! (sleeping) ok\n");
  855. pInfo->awake_flag = 0;
  856. pInfo->sleep_flag = 0;
  857. mtk_wcn_hif_sdio_en_deep_sleep(clt_ctx);
  858. osal_raise_signal(&pInfo->isr_check_complete);
  859. } else {
  860. STPSDIO_ERR_FUNC
  861. ("set firmware own! (sleeping) fail, set CLR BACK\n");
  862. /* if set firmware own not successful (possibly pending interrupts), */
  863. /* indicate an own clear event */
  864. /* [COHEC_00006052] SW work-around solution:
  865. using CMD52 write instead of CMD53 write for CCIR, CHLPCR, CSDIOCSR */
  866. #if COHEC_00006052
  867. iRet =
  868. mtk_wcn_hif_sdio_writeb(clt_ctx,
  869. (UINT32) (CHLPCR +
  870. 0x01), (UINT8)
  871. (C_FW_OWN_REQ_CLR >>
  872. 8));
  873. #else
  874. iRet =
  875. mtk_wcn_hif_sdio_writel(clt_ctx, CHLPCR,
  876. C_FW_OWN_REQ_CLR);
  877. #endif /* COHEC_00006052 */
  878. }
  879. }
  880. }
  881. } else {
  882. }
  883. if (1000 < while_loop_counter) {
  884. while_loop_counter = 0;
  885. pInfo->dump_flag = 1;
  886. STPSDIO_ERR_FUNC("stp_is_ready(%d) irq_pending(%d) tx_packet_num(%d) rx_pkt_len(%d)\n",
  887. mtk_wcn_stp_is_ready(), pInfo->irq_pending,
  888. pInfo->firmware_info.tx_packet_num, pInfo->rx_pkt_len);
  889. /*make fake irq flag to dump CHISR information */
  890. pInfo->irq_pending = 1;
  891. if ((0 != pInfo->sleep_flag) || (0 != pInfo->wakeup_flag)) {
  892. /*clear wakeup/sleep pending flag, wakeup wmtd thread */
  893. pInfo->wakeup_flag = 0;
  894. pInfo->sleep_flag = 0;
  895. osal_raise_signal(&pInfo->isr_check_complete);
  896. if (STP_SDIO_TX_PKT_MAX_CNT == pInfo->firmware_info.tx_packet_num) {
  897. STPSDIO_ERR_FUNC("STP-SDIO can't handle tx request. tx_packet_num:%d\n",
  898. pInfo->firmware_info.tx_packet_num);
  899. osal_sleep_ms(200);
  900. }
  901. }
  902. } else {
  903. pInfo->dump_flag = 0;
  904. }
  905. osal_wait_for_event(&pInfo->tx_rx_event, _stp_sdio_wait_for_msg, (PVOID) pInfo);
  906. /* Read Packet from Firmware until firmware rx packet empty */
  907. STPSDIO_DBG_FUNC("stp_tx_rx_thread receive signal\n");
  908. }
  909. /*make sure thread who is waiting for STP-SDIO's sleep/wakeup completion event */
  910. if ((0 != pInfo->sleep_flag) || (0 != pInfo->wakeup_flag)) {
  911. pInfo->wakeup_flag = 0;
  912. pInfo->sleep_flag = 0;
  913. STPSDIO_WARN_FUNC("someone is wait for sleep/wakeup event, signal it to return\n");
  914. osal_raise_signal(&pInfo->isr_check_complete);
  915. }
  916. while (0 < osal_signal_active_state(&pInfo->isr_check_complete)) {
  917. STPSDIO_WARN_FUNC("is_check_complete signal in active state, wait for a moment.\n");
  918. osal_sleep_ms(10);
  919. }
  920. STPSDIO_INFO_FUNC("stp_tx_rx_thread exit\n");
  921. }
  922. #endif
  923. /*!
  924. * \brief Tx callback function for STP-CORE module
  925. *
  926. * \details A function registered to STP-CORE to provide STP-SDIO tx method.
  927. * Multiple STP packet may be aggregated when available.
  928. *
  929. * \param[IN] data STP packet buffer to be sent through STP-SDIO
  930. * \param[IN] size STP packet length to be sent
  931. * \param[OUT] written_size Accepted buffer length by STP-SDIO. Shall be $size
  932. * if success.
  933. *
  934. *\note Tx may do aggregation to previous entry with lock protection. If no
  935. * aggregation is done, protection is NOT required.
  936. *
  937. * \retval 0 success
  938. * \retval -1 invalid input parameters
  939. * \todo return !0 when fail case (TBD)
  940. */
  941. #if STP_SDIO_NEW_TXRING
  942. INT32 stp_sdio_tx(const PUINT8 data, const UINT32 size, PUINT32 written_size)
  943. {
  944. PUINT8 pkt_bufp;
  945. UINT32 prev_wr_idx;
  946. UINT32 prev_size;
  947. MTK_WCN_STP_SDIO_PKT_BUF *pb;
  948. UINT32 idx;
  949. STPSDIO_LOUD_FUNC("enter\n");
  950. if (written_size)
  951. *written_size = 0;
  952. /* do sanity check */
  953. if ((STP_SDIO_TX_FIFO_SIZE < size)
  954. || (!data)) {
  955. STPSDIO_LOUD_FUNC("invalid size(%ld) > fifo(%d) or data(0x%p)\n",
  956. size, STP_SDIO_TX_FIFO_SIZE, data);
  957. return -1;
  958. }
  959. pb = &gp_info->pkt_buf;
  960. /* 4 <1> enqueue the stp Tx packet */
  961. spin_lock_irqsave(&pb->rd_cnt_lock, pb->rd_irq_flag);
  962. /* Case 1: buffer is empty (No aggregation). Full flag is useless in this
  963. * condition.
  964. */
  965. if (pb->rd_cnt == pb->wr_cnt) {
  966. spin_unlock_irqrestore(&pb->rd_cnt_lock, pb->rd_irq_flag);
  967. /* Set the size in SDIO packet header later in tx_worker, not here */
  968. idx = pb->wr_cnt & STP_SDIO_TX_BUF_CNT_MASK;
  969. pb->tx_buf_ts[idx] = jiffies;
  970. pb->tx_buf_sz[idx] = size + STP_SDIO_HDR_SIZE;
  971. #if KMALLOC_UPDATE
  972. pkt_bufp = pb->tx_buf + idx * STP_SDIO_TX_ENTRY_SIZE + STP_SDIO_HDR_SIZE;
  973. #else
  974. pkt_bufp = &pb->tx_buf[idx][STP_SDIO_HDR_SIZE];
  975. #endif
  976. memcpy(pkt_bufp, data, size);
  977. ++(pb->wr_cnt);
  978. if (written_size)
  979. *written_size = size;
  980. STPSDIO_DBG_FUNC("(Empty) Enqueue done\n");
  981. }
  982. /* Case 2: buffer is neither empty(w != r) nor full (w-r < s) */
  983. else if ((pb->wr_cnt - pb->rd_cnt) < STP_SDIO_TX_BUF_CNT) {
  984. prev_wr_idx = (pb->wr_cnt - 1) & STP_SDIO_TX_BUF_CNT_MASK;
  985. prev_size = pb->tx_buf_sz[prev_wr_idx];
  986. /* Case 2.1 Aggregate if rd_cnt+1 != wr_cnt */
  987. /* George: do length check using add instead of sub operation. Compare
  988. * to FIFO size instead of sw entry size.
  989. */
  990. if (((pb->rd_cnt + 1) != pb->wr_cnt)
  991. && ((size + prev_size) <= STP_SDIO_TX_FIFO_SIZE)) {
  992. #if KMALLOC_UPDATE
  993. pkt_bufp = pb->tx_buf + prev_wr_idx * STP_SDIO_TX_ENTRY_SIZE + prev_size;
  994. #else
  995. pkt_bufp = &pb->tx_buf[prev_wr_idx][prev_size];
  996. #endif
  997. pb->tx_buf_sz[prev_wr_idx] += size;
  998. memcpy(pkt_bufp, data, size);
  999. spin_unlock_irqrestore(&pb->rd_cnt_lock, pb->rd_irq_flag);
  1000. STPSDIO_DBG_FUNC("(Not empty-aggre) Enqueue done\n");
  1001. if (written_size)
  1002. *written_size = size;
  1003. }
  1004. /* Case 2.2 Use next entry w/o aggregation */
  1005. else {
  1006. /* Check the ring buf is full or not */
  1007. if ((pb->wr_cnt - pb->rd_cnt) == 1)
  1008. pb->full_flag = MTK_WCN_BOOL_TRUE;
  1009. spin_unlock_irqrestore(&pb->rd_cnt_lock, pb->rd_irq_flag);
  1010. /* George: if tx_wkr preempts here and pop out all buffered entries,
  1011. * ie increase rd_idx utill wr_idx, tx_wkr will encounter buffer
  1012. * empty condition and stop, then being scheduled before end of this
  1013. * function. It's safe!
  1014. */
  1015. idx = pb->wr_cnt & STP_SDIO_TX_BUF_CNT_MASK;
  1016. pb->tx_buf_ts[idx] = jiffies;
  1017. pb->tx_buf_sz[idx] = size + STP_SDIO_HDR_SIZE;
  1018. #if KMALLOC_UPDATE
  1019. pkt_bufp = pb->tx_buf + idx * STP_SDIO_TX_ENTRY_SIZE + STP_SDIO_HDR_SIZE;
  1020. #else
  1021. pkt_bufp = &pb->tx_buf[idx][STP_SDIO_HDR_SIZE];
  1022. #endif
  1023. memcpy(pkt_bufp, data, size);
  1024. ++(pb->wr_cnt);
  1025. STPSDIO_DBG_FUNC("(Not empty-no aggre) Enqueue done\n");
  1026. if (written_size)
  1027. *written_size = size;
  1028. }
  1029. }
  1030. /* Case 3: buffer is full (w-r >= s), (try aggregation) */
  1031. else
  1032. /**/ {
  1033. if (!((pb->wr_cnt - pb->rd_cnt) >= STP_SDIO_TX_BUF_CNT)) {
  1034. STPSDIO_ERR_FUNC
  1035. ("abnormal condition and flow, wr_cnt(0x%x), rd_cnt(0x%x)\n",
  1036. pb->wr_cnt, pb->rd_cnt);
  1037. }
  1038. prev_wr_idx = (pb->wr_cnt - 1) & STP_SDIO_TX_BUF_CNT_MASK;
  1039. prev_size = pb->tx_buf_sz[prev_wr_idx];
  1040. /* George: do length check using add instead of sub operation. Compare
  1041. * to FIFO size instead of sw entry size. (buf_allocation != 0) shall be
  1042. * an assert true condition, not a if () condition......
  1043. */
  1044. /* Case 3.1 Aggregation */
  1045. if ((size + prev_size) <= STP_SDIO_TX_FIFO_SIZE) {
  1046. if (0 != prev_size)
  1047. STPSDIO_ERR_FUNC("abnormal, wr_cnt(0x%x), rd_cnt(0x%x), prev(%d), prev_size(%d)\n",
  1048. pb->wr_cnt, pb->rd_cnt,
  1049. prev_wr_idx, prev_size);
  1050. #if KMALLOC_UPDATE
  1051. pkt_bufp = pb->tx_buf + prev_wr_idx * STP_SDIO_TX_ENTRY_SIZE + prev_size;
  1052. #else
  1053. pkt_bufp = &pb->tx_buf[prev_wr_idx][prev_size];
  1054. #endif
  1055. pb->tx_buf_sz[prev_wr_idx] += size;
  1056. /* unlock after copying data to ring buffer done so that rd_cnt can
  1057. * move forward and may overlap to prev_wr_idx.
  1058. */
  1059. memcpy(pkt_bufp, data, size);
  1060. spin_unlock_irqrestore(&pb->rd_cnt_lock, pb->rd_irq_flag);
  1061. STPSDIO_DBG_FUNC("(full-aggre) Enqueue done\n");
  1062. if (written_size)
  1063. *written_size = size;
  1064. }
  1065. /* Case 3.2 Buffer is full */
  1066. else {
  1067. spin_unlock_irqrestore(&pb->rd_cnt_lock, pb->rd_irq_flag);
  1068. STPSDIO_WARN_FUNC("Local Tx buffer is full !\n");
  1069. /* Wait for tx ring buffer is not full */
  1070. /* TODO:[FixMe][George] This wait() call IS a problem if caller runs
  1071. in interrupt context (sw or hw) !! */
  1072. /* TODO:[FixMe][George] should use timeout version,
  1073. not interruptible version. Return error when timeout! */
  1074. wait_event_interruptible(pb->fullwait_q,
  1075. (MTK_WCN_BOOL_FALSE == pb->full_flag));
  1076. STPSDIO_INFO_FUNC("wait event return\n");
  1077. spin_lock_irqsave(&pb->rd_cnt_lock, pb->rd_irq_flag);
  1078. /* Check if the local buf is free enough */
  1079. if ((pb->wr_cnt - pb->rd_cnt) == 1)
  1080. pb->full_flag = MTK_WCN_BOOL_TRUE;
  1081. spin_unlock_irqrestore(&pb->rd_cnt_lock, pb->rd_irq_flag);
  1082. /* George: use this new entry w/o protection */
  1083. idx = pb->wr_cnt & STP_SDIO_TX_BUF_CNT_MASK;
  1084. pb->tx_buf_ts[idx] = jiffies;
  1085. pb->tx_buf_sz[idx] = size + STP_SDIO_HDR_SIZE;
  1086. #if KMALLOC_UPDATE
  1087. pkt_bufp = pb->tx_buf + idx * STP_SDIO_TX_ENTRY_SIZE + STP_SDIO_HDR_SIZE;
  1088. #else
  1089. pkt_bufp = &pb->tx_buf[idx][STP_SDIO_HDR_SIZE];
  1090. #endif
  1091. /* Copy data to ring buffer */
  1092. memcpy(pkt_bufp, data, size);
  1093. ++(pb->wr_cnt);
  1094. if (written_size)
  1095. *written_size = size;
  1096. }
  1097. }
  1098. /* <2> schedule for Tx worker tasklet */
  1099. #if STP_SDIO_OWN_THREAD
  1100. /* tasklet_schedule(&gp_info->tx_rx_job); */
  1101. STPSDIO_DBG_FUNC("osal_trigger_event gp_info->tx_rx_event\n");
  1102. osal_trigger_event(&gp_info->tx_rx_event);
  1103. #else
  1104. schedule_work(&gp_info->tx_work);
  1105. #endif
  1106. return 0;
  1107. }
  1108. #else
  1109. INT32 stp_sdio_tx(const PUINT8 data, const UINT32 size, PUINT32 written_size)
  1110. {
  1111. PUINT8 pkt_bufp;
  1112. UINT32 prev_wr_idx;
  1113. UINT32 buf_allocation;
  1114. UINT32 room;
  1115. STPSDIO_LOUD_FUNC("enter\n");
  1116. /* 4 <1> enqueue the stp Tx packet */
  1117. *written_size = 0;
  1118. spin_lock_irqsave(&gp_info->pkt_buf.rd_idx_lock, gp_info->pkt_buf.rd_irq_flag);
  1119. /* Case 1: buffer is empty (Not aggregation) */
  1120. if ((gp_info->pkt_buf.rd_idx == gp_info->pkt_buf.wr_idx)
  1121. && (MTK_WCN_BOOL_FALSE == gp_info->pkt_buf.full_flag)) {
  1122. spin_unlock_irqrestore(&gp_info->pkt_buf.rd_idx_lock, gp_info->pkt_buf.rd_irq_flag);
  1123. /* set the size in SDIO packet header */
  1124. #if KMALLOC_UPDATE
  1125. *(gp_info->pkt_buf.tx_buf + gp_info->pkt_buf.wr_idx * STP_SDIO_TX_ENTRY_SIZE + 0) =
  1126. (UINT8) ((size + STP_SDIO_HDR_SIZE) & 0xff);
  1127. *(gp_info->pkt_buf.tx_buf + gp_info->pkt_buf.wr_idx * STP_SDIO_TX_ENTRY_SIZE + 1) =
  1128. (UINT8) ((size + STP_SDIO_HDR_SIZE) >> 8);
  1129. #else
  1130. gp_info->pkt_buf.tx_buf[gp_info->pkt_buf.wr_idx][0] =
  1131. (UINT8) ((size + STP_SDIO_HDR_SIZE) & 0xff);
  1132. gp_info->pkt_buf.tx_buf[gp_info->pkt_buf.wr_idx][1] =
  1133. (UINT8) ((size + STP_SDIO_HDR_SIZE) >> 8);
  1134. #endif
  1135. gp_info->pkt_buf.tx_buf_ts[gp_info->pkt_buf.wr_idx] = jiffies;
  1136. STPSDIO_DBG_FUNC("(Empty) Enqueue done\n");
  1137. #if KMALLOC_UPDATE
  1138. pkt_bufp =
  1139. gp_info->pkt_buf.tx_buf + gp_info->pkt_buf.wr_idx * STP_SDIO_TX_ENTRY_SIZE +
  1140. STP_SDIO_HDR_SIZE;
  1141. #else
  1142. pkt_bufp = &gp_info->pkt_buf.tx_buf[gp_info->pkt_buf.wr_idx][STP_SDIO_HDR_SIZE];
  1143. #endif
  1144. memcpy(pkt_bufp, data, size);
  1145. *written_size = size;
  1146. gp_info->pkt_buf.wr_idx = (gp_info->pkt_buf.wr_idx + 1) % STP_SDIO_TX_BUF_CNT;
  1147. }
  1148. /* Case 2: buffer is not empty */
  1149. else if (gp_info->pkt_buf.rd_idx != gp_info->pkt_buf.wr_idx) {
  1150. prev_wr_idx =
  1151. (gp_info->pkt_buf.wr_idx - 1 + STP_SDIO_TX_BUF_CNT) % STP_SDIO_TX_BUF_CNT;
  1152. /* set the packet size form previous SDIO packet header */
  1153. #if KMALLOC_UPDATE
  1154. buf_allocation =
  1155. *(gp_info->pkt_buf.tx_buf + prev_wr_idx * STP_SDIO_TX_ENTRY_SIZE + 1);
  1156. buf_allocation =
  1157. (buf_allocation << 8) | *(gp_info->pkt_buf.tx_buf +
  1158. prev_wr_idx * STP_SDIO_TX_ENTRY_SIZE + 0);
  1159. #else
  1160. buf_allocation = gp_info->pkt_buf.tx_buf[prev_wr_idx][1];
  1161. buf_allocation = (buf_allocation << 8) | gp_info->pkt_buf.tx_buf[prev_wr_idx][0];
  1162. #endif
  1163. /* Case 2.1 Aggregation */
  1164. /* George: do length check using add instead of sub operation. Compare
  1165. * to FIFO size instead of sw entry size.
  1166. */
  1167. if ((prev_wr_idx != gp_info->pkt_buf.rd_idx)
  1168. && ((size + buf_allocation) <= STP_SDIO_TX_FIFO_SIZE)) {
  1169. #if KMALLOC_UPDATE
  1170. pkt_bufp =
  1171. gp_info->pkt_buf.tx_buf + prev_wr_idx * STP_SDIO_TX_ENTRY_SIZE +
  1172. buf_allocation;
  1173. buf_allocation += size;
  1174. *(gp_info->pkt_buf.tx_buf + prev_wr_idx * STP_SDIO_TX_ENTRY_SIZE + 0) =
  1175. (UINT8) (buf_allocation & 0xff);
  1176. *(gp_info->pkt_buf.tx_buf + prev_wr_idx * STP_SDIO_TX_ENTRY_SIZE + 1) =
  1177. (UINT8) (buf_allocation >> 8);
  1178. #else
  1179. pkt_bufp = &gp_info->pkt_buf.tx_buf[prev_wr_idx][buf_allocation];
  1180. buf_allocation += size;
  1181. gp_info->pkt_buf.tx_buf[prev_wr_idx][0] = (UINT8) (buf_allocation & 0xff);
  1182. gp_info->pkt_buf.tx_buf[prev_wr_idx][1] = (UINT8) (buf_allocation >> 8);
  1183. #endif
  1184. memcpy(pkt_bufp, data, size);
  1185. spin_unlock_irqrestore(&gp_info->pkt_buf.rd_idx_lock,
  1186. gp_info->pkt_buf.rd_irq_flag);
  1187. STPSDIO_DBG_FUNC("(Not empty-aggre) Enqueue done\n");
  1188. *written_size = size;
  1189. }
  1190. /* Case 2.2 Not aggregation */
  1191. else {
  1192. /* Check the ring buf is full or not */
  1193. room = (gp_info->pkt_buf.wr_idx >= gp_info->pkt_buf.rd_idx) ?
  1194. (STP_SDIO_TX_BUF_CNT -
  1195. (gp_info->pkt_buf.wr_idx -
  1196. gp_info->pkt_buf.rd_idx)) : (gp_info->pkt_buf.rd_idx -
  1197. gp_info->pkt_buf.wr_idx);
  1198. if (room == 1)
  1199. gp_info->pkt_buf.full_flag = MTK_WCN_BOOL_TRUE;
  1200. spin_unlock_irqrestore(&gp_info->pkt_buf.rd_idx_lock,
  1201. gp_info->pkt_buf.rd_irq_flag);
  1202. /* George: if tx_wkr preempts here and pop out all buffered entries,
  1203. * ie increase rd_idx utill wr_idx, tx_wkr will encounter buffer
  1204. * empty condition and stop, then being scheduled before end of this
  1205. * function. It's safe!
  1206. */
  1207. /* set the size in SDIO packet header */
  1208. #if KMALLOC_UPDATE
  1209. *(gp_info->pkt_buf.tx_buf +
  1210. gp_info->pkt_buf.wr_idx * STP_SDIO_TX_ENTRY_SIZE + 0) =
  1211. (UINT8) ((size + STP_SDIO_HDR_SIZE) & 0xff);
  1212. *(gp_info->pkt_buf.tx_buf +
  1213. gp_info->pkt_buf.wr_idx * STP_SDIO_TX_ENTRY_SIZE + 1) =
  1214. (UINT8) ((size + STP_SDIO_HDR_SIZE) >> 8);
  1215. gp_info->pkt_buf.tx_buf_ts[gp_info->pkt_buf.wr_idx] = jiffies;
  1216. pkt_bufp =
  1217. gp_info->pkt_buf.tx_buf +
  1218. gp_info->pkt_buf.wr_idx * STP_SDIO_TX_ENTRY_SIZE + STP_SDIO_HDR_SIZE;
  1219. #else
  1220. gp_info->pkt_buf.tx_buf[gp_info->pkt_buf.wr_idx][0] =
  1221. (UINT8) ((size + STP_SDIO_HDR_SIZE) & 0xff);
  1222. gp_info->pkt_buf.tx_buf[gp_info->pkt_buf.wr_idx][1] =
  1223. (UINT8) ((size + STP_SDIO_HDR_SIZE) >> 8);
  1224. gp_info->pkt_buf.tx_buf_ts[gp_info->pkt_buf.wr_idx] = jiffies;
  1225. pkt_bufp =
  1226. &gp_info->pkt_buf.tx_buf[gp_info->pkt_buf.wr_idx][STP_SDIO_HDR_SIZE];
  1227. #endif
  1228. memcpy(pkt_bufp, data, size);
  1229. STPSDIO_DBG_FUNC("(Not empty-no aggre) Enqueue done\n");
  1230. *written_size = size;
  1231. gp_info->pkt_buf.wr_idx =
  1232. (gp_info->pkt_buf.wr_idx + 1) % STP_SDIO_TX_BUF_CNT;
  1233. }
  1234. }
  1235. /* Case 3: buffer is full (Aggregation) */
  1236. else if (MTK_WCN_BOOL_FALSE != gp_info->pkt_buf.full_flag) {
  1237. prev_wr_idx =
  1238. (gp_info->pkt_buf.wr_idx - 1 + STP_SDIO_TX_BUF_CNT) % STP_SDIO_TX_BUF_CNT;
  1239. #if KMALLOC_UPDATE
  1240. buf_allocation =
  1241. *(gp_info->pkt_buf.tx_buf + prev_wr_idx * STP_SDIO_TX_ENTRY_SIZE + 1);
  1242. buf_allocation =
  1243. (buf_allocation << 8) | *(gp_info->pkt_buf.tx_buf +
  1244. prev_wr_idx * STP_SDIO_TX_ENTRY_SIZE + 0);
  1245. #else
  1246. buf_allocation = gp_info->pkt_buf.tx_buf[prev_wr_idx][1];
  1247. buf_allocation = (buf_allocation << 8) | gp_info->pkt_buf.tx_buf[prev_wr_idx][0];
  1248. #endif
  1249. /* Case 3.1 Aggregation */
  1250. /* George: do length check using add instead of sub operation. Compare
  1251. * to FIFO size instead of sw entry size. (buf_allocation != 0) shall be
  1252. * an assert true condition, not a if () condition......
  1253. */
  1254. if ((buf_allocation != 0)
  1255. && ((size + buf_allocation) <= STP_SDIO_TX_FIFO_SIZE)) {
  1256. #if KMALLOC_UPDATE
  1257. pkt_bufp =
  1258. gp_info->pkt_buf.tx_buf + prev_wr_idx * STP_SDIO_TX_ENTRY_SIZE +
  1259. buf_allocation;
  1260. #else
  1261. pkt_bufp = &gp_info->pkt_buf.tx_buf[prev_wr_idx][buf_allocation];
  1262. #endif
  1263. buf_allocation += size;
  1264. #if KMALLOC_UPDATE
  1265. *(gp_info->pkt_buf.tx_buf + prev_wr_idx * STP_SDIO_TX_ENTRY_SIZE + 0) =
  1266. (UINT8) (buf_allocation & 0xff);
  1267. *(gp_info->pkt_buf.tx_buf + prev_wr_idx * STP_SDIO_TX_ENTRY_SIZE + 1) =
  1268. (UINT8) (buf_allocation >> 8);
  1269. #else
  1270. gp_info->pkt_buf.tx_buf[prev_wr_idx][0] = (UINT8) (buf_allocation & 0xff);
  1271. gp_info->pkt_buf.tx_buf[prev_wr_idx][1] = (UINT8) (buf_allocation >> 8);
  1272. #endif
  1273. /* Copy data to ring buffer */
  1274. memcpy(pkt_bufp, data, size);
  1275. spin_unlock_irqrestore(&gp_info->pkt_buf.rd_idx_lock,
  1276. gp_info->pkt_buf.rd_irq_flag);
  1277. STPSDIO_DBG_FUNC("(full-aggre) Enqueue done\n");
  1278. *written_size = size;
  1279. }
  1280. /* Case 3.2 Buffer is full */
  1281. else {
  1282. spin_unlock_irqrestore(&gp_info->pkt_buf.rd_idx_lock,
  1283. gp_info->pkt_buf.rd_irq_flag);
  1284. STPSDIO_WARN_FUNC("Local Tx buffer is full !!!!!\n");
  1285. /* Wait for tx ring buffer is not full */
  1286. /* TODO:[FixMe][George] This wait() call IS a problem
  1287. if caller runs in interrupt context (sw or hw) !! */
  1288. /* TODO:[FixMe][George] should use timeout version,
  1289. not interruptible version. Return error when timeout! */
  1290. wait_event_interruptible(gp_info->pkt_buf.fullwait_q,
  1291. (!gp_info->pkt_buf.full_flag));
  1292. STPSDIO_INFO_FUNC("wait event return\n");
  1293. spin_lock_irqsave(&gp_info->pkt_buf.rd_idx_lock,
  1294. gp_info->pkt_buf.rd_irq_flag);
  1295. /* Check if the local buf is free enough */
  1296. room = (gp_info->pkt_buf.wr_idx >= gp_info->pkt_buf.rd_idx) ?
  1297. (STP_SDIO_TX_BUF_CNT -
  1298. (gp_info->pkt_buf.wr_idx -
  1299. gp_info->pkt_buf.rd_idx)) : (gp_info->pkt_buf.rd_idx -
  1300. gp_info->pkt_buf.wr_idx);
  1301. if (room == 1)
  1302. gp_info->pkt_buf.full_flag = MTK_WCN_BOOL_TRUE;
  1303. spin_unlock_irqrestore(&gp_info->pkt_buf.rd_idx_lock,
  1304. gp_info->pkt_buf.rd_irq_flag);
  1305. /* George: use this new entry w/o protection */
  1306. #if KMALLOC_UPDATE
  1307. *(gp_info->pkt_buf.tx_buf + gp_info->pkt_buf.wr_idx * STP_SDIO_TX_ENTRY_SIZE + 0) =
  1308. (UINT8) ((size + STP_SDIO_HDR_SIZE) & 0xff);
  1309. *(gp_info->pkt_buf.tx_buf + gp_info->pkt_buf.wr_idx * STP_SDIO_TX_ENTRY_SIZE + 1) =
  1310. (UINT8) ((size + STP_SDIO_HDR_SIZE) >> 8);
  1311. gp_info->pkt_buf.tx_buf_ts[gp_info->pkt_buf.wr_idx] = jiffies;
  1312. pkt_bufp = gp_info->pkt_buf.tx_buf + gp_info->pkt_buf.wr_idx
  1313. * STP_SDIO_TX_ENTRY_SIZE + STP_SDIO_HDR_SIZE;
  1314. #else
  1315. gp_info->pkt_buf.tx_buf[gp_info->pkt_buf.wr_idx][0] =
  1316. (UINT8) ((size + STP_SDIO_HDR_SIZE) & 0xff);
  1317. gp_info->pkt_buf.tx_buf[gp_info->pkt_buf.wr_idx][1] =
  1318. (UINT8) ((size + STP_SDIO_HDR_SIZE) >> 8);
  1319. gp_info->pkt_buf.tx_buf_ts[gp_info->pkt_buf.wr_idx] = jiffies;
  1320. pkt_bufp =
  1321. &gp_info->pkt_buf.tx_buf[gp_info->pkt_buf.wr_idx][STP_SDIO_HDR_SIZE];
  1322. #endif
  1323. /* Copy data to ring buffer */
  1324. memcpy(pkt_bufp, data, size);
  1325. *written_size = size;
  1326. gp_info->pkt_buf.wr_idx =
  1327. (gp_info->pkt_buf.wr_idx + 1) % STP_SDIO_TX_BUF_CNT;
  1328. }
  1329. }
  1330. /* <2> schedule for Tx worker tasklet */
  1331. #if STP_SDIO_OWN_THREAD
  1332. /* tasklet_schedule(&gp_info->tx_rx_job); */
  1333. STPSDIO_DBG_FUNC("osal_trigger_event gp_info->tx_rx_event\n");
  1334. osal_trigger_event(&gp_info->tx_rx_event);
  1335. #else
  1336. schedule_work(&gp_info->tx_work);
  1337. #endif
  1338. return 0;
  1339. }
  1340. #endif /* end of !STP_SDIO_NEW_TXRING */
  1341. /*!
  1342. * \brief Do STP-SDIO tx status, counters, debug information sanity check
  1343. *
  1344. * \details A function doing sanity checks on STP-SDIO Tx-related status,
  1345. * counters, debugging information. Used in tx_worker before and after bus
  1346. * write to check if any abnormal status happened.
  1347. *
  1348. * \param[IN] p_info The STP-SDIO HIF information structure pointer
  1349. * \param[IN] id The sanity check location ID, assigned by caller
  1350. *
  1351. * \retval none.
  1352. */
  1353. static VOID stp_sdio_check_tx_sanity(const MTK_WCN_STP_SDIO_HIF_INFO *p_info, const UINT32 id)
  1354. {
  1355. #if STP_SDIO_DBG_SUPPORT && STP_SDIO_TXDBG
  1356. if ((p_info) && (0 == p_info->firmware_info.tx_packet_num)) {
  1357. if (!(p_info->tx_pkt_list.pkt_rd_cnt == p_info->tx_pkt_list.pkt_wr_cnt)) {
  1358. STPSDIO_ERR_FUNC
  1359. ("abnormal fifo_size(%d) pkt_num(%d) pkt_rd(0x%x, %ld) pkt_wr(0x%x, %ld)!(%d)\n",
  1360. p_info->firmware_info.tx_fifo_size,
  1361. p_info->firmware_info.tx_packet_num, p_info->tx_pkt_list.pkt_rd_cnt,
  1362. STP_SDIO_GET_PKT_AR_IDX(p_info->tx_pkt_list.pkt_rd_cnt),
  1363. p_info->tx_pkt_list.pkt_wr_cnt,
  1364. STP_SDIO_GET_PKT_AR_IDX(p_info->tx_pkt_list.pkt_wr_cnt), id);
  1365. /* stp_sdio_dump_txdbg(); */
  1366. }
  1367. if (p_info->firmware_info.tx_fifo_size != STP_SDIO_TX_FIFO_SIZE) {
  1368. STPSDIO_ERR_FUNC
  1369. ("abnormal fifo_size(%d) pkt_num(%d) pkt_rd(0x%x, %ld) pkt_wr(0x%x, %ld)!(%d)\n",
  1370. p_info->firmware_info.tx_fifo_size,
  1371. p_info->firmware_info.tx_packet_num, p_info->tx_pkt_list.pkt_rd_cnt,
  1372. STP_SDIO_GET_PKT_AR_IDX(p_info->tx_pkt_list.pkt_rd_cnt),
  1373. p_info->tx_pkt_list.pkt_wr_cnt,
  1374. STP_SDIO_GET_PKT_AR_IDX(p_info->tx_pkt_list.pkt_wr_cnt), id);
  1375. /* stp_sdio_dump_txdbg(); */
  1376. }
  1377. } else {
  1378. if ((p_info) && (p_info->tx_pkt_list.pkt_rd_cnt == p_info->tx_pkt_list.pkt_wr_cnt)) {
  1379. STPSDIO_ERR_FUNC
  1380. ("abnormal fifo_size(%d) pkt_num(%d) pkt_rd(0x%x, %ld) pkt_wr(0x%x, %ld)!(%d)\n",
  1381. p_info->firmware_info.tx_fifo_size,
  1382. p_info->firmware_info.tx_packet_num, p_info->tx_pkt_list.pkt_rd_cnt,
  1383. STP_SDIO_GET_PKT_AR_IDX(p_info->tx_pkt_list.pkt_rd_cnt),
  1384. p_info->tx_pkt_list.pkt_wr_cnt,
  1385. STP_SDIO_GET_PKT_AR_IDX(p_info->tx_pkt_list.pkt_wr_cnt), id);
  1386. /* stp_sdio_dump_txdbg(); */
  1387. }
  1388. }
  1389. #endif
  1390. }
  1391. /*!
  1392. * \brief Handle STP-SDIO TX IRQ BH part and complete count
  1393. *
  1394. * \details Handle STP-SDIO TX IRQ bottom half part and reported tx complete
  1395. * coount. This function is used in tx_worker ONLY to avoid race condition.
  1396. *
  1397. * \note tx_comp_num in firmware_info structure shall be handled atomically.
  1398. * It is added in STP-SDIO Tx IRQ top half handler with the number reported
  1399. * in CHISR. It is deducted in this function.
  1400. *
  1401. * \note tx_fifo_size is deducted in tx_worker when writing data to bus and
  1402. * added back in this function when tx complete.
  1403. *
  1404. * \param[IN] p_info The STP-SDIO HIF information structure pointer
  1405. *
  1406. * \retval none.
  1407. */
  1408. static VOID stp_sdio_tx_wkr_comp(MTK_WCN_STP_SDIO_HIF_INFO * const p_info)
  1409. {
  1410. INT32 comp_count;
  1411. UINT32 idx;
  1412. comp_count = atomic_read(&p_info->firmware_info.tx_comp_num);
  1413. atomic_sub(comp_count, &p_info->firmware_info.tx_comp_num);
  1414. /* update tx to firemware information */
  1415. if (p_info->firmware_info.tx_packet_num >= comp_count) {
  1416. STPSDIO_DBG_FUNC("tx_pack_num(%d), comp_count(%d),tx_comp_num(%d)\n",
  1417. p_info->firmware_info.tx_packet_num, comp_count,
  1418. atomic_read(&p_info->firmware_info.tx_comp_num));
  1419. p_info->firmware_info.tx_packet_num -= comp_count;
  1420. } else {
  1421. STPSDIO_ERR_FUNC("abnormal complete count(%d), tx_packet_num(%d)!\n",
  1422. comp_count, p_info->firmware_info.tx_packet_num);
  1423. /* TODO: [FixMe][George] Add error handling or bug report!! */
  1424. }
  1425. while (comp_count > 0) {
  1426. if (p_info->tx_pkt_list.pkt_rd_cnt == p_info->tx_pkt_list.pkt_wr_cnt) {
  1427. STPSDIO_ERR_FUNC("tx complete count(%d) but tx_pkt_list empty\n",
  1428. comp_count);
  1429. STPSDIO_ERR_FUNC("rd_cnt(0x%ud, idx:%lx), wr_cnt(0x%ud, idx:%lx)!\n",
  1430. p_info->tx_pkt_list.pkt_rd_cnt,
  1431. p_info->tx_pkt_list.pkt_rd_cnt & STP_SDIO_TX_PKT_LIST_SIZE_MASK,
  1432. p_info->tx_pkt_list.pkt_wr_cnt,
  1433. p_info->tx_pkt_list.pkt_wr_cnt & STP_SDIO_TX_PKT_LIST_SIZE_MASK);
  1434. break;
  1435. }
  1436. idx = p_info->tx_pkt_list.pkt_rd_cnt++ & STP_SDIO_TX_PKT_LIST_SIZE_MASK;
  1437. p_info->firmware_info.tx_fifo_size += p_info->tx_pkt_list.pkt_size_list[idx];
  1438. p_info->tx_pkt_list.out_ts[idx] = jiffies;
  1439. --comp_count;
  1440. }
  1441. }
  1442. /*!
  1443. * \brief Handle STP-SDIO Tx buffer and send to bus
  1444. *
  1445. * \details Handle STP-SDIO Tx buffer and send SDIO packet to bus if everything
  1446. * is checked ok.
  1447. *
  1448. * \note Tx count to FIFO is counted on a 4-byte aligned base. 1~3 bytes padding
  1449. * are also sent into HW FIFO and SHALL be trimmed off by firmware.
  1450. * tx_fifo_size is deducted in this bus when writing data to bus and added
  1451. * back in handle_tx_comp() function.
  1452. *
  1453. * \note Data length written to bus shall be 4-byte aligned AND block_size
  1454. * aligned if length > block_size. Padding bytes added for block_size is
  1455. * removed by HW.
  1456. *
  1457. * \note Max accumulated Tx size to FIFO is limited by STP_SDIO_TX_FIFO_SIZE and
  1458. * it is (2080) for MT6620. It is NOT limited to 256*5=1280 bytes.
  1459. *
  1460. * \note Max outstanding Tx packet count is limited by STP_SDIO_TX_PKT_MAX_CNT
  1461. * and it is (7) for MT6620.
  1462. *
  1463. * \param[IN] work Tx work struct work_struct pointer used by STP-SDIO
  1464. *
  1465. * \retval none.
  1466. */
  1467. #if STP_SDIO_NEW_TXRING
  1468. static VOID stp_sdio_tx_wkr(
  1469. /* unsigned long data */
  1470. struct work_struct *work)
  1471. {
  1472. MTK_WCN_STP_SDIO_HIF_INFO *p_info;
  1473. UINT32 bus_txlen;
  1474. UINT32 four_byte_align_len;
  1475. PUINT8 buf_tx;
  1476. INT32 ret;
  1477. UINT32 idx;
  1478. MTK_WCN_STP_SDIO_PKT_BUF *pb;
  1479. struct timeval now;
  1480. p_info = container_of(work, MTK_WCN_STP_SDIO_HIF_INFO, tx_work);
  1481. ret = HIF_SDIO_ERR_SUCCESS;
  1482. pb = &p_info->pkt_buf;
  1483. STPSDIO_LOUD_FUNC("start\n");
  1484. /* 4 <0> Tx worker has been scheduled to send data */
  1485. do {
  1486. /* handle tx complete count if any */
  1487. stp_sdio_tx_wkr_comp(p_info);
  1488. /* check sanity of local tx information */
  1489. stp_sdio_check_tx_sanity(p_info, 1);
  1490. /* check if Tx ring buffer is empty */
  1491. if (p_info->pkt_buf.wr_cnt == p_info->pkt_buf.rd_cnt) {
  1492. /* full flag is use less in this condition */
  1493. STPSDIO_DBG_FUNC("Tx entry ring buffer empty\n");
  1494. break;
  1495. }
  1496. #if STP_SDIO_DBG_SUPPORT && STP_SDIO_TXPERFDBG
  1497. ++stp_sdio_txperf_worker_cnt;
  1498. #endif
  1499. /* George: check txed packet number < limit(7)
  1500. * tx_packet_num is maintained only in tw_worker, no protection.
  1501. */
  1502. if (STP_SDIO_TX_PKT_MAX_CNT <= p_info->firmware_info.tx_packet_num) {
  1503. STPSDIO_DBG_FUNC
  1504. ("tx_packet_num(%ld) limit, tx_fifo_size(%ld), four_byte_align_len(%ld)\n",
  1505. p_info->firmware_info.tx_packet_num,
  1506. p_info->firmware_info.tx_fifo_size, four_byte_align_len);
  1507. #if STP_SDIO_DBG_SUPPORT && STP_SDIO_TXPERFDBG
  1508. ++stp_sdio_txperf_pkt_num_lmt_cnt;
  1509. #endif
  1510. break;
  1511. }
  1512. #if STP_SDIO_DBG_SUPPORT && STP_SDIO_TXPERFDBG
  1513. stp_sdio_txperf_txed_pkt_num += p_info->firmware_info.tx_packet_num;
  1514. #endif
  1515. /* Access content in rd_cnt is safe because it will not be aggregated
  1516. * anymore in sdio_tx(). Check current tx condition with info in rd_cnt.
  1517. */
  1518. idx = pb->rd_cnt & STP_SDIO_TX_BUF_CNT_MASK;
  1519. /* Get Tx packet size from Tx size ring buf */
  1520. bus_txlen = pb->tx_buf_sz[idx];
  1521. /* Update packet length in Tx entry */
  1522. #if KMALLOC_UPDATE
  1523. buf_tx = gp_info->pkt_buf.tx_buf + idx * STP_SDIO_TX_ENTRY_SIZE + 0;
  1524. #else
  1525. buf_tx = &pb->tx_buf[idx][0];
  1526. #endif
  1527. buf_tx[0] = (UINT8) (bus_txlen & 0xff);
  1528. buf_tx[1] = (UINT8) ((bus_txlen >> 8) & 0xff);
  1529. /* George: hw always count fifo in 4-byte aligned length */
  1530. bus_txlen += 0x3;
  1531. bus_txlen &= ~(0x3UL);
  1532. four_byte_align_len = bus_txlen;
  1533. /* Sanity check: 4-byte aligned length shall not exceed HW FIFO Size */
  1534. if (four_byte_align_len > STP_SDIO_TX_FIFO_SIZE) {
  1535. STPSDIO_ERR_FUNC("abnormal four_byte_align_len(%d) > TX_FIFO_SIZE(%ld)!!\n",
  1536. four_byte_align_len, STP_SDIO_TX_FIFO_SIZE);
  1537. }
  1538. /* George: check if tx FIFO space is enough for 4-byte aligned length.
  1539. * If enough, tx this entry and increase rd_cnt.
  1540. */
  1541. if (p_info->firmware_info.tx_fifo_size >= four_byte_align_len) {
  1542. /* George: refine block_size alignment with the assumption: block_size is 2^*x */
  1543. if (STP_SDIO_BLK_SIZE < bus_txlen) {
  1544. bus_txlen += (STP_SDIO_BLK_SIZE - 1);
  1545. bus_txlen &= ~((UINT32) STP_SDIO_BLK_SIZE - 1);
  1546. }
  1547. /* Sanity check: bus_txlen shall not exceed SW entry size */
  1548. if (STP_SDIO_TX_ENTRY_SIZE < bus_txlen) {
  1549. STPSDIO_ERR_FUNC
  1550. ("abnormal bus_txlen(%d) > STP_SDIO_TX_ENTRY_SIZE(%ld)!!\n",
  1551. bus_txlen, STP_SDIO_TX_ENTRY_SIZE);
  1552. }
  1553. ++(p_info->firmware_info.tx_packet_num);
  1554. /* decrease Tx FIFO size: using 4-byte aligned length! */
  1555. p_info->firmware_info.tx_fifo_size -= four_byte_align_len;
  1556. /* record the SDIO packet size in packet size list: using 4-byte aligned length! */
  1557. idx = p_info->tx_pkt_list.pkt_wr_cnt++ & STP_SDIO_TX_PKT_LIST_SIZE_MASK;
  1558. p_info->tx_pkt_list.pkt_size_list[idx] = four_byte_align_len;
  1559. p_info->tx_pkt_list.in_ts[idx] = jiffies;
  1560. p_info->tx_pkt_list.out_ts[idx] = 0;
  1561. STPSDIO_DBG_FUNC("update tx packet size list\n");
  1562. STPSDIO_DBG_FUNC("wr(0x%x, %ld) rd(0x%x, %ld), tx fifo(size:%d), pkt_num(%d)done\n",
  1563. p_info->tx_pkt_list.pkt_wr_cnt,
  1564. STP_SDIO_GET_PKT_AR_IDX(p_info->tx_pkt_list.pkt_wr_cnt),
  1565. p_info->tx_pkt_list.pkt_rd_cnt,
  1566. STP_SDIO_GET_PKT_AR_IDX(p_info->tx_pkt_list.pkt_rd_cnt),
  1567. p_info->firmware_info.tx_fifo_size,
  1568. p_info->firmware_info.tx_packet_num);
  1569. /* port write the packet to CTDR */
  1570. ret = mtk_wcn_hif_sdio_write_buf(p_info->sdio_cltctx, CTDR,
  1571. (PUINT32) buf_tx, bus_txlen);
  1572. STPSDIO_DBG_FUNC("write to CTDR done\n");
  1573. #if STP_SDIO_DBG_SUPPORT && STP_SDIO_TXDBG
  1574. do {
  1575. idx = stp_sdio_txdbg_cnt++ & STP_SDIO_TXDBG_COUNT_MASK;
  1576. /* skip clear buf */
  1577. stp_sdio_txdbg_buffer[idx].ts = jiffies;
  1578. stp_sdio_txdbg_buffer[idx].bus_txlen = bus_txlen;
  1579. stp_sdio_txdbg_buffer[idx].four_byte_align_len =
  1580. four_byte_align_len;
  1581. /* store content */
  1582. if (bus_txlen <= STP_SDIO_TX_ENTRY_SIZE) {
  1583. memcpy(&stp_sdio_txdbg_buffer[idx].tx_pkt_buf[0], buf_tx,
  1584. bus_txlen);
  1585. } else {
  1586. memcpy(&stp_sdio_txdbg_buffer[idx].tx_pkt_buf[0], buf_tx,
  1587. STP_SDIO_TX_ENTRY_SIZE);
  1588. STPSDIO_ERR_FUNC("abnormal bus_txlen (%d)!\n", bus_txlen);
  1589. }
  1590. } while (0);
  1591. #endif
  1592. if (ret) {
  1593. STPSDIO_ERR_FUNC("get CTDR information Tx error(%d)!\n", ret);
  1594. /* TODO: error handling! */
  1595. #if STP_SDIO_DBG_SUPPORT && STP_SDIO_TXDBG
  1596. stp_sdio_txdbg_dump();
  1597. #endif
  1598. osal_dbg_assert_aee("<HIF_SDIO> sdio_writesb ERROR",
  1599. "write data by SDIO report error");
  1600. }
  1601. /* clear rd index entry of Tx ring buffer */
  1602. /*memset(buf_tx, 0, STP_SDIO_TX_ENTRY_SIZE); */
  1603. /* George: clear STP-SDIO header only for debugging. */
  1604. /*memset(buf_tx, 0, 4); */
  1605. /* need clear??? skip it for debugging */
  1606. spin_lock_irqsave(&pb->rd_cnt_lock, pb->rd_irq_flag);
  1607. ++(pb->rd_cnt);
  1608. /* TODO: [FixMe][George] check if full_flag needed? */
  1609. if (MTK_WCN_BOOL_FALSE != pb->full_flag) {
  1610. pb->full_flag = MTK_WCN_BOOL_FALSE;
  1611. wake_up_interruptible(&pb->fullwait_q);
  1612. }
  1613. spin_unlock_irqrestore(&pb->rd_cnt_lock, pb->rd_irq_flag);
  1614. do_gettimeofday(&old);
  1615. } else {
  1616. /* tx FIFO free space < packet size, wait next time */
  1617. #if STP_SDIO_DBG_SUPPORT && STP_SDIO_TXPERFDBG
  1618. stp_sdio_txperf_fifo_left += p_info->firmware_info.tx_fifo_size;
  1619. stp_sdio_txperf_to_send += four_byte_align_len;
  1620. ++stp_sdio_txperf_fifo_lmt_cnt;
  1621. #endif
  1622. do_gettimeofday(&now);
  1623. if ((now.tv_sec - old.tv_sec) > TX_NO_ACK_TIMEOUT_ASSERT) {
  1624. STPSDIO_INFO_FUNC("tx_fifo_size(%d), four_byte_align_len(%d), tx_packet_num(%d)\n",
  1625. p_info->firmware_info.tx_fifo_size, four_byte_align_len,
  1626. p_info->firmware_info.tx_packet_num);
  1627. STPSDIO_INFO_FUNC("No ack trigger assert, tx %d seconds later\n",
  1628. TX_NO_ACK_TIMEOUT_ASSERT);
  1629. p_info->firmware_info.tx_fifo_size = STP_SDIO_TX_FIFO_SIZE;
  1630. if (MTK_WCN_BOOL_FALSE != pb->full_flag) {
  1631. pb->full_flag = MTK_WCN_BOOL_FALSE;
  1632. wake_up_interruptible(&pb->fullwait_q);
  1633. }
  1634. ret = mtk_wcn_wmt_assert_timeout(WMTDRV_TYPE_STP, 33, 0);
  1635. if (!ret)
  1636. STPSDIO_INFO_FUNC("trigger assert fail\n");
  1637. }
  1638. break;
  1639. }
  1640. stp_sdio_check_tx_sanity(p_info, 2);
  1641. } while (1);
  1642. STPSDIO_LOUD_FUNC("end\n");
  1643. }
  1644. #else
  1645. static VOID stp_sdio_tx_wkr(
  1646. /* unsigned long data */
  1647. struct work_struct *work)
  1648. {
  1649. MTK_WCN_STP_SDIO_HIF_INFO *p_info;
  1650. UINT32 bus_txlen;
  1651. UINT32 four_byte_align_len;
  1652. PUINT8 buf_tx;
  1653. INT32 ret;
  1654. UINT32 idx;
  1655. MTK_WCN_STP_SDIO_PKT_BUF *pb;
  1656. struct timeval now;
  1657. p_info = container_of(work, MTK_WCN_STP_SDIO_HIF_INFO, tx_work);
  1658. ret = HIF_SDIO_ERR_SUCCESS;
  1659. pb = &p_info->pkt_buf;
  1660. STPSDIO_LOUD_FUNC("start\n");
  1661. /* 4 <0> Tx worker has been scheduled to send data */
  1662. do {
  1663. /* handle tx complete count if any */
  1664. stp_sdio_tx_wkr_comp(p_info);
  1665. stp_sdio_check_tx_sanity(p_info, 1);
  1666. /* check if Tx ring buffer is empty */
  1667. if ((p_info->pkt_buf.wr_idx == p_info->pkt_buf.rd_idx)
  1668. && (MTK_WCN_BOOL_FALSE == p_info->pkt_buf.full_flag)) {
  1669. STPSDIO_DBG_FUNC("Tx ring buffer is empty\n");
  1670. break;
  1671. }
  1672. /* George: no race condition here! Updating rd_idx content will not be
  1673. * put into more data by stp_sdio_tx
  1674. */
  1675. /* Get Tx packet size from Tx ring buf */
  1676. #if KMALLOC_UPDATE
  1677. buf_tx =
  1678. gp_info->pkt_buf.tx_buf + p_info->pkt_buf.rd_idx * STP_SDIO_TX_ENTRY_SIZE + 0;
  1679. #else
  1680. buf_tx = &p_info->pkt_buf.tx_buf[p_info->pkt_buf.rd_idx][0];
  1681. #endif
  1682. bus_txlen = buf_tx[1];
  1683. bus_txlen = (bus_txlen << 8) | buf_tx[0];
  1684. /* George: hw always count fifo in 4-byte aligned length */
  1685. bus_txlen += 0x3;
  1686. bus_txlen &= ~(0x3UL);
  1687. four_byte_align_len = bus_txlen;
  1688. /* Sanity check: 4-byte aligned length shall not exceed HW FIFO Size */
  1689. if (four_byte_align_len > STP_SDIO_TX_FIFO_SIZE) {
  1690. STPSDIO_ERR_FUNC("abnormal four_byte_align_len(%d) > TX_FIFO_SIZE(%ld)!!\n",
  1691. four_byte_align_len, STP_SDIO_TX_FIFO_SIZE);
  1692. }
  1693. /* George: check if
  1694. * 1. tx FIFO free space is enough using 4-byte aligned length
  1695. * 2. tx max pkt count is not reached
  1696. */
  1697. if ((p_info->firmware_info.tx_fifo_size >= four_byte_align_len)
  1698. && (p_info->firmware_info.tx_packet_num < STP_SDIO_TX_PKT_MAX_CNT)) {
  1699. /* George: refine block_size alignment with the assumption: block_size is 2^*x */
  1700. if (STP_SDIO_BLK_SIZE < bus_txlen) {
  1701. bus_txlen += (STP_SDIO_BLK_SIZE - 1);
  1702. bus_txlen &= ~((UINT32) STP_SDIO_BLK_SIZE - 1);
  1703. }
  1704. /* Sanity check: bus_txlen shall not exceed SW entry size */
  1705. if (STP_SDIO_TX_ENTRY_SIZE < bus_txlen) {
  1706. STPSDIO_ERR_FUNC
  1707. ("abnormal bus_txlen(%d) > STP_SDIO_TX_ENTRY_SIZE(%ld)!!\n",
  1708. bus_txlen, STP_SDIO_TX_ENTRY_SIZE);
  1709. }
  1710. ++(p_info->firmware_info.tx_packet_num);
  1711. /* decrease Tx FIFO size: using 4-byte aligned length! */
  1712. p_info->firmware_info.tx_fifo_size -= four_byte_align_len;
  1713. /* record the SDIO packet size in packet size list: using 4-byte aligned length! */
  1714. idx = p_info->tx_pkt_list.pkt_wr_cnt++ & STP_SDIO_TX_PKT_LIST_SIZE_MASK;
  1715. p_info->tx_pkt_list.pkt_size_list[idx] = four_byte_align_len;
  1716. p_info->tx_pkt_list.in_ts[idx] = jiffies;
  1717. p_info->tx_pkt_list.out_ts[idx] = 0;
  1718. STPSDIO_DBG_FUNC("update tx packet size list\n");
  1719. STPSDIO_DBG_FUNC("wr(0x%x, %ld) rd(0x%x, %ld), tx fifo(size:%d), pkt_num(%d)done\n",
  1720. p_info->tx_pkt_list.pkt_wr_cnt,
  1721. STP_SDIO_GET_PKT_AR_IDX(p_info->tx_pkt_list.pkt_wr_cnt),
  1722. p_info->tx_pkt_list.pkt_rd_cnt,
  1723. STP_SDIO_GET_PKT_AR_IDX(p_info->tx_pkt_list.pkt_rd_cnt),
  1724. p_info->firmware_info.tx_fifo_size,
  1725. p_info->firmware_info.tx_packet_num);
  1726. /* port write the packet to CTDR */
  1727. ret = mtk_wcn_hif_sdio_write_buf(p_info->sdio_cltctx, CTDR,
  1728. (PUINT32)buf_tx, bus_txlen);
  1729. STPSDIO_DBG_FUNC("write to CTDR done\n");
  1730. #if STP_SDIO_DBG_SUPPORT && STP_SDIO_TXDBG
  1731. do {
  1732. idx = stp_sdio_txdbg_cnt++ & STP_SDIO_TXDBG_COUNT_MASK;
  1733. /* skip clear buf */
  1734. stp_sdio_txdbg_buffer[idx].ts = jiffies;
  1735. stp_sdio_txdbg_buffer[idx].bus_txlen = bus_txlen;
  1736. stp_sdio_txdbg_buffer[idx].four_byte_align_len =
  1737. four_byte_align_len;
  1738. /* store content */
  1739. if (bus_txlen <= STP_SDIO_TX_ENTRY_SIZE) {
  1740. memcpy(&stp_sdio_txdbg_buffer[idx].tx_pkt_buf[0], buf_tx,
  1741. bus_txlen);
  1742. } else {
  1743. memcpy(&stp_sdio_txdbg_buffer[idx].tx_pkt_buf[0], buf_tx,
  1744. STP_SDIO_TX_ENTRY_SIZE);
  1745. STPSDIO_ERR_FUNC("abnormal bus_txlen(%d)!\n", bus_txlen);
  1746. }
  1747. } while (0);
  1748. #endif
  1749. if (ret) {
  1750. STPSDIO_ERR_FUNC("get CTDR information Tx error(%d)!\n", ret);
  1751. /* TODO: error handling! */
  1752. #if STP_SDIO_DBG_SUPPORT && STP_SDIO_TXDBG
  1753. stp_sdio_txdbg_dump();
  1754. #endif
  1755. osal_dbg_assert_aee("<HIF_SDIO> sdio_writesb ERROR",
  1756. "write data by SDIO report error");
  1757. }
  1758. /* clear rd index entry of Tx ring buffer */
  1759. /*memset(buf_tx, 0, STP_SDIO_TX_ENTRY_SIZE); */
  1760. /* George: clear STP-SDIO header only for debugging. */
  1761. /*memset(buf_tx, 0, 4); */
  1762. /* need clear??? skip it for debugging */
  1763. spin_lock_irqsave(&p_info->pkt_buf.rd_idx_lock,
  1764. p_info->pkt_buf.rd_irq_flag);
  1765. /* release tx ring buffer */
  1766. p_info->pkt_buf.rd_idx = (p_info->pkt_buf.rd_idx + 1) % STP_SDIO_TX_BUF_CNT;
  1767. /* Set Tx ring buffer is not full */
  1768. if (MTK_WCN_BOOL_FALSE != p_info->pkt_buf.full_flag) {
  1769. p_info->pkt_buf.full_flag = MTK_WCN_BOOL_FALSE;
  1770. wake_up_interruptible(&p_info->pkt_buf.fullwait_q);
  1771. }
  1772. spin_unlock_irqrestore(&p_info->pkt_buf.rd_idx_lock,
  1773. p_info->pkt_buf.rd_irq_flag);
  1774. do_gettimeofday(&old);
  1775. } else {
  1776. #if STP_SDIO_DBG_SUPPORT && STP_SDIO_TXPERFDBG
  1777. stp_sdio_txperf_fifo_left += p_info->firmware_info.tx_fifo_size;
  1778. stp_sdio_txperf_to_send += four_byte_align_len;
  1779. ++stp_sdio_txperf_fifo_lmt_cnt;
  1780. #endif
  1781. /* (tx FIFO free space < packet size) or (the number of tx packets >= 7) */
  1782. do_gettimeofday(&now);
  1783. if ((now.tv_sec - old.tv_sec) > TX_NO_ACK_TIMEOUT_ASSERT) {
  1784. STPSDIO_INFO_FUNC("tx_fifo_size(%d), four_byte_align_len(%d), tx_packet_num(%d)\n",
  1785. p_info->firmware_info.tx_fifo_size, four_byte_align_len,
  1786. p_info->firmware_info.tx_packet_num);
  1787. STPSDIO_INFO_FUNC("No ack trigger assert, tx %d seconds later\n",
  1788. TX_NO_ACK_TIMEOUT_ASSERT);
  1789. p_info->firmware_info.tx_fifo_size = STP_SDIO_TX_FIFO_SIZE;
  1790. if (MTK_WCN_BOOL_FALSE != pb->full_flag) {
  1791. pb->full_flag = MTK_WCN_BOOL_FALSE;
  1792. wake_up_interruptible(&pb->fullwait_q);
  1793. }
  1794. ret = mtk_wcn_wmt_assert_timeout(WMTDRV_TYPE_STP, 33, 0);
  1795. if (!ret)
  1796. STPSDIO_INFO_FUNC("trigger assert fail\n");
  1797. }
  1798. break;
  1799. }
  1800. stp_sdio_check_tx_sanity(p_info, 2);
  1801. } while (1);
  1802. STPSDIO_LOUD_FUNC("end\n");
  1803. }
  1804. #endif /* end of stp_sdio_tx_wkr and STP_SDIO_NEW_TXRING */
  1805. /*!
  1806. * \brief Handle STP-SDIO Rx IRQ BH and read data from bus
  1807. *
  1808. * \details Handle STP-SDIO Rx IRQ buttom half and read data from bus according
  1809. * to the length read in Rx IRQ top half (stp_sdio_irq()) from CHISR
  1810. *
  1811. * \note rx_pkt_len read in stp_sdio_irq() from CHISR. No Rx IRQ would be
  1812. * triggered by FW before all Rx FIFO data is read by host driver. Do
  1813. * sanity check for this condition.
  1814. *
  1815. * \note HW Rx FIFO size is (2304 = 256*9) for MT6620
  1816. *
  1817. * \param[IN] work Rx work struct work_struct pointer used by STP-SDIO
  1818. *
  1819. * \retval none.
  1820. */
  1821. static VOID stp_sdio_rx_wkr(struct work_struct *work)
  1822. {
  1823. PUINT8 bufp;
  1824. UINT32 bus_rxlen;
  1825. UINT32 chisr_rxlen;
  1826. INT32 ret;
  1827. MTK_WCN_STP_SDIO_HIF_INFO *p_info;
  1828. p_info = container_of(work, MTK_WCN_STP_SDIO_HIF_INFO, rx_work);
  1829. /* 4 <0> receive data from CRDR */
  1830. /* George: refine 4-byte alignment */
  1831. chisr_rxlen = p_info->rx_pkt_len;
  1832. if (STP_SDIO_RX_FIFO_SIZE < chisr_rxlen) {
  1833. /* TODO: error handling! */
  1834. STPSDIO_ERR_FUNC("abnormal chisr_rxlen(%d) rx_worker stop\n", chisr_rxlen);
  1835. return;
  1836. }
  1837. bus_rxlen = chisr_rxlen;
  1838. bus_rxlen += 0x3;
  1839. bus_rxlen &= ~(0x3UL);
  1840. /* George: refine block_size alignment with the assumption: BLK_SIZE is 2^x. */
  1841. if (STP_SDIO_BLK_SIZE < bus_rxlen) {
  1842. bus_rxlen += (STP_SDIO_BLK_SIZE - 1);
  1843. bus_rxlen &= ~((UINT32) STP_SDIO_BLK_SIZE - 1);
  1844. }
  1845. ret = mtk_wcn_hif_sdio_read_buf(p_info->sdio_cltctx,
  1846. CRDR, (PUINT32)(&p_info->pkt_buf.rx_buf[0]), bus_rxlen);
  1847. if (ret) {
  1848. /* TODO: error handling! */
  1849. STPSDIO_ERR_FUNC("read CRDR len(%d) rx error!(%d)\n", bus_rxlen, ret);
  1850. p_info->rx_pkt_len = 0;
  1851. STPSDIO_HINT_FUNC("set to p_info->rx_pkt_len 0\n");
  1852. osal_dbg_assert_aee("<HIF_SDIO> sdio_readsb ERROR",
  1853. "read data by SDIO report error");
  1854. return;
  1855. }
  1856. p_info->rx_pkt_len = 0;
  1857. STPSDIO_HINT_FUNC("set to p_info->rx_pkt_len 0\n");
  1858. #if STP_SDIO_DBG_SUPPORT && STP_SDIO_RXDBG
  1859. do {
  1860. UINT32 idx = stp_sdio_rxdbg_cnt++ & (STP_SDIO_RXDBG_COUNT - 1);
  1861. /* skip clear buf */
  1862. stp_sdio_rxdbg_buffer[idx].ts = jiffies;
  1863. stp_sdio_rxdbg_buffer[idx].chisr_rxlen = chisr_rxlen;
  1864. stp_sdio_rxdbg_buffer[idx].bus_rxlen = bus_rxlen;
  1865. /* store content */
  1866. memcpy(&stp_sdio_rxdbg_buffer[idx].rx_pkt_buf[0], &p_info->pkt_buf.rx_buf[0],
  1867. bus_rxlen);
  1868. } while (0);
  1869. #endif
  1870. bufp = &p_info->pkt_buf.rx_buf[4];
  1871. /* Notice: len = SDIO_HDR(4) + (STP Packet + padding)*N */
  1872. /* George: refine sanity check */
  1873. bus_rxlen = p_info->pkt_buf.rx_buf[1];
  1874. bus_rxlen = (bus_rxlen << 8) | p_info->pkt_buf.rx_buf[0];
  1875. STPSDIO_DBG_FUNC("bus_rxlen(%d) rx_len in chisr(%d)\n", bus_rxlen, chisr_rxlen);
  1876. if (bus_rxlen != chisr_rxlen) {
  1877. STPSDIO_ERR_FUNC("abnormal bus_rxlen(%d) in SDIO packet header!in chisr(%d)\n",
  1878. bus_rxlen, chisr_rxlen);
  1879. return;
  1880. }
  1881. if (p_info->pkt_buf.rx_buf[2] || p_info->pkt_buf.rx_buf[3]) {
  1882. STPSDIO_ERR_FUNC("abnormal p_info->pkt_buf.rx_buf[2](0x%02x) [3](0x%02x)\n",
  1883. p_info->pkt_buf.rx_buf[2], p_info->pkt_buf.rx_buf[3]);
  1884. return;
  1885. }
  1886. if (STP_SDIO_HDR_SIZE < bus_rxlen) {
  1887. bus_rxlen -= STP_SDIO_HDR_SIZE;
  1888. /* transmit data to stp core driver */
  1889. ret = mtk_wcn_stp_parser_data(bufp, bus_rxlen);
  1890. #if STP_SDIO_DBG_SUPPORT && (STP_SDIO_TXDBG || STP_SDIO_TXPERFDBG)
  1891. if (ret && (0 == p_info->tx_dbg_dump_flag)) {
  1892. p_info->tx_dbg_dump_flag = 1;
  1893. stp_sdio_txdbg_dump();
  1894. }
  1895. #endif
  1896. } else {
  1897. STPSDIO_ERR_FUNC("abnormal rx length(%d, %d)\n", bus_rxlen, chisr_rxlen);
  1898. }
  1899. /* [George]: no need to mask/unmask rx interrupt. chip/fw assert next rx int
  1900. * if and only if host reads all rx data.
  1901. */
  1902. }
  1903. #if STP_SDIO_NEW_IRQ_HANDLER
  1904. static INT32 stp_sdio_irq(const MTK_WCN_HIF_SDIO_CLTCTX clt_ctx)
  1905. {
  1906. INT32 iRet = 0;
  1907. UINT32 chlcpr_value = 0;
  1908. MTK_WCN_STP_SDIO_HIF_INFO *p_info = gp_info;
  1909. STPSDIO_HINT_FUNC("disable IRQ\n");
  1910. /*Disable Common interrupt output in CHLPCR */
  1911. /* [COHEC_00006052] SW work-around solution:
  1912. using CMD52 write instead of CMD53 write for CCIR, CHLPCR, CSDIOCSR */
  1913. #if COHEC_00006052
  1914. iRet = mtk_wcn_hif_sdio_writeb(clt_ctx, CHLPCR, C_FW_INT_EN_CLR);
  1915. #else
  1916. iRet = mtk_wcn_hif_sdio_writel(clt_ctx, CHLPCR, C_FW_INT_EN_CLR);
  1917. #endif /* COHEC_00006052 */
  1918. if (iRet) {
  1919. STPSDIO_ERR_FUNC("disalbe IRQ fail\n");
  1920. } else {
  1921. iRet = mtk_wcn_hif_sdio_readl(clt_ctx, CHLPCR, &chlcpr_value);
  1922. if (iRet) {
  1923. STPSDIO_ERR_FUNC("read CHLPCR fail. iRet(%d)\n", iRet);
  1924. } else {
  1925. if (!(chlcpr_value & C_FW_INT_EN_SET)) {
  1926. STPSDIO_DBG_FUNC("disable COM IRQ okay (0x%x)\n", chlcpr_value);
  1927. p_info->irq_pending = 1;
  1928. /*inform stp_sdio thread to to rx/tx job */
  1929. STPSDIO_DBG_FUNC("signal stp_tx_rx\n");
  1930. osal_trigger_event(&gp_info->tx_rx_event);
  1931. } else {
  1932. STPSDIO_ERR_FUNC
  1933. ("**********disable COM IRQ fail, don't signal stp-sdio thread******\n");
  1934. }
  1935. }
  1936. }
  1937. return 0;
  1938. }
  1939. #else
  1940. /*!
  1941. * \brief Handle STP-SDIO interrupt
  1942. *
  1943. * \details Top half interrupt handler of STP-SDIO. Most of Tx/Rx jobs are put
  1944. * to bottom half workers respectively.
  1945. *
  1946. * \note Rx ok interrupt shall be asserted by hw ONLY after last data are all
  1947. * read by driver. Do sanity check on rx_pkt_len and should be 0: rx BH
  1948. * finished.
  1949. *
  1950. * \note Tx complete count shall be handled atomically TH here and BH in
  1951. * tx_worker.
  1952. *
  1953. * \param[IN] clt_ctx A HIF-SDIO client context
  1954. *
  1955. * \retval 0 success
  1956. * \retval !=0 fail
  1957. */
  1958. static INT32 stp_sdio_irq(const MTK_WCN_HIF_SDIO_CLTCTX clt_ctx)
  1959. {
  1960. /*MTK_WCN_STP_SDIO_PRIVATE_INFO *p_priv; */
  1961. MTK_WCN_STP_SDIO_HIF_INFO *p_info = NULL;
  1962. UINT32 chisr = 0;
  1963. UINT32 tx_comp;
  1964. INT32 ret;
  1965. STPSDIO_LOUD_FUNC("enter\n");
  1966. /*
  1967. p_priv = mtk_wcn_hif_sdio_get_drvdata(clt_ctx);
  1968. // TODO:[FixMe][George] do sanity check!
  1969. p_info = &g_stp_sdio_host_info[p_priv->stp_sdio_host_idx];
  1970. */
  1971. p_info = gp_info;
  1972. ret = HIF_SDIO_ERR_SUCCESS;
  1973. /* 4 <0> get CHLPCR information */
  1974. if (OWN_CLR == stp_sdio_get_own_state()) {
  1975. STPSDIO_DBG_FUNC("OWN on driver side!\n");
  1976. } else {
  1977. STPSDIO_DBG_FUNC("OWN on fw side!\n");
  1978. if (0 == stp_sdio_do_own_clr(0)) {
  1979. STPSDIO_DBG_FUNC("set OWN to driver side ok!\n");
  1980. } else {
  1981. STPSDIO_ERR_FUNC("set OWN to driver side error!\n");
  1982. return -1;
  1983. }
  1984. }
  1985. retry:
  1986. /* 4 <1> get CHISR information */
  1987. ret = mtk_wcn_hif_sdio_readl(clt_ctx, CHISR, &chisr);
  1988. if (ret) {
  1989. /* 4 <1.1> get CHISR Rx error handling */
  1990. /* TODO: error handling! */
  1991. STPSDIO_ERR_FUNC("get CHISR information rx error,ret:%d\n", ret);
  1992. if (-5 == ret) {
  1993. STPSDIO_ERR_FUNC("get CHISR DAT CRC error, retry.\n");
  1994. chisr = stp_sdio_rc_reg_readl_retry(clt_ctx, CSR, 100);
  1995. } else
  1996. goto retry;
  1997. }
  1998. STPSDIO_HINT_FUNC("CHISR(0x%08x)\n", chisr);
  1999. if (0x0 == chisr) {
  2000. STPSDIO_ERR_FUNC("******CHISR == 0*****\n");
  2001. return 0;
  2002. }
  2003. /* 4 <2> handle ownership back interrupt */
  2004. if (chisr & FW_OWN_BACK_INT) {
  2005. STPSDIO_INFO_FUNC("FW_OWN_BACK_INT\n");
  2006. if (is_wait_ownback) {
  2007. is_wait_ownback = 0;
  2008. wake_up(&g_ownback_done);
  2009. } else {
  2010. mtk_wcn_stp_wmt_sdio_host_awake();
  2011. /* if (cmb_bgf_eirq_cb) { */
  2012. /* (*cmb_bgf_eirq_cb)(); */
  2013. /* } */
  2014. }
  2015. }
  2016. /* 4 <3> handle Rx interrupt */
  2017. if (chisr & RX_DONE) {
  2018. /* STPSDIO_INFO_FUNC("RX_DONE_INT\n"); */
  2019. /* TODO: [FixMe][George] testing... */
  2020. if (p_info->rx_pkt_len) {
  2021. STPSDIO_ERR_FUNC("rx worker is not finished yet!!!(%d)\n",
  2022. p_info->rx_pkt_len);
  2023. }
  2024. /* get Rx packet length */
  2025. p_info->rx_pkt_len = (chisr & RX_PKT_LEN) >> 16;
  2026. STPSDIO_HINT_FUNC("rx_pkt_len(%d)\n", p_info->rx_pkt_len);
  2027. /* sanity check */
  2028. if ((0 == p_info->rx_pkt_len)
  2029. || (STP_SDIO_RX_FIFO_SIZE < p_info->rx_pkt_len)) {
  2030. STPSDIO_ERR_FUNC
  2031. ("abnormal rx_pkt_len(%d) in CHISR(0x%08x) skip rx_worker\n",
  2032. p_info->rx_pkt_len, chisr);
  2033. p_info->rx_pkt_len = 0;
  2034. } else {
  2035. /* Before host driver read all rx data, chip/fw will not send more data
  2036. * to host. No need to mask rx interrupt. schedule rx worker to get data
  2037. * back and handle it.
  2038. */
  2039. if (p_info->rx_pkt_len & 0x3) {
  2040. STPSDIO_WARN_FUNC
  2041. ("rx data len is not 4 bytes allignment, CHISR(0x%08x), rx len (%d).\n",
  2042. chisr, p_info->rx_pkt_len);
  2043. }
  2044. #if STP_SDIO_OWN_THREAD
  2045. /* tasklet_schedule(&p_info->tx_rx_job); */
  2046. STPSDIO_DBG_FUNC("osal_trigger_event gp_info->tx_rx_event\n");
  2047. osal_trigger_event(&gp_info->tx_rx_event);
  2048. #else
  2049. schedule_work(&p_info->rx_work);
  2050. #endif
  2051. }
  2052. }
  2053. /* 4 <4> handle Tx interrupt */
  2054. if ((chisr & TX_EMPTY) || (chisr & TX_UNDER_THOLD)) {
  2055. STPSDIO_DBG_FUNC("Tx interrupt\n");
  2056. /* get complete count */
  2057. tx_comp = (chisr & TX_COMPLETE_COUNT) >> 4;
  2058. #if 0
  2059. atomic_add(tx_comp, &p_info->firmware_info.tx_comp_num);
  2060. /* TODO:[FixMe][George]: debug and to be removed... */
  2061. tx_comp = atomic_read(&p_info->firmware_info.tx_comp_num);
  2062. #else
  2063. tx_comp = atomic_add_return(tx_comp, &p_info->firmware_info.tx_comp_num);
  2064. #endif
  2065. if (tx_comp > STP_SDIO_TX_PKT_MAX_CNT) {
  2066. STPSDIO_ERR_FUNC("Abnormal accumulated comp count(%d) chisr(0x%x)\n",
  2067. tx_comp, chisr);
  2068. }
  2069. /* move most of tx jobs to tx_worker */
  2070. /* schedule tx worker for tx complete count and following tx data */
  2071. #if STP_SDIO_OWN_THREAD
  2072. /* tasklet_schedule(&p_info->tx_rx_job); */
  2073. STPSDIO_DBG_FUNC("osal_trigger_event gp_info->tx_rx_event\n");
  2074. osal_trigger_event(&gp_info->tx_rx_event);
  2075. #else
  2076. schedule_work(&p_info->tx_work);
  2077. #endif
  2078. }
  2079. STPSDIO_LOUD_FUNC("exit\n");
  2080. return ret;
  2081. }
  2082. #endif
  2083. #if STP_SDIO_POLL_OWNBACK_INTR
  2084. /*****************************************************************************
  2085. * FUNCTION
  2086. * stp_sdio_ownback_poll
  2087. * DESCRIPTION
  2088. * Poll ownback interrupt
  2089. * PARAMETERS
  2090. * 1. *func [IN] sdio driver function pointer
  2091. * 2. retryp [IN] polling retry times
  2092. * 3. delay_us [IN] polling delay (unit: us)
  2093. * RETURNS
  2094. * ret: Probe result
  2095. *****************************************************************************/
  2096. static INT32
  2097. stp_sdio_ownback_poll(const MTK_WCN_HIF_SDIO_CLTCTX clt_ctx, UINT32 retry, UINT32 delay_us)
  2098. {
  2099. INT32 ret;
  2100. UINT32 chlpcr = 0;
  2101. do {
  2102. /*ret = mtk_wcn_hif_sdio_readl(clt_ctx, CHISR, &chisr_value); */
  2103. /* 20111020: change to poll CHLPCR instead of read-cleared CHISR */
  2104. ret = mtk_wcn_hif_sdio_readl(clt_ctx, CHLPCR, &chlpcr);
  2105. if (ret) {
  2106. /* 4 <1.1> get CHISR Rx error handling */
  2107. STPSDIO_ERR_FUNC("get CHLPCR information rx error!(%d)\n", ret);
  2108. return ret;
  2109. }
  2110. /*if (chisr_value & FW_OWN_BACK_INT) { */
  2111. if (chlpcr & C_FW_COM_DRV_OWN) {
  2112. /* 4 <2> handle ownership back interrupt */
  2113. STPSDIO_INFO_FUNC("Driver own is polled!(%d)\n", retry);
  2114. break;
  2115. }
  2116. udelay(delay_us);
  2117. } while (retry-- > 0);
  2118. /*return (chisr_value & FW_OWN_BACK_INT) ? 0 : -HIF_SDIO_ERR_FAIL; */
  2119. return (chlpcr & C_FW_COM_DRV_OWN) ? 0 : -HIF_SDIO_ERR_FAIL;
  2120. }
  2121. #endif
  2122. /*****************************************************************************
  2123. * FUNCTION
  2124. * stp_sdio_probe
  2125. * DESCRIPTION
  2126. * Probe function of SDIO driver
  2127. * PARAMETERS
  2128. * 1. *func [IN] sdio driver function pointer
  2129. * 2. *id [IN] sdio function id
  2130. * RETURNS
  2131. * ret: Probe result
  2132. *****************************************************************************/
  2133. /* typedef INT32 (*MTK_WCN_HIF_SDIO_PROBE)(MTK_WCN_HIF_SDIO_CLTCTX, const MTK_WCN_HIF_SDIO_FUNCINFO *); */
  2134. static INT32
  2135. stp_sdio_probe(const MTK_WCN_HIF_SDIO_CLTCTX clt_ctx,
  2136. const MTK_WCN_HIF_SDIO_FUNCINFO *sdio_func_infop)
  2137. {
  2138. INT32 ret = HIF_SDIO_ERR_SUCCESS;
  2139. UINT32 i = 0, chlcpr_value = 0;
  2140. STPSDIO_DBG_FUNC("sdio_cltctx: 0x%08x\n", clt_ctx);
  2141. if (g_stp_sdio_host_count) {
  2142. STPSDIO_ERR_FUNC("g_stp_sdio_host_count(%d) probed already!\n",
  2143. g_stp_sdio_host_count);
  2144. return -1;
  2145. }
  2146. /* 4 <1> check if input pointer is valid */
  2147. if (g_stp_sdio_host_info.sdio_cltctx == clt_ctx) {
  2148. STPSDIO_WARN_FUNC("sdio_cltctx(%d) already probed!\n", clt_ctx);
  2149. return 0;
  2150. }
  2151. /* 4 <2> allocate host inform structure and initialize private variables */
  2152. /* init host info private variables */
  2153. g_stp_sdio_host_info.sdio_cltctx = clt_ctx;
  2154. /* init Tx packet ring buffer */
  2155. for (i = 0; i < STP_SDIO_TX_BUF_CNT; ++i) {
  2156. #if KMALLOC_UPDATE
  2157. UINT8 *pData = g_stp_sdio_host_info.pkt_buf.tx_buf + i * STP_SDIO_TX_ENTRY_SIZE + 0;
  2158. memset(pData, 0, STP_SDIO_TX_ENTRY_SIZE);
  2159. #else
  2160. memset(&g_stp_sdio_host_info.pkt_buf.tx_buf[i][0], 0,
  2161. sizeof(g_stp_sdio_host_info.pkt_buf.tx_buf[i]));
  2162. #endif
  2163. }
  2164. #if STP_SDIO_NEW_TXRING
  2165. spin_lock_init(&g_stp_sdio_host_info.pkt_buf.rd_cnt_lock);
  2166. g_stp_sdio_host_info.pkt_buf.wr_cnt = 0;
  2167. g_stp_sdio_host_info.pkt_buf.rd_cnt = 0;
  2168. #else
  2169. /*g_stp_sdio_host_info.pkt_buf.rd_idx_lock = SPIN_LOCK_UNLOCKED; */
  2170. spin_lock_init(&g_stp_sdio_host_info.pkt_buf.rd_idx_lock);
  2171. g_stp_sdio_host_info.pkt_buf.wr_idx = 0;
  2172. g_stp_sdio_host_info.pkt_buf.rd_idx = 0;
  2173. #endif
  2174. g_stp_sdio_host_info.pkt_buf.full_flag = MTK_WCN_BOOL_FALSE;
  2175. /* init wait queue head for Tx ring buf full */
  2176. init_waitqueue_head(&g_stp_sdio_host_info.pkt_buf.fullwait_q);
  2177. /* init Tx packet size list information */
  2178. memset(&g_stp_sdio_host_info.tx_pkt_list.pkt_size_list[0], 0,
  2179. sizeof(g_stp_sdio_host_info.tx_pkt_list.pkt_size_list));
  2180. g_stp_sdio_host_info.tx_pkt_list.pkt_rd_cnt = 0;
  2181. g_stp_sdio_host_info.tx_pkt_list.pkt_wr_cnt = 0;
  2182. /* init Rx interrupt mask */
  2183. /* g_stp_sdio_host_info.rx_intr_mask = MTK_WCN_BOOL_FALSE; */
  2184. /* init firmware related information */
  2185. g_stp_sdio_host_info.firmware_info.tx_fifo_size = STP_SDIO_TX_FIFO_SIZE;
  2186. g_stp_sdio_host_info.firmware_info.tx_packet_num = 0;
  2187. atomic_set(&g_stp_sdio_host_info.firmware_info.tx_comp_num, 0);
  2188. #if STP_SDIO_OWN_THREAD
  2189. /* tasklet_init(&g_stp_sdio_host_info.tx_rx_job, stp_sdio_tx_rx_handling,
  2190. (unsigned long) &g_stp_sdio_host_info); */
  2191. /* Create stp_sdio_tx_rx_thread, in suspend state */
  2192. g_stp_sdio_host_info.irq_pending = 0;
  2193. g_stp_sdio_host_info.sleep_flag = 0;
  2194. g_stp_sdio_host_info.wakeup_flag = 0;
  2195. osal_event_init(&g_stp_sdio_host_info.tx_rx_event);
  2196. g_stp_sdio_host_info.tx_rx_thread.pThreadFunc = stp_sdio_tx_rx_handling;
  2197. g_stp_sdio_host_info.tx_rx_thread.pThreadData = (PVOID) &g_stp_sdio_host_info;
  2198. g_stp_sdio_host_info.tx_dbg_dump_flag = 0;
  2199. osal_strncpy((PINT8)&g_stp_sdio_host_info.tx_rx_thread.threadName,
  2200. "stp_sdio_tx_rx", osal_sizeof(g_stp_sdio_host_info.tx_rx_thread.threadName));
  2201. ret = osal_thread_create(&g_stp_sdio_host_info.tx_rx_thread);
  2202. if (ret < 0) {
  2203. STPSDIO_ERR_FUNC("osal_thread_create fail...: %p\n", g_stp_sdio_host_info.tx_rx_thread.pThread);
  2204. return ret;
  2205. }
  2206. #else
  2207. /* init tx_tasklet and rx work_queue */
  2208. INIT_WORK(&g_stp_sdio_host_info.tx_work, stp_sdio_tx_wkr);
  2209. INIT_WORK(&g_stp_sdio_host_info.rx_work, stp_sdio_rx_wkr);
  2210. #endif
  2211. /* init stp sdio host private information *//* TODO: [FixMe][George] Still need this? */
  2212. g_stp_sdio_host_info.private_info.stp_sdio_host_idx = g_stp_sdio_host_count;
  2213. mtk_wcn_hif_sdio_set_drvdata(clt_ctx, &g_stp_sdio_host_info.private_info);
  2214. ++g_stp_sdio_host_count;
  2215. /* 4 <3> request firmware-own back */
  2216. /* [COHEC_00006052] SW work-around solution:
  2217. using CMD52 write instead of CMD53 write for CCIR, CHLPCR, CSDIOCSR */
  2218. #if COHEC_00006052
  2219. ret =
  2220. mtk_wcn_hif_sdio_writeb(clt_ctx, (UINT32) (CHLPCR + 0x1),
  2221. (UINT8) (C_FW_OWN_REQ_CLR >> 8));
  2222. #else
  2223. ret = mtk_wcn_hif_sdio_writel(clt_ctx, CHLPCR, C_FW_OWN_REQ_CLR);
  2224. #endif /* COHEC_00006052 */
  2225. if (ret) {
  2226. STPSDIO_ERR_FUNC("request FW-Own back fail!(%d)\n", ret);
  2227. goto out;
  2228. }
  2229. STPSDIO_INFO_FUNC("request FW-Own back done\n");
  2230. #if STP_SDIO_POLL_OWNBACK_INTR
  2231. /* 4 <3.1> polling own back bit */
  2232. ret = stp_sdio_ownback_poll(clt_ctx, 10, 100);
  2233. if (ret) {
  2234. STPSDIO_ERR_FUNC("poll FW-Own back fail!(%d)\n", ret);
  2235. goto out;
  2236. }
  2237. #endif
  2238. /* 4 <4.0> enable irq flag in HIF-SDIO */
  2239. mtk_wcn_hif_sdio_enable_irq(clt_ctx, MTK_WCN_BOOL_TRUE);
  2240. /* 4 <4> enabling all host interrupt except abnormal ones */
  2241. /* ret = mtk_wcn_hif_sdio_writel(clt_ctx, CHIER, (CHISR_EN_15_7|CHISR_EN_3_0));
  2242. enable CHISR interrupt output */
  2243. ret = mtk_wcn_hif_sdio_writel(clt_ctx, CHIER, (FIRMWARE_INT | TX_FIFO_OVERFLOW |
  2244. FW_INT_IND_INDICATOR | TX_COMPLETE_COUNT |
  2245. TX_UNDER_THOLD | TX_EMPTY | RX_DONE));
  2246. if (ret) {
  2247. STPSDIO_ERR_FUNC("set interrupt output fail!(%d)\n", ret);
  2248. goto out;
  2249. }
  2250. STPSDIO_DBG_FUNC("set interrupt output done\n");
  2251. /* [COHEC_00006052] SW work-around solution:
  2252. using CMD52 write instead of CMD53 write for CCIR, CHLPCR, CSDIOCSR */
  2253. #if COHEC_00006052
  2254. ret = mtk_wcn_hif_sdio_writeb(clt_ctx, CHLPCR, C_FW_INT_EN_SET); /* enable interrupt */
  2255. #else
  2256. ret = mtk_wcn_hif_sdio_writel(clt_ctx, CHLPCR, C_FW_INT_EN_SET); /* enable interrupt */
  2257. #endif /* COHEC_00006052 */
  2258. if (ret) {
  2259. STPSDIO_ERR_FUNC("enable interrupt fail!(%d)\n", ret);
  2260. goto out;
  2261. }
  2262. ret = mtk_wcn_hif_sdio_readl(clt_ctx, CHLPCR, &chlcpr_value);
  2263. if (ret) {
  2264. STPSDIO_ERR_FUNC("Read CHLPCR fail!(%d)\n", ret);
  2265. goto out;
  2266. } else {
  2267. if (chlcpr_value & C_FW_INT_EN_SET)
  2268. STPSDIO_DBG_FUNC("enable interrupt okay (0x%x)\n", chlcpr_value);
  2269. }
  2270. STPSDIO_DBG_FUNC("enable interrupt done\n");
  2271. #if STP_SDIO_OWN_THREAD
  2272. ret = osal_thread_run(&g_stp_sdio_host_info.tx_rx_thread);
  2273. if (ret < 0) {
  2274. STPSDIO_ERR_FUNC("osal_thread_run fail...\n");
  2275. goto out;
  2276. }
  2277. #endif
  2278. /* 4 <5> register mtk_wcn_stp_if_tx() to stp driver */
  2279. mtk_wcn_stp_register_if_tx(STP_SDIO_IF_TX, (MTK_WCN_STP_IF_TX) stp_sdio_tx);
  2280. #if 0 /* controlled by 6620_launcher & WMT */
  2281. /*set STP sdio mode */
  2282. pr_warn(DFT_TAG "%s: set stp sdio mode\n", __func__);
  2283. mtk_wcn_stp_set_sdio_mode(1);
  2284. /*indicate the stp the sdio ready */
  2285. pr_warn(DFT_TAG "%s: stp enable\n", __func__);
  2286. mtk_wcn_stp_enable(1);
  2287. #endif
  2288. out:
  2289. /* 4 <6> error handling */
  2290. /* TODO: error handling */
  2291. if (ret) {
  2292. #if STP_SDIO_OWN_THREAD
  2293. osal_thread_destroy(&g_stp_sdio_host_info.tx_rx_thread);
  2294. #endif
  2295. if (g_stp_sdio_host_count > 0)
  2296. --g_stp_sdio_host_count;
  2297. }
  2298. return ret;
  2299. }
  2300. /*****************************************************************************
  2301. * FUNCTION
  2302. * stp_sdio_probe
  2303. * DESCRIPTION
  2304. * SDIO hardware remove function.
  2305. * PARAMETERS
  2306. * *func [IN] SDIO driver handler pointer.
  2307. * RETURNS
  2308. * none.
  2309. *****************************************************************************/
  2310. static INT32 stp_sdio_remove(const MTK_WCN_HIF_SDIO_CLTCTX clt_ctx)
  2311. {
  2312. /*
  2313. MTK_WCN_STP_SDIO_PRIVATE_INFO *p_priv;
  2314. p_priv = mtk_wcn_hif_sdio_get_drvdata(clt_ctx);
  2315. */
  2316. STPSDIO_LOUD_FUNC("start\n");
  2317. if (g_stp_sdio_host_info.sdio_cltctx == clt_ctx) {
  2318. STPSDIO_INFO_FUNC("sdio_cltctx(%d) found\n", clt_ctx);
  2319. } else {
  2320. STPSDIO_ERR_FUNC("sdio_cltctx(%d) not found\n", clt_ctx);
  2321. return -1;
  2322. }
  2323. if (g_stp_sdio_host_count > 0)
  2324. --g_stp_sdio_host_count;
  2325. /* 4 <0> disable irq flag in HIF-SDIO */
  2326. mtk_wcn_hif_sdio_enable_irq(clt_ctx, MTK_WCN_BOOL_FALSE);
  2327. /* 4 <1> unregister if_tx() function */
  2328. mtk_wcn_stp_register_if_tx(STP_SDIO_IF_TX, NULL);
  2329. /* <2> stop Tx tasklet/Rx work queue of the host */
  2330. #if STP_SDIO_OWN_THREAD
  2331. /* tasklet_kill(&g_stp_sdio_host_info.tx_rx_job); */
  2332. /* STPSDIO_INFO_FUNC("kill tasklet finished\n"); */
  2333. osal_thread_destroy(&g_stp_sdio_host_info.tx_rx_thread);
  2334. osal_event_deinit(&g_stp_sdio_host_info.tx_rx_event);
  2335. STPSDIO_INFO_FUNC("destroy STP-SDIO tx_rx_thread\n");
  2336. #else
  2337. flush_scheduled_work();
  2338. STPSDIO_INFO_FUNC("flush scheduled work end\n");
  2339. #endif
  2340. /* 4 <3> return ownership to firmware of the host */
  2341. /* TODO: check set which register ! */
  2342. /* 4 <4> clear the host struct list */
  2343. stp_sdio_host_info_op(1);
  2344. STPSDIO_INFO_FUNC("clear g_stp_sdio_host_info[p_priv->stp_sdio_host_idx] done\n");
  2345. STPSDIO_LOUD_FUNC("end\n");
  2346. return 0;
  2347. }
  2348. static INT32 stp_sdio_rc_reg_readl_retry(MTK_WCN_HIF_SDIO_CLTCTX clt_ctx, UINT32 offset,
  2349. UINT32 retry_limit, INT32 *p_ret)
  2350. {
  2351. INT32 ret = -1;
  2352. INT32 value = 0;
  2353. #define MAX_RETRY_NUM 100
  2354. UINT32 card_id = CLTCTX_CID(clt_ctx);
  2355. if (card_id != 0x6630) {
  2356. STPSDIO_INFO_FUNC
  2357. ("card_id is :0x%x, does not support CSR (Common Snapshot Register)\n",
  2358. card_id);
  2359. if (p_ret)
  2360. *p_ret = 0;
  2361. return value;
  2362. }
  2363. STPSDIO_INFO_FUNC("clt_ctx:0x%x, offset:0x%x, retry_limit:%d\n", clt_ctx, offset,
  2364. retry_limit);
  2365. retry_limit = retry_limit == 0 ? 1 : retry_limit;
  2366. retry_limit = retry_limit > MAX_RETRY_NUM ? MAX_RETRY_NUM : retry_limit;
  2367. while (retry_limit > 0) {
  2368. ret = mtk_wcn_hif_sdio_readl(clt_ctx, offset, &value);
  2369. if (ret != 0) {
  2370. STPSDIO_ERR_FUNC("read Common Snapshot Register failed, ret:%d\n", ret);
  2371. } else {
  2372. STPSDIO_DBG_FUNC("CSR:0x%x\n", value);
  2373. break;
  2374. }
  2375. retry_limit--;
  2376. }
  2377. if (p_ret)
  2378. *p_ret = ret;
  2379. return value;
  2380. }
  2381. #if STP_SDIO_DBG_SUPPORT && STP_SDIO_RXDBG
  2382. #if USE_NEW_PROC_FS_FLAG
  2383. ssize_t stp_sdio_rxdbg_read(struct file *filp, char __user *buf, size_t count, loff_t *f_pos)
  2384. {
  2385. UINT32 idx;
  2386. UINT32 i;
  2387. UINT32 j;
  2388. PUINT8 pbuf;
  2389. UINT32 len;
  2390. if (*f_pos > 0)
  2391. return 0;
  2392. for (i = 0; i < STP_SDIO_RXDBG_COUNT; ++i) {
  2393. idx = (stp_sdio_rxdbg_cnt - 1 - i) & STP_SDIO_TXDBG_COUNT_MASK;
  2394. len = stp_sdio_rxdbg_buffer[idx].bus_rxlen;
  2395. if (0 == len) {
  2396. pr_warn(DFT_TAG "idx(0x%x) 0 == len dump skip\n",
  2397. stp_sdio_rxdbg_cnt);
  2398. }
  2399. pr_warn(DFT_TAG "idx(0x%x) chisr_rxlen(%d) bus_rxlen(%d) ts(%d)\n",
  2400. stp_sdio_rxdbg_cnt, stp_sdio_rxdbg_buffer[idx].chisr_rxlen, len,
  2401. stp_sdio_rxdbg_buffer[idx].ts);
  2402. for (j = 0; j < STP_SDIO_RX_BUF_SIZE && j < len; j += 16) {
  2403. pbuf = &stp_sdio_rxdbg_buffer[idx].rx_pkt_buf[j];
  2404. pr_warn(DFT_TAG "[0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x ",
  2405. pbuf[0], pbuf[1], pbuf[2], pbuf[3], pbuf[4], pbuf[5], pbuf[6], pbuf[7]);
  2406. pr_warn(DFT_TAG "0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x]\n",
  2407. pbuf[8], pbuf[9], pbuf[10], pbuf[11], pbuf[12], pbuf[13],
  2408. pbuf[14], pbuf[15]);
  2409. msleep(20);
  2410. }
  2411. pr_warn(DFT_TAG "dump ok\n");
  2412. }
  2413. return 0;
  2414. }
  2415. ssize_t stp_sdio_rxdbg_write(struct file *filp, const char __user *buf, size_t count,
  2416. loff_t *f_pos)
  2417. {
  2418. unsigned long len = count;
  2419. pr_warn(DFT_TAG "write parameter len = %lu\n\r", len);
  2420. return len;
  2421. }
  2422. #else
  2423. /*!
  2424. * \brief /proc debug read interface and dump rx dbg information
  2425. *
  2426. * \details Dump all rx debug information to console.
  2427. *
  2428. * \retval 0 success
  2429. */
  2430. static int stp_sdio_rxdbg_read(char *page, char **start, off_t off, int count, int *eof, void *data)
  2431. {
  2432. UINT32 idx;
  2433. UINT32 i;
  2434. UINT32 j;
  2435. PUINT8 pbuf;
  2436. UINT32 len;
  2437. if (off > 0)
  2438. return 0;
  2439. for (i = 0; i < STP_SDIO_RXDBG_COUNT; ++i) {
  2440. idx = (stp_sdio_rxdbg_cnt - 1 - i) & STP_SDIO_TXDBG_COUNT_MASK;
  2441. len = stp_sdio_rxdbg_buffer[idx].bus_rxlen;
  2442. if (0 == len)
  2443. pr_warn(DFT_TAG "idx(0x%x) 0 == len dump skip\n", stp_sdio_rxdbg_cnt);
  2444. pr_warn(DFT_TAG "idx(0x%x) chisr_rxlen(%d) bus_rxlen(%d) ts(%d)\n",
  2445. stp_sdio_rxdbg_cnt, stp_sdio_rxdbg_buffer[idx].chisr_rxlen, len,
  2446. stp_sdio_rxdbg_buffer[idx].ts);
  2447. for (j = 0; j < STP_SDIO_RX_BUF_SIZE && j < len; j += 16) {
  2448. pbuf = &stp_sdio_rxdbg_buffer[idx].rx_pkt_buf[j];
  2449. pr_warn(DFT_TAG
  2450. "[0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x]\n",
  2451. pbuf[0], pbuf[1], pbuf[2], pbuf[3], pbuf[4], pbuf[5], pbuf[6],
  2452. pbuf[7], pbuf[8], pbuf[9], pbuf[10], pbuf[11], pbuf[12], pbuf[13],
  2453. pbuf[14], pbuf[15]);
  2454. msleep(20);
  2455. }
  2456. pr_warn(DFT_TAG "dump ok\n");
  2457. }
  2458. return 0;
  2459. }
  2460. /*!
  2461. * \brief /proc debug write interface. do nothing.
  2462. *
  2463. * \details
  2464. *
  2465. * \retval 0 success
  2466. */
  2467. static int
  2468. stp_sdio_rxdbg_write(struct file *file, const char *buffer, unsigned long count, void *data)
  2469. {
  2470. unsigned long len = count;
  2471. pr_warn(DFT_TAG "write parameter len = %lu\n\r", len);
  2472. return len;
  2473. }
  2474. #endif
  2475. /*!
  2476. * \brief /proc initial procedures. Initialize global debugging information.
  2477. *
  2478. * \details Setup entry for /proc debugging for rx
  2479. *
  2480. * \retval 0 success
  2481. */
  2482. INT32 stp_sdio_rxdbg_setup(VOID)
  2483. {
  2484. stp_sdio_rxdbg_cnt = 0;
  2485. #if USE_NEW_PROC_FS_FLAG
  2486. gStpSdioRxDbgEntry = proc_create(STP_SDIO_RXDBG_PROCNAME, 0644, NULL, &stp_sdio_rxdbg_fops);
  2487. if (gStpSdioRxDbgEntry == NULL) {
  2488. pr_warn(DFT_TAG "Unable to create /proc entry\n\r");
  2489. return -1;
  2490. }
  2491. #else
  2492. gStpSdioRxDbgEntry = create_proc_entry(STP_SDIO_RXDBG_PROCNAME, 0644, NULL);
  2493. if (gStpSdioRxDbgEntry == NULL) {
  2494. pr_warn(DFT_TAG "Unable to create /proc entry\n\r");
  2495. return -1;
  2496. }
  2497. gStpSdioRxDbgEntry->read_proc = stp_sdio_rxdbg_read;
  2498. gStpSdioRxDbgEntry->write_proc = stp_sdio_rxdbg_write;
  2499. pr_warn(DFT_TAG "Create /proc entry succeed\n\r");
  2500. #endif
  2501. return 0;
  2502. }
  2503. /*!
  2504. * \brief /proc de-init procedures.
  2505. *
  2506. * \details remove entry for /proc debugging for rx
  2507. *
  2508. * \retval 0 success
  2509. */
  2510. INT32 stp_sdio_rxdbg_remove(VOID)
  2511. {
  2512. #if USE_NEW_PROC_FS_FLAG
  2513. if (NULL != gStpSdioRxDbgEntry)
  2514. proc_remove(gStpSdioRxDbgEntry);
  2515. #else
  2516. if (NULL != gStpSdioRxDbgEntry)
  2517. remove_proc_entry(STP_SDIO_RXDBG_PROCNAME, NULL);
  2518. #endif
  2519. return 0;
  2520. }
  2521. #endif
  2522. #if STP_SDIO_DBG_SUPPORT && (STP_SDIO_TXDBG || STP_SDIO_TXPERFDBG)
  2523. static VOID stp_sdio_txperf_dump(VOID)
  2524. {
  2525. #if STP_SDIO_DBG_SUPPORT && STP_SDIO_TXPERFDBG
  2526. UINT32 cnt;
  2527. UINT32 fifo;
  2528. UINT32 data;
  2529. UINT32 wkr;
  2530. UINT32 pkt_num;
  2531. UINT32 lmt_cnt;
  2532. /* get debug counter snapshot */
  2533. cnt = stp_sdio_txperf_fifo_lmt_cnt;
  2534. fifo = stp_sdio_txperf_fifo_left;
  2535. data = stp_sdio_txperf_to_send;
  2536. wkr = stp_sdio_txperf_worker_cnt;
  2537. pkt_num = stp_sdio_txperf_txed_pkt_num;
  2538. lmt_cnt = stp_sdio_txperf_pkt_num_lmt_cnt;
  2539. pr_warn(DFT_TAG "txwait_fifo_left(%d), txwait_to_send(%d), txwait_count(%d)\n",
  2540. fifo, data, cnt);
  2541. if (cnt)
  2542. pr_warn(DFT_TAG "avg left(%d), to_send(%d)\n", (fifo / cnt), (data / cnt));
  2543. pr_warn(DFT_TAG "tx_worker_cnt(%d), pkt_num(%d), pkt_num_lmt_cnt(%d)\n",
  2544. wkr, pkt_num, lmt_cnt);
  2545. #endif
  2546. }
  2547. static VOID stp_sdio_txdbg_dump(VOID)
  2548. {
  2549. #if STP_SDIO_TXDBG
  2550. UINT32 idx;
  2551. UINT32 i;
  2552. UINT32 j;
  2553. PUINT8 pbuf;
  2554. UINT32 len;
  2555. for (i = 0; i < STP_SDIO_TXDBG_COUNT; ++i) {
  2556. idx = (stp_sdio_txdbg_cnt - 1 - i) & STP_SDIO_TXDBG_COUNT_MASK;
  2557. len = stp_sdio_txdbg_buffer[idx].bus_txlen;
  2558. if (0 == len) {
  2559. STPSDIO_INFO_FUNC("idx(%x) 0 == len dump skip\n", idx);
  2560. continue;
  2561. }
  2562. len = len > STP_SDIO_TXDBG_MAX_SIZE ? STP_SDIO_TXDBG_MAX_SIZE : len;
  2563. STPSDIO_INFO_FUNC(
  2564. "stp_sdio_txdbg_buffer idx(%x) bus_txlen(0x%x, %d) ts(%d)\n", idx, len, len,
  2565. stp_sdio_txdbg_buffer[idx].ts);
  2566. for (j = 0; j < STP_SDIO_TX_ENTRY_SIZE && j < len; j += 16) {
  2567. pbuf = &stp_sdio_txdbg_buffer[idx].tx_pkt_buf[j];
  2568. STPSDIO_INFO_FUNC(
  2569. "[0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x]\n",
  2570. pbuf[0], pbuf[1], pbuf[2], pbuf[3], pbuf[4], pbuf[5], pbuf[6],
  2571. pbuf[7], pbuf[8], pbuf[9], pbuf[10], pbuf[11], pbuf[12], pbuf[13],
  2572. pbuf[14], pbuf[15]);
  2573. msleep(20);
  2574. }
  2575. STPSDIO_INFO_FUNC("stp_sdio_txdbg_buffer dump ok\n");
  2576. }
  2577. for (i = 0; i < STP_SDIO_TXDBG_COUNT; ++i) {
  2578. idx = (stp_sdio_txdbg_cnt - 1 - i) & STP_SDIO_TXDBG_COUNT_MASK;
  2579. len = stp_sdio_txdbg_buffer[idx].bus_txlen;
  2580. STPSDIO_INFO_FUNC(
  2581. "stp_sdio_txdbg_buffer idx(%x) bus_txlen(0x%x, %d) ts(%d)\n", idx, len, len,
  2582. stp_sdio_txdbg_buffer[idx].ts);
  2583. }
  2584. STPSDIO_INFO_FUNC(
  2585. "Dump tx info: pkt_num(%d) fifo(%d) pkt_list.rd(0x%x, %ld) pkt_list.wr(0x%x, %ld)\n",
  2586. gp_info->firmware_info.tx_packet_num, gp_info->firmware_info.tx_fifo_size,
  2587. gp_info->tx_pkt_list.pkt_rd_cnt,
  2588. STP_SDIO_GET_PKT_AR_IDX(gp_info->tx_pkt_list.pkt_rd_cnt),
  2589. gp_info->tx_pkt_list.pkt_wr_cnt,
  2590. STP_SDIO_GET_PKT_AR_IDX(gp_info->tx_pkt_list.pkt_wr_cnt));
  2591. for (i = 0; i < STP_SDIO_TX_PKT_LIST_SIZE; ++i) {
  2592. idx = STP_SDIO_GET_PKT_AR_IDX(gp_info->tx_pkt_list.pkt_wr_cnt - 1 - i);
  2593. STPSDIO_INFO_FUNC(
  2594. "tx_pkt_list idx(0x%x, %d) size(0x%x, %d), in_ts(%d), out_ts(%d)\n",
  2595. (gp_info->tx_pkt_list.pkt_wr_cnt - 1 - i), idx,
  2596. gp_info->tx_pkt_list.pkt_size_list[idx],
  2597. gp_info->tx_pkt_list.pkt_size_list[idx], gp_info->tx_pkt_list.in_ts[idx],
  2598. gp_info->tx_pkt_list.out_ts[idx]);
  2599. }
  2600. #if STP_SDIO_NEW_TXRING
  2601. STPSDIO_INFO_FUNC("\n\ndump pkt_buf.tx_buf: rd(%d) wr(%d) full(%d)\n",
  2602. gp_info->pkt_buf.rd_cnt, gp_info->pkt_buf.wr_cnt, gp_info->pkt_buf.full_flag);
  2603. #else
  2604. STPSDIO_INFO_FUNC("\n\ndump pkt_buf.tx_buf: rdi(%d) wri(%d) full(%d)\n",
  2605. gp_info->pkt_buf.rd_idx, gp_info->pkt_buf.wr_idx, gp_info->pkt_buf.full_flag);
  2606. #endif
  2607. for (i = 0; i < STP_SDIO_TX_BUF_CNT; ++i) {
  2608. #if STP_SDIO_NEW_TXRING
  2609. idx = (gp_info->pkt_buf.wr_cnt - 1 - i) & STP_SDIO_TX_BUF_CNT_MASK;
  2610. len = gp_info->pkt_buf.tx_buf_sz[idx];
  2611. #else
  2612. idx = (gp_info->pkt_buf.wr_idx - 1 - i + STP_SDIO_TX_BUF_CNT) % STP_SDIO_TX_BUF_CNT;
  2613. #if KMALLOC_UPDATE
  2614. len = *(gp_info->pkt_buf.tx_buf + idx * STP_SDIO_TX_ENTRY_SIZE + 1);
  2615. len = (len << 8) | *(gp_info->pkt_buf.tx_buf + idx * STP_SDIO_TX_ENTRY_SIZE + 0);
  2616. #else
  2617. len = gp_info->pkt_buf.tx_buf[idx][1];
  2618. len = (len << 8) | gp_info->pkt_buf.tx_buf[idx][0];
  2619. #endif
  2620. #endif
  2621. STPSDIO_INFO_FUNC("pkt_buf.tx_buf idx(%x) ts(%d) len(%d)\n",
  2622. idx, gp_info->pkt_buf.tx_buf_ts[idx], len);
  2623. if (0 == len) {
  2624. STPSDIO_INFO_FUNC("idx(%x) 0 == len dump skip\n", idx);
  2625. continue;
  2626. }
  2627. len = len > STP_SDIO_TXDBG_MAX_SIZE ? STP_SDIO_TXDBG_MAX_SIZE : len;
  2628. for (j = 0; j < STP_SDIO_TX_ENTRY_SIZE && j < len; j += 16) {
  2629. #if KMALLOC_UPDATE
  2630. pbuf = gp_info->pkt_buf.tx_buf + idx * STP_SDIO_TX_ENTRY_SIZE + j;
  2631. #else
  2632. pbuf = &gp_info->pkt_buf.tx_buf[idx][j];
  2633. #endif
  2634. STPSDIO_INFO_FUNC(
  2635. "[0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x]\n",
  2636. pbuf[0], pbuf[1], pbuf[2], pbuf[3], pbuf[4], pbuf[5], pbuf[6],
  2637. pbuf[7], pbuf[8], pbuf[9], pbuf[10], pbuf[11], pbuf[12], pbuf[13],
  2638. pbuf[14], pbuf[15]);
  2639. msleep(20);
  2640. }
  2641. STPSDIO_INFO_FUNC("pkt_buf.tx_buf dump ok\n");
  2642. }
  2643. #endif /* end of STP_SDIO_TXDBG */
  2644. }
  2645. #if USE_NEW_PROC_FS_FLAG
  2646. ssize_t stp_sdio_txdbg_read(struct file *filp, char __user *buf, size_t count, loff_t *f_pos)
  2647. {
  2648. if (*f_pos > 0)
  2649. return 0;
  2650. stp_sdio_txdbg_dump();
  2651. stp_sdio_txperf_dump();
  2652. return 0;
  2653. }
  2654. ssize_t stp_sdio_txdbg_write(struct file *filp, const char __user *buf, size_t count,
  2655. loff_t *f_pos)
  2656. {
  2657. unsigned long len = count;
  2658. pr_warn(DFT_TAG "write parameter len = %lu\n\r", len);
  2659. return len;
  2660. }
  2661. #else
  2662. /*!
  2663. * \brief /proc debug read interface and dump tx dbg information
  2664. *
  2665. * \details Dump all tx debug information to console.
  2666. *
  2667. * \retval 0 success
  2668. */
  2669. static int stp_sdio_txdbg_read(char *page, char **start, off_t off, int count, int *eof, void *data)
  2670. {
  2671. if (off > 0)
  2672. return 0;
  2673. stp_sdio_txdbg_dump();
  2674. stp_sdio_txperf_dump();
  2675. return 0;
  2676. }
  2677. /*!
  2678. * \brief /proc debug write interface. do nothing.
  2679. *
  2680. * \details
  2681. *
  2682. * \retval 0 success
  2683. */
  2684. static int
  2685. stp_sdio_txdbg_write(struct file *file, const char *buffer, unsigned long count, void *data)
  2686. {
  2687. unsigned long len = count;
  2688. pr_warn(DFT_TAG "write parameter len = %lu\n\r", len);
  2689. return len;
  2690. }
  2691. #endif
  2692. #if USE_NEW_PROC_FS_FLAG
  2693. ssize_t stp_sdio_own_read(struct file *filp, char __user *buf, size_t count, loff_t *f_pos)
  2694. {
  2695. if (*f_pos > 0)
  2696. return 0;
  2697. return 0;
  2698. }
  2699. #else
  2700. /*!
  2701. * \brief /proc debug read interface and dump tx dbg information
  2702. *
  2703. * \details Dump all tx debug information to console.
  2704. *
  2705. * \retval 0 success
  2706. */
  2707. static int
  2708. stp_sdio_owndbg_read(char *page, char **start, off_t off, int count, int *eof, void *data)
  2709. {
  2710. if (off > 0)
  2711. return 0;
  2712. return 0;
  2713. }
  2714. #endif
  2715. /*!
  2716. * \brief /proc debug write interface. do nothing.
  2717. *
  2718. * \details
  2719. *
  2720. * \retval 0 success
  2721. */
  2722. #if USE_NEW_PROC_FS_FLAG
  2723. ssize_t stp_sdio_own_write(struct file *filp, const char __user *buffer, size_t count,
  2724. loff_t *f_pos)
  2725. #else
  2726. static int
  2727. stp_sdio_owndbg_write(struct file *file, const char *buffer, unsigned long count, void *data)
  2728. #endif
  2729. {
  2730. unsigned long len = count;
  2731. PINT8 pBuf = NULL;
  2732. PINT8 pToken = NULL;
  2733. PINT8 pDelimiter = " \t";
  2734. INT32 x = 0;
  2735. INT8 buf[128] = { 0 };
  2736. long res;
  2737. if (len >= osal_sizeof(buf)) {
  2738. STPSDIO_ERR_FUNC("input handling fail!\n");
  2739. len = osal_sizeof(buf) - 1;
  2740. return -1;
  2741. }
  2742. if (copy_from_user(buf, buffer, len)) {
  2743. STPSDIO_ERR_FUNC("copy_from_user error.\n");
  2744. return -EFAULT;
  2745. }
  2746. buf[len] = '\0';
  2747. pBuf = buf;
  2748. pToken = osal_strsep(&pBuf, pDelimiter);
  2749. osal_strtol(pToken, 16, &res);
  2750. x = NULL != pToken ? (INT32)res : 0;
  2751. if (0 == x) {
  2752. STPSDIO_INFO_FUNC("stp_sdio_own_ctrl(OWN_CLR)\n\r");
  2753. stp_sdio_own_ctrl(OWN_CLR);
  2754. } else if (2 == x) {
  2755. STPSDIO_INFO_FUNC("stp_sdio_own_ctrl(OWN_SET) -->Sleep\n\r");
  2756. stp_sdio_own_ctrl(OWN_SET);
  2757. } else if (3 == x) {
  2758. gStpSdioDbgLvl = STPSDIO_LOG_WARN;
  2759. STPSDIO_WARN_FUNC("set STP-SDIO LogLevel to STPSDIO_LOG_WARN\n\r");
  2760. } else if (4 == x) {
  2761. gStpSdioDbgLvl = STPSDIO_LOG_INFO;
  2762. STPSDIO_INFO_FUNC("set STP-SDIO LogLevel to STPSDIO_LOG_INFO\n\r");
  2763. } else if (5 == x) {
  2764. gStpSdioDbgLvl = STPSDIO_LOG_HINT;
  2765. STPSDIO_INFO_FUNC("set STP-SDIO LogLevel to STPSDIO_LOG_HINT\n\r");
  2766. } else if (6 == x) {
  2767. gStpSdioDbgLvl = STPSDIO_LOG_DBG;
  2768. STPSDIO_INFO_FUNC("set STP-SDIO LogLevel to STPSDIO_LOG_DBG\n\r");
  2769. } else if (7 == x) {
  2770. gStpSdioDbgLvl = STPSDIO_LOG_LOUD;
  2771. STPSDIO_INFO_FUNC("set STP-SDIO LogLevel to STPSDIO_LOG_LOUD\n\r");
  2772. }
  2773. return len;
  2774. }
  2775. /*!
  2776. * \brief /proc initial procedures. Initialize global debugging information.
  2777. *
  2778. * \details Setup entry for /proc debugging for tx
  2779. *
  2780. * \retval 0 success
  2781. */
  2782. INT32 stp_sdio_txdbg_setup(VOID)
  2783. {
  2784. #if USE_NEW_PROC_FS_FLAG
  2785. gStpSdioTxDbgEntry = proc_create(STP_SDIO_TXDBG_PROCNAME, 0644, NULL, &stp_sdio_txdbg_fops);
  2786. if (gStpSdioTxDbgEntry == NULL) {
  2787. pr_warn(DFT_TAG "Unable to create /proc entry\n\r");
  2788. return -1;
  2789. }
  2790. #else
  2791. gStpSdioTxDbgEntry = create_proc_entry(STP_SDIO_TXDBG_PROCNAME, 0644, NULL);
  2792. if (gStpSdioTxDbgEntry == NULL) {
  2793. pr_warn(DFT_TAG "Unable to create /proc entry\n\r");
  2794. return -1;
  2795. }
  2796. gStpSdioTxDbgEntry->read_proc = stp_sdio_txdbg_read;
  2797. gStpSdioTxDbgEntry->write_proc = stp_sdio_txdbg_write;
  2798. pr_warn(DFT_TAG "Unable to create /proc entry\n\r");
  2799. #endif
  2800. #if STP_SDIO_TXPERFDBG
  2801. stp_sdio_txperf_worker_cnt = 0;
  2802. stp_sdio_txperf_fifo_left = 0;
  2803. stp_sdio_txperf_to_send = 0;
  2804. stp_sdio_txperf_fifo_lmt_cnt = 0;
  2805. stp_sdio_txperf_txed_pkt_num = 0;
  2806. stp_sdio_txperf_pkt_num_lmt_cnt = 0;
  2807. #endif
  2808. #if STP_SDIO_TXDBG
  2809. stp_sdio_txdbg_cnt = 0;
  2810. #endif
  2811. return 0;
  2812. }
  2813. /*!
  2814. * \brief /proc de-init procedures.
  2815. *
  2816. * \details remove entry for /proc debugging for tx
  2817. *
  2818. * \retval 0 success
  2819. */
  2820. INT32 stp_sdio_txdbg_remove(VOID)
  2821. {
  2822. #if USE_NEW_PROC_FS_FLAG
  2823. if (NULL != gStpSdioTxDbgEntry)
  2824. proc_remove(gStpSdioTxDbgEntry);
  2825. #else
  2826. if (NULL != gStpSdioTxDbgEntry)
  2827. remove_proc_entry(STP_SDIO_TXDBG_PROCNAME, NULL);
  2828. #endif
  2829. return 0;
  2830. }
  2831. #endif /* end of STP_SDIO_DBG_SUPPORT && (STP_SDIO_TXDBG || STP_SDIO_TXPERFDBG) */
  2832. #if STP_SDIO_DBG_SUPPORT && STP_SDIO_OWNBACKDBG
  2833. /*!
  2834. * \brief /proc initial procedures. Initialize global debugging information.
  2835. *
  2836. * \details Setup entry for /proc debugging for tx
  2837. *
  2838. * \retval 0 success
  2839. */
  2840. INT32 stp_sdio_owndbg_setup(VOID)
  2841. {
  2842. #if USE_NEW_PROC_FS_FLAG
  2843. gStpSdioOwnEntry = proc_create(STP_SDIO_OWNDBG_PROCNAME, 0644, NULL, &stp_sdio_own_fops);
  2844. if (gStpSdioOwnEntry == NULL) {
  2845. pr_warn(DFT_TAG "Unable to create /proc entry\n\r");
  2846. return -1;
  2847. }
  2848. #else
  2849. gStpSdioOwnEntry = create_proc_entry(STP_SDIO_OWNDBG_PROCNAME, 0644, NULL);
  2850. if (gStpSdioOwnEntry == NULL) {
  2851. pr_warn(DFT_TAG "Unable to create /proc entry\n\r");
  2852. return -1;
  2853. }
  2854. gStpSdioOwnEntry->read_proc = stp_sdio_owndbg_read;
  2855. gStpSdioOwnEntry->write_proc = stp_sdio_owndbg_write;
  2856. pr_warn(DFT_TAG "Unable to create /proc entry\n\r");
  2857. #endif
  2858. return 0;
  2859. }
  2860. /*!
  2861. * \brief /proc de-init procedures.
  2862. *
  2863. * \details remove entry for /proc debugging for tx
  2864. *
  2865. * \retval 0 success
  2866. */
  2867. INT32 stp_sdio_owndbg_remove(VOID)
  2868. {
  2869. #if USE_NEW_PROC_FS_FLAG
  2870. if (NULL != gStpSdioOwnEntry)
  2871. proc_remove(gStpSdioOwnEntry);
  2872. #else
  2873. if (NULL != gStpSdioOwnEntry)
  2874. remove_proc_entry(STP_SDIO_OWNDBG_PROCNAME, NULL);
  2875. #endif
  2876. return 0;
  2877. }
  2878. #endif
  2879. /*!
  2880. * \brief hif_sdio init function
  2881. *
  2882. * detailed descriptions
  2883. *
  2884. * \retval
  2885. */
  2886. static int stp_sdio_init(void)
  2887. {
  2888. INT32 ret;
  2889. INT32 i;
  2890. STPSDIO_LOUD_FUNC("start\n");
  2891. /* 4 <1> initialize all private variables */
  2892. stp_sdio_host_info_op(1);
  2893. g_stp_sdio_host_count = 0;
  2894. /* Init stp sdio client info */
  2895. #if 0 /* George: chage to be a constant struct */
  2896. g_stp_sdio_cltinfo.func_tbl = mtk_stp_sdio_id_tbl;
  2897. g_stp_sdio_cltinfo.func_tbl_size =
  2898. sizeof(mtk_stp_sdio_id_tbl) / sizeof(MTK_WCN_HIF_SDIO_FUNCINFO) - 1;
  2899. g_stp_sdio_cltinfo.hif_clt_irq = stp_sdio_irq;
  2900. g_stp_sdio_cltinfo.hif_clt_probe = stp_sdio_probe;
  2901. g_stp_sdio_cltinfo.hif_clt_remove = stp_sdio_remove;
  2902. #endif
  2903. STPSDIO_INFO_FUNC("cltinfo func table size:%d\n", g_stp_sdio_cltinfo.func_tbl_size);
  2904. for (i = 0; i < g_stp_sdio_cltinfo.func_tbl_size; i++) {
  2905. STPSDIO_INFO_FUNC("manf_id:0x%x, card_id:0x%x, func_num:%d, blk_size:%d\n",
  2906. mtk_stp_sdio_id_tbl[i].manf_id, mtk_stp_sdio_id_tbl[i].card_id,
  2907. mtk_stp_sdio_id_tbl[i].func_num, mtk_stp_sdio_id_tbl[i].blk_sz);
  2908. }
  2909. /* 4 <2> register supported functions from sdio id table to hif sdio driver */
  2910. ret = mtk_wcn_hif_sdio_client_reg(&g_stp_sdio_cltinfo);
  2911. if (ret)
  2912. STPSDIO_ERR_FUNC("mtk_wcn_hif_sdio_client_reg fail(%d)!\n", ret);
  2913. ret = mtk_wcn_stp_wmt_sdio_op_reg(stp_sdio_own_ctrl);
  2914. if (ret)
  2915. STPSDIO_ERR_FUNC
  2916. ("mtk_wcn_stp_wmt_sdio_op_reg(mtk_wcn_stp_sdio_own_ctrl) fail(%d)!\n", ret);
  2917. STPSDIO_LOUD_FUNC("end\n");
  2918. #if STP_SDIO_DBG_SUPPORT && STP_SDIO_RXDBG
  2919. stp_sdio_rxdbg_setup();
  2920. #endif
  2921. #if STP_SDIO_DBG_SUPPORT && STP_SDIO_TXDBG
  2922. stp_sdio_txdbg_setup();
  2923. #endif
  2924. #if STP_SDIO_DBG_SUPPORT && STP_SDIO_OWNBACKDBG
  2925. stp_sdio_owndbg_setup();
  2926. #endif
  2927. STPSDIO_INFO_FUNC
  2928. ("blk_size(%ld), tx_buf_cnt(%ld), fifo tx(%ld) rx(%ld), buf tx(%ld) rx(%ld)\n",
  2929. STP_SDIO_BLK_SIZE, STP_SDIO_TX_BUF_CNT, STP_SDIO_TX_FIFO_SIZE, STP_SDIO_RX_FIFO_SIZE,
  2930. STP_SDIO_TX_ENTRY_SIZE, STP_SDIO_TX_ENTRY_SIZE);
  2931. return ret;
  2932. }
  2933. /*!
  2934. * \brief hif_sdio init function
  2935. *
  2936. * detailed descriptions
  2937. *
  2938. * \retval
  2939. */
  2940. static void stp_sdio_exit(void)
  2941. {
  2942. STPSDIO_LOUD_FUNC("start\n");
  2943. #if STP_SDIO_DBG_SUPPORT && STP_SDIO_TXDBG
  2944. stp_sdio_txdbg_remove();
  2945. #endif
  2946. #if STP_SDIO_DBG_SUPPORT && STP_SDIO_RXDBG
  2947. stp_sdio_rxdbg_remove();
  2948. #endif
  2949. #if STP_SDIO_DBG_SUPPORT && STP_SDIO_OWNBACKDBG
  2950. stp_sdio_owndbg_remove();
  2951. #endif
  2952. /* 4 <0> unregister if_tx() function */
  2953. mtk_wcn_stp_register_if_tx(STP_SDIO_IF_TX, 0x0);
  2954. /* 4 <1> for all functions that have not been unregistered */
  2955. /* 4 <1.1> unregister stp sdio func of the host */
  2956. mtk_wcn_hif_sdio_client_unreg(&g_stp_sdio_cltinfo);
  2957. /* 4 <1.2> stop Tx tasklet/Rx work queue of the host */
  2958. flush_scheduled_work();
  2959. STPSDIO_DBG_FUNC("flush scheduled work end\n");
  2960. /* 4 <1.3> return ownership to firmware of the host */
  2961. /* TODO: check set which register ! */
  2962. /* 4 <1.4> clear the host struct list and free the memory allocation of the host */
  2963. g_stp_sdio_host_count = 0;
  2964. stp_sdio_host_info_op(0);
  2965. /* 4 <1.5> Notice: while rmmod client driver, the stp_sdio_remove()
  2966. will not be called after stp_sdio_exit() ! */
  2967. STPSDIO_DBG_FUNC("end\n");
  2968. }
  2969. #ifdef MTK_WCN_REMOVE_KERNEL_MODULE
  2970. INT32 mtk_wcn_stp_sdio_drv_init(VOID)
  2971. {
  2972. return stp_sdio_init();
  2973. }
  2974. EXPORT_SYMBOL(mtk_wcn_stp_sdio_drv_init);
  2975. VOID mtk_wcn_stp_sdio_drv_exit(VOID)
  2976. {
  2977. return stp_sdio_exit();
  2978. }
  2979. EXPORT_SYMBOL(mtk_wcn_stp_sdio_drv_exit);
  2980. #else
  2981. module_init(stp_sdio_init);
  2982. module_exit(stp_sdio_exit);
  2983. #endif