dp_htt.c 20 KB

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