dp_htt.c 21 KB

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