dp_ipa.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551
  1. /*
  2. * Copyright (c) 2017, The Linux Foundation. All rights reserved.
  3. *
  4. * Permission to use, copy, modify, and/or distribute this software for any
  5. * purpose with or without fee is hereby granted, provided that the above
  6. * copyright notice and this permission notice appear in all copies.
  7. *
  8. * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
  9. * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
  10. * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
  11. * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  12. * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
  13. * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  14. * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  15. */
  16. #ifdef IPA_OFFLOAD
  17. #include <ipa_wdi3.h>
  18. #include <qdf_types.h>
  19. #include <qdf_lock.h>
  20. #include <hal_api.h>
  21. #include <hif.h>
  22. #include <htt.h>
  23. #include <wdi_event.h>
  24. #include <queue.h>
  25. #include "dp_types.h"
  26. #include "dp_tx.h"
  27. #include "dp_ipa.h"
  28. /**
  29. * dp_ipa_uc_get_resource() - Client request resource information
  30. * @ppdev - handle to the device instance
  31. *
  32. * IPA client will request IPA UC related resource information
  33. * Resource information will be distributed to IPA module
  34. * All of the required resources should be pre-allocated
  35. *
  36. * Return: QDF_STATUS
  37. */
  38. QDF_STATUS dp_ipa_get_resource(struct cdp_pdev *ppdev)
  39. {
  40. struct dp_pdev *pdev = (struct dp_pdev *)ppdev;
  41. struct dp_soc *soc = pdev->soc;
  42. struct dp_ipa_resources *ipa_res = &pdev->ipa_resource;
  43. ipa_res->tx_ring_base_paddr =
  44. soc->ipa_uc_tx_rsc.ipa_tcl_ring_base_paddr;
  45. ipa_res->tx_ring_size =
  46. soc->ipa_uc_tx_rsc.ipa_tcl_ring_size;
  47. ipa_res->tx_num_alloc_buffer =
  48. (uint32_t)soc->ipa_uc_tx_rsc.alloc_tx_buf_cnt;
  49. ipa_res->tx_comp_ring_base_paddr =
  50. soc->ipa_uc_tx_rsc.ipa_wbm_ring_base_paddr;
  51. ipa_res->tx_comp_ring_size =
  52. soc->ipa_uc_tx_rsc.ipa_wbm_ring_size;
  53. ipa_res->rx_rdy_ring_base_paddr =
  54. soc->ipa_uc_rx_rsc.ipa_reo_ring_base_paddr;
  55. ipa_res->rx_rdy_ring_size =
  56. soc->ipa_uc_rx_rsc.ipa_reo_ring_size;
  57. ipa_res->rx_refill_ring_base_paddr =
  58. soc->ipa_uc_rx_rsc.ipa_rx_refill_buf_ring_base_paddr;
  59. ipa_res->rx_refill_ring_size =
  60. soc->ipa_uc_rx_rsc.ipa_rx_refill_buf_ring_size;
  61. if ((0 == ipa_res->tx_comp_ring_base_paddr) ||
  62. (0 == ipa_res->rx_rdy_ring_base_paddr))
  63. return QDF_STATUS_E_FAILURE;
  64. return QDF_STATUS_SUCCESS;
  65. }
  66. /**
  67. * dp_ipa_set_doorbell_paddr () - Set doorbell register physical address to SRNG
  68. * @ppdev - handle to the device instance
  69. *
  70. * Set TX_COMP_DOORBELL register physical address to WBM Head_Ptr_MemAddr_LSB
  71. * Set RX_READ_DOORBELL register physical address to REO Head_Ptr_MemAddr_LSB
  72. *
  73. * Return: none
  74. */
  75. QDF_STATUS dp_ipa_set_doorbell_paddr(struct cdp_pdev *ppdev)
  76. {
  77. struct dp_pdev *pdev = (struct dp_pdev *)ppdev;
  78. struct dp_soc *soc = pdev->soc;
  79. struct dp_ipa_resources *ipa_res = &pdev->ipa_resource;
  80. hal_srng_set_hp_paddr(soc->tx_comp_ring[IPA_TX_COMP_RING_IDX].
  81. hal_srng, ipa_res->tx_comp_doorbell_paddr);
  82. hal_srng_set_hp_paddr(soc->reo_dest_ring[IPA_REO_DEST_RING_IDX].
  83. hal_srng, ipa_res->rx_ready_doorbell_paddr);
  84. return QDF_STATUS_SUCCESS;
  85. }
  86. /**
  87. * dp_ipa_op_response() - Handle OP command response from firmware
  88. * @ppdev - handle to the device instance
  89. * @op_msg: op response message from firmware
  90. *
  91. * Return: none
  92. */
  93. QDF_STATUS dp_ipa_op_response(struct cdp_pdev *ppdev, uint8_t *op_msg)
  94. {
  95. struct dp_pdev *pdev = (struct dp_pdev *)ppdev;
  96. if (pdev->ipa_uc_op_cb) {
  97. pdev->ipa_uc_op_cb(op_msg, pdev->usr_ctxt);
  98. } else {
  99. QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
  100. "%s: IPA callback function is not registered", __func__);
  101. qdf_mem_free(op_msg);
  102. return QDF_STATUS_E_FAILURE;
  103. }
  104. return QDF_STATUS_SUCCESS;
  105. }
  106. /**
  107. * dp_ipa_register_op_cb() - Register OP handler function
  108. * @ppdev - handle to the device instance
  109. * @op_cb: handler function pointer
  110. *
  111. * Return: none
  112. */
  113. QDF_STATUS dp_ipa_register_op_cb(struct cdp_pdev *ppdev,
  114. ipa_uc_op_cb_type op_cb,
  115. void *usr_ctxt)
  116. {
  117. struct dp_pdev *pdev = (struct dp_pdev *)ppdev;
  118. pdev->ipa_uc_op_cb = op_cb;
  119. pdev->usr_ctxt = usr_ctxt;
  120. return QDF_STATUS_SUCCESS;
  121. }
  122. /**
  123. * dp_ipa_get_stat() - Get firmware wdi status
  124. * @ppdev - handle to the device instance
  125. *
  126. * Return: none
  127. */
  128. QDF_STATUS dp_ipa_get_stat(struct cdp_pdev *ppdev)
  129. {
  130. /* TBD */
  131. return QDF_STATUS_SUCCESS;
  132. }
  133. /**
  134. * dp_tx_send_ipa_data_frame() - send IPA data frame
  135. * @vdev: vdev
  136. * @skb: skb
  137. *
  138. * Return: skb/ NULL is for success
  139. */
  140. qdf_nbuf_t dp_tx_send_ipa_data_frame(struct cdp_vdev *vdev, qdf_nbuf_t skb)
  141. {
  142. qdf_nbuf_t ret;
  143. /* Terminate the (single-element) list of tx frames */
  144. qdf_nbuf_set_next(skb, NULL);
  145. ret = dp_tx_send((struct dp_vdev_t *)vdev, skb);
  146. if (ret) {
  147. QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
  148. "Failed to tx");
  149. return ret;
  150. }
  151. return NULL;
  152. }
  153. /**
  154. * dp_ipa_enable_autonomy() – Enable autonomy RX path
  155. * @pdev - handle to the device instance
  156. *
  157. * Set all RX packet route to IPA REO ring
  158. * Program Destination_Ring_Ctrl_IX_0 REO register to point IPA REO ring
  159. * Return: none
  160. */
  161. QDF_STATUS dp_ipa_enable_autonomy(struct cdp_pdev *ppdev)
  162. {
  163. struct dp_pdev *pdev = (struct dp_pdev *)ppdev;
  164. struct dp_soc *soc = pdev->soc;
  165. uint32_t remap_val;
  166. /* Call HAL API to remap REO rings to REO2IPA ring */
  167. remap_val = HAL_REO_REMAP_VAL(REO_REMAP_TCL, REO_REMAP_TCL) |
  168. HAL_REO_REMAP_VAL(REO_REMAP_SW1, REO_REMAP_SW4) |
  169. HAL_REO_REMAP_VAL(REO_REMAP_SW2, REO_REMAP_SW4) |
  170. HAL_REO_REMAP_VAL(REO_REMAP_SW3, REO_REMAP_SW4) |
  171. HAL_REO_REMAP_VAL(REO_REMAP_SW4, REO_REMAP_SW4) |
  172. HAL_REO_REMAP_VAL(REO_REMAP_RELEASE, REO_REMAP_RELEASE) |
  173. HAL_REO_REMAP_VAL(REO_REMAP_FW, REO_REMAP_FW) |
  174. HAL_REO_REMAP_VAL(REO_REMAP_UNUSED, REO_REMAP_FW);
  175. hal_reo_remap_IX0(soc->hal_soc, remap_val);
  176. return QDF_STATUS_SUCCESS;
  177. }
  178. /**
  179. * dp_ipa_disable_autonomy() – Disable autonomy RX path
  180. * @ppdev - handle to the device instance
  181. *
  182. * Disable RX packet routing to IPA REO
  183. * Program Destination_Ring_Ctrl_IX_0 REO register to disable
  184. * Return: none
  185. */
  186. QDF_STATUS dp_ipa_disable_autonomy(struct cdp_pdev *ppdev)
  187. {
  188. struct dp_pdev *pdev = (struct dp_pdev *)ppdev;
  189. struct dp_soc *soc = pdev->soc;
  190. uint32_t remap_val;
  191. /* Call HAL API to remap REO rings to REO2IPA ring */
  192. remap_val = HAL_REO_REMAP_VAL(REO_REMAP_TCL, REO_REMAP_TCL) |
  193. HAL_REO_REMAP_VAL(REO_REMAP_SW1, REO_REMAP_SW1) |
  194. HAL_REO_REMAP_VAL(REO_REMAP_SW2, REO_REMAP_SW2) |
  195. HAL_REO_REMAP_VAL(REO_REMAP_SW3, REO_REMAP_SW3) |
  196. HAL_REO_REMAP_VAL(REO_REMAP_SW4, REO_REMAP_SW2) |
  197. HAL_REO_REMAP_VAL(REO_REMAP_RELEASE, REO_REMAP_RELEASE) |
  198. HAL_REO_REMAP_VAL(REO_REMAP_FW, REO_REMAP_FW) |
  199. HAL_REO_REMAP_VAL(REO_REMAP_UNUSED, REO_REMAP_FW);
  200. hal_reo_remap_IX0(soc->hal_soc, remap_val);
  201. return QDF_STATUS_SUCCESS;
  202. }
  203. /* This should be configurable per H/W configuration enable status */
  204. #define L3_HEADER_PADDING 2
  205. /**
  206. * dp_ipa_setup() - Setup and connect IPA pipes
  207. * @ppdev - handle to the device instance
  208. * @ipa_i2w_cb: IPA to WLAN callback
  209. * @ipa_w2i_cb: WLAN to IPA callback
  210. * @ipa_wdi_meter_notifier_cb: IPA WDI metering callback
  211. * @ipa_desc_size: IPA descriptor size
  212. * @ipa_priv: handle to the HTT instance
  213. * @is_rm_enabled: Is IPA RM enabled or not
  214. * @tx_pipe_handle: pointer to Tx pipe handle
  215. * @rx_pipe_handle: pointer to Rx pipe handle
  216. *
  217. * Return: QDF_STATUS
  218. */
  219. QDF_STATUS dp_ipa_setup(struct cdp_pdev *ppdev, void *ipa_i2w_cb,
  220. void *ipa_w2i_cb, void *ipa_wdi_meter_notifier_cb,
  221. uint32_t ipa_desc_size, void *ipa_priv,
  222. bool is_rm_enabled, uint32_t *tx_pipe_handle,
  223. uint32_t *rx_pipe_handle)
  224. {
  225. struct dp_pdev *pdev = (struct dp_pdev *)ppdev;
  226. struct dp_soc *soc = pdev->soc;
  227. struct dp_ipa_resources *ipa_res = &pdev->ipa_resource;
  228. struct ipa_wdi3_setup_info tx;
  229. struct ipa_wdi3_setup_info rx;
  230. struct ipa_wdi3_conn_in_params pipe_in;
  231. struct ipa_wdi3_conn_out_params pipe_out;
  232. int ret;
  233. qdf_mem_zero(&pipe_in, sizeof(struct ipa_wdi3_conn_in_params));
  234. qdf_mem_zero(&pipe_out, sizeof(struct ipa_wdi3_conn_out_params));
  235. /* TX PIPE */
  236. /**
  237. * Transfer Ring: WBM Ring
  238. * Transfer Ring Doorbell PA: WBM Tail Pointer Address
  239. * Event Ring: TCL ring
  240. * Event Ring Doorbell PA: TCL Head Pointer Address
  241. */
  242. tx.ipa_ep_cfg.nat.nat_en = IPA_BYPASS_NAT;
  243. tx.ipa_ep_cfg.hdr.hdr_len = DP_IPA_UC_WLAN_TX_HDR_LEN;
  244. tx.ipa_ep_cfg.hdr.hdr_ofst_pkt_size_valid = 0;
  245. tx.ipa_ep_cfg.hdr.hdr_ofst_pkt_size = 0;
  246. tx.ipa_ep_cfg.hdr.hdr_additional_const_len = 0;
  247. tx.ipa_ep_cfg.mode.mode = IPA_BASIC;
  248. tx.ipa_ep_cfg.hdr_ext.hdr_little_endian = true;
  249. tx.client = IPA_CLIENT_WLAN1_CONS;
  250. tx.transfer_ring_base_pa = ipa_res->tx_comp_ring_base_paddr;
  251. tx.transfer_ring_size = ipa_res->tx_comp_ring_size;
  252. tx.transfer_ring_doorbell_pa = /* WBM Tail Pointer Address */
  253. soc->ipa_uc_tx_rsc.ipa_wbm_tp_paddr;
  254. tx.event_ring_base_pa = ipa_res->tx_ring_base_paddr;
  255. tx.event_ring_size = ipa_res->tx_ring_size;
  256. tx.event_ring_doorbell_pa = /* TCL Head Pointer Address */
  257. soc->ipa_uc_tx_rsc.ipa_tcl_hp_paddr;
  258. tx.num_pkt_buffers = ipa_res->tx_num_alloc_buffer;
  259. tx.pkt_offset = 0;
  260. /* RX PIPE */
  261. /**
  262. * Transfer Ring: REO Ring
  263. * Transfer Ring Doorbell PA: REO Tail Pointer Address
  264. * Event Ring: FW ring
  265. * Event Ring Doorbell PA: FW Head Pointer Address
  266. */
  267. rx.ipa_ep_cfg.nat.nat_en = IPA_BYPASS_NAT;
  268. rx.ipa_ep_cfg.hdr.hdr_len = DP_IPA_UC_WLAN_RX_HDR_LEN;
  269. rx.ipa_ep_cfg.hdr.hdr_ofst_metadata_valid = 0;
  270. rx.ipa_ep_cfg.hdr.hdr_metadata_reg_valid = 1;
  271. rx.ipa_ep_cfg.mode.mode = IPA_BASIC;
  272. rx.client = IPA_CLIENT_WLAN1_PROD;
  273. rx.transfer_ring_base_pa = ipa_res->rx_rdy_ring_base_paddr;
  274. rx.transfer_ring_size = ipa_res->rx_rdy_ring_size;
  275. rx.transfer_ring_doorbell_pa = /* REO Tail Pointer Address */
  276. soc->ipa_uc_rx_rsc.ipa_reo_tp_paddr;
  277. rx.event_ring_base_pa = ipa_res->rx_refill_ring_base_paddr;
  278. rx.event_ring_size = ipa_res->rx_refill_ring_size;
  279. rx.event_ring_doorbell_pa = /* FW Head Pointer Address */
  280. soc->ipa_uc_rx_rsc.ipa_rx_refill_buf_hp_paddr;
  281. rx.pkt_offset = RX_PKT_TLVS_LEN + L3_HEADER_PADDING;
  282. pipe_in.notify = ipa_w2i_cb;
  283. pipe_in.priv = ipa_priv;
  284. memcpy(&pipe_in.tx, &tx, sizeof(struct ipa_wdi3_setup_info));
  285. memcpy(&pipe_in.rx, &rx, sizeof(struct ipa_wdi3_setup_info));
  286. /* Connect WDI IPA PIPE */
  287. ret = ipa_wdi3_conn_pipes(&pipe_in, &pipe_out);
  288. if (ret) {
  289. QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
  290. "ipa_wdi3_conn_pipes: IPA pipe setup failed: ret=%d",
  291. ret);
  292. return QDF_STATUS_E_FAILURE;
  293. }
  294. /* IPA uC Doorbell registers */
  295. QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_DEBUG,
  296. "Tx DB PA=0x%x, Rx DB PA=0x%x",
  297. (unsigned int)pipe_out.tx_uc_db_pa,
  298. (unsigned int)pipe_out.rx_uc_db_pa);
  299. ipa_res->tx_comp_doorbell_paddr = pipe_out.tx_uc_db_pa;
  300. ipa_res->rx_ready_doorbell_paddr = pipe_out.rx_uc_db_pa;
  301. QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_DEBUG,
  302. "Tx: %s=%pK, %s=%d, %s=%pK, %s=%pK, %s=%d, %s=%pK, %s=%d, %s=%pK",
  303. "transfer_ring_base_pa",
  304. (void *)pipe_in.tx.transfer_ring_base_pa,
  305. "transfer_ring_size",
  306. pipe_in.tx.transfer_ring_size,
  307. "transfer_ring_doorbell_pa",
  308. (void *)pipe_in.tx.transfer_ring_doorbell_pa,
  309. "event_ring_base_pa",
  310. (void *)pipe_in.tx.event_ring_base_pa,
  311. "event_ring_size",
  312. pipe_in.tx.event_ring_size,
  313. "event_ring_doorbell_pa",
  314. (void *)pipe_in.tx.event_ring_doorbell_pa,
  315. "num_pkt_buffers",
  316. pipe_in.tx.num_pkt_buffers,
  317. "tx_comp_doorbell_paddr",
  318. (void *)ipa_res->tx_comp_doorbell_paddr);
  319. QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_DEBUG,
  320. "Rx: %s=%pK, %s=%d, %s=%pK, %s=%pK, %s=%d, %s=%pK, %s=%d, %s=%pK",
  321. "transfer_ring_base_pa",
  322. (void *)pipe_in.rx.transfer_ring_base_pa,
  323. "transfer_ring_size",
  324. pipe_in.rx.transfer_ring_size,
  325. "transfer_ring_doorbell_pa",
  326. (void *)pipe_in.rx.transfer_ring_doorbell_pa,
  327. "event_ring_base_pa",
  328. (void *)pipe_in.rx.event_ring_base_pa,
  329. "event_ring_size",
  330. pipe_in.rx.event_ring_size,
  331. "event_ring_doorbell_pa",
  332. (void *)pipe_in.rx.event_ring_doorbell_pa,
  333. "num_pkt_buffers",
  334. pipe_in.rx.num_pkt_buffers,
  335. "tx_comp_doorbell_paddr",
  336. (void *)ipa_res->rx_ready_doorbell_paddr);
  337. return QDF_STATUS_SUCCESS;
  338. }
  339. /**
  340. * dp_ipa_cleanup() - Disconnect IPA pipes
  341. * @tx_pipe_handle: Tx pipe handle
  342. * @rx_pipe_handle: Rx pipe handle
  343. *
  344. * Return: QDF_STATUS
  345. */
  346. QDF_STATUS dp_ipa_cleanup(uint32_t tx_pipe_handle, uint32_t rx_pipe_handle)
  347. {
  348. int ret;
  349. ret = ipa_wdi3_disconn_pipes();
  350. if (ret) {
  351. QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
  352. "ipa_wdi3_disconn_pipes: IPA pipe cleanup failed: ret=%d",
  353. ret);
  354. return QDF_STATUS_E_FAILURE;
  355. }
  356. return QDF_STATUS_SUCCESS;
  357. }
  358. /**
  359. * dp_ipa_setup_iface() - Setup IPA header and register interface
  360. * @ifname: Interface name
  361. * @mac_addr: Interface MAC address
  362. * @prod_client: IPA prod client type
  363. * @cons_client: IPA cons client type
  364. * @session_id: Session ID
  365. * @is_ipv6_enabled: Is IPV6 enabled or not
  366. *
  367. * Return: QDF_STATUS
  368. */
  369. QDF_STATUS dp_ipa_setup_iface(char *ifname, uint8_t *mac_addr,
  370. enum ipa_client_type prod_client,
  371. enum ipa_client_type cons_client,
  372. uint8_t session_id, bool is_ipv6_enabled)
  373. {
  374. struct ipa_wdi3_reg_intf_in_params in;
  375. struct ipa_wdi3_hdr_info hdr_info;
  376. struct dp_ipa_uc_tx_hdr uc_tx_hdr;
  377. int ret = -EINVAL;
  378. QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_DEBUG,
  379. "Add Partial hdr: %s, %pM",
  380. ifname, mac_addr);
  381. qdf_mem_zero(&hdr_info, sizeof(struct ipa_wdi3_hdr_info));
  382. qdf_ether_addr_copy(uc_tx_hdr.eth.h_source, mac_addr);
  383. /* IPV4 header */
  384. uc_tx_hdr.eth.h_proto = qdf_htons(ETH_P_IP);
  385. hdr_info.hdr = (uint8_t *)&uc_tx_hdr;
  386. hdr_info.hdr_len = DP_IPA_UC_WLAN_TX_HDR_LEN;
  387. hdr_info.hdr_type = IPA_HDR_L2_ETHERNET_II;
  388. hdr_info.dst_mac_addr_offset = DP_IPA_UC_WLAN_HDR_DES_MAC_OFFSET;
  389. in.netdev_name = ifname;
  390. memcpy(&(in.hdr_info[0]), &hdr_info, sizeof(struct ipa_wdi3_hdr_info));
  391. in.is_meta_data_valid = 1;
  392. in.meta_data = htonl(session_id << 16);
  393. in.meta_data_mask = htonl(0x00FF0000);
  394. /* IPV6 header */
  395. if (is_ipv6_enabled) {
  396. uc_tx_hdr.eth.h_proto = qdf_htons(ETH_P_IPV6);
  397. memcpy(&(in.hdr_info[1]), &hdr_info,
  398. sizeof(struct ipa_wdi3_hdr_info));
  399. }
  400. ret = ipa_wdi3_reg_intf(&in);
  401. if (ret) {
  402. QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
  403. "ipa_wdi3_reg_intf: register IPA interface falied: ret=%d",
  404. ret);
  405. return QDF_STATUS_E_FAILURE;
  406. }
  407. return QDF_STATUS_SUCCESS;
  408. }
  409. /**
  410. * dp_ipa_cleanup_iface() - Cleanup IPA header and deregister interface
  411. * @ifname: Interface name
  412. * @is_ipv6_enabled: Is IPV6 enabled or not
  413. *
  414. * Return: QDF_STATUS
  415. */
  416. QDF_STATUS dp_ipa_cleanup_iface(char *ifname, bool is_ipv6_enabled)
  417. {
  418. int ret;
  419. ret = ipa_wdi3_dereg_intf(ifname);
  420. if (ret) {
  421. QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
  422. "ipa_wdi3_dereg_intf: IPA pipe deregistration failed: ret=%d",
  423. ret);
  424. return QDF_STATUS_E_FAILURE;
  425. }
  426. return QDF_STATUS_SUCCESS;
  427. }
  428. /**
  429. * dp_ipa_uc_enable_pipes() - Enable and resume traffic on Tx/Rx pipes
  430. * @ppdev - handle to the device instance
  431. *
  432. * Return: QDF_STATUS
  433. */
  434. QDF_STATUS dp_ipa_enable_pipes(struct cdp_pdev *ppdev)
  435. {
  436. QDF_STATUS result;
  437. result = ipa_wdi3_enable_pipes();
  438. if (result) {
  439. QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
  440. "%s: Enable WDI PIPE fail, code %d",
  441. __func__, result);
  442. return QDF_STATUS_E_FAILURE;
  443. }
  444. return QDF_STATUS_SUCCESS;
  445. }
  446. /**
  447. * dp_ipa_uc_disable_pipes() – Suspend traffic and disable Tx/Rx pipes
  448. * @ppdev - handle to the device instance
  449. *
  450. * Return: QDF_STATUS
  451. */
  452. QDF_STATUS dp_ipa_disable_pipes(struct cdp_pdev *ppdev)
  453. {
  454. QDF_STATUS result;
  455. result = ipa_wdi3_disable_pipes();
  456. if (result) {
  457. QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
  458. "%s: Disable WDI PIPE fail, code %d",
  459. __func__, result);
  460. return QDF_STATUS_E_FAILURE;
  461. }
  462. return QDF_STATUS_SUCCESS;
  463. }
  464. /**
  465. * dp_ipa_set_perf_level() - Set IPA clock bandwidth based on data rates
  466. * @client: Client type
  467. * @max_supported_bw_mbps: Maximum bandwidth needed (in Mbps)
  468. *
  469. * Return: QDF_STATUS
  470. */
  471. QDF_STATUS dp_ipa_set_perf_level(int client, uint32_t max_supported_bw_mbps)
  472. {
  473. struct ipa_wdi3_perf_profile profile;
  474. QDF_STATUS result;
  475. profile.client = client;
  476. profile.max_supported_bw_mbps = max_supported_bw_mbps;
  477. result = ipa_wdi3_set_perf_profile(&profile);
  478. if (result) {
  479. QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
  480. "%s: ipa_wdi3_set_perf_profile fail, code %d",
  481. __func__, result);
  482. return QDF_STATUS_E_FAILURE;
  483. }
  484. return QDF_STATUS_SUCCESS;
  485. }
  486. #endif