blob: 8f74d3ad816325e527cabb187143f9a93f4ac48d [file] [log] [blame]
Yun Parkb4f591d2017-03-29 15:51:01 -07001/*
Sravan Kumar Kairamc047d292018-11-19 18:43:15 +05302 * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
Yun Parkb4f591d2017-03-29 15:51:01 -07003 *
Yun Parkf20b2ca2017-08-16 11:41:45 -07004 * 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.
Yun Parkb4f591d2017-03-29 15:51:01 -07007 *
Yun Parkf20b2ca2017-08-16 11:41:45 -07008 * 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.
Yun Parkb4f591d2017-03-29 15:51:01 -070015 */
16
17/*=== includes ===*/
18/* header files for OS primitives */
19#include <osdep.h> /* uint32_t, etc. */
20#include <qdf_mem.h> /* qdf_mem_malloc,free */
21#include <qdf_types.h> /* qdf_device_t, qdf_print */
22#include <qdf_lock.h> /* qdf_spinlock */
23#include <qdf_atomic.h> /* qdf_atomic_read */
24
Yun Parkb4f591d2017-03-29 15:51:01 -070025/* header files for utilities */
Ashish Kumar Dhanotiya94ffbd12019-08-08 18:00:59 +053026#include "queue.h" /* TAILQ */
Yun Parkb4f591d2017-03-29 15:51:01 -070027
28/* header files for configuration API */
29#include <ol_cfg.h> /* ol_cfg_is_high_latency */
30#include <ol_if_athvar.h>
31
32/* header files for HTT API */
33#include <ol_htt_api.h>
34#include <ol_htt_tx_api.h>
35
36/* header files for our own APIs */
37#include <ol_txrx_api.h>
38#include <ol_txrx_dbg.h>
39#include <cdp_txrx_ocb.h>
40#include <ol_txrx_ctrl_api.h>
41#include <cdp_txrx_stats.h>
42#include <ol_txrx_osif_api.h>
43/* header files for our internal definitions */
44#include <ol_txrx_internal.h> /* TXRX_ASSERT, etc. */
45#include <wdi_event.h> /* WDI events */
46#include <ol_tx.h> /* ol_tx_ll */
47#include <ol_rx.h> /* ol_rx_deliver */
48#include <ol_txrx_peer_find.h> /* ol_txrx_peer_find_attach, etc. */
49#include <ol_rx_pn.h> /* ol_rx_pn_check, etc. */
50#include <ol_rx_fwd.h> /* ol_rx_fwd_check, etc. */
51#include <ol_rx_reorder_timeout.h> /* OL_RX_REORDER_TIMEOUT_INIT, etc. */
52#include <ol_rx_reorder.h>
53#include <ol_tx_send.h> /* ol_tx_discard_target_frms */
54#include <ol_tx_desc.h> /* ol_tx_desc_frame_free */
55#include <ol_tx_queue.h>
56#include <ol_tx_sched.h> /* ol_tx_sched_attach, etc. */
57#include <ol_txrx.h>
58#include <ol_txrx_types.h>
59#include <cdp_txrx_flow_ctrl_legacy.h>
60#include <cdp_txrx_bus.h>
61#include <cdp_txrx_ipa.h>
62#include <cdp_txrx_pmf.h>
63#include "wma.h"
64#include "hif.h"
65#include <cdp_txrx_peer_ops.h>
66#ifndef REMOVE_PKT_LOG
67#include "pktlog_ac.h"
68#endif
69#include "epping_main.h"
70#include <a_types.h>
71
72#ifdef IPA_OFFLOAD
73#include <ol_txrx_ipa.h>
74
75/* For Tx pipes, use Ethernet-II Header format */
jiad80055eb2018-04-05 12:45:58 +080076#ifdef QCA_WIFI_3_0
Yun Parkb4f591d2017-03-29 15:51:01 -070077struct ol_txrx_ipa_uc_tx_hdr ipa_uc_tx_hdr = {
78 {
79 0x0000,
80 0x00000000,
81 0x00000000
82 },
83 {
84 0x00000000
85 },
86 {
87 {0x00, 0x03, 0x7f, 0xaa, 0xbb, 0xcc},
88 {0x00, 0x03, 0x7f, 0xdd, 0xee, 0xff},
89 0x0008
90 }
91};
jiad80055eb2018-04-05 12:45:58 +080092#else
93struct ol_txrx_ipa_uc_tx_hdr ipa_uc_tx_hdr = {
94 {
95 0x00000000,
96 0x00000000
97 },
98 {
99 0x00000000
100 },
101 {
102 {0x00, 0x03, 0x7f, 0xaa, 0xbb, 0xcc},
103 {0x00, 0x03, 0x7f, 0xdd, 0xee, 0xff},
104 0x0008
105 }
106};
107#endif
Yun Parkb4f591d2017-03-29 15:51:01 -0700108
Vevek Venkatesan29076ec2019-08-22 17:53:12 +0530109QDF_STATUS ol_txrx_ipa_uc_get_resource(struct cdp_soc_t *soc_hdl,
110 uint8_t pdev_id)
Yun Parkb4f591d2017-03-29 15:51:01 -0700111{
Vevek Venkatesan29076ec2019-08-22 17:53:12 +0530112 struct ol_txrx_soc_t *soc = cdp_soc_t_to_ol_txrx_soc_t(soc_hdl);
113 ol_txrx_pdev_handle pdev = ol_txrx_get_pdev_from_pdev_id(soc, pdev_id);
114 struct ol_txrx_ipa_resources *ipa_res;
Sravan Kumar Kairamb664b6c2018-02-27 17:43:10 +0530115 qdf_device_t osdev = cds_get_context(QDF_MODULE_ID_QDF_DEVICE);
Yun Parkb4f591d2017-03-29 15:51:01 -0700116
Vevek Venkatesan29076ec2019-08-22 17:53:12 +0530117 if (!pdev) {
118 ol_txrx_err("%s invalid instance", __func__);
119 return QDF_STATUS_E_FAILURE;
120 }
121
Ryan Hsub5783cf2018-05-14 12:13:15 -0700122 if (!osdev) {
123 QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
124 "%s: qdf device is null!", __func__);
125 return QDF_STATUS_E_NOENT;
126 }
127
Vevek Venkatesan29076ec2019-08-22 17:53:12 +0530128 ipa_res = &pdev->ipa_resource;
Yun Parkb4f591d2017-03-29 15:51:01 -0700129 htt_ipa_uc_get_resource(pdev->htt_pdev,
Sravan Kumar Kairamb664b6c2018-02-27 17:43:10 +0530130 &ipa_res->ce_sr,
131 &ipa_res->tx_comp_ring,
132 &ipa_res->rx_rdy_ring,
133 &ipa_res->rx2_rdy_ring,
134 &ipa_res->rx_proc_done_idx,
135 &ipa_res->rx2_proc_done_idx,
Yun Parkb4f591d2017-03-29 15:51:01 -0700136 &ipa_res->ce_sr_ring_size,
137 &ipa_res->ce_reg_paddr,
Sravan Kumar Kairamb664b6c2018-02-27 17:43:10 +0530138 &ipa_res->tx_num_alloc_buffer);
Yun Parkb4f591d2017-03-29 15:51:01 -0700139
Sravan Kumar Kairamb664b6c2018-02-27 17:43:10 +0530140 if ((0 == qdf_mem_get_dma_addr(osdev,
141 &ipa_res->ce_sr->mem_info)) ||
142 (0 == qdf_mem_get_dma_addr(osdev,
143 &ipa_res->tx_comp_ring->mem_info)) ||
144 (0 == qdf_mem_get_dma_addr(osdev,
145 &ipa_res->rx_rdy_ring->mem_info))
Yun Parkb4f591d2017-03-29 15:51:01 -0700146#if defined(QCA_WIFI_3_0) && defined(CONFIG_IPA3)
Sravan Kumar Kairamb664b6c2018-02-27 17:43:10 +0530147 || (0 == qdf_mem_get_dma_addr(osdev,
148 &ipa_res->rx2_rdy_ring->mem_info))
Yun Parkb4f591d2017-03-29 15:51:01 -0700149#endif
150 )
151 return QDF_STATUS_E_FAILURE;
152
153 return QDF_STATUS_SUCCESS;
154}
155
Vevek Venkatesan29076ec2019-08-22 17:53:12 +0530156QDF_STATUS ol_txrx_ipa_uc_set_doorbell_paddr(struct cdp_soc_t *soc_hdl,
157 uint8_t pdev_id)
Yun Parkb4f591d2017-03-29 15:51:01 -0700158{
Vevek Venkatesan29076ec2019-08-22 17:53:12 +0530159 struct ol_txrx_soc_t *soc = cdp_soc_t_to_ol_txrx_soc_t(soc_hdl);
160 ol_txrx_pdev_handle pdev = ol_txrx_get_pdev_from_pdev_id(soc, pdev_id);
161 struct ol_txrx_ipa_resources *ipa_res;
Yun Parkb4f591d2017-03-29 15:51:01 -0700162 int ret;
163
Vevek Venkatesan29076ec2019-08-22 17:53:12 +0530164 if (!pdev) {
165 ol_txrx_err("%s invalid instance", __func__);
166 return QDF_STATUS_E_FAILURE;
167 }
168
169 ipa_res = &pdev->ipa_resource;
Yun Parkb4f591d2017-03-29 15:51:01 -0700170 ret = htt_ipa_uc_set_doorbell_paddr(pdev->htt_pdev,
Sravan Kumar Kairamb664b6c2018-02-27 17:43:10 +0530171 ipa_res->tx_comp_doorbell_dmaaddr,
172 ipa_res->rx_ready_doorbell_dmaaddr);
Yun Parkb4f591d2017-03-29 15:51:01 -0700173
174 if (ret) {
175 QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
Sravan Kumar Kairamb664b6c2018-02-27 17:43:10 +0530176 "htt_ipa_uc_set_doorbell_dmaaddr fail: %d", ret);
Yun Parkb4f591d2017-03-29 15:51:01 -0700177 return QDF_STATUS_E_FAILURE;
178 }
179
180 return QDF_STATUS_SUCCESS;
181}
182
Vevek Venkatesan29076ec2019-08-22 17:53:12 +0530183QDF_STATUS ol_txrx_ipa_uc_set_active(struct cdp_soc_t *soc_hdl, uint8_t pdev_id,
184 bool uc_active, bool is_tx)
Yun Parkb4f591d2017-03-29 15:51:01 -0700185{
Vevek Venkatesan29076ec2019-08-22 17:53:12 +0530186 struct ol_txrx_soc_t *soc = cdp_soc_t_to_ol_txrx_soc_t(soc_hdl);
187 ol_txrx_pdev_handle pdev = ol_txrx_get_pdev_from_pdev_id(soc, pdev_id);
Yun Parkb4f591d2017-03-29 15:51:01 -0700188 int ret;
189
Vevek Venkatesan29076ec2019-08-22 17:53:12 +0530190 if (!pdev) {
191 ol_txrx_err("%s invalid instance", __func__);
192 return QDF_STATUS_E_FAILURE;
193 }
194
Yun Parkb4f591d2017-03-29 15:51:01 -0700195 ret = htt_h2t_ipa_uc_set_active(pdev->htt_pdev, uc_active, is_tx);
196 if (ret) {
197 QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
198 "htt_h2t_ipa_uc_set_active fail: %d", ret);
199 return QDF_STATUS_E_FAILURE;
200 }
201
202 return QDF_STATUS_SUCCESS;
203}
204
Vevek Venkatesan29076ec2019-08-22 17:53:12 +0530205QDF_STATUS ol_txrx_ipa_uc_op_response(struct cdp_soc_t *soc_hdl,
206 uint8_t pdev_id, uint8_t *op_msg)
Yun Parkb4f591d2017-03-29 15:51:01 -0700207{
Vevek Venkatesan29076ec2019-08-22 17:53:12 +0530208 struct ol_txrx_soc_t *soc = cdp_soc_t_to_ol_txrx_soc_t(soc_hdl);
209 ol_txrx_pdev_handle pdev = ol_txrx_get_pdev_from_pdev_id(soc, pdev_id);
210
211 if (!pdev) {
212 ol_txrx_err("%s invalid instance", __func__);
213 return QDF_STATUS_E_FAILURE;
214 }
Yun Parkb4f591d2017-03-29 15:51:01 -0700215
216 if (pdev->ipa_uc_op_cb) {
217 pdev->ipa_uc_op_cb(op_msg, pdev->usr_ctxt);
218 } else {
219 QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
220 "%s: IPA callback function is not registered", __func__);
221 qdf_mem_free(op_msg);
222 return QDF_STATUS_E_FAILURE;
223 }
224
225 return QDF_STATUS_SUCCESS;
226}
227
Vevek Venkatesan29076ec2019-08-22 17:53:12 +0530228QDF_STATUS ol_txrx_ipa_uc_register_op_cb(struct cdp_soc_t *soc_hdl,
229 uint8_t pdev_id,
230 ipa_uc_op_cb_type op_cb,
231 void *usr_ctxt)
Yun Parkb4f591d2017-03-29 15:51:01 -0700232{
Vevek Venkatesan29076ec2019-08-22 17:53:12 +0530233 struct ol_txrx_soc_t *soc = cdp_soc_t_to_ol_txrx_soc_t(soc_hdl);
234 ol_txrx_pdev_handle pdev = ol_txrx_get_pdev_from_pdev_id(soc, pdev_id);
235
236 if (!pdev) {
237 ol_txrx_err("%s invalid instance", __func__);
238 return QDF_STATUS_E_FAILURE;
239 }
Yun Parkb4f591d2017-03-29 15:51:01 -0700240
241 pdev->ipa_uc_op_cb = op_cb;
242 pdev->usr_ctxt = usr_ctxt;
243
244 return QDF_STATUS_SUCCESS;
245}
246
Vevek Venkatesan29076ec2019-08-22 17:53:12 +0530247QDF_STATUS ol_txrx_ipa_uc_get_stat(struct cdp_soc_t *soc_hdl, uint8_t pdev_id)
Yun Parkb4f591d2017-03-29 15:51:01 -0700248{
Vevek Venkatesan29076ec2019-08-22 17:53:12 +0530249 struct ol_txrx_soc_t *soc = cdp_soc_t_to_ol_txrx_soc_t(soc_hdl);
250 ol_txrx_pdev_handle pdev = ol_txrx_get_pdev_from_pdev_id(soc, pdev_id);
Yun Parkb4f591d2017-03-29 15:51:01 -0700251 int ret;
252
Vevek Venkatesan29076ec2019-08-22 17:53:12 +0530253 if (!pdev) {
254 ol_txrx_err("%s invalid instance", __func__);
255 return QDF_STATUS_E_FAILURE;
256 }
257
Yun Parkb4f591d2017-03-29 15:51:01 -0700258 ret = htt_h2t_ipa_uc_get_stats(pdev->htt_pdev);
259
260 if (ret) {
261 QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
262 "htt_h2t_ipa_uc_get_stats fail: %d", ret);
263 return QDF_STATUS_E_FAILURE;
264 }
265
266 return QDF_STATUS_SUCCESS;
267}
268
Vevek Venkatesan29076ec2019-08-22 17:53:12 +0530269QDF_STATUS ol_txrx_ipa_enable_autonomy(struct cdp_soc_t *soc_hdl,
270 uint8_t pdev_id)
Yun Parkb4f591d2017-03-29 15:51:01 -0700271{
272 /* TBD */
273 return QDF_STATUS_SUCCESS;
274}
275
Vevek Venkatesan29076ec2019-08-22 17:53:12 +0530276QDF_STATUS ol_txrx_ipa_disable_autonomy(struct cdp_soc_t *soc_hdl,
277 uint8_t pdev_id)
Yun Parkb4f591d2017-03-29 15:51:01 -0700278{
279 /* TBD */
280 return QDF_STATUS_SUCCESS;
281}
282
Yun Park84c0ceb2018-01-11 10:37:10 -0800283#ifdef CONFIG_IPA_WDI_UNIFIED_API
284
285#ifndef QCA_LL_TX_FLOW_CONTROL_V2
286static inline void ol_txrx_setup_mcc_sys_pipes(
287 qdf_ipa_sys_connect_params_t *sys_in,
288 qdf_ipa_wdi_conn_in_params_t *pipe_in)
289{
Chaoli Zhou50bc9ad2018-12-12 10:30:03 +0800290 int i = 0;
291
Yun Park84c0ceb2018-01-11 10:37:10 -0800292 /* Setup MCC sys pipe */
293 QDF_IPA_WDI_CONN_IN_PARAMS_NUM_SYS_PIPE_NEEDED(pipe_in) =
294 OL_TXRX_IPA_MAX_IFACE;
Chaoli Zhou50bc9ad2018-12-12 10:30:03 +0800295 for (i = 0; i < OL_TXRX_IPA_MAX_IFACE; i++)
Yun Park84c0ceb2018-01-11 10:37:10 -0800296 memcpy(&QDF_IPA_WDI_CONN_IN_PARAMS_SYS_IN(pipe_in)[i],
297 &sys_in[i], sizeof(qdf_ipa_sys_connect_params_t));
298}
299#else
300static inline void ol_txrx_setup_mcc_sys_pipes(
301 qdf_ipa_sys_connect_params_t *sys_in,
302 qdf_ipa_wdi_conn_in_params_t *pipe_in)
303{
304 QDF_IPA_WDI_CONN_IN_PARAMS_NUM_SYS_PIPE_NEEDED(pipe_in) = 0;
305}
306#endif
307
Sravan Kumar Kairamb664b6c2018-02-27 17:43:10 +0530308#ifdef ENABLE_SMMU_S1_TRANSLATION
309/**
310 * ol_txrx_ipa_wdi_tx_smmu_params() - Config IPA TX params
311 * @ipa_res: IPA resources
312 * @tx_smmu: IPA WDI pipe setup info
313 *
314 * Return: None
315 */
316static inline void ol_txrx_ipa_wdi_tx_smmu_params(
317 struct ol_txrx_ipa_resources *ipa_res,
318 qdf_ipa_wdi_pipe_setup_info_smmu_t *tx_smmu)
319{
320 QDF_IPA_WDI_SETUP_INFO_SMMU_CLIENT(tx_smmu) =
321 IPA_CLIENT_WLAN1_CONS;
322 qdf_mem_copy(&QDF_IPA_WDI_SETUP_INFO_SMMU_TRANSFER_RING_BASE(
323 tx_smmu),
324 &ipa_res->tx_comp_ring->sgtable,
325 sizeof(sgtable_t));
326 QDF_IPA_WDI_SETUP_INFO_SMMU_TRANSFER_RING_SIZE(tx_smmu) =
327 ipa_res->tx_comp_ring->mem_info.size;
328 qdf_mem_copy(&QDF_IPA_WDI_SETUP_INFO_SMMU_EVENT_RING_BASE(
329 tx_smmu),
330 &ipa_res->ce_sr->sgtable,
331 sizeof(sgtable_t));
332 QDF_IPA_WDI_SETUP_INFO_SMMU_EVENT_RING_SIZE(tx_smmu) =
333 ipa_res->ce_sr_ring_size;
334 QDF_IPA_WDI_SETUP_INFO_SMMU_EVENT_RING_DOORBELL_PA(tx_smmu) =
335 ipa_res->ce_reg_paddr;
336 QDF_IPA_WDI_SETUP_INFO_SMMU_NUM_PKT_BUFFERS(tx_smmu) =
337 ipa_res->tx_num_alloc_buffer;
338 QDF_IPA_WDI_SETUP_INFO_SMMU_PKT_OFFSET(tx_smmu) = 0;
339}
340
Chaoli Zhou678a32b2019-07-04 15:12:11 +0800341#ifdef QCA_WIFI_3_0
Sravan Kumar Kairamb664b6c2018-02-27 17:43:10 +0530342/**
343 * ol_txrx_ipa_wdi_rx_smmu_params() - Config IPA RX params
344 * @ipa_res: IPA resources
345 * @rx_smmu: IPA WDI pipe setup info
346 *
347 * Return: None
348 */
349static inline void ol_txrx_ipa_wdi_rx_smmu_params(
350 struct ol_txrx_ipa_resources *ipa_res,
351 qdf_ipa_wdi_pipe_setup_info_smmu_t *rx_smmu)
352{
353 QDF_IPA_WDI_SETUP_INFO_SMMU_CLIENT(rx_smmu) =
354 IPA_CLIENT_WLAN1_PROD;
355 qdf_mem_copy(&QDF_IPA_WDI_SETUP_INFO_SMMU_TRANSFER_RING_BASE(
356 rx_smmu),
357 &ipa_res->rx_rdy_ring->sgtable,
358 sizeof(sgtable_t));
359 QDF_IPA_WDI_SETUP_INFO_SMMU_TRANSFER_RING_SIZE(rx_smmu) =
360 ipa_res->rx_rdy_ring->mem_info.size;
361 QDF_IPA_WDI_SETUP_INFO_SMMU_TRANSFER_RING_DOORBELL_PA(rx_smmu) =
362 ipa_res->rx_proc_done_idx->mem_info.pa;
363 qdf_mem_copy(&QDF_IPA_WDI_SETUP_INFO_SMMU_EVENT_RING_BASE(
364 rx_smmu),
365 &ipa_res->rx2_rdy_ring->sgtable,
366 sizeof(sgtable_t));
367 QDF_IPA_WDI_SETUP_INFO_SMMU_EVENT_RING_SIZE(rx_smmu) =
368 ipa_res->rx2_rdy_ring->mem_info.size;
369 QDF_IPA_WDI_SETUP_INFO_SMMU_EVENT_RING_DOORBELL_PA(rx_smmu) =
370 ipa_res->rx2_proc_done_idx->mem_info.pa;
371 QDF_IPA_WDI_SETUP_INFO_SMMU_PKT_OFFSET(rx_smmu) = 0;
372
373}
Chaoli Zhou678a32b2019-07-04 15:12:11 +0800374#else
375static inline void ol_txrx_ipa_wdi_rx_smmu_params(
376 struct ol_txrx_ipa_resources *ipa_res,
377 qdf_ipa_wdi_pipe_setup_info_smmu_t *rx_smmu)
378{
379 QDF_IPA_WDI_SETUP_INFO_SMMU_CLIENT(rx_smmu) =
380 IPA_CLIENT_WLAN1_PROD;
381 qdf_mem_copy(&QDF_IPA_WDI_SETUP_INFO_SMMU_TRANSFER_RING_BASE(
382 rx_smmu),
383 &ipa_res->rx_rdy_ring->sgtable,
384 sizeof(sgtable_t));
385 QDF_IPA_WDI_SETUP_INFO_SMMU_TRANSFER_RING_SIZE(rx_smmu) =
386 ipa_res->rx_rdy_ring->mem_info.size;
387 QDF_IPA_WDI_SETUP_INFO_SMMU_TRANSFER_RING_DOORBELL_PA(rx_smmu) =
388 ipa_res->rx_proc_done_idx->mem_info.pa;
389 QDF_IPA_WDI_SETUP_INFO_SMMU_PKT_OFFSET(rx_smmu) = 0;
390}
391
392#endif
Sravan Kumar Kairamb664b6c2018-02-27 17:43:10 +0530393
394#else
395
396static inline void ol_txrx_ipa_wdi_tx_smmu_params(
397 struct ol_txrx_ipa_resources *ipa_res,
398 qdf_ipa_wdi_pipe_setup_info_smmu_t *tx_smmu)
399{
400}
401
402static inline void ol_txrx_ipa_wdi_rx_smmu_params(
403 struct ol_txrx_ipa_resources *ipa_res,
404 qdf_ipa_wdi_pipe_setup_info_smmu_t *rx_smmu)
405{
406}
407#endif
408
409/**
410 * ol_txrx_ipa_wdi_tx_params() - Config IPA TX params
411 * @ipa_res: IPA resources
412 * @tx: IPA WDI pipe setup info
413 *
414 * Return: None
415 */
416static inline void ol_txrx_ipa_wdi_tx_params(
417 struct ol_txrx_ipa_resources *ipa_res,
418 qdf_ipa_wdi_pipe_setup_info_t *tx)
419{
420 qdf_device_t osdev = cds_get_context(QDF_MODULE_ID_QDF_DEVICE);
421
Ryan Hsub5783cf2018-05-14 12:13:15 -0700422 if (!osdev) {
423 QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
424 "%s: qdf device is null!", __func__);
425 return;
426 }
427
Sravan Kumar Kairamb664b6c2018-02-27 17:43:10 +0530428 QDF_IPA_WDI_SETUP_INFO_CLIENT(tx) = IPA_CLIENT_WLAN1_CONS;
429 QDF_IPA_WDI_SETUP_INFO_TRANSFER_RING_BASE_PA(tx) =
430 qdf_mem_get_dma_addr(osdev,
431 &ipa_res->tx_comp_ring->mem_info);
432 QDF_IPA_WDI_SETUP_INFO_TRANSFER_RING_SIZE(tx) =
433 ipa_res->tx_comp_ring->mem_info.size;
434 QDF_IPA_WDI_SETUP_INFO_EVENT_RING_BASE_PA(tx) =
435 qdf_mem_get_dma_addr(osdev,
436 &ipa_res->ce_sr->mem_info);
437 QDF_IPA_WDI_SETUP_INFO_EVENT_RING_SIZE(tx) =
438 ipa_res->ce_sr_ring_size;
439 QDF_IPA_WDI_SETUP_INFO_EVENT_RING_DOORBELL_PA(tx) =
440 ipa_res->ce_reg_paddr;
441 QDF_IPA_WDI_SETUP_INFO_NUM_PKT_BUFFERS(tx) =
442 ipa_res->tx_num_alloc_buffer;
443 QDF_IPA_WDI_SETUP_INFO_PKT_OFFSET(tx) = 0;
444}
445
Chaoli Zhou678a32b2019-07-04 15:12:11 +0800446#ifdef QCA_WIFI_3_0
Sravan Kumar Kairamb664b6c2018-02-27 17:43:10 +0530447/**
448 * ol_txrx_ipa_wdi_rx_params() - Config IPA RX params
449 * @ipa_res: IPA resources
450 * @rx: IPA WDI pipe setup info
451 *
452 * Return: None
453 */
454static inline void ol_txrx_ipa_wdi_rx_params(
455 struct ol_txrx_ipa_resources *ipa_res,
456 qdf_ipa_wdi_pipe_setup_info_t *rx)
457{
458 QDF_IPA_WDI_SETUP_INFO_CLIENT(rx) = IPA_CLIENT_WLAN1_PROD;
459 QDF_IPA_WDI_SETUP_INFO_TRANSFER_RING_BASE_PA(rx) =
460 ipa_res->rx_rdy_ring->mem_info.pa;
461 QDF_IPA_WDI_SETUP_INFO_TRANSFER_RING_SIZE(rx) =
462 ipa_res->rx_rdy_ring->mem_info.size;
463 QDF_IPA_WDI_SETUP_INFO_TRANSFER_RING_DOORBELL_PA(rx) =
464 ipa_res->rx_proc_done_idx->mem_info.pa;
465 QDF_IPA_WDI_SETUP_INFO_EVENT_RING_BASE_PA(rx) =
466 ipa_res->rx2_rdy_ring->mem_info.pa;
467 QDF_IPA_WDI_SETUP_INFO_EVENT_RING_SIZE(rx) =
468 ipa_res->rx2_rdy_ring->mem_info.size;
469 QDF_IPA_WDI_SETUP_INFO_EVENT_RING_DOORBELL_PA(rx) =
470 ipa_res->rx2_proc_done_idx->mem_info.pa;
471 QDF_IPA_WDI_SETUP_INFO_PKT_OFFSET(rx) = 0;
472}
473
Chaoli Zhou678a32b2019-07-04 15:12:11 +0800474#else
475
476static inline void ol_txrx_ipa_wdi_rx_params(
477 struct ol_txrx_ipa_resources *ipa_res,
478 qdf_ipa_wdi_pipe_setup_info_t *rx)
479{
480 QDF_IPA_WDI_SETUP_INFO_CLIENT(rx) = IPA_CLIENT_WLAN1_PROD;
481 QDF_IPA_WDI_SETUP_INFO_TRANSFER_RING_BASE_PA(rx) =
482 ipa_res->rx_rdy_ring->mem_info.pa;
483 QDF_IPA_WDI_SETUP_INFO_TRANSFER_RING_SIZE(rx) =
484 ipa_res->rx_rdy_ring->mem_info.size;
485 QDF_IPA_WDI_SETUP_INFO_TRANSFER_RING_DOORBELL_PA(rx) =
486 ipa_res->rx_proc_done_idx->mem_info.pa;
487 QDF_IPA_WDI_SETUP_INFO_PKT_OFFSET(rx) = 0;
488}
489
490#endif
Vevek Venkatesan29076ec2019-08-22 17:53:12 +0530491
492QDF_STATUS ol_txrx_ipa_setup(struct cdp_soc_t *soc_hdl, uint8_t pdev_id,
493 void *ipa_i2w_cb, void *ipa_w2i_cb,
494 void *ipa_wdi_meter_notifier_cb,
Yun Park84c0ceb2018-01-11 10:37:10 -0800495 uint32_t ipa_desc_size, void *ipa_priv,
496 bool is_rm_enabled, uint32_t *p_tx_pipe_handle,
497 uint32_t *p_rx_pipe_handle, bool is_smmu_enabled,
Sravan Kumar Kairamc047d292018-11-19 18:43:15 +0530498 qdf_ipa_sys_connect_params_t *sys_in,
499 bool over_gsi)
Yun Park84c0ceb2018-01-11 10:37:10 -0800500{
Vevek Venkatesan29076ec2019-08-22 17:53:12 +0530501 struct ol_txrx_soc_t *soc = cdp_soc_t_to_ol_txrx_soc_t(soc_hdl);
502 ol_txrx_pdev_handle pdev = ol_txrx_get_pdev_from_pdev_id(soc, pdev_id);
503 struct ol_txrx_ipa_resources *ipa_res;
Yun Park84c0ceb2018-01-11 10:37:10 -0800504 qdf_ipa_ep_cfg_t *tx_cfg;
505 qdf_ipa_ep_cfg_t *rx_cfg;
506 qdf_ipa_wdi_pipe_setup_info_t *tx;
507 qdf_ipa_wdi_pipe_setup_info_t *rx;
508 qdf_ipa_wdi_pipe_setup_info_smmu_t *tx_smmu;
509 qdf_ipa_wdi_pipe_setup_info_smmu_t *rx_smmu;
Vevek Venkatesan606bdbc2020-03-11 15:33:33 +0530510 qdf_ipa_wdi_conn_in_params_t *pipe_in = NULL;
Yun Park84c0ceb2018-01-11 10:37:10 -0800511 qdf_ipa_wdi_conn_out_params_t pipe_out;
Sravan Kumar Kairamb664b6c2018-02-27 17:43:10 +0530512 qdf_device_t osdev = cds_get_context(QDF_MODULE_ID_QDF_DEVICE);
513 uint32_t tx_comp_db_dmaaddr = 0, rx_rdy_db_dmaaddr = 0;
Yun Park84c0ceb2018-01-11 10:37:10 -0800514 int ret;
515
Vevek Venkatesan29076ec2019-08-22 17:53:12 +0530516 if (!pdev) {
517 ol_txrx_err("%s invalid instance", __func__);
518 return QDF_STATUS_E_FAILURE;
519 }
520
Ryan Hsub5783cf2018-05-14 12:13:15 -0700521 if (!osdev) {
522 QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
523 "%s: qdf device is null!", __func__);
524 return QDF_STATUS_E_NOENT;
525 }
526
Vevek Venkatesan606bdbc2020-03-11 15:33:33 +0530527 pipe_in = qdf_mem_malloc(sizeof(*pipe_in));
528 if (!pipe_in) {
529 ol_txrx_err("pipe_in allocation failed");
530 return QDF_STATUS_E_NOMEM;
531 }
532
Vevek Venkatesan29076ec2019-08-22 17:53:12 +0530533 ipa_res = &pdev->ipa_resource;
Vevek Venkatesan606bdbc2020-03-11 15:33:33 +0530534 qdf_mem_zero(pipe_in, sizeof(*pipe_in));
Yun Park84c0ceb2018-01-11 10:37:10 -0800535 qdf_mem_zero(&pipe_out, sizeof(pipe_out));
536
Vevek Venkatesan606bdbc2020-03-11 15:33:33 +0530537 ol_txrx_setup_mcc_sys_pipes(sys_in, pipe_in);
Yun Park84c0ceb2018-01-11 10:37:10 -0800538
539 /* TX PIPE */
Sravan Kumar Kairamb664b6c2018-02-27 17:43:10 +0530540 if (is_smmu_enabled) {
Vevek Venkatesan606bdbc2020-03-11 15:33:33 +0530541 QDF_IPA_WDI_CONN_IN_PARAMS_SMMU_ENABLED(pipe_in) = true;
542 tx_smmu = &QDF_IPA_WDI_CONN_IN_PARAMS_TX_SMMU(pipe_in);
Yun Park84c0ceb2018-01-11 10:37:10 -0800543 tx_cfg = &QDF_IPA_WDI_SETUP_INFO_SMMU_EP_CFG(tx_smmu);
544 } else {
Vevek Venkatesan606bdbc2020-03-11 15:33:33 +0530545 QDF_IPA_WDI_CONN_IN_PARAMS_SMMU_ENABLED(pipe_in) = false;
546 tx = &QDF_IPA_WDI_CONN_IN_PARAMS_TX(pipe_in);
Yun Park84c0ceb2018-01-11 10:37:10 -0800547 tx_cfg = &QDF_IPA_WDI_SETUP_INFO_EP_CFG(tx);
548 }
549
550 QDF_IPA_EP_CFG_NAT_EN(tx_cfg) = IPA_BYPASS_NAT;
551 QDF_IPA_EP_CFG_HDR_LEN(tx_cfg) = OL_TXRX_IPA_UC_WLAN_TX_HDR_LEN;
552 QDF_IPA_EP_CFG_HDR_OFST_PKT_SIZE_VALID(tx_cfg) = 1;
553 QDF_IPA_EP_CFG_HDR_OFST_PKT_SIZE(tx_cfg) = 0;
554 QDF_IPA_EP_CFG_HDR_ADDITIONAL_CONST_LEN(tx_cfg) =
Sravan Kumar Kairamb664b6c2018-02-27 17:43:10 +0530555 OL_TXRX_IPA_UC_WLAN_8023_HDR_SIZE;
Yun Park84c0ceb2018-01-11 10:37:10 -0800556 QDF_IPA_EP_CFG_MODE(tx_cfg) = IPA_BASIC;
557 QDF_IPA_EP_CFG_HDR_LITTLE_ENDIAN(tx_cfg) = true;
558
Sravan Kumar Kairamb664b6c2018-02-27 17:43:10 +0530559 if (is_smmu_enabled)
560 ol_txrx_ipa_wdi_tx_smmu_params(ipa_res, tx_smmu);
561 else
562 ol_txrx_ipa_wdi_tx_params(ipa_res, tx);
Yun Park84c0ceb2018-01-11 10:37:10 -0800563
Yun Park84c0ceb2018-01-11 10:37:10 -0800564
565 /* RX PIPE */
Sravan Kumar Kairamb664b6c2018-02-27 17:43:10 +0530566 if (is_smmu_enabled) {
Vevek Venkatesan606bdbc2020-03-11 15:33:33 +0530567 rx_smmu = &QDF_IPA_WDI_CONN_IN_PARAMS_RX_SMMU(pipe_in);
Sravan Kumar Kairamb664b6c2018-02-27 17:43:10 +0530568 rx_cfg = &QDF_IPA_WDI_SETUP_INFO_EP_CFG(rx_smmu);
Yun Park84c0ceb2018-01-11 10:37:10 -0800569 } else {
Vevek Venkatesan606bdbc2020-03-11 15:33:33 +0530570 rx = &QDF_IPA_WDI_CONN_IN_PARAMS_RX(pipe_in);
Yun Park84c0ceb2018-01-11 10:37:10 -0800571 rx_cfg = &QDF_IPA_WDI_SETUP_INFO_EP_CFG(rx);
572 }
573
574 QDF_IPA_EP_CFG_NAT_EN(rx_cfg) = IPA_BYPASS_NAT;
575 QDF_IPA_EP_CFG_HDR_LEN(rx_cfg) = OL_TXRX_IPA_UC_WLAN_RX_HDR_LEN;
576 QDF_IPA_EP_CFG_HDR_OFST_PKT_SIZE_VALID(rx_cfg) = 1;
577 QDF_IPA_EP_CFG_HDR_OFST_PKT_SIZE(rx_cfg) = 0;
578 QDF_IPA_EP_CFG_HDR_ADDITIONAL_CONST_LEN(rx_cfg) =
Sravan Kumar Kairamb664b6c2018-02-27 17:43:10 +0530579 OL_TXRX_IPA_UC_WLAN_8023_HDR_SIZE;
Yun Park84c0ceb2018-01-11 10:37:10 -0800580 QDF_IPA_EP_CFG_HDR_OFST_METADATA_VALID(rx_cfg) = 0;
581 QDF_IPA_EP_CFG_HDR_METADATA_REG_VALID(rx_cfg) = 1;
582 QDF_IPA_EP_CFG_MODE(rx_cfg) = IPA_BASIC;
583 QDF_IPA_EP_CFG_HDR_LITTLE_ENDIAN(rx_cfg) = true;
584
Sravan Kumar Kairamb664b6c2018-02-27 17:43:10 +0530585 if (is_smmu_enabled)
586 ol_txrx_ipa_wdi_rx_smmu_params(ipa_res, rx_smmu);
587 else
588 ol_txrx_ipa_wdi_rx_params(ipa_res, rx);
Yun Park84c0ceb2018-01-11 10:37:10 -0800589
Vevek Venkatesan606bdbc2020-03-11 15:33:33 +0530590 QDF_IPA_WDI_CONN_IN_PARAMS_NOTIFY(pipe_in) = ipa_w2i_cb;
591 QDF_IPA_WDI_CONN_IN_PARAMS_PRIV(pipe_in) = ipa_priv;
Yun Park84c0ceb2018-01-11 10:37:10 -0800592
593 /* Connect WDI IPA PIPE */
Vevek Venkatesan606bdbc2020-03-11 15:33:33 +0530594 ret = qdf_ipa_wdi_conn_pipes(pipe_in, &pipe_out);
Yun Park84c0ceb2018-01-11 10:37:10 -0800595 if (ret) {
596 QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
597 "%s: ipa_wdi_conn_pipes: IPA pipe setup failed: ret=%d",
598 __func__, ret);
Vevek Venkatesan606bdbc2020-03-11 15:33:33 +0530599 qdf_mem_free(pipe_in);
Yun Park84c0ceb2018-01-11 10:37:10 -0800600 return QDF_STATUS_E_FAILURE;
601 }
602
603 /* IPA uC Doorbell registers */
604 QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_DEBUG,
Sravan Kumar Kairamb664b6c2018-02-27 17:43:10 +0530605 "%s: Tx DB PA=0x%x, Rx DB PA=0x%x", __func__,
606 (unsigned int)
607 QDF_IPA_WDI_CONN_OUT_PARAMS_TX_UC_DB_PA(&pipe_out),
608 (unsigned int)
609 QDF_IPA_WDI_CONN_OUT_PARAMS_RX_UC_DB_PA(&pipe_out));
Yun Park84c0ceb2018-01-11 10:37:10 -0800610
Sravan Kumar Kairamb664b6c2018-02-27 17:43:10 +0530611 ipa_res->tx_comp_doorbell_dmaaddr =
Yun Park84c0ceb2018-01-11 10:37:10 -0800612 QDF_IPA_WDI_CONN_OUT_PARAMS_TX_UC_DB_PA(&pipe_out);
Sravan Kumar Kairamb664b6c2018-02-27 17:43:10 +0530613 ipa_res->rx_ready_doorbell_dmaaddr =
Yun Park84c0ceb2018-01-11 10:37:10 -0800614 QDF_IPA_WDI_CONN_OUT_PARAMS_RX_UC_DB_PA(&pipe_out);
615
Sravan Kumar Kairamb664b6c2018-02-27 17:43:10 +0530616 if (is_smmu_enabled) {
617 pld_smmu_map(osdev->dev, ipa_res->tx_comp_doorbell_dmaaddr,
618 &tx_comp_db_dmaaddr, sizeof(uint32_t));
619 ipa_res->tx_comp_doorbell_dmaaddr = tx_comp_db_dmaaddr;
620
621 pld_smmu_map(osdev->dev, ipa_res->rx_ready_doorbell_dmaaddr,
622 &rx_rdy_db_dmaaddr, sizeof(uint32_t));
623 ipa_res->rx_ready_doorbell_dmaaddr = rx_rdy_db_dmaaddr;
624 }
625
Vevek Venkatesan606bdbc2020-03-11 15:33:33 +0530626 qdf_mem_free(pipe_in);
Yun Park84c0ceb2018-01-11 10:37:10 -0800627 return QDF_STATUS_SUCCESS;
628}
629
630/**
631 * ol_txrx_ipa_cleanup() - Disconnect IPA pipes
632 * @tx_pipe_handle: Tx pipe handle
633 * @rx_pipe_handle: Rx pipe handle
634 *
635 * Return: QDF_STATUS
636 */
637QDF_STATUS ol_txrx_ipa_cleanup(uint32_t tx_pipe_handle, uint32_t rx_pipe_handle)
638{
639 int ret;
Vevek Venkatesand222d482020-03-16 14:25:51 +0530640 struct ol_txrx_ipa_resources *ipa_res;
641 struct ol_txrx_soc_t *soc = cds_get_context(QDF_MODULE_ID_SOC);
642 qdf_device_t osdev = cds_get_context(QDF_MODULE_ID_QDF_DEVICE);
643 ol_txrx_pdev_handle pdev =
644 ol_txrx_get_pdev_from_pdev_id(soc, OL_TXRX_PDEV_ID);
645
646 if (!pdev) {
647 ol_txrx_err("%s invalid instance", __func__);
648 return QDF_STATUS_E_FAILURE;
649 }
650
651 ipa_res = &pdev->ipa_resource;
652 if (osdev->smmu_s1_enabled) {
653 ret = pld_smmu_unmap(osdev->dev,
654 ipa_res->rx_ready_doorbell_dmaaddr,
655 sizeof(uint32_t));
656 if (ret)
657 ol_txrx_err("%s rx_ready, smmu unmap failed", __func__);
658
659 ret = pld_smmu_unmap(osdev->dev,
660 ipa_res->tx_comp_doorbell_dmaaddr,
661 sizeof(uint32_t));
662 if (ret)
663 ol_txrx_err("%s tx_comp, smmu unmap failed", __func__);
664 }
Yun Park84c0ceb2018-01-11 10:37:10 -0800665
666 QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_DEBUG,
667 "%s: Disconnect IPA pipe", __func__);
668 ret = qdf_ipa_wdi_disconn_pipes();
669 if (ret) {
670 QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
671 "ipa_wdi_disconn_pipes failed: ret=%d", ret);
672 return QDF_STATUS_E_FAILURE;
673 }
674
675 return QDF_STATUS_SUCCESS;
676}
677
678/**
679 * ol_txrx_ipa_setup_iface() - Setup IPA header and register interface
680 * @ifname: Interface name
681 * @mac_addr: Interface MAC address
682 * @prod_client: IPA prod client type
683 * @cons_client: IPA cons client type
684 * @session_id: Session ID
685 * @is_ipv6_enabled: Is IPV6 enabled or not
686 *
687 * Return: QDF_STATUS
688 */
689QDF_STATUS ol_txrx_ipa_setup_iface(char *ifname, uint8_t *mac_addr,
690 qdf_ipa_client_type_t prod_client,
691 qdf_ipa_client_type_t cons_client,
692 uint8_t session_id, bool is_ipv6_enabled)
693{
694 qdf_ipa_wdi_reg_intf_in_params_t in;
695 qdf_ipa_wdi_hdr_info_t hdr_info;
696 struct ol_txrx_ipa_uc_tx_hdr uc_tx_hdr;
697 struct ol_txrx_ipa_uc_tx_hdr uc_tx_hdr_v6;
698 int ret = -EINVAL;
699
700 QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_DEBUG,
701 "%s: Add Partial hdr: %s, %pM",
702 __func__, ifname, mac_addr);
703
704 qdf_mem_zero(&hdr_info, sizeof(qdf_ipa_wdi_hdr_info_t));
705 memcpy(&uc_tx_hdr, &ipa_uc_tx_hdr, OL_TXRX_IPA_UC_WLAN_TX_HDR_LEN);
706 qdf_ether_addr_copy(uc_tx_hdr.eth.h_source, mac_addr);
707 uc_tx_hdr.ipa_hd.vdev_id = session_id;
708
709 /* IPV4 header */
710 uc_tx_hdr.eth.h_proto = qdf_htons(ETH_P_IP);
711
712 QDF_IPA_WDI_HDR_INFO_HDR(&hdr_info) = (uint8_t *)&uc_tx_hdr;
713 QDF_IPA_WDI_HDR_INFO_HDR_LEN(&hdr_info) =
714 OL_TXRX_IPA_UC_WLAN_TX_HDR_LEN;
715 QDF_IPA_WDI_HDR_INFO_HDR_TYPE(&hdr_info) = IPA_HDR_L2_ETHERNET_II;
716 QDF_IPA_WDI_HDR_INFO_DST_MAC_ADDR_OFFSET(&hdr_info) =
717 OL_TXRX_IPA_UC_WLAN_HDR_DES_MAC_OFFSET;
718
719 QDF_IPA_WDI_REG_INTF_IN_PARAMS_NETDEV_NAME(&in) = ifname;
720 memcpy(&(QDF_IPA_WDI_REG_INTF_IN_PARAMS_HDR_INFO(&in)[IPA_IP_v4]),
721 &hdr_info, sizeof(qdf_ipa_wdi_hdr_info_t));
722 QDF_IPA_WDI_REG_INTF_IN_PARAMS_ALT_DST_PIPE(&in) = cons_client;
723 QDF_IPA_WDI_REG_INTF_IN_PARAMS_IS_META_DATA_VALID(&in) = 1;
724 QDF_IPA_WDI_REG_INTF_IN_PARAMS_META_DATA(&in) =
725 htonl(session_id << 16);
726 QDF_IPA_WDI_REG_INTF_IN_PARAMS_META_DATA_MASK(&in) = htonl(0x00FF0000);
727
728 /* IPV6 header */
729 if (is_ipv6_enabled) {
730 memcpy(&uc_tx_hdr_v6, &uc_tx_hdr,
731 OL_TXRX_IPA_UC_WLAN_TX_HDR_LEN);
732 uc_tx_hdr_v6.eth.h_proto = qdf_htons(ETH_P_IPV6);
733 QDF_IPA_WDI_HDR_INFO_HDR(&hdr_info) = (uint8_t *)&uc_tx_hdr_v6;
734 memcpy(&(QDF_IPA_WDI_REG_INTF_IN_PARAMS_HDR_INFO(&in)[IPA_IP_v6]),
735 &hdr_info, sizeof(qdf_ipa_wdi_hdr_info_t));
736 }
737
738 ret = qdf_ipa_wdi_reg_intf(&in);
739 if (ret) {
740 QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
741 "%s: ipa_wdi_reg_intf falied: ret=%d", __func__, ret);
742 }
743
744 return ret;
745}
746
747/**
748 * ol_txrx_ipa_cleanup_iface() - Cleanup IPA header and deregister interface
749 * @ifname: Interface name
750 * @is_ipv6_enabled: Is IPV6 enabled or not
751 *
752 * Return: QDF_STATUS
753 */
754QDF_STATUS ol_txrx_ipa_cleanup_iface(char *ifname, bool is_ipv6_enabled)
755{
756 int ret;
757
758 /* unregister the interface with IPA */
759 ret = qdf_ipa_wdi_dereg_intf(ifname);
760 if (ret) {
761 QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_DEBUG,
762 "%s: ipa_wdi_dereg_intf failed: devname=%s, ret=%d",
763 __func__, ifname, ret);
764 return QDF_STATUS_E_FAILURE;
765 }
766
767 return QDF_STATUS_SUCCESS;
768}
769
Vevek Venkatesan29076ec2019-08-22 17:53:12 +0530770QDF_STATUS ol_txrx_ipa_enable_pipes(struct cdp_soc_t *soc_hdl, uint8_t pdev_id)
Yun Park84c0ceb2018-01-11 10:37:10 -0800771{
Vevek Venkatesan29076ec2019-08-22 17:53:12 +0530772 struct ol_txrx_soc_t *soc = cdp_soc_t_to_ol_txrx_soc_t(soc_hdl);
773 ol_txrx_pdev_handle pdev = ol_txrx_get_pdev_from_pdev_id(soc, pdev_id);
Sravan Kumar Kairamb5870bb2018-06-13 16:49:27 +0530774 QDF_STATUS status;
Yun Park84c0ceb2018-01-11 10:37:10 -0800775 int ret;
776
Vevek Venkatesan29076ec2019-08-22 17:53:12 +0530777 if (!pdev) {
778 ol_txrx_err("%s invalid instance", __func__);
779 return QDF_STATUS_E_FAILURE;
780 }
781
Sravan Kumar Kairamb5870bb2018-06-13 16:49:27 +0530782 status = htt_rx_update_smmu_map(pdev->htt_pdev, true);
783 if (status != QDF_STATUS_SUCCESS) {
784 QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
785 "IPA SMMU map failed status:%d", status);
786 return status;
787 }
788
Yun Park84c0ceb2018-01-11 10:37:10 -0800789 /* ACTIVATE TX PIPE */
790 QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_DEBUG,
791 "%s: Enable IPA pipes", __func__);
792 ret = qdf_ipa_wdi_enable_pipes();
793 if (ret) {
794 QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
795 "%s: ipa_wdi_enable_pipes failed: ret=%d",
796 __func__, ret);
Sravan Kumar Kairamb5870bb2018-06-13 16:49:27 +0530797 status = htt_rx_update_smmu_map(pdev->htt_pdev, false);
798 if (status != QDF_STATUS_SUCCESS)
799 QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
800 "IPA SMMU unmap failed");
Yun Park84c0ceb2018-01-11 10:37:10 -0800801 return QDF_STATUS_E_FAILURE;
802 }
803
Vevek Venkatesan29076ec2019-08-22 17:53:12 +0530804 ol_txrx_ipa_uc_set_active(soc_hdl, pdev_id, true, true);
805 ol_txrx_ipa_uc_set_active(soc_hdl, pdev_id, true, false);
Yun Park84c0ceb2018-01-11 10:37:10 -0800806
807 return QDF_STATUS_SUCCESS;
808}
809
Vevek Venkatesan29076ec2019-08-22 17:53:12 +0530810QDF_STATUS ol_txrx_ipa_disable_pipes(struct cdp_soc_t *soc_hdl, uint8_t pdev_id)
Yun Park84c0ceb2018-01-11 10:37:10 -0800811{
Vevek Venkatesan29076ec2019-08-22 17:53:12 +0530812 struct ol_txrx_soc_t *soc = cdp_soc_t_to_ol_txrx_soc_t(soc_hdl);
813 ol_txrx_pdev_handle pdev = ol_txrx_get_pdev_from_pdev_id(soc, pdev_id);
Yun Park84c0ceb2018-01-11 10:37:10 -0800814 int ret;
815
Vevek Venkatesan29076ec2019-08-22 17:53:12 +0530816 if (!pdev) {
817 ol_txrx_err("%s invalid instance", __func__);
818 return QDF_STATUS_E_FAILURE;
819 }
820
Yun Park84c0ceb2018-01-11 10:37:10 -0800821 QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_DEBUG,
822 "%s: Disable IPA pipes", __func__);
823 ret = qdf_ipa_wdi_disable_pipes();
824 if (ret) {
825 QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
826 "%s: ipa_wdi_disable_pipes failed: ret=%d",
827 __func__, ret);
Yun Park84c0ceb2018-01-11 10:37:10 -0800828 }
829
Sravan Kumar Kairamb5870bb2018-06-13 16:49:27 +0530830 if (htt_rx_update_smmu_map(pdev->htt_pdev, false) !=
831 QDF_STATUS_SUCCESS) {
832 QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
Sravan Kumar Kairam5eeeb7a2018-06-21 13:27:13 +0530833 "IPA SMMU unmap failed");
Sravan Kumar Kairamb5870bb2018-06-13 16:49:27 +0530834 }
835
836 return ret ? QDF_STATUS_E_FAILURE : QDF_STATUS_SUCCESS;
Yun Park84c0ceb2018-01-11 10:37:10 -0800837}
838
Sravan Kumar Kairamfbc87b72018-04-09 14:09:52 +0530839/**
840 * ol_txrx_ipa_set_perf_level() - Set IPA clock bandwidth based on data rates
841 * @client: Client type
842 * @max_supported_bw_mbps: Maximum bandwidth needed (in Mbps)
843 *
844 * Return: QDF_STATUS
845 */
846QDF_STATUS ol_txrx_ipa_set_perf_level(int client,
847 uint32_t max_supported_bw_mbps)
848{
849 qdf_ipa_wdi_perf_profile_t profile;
850 int result;
851
852 QDF_IPA_WDI_PERF_PROFILE_CLIENT(&profile) = client;
853 QDF_IPA_WDI_PERF_PROFILE_MAX_SUPPORTED_BW_MBPS(&profile) =
854 max_supported_bw_mbps;
855 result = qdf_ipa_wdi_set_perf_profile(&profile);
856
857 if (result) {
858 QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
859 "Set perf profile failed, code %d", result);
860
861 return QDF_STATUS_E_FAILURE;
862 }
863
864 return QDF_STATUS_SUCCESS;
865}
866
Yun Park84c0ceb2018-01-11 10:37:10 -0800867#else /* CONFIG_IPA_WDI_UNIFIED_API */
868
Sravan Kumar Kairamb664b6c2018-02-27 17:43:10 +0530869#ifdef ENABLE_SMMU_S1_TRANSLATION
870/**
871 * ol_txrx_ipa_tx_smmu_params() - Config IPA TX params
872 * @ipa_res: IPA resources
873 * @pipe_in: IPA WDI TX pipe params
874 *
875 * Return: None
876 */
877static inline void ol_txrx_ipa_tx_smmu_params(
878 struct ol_txrx_ipa_resources *ipa_res,
879 qdf_ipa_wdi_in_params_t *pipe_in)
880{
881 QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_DEBUG,
882 "%s: SMMU Enabled", __func__);
883
884 QDF_IPA_PIPE_IN_SMMU_ENABLED(pipe_in) = true;
885 qdf_mem_copy(&QDF_IPA_PIPE_IN_DL_SMMU_COMP_RING(pipe_in),
886 &ipa_res->tx_comp_ring->sgtable,
887 sizeof(sgtable_t));
888 QDF_IPA_PIPE_IN_DL_SMMU_COMP_RING_SIZE(pipe_in) =
889 ipa_res->tx_comp_ring->mem_info.size;
890 qdf_mem_copy(&QDF_IPA_PIPE_IN_DL_SMMU_CE_RING(pipe_in),
891 &ipa_res->ce_sr->sgtable,
892 sizeof(sgtable_t));
893 QDF_IPA_PIPE_IN_DL_SMMU_CE_DOOR_BELL_PA(pipe_in) =
894 ipa_res->ce_reg_paddr;
895 QDF_IPA_PIPE_IN_DL_SMMU_CE_RING_SIZE(pipe_in) =
896 ipa_res->ce_sr_ring_size;
897 QDF_IPA_PIPE_IN_DL_SMMU_NUM_TX_BUFFERS(pipe_in) =
898 ipa_res->tx_num_alloc_buffer;
899}
900
901/**
902 * ol_txrx_ipa_rx_smmu_params() - Config IPA TX params
903 * @ipa_res: IPA resources
904 * @pipe_in: IPA WDI TX pipe params
905 *
906 * Return: None
907 */
908static inline void ol_txrx_ipa_rx_smmu_params(
909 struct ol_txrx_ipa_resources *ipa_res,
910 qdf_ipa_wdi_in_params_t *pipe_in)
911{
912 qdf_mem_copy(&QDF_IPA_PIPE_IN_UL_SMMU_RDY_RING(pipe_in),
913 &ipa_res->rx_rdy_ring->sgtable,
914 sizeof(sgtable_t));
915 QDF_IPA_PIPE_IN_UL_SMMU_RDY_RING_SIZE(pipe_in) =
916 ipa_res->rx_rdy_ring->mem_info.size;
917 QDF_IPA_PIPE_IN_UL_SMMU_RDY_RING_RP_PA(pipe_in) =
918 ipa_res->rx_proc_done_idx->mem_info.pa;
919
920 QDF_IPA_PIPE_IN_UL_SMMU_RDY_RING_RP_VA(pipe_in) =
921 ipa_res->rx_proc_done_idx->vaddr;
922 qdf_mem_copy(&QDF_IPA_PIPE_IN_UL_SMMU_RDY_COMP_RING(pipe_in),
923 &ipa_res->rx2_rdy_ring->sgtable,
924 sizeof(sgtable_t));
925 QDF_IPA_PIPE_IN_UL_SMMU_RDY_COMP_RING_SIZE(pipe_in) =
926 ipa_res->rx2_rdy_ring->mem_info.size;
927 QDF_IPA_PIPE_IN_UL_SMMU_RDY_COMP_RING_WP_PA(pipe_in) =
928 ipa_res->rx2_proc_done_idx->mem_info.pa;
929 QDF_IPA_PIPE_IN_UL_SMMU_RDY_COMP_RING_WP_VA(pipe_in) =
930 ipa_res->rx2_proc_done_idx->vaddr;
931}
932#else
933static inline void ol_txrx_ipa_tx_smmu_params(
934 struct ol_txrx_ipa_resources *ipa_res,
935 qdf_ipa_wdi_in_params_t *pipe_in)
936{
937}
938
939static inline void ol_txrx_ipa_rx_smmu_params(
940 struct ol_txrx_ipa_resources *ipa_res,
941 qdf_ipa_wdi_in_params_t *pipe_in)
942{
943}
944#endif
945
946/**
947 * ol_txrx_ipa_tx_params() - Config IPA TX params
948 * @ipa_res: IPA resources
949 * @pipe_in: IPA WDI TX pipe params
950 *
951 * Return: None
952 */
953static inline void ol_txrx_ipa_tx_params(
954 struct ol_txrx_ipa_resources *ipa_res,
955 qdf_ipa_wdi_in_params_t *pipe_in)
956{
957 qdf_device_t osdev = cds_get_context(QDF_MODULE_ID_QDF_DEVICE);
958
Vulupala Shashank Reddy4bf9be62019-06-03 12:33:00 +0530959 if (!osdev) {
960 QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
961 "%s: qdf device is null!", __func__);
962 return;
963 }
964
Sravan Kumar Kairamb664b6c2018-02-27 17:43:10 +0530965 QDF_IPA_PIPE_IN_DL_COMP_RING_BASE_PA(pipe_in) =
966 qdf_mem_get_dma_addr(osdev,
967 &ipa_res->tx_comp_ring->mem_info);
968 QDF_IPA_PIPE_IN_DL_COMP_RING_SIZE(pipe_in) =
969 ipa_res->tx_comp_ring->mem_info.size;
970 QDF_IPA_PIPE_IN_DL_CE_RING_BASE_PA(pipe_in) =
971 qdf_mem_get_dma_addr(osdev,
972 &ipa_res->ce_sr->mem_info);
973 QDF_IPA_PIPE_IN_DL_CE_DOOR_BELL_PA(pipe_in) =
974 ipa_res->ce_reg_paddr;
975 QDF_IPA_PIPE_IN_DL_CE_RING_SIZE(pipe_in) =
976 ipa_res->ce_sr_ring_size;
977 QDF_IPA_PIPE_IN_DL_NUM_TX_BUFFERS(pipe_in) =
978 ipa_res->tx_num_alloc_buffer;
979}
980
981/**
982 * ol_txrx_ipa_rx_params() - Config IPA RX params
983 * @ipa_res: IPA resources
984 * @pipe_in: IPA WDI RX pipe params
985 *
986 * Return: None
987 */
988static inline void ol_txrx_ipa_rx_params(
989 struct ol_txrx_ipa_resources *ipa_res,
990 qdf_ipa_wdi_in_params_t *pipe_in)
991{
Vulupala Shashank Reddy4bf9be62019-06-03 12:33:00 +0530992 qdf_device_t osdev = cds_get_context(QDF_MODULE_ID_QDF_DEVICE);
993
994 if (!osdev) {
995 QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
996 "%s: qdf device is null!", __func__);
997 return;
998 }
999
Sravan Kumar Kairamb664b6c2018-02-27 17:43:10 +05301000 QDF_IPA_PIPE_IN_UL_RDY_RING_BASE_PA(pipe_in) =
1001 ipa_res->rx_rdy_ring->mem_info.pa;
1002 QDF_IPA_PIPE_IN_UL_RDY_RING_SIZE(pipe_in) =
1003 ipa_res->rx_rdy_ring->mem_info.size;
1004 QDF_IPA_PIPE_IN_UL_RDY_RING_RP_PA(pipe_in) =
1005 ipa_res->rx_proc_done_idx->mem_info.pa;
1006 OL_TXRX_IPA_WDI2_SET(pipe_in, ipa_res,
Vulupala Shashank Reddy4bf9be62019-06-03 12:33:00 +05301007 osdev);
Sravan Kumar Kairamb664b6c2018-02-27 17:43:10 +05301008}
1009
Vevek Venkatesan29076ec2019-08-22 17:53:12 +05301010QDF_STATUS ol_txrx_ipa_setup(struct cdp_soc_t *soc_hdl, uint8_t pdev_id,
1011 void *ipa_i2w_cb, void *ipa_w2i_cb,
1012 void *ipa_wdi_meter_notifier_cb,
Yun Parkb4f591d2017-03-29 15:51:01 -07001013 uint32_t ipa_desc_size, void *ipa_priv,
1014 bool is_rm_enabled, uint32_t *p_tx_pipe_handle,
1015 uint32_t *p_rx_pipe_handle)
Yun Parkb4f591d2017-03-29 15:51:01 -07001016{
Vevek Venkatesan29076ec2019-08-22 17:53:12 +05301017 struct ol_txrx_soc_t *soc = cdp_soc_t_to_ol_txrx_soc_t(soc_hdl);
1018 ol_txrx_pdev_handle pdev = ol_txrx_get_pdev_from_pdev_id(soc, pdev_id);
Sravan Kumar Kairamb664b6c2018-02-27 17:43:10 +05301019 qdf_device_t osdev = cds_get_context(QDF_MODULE_ID_QDF_DEVICE);
Vevek Venkatesan29076ec2019-08-22 17:53:12 +05301020 struct ol_txrx_ipa_resources *ipa_res;
Yun Park6c86a662017-10-05 16:09:15 -07001021 qdf_ipa_wdi_in_params_t pipe_in;
1022 qdf_ipa_wdi_out_params_t pipe_out;
Sravan Kumar Kairamb664b6c2018-02-27 17:43:10 +05301023 uint32_t tx_comp_db_dmaaddr = 0, rx_rdy_db_dmaaddr = 0;
Yun Parkb4f591d2017-03-29 15:51:01 -07001024 int ret;
1025
Vevek Venkatesan29076ec2019-08-22 17:53:12 +05301026 if (!pdev) {
1027 ol_txrx_err("%s invalid instance", __func__);
1028 return QDF_STATUS_E_FAILURE;
1029 }
1030
Vulupala Shashank Reddy4bf9be62019-06-03 12:33:00 +05301031 if (!osdev) {
1032 QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
1033 "%s: qdf device is null!", __func__);
1034 return QDF_STATUS_E_NOENT;
1035 }
1036
Vevek Venkatesan29076ec2019-08-22 17:53:12 +05301037 ipa_res = &pdev->ipa_resource;
Yun Park6c86a662017-10-05 16:09:15 -07001038 qdf_mem_zero(&pipe_in, sizeof(pipe_in));
1039 qdf_mem_zero(&pipe_out, sizeof(pipe_out));
1040
Yun Parkb4f591d2017-03-29 15:51:01 -07001041 /* TX PIPE */
Yun Park6c86a662017-10-05 16:09:15 -07001042 QDF_IPA_PIPE_IN_NAT_EN(&pipe_in) = IPA_BYPASS_NAT;
1043 QDF_IPA_PIPE_IN_HDR_LEN(&pipe_in) = OL_TXRX_IPA_UC_WLAN_TX_HDR_LEN;
1044 QDF_IPA_PIPE_IN_HDR_OFST_PKT_SIZE_VALID(&pipe_in) = 1;
1045 QDF_IPA_PIPE_IN_HDR_OFST_PKT_SIZE(&pipe_in) = 0;
1046 QDF_IPA_PIPE_IN_HDR_ADDITIONAL_CONST_LEN(&pipe_in) =
Yun Parkb4f591d2017-03-29 15:51:01 -07001047 OL_TXRX_IPA_UC_WLAN_8023_HDR_SIZE;
Yun Park6c86a662017-10-05 16:09:15 -07001048 QDF_IPA_PIPE_IN_MODE(&pipe_in) = IPA_BASIC;
1049 QDF_IPA_PIPE_IN_CLIENT(&pipe_in) = IPA_CLIENT_WLAN1_CONS;
1050 QDF_IPA_PIPE_IN_DESC_FIFO_SZ(&pipe_in) = ipa_desc_size;
1051 QDF_IPA_PIPE_IN_PRIV(&pipe_in) = ipa_priv;
1052 QDF_IPA_PIPE_IN_HDR_LITTLE_ENDIAN(&pipe_in) = true;
1053 QDF_IPA_PIPE_IN_NOTIFY(&pipe_in) = ipa_i2w_cb;
1054
Yun Parkb4f591d2017-03-29 15:51:01 -07001055 if (!is_rm_enabled) {
1056 QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_DEBUG,
1057 "%s: IPA RM DISABLED, IPA AWAKE", __func__);
Yun Park6c86a662017-10-05 16:09:15 -07001058 QDF_IPA_PIPE_IN_KEEP_IPA_AWAKE(&pipe_in) = true;
Yun Parkb4f591d2017-03-29 15:51:01 -07001059 }
1060
Sravan Kumar Kairamb664b6c2018-02-27 17:43:10 +05301061 if (qdf_mem_smmu_s1_enabled(osdev))
1062 ol_txrx_ipa_tx_smmu_params(ipa_res, &pipe_in);
1063 else
1064 ol_txrx_ipa_tx_params(ipa_res, &pipe_in);
Yun Parkb4f591d2017-03-29 15:51:01 -07001065
1066 /* Connect WDI IPA PIPE */
Yun Park84c0ceb2018-01-11 10:37:10 -08001067 ret = qdf_ipa_connect_wdi_pipe(&pipe_in, &pipe_out);
Yun Parkb4f591d2017-03-29 15:51:01 -07001068 if (ret) {
1069 QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
1070 "ipa_connect_wdi_pipe: Tx pipe setup failed: ret=%d", ret);
1071 return QDF_STATUS_E_FAILURE;
1072 }
1073
1074 /* Micro Controller Doorbell register */
1075 QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_DEBUG,
Yun Park6c86a662017-10-05 16:09:15 -07001076 "%s CONS DB pipe out 0x%x TX PIPE Handle 0x%x", __func__,
1077 (unsigned int)QDF_IPA_PIPE_OUT_UC_DOOR_BELL_PA(&pipe_out),
Yun Parkb4f591d2017-03-29 15:51:01 -07001078 pipe_out.clnt_hdl);
Sravan Kumar Kairamb664b6c2018-02-27 17:43:10 +05301079 ipa_res->tx_comp_doorbell_dmaaddr =
Yun Park6c86a662017-10-05 16:09:15 -07001080 QDF_IPA_PIPE_OUT_UC_DOOR_BELL_PA(&pipe_out);
Yun Parkb4f591d2017-03-29 15:51:01 -07001081 /* WLAN TX PIPE Handle */
Yun Park6c86a662017-10-05 16:09:15 -07001082 ipa_res->tx_pipe_handle = QDF_IPA_PIPE_OUT_CLNT_HDL(&pipe_out);
1083 *p_tx_pipe_handle = QDF_IPA_PIPE_OUT_CLNT_HDL(&pipe_out);
Yun Parkb4f591d2017-03-29 15:51:01 -07001084
1085 /* RX PIPE */
Yun Park6c86a662017-10-05 16:09:15 -07001086 QDF_IPA_PIPE_IN_NAT_EN(&pipe_in) = IPA_BYPASS_NAT;
1087 QDF_IPA_PIPE_IN_HDR_LEN(&pipe_in) = OL_TXRX_IPA_UC_WLAN_RX_HDR_LEN;
1088 QDF_IPA_PIPE_IN_HDR_OFST_METADATA_VALID(&pipe_in) = 0;
1089 QDF_IPA_PIPE_IN_HDR_METADATA_REG_VALID(&pipe_in) = 1;
1090 QDF_IPA_PIPE_IN_MODE(&pipe_in) = IPA_BASIC;
1091 QDF_IPA_PIPE_IN_CLIENT(&pipe_in) = IPA_CLIENT_WLAN1_PROD;
1092 QDF_IPA_PIPE_IN_DESC_FIFO_SZ(&pipe_in) =
Yuanyuan Liu23a8eec2017-12-15 16:01:12 -08001093 ipa_desc_size + SPS_DESC_SIZE;
Yun Park6c86a662017-10-05 16:09:15 -07001094 QDF_IPA_PIPE_IN_NOTIFY(&pipe_in) = ipa_w2i_cb;
Yun Parkb4f591d2017-03-29 15:51:01 -07001095 if (!is_rm_enabled) {
1096 QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
1097 "%s: IPA RM DISABLED, IPA AWAKE", __func__);
Yun Park6c86a662017-10-05 16:09:15 -07001098 QDF_IPA_PIPE_IN_KEEP_IPA_AWAKE(&pipe_in) = true;
Yun Parkb4f591d2017-03-29 15:51:01 -07001099 }
1100
Sravan Kumar Kairamb664b6c2018-02-27 17:43:10 +05301101 if (qdf_mem_smmu_s1_enabled(osdev))
1102 ol_txrx_ipa_rx_smmu_params(ipa_res, &pipe_in);
1103 else
1104 ol_txrx_ipa_rx_params(ipa_res, &pipe_in);
Yun Parkb4f591d2017-03-29 15:51:01 -07001105
1106#ifdef FEATURE_METERING
Yun Park6c86a662017-10-05 16:09:15 -07001107 QDF_IPA_PIPE_IN_WDI_NOTIFY(&pipe_in) = ipa_wdi_meter_notifier_cb;
Yun Parkb4f591d2017-03-29 15:51:01 -07001108#endif
1109
Yun Park84c0ceb2018-01-11 10:37:10 -08001110 ret = qdf_ipa_connect_wdi_pipe(&pipe_in, &pipe_out);
Yun Parkb4f591d2017-03-29 15:51:01 -07001111 if (ret) {
1112 QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
1113 "ipa_connect_wdi_pipe: Rx pipe setup failed: ret=%d", ret);
1114 return QDF_STATUS_E_FAILURE;
1115 }
Sravan Kumar Kairamb664b6c2018-02-27 17:43:10 +05301116 ipa_res->rx_ready_doorbell_dmaaddr =
Yun Park6c86a662017-10-05 16:09:15 -07001117 QDF_IPA_PIPE_OUT_UC_DOOR_BELL_PA(&pipe_out);
1118 ipa_res->rx_pipe_handle = QDF_IPA_PIPE_OUT_CLNT_HDL(&pipe_out);
1119 *p_rx_pipe_handle = QDF_IPA_PIPE_OUT_CLNT_HDL(&pipe_out);
Sravan Kumar Kairamb664b6c2018-02-27 17:43:10 +05301120
1121 if (qdf_mem_smmu_s1_enabled(osdev)) {
1122 pld_smmu_map(osdev->dev, ipa_res->tx_comp_doorbell_dmaaddr,
1123 &tx_comp_db_dmaaddr, sizeof(uint32_t));
1124 ipa_res->tx_comp_doorbell_dmaaddr = tx_comp_db_dmaaddr;
1125
1126 pld_smmu_map(osdev->dev, ipa_res->rx_ready_doorbell_dmaaddr,
1127 &rx_rdy_db_dmaaddr, sizeof(uint32_t));
1128 ipa_res->rx_ready_doorbell_dmaaddr = rx_rdy_db_dmaaddr;
1129 }
Yun Parkb4f591d2017-03-29 15:51:01 -07001130
1131 return QDF_STATUS_SUCCESS;
1132}
1133
1134/**
1135 * ol_txrx_ipa_cleanup() - Disconnect IPA pipes
1136 * @tx_pipe_handle: Tx pipe handle
1137 * @rx_pipe_handle: Rx pipe handle
1138 *
1139 * Return: QDF_STATUS
1140 */
1141QDF_STATUS ol_txrx_ipa_cleanup(uint32_t tx_pipe_handle, uint32_t rx_pipe_handle)
1142{
1143 int ret;
1144
1145 QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_DEBUG,
1146 "%s: Disconnect TX PIPE tx_pipe_handle=0x%x",
1147 __func__, tx_pipe_handle);
Yun Park84c0ceb2018-01-11 10:37:10 -08001148 ret = qdf_ipa_disconnect_wdi_pipe(tx_pipe_handle);
Yun Parkb4f591d2017-03-29 15:51:01 -07001149 if (ret) {
1150 QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
1151 "ipa_disconnect_wdi_pipe: Tx pipe cleanup failed: ret=%d",
1152 ret);
1153 return QDF_STATUS_E_FAILURE;
1154 }
1155
1156 QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_DEBUG,
1157 "%s: Disconnect RX PIPE rx_pipe_handle=0x%x",
1158 __func__, rx_pipe_handle);
Yun Park84c0ceb2018-01-11 10:37:10 -08001159 ret = qdf_ipa_disconnect_wdi_pipe(rx_pipe_handle);
Yun Parkb4f591d2017-03-29 15:51:01 -07001160 if (ret) {
1161 QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
1162 "ipa_disconnect_wdi_pipe: Rx pipe cleanup failed: ret=%d",
1163 ret);
1164 return QDF_STATUS_E_FAILURE;
1165 }
1166
1167 return QDF_STATUS_SUCCESS;
1168}
1169
1170/**
1171 * ol_txrx_remove_ipa_header() - Remove a specific header from IPA
1172 * @name: Name of the header to be removed
1173 *
1174 * Return: QDF_STATUS
1175 */
1176static QDF_STATUS ol_txrx_ipa_remove_header(char *name)
1177{
Yun Park6c86a662017-10-05 16:09:15 -07001178 qdf_ipa_ioc_get_hdr_t hdrlookup;
Yun Parkb4f591d2017-03-29 15:51:01 -07001179 int ret = 0, len;
Yun Park6c86a662017-10-05 16:09:15 -07001180 qdf_ipa_ioc_del_hdr_t *ipa_hdr;
Yun Parkb4f591d2017-03-29 15:51:01 -07001181
1182 qdf_mem_zero(&hdrlookup, sizeof(hdrlookup));
1183 strlcpy(hdrlookup.name, name, sizeof(hdrlookup.name));
Yun Park6c86a662017-10-05 16:09:15 -07001184 ret = qdf_ipa_get_hdr(&hdrlookup);
Yun Parkb4f591d2017-03-29 15:51:01 -07001185 if (ret) {
1186 QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_DEBUG,
1187 "Hdr deleted already %s, %d", name, ret);
1188 return QDF_STATUS_E_FAILURE;
1189 }
1190
1191 QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_DEBUG, "hdl: 0x%x",
1192 hdrlookup.hdl);
Yun Park6c86a662017-10-05 16:09:15 -07001193 len = sizeof(qdf_ipa_ioc_del_hdr_t) + sizeof(qdf_ipa_hdr_del_t) * 1;
1194 ipa_hdr = (qdf_ipa_ioc_del_hdr_t *)qdf_mem_malloc(len);
Nirav Shah7c8c1712018-09-10 16:01:31 +05301195 if (!ipa_hdr)
Yun Parkb4f591d2017-03-29 15:51:01 -07001196 return QDF_STATUS_E_FAILURE;
Nirav Shah7c8c1712018-09-10 16:01:31 +05301197
Yun Park6c86a662017-10-05 16:09:15 -07001198 QDF_IPA_IOC_DEL_HDR_NUM_HDRS(ipa_hdr) = 1;
1199 QDF_IPA_IOC_DEL_HDR_COMMIT(ipa_hdr) = 0;
1200 QDF_IPA_IOC_DEL_HDR_HDL(ipa_hdr) = QDF_IPA_IOC_GET_HDR_HDL(&hdrlookup);
1201 QDF_IPA_IOC_DEL_HDR_STATUS(ipa_hdr) = -1;
1202 ret = qdf_ipa_del_hdr(ipa_hdr);
Yun Parkb4f591d2017-03-29 15:51:01 -07001203 if (ret != 0) {
1204 QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
1205 "Delete header failed: %d", ret);
1206 qdf_mem_free(ipa_hdr);
1207 return QDF_STATUS_E_FAILURE;
1208 }
1209
1210 qdf_mem_free(ipa_hdr);
1211 return QDF_STATUS_SUCCESS;
1212}
1213
1214/**
1215 * ol_txrx_ipa_add_header_info() - Add IPA header for a given interface
1216 * @ifname: Interface name
1217 * @mac_addr: Interface MAC address
1218 * @is_ipv6_enabled: Is IPV6 enabled or not
1219 *
1220 * Return: 0 on success, negativer errno value on error
1221 */
1222static int ol_txrx_ipa_add_header_info(char *ifname, uint8_t *mac_addr,
1223 uint8_t session_id, bool is_ipv6_enabled)
1224{
Yun Park6c86a662017-10-05 16:09:15 -07001225 qdf_ipa_ioc_add_hdr_t *ipa_hdr = NULL;
Yun Parkb4f591d2017-03-29 15:51:01 -07001226 int ret = -EINVAL;
1227 struct ol_txrx_ipa_uc_tx_hdr *uc_tx_hdr = NULL;
1228
1229 QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_DEBUG,
1230 "Add Partial hdr: %s, %pM", ifname, mac_addr);
1231
1232 /* dynamically allocate the memory to add the hdrs */
Yun Park6c86a662017-10-05 16:09:15 -07001233 ipa_hdr = qdf_mem_malloc(sizeof(qdf_ipa_ioc_add_hdr_t)
1234 + sizeof(qdf_ipa_hdr_add_t));
Yun Parkb4f591d2017-03-29 15:51:01 -07001235 if (!ipa_hdr) {
Yun Parkb4f591d2017-03-29 15:51:01 -07001236 ret = -ENOMEM;
1237 goto end;
1238 }
1239
Yun Park6c86a662017-10-05 16:09:15 -07001240 QDF_IPA_IOC_ADD_HDR_COMMIT(ipa_hdr) = 0;
1241 QDF_IPA_IOC_ADD_HDR_NUM_HDRS(ipa_hdr) = 1;
Yun Parkb4f591d2017-03-29 15:51:01 -07001242
Yun Park6c86a662017-10-05 16:09:15 -07001243 uc_tx_hdr = (struct ol_txrx_ipa_uc_tx_hdr *)
1244 QDF_IPA_IOC_ADD_HDR_HDR(ipa_hdr);
Yun Parkb4f591d2017-03-29 15:51:01 -07001245 memcpy(uc_tx_hdr, &ipa_uc_tx_hdr, OL_TXRX_IPA_UC_WLAN_TX_HDR_LEN);
1246 memcpy(uc_tx_hdr->eth.h_source, mac_addr, ETH_ALEN);
1247 uc_tx_hdr->ipa_hd.vdev_id = session_id;
1248 QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_DEBUG,
1249 "ifname=%s, vdev_id=%d",
1250 ifname, uc_tx_hdr->ipa_hd.vdev_id);
Yun Park6c86a662017-10-05 16:09:15 -07001251 snprintf(QDF_IPA_IOC_ADD_HDR_NAME(ipa_hdr), IPA_RESOURCE_NAME_MAX,
1252 "%s%s", ifname, OL_TXRX_IPA_IPV4_NAME_EXT);
1253 QDF_IPA_IOC_ADD_HDR_HDR_LEN(ipa_hdr) = OL_TXRX_IPA_UC_WLAN_TX_HDR_LEN;
1254 QDF_IPA_IOC_ADD_HDR_TYPE(ipa_hdr) = IPA_HDR_L2_ETHERNET_II;
1255 QDF_IPA_IOC_ADD_HDR_IS_PARTIAL(ipa_hdr) = 1;
1256 QDF_IPA_IOC_ADD_HDR_HDR_HDL(ipa_hdr) = 0;
1257 QDF_IPA_IOC_ADD_HDR_IS_ETH2_OFST_VALID(ipa_hdr) = 1;
1258 QDF_IPA_IOC_ADD_HDR_ETH2_OFST(ipa_hdr) =
1259 OL_TXRX_IPA_UC_WLAN_HDR_DES_MAC_OFFSET;
Yun Parkb4f591d2017-03-29 15:51:01 -07001260
Yun Park6c86a662017-10-05 16:09:15 -07001261 ret = qdf_ipa_add_hdr(ipa_hdr);
Yun Parkb4f591d2017-03-29 15:51:01 -07001262 if (ret) {
1263 QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
1264 "%s IPv4 add hdr failed: %d", ifname, ret);
1265 goto end;
1266 }
1267
1268 QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_DEBUG,
Yun Park6c86a662017-10-05 16:09:15 -07001269 "%s: IPv4 hdr_hdl: 0x%x",
1270 QDF_IPA_IOC_ADD_HDR_NAME(ipa_hdr),
1271 QDF_IPA_IOC_ADD_HDR_HDR_HDL(ipa_hdr));
Yun Parkb4f591d2017-03-29 15:51:01 -07001272
1273 if (is_ipv6_enabled) {
Yun Park6c86a662017-10-05 16:09:15 -07001274 snprintf(QDF_IPA_IOC_ADD_HDR_NAME(ipa_hdr),
1275 IPA_RESOURCE_NAME_MAX, "%s%s",
Yun Parkb4f591d2017-03-29 15:51:01 -07001276 ifname, OL_TXRX_IPA_IPV6_NAME_EXT);
1277
Yun Park6c86a662017-10-05 16:09:15 -07001278 uc_tx_hdr = (struct ol_txrx_ipa_uc_tx_hdr *)
1279 QDF_IPA_IOC_ADD_HDR_HDR(ipa_hdr);
Yun Parkb4f591d2017-03-29 15:51:01 -07001280 uc_tx_hdr->eth.h_proto = cpu_to_be16(ETH_P_IPV6);
1281
Yun Park6c86a662017-10-05 16:09:15 -07001282 ret = qdf_ipa_add_hdr(ipa_hdr);
Yun Parkb4f591d2017-03-29 15:51:01 -07001283 if (ret) {
1284 QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
1285 "%s: IPv6 add hdr failed: %d", ifname, ret);
1286 goto clean_ipv4_hdr;
1287 }
1288
1289 QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_DEBUG,
Yun Park6c86a662017-10-05 16:09:15 -07001290 "%s: IPv6 hdr_hdl: 0x%x",
1291 QDF_IPA_IOC_ADD_HDR_NAME(ipa_hdr),
1292 QDF_IPA_IOC_ADD_HDR_HDR_HDL(ipa_hdr));
Yun Parkb4f591d2017-03-29 15:51:01 -07001293 }
1294
1295 qdf_mem_free(ipa_hdr);
1296
1297 return ret;
1298
1299clean_ipv4_hdr:
1300 snprintf(ipa_hdr->hdr[0].name, IPA_RESOURCE_NAME_MAX, "%s%s",
1301 ifname, OL_TXRX_IPA_IPV4_NAME_EXT);
1302 ol_txrx_ipa_remove_header(ipa_hdr->hdr[0].name);
1303end:
1304 if (ipa_hdr)
1305 qdf_mem_free(ipa_hdr);
1306
1307 return ret;
1308}
1309
1310/**
1311 * ol_txrx_ipa_register_interface() - register IPA interface
1312 * @ifname: Interface name
1313 * @prod_client: IPA prod client type
1314 * @cons_client: IPA cons client type
1315 * @session_id: Session ID
1316 * @is_ipv6_enabled: Is IPV6 enabled or not
1317 *
1318 * Return: 0 on success, negative errno on error
1319 */
1320static int ol_txrx_ipa_register_interface(char *ifname,
Yun Park6c86a662017-10-05 16:09:15 -07001321 qdf_ipa_client_type_t prod_client,
1322 qdf_ipa_client_type_t cons_client,
Yun Parkb4f591d2017-03-29 15:51:01 -07001323 uint8_t session_id,
1324 bool is_ipv6_enabled)
1325{
Yun Park6c86a662017-10-05 16:09:15 -07001326 qdf_ipa_tx_intf_t tx_intf;
1327 qdf_ipa_rx_intf_t rx_intf;
1328 qdf_ipa_ioc_tx_intf_prop_t *tx_prop = NULL;
1329 qdf_ipa_ioc_rx_intf_prop_t *rx_prop = NULL;
Yun Parkb4f591d2017-03-29 15:51:01 -07001330
1331 char ipv4_hdr_name[IPA_RESOURCE_NAME_MAX];
1332 char ipv6_hdr_name[IPA_RESOURCE_NAME_MAX];
1333
1334 int num_prop = 1;
1335 int ret = 0;
1336
1337 if (is_ipv6_enabled)
1338 num_prop++;
1339
1340 /* Allocate TX properties for TOS categories, 1 each for IPv4 & IPv6 */
1341 tx_prop =
Yun Park6c86a662017-10-05 16:09:15 -07001342 qdf_mem_malloc(sizeof(qdf_ipa_ioc_tx_intf_prop_t) * num_prop);
Nirav Shah7c8c1712018-09-10 16:01:31 +05301343 if (!tx_prop)
Yun Parkb4f591d2017-03-29 15:51:01 -07001344 goto register_interface_fail;
Yun Parkb4f591d2017-03-29 15:51:01 -07001345
1346 /* Allocate RX properties, 1 each for IPv4 & IPv6 */
1347 rx_prop =
Yun Park6c86a662017-10-05 16:09:15 -07001348 qdf_mem_malloc(sizeof(qdf_ipa_ioc_rx_intf_prop_t) * num_prop);
Nirav Shah7c8c1712018-09-10 16:01:31 +05301349 if (!rx_prop)
Yun Parkb4f591d2017-03-29 15:51:01 -07001350 goto register_interface_fail;
Yun Parkb4f591d2017-03-29 15:51:01 -07001351
1352 qdf_mem_zero(&tx_intf, sizeof(tx_intf));
1353 qdf_mem_zero(&rx_intf, sizeof(rx_intf));
1354
1355 snprintf(ipv4_hdr_name, IPA_RESOURCE_NAME_MAX, "%s%s",
1356 ifname, OL_TXRX_IPA_IPV4_NAME_EXT);
1357 snprintf(ipv6_hdr_name, IPA_RESOURCE_NAME_MAX, "%s%s",
1358 ifname, OL_TXRX_IPA_IPV6_NAME_EXT);
1359
Yun Park6c86a662017-10-05 16:09:15 -07001360 QDF_IPA_IOC_RX_INTF_PROP_IP(&rx_prop[IPA_IP_v4]) = IPA_IP_v4;
1361 QDF_IPA_IOC_RX_INTF_PROP_SRC_PIPE(&rx_prop[IPA_IP_v4]) = prod_client;
1362 QDF_IPA_IOC_RX_INTF_PROP_HDR_L2_TYPE(&rx_prop[IPA_IP_v4]) =
1363 IPA_HDR_L2_ETHERNET_II;
1364 QDF_IPA_IOC_RX_INTF_PROP_ATTRIB_MASK(&rx_prop[IPA_IP_v4]) =
1365 IPA_FLT_META_DATA;
Yun Parkb4f591d2017-03-29 15:51:01 -07001366
1367 /*
1368 * Interface ID is 3rd byte in the CLD header. Add the meta data and
1369 * mask to identify the interface in IPA hardware
1370 */
Yun Park6c86a662017-10-05 16:09:15 -07001371 QDF_IPA_IOC_RX_INTF_PROP_META_DATA(&rx_prop[IPA_IP_v4]) =
Yun Parkb4f591d2017-03-29 15:51:01 -07001372 htonl(session_id << 16);
Yun Park6c86a662017-10-05 16:09:15 -07001373 QDF_IPA_IOC_RX_INTF_PROP_META_DATA_MASK(&rx_prop[IPA_IP_v4]) =
1374 htonl(0x00FF0000);
Yun Parkb4f591d2017-03-29 15:51:01 -07001375
1376 rx_intf.num_props++;
1377 if (is_ipv6_enabled) {
Yun Park6c86a662017-10-05 16:09:15 -07001378 QDF_IPA_IOC_RX_INTF_PROP_IP(&rx_prop[IPA_IP_v6]) = IPA_IP_v6;
1379 QDF_IPA_IOC_RX_INTF_PROP_SRC_PIPE(&rx_prop[IPA_IP_v6]) =
1380 prod_client;
1381 QDF_IPA_IOC_RX_INTF_PROP_HDR_L2_TYPE(&rx_prop[IPA_IP_v6]) =
1382 IPA_HDR_L2_ETHERNET_II;
1383 QDF_IPA_IOC_RX_INTF_PROP_ATTRIB_MASK(&rx_prop[IPA_IP_v6]) =
1384 IPA_FLT_META_DATA;
1385 QDF_IPA_IOC_RX_INTF_PROP_META_DATA(&rx_prop[IPA_IP_v6]) =
Yun Parkb4f591d2017-03-29 15:51:01 -07001386 htonl(session_id << 16);
Yun Park6c86a662017-10-05 16:09:15 -07001387 QDF_IPA_IOC_RX_INTF_PROP_META_DATA_MASK(&rx_prop[IPA_IP_v6]) =
1388 htonl(0x00FF0000);
Yun Parkb4f591d2017-03-29 15:51:01 -07001389
1390 rx_intf.num_props++;
1391 }
1392
Yun Park6c86a662017-10-05 16:09:15 -07001393 QDF_IPA_IOC_TX_INTF_PROP_IP(&tx_prop[IPA_IP_v4]) = IPA_IP_v4;
1394 QDF_IPA_IOC_TX_INTF_PROP_HDR_L2_TYPE(&tx_prop[IPA_IP_v4]) =
1395 IPA_HDR_L2_ETHERNET_II;
1396 QDF_IPA_IOC_TX_INTF_PROP_DST_PIPE(&tx_prop[IPA_IP_v4]) =
1397 IPA_CLIENT_WLAN1_CONS;
1398 QDF_IPA_IOC_TX_INTF_PROP_ALT_DST_PIPE(&tx_prop[IPA_IP_v4]) =
1399 cons_client;
1400 strlcpy(QDF_IPA_IOC_TX_INTF_PROP_HDR_NAME(&tx_prop[IPA_IP_v4]),
1401 ipv4_hdr_name, IPA_RESOURCE_NAME_MAX);
Yun Parkb4f591d2017-03-29 15:51:01 -07001402 tx_intf.num_props++;
1403
1404 if (is_ipv6_enabled) {
Yun Park6c86a662017-10-05 16:09:15 -07001405 QDF_IPA_IOC_TX_INTF_PROP_IP(&tx_prop[IPA_IP_v6]) = IPA_IP_v6;
1406 QDF_IPA_IOC_TX_INTF_PROP_HDR_L2_TYPE(&tx_prop[IPA_IP_v6]) =
1407 IPA_HDR_L2_ETHERNET_II;
1408 QDF_IPA_IOC_TX_INTF_PROP_DST_PIPE(&tx_prop[IPA_IP_v6]) =
1409 IPA_CLIENT_WLAN1_CONS;
1410 QDF_IPA_IOC_TX_INTF_PROP_ALT_DST_PIPE(&tx_prop[IPA_IP_v6]) =
1411 cons_client;
1412 strlcpy(QDF_IPA_IOC_TX_INTF_PROP_HDR_NAME(&tx_prop[IPA_IP_v6]),
1413 ipv6_hdr_name, IPA_RESOURCE_NAME_MAX);
Yun Parkb4f591d2017-03-29 15:51:01 -07001414 tx_intf.num_props++;
1415 }
1416
Yun Park6c86a662017-10-05 16:09:15 -07001417 QDF_IPA_TX_INTF_PROP(&tx_intf) = tx_prop;
1418 QDF_IPA_RX_INTF_PROP(&rx_intf) = rx_prop;
Yun Parkb4f591d2017-03-29 15:51:01 -07001419
1420 /* Call the ipa api to register interface */
Yun Park84c0ceb2018-01-11 10:37:10 -08001421 ret = qdf_ipa_register_intf(ifname, &tx_intf, &rx_intf);
Yun Parkb4f591d2017-03-29 15:51:01 -07001422
1423register_interface_fail:
1424 qdf_mem_free(tx_prop);
1425 qdf_mem_free(rx_prop);
1426 return ret;
1427}
1428
1429/**
1430 * ol_txrx_ipa_setup_iface() - Setup IPA header and register interface
1431 * @ifname: Interface name
1432 * @mac_addr: Interface MAC address
1433 * @prod_client: IPA prod client type
1434 * @cons_client: IPA cons client type
1435 * @session_id: Session ID
1436 * @is_ipv6_enabled: Is IPV6 enabled or not
1437 *
1438 * Return: QDF_STATUS
1439 */
1440QDF_STATUS ol_txrx_ipa_setup_iface(char *ifname, uint8_t *mac_addr,
Yun Park6c86a662017-10-05 16:09:15 -07001441 qdf_ipa_client_type_t prod_client,
1442 qdf_ipa_client_type_t cons_client,
Yun Parkb4f591d2017-03-29 15:51:01 -07001443 uint8_t session_id, bool is_ipv6_enabled)
1444{
1445 int ret;
1446
1447 ret = ol_txrx_ipa_add_header_info(ifname, mac_addr, session_id,
1448 is_ipv6_enabled);
1449 if (ret)
1450 return QDF_STATUS_E_FAILURE;
1451
1452 /* Configure the TX and RX pipes filter rules */
Yun Park6c86a662017-10-05 16:09:15 -07001453 ret = ol_txrx_ipa_register_interface(ifname,
1454 prod_client,
1455 cons_client,
Yun Parkb4f591d2017-03-29 15:51:01 -07001456 session_id, is_ipv6_enabled);
1457 if (ret)
1458 return QDF_STATUS_E_FAILURE;
1459
1460 return QDF_STATUS_SUCCESS;
1461}
1462
1463/**
1464 * ol_txrx_ipa_cleanup_iface() - Cleanup IPA header and deregister interface
1465 * @ifname: Interface name
1466 * @is_ipv6_enabled: Is IPV6 enabled or not
1467 *
1468 * Return: QDF_STATUS
1469 */
1470QDF_STATUS ol_txrx_ipa_cleanup_iface(char *ifname, bool is_ipv6_enabled)
1471{
1472 char name_ipa[IPA_RESOURCE_NAME_MAX];
1473 int ret;
1474
1475 /* Remove the headers */
1476 snprintf(name_ipa, IPA_RESOURCE_NAME_MAX, "%s%s",
1477 ifname, OL_TXRX_IPA_IPV4_NAME_EXT);
1478 ol_txrx_ipa_remove_header(name_ipa);
1479
1480 if (is_ipv6_enabled) {
1481 snprintf(name_ipa, IPA_RESOURCE_NAME_MAX, "%s%s",
1482 ifname, OL_TXRX_IPA_IPV6_NAME_EXT);
1483 ol_txrx_ipa_remove_header(name_ipa);
1484 }
1485 /* unregister the interface with IPA */
Yun Park6c86a662017-10-05 16:09:15 -07001486 ret = qdf_ipa_deregister_intf(ifname);
Yun Parkb4f591d2017-03-29 15:51:01 -07001487 if (ret) {
1488 QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_DEBUG,
1489 "%s: ipa_deregister_intf fail: %d",
1490 ifname, ret);
1491 return QDF_STATUS_E_FAILURE;
1492 }
1493
1494 return QDF_STATUS_SUCCESS;
1495}
1496
Vevek Venkatesan29076ec2019-08-22 17:53:12 +05301497QDF_STATUS ol_txrx_ipa_enable_pipes(struct cdp_soc_t *soc_hdl, uint8_t pdev_id)
Yun Parkb4f591d2017-03-29 15:51:01 -07001498{
Vevek Venkatesan29076ec2019-08-22 17:53:12 +05301499 struct ol_txrx_soc_t *soc = cdp_soc_t_to_ol_txrx_soc_t(soc_hdl);
1500 ol_txrx_pdev_handle pdev = ol_txrx_get_pdev_from_pdev_id(soc, pdev_id);
1501 struct ol_txrx_ipa_resources *ipa_res;
Yun Parkb4f591d2017-03-29 15:51:01 -07001502 int result;
Sravan Kumar Kairamb5870bb2018-06-13 16:49:27 +05301503 QDF_STATUS status;
1504
Vevek Venkatesan29076ec2019-08-22 17:53:12 +05301505 if (!pdev) {
1506 ol_txrx_err("%s invalid instance", __func__);
1507 return QDF_STATUS_E_FAILURE;
1508 }
1509
1510 ipa_res = &pdev->ipa_resource;
Sravan Kumar Kairamb5870bb2018-06-13 16:49:27 +05301511 status = htt_rx_update_smmu_map(pdev->htt_pdev, true);
1512 if (status != QDF_STATUS_SUCCESS) {
1513 QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
1514 "IPA SMMU map failed status:%d", status);
1515 return status;
1516 }
Yun Parkb4f591d2017-03-29 15:51:01 -07001517
1518 /* ACTIVATE TX PIPE */
1519 QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_DEBUG,
1520 "%s: Enable TX PIPE(tx_pipe_handle=%d)",
1521 __func__, ipa_res->tx_pipe_handle);
Yun Park84c0ceb2018-01-11 10:37:10 -08001522 result = qdf_ipa_enable_wdi_pipe(ipa_res->tx_pipe_handle);
Yun Parkb4f591d2017-03-29 15:51:01 -07001523 if (result) {
1524 QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
1525 "%s: Enable TX PIPE fail, code %d",
1526 __func__, result);
Sravan Kumar Kairamb5870bb2018-06-13 16:49:27 +05301527 goto smmu_unmap;
Yun Parkb4f591d2017-03-29 15:51:01 -07001528 }
Yun Park84c0ceb2018-01-11 10:37:10 -08001529 result = qdf_ipa_resume_wdi_pipe(ipa_res->tx_pipe_handle);
Yun Parkb4f591d2017-03-29 15:51:01 -07001530 if (result) {
1531 QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
1532 "%s: Resume TX PIPE fail, code %d",
1533 __func__, result);
Sravan Kumar Kairamb5870bb2018-06-13 16:49:27 +05301534 goto smmu_unmap;
Yun Parkb4f591d2017-03-29 15:51:01 -07001535 }
Vevek Venkatesan29076ec2019-08-22 17:53:12 +05301536 ol_txrx_ipa_uc_set_active(soc_hdl, pdev_id, true, true);
Yun Parkb4f591d2017-03-29 15:51:01 -07001537
1538 /* ACTIVATE RX PIPE */
1539 QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_DEBUG,
1540 "%s: Enable RX PIPE(rx_pipe_handle=%d)",
1541 __func__, ipa_res->rx_pipe_handle);
Yun Park84c0ceb2018-01-11 10:37:10 -08001542 result = qdf_ipa_enable_wdi_pipe(ipa_res->rx_pipe_handle);
Yun Parkb4f591d2017-03-29 15:51:01 -07001543 if (result) {
1544 QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
1545 "%s: Enable RX PIPE fail, code %d",
1546 __func__, result);
Sravan Kumar Kairamb5870bb2018-06-13 16:49:27 +05301547 goto smmu_unmap;
Yun Parkb4f591d2017-03-29 15:51:01 -07001548 }
Yun Park84c0ceb2018-01-11 10:37:10 -08001549 result = qdf_ipa_resume_wdi_pipe(ipa_res->rx_pipe_handle);
Yun Parkb4f591d2017-03-29 15:51:01 -07001550 if (result) {
1551 QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
1552 "%s: Resume RX PIPE fail, code %d",
1553 __func__, result);
Sravan Kumar Kairamb5870bb2018-06-13 16:49:27 +05301554 goto smmu_unmap;
Yun Parkb4f591d2017-03-29 15:51:01 -07001555 }
Vevek Venkatesan29076ec2019-08-22 17:53:12 +05301556 ol_txrx_ipa_uc_set_active(soc_hdl, pdev_id, true, false);
Yun Parkb4f591d2017-03-29 15:51:01 -07001557
1558 return QDF_STATUS_SUCCESS;
Sravan Kumar Kairamb5870bb2018-06-13 16:49:27 +05301559
1560smmu_unmap:
1561 if (htt_rx_update_smmu_map(pdev->htt_pdev, false) !=
1562 QDF_STATUS_SUCCESS) {
1563 QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
1564 "IPA SMMU unmap failed");
1565 }
1566
1567 return QDF_STATUS_E_FAILURE;
Yun Parkb4f591d2017-03-29 15:51:01 -07001568}
1569
Vevek Venkatesan29076ec2019-08-22 17:53:12 +05301570QDF_STATUS ol_txrx_ipa_disable_pipes(struct cdp_soc_t *soc_hdl, uint8_t pdev_id)
Yun Parkb4f591d2017-03-29 15:51:01 -07001571{
Vevek Venkatesan29076ec2019-08-22 17:53:12 +05301572 struct ol_txrx_soc_t *soc = cdp_soc_t_to_ol_txrx_soc_t(soc_hdl);
1573 ol_txrx_pdev_handle pdev = ol_txrx_get_pdev_from_pdev_id(soc, pdev_id);
1574 struct ol_txrx_ipa_resources *ipa_res;
Yun Parkb4f591d2017-03-29 15:51:01 -07001575 int result;
1576
Vevek Venkatesan29076ec2019-08-22 17:53:12 +05301577 if (!pdev) {
1578 ol_txrx_err("%s invalid instance", __func__);
1579 return QDF_STATUS_E_FAILURE;
1580 }
1581
1582 ipa_res = &pdev->ipa_resource;
Yun Parkb4f591d2017-03-29 15:51:01 -07001583 QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_DEBUG,
1584 "%s: Disable RX PIPE", __func__);
Yun Park84c0ceb2018-01-11 10:37:10 -08001585 result = qdf_ipa_suspend_wdi_pipe(ipa_res->rx_pipe_handle);
Yun Parkb4f591d2017-03-29 15:51:01 -07001586 if (result) {
1587 QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
1588 "%s: Suspend RX PIPE fail, code %d",
1589 __func__, result);
Sravan Kumar Kairamb5870bb2018-06-13 16:49:27 +05301590 goto smmu_unmap;
Yun Parkb4f591d2017-03-29 15:51:01 -07001591 }
1592
Yun Park84c0ceb2018-01-11 10:37:10 -08001593 result = qdf_ipa_disable_wdi_pipe(ipa_res->rx_pipe_handle);
Yun Parkb4f591d2017-03-29 15:51:01 -07001594 if (result) {
1595 QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
1596 "%s: Disable RX PIPE fail, code %d",
1597 __func__, result);
Sravan Kumar Kairamb5870bb2018-06-13 16:49:27 +05301598 goto smmu_unmap;
Yun Parkb4f591d2017-03-29 15:51:01 -07001599 }
1600
1601 QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_DEBUG,
1602 "%s: Disable TX PIPE", __func__);
Yun Park84c0ceb2018-01-11 10:37:10 -08001603 result = qdf_ipa_suspend_wdi_pipe(ipa_res->tx_pipe_handle);
Yun Parkb4f591d2017-03-29 15:51:01 -07001604 if (result) {
1605 QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
1606 "%s: Suspend TX PIPE fail, code %d",
1607 __func__, result);
Sravan Kumar Kairamb5870bb2018-06-13 16:49:27 +05301608 goto smmu_unmap;
Yun Parkb4f591d2017-03-29 15:51:01 -07001609 }
Yun Park84c0ceb2018-01-11 10:37:10 -08001610 result = qdf_ipa_disable_wdi_pipe(ipa_res->tx_pipe_handle);
Yun Parkb4f591d2017-03-29 15:51:01 -07001611 if (result) {
1612 QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
1613 "%s: Disable TX PIPE fail, code %d",
1614 __func__, result);
Sravan Kumar Kairamb5870bb2018-06-13 16:49:27 +05301615 goto smmu_unmap;
Yun Parkb4f591d2017-03-29 15:51:01 -07001616 }
1617
Sravan Kumar Kairamb5870bb2018-06-13 16:49:27 +05301618smmu_unmap:
1619 if (htt_rx_update_smmu_map(pdev->htt_pdev, false) !=
1620 QDF_STATUS_SUCCESS) {
1621 QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
1622 "IPA SMMU unmap failed");
1623 }
1624
1625 return result ? QDF_STATUS_E_FAILURE : QDF_STATUS_SUCCESS;
Yun Parkb4f591d2017-03-29 15:51:01 -07001626}
1627
1628/**
1629 * ol_txrx_ipa_set_perf_level() - Set IPA clock bandwidth based on data rates
1630 * @client: Client type
1631 * @max_supported_bw_mbps: Maximum bandwidth needed (in Mbps)
1632 *
1633 * Return: QDF_STATUS
1634 */
1635QDF_STATUS ol_txrx_ipa_set_perf_level(int client,
1636 uint32_t max_supported_bw_mbps)
1637{
Sravan Kumar Kairamfbc87b72018-04-09 14:09:52 +05301638 qdf_ipa_rm_resource_name_t resource_name;
Yun Park6c86a662017-10-05 16:09:15 -07001639 qdf_ipa_rm_perf_profile_t profile;
Yun Parkb4f591d2017-03-29 15:51:01 -07001640 int result;
1641
Sravan Kumar Kairamfbc87b72018-04-09 14:09:52 +05301642 if (client == QDF_IPA_CLIENT_WLAN1_PROD) {
1643 resource_name = QDF_IPA_RM_RESOURCE_WLAN_PROD;
1644 } else if (client == QDF_IPA_CLIENT_WLAN1_CONS) {
1645 resource_name = QDF_IPA_RM_RESOURCE_WLAN_CONS;
1646 } else {
1647 QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
1648 "not supported client %d", client);
1649 return QDF_STATUS_E_FAILURE;
1650 }
1651
Yun Park6c86a662017-10-05 16:09:15 -07001652 QDF_IPA_RM_PERF_PROFILE_MAX_SUPPORTED_BANDWIDTH_MBPS(&profile) =
1653 max_supported_bw_mbps;
Sravan Kumar Kairamfbc87b72018-04-09 14:09:52 +05301654 result = qdf_ipa_rm_set_perf_profile(resource_name, &profile);
Yun Parkb4f591d2017-03-29 15:51:01 -07001655
1656 if (result) {
1657 QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
1658 "Set perf profile failed, code %d", result);
1659
1660 return QDF_STATUS_E_FAILURE;
1661 }
1662
1663 return QDF_STATUS_SUCCESS;
1664}
1665
Sravan Kumar Kairamfbc87b72018-04-09 14:09:52 +05301666#endif /* CONFIG_IPA_WDI_UNIFIED_API */
1667
Yun Parkb4f591d2017-03-29 15:51:01 -07001668#ifdef FEATURE_METERING
Vevek Venkatesan29076ec2019-08-22 17:53:12 +05301669QDF_STATUS ol_txrx_ipa_uc_get_share_stats(struct cdp_soc_t *soc_hdl,
1670 uint8_t pdev_id, uint8_t reset_stats)
Yun Parkb4f591d2017-03-29 15:51:01 -07001671{
Vevek Venkatesan29076ec2019-08-22 17:53:12 +05301672 struct ol_txrx_soc_t *soc = cdp_soc_t_to_ol_txrx_soc_t(soc_hdl);
1673 ol_txrx_pdev_handle pdev = ol_txrx_get_pdev_from_pdev_id(soc, pdev_id);
Yun Parkb4f591d2017-03-29 15:51:01 -07001674 int result;
1675
Vevek Venkatesan29076ec2019-08-22 17:53:12 +05301676 if (!pdev) {
1677 ol_txrx_err("%s invalid instance", __func__);
1678 return QDF_STATUS_E_FAILURE;
1679 }
1680
Yun Parkb4f591d2017-03-29 15:51:01 -07001681 result = htt_h2t_ipa_uc_get_share_stats(pdev->htt_pdev, reset_stats);
1682
1683 if (result) {
1684 QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
1685 "Get IPA sharing stats failed, code %d", result);
1686 return QDF_STATUS_E_FAILURE;
1687 }
1688
1689 return QDF_STATUS_SUCCESS;
1690}
1691
Vevek Venkatesan29076ec2019-08-22 17:53:12 +05301692QDF_STATUS ol_txrx_ipa_uc_set_quota(struct cdp_soc_t *soc_hdl, uint8_t pdev_id,
1693 uint64_t quota_bytes)
Yun Parkb4f591d2017-03-29 15:51:01 -07001694{
Vevek Venkatesan29076ec2019-08-22 17:53:12 +05301695 struct ol_txrx_soc_t *soc = cdp_soc_t_to_ol_txrx_soc_t(soc_hdl);
1696 ol_txrx_pdev_handle pdev = ol_txrx_get_pdev_from_pdev_id(soc, pdev_id);
Yun Parkb4f591d2017-03-29 15:51:01 -07001697 int result;
1698
Vevek Venkatesan29076ec2019-08-22 17:53:12 +05301699 if (!pdev) {
1700 ol_txrx_err("%s invalid instance", __func__);
1701 return QDF_STATUS_E_FAILURE;
1702 }
1703
Yun Parkb4f591d2017-03-29 15:51:01 -07001704 result = htt_h2t_ipa_uc_set_quota(pdev->htt_pdev, quota_bytes);
1705
1706 if (result) {
1707 QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
1708 "Set IPA quota failed, code %d", result);
1709 return QDF_STATUS_E_FAILURE;
1710 }
1711
1712 return QDF_STATUS_SUCCESS;
1713}
1714#endif
1715#endif /* IPA_UC_OFFLOAD */