dp_rh_htt.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404
  1. /*
  2. * Copyright (c) 2023 Qualcomm Innovation Center, Inc. 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 "dp_types.h"
  20. #include "dp_internal.h"
  21. #include "dp_rh_htt.h"
  22. #include "dp_rh_rx.h"
  23. #include "qdf_mem.h"
  24. #include "cdp_txrx_cmn_struct.h"
  25. #define HTT_MSG_BUF_SIZE(msg_bytes) \
  26. ((msg_bytes) + HTC_HEADER_LEN + HTC_HDR_ALIGNMENT_PADDING)
  27. #define HTT_T2H_MSG_BUF_REINIT(_buf, dev) \
  28. do { \
  29. QDF_NBUF_CB_PADDR(_buf) -= (HTC_HEADER_LEN + \
  30. HTC_HDR_ALIGNMENT_PADDING); \
  31. qdf_nbuf_init_fast((_buf)); \
  32. qdf_mem_dma_sync_single_for_device(dev, \
  33. (QDF_NBUF_CB_PADDR(_buf)), \
  34. (skb_end_pointer(_buf) - \
  35. (_buf)->data), \
  36. PCI_DMA_FROMDEVICE); \
  37. } while (0)
  38. /*
  39. * dp_htt_h2t_send_complete_free_netbuf() - Free completed buffer
  40. * @soc: SOC handle
  41. * @status: Completion status
  42. * @netbuf: HTT buffer
  43. */
  44. static void
  45. dp_htt_h2t_send_complete_free_netbuf(
  46. void *soc, A_STATUS status, qdf_nbuf_t netbuf)
  47. {
  48. qdf_nbuf_free(netbuf);
  49. }
  50. QDF_STATUS dp_htt_h2t_rx_ring_rfs_cfg(struct htt_soc *soc)
  51. {
  52. struct dp_htt_htc_pkt *pkt;
  53. qdf_nbuf_t msg;
  54. uint32_t *msg_word;
  55. QDF_STATUS status;
  56. uint8_t *htt_logger_bufp;
  57. /*
  58. * TODO check do we need ini support in Evros
  59. * Receive flow steering configuration,
  60. * disable gEnableFlowSteering(=0) in ini if
  61. * FW doesn't support it
  62. */
  63. /* reserve room for the HTC header */
  64. msg = qdf_nbuf_alloc(soc->osdev,
  65. HTT_MSG_BUF_SIZE(HTT_RFS_CFG_REQ_BYTES),
  66. HTC_HEADER_LEN + HTC_HDR_ALIGNMENT_PADDING, 4,
  67. true);
  68. if (!msg) {
  69. dp_err("htt_msg alloc failed for RFS config");
  70. return QDF_STATUS_E_NOMEM;
  71. }
  72. /*
  73. * Set the length of the message.
  74. * The contribution from the HTC_HDR_ALIGNMENT_PADDING is added
  75. * separately during the below call to qdf_nbuf_push_head.
  76. * The contribution from the HTC header is added separately inside HTC.
  77. */
  78. qdf_nbuf_put_tail(msg, HTT_RFS_CFG_REQ_BYTES);
  79. /* fill in the message contents */
  80. msg_word = (uint32_t *)qdf_nbuf_data(msg);
  81. /* rewind beyond alignment pad to get to the HTC header reserved area */
  82. qdf_nbuf_push_head(msg, HTC_HDR_ALIGNMENT_PADDING);
  83. /* word 0 */
  84. *msg_word = 0;
  85. htt_logger_bufp = (uint8_t *)msg_word;
  86. HTT_H2T_MSG_TYPE_SET(*msg_word, HTT_H2T_MSG_TYPE_RFS_CONFIG);
  87. HTT_RX_RFS_CONFIG_SET(*msg_word, 1);
  88. /*
  89. * TODO value should be obtained from ini maxMSDUsPerRxInd
  90. * currently this ini is legacy ol and available only from cds
  91. * make this ini common to HL and evros DP
  92. */
  93. *msg_word |= ((32 & 0xff) << 16);
  94. dp_htt_info("RFS sent to F.W: 0x%08x", *msg_word);
  95. /*start*/
  96. pkt = htt_htc_pkt_alloc(soc);
  97. if (!pkt) {
  98. qdf_nbuf_free(msg);
  99. return QDF_STATUS_E_NOMEM;
  100. }
  101. pkt->soc_ctxt = NULL; /* not used during send-done callback */
  102. SET_HTC_PACKET_INFO_TX(
  103. &pkt->htc_pkt,
  104. dp_htt_h2t_send_complete_free_netbuf,
  105. qdf_nbuf_data(msg),
  106. qdf_nbuf_len(msg),
  107. soc->htc_endpoint,
  108. HTC_TX_PACKET_TAG_RUNTIME_PUT); /* tag for no FW response msg */
  109. SET_HTC_PACKET_NET_BUF_CONTEXT(&pkt->htc_pkt, msg);
  110. status = DP_HTT_SEND_HTC_PKT(soc, pkt, HTT_H2T_MSG_TYPE_RFS_CONFIG,
  111. htt_logger_bufp);
  112. if (status != QDF_STATUS_SUCCESS) {
  113. qdf_nbuf_free(msg);
  114. htt_htc_pkt_free(soc, pkt);
  115. }
  116. return status;
  117. }
  118. static void
  119. dp_htt_rx_addba_handler_rh(struct dp_soc *soc, uint16_t peer_id,
  120. uint8_t tid, uint16_t win_sz)
  121. {
  122. }
  123. static QDF_STATUS
  124. dp_htt_rx_delba_ind_handler_rh(void *soc_handle, uint16_t peer_id,
  125. uint8_t tid, uint16_t win_sz)
  126. {
  127. return QDF_STATUS_SUCCESS;
  128. }
  129. /**
  130. * dp_htt_t2h_msg_handler_fast() - Fastpath specific message handler
  131. * @context: HTT context
  132. * @cmpl_msdus: netbuf completions
  133. * @num_cmpls: number of completions to be handled
  134. *
  135. * Return: None
  136. */
  137. static void
  138. dp_htt_t2h_msg_handler_fast(void *context, qdf_nbuf_t *cmpl_msdus,
  139. uint32_t num_cmpls)
  140. {
  141. struct htt_soc *soc = (struct htt_soc *)context;
  142. qdf_nbuf_t htt_t2h_msg;
  143. uint32_t *msg_word;
  144. uint32_t i;
  145. enum htt_t2h_msg_type msg_type;
  146. uint32_t msg_len;
  147. for (i = 0; i < num_cmpls; i++) {
  148. htt_t2h_msg = cmpl_msdus[i];
  149. msg_len = qdf_nbuf_len(htt_t2h_msg);
  150. /*
  151. * Move the data pointer to point to HTT header
  152. * past the HTC header + HTC header alignment padding
  153. */
  154. qdf_nbuf_pull_head(htt_t2h_msg, HTC_HEADER_LEN +
  155. HTC_HDR_ALIGNMENT_PADDING);
  156. msg_word = (uint32_t *)qdf_nbuf_data(htt_t2h_msg);
  157. msg_type = HTT_T2H_MSG_TYPE_GET(*msg_word);
  158. switch (msg_type) {
  159. case HTT_T2H_MSG_TYPE_RX_DATA_IND:
  160. {
  161. uint16_t vdev_id, msdu_cnt;
  162. uint16_t peer_id, frag_ind;
  163. peer_id = HTT_RX_DATA_IND_PEER_ID_GET(*msg_word);
  164. frag_ind = HTT_RX_DATA_IND_FRAG_GET(*(msg_word + 1));
  165. vdev_id = HTT_RX_DATA_IND_VDEV_ID_GET(*msg_word);
  166. if (qdf_unlikely(frag_ind)) {
  167. dp_rx_frag_indication_handler(soc->dp_soc,
  168. htt_t2h_msg,
  169. vdev_id, peer_id);
  170. break;
  171. }
  172. msdu_cnt =
  173. HTT_RX_DATA_IND_MSDU_CNT_GET(*(msg_word + 1));
  174. dp_rx_data_indication_handler(soc->dp_soc, htt_t2h_msg,
  175. vdev_id, peer_id,
  176. msdu_cnt);
  177. break;
  178. }
  179. /* TODO add support for TX completion handling */
  180. case HTT_T2H_MSG_TYPE_RX_PN_IND:
  181. {
  182. /* TODO check and add PN IND handling */
  183. break;
  184. }
  185. case HTT_T2H_MSG_TYPE_RX_ADDBA:
  186. {
  187. uint16_t peer_id;
  188. uint8_t tid;
  189. uint16_t win_sz;
  190. /*
  191. * Update REO Queue Desc with new values
  192. */
  193. peer_id = HTT_RX_ADDBA_PEER_ID_GET(*msg_word);
  194. tid = HTT_RX_ADDBA_TID_GET(*msg_word);
  195. win_sz = HTT_RX_ADDBA_WIN_SIZE_GET(*msg_word);
  196. /*
  197. * Window size needs to be incremented by 1
  198. * since fw needs to represent a value of 256
  199. * using just 8 bits
  200. */
  201. dp_htt_rx_addba_handler_rh(soc->dp_soc, peer_id,
  202. tid, win_sz + 1);
  203. break;
  204. }
  205. case HTT_T2H_MSG_TYPE_RX_DELBA:
  206. {
  207. uint16_t peer_id;
  208. uint8_t tid;
  209. uint8_t win_sz;
  210. QDF_STATUS status;
  211. peer_id = HTT_RX_DELBA_PEER_ID_GET(*msg_word);
  212. tid = HTT_RX_DELBA_TID_GET(*msg_word);
  213. win_sz = HTT_RX_DELBA_WIN_SIZE_GET(*msg_word);
  214. status = dp_htt_rx_delba_ind_handler_rh(soc->dp_soc,
  215. peer_id, tid,
  216. win_sz);
  217. dp_htt_info("DELBA PeerID %d BAW %d TID %d stat %d",
  218. peer_id, win_sz, tid, status);
  219. break;
  220. }
  221. case HTT_T2H_MSG_TYPE_PPDU_STATS_IND:
  222. {
  223. qdf_nbuf_t nbuf_copy;
  224. HTC_PACKET htc_pkt = {0};
  225. nbuf_copy = qdf_nbuf_copy(htt_t2h_msg);
  226. if (qdf_unlikely(!nbuf_copy)) {
  227. dp_htt_err("NBUF copy failed for PPDU stats msg");
  228. break;
  229. }
  230. htc_pkt.Status = QDF_STATUS_SUCCESS;
  231. htc_pkt.pPktContext = (void *)nbuf_copy;
  232. dp_htt_t2h_msg_handler(context, &htc_pkt);
  233. break;
  234. }
  235. default:
  236. {
  237. HTC_PACKET htc_pkt = {0};
  238. htc_pkt.Status = QDF_STATUS_SUCCESS;
  239. htc_pkt.pPktContext = (void *)htt_t2h_msg;
  240. /*
  241. * Increment user count to protect buffer
  242. * from generic handler free count will be
  243. * reset to 1 during MSG_BUF_REINIT
  244. */
  245. qdf_nbuf_inc_users(htt_t2h_msg);
  246. dp_htt_t2h_msg_handler(context, &htc_pkt);
  247. break;
  248. }
  249. /* Re-initialize the indication buffer */
  250. HTT_T2H_MSG_BUF_REINIT(htt_t2h_msg, soc->osdev);
  251. qdf_nbuf_set_pktlen(htt_t2h_msg, 0);
  252. }
  253. }
  254. }
  255. static QDF_STATUS
  256. dp_htt_htc_attach(struct htt_soc *soc, uint16_t service_id)
  257. {
  258. struct htc_service_connect_req connect;
  259. struct htc_service_connect_resp response;
  260. QDF_STATUS status;
  261. qdf_mem_zero(&connect, sizeof(connect));
  262. qdf_mem_zero(&response, sizeof(response));
  263. connect.pMetaData = NULL;
  264. connect.MetaDataLength = 0;
  265. connect.EpCallbacks.pContext = soc;
  266. connect.EpCallbacks.EpTxComplete = dp_htt_h2t_send_complete;
  267. connect.EpCallbacks.EpTxCompleteMultiple = NULL;
  268. /* fastpath handler will be used instead */
  269. connect.EpCallbacks.EpRecv = NULL;
  270. /* rx buffers currently are provided by HIF, not by EpRecvRefill */
  271. connect.EpCallbacks.EpRecvRefill = NULL;
  272. /* N/A, fill is done by HIF */
  273. connect.EpCallbacks.RecvRefillWaterMark = 1;
  274. connect.EpCallbacks.EpSendFull = dp_htt_h2t_full;
  275. /*
  276. * Specify how deep to let a queue get before htc_send_pkt will
  277. * call the EpSendFull function due to excessive send queue depth.
  278. */
  279. connect.MaxSendQueueDepth = DP_HTT_MAX_SEND_QUEUE_DEPTH;
  280. /* disable flow control for HTT data message service */
  281. connect.ConnectionFlags |= HTC_CONNECT_FLAGS_DISABLE_CREDIT_FLOW_CTRL;
  282. /* connect to control service */
  283. connect.service_id = service_id;
  284. status = htc_connect_service(soc->htc_soc, &connect, &response);
  285. if (status != QDF_STATUS_SUCCESS) {
  286. dp_htt_err("HTC connect svc failed for id:%u", service_id);
  287. return status;
  288. }
  289. if (service_id == HTT_DATA_MSG_SVC)
  290. soc->htc_endpoint = response.Endpoint;
  291. /*
  292. * TODO do we need to set tx_svc end point
  293. * hif_save_htc_htt_config_endpoint(dpsoc->hif_handle,
  294. * soc->htc_endpoint);
  295. */
  296. return QDF_STATUS_SUCCESS;
  297. }
  298. static QDF_STATUS
  299. dp_htt_htc_soc_attach_all(struct htt_soc *soc)
  300. {
  301. struct dp_soc *dp_soc = soc->dp_soc;
  302. int svc_list[3] = {HTT_DATA_MSG_SVC, HTT_DATA2_MSG_SVC,
  303. HTT_DATA3_MSG_SVC};
  304. QDF_STATUS status;
  305. int i;
  306. for (i = 0; i < QDF_ARRAY_SIZE(svc_list); i++) {
  307. status = dp_htt_htc_attach(soc, svc_list[i]);
  308. if (QDF_IS_STATUS_ERROR(status))
  309. return status;
  310. }
  311. dp_hif_update_pipe_callback(dp_soc, (void *)soc,
  312. dp_htt_hif_t2h_hp_callback,
  313. DP_HTT_T2H_HP_PIPE);
  314. /* Register fastpath cb handlers for RX CE's */
  315. if (hif_ce_fastpath_cb_register(dp_soc->hif_handle,
  316. dp_htt_t2h_msg_handler_fast, soc)) {
  317. dp_htt_err("failed to register fastpath callback");
  318. return QDF_STATUS_E_FAILURE;
  319. }
  320. return QDF_STATUS_SUCCESS;
  321. }
  322. /*
  323. * dp_htt_soc_initialize_rh() - SOC level HTT initialization
  324. * @htt_soc: Opaque htt SOC handle
  325. * @ctrl_psoc: Opaque ctrl SOC handle
  326. * @htc_soc: SOC level HTC handle
  327. * @hal_soc: Opaque HAL SOC handle
  328. * @osdev: QDF device
  329. *
  330. * Return: HTT handle on success; NULL on failure
  331. */
  332. void *
  333. dp_htt_soc_initialize_rh(struct htt_soc *htt_soc,
  334. struct cdp_ctrl_objmgr_psoc *ctrl_psoc,
  335. HTC_HANDLE htc_soc,
  336. hal_soc_handle_t hal_soc_hdl, qdf_device_t osdev)
  337. {
  338. struct htt_soc *soc = (struct htt_soc *)htt_soc;
  339. soc->osdev = osdev;
  340. soc->ctrl_psoc = ctrl_psoc;
  341. soc->htc_soc = htc_soc;
  342. soc->hal_soc = hal_soc_hdl;
  343. if (dp_htt_htc_soc_attach_all(soc))
  344. goto fail2;
  345. return soc;
  346. fail2:
  347. return NULL;
  348. }