dp_ipa.c 16 KB

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