1 /*
2 * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved.
3 * Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved.
4 *
5 * Permission to use, copy, modify, and/or distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
8 *
9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 */
17
18 /*=== includes ===*/
19 /* header files for OS primitives */
20 #include <osdep.h> /* uint32_t, etc. */
21 #include <qdf_mem.h> /* qdf_mem_malloc,free */
22 #include <qdf_types.h> /* qdf_device_t, qdf_print */
23 #include <qdf_lock.h> /* qdf_spinlock */
24 #include <qdf_atomic.h> /* qdf_atomic_read */
25
26 /* header files for utilities */
27 #include "queue.h" /* TAILQ */
28
29 /* header files for configuration API */
30 #include <ol_cfg.h> /* ol_cfg_is_high_latency */
31 #include <ol_if_athvar.h>
32
33 /* header files for HTT API */
34 #include <ol_htt_api.h>
35 #include <ol_htt_tx_api.h>
36
37 /* header files for our own APIs */
38 #include <ol_txrx_api.h>
39 #include <ol_txrx_dbg.h>
40 #include <cdp_txrx_ocb.h>
41 #include <ol_txrx_ctrl_api.h>
42 #include <cdp_txrx_stats.h>
43 #include <ol_txrx_osif_api.h>
44 /* header files for our internal definitions */
45 #include <ol_txrx_internal.h> /* TXRX_ASSERT, etc. */
46 #include <wdi_event.h> /* WDI events */
47 #include <ol_tx.h> /* ol_tx_ll */
48 #include <ol_rx.h> /* ol_rx_deliver */
49 #include <ol_txrx_peer_find.h> /* ol_txrx_peer_find_attach, etc. */
50 #include <ol_rx_pn.h> /* ol_rx_pn_check, etc. */
51 #include <ol_rx_fwd.h> /* ol_rx_fwd_check, etc. */
52 #include <ol_rx_reorder_timeout.h> /* OL_RX_REORDER_TIMEOUT_INIT, etc. */
53 #include <ol_rx_reorder.h>
54 #include <ol_tx_send.h> /* ol_tx_discard_target_frms */
55 #include <ol_tx_desc.h> /* ol_tx_desc_frame_free */
56 #include <ol_tx_queue.h>
57 #include <ol_tx_sched.h> /* ol_tx_sched_attach, etc. */
58 #include <ol_txrx.h>
59 #include <ol_txrx_types.h>
60 #include <cdp_txrx_flow_ctrl_legacy.h>
61 #include <cdp_txrx_bus.h>
62 #include <cdp_txrx_ipa.h>
63 #include <cdp_txrx_pmf.h>
64 #include "wma.h"
65 #include "hif.h"
66 #include <cdp_txrx_peer_ops.h>
67 #ifndef REMOVE_PKT_LOG
68 #include "pktlog_ac.h"
69 #endif
70 #include "epping_main.h"
71 #include <a_types.h>
72
73 #ifdef IPA_OFFLOAD
74 #include <ol_txrx_ipa.h>
75
76 /* For Tx pipes, use Ethernet-II Header format */
77 #ifdef QCA_WIFI_3_0
78 struct ol_txrx_ipa_uc_tx_hdr ipa_uc_tx_hdr = {
79 {
80 0x0000,
81 0x00000000,
82 0x00000000
83 },
84 {
85 0x00000000
86 },
87 {
88 {0x00, 0x03, 0x7f, 0xaa, 0xbb, 0xcc},
89 {0x00, 0x03, 0x7f, 0xdd, 0xee, 0xff},
90 0x0008
91 }
92 };
93 #else
94 struct ol_txrx_ipa_uc_tx_hdr ipa_uc_tx_hdr = {
95 {
96 0x00000000,
97 0x00000000
98 },
99 {
100 0x00000000
101 },
102 {
103 {0x00, 0x03, 0x7f, 0xaa, 0xbb, 0xcc},
104 {0x00, 0x03, 0x7f, 0xdd, 0xee, 0xff},
105 0x0008
106 }
107 };
108 #endif
109
ol_txrx_ipa_uc_get_resource(struct cdp_soc_t * soc_hdl,uint8_t pdev_id)110 QDF_STATUS ol_txrx_ipa_uc_get_resource(struct cdp_soc_t *soc_hdl,
111 uint8_t pdev_id)
112 {
113 struct ol_txrx_soc_t *soc = cdp_soc_t_to_ol_txrx_soc_t(soc_hdl);
114 ol_txrx_pdev_handle pdev = ol_txrx_get_pdev_from_pdev_id(soc, pdev_id);
115 struct ol_txrx_ipa_resources *ipa_res;
116 qdf_device_t osdev = cds_get_context(QDF_MODULE_ID_QDF_DEVICE);
117
118 if (!pdev) {
119 ol_txrx_err("Invalid instance");
120 return QDF_STATUS_E_FAILURE;
121 }
122
123 if (!osdev)
124 return QDF_STATUS_E_NOENT;
125
126 ipa_res = &pdev->ipa_resource;
127 htt_ipa_uc_get_resource(pdev->htt_pdev,
128 &ipa_res->ce_sr,
129 &ipa_res->tx_comp_ring,
130 &ipa_res->rx_rdy_ring,
131 &ipa_res->rx2_rdy_ring,
132 &ipa_res->rx_proc_done_idx,
133 &ipa_res->rx2_proc_done_idx,
134 &ipa_res->ce_sr_ring_size,
135 &ipa_res->ce_reg_paddr,
136 &ipa_res->tx_num_alloc_buffer);
137
138 if ((0 == qdf_mem_get_dma_addr(osdev,
139 &ipa_res->ce_sr->mem_info)) ||
140 (0 == qdf_mem_get_dma_addr(osdev,
141 &ipa_res->tx_comp_ring->mem_info)) ||
142 (0 == qdf_mem_get_dma_addr(osdev,
143 &ipa_res->rx_rdy_ring->mem_info))
144 #if defined(QCA_WIFI_3_0) && defined(CONFIG_IPA3)
145 || (0 == qdf_mem_get_dma_addr(osdev,
146 &ipa_res->rx2_rdy_ring->mem_info))
147 #endif
148 )
149 return QDF_STATUS_E_FAILURE;
150
151 return QDF_STATUS_SUCCESS;
152 }
153
ol_txrx_ipa_uc_set_doorbell_paddr(struct cdp_soc_t * soc_hdl,uint8_t pdev_id)154 QDF_STATUS ol_txrx_ipa_uc_set_doorbell_paddr(struct cdp_soc_t *soc_hdl,
155 uint8_t pdev_id)
156 {
157 struct ol_txrx_soc_t *soc = cdp_soc_t_to_ol_txrx_soc_t(soc_hdl);
158 ol_txrx_pdev_handle pdev = ol_txrx_get_pdev_from_pdev_id(soc, pdev_id);
159 struct ol_txrx_ipa_resources *ipa_res;
160 int ret;
161
162 if (!pdev) {
163 ol_txrx_err("Invalid instance");
164 return QDF_STATUS_E_FAILURE;
165 }
166
167 ipa_res = &pdev->ipa_resource;
168 ret = htt_ipa_uc_set_doorbell_paddr(pdev->htt_pdev,
169 ipa_res->tx_comp_doorbell_dmaaddr,
170 ipa_res->rx_ready_doorbell_dmaaddr);
171
172 if (ret) {
173 QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
174 "htt_ipa_uc_set_doorbell_dmaaddr fail: %d", ret);
175 return QDF_STATUS_E_FAILURE;
176 }
177
178 return QDF_STATUS_SUCCESS;
179 }
180
ol_txrx_ipa_uc_set_active(struct cdp_soc_t * soc_hdl,uint8_t pdev_id,bool uc_active,bool is_tx)181 QDF_STATUS ol_txrx_ipa_uc_set_active(struct cdp_soc_t *soc_hdl, uint8_t pdev_id,
182 bool uc_active, bool is_tx)
183 {
184 struct ol_txrx_soc_t *soc = cdp_soc_t_to_ol_txrx_soc_t(soc_hdl);
185 ol_txrx_pdev_handle pdev = ol_txrx_get_pdev_from_pdev_id(soc, pdev_id);
186 int ret;
187
188 if (!pdev) {
189 ol_txrx_err("Invalid instance");
190 return QDF_STATUS_E_FAILURE;
191 }
192
193 ret = htt_h2t_ipa_uc_set_active(pdev->htt_pdev, uc_active, is_tx);
194 if (ret) {
195 QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
196 "htt_h2t_ipa_uc_set_active fail: %d", ret);
197 return QDF_STATUS_E_FAILURE;
198 }
199
200 return QDF_STATUS_SUCCESS;
201 }
202
ol_txrx_ipa_uc_op_response(struct cdp_soc_t * soc_hdl,uint8_t pdev_id,uint8_t * op_msg)203 QDF_STATUS ol_txrx_ipa_uc_op_response(struct cdp_soc_t *soc_hdl,
204 uint8_t pdev_id, uint8_t *op_msg)
205 {
206 struct ol_txrx_soc_t *soc = cdp_soc_t_to_ol_txrx_soc_t(soc_hdl);
207 ol_txrx_pdev_handle pdev = ol_txrx_get_pdev_from_pdev_id(soc, pdev_id);
208
209 if (!pdev) {
210 ol_txrx_err("Invalid instance");
211 return QDF_STATUS_E_FAILURE;
212 }
213
214 if (pdev->ipa_uc_op_cb) {
215 pdev->ipa_uc_op_cb(op_msg, pdev->usr_ctxt);
216 } else {
217 QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
218 "%s: IPA callback function is not registered", __func__);
219 qdf_mem_free(op_msg);
220 return QDF_STATUS_E_FAILURE;
221 }
222
223 return QDF_STATUS_SUCCESS;
224 }
225
ol_txrx_ipa_uc_register_op_cb(struct cdp_soc_t * soc_hdl,uint8_t pdev_id,ipa_uc_op_cb_type op_cb,void * usr_ctxt)226 QDF_STATUS ol_txrx_ipa_uc_register_op_cb(struct cdp_soc_t *soc_hdl,
227 uint8_t pdev_id,
228 ipa_uc_op_cb_type op_cb,
229 void *usr_ctxt)
230 {
231 struct ol_txrx_soc_t *soc = cdp_soc_t_to_ol_txrx_soc_t(soc_hdl);
232 ol_txrx_pdev_handle pdev = ol_txrx_get_pdev_from_pdev_id(soc, pdev_id);
233
234 if (!pdev) {
235 ol_txrx_err("Invalid instance");
236 return QDF_STATUS_E_FAILURE;
237 }
238
239 pdev->ipa_uc_op_cb = op_cb;
240 pdev->usr_ctxt = usr_ctxt;
241
242 return QDF_STATUS_SUCCESS;
243 }
244
ol_txrx_ipa_uc_get_stat(struct cdp_soc_t * soc_hdl,uint8_t pdev_id)245 QDF_STATUS ol_txrx_ipa_uc_get_stat(struct cdp_soc_t *soc_hdl, uint8_t pdev_id)
246 {
247 struct ol_txrx_soc_t *soc = cdp_soc_t_to_ol_txrx_soc_t(soc_hdl);
248 ol_txrx_pdev_handle pdev = ol_txrx_get_pdev_from_pdev_id(soc, pdev_id);
249 int ret;
250
251 if (!pdev) {
252 ol_txrx_err("Invalid instance");
253 return QDF_STATUS_E_FAILURE;
254 }
255
256 ret = htt_h2t_ipa_uc_get_stats(pdev->htt_pdev);
257
258 if (ret) {
259 QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
260 "htt_h2t_ipa_uc_get_stats fail: %d", ret);
261 return QDF_STATUS_E_FAILURE;
262 }
263
264 return QDF_STATUS_SUCCESS;
265 }
266
ol_txrx_ipa_enable_autonomy(struct cdp_soc_t * soc_hdl,uint8_t pdev_id)267 QDF_STATUS ol_txrx_ipa_enable_autonomy(struct cdp_soc_t *soc_hdl,
268 uint8_t pdev_id)
269 {
270 /* TBD */
271 return QDF_STATUS_SUCCESS;
272 }
273
ol_txrx_ipa_disable_autonomy(struct cdp_soc_t * soc_hdl,uint8_t pdev_id)274 QDF_STATUS ol_txrx_ipa_disable_autonomy(struct cdp_soc_t *soc_hdl,
275 uint8_t pdev_id)
276 {
277 /* TBD */
278 return QDF_STATUS_SUCCESS;
279 }
280
__ol_txrx_ipa_tx_buf_smmu_mapping(struct ol_txrx_pdev_t * pdev,bool create)281 static QDF_STATUS __ol_txrx_ipa_tx_buf_smmu_mapping(struct ol_txrx_pdev_t *pdev,
282 bool create)
283 {
284 uint32_t index;
285 uint32_t unmap_cnt = 0;
286 uint32_t tx_buffer_cnt;
287 QDF_STATUS ret = QDF_STATUS_SUCCESS;
288 struct htt_pdev_t *htt_pdev = pdev->htt_pdev;
289 qdf_mem_info_t *mem_map_table = NULL, *mem_info = NULL;
290
291 if (!htt_pdev) {
292 ol_txrx_err("htt_pdev is NULL");
293 return QDF_STATUS_E_FAILURE;
294 }
295
296 if (!qdf_mem_smmu_s1_enabled(htt_pdev->osdev)) {
297 ol_txrx_info("SMMU-S1 mapping is disabled");
298 return QDF_STATUS_SUCCESS;
299 }
300
301 tx_buffer_cnt = htt_pdev->ipa_uc_tx_rsc.alloc_tx_buf_cnt;
302 mem_map_table = qdf_mem_map_table_alloc(tx_buffer_cnt);
303 if (!mem_map_table) {
304 ol_txrx_err("Failed to allocate memory");
305 return QDF_STATUS_E_FAILURE;
306 }
307 mem_info = mem_map_table;
308
309 for (index = 0; index < tx_buffer_cnt; index++) {
310 if (htt_pdev->ipa_uc_tx_rsc.tx_buf_pool_strg[index]) {
311 *mem_info = htt_pdev->ipa_uc_tx_rsc.
312 tx_buf_pool_strg[index]->mem_info;
313 mem_info++;
314 unmap_cnt++;
315 }
316 }
317
318 ret = cds_smmu_map_unmap(create, unmap_cnt, mem_map_table);
319 qdf_assert_always(!ret);
320 qdf_mem_free(mem_map_table);
321 htt_pdev->ipa_uc_tx_rsc.ipa_smmu_mapped = create;
322 ol_txrx_info("smmu_map_unmap:%d of %d Tx buffers", create, unmap_cnt);
323
324 return ret;
325 }
326
ol_txrx_ipa_tx_buf_smmu_mapping(struct cdp_soc_t * soc_hdl,uint8_t pdev_id,const char * func,uint32_t line)327 QDF_STATUS ol_txrx_ipa_tx_buf_smmu_mapping(struct cdp_soc_t *soc_hdl,
328 uint8_t pdev_id,
329 const char *func,
330 uint32_t line)
331 {
332 QDF_STATUS ret;
333 struct ol_txrx_soc_t *soc = cdp_soc_t_to_ol_txrx_soc_t(soc_hdl);
334 ol_txrx_pdev_handle pdev = ol_txrx_get_pdev_from_pdev_id(soc, pdev_id);
335
336 if (!pdev) {
337 ol_txrx_err("invalid instance");
338 return QDF_STATUS_E_FAILURE;
339 }
340
341 if (!qdf_mem_smmu_s1_enabled(pdev->htt_pdev->osdev)) {
342 ol_txrx_err("SMMU S1 disabled");
343 return QDF_STATUS_SUCCESS;
344 }
345 ret = __ol_txrx_ipa_tx_buf_smmu_mapping(pdev, true);
346
347 return ret;
348 }
349
ol_txrx_ipa_tx_buf_smmu_unmapping(struct cdp_soc_t * soc_hdl,uint8_t pdev_id,const char * func,uint32_t line)350 QDF_STATUS ol_txrx_ipa_tx_buf_smmu_unmapping(struct cdp_soc_t *soc_hdl,
351 uint8_t pdev_id,
352 const char *func,
353 uint32_t line)
354 {
355 QDF_STATUS ret;
356 struct ol_txrx_soc_t *soc = cdp_soc_t_to_ol_txrx_soc_t(soc_hdl);
357 ol_txrx_pdev_handle pdev = ol_txrx_get_pdev_from_pdev_id(soc, pdev_id);
358
359 if (!pdev) {
360 ol_txrx_err("invalid instance");
361 return QDF_STATUS_E_FAILURE;
362 }
363
364 if (!qdf_mem_smmu_s1_enabled(pdev->htt_pdev->osdev)) {
365 ol_txrx_err("SMMU S1 disabled");
366 return QDF_STATUS_SUCCESS;
367 }
368 ret = __ol_txrx_ipa_tx_buf_smmu_mapping(pdev, false);
369
370 return ret;
371 }
372
373 #ifdef CONFIG_IPA_WDI_UNIFIED_API
374
375 #ifndef QCA_LL_TX_FLOW_CONTROL_V2
ol_txrx_setup_mcc_sys_pipes(qdf_ipa_sys_connect_params_t * sys_in,qdf_ipa_wdi_conn_in_params_t * pipe_in)376 static inline void ol_txrx_setup_mcc_sys_pipes(
377 qdf_ipa_sys_connect_params_t *sys_in,
378 qdf_ipa_wdi_conn_in_params_t *pipe_in)
379 {
380 int i = 0;
381
382 /* Setup MCC sys pipe */
383 QDF_IPA_WDI_CONN_IN_PARAMS_NUM_SYS_PIPE_NEEDED(pipe_in) =
384 OL_TXRX_IPA_MAX_IFACE;
385 for (i = 0; i < OL_TXRX_IPA_MAX_IFACE; i++)
386 memcpy(&QDF_IPA_WDI_CONN_IN_PARAMS_SYS_IN(pipe_in)[i],
387 &sys_in[i], sizeof(qdf_ipa_sys_connect_params_t));
388 }
389 #else
ol_txrx_setup_mcc_sys_pipes(qdf_ipa_sys_connect_params_t * sys_in,qdf_ipa_wdi_conn_in_params_t * pipe_in)390 static inline void ol_txrx_setup_mcc_sys_pipes(
391 qdf_ipa_sys_connect_params_t *sys_in,
392 qdf_ipa_wdi_conn_in_params_t *pipe_in)
393 {
394 QDF_IPA_WDI_CONN_IN_PARAMS_NUM_SYS_PIPE_NEEDED(pipe_in) = 0;
395 }
396 #endif
397
398 #ifdef ENABLE_SMMU_S1_TRANSLATION
399 #ifdef QCA_WIFI_3_0
400 /**
401 * ol_txrx_ipa_wdi_tx_smmu_params() - Config IPA TX params
402 * @ipa_res: IPA resources
403 * @tx_smmu: IPA WDI pipe setup info
404 *
405 * Return: None
406 */
ol_txrx_ipa_wdi_tx_smmu_params(struct ol_txrx_ipa_resources * ipa_res,qdf_ipa_wdi_pipe_setup_info_smmu_t * tx_smmu,bool over_gsi)407 static inline void ol_txrx_ipa_wdi_tx_smmu_params(
408 struct ol_txrx_ipa_resources *ipa_res,
409 qdf_ipa_wdi_pipe_setup_info_smmu_t *tx_smmu,
410 bool over_gsi)
411 {
412 QDF_IPA_WDI_SETUP_INFO_SMMU_CLIENT(tx_smmu) =
413 QDF_IPA_CLIENT_WLAN_WDI2_CONS;
414 qdf_mem_copy(&QDF_IPA_WDI_SETUP_INFO_SMMU_TRANSFER_RING_BASE(
415 tx_smmu),
416 &ipa_res->tx_comp_ring->sgtable,
417 sizeof(sgtable_t));
418 QDF_IPA_WDI_SETUP_INFO_SMMU_TRANSFER_RING_SIZE(tx_smmu) =
419 ipa_res->tx_comp_ring->mem_info.size;
420 qdf_mem_copy(&QDF_IPA_WDI_SETUP_INFO_SMMU_EVENT_RING_BASE(
421 tx_smmu),
422 &ipa_res->ce_sr->sgtable,
423 sizeof(sgtable_t));
424 QDF_IPA_WDI_SETUP_INFO_SMMU_EVENT_RING_SIZE(tx_smmu) =
425 ipa_res->ce_sr_ring_size;
426 QDF_IPA_WDI_SETUP_INFO_SMMU_EVENT_RING_DOORBELL_PA(tx_smmu) =
427 ipa_res->ce_reg_paddr;
428 if (over_gsi)
429 QDF_IPA_WDI_SETUP_INFO_SMMU_IS_EVT_RN_DB_PCIE_ADDR(tx_smmu) = true;
430 QDF_IPA_WDI_SETUP_INFO_SMMU_NUM_PKT_BUFFERS(tx_smmu) =
431 ipa_res->tx_num_alloc_buffer;
432 QDF_IPA_WDI_SETUP_INFO_SMMU_PKT_OFFSET(tx_smmu) = 0;
433 }
434
435 /**
436 * ol_txrx_ipa_wdi_rx_smmu_params() - Config IPA RX params
437 * @ipa_res: IPA resources
438 * @rx_smmu: IPA WDI pipe setup info
439 *
440 * Return: None
441 */
ol_txrx_ipa_wdi_rx_smmu_params(struct ol_txrx_ipa_resources * ipa_res,qdf_ipa_wdi_pipe_setup_info_smmu_t * rx_smmu,bool over_gsi)442 static inline void ol_txrx_ipa_wdi_rx_smmu_params(
443 struct ol_txrx_ipa_resources *ipa_res,
444 qdf_ipa_wdi_pipe_setup_info_smmu_t *rx_smmu,
445 bool over_gsi)
446 {
447 QDF_IPA_WDI_SETUP_INFO_SMMU_CLIENT(rx_smmu) =
448 QDF_IPA_CLIENT_WLAN_WDI2_PROD;
449 qdf_mem_copy(&QDF_IPA_WDI_SETUP_INFO_SMMU_TRANSFER_RING_BASE(
450 rx_smmu),
451 &ipa_res->rx_rdy_ring->sgtable,
452 sizeof(sgtable_t));
453 QDF_IPA_WDI_SETUP_INFO_SMMU_TRANSFER_RING_SIZE(rx_smmu) =
454 ipa_res->rx_rdy_ring->mem_info.size;
455 QDF_IPA_WDI_SETUP_INFO_SMMU_TRANSFER_RING_DOORBELL_PA(rx_smmu) =
456 ipa_res->rx_proc_done_idx->mem_info.pa;
457 if (over_gsi)
458 QDF_IPA_WDI_SETUP_INFO_SMMU_IS_TXR_RN_DB_PCIE_ADDR(rx_smmu) = false;
459 qdf_mem_copy(&QDF_IPA_WDI_SETUP_INFO_SMMU_EVENT_RING_BASE(
460 rx_smmu),
461 &ipa_res->rx2_rdy_ring->sgtable,
462 sizeof(sgtable_t));
463 QDF_IPA_WDI_SETUP_INFO_SMMU_EVENT_RING_SIZE(rx_smmu) =
464 ipa_res->rx2_rdy_ring->mem_info.size;
465 QDF_IPA_WDI_SETUP_INFO_SMMU_EVENT_RING_DOORBELL_PA(rx_smmu) =
466 ipa_res->rx2_proc_done_idx->mem_info.pa;
467 if (over_gsi)
468 QDF_IPA_WDI_SETUP_INFO_SMMU_IS_EVT_RN_DB_PCIE_ADDR(rx_smmu) = false;
469 QDF_IPA_WDI_SETUP_INFO_SMMU_PKT_OFFSET(rx_smmu) = 0;
470
471 }
472 #else
473
ol_txrx_ipa_wdi_tx_smmu_params(struct ol_txrx_ipa_resources * ipa_res,qdf_ipa_wdi_pipe_setup_info_smmu_t * tx_smmu,bool over_gsi)474 static inline void ol_txrx_ipa_wdi_tx_smmu_params(
475 struct ol_txrx_ipa_resources *ipa_res,
476 qdf_ipa_wdi_pipe_setup_info_smmu_t *tx_smmu,
477 bool over_gsi)
478 {
479 QDF_IPA_WDI_SETUP_INFO_SMMU_CLIENT(tx_smmu) =
480 QDF_IPA_CLIENT_WLAN_LEGACY_CONS;
481 qdf_mem_copy(&QDF_IPA_WDI_SETUP_INFO_SMMU_TRANSFER_RING_BASE(
482 tx_smmu),
483 &ipa_res->tx_comp_ring->sgtable,
484 sizeof(sgtable_t));
485 QDF_IPA_WDI_SETUP_INFO_SMMU_TRANSFER_RING_SIZE(tx_smmu) =
486 ipa_res->tx_comp_ring->mem_info.size;
487 qdf_mem_copy(&QDF_IPA_WDI_SETUP_INFO_SMMU_EVENT_RING_BASE(
488 tx_smmu),
489 &ipa_res->ce_sr->sgtable,
490 sizeof(sgtable_t));
491 QDF_IPA_WDI_SETUP_INFO_SMMU_EVENT_RING_SIZE(tx_smmu) =
492 ipa_res->ce_sr_ring_size;
493 QDF_IPA_WDI_SETUP_INFO_SMMU_EVENT_RING_DOORBELL_PA(tx_smmu) =
494 ipa_res->ce_reg_paddr;
495 QDF_IPA_WDI_SETUP_INFO_SMMU_NUM_PKT_BUFFERS(tx_smmu) =
496 ipa_res->tx_num_alloc_buffer;
497 QDF_IPA_WDI_SETUP_INFO_SMMU_PKT_OFFSET(tx_smmu) = 0;
498 }
499
ol_txrx_ipa_wdi_rx_smmu_params(struct ol_txrx_ipa_resources * ipa_res,qdf_ipa_wdi_pipe_setup_info_smmu_t * rx_smmu,bool over_gsi)500 static inline void ol_txrx_ipa_wdi_rx_smmu_params(
501 struct ol_txrx_ipa_resources *ipa_res,
502 qdf_ipa_wdi_pipe_setup_info_smmu_t *rx_smmu,
503 bool over_gsi)
504 {
505 QDF_IPA_WDI_SETUP_INFO_SMMU_CLIENT(rx_smmu) =
506 QDF_IPA_CLIENT_WLAN_LEGACY_PROD;
507 qdf_mem_copy(&QDF_IPA_WDI_SETUP_INFO_SMMU_TRANSFER_RING_BASE(
508 rx_smmu),
509 &ipa_res->rx_rdy_ring->sgtable,
510 sizeof(sgtable_t));
511 QDF_IPA_WDI_SETUP_INFO_SMMU_TRANSFER_RING_SIZE(rx_smmu) =
512 ipa_res->rx_rdy_ring->mem_info.size;
513 QDF_IPA_WDI_SETUP_INFO_SMMU_TRANSFER_RING_DOORBELL_PA(rx_smmu) =
514 ipa_res->rx_proc_done_idx->mem_info.pa;
515 QDF_IPA_WDI_SETUP_INFO_SMMU_PKT_OFFSET(rx_smmu) = 0;
516 }
517
518 #endif
519
520 #else
521
ol_txrx_ipa_wdi_tx_smmu_params(struct ol_txrx_ipa_resources * ipa_res,qdf_ipa_wdi_pipe_setup_info_smmu_t * tx_smmu,bool over_gsi)522 static inline void ol_txrx_ipa_wdi_tx_smmu_params(
523 struct ol_txrx_ipa_resources *ipa_res,
524 qdf_ipa_wdi_pipe_setup_info_smmu_t *tx_smmu,
525 bool over_gsi)
526 {
527 }
528
ol_txrx_ipa_wdi_rx_smmu_params(struct ol_txrx_ipa_resources * ipa_res,qdf_ipa_wdi_pipe_setup_info_smmu_t * rx_smmu,bool over_gsi)529 static inline void ol_txrx_ipa_wdi_rx_smmu_params(
530 struct ol_txrx_ipa_resources *ipa_res,
531 qdf_ipa_wdi_pipe_setup_info_smmu_t *rx_smmu,
532 bool over_gsi)
533 {
534 }
535 #endif
536
537 #ifdef QCA_WIFI_3_0
538 /**
539 * ol_txrx_ipa_wdi_tx_params() - Config IPA TX params
540 * @ipa_res: IPA resources
541 * @tx: IPA WDI pipe setup info
542 *
543 * Return: None
544 */
ol_txrx_ipa_wdi_tx_params(struct ol_txrx_ipa_resources * ipa_res,qdf_ipa_wdi_pipe_setup_info_t * tx,bool over_gsi)545 static inline void ol_txrx_ipa_wdi_tx_params(
546 struct ol_txrx_ipa_resources *ipa_res,
547 qdf_ipa_wdi_pipe_setup_info_t *tx,
548 bool over_gsi)
549 {
550 qdf_device_t osdev = cds_get_context(QDF_MODULE_ID_QDF_DEVICE);
551
552 if (!osdev)
553 return;
554
555 QDF_IPA_WDI_SETUP_INFO_CLIENT(tx) = IPA_CLIENT_WLAN1_CONS;
556 QDF_IPA_WDI_SETUP_INFO_TRANSFER_RING_BASE_PA(tx) =
557 qdf_mem_get_dma_addr(osdev,
558 &ipa_res->tx_comp_ring->mem_info);
559 QDF_IPA_WDI_SETUP_INFO_TRANSFER_RING_SIZE(tx) =
560 ipa_res->tx_comp_ring->mem_info.size;
561 QDF_IPA_WDI_SETUP_INFO_EVENT_RING_BASE_PA(tx) =
562 qdf_mem_get_dma_addr(osdev,
563 &ipa_res->ce_sr->mem_info);
564 QDF_IPA_WDI_SETUP_INFO_EVENT_RING_SIZE(tx) =
565 ipa_res->ce_sr_ring_size;
566 QDF_IPA_WDI_SETUP_INFO_EVENT_RING_DOORBELL_PA(tx) =
567 ipa_res->ce_reg_paddr;
568 if (over_gsi)
569 QDF_IPA_WDI_SETUP_INFO_IS_EVT_RN_DB_PCIE_ADDR(tx) = true;
570 QDF_IPA_WDI_SETUP_INFO_NUM_PKT_BUFFERS(tx) =
571 ipa_res->tx_num_alloc_buffer;
572 QDF_IPA_WDI_SETUP_INFO_PKT_OFFSET(tx) = 0;
573 }
574
575 /**
576 * ol_txrx_ipa_wdi_rx_params() - Config IPA RX params
577 * @ipa_res: IPA resources
578 * @rx: IPA WDI pipe setup info
579 *
580 * Return: None
581 */
ol_txrx_ipa_wdi_rx_params(struct ol_txrx_ipa_resources * ipa_res,qdf_ipa_wdi_pipe_setup_info_t * rx,bool over_gsi)582 static inline void ol_txrx_ipa_wdi_rx_params(
583 struct ol_txrx_ipa_resources *ipa_res,
584 qdf_ipa_wdi_pipe_setup_info_t *rx,
585 bool over_gsi)
586 {
587 QDF_IPA_WDI_SETUP_INFO_CLIENT(rx) = IPA_CLIENT_WLAN1_PROD;
588 QDF_IPA_WDI_SETUP_INFO_TRANSFER_RING_BASE_PA(rx) =
589 ipa_res->rx_rdy_ring->mem_info.pa;
590 QDF_IPA_WDI_SETUP_INFO_TRANSFER_RING_SIZE(rx) =
591 ipa_res->rx_rdy_ring->mem_info.size;
592 QDF_IPA_WDI_SETUP_INFO_TRANSFER_RING_DOORBELL_PA(rx) =
593 ipa_res->rx_proc_done_idx->mem_info.pa;
594 if (over_gsi)
595 QDF_IPA_WDI_SETUP_INFO_IS_TXR_RN_DB_PCIE_ADDR(rx) = false;
596 QDF_IPA_WDI_SETUP_INFO_EVENT_RING_BASE_PA(rx) =
597 ipa_res->rx2_rdy_ring->mem_info.pa;
598 QDF_IPA_WDI_SETUP_INFO_EVENT_RING_SIZE(rx) =
599 ipa_res->rx2_rdy_ring->mem_info.size;
600 QDF_IPA_WDI_SETUP_INFO_EVENT_RING_DOORBELL_PA(rx) =
601 ipa_res->rx2_proc_done_idx->mem_info.pa;
602 if (over_gsi)
603 QDF_IPA_WDI_SETUP_INFO_IS_EVT_RN_DB_PCIE_ADDR(rx) = false;
604 QDF_IPA_WDI_SETUP_INFO_PKT_OFFSET(rx) = 0;
605 }
606
607 #else
ol_txrx_ipa_wdi_tx_params(struct ol_txrx_ipa_resources * ipa_res,qdf_ipa_wdi_pipe_setup_info_t * tx,bool over_gsi)608 static inline void ol_txrx_ipa_wdi_tx_params(
609 struct ol_txrx_ipa_resources *ipa_res,
610 qdf_ipa_wdi_pipe_setup_info_t *tx,
611 bool over_gsi)
612 {
613 qdf_device_t osdev = cds_get_context(QDF_MODULE_ID_QDF_DEVICE);
614
615 if (!osdev)
616 return;
617
618 QDF_IPA_WDI_SETUP_INFO_CLIENT(tx) = QDF_IPA_CLIENT_WLAN_LEGACY_CONS;
619 QDF_IPA_WDI_SETUP_INFO_TRANSFER_RING_BASE_PA(tx) =
620 qdf_mem_get_dma_addr(osdev,
621 &ipa_res->tx_comp_ring->mem_info);
622 QDF_IPA_WDI_SETUP_INFO_TRANSFER_RING_SIZE(tx) =
623 ipa_res->tx_comp_ring->mem_info.size;
624 QDF_IPA_WDI_SETUP_INFO_EVENT_RING_BASE_PA(tx) =
625 qdf_mem_get_dma_addr(osdev,
626 &ipa_res->ce_sr->mem_info);
627 QDF_IPA_WDI_SETUP_INFO_EVENT_RING_SIZE(tx) =
628 ipa_res->ce_sr_ring_size;
629 QDF_IPA_WDI_SETUP_INFO_EVENT_RING_DOORBELL_PA(tx) =
630 ipa_res->ce_reg_paddr;
631 QDF_IPA_WDI_SETUP_INFO_NUM_PKT_BUFFERS(tx) =
632 ipa_res->tx_num_alloc_buffer;
633 QDF_IPA_WDI_SETUP_INFO_PKT_OFFSET(tx) = 0;
634 }
635
ol_txrx_ipa_wdi_rx_params(struct ol_txrx_ipa_resources * ipa_res,qdf_ipa_wdi_pipe_setup_info_t * rx,bool over_gsi)636 static inline void ol_txrx_ipa_wdi_rx_params(
637 struct ol_txrx_ipa_resources *ipa_res,
638 qdf_ipa_wdi_pipe_setup_info_t *rx,
639 bool over_gsi)
640 {
641 QDF_IPA_WDI_SETUP_INFO_CLIENT(rx) = QDF_IPA_CLIENT_WLAN_LEGACY_PROD;
642 QDF_IPA_WDI_SETUP_INFO_TRANSFER_RING_BASE_PA(rx) =
643 ipa_res->rx_rdy_ring->mem_info.pa;
644 QDF_IPA_WDI_SETUP_INFO_TRANSFER_RING_SIZE(rx) =
645 ipa_res->rx_rdy_ring->mem_info.size;
646 QDF_IPA_WDI_SETUP_INFO_TRANSFER_RING_DOORBELL_PA(rx) =
647 ipa_res->rx_proc_done_idx->mem_info.pa;
648 QDF_IPA_WDI_SETUP_INFO_PKT_OFFSET(rx) = 0;
649 }
650
651 #endif
652
ol_txrx_ipa_setup(struct cdp_soc_t * soc_hdl,uint8_t pdev_id,void * ipa_i2w_cb,void * ipa_w2i_cb,void * ipa_wdi_meter_notifier_cb,uint32_t ipa_desc_size,void * ipa_priv,bool is_rm_enabled,uint32_t * p_tx_pipe_handle,uint32_t * p_rx_pipe_handle,bool is_smmu_enabled,qdf_ipa_sys_connect_params_t * sys_in,bool over_gsi,qdf_ipa_wdi_hdl_t hdl,qdf_ipa_wdi_hdl_t id,void * ipa_ast_notify_cb)653 QDF_STATUS ol_txrx_ipa_setup(struct cdp_soc_t *soc_hdl, uint8_t pdev_id,
654 void *ipa_i2w_cb, void *ipa_w2i_cb,
655 void *ipa_wdi_meter_notifier_cb,
656 uint32_t ipa_desc_size, void *ipa_priv,
657 bool is_rm_enabled, uint32_t *p_tx_pipe_handle,
658 uint32_t *p_rx_pipe_handle, bool is_smmu_enabled,
659 qdf_ipa_sys_connect_params_t *sys_in,
660 bool over_gsi,
661 qdf_ipa_wdi_hdl_t hdl,
662 qdf_ipa_wdi_hdl_t id,
663 void *ipa_ast_notify_cb)
664 {
665 struct ol_txrx_soc_t *soc = cdp_soc_t_to_ol_txrx_soc_t(soc_hdl);
666 ol_txrx_pdev_handle pdev = ol_txrx_get_pdev_from_pdev_id(soc, pdev_id);
667 struct ol_txrx_ipa_resources *ipa_res;
668 qdf_ipa_ep_cfg_t *tx_cfg;
669 qdf_ipa_ep_cfg_t *rx_cfg;
670 qdf_ipa_wdi_pipe_setup_info_t *tx;
671 qdf_ipa_wdi_pipe_setup_info_t *rx;
672 qdf_ipa_wdi_pipe_setup_info_smmu_t *tx_smmu;
673 qdf_ipa_wdi_pipe_setup_info_smmu_t *rx_smmu;
674 qdf_ipa_wdi_conn_in_params_t *pipe_in = NULL;
675 qdf_ipa_wdi_conn_out_params_t pipe_out;
676 qdf_device_t osdev = cds_get_context(QDF_MODULE_ID_QDF_DEVICE);
677 uint32_t tx_comp_db_dmaaddr = 0, rx_rdy_db_dmaaddr = 0;
678 int ret;
679
680 if (!pdev) {
681 ol_txrx_err("Invalid instance");
682 return QDF_STATUS_E_FAILURE;
683 }
684
685 if (!osdev)
686 return QDF_STATUS_E_NOENT;
687
688 pipe_in = qdf_mem_malloc(sizeof(*pipe_in));
689 if (!pipe_in)
690 return QDF_STATUS_E_NOMEM;
691
692 ipa_res = &pdev->ipa_resource;
693 qdf_mem_zero(pipe_in, sizeof(*pipe_in));
694 qdf_mem_zero(&pipe_out, sizeof(pipe_out));
695
696 ol_txrx_setup_mcc_sys_pipes(sys_in, pipe_in);
697
698 /* TX PIPE */
699 if (is_smmu_enabled) {
700 QDF_IPA_WDI_CONN_IN_PARAMS_SMMU_ENABLED(pipe_in) = true;
701 tx_smmu = &QDF_IPA_WDI_CONN_IN_PARAMS_TX_SMMU(pipe_in);
702 tx_cfg = &QDF_IPA_WDI_SETUP_INFO_SMMU_EP_CFG(tx_smmu);
703 } else {
704 QDF_IPA_WDI_CONN_IN_PARAMS_SMMU_ENABLED(pipe_in) = false;
705 tx = &QDF_IPA_WDI_CONN_IN_PARAMS_TX(pipe_in);
706 tx_cfg = &QDF_IPA_WDI_SETUP_INFO_EP_CFG(tx);
707 }
708
709 QDF_IPA_EP_CFG_NAT_EN(tx_cfg) = IPA_BYPASS_NAT;
710 QDF_IPA_EP_CFG_HDR_LEN(tx_cfg) = OL_TXRX_IPA_UC_WLAN_TX_HDR_LEN;
711 QDF_IPA_EP_CFG_HDR_OFST_PKT_SIZE_VALID(tx_cfg) = 1;
712 QDF_IPA_EP_CFG_HDR_OFST_PKT_SIZE(tx_cfg) = 0;
713 QDF_IPA_EP_CFG_HDR_ADDITIONAL_CONST_LEN(tx_cfg) =
714 OL_TXRX_IPA_UC_WLAN_8023_HDR_SIZE;
715 QDF_IPA_EP_CFG_MODE(tx_cfg) = IPA_BASIC;
716 QDF_IPA_EP_CFG_HDR_LITTLE_ENDIAN(tx_cfg) = true;
717
718 if (is_smmu_enabled)
719 ol_txrx_ipa_wdi_tx_smmu_params(ipa_res, tx_smmu, over_gsi);
720 else
721 ol_txrx_ipa_wdi_tx_params(ipa_res, tx, over_gsi);
722
723
724 /* RX PIPE */
725 if (is_smmu_enabled) {
726 rx_smmu = &QDF_IPA_WDI_CONN_IN_PARAMS_RX_SMMU(pipe_in);
727 rx_cfg = &QDF_IPA_WDI_SETUP_INFO_EP_CFG(rx_smmu);
728 } else {
729 rx = &QDF_IPA_WDI_CONN_IN_PARAMS_RX(pipe_in);
730 rx_cfg = &QDF_IPA_WDI_SETUP_INFO_EP_CFG(rx);
731 }
732
733 QDF_IPA_EP_CFG_NAT_EN(rx_cfg) = IPA_BYPASS_NAT;
734 QDF_IPA_EP_CFG_HDR_LEN(rx_cfg) = OL_TXRX_IPA_UC_WLAN_RX_HDR_LEN;
735 QDF_IPA_EP_CFG_HDR_OFST_PKT_SIZE_VALID(rx_cfg) = 1;
736 QDF_IPA_EP_CFG_HDR_OFST_PKT_SIZE(rx_cfg) = 0;
737 QDF_IPA_EP_CFG_HDR_ADDITIONAL_CONST_LEN(rx_cfg) =
738 OL_TXRX_IPA_UC_WLAN_8023_HDR_SIZE;
739 QDF_IPA_EP_CFG_HDR_OFST_METADATA_VALID(rx_cfg) = 0;
740 QDF_IPA_EP_CFG_HDR_METADATA_REG_VALID(rx_cfg) = 1;
741 QDF_IPA_EP_CFG_MODE(rx_cfg) = IPA_BASIC;
742 QDF_IPA_EP_CFG_HDR_LITTLE_ENDIAN(rx_cfg) = true;
743
744 if (is_smmu_enabled)
745 ol_txrx_ipa_wdi_rx_smmu_params(ipa_res, rx_smmu, over_gsi);
746 else
747 ol_txrx_ipa_wdi_rx_params(ipa_res, rx, over_gsi);
748
749 QDF_IPA_WDI_CONN_IN_PARAMS_NOTIFY(pipe_in) = ipa_w2i_cb;
750 QDF_IPA_WDI_CONN_IN_PARAMS_PRIV(pipe_in) = ipa_priv;
751
752 /* Connect WDI IPA PIPE */
753 ret = qdf_ipa_wdi_conn_pipes(pipe_in, &pipe_out);
754 if (ret) {
755 QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
756 "%s: ipa_wdi_conn_pipes: IPA pipe setup failed: ret=%d",
757 __func__, ret);
758 qdf_mem_free(pipe_in);
759 return QDF_STATUS_E_FAILURE;
760 }
761
762 /* IPA uC Doorbell registers */
763 QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_DEBUG,
764 "%s: Tx DB PA=0x%x, Rx DB PA=0x%x", __func__,
765 (unsigned int)
766 QDF_IPA_WDI_CONN_OUT_PARAMS_TX_UC_DB_PA(&pipe_out),
767 (unsigned int)
768 QDF_IPA_WDI_CONN_OUT_PARAMS_RX_UC_DB_PA(&pipe_out));
769
770 ipa_res->tx_comp_doorbell_dmaaddr =
771 QDF_IPA_WDI_CONN_OUT_PARAMS_TX_UC_DB_PA(&pipe_out);
772 ipa_res->rx_ready_doorbell_dmaaddr =
773 QDF_IPA_WDI_CONN_OUT_PARAMS_RX_UC_DB_PA(&pipe_out);
774
775 if (is_smmu_enabled) {
776 pld_smmu_map(osdev->dev, ipa_res->tx_comp_doorbell_dmaaddr,
777 &tx_comp_db_dmaaddr, sizeof(uint32_t));
778 ipa_res->tx_comp_doorbell_dmaaddr = tx_comp_db_dmaaddr;
779
780 pld_smmu_map(osdev->dev, ipa_res->rx_ready_doorbell_dmaaddr,
781 &rx_rdy_db_dmaaddr, sizeof(uint32_t));
782 ipa_res->rx_ready_doorbell_dmaaddr = rx_rdy_db_dmaaddr;
783 }
784
785 qdf_mem_free(pipe_in);
786 return QDF_STATUS_SUCCESS;
787 }
788
789 /**
790 * ol_txrx_ipa_cleanup() - Disconnect IPA pipes
791 * @soc_hdl: soc handle
792 * @pdev_id: pdev id
793 * @tx_pipe_handle: Tx pipe handle
794 * @rx_pipe_handle: Rx pipe handle
795 *
796 * Return: QDF_STATUS
797 */
ol_txrx_ipa_cleanup(struct cdp_soc_t * soc_hdl,uint8_t pdev_id,uint32_t tx_pipe_handle,uint32_t rx_pipe_handle,qdf_ipa_wdi_hdl_t hdl)798 QDF_STATUS ol_txrx_ipa_cleanup(struct cdp_soc_t *soc_hdl, uint8_t pdev_id,
799 uint32_t tx_pipe_handle,
800 uint32_t rx_pipe_handle,
801 qdf_ipa_wdi_hdl_t hdl)
802 {
803 int ret;
804 struct ol_txrx_ipa_resources *ipa_res;
805 struct ol_txrx_soc_t *soc = cds_get_context(QDF_MODULE_ID_SOC);
806 qdf_device_t osdev = cds_get_context(QDF_MODULE_ID_QDF_DEVICE);
807 ol_txrx_pdev_handle pdev;
808
809 if (!soc || !osdev)
810 return QDF_STATUS_E_FAILURE;
811
812 pdev = ol_txrx_get_pdev_from_pdev_id(soc, OL_TXRX_PDEV_ID);
813 if (!pdev) {
814 ol_txrx_err("NULL pdev invalid instance");
815 return QDF_STATUS_E_FAILURE;
816 }
817
818 ipa_res = &pdev->ipa_resource;
819 if (osdev->smmu_s1_enabled) {
820 ret = pld_smmu_unmap(osdev->dev,
821 ipa_res->rx_ready_doorbell_dmaaddr,
822 sizeof(uint32_t));
823 if (ret)
824 ol_txrx_err("rx_ready, smmu unmap failed");
825
826 ret = pld_smmu_unmap(osdev->dev,
827 ipa_res->tx_comp_doorbell_dmaaddr,
828 sizeof(uint32_t));
829 if (ret)
830 ol_txrx_err("tx_comp, smmu unmap failed");
831 }
832
833 QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_DEBUG,
834 "%s: Disconnect IPA pipe", __func__);
835 ret = qdf_ipa_wdi_disconn_pipes(hdl);
836 if (ret) {
837 QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
838 "ipa_wdi_disconn_pipes failed: ret=%d", ret);
839 return QDF_STATUS_E_FAILURE;
840 }
841
842 return QDF_STATUS_SUCCESS;
843 }
844
845 /**
846 * ol_txrx_ipa_setup_iface() - Setup IPA header and register interface
847 * @ifname: Interface name
848 * @mac_addr: Interface MAC address
849 * @prod_client: IPA prod client type
850 * @cons_client: IPA cons client type
851 * @session_id: Session ID
852 * @is_ipv6_enabled: Is IPV6 enabled or not
853 *
854 * Return: QDF_STATUS
855 */
ol_txrx_ipa_setup_iface(char * ifname,uint8_t * mac_addr,qdf_ipa_client_type_t prod_client,qdf_ipa_client_type_t cons_client,uint8_t session_id,bool is_ipv6_enabled,qdf_ipa_wdi_hdl_t hdl)856 QDF_STATUS ol_txrx_ipa_setup_iface(char *ifname, uint8_t *mac_addr,
857 qdf_ipa_client_type_t prod_client,
858 qdf_ipa_client_type_t cons_client,
859 uint8_t session_id, bool is_ipv6_enabled,
860 qdf_ipa_wdi_hdl_t hdl)
861 {
862 qdf_ipa_wdi_reg_intf_in_params_t in;
863 qdf_ipa_wdi_hdr_info_t hdr_info;
864 struct ol_txrx_ipa_uc_tx_hdr uc_tx_hdr;
865 struct ol_txrx_ipa_uc_tx_hdr uc_tx_hdr_v6;
866 int ret = -EINVAL;
867
868 QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_DEBUG,
869 "%s: Add Partial hdr: %s, "QDF_MAC_ADDR_FMT,
870 __func__, ifname, QDF_MAC_ADDR_REF(mac_addr));
871
872 qdf_mem_zero(&hdr_info, sizeof(qdf_ipa_wdi_hdr_info_t));
873 memcpy(&uc_tx_hdr, &ipa_uc_tx_hdr, OL_TXRX_IPA_UC_WLAN_TX_HDR_LEN);
874 qdf_ether_addr_copy(uc_tx_hdr.eth.h_source, mac_addr);
875 uc_tx_hdr.ipa_hd.vdev_id = session_id;
876
877 /* IPV4 header */
878 uc_tx_hdr.eth.h_proto = qdf_htons(ETH_P_IP);
879
880 QDF_IPA_WDI_HDR_INFO_HDR(&hdr_info) = (uint8_t *)&uc_tx_hdr;
881 QDF_IPA_WDI_HDR_INFO_HDR_LEN(&hdr_info) =
882 OL_TXRX_IPA_UC_WLAN_TX_HDR_LEN;
883 QDF_IPA_WDI_HDR_INFO_HDR_TYPE(&hdr_info) = IPA_HDR_L2_ETHERNET_II;
884 QDF_IPA_WDI_HDR_INFO_DST_MAC_ADDR_OFFSET(&hdr_info) =
885 OL_TXRX_IPA_UC_WLAN_HDR_DES_MAC_OFFSET;
886
887 QDF_IPA_WDI_REG_INTF_IN_PARAMS_NETDEV_NAME(&in) = ifname;
888 memcpy(&(QDF_IPA_WDI_REG_INTF_IN_PARAMS_HDR_INFO(&in)[IPA_IP_v4]),
889 &hdr_info, sizeof(qdf_ipa_wdi_hdr_info_t));
890 QDF_IPA_WDI_REG_INTF_IN_PARAMS_ALT_DST_PIPE(&in) = cons_client;
891 QDF_IPA_WDI_REG_INTF_IN_PARAMS_IS_META_DATA_VALID(&in) = 1;
892 QDF_IPA_WDI_REG_INTF_IN_PARAMS_META_DATA(&in) =
893 htonl(session_id << 16);
894 QDF_IPA_WDI_REG_INTF_IN_PARAMS_META_DATA_MASK(&in) = htonl(0x00FF0000);
895
896 /* IPV6 header */
897 if (is_ipv6_enabled) {
898 memcpy(&uc_tx_hdr_v6, &uc_tx_hdr,
899 OL_TXRX_IPA_UC_WLAN_TX_HDR_LEN);
900 uc_tx_hdr_v6.eth.h_proto = qdf_htons(ETH_P_IPV6);
901 QDF_IPA_WDI_HDR_INFO_HDR(&hdr_info) = (uint8_t *)&uc_tx_hdr_v6;
902 memcpy(&(QDF_IPA_WDI_REG_INTF_IN_PARAMS_HDR_INFO(&in)[IPA_IP_v6]),
903 &hdr_info, sizeof(qdf_ipa_wdi_hdr_info_t));
904 }
905
906 ret = qdf_ipa_wdi_reg_intf(&in);
907 if (ret) {
908 QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
909 "%s: ipa_wdi_reg_intf failed: ret=%d", __func__, ret);
910 }
911
912 return ret;
913 }
914
915 /**
916 * ol_txrx_ipa_cleanup_iface() - Cleanup IPA header and deregister interface
917 * @ifname: Interface name
918 * @is_ipv6_enabled: Is IPV6 enabled or not
919 *
920 * Return: QDF_STATUS
921 */
ol_txrx_ipa_cleanup_iface(char * ifname,bool is_ipv6_enabled,qdf_ipa_wdi_hdl_t hdl)922 QDF_STATUS ol_txrx_ipa_cleanup_iface(char *ifname, bool is_ipv6_enabled,
923 qdf_ipa_wdi_hdl_t hdl)
924 {
925 int ret;
926
927 /* unregister the interface with IPA */
928 ret = qdf_ipa_wdi_dereg_intf(ifname, hdl);
929 if (ret) {
930 QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_DEBUG,
931 "%s: ipa_wdi_dereg_intf failed: devname=%s, ret=%d",
932 __func__, ifname, ret);
933 return QDF_STATUS_E_FAILURE;
934 }
935
936 return QDF_STATUS_SUCCESS;
937 }
938
ol_txrx_ipa_enable_pipes(struct cdp_soc_t * soc_hdl,uint8_t pdev_id,qdf_ipa_wdi_hdl_t hdl)939 QDF_STATUS ol_txrx_ipa_enable_pipes(struct cdp_soc_t *soc_hdl, uint8_t pdev_id,
940 qdf_ipa_wdi_hdl_t hdl)
941 {
942 struct ol_txrx_soc_t *soc = cdp_soc_t_to_ol_txrx_soc_t(soc_hdl);
943 ol_txrx_pdev_handle pdev = ol_txrx_get_pdev_from_pdev_id(soc, pdev_id);
944 QDF_STATUS status;
945 int ret;
946
947 if (!pdev) {
948 ol_txrx_err("Invalid instance");
949 return QDF_STATUS_E_FAILURE;
950 }
951
952 status = htt_rx_update_smmu_map(pdev->htt_pdev, true);
953 if (status != QDF_STATUS_SUCCESS) {
954 QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
955 "IPA SMMU map failed status:%d", status);
956 return status;
957 }
958
959 /* ACTIVATE TX PIPE */
960 QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_DEBUG,
961 "%s: Enable IPA pipes", __func__);
962 ret = qdf_ipa_wdi_enable_pipes(hdl);
963 if (ret) {
964 QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
965 "%s: ipa_wdi_enable_pipes failed: ret=%d",
966 __func__, ret);
967 status = htt_rx_update_smmu_map(pdev->htt_pdev, false);
968 if (status != QDF_STATUS_SUCCESS)
969 QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
970 "IPA SMMU unmap failed");
971 return QDF_STATUS_E_FAILURE;
972 }
973
974 ol_txrx_ipa_uc_set_active(soc_hdl, pdev_id, true, true);
975 ol_txrx_ipa_uc_set_active(soc_hdl, pdev_id, true, false);
976
977 return QDF_STATUS_SUCCESS;
978 }
979
ol_txrx_ipa_disable_pipes(struct cdp_soc_t * soc_hdl,uint8_t pdev_id,qdf_ipa_wdi_hdl_t hdl)980 QDF_STATUS ol_txrx_ipa_disable_pipes(struct cdp_soc_t *soc_hdl, uint8_t pdev_id,
981 qdf_ipa_wdi_hdl_t hdl)
982 {
983 struct ol_txrx_soc_t *soc = cdp_soc_t_to_ol_txrx_soc_t(soc_hdl);
984 ol_txrx_pdev_handle pdev = ol_txrx_get_pdev_from_pdev_id(soc, pdev_id);
985 int ret;
986
987 if (!pdev) {
988 ol_txrx_err("Invalid instance");
989 return QDF_STATUS_E_FAILURE;
990 }
991
992 QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_DEBUG,
993 "%s: Disable IPA pipes", __func__);
994 ret = qdf_ipa_wdi_disable_pipes(hdl);
995 if (ret) {
996 QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
997 "%s: ipa_wdi_disable_pipes failed: ret=%d",
998 __func__, ret);
999 }
1000
1001 if (htt_rx_update_smmu_map(pdev->htt_pdev, false) !=
1002 QDF_STATUS_SUCCESS) {
1003 QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
1004 "IPA SMMU unmap failed");
1005 }
1006
1007 return ret ? QDF_STATUS_E_FAILURE : QDF_STATUS_SUCCESS;
1008 }
1009
1010 /**
1011 * ol_txrx_ipa_set_perf_level() - Set IPA clock bandwidth based on data rates
1012 * @client: Client type
1013 * @max_supported_bw_mbps: Maximum bandwidth needed (in Mbps)
1014 *
1015 * Return: QDF_STATUS
1016 */
ol_txrx_ipa_set_perf_level(int client,uint32_t max_supported_bw_mbps,qdf_ipa_wdi_hdl_t hdl)1017 QDF_STATUS ol_txrx_ipa_set_perf_level(int client,
1018 uint32_t max_supported_bw_mbps,
1019 qdf_ipa_wdi_hdl_t hdl)
1020 {
1021 qdf_ipa_wdi_perf_profile_t profile;
1022 int result;
1023
1024 QDF_IPA_WDI_PERF_PROFILE_CLIENT(&profile) = client;
1025 QDF_IPA_WDI_PERF_PROFILE_MAX_SUPPORTED_BW_MBPS(&profile) =
1026 max_supported_bw_mbps;
1027 result = qdf_ipa_wdi_set_perf_profile(hdl, &profile);
1028
1029 if (result) {
1030 QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
1031 "Set perf profile failed, code %d", result);
1032
1033 return QDF_STATUS_E_FAILURE;
1034 }
1035
1036 return QDF_STATUS_SUCCESS;
1037 }
1038
1039 #else /* CONFIG_IPA_WDI_UNIFIED_API */
1040
1041 #ifdef ENABLE_SMMU_S1_TRANSLATION
1042 /**
1043 * ol_txrx_ipa_tx_smmu_params() - Config IPA TX params
1044 * @ipa_res: IPA resources
1045 * @pipe_in: IPA WDI TX pipe params
1046 *
1047 * Return: None
1048 */
ol_txrx_ipa_tx_smmu_params(struct ol_txrx_ipa_resources * ipa_res,qdf_ipa_wdi_in_params_t * pipe_in)1049 static inline void ol_txrx_ipa_tx_smmu_params(
1050 struct ol_txrx_ipa_resources *ipa_res,
1051 qdf_ipa_wdi_in_params_t *pipe_in)
1052 {
1053 QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_DEBUG,
1054 "%s: SMMU Enabled", __func__);
1055
1056 QDF_IPA_PIPE_IN_SMMU_ENABLED(pipe_in) = true;
1057 qdf_mem_copy(&QDF_IPA_PIPE_IN_DL_SMMU_COMP_RING(pipe_in),
1058 &ipa_res->tx_comp_ring->sgtable,
1059 sizeof(sgtable_t));
1060 QDF_IPA_PIPE_IN_DL_SMMU_COMP_RING_SIZE(pipe_in) =
1061 ipa_res->tx_comp_ring->mem_info.size;
1062 qdf_mem_copy(&QDF_IPA_PIPE_IN_DL_SMMU_CE_RING(pipe_in),
1063 &ipa_res->ce_sr->sgtable,
1064 sizeof(sgtable_t));
1065 QDF_IPA_PIPE_IN_DL_SMMU_CE_DOOR_BELL_PA(pipe_in) =
1066 ipa_res->ce_reg_paddr;
1067 QDF_IPA_PIPE_IN_DL_SMMU_CE_RING_SIZE(pipe_in) =
1068 ipa_res->ce_sr_ring_size;
1069 QDF_IPA_PIPE_IN_DL_SMMU_NUM_TX_BUFFERS(pipe_in) =
1070 ipa_res->tx_num_alloc_buffer;
1071 }
1072
1073 /**
1074 * ol_txrx_ipa_rx_smmu_params() - Config IPA TX params
1075 * @ipa_res: IPA resources
1076 * @pipe_in: IPA WDI TX pipe params
1077 *
1078 * Return: None
1079 */
ol_txrx_ipa_rx_smmu_params(struct ol_txrx_ipa_resources * ipa_res,qdf_ipa_wdi_in_params_t * pipe_in)1080 static inline void ol_txrx_ipa_rx_smmu_params(
1081 struct ol_txrx_ipa_resources *ipa_res,
1082 qdf_ipa_wdi_in_params_t *pipe_in)
1083 {
1084 qdf_mem_copy(&QDF_IPA_PIPE_IN_UL_SMMU_RDY_RING(pipe_in),
1085 &ipa_res->rx_rdy_ring->sgtable,
1086 sizeof(sgtable_t));
1087 QDF_IPA_PIPE_IN_UL_SMMU_RDY_RING_SIZE(pipe_in) =
1088 ipa_res->rx_rdy_ring->mem_info.size;
1089 QDF_IPA_PIPE_IN_UL_SMMU_RDY_RING_RP_PA(pipe_in) =
1090 ipa_res->rx_proc_done_idx->mem_info.pa;
1091
1092 QDF_IPA_PIPE_IN_UL_SMMU_RDY_RING_RP_VA(pipe_in) =
1093 ipa_res->rx_proc_done_idx->vaddr;
1094 qdf_mem_copy(&QDF_IPA_PIPE_IN_UL_SMMU_RDY_COMP_RING(pipe_in),
1095 &ipa_res->rx2_rdy_ring->sgtable,
1096 sizeof(sgtable_t));
1097 QDF_IPA_PIPE_IN_UL_SMMU_RDY_COMP_RING_SIZE(pipe_in) =
1098 ipa_res->rx2_rdy_ring->mem_info.size;
1099 QDF_IPA_PIPE_IN_UL_SMMU_RDY_COMP_RING_WP_PA(pipe_in) =
1100 ipa_res->rx2_proc_done_idx->mem_info.pa;
1101 QDF_IPA_PIPE_IN_UL_SMMU_RDY_COMP_RING_WP_VA(pipe_in) =
1102 ipa_res->rx2_proc_done_idx->vaddr;
1103 }
1104 #else
ol_txrx_ipa_tx_smmu_params(struct ol_txrx_ipa_resources * ipa_res,qdf_ipa_wdi_in_params_t * pipe_in)1105 static inline void ol_txrx_ipa_tx_smmu_params(
1106 struct ol_txrx_ipa_resources *ipa_res,
1107 qdf_ipa_wdi_in_params_t *pipe_in)
1108 {
1109 }
1110
ol_txrx_ipa_rx_smmu_params(struct ol_txrx_ipa_resources * ipa_res,qdf_ipa_wdi_in_params_t * pipe_in)1111 static inline void ol_txrx_ipa_rx_smmu_params(
1112 struct ol_txrx_ipa_resources *ipa_res,
1113 qdf_ipa_wdi_in_params_t *pipe_in)
1114 {
1115 }
1116 #endif
1117
1118 /**
1119 * ol_txrx_ipa_tx_params() - Config IPA TX params
1120 * @ipa_res: IPA resources
1121 * @pipe_in: IPA WDI TX pipe params
1122 *
1123 * Return: None
1124 */
ol_txrx_ipa_tx_params(struct ol_txrx_ipa_resources * ipa_res,qdf_ipa_wdi_in_params_t * pipe_in)1125 static inline void ol_txrx_ipa_tx_params(
1126 struct ol_txrx_ipa_resources *ipa_res,
1127 qdf_ipa_wdi_in_params_t *pipe_in)
1128 {
1129 qdf_device_t osdev = cds_get_context(QDF_MODULE_ID_QDF_DEVICE);
1130
1131 if (!osdev)
1132 return;
1133
1134 QDF_IPA_PIPE_IN_DL_COMP_RING_BASE_PA(pipe_in) =
1135 qdf_mem_get_dma_addr(osdev,
1136 &ipa_res->tx_comp_ring->mem_info);
1137 QDF_IPA_PIPE_IN_DL_COMP_RING_SIZE(pipe_in) =
1138 ipa_res->tx_comp_ring->mem_info.size;
1139 QDF_IPA_PIPE_IN_DL_CE_RING_BASE_PA(pipe_in) =
1140 qdf_mem_get_dma_addr(osdev,
1141 &ipa_res->ce_sr->mem_info);
1142 QDF_IPA_PIPE_IN_DL_CE_DOOR_BELL_PA(pipe_in) =
1143 ipa_res->ce_reg_paddr;
1144 QDF_IPA_PIPE_IN_DL_CE_RING_SIZE(pipe_in) =
1145 ipa_res->ce_sr_ring_size;
1146 QDF_IPA_PIPE_IN_DL_NUM_TX_BUFFERS(pipe_in) =
1147 ipa_res->tx_num_alloc_buffer;
1148 }
1149
1150 /**
1151 * ol_txrx_ipa_rx_params() - Config IPA RX params
1152 * @ipa_res: IPA resources
1153 * @pipe_in: IPA WDI RX pipe params
1154 *
1155 * Return: None
1156 */
ol_txrx_ipa_rx_params(struct ol_txrx_ipa_resources * ipa_res,qdf_ipa_wdi_in_params_t * pipe_in)1157 static inline void ol_txrx_ipa_rx_params(
1158 struct ol_txrx_ipa_resources *ipa_res,
1159 qdf_ipa_wdi_in_params_t *pipe_in)
1160 {
1161 qdf_device_t osdev = cds_get_context(QDF_MODULE_ID_QDF_DEVICE);
1162
1163 if (!osdev)
1164 return;
1165
1166 QDF_IPA_PIPE_IN_UL_RDY_RING_BASE_PA(pipe_in) =
1167 ipa_res->rx_rdy_ring->mem_info.pa;
1168 QDF_IPA_PIPE_IN_UL_RDY_RING_SIZE(pipe_in) =
1169 ipa_res->rx_rdy_ring->mem_info.size;
1170 QDF_IPA_PIPE_IN_UL_RDY_RING_RP_PA(pipe_in) =
1171 ipa_res->rx_proc_done_idx->mem_info.pa;
1172 OL_TXRX_IPA_WDI2_SET(pipe_in, ipa_res,
1173 osdev);
1174 }
1175
ol_txrx_ipa_setup(struct cdp_soc_t * soc_hdl,uint8_t pdev_id,void * ipa_i2w_cb,void * ipa_w2i_cb,void * ipa_wdi_meter_notifier_cb,uint32_t ipa_desc_size,void * ipa_priv,bool is_rm_enabled,uint32_t * p_tx_pipe_handle,uint32_t * p_rx_pipe_handle)1176 QDF_STATUS ol_txrx_ipa_setup(struct cdp_soc_t *soc_hdl, uint8_t pdev_id,
1177 void *ipa_i2w_cb, void *ipa_w2i_cb,
1178 void *ipa_wdi_meter_notifier_cb,
1179 uint32_t ipa_desc_size, void *ipa_priv,
1180 bool is_rm_enabled, uint32_t *p_tx_pipe_handle,
1181 uint32_t *p_rx_pipe_handle)
1182 {
1183 struct ol_txrx_soc_t *soc = cdp_soc_t_to_ol_txrx_soc_t(soc_hdl);
1184 ol_txrx_pdev_handle pdev = ol_txrx_get_pdev_from_pdev_id(soc, pdev_id);
1185 qdf_device_t osdev = cds_get_context(QDF_MODULE_ID_QDF_DEVICE);
1186 struct ol_txrx_ipa_resources *ipa_res;
1187 qdf_ipa_wdi_in_params_t pipe_in;
1188 qdf_ipa_wdi_out_params_t pipe_out;
1189 uint32_t tx_comp_db_dmaaddr = 0, rx_rdy_db_dmaaddr = 0;
1190 int ret;
1191
1192 if (!pdev) {
1193 ol_txrx_err("Invalid instance");
1194 return QDF_STATUS_E_FAILURE;
1195 }
1196
1197 if (!osdev)
1198 return QDF_STATUS_E_NOENT;
1199
1200 ipa_res = &pdev->ipa_resource;
1201 qdf_mem_zero(&pipe_in, sizeof(pipe_in));
1202 qdf_mem_zero(&pipe_out, sizeof(pipe_out));
1203
1204 /* TX PIPE */
1205 QDF_IPA_PIPE_IN_NAT_EN(&pipe_in) = IPA_BYPASS_NAT;
1206 QDF_IPA_PIPE_IN_HDR_LEN(&pipe_in) = OL_TXRX_IPA_UC_WLAN_TX_HDR_LEN;
1207 QDF_IPA_PIPE_IN_HDR_OFST_PKT_SIZE_VALID(&pipe_in) = 1;
1208 QDF_IPA_PIPE_IN_HDR_OFST_PKT_SIZE(&pipe_in) = 0;
1209 QDF_IPA_PIPE_IN_HDR_ADDITIONAL_CONST_LEN(&pipe_in) =
1210 OL_TXRX_IPA_UC_WLAN_8023_HDR_SIZE;
1211 QDF_IPA_PIPE_IN_MODE(&pipe_in) = IPA_BASIC;
1212 QDF_IPA_PIPE_IN_CLIENT(&pipe_in) = IPA_CLIENT_WLAN1_CONS;
1213 QDF_IPA_PIPE_IN_DESC_FIFO_SZ(&pipe_in) = ipa_desc_size;
1214 QDF_IPA_PIPE_IN_PRIV(&pipe_in) = ipa_priv;
1215 QDF_IPA_PIPE_IN_HDR_LITTLE_ENDIAN(&pipe_in) = true;
1216 QDF_IPA_PIPE_IN_NOTIFY(&pipe_in) = ipa_i2w_cb;
1217
1218 if (!is_rm_enabled) {
1219 QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_DEBUG,
1220 "%s: IPA RM DISABLED, IPA AWAKE", __func__);
1221 QDF_IPA_PIPE_IN_KEEP_IPA_AWAKE(&pipe_in) = true;
1222 }
1223
1224 if (qdf_mem_smmu_s1_enabled(osdev))
1225 ol_txrx_ipa_tx_smmu_params(ipa_res, &pipe_in);
1226 else
1227 ol_txrx_ipa_tx_params(ipa_res, &pipe_in);
1228
1229 /* Connect WDI IPA PIPE */
1230 ret = qdf_ipa_connect_wdi_pipe(&pipe_in, &pipe_out);
1231 if (ret) {
1232 QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
1233 "ipa_connect_wdi_pipe: Tx pipe setup failed: ret=%d", ret);
1234 return QDF_STATUS_E_FAILURE;
1235 }
1236
1237 /* Micro Controller Doorbell register */
1238 QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_DEBUG,
1239 "%s CONS DB pipe out 0x%x TX PIPE Handle 0x%x", __func__,
1240 (unsigned int)QDF_IPA_PIPE_OUT_UC_DOOR_BELL_PA(&pipe_out),
1241 pipe_out.clnt_hdl);
1242 ipa_res->tx_comp_doorbell_dmaaddr =
1243 QDF_IPA_PIPE_OUT_UC_DOOR_BELL_PA(&pipe_out);
1244 /* WLAN TX PIPE Handle */
1245 ipa_res->tx_pipe_handle = QDF_IPA_PIPE_OUT_CLNT_HDL(&pipe_out);
1246 *p_tx_pipe_handle = QDF_IPA_PIPE_OUT_CLNT_HDL(&pipe_out);
1247
1248 /* RX PIPE */
1249 QDF_IPA_PIPE_IN_NAT_EN(&pipe_in) = IPA_BYPASS_NAT;
1250 QDF_IPA_PIPE_IN_HDR_LEN(&pipe_in) = OL_TXRX_IPA_UC_WLAN_RX_HDR_LEN;
1251 QDF_IPA_PIPE_IN_HDR_OFST_METADATA_VALID(&pipe_in) = 0;
1252 QDF_IPA_PIPE_IN_HDR_METADATA_REG_VALID(&pipe_in) = 1;
1253 QDF_IPA_PIPE_IN_MODE(&pipe_in) = IPA_BASIC;
1254 QDF_IPA_PIPE_IN_CLIENT(&pipe_in) = IPA_CLIENT_WLAN1_PROD;
1255 QDF_IPA_PIPE_IN_DESC_FIFO_SZ(&pipe_in) =
1256 ipa_desc_size + SPS_DESC_SIZE;
1257 QDF_IPA_PIPE_IN_NOTIFY(&pipe_in) = ipa_w2i_cb;
1258 if (!is_rm_enabled) {
1259 QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
1260 "%s: IPA RM DISABLED, IPA AWAKE", __func__);
1261 QDF_IPA_PIPE_IN_KEEP_IPA_AWAKE(&pipe_in) = true;
1262 }
1263
1264 if (qdf_mem_smmu_s1_enabled(osdev))
1265 ol_txrx_ipa_rx_smmu_params(ipa_res, &pipe_in);
1266 else
1267 ol_txrx_ipa_rx_params(ipa_res, &pipe_in);
1268
1269 #ifdef FEATURE_METERING
1270 QDF_IPA_PIPE_IN_WDI_NOTIFY(&pipe_in) = ipa_wdi_meter_notifier_cb;
1271 #endif
1272
1273 ret = qdf_ipa_connect_wdi_pipe(&pipe_in, &pipe_out);
1274 if (ret) {
1275 QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
1276 "ipa_connect_wdi_pipe: Rx pipe setup failed: ret=%d", ret);
1277 return QDF_STATUS_E_FAILURE;
1278 }
1279 ipa_res->rx_ready_doorbell_dmaaddr =
1280 QDF_IPA_PIPE_OUT_UC_DOOR_BELL_PA(&pipe_out);
1281 ipa_res->rx_pipe_handle = QDF_IPA_PIPE_OUT_CLNT_HDL(&pipe_out);
1282 *p_rx_pipe_handle = QDF_IPA_PIPE_OUT_CLNT_HDL(&pipe_out);
1283
1284 if (qdf_mem_smmu_s1_enabled(osdev)) {
1285 pld_smmu_map(osdev->dev, ipa_res->tx_comp_doorbell_dmaaddr,
1286 &tx_comp_db_dmaaddr, sizeof(uint32_t));
1287 ipa_res->tx_comp_doorbell_dmaaddr = tx_comp_db_dmaaddr;
1288
1289 pld_smmu_map(osdev->dev, ipa_res->rx_ready_doorbell_dmaaddr,
1290 &rx_rdy_db_dmaaddr, sizeof(uint32_t));
1291 ipa_res->rx_ready_doorbell_dmaaddr = rx_rdy_db_dmaaddr;
1292 }
1293
1294 return QDF_STATUS_SUCCESS;
1295 }
1296
1297 /**
1298 * ol_txrx_ipa_cleanup() - Disconnect IPA pipes
1299 * @soc_hdl: soc handle
1300 * @pdev_id: pdev id
1301 * @tx_pipe_handle: Tx pipe handle
1302 * @rx_pipe_handle: Rx pipe handle
1303 *
1304 * Return: QDF_STATUS
1305 */
ol_txrx_ipa_cleanup(struct cdp_soc_t * soc_hdl,uint8_t pdev_id,uint32_t tx_pipe_handle,uint32_t rx_pipe_handle)1306 QDF_STATUS ol_txrx_ipa_cleanup(struct cdp_soc_t *soc_hdl, uint8_t pdev_id,
1307 uint32_t tx_pipe_handle,
1308 uint32_t rx_pipe_handle)
1309 {
1310 int ret;
1311
1312 QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_DEBUG,
1313 "%s: Disconnect TX PIPE tx_pipe_handle=0x%x",
1314 __func__, tx_pipe_handle);
1315 ret = qdf_ipa_disconnect_wdi_pipe(tx_pipe_handle);
1316 if (ret) {
1317 QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
1318 "ipa_disconnect_wdi_pipe: Tx pipe cleanup failed: ret=%d",
1319 ret);
1320 return QDF_STATUS_E_FAILURE;
1321 }
1322
1323 QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_DEBUG,
1324 "%s: Disconnect RX PIPE rx_pipe_handle=0x%x",
1325 __func__, rx_pipe_handle);
1326 ret = qdf_ipa_disconnect_wdi_pipe(rx_pipe_handle);
1327 if (ret) {
1328 QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
1329 "ipa_disconnect_wdi_pipe: Rx pipe cleanup failed: ret=%d",
1330 ret);
1331 return QDF_STATUS_E_FAILURE;
1332 }
1333
1334 return QDF_STATUS_SUCCESS;
1335 }
1336
1337 /**
1338 * ol_txrx_remove_ipa_header() - Remove a specific header from IPA
1339 * @name: Name of the header to be removed
1340 *
1341 * Return: QDF_STATUS
1342 */
ol_txrx_ipa_remove_header(char * name)1343 static QDF_STATUS ol_txrx_ipa_remove_header(char *name)
1344 {
1345 qdf_ipa_ioc_get_hdr_t hdrlookup;
1346 int ret = 0, len;
1347 qdf_ipa_ioc_del_hdr_t *ipa_hdr;
1348
1349 qdf_mem_zero(&hdrlookup, sizeof(hdrlookup));
1350 strlcpy(hdrlookup.name, name, sizeof(hdrlookup.name));
1351 ret = qdf_ipa_get_hdr(&hdrlookup);
1352 if (ret) {
1353 QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_DEBUG,
1354 "Hdr deleted already %s, %d", name, ret);
1355 return QDF_STATUS_E_FAILURE;
1356 }
1357
1358 QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_DEBUG, "hdl: 0x%x",
1359 hdrlookup.hdl);
1360 len = sizeof(qdf_ipa_ioc_del_hdr_t) + sizeof(qdf_ipa_hdr_del_t) * 1;
1361 ipa_hdr = (qdf_ipa_ioc_del_hdr_t *)qdf_mem_malloc(len);
1362 if (!ipa_hdr)
1363 return QDF_STATUS_E_FAILURE;
1364
1365 QDF_IPA_IOC_DEL_HDR_NUM_HDRS(ipa_hdr) = 1;
1366 QDF_IPA_IOC_DEL_HDR_COMMIT(ipa_hdr) = 0;
1367 QDF_IPA_IOC_DEL_HDR_HDL(ipa_hdr) = QDF_IPA_IOC_GET_HDR_HDL(&hdrlookup);
1368 QDF_IPA_IOC_DEL_HDR_STATUS(ipa_hdr) = -1;
1369 ret = qdf_ipa_del_hdr(ipa_hdr);
1370 if (ret != 0) {
1371 QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
1372 "Delete header failed: %d", ret);
1373 qdf_mem_free(ipa_hdr);
1374 return QDF_STATUS_E_FAILURE;
1375 }
1376
1377 qdf_mem_free(ipa_hdr);
1378 return QDF_STATUS_SUCCESS;
1379 }
1380
1381 /**
1382 * ol_txrx_ipa_add_header_info() - Add IPA header for a given interface
1383 * @ifname: Interface name
1384 * @mac_addr: Interface MAC address
1385 * @is_ipv6_enabled: Is IPV6 enabled or not
1386 *
1387 * Return: 0 on success, negativer errno value on error
1388 */
ol_txrx_ipa_add_header_info(char * ifname,uint8_t * mac_addr,uint8_t session_id,bool is_ipv6_enabled)1389 static int ol_txrx_ipa_add_header_info(char *ifname, uint8_t *mac_addr,
1390 uint8_t session_id, bool is_ipv6_enabled)
1391 {
1392 qdf_ipa_ioc_add_hdr_t *ipa_hdr = NULL;
1393 int ret = -EINVAL;
1394 struct ol_txrx_ipa_uc_tx_hdr *uc_tx_hdr = NULL;
1395
1396 QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_DEBUG,
1397 "Add Partial hdr: %s, "QDF_MAC_ADDR_FMT, ifname,
1398 QDF_MAC_ADDR_REF(mac_addr));
1399
1400 /* dynamically allocate the memory to add the hdrs */
1401 ipa_hdr = qdf_mem_malloc(sizeof(qdf_ipa_ioc_add_hdr_t)
1402 + sizeof(qdf_ipa_hdr_add_t));
1403 if (!ipa_hdr) {
1404 ret = -ENOMEM;
1405 goto end;
1406 }
1407
1408 QDF_IPA_IOC_ADD_HDR_COMMIT(ipa_hdr) = 0;
1409 QDF_IPA_IOC_ADD_HDR_NUM_HDRS(ipa_hdr) = 1;
1410
1411 uc_tx_hdr = (struct ol_txrx_ipa_uc_tx_hdr *)
1412 QDF_IPA_IOC_ADD_HDR_HDR(ipa_hdr);
1413 memcpy(uc_tx_hdr, &ipa_uc_tx_hdr, OL_TXRX_IPA_UC_WLAN_TX_HDR_LEN);
1414 memcpy(uc_tx_hdr->eth.h_source, mac_addr, ETH_ALEN);
1415 uc_tx_hdr->ipa_hd.vdev_id = session_id;
1416 QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_DEBUG,
1417 "ifname=%s, vdev_id=%d",
1418 ifname, uc_tx_hdr->ipa_hd.vdev_id);
1419 snprintf(QDF_IPA_IOC_ADD_HDR_NAME(ipa_hdr), IPA_RESOURCE_NAME_MAX,
1420 "%s%s", ifname, OL_TXRX_IPA_IPV4_NAME_EXT);
1421 QDF_IPA_IOC_ADD_HDR_HDR_LEN(ipa_hdr) = OL_TXRX_IPA_UC_WLAN_TX_HDR_LEN;
1422 QDF_IPA_IOC_ADD_HDR_TYPE(ipa_hdr) = IPA_HDR_L2_ETHERNET_II;
1423 QDF_IPA_IOC_ADD_HDR_IS_PARTIAL(ipa_hdr) = 1;
1424 QDF_IPA_IOC_ADD_HDR_HDR_HDL(ipa_hdr) = 0;
1425 QDF_IPA_IOC_ADD_HDR_IS_ETH2_OFST_VALID(ipa_hdr) = 1;
1426 QDF_IPA_IOC_ADD_HDR_ETH2_OFST(ipa_hdr) =
1427 OL_TXRX_IPA_UC_WLAN_HDR_DES_MAC_OFFSET;
1428
1429 ret = qdf_ipa_add_hdr(ipa_hdr);
1430 if (ret) {
1431 QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
1432 "%s IPv4 add hdr failed: %d", ifname, ret);
1433 goto end;
1434 }
1435
1436 QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_DEBUG,
1437 "%s: IPv4 hdr_hdl: 0x%x",
1438 QDF_IPA_IOC_ADD_HDR_NAME(ipa_hdr),
1439 QDF_IPA_IOC_ADD_HDR_HDR_HDL(ipa_hdr));
1440
1441 if (is_ipv6_enabled) {
1442 snprintf(QDF_IPA_IOC_ADD_HDR_NAME(ipa_hdr),
1443 IPA_RESOURCE_NAME_MAX, "%s%s",
1444 ifname, OL_TXRX_IPA_IPV6_NAME_EXT);
1445
1446 uc_tx_hdr = (struct ol_txrx_ipa_uc_tx_hdr *)
1447 QDF_IPA_IOC_ADD_HDR_HDR(ipa_hdr);
1448 uc_tx_hdr->eth.h_proto = cpu_to_be16(ETH_P_IPV6);
1449
1450 ret = qdf_ipa_add_hdr(ipa_hdr);
1451 if (ret) {
1452 QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
1453 "%s: IPv6 add hdr failed: %d", ifname, ret);
1454 goto clean_ipv4_hdr;
1455 }
1456
1457 QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_DEBUG,
1458 "%s: IPv6 hdr_hdl: 0x%x",
1459 QDF_IPA_IOC_ADD_HDR_NAME(ipa_hdr),
1460 QDF_IPA_IOC_ADD_HDR_HDR_HDL(ipa_hdr));
1461 }
1462
1463 qdf_mem_free(ipa_hdr);
1464
1465 return ret;
1466
1467 clean_ipv4_hdr:
1468 snprintf(ipa_hdr->hdr[0].name, IPA_RESOURCE_NAME_MAX, "%s%s",
1469 ifname, OL_TXRX_IPA_IPV4_NAME_EXT);
1470 ol_txrx_ipa_remove_header(ipa_hdr->hdr[0].name);
1471 end:
1472 if (ipa_hdr)
1473 qdf_mem_free(ipa_hdr);
1474
1475 return ret;
1476 }
1477
1478 /**
1479 * ol_txrx_ipa_register_interface() - register IPA interface
1480 * @ifname: Interface name
1481 * @prod_client: IPA prod client type
1482 * @cons_client: IPA cons client type
1483 * @session_id: Session ID
1484 * @is_ipv6_enabled: Is IPV6 enabled or not
1485 *
1486 * Return: 0 on success, negative errno on error
1487 */
ol_txrx_ipa_register_interface(char * ifname,qdf_ipa_client_type_t prod_client,qdf_ipa_client_type_t cons_client,uint8_t session_id,bool is_ipv6_enabled)1488 static int ol_txrx_ipa_register_interface(char *ifname,
1489 qdf_ipa_client_type_t prod_client,
1490 qdf_ipa_client_type_t cons_client,
1491 uint8_t session_id,
1492 bool is_ipv6_enabled)
1493 {
1494 qdf_ipa_tx_intf_t tx_intf;
1495 qdf_ipa_rx_intf_t rx_intf;
1496 qdf_ipa_ioc_tx_intf_prop_t *tx_prop = NULL;
1497 qdf_ipa_ioc_rx_intf_prop_t *rx_prop = NULL;
1498
1499 char ipv4_hdr_name[IPA_RESOURCE_NAME_MAX];
1500 char ipv6_hdr_name[IPA_RESOURCE_NAME_MAX];
1501
1502 int num_prop = 1;
1503 int ret = 0;
1504
1505 if (is_ipv6_enabled)
1506 num_prop++;
1507
1508 /* Allocate TX properties for TOS categories, 1 each for IPv4 & IPv6 */
1509 tx_prop =
1510 qdf_mem_malloc(sizeof(qdf_ipa_ioc_tx_intf_prop_t) * num_prop);
1511 if (!tx_prop)
1512 goto register_interface_fail;
1513
1514 /* Allocate RX properties, 1 each for IPv4 & IPv6 */
1515 rx_prop =
1516 qdf_mem_malloc(sizeof(qdf_ipa_ioc_rx_intf_prop_t) * num_prop);
1517 if (!rx_prop)
1518 goto register_interface_fail;
1519
1520 qdf_mem_zero(&tx_intf, sizeof(tx_intf));
1521 qdf_mem_zero(&rx_intf, sizeof(rx_intf));
1522
1523 snprintf(ipv4_hdr_name, IPA_RESOURCE_NAME_MAX, "%s%s",
1524 ifname, OL_TXRX_IPA_IPV4_NAME_EXT);
1525 snprintf(ipv6_hdr_name, IPA_RESOURCE_NAME_MAX, "%s%s",
1526 ifname, OL_TXRX_IPA_IPV6_NAME_EXT);
1527
1528 QDF_IPA_IOC_RX_INTF_PROP_IP(&rx_prop[IPA_IP_v4]) = IPA_IP_v4;
1529 QDF_IPA_IOC_RX_INTF_PROP_SRC_PIPE(&rx_prop[IPA_IP_v4]) = prod_client;
1530 QDF_IPA_IOC_RX_INTF_PROP_HDR_L2_TYPE(&rx_prop[IPA_IP_v4]) =
1531 IPA_HDR_L2_ETHERNET_II;
1532 QDF_IPA_IOC_RX_INTF_PROP_ATTRIB_MASK(&rx_prop[IPA_IP_v4]) =
1533 IPA_FLT_META_DATA;
1534
1535 /*
1536 * Interface ID is 3rd byte in the CLD header. Add the meta data and
1537 * mask to identify the interface in IPA hardware
1538 */
1539 QDF_IPA_IOC_RX_INTF_PROP_META_DATA(&rx_prop[IPA_IP_v4]) =
1540 htonl(session_id << 16);
1541 QDF_IPA_IOC_RX_INTF_PROP_META_DATA_MASK(&rx_prop[IPA_IP_v4]) =
1542 htonl(0x00FF0000);
1543
1544 rx_intf.num_props++;
1545 if (is_ipv6_enabled) {
1546 QDF_IPA_IOC_RX_INTF_PROP_IP(&rx_prop[IPA_IP_v6]) = IPA_IP_v6;
1547 QDF_IPA_IOC_RX_INTF_PROP_SRC_PIPE(&rx_prop[IPA_IP_v6]) =
1548 prod_client;
1549 QDF_IPA_IOC_RX_INTF_PROP_HDR_L2_TYPE(&rx_prop[IPA_IP_v6]) =
1550 IPA_HDR_L2_ETHERNET_II;
1551 QDF_IPA_IOC_RX_INTF_PROP_ATTRIB_MASK(&rx_prop[IPA_IP_v6]) =
1552 IPA_FLT_META_DATA;
1553 QDF_IPA_IOC_RX_INTF_PROP_META_DATA(&rx_prop[IPA_IP_v6]) =
1554 htonl(session_id << 16);
1555 QDF_IPA_IOC_RX_INTF_PROP_META_DATA_MASK(&rx_prop[IPA_IP_v6]) =
1556 htonl(0x00FF0000);
1557
1558 rx_intf.num_props++;
1559 }
1560
1561 QDF_IPA_IOC_TX_INTF_PROP_IP(&tx_prop[IPA_IP_v4]) = IPA_IP_v4;
1562 QDF_IPA_IOC_TX_INTF_PROP_HDR_L2_TYPE(&tx_prop[IPA_IP_v4]) =
1563 IPA_HDR_L2_ETHERNET_II;
1564 QDF_IPA_IOC_TX_INTF_PROP_DST_PIPE(&tx_prop[IPA_IP_v4]) =
1565 IPA_CLIENT_WLAN1_CONS;
1566 QDF_IPA_IOC_TX_INTF_PROP_ALT_DST_PIPE(&tx_prop[IPA_IP_v4]) =
1567 cons_client;
1568 strlcpy(QDF_IPA_IOC_TX_INTF_PROP_HDR_NAME(&tx_prop[IPA_IP_v4]),
1569 ipv4_hdr_name, IPA_RESOURCE_NAME_MAX);
1570 tx_intf.num_props++;
1571
1572 if (is_ipv6_enabled) {
1573 QDF_IPA_IOC_TX_INTF_PROP_IP(&tx_prop[IPA_IP_v6]) = IPA_IP_v6;
1574 QDF_IPA_IOC_TX_INTF_PROP_HDR_L2_TYPE(&tx_prop[IPA_IP_v6]) =
1575 IPA_HDR_L2_ETHERNET_II;
1576 QDF_IPA_IOC_TX_INTF_PROP_DST_PIPE(&tx_prop[IPA_IP_v6]) =
1577 IPA_CLIENT_WLAN1_CONS;
1578 QDF_IPA_IOC_TX_INTF_PROP_ALT_DST_PIPE(&tx_prop[IPA_IP_v6]) =
1579 cons_client;
1580 strlcpy(QDF_IPA_IOC_TX_INTF_PROP_HDR_NAME(&tx_prop[IPA_IP_v6]),
1581 ipv6_hdr_name, IPA_RESOURCE_NAME_MAX);
1582 tx_intf.num_props++;
1583 }
1584
1585 QDF_IPA_TX_INTF_PROP(&tx_intf) = tx_prop;
1586 QDF_IPA_RX_INTF_PROP(&rx_intf) = rx_prop;
1587
1588 /* Call the ipa api to register interface */
1589 ret = qdf_ipa_register_intf(ifname, &tx_intf, &rx_intf);
1590
1591 register_interface_fail:
1592 qdf_mem_free(tx_prop);
1593 qdf_mem_free(rx_prop);
1594 return ret;
1595 }
1596
1597 /**
1598 * ol_txrx_ipa_setup_iface() - Setup IPA header and register interface
1599 * @ifname: Interface name
1600 * @mac_addr: Interface MAC address
1601 * @prod_client: IPA prod client type
1602 * @cons_client: IPA cons client type
1603 * @session_id: Session ID
1604 * @is_ipv6_enabled: Is IPV6 enabled or not
1605 *
1606 * Return: QDF_STATUS
1607 */
ol_txrx_ipa_setup_iface(char * ifname,uint8_t * mac_addr,qdf_ipa_client_type_t prod_client,qdf_ipa_client_type_t cons_client,uint8_t session_id,bool is_ipv6_enabled)1608 QDF_STATUS ol_txrx_ipa_setup_iface(char *ifname, uint8_t *mac_addr,
1609 qdf_ipa_client_type_t prod_client,
1610 qdf_ipa_client_type_t cons_client,
1611 uint8_t session_id, bool is_ipv6_enabled)
1612 {
1613 int ret;
1614
1615 ret = ol_txrx_ipa_add_header_info(ifname, mac_addr, session_id,
1616 is_ipv6_enabled);
1617 if (ret)
1618 return QDF_STATUS_E_FAILURE;
1619
1620 /* Configure the TX and RX pipes filter rules */
1621 ret = ol_txrx_ipa_register_interface(ifname,
1622 prod_client,
1623 cons_client,
1624 session_id, is_ipv6_enabled);
1625 if (ret)
1626 return QDF_STATUS_E_FAILURE;
1627
1628 return QDF_STATUS_SUCCESS;
1629 }
1630
1631 /**
1632 * ol_txrx_ipa_cleanup_iface() - Cleanup IPA header and deregister interface
1633 * @ifname: Interface name
1634 * @is_ipv6_enabled: Is IPV6 enabled or not
1635 *
1636 * Return: QDF_STATUS
1637 */
ol_txrx_ipa_cleanup_iface(char * ifname,bool is_ipv6_enabled)1638 QDF_STATUS ol_txrx_ipa_cleanup_iface(char *ifname, bool is_ipv6_enabled)
1639 {
1640 char name_ipa[IPA_RESOURCE_NAME_MAX];
1641 int ret;
1642
1643 /* Remove the headers */
1644 snprintf(name_ipa, IPA_RESOURCE_NAME_MAX, "%s%s",
1645 ifname, OL_TXRX_IPA_IPV4_NAME_EXT);
1646 ol_txrx_ipa_remove_header(name_ipa);
1647
1648 if (is_ipv6_enabled) {
1649 snprintf(name_ipa, IPA_RESOURCE_NAME_MAX, "%s%s",
1650 ifname, OL_TXRX_IPA_IPV6_NAME_EXT);
1651 ol_txrx_ipa_remove_header(name_ipa);
1652 }
1653 /* unregister the interface with IPA */
1654 ret = qdf_ipa_deregister_intf(ifname);
1655 if (ret) {
1656 QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_DEBUG,
1657 "%s: ipa_deregister_intf fail: %d",
1658 ifname, ret);
1659 return QDF_STATUS_E_FAILURE;
1660 }
1661
1662 return QDF_STATUS_SUCCESS;
1663 }
1664
ol_txrx_ipa_enable_pipes(struct cdp_soc_t * soc_hdl,uint8_t pdev_id)1665 QDF_STATUS ol_txrx_ipa_enable_pipes(struct cdp_soc_t *soc_hdl, uint8_t pdev_id)
1666 {
1667 struct ol_txrx_soc_t *soc = cdp_soc_t_to_ol_txrx_soc_t(soc_hdl);
1668 ol_txrx_pdev_handle pdev = ol_txrx_get_pdev_from_pdev_id(soc, pdev_id);
1669 struct ol_txrx_ipa_resources *ipa_res;
1670 int result;
1671 QDF_STATUS status;
1672
1673 if (!pdev) {
1674 ol_txrx_err("Invalid instance");
1675 return QDF_STATUS_E_FAILURE;
1676 }
1677
1678 ipa_res = &pdev->ipa_resource;
1679 status = htt_rx_update_smmu_map(pdev->htt_pdev, true);
1680 if (status != QDF_STATUS_SUCCESS) {
1681 QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
1682 "IPA SMMU map failed status:%d", status);
1683 return status;
1684 }
1685
1686 /* ACTIVATE TX PIPE */
1687 QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_DEBUG,
1688 "%s: Enable TX PIPE(tx_pipe_handle=%d)",
1689 __func__, ipa_res->tx_pipe_handle);
1690 result = qdf_ipa_enable_wdi_pipe(ipa_res->tx_pipe_handle);
1691 if (result) {
1692 QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
1693 "%s: Enable TX PIPE fail, code %d",
1694 __func__, result);
1695 goto smmu_unmap;
1696 }
1697 result = qdf_ipa_resume_wdi_pipe(ipa_res->tx_pipe_handle);
1698 if (result) {
1699 QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
1700 "%s: Resume TX PIPE fail, code %d",
1701 __func__, result);
1702 goto smmu_unmap;
1703 }
1704 ol_txrx_ipa_uc_set_active(soc_hdl, pdev_id, true, true);
1705
1706 /* ACTIVATE RX PIPE */
1707 QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_DEBUG,
1708 "%s: Enable RX PIPE(rx_pipe_handle=%d)",
1709 __func__, ipa_res->rx_pipe_handle);
1710 result = qdf_ipa_enable_wdi_pipe(ipa_res->rx_pipe_handle);
1711 if (result) {
1712 QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
1713 "%s: Enable RX PIPE fail, code %d",
1714 __func__, result);
1715 goto smmu_unmap;
1716 }
1717 result = qdf_ipa_resume_wdi_pipe(ipa_res->rx_pipe_handle);
1718 if (result) {
1719 QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
1720 "%s: Resume RX PIPE fail, code %d",
1721 __func__, result);
1722 goto smmu_unmap;
1723 }
1724 ol_txrx_ipa_uc_set_active(soc_hdl, pdev_id, true, false);
1725
1726 return QDF_STATUS_SUCCESS;
1727
1728 smmu_unmap:
1729 if (htt_rx_update_smmu_map(pdev->htt_pdev, false) !=
1730 QDF_STATUS_SUCCESS) {
1731 QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
1732 "IPA SMMU unmap failed");
1733 }
1734
1735 return QDF_STATUS_E_FAILURE;
1736 }
1737
ol_txrx_ipa_disable_pipes(struct cdp_soc_t * soc_hdl,uint8_t pdev_id)1738 QDF_STATUS ol_txrx_ipa_disable_pipes(struct cdp_soc_t *soc_hdl, uint8_t pdev_id)
1739 {
1740 struct ol_txrx_soc_t *soc = cdp_soc_t_to_ol_txrx_soc_t(soc_hdl);
1741 ol_txrx_pdev_handle pdev = ol_txrx_get_pdev_from_pdev_id(soc, pdev_id);
1742 struct ol_txrx_ipa_resources *ipa_res;
1743 int result;
1744
1745 if (!pdev) {
1746 ol_txrx_err("Invalid instance");
1747 return QDF_STATUS_E_FAILURE;
1748 }
1749
1750 ipa_res = &pdev->ipa_resource;
1751 QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_DEBUG,
1752 "%s: Disable RX PIPE", __func__);
1753 result = qdf_ipa_suspend_wdi_pipe(ipa_res->rx_pipe_handle);
1754 if (result) {
1755 QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
1756 "%s: Suspend RX PIPE fail, code %d",
1757 __func__, result);
1758 goto smmu_unmap;
1759 }
1760
1761 result = qdf_ipa_disable_wdi_pipe(ipa_res->rx_pipe_handle);
1762 if (result) {
1763 QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
1764 "%s: Disable RX PIPE fail, code %d",
1765 __func__, result);
1766 goto smmu_unmap;
1767 }
1768
1769 QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_DEBUG,
1770 "%s: Disable TX PIPE", __func__);
1771 result = qdf_ipa_suspend_wdi_pipe(ipa_res->tx_pipe_handle);
1772 if (result) {
1773 QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
1774 "%s: Suspend TX PIPE fail, code %d",
1775 __func__, result);
1776 goto smmu_unmap;
1777 }
1778 result = qdf_ipa_disable_wdi_pipe(ipa_res->tx_pipe_handle);
1779 if (result) {
1780 QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
1781 "%s: Disable TX PIPE fail, code %d",
1782 __func__, result);
1783 goto smmu_unmap;
1784 }
1785
1786 smmu_unmap:
1787 if (htt_rx_update_smmu_map(pdev->htt_pdev, false) !=
1788 QDF_STATUS_SUCCESS) {
1789 QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
1790 "IPA SMMU unmap failed");
1791 }
1792
1793 return result ? QDF_STATUS_E_FAILURE : QDF_STATUS_SUCCESS;
1794 }
1795
1796 /**
1797 * ol_txrx_ipa_set_perf_level() - Set IPA clock bandwidth based on data rates
1798 * @client: Client type
1799 * @max_supported_bw_mbps: Maximum bandwidth needed (in Mbps)
1800 *
1801 * Return: QDF_STATUS
1802 */
ol_txrx_ipa_set_perf_level(int client,uint32_t max_supported_bw_mbps)1803 QDF_STATUS ol_txrx_ipa_set_perf_level(int client,
1804 uint32_t max_supported_bw_mbps)
1805 {
1806 qdf_ipa_rm_resource_name_t resource_name;
1807 qdf_ipa_rm_perf_profile_t profile;
1808 int result;
1809
1810 if (client == QDF_IPA_CLIENT_WLAN1_PROD) {
1811 resource_name = QDF_IPA_RM_RESOURCE_WLAN_PROD;
1812 } else if (client == QDF_IPA_CLIENT_WLAN1_CONS) {
1813 resource_name = QDF_IPA_RM_RESOURCE_WLAN_CONS;
1814 } else {
1815 QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
1816 "not supported client %d", client);
1817 return QDF_STATUS_E_FAILURE;
1818 }
1819
1820 QDF_IPA_RM_PERF_PROFILE_MAX_SUPPORTED_BANDWIDTH_MBPS(&profile) =
1821 max_supported_bw_mbps;
1822 result = qdf_ipa_rm_set_perf_profile(resource_name, &profile);
1823
1824 if (result) {
1825 QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
1826 "Set perf profile failed, code %d", result);
1827
1828 return QDF_STATUS_E_FAILURE;
1829 }
1830
1831 return QDF_STATUS_SUCCESS;
1832 }
1833
1834 #endif /* CONFIG_IPA_WDI_UNIFIED_API */
1835
1836 #ifdef FEATURE_METERING
ol_txrx_ipa_uc_get_share_stats(struct cdp_soc_t * soc_hdl,uint8_t pdev_id,uint8_t reset_stats)1837 QDF_STATUS ol_txrx_ipa_uc_get_share_stats(struct cdp_soc_t *soc_hdl,
1838 uint8_t pdev_id, uint8_t reset_stats)
1839 {
1840 struct ol_txrx_soc_t *soc = cdp_soc_t_to_ol_txrx_soc_t(soc_hdl);
1841 ol_txrx_pdev_handle pdev = ol_txrx_get_pdev_from_pdev_id(soc, pdev_id);
1842 int result;
1843
1844 if (!pdev) {
1845 ol_txrx_err("Invalid instance");
1846 return QDF_STATUS_E_FAILURE;
1847 }
1848
1849 result = htt_h2t_ipa_uc_get_share_stats(pdev->htt_pdev, reset_stats);
1850
1851 if (result) {
1852 QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
1853 "Get IPA sharing stats failed, code %d", result);
1854 return QDF_STATUS_E_FAILURE;
1855 }
1856
1857 return QDF_STATUS_SUCCESS;
1858 }
1859
ol_txrx_ipa_uc_set_quota(struct cdp_soc_t * soc_hdl,uint8_t pdev_id,uint64_t quota_bytes)1860 QDF_STATUS ol_txrx_ipa_uc_set_quota(struct cdp_soc_t *soc_hdl, uint8_t pdev_id,
1861 uint64_t quota_bytes)
1862 {
1863 struct ol_txrx_soc_t *soc = cdp_soc_t_to_ol_txrx_soc_t(soc_hdl);
1864 ol_txrx_pdev_handle pdev = ol_txrx_get_pdev_from_pdev_id(soc, pdev_id);
1865 int result;
1866
1867 if (!pdev) {
1868 ol_txrx_err("Invalid instance");
1869 return QDF_STATUS_E_FAILURE;
1870 }
1871
1872 result = htt_h2t_ipa_uc_set_quota(pdev->htt_pdev, quota_bytes);
1873
1874 if (result) {
1875 QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
1876 "Set IPA quota failed, code %d", result);
1877 return QDF_STATUS_E_FAILURE;
1878 }
1879
1880 return QDF_STATUS_SUCCESS;
1881 }
1882 #endif
1883 #endif /* IPA_UC_OFFLOAD */
1884