dp_htt.c 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738
  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. #define HTT_HTC_PKT_POOL_INIT_SIZE 64
  24. #define HTT_MSG_BUF_SIZE(msg_bytes) \
  25. ((msg_bytes) + HTC_HEADER_LEN + HTC_HDR_ALIGNMENT_PADDING)
  26. /*
  27. * htt_htc_pkt_alloc() - Allocate HTC packet buffer
  28. * @htt_soc: HTT SOC handle
  29. *
  30. * Return: Pointer to htc packet buffer
  31. */
  32. static struct dp_htt_htc_pkt *
  33. htt_htc_pkt_alloc(struct htt_soc *soc)
  34. {
  35. struct dp_htt_htc_pkt_union *pkt = NULL;
  36. HTT_TX_MUTEX_ACQUIRE(&soc->htt_tx_mutex);
  37. if (soc->htt_htc_pkt_freelist) {
  38. pkt = soc->htt_htc_pkt_freelist;
  39. soc->htt_htc_pkt_freelist = soc->htt_htc_pkt_freelist->u.next;
  40. }
  41. HTT_TX_MUTEX_RELEASE(&soc->htt_tx_mutex);
  42. if (pkt == NULL)
  43. pkt = qdf_mem_malloc(sizeof(*pkt));
  44. return &pkt->u.pkt; /* not actually a dereference */
  45. }
  46. /*
  47. * htt_htc_pkt_free() - Free HTC packet buffer
  48. * @htt_soc: HTT SOC handle
  49. */
  50. static void
  51. htt_htc_pkt_free(struct htt_soc *soc, struct dp_htt_htc_pkt *pkt)
  52. {
  53. struct dp_htt_htc_pkt_union *u_pkt =
  54. (struct dp_htt_htc_pkt_union *)pkt;
  55. HTT_TX_MUTEX_ACQUIRE(&soc->htt_tx_mutex);
  56. u_pkt->u.next = soc->htt_htc_pkt_freelist;
  57. soc->htt_htc_pkt_freelist = u_pkt;
  58. HTT_TX_MUTEX_RELEASE(&soc->htt_tx_mutex);
  59. }
  60. /*
  61. * htt_htc_pkt_pool_free() - Free HTC packet pool
  62. * @htt_soc: HTT SOC handle
  63. */
  64. static void
  65. htt_htc_pkt_pool_free(struct htt_soc *soc)
  66. {
  67. struct dp_htt_htc_pkt_union *pkt, *next;
  68. pkt = soc->htt_htc_pkt_freelist;
  69. while (pkt) {
  70. next = pkt->u.next;
  71. qdf_mem_free(pkt);
  72. pkt = next;
  73. }
  74. soc->htt_htc_pkt_freelist = NULL;
  75. }
  76. /*
  77. * htt_t2h_mac_addr_deswizzle() - Swap MAC addr bytes if FW endianess differ
  78. * @tgt_mac_addr: Target MAC
  79. * @buffer: Output buffer
  80. */
  81. static u_int8_t *
  82. htt_t2h_mac_addr_deswizzle(u_int8_t *tgt_mac_addr, u_int8_t *buffer)
  83. {
  84. #ifdef BIG_ENDIAN_HOST
  85. /*
  86. * The host endianness is opposite of the target endianness.
  87. * To make u_int32_t elements come out correctly, the target->host
  88. * upload has swizzled the bytes in each u_int32_t element of the
  89. * message.
  90. * For byte-array message fields like the MAC address, this
  91. * upload swizzling puts the bytes in the wrong order, and needs
  92. * to be undone.
  93. */
  94. buffer[0] = tgt_mac_addr[3];
  95. buffer[1] = tgt_mac_addr[2];
  96. buffer[2] = tgt_mac_addr[1];
  97. buffer[3] = tgt_mac_addr[0];
  98. buffer[4] = tgt_mac_addr[7];
  99. buffer[5] = tgt_mac_addr[6];
  100. return buffer;
  101. #else
  102. /*
  103. * The host endianness matches the target endianness -
  104. * we can use the mac addr directly from the message buffer.
  105. */
  106. return tgt_mac_addr;
  107. #endif
  108. }
  109. /*
  110. * dp_htt_h2t_send_complete_free_netbuf() - Free completed buffer
  111. * @soc: SOC handle
  112. * @status: Completion status
  113. * @netbuf: HTT buffer
  114. */
  115. static void
  116. dp_htt_h2t_send_complete_free_netbuf(
  117. void *soc, A_STATUS status, qdf_nbuf_t netbuf)
  118. {
  119. qdf_nbuf_free(netbuf);
  120. }
  121. /*
  122. * dp_htt_h2t_send_complete() - H2T completion handler
  123. * @context: Opaque context (HTT SOC handle)
  124. * @htc_pkt: HTC packet
  125. */
  126. static void
  127. dp_htt_h2t_send_complete(void *context, HTC_PACKET *htc_pkt)
  128. {
  129. void (*send_complete_part2)(
  130. void *soc, A_STATUS status, qdf_nbuf_t msdu);
  131. struct htt_soc *soc = (struct htt_soc *) context;
  132. struct dp_htt_htc_pkt *htt_pkt;
  133. qdf_nbuf_t netbuf;
  134. send_complete_part2 = htc_pkt->pPktContext;
  135. htt_pkt = container_of(htc_pkt, struct dp_htt_htc_pkt, htc_pkt);
  136. /* process (free or keep) the netbuf that held the message */
  137. netbuf = (qdf_nbuf_t) htc_pkt->pNetBufContext;
  138. /*
  139. * adf sendcomplete is required for windows only
  140. */
  141. /* qdf_nbuf_set_sendcompleteflag(netbuf, TRUE); */
  142. if (send_complete_part2 != NULL) {
  143. send_complete_part2(
  144. htt_pkt->soc_ctxt, htc_pkt->Status, netbuf);
  145. }
  146. /* free the htt_htc_pkt / HTC_PACKET object */
  147. htt_htc_pkt_free(soc, htt_pkt);
  148. }
  149. /*
  150. * htt_h2t_ver_req_msg() - Send HTT version request message to target
  151. * @htt_soc: HTT SOC handle
  152. *
  153. * Return: 0 on success; error code on failure
  154. */
  155. static int htt_h2t_ver_req_msg(struct htt_soc *soc)
  156. {
  157. struct dp_htt_htc_pkt *pkt;
  158. qdf_nbuf_t msg;
  159. uint32_t *msg_word;
  160. msg = qdf_nbuf_alloc(
  161. soc->osdev,
  162. HTT_MSG_BUF_SIZE(HTT_VER_REQ_BYTES),
  163. /* reserve room for the HTC header */
  164. HTC_HEADER_LEN + HTC_HDR_ALIGNMENT_PADDING, 4, TRUE);
  165. if (!msg)
  166. return QDF_STATUS_E_NOMEM;
  167. /*
  168. * Set the length of the message.
  169. * The contribution from the HTC_HDR_ALIGNMENT_PADDING is added
  170. * separately during the below call to qdf_nbuf_push_head.
  171. * The contribution from the HTC header is added separately inside HTC.
  172. */
  173. if (qdf_nbuf_put_tail(msg, HTT_VER_REQ_BYTES) == NULL) {
  174. QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
  175. "%s: Failed to expand head for HTT_H2T_MSG_TYPE_VERSION_REQ msg\n",
  176. __func__);
  177. return QDF_STATUS_E_FAILURE;
  178. }
  179. /* fill in the message contents */
  180. msg_word = (u_int32_t *) qdf_nbuf_data(msg);
  181. /* rewind beyond alignment pad to get to the HTC header reserved area */
  182. qdf_nbuf_push_head(msg, HTC_HDR_ALIGNMENT_PADDING);
  183. *msg_word = 0;
  184. HTT_H2T_MSG_TYPE_SET(*msg_word, HTT_H2T_MSG_TYPE_VERSION_REQ);
  185. pkt = htt_htc_pkt_alloc(soc);
  186. if (!pkt) {
  187. qdf_nbuf_free(msg);
  188. return QDF_STATUS_E_FAILURE;
  189. }
  190. pkt->soc_ctxt = NULL; /* not used during send-done callback */
  191. SET_HTC_PACKET_INFO_TX(&pkt->htc_pkt,
  192. dp_htt_h2t_send_complete_free_netbuf, qdf_nbuf_data(msg),
  193. qdf_nbuf_len(msg), soc->htc_endpoint,
  194. 1); /* tag - not relevant here */
  195. SET_HTC_PACKET_NET_BUF_CONTEXT(&pkt->htc_pkt, msg);
  196. htc_send_pkt(soc->htc_soc, &pkt->htc_pkt);
  197. return 0;
  198. }
  199. /*
  200. * htt_srng_setup() - Send SRNG setup message to target
  201. * @htt_soc: HTT SOC handle
  202. * @mac_id: MAC Id
  203. * @hal_srng: Opaque HAL SRNG pointer
  204. * @hal_ring_type: SRNG ring type
  205. *
  206. * Return: 0 on success; error code on failure
  207. */
  208. int htt_srng_setup(void *htt_soc, int mac_id, void *hal_srng,
  209. int hal_ring_type)
  210. {
  211. struct htt_soc *soc = (struct htt_soc *)htt_soc;
  212. struct dp_htt_htc_pkt *pkt;
  213. qdf_nbuf_t htt_msg;
  214. uint32_t *msg_word;
  215. struct hal_srng_params srng_params;
  216. qdf_dma_addr_t hp_addr, tp_addr;
  217. uint32_t ring_entry_size =
  218. hal_srng_get_entrysize(soc->hal_soc, hal_ring_type);
  219. int htt_ring_type, htt_ring_id;
  220. /* Sizes should be set in 4-byte words */
  221. ring_entry_size = ring_entry_size >> 2;
  222. htt_msg = qdf_nbuf_alloc(soc->osdev,
  223. HTT_MSG_BUF_SIZE(HTT_SRING_SETUP_SZ),
  224. /* reserve room for the HTC header */
  225. HTC_HEADER_LEN + HTC_HDR_ALIGNMENT_PADDING, 4, TRUE);
  226. if (!htt_msg)
  227. goto fail0;
  228. hal_get_srng_params(soc->hal_soc, hal_srng, &srng_params);
  229. hp_addr = hal_srng_get_hp_addr(soc->hal_soc, hal_srng);
  230. tp_addr = hal_srng_get_tp_addr(soc->hal_soc, hal_srng);
  231. switch (hal_ring_type) {
  232. case RXDMA_BUF:
  233. if (srng_params.ring_id ==
  234. HAL_SRNG_WMAC1_SW2RXDMA0_BUF) {
  235. #ifdef QCA_HOST2FW_RXBUF_RING
  236. htt_ring_id = HTT_HOST1_TO_FW_RXBUF_RING;
  237. htt_ring_type = HTT_SW_TO_SW_RING;
  238. #else
  239. htt_ring_id = HTT_RXDMA_HOST_BUF_RING;
  240. htt_ring_type = HTT_SW_TO_HW_RING;
  241. #endif
  242. } else if (srng_params.ring_id ==
  243. (HAL_SRNG_WMAC1_SW2RXDMA1_BUF +
  244. (mac_id * HAL_MAX_RINGS_PER_LMAC))) {
  245. htt_ring_id = HTT_RXDMA_HOST_BUF_RING;
  246. htt_ring_type = HTT_SW_TO_HW_RING;
  247. } else {
  248. QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
  249. "%s: Ring %d currently not supported\n",
  250. __func__, srng_params.ring_id);
  251. goto fail1;
  252. }
  253. QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
  254. "%s: ring_type %d ring_id %d\n",
  255. __func__, hal_ring_type, srng_params.ring_id);
  256. QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
  257. "%s: hp_addr 0x%llx tp_addr 0x%llx\n",
  258. __func__, (uint64_t)hp_addr, (uint64_t)tp_addr);
  259. QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
  260. "%s: htt_ring_id %d\n", __func__, htt_ring_id);
  261. break;
  262. case RXDMA_MONITOR_BUF:
  263. htt_ring_id = HTT_RXDMA_MONITOR_BUF_RING;
  264. htt_ring_type = HTT_SW_TO_HW_RING;
  265. break;
  266. case RXDMA_MONITOR_STATUS:
  267. htt_ring_id = HTT_RXDMA_MONITOR_STATUS_RING;
  268. htt_ring_type = HTT_SW_TO_HW_RING;
  269. break;
  270. case RXDMA_MONITOR_DST:
  271. htt_ring_id = HTT_RXDMA_MONITOR_DEST_RING;
  272. htt_ring_type = HTT_HW_TO_SW_RING;
  273. break;
  274. case RXDMA_DST:
  275. default:
  276. QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
  277. "%s: Ring currently not supported\n", __func__);
  278. goto fail1;
  279. }
  280. /*
  281. * Set the length of the message.
  282. * The contribution from the HTC_HDR_ALIGNMENT_PADDING is added
  283. * separately during the below call to qdf_nbuf_push_head.
  284. * The contribution from the HTC header is added separately inside HTC.
  285. */
  286. if (qdf_nbuf_put_tail(htt_msg, HTT_SRING_SETUP_SZ) == NULL) {
  287. QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
  288. "%s: Failed to expand head for SRING_SETUP msg\n",
  289. __func__);
  290. return QDF_STATUS_E_FAILURE;
  291. }
  292. msg_word = (uint32_t *)qdf_nbuf_data(htt_msg);
  293. /* rewind beyond alignment pad to get to the HTC header reserved area */
  294. qdf_nbuf_push_head(htt_msg, HTC_HDR_ALIGNMENT_PADDING);
  295. /* word 0 */
  296. *msg_word = 0;
  297. HTT_H2T_MSG_TYPE_SET(*msg_word, HTT_H2T_MSG_TYPE_SRING_SETUP);
  298. if (htt_ring_type == HTT_SW_TO_HW_RING)
  299. HTT_SRING_SETUP_PDEV_ID_SET(*msg_word,
  300. DP_SW2HW_MACID(mac_id));
  301. else
  302. HTT_SRING_SETUP_PDEV_ID_SET(*msg_word, mac_id);
  303. QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
  304. "%s: mac_id %d\n", __func__, mac_id);
  305. HTT_SRING_SETUP_RING_TYPE_SET(*msg_word, htt_ring_type);
  306. /* TODO: Discuss with FW on changing this to unique ID and using
  307. * htt_ring_type to send the type of ring
  308. */
  309. HTT_SRING_SETUP_RING_ID_SET(*msg_word, htt_ring_id);
  310. /* word 1 */
  311. msg_word++;
  312. *msg_word = 0;
  313. HTT_SRING_SETUP_RING_BASE_ADDR_LO_SET(*msg_word,
  314. srng_params.ring_base_paddr & 0xffffffff);
  315. /* word 2 */
  316. msg_word++;
  317. *msg_word = 0;
  318. HTT_SRING_SETUP_RING_BASE_ADDR_HI_SET(*msg_word,
  319. (uint64_t)srng_params.ring_base_paddr >> 32);
  320. /* word 3 */
  321. msg_word++;
  322. *msg_word = 0;
  323. HTT_SRING_SETUP_ENTRY_SIZE_SET(*msg_word, ring_entry_size);
  324. HTT_SRING_SETUP_RING_SIZE_SET(*msg_word,
  325. (ring_entry_size * srng_params.num_entries));
  326. QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
  327. "%s: entry_size %d\n", __func__,
  328. ring_entry_size);
  329. QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
  330. "%s: num_entries %d\n", __func__,
  331. srng_params.num_entries);
  332. QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
  333. "%s: ring_size %d\n", __func__,
  334. (ring_entry_size * srng_params.num_entries));
  335. if (htt_ring_type == HTT_SW_TO_HW_RING)
  336. HTT_SRING_SETUP_RING_MISC_CFG_FLAG_LOOPCOUNT_DISABLE_SET(
  337. *msg_word, 1);
  338. HTT_SRING_SETUP_RING_MISC_CFG_FLAG_MSI_SWAP_SET(*msg_word,
  339. !!(srng_params.flags & HAL_SRNG_MSI_SWAP));
  340. HTT_SRING_SETUP_RING_MISC_CFG_FLAG_TLV_SWAP_SET(*msg_word,
  341. !!(srng_params.flags & HAL_SRNG_DATA_TLV_SWAP));
  342. HTT_SRING_SETUP_RING_MISC_CFG_FLAG_HOST_FW_SWAP_SET(*msg_word,
  343. !!(srng_params.flags & HAL_SRNG_RING_PTR_SWAP));
  344. /* word 4 */
  345. msg_word++;
  346. *msg_word = 0;
  347. HTT_SRING_SETUP_HEAD_OFFSET32_REMOTE_BASE_ADDR_LO_SET(*msg_word,
  348. hp_addr & 0xffffffff);
  349. /* word 5 */
  350. msg_word++;
  351. *msg_word = 0;
  352. HTT_SRING_SETUP_HEAD_OFFSET32_REMOTE_BASE_ADDR_HI_SET(*msg_word,
  353. (uint64_t)hp_addr >> 32);
  354. /* word 6 */
  355. msg_word++;
  356. *msg_word = 0;
  357. HTT_SRING_SETUP_TAIL_OFFSET32_REMOTE_BASE_ADDR_LO_SET(*msg_word,
  358. tp_addr & 0xffffffff);
  359. /* word 7 */
  360. msg_word++;
  361. *msg_word = 0;
  362. HTT_SRING_SETUP_TAIL_OFFSET32_REMOTE_BASE_ADDR_HI_SET(*msg_word,
  363. (uint64_t)tp_addr >> 32);
  364. /* word 8 */
  365. msg_word++;
  366. *msg_word = 0;
  367. HTT_SRING_SETUP_RING_MSI_ADDR_LO_SET(*msg_word,
  368. srng_params.msi_addr & 0xffffffff);
  369. /* word 9 */
  370. msg_word++;
  371. *msg_word = 0;
  372. HTT_SRING_SETUP_RING_MSI_ADDR_HI_SET(*msg_word,
  373. (uint64_t)(srng_params.msi_addr) >> 32);
  374. /* word 10 */
  375. msg_word++;
  376. *msg_word = 0;
  377. HTT_SRING_SETUP_RING_MSI_DATA_SET(*msg_word,
  378. srng_params.msi_data);
  379. /* word 11 */
  380. msg_word++;
  381. *msg_word = 0;
  382. HTT_SRING_SETUP_INTR_BATCH_COUNTER_TH_SET(*msg_word,
  383. srng_params.intr_batch_cntr_thres_entries *
  384. ring_entry_size);
  385. HTT_SRING_SETUP_INTR_TIMER_TH_SET(*msg_word,
  386. srng_params.intr_timer_thres_us >> 3);
  387. /* word 12 */
  388. msg_word++;
  389. *msg_word = 0;
  390. if (srng_params.flags & HAL_SRNG_LOW_THRES_INTR_ENABLE) {
  391. /* TODO: Setting low threshold to 1/8th of ring size - see
  392. * if this needs to be configurable
  393. */
  394. HTT_SRING_SETUP_INTR_LOW_TH_SET(*msg_word,
  395. srng_params.low_threshold);
  396. }
  397. /* "response_required" field should be set if a HTT response message is
  398. * required after setting up the ring.
  399. */
  400. pkt = htt_htc_pkt_alloc(soc);
  401. if (!pkt)
  402. goto fail1;
  403. pkt->soc_ctxt = NULL; /* not used during send-done callback */
  404. SET_HTC_PACKET_INFO_TX(
  405. &pkt->htc_pkt,
  406. dp_htt_h2t_send_complete_free_netbuf,
  407. qdf_nbuf_data(htt_msg),
  408. qdf_nbuf_len(htt_msg),
  409. soc->htc_endpoint,
  410. 1); /* tag - not relevant here */
  411. SET_HTC_PACKET_NET_BUF_CONTEXT(&pkt->htc_pkt, htt_msg);
  412. htc_send_pkt(soc->htc_soc, &pkt->htc_pkt);
  413. return 0;
  414. fail1:
  415. qdf_nbuf_free(htt_msg);
  416. fail0:
  417. return QDF_STATUS_E_FAILURE;
  418. }
  419. /*
  420. * htt_soc_attach_target() - SOC level HTT setup
  421. * @htt_soc: HTT SOC handle
  422. *
  423. * Return: 0 on success; error code on failure
  424. */
  425. int htt_soc_attach_target(void *htt_soc)
  426. {
  427. struct htt_soc *soc = (struct htt_soc *)htt_soc;
  428. return htt_h2t_ver_req_msg(soc);
  429. }
  430. /*
  431. * dp_htt_t2h_msg_handler() - Generic Target to host Msg/event handler
  432. * @context: Opaque context (HTT SOC handle)
  433. * @pkt: HTC packet
  434. */
  435. static void dp_htt_t2h_msg_handler(void *context, HTC_PACKET *pkt)
  436. {
  437. struct htt_soc *soc = (struct htt_soc *) context;
  438. qdf_nbuf_t htt_t2h_msg = (qdf_nbuf_t) pkt->pPktContext;
  439. u_int32_t *msg_word;
  440. enum htt_t2h_msg_type msg_type;
  441. /* check for successful message reception */
  442. if (pkt->Status != A_OK) {
  443. if (pkt->Status != A_ECANCELED)
  444. soc->stats.htc_err_cnt++;
  445. qdf_nbuf_free(htt_t2h_msg);
  446. return;
  447. }
  448. /* TODO: Check if we should pop the HTC/HTT header alignment padding */
  449. msg_word = (u_int32_t *) qdf_nbuf_data(htt_t2h_msg);
  450. msg_type = HTT_T2H_MSG_TYPE_GET(*msg_word);
  451. switch (msg_type) {
  452. case HTT_T2H_MSG_TYPE_PEER_MAP:
  453. {
  454. u_int8_t mac_addr_deswizzle_buf[HTT_MAC_ADDR_LEN];
  455. u_int8_t *peer_mac_addr;
  456. u_int16_t peer_id;
  457. u_int8_t vdev_id;
  458. peer_id = HTT_RX_PEER_MAP_PEER_ID_GET(*msg_word);
  459. vdev_id = HTT_RX_PEER_MAP_VDEV_ID_GET(*msg_word);
  460. peer_mac_addr = htt_t2h_mac_addr_deswizzle(
  461. (u_int8_t *) (msg_word+1),
  462. &mac_addr_deswizzle_buf[0]);
  463. dp_rx_peer_map_handler(
  464. soc->dp_soc, peer_id, vdev_id, peer_mac_addr);
  465. break;
  466. }
  467. case HTT_T2H_MSG_TYPE_PEER_UNMAP:
  468. {
  469. u_int16_t peer_id;
  470. peer_id = HTT_RX_PEER_UNMAP_PEER_ID_GET(*msg_word);
  471. dp_rx_peer_unmap_handler(soc->dp_soc, peer_id);
  472. break;
  473. }
  474. case HTT_T2H_MSG_TYPE_SEC_IND:
  475. {
  476. u_int16_t peer_id;
  477. enum htt_sec_type sec_type;
  478. int is_unicast;
  479. peer_id = HTT_SEC_IND_PEER_ID_GET(*msg_word);
  480. sec_type = HTT_SEC_IND_SEC_TYPE_GET(*msg_word);
  481. is_unicast = HTT_SEC_IND_UNICAST_GET(*msg_word);
  482. /* point to the first part of the Michael key */
  483. msg_word++;
  484. dp_rx_sec_ind_handler(
  485. soc->dp_soc, peer_id, sec_type, is_unicast,
  486. msg_word, msg_word + 2);
  487. break;
  488. }
  489. #ifdef notyet
  490. #ifndef REMOVE_PKT_LOG
  491. case HTT_T2H_MSG_TYPE_PKTLOG:
  492. {
  493. u_int32_t *pl_hdr;
  494. pl_hdr = (msg_word + 1);
  495. wdi_event_handler(WDI_EVENT_OFFLOAD_ALL, soc->dp_soc,
  496. pl_hdr, HTT_INVALID_PEER, WDI_NO_VAL);
  497. break;
  498. }
  499. #endif
  500. #endif /* notyet */
  501. case HTT_T2H_MSG_TYPE_VERSION_CONF:
  502. {
  503. soc->tgt_ver.major = HTT_VER_CONF_MAJOR_GET(*msg_word);
  504. soc->tgt_ver.minor = HTT_VER_CONF_MINOR_GET(*msg_word);
  505. QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_INFO_HIGH,
  506. "target uses HTT version %d.%d; host uses %d.%d\n",
  507. soc->tgt_ver.major, soc->tgt_ver.minor,
  508. HTT_CURRENT_VERSION_MAJOR,
  509. HTT_CURRENT_VERSION_MINOR);
  510. if (soc->tgt_ver.major != HTT_CURRENT_VERSION_MAJOR) {
  511. QDF_TRACE(QDF_MODULE_ID_TXRX,
  512. QDF_TRACE_LEVEL_ERROR,
  513. "*** Incompatible host/target HTT versions!\n");
  514. }
  515. /* abort if the target is incompatible with the host */
  516. qdf_assert(soc->tgt_ver.major ==
  517. HTT_CURRENT_VERSION_MAJOR);
  518. if (soc->tgt_ver.minor != HTT_CURRENT_VERSION_MINOR) {
  519. QDF_TRACE(QDF_MODULE_ID_TXRX,
  520. QDF_TRACE_LEVEL_WARN,
  521. "*** Warning: host/target HTT versions"
  522. " are different, though compatible!\n");
  523. }
  524. break;
  525. }
  526. default:
  527. break;
  528. };
  529. /* Free the indication buffer */
  530. qdf_nbuf_free(htt_t2h_msg);
  531. }
  532. /*
  533. * dp_htt_h2t_full() - Send full handler (called from HTC)
  534. * @context: Opaque context (HTT SOC handle)
  535. * @pkt: HTC packet
  536. *
  537. * Return: HTC_SEND_FULL_ACTION
  538. */
  539. static HTC_SEND_FULL_ACTION
  540. dp_htt_h2t_full(void *context, HTC_PACKET *pkt)
  541. {
  542. return HTC_SEND_FULL_KEEP;
  543. }
  544. /*
  545. * htt_htc_soc_attach() - Register SOC level HTT instance with HTC
  546. * @htt_soc: HTT SOC handle
  547. *
  548. * Return: 0 on success; error code on failure
  549. */
  550. static int
  551. htt_htc_soc_attach(struct htt_soc *soc)
  552. {
  553. HTC_SERVICE_CONNECT_REQ connect;
  554. HTC_SERVICE_CONNECT_RESP response;
  555. A_STATUS status;
  556. qdf_mem_set(&connect, sizeof(connect), 0);
  557. qdf_mem_set(&response, sizeof(response), 0);
  558. connect.pMetaData = NULL;
  559. connect.MetaDataLength = 0;
  560. connect.EpCallbacks.pContext = soc;
  561. connect.EpCallbacks.EpTxComplete = dp_htt_h2t_send_complete;
  562. connect.EpCallbacks.EpTxCompleteMultiple = NULL;
  563. connect.EpCallbacks.EpRecv = dp_htt_t2h_msg_handler;
  564. /* rx buffers currently are provided by HIF, not by EpRecvRefill */
  565. connect.EpCallbacks.EpRecvRefill = NULL;
  566. /* N/A, fill is done by HIF */
  567. connect.EpCallbacks.RecvRefillWaterMark = 1;
  568. connect.EpCallbacks.EpSendFull = dp_htt_h2t_full;
  569. /*
  570. * Specify how deep to let a queue get before htc_send_pkt will
  571. * call the EpSendFull function due to excessive send queue depth.
  572. */
  573. connect.MaxSendQueueDepth = DP_HTT_MAX_SEND_QUEUE_DEPTH;
  574. /* disable flow control for HTT data message service */
  575. connect.ConnectionFlags |= HTC_CONNECT_FLAGS_DISABLE_CREDIT_FLOW_CTRL;
  576. /* connect to control service */
  577. connect.service_id = HTT_DATA_MSG_SVC;
  578. status = htc_connect_service(soc->htc_soc, &connect, &response);
  579. if (status != A_OK)
  580. return QDF_STATUS_E_FAILURE;
  581. soc->htc_endpoint = response.Endpoint;
  582. return 0; /* success */
  583. }
  584. /*
  585. * htt_soc_attach() - SOC level HTT initialization
  586. * @dp_soc: Opaque Data path SOC handle
  587. * @osif_soc: Opaque OSIF SOC handle
  588. * @htc_soc: SOC level HTC handle
  589. * @hal_soc: Opaque HAL SOC handle
  590. * @osdev: QDF device
  591. *
  592. * Return: HTT handle on success; NULL on failure
  593. */
  594. void *
  595. htt_soc_attach(void *dp_soc, void *osif_soc, HTC_HANDLE htc_soc,
  596. void *hal_soc, qdf_device_t osdev)
  597. {
  598. struct htt_soc *soc;
  599. int i;
  600. soc = qdf_mem_malloc(sizeof(*soc));
  601. if (!soc)
  602. goto fail1;
  603. soc->osdev = osdev;
  604. soc->osif_soc = osif_soc;
  605. soc->dp_soc = dp_soc;
  606. soc->htc_soc = htc_soc;
  607. soc->hal_soc = hal_soc;
  608. /* TODO: See if any NSS related context is requred in htt_soc */
  609. soc->htt_htc_pkt_freelist = NULL;
  610. if (htt_htc_soc_attach(soc))
  611. goto fail2;
  612. /* TODO: See if any Rx data specific intialization is required. For
  613. * MCL use cases, the data will be received as single packet and
  614. * should not required any descriptor or reorder handling
  615. */
  616. HTT_TX_MUTEX_INIT(&soc->htt_tx_mutex);
  617. /* pre-allocate some HTC_PACKET objects */
  618. for (i = 0; i < HTT_HTC_PKT_POOL_INIT_SIZE; i++) {
  619. struct dp_htt_htc_pkt_union *pkt;
  620. pkt = qdf_mem_malloc(sizeof(*pkt));
  621. if (!pkt)
  622. break;
  623. htt_htc_pkt_free(soc, &pkt->u.pkt);
  624. }
  625. return soc;
  626. fail2:
  627. qdf_mem_free(soc);
  628. fail1:
  629. return NULL;
  630. }
  631. /*
  632. * htt_soc_detach() - Detach SOC level HTT
  633. * @htt_soc: HTT SOC handle
  634. */
  635. void
  636. htt_soc_detach(void *htt_soc)
  637. {
  638. struct htt_soc *soc = (struct htt_soc *)htt_soc;
  639. htt_htc_pkt_pool_free(soc);
  640. HTT_TX_MUTEX_DESTROY(&soc->htt_tx_mutex);
  641. qdf_mem_free(soc);
  642. }