dp_htt.c 69 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482
  1. /*
  2. * Copyright (c) 2016-2017 The Linux Foundation. All rights reserved.
  3. *
  4. * Permission to use, copy, modify, and/or distribute this software for
  5. * any purpose with or without fee is hereby granted, provided that the
  6. * above copyright notice and this permission notice appear in all
  7. * copies.
  8. *
  9. * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
  10. * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
  11. * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
  12. * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
  13. * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
  14. * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
  15. * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
  16. * PERFORMANCE OF THIS SOFTWARE.
  17. */
  18. #include <htt.h>
  19. #include <hal_api.h>
  20. #include "dp_htt.h"
  21. #include "dp_peer.h"
  22. #include "dp_types.h"
  23. #include "dp_internal.h"
  24. #include "dp_rx_mon.h"
  25. #include "htt_stats.h"
  26. #include "htt_ppdu_stats.h"
  27. #include "qdf_mem.h" /* qdf_mem_malloc,free */
  28. #include "cdp_txrx_cmn_struct.h"
  29. #define HTT_TLV_HDR_LEN HTT_T2H_EXT_STATS_CONF_TLV_HDR_SIZE
  30. #define HTT_HTC_PKT_POOL_INIT_SIZE 64
  31. #define HTT_T2H_MAX_MSG_SIZE 2048
  32. #define HTT_MSG_BUF_SIZE(msg_bytes) \
  33. ((msg_bytes) + HTC_HEADER_LEN + HTC_HDR_ALIGNMENT_PADDING)
  34. #define DP_EXT_MSG_LENGTH 2048
  35. #define DP_HTT_SEND_HTC_PKT(soc, pkt) \
  36. do { \
  37. if (htc_send_pkt(soc->htc_soc, &pkt->htc_pkt) == \
  38. QDF_STATUS_SUCCESS) \
  39. htt_htc_misc_pkt_list_add(soc, pkt); \
  40. } while (0)
  41. /*
  42. * dp_tx_stats_update() - Update per-peer statistics
  43. * @soc: Datapath soc handle
  44. * @peer: Datapath peer handle
  45. * @ppdu: PPDU Descriptor
  46. * @ack_rssi: RSSI of last ack received
  47. *
  48. * Return: None
  49. */
  50. #ifdef FEATURE_PERPKT_INFO
  51. static void dp_tx_stats_update(struct dp_soc *soc, struct dp_peer *peer,
  52. struct cdp_tx_completion_ppdu_user *ppdu, uint32_t ack_rssi)
  53. {
  54. struct dp_pdev *pdev = NULL;
  55. if (!peer)
  56. return;
  57. pdev = peer->vdev->pdev;
  58. DP_STATS_INC_PKT(peer, tx.comp_pkt,
  59. (ppdu->success_msdus + ppdu->retry_msdus +
  60. ppdu->failed_msdus),
  61. ppdu->success_bytes);
  62. DP_STATS_INC(peer, tx.tx_failed, ppdu->failed_msdus);
  63. DP_STATS_INC(peer,
  64. tx.pkt_type[ppdu->preamble].mcs_count[ppdu->mcs], 1);
  65. DP_STATS_INC(peer, tx.sgi_count[ppdu->gi], 1);
  66. DP_STATS_INC(peer, tx.bw[ppdu->bw], 1);
  67. DP_STATS_UPD(peer, tx.last_ack_rssi, ack_rssi);
  68. DP_STATS_INC(peer, tx.wme_ac_type[TID_TO_WME_AC(ppdu->tid)], 1);
  69. DP_STATS_INC(peer, tx.stbc, ppdu->stbc);
  70. DP_STATS_INC(peer, tx.ldpc, ppdu->ldpc);
  71. DP_STATS_INC_PKT(peer, tx.tx_success, ppdu->success_msdus,
  72. ppdu->success_bytes);
  73. DP_STATS_INC(peer, tx.retries,
  74. (ppdu->long_retries + ppdu->short_retries));
  75. if (soc->cdp_soc.ol_ops->update_dp_stats) {
  76. soc->cdp_soc.ol_ops->update_dp_stats(pdev->osif_pdev,
  77. &peer->stats, ppdu->peer_id,
  78. UPDATE_PEER_STATS);
  79. }
  80. }
  81. #endif
  82. /*
  83. * htt_htc_pkt_alloc() - Allocate HTC packet buffer
  84. * @htt_soc: HTT SOC handle
  85. *
  86. * Return: Pointer to htc packet buffer
  87. */
  88. static struct dp_htt_htc_pkt *
  89. htt_htc_pkt_alloc(struct htt_soc *soc)
  90. {
  91. struct dp_htt_htc_pkt_union *pkt = NULL;
  92. HTT_TX_MUTEX_ACQUIRE(&soc->htt_tx_mutex);
  93. if (soc->htt_htc_pkt_freelist) {
  94. pkt = soc->htt_htc_pkt_freelist;
  95. soc->htt_htc_pkt_freelist = soc->htt_htc_pkt_freelist->u.next;
  96. }
  97. HTT_TX_MUTEX_RELEASE(&soc->htt_tx_mutex);
  98. if (pkt == NULL)
  99. pkt = qdf_mem_malloc(sizeof(*pkt));
  100. return &pkt->u.pkt; /* not actually a dereference */
  101. }
  102. /*
  103. * htt_htc_pkt_free() - Free HTC packet buffer
  104. * @htt_soc: HTT SOC handle
  105. */
  106. static void
  107. htt_htc_pkt_free(struct htt_soc *soc, struct dp_htt_htc_pkt *pkt)
  108. {
  109. struct dp_htt_htc_pkt_union *u_pkt =
  110. (struct dp_htt_htc_pkt_union *)pkt;
  111. HTT_TX_MUTEX_ACQUIRE(&soc->htt_tx_mutex);
  112. u_pkt->u.next = soc->htt_htc_pkt_freelist;
  113. soc->htt_htc_pkt_freelist = u_pkt;
  114. HTT_TX_MUTEX_RELEASE(&soc->htt_tx_mutex);
  115. }
  116. /*
  117. * htt_htc_pkt_pool_free() - Free HTC packet pool
  118. * @htt_soc: HTT SOC handle
  119. */
  120. static void
  121. htt_htc_pkt_pool_free(struct htt_soc *soc)
  122. {
  123. struct dp_htt_htc_pkt_union *pkt, *next;
  124. pkt = soc->htt_htc_pkt_freelist;
  125. while (pkt) {
  126. next = pkt->u.next;
  127. qdf_mem_free(pkt);
  128. pkt = next;
  129. }
  130. soc->htt_htc_pkt_freelist = NULL;
  131. }
  132. /*
  133. * htt_htc_misc_pkt_list_trim() - trim misc list
  134. * @htt_soc: HTT SOC handle
  135. * @level: max no. of pkts in list
  136. */
  137. static void
  138. htt_htc_misc_pkt_list_trim(struct htt_soc *soc, int level)
  139. {
  140. struct dp_htt_htc_pkt_union *pkt, *next, *prev = NULL;
  141. int i = 0;
  142. qdf_nbuf_t netbuf;
  143. HTT_TX_MUTEX_ACQUIRE(&soc->htt_tx_mutex);
  144. pkt = soc->htt_htc_pkt_misclist;
  145. while (pkt) {
  146. next = pkt->u.next;
  147. /* trim the out grown list*/
  148. if (++i > level) {
  149. netbuf =
  150. (qdf_nbuf_t)(pkt->u.pkt.htc_pkt.pNetBufContext);
  151. qdf_nbuf_unmap(soc->osdev, netbuf, QDF_DMA_TO_DEVICE);
  152. qdf_nbuf_free(netbuf);
  153. qdf_mem_free(pkt);
  154. pkt = NULL;
  155. if (prev)
  156. prev->u.next = NULL;
  157. }
  158. prev = pkt;
  159. pkt = next;
  160. }
  161. HTT_TX_MUTEX_RELEASE(&soc->htt_tx_mutex);
  162. }
  163. /*
  164. * htt_htc_misc_pkt_list_add() - Add pkt to misc list
  165. * @htt_soc: HTT SOC handle
  166. * @dp_htt_htc_pkt: pkt to be added to list
  167. */
  168. static void
  169. htt_htc_misc_pkt_list_add(struct htt_soc *soc, struct dp_htt_htc_pkt *pkt)
  170. {
  171. struct dp_htt_htc_pkt_union *u_pkt =
  172. (struct dp_htt_htc_pkt_union *)pkt;
  173. int misclist_trim_level = htc_get_tx_queue_depth(soc->htc_soc,
  174. pkt->htc_pkt.Endpoint)
  175. + DP_HTT_HTC_PKT_MISCLIST_SIZE;
  176. HTT_TX_MUTEX_ACQUIRE(&soc->htt_tx_mutex);
  177. if (soc->htt_htc_pkt_misclist) {
  178. u_pkt->u.next = soc->htt_htc_pkt_misclist;
  179. soc->htt_htc_pkt_misclist = u_pkt;
  180. } else {
  181. soc->htt_htc_pkt_misclist = u_pkt;
  182. }
  183. HTT_TX_MUTEX_RELEASE(&soc->htt_tx_mutex);
  184. /* only ce pipe size + tx_queue_depth could possibly be in use
  185. * free older packets in the misclist
  186. */
  187. htt_htc_misc_pkt_list_trim(soc, misclist_trim_level);
  188. }
  189. /*
  190. * htt_htc_misc_pkt_pool_free() - free pkts in misc list
  191. * @htt_soc: HTT SOC handle
  192. */
  193. static void
  194. htt_htc_misc_pkt_pool_free(struct htt_soc *soc)
  195. {
  196. struct dp_htt_htc_pkt_union *pkt, *next;
  197. qdf_nbuf_t netbuf;
  198. pkt = soc->htt_htc_pkt_misclist;
  199. while (pkt) {
  200. next = pkt->u.next;
  201. netbuf = (qdf_nbuf_t) (pkt->u.pkt.htc_pkt.pNetBufContext);
  202. qdf_nbuf_unmap(soc->osdev, netbuf, QDF_DMA_TO_DEVICE);
  203. soc->stats.htc_pkt_free++;
  204. QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_DEBUG,
  205. "%s: Pkt free count %d\n",
  206. __func__, soc->stats.htc_pkt_free);
  207. qdf_nbuf_free(netbuf);
  208. qdf_mem_free(pkt);
  209. pkt = next;
  210. }
  211. soc->htt_htc_pkt_misclist = NULL;
  212. }
  213. /*
  214. * htt_t2h_mac_addr_deswizzle() - Swap MAC addr bytes if FW endianess differ
  215. * @tgt_mac_addr: Target MAC
  216. * @buffer: Output buffer
  217. */
  218. static u_int8_t *
  219. htt_t2h_mac_addr_deswizzle(u_int8_t *tgt_mac_addr, u_int8_t *buffer)
  220. {
  221. #ifdef BIG_ENDIAN_HOST
  222. /*
  223. * The host endianness is opposite of the target endianness.
  224. * To make u_int32_t elements come out correctly, the target->host
  225. * upload has swizzled the bytes in each u_int32_t element of the
  226. * message.
  227. * For byte-array message fields like the MAC address, this
  228. * upload swizzling puts the bytes in the wrong order, and needs
  229. * to be undone.
  230. */
  231. buffer[0] = tgt_mac_addr[3];
  232. buffer[1] = tgt_mac_addr[2];
  233. buffer[2] = tgt_mac_addr[1];
  234. buffer[3] = tgt_mac_addr[0];
  235. buffer[4] = tgt_mac_addr[7];
  236. buffer[5] = tgt_mac_addr[6];
  237. return buffer;
  238. #else
  239. /*
  240. * The host endianness matches the target endianness -
  241. * we can use the mac addr directly from the message buffer.
  242. */
  243. return tgt_mac_addr;
  244. #endif
  245. }
  246. /*
  247. * dp_htt_h2t_send_complete_free_netbuf() - Free completed buffer
  248. * @soc: SOC handle
  249. * @status: Completion status
  250. * @netbuf: HTT buffer
  251. */
  252. static void
  253. dp_htt_h2t_send_complete_free_netbuf(
  254. void *soc, A_STATUS status, qdf_nbuf_t netbuf)
  255. {
  256. qdf_nbuf_free(netbuf);
  257. }
  258. /*
  259. * dp_htt_h2t_send_complete() - H2T completion handler
  260. * @context: Opaque context (HTT SOC handle)
  261. * @htc_pkt: HTC packet
  262. */
  263. static void
  264. dp_htt_h2t_send_complete(void *context, HTC_PACKET *htc_pkt)
  265. {
  266. void (*send_complete_part2)(
  267. void *soc, A_STATUS status, qdf_nbuf_t msdu);
  268. struct htt_soc *soc = (struct htt_soc *) context;
  269. struct dp_htt_htc_pkt *htt_pkt;
  270. qdf_nbuf_t netbuf;
  271. send_complete_part2 = htc_pkt->pPktContext;
  272. htt_pkt = container_of(htc_pkt, struct dp_htt_htc_pkt, htc_pkt);
  273. /* process (free or keep) the netbuf that held the message */
  274. netbuf = (qdf_nbuf_t) htc_pkt->pNetBufContext;
  275. /*
  276. * adf sendcomplete is required for windows only
  277. */
  278. /* qdf_nbuf_set_sendcompleteflag(netbuf, TRUE); */
  279. if (send_complete_part2 != NULL) {
  280. send_complete_part2(
  281. htt_pkt->soc_ctxt, htc_pkt->Status, netbuf);
  282. }
  283. /* free the htt_htc_pkt / HTC_PACKET object */
  284. htt_htc_pkt_free(soc, htt_pkt);
  285. }
  286. /*
  287. * htt_h2t_ver_req_msg() - Send HTT version request message to target
  288. * @htt_soc: HTT SOC handle
  289. *
  290. * Return: 0 on success; error code on failure
  291. */
  292. static int htt_h2t_ver_req_msg(struct htt_soc *soc)
  293. {
  294. struct dp_htt_htc_pkt *pkt;
  295. qdf_nbuf_t msg;
  296. uint32_t *msg_word;
  297. msg = qdf_nbuf_alloc(
  298. soc->osdev,
  299. HTT_MSG_BUF_SIZE(HTT_VER_REQ_BYTES),
  300. /* reserve room for the HTC header */
  301. HTC_HEADER_LEN + HTC_HDR_ALIGNMENT_PADDING, 4, TRUE);
  302. if (!msg)
  303. return QDF_STATUS_E_NOMEM;
  304. /*
  305. * Set the length of the message.
  306. * The contribution from the HTC_HDR_ALIGNMENT_PADDING is added
  307. * separately during the below call to qdf_nbuf_push_head.
  308. * The contribution from the HTC header is added separately inside HTC.
  309. */
  310. if (qdf_nbuf_put_tail(msg, HTT_VER_REQ_BYTES) == NULL) {
  311. QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
  312. "%s: Failed to expand head for HTT_H2T_MSG_TYPE_VERSION_REQ msg\n",
  313. __func__);
  314. return QDF_STATUS_E_FAILURE;
  315. }
  316. /* fill in the message contents */
  317. msg_word = (u_int32_t *) qdf_nbuf_data(msg);
  318. /* rewind beyond alignment pad to get to the HTC header reserved area */
  319. qdf_nbuf_push_head(msg, HTC_HDR_ALIGNMENT_PADDING);
  320. *msg_word = 0;
  321. HTT_H2T_MSG_TYPE_SET(*msg_word, HTT_H2T_MSG_TYPE_VERSION_REQ);
  322. pkt = htt_htc_pkt_alloc(soc);
  323. if (!pkt) {
  324. qdf_nbuf_free(msg);
  325. return QDF_STATUS_E_FAILURE;
  326. }
  327. pkt->soc_ctxt = NULL; /* not used during send-done callback */
  328. SET_HTC_PACKET_INFO_TX(&pkt->htc_pkt,
  329. dp_htt_h2t_send_complete_free_netbuf, qdf_nbuf_data(msg),
  330. qdf_nbuf_len(msg), soc->htc_endpoint,
  331. 1); /* tag - not relevant here */
  332. SET_HTC_PACKET_NET_BUF_CONTEXT(&pkt->htc_pkt, msg);
  333. DP_HTT_SEND_HTC_PKT(soc, pkt);
  334. return 0;
  335. }
  336. /*
  337. * htt_srng_setup() - Send SRNG setup message to target
  338. * @htt_soc: HTT SOC handle
  339. * @mac_id: MAC Id
  340. * @hal_srng: Opaque HAL SRNG pointer
  341. * @hal_ring_type: SRNG ring type
  342. *
  343. * Return: 0 on success; error code on failure
  344. */
  345. int htt_srng_setup(void *htt_soc, int mac_id, void *hal_srng,
  346. int hal_ring_type)
  347. {
  348. struct htt_soc *soc = (struct htt_soc *)htt_soc;
  349. struct dp_htt_htc_pkt *pkt;
  350. qdf_nbuf_t htt_msg;
  351. uint32_t *msg_word;
  352. struct hal_srng_params srng_params;
  353. qdf_dma_addr_t hp_addr, tp_addr;
  354. uint32_t ring_entry_size =
  355. hal_srng_get_entrysize(soc->hal_soc, hal_ring_type);
  356. int htt_ring_type, htt_ring_id;
  357. /* Sizes should be set in 4-byte words */
  358. ring_entry_size = ring_entry_size >> 2;
  359. htt_msg = qdf_nbuf_alloc(soc->osdev,
  360. HTT_MSG_BUF_SIZE(HTT_SRING_SETUP_SZ),
  361. /* reserve room for the HTC header */
  362. HTC_HEADER_LEN + HTC_HDR_ALIGNMENT_PADDING, 4, TRUE);
  363. if (!htt_msg)
  364. goto fail0;
  365. hal_get_srng_params(soc->hal_soc, hal_srng, &srng_params);
  366. hp_addr = hal_srng_get_hp_addr(soc->hal_soc, hal_srng);
  367. tp_addr = hal_srng_get_tp_addr(soc->hal_soc, hal_srng);
  368. switch (hal_ring_type) {
  369. case RXDMA_BUF:
  370. #ifdef QCA_HOST2FW_RXBUF_RING
  371. if (srng_params.ring_id ==
  372. (HAL_SRNG_WMAC1_SW2RXDMA0_BUF0)) {
  373. htt_ring_id = HTT_HOST1_TO_FW_RXBUF_RING;
  374. htt_ring_type = HTT_SW_TO_SW_RING;
  375. #ifdef IPA_OFFLOAD
  376. } else if (srng_params.ring_id ==
  377. (HAL_SRNG_WMAC1_SW2RXDMA0_BUF2)) {
  378. htt_ring_id = HTT_HOST2_TO_FW_RXBUF_RING;
  379. htt_ring_type = HTT_SW_TO_SW_RING;
  380. #endif
  381. #else
  382. if (srng_params.ring_id ==
  383. (HAL_SRNG_WMAC1_SW2RXDMA0_BUF0 +
  384. (mac_id * HAL_MAX_RINGS_PER_LMAC))) {
  385. htt_ring_id = HTT_RXDMA_HOST_BUF_RING;
  386. htt_ring_type = HTT_SW_TO_HW_RING;
  387. #endif
  388. } else if (srng_params.ring_id ==
  389. #ifdef IPA_OFFLOAD
  390. (HAL_SRNG_WMAC1_SW2RXDMA0_BUF1 +
  391. #else
  392. (HAL_SRNG_WMAC1_SW2RXDMA1_BUF +
  393. #endif
  394. (mac_id * HAL_MAX_RINGS_PER_LMAC))) {
  395. htt_ring_id = HTT_RXDMA_HOST_BUF_RING;
  396. htt_ring_type = HTT_SW_TO_HW_RING;
  397. } else {
  398. QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
  399. "%s: Ring %d currently not supported\n",
  400. __func__, srng_params.ring_id);
  401. goto fail1;
  402. }
  403. QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
  404. "%s: ring_type %d ring_id %d\n",
  405. __func__, hal_ring_type, srng_params.ring_id);
  406. QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
  407. "%s: hp_addr 0x%llx tp_addr 0x%llx\n",
  408. __func__, (uint64_t)hp_addr, (uint64_t)tp_addr);
  409. QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
  410. "%s: htt_ring_id %d\n", __func__, htt_ring_id);
  411. break;
  412. case RXDMA_MONITOR_BUF:
  413. htt_ring_id = HTT_RXDMA_MONITOR_BUF_RING;
  414. htt_ring_type = HTT_SW_TO_HW_RING;
  415. break;
  416. case RXDMA_MONITOR_STATUS:
  417. htt_ring_id = HTT_RXDMA_MONITOR_STATUS_RING;
  418. htt_ring_type = HTT_SW_TO_HW_RING;
  419. break;
  420. case RXDMA_MONITOR_DST:
  421. htt_ring_id = HTT_RXDMA_MONITOR_DEST_RING;
  422. htt_ring_type = HTT_HW_TO_SW_RING;
  423. break;
  424. case RXDMA_MONITOR_DESC:
  425. htt_ring_id = HTT_RXDMA_MONITOR_DESC_RING;
  426. htt_ring_type = HTT_SW_TO_HW_RING;
  427. break;
  428. case RXDMA_DST:
  429. htt_ring_id = HTT_RXDMA_NON_MONITOR_DEST_RING;
  430. htt_ring_type = HTT_HW_TO_SW_RING;
  431. break;
  432. default:
  433. QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
  434. "%s: Ring currently not supported\n", __func__);
  435. goto fail1;
  436. }
  437. /*
  438. * Set the length of the message.
  439. * The contribution from the HTC_HDR_ALIGNMENT_PADDING is added
  440. * separately during the below call to qdf_nbuf_push_head.
  441. * The contribution from the HTC header is added separately inside HTC.
  442. */
  443. if (qdf_nbuf_put_tail(htt_msg, HTT_SRING_SETUP_SZ) == NULL) {
  444. QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
  445. "%s: Failed to expand head for SRING_SETUP msg\n",
  446. __func__);
  447. return QDF_STATUS_E_FAILURE;
  448. }
  449. msg_word = (uint32_t *)qdf_nbuf_data(htt_msg);
  450. /* rewind beyond alignment pad to get to the HTC header reserved area */
  451. qdf_nbuf_push_head(htt_msg, HTC_HDR_ALIGNMENT_PADDING);
  452. /* word 0 */
  453. *msg_word = 0;
  454. HTT_H2T_MSG_TYPE_SET(*msg_word, HTT_H2T_MSG_TYPE_SRING_SETUP);
  455. if ((htt_ring_type == HTT_SW_TO_HW_RING) ||
  456. (htt_ring_type == HTT_HW_TO_SW_RING))
  457. HTT_SRING_SETUP_PDEV_ID_SET(*msg_word,
  458. DP_SW2HW_MACID(mac_id));
  459. else
  460. HTT_SRING_SETUP_PDEV_ID_SET(*msg_word, mac_id);
  461. QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
  462. "%s: mac_id %d\n", __func__, mac_id);
  463. HTT_SRING_SETUP_RING_TYPE_SET(*msg_word, htt_ring_type);
  464. /* TODO: Discuss with FW on changing this to unique ID and using
  465. * htt_ring_type to send the type of ring
  466. */
  467. HTT_SRING_SETUP_RING_ID_SET(*msg_word, htt_ring_id);
  468. /* word 1 */
  469. msg_word++;
  470. *msg_word = 0;
  471. HTT_SRING_SETUP_RING_BASE_ADDR_LO_SET(*msg_word,
  472. srng_params.ring_base_paddr & 0xffffffff);
  473. /* word 2 */
  474. msg_word++;
  475. *msg_word = 0;
  476. HTT_SRING_SETUP_RING_BASE_ADDR_HI_SET(*msg_word,
  477. (uint64_t)srng_params.ring_base_paddr >> 32);
  478. /* word 3 */
  479. msg_word++;
  480. *msg_word = 0;
  481. HTT_SRING_SETUP_ENTRY_SIZE_SET(*msg_word, ring_entry_size);
  482. HTT_SRING_SETUP_RING_SIZE_SET(*msg_word,
  483. (ring_entry_size * srng_params.num_entries));
  484. QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
  485. "%s: entry_size %d\n", __func__,
  486. ring_entry_size);
  487. QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
  488. "%s: num_entries %d\n", __func__,
  489. srng_params.num_entries);
  490. QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
  491. "%s: ring_size %d\n", __func__,
  492. (ring_entry_size * srng_params.num_entries));
  493. if (htt_ring_type == HTT_SW_TO_HW_RING)
  494. HTT_SRING_SETUP_RING_MISC_CFG_FLAG_LOOPCOUNT_DISABLE_SET(
  495. *msg_word, 1);
  496. HTT_SRING_SETUP_RING_MISC_CFG_FLAG_MSI_SWAP_SET(*msg_word,
  497. !!(srng_params.flags & HAL_SRNG_MSI_SWAP));
  498. HTT_SRING_SETUP_RING_MISC_CFG_FLAG_TLV_SWAP_SET(*msg_word,
  499. !!(srng_params.flags & HAL_SRNG_DATA_TLV_SWAP));
  500. HTT_SRING_SETUP_RING_MISC_CFG_FLAG_HOST_FW_SWAP_SET(*msg_word,
  501. !!(srng_params.flags & HAL_SRNG_RING_PTR_SWAP));
  502. /* word 4 */
  503. msg_word++;
  504. *msg_word = 0;
  505. HTT_SRING_SETUP_HEAD_OFFSET32_REMOTE_BASE_ADDR_LO_SET(*msg_word,
  506. hp_addr & 0xffffffff);
  507. /* word 5 */
  508. msg_word++;
  509. *msg_word = 0;
  510. HTT_SRING_SETUP_HEAD_OFFSET32_REMOTE_BASE_ADDR_HI_SET(*msg_word,
  511. (uint64_t)hp_addr >> 32);
  512. /* word 6 */
  513. msg_word++;
  514. *msg_word = 0;
  515. HTT_SRING_SETUP_TAIL_OFFSET32_REMOTE_BASE_ADDR_LO_SET(*msg_word,
  516. tp_addr & 0xffffffff);
  517. /* word 7 */
  518. msg_word++;
  519. *msg_word = 0;
  520. HTT_SRING_SETUP_TAIL_OFFSET32_REMOTE_BASE_ADDR_HI_SET(*msg_word,
  521. (uint64_t)tp_addr >> 32);
  522. /* word 8 */
  523. msg_word++;
  524. *msg_word = 0;
  525. HTT_SRING_SETUP_RING_MSI_ADDR_LO_SET(*msg_word,
  526. srng_params.msi_addr & 0xffffffff);
  527. /* word 9 */
  528. msg_word++;
  529. *msg_word = 0;
  530. HTT_SRING_SETUP_RING_MSI_ADDR_HI_SET(*msg_word,
  531. (uint64_t)(srng_params.msi_addr) >> 32);
  532. /* word 10 */
  533. msg_word++;
  534. *msg_word = 0;
  535. HTT_SRING_SETUP_RING_MSI_DATA_SET(*msg_word,
  536. srng_params.msi_data);
  537. /* word 11 */
  538. msg_word++;
  539. *msg_word = 0;
  540. HTT_SRING_SETUP_INTR_BATCH_COUNTER_TH_SET(*msg_word,
  541. srng_params.intr_batch_cntr_thres_entries *
  542. ring_entry_size);
  543. HTT_SRING_SETUP_INTR_TIMER_TH_SET(*msg_word,
  544. srng_params.intr_timer_thres_us >> 3);
  545. /* word 12 */
  546. msg_word++;
  547. *msg_word = 0;
  548. if (srng_params.flags & HAL_SRNG_LOW_THRES_INTR_ENABLE) {
  549. /* TODO: Setting low threshold to 1/8th of ring size - see
  550. * if this needs to be configurable
  551. */
  552. HTT_SRING_SETUP_INTR_LOW_TH_SET(*msg_word,
  553. srng_params.low_threshold);
  554. }
  555. /* "response_required" field should be set if a HTT response message is
  556. * required after setting up the ring.
  557. */
  558. pkt = htt_htc_pkt_alloc(soc);
  559. if (!pkt)
  560. goto fail1;
  561. pkt->soc_ctxt = NULL; /* not used during send-done callback */
  562. SET_HTC_PACKET_INFO_TX(
  563. &pkt->htc_pkt,
  564. dp_htt_h2t_send_complete_free_netbuf,
  565. qdf_nbuf_data(htt_msg),
  566. qdf_nbuf_len(htt_msg),
  567. soc->htc_endpoint,
  568. 1); /* tag - not relevant here */
  569. SET_HTC_PACKET_NET_BUF_CONTEXT(&pkt->htc_pkt, htt_msg);
  570. DP_HTT_SEND_HTC_PKT(soc, pkt);
  571. return QDF_STATUS_SUCCESS;
  572. fail1:
  573. qdf_nbuf_free(htt_msg);
  574. fail0:
  575. return QDF_STATUS_E_FAILURE;
  576. }
  577. /*
  578. * htt_h2t_rx_ring_cfg() - Send SRNG packet and TLV filter
  579. * config message to target
  580. * @htt_soc: HTT SOC handle
  581. * @pdev_id: PDEV Id
  582. * @hal_srng: Opaque HAL SRNG pointer
  583. * @hal_ring_type: SRNG ring type
  584. * @ring_buf_size: SRNG buffer size
  585. * @htt_tlv_filter: Rx SRNG TLV and filter setting
  586. * Return: 0 on success; error code on failure
  587. */
  588. int htt_h2t_rx_ring_cfg(void *htt_soc, int pdev_id, void *hal_srng,
  589. int hal_ring_type, int ring_buf_size,
  590. struct htt_rx_ring_tlv_filter *htt_tlv_filter)
  591. {
  592. struct htt_soc *soc = (struct htt_soc *)htt_soc;
  593. struct dp_htt_htc_pkt *pkt;
  594. qdf_nbuf_t htt_msg;
  595. uint32_t *msg_word;
  596. struct hal_srng_params srng_params;
  597. uint32_t htt_ring_type, htt_ring_id;
  598. uint32_t tlv_filter;
  599. htt_msg = qdf_nbuf_alloc(soc->osdev,
  600. HTT_MSG_BUF_SIZE(HTT_RX_RING_SELECTION_CFG_SZ),
  601. /* reserve room for the HTC header */
  602. HTC_HEADER_LEN + HTC_HDR_ALIGNMENT_PADDING, 4, TRUE);
  603. if (!htt_msg)
  604. goto fail0;
  605. hal_get_srng_params(soc->hal_soc, hal_srng, &srng_params);
  606. switch (hal_ring_type) {
  607. case RXDMA_BUF:
  608. #if QCA_HOST2FW_RXBUF_RING
  609. htt_ring_id = HTT_HOST1_TO_FW_RXBUF_RING;
  610. htt_ring_type = HTT_SW_TO_SW_RING;
  611. #else
  612. htt_ring_id = HTT_RXDMA_HOST_BUF_RING;
  613. htt_ring_type = HTT_SW_TO_HW_RING;
  614. #endif
  615. break;
  616. case RXDMA_MONITOR_BUF:
  617. htt_ring_id = HTT_RXDMA_MONITOR_BUF_RING;
  618. htt_ring_type = HTT_SW_TO_HW_RING;
  619. break;
  620. case RXDMA_MONITOR_STATUS:
  621. htt_ring_id = HTT_RXDMA_MONITOR_STATUS_RING;
  622. htt_ring_type = HTT_SW_TO_HW_RING;
  623. break;
  624. case RXDMA_MONITOR_DST:
  625. htt_ring_id = HTT_RXDMA_MONITOR_DEST_RING;
  626. htt_ring_type = HTT_HW_TO_SW_RING;
  627. break;
  628. case RXDMA_MONITOR_DESC:
  629. htt_ring_id = HTT_RXDMA_MONITOR_DESC_RING;
  630. htt_ring_type = HTT_SW_TO_HW_RING;
  631. break;
  632. case RXDMA_DST:
  633. htt_ring_id = HTT_RXDMA_NON_MONITOR_DEST_RING;
  634. htt_ring_type = HTT_HW_TO_SW_RING;
  635. break;
  636. default:
  637. QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
  638. "%s: Ring currently not supported\n", __func__);
  639. goto fail1;
  640. }
  641. /*
  642. * Set the length of the message.
  643. * The contribution from the HTC_HDR_ALIGNMENT_PADDING is added
  644. * separately during the below call to qdf_nbuf_push_head.
  645. * The contribution from the HTC header is added separately inside HTC.
  646. */
  647. if (qdf_nbuf_put_tail(htt_msg, HTT_RX_RING_SELECTION_CFG_SZ) == NULL) {
  648. QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
  649. "%s: Failed to expand head for RX Ring Cfg msg\n",
  650. __func__);
  651. goto fail1; /* failure */
  652. }
  653. msg_word = (uint32_t *)qdf_nbuf_data(htt_msg);
  654. /* rewind beyond alignment pad to get to the HTC header reserved area */
  655. qdf_nbuf_push_head(htt_msg, HTC_HDR_ALIGNMENT_PADDING);
  656. /* word 0 */
  657. *msg_word = 0;
  658. HTT_H2T_MSG_TYPE_SET(*msg_word, HTT_H2T_MSG_TYPE_RX_RING_SELECTION_CFG);
  659. /*
  660. * pdev_id is indexed from 0 whereas mac_id is indexed from 1
  661. * SW_TO_SW and SW_TO_HW rings are unaffected by this
  662. */
  663. if (htt_ring_type == HTT_SW_TO_SW_RING ||
  664. htt_ring_type == HTT_SW_TO_HW_RING)
  665. HTT_RX_RING_SELECTION_CFG_PDEV_ID_SET(*msg_word,
  666. DP_SW2HW_MACID(pdev_id));
  667. /* TODO: Discuss with FW on changing this to unique ID and using
  668. * htt_ring_type to send the type of ring
  669. */
  670. HTT_RX_RING_SELECTION_CFG_RING_ID_SET(*msg_word, htt_ring_id);
  671. HTT_RX_RING_SELECTION_CFG_STATUS_TLV_SET(*msg_word,
  672. !!(srng_params.flags & HAL_SRNG_MSI_SWAP));
  673. HTT_RX_RING_SELECTION_CFG_PKT_TLV_SET(*msg_word,
  674. !!(srng_params.flags & HAL_SRNG_DATA_TLV_SWAP));
  675. /* word 1 */
  676. msg_word++;
  677. *msg_word = 0;
  678. HTT_RX_RING_SELECTION_CFG_RING_BUFFER_SIZE_SET(*msg_word,
  679. ring_buf_size);
  680. /* word 2 */
  681. msg_word++;
  682. *msg_word = 0;
  683. if (htt_tlv_filter->enable_fp) {
  684. htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG0, FP,
  685. MGMT, 0000, 1);
  686. htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG0, FP,
  687. MGMT, 0001, 1);
  688. htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG0, FP,
  689. MGMT, 0010, 1);
  690. htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG0, FP,
  691. MGMT, 0011, 1);
  692. htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG0, FP,
  693. MGMT, 0100, 1);
  694. htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG0, FP,
  695. MGMT, 0101, 1);
  696. htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG0, FP,
  697. MGMT, 0110, 1);
  698. htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG0, FP,
  699. MGMT, 0111, 1);
  700. htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG0, FP,
  701. MGMT, 1000, 1);
  702. htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG0, FP,
  703. MGMT, 1001, 1);
  704. }
  705. if (htt_tlv_filter->enable_md) {
  706. htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG0, MD,
  707. MGMT, 0000, 1);
  708. htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG0, MD,
  709. MGMT, 0001, 1);
  710. htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG0, MD,
  711. MGMT, 0010, 1);
  712. htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG0, MD,
  713. MGMT, 0011, 1);
  714. htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG0, MD,
  715. MGMT, 0100, 1);
  716. htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG0, MD,
  717. MGMT, 0101, 1);
  718. htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG0, MD,
  719. MGMT, 0110, 1);
  720. htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG0, MD,
  721. MGMT, 0111, 1);
  722. htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG0, MD,
  723. MGMT, 1000, 1);
  724. htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG0, MD,
  725. MGMT, 1001, 1);
  726. }
  727. if (htt_tlv_filter->enable_mo) {
  728. htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG0, MO,
  729. MGMT, 0000, 1);
  730. htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG0, MO,
  731. MGMT, 0001, 1);
  732. htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG0, MO,
  733. MGMT, 0010, 1);
  734. htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG0, MO,
  735. MGMT, 0011, 1);
  736. htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG0, MO,
  737. MGMT, 0100, 1);
  738. htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG0, MO,
  739. MGMT, 0101, 1);
  740. htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG0, MO,
  741. MGMT, 0110, 1);
  742. htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG0, MO,
  743. MGMT, 0111, 1);
  744. htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG0, MO,
  745. MGMT, 1000, 1);
  746. htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG0, MO,
  747. MGMT, 1001, 1);
  748. }
  749. /* word 3 */
  750. msg_word++;
  751. *msg_word = 0;
  752. if (htt_tlv_filter->enable_fp) {
  753. htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG1, FP,
  754. MGMT, 1010, 1);
  755. htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG1, FP,
  756. MGMT, 1011, 1);
  757. htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG1, FP,
  758. MGMT, 1100, 1);
  759. htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG1, FP,
  760. MGMT, 1101, 1);
  761. htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG1, FP,
  762. MGMT, 1110, 1);
  763. htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG1, FP,
  764. MGMT, 1111, 1);
  765. }
  766. if (htt_tlv_filter->enable_md) {
  767. htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG1, MD,
  768. MGMT, 1010, 1);
  769. htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG1, MD,
  770. MGMT, 1011, 1);
  771. htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG1, MD,
  772. MGMT, 1100, 1);
  773. htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG1, MD,
  774. MGMT, 1101, 1);
  775. htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG1, MD,
  776. MGMT, 1110, 1);
  777. }
  778. if (htt_tlv_filter->enable_mo) {
  779. htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG1, MO,
  780. MGMT, 1010, 1);
  781. htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG1, MO,
  782. MGMT, 1011, 1);
  783. htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG1, MO,
  784. MGMT, 1100, 1);
  785. htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG1, MO,
  786. MGMT, 1101, 1);
  787. htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG1, MO,
  788. MGMT, 1110, 1);
  789. htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG1, MO,
  790. MGMT, 1111, 1);
  791. }
  792. /* word 4 */
  793. msg_word++;
  794. *msg_word = 0;
  795. if (htt_tlv_filter->enable_fp) {
  796. htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG2, FP,
  797. CTRL, 0000, 1);
  798. htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG2, FP,
  799. CTRL, 0001, 1);
  800. htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG2, FP,
  801. CTRL, 0010, 1);
  802. htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG2, FP,
  803. CTRL, 0011, 1);
  804. htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG2, FP,
  805. CTRL, 0100, 1);
  806. htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG2, FP,
  807. CTRL, 0101, 1);
  808. htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG2, FP,
  809. CTRL, 0110, 1);
  810. htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG2, FP,
  811. CTRL, 0111, 1);
  812. htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG2, FP,
  813. CTRL, 1000, 1);
  814. htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG2, FP,
  815. CTRL, 1001, 1);
  816. }
  817. if (htt_tlv_filter->enable_md) {
  818. htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG2, MO,
  819. CTRL, 0000, 1);
  820. htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG2, MO,
  821. CTRL, 0001, 1);
  822. htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG2, MO,
  823. CTRL, 0010, 1);
  824. htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG2, MO,
  825. CTRL, 0011, 1);
  826. htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG2, MO,
  827. CTRL, 0100, 1);
  828. htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG2, MO,
  829. CTRL, 0101, 1);
  830. htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG2, MO,
  831. CTRL, 0110, 1);
  832. htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG2, MD,
  833. CTRL, 0111, 1);
  834. htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG2, MD,
  835. CTRL, 1000, 1);
  836. htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG2, MD,
  837. CTRL, 1001, 1);
  838. }
  839. if (htt_tlv_filter->enable_mo) {
  840. htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG2, MO,
  841. CTRL, 0000, 1);
  842. htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG2, MO,
  843. CTRL, 0001, 1);
  844. htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG2, MO,
  845. CTRL, 0010, 1);
  846. htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG2, MO,
  847. CTRL, 0011, 1);
  848. htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG2, MO,
  849. CTRL, 0100, 1);
  850. htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG2, MO,
  851. CTRL, 0101, 1);
  852. htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG2, MO,
  853. CTRL, 0110, 1);
  854. htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG2, MO,
  855. CTRL, 0111, 1);
  856. htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG2, MO,
  857. CTRL, 1000, 1);
  858. htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG2, MO,
  859. CTRL, 1001, 1);
  860. }
  861. /* word 5 */
  862. msg_word++;
  863. *msg_word = 0;
  864. if (htt_tlv_filter->enable_fp) {
  865. htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG3, FP,
  866. CTRL, 1010, 1);
  867. htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG3, FP,
  868. CTRL, 1011, 1);
  869. htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG3, FP,
  870. CTRL, 1100, 1);
  871. htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG3, FP,
  872. CTRL, 1101, 1);
  873. htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG3, FP,
  874. CTRL, 1110, 1);
  875. htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG3, FP,
  876. CTRL, 1111, 1);
  877. htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG3, FP,
  878. DATA, MCAST, 1);
  879. htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG3, FP,
  880. DATA, UCAST, 1);
  881. htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG3, FP,
  882. DATA, NULL, 1);
  883. }
  884. if (htt_tlv_filter->enable_md) {
  885. htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG3, MD,
  886. CTRL, 1010, 1);
  887. htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG3, MD,
  888. CTRL, 1011, 1);
  889. htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG3, MD,
  890. CTRL, 1100, 1);
  891. htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG3, MD,
  892. CTRL, 1101, 1);
  893. htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG3, MD,
  894. CTRL, 1110, 1);
  895. htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG3, MD,
  896. CTRL, 1111, 1);
  897. htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG3, MD,
  898. DATA, MCAST, 1);
  899. htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG3, MD,
  900. DATA, UCAST, 1);
  901. htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG3, MD,
  902. DATA, NULL, 1);
  903. }
  904. if (htt_tlv_filter->enable_mo) {
  905. htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG3, MO,
  906. CTRL, 1010, 1);
  907. htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG3, MO,
  908. CTRL, 1011, 1);
  909. htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG3, MO,
  910. CTRL, 1100, 1);
  911. htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG3, MO,
  912. CTRL, 1101, 1);
  913. htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG3, MO,
  914. CTRL, 1110, 1);
  915. htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG3, MO,
  916. CTRL, 1111, 1);
  917. htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG3, MO,
  918. DATA, MCAST, 1);
  919. htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG3, MO,
  920. DATA, UCAST, 1);
  921. htt_rx_ring_pkt_enable_subtype_set(*msg_word, FLAG3, MO,
  922. DATA, NULL, 1);
  923. }
  924. /* word 6 */
  925. msg_word++;
  926. *msg_word = 0;
  927. tlv_filter = 0;
  928. htt_rx_ring_tlv_filter_in_enable_set(tlv_filter, MPDU_START,
  929. htt_tlv_filter->mpdu_start);
  930. htt_rx_ring_tlv_filter_in_enable_set(tlv_filter, MSDU_START,
  931. htt_tlv_filter->msdu_start);
  932. htt_rx_ring_tlv_filter_in_enable_set(tlv_filter, PACKET,
  933. htt_tlv_filter->packet);
  934. htt_rx_ring_tlv_filter_in_enable_set(tlv_filter, MSDU_END,
  935. htt_tlv_filter->msdu_end);
  936. htt_rx_ring_tlv_filter_in_enable_set(tlv_filter, MPDU_END,
  937. htt_tlv_filter->mpdu_end);
  938. htt_rx_ring_tlv_filter_in_enable_set(tlv_filter, PACKET_HEADER,
  939. htt_tlv_filter->packet_header);
  940. htt_rx_ring_tlv_filter_in_enable_set(tlv_filter, ATTENTION,
  941. htt_tlv_filter->attention);
  942. htt_rx_ring_tlv_filter_in_enable_set(tlv_filter, PPDU_START,
  943. htt_tlv_filter->ppdu_start);
  944. htt_rx_ring_tlv_filter_in_enable_set(tlv_filter, PPDU_END,
  945. htt_tlv_filter->ppdu_end);
  946. htt_rx_ring_tlv_filter_in_enable_set(tlv_filter, PPDU_END_USER_STATS,
  947. htt_tlv_filter->ppdu_end_user_stats);
  948. htt_rx_ring_tlv_filter_in_enable_set(tlv_filter,
  949. PPDU_END_USER_STATS_EXT,
  950. htt_tlv_filter->ppdu_end_user_stats_ext);
  951. htt_rx_ring_tlv_filter_in_enable_set(tlv_filter, PPDU_END_STATUS_DONE,
  952. htt_tlv_filter->ppdu_end_status_done);
  953. HTT_RX_RING_SELECTION_CFG_TLV_FILTER_IN_FLAG_SET(*msg_word, tlv_filter);
  954. /* "response_required" field should be set if a HTT response message is
  955. * required after setting up the ring.
  956. */
  957. pkt = htt_htc_pkt_alloc(soc);
  958. if (!pkt)
  959. goto fail1;
  960. pkt->soc_ctxt = NULL; /* not used during send-done callback */
  961. SET_HTC_PACKET_INFO_TX(
  962. &pkt->htc_pkt,
  963. dp_htt_h2t_send_complete_free_netbuf,
  964. qdf_nbuf_data(htt_msg),
  965. qdf_nbuf_len(htt_msg),
  966. soc->htc_endpoint,
  967. 1); /* tag - not relevant here */
  968. SET_HTC_PACKET_NET_BUF_CONTEXT(&pkt->htc_pkt, htt_msg);
  969. DP_HTT_SEND_HTC_PKT(soc, pkt);
  970. return QDF_STATUS_SUCCESS;
  971. fail1:
  972. qdf_nbuf_free(htt_msg);
  973. fail0:
  974. return QDF_STATUS_E_FAILURE;
  975. }
  976. /**
  977. * dp_process_htt_stat_msg(): Process the list of buffers of HTT EXT stats
  978. * @htt_stats: htt stats info
  979. *
  980. * The FW sends the HTT EXT STATS as a stream of T2H messages. Each T2H message
  981. * contains sub messages which are identified by a TLV header.
  982. * In this function we will process the stream of T2H messages and read all the
  983. * TLV contained in the message.
  984. *
  985. * THe following cases have been taken care of
  986. * Case 1: When the tlv_remain_length <= msg_remain_length of HTT MSG buffer
  987. * In this case the buffer will contain multiple tlvs.
  988. * Case 2: When the tlv_remain_length > msg_remain_length of HTT MSG buffer.
  989. * Only one tlv will be contained in the HTT message and this tag
  990. * will extend onto the next buffer.
  991. * Case 3: When the buffer is the continuation of the previous message
  992. * Case 4: tlv length is 0. which will indicate the end of message
  993. *
  994. * return: void
  995. */
  996. static inline void dp_process_htt_stat_msg(struct htt_stats_context *htt_stats)
  997. {
  998. htt_tlv_tag_t tlv_type = 0xff;
  999. qdf_nbuf_t htt_msg = NULL;
  1000. uint32_t *msg_word;
  1001. uint8_t *tlv_buf_head = NULL;
  1002. uint8_t *tlv_buf_tail = NULL;
  1003. uint32_t msg_remain_len = 0;
  1004. uint32_t tlv_remain_len = 0;
  1005. uint32_t *tlv_start;
  1006. /* Process node in the HTT message queue */
  1007. while ((htt_msg = qdf_nbuf_queue_remove(&htt_stats->msg))
  1008. != NULL) {
  1009. msg_word = (uint32_t *) qdf_nbuf_data(htt_msg);
  1010. /* read 5th word */
  1011. msg_word = msg_word + 4;
  1012. msg_remain_len = qdf_min(htt_stats->msg_len,
  1013. (uint32_t) DP_EXT_MSG_LENGTH);
  1014. /* Keep processing the node till node length is 0 */
  1015. while (msg_remain_len) {
  1016. /*
  1017. * if message is not a continuation of previous message
  1018. * read the tlv type and tlv length
  1019. */
  1020. if (!tlv_buf_head) {
  1021. tlv_type = HTT_STATS_TLV_TAG_GET(
  1022. *msg_word);
  1023. tlv_remain_len = HTT_STATS_TLV_LENGTH_GET(
  1024. *msg_word);
  1025. }
  1026. if (tlv_remain_len == 0) {
  1027. msg_remain_len = 0;
  1028. if (tlv_buf_head) {
  1029. qdf_mem_free(tlv_buf_head);
  1030. tlv_buf_head = NULL;
  1031. tlv_buf_tail = NULL;
  1032. }
  1033. goto error;
  1034. }
  1035. tlv_remain_len += HTT_TLV_HDR_LEN;
  1036. if ((tlv_remain_len <= msg_remain_len)) {
  1037. /* Case 3 */
  1038. if (tlv_buf_head) {
  1039. qdf_mem_copy(tlv_buf_tail,
  1040. (uint8_t *)msg_word,
  1041. tlv_remain_len);
  1042. tlv_start = (uint32_t *)tlv_buf_head;
  1043. } else {
  1044. /* Case 1 */
  1045. tlv_start = msg_word;
  1046. }
  1047. dp_htt_stats_print_tag(tlv_type, tlv_start);
  1048. msg_remain_len -= tlv_remain_len;
  1049. msg_word = (uint32_t *)
  1050. (((uint8_t *)msg_word) +
  1051. tlv_remain_len);
  1052. tlv_remain_len = 0;
  1053. if (tlv_buf_head) {
  1054. qdf_mem_free(tlv_buf_head);
  1055. tlv_buf_head = NULL;
  1056. tlv_buf_tail = NULL;
  1057. }
  1058. } else { /* tlv_remain_len > msg_remain_len */
  1059. /* Case 2 & 3 */
  1060. if (!tlv_buf_head) {
  1061. tlv_buf_head = qdf_mem_malloc(
  1062. tlv_remain_len);
  1063. if (!tlv_buf_head) {
  1064. QDF_TRACE(QDF_MODULE_ID_TXRX,
  1065. QDF_TRACE_LEVEL_ERROR,
  1066. "Alloc failed");
  1067. goto error;
  1068. }
  1069. tlv_buf_tail = tlv_buf_head;
  1070. }
  1071. qdf_mem_copy(tlv_buf_tail, (uint8_t *)msg_word,
  1072. msg_remain_len);
  1073. tlv_remain_len -= msg_remain_len;
  1074. tlv_buf_tail += msg_remain_len;
  1075. msg_remain_len = 0;
  1076. }
  1077. }
  1078. if (htt_stats->msg_len >= DP_EXT_MSG_LENGTH) {
  1079. htt_stats->msg_len -= DP_EXT_MSG_LENGTH;
  1080. }
  1081. qdf_nbuf_free(htt_msg);
  1082. }
  1083. return;
  1084. error:
  1085. qdf_nbuf_free(htt_msg);
  1086. while ((htt_msg = qdf_nbuf_queue_remove(&htt_stats->msg))
  1087. != NULL)
  1088. qdf_nbuf_free(htt_msg);
  1089. }
  1090. void htt_t2h_stats_handler(void *context)
  1091. {
  1092. struct dp_soc *soc = (struct dp_soc *)context;
  1093. struct htt_stats_context htt_stats;
  1094. uint32_t length;
  1095. uint32_t *msg_word;
  1096. qdf_nbuf_t htt_msg = NULL;
  1097. uint8_t done;
  1098. uint8_t rem_stats;
  1099. if (!soc || !qdf_atomic_read(&soc->cmn_init_done)) {
  1100. QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
  1101. "soc: 0x%p, init_done: %d", soc,
  1102. qdf_atomic_read(&soc->cmn_init_done));
  1103. return;
  1104. }
  1105. qdf_mem_zero(&htt_stats, sizeof(htt_stats));
  1106. qdf_nbuf_queue_init(&htt_stats.msg);
  1107. /* pull one completed stats from soc->htt_stats_msg and process */
  1108. qdf_spin_lock_bh(&soc->htt_stats.lock);
  1109. if (!soc->htt_stats.num_stats) {
  1110. qdf_spin_unlock_bh(&soc->htt_stats.lock);
  1111. return;
  1112. }
  1113. while ((htt_msg = qdf_nbuf_queue_remove(&soc->htt_stats.msg)) != NULL) {
  1114. msg_word = (uint32_t *) qdf_nbuf_data(htt_msg);
  1115. msg_word = msg_word + HTT_T2H_EXT_STATS_TLV_START_OFFSET;
  1116. length = HTT_T2H_EXT_STATS_CONF_TLV_LENGTH_GET(*msg_word);
  1117. done = HTT_T2H_EXT_STATS_CONF_TLV_DONE_GET(*msg_word);
  1118. qdf_nbuf_queue_add(&htt_stats.msg, htt_msg);
  1119. /*
  1120. * HTT EXT stats response comes as stream of TLVs which span over
  1121. * multiple T2H messages.
  1122. * The first message will carry length of the response.
  1123. * For rest of the messages length will be zero.
  1124. */
  1125. if (length)
  1126. htt_stats.msg_len = length;
  1127. /*
  1128. * Done bit signifies that this is the last T2H buffer in the
  1129. * stream of HTT EXT STATS message
  1130. */
  1131. if (done)
  1132. break;
  1133. }
  1134. rem_stats = --soc->htt_stats.num_stats;
  1135. qdf_spin_unlock_bh(&soc->htt_stats.lock);
  1136. dp_process_htt_stat_msg(&htt_stats);
  1137. /* If there are more stats to process, schedule stats work again */
  1138. if (rem_stats)
  1139. qdf_sched_work(0, &soc->htt_stats.work);
  1140. }
  1141. /*
  1142. * dp_get_ppdu_info_user_index: Find place holder for the received
  1143. * ppdu stats info
  1144. * pdev: DP pdev handle
  1145. *
  1146. * return:user index to be populated
  1147. */
  1148. #ifdef FEATURE_PERPKT_INFO
  1149. static uint8_t dp_get_ppdu_info_user_index(struct dp_pdev *pdev,
  1150. uint32_t peer_id)
  1151. {
  1152. uint8_t user_index = 0;
  1153. struct cdp_tx_completion_ppdu *ppdu_desc;
  1154. struct cdp_tx_completion_ppdu_user *ppdu_user_desc;
  1155. ppdu_desc =
  1156. (struct cdp_tx_completion_ppdu *)qdf_nbuf_data(pdev->tx_ppdu_info.buf);
  1157. while ((user_index + 1) <= pdev->tx_ppdu_info.last_user) {
  1158. ppdu_user_desc = &ppdu_desc->user[user_index];
  1159. if (ppdu_user_desc->peer_id != peer_id) {
  1160. user_index++;
  1161. continue;
  1162. } else {
  1163. return user_index;
  1164. }
  1165. }
  1166. pdev->tx_ppdu_info.last_user++;
  1167. return pdev->tx_ppdu_info.last_user - 1;
  1168. }
  1169. #endif
  1170. /*
  1171. * dp_process_ppdu_stats_common_tlv: Process htt_ppdu_stats_common_tlv
  1172. * pdev: DP pdev handle
  1173. * @tag_buf: buffer containing the tlv htt_ppdu_stats_common_tlv
  1174. *
  1175. * return:void
  1176. */
  1177. #ifdef FEATURE_PERPKT_INFO
  1178. static void dp_process_ppdu_stats_common_tlv(struct dp_pdev *pdev,
  1179. uint32_t *tag_buf)
  1180. {
  1181. struct cdp_tx_completion_ppdu *ppdu_desc;
  1182. htt_ppdu_stats_common_tlv *dp_stats_buf =
  1183. (htt_ppdu_stats_common_tlv *)tag_buf;
  1184. ppdu_desc =
  1185. (struct cdp_tx_completion_ppdu *)qdf_nbuf_data(pdev->tx_ppdu_info.buf);
  1186. ppdu_desc->ppdu_id = dp_stats_buf->ppdu_id;
  1187. tag_buf += 2;
  1188. ppdu_desc->num_users =
  1189. HTT_PPDU_STATS_COMMON_TLV_NUM_USERS_GET(*tag_buf);
  1190. tag_buf++;
  1191. ppdu_desc->frame_type =
  1192. HTT_PPDU_STATS_COMMON_TLV_FRM_TYPE_GET(*tag_buf);
  1193. ppdu_desc->ppdu_start_timestamp = dp_stats_buf->ppdu_start_tstmp_us;
  1194. ppdu_desc->ppdu_end_timestamp = 0; /*TODO: value to be provided by FW */
  1195. tag_buf += 6;
  1196. ppdu_desc->channel = HTT_PPDU_STATS_COMMON_TLV_CHAN_MHZ_GET(*tag_buf);
  1197. ppdu_desc->phy_mode = HTT_PPDU_STATS_COMMON_TLV_PHY_MODE_GET(*tag_buf);
  1198. }
  1199. #endif
  1200. /*
  1201. * dp_process_ppdu_stats_user_common_tlv: Process ppdu_stats_user_common
  1202. * @tag_buf: buffer containing the tlv htt_ppdu_stats_user_common_tlv
  1203. *
  1204. * return:void
  1205. */
  1206. #ifdef FEATURE_PERPKT_INFO
  1207. static void dp_process_ppdu_stats_user_common_tlv(
  1208. struct dp_pdev *pdev, uint32_t *tag_buf)
  1209. {
  1210. uint32_t peer_id;
  1211. struct dp_peer *peer;
  1212. struct cdp_tx_completion_ppdu *ppdu_desc;
  1213. struct cdp_tx_completion_ppdu_user *ppdu_user_desc;
  1214. uint8_t curr_user_index = 0;
  1215. ppdu_desc =
  1216. (struct cdp_tx_completion_ppdu *) qdf_nbuf_data(pdev->tx_ppdu_info.buf);
  1217. tag_buf++;
  1218. peer_id = HTT_PPDU_STATS_USER_COMMON_TLV_SW_PEER_ID_GET(*tag_buf);
  1219. peer = dp_peer_find_by_id(pdev->soc, peer_id);
  1220. if (!peer)
  1221. return;
  1222. curr_user_index = dp_get_ppdu_info_user_index(pdev, peer_id);
  1223. ppdu_user_desc = &ppdu_desc->user[curr_user_index];
  1224. ppdu_user_desc->peer_id = peer_id;
  1225. tag_buf++;
  1226. if (HTT_PPDU_STATS_USER_COMMON_TLV_MCAST_GET(*tag_buf))
  1227. ppdu_user_desc->mpdu_tried_mcast =
  1228. HTT_PPDU_STATS_USER_COMMON_TLV_MPDUS_TRIED_GET(*tag_buf);
  1229. else
  1230. ppdu_user_desc->mpdu_tried_ucast =
  1231. HTT_PPDU_STATS_USER_COMMON_TLV_MPDUS_TRIED_GET(*tag_buf);
  1232. ppdu_user_desc->qos_ctrl =
  1233. HTT_PPDU_STATS_USER_COMMON_TLV_QOS_CTRL_GET(*tag_buf);
  1234. ppdu_user_desc->frame_ctrl =
  1235. HTT_PPDU_STATS_USER_COMMON_TLV_FRAME_CTRL_GET(*tag_buf);
  1236. }
  1237. #endif
  1238. /**
  1239. * dp_process_ppdu_stats_user_rate_tlv() - Process htt_ppdu_stats_user_rate_tlv
  1240. * @pdev: DP pdev handle
  1241. * @tag_buf: T2H message buffer carrying the user rate TLV
  1242. *
  1243. * return:void
  1244. */
  1245. #ifdef FEATURE_PERPKT_INFO
  1246. static void dp_process_ppdu_stats_user_rate_tlv(struct dp_pdev *pdev,
  1247. uint32_t *tag_buf)
  1248. {
  1249. uint32_t peer_id;
  1250. struct dp_peer *peer;
  1251. struct cdp_tx_completion_ppdu *ppdu_desc;
  1252. struct cdp_tx_completion_ppdu_user *ppdu_user_desc;
  1253. uint8_t curr_user_index = 0;
  1254. ppdu_desc =
  1255. (struct cdp_tx_completion_ppdu *) qdf_nbuf_data(pdev->tx_ppdu_info.buf);
  1256. tag_buf++;
  1257. peer_id = HTT_PPDU_STATS_USER_RATE_TLV_SW_PEER_ID_GET(*tag_buf);
  1258. peer = dp_peer_find_by_id(pdev->soc, peer_id);
  1259. if (!peer)
  1260. return;
  1261. curr_user_index = dp_get_ppdu_info_user_index(pdev, peer_id);
  1262. ppdu_user_desc = &ppdu_desc->user[curr_user_index];
  1263. ppdu_user_desc->peer_id = peer_id;
  1264. ppdu_user_desc->tid =
  1265. HTT_PPDU_STATS_USER_RATE_TLV_TID_NUM_GET(*tag_buf);
  1266. ppdu_user_desc->peer_id =
  1267. HTT_PPDU_STATS_USER_RATE_TLV_SW_PEER_ID_GET(*tag_buf);
  1268. qdf_mem_copy(ppdu_user_desc->mac_addr, peer->mac_addr.raw,
  1269. DP_MAC_ADDR_LEN);
  1270. tag_buf += 5;
  1271. ppdu_user_desc->ltf_size =
  1272. HTT_PPDU_STATS_USER_RATE_TLV_LTF_SIZE_GET(*tag_buf);
  1273. ppdu_user_desc->stbc =
  1274. HTT_PPDU_STATS_USER_RATE_TLV_STBC_GET(*tag_buf);
  1275. ppdu_user_desc->he_re =
  1276. HTT_PPDU_STATS_USER_RATE_TLV_HE_RE_GET(*tag_buf);
  1277. ppdu_user_desc->txbf =
  1278. HTT_PPDU_STATS_USER_RATE_TLV_TXBF_GET(*tag_buf);
  1279. ppdu_user_desc->bw =
  1280. HTT_PPDU_STATS_USER_RATE_TLV_BW_GET(*tag_buf);
  1281. ppdu_user_desc->nss = HTT_PPDU_STATS_USER_RATE_TLV_NSS_GET(*tag_buf);
  1282. ppdu_user_desc->mcs = HTT_PPDU_STATS_USER_RATE_TLV_MCS_GET(*tag_buf);
  1283. ppdu_user_desc->preamble =
  1284. HTT_PPDU_STATS_USER_RATE_TLV_PREAMBLE_GET(*tag_buf);
  1285. ppdu_user_desc->gi = HTT_PPDU_STATS_USER_RATE_TLV_GI_GET(*tag_buf);
  1286. ppdu_user_desc->dcm = HTT_PPDU_STATS_USER_RATE_TLV_DCM_GET(*tag_buf);
  1287. ppdu_user_desc->ldpc = HTT_PPDU_STATS_USER_RATE_TLV_LDPC_GET(*tag_buf);
  1288. ppdu_user_desc->ppdu_type =
  1289. HTT_PPDU_STATS_USER_RATE_TLV_PPDU_TYPE_GET(*tag_buf);
  1290. }
  1291. #endif
  1292. /*
  1293. * dp_process_ppdu_stats_enq_mpdu_bitmap_64_tlv: Process
  1294. * htt_ppdu_stats_enq_mpdu_bitmap_64_tlv
  1295. * soc: DP SOC handle
  1296. * @tag_buf: buffer containing the tlv htt_ppdu_stats_enq_mpdu_bitmap_64_tlv
  1297. *
  1298. * return:void
  1299. */
  1300. #ifdef FEATURE_PERPKT_INFO
  1301. static void dp_process_ppdu_stats_enq_mpdu_bitmap_64_tlv(
  1302. struct dp_pdev *pdev, uint32_t *tag_buf)
  1303. {
  1304. htt_ppdu_stats_enq_mpdu_bitmap_64_tlv *dp_stats_buf =
  1305. (htt_ppdu_stats_enq_mpdu_bitmap_64_tlv *)tag_buf;
  1306. struct cdp_tx_completion_ppdu *ppdu_desc;
  1307. struct cdp_tx_completion_ppdu_user *ppdu_user_desc;
  1308. uint8_t curr_user_index = 0;
  1309. uint32_t peer_id;
  1310. struct dp_peer *peer;
  1311. ppdu_desc =
  1312. (struct cdp_tx_completion_ppdu *)qdf_nbuf_data(pdev->tx_ppdu_info.buf);
  1313. tag_buf++;
  1314. peer_id =
  1315. HTT_PPDU_STATS_USER_CMPLTN_BA_BITMAP_TLV_SW_PEER_ID_GET(*tag_buf);
  1316. peer = dp_peer_find_by_id(pdev->soc, peer_id);
  1317. if (!peer)
  1318. return;
  1319. curr_user_index = dp_get_ppdu_info_user_index(pdev, peer_id);
  1320. ppdu_user_desc = &ppdu_desc->user[curr_user_index];
  1321. ppdu_user_desc->start_seq = dp_stats_buf->start_seq;
  1322. qdf_mem_copy(&ppdu_user_desc->enq_bitmap, &dp_stats_buf->enq_bitmap,
  1323. CDP_BA_64_BIT_MAP_SIZE_DWORDS);
  1324. }
  1325. #endif
  1326. /*
  1327. * dp_process_ppdu_stats_enq_mpdu_bitmap_256_tlv: Process
  1328. * htt_ppdu_stats_enq_mpdu_bitmap_256_tlv
  1329. * soc: DP SOC handle
  1330. * @tag_buf: buffer containing the tlv htt_ppdu_stats_enq_mpdu_bitmap_256_tlv
  1331. *
  1332. * return:void
  1333. */
  1334. #ifdef FEATURE_PERPKT_INFO
  1335. static void dp_process_ppdu_stats_enq_mpdu_bitmap_256_tlv(
  1336. struct dp_pdev *pdev, uint32_t *tag_buf)
  1337. {
  1338. htt_ppdu_stats_enq_mpdu_bitmap_256_tlv *dp_stats_buf =
  1339. (htt_ppdu_stats_enq_mpdu_bitmap_256_tlv *)tag_buf;
  1340. struct cdp_tx_completion_ppdu *ppdu_desc;
  1341. struct cdp_tx_completion_ppdu_user *ppdu_user_desc;
  1342. uint8_t curr_user_index = 0;
  1343. uint32_t peer_id;
  1344. struct dp_peer *peer;
  1345. ppdu_desc =
  1346. (struct cdp_tx_completion_ppdu *)qdf_nbuf_data(pdev->tx_ppdu_info.buf);
  1347. tag_buf++;
  1348. peer_id =
  1349. HTT_PPDU_STATS_USER_CMPLTN_BA_BITMAP_TLV_SW_PEER_ID_GET(*tag_buf);
  1350. peer = dp_peer_find_by_id(pdev->soc, peer_id);
  1351. if (!peer)
  1352. return;
  1353. curr_user_index = dp_get_ppdu_info_user_index(pdev, peer_id);
  1354. ppdu_user_desc = &ppdu_desc->user[curr_user_index];
  1355. ppdu_user_desc->start_seq = dp_stats_buf->start_seq;
  1356. qdf_mem_copy(&ppdu_user_desc->enq_bitmap, &dp_stats_buf->enq_bitmap,
  1357. CDP_BA_256_BIT_MAP_SIZE_DWORDS);
  1358. }
  1359. #endif
  1360. /*
  1361. * dp_process_ppdu_stats_user_cmpltn_common_tlv: Process
  1362. * htt_ppdu_stats_user_cmpltn_common_tlv
  1363. * soc: DP SOC handle
  1364. * @tag_buf: buffer containing the tlv htt_ppdu_stats_user_cmpltn_common_tlv
  1365. *
  1366. * return:void
  1367. */
  1368. #ifdef FEATURE_PERPKT_INFO
  1369. static void dp_process_ppdu_stats_user_cmpltn_common_tlv(
  1370. struct dp_pdev *pdev, uint32_t *tag_buf)
  1371. {
  1372. uint32_t peer_id;
  1373. struct dp_peer *peer;
  1374. struct cdp_tx_completion_ppdu *ppdu_desc;
  1375. struct cdp_tx_completion_ppdu_user *ppdu_user_desc;
  1376. uint8_t curr_user_index = 0;
  1377. htt_ppdu_stats_user_cmpltn_common_tlv *dp_stats_buf =
  1378. (htt_ppdu_stats_user_cmpltn_common_tlv *)tag_buf;
  1379. ppdu_desc =
  1380. (struct cdp_tx_completion_ppdu *)qdf_nbuf_data(pdev->tx_ppdu_info.buf);
  1381. tag_buf++;
  1382. peer_id =
  1383. HTT_PPDU_STATS_USER_CMPLTN_COMMON_TLV_SW_PEER_ID_GET(*tag_buf);
  1384. peer = dp_peer_find_by_id(pdev->soc, peer_id);
  1385. if (!peer)
  1386. return;
  1387. curr_user_index = dp_get_ppdu_info_user_index(pdev, peer_id);
  1388. ppdu_user_desc = &ppdu_desc->user[curr_user_index];
  1389. ppdu_user_desc->peer_id = peer_id;
  1390. ppdu_user_desc->completion_status =
  1391. HTT_PPDU_STATS_USER_CMPLTN_COMMON_TLV_COMPLETION_STATUS_GET(
  1392. *tag_buf);
  1393. ppdu_user_desc->tid =
  1394. HTT_PPDU_STATS_USER_CMPLTN_COMMON_TLV_TID_NUM_GET(*tag_buf);
  1395. tag_buf++;
  1396. ppdu_desc->ack_rssi = dp_stats_buf->ack_rssi;
  1397. tag_buf++;
  1398. ppdu_user_desc->mpdu_success =
  1399. HTT_PPDU_STATS_USER_CMPLTN_COMMON_TLV_MPDU_SUCCESS_GET(*tag_buf);
  1400. tag_buf++;
  1401. ppdu_user_desc->long_retries =
  1402. HTT_PPDU_STATS_USER_CMPLTN_COMMON_TLV_LONG_RETRY_GET(*tag_buf);
  1403. ppdu_user_desc->short_retries =
  1404. HTT_PPDU_STATS_USER_CMPLTN_COMMON_TLV_SHORT_RETRY_GET(*tag_buf);
  1405. ppdu_user_desc->is_ampdu =
  1406. HTT_PPDU_STATS_USER_CMPLTN_COMMON_TLV_IS_AMPDU_GET(*tag_buf);
  1407. }
  1408. #endif
  1409. /*
  1410. * dp_process_ppdu_stats_user_compltn_ba_bitmap_64_tlv: Process
  1411. * htt_ppdu_stats_user_compltn_ba_bitmap_64_tlv
  1412. * soc: DP SOC handle
  1413. * @tag_buf: buffer containing the htt_ppdu_stats_user_compltn_ba_bitmap_64_tlv
  1414. *
  1415. * return:void
  1416. */
  1417. #ifdef FEATURE_PERPKT_INFO
  1418. static void dp_process_ppdu_stats_user_compltn_ba_bitmap_64_tlv(
  1419. struct dp_pdev *pdev, uint32_t *tag_buf)
  1420. {
  1421. htt_ppdu_stats_user_compltn_ba_bitmap_64_tlv *dp_stats_buf =
  1422. (htt_ppdu_stats_user_compltn_ba_bitmap_64_tlv *)tag_buf;
  1423. struct cdp_tx_completion_ppdu_user *ppdu_user_desc;
  1424. struct cdp_tx_completion_ppdu *ppdu_desc;
  1425. uint8_t curr_user_index = 0;
  1426. uint32_t peer_id;
  1427. struct dp_peer *peer;
  1428. ppdu_desc =
  1429. (struct cdp_tx_completion_ppdu *)qdf_nbuf_data(pdev->tx_ppdu_info.buf);
  1430. tag_buf++;
  1431. peer_id =
  1432. HTT_PPDU_STATS_USER_CMPLTN_BA_BITMAP_TLV_SW_PEER_ID_GET(*tag_buf);
  1433. peer = dp_peer_find_by_id(pdev->soc, peer_id);
  1434. if (!peer)
  1435. return;
  1436. curr_user_index = dp_get_ppdu_info_user_index(pdev, peer_id);
  1437. ppdu_user_desc = &ppdu_desc->user[curr_user_index];
  1438. ppdu_user_desc->ba_seq_no = dp_stats_buf->ba_seq_no;
  1439. qdf_mem_copy(&ppdu_user_desc->ba_bitmap, &dp_stats_buf->ba_bitmap,
  1440. CDP_BA_64_BIT_MAP_SIZE_DWORDS);
  1441. }
  1442. #endif
  1443. /*
  1444. * dp_process_ppdu_stats_user_compltn_ba_bitmap_256_tlv: Process
  1445. * htt_ppdu_stats_user_compltn_ba_bitmap_256_tlv
  1446. * soc: DP SOC handle
  1447. * @tag_buf: buffer containing the htt_ppdu_stats_user_compltn_ba_bitmap_256_tlv
  1448. *
  1449. * return:void
  1450. */
  1451. #ifdef FEATURE_PERPKT_INFO
  1452. static void dp_process_ppdu_stats_user_compltn_ba_bitmap_256_tlv(
  1453. struct dp_pdev *pdev, uint32_t *tag_buf)
  1454. {
  1455. htt_ppdu_stats_user_compltn_ba_bitmap_256_tlv *dp_stats_buf =
  1456. (htt_ppdu_stats_user_compltn_ba_bitmap_256_tlv *)tag_buf;
  1457. struct cdp_tx_completion_ppdu_user *ppdu_user_desc;
  1458. struct cdp_tx_completion_ppdu *ppdu_desc;
  1459. uint8_t curr_user_index = 0;
  1460. uint32_t peer_id;
  1461. struct dp_peer *peer;
  1462. ppdu_desc =
  1463. (struct cdp_tx_completion_ppdu *)qdf_nbuf_data(pdev->tx_ppdu_info.buf);
  1464. tag_buf++;
  1465. peer_id =
  1466. HTT_PPDU_STATS_USER_CMPLTN_BA_BITMAP_TLV_SW_PEER_ID_GET(*tag_buf);
  1467. peer = dp_peer_find_by_id(pdev->soc, peer_id);
  1468. if (!peer)
  1469. return;
  1470. curr_user_index = dp_get_ppdu_info_user_index(pdev, peer_id);
  1471. ppdu_user_desc = &ppdu_desc->user[curr_user_index];
  1472. ppdu_user_desc->ba_seq_no = dp_stats_buf->ba_seq_no;
  1473. qdf_mem_copy(&ppdu_user_desc->ba_bitmap, &dp_stats_buf->ba_bitmap,
  1474. CDP_BA_256_BIT_MAP_SIZE_DWORDS);
  1475. }
  1476. #endif
  1477. /*
  1478. * dp_process_ppdu_stats_user_compltn_ack_ba_status_tlv: Process
  1479. * htt_ppdu_stats_user_compltn_ack_ba_status_tlv
  1480. * soc: DP SOC handle
  1481. * @tag_buf: buffer containing the htt_ppdu_stats_user_compltn_ack_ba_status_tlv
  1482. *
  1483. * return:void
  1484. */
  1485. #ifdef FEATURE_PERPKT_INFO
  1486. static void dp_process_ppdu_stats_user_compltn_ack_ba_status_tlv(
  1487. struct dp_pdev *pdev, uint32_t *tag_buf)
  1488. {
  1489. uint32_t peer_id;
  1490. struct dp_peer *peer;
  1491. struct cdp_tx_completion_ppdu *ppdu_desc;
  1492. struct cdp_tx_completion_ppdu_user *ppdu_user_desc;
  1493. uint8_t curr_user_index = 0;
  1494. ppdu_desc =
  1495. (struct cdp_tx_completion_ppdu *)qdf_nbuf_data(pdev->tx_ppdu_info.buf);
  1496. tag_buf += 2;
  1497. peer_id =
  1498. HTT_PPDU_STATS_USER_CMPLTN_ACK_BA_STATUS_TLV_SW_PEER_ID_GET(*tag_buf);
  1499. peer = dp_peer_find_by_id(pdev->soc, peer_id);
  1500. if (!peer)
  1501. return;
  1502. curr_user_index = dp_get_ppdu_info_user_index(pdev, peer_id);
  1503. ppdu_user_desc = &ppdu_desc->user[curr_user_index];
  1504. tag_buf += 2;
  1505. ppdu_user_desc->num_mpdu =
  1506. HTT_PPDU_STATS_USER_CMPLTN_ACK_BA_STATUS_TLV_NUM_MPDU_GET(*tag_buf);
  1507. ppdu_user_desc->num_msdu =
  1508. HTT_PPDU_STATS_USER_CMPLTN_ACK_BA_STATUS_TLV_NUM_MSDU_GET(*tag_buf);
  1509. }
  1510. #endif
  1511. /**
  1512. * dp_process_ppdu_tag(): Function to process the PPDU TLVs
  1513. * @soc: DP Physical device (radio) handle
  1514. * @tag_buf: TLV buffer
  1515. *
  1516. * return: void
  1517. */
  1518. #ifdef FEATURE_PERPKT_INFO
  1519. static void dp_process_ppdu_tag(struct dp_pdev *pdev, uint32_t *tag_buf,
  1520. uint32_t tlv_len)
  1521. {
  1522. uint32_t tlv_type = HTT_STATS_TLV_TAG_GET(*tag_buf);
  1523. switch (tlv_type) {
  1524. case HTT_PPDU_STATS_COMMON_TLV:
  1525. dp_process_ppdu_stats_common_tlv(pdev, tag_buf);
  1526. break;
  1527. case HTT_PPDU_STATS_USR_COMMON_TLV:
  1528. dp_process_ppdu_stats_user_common_tlv(pdev, tag_buf);
  1529. break;
  1530. case HTT_PPDU_STATS_USR_RATE_TLV:
  1531. qdf_assert_always(tlv_len ==
  1532. sizeof(htt_ppdu_stats_user_rate_tlv));
  1533. dp_process_ppdu_stats_user_rate_tlv(pdev, tag_buf);
  1534. break;
  1535. case HTT_PPDU_STATS_USR_MPDU_ENQ_BITMAP_64_TLV:
  1536. dp_process_ppdu_stats_enq_mpdu_bitmap_64_tlv(pdev, tag_buf);
  1537. break;
  1538. case HTT_PPDU_STATS_USR_MPDU_ENQ_BITMAP_256_TLV:
  1539. dp_process_ppdu_stats_enq_mpdu_bitmap_256_tlv(pdev, tag_buf);
  1540. break;
  1541. case HTT_PPDU_STATS_USR_COMPLTN_COMMON_TLV:
  1542. dp_process_ppdu_stats_user_cmpltn_common_tlv(pdev, tag_buf);
  1543. break;
  1544. case HTT_PPDU_STATS_USR_COMPLTN_BA_BITMAP_64_TLV:
  1545. dp_process_ppdu_stats_user_compltn_ba_bitmap_64_tlv(pdev,
  1546. tag_buf);
  1547. break;
  1548. case HTT_PPDU_STATS_USR_COMPLTN_BA_BITMAP_256_TLV:
  1549. dp_process_ppdu_stats_user_compltn_ba_bitmap_256_tlv(pdev,
  1550. tag_buf);
  1551. break;
  1552. case HTT_PPDU_STATS_USR_COMPLTN_ACK_BA_STATUS_TLV:
  1553. dp_process_ppdu_stats_user_compltn_ack_ba_status_tlv(pdev,
  1554. tag_buf);
  1555. break;
  1556. default:
  1557. break;
  1558. }
  1559. }
  1560. #endif
  1561. #ifdef FEATURE_PERPKT_INFO
  1562. static QDF_STATUS dp_htt_process_tlv(struct dp_pdev *pdev,
  1563. qdf_nbuf_t htt_t2h_msg)
  1564. {
  1565. uint32_t length;
  1566. uint32_t ppdu_id;
  1567. uint8_t tlv_type;
  1568. uint32_t tlv_length;
  1569. uint8_t *tlv_buf;
  1570. QDF_STATUS status = QDF_STATUS_E_PENDING;
  1571. uint32_t *msg_word = (uint32_t *) qdf_nbuf_data(htt_t2h_msg);
  1572. length = HTT_T2H_PPDU_STATS_PAYLOAD_SIZE_GET(*msg_word);
  1573. msg_word = msg_word + 1;
  1574. ppdu_id = HTT_T2H_PPDU_STATS_PPDU_ID_GET(*msg_word);
  1575. msg_word = msg_word + 3;
  1576. while (length > 0) {
  1577. tlv_buf = (uint8_t *)msg_word;
  1578. tlv_type = HTT_STATS_TLV_TAG_GET(*msg_word);
  1579. tlv_length = HTT_STATS_TLV_LENGTH_GET(*msg_word);
  1580. QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_DEBUG,
  1581. "HTT PPDU Tag %d, Length %d", tlv_type,
  1582. tlv_length);
  1583. if (tlv_length == 0)
  1584. break;
  1585. if (tlv_type == HTT_PPDU_STATS_SCH_CMD_STATUS_TLV)
  1586. status = QDF_STATUS_SUCCESS;
  1587. tlv_length += HTT_TLV_HDR_LEN;
  1588. dp_process_ppdu_tag(pdev, msg_word, tlv_length);
  1589. msg_word = (uint32_t *)((uint8_t *)tlv_buf + tlv_length);
  1590. length -= (tlv_length);
  1591. }
  1592. return status;
  1593. }
  1594. #endif
  1595. /**
  1596. * dp_txrx_ppdu_stats_handler() - Function to process HTT PPDU stats from FW
  1597. * @soc: DP SOC handle
  1598. * @pdev_id: pdev id
  1599. * @htt_t2h_msg: HTT message nbuf
  1600. *
  1601. * return:void
  1602. */
  1603. #if defined(CONFIG_WIN) && WDI_EVENT_ENABLE
  1604. #ifdef FEATURE_PERPKT_INFO
  1605. static void dp_txrx_ppdu_stats_handler(struct dp_soc *soc,
  1606. uint8_t pdev_id, qdf_nbuf_t htt_t2h_msg)
  1607. {
  1608. struct dp_pdev *pdev = soc->pdev_list[pdev_id];
  1609. struct dp_vdev *vdev;
  1610. struct dp_peer *peer;
  1611. struct cdp_tx_completion_ppdu *ppdu_desc;
  1612. int status;
  1613. int i;
  1614. if (!pdev->enhanced_stats_en)
  1615. return;
  1616. if (!pdev->tx_ppdu_info.buf) {
  1617. /*
  1618. * Todo: For MU/OFDMA, we need to account for multiple user
  1619. * descriptors in a PPDU, in skb size.
  1620. * The allocation has to be moved to ppdu_cmn tlv processing
  1621. */
  1622. pdev->tx_ppdu_info.buf = qdf_nbuf_alloc(soc->osdev,
  1623. sizeof(struct cdp_tx_completion_ppdu), 0, 4,
  1624. TRUE);
  1625. if (!pdev->tx_ppdu_info.buf) {
  1626. QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
  1627. "Nbuf Allocation failed for HTT PPDU");
  1628. return;
  1629. }
  1630. if (qdf_nbuf_put_tail(pdev->tx_ppdu_info.buf,
  1631. sizeof(struct cdp_tx_completion_ppdu)) == NULL) {
  1632. QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
  1633. "No tailroom for HTT PPDU");
  1634. return;
  1635. }
  1636. }
  1637. status = dp_htt_process_tlv(pdev, htt_t2h_msg);
  1638. if (status == QDF_STATUS_SUCCESS) {
  1639. ppdu_desc = (struct cdp_tx_completion_ppdu *)
  1640. qdf_nbuf_data(pdev->tx_ppdu_info.buf);
  1641. vdev = dp_get_vdev_from_soc_vdev_id_wifi3(soc,
  1642. ppdu_desc->vdev_id);
  1643. for (i = 0; i < ppdu_desc->num_users; i++) {
  1644. peer = dp_peer_find_by_id(soc,
  1645. ppdu_desc->user[i].peer_id);
  1646. dp_tx_stats_update(soc, peer, &ppdu_desc->user[i],
  1647. ppdu_desc->ack_rssi);
  1648. }
  1649. dp_wdi_event_handler(WDI_EVENT_TX_PPDU_DESC, soc,
  1650. pdev->tx_ppdu_info.buf, HTT_INVALID_PEER,
  1651. WDI_NO_VAL, pdev_id);
  1652. pdev->tx_ppdu_info.buf = NULL;
  1653. pdev->tx_ppdu_info.last_user = 0;
  1654. }
  1655. }
  1656. #else
  1657. static void dp_txrx_ppdu_stats_handler(struct dp_soc *soc,
  1658. uint8_t pdev_id, qdf_nbuf_t htt_t2h_msg)
  1659. {
  1660. }
  1661. #endif
  1662. #endif
  1663. /**
  1664. * dp_txrx_fw_stats_handler() - Function to process HTT EXT stats
  1665. * @soc: DP SOC handle
  1666. * @htt_t2h_msg: HTT message nbuf
  1667. *
  1668. * return:void
  1669. */
  1670. static inline void dp_txrx_fw_stats_handler(struct dp_soc *soc,
  1671. qdf_nbuf_t htt_t2h_msg)
  1672. {
  1673. uint8_t done;
  1674. qdf_nbuf_t msg_copy;
  1675. uint32_t *msg_word;
  1676. msg_word = (uint32_t *) qdf_nbuf_data(htt_t2h_msg);
  1677. msg_word = msg_word + 3;
  1678. done = HTT_T2H_EXT_STATS_CONF_TLV_DONE_GET(*msg_word);
  1679. /*
  1680. * HTT EXT stats response comes as stream of TLVs which span over
  1681. * multiple T2H messages.
  1682. * The first message will carry length of the response.
  1683. * For rest of the messages length will be zero.
  1684. *
  1685. * Clone the T2H message buffer and store it in a list to process
  1686. * it later.
  1687. *
  1688. * The original T2H message buffers gets freed in the T2H HTT event
  1689. * handler
  1690. */
  1691. msg_copy = qdf_nbuf_clone(htt_t2h_msg);
  1692. if (!msg_copy) {
  1693. QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_INFO,
  1694. "T2H messge clone failed for HTT EXT STATS");
  1695. goto error;
  1696. }
  1697. qdf_spin_lock_bh(&soc->htt_stats.lock);
  1698. qdf_nbuf_queue_add(&soc->htt_stats.msg, msg_copy);
  1699. /*
  1700. * Done bit signifies that this is the last T2H buffer in the stream of
  1701. * HTT EXT STATS message
  1702. */
  1703. if (done) {
  1704. soc->htt_stats.num_stats++;
  1705. qdf_sched_work(0, &soc->htt_stats.work);
  1706. }
  1707. qdf_spin_unlock_bh(&soc->htt_stats.lock);
  1708. return;
  1709. error:
  1710. qdf_spin_lock_bh(&soc->htt_stats.lock);
  1711. while ((msg_copy = qdf_nbuf_queue_remove(&soc->htt_stats.msg))
  1712. != NULL) {
  1713. qdf_nbuf_free(msg_copy);
  1714. }
  1715. soc->htt_stats.num_stats = 0;
  1716. qdf_spin_unlock_bh(&soc->htt_stats.lock);
  1717. return;
  1718. }
  1719. /*
  1720. * htt_soc_attach_target() - SOC level HTT setup
  1721. * @htt_soc: HTT SOC handle
  1722. *
  1723. * Return: 0 on success; error code on failure
  1724. */
  1725. int htt_soc_attach_target(void *htt_soc)
  1726. {
  1727. struct htt_soc *soc = (struct htt_soc *)htt_soc;
  1728. return htt_h2t_ver_req_msg(soc);
  1729. }
  1730. /*
  1731. * dp_htt_t2h_msg_handler() - Generic Target to host Msg/event handler
  1732. * @context: Opaque context (HTT SOC handle)
  1733. * @pkt: HTC packet
  1734. */
  1735. static void dp_htt_t2h_msg_handler(void *context, HTC_PACKET *pkt)
  1736. {
  1737. struct htt_soc *soc = (struct htt_soc *) context;
  1738. qdf_nbuf_t htt_t2h_msg = (qdf_nbuf_t) pkt->pPktContext;
  1739. u_int32_t *msg_word;
  1740. enum htt_t2h_msg_type msg_type;
  1741. /* check for successful message reception */
  1742. if (pkt->Status != QDF_STATUS_SUCCESS) {
  1743. if (pkt->Status != QDF_STATUS_E_CANCELED)
  1744. soc->stats.htc_err_cnt++;
  1745. qdf_nbuf_free(htt_t2h_msg);
  1746. return;
  1747. }
  1748. /* TODO: Check if we should pop the HTC/HTT header alignment padding */
  1749. msg_word = (u_int32_t *) qdf_nbuf_data(htt_t2h_msg);
  1750. msg_type = HTT_T2H_MSG_TYPE_GET(*msg_word);
  1751. switch (msg_type) {
  1752. case HTT_T2H_MSG_TYPE_PEER_MAP:
  1753. {
  1754. u_int8_t mac_addr_deswizzle_buf[HTT_MAC_ADDR_LEN];
  1755. u_int8_t *peer_mac_addr;
  1756. u_int16_t peer_id;
  1757. u_int16_t hw_peer_id;
  1758. u_int8_t vdev_id;
  1759. peer_id = HTT_RX_PEER_MAP_PEER_ID_GET(*msg_word);
  1760. hw_peer_id =
  1761. HTT_RX_PEER_MAP_HW_PEER_ID_GET(*(msg_word+2));
  1762. vdev_id = HTT_RX_PEER_MAP_VDEV_ID_GET(*msg_word);
  1763. peer_mac_addr = htt_t2h_mac_addr_deswizzle(
  1764. (u_int8_t *) (msg_word+1),
  1765. &mac_addr_deswizzle_buf[0]);
  1766. QDF_TRACE(QDF_MODULE_ID_TXRX,
  1767. QDF_TRACE_LEVEL_INFO,
  1768. "HTT_T2H_MSG_TYPE_PEER_MAP msg for peer id %d vdev id %d n",
  1769. peer_id, vdev_id);
  1770. dp_rx_peer_map_handler(soc->dp_soc, peer_id, hw_peer_id,
  1771. vdev_id, peer_mac_addr);
  1772. break;
  1773. }
  1774. case HTT_T2H_MSG_TYPE_PEER_UNMAP:
  1775. {
  1776. u_int16_t peer_id;
  1777. peer_id = HTT_RX_PEER_UNMAP_PEER_ID_GET(*msg_word);
  1778. dp_rx_peer_unmap_handler(soc->dp_soc, peer_id);
  1779. break;
  1780. }
  1781. case HTT_T2H_MSG_TYPE_SEC_IND:
  1782. {
  1783. u_int16_t peer_id;
  1784. enum htt_sec_type sec_type;
  1785. int is_unicast;
  1786. peer_id = HTT_SEC_IND_PEER_ID_GET(*msg_word);
  1787. sec_type = HTT_SEC_IND_SEC_TYPE_GET(*msg_word);
  1788. is_unicast = HTT_SEC_IND_UNICAST_GET(*msg_word);
  1789. /* point to the first part of the Michael key */
  1790. msg_word++;
  1791. dp_rx_sec_ind_handler(
  1792. soc->dp_soc, peer_id, sec_type, is_unicast,
  1793. msg_word, msg_word + 2);
  1794. break;
  1795. }
  1796. #if defined(CONFIG_WIN) && WDI_EVENT_ENABLE
  1797. #ifndef REMOVE_PKT_LOG
  1798. case HTT_T2H_MSG_TYPE_PPDU_STATS_IND:
  1799. {
  1800. u_int8_t pdev_id;
  1801. qdf_nbuf_set_pktlen(htt_t2h_msg, HTT_T2H_MAX_MSG_SIZE);
  1802. QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_INFO,
  1803. "received HTT_T2H_MSG_TYPE_PPDU_STATS_IND\n");
  1804. pdev_id = HTT_T2H_PPDU_STATS_MAC_ID_GET(*msg_word);
  1805. pdev_id = DP_HW2SW_MACID(pdev_id);
  1806. dp_txrx_ppdu_stats_handler(soc->dp_soc, pdev_id,
  1807. htt_t2h_msg);
  1808. dp_wdi_event_handler(WDI_EVENT_LITE_T2H, soc->dp_soc,
  1809. htt_t2h_msg, HTT_INVALID_PEER, WDI_NO_VAL,
  1810. pdev_id);
  1811. break;
  1812. }
  1813. #endif
  1814. #endif
  1815. case HTT_T2H_MSG_TYPE_VERSION_CONF:
  1816. {
  1817. soc->tgt_ver.major = HTT_VER_CONF_MAJOR_GET(*msg_word);
  1818. soc->tgt_ver.minor = HTT_VER_CONF_MINOR_GET(*msg_word);
  1819. QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_INFO_HIGH,
  1820. "target uses HTT version %d.%d; host uses %d.%d\n",
  1821. soc->tgt_ver.major, soc->tgt_ver.minor,
  1822. HTT_CURRENT_VERSION_MAJOR,
  1823. HTT_CURRENT_VERSION_MINOR);
  1824. if (soc->tgt_ver.major != HTT_CURRENT_VERSION_MAJOR) {
  1825. QDF_TRACE(QDF_MODULE_ID_TXRX,
  1826. QDF_TRACE_LEVEL_ERROR,
  1827. "*** Incompatible host/target HTT versions!\n");
  1828. }
  1829. /* abort if the target is incompatible with the host */
  1830. qdf_assert(soc->tgt_ver.major ==
  1831. HTT_CURRENT_VERSION_MAJOR);
  1832. if (soc->tgt_ver.minor != HTT_CURRENT_VERSION_MINOR) {
  1833. QDF_TRACE(QDF_MODULE_ID_TXRX,
  1834. QDF_TRACE_LEVEL_WARN,
  1835. "*** Warning: host/target HTT versions"
  1836. " are different, though compatible!\n");
  1837. }
  1838. break;
  1839. }
  1840. case HTT_T2H_MSG_TYPE_RX_ADDBA:
  1841. {
  1842. uint16_t peer_id;
  1843. uint8_t tid;
  1844. uint8_t win_sz;
  1845. uint16_t status;
  1846. struct dp_peer *peer;
  1847. /*
  1848. * Update REO Queue Desc with new values
  1849. */
  1850. peer_id = HTT_RX_ADDBA_PEER_ID_GET(*msg_word);
  1851. tid = HTT_RX_ADDBA_TID_GET(*msg_word);
  1852. win_sz = HTT_RX_ADDBA_WIN_SIZE_GET(*msg_word);
  1853. peer = dp_peer_find_by_id(soc->dp_soc, peer_id);
  1854. /*
  1855. * Window size needs to be incremented by 1
  1856. * since fw needs to represent a value of 256
  1857. * using just 8 bits
  1858. */
  1859. if (peer) {
  1860. status = dp_addba_requestprocess_wifi3(peer,
  1861. 0, tid, 0, win_sz + 1, 0xffff);
  1862. QDF_TRACE(QDF_MODULE_ID_TXRX,
  1863. QDF_TRACE_LEVEL_INFO,
  1864. FL("PeerID %d BAW %d TID %d stat %d\n"),
  1865. peer_id, win_sz, tid, status);
  1866. } else {
  1867. QDF_TRACE(QDF_MODULE_ID_TXRX,
  1868. QDF_TRACE_LEVEL_ERROR,
  1869. FL("Peer not found peer id %d\n"),
  1870. peer_id);
  1871. }
  1872. break;
  1873. }
  1874. case HTT_T2H_MSG_TYPE_EXT_STATS_CONF:
  1875. {
  1876. dp_txrx_fw_stats_handler(soc->dp_soc, htt_t2h_msg);
  1877. break;
  1878. }
  1879. default:
  1880. break;
  1881. };
  1882. /* Free the indication buffer */
  1883. qdf_nbuf_free(htt_t2h_msg);
  1884. }
  1885. /*
  1886. * dp_htt_h2t_full() - Send full handler (called from HTC)
  1887. * @context: Opaque context (HTT SOC handle)
  1888. * @pkt: HTC packet
  1889. *
  1890. * Return: enum htc_send_full_action
  1891. */
  1892. static enum htc_send_full_action
  1893. dp_htt_h2t_full(void *context, HTC_PACKET *pkt)
  1894. {
  1895. return HTC_SEND_FULL_KEEP;
  1896. }
  1897. /*
  1898. * htt_htc_soc_attach() - Register SOC level HTT instance with HTC
  1899. * @htt_soc: HTT SOC handle
  1900. *
  1901. * Return: 0 on success; error code on failure
  1902. */
  1903. static int
  1904. htt_htc_soc_attach(struct htt_soc *soc)
  1905. {
  1906. struct htc_service_connect_req connect;
  1907. struct htc_service_connect_resp response;
  1908. A_STATUS status;
  1909. qdf_mem_set(&connect, sizeof(connect), 0);
  1910. qdf_mem_set(&response, sizeof(response), 0);
  1911. connect.pMetaData = NULL;
  1912. connect.MetaDataLength = 0;
  1913. connect.EpCallbacks.pContext = soc;
  1914. connect.EpCallbacks.EpTxComplete = dp_htt_h2t_send_complete;
  1915. connect.EpCallbacks.EpTxCompleteMultiple = NULL;
  1916. connect.EpCallbacks.EpRecv = dp_htt_t2h_msg_handler;
  1917. /* rx buffers currently are provided by HIF, not by EpRecvRefill */
  1918. connect.EpCallbacks.EpRecvRefill = NULL;
  1919. /* N/A, fill is done by HIF */
  1920. connect.EpCallbacks.RecvRefillWaterMark = 1;
  1921. connect.EpCallbacks.EpSendFull = dp_htt_h2t_full;
  1922. /*
  1923. * Specify how deep to let a queue get before htc_send_pkt will
  1924. * call the EpSendFull function due to excessive send queue depth.
  1925. */
  1926. connect.MaxSendQueueDepth = DP_HTT_MAX_SEND_QUEUE_DEPTH;
  1927. /* disable flow control for HTT data message service */
  1928. connect.ConnectionFlags |= HTC_CONNECT_FLAGS_DISABLE_CREDIT_FLOW_CTRL;
  1929. /* connect to control service */
  1930. connect.service_id = HTT_DATA_MSG_SVC;
  1931. status = htc_connect_service(soc->htc_soc, &connect, &response);
  1932. if (status != A_OK)
  1933. return QDF_STATUS_E_FAILURE;
  1934. soc->htc_endpoint = response.Endpoint;
  1935. return 0; /* success */
  1936. }
  1937. /*
  1938. * htt_soc_attach() - SOC level HTT initialization
  1939. * @dp_soc: Opaque Data path SOC handle
  1940. * @osif_soc: Opaque OSIF SOC handle
  1941. * @htc_soc: SOC level HTC handle
  1942. * @hal_soc: Opaque HAL SOC handle
  1943. * @osdev: QDF device
  1944. *
  1945. * Return: HTT handle on success; NULL on failure
  1946. */
  1947. void *
  1948. htt_soc_attach(void *dp_soc, void *osif_soc, HTC_HANDLE htc_soc,
  1949. void *hal_soc, qdf_device_t osdev)
  1950. {
  1951. struct htt_soc *soc;
  1952. int i;
  1953. soc = qdf_mem_malloc(sizeof(*soc));
  1954. if (!soc)
  1955. goto fail1;
  1956. soc->osdev = osdev;
  1957. soc->osif_soc = osif_soc;
  1958. soc->dp_soc = dp_soc;
  1959. soc->htc_soc = htc_soc;
  1960. soc->hal_soc = hal_soc;
  1961. /* TODO: See if any NSS related context is requred in htt_soc */
  1962. soc->htt_htc_pkt_freelist = NULL;
  1963. if (htt_htc_soc_attach(soc))
  1964. goto fail2;
  1965. /* TODO: See if any Rx data specific intialization is required. For
  1966. * MCL use cases, the data will be received as single packet and
  1967. * should not required any descriptor or reorder handling
  1968. */
  1969. HTT_TX_MUTEX_INIT(&soc->htt_tx_mutex);
  1970. /* pre-allocate some HTC_PACKET objects */
  1971. for (i = 0; i < HTT_HTC_PKT_POOL_INIT_SIZE; i++) {
  1972. struct dp_htt_htc_pkt_union *pkt;
  1973. pkt = qdf_mem_malloc(sizeof(*pkt));
  1974. if (!pkt)
  1975. break;
  1976. htt_htc_pkt_free(soc, &pkt->u.pkt);
  1977. }
  1978. return soc;
  1979. fail2:
  1980. qdf_mem_free(soc);
  1981. fail1:
  1982. return NULL;
  1983. }
  1984. /*
  1985. * htt_soc_detach() - Detach SOC level HTT
  1986. * @htt_soc: HTT SOC handle
  1987. */
  1988. void
  1989. htt_soc_detach(void *htt_soc)
  1990. {
  1991. struct htt_soc *soc = (struct htt_soc *)htt_soc;
  1992. htt_htc_misc_pkt_pool_free(soc);
  1993. htt_htc_pkt_pool_free(soc);
  1994. HTT_TX_MUTEX_DESTROY(&soc->htt_tx_mutex);
  1995. qdf_mem_free(soc);
  1996. }
  1997. /**
  1998. * dp_h2t_ext_stats_msg_send(): function to contruct HTT message to pass to FW
  1999. * @pdev: DP PDEV handle
  2000. * @stats_type_upload_mask: stats type requested by user
  2001. * @config_param_0: extra configuration parameters
  2002. * @config_param_1: extra configuration parameters
  2003. * @config_param_2: extra configuration parameters
  2004. * @config_param_3: extra configuration parameters
  2005. *
  2006. * return: QDF STATUS
  2007. */
  2008. QDF_STATUS dp_h2t_ext_stats_msg_send(struct dp_pdev *pdev,
  2009. uint32_t stats_type_upload_mask, uint32_t config_param_0,
  2010. uint32_t config_param_1, uint32_t config_param_2,
  2011. uint32_t config_param_3)
  2012. {
  2013. struct htt_soc *soc = pdev->soc->htt_handle;
  2014. struct dp_htt_htc_pkt *pkt;
  2015. qdf_nbuf_t msg;
  2016. uint32_t *msg_word;
  2017. uint8_t pdev_mask;
  2018. msg = qdf_nbuf_alloc(
  2019. soc->osdev,
  2020. HTT_MSG_BUF_SIZE(HTT_H2T_EXT_STATS_REQ_MSG_SZ),
  2021. HTC_HEADER_LEN + HTC_HDR_ALIGNMENT_PADDING, 4, TRUE);
  2022. if (!msg)
  2023. return QDF_STATUS_E_NOMEM;
  2024. /*TODO:Add support for SOC stats
  2025. * Bit 0: SOC Stats
  2026. * Bit 1: Pdev stats for pdev id 0
  2027. * Bit 2: Pdev stats for pdev id 1
  2028. * Bit 3: Pdev stats for pdev id 2
  2029. */
  2030. pdev_mask = 1 << (pdev->pdev_id + 1);
  2031. /*
  2032. * Set the length of the message.
  2033. * The contribution from the HTC_HDR_ALIGNMENT_PADDING is added
  2034. * separately during the below call to qdf_nbuf_push_head.
  2035. * The contribution from the HTC header is added separately inside HTC.
  2036. */
  2037. if (qdf_nbuf_put_tail(msg, HTT_H2T_EXT_STATS_REQ_MSG_SZ) == NULL) {
  2038. QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
  2039. "Failed to expand head for HTT_EXT_STATS");
  2040. qdf_nbuf_free(msg);
  2041. return QDF_STATUS_E_FAILURE;
  2042. }
  2043. msg_word = (uint32_t *) qdf_nbuf_data(msg);
  2044. qdf_nbuf_push_head(msg, HTC_HDR_ALIGNMENT_PADDING);
  2045. *msg_word = 0;
  2046. HTT_H2T_MSG_TYPE_SET(*msg_word, HTT_H2T_MSG_TYPE_EXT_STATS_REQ);
  2047. HTT_H2T_EXT_STATS_REQ_PDEV_MASK_SET(*msg_word, pdev_mask);
  2048. HTT_H2T_EXT_STATS_REQ_STATS_TYPE_SET(*msg_word, stats_type_upload_mask);
  2049. /* word 1 */
  2050. msg_word++;
  2051. *msg_word = 0;
  2052. HTT_H2T_EXT_STATS_REQ_CONFIG_PARAM_SET(*msg_word, config_param_0);
  2053. /* word 2 */
  2054. msg_word++;
  2055. *msg_word = 0;
  2056. HTT_H2T_EXT_STATS_REQ_CONFIG_PARAM_SET(*msg_word, config_param_1);
  2057. /* word 3 */
  2058. msg_word++;
  2059. *msg_word = 0;
  2060. HTT_H2T_EXT_STATS_REQ_CONFIG_PARAM_SET(*msg_word, config_param_2);
  2061. /* word 4 */
  2062. msg_word++;
  2063. *msg_word = 0;
  2064. HTT_H2T_EXT_STATS_REQ_CONFIG_PARAM_SET(*msg_word, config_param_3);
  2065. HTT_H2T_EXT_STATS_REQ_CONFIG_PARAM_SET(*msg_word, 0);
  2066. pkt = htt_htc_pkt_alloc(soc);
  2067. if (!pkt) {
  2068. qdf_nbuf_free(msg);
  2069. return QDF_STATUS_E_NOMEM;
  2070. }
  2071. pkt->soc_ctxt = NULL; /* not used during send-done callback */
  2072. SET_HTC_PACKET_INFO_TX(&pkt->htc_pkt,
  2073. dp_htt_h2t_send_complete_free_netbuf,
  2074. qdf_nbuf_data(msg), qdf_nbuf_len(msg),
  2075. soc->htc_endpoint,
  2076. 1); /* tag - not relevant here */
  2077. SET_HTC_PACKET_NET_BUF_CONTEXT(&pkt->htc_pkt, msg);
  2078. DP_HTT_SEND_HTC_PKT(soc, pkt);
  2079. return 0;
  2080. }
  2081. /* This macro will revert once proper HTT header will define for
  2082. * HTT_H2T_MSG_TYPE_PPDU_STATS_CFG in htt.h file
  2083. * */
  2084. #if defined(CONFIG_WIN) && WDI_EVENT_ENABLE
  2085. /**
  2086. * dp_h2t_cfg_stats_msg_send(): function to construct HTT message to pass to FW
  2087. * @pdev: DP PDEV handle
  2088. * @stats_type_upload_mask: stats type requested by user
  2089. *
  2090. * return: QDF STATUS
  2091. */
  2092. QDF_STATUS dp_h2t_cfg_stats_msg_send(struct dp_pdev *pdev,
  2093. uint32_t stats_type_upload_mask)
  2094. {
  2095. struct htt_soc *soc = pdev->soc->htt_handle;
  2096. struct dp_htt_htc_pkt *pkt;
  2097. qdf_nbuf_t msg;
  2098. uint32_t *msg_word;
  2099. uint8_t pdev_mask;
  2100. msg = qdf_nbuf_alloc(
  2101. soc->osdev,
  2102. HTT_MSG_BUF_SIZE(HTT_H2T_PPDU_STATS_CFG_MSG_SZ),
  2103. HTC_HEADER_LEN + HTC_HDR_ALIGNMENT_PADDING, 4, true);
  2104. if (!msg) {
  2105. QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR,
  2106. "Fail to allocate HTT_H2T_PPDU_STATS_CFG_MSG_SZ msg buffer\n");
  2107. qdf_assert(0);
  2108. return QDF_STATUS_E_NOMEM;
  2109. }
  2110. /*TODO:Add support for SOC stats
  2111. * Bit 0: SOC Stats
  2112. * Bit 1: Pdev stats for pdev id 0
  2113. * Bit 2: Pdev stats for pdev id 1
  2114. * Bit 3: Pdev stats for pdev id 2
  2115. */
  2116. pdev_mask = 1 << DP_SW2HW_MACID(pdev->pdev_id);
  2117. /*
  2118. * Set the length of the message.
  2119. * The contribution from the HTC_HDR_ALIGNMENT_PADDING is added
  2120. * separately during the below call to qdf_nbuf_push_head.
  2121. * The contribution from the HTC header is added separately inside HTC.
  2122. */
  2123. if (qdf_nbuf_put_tail(msg, HTT_H2T_PPDU_STATS_CFG_MSG_SZ) == NULL) {
  2124. QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR,
  2125. "Failed to expand head for HTT_CFG_STATS\n");
  2126. qdf_nbuf_free(msg);
  2127. return QDF_STATUS_E_FAILURE;
  2128. }
  2129. msg_word = (uint32_t *) qdf_nbuf_data(msg);
  2130. qdf_nbuf_push_head(msg, HTC_HDR_ALIGNMENT_PADDING);
  2131. *msg_word = 0;
  2132. HTT_H2T_MSG_TYPE_SET(*msg_word, HTT_H2T_MSG_TYPE_PPDU_STATS_CFG);
  2133. HTT_H2T_PPDU_STATS_CFG_PDEV_MASK_SET(*msg_word, pdev_mask);
  2134. HTT_H2T_PPDU_STATS_CFG_TLV_BITMASK_SET(*msg_word,
  2135. stats_type_upload_mask);
  2136. pkt = htt_htc_pkt_alloc(soc);
  2137. if (!pkt) {
  2138. QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR,
  2139. "Fail to allocate dp_htt_htc_pkt buffer\n");
  2140. qdf_assert(0);
  2141. qdf_nbuf_free(msg);
  2142. return QDF_STATUS_E_NOMEM;
  2143. }
  2144. pkt->soc_ctxt = NULL; /* not used during send-done callback */
  2145. SET_HTC_PACKET_INFO_TX(&pkt->htc_pkt,
  2146. dp_htt_h2t_send_complete_free_netbuf,
  2147. qdf_nbuf_data(msg), qdf_nbuf_len(msg),
  2148. soc->htc_endpoint,
  2149. 1); /* tag - not relevant here */
  2150. SET_HTC_PACKET_NET_BUF_CONTEXT(&pkt->htc_pkt, msg);
  2151. DP_HTT_SEND_HTC_PKT(soc, pkt);
  2152. return 0;
  2153. }
  2154. #endif