dp_htt.c 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741
  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. #ifdef QCA_HOST2FW_RXBUF_RING
  234. if (srng_params.ring_id ==
  235. (HAL_SRNG_WMAC1_SW2RXDMA0_BUF)) {
  236. htt_ring_id = HTT_HOST1_TO_FW_RXBUF_RING;
  237. htt_ring_type = HTT_SW_TO_SW_RING;
  238. #else
  239. if (srng_params.ring_id ==
  240. (HAL_SRNG_WMAC1_SW2RXDMA0_BUF +
  241. (mac_id * HAL_MAX_RINGS_PER_LMAC))) {
  242. htt_ring_id = HTT_RXDMA_HOST_BUF_RING;
  243. htt_ring_type = HTT_SW_TO_HW_RING;
  244. #endif
  245. } else if (srng_params.ring_id ==
  246. (HAL_SRNG_WMAC1_SW2RXDMA1_BUF +
  247. (mac_id * HAL_MAX_RINGS_PER_LMAC))) {
  248. htt_ring_id = HTT_RXDMA_HOST_BUF_RING;
  249. htt_ring_type = HTT_SW_TO_HW_RING;
  250. } else {
  251. QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
  252. "%s: Ring %d currently not supported\n",
  253. __func__, srng_params.ring_id);
  254. goto fail1;
  255. }
  256. QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
  257. "%s: ring_type %d ring_id %d\n",
  258. __func__, hal_ring_type, srng_params.ring_id);
  259. QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
  260. "%s: hp_addr 0x%llx tp_addr 0x%llx\n",
  261. __func__, (uint64_t)hp_addr, (uint64_t)tp_addr);
  262. QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
  263. "%s: htt_ring_id %d\n", __func__, htt_ring_id);
  264. break;
  265. case RXDMA_MONITOR_BUF:
  266. htt_ring_id = HTT_RXDMA_MONITOR_BUF_RING;
  267. htt_ring_type = HTT_SW_TO_HW_RING;
  268. break;
  269. case RXDMA_MONITOR_STATUS:
  270. htt_ring_id = HTT_RXDMA_MONITOR_STATUS_RING;
  271. htt_ring_type = HTT_SW_TO_HW_RING;
  272. break;
  273. case RXDMA_MONITOR_DST:
  274. htt_ring_id = HTT_RXDMA_MONITOR_DEST_RING;
  275. htt_ring_type = HTT_HW_TO_SW_RING;
  276. break;
  277. case RXDMA_DST:
  278. default:
  279. QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
  280. "%s: Ring currently not supported\n", __func__);
  281. goto fail1;
  282. }
  283. /*
  284. * Set the length of the message.
  285. * The contribution from the HTC_HDR_ALIGNMENT_PADDING is added
  286. * separately during the below call to qdf_nbuf_push_head.
  287. * The contribution from the HTC header is added separately inside HTC.
  288. */
  289. if (qdf_nbuf_put_tail(htt_msg, HTT_SRING_SETUP_SZ) == NULL) {
  290. QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
  291. "%s: Failed to expand head for SRING_SETUP msg\n",
  292. __func__);
  293. return QDF_STATUS_E_FAILURE;
  294. }
  295. msg_word = (uint32_t *)qdf_nbuf_data(htt_msg);
  296. /* rewind beyond alignment pad to get to the HTC header reserved area */
  297. qdf_nbuf_push_head(htt_msg, HTC_HDR_ALIGNMENT_PADDING);
  298. /* word 0 */
  299. *msg_word = 0;
  300. HTT_H2T_MSG_TYPE_SET(*msg_word, HTT_H2T_MSG_TYPE_SRING_SETUP);
  301. if (htt_ring_type == HTT_SW_TO_HW_RING)
  302. HTT_SRING_SETUP_PDEV_ID_SET(*msg_word,
  303. DP_SW2HW_MACID(mac_id));
  304. else
  305. HTT_SRING_SETUP_PDEV_ID_SET(*msg_word, mac_id);
  306. QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
  307. "%s: mac_id %d\n", __func__, mac_id);
  308. HTT_SRING_SETUP_RING_TYPE_SET(*msg_word, htt_ring_type);
  309. /* TODO: Discuss with FW on changing this to unique ID and using
  310. * htt_ring_type to send the type of ring
  311. */
  312. HTT_SRING_SETUP_RING_ID_SET(*msg_word, htt_ring_id);
  313. /* word 1 */
  314. msg_word++;
  315. *msg_word = 0;
  316. HTT_SRING_SETUP_RING_BASE_ADDR_LO_SET(*msg_word,
  317. srng_params.ring_base_paddr & 0xffffffff);
  318. /* word 2 */
  319. msg_word++;
  320. *msg_word = 0;
  321. HTT_SRING_SETUP_RING_BASE_ADDR_HI_SET(*msg_word,
  322. (uint64_t)srng_params.ring_base_paddr >> 32);
  323. /* word 3 */
  324. msg_word++;
  325. *msg_word = 0;
  326. HTT_SRING_SETUP_ENTRY_SIZE_SET(*msg_word, ring_entry_size);
  327. HTT_SRING_SETUP_RING_SIZE_SET(*msg_word,
  328. (ring_entry_size * srng_params.num_entries));
  329. QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
  330. "%s: entry_size %d\n", __func__,
  331. ring_entry_size);
  332. QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
  333. "%s: num_entries %d\n", __func__,
  334. srng_params.num_entries);
  335. QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
  336. "%s: ring_size %d\n", __func__,
  337. (ring_entry_size * srng_params.num_entries));
  338. if (htt_ring_type == HTT_SW_TO_HW_RING)
  339. HTT_SRING_SETUP_RING_MISC_CFG_FLAG_LOOPCOUNT_DISABLE_SET(
  340. *msg_word, 1);
  341. HTT_SRING_SETUP_RING_MISC_CFG_FLAG_MSI_SWAP_SET(*msg_word,
  342. !!(srng_params.flags & HAL_SRNG_MSI_SWAP));
  343. HTT_SRING_SETUP_RING_MISC_CFG_FLAG_TLV_SWAP_SET(*msg_word,
  344. !!(srng_params.flags & HAL_SRNG_DATA_TLV_SWAP));
  345. HTT_SRING_SETUP_RING_MISC_CFG_FLAG_HOST_FW_SWAP_SET(*msg_word,
  346. !!(srng_params.flags & HAL_SRNG_RING_PTR_SWAP));
  347. /* word 4 */
  348. msg_word++;
  349. *msg_word = 0;
  350. HTT_SRING_SETUP_HEAD_OFFSET32_REMOTE_BASE_ADDR_LO_SET(*msg_word,
  351. hp_addr & 0xffffffff);
  352. /* word 5 */
  353. msg_word++;
  354. *msg_word = 0;
  355. HTT_SRING_SETUP_HEAD_OFFSET32_REMOTE_BASE_ADDR_HI_SET(*msg_word,
  356. (uint64_t)hp_addr >> 32);
  357. /* word 6 */
  358. msg_word++;
  359. *msg_word = 0;
  360. HTT_SRING_SETUP_TAIL_OFFSET32_REMOTE_BASE_ADDR_LO_SET(*msg_word,
  361. tp_addr & 0xffffffff);
  362. /* word 7 */
  363. msg_word++;
  364. *msg_word = 0;
  365. HTT_SRING_SETUP_TAIL_OFFSET32_REMOTE_BASE_ADDR_HI_SET(*msg_word,
  366. (uint64_t)tp_addr >> 32);
  367. /* word 8 */
  368. msg_word++;
  369. *msg_word = 0;
  370. HTT_SRING_SETUP_RING_MSI_ADDR_LO_SET(*msg_word,
  371. srng_params.msi_addr & 0xffffffff);
  372. /* word 9 */
  373. msg_word++;
  374. *msg_word = 0;
  375. HTT_SRING_SETUP_RING_MSI_ADDR_HI_SET(*msg_word,
  376. (uint64_t)(srng_params.msi_addr) >> 32);
  377. /* word 10 */
  378. msg_word++;
  379. *msg_word = 0;
  380. HTT_SRING_SETUP_RING_MSI_DATA_SET(*msg_word,
  381. srng_params.msi_data);
  382. /* word 11 */
  383. msg_word++;
  384. *msg_word = 0;
  385. HTT_SRING_SETUP_INTR_BATCH_COUNTER_TH_SET(*msg_word,
  386. srng_params.intr_batch_cntr_thres_entries *
  387. ring_entry_size);
  388. HTT_SRING_SETUP_INTR_TIMER_TH_SET(*msg_word,
  389. srng_params.intr_timer_thres_us >> 3);
  390. /* word 12 */
  391. msg_word++;
  392. *msg_word = 0;
  393. if (srng_params.flags & HAL_SRNG_LOW_THRES_INTR_ENABLE) {
  394. /* TODO: Setting low threshold to 1/8th of ring size - see
  395. * if this needs to be configurable
  396. */
  397. HTT_SRING_SETUP_INTR_LOW_TH_SET(*msg_word,
  398. srng_params.low_threshold);
  399. }
  400. /* "response_required" field should be set if a HTT response message is
  401. * required after setting up the ring.
  402. */
  403. pkt = htt_htc_pkt_alloc(soc);
  404. if (!pkt)
  405. goto fail1;
  406. pkt->soc_ctxt = NULL; /* not used during send-done callback */
  407. SET_HTC_PACKET_INFO_TX(
  408. &pkt->htc_pkt,
  409. dp_htt_h2t_send_complete_free_netbuf,
  410. qdf_nbuf_data(htt_msg),
  411. qdf_nbuf_len(htt_msg),
  412. soc->htc_endpoint,
  413. 1); /* tag - not relevant here */
  414. SET_HTC_PACKET_NET_BUF_CONTEXT(&pkt->htc_pkt, htt_msg);
  415. htc_send_pkt(soc->htc_soc, &pkt->htc_pkt);
  416. return 0;
  417. fail1:
  418. qdf_nbuf_free(htt_msg);
  419. fail0:
  420. return QDF_STATUS_E_FAILURE;
  421. }
  422. /*
  423. * htt_soc_attach_target() - SOC level HTT setup
  424. * @htt_soc: HTT SOC handle
  425. *
  426. * Return: 0 on success; error code on failure
  427. */
  428. int htt_soc_attach_target(void *htt_soc)
  429. {
  430. struct htt_soc *soc = (struct htt_soc *)htt_soc;
  431. return htt_h2t_ver_req_msg(soc);
  432. }
  433. /*
  434. * dp_htt_t2h_msg_handler() - Generic Target to host Msg/event handler
  435. * @context: Opaque context (HTT SOC handle)
  436. * @pkt: HTC packet
  437. */
  438. static void dp_htt_t2h_msg_handler(void *context, HTC_PACKET *pkt)
  439. {
  440. struct htt_soc *soc = (struct htt_soc *) context;
  441. qdf_nbuf_t htt_t2h_msg = (qdf_nbuf_t) pkt->pPktContext;
  442. u_int32_t *msg_word;
  443. enum htt_t2h_msg_type msg_type;
  444. /* check for successful message reception */
  445. if (pkt->Status != A_OK) {
  446. if (pkt->Status != A_ECANCELED)
  447. soc->stats.htc_err_cnt++;
  448. qdf_nbuf_free(htt_t2h_msg);
  449. return;
  450. }
  451. /* TODO: Check if we should pop the HTC/HTT header alignment padding */
  452. msg_word = (u_int32_t *) qdf_nbuf_data(htt_t2h_msg);
  453. msg_type = HTT_T2H_MSG_TYPE_GET(*msg_word);
  454. switch (msg_type) {
  455. case HTT_T2H_MSG_TYPE_PEER_MAP:
  456. {
  457. u_int8_t mac_addr_deswizzle_buf[HTT_MAC_ADDR_LEN];
  458. u_int8_t *peer_mac_addr;
  459. u_int16_t peer_id;
  460. u_int8_t vdev_id;
  461. peer_id = HTT_RX_PEER_MAP_PEER_ID_GET(*msg_word);
  462. vdev_id = HTT_RX_PEER_MAP_VDEV_ID_GET(*msg_word);
  463. peer_mac_addr = htt_t2h_mac_addr_deswizzle(
  464. (u_int8_t *) (msg_word+1),
  465. &mac_addr_deswizzle_buf[0]);
  466. dp_rx_peer_map_handler(
  467. soc->dp_soc, peer_id, vdev_id, peer_mac_addr);
  468. break;
  469. }
  470. case HTT_T2H_MSG_TYPE_PEER_UNMAP:
  471. {
  472. u_int16_t peer_id;
  473. peer_id = HTT_RX_PEER_UNMAP_PEER_ID_GET(*msg_word);
  474. dp_rx_peer_unmap_handler(soc->dp_soc, peer_id);
  475. break;
  476. }
  477. case HTT_T2H_MSG_TYPE_SEC_IND:
  478. {
  479. u_int16_t peer_id;
  480. enum htt_sec_type sec_type;
  481. int is_unicast;
  482. peer_id = HTT_SEC_IND_PEER_ID_GET(*msg_word);
  483. sec_type = HTT_SEC_IND_SEC_TYPE_GET(*msg_word);
  484. is_unicast = HTT_SEC_IND_UNICAST_GET(*msg_word);
  485. /* point to the first part of the Michael key */
  486. msg_word++;
  487. dp_rx_sec_ind_handler(
  488. soc->dp_soc, peer_id, sec_type, is_unicast,
  489. msg_word, msg_word + 2);
  490. break;
  491. }
  492. #ifdef notyet
  493. #ifndef REMOVE_PKT_LOG
  494. case HTT_T2H_MSG_TYPE_PKTLOG:
  495. {
  496. u_int32_t *pl_hdr;
  497. pl_hdr = (msg_word + 1);
  498. wdi_event_handler(WDI_EVENT_OFFLOAD_ALL, soc->dp_soc,
  499. pl_hdr, HTT_INVALID_PEER, WDI_NO_VAL);
  500. break;
  501. }
  502. #endif
  503. #endif /* notyet */
  504. case HTT_T2H_MSG_TYPE_VERSION_CONF:
  505. {
  506. soc->tgt_ver.major = HTT_VER_CONF_MAJOR_GET(*msg_word);
  507. soc->tgt_ver.minor = HTT_VER_CONF_MINOR_GET(*msg_word);
  508. QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_INFO_HIGH,
  509. "target uses HTT version %d.%d; host uses %d.%d\n",
  510. soc->tgt_ver.major, soc->tgt_ver.minor,
  511. HTT_CURRENT_VERSION_MAJOR,
  512. HTT_CURRENT_VERSION_MINOR);
  513. if (soc->tgt_ver.major != HTT_CURRENT_VERSION_MAJOR) {
  514. QDF_TRACE(QDF_MODULE_ID_TXRX,
  515. QDF_TRACE_LEVEL_ERROR,
  516. "*** Incompatible host/target HTT versions!\n");
  517. }
  518. /* abort if the target is incompatible with the host */
  519. qdf_assert(soc->tgt_ver.major ==
  520. HTT_CURRENT_VERSION_MAJOR);
  521. if (soc->tgt_ver.minor != HTT_CURRENT_VERSION_MINOR) {
  522. QDF_TRACE(QDF_MODULE_ID_TXRX,
  523. QDF_TRACE_LEVEL_WARN,
  524. "*** Warning: host/target HTT versions"
  525. " are different, though compatible!\n");
  526. }
  527. break;
  528. }
  529. default:
  530. break;
  531. };
  532. /* Free the indication buffer */
  533. qdf_nbuf_free(htt_t2h_msg);
  534. }
  535. /*
  536. * dp_htt_h2t_full() - Send full handler (called from HTC)
  537. * @context: Opaque context (HTT SOC handle)
  538. * @pkt: HTC packet
  539. *
  540. * Return: HTC_SEND_FULL_ACTION
  541. */
  542. static HTC_SEND_FULL_ACTION
  543. dp_htt_h2t_full(void *context, HTC_PACKET *pkt)
  544. {
  545. return HTC_SEND_FULL_KEEP;
  546. }
  547. /*
  548. * htt_htc_soc_attach() - Register SOC level HTT instance with HTC
  549. * @htt_soc: HTT SOC handle
  550. *
  551. * Return: 0 on success; error code on failure
  552. */
  553. static int
  554. htt_htc_soc_attach(struct htt_soc *soc)
  555. {
  556. HTC_SERVICE_CONNECT_REQ connect;
  557. HTC_SERVICE_CONNECT_RESP response;
  558. A_STATUS status;
  559. qdf_mem_set(&connect, sizeof(connect), 0);
  560. qdf_mem_set(&response, sizeof(response), 0);
  561. connect.pMetaData = NULL;
  562. connect.MetaDataLength = 0;
  563. connect.EpCallbacks.pContext = soc;
  564. connect.EpCallbacks.EpTxComplete = dp_htt_h2t_send_complete;
  565. connect.EpCallbacks.EpTxCompleteMultiple = NULL;
  566. connect.EpCallbacks.EpRecv = dp_htt_t2h_msg_handler;
  567. /* rx buffers currently are provided by HIF, not by EpRecvRefill */
  568. connect.EpCallbacks.EpRecvRefill = NULL;
  569. /* N/A, fill is done by HIF */
  570. connect.EpCallbacks.RecvRefillWaterMark = 1;
  571. connect.EpCallbacks.EpSendFull = dp_htt_h2t_full;
  572. /*
  573. * Specify how deep to let a queue get before htc_send_pkt will
  574. * call the EpSendFull function due to excessive send queue depth.
  575. */
  576. connect.MaxSendQueueDepth = DP_HTT_MAX_SEND_QUEUE_DEPTH;
  577. /* disable flow control for HTT data message service */
  578. connect.ConnectionFlags |= HTC_CONNECT_FLAGS_DISABLE_CREDIT_FLOW_CTRL;
  579. /* connect to control service */
  580. connect.service_id = HTT_DATA_MSG_SVC;
  581. status = htc_connect_service(soc->htc_soc, &connect, &response);
  582. if (status != A_OK)
  583. return QDF_STATUS_E_FAILURE;
  584. soc->htc_endpoint = response.Endpoint;
  585. return 0; /* success */
  586. }
  587. /*
  588. * htt_soc_attach() - SOC level HTT initialization
  589. * @dp_soc: Opaque Data path SOC handle
  590. * @osif_soc: Opaque OSIF SOC handle
  591. * @htc_soc: SOC level HTC handle
  592. * @hal_soc: Opaque HAL SOC handle
  593. * @osdev: QDF device
  594. *
  595. * Return: HTT handle on success; NULL on failure
  596. */
  597. void *
  598. htt_soc_attach(void *dp_soc, void *osif_soc, HTC_HANDLE htc_soc,
  599. void *hal_soc, qdf_device_t osdev)
  600. {
  601. struct htt_soc *soc;
  602. int i;
  603. soc = qdf_mem_malloc(sizeof(*soc));
  604. if (!soc)
  605. goto fail1;
  606. soc->osdev = osdev;
  607. soc->osif_soc = osif_soc;
  608. soc->dp_soc = dp_soc;
  609. soc->htc_soc = htc_soc;
  610. soc->hal_soc = hal_soc;
  611. /* TODO: See if any NSS related context is requred in htt_soc */
  612. soc->htt_htc_pkt_freelist = NULL;
  613. if (htt_htc_soc_attach(soc))
  614. goto fail2;
  615. /* TODO: See if any Rx data specific intialization is required. For
  616. * MCL use cases, the data will be received as single packet and
  617. * should not required any descriptor or reorder handling
  618. */
  619. HTT_TX_MUTEX_INIT(&soc->htt_tx_mutex);
  620. /* pre-allocate some HTC_PACKET objects */
  621. for (i = 0; i < HTT_HTC_PKT_POOL_INIT_SIZE; i++) {
  622. struct dp_htt_htc_pkt_union *pkt;
  623. pkt = qdf_mem_malloc(sizeof(*pkt));
  624. if (!pkt)
  625. break;
  626. htt_htc_pkt_free(soc, &pkt->u.pkt);
  627. }
  628. return soc;
  629. fail2:
  630. qdf_mem_free(soc);
  631. fail1:
  632. return NULL;
  633. }
  634. /*
  635. * htt_soc_detach() - Detach SOC level HTT
  636. * @htt_soc: HTT SOC handle
  637. */
  638. void
  639. htt_soc_detach(void *htt_soc)
  640. {
  641. struct htt_soc *soc = (struct htt_soc *)htt_soc;
  642. htt_htc_pkt_pool_free(soc);
  643. HTT_TX_MUTEX_DESTROY(&soc->htt_tx_mutex);
  644. qdf_mem_free(soc);
  645. }