blob: 71df7a253766b9d0d156a9cb48504fc7eb12394b [file] [log] [blame]
Yun Parkfde6b9e2017-06-26 17:13:11 -07001/*
Sravan Kumar Kairamfc3c8cf2018-11-19 18:32:50 +05302 * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
Yun Parkfde6b9e2017-06-26 17:13:11 -07003 *
Yun Parke56aa7b2017-08-16 11:45:56 -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 Parkfde6b9e2017-06-26 17:13:11 -07007 *
Yun Parke56aa7b2017-08-16 11:45:56 -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.
15 */
Yun Parkfde6b9e2017-06-26 17:13:11 -070016
17#ifdef IPA_OFFLOAD
18
Yun Parkfd269b52017-10-05 14:41:32 -070019#include <qdf_ipa_wdi3.h>
Yun Parkfde6b9e2017-06-26 17:13:11 -070020#include <qdf_types.h>
21#include <qdf_lock.h>
Balamurugan Mahalingamf72cb1f2018-06-25 12:18:34 +053022#include <hal_hw_headers.h>
Yun Parkfde6b9e2017-06-26 17:13:11 -070023#include <hal_api.h>
24#include <hif.h>
25#include <htt.h>
26#include <wdi_event.h>
27#include <queue.h>
28#include "dp_types.h"
Yun Park601d0d82017-08-28 21:49:31 -070029#include "dp_htt.h"
Yun Parkfde6b9e2017-06-26 17:13:11 -070030#include "dp_tx.h"
jiad3b8104b2019-03-08 17:23:35 +080031#include "dp_rx.h"
Yun Parkfde6b9e2017-06-26 17:13:11 -070032#include "dp_ipa.h"
33
Yun Park4711ade2017-08-28 21:49:31 -070034/* Hard coded config parameters until dp_ops_cfg.cfg_attach implemented */
35#define CFG_IPA_UC_TX_BUF_SIZE_DEFAULT (2048)
36
jiad3b8104b2019-03-08 17:23:35 +080037static QDF_STATUS __dp_ipa_handle_buf_smmu_mapping(struct dp_soc *soc,
38 qdf_nbuf_t nbuf,
39 bool create)
40{
41 qdf_mem_info_t mem_map_table = {0};
42
43 qdf_update_mem_map_table(soc->osdev, &mem_map_table,
44 qdf_nbuf_get_frag_paddr(nbuf, 0),
45 skb_end_pointer(nbuf) - nbuf->data);
46
47 if (create)
48 qdf_ipa_wdi_create_smmu_mapping(1, &mem_map_table);
49 else
50 qdf_ipa_wdi_release_smmu_mapping(1, &mem_map_table);
51
52 return QDF_STATUS_SUCCESS;
53}
54
55QDF_STATUS dp_ipa_handle_rx_buf_smmu_mapping(struct dp_soc *soc,
56 qdf_nbuf_t nbuf,
57 bool create)
58{
59 bool reo_remapped = false;
60 struct dp_pdev *pdev;
61 int i;
62
63 for (i = 0; i < soc->pdev_count; i++) {
64 pdev = soc->pdev_list[i];
65 if (pdev && pdev->monitor_configured)
66 return QDF_STATUS_SUCCESS;
67 }
68
69 if (!wlan_cfg_is_ipa_enabled(soc->wlan_cfg_ctx) ||
70 !qdf_mem_smmu_s1_enabled(soc->osdev))
71 return QDF_STATUS_SUCCESS;
72
73 qdf_spin_lock_bh(&soc->remap_lock);
74 reo_remapped = soc->reo_remapped;
75 qdf_spin_unlock_bh(&soc->remap_lock);
76
77 if (!reo_remapped)
78 return QDF_STATUS_SUCCESS;
79
80 return __dp_ipa_handle_buf_smmu_mapping(soc, nbuf, create);
81}
82
83static QDF_STATUS dp_ipa_handle_rx_buf_pool_smmu_mapping(struct dp_soc *soc,
84 struct dp_pdev *pdev,
85 bool create)
86{
87 struct rx_desc_pool *rx_pool;
88 uint8_t pdev_id;
89 qdf_nbuf_t nbuf;
90 int i;
91
92 if (!qdf_mem_smmu_s1_enabled(soc->osdev))
93 return QDF_STATUS_SUCCESS;
94
95 pdev_id = pdev->pdev_id;
96 rx_pool = &soc->rx_desc_buf[pdev_id];
97
98 qdf_spin_lock_bh(&rx_pool->lock);
99 for (i = 0; i < rx_pool->pool_size; i++) {
100 if ((!(rx_pool->array[i].rx_desc.in_use)) ||
101 rx_pool->array[i].rx_desc.unmapped)
102 continue;
103
104 nbuf = rx_pool->array[i].rx_desc.nbuf;
105
106 __dp_ipa_handle_buf_smmu_mapping(soc, nbuf, create);
107 }
108 qdf_spin_unlock_bh(&rx_pool->lock);
109
110 return QDF_STATUS_SUCCESS;
111}
112
Yun Parkfde6b9e2017-06-26 17:13:11 -0700113/**
Yun Park601d0d82017-08-28 21:49:31 -0700114 * dp_tx_ipa_uc_detach - Free autonomy TX resources
115 * @soc: data path instance
116 * @pdev: core txrx pdev context
117 *
118 * Free allocated TX buffers with WBM SRNG
119 *
120 * Return: none
121 */
122static void dp_tx_ipa_uc_detach(struct dp_soc *soc, struct dp_pdev *pdev)
123{
124 int idx;
Mohit Khanna81179cb2018-08-16 20:50:43 -0700125 qdf_nbuf_t nbuf;
jiad3b8104b2019-03-08 17:23:35 +0800126 struct dp_ipa_resources *ipa_res;
Yun Park601d0d82017-08-28 21:49:31 -0700127
128 for (idx = 0; idx < soc->ipa_uc_tx_rsc.alloc_tx_buf_cnt; idx++) {
Mohit Khanna81179cb2018-08-16 20:50:43 -0700129 nbuf = (qdf_nbuf_t)
130 soc->ipa_uc_tx_rsc.tx_buf_pool_vaddr_unaligned[idx];
131 if (!nbuf)
132 continue;
jiad3b8104b2019-03-08 17:23:35 +0800133
134 if (qdf_mem_smmu_s1_enabled(soc->osdev))
135 __dp_ipa_handle_buf_smmu_mapping(soc, nbuf, false);
136
Mohit Khanna81179cb2018-08-16 20:50:43 -0700137 qdf_nbuf_unmap_single(soc->osdev, nbuf, QDF_DMA_BIDIRECTIONAL);
138 qdf_nbuf_free(nbuf);
139 soc->ipa_uc_tx_rsc.tx_buf_pool_vaddr_unaligned[idx] =
140 (void *)NULL;
Yun Park601d0d82017-08-28 21:49:31 -0700141 }
142
Yun Park4711ade2017-08-28 21:49:31 -0700143 qdf_mem_free(soc->ipa_uc_tx_rsc.tx_buf_pool_vaddr_unaligned);
144 soc->ipa_uc_tx_rsc.tx_buf_pool_vaddr_unaligned = NULL;
jiad3b8104b2019-03-08 17:23:35 +0800145
146 ipa_res = &pdev->ipa_resource;
147 iounmap(ipa_res->tx_comp_doorbell_vaddr);
148
149 qdf_mem_free_sgtable(&ipa_res->tx_ring.sgtable);
150 qdf_mem_free_sgtable(&ipa_res->tx_comp_ring.sgtable);
Yun Park601d0d82017-08-28 21:49:31 -0700151}
152
153/**
154 * dp_rx_ipa_uc_detach - free autonomy RX resources
155 * @soc: data path instance
156 * @pdev: core txrx pdev context
157 *
158 * This function will detach DP RX into main device context
159 * will free DP Rx resources.
160 *
161 * Return: none
162 */
163static void dp_rx_ipa_uc_detach(struct dp_soc *soc, struct dp_pdev *pdev)
164{
jiad3b8104b2019-03-08 17:23:35 +0800165 struct dp_ipa_resources *ipa_res = &pdev->ipa_resource;
166
167 qdf_mem_free_sgtable(&ipa_res->rx_rdy_ring.sgtable);
168 qdf_mem_free_sgtable(&ipa_res->rx_refill_ring.sgtable);
Yun Park601d0d82017-08-28 21:49:31 -0700169}
170
171int dp_ipa_uc_detach(struct dp_soc *soc, struct dp_pdev *pdev)
172{
jiad3b8104b2019-03-08 17:23:35 +0800173 if (!wlan_cfg_is_ipa_enabled(soc->wlan_cfg_ctx))
174 return QDF_STATUS_SUCCESS;
175
Yun Park601d0d82017-08-28 21:49:31 -0700176 /* TX resource detach */
177 dp_tx_ipa_uc_detach(soc, pdev);
178
179 /* RX resource detach */
180 dp_rx_ipa_uc_detach(soc, pdev);
181
jiad3b8104b2019-03-08 17:23:35 +0800182 qdf_spinlock_destroy(&soc->remap_lock);
183
Yun Park601d0d82017-08-28 21:49:31 -0700184 return QDF_STATUS_SUCCESS; /* success */
185}
186
Yun Park601d0d82017-08-28 21:49:31 -0700187/**
188 * dp_tx_ipa_uc_attach - Allocate autonomy TX resources
189 * @soc: data path instance
190 * @pdev: Physical device handle
191 *
192 * Allocate TX buffer from non-cacheable memory
193 * Attache allocated TX buffers with WBM SRNG
194 *
195 * Return: int
196 */
197static int dp_tx_ipa_uc_attach(struct dp_soc *soc, struct dp_pdev *pdev)
198{
199 uint32_t tx_buffer_count;
200 uint32_t ring_base_align = 8;
Yun Park601d0d82017-08-28 21:49:31 -0700201 qdf_dma_addr_t buffer_paddr;
202 struct hal_srng *wbm_srng =
203 soc->tx_comp_ring[IPA_TX_COMP_RING_IDX].hal_srng;
204 struct hal_srng_params srng_params;
205 uint32_t paddr_lo;
206 uint32_t paddr_hi;
207 void *ring_entry;
208 int num_entries;
Pramod Simhab2ef27b2018-09-14 14:43:19 -0700209 qdf_nbuf_t nbuf;
Yun Park601d0d82017-08-28 21:49:31 -0700210 int retval = QDF_STATUS_SUCCESS;
jiad3b8104b2019-03-08 17:23:35 +0800211
Yun Park601d0d82017-08-28 21:49:31 -0700212 /*
213 * Uncomment when dp_ops_cfg.cfg_attach is implemented
214 * unsigned int uc_tx_buf_sz =
215 * dp_cfg_ipa_uc_tx_buf_size(pdev->osif_pdev);
216 */
217 unsigned int uc_tx_buf_sz = CFG_IPA_UC_TX_BUF_SIZE_DEFAULT;
218 unsigned int alloc_size = uc_tx_buf_sz + ring_base_align - 1;
219
220 hal_get_srng_params(soc->hal_soc, (void *)wbm_srng, &srng_params);
221 num_entries = srng_params.num_entries;
222
Yun Park4711ade2017-08-28 21:49:31 -0700223 QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_INFO,
224 "%s: requested %d buffers to be posted to wbm ring",
225 __func__, num_entries);
Yun Park601d0d82017-08-28 21:49:31 -0700226
Yun Park4711ade2017-08-28 21:49:31 -0700227 soc->ipa_uc_tx_rsc.tx_buf_pool_vaddr_unaligned =
228 qdf_mem_malloc(num_entries *
229 sizeof(*soc->ipa_uc_tx_rsc.tx_buf_pool_vaddr_unaligned));
230 if (!soc->ipa_uc_tx_rsc.tx_buf_pool_vaddr_unaligned) {
Yun Park601d0d82017-08-28 21:49:31 -0700231 QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR,
Yun Park4711ade2017-08-28 21:49:31 -0700232 "%s: IPA WBM Ring Tx buf pool vaddr alloc fail",
233 __func__);
234 return -ENOMEM;
235 }
236
jiadcc43b532019-04-04 11:11:19 +0800237 hal_srng_access_start_unlocked(soc->hal_soc, (void *)wbm_srng);
Yun Park601d0d82017-08-28 21:49:31 -0700238
239 /*
240 * Allocate Tx buffers as many as possible
241 * Populate Tx buffers into WBM2IPA ring
242 * This initial buffer population will simulate H/W as source ring,
243 * and update HP
244 */
245 for (tx_buffer_count = 0;
246 tx_buffer_count < num_entries - 1; tx_buffer_count++) {
Pramod Simhab2ef27b2018-09-14 14:43:19 -0700247 nbuf = qdf_nbuf_alloc(soc->osdev, alloc_size, 0, 256, FALSE);
248 if (!nbuf)
Yun Park601d0d82017-08-28 21:49:31 -0700249 break;
250
251 ring_entry = hal_srng_dst_get_next_hp(soc->hal_soc,
252 (void *)wbm_srng);
253 if (!ring_entry) {
Yun Park4711ade2017-08-28 21:49:31 -0700254 QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_INFO,
Aditya Sathishded018e2018-07-02 16:25:21 +0530255 "%s: Failed to get WBM ring entry",
Yun Park4711ade2017-08-28 21:49:31 -0700256 __func__);
Pramod Simhab2ef27b2018-09-14 14:43:19 -0700257 qdf_nbuf_free(nbuf);
Yun Park4711ade2017-08-28 21:49:31 -0700258 break;
Yun Park601d0d82017-08-28 21:49:31 -0700259 }
260
Pramod Simhab2ef27b2018-09-14 14:43:19 -0700261 qdf_nbuf_map_single(soc->osdev, nbuf,
262 QDF_DMA_BIDIRECTIONAL);
263 buffer_paddr = qdf_nbuf_get_frag_paddr(nbuf, 0);
Yun Park601d0d82017-08-28 21:49:31 -0700264
Krunal Sonibe43d552018-10-03 11:20:20 -0700265 paddr_lo = ((uint64_t)buffer_paddr & 0x00000000ffffffff);
266 paddr_hi = ((uint64_t)buffer_paddr & 0x0000001f00000000) >> 32;
Pramod Simhab2ef27b2018-09-14 14:43:19 -0700267 HAL_RXDMA_PADDR_LO_SET(ring_entry, paddr_lo);
268 HAL_RXDMA_PADDR_HI_SET(ring_entry, paddr_hi);
269 HAL_RXDMA_MANAGER_SET(ring_entry, (IPA_TCL_DATA_RING_IDX +
270 HAL_WBM_SW0_BM_ID));
Yun Park601d0d82017-08-28 21:49:31 -0700271
Yun Park4711ade2017-08-28 21:49:31 -0700272 soc->ipa_uc_tx_rsc.tx_buf_pool_vaddr_unaligned[tx_buffer_count]
Pramod Simhab2ef27b2018-09-14 14:43:19 -0700273 = (void *)nbuf;
jiad3b8104b2019-03-08 17:23:35 +0800274
275 if (qdf_mem_smmu_s1_enabled(soc->osdev))
276 __dp_ipa_handle_buf_smmu_mapping(soc, nbuf, true);
Yun Park601d0d82017-08-28 21:49:31 -0700277 }
278
jiadcc43b532019-04-04 11:11:19 +0800279 hal_srng_access_end_unlocked(soc->hal_soc, wbm_srng);
Yun Park601d0d82017-08-28 21:49:31 -0700280
281 soc->ipa_uc_tx_rsc.alloc_tx_buf_cnt = tx_buffer_count;
282
Yun Park4711ade2017-08-28 21:49:31 -0700283 if (tx_buffer_count) {
284 QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_INFO,
Aditya Sathishded018e2018-07-02 16:25:21 +0530285 "%s: IPA WDI TX buffer: %d allocated",
Yun Park4711ade2017-08-28 21:49:31 -0700286 __func__, tx_buffer_count);
287 } else {
288 QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR,
Aditya Sathishded018e2018-07-02 16:25:21 +0530289 "%s: No IPA WDI TX buffer allocated",
Yun Park4711ade2017-08-28 21:49:31 -0700290 __func__);
291 qdf_mem_free(soc->ipa_uc_tx_rsc.tx_buf_pool_vaddr_unaligned);
292 soc->ipa_uc_tx_rsc.tx_buf_pool_vaddr_unaligned = NULL;
Yun Park4711ade2017-08-28 21:49:31 -0700293 retval = -ENOMEM;
294 }
Yun Park601d0d82017-08-28 21:49:31 -0700295
296 return retval;
Yun Park601d0d82017-08-28 21:49:31 -0700297}
298
299/**
300 * dp_rx_ipa_uc_attach - Allocate autonomy RX resources
301 * @soc: data path instance
302 * @pdev: core txrx pdev context
303 *
304 * This function will attach a DP RX instance into the main
305 * device (SOC) context.
306 *
307 * Return: QDF_STATUS_SUCCESS: success
308 * QDF_STATUS_E_RESOURCES: Error return
309 */
310static int dp_rx_ipa_uc_attach(struct dp_soc *soc, struct dp_pdev *pdev)
311{
312 return QDF_STATUS_SUCCESS;
313}
314
315int dp_ipa_uc_attach(struct dp_soc *soc, struct dp_pdev *pdev)
316{
317 int error;
318
Mohit Khanna81179cb2018-08-16 20:50:43 -0700319 if (!wlan_cfg_is_ipa_enabled(soc->wlan_cfg_ctx))
320 return QDF_STATUS_SUCCESS;
321
jiad3b8104b2019-03-08 17:23:35 +0800322 qdf_spinlock_create(&soc->remap_lock);
323
Yun Park601d0d82017-08-28 21:49:31 -0700324 /* TX resource attach */
325 error = dp_tx_ipa_uc_attach(soc, pdev);
326 if (error) {
327 QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR,
Aditya Sathishded018e2018-07-02 16:25:21 +0530328 "%s: DP IPA UC TX attach fail code %d",
Yun Park4711ade2017-08-28 21:49:31 -0700329 __func__, error);
Yun Park601d0d82017-08-28 21:49:31 -0700330 return error;
331 }
332
333 /* RX resource attach */
334 error = dp_rx_ipa_uc_attach(soc, pdev);
335 if (error) {
336 QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR,
Aditya Sathishded018e2018-07-02 16:25:21 +0530337 "%s: DP IPA UC RX attach fail code %d",
Yun Park4711ade2017-08-28 21:49:31 -0700338 __func__, error);
Yun Park601d0d82017-08-28 21:49:31 -0700339 dp_tx_ipa_uc_detach(soc, pdev);
340 return error;
341 }
342
343 return QDF_STATUS_SUCCESS; /* success */
344}
345
346/*
347 * dp_ipa_ring_resource_setup() - setup IPA ring resources
348 * @soc: data path SoC handle
349 *
350 * Return: none
351 */
352int dp_ipa_ring_resource_setup(struct dp_soc *soc,
353 struct dp_pdev *pdev)
354{
355 struct hal_soc *hal_soc = (struct hal_soc *)soc->hal_soc;
356 struct hal_srng *hal_srng;
357 struct hal_srng_params srng_params;
358 qdf_dma_addr_t hp_addr;
359 unsigned long addr_offset, dev_base_paddr;
360
Mohit Khanna81179cb2018-08-16 20:50:43 -0700361 if (!wlan_cfg_is_ipa_enabled(soc->wlan_cfg_ctx))
362 return QDF_STATUS_SUCCESS;
363
Yun Park601d0d82017-08-28 21:49:31 -0700364 /* IPA TCL_DATA Ring - HAL_SRNG_SW2TCL3 */
365 hal_srng = soc->tcl_data_ring[IPA_TCL_DATA_RING_IDX].hal_srng;
366 hal_get_srng_params(hal_soc, (void *)hal_srng, &srng_params);
367
368 soc->ipa_uc_tx_rsc.ipa_tcl_ring_base_paddr =
369 srng_params.ring_base_paddr;
370 soc->ipa_uc_tx_rsc.ipa_tcl_ring_base_vaddr =
371 srng_params.ring_base_vaddr;
372 soc->ipa_uc_tx_rsc.ipa_tcl_ring_size =
373 (srng_params.num_entries * srng_params.entry_size) << 2;
374 /*
375 * For the register backed memory addresses, use the scn->mem_pa to
376 * calculate the physical address of the shadow registers
377 */
378 dev_base_paddr =
379 (unsigned long)
380 ((struct hif_softc *)(hal_soc->hif_handle))->mem_pa;
381 addr_offset = (unsigned long)(hal_srng->u.src_ring.hp_addr) -
382 (unsigned long)(hal_soc->dev_base_addr);
383 soc->ipa_uc_tx_rsc.ipa_tcl_hp_paddr =
384 (qdf_dma_addr_t)(addr_offset + dev_base_paddr);
385
Mohit Khanna81179cb2018-08-16 20:50:43 -0700386 dp_info("IPA TCL_DATA Ring addr_offset=%x, dev_base_paddr=%x, hp_paddr=%x paddr=%pK vaddr=%pK size= %u(%u bytes)",
387 (unsigned int)addr_offset,
Yun Park601d0d82017-08-28 21:49:31 -0700388 (unsigned int)dev_base_paddr,
Mohit Khanna81179cb2018-08-16 20:50:43 -0700389 (unsigned int)(soc->ipa_uc_tx_rsc.ipa_tcl_hp_paddr),
390 (void *)soc->ipa_uc_tx_rsc.ipa_tcl_ring_base_paddr,
391 (void *)soc->ipa_uc_tx_rsc.ipa_tcl_ring_base_vaddr,
392 srng_params.num_entries,
393 soc->ipa_uc_tx_rsc.ipa_tcl_ring_size);
Yun Park601d0d82017-08-28 21:49:31 -0700394
395 /* IPA TX COMP Ring - HAL_SRNG_WBM2SW2_RELEASE */
396 hal_srng = soc->tx_comp_ring[IPA_TX_COMP_RING_IDX].hal_srng;
397 hal_get_srng_params(hal_soc, (void *)hal_srng, &srng_params);
398
399 soc->ipa_uc_tx_rsc.ipa_wbm_ring_base_paddr =
Mohit Khanna81179cb2018-08-16 20:50:43 -0700400 srng_params.ring_base_paddr;
Yun Park601d0d82017-08-28 21:49:31 -0700401 soc->ipa_uc_tx_rsc.ipa_wbm_ring_base_vaddr =
Mohit Khanna81179cb2018-08-16 20:50:43 -0700402 srng_params.ring_base_vaddr;
Yun Park601d0d82017-08-28 21:49:31 -0700403 soc->ipa_uc_tx_rsc.ipa_wbm_ring_size =
404 (srng_params.num_entries * srng_params.entry_size) << 2;
405 addr_offset = (unsigned long)(hal_srng->u.dst_ring.tp_addr) -
406 (unsigned long)(hal_soc->dev_base_addr);
407 soc->ipa_uc_tx_rsc.ipa_wbm_tp_paddr =
408 (qdf_dma_addr_t)(addr_offset + dev_base_paddr);
409
Mohit Khanna81179cb2018-08-16 20:50:43 -0700410 dp_info("IPA TX COMP Ring addr_offset=%x, dev_base_paddr=%x, ipa_wbm_tp_paddr=%x paddr=%pK vaddr=0%pK size= %u(%u bytes)",
411 (unsigned int)addr_offset,
Yun Park601d0d82017-08-28 21:49:31 -0700412 (unsigned int)dev_base_paddr,
Mohit Khanna81179cb2018-08-16 20:50:43 -0700413 (unsigned int)(soc->ipa_uc_tx_rsc.ipa_wbm_tp_paddr),
414 (void *)soc->ipa_uc_tx_rsc.ipa_wbm_ring_base_paddr,
415 (void *)soc->ipa_uc_tx_rsc.ipa_wbm_ring_base_vaddr,
416 srng_params.num_entries,
417 soc->ipa_uc_tx_rsc.ipa_wbm_ring_size);
Yun Park601d0d82017-08-28 21:49:31 -0700418
419 /* IPA REO_DEST Ring - HAL_SRNG_REO2SW4 */
420 hal_srng = soc->reo_dest_ring[IPA_REO_DEST_RING_IDX].hal_srng;
421 hal_get_srng_params(hal_soc, (void *)hal_srng, &srng_params);
422
423 soc->ipa_uc_rx_rsc.ipa_reo_ring_base_paddr =
Mohit Khanna81179cb2018-08-16 20:50:43 -0700424 srng_params.ring_base_paddr;
Yun Park601d0d82017-08-28 21:49:31 -0700425 soc->ipa_uc_rx_rsc.ipa_reo_ring_base_vaddr =
Mohit Khanna81179cb2018-08-16 20:50:43 -0700426 srng_params.ring_base_vaddr;
Yun Park601d0d82017-08-28 21:49:31 -0700427 soc->ipa_uc_rx_rsc.ipa_reo_ring_size =
428 (srng_params.num_entries * srng_params.entry_size) << 2;
429 addr_offset = (unsigned long)(hal_srng->u.dst_ring.tp_addr) -
430 (unsigned long)(hal_soc->dev_base_addr);
431 soc->ipa_uc_rx_rsc.ipa_reo_tp_paddr =
432 (qdf_dma_addr_t)(addr_offset + dev_base_paddr);
433
Mohit Khanna81179cb2018-08-16 20:50:43 -0700434 dp_info("IPA REO_DEST Ring addr_offset=%x, dev_base_paddr=%x, tp_paddr=%x paddr=%pK vaddr=%pK size= %u(%u bytes)",
435 (unsigned int)addr_offset,
Yun Park601d0d82017-08-28 21:49:31 -0700436 (unsigned int)dev_base_paddr,
Mohit Khanna81179cb2018-08-16 20:50:43 -0700437 (unsigned int)(soc->ipa_uc_rx_rsc.ipa_reo_tp_paddr),
438 (void *)soc->ipa_uc_rx_rsc.ipa_reo_ring_base_paddr,
439 (void *)soc->ipa_uc_rx_rsc.ipa_reo_ring_base_vaddr,
440 srng_params.num_entries,
441 soc->ipa_uc_rx_rsc.ipa_reo_ring_size);
Yun Park601d0d82017-08-28 21:49:31 -0700442
443 hal_srng = pdev->rx_refill_buf_ring2.hal_srng;
444 hal_get_srng_params(hal_soc, (void *)hal_srng, &srng_params);
445 soc->ipa_uc_rx_rsc.ipa_rx_refill_buf_ring_base_paddr =
446 srng_params.ring_base_paddr;
447 soc->ipa_uc_rx_rsc.ipa_rx_refill_buf_ring_base_vaddr =
448 srng_params.ring_base_vaddr;
449 soc->ipa_uc_rx_rsc.ipa_rx_refill_buf_ring_size =
450 (srng_params.num_entries * srng_params.entry_size) << 2;
451 hp_addr = hal_srng_get_hp_addr(hal_soc, (void *)hal_srng);
jiad3b8104b2019-03-08 17:23:35 +0800452 soc->ipa_uc_rx_rsc.ipa_rx_refill_buf_hp_paddr =
453 qdf_mem_paddr_from_dmaaddr(soc->osdev, hp_addr);
Yun Park601d0d82017-08-28 21:49:31 -0700454
Mohit Khanna81179cb2018-08-16 20:50:43 -0700455 dp_info("IPA REFILL_BUF Ring hp_paddr=%x paddr=%pK vaddr=%pK size= %u(%u bytes)",
456 (unsigned int)(soc->ipa_uc_rx_rsc.ipa_rx_refill_buf_hp_paddr),
457 (void *)soc->ipa_uc_rx_rsc.ipa_rx_refill_buf_ring_base_paddr,
458 (void *)soc->ipa_uc_rx_rsc.ipa_rx_refill_buf_ring_base_vaddr,
459 srng_params.num_entries,
460 soc->ipa_uc_rx_rsc.ipa_rx_refill_buf_ring_size);
Yun Park601d0d82017-08-28 21:49:31 -0700461
462 return 0;
463}
464
jiad3b8104b2019-03-08 17:23:35 +0800465static QDF_STATUS dp_ipa_get_shared_mem_info(qdf_device_t osdev,
466 qdf_shared_mem_t *shared_mem,
467 void *cpu_addr,
468 qdf_dma_addr_t dma_addr,
469 uint32_t size)
470{
471 qdf_dma_addr_t paddr;
472 int ret;
473
474 shared_mem->vaddr = cpu_addr;
475 qdf_mem_set_dma_size(osdev, &shared_mem->mem_info, size);
476 *qdf_mem_get_dma_addr_ptr(osdev, &shared_mem->mem_info) = dma_addr;
477
478 paddr = qdf_mem_paddr_from_dmaaddr(osdev, dma_addr);
479 qdf_mem_set_dma_pa(osdev, &shared_mem->mem_info, paddr);
480
481 ret = qdf_mem_dma_get_sgtable(osdev->dev, &shared_mem->sgtable,
482 shared_mem->vaddr, dma_addr, size);
483 if (ret) {
484 dp_err("Unable to get DMA sgtable");
485 return QDF_STATUS_E_NOMEM;
486 }
487
488 qdf_dma_get_sgtable_dma_addr(&shared_mem->sgtable);
489
490 return QDF_STATUS_SUCCESS;
491}
492
Yun Park601d0d82017-08-28 21:49:31 -0700493/**
Yun Parkfde6b9e2017-06-26 17:13:11 -0700494 * dp_ipa_uc_get_resource() - Client request resource information
495 * @ppdev - handle to the device instance
496 *
497 * IPA client will request IPA UC related resource information
498 * Resource information will be distributed to IPA module
499 * All of the required resources should be pre-allocated
500 *
501 * Return: QDF_STATUS
502 */
503QDF_STATUS dp_ipa_get_resource(struct cdp_pdev *ppdev)
504{
505 struct dp_pdev *pdev = (struct dp_pdev *)ppdev;
506 struct dp_soc *soc = pdev->soc;
507 struct dp_ipa_resources *ipa_res = &pdev->ipa_resource;
508
Mohit Khanna81179cb2018-08-16 20:50:43 -0700509 if (!wlan_cfg_is_ipa_enabled(soc->wlan_cfg_ctx))
510 return QDF_STATUS_SUCCESS;
511
Yun Parkfde6b9e2017-06-26 17:13:11 -0700512 ipa_res->tx_num_alloc_buffer =
513 (uint32_t)soc->ipa_uc_tx_rsc.alloc_tx_buf_cnt;
514
jiad3b8104b2019-03-08 17:23:35 +0800515 dp_ipa_get_shared_mem_info(soc->osdev, &ipa_res->tx_ring,
516 soc->ipa_uc_tx_rsc.ipa_tcl_ring_base_vaddr,
517 soc->ipa_uc_tx_rsc.ipa_tcl_ring_base_paddr,
518 soc->ipa_uc_tx_rsc.ipa_tcl_ring_size);
Yun Parkfde6b9e2017-06-26 17:13:11 -0700519
jiad3b8104b2019-03-08 17:23:35 +0800520 dp_ipa_get_shared_mem_info(soc->osdev, &ipa_res->tx_comp_ring,
521 soc->ipa_uc_tx_rsc.ipa_wbm_ring_base_vaddr,
522 soc->ipa_uc_tx_rsc.ipa_wbm_ring_base_paddr,
523 soc->ipa_uc_tx_rsc.ipa_wbm_ring_size);
Yun Parkfde6b9e2017-06-26 17:13:11 -0700524
jiad3b8104b2019-03-08 17:23:35 +0800525 dp_ipa_get_shared_mem_info(soc->osdev, &ipa_res->rx_rdy_ring,
526 soc->ipa_uc_rx_rsc.ipa_reo_ring_base_vaddr,
527 soc->ipa_uc_rx_rsc.ipa_reo_ring_base_paddr,
528 soc->ipa_uc_rx_rsc.ipa_reo_ring_size);
Yun Parkfde6b9e2017-06-26 17:13:11 -0700529
jiad3b8104b2019-03-08 17:23:35 +0800530 dp_ipa_get_shared_mem_info(
531 soc->osdev, &ipa_res->rx_refill_ring,
532 soc->ipa_uc_rx_rsc.ipa_rx_refill_buf_ring_base_vaddr,
533 soc->ipa_uc_rx_rsc.ipa_rx_refill_buf_ring_base_paddr,
534 soc->ipa_uc_rx_rsc.ipa_rx_refill_buf_ring_size);
Mohit Khanna81179cb2018-08-16 20:50:43 -0700535
jiad3b8104b2019-03-08 17:23:35 +0800536 if (!qdf_mem_get_dma_addr(soc->osdev,
537 &ipa_res->tx_comp_ring.mem_info) ||
538 !qdf_mem_get_dma_addr(soc->osdev, &ipa_res->rx_rdy_ring.mem_info))
Yun Parkfde6b9e2017-06-26 17:13:11 -0700539 return QDF_STATUS_E_FAILURE;
540
541 return QDF_STATUS_SUCCESS;
542}
543
544/**
545 * dp_ipa_set_doorbell_paddr () - Set doorbell register physical address to SRNG
546 * @ppdev - handle to the device instance
547 *
548 * Set TX_COMP_DOORBELL register physical address to WBM Head_Ptr_MemAddr_LSB
549 * Set RX_READ_DOORBELL register physical address to REO Head_Ptr_MemAddr_LSB
550 *
551 * Return: none
552 */
553QDF_STATUS dp_ipa_set_doorbell_paddr(struct cdp_pdev *ppdev)
554{
555 struct dp_pdev *pdev = (struct dp_pdev *)ppdev;
556 struct dp_soc *soc = pdev->soc;
557 struct dp_ipa_resources *ipa_res = &pdev->ipa_resource;
Yun Park601d0d82017-08-28 21:49:31 -0700558 struct hal_srng *wbm_srng =
559 soc->tx_comp_ring[IPA_TX_COMP_RING_IDX].hal_srng;
560 struct hal_srng *reo_srng =
561 soc->reo_dest_ring[IPA_REO_DEST_RING_IDX].hal_srng;
jiad3b8104b2019-03-08 17:23:35 +0800562 uint32_t tx_comp_doorbell_dmaaddr;
563 uint32_t rx_ready_doorbell_dmaaddr;
Yun Parkfde6b9e2017-06-26 17:13:11 -0700564
Mohit Khanna81179cb2018-08-16 20:50:43 -0700565 if (!wlan_cfg_is_ipa_enabled(soc->wlan_cfg_ctx))
566 return QDF_STATUS_SUCCESS;
Yun Parkfde6b9e2017-06-26 17:13:11 -0700567
Mohit Khanna81179cb2018-08-16 20:50:43 -0700568 ipa_res->tx_comp_doorbell_vaddr =
569 ioremap(ipa_res->tx_comp_doorbell_paddr, 4);
jiad3b8104b2019-03-08 17:23:35 +0800570
571 if (qdf_mem_smmu_s1_enabled(soc->osdev)) {
572 pld_smmu_map(soc->osdev->dev, ipa_res->tx_comp_doorbell_paddr,
573 &tx_comp_doorbell_dmaaddr, sizeof(uint32_t));
574 ipa_res->tx_comp_doorbell_paddr = tx_comp_doorbell_dmaaddr;
575
576 pld_smmu_map(soc->osdev->dev, ipa_res->rx_ready_doorbell_paddr,
577 &rx_ready_doorbell_dmaaddr, sizeof(uint32_t));
578 ipa_res->rx_ready_doorbell_paddr = rx_ready_doorbell_dmaaddr;
579 }
580
581 hal_srng_dst_set_hp_paddr(wbm_srng, ipa_res->tx_comp_doorbell_paddr);
582
Mohit Khanna81179cb2018-08-16 20:50:43 -0700583 dp_info("paddr %pK vaddr %pK",
584 (void *)ipa_res->tx_comp_doorbell_paddr,
585 (void *)ipa_res->tx_comp_doorbell_vaddr);
586
587 hal_srng_dst_init_hp(wbm_srng, ipa_res->tx_comp_doorbell_vaddr);
588
589 /*
590 * For RX, REO module on Napier/Hastings does reordering on incoming
591 * Ethernet packets and writes one or more descriptors to REO2IPA Rx
592 * ring.It then updates the ring’s Write/Head ptr and rings a doorbell
593 * to IPA.
594 * Set the doorbell addr for the REO ring.
595 */
596 hal_srng_dst_set_hp_paddr(reo_srng, ipa_res->rx_ready_doorbell_paddr);
Yun Parkfde6b9e2017-06-26 17:13:11 -0700597 return QDF_STATUS_SUCCESS;
598}
599
600/**
601 * dp_ipa_op_response() - Handle OP command response from firmware
602 * @ppdev - handle to the device instance
603 * @op_msg: op response message from firmware
604 *
605 * Return: none
606 */
607QDF_STATUS dp_ipa_op_response(struct cdp_pdev *ppdev, uint8_t *op_msg)
608{
609 struct dp_pdev *pdev = (struct dp_pdev *)ppdev;
610
Mohit Khanna81179cb2018-08-16 20:50:43 -0700611 if (!wlan_cfg_is_ipa_enabled(pdev->soc->wlan_cfg_ctx))
612 return QDF_STATUS_SUCCESS;
613
Yun Parkfde6b9e2017-06-26 17:13:11 -0700614 if (pdev->ipa_uc_op_cb) {
615 pdev->ipa_uc_op_cb(op_msg, pdev->usr_ctxt);
616 } else {
617 QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
618 "%s: IPA callback function is not registered", __func__);
619 qdf_mem_free(op_msg);
620 return QDF_STATUS_E_FAILURE;
621 }
622
623 return QDF_STATUS_SUCCESS;
624}
625
626/**
627 * dp_ipa_register_op_cb() - Register OP handler function
628 * @ppdev - handle to the device instance
629 * @op_cb: handler function pointer
630 *
631 * Return: none
632 */
633QDF_STATUS dp_ipa_register_op_cb(struct cdp_pdev *ppdev,
634 ipa_uc_op_cb_type op_cb,
635 void *usr_ctxt)
636{
637 struct dp_pdev *pdev = (struct dp_pdev *)ppdev;
638
Mohit Khanna81179cb2018-08-16 20:50:43 -0700639 if (!wlan_cfg_is_ipa_enabled(pdev->soc->wlan_cfg_ctx))
640 return QDF_STATUS_SUCCESS;
641
Yun Parkfde6b9e2017-06-26 17:13:11 -0700642 pdev->ipa_uc_op_cb = op_cb;
643 pdev->usr_ctxt = usr_ctxt;
644
645 return QDF_STATUS_SUCCESS;
646}
647
648/**
649 * dp_ipa_get_stat() - Get firmware wdi status
650 * @ppdev - handle to the device instance
651 *
652 * Return: none
653 */
654QDF_STATUS dp_ipa_get_stat(struct cdp_pdev *ppdev)
655{
656 /* TBD */
657 return QDF_STATUS_SUCCESS;
658}
659
660/**
661 * dp_tx_send_ipa_data_frame() - send IPA data frame
662 * @vdev: vdev
663 * @skb: skb
664 *
665 * Return: skb/ NULL is for success
666 */
667qdf_nbuf_t dp_tx_send_ipa_data_frame(struct cdp_vdev *vdev, qdf_nbuf_t skb)
668{
669 qdf_nbuf_t ret;
670
671 /* Terminate the (single-element) list of tx frames */
672 qdf_nbuf_set_next(skb, NULL);
673 ret = dp_tx_send((struct dp_vdev_t *)vdev, skb);
674 if (ret) {
675 QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
Yun Park4711ade2017-08-28 21:49:31 -0700676 "%s: Failed to tx", __func__);
Yun Parkfde6b9e2017-06-26 17:13:11 -0700677 return ret;
678 }
679
680 return NULL;
681}
682
683/**
684 * dp_ipa_enable_autonomy() – Enable autonomy RX path
685 * @pdev - handle to the device instance
686 *
687 * Set all RX packet route to IPA REO ring
688 * Program Destination_Ring_Ctrl_IX_0 REO register to point IPA REO ring
689 * Return: none
690 */
691QDF_STATUS dp_ipa_enable_autonomy(struct cdp_pdev *ppdev)
692{
693 struct dp_pdev *pdev = (struct dp_pdev *)ppdev;
694 struct dp_soc *soc = pdev->soc;
695 uint32_t remap_val;
696
Mohit Khanna81179cb2018-08-16 20:50:43 -0700697 if (!wlan_cfg_is_ipa_enabled(soc->wlan_cfg_ctx))
698 return QDF_STATUS_SUCCESS;
699
jiad3b8104b2019-03-08 17:23:35 +0800700 qdf_spin_lock_bh(&soc->remap_lock);
701 soc->reo_remapped = true;
702 qdf_spin_unlock_bh(&soc->remap_lock);
703
704 dp_ipa_handle_rx_buf_pool_smmu_mapping(soc, pdev, true);
705
Yun Parkfde6b9e2017-06-26 17:13:11 -0700706 /* Call HAL API to remap REO rings to REO2IPA ring */
707 remap_val = HAL_REO_REMAP_VAL(REO_REMAP_TCL, REO_REMAP_TCL) |
708 HAL_REO_REMAP_VAL(REO_REMAP_SW1, REO_REMAP_SW4) |
709 HAL_REO_REMAP_VAL(REO_REMAP_SW2, REO_REMAP_SW4) |
710 HAL_REO_REMAP_VAL(REO_REMAP_SW3, REO_REMAP_SW4) |
711 HAL_REO_REMAP_VAL(REO_REMAP_SW4, REO_REMAP_SW4) |
712 HAL_REO_REMAP_VAL(REO_REMAP_RELEASE, REO_REMAP_RELEASE) |
713 HAL_REO_REMAP_VAL(REO_REMAP_FW, REO_REMAP_FW) |
714 HAL_REO_REMAP_VAL(REO_REMAP_UNUSED, REO_REMAP_FW);
715 hal_reo_remap_IX0(soc->hal_soc, remap_val);
Yun Parkfde6b9e2017-06-26 17:13:11 -0700716 return QDF_STATUS_SUCCESS;
717}
718
719/**
720 * dp_ipa_disable_autonomy() – Disable autonomy RX path
721 * @ppdev - handle to the device instance
722 *
723 * Disable RX packet routing to IPA REO
724 * Program Destination_Ring_Ctrl_IX_0 REO register to disable
725 * Return: none
726 */
727QDF_STATUS dp_ipa_disable_autonomy(struct cdp_pdev *ppdev)
728{
729 struct dp_pdev *pdev = (struct dp_pdev *)ppdev;
730 struct dp_soc *soc = pdev->soc;
731 uint32_t remap_val;
732
Mohit Khanna81179cb2018-08-16 20:50:43 -0700733 if (!wlan_cfg_is_ipa_enabled(soc->wlan_cfg_ctx))
734 return QDF_STATUS_SUCCESS;
735
Yun Parkfde6b9e2017-06-26 17:13:11 -0700736 /* Call HAL API to remap REO rings to REO2IPA ring */
737 remap_val = HAL_REO_REMAP_VAL(REO_REMAP_TCL, REO_REMAP_TCL) |
738 HAL_REO_REMAP_VAL(REO_REMAP_SW1, REO_REMAP_SW1) |
739 HAL_REO_REMAP_VAL(REO_REMAP_SW2, REO_REMAP_SW2) |
740 HAL_REO_REMAP_VAL(REO_REMAP_SW3, REO_REMAP_SW3) |
741 HAL_REO_REMAP_VAL(REO_REMAP_SW4, REO_REMAP_SW2) |
742 HAL_REO_REMAP_VAL(REO_REMAP_RELEASE, REO_REMAP_RELEASE) |
743 HAL_REO_REMAP_VAL(REO_REMAP_FW, REO_REMAP_FW) |
744 HAL_REO_REMAP_VAL(REO_REMAP_UNUSED, REO_REMAP_FW);
745 hal_reo_remap_IX0(soc->hal_soc, remap_val);
746
jiad3b8104b2019-03-08 17:23:35 +0800747 qdf_spin_lock_bh(&soc->remap_lock);
748 soc->reo_remapped = false;
749 qdf_spin_unlock_bh(&soc->remap_lock);
750
751 dp_ipa_handle_rx_buf_pool_smmu_mapping(soc, pdev, false);
752
Yun Parkfde6b9e2017-06-26 17:13:11 -0700753 return QDF_STATUS_SUCCESS;
754}
755
756/* This should be configurable per H/W configuration enable status */
757#define L3_HEADER_PADDING 2
758
Mohit Khannaf83015c2018-02-13 08:29:39 -0800759#ifdef CONFIG_IPA_WDI_UNIFIED_API
760
761#ifndef QCA_LL_TX_FLOW_CONTROL_V2
762static inline void dp_setup_mcc_sys_pipes(
763 qdf_ipa_sys_connect_params_t *sys_in,
764 qdf_ipa_wdi_conn_in_params_t *pipe_in)
765{
766 /* Setup MCC sys pipe */
767 QDF_IPA_WDI_CONN_IN_PARAMS_NUM_SYS_PIPE_NEEDED(pipe_in) =
768 DP_IPA_MAX_IFACE;
769 for (int i = 0; i < DP_IPA_MAX_IFACE; i++)
770 memcpy(&QDF_IPA_WDI_CONN_IN_PARAMS_SYS_IN(pipe_in)[i],
771 &sys_in[i], sizeof(qdf_ipa_sys_connect_params_t));
772}
773#else
774static inline void dp_setup_mcc_sys_pipes(
775 qdf_ipa_sys_connect_params_t *sys_in,
776 qdf_ipa_wdi_conn_in_params_t *pipe_in)
777{
778 QDF_IPA_WDI_CONN_IN_PARAMS_NUM_SYS_PIPE_NEEDED(pipe_in) = 0;
779}
780#endif
781
jiad3b8104b2019-03-08 17:23:35 +0800782static void dp_ipa_wdi_tx_params(struct dp_soc *soc,
783 struct dp_ipa_resources *ipa_res,
784 qdf_ipa_wdi_pipe_setup_info_t *tx,
785 bool over_gsi)
786{
787 struct tcl_data_cmd *tcl_desc_ptr;
788 uint8_t *desc_addr;
789 uint32_t desc_size;
790
791 if (over_gsi)
792 QDF_IPA_WDI_SETUP_INFO_CLIENT(tx) = IPA_CLIENT_WLAN2_CONS;
793 else
794 QDF_IPA_WDI_SETUP_INFO_CLIENT(tx) = IPA_CLIENT_WLAN1_CONS;
795
796 QDF_IPA_WDI_SETUP_INFO_TRANSFER_RING_BASE_PA(tx) =
797 qdf_mem_get_dma_addr(soc->osdev,
798 &ipa_res->tx_comp_ring.mem_info);
799 QDF_IPA_WDI_SETUP_INFO_TRANSFER_RING_SIZE(tx) =
800 qdf_mem_get_dma_size(soc->osdev,
801 &ipa_res->tx_comp_ring.mem_info);
802
803 /* WBM Tail Pointer Address */
804 QDF_IPA_WDI_SETUP_INFO_TRANSFER_RING_DOORBELL_PA(tx) =
805 soc->ipa_uc_tx_rsc.ipa_wbm_tp_paddr;
jiad443059e2019-03-05 15:26:32 +0800806 QDF_IPA_WDI_SETUP_INFO_IS_TXR_RN_DB_PCIE_ADDR(tx) = true;
jiad3b8104b2019-03-08 17:23:35 +0800807
808 QDF_IPA_WDI_SETUP_INFO_EVENT_RING_BASE_PA(tx) =
809 qdf_mem_get_dma_addr(soc->osdev,
810 &ipa_res->tx_ring.mem_info);
811 QDF_IPA_WDI_SETUP_INFO_EVENT_RING_SIZE(tx) =
812 qdf_mem_get_dma_size(soc->osdev,
813 &ipa_res->tx_ring.mem_info);
814
815 /* TCL Head Pointer Address */
816 QDF_IPA_WDI_SETUP_INFO_EVENT_RING_DOORBELL_PA(tx) =
817 soc->ipa_uc_tx_rsc.ipa_tcl_hp_paddr;
jiad443059e2019-03-05 15:26:32 +0800818 QDF_IPA_WDI_SETUP_INFO_IS_EVT_RN_DB_PCIE_ADDR(tx) = true;
jiad3b8104b2019-03-08 17:23:35 +0800819
820 QDF_IPA_WDI_SETUP_INFO_NUM_PKT_BUFFERS(tx) =
821 ipa_res->tx_num_alloc_buffer;
822
823 QDF_IPA_WDI_SETUP_INFO_PKT_OFFSET(tx) = 0;
824
825 /* Preprogram TCL descriptor */
826 desc_addr =
827 (uint8_t *)QDF_IPA_WDI_SETUP_INFO_DESC_FORMAT_TEMPLATE(tx);
828 desc_size = sizeof(struct tcl_data_cmd);
829 HAL_TX_DESC_SET_TLV_HDR(desc_addr, HAL_TX_TCL_DATA_TAG, desc_size);
830 tcl_desc_ptr = (struct tcl_data_cmd *)
831 (QDF_IPA_WDI_SETUP_INFO_DESC_FORMAT_TEMPLATE(tx) + 1);
832 tcl_desc_ptr->buf_addr_info.return_buffer_manager =
833 HAL_RX_BUF_RBM_SW2_BM;
834 tcl_desc_ptr->addrx_en = 1; /* Address X search enable in ASE */
835 tcl_desc_ptr->encap_type = HAL_TX_ENCAP_TYPE_ETHERNET;
836 tcl_desc_ptr->packet_offset = 2; /* padding for alignment */
837}
838
839static void dp_ipa_wdi_rx_params(struct dp_soc *soc,
840 struct dp_ipa_resources *ipa_res,
841 qdf_ipa_wdi_pipe_setup_info_t *rx,
842 bool over_gsi)
843{
844 if (over_gsi)
845 QDF_IPA_WDI_SETUP_INFO_CLIENT(rx) =
846 IPA_CLIENT_WLAN2_PROD;
847 else
848 QDF_IPA_WDI_SETUP_INFO_CLIENT(rx) =
849 IPA_CLIENT_WLAN1_PROD;
850
851 QDF_IPA_WDI_SETUP_INFO_TRANSFER_RING_BASE_PA(rx) =
852 qdf_mem_get_dma_addr(soc->osdev,
853 &ipa_res->rx_rdy_ring.mem_info);
854 QDF_IPA_WDI_SETUP_INFO_TRANSFER_RING_SIZE(rx) =
855 qdf_mem_get_dma_size(soc->osdev,
856 &ipa_res->rx_rdy_ring.mem_info);
857
858 /* REO Tail Pointer Address */
859 QDF_IPA_WDI_SETUP_INFO_TRANSFER_RING_DOORBELL_PA(rx) =
860 soc->ipa_uc_rx_rsc.ipa_reo_tp_paddr;
jiad443059e2019-03-05 15:26:32 +0800861 QDF_IPA_WDI_SETUP_INFO_IS_TXR_RN_DB_PCIE_ADDR(rx) = true;
jiad3b8104b2019-03-08 17:23:35 +0800862
863 QDF_IPA_WDI_SETUP_INFO_EVENT_RING_BASE_PA(rx) =
864 qdf_mem_get_dma_addr(soc->osdev,
865 &ipa_res->rx_refill_ring.mem_info);
866 QDF_IPA_WDI_SETUP_INFO_EVENT_RING_SIZE(rx) =
867 qdf_mem_get_dma_size(soc->osdev,
868 &ipa_res->rx_refill_ring.mem_info);
869
870 /* FW Head Pointer Address */
871 QDF_IPA_WDI_SETUP_INFO_EVENT_RING_DOORBELL_PA(rx) =
872 soc->ipa_uc_rx_rsc.ipa_rx_refill_buf_hp_paddr;
jiad443059e2019-03-05 15:26:32 +0800873 QDF_IPA_WDI_SETUP_INFO_IS_EVT_RN_DB_PCIE_ADDR(rx) = false;
jiad3b8104b2019-03-08 17:23:35 +0800874
875 QDF_IPA_WDI_SETUP_INFO_PKT_OFFSET(rx) =
876 RX_PKT_TLVS_LEN + L3_HEADER_PADDING;
877}
878
879static void
880dp_ipa_wdi_tx_smmu_params(struct dp_soc *soc,
881 struct dp_ipa_resources *ipa_res,
882 qdf_ipa_wdi_pipe_setup_info_smmu_t *tx_smmu,
883 bool over_gsi)
884{
885 struct tcl_data_cmd *tcl_desc_ptr;
886 uint8_t *desc_addr;
887 uint32_t desc_size;
888
889 if (over_gsi)
890 QDF_IPA_WDI_SETUP_INFO_SMMU_CLIENT(tx_smmu) =
891 IPA_CLIENT_WLAN2_CONS;
892 else
893 QDF_IPA_WDI_SETUP_INFO_SMMU_CLIENT(tx_smmu) =
894 IPA_CLIENT_WLAN1_CONS;
895
896 qdf_mem_copy(&QDF_IPA_WDI_SETUP_INFO_SMMU_TRANSFER_RING_BASE(tx_smmu),
897 &ipa_res->tx_comp_ring.sgtable,
898 sizeof(sgtable_t));
899 QDF_IPA_WDI_SETUP_INFO_SMMU_TRANSFER_RING_SIZE(tx_smmu) =
900 qdf_mem_get_dma_size(soc->osdev,
901 &ipa_res->tx_comp_ring.mem_info);
902 /* WBM Tail Pointer Address */
903 QDF_IPA_WDI_SETUP_INFO_SMMU_TRANSFER_RING_DOORBELL_PA(tx_smmu) =
904 soc->ipa_uc_tx_rsc.ipa_wbm_tp_paddr;
jiad443059e2019-03-05 15:26:32 +0800905 QDF_IPA_WDI_SETUP_INFO_SMMU_IS_TXR_RN_DB_PCIE_ADDR(tx_smmu) = true;
jiad3b8104b2019-03-08 17:23:35 +0800906
907 qdf_mem_copy(&QDF_IPA_WDI_SETUP_INFO_SMMU_EVENT_RING_BASE(tx_smmu),
908 &ipa_res->tx_ring.sgtable,
909 sizeof(sgtable_t));
910 QDF_IPA_WDI_SETUP_INFO_SMMU_EVENT_RING_SIZE(tx_smmu) =
911 qdf_mem_get_dma_size(soc->osdev,
912 &ipa_res->tx_ring.mem_info);
913 /* TCL Head Pointer Address */
914 QDF_IPA_WDI_SETUP_INFO_SMMU_EVENT_RING_DOORBELL_PA(tx_smmu) =
915 soc->ipa_uc_tx_rsc.ipa_tcl_hp_paddr;
jiad443059e2019-03-05 15:26:32 +0800916 QDF_IPA_WDI_SETUP_INFO_SMMU_IS_EVT_RN_DB_PCIE_ADDR(tx_smmu) = true;
jiad3b8104b2019-03-08 17:23:35 +0800917
918 QDF_IPA_WDI_SETUP_INFO_SMMU_NUM_PKT_BUFFERS(tx_smmu) =
919 ipa_res->tx_num_alloc_buffer;
920 QDF_IPA_WDI_SETUP_INFO_SMMU_PKT_OFFSET(tx_smmu) = 0;
921
922 /* Preprogram TCL descriptor */
923 desc_addr = (uint8_t *)QDF_IPA_WDI_SETUP_INFO_SMMU_DESC_FORMAT_TEMPLATE(
924 tx_smmu);
925 desc_size = sizeof(struct tcl_data_cmd);
926 HAL_TX_DESC_SET_TLV_HDR(desc_addr, HAL_TX_TCL_DATA_TAG, desc_size);
927 tcl_desc_ptr = (struct tcl_data_cmd *)
928 (QDF_IPA_WDI_SETUP_INFO_SMMU_DESC_FORMAT_TEMPLATE(tx_smmu) + 1);
929 tcl_desc_ptr->buf_addr_info.return_buffer_manager =
930 HAL_RX_BUF_RBM_SW2_BM;
931 tcl_desc_ptr->addrx_en = 1; /* Address X search enable in ASE */
932 tcl_desc_ptr->encap_type = HAL_TX_ENCAP_TYPE_ETHERNET;
933 tcl_desc_ptr->packet_offset = 2; /* padding for alignment */
934}
935
936static void
937dp_ipa_wdi_rx_smmu_params(struct dp_soc *soc,
938 struct dp_ipa_resources *ipa_res,
939 qdf_ipa_wdi_pipe_setup_info_smmu_t *rx_smmu,
940 bool over_gsi)
941{
942 if (over_gsi)
943 QDF_IPA_WDI_SETUP_INFO_SMMU_CLIENT(rx_smmu) =
944 IPA_CLIENT_WLAN2_PROD;
945 else
946 QDF_IPA_WDI_SETUP_INFO_SMMU_CLIENT(rx_smmu) =
947 IPA_CLIENT_WLAN1_PROD;
948
949 qdf_mem_copy(&QDF_IPA_WDI_SETUP_INFO_SMMU_TRANSFER_RING_BASE(rx_smmu),
950 &ipa_res->rx_rdy_ring.sgtable,
951 sizeof(sgtable_t));
952 QDF_IPA_WDI_SETUP_INFO_SMMU_TRANSFER_RING_SIZE(rx_smmu) =
953 qdf_mem_get_dma_size(soc->osdev,
954 &ipa_res->rx_rdy_ring.mem_info);
955 /* REO Tail Pointer Address */
956 QDF_IPA_WDI_SETUP_INFO_SMMU_TRANSFER_RING_DOORBELL_PA(rx_smmu) =
957 soc->ipa_uc_rx_rsc.ipa_reo_tp_paddr;
jiad443059e2019-03-05 15:26:32 +0800958 QDF_IPA_WDI_SETUP_INFO_SMMU_IS_TXR_RN_DB_PCIE_ADDR(rx_smmu) = true;
jiad3b8104b2019-03-08 17:23:35 +0800959
960 qdf_mem_copy(&QDF_IPA_WDI_SETUP_INFO_SMMU_EVENT_RING_BASE(rx_smmu),
961 &ipa_res->rx_refill_ring.sgtable,
962 sizeof(sgtable_t));
963 QDF_IPA_WDI_SETUP_INFO_SMMU_EVENT_RING_SIZE(rx_smmu) =
964 qdf_mem_get_dma_size(soc->osdev,
965 &ipa_res->rx_refill_ring.mem_info);
966
967 /* FW Head Pointer Address */
968 QDF_IPA_WDI_SETUP_INFO_SMMU_EVENT_RING_DOORBELL_PA(rx_smmu) =
969 soc->ipa_uc_rx_rsc.ipa_rx_refill_buf_hp_paddr;
jiad443059e2019-03-05 15:26:32 +0800970 QDF_IPA_WDI_SETUP_INFO_SMMU_IS_EVT_RN_DB_PCIE_ADDR(rx_smmu) = false;
jiad3b8104b2019-03-08 17:23:35 +0800971
972 QDF_IPA_WDI_SETUP_INFO_SMMU_PKT_OFFSET(rx_smmu) =
973 RX_PKT_TLVS_LEN + L3_HEADER_PADDING;
974}
975
Mohit Khannaf83015c2018-02-13 08:29:39 -0800976/**
977 * dp_ipa_setup() - Setup and connect IPA pipes
978 * @ppdev - handle to the device instance
979 * @ipa_i2w_cb: IPA to WLAN callback
980 * @ipa_w2i_cb: WLAN to IPA callback
981 * @ipa_wdi_meter_notifier_cb: IPA WDI metering callback
982 * @ipa_desc_size: IPA descriptor size
983 * @ipa_priv: handle to the HTT instance
984 * @is_rm_enabled: Is IPA RM enabled or not
985 * @tx_pipe_handle: pointer to Tx pipe handle
986 * @rx_pipe_handle: pointer to Rx pipe handle
987 * @is_smmu_enabled: Is SMMU enabled or not
988 * @sys_in: parameters to setup sys pipe in mcc mode
989 *
990 * Return: QDF_STATUS
991 */
992QDF_STATUS dp_ipa_setup(struct cdp_pdev *ppdev, void *ipa_i2w_cb,
993 void *ipa_w2i_cb, void *ipa_wdi_meter_notifier_cb,
994 uint32_t ipa_desc_size, void *ipa_priv,
995 bool is_rm_enabled, uint32_t *tx_pipe_handle,
996 uint32_t *rx_pipe_handle, bool is_smmu_enabled,
Sravan Kumar Kairamfc3c8cf2018-11-19 18:32:50 +0530997 qdf_ipa_sys_connect_params_t *sys_in, bool over_gsi)
Mohit Khannaf83015c2018-02-13 08:29:39 -0800998{
999 struct dp_pdev *pdev = (struct dp_pdev *)ppdev;
1000 struct dp_soc *soc = pdev->soc;
1001 struct dp_ipa_resources *ipa_res = &pdev->ipa_resource;
1002 qdf_ipa_ep_cfg_t *tx_cfg;
1003 qdf_ipa_ep_cfg_t *rx_cfg;
1004 qdf_ipa_wdi_pipe_setup_info_t *tx;
1005 qdf_ipa_wdi_pipe_setup_info_t *rx;
1006 qdf_ipa_wdi_pipe_setup_info_smmu_t *tx_smmu;
1007 qdf_ipa_wdi_pipe_setup_info_smmu_t *rx_smmu;
1008 qdf_ipa_wdi_conn_in_params_t pipe_in;
1009 qdf_ipa_wdi_conn_out_params_t pipe_out;
Mohit Khannaf83015c2018-02-13 08:29:39 -08001010 int ret;
1011
Mohit Khanna81179cb2018-08-16 20:50:43 -07001012 if (!wlan_cfg_is_ipa_enabled(soc->wlan_cfg_ctx))
1013 return QDF_STATUS_SUCCESS;
1014
1015
Mohit Khannaf83015c2018-02-13 08:29:39 -08001016 qdf_mem_zero(&tx, sizeof(qdf_ipa_wdi_pipe_setup_info_t));
1017 qdf_mem_zero(&rx, sizeof(qdf_ipa_wdi_pipe_setup_info_t));
1018 qdf_mem_zero(&pipe_in, sizeof(pipe_in));
1019 qdf_mem_zero(&pipe_out, sizeof(pipe_out));
1020
1021 if (is_smmu_enabled)
1022 QDF_IPA_WDI_CONN_IN_PARAMS_SMMU_ENABLED(&pipe_in) = true;
1023 else
1024 QDF_IPA_WDI_CONN_IN_PARAMS_SMMU_ENABLED(&pipe_in) = false;
1025
1026 dp_setup_mcc_sys_pipes(sys_in, &pipe_in);
1027
1028 /* TX PIPE */
1029 if (QDF_IPA_WDI_CONN_IN_PARAMS_SMMU_ENABLED(&pipe_in)) {
1030 tx_smmu = &QDF_IPA_WDI_CONN_IN_PARAMS_TX_SMMU(&pipe_in);
1031 tx_cfg = &QDF_IPA_WDI_SETUP_INFO_SMMU_EP_CFG(tx_smmu);
1032 } else {
1033 tx = &QDF_IPA_WDI_CONN_IN_PARAMS_TX(&pipe_in);
1034 tx_cfg = &QDF_IPA_WDI_SETUP_INFO_EP_CFG(tx);
1035 }
1036
1037 QDF_IPA_EP_CFG_NAT_EN(tx_cfg) = IPA_BYPASS_NAT;
1038 QDF_IPA_EP_CFG_HDR_LEN(tx_cfg) = DP_IPA_UC_WLAN_TX_HDR_LEN;
1039 QDF_IPA_EP_CFG_HDR_OFST_PKT_SIZE_VALID(tx_cfg) = 0;
1040 QDF_IPA_EP_CFG_HDR_OFST_PKT_SIZE(tx_cfg) = 0;
1041 QDF_IPA_EP_CFG_HDR_ADDITIONAL_CONST_LEN(tx_cfg) = 0;
1042 QDF_IPA_EP_CFG_MODE(tx_cfg) = IPA_BASIC;
1043 QDF_IPA_EP_CFG_HDR_LITTLE_ENDIAN(tx_cfg) = true;
1044
1045 /**
1046 * Transfer Ring: WBM Ring
1047 * Transfer Ring Doorbell PA: WBM Tail Pointer Address
1048 * Event Ring: TCL ring
1049 * Event Ring Doorbell PA: TCL Head Pointer Address
1050 */
jiad3b8104b2019-03-08 17:23:35 +08001051 if (is_smmu_enabled)
1052 dp_ipa_wdi_tx_smmu_params(soc, ipa_res, tx_smmu, over_gsi);
Sravan Kumar Kairamfc3c8cf2018-11-19 18:32:50 +05301053 else
jiad3b8104b2019-03-08 17:23:35 +08001054 dp_ipa_wdi_tx_params(soc, ipa_res, tx, over_gsi);
Mohit Khannaf83015c2018-02-13 08:29:39 -08001055
1056 /* RX PIPE */
1057 if (QDF_IPA_WDI_CONN_IN_PARAMS_SMMU_ENABLED(&pipe_in)) {
1058 rx_smmu = &QDF_IPA_WDI_CONN_IN_PARAMS_RX_SMMU(&pipe_in);
1059 rx_cfg = &QDF_IPA_WDI_SETUP_INFO_SMMU_EP_CFG(rx_smmu);
1060 } else {
1061 rx = &QDF_IPA_WDI_CONN_IN_PARAMS_RX(&pipe_in);
1062 rx_cfg = &QDF_IPA_WDI_SETUP_INFO_EP_CFG(rx);
1063 }
1064
1065 QDF_IPA_EP_CFG_NAT_EN(rx_cfg) = IPA_BYPASS_NAT;
1066 QDF_IPA_EP_CFG_HDR_LEN(rx_cfg) = DP_IPA_UC_WLAN_RX_HDR_LEN;
1067 QDF_IPA_EP_CFG_HDR_OFST_PKT_SIZE_VALID(rx_cfg) = 1;
1068 QDF_IPA_EP_CFG_HDR_OFST_PKT_SIZE(rx_cfg) = 0;
1069 QDF_IPA_EP_CFG_HDR_ADDITIONAL_CONST_LEN(rx_cfg) = 0;
1070 QDF_IPA_EP_CFG_HDR_OFST_METADATA_VALID(rx_cfg) = 0;
1071 QDF_IPA_EP_CFG_HDR_METADATA_REG_VALID(rx_cfg) = 1;
1072 QDF_IPA_EP_CFG_MODE(rx_cfg) = IPA_BASIC;
1073 QDF_IPA_EP_CFG_HDR_LITTLE_ENDIAN(rx_cfg) = true;
1074
1075 /**
1076 * Transfer Ring: REO Ring
1077 * Transfer Ring Doorbell PA: REO Tail Pointer Address
1078 * Event Ring: FW ring
1079 * Event Ring Doorbell PA: FW Head Pointer Address
1080 */
jiad3b8104b2019-03-08 17:23:35 +08001081 if (is_smmu_enabled)
1082 dp_ipa_wdi_rx_smmu_params(soc, ipa_res, rx_smmu, over_gsi);
1083 else
1084 dp_ipa_wdi_rx_params(soc, ipa_res, rx, over_gsi);
Mohit Khannaf83015c2018-02-13 08:29:39 -08001085
1086 QDF_IPA_WDI_CONN_IN_PARAMS_NOTIFY(&pipe_in) = ipa_w2i_cb;
1087 QDF_IPA_WDI_CONN_IN_PARAMS_PRIV(&pipe_in) = ipa_priv;
1088
Mohit Khanna81179cb2018-08-16 20:50:43 -07001089 /* Connect WDI IPA PIPEs */
Mohit Khannaf83015c2018-02-13 08:29:39 -08001090 ret = qdf_ipa_wdi_conn_pipes(&pipe_in, &pipe_out);
Mohit Khanna81179cb2018-08-16 20:50:43 -07001091
Mohit Khannaf83015c2018-02-13 08:29:39 -08001092 if (ret) {
1093 QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
1094 "%s: ipa_wdi_conn_pipes: IPA pipe setup failed: ret=%d",
1095 __func__, ret);
1096 return QDF_STATUS_E_FAILURE;
1097 }
1098
1099 /* IPA uC Doorbell registers */
Mohit Khanna81179cb2018-08-16 20:50:43 -07001100 dp_info("Tx DB PA=0x%x, Rx DB PA=0x%x",
1101 (unsigned int)QDF_IPA_WDI_CONN_OUT_PARAMS_TX_UC_DB_PA(&pipe_out),
1102 (unsigned int)QDF_IPA_WDI_CONN_OUT_PARAMS_RX_UC_DB_PA(&pipe_out));
Mohit Khannaf83015c2018-02-13 08:29:39 -08001103
1104 ipa_res->tx_comp_doorbell_paddr =
1105 QDF_IPA_WDI_CONN_OUT_PARAMS_TX_UC_DB_PA(&pipe_out);
1106 ipa_res->rx_ready_doorbell_paddr =
1107 QDF_IPA_WDI_CONN_OUT_PARAMS_RX_UC_DB_PA(&pipe_out);
1108
Mohit Khannaf83015c2018-02-13 08:29:39 -08001109 return QDF_STATUS_SUCCESS;
1110}
1111
1112/**
1113 * dp_ipa_setup_iface() - Setup IPA header and register interface
1114 * @ifname: Interface name
1115 * @mac_addr: Interface MAC address
1116 * @prod_client: IPA prod client type
1117 * @cons_client: IPA cons client type
1118 * @session_id: Session ID
1119 * @is_ipv6_enabled: Is IPV6 enabled or not
1120 *
1121 * Return: QDF_STATUS
1122 */
1123QDF_STATUS dp_ipa_setup_iface(char *ifname, uint8_t *mac_addr,
1124 qdf_ipa_client_type_t prod_client,
1125 qdf_ipa_client_type_t cons_client,
1126 uint8_t session_id, bool is_ipv6_enabled)
1127{
1128 qdf_ipa_wdi_reg_intf_in_params_t in;
1129 qdf_ipa_wdi_hdr_info_t hdr_info;
1130 struct dp_ipa_uc_tx_hdr uc_tx_hdr;
1131 struct dp_ipa_uc_tx_hdr uc_tx_hdr_v6;
1132 int ret = -EINVAL;
1133
Mohit Khanna81179cb2018-08-16 20:50:43 -07001134 dp_debug("Add Partial hdr: %s, %pM", ifname, mac_addr);
Mohit Khannaf83015c2018-02-13 08:29:39 -08001135 qdf_mem_zero(&hdr_info, sizeof(qdf_ipa_wdi_hdr_info_t));
1136 qdf_ether_addr_copy(uc_tx_hdr.eth.h_source, mac_addr);
1137
1138 /* IPV4 header */
1139 uc_tx_hdr.eth.h_proto = qdf_htons(ETH_P_IP);
1140
1141 QDF_IPA_WDI_HDR_INFO_HDR(&hdr_info) = (uint8_t *)&uc_tx_hdr;
1142 QDF_IPA_WDI_HDR_INFO_HDR_LEN(&hdr_info) = DP_IPA_UC_WLAN_TX_HDR_LEN;
1143 QDF_IPA_WDI_HDR_INFO_HDR_TYPE(&hdr_info) = IPA_HDR_L2_ETHERNET_II;
1144 QDF_IPA_WDI_HDR_INFO_DST_MAC_ADDR_OFFSET(&hdr_info) =
1145 DP_IPA_UC_WLAN_HDR_DES_MAC_OFFSET;
1146
1147 QDF_IPA_WDI_REG_INTF_IN_PARAMS_NETDEV_NAME(&in) = ifname;
1148 qdf_mem_copy(&(QDF_IPA_WDI_REG_INTF_IN_PARAMS_HDR_INFO(&in)[IPA_IP_v4]),
1149 &hdr_info, sizeof(qdf_ipa_wdi_hdr_info_t));
1150 QDF_IPA_WDI_REG_INTF_IN_PARAMS_ALT_DST_PIPE(&in) = cons_client;
1151 QDF_IPA_WDI_REG_INTF_IN_PARAMS_IS_META_DATA_VALID(&in) = 1;
1152 QDF_IPA_WDI_REG_INTF_IN_PARAMS_META_DATA(&in) =
1153 htonl(session_id << 16);
1154 QDF_IPA_WDI_REG_INTF_IN_PARAMS_META_DATA_MASK(&in) = htonl(0x00FF0000);
1155
1156 /* IPV6 header */
1157 if (is_ipv6_enabled) {
1158 qdf_mem_copy(&uc_tx_hdr_v6, &uc_tx_hdr,
1159 DP_IPA_UC_WLAN_TX_HDR_LEN);
1160 uc_tx_hdr_v6.eth.h_proto = qdf_htons(ETH_P_IPV6);
1161 QDF_IPA_WDI_HDR_INFO_HDR(&hdr_info) = (uint8_t *)&uc_tx_hdr_v6;
1162 qdf_mem_copy(&(QDF_IPA_WDI_REG_INTF_IN_PARAMS_HDR_INFO(&in)[IPA_IP_v6]),
1163 &hdr_info, sizeof(qdf_ipa_wdi_hdr_info_t));
1164 }
1165
Mohit Khanna81179cb2018-08-16 20:50:43 -07001166 dp_debug("registering for session_id: %u", session_id);
1167
Mohit Khannaf83015c2018-02-13 08:29:39 -08001168 ret = qdf_ipa_wdi_reg_intf(&in);
Mohit Khanna81179cb2018-08-16 20:50:43 -07001169
Mohit Khannaf83015c2018-02-13 08:29:39 -08001170 if (ret) {
1171 QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
1172 "%s: ipa_wdi_reg_intf: register IPA interface falied: ret=%d",
1173 __func__, ret);
1174 return QDF_STATUS_E_FAILURE;
1175 }
1176
1177 return QDF_STATUS_SUCCESS;
1178}
1179
1180#else /* CONFIG_IPA_WDI_UNIFIED_API */
1181
Yun Parkfde6b9e2017-06-26 17:13:11 -07001182/**
1183 * dp_ipa_setup() - Setup and connect IPA pipes
1184 * @ppdev - handle to the device instance
1185 * @ipa_i2w_cb: IPA to WLAN callback
1186 * @ipa_w2i_cb: WLAN to IPA callback
1187 * @ipa_wdi_meter_notifier_cb: IPA WDI metering callback
1188 * @ipa_desc_size: IPA descriptor size
1189 * @ipa_priv: handle to the HTT instance
1190 * @is_rm_enabled: Is IPA RM enabled or not
1191 * @tx_pipe_handle: pointer to Tx pipe handle
1192 * @rx_pipe_handle: pointer to Rx pipe handle
1193 *
1194 * Return: QDF_STATUS
1195 */
1196QDF_STATUS dp_ipa_setup(struct cdp_pdev *ppdev, void *ipa_i2w_cb,
1197 void *ipa_w2i_cb, void *ipa_wdi_meter_notifier_cb,
1198 uint32_t ipa_desc_size, void *ipa_priv,
1199 bool is_rm_enabled, uint32_t *tx_pipe_handle,
1200 uint32_t *rx_pipe_handle)
1201{
1202 struct dp_pdev *pdev = (struct dp_pdev *)ppdev;
1203 struct dp_soc *soc = pdev->soc;
1204 struct dp_ipa_resources *ipa_res = &pdev->ipa_resource;
Mohit Khannaf83015c2018-02-13 08:29:39 -08001205 qdf_ipa_wdi_pipe_setup_info_t *tx;
1206 qdf_ipa_wdi_pipe_setup_info_t *rx;
1207 qdf_ipa_wdi_conn_in_params_t pipe_in;
1208 qdf_ipa_wdi_conn_out_params_t pipe_out;
Yun Park601d0d82017-08-28 21:49:31 -07001209 struct tcl_data_cmd *tcl_desc_ptr;
1210 uint8_t *desc_addr;
1211 uint32_t desc_size;
Yun Parkfde6b9e2017-06-26 17:13:11 -07001212 int ret;
1213
Mohit Khanna81179cb2018-08-16 20:50:43 -07001214 if (!wlan_cfg_is_ipa_enabled(soc->wlan_cfg_ctx))
1215 return QDF_STATUS_SUCCESS;
1216
Mohit Khannaf83015c2018-02-13 08:29:39 -08001217 qdf_mem_zero(&tx, sizeof(qdf_ipa_wdi_pipe_setup_info_t));
1218 qdf_mem_zero(&rx, sizeof(qdf_ipa_wdi_pipe_setup_info_t));
Yun Parkfd269b52017-10-05 14:41:32 -07001219 qdf_mem_zero(&pipe_in, sizeof(pipe_in));
1220 qdf_mem_zero(&pipe_out, sizeof(pipe_out));
Yun Parkfde6b9e2017-06-26 17:13:11 -07001221
1222 /* TX PIPE */
1223 /**
1224 * Transfer Ring: WBM Ring
1225 * Transfer Ring Doorbell PA: WBM Tail Pointer Address
1226 * Event Ring: TCL ring
1227 * Event Ring Doorbell PA: TCL Head Pointer Address
1228 */
Mohit Khannaf83015c2018-02-13 08:29:39 -08001229 tx = &QDF_IPA_WDI_CONN_IN_PARAMS_TX(&pipe_in);
1230 QDF_IPA_WDI_SETUP_INFO_NAT_EN(tx) = IPA_BYPASS_NAT;
1231 QDF_IPA_WDI_SETUP_INFO_HDR_LEN(tx) = DP_IPA_UC_WLAN_TX_HDR_LEN;
1232 QDF_IPA_WDI_SETUP_INFO_HDR_OFST_PKT_SIZE_VALID(tx) = 0;
1233 QDF_IPA_WDI_SETUP_INFO_HDR_OFST_PKT_SIZE(tx) = 0;
1234 QDF_IPA_WDI_SETUP_INFO_HDR_ADDITIONAL_CONST_LEN(tx) = 0;
1235 QDF_IPA_WDI_SETUP_INFO_MODE(tx) = IPA_BASIC;
1236 QDF_IPA_WDI_SETUP_INFO_HDR_LITTLE_ENDIAN(tx) = true;
1237 QDF_IPA_WDI_SETUP_INFO_CLIENT(tx) = IPA_CLIENT_WLAN1_CONS;
1238 QDF_IPA_WDI_SETUP_INFO_TRANSFER_RING_BASE_PA(tx) =
Yun Parkfd269b52017-10-05 14:41:32 -07001239 ipa_res->tx_comp_ring_base_paddr;
Mohit Khannaf83015c2018-02-13 08:29:39 -08001240 QDF_IPA_WDI_SETUP_INFO_TRANSFER_RING_SIZE(tx) =
Yun Parkfd269b52017-10-05 14:41:32 -07001241 ipa_res->tx_comp_ring_size;
1242 /* WBM Tail Pointer Address */
Mohit Khannaf83015c2018-02-13 08:29:39 -08001243 QDF_IPA_WDI_SETUP_INFO_TRANSFER_RING_DOORBELL_PA(tx) =
Yun Parkfde6b9e2017-06-26 17:13:11 -07001244 soc->ipa_uc_tx_rsc.ipa_wbm_tp_paddr;
Mohit Khannaf83015c2018-02-13 08:29:39 -08001245 QDF_IPA_WDI_SETUP_INFO_EVENT_RING_BASE_PA(tx) =
Yun Parkfd269b52017-10-05 14:41:32 -07001246 ipa_res->tx_ring_base_paddr;
Mohit Khannaf83015c2018-02-13 08:29:39 -08001247 QDF_IPA_WDI_SETUP_INFO_EVENT_RING_SIZE(tx) = ipa_res->tx_ring_size;
Yun Parkfd269b52017-10-05 14:41:32 -07001248 /* TCL Head Pointer Address */
Mohit Khannaf83015c2018-02-13 08:29:39 -08001249 QDF_IPA_WDI_SETUP_INFO_EVENT_RING_DOORBELL_PA(tx) =
Yun Parkfde6b9e2017-06-26 17:13:11 -07001250 soc->ipa_uc_tx_rsc.ipa_tcl_hp_paddr;
Mohit Khannaf83015c2018-02-13 08:29:39 -08001251 QDF_IPA_WDI_SETUP_INFO_NUM_PKT_BUFFERS(tx) =
Yun Parkfd269b52017-10-05 14:41:32 -07001252 ipa_res->tx_num_alloc_buffer;
Mohit Khannaf83015c2018-02-13 08:29:39 -08001253 QDF_IPA_WDI_SETUP_INFO_PKT_OFFSET(tx) = 0;
Yun Parkfde6b9e2017-06-26 17:13:11 -07001254
Yun Park601d0d82017-08-28 21:49:31 -07001255 /* Preprogram TCL descriptor */
Yun Parkfd269b52017-10-05 14:41:32 -07001256 desc_addr =
Mohit Khannaf83015c2018-02-13 08:29:39 -08001257 (uint8_t *)QDF_IPA_WDI_SETUP_INFO_DESC_FORMAT_TEMPLATE(tx);
Yun Park601d0d82017-08-28 21:49:31 -07001258 desc_size = sizeof(struct tcl_data_cmd);
1259 HAL_TX_DESC_SET_TLV_HDR(desc_addr, HAL_TX_TCL_DATA_TAG, desc_size);
Yun Parkfd269b52017-10-05 14:41:32 -07001260 tcl_desc_ptr = (struct tcl_data_cmd *)
Mohit Khannaf83015c2018-02-13 08:29:39 -08001261 (QDF_IPA_WDI_SETUP_INFO_DESC_FORMAT_TEMPLATE(tx) + 1);
Yun Park601d0d82017-08-28 21:49:31 -07001262 tcl_desc_ptr->buf_addr_info.return_buffer_manager =
1263 HAL_RX_BUF_RBM_SW2_BM;
1264 tcl_desc_ptr->addrx_en = 1; /* Address X search enable in ASE */
1265 tcl_desc_ptr->encap_type = HAL_TX_ENCAP_TYPE_ETHERNET;
1266 tcl_desc_ptr->packet_offset = 2; /* padding for alignment */
1267
Yun Parkfde6b9e2017-06-26 17:13:11 -07001268 /* RX PIPE */
1269 /**
1270 * Transfer Ring: REO Ring
1271 * Transfer Ring Doorbell PA: REO Tail Pointer Address
1272 * Event Ring: FW ring
1273 * Event Ring Doorbell PA: FW Head Pointer Address
1274 */
Mohit Khannaf83015c2018-02-13 08:29:39 -08001275 rx = &QDF_IPA_WDI_CONN_IN_PARAMS_RX(&pipe_in);
1276 QDF_IPA_WDI_SETUP_INFO_NAT_EN(rx) = IPA_BYPASS_NAT;
1277 QDF_IPA_WDI_SETUP_INFO_HDR_LEN(rx) = DP_IPA_UC_WLAN_RX_HDR_LEN;
1278 QDF_IPA_WDI_SETUP_INFO_HDR_OFST_PKT_SIZE_VALID(rx) = 0;
1279 QDF_IPA_WDI_SETUP_INFO_HDR_OFST_PKT_SIZE(rx) = 0;
1280 QDF_IPA_WDI_SETUP_INFO_HDR_ADDITIONAL_CONST_LEN(rx) = 0;
1281 QDF_IPA_WDI_SETUP_INFO_HDR_OFST_METADATA_VALID(rx) = 0;
1282 QDF_IPA_WDI_SETUP_INFO_HDR_METADATA_REG_VALID(rx) = 1;
1283 QDF_IPA_WDI_SETUP_INFO_MODE(rx) = IPA_BASIC;
1284 QDF_IPA_WDI_SETUP_INFO_HDR_LITTLE_ENDIAN(rx) = true;
1285 QDF_IPA_WDI_SETUP_INFO_CLIENT(rx) = IPA_CLIENT_WLAN1_PROD;
1286 QDF_IPA_WDI_SETUP_INFO_TRANSFER_RING_BASE_PA(rx) =
1287 ipa_res->rx_rdy_ring_base_paddr;
1288 QDF_IPA_WDI_SETUP_INFO_TRANSFER_RING_SIZE(rx) =
1289 ipa_res->rx_rdy_ring_size;
1290 /* REO Tail Pointer Address */
1291 QDF_IPA_WDI_SETUP_INFO_TRANSFER_RING_DOORBELL_PA(rx) =
1292 soc->ipa_uc_rx_rsc.ipa_reo_tp_paddr;
1293 QDF_IPA_WDI_SETUP_INFO_EVENT_RING_BASE_PA(rx) =
1294 ipa_res->rx_refill_ring_base_paddr;
1295 QDF_IPA_WDI_SETUP_INFO_EVENT_RING_SIZE(rx) =
1296 ipa_res->rx_refill_ring_size;
1297 /* FW Head Pointer Address */
1298 QDF_IPA_WDI_SETUP_INFO_EVENT_RING_DOORBELL_PA(rx) =
1299 soc->ipa_uc_rx_rsc.ipa_rx_refill_buf_hp_paddr;
1300 QDF_IPA_WDI_SETUP_INFO_PKT_OFFSET(rx) = RX_PKT_TLVS_LEN +
1301 L3_HEADER_PADDING;
1302 QDF_IPA_WDI_CONN_IN_PARAMS_NOTIFY(&pipe_in) = ipa_w2i_cb;
1303 QDF_IPA_WDI_CONN_IN_PARAMS_PRIV(&pipe_in) = ipa_priv;
Yun Parkfde6b9e2017-06-26 17:13:11 -07001304
1305 /* Connect WDI IPA PIPE */
Mohit Khannaf83015c2018-02-13 08:29:39 -08001306 ret = qdf_ipa_wdi_conn_pipes(&pipe_in, &pipe_out);
Yun Parkfde6b9e2017-06-26 17:13:11 -07001307 if (ret) {
1308 QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
Mohit Khannaf83015c2018-02-13 08:29:39 -08001309 "%s: ipa_wdi_conn_pipes: IPA pipe setup failed: ret=%d",
Yun Park4711ade2017-08-28 21:49:31 -07001310 __func__, ret);
Yun Parkfde6b9e2017-06-26 17:13:11 -07001311 return QDF_STATUS_E_FAILURE;
1312 }
1313
1314 /* IPA uC Doorbell registers */
1315 QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_DEBUG,
Yun Park4711ade2017-08-28 21:49:31 -07001316 "%s: Tx DB PA=0x%x, Rx DB PA=0x%x",
1317 __func__,
Mohit Khannaf83015c2018-02-13 08:29:39 -08001318 (unsigned int)QDF_IPA_WDI_CONN_OUT_PARAMS_TX_UC_DB_PA(&pipe_out),
1319 (unsigned int)QDF_IPA_WDI_CONN_OUT_PARAMS_RX_UC_DB_PA(&pipe_out));
Yun Parkfde6b9e2017-06-26 17:13:11 -07001320
Yun Parkfd269b52017-10-05 14:41:32 -07001321 ipa_res->tx_comp_doorbell_paddr =
Mohit Khannaf83015c2018-02-13 08:29:39 -08001322 QDF_IPA_WDI_CONN_OUT_PARAMS_TX_UC_DB_PA(&pipe_out);
Yun Parkfd269b52017-10-05 14:41:32 -07001323 ipa_res->tx_comp_doorbell_vaddr =
Mohit Khannaf83015c2018-02-13 08:29:39 -08001324 QDF_IPA_WDI_CONN_OUT_PARAMS_TX_UC_DB_VA(&pipe_out);
Yun Parkfd269b52017-10-05 14:41:32 -07001325 ipa_res->rx_ready_doorbell_paddr =
Mohit Khannaf83015c2018-02-13 08:29:39 -08001326 QDF_IPA_WDI_CONN_OUT_PARAMS_RX_UC_DB_PA(&pipe_out);
Yun Parkfde6b9e2017-06-26 17:13:11 -07001327
1328 QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_DEBUG,
Yun Park4711ade2017-08-28 21:49:31 -07001329 "%s: Tx: %s=%pK, %s=%d, %s=%pK, %s=%pK, %s=%d, %s=%pK, %s=%d, %s=%pK",
1330 __func__,
Yun Parkfde6b9e2017-06-26 17:13:11 -07001331 "transfer_ring_base_pa",
Mohit Khannaf83015c2018-02-13 08:29:39 -08001332 (void *)QDF_IPA_WDI_SETUP_INFO_TRANSFER_RING_BASE_PA(tx),
Yun Parkfde6b9e2017-06-26 17:13:11 -07001333 "transfer_ring_size",
Mohit Khannaf83015c2018-02-13 08:29:39 -08001334 QDF_IPA_WDI_SETUP_INFO_TRANSFER_RING_SIZE(tx),
Yun Parkfde6b9e2017-06-26 17:13:11 -07001335 "transfer_ring_doorbell_pa",
Mohit Khannaf83015c2018-02-13 08:29:39 -08001336 (void *)QDF_IPA_WDI_SETUP_INFO_TRANSFER_RING_DOORBELL_PA(tx),
Yun Parkfde6b9e2017-06-26 17:13:11 -07001337 "event_ring_base_pa",
Mohit Khannaf83015c2018-02-13 08:29:39 -08001338 (void *)QDF_IPA_WDI_SETUP_INFO_EVENT_RING_BASE_PA(tx),
Yun Parkfde6b9e2017-06-26 17:13:11 -07001339 "event_ring_size",
Mohit Khannaf83015c2018-02-13 08:29:39 -08001340 QDF_IPA_WDI_SETUP_INFO_EVENT_RING_SIZE(tx),
Yun Parkfde6b9e2017-06-26 17:13:11 -07001341 "event_ring_doorbell_pa",
Mohit Khannaf83015c2018-02-13 08:29:39 -08001342 (void *)QDF_IPA_WDI_SETUP_INFO_EVENT_RING_DOORBELL_PA(tx),
Yun Parkfde6b9e2017-06-26 17:13:11 -07001343 "num_pkt_buffers",
Mohit Khannaf83015c2018-02-13 08:29:39 -08001344 QDF_IPA_WDI_SETUP_INFO_NUM_PKT_BUFFERS(tx),
Yun Parkfde6b9e2017-06-26 17:13:11 -07001345 "tx_comp_doorbell_paddr",
1346 (void *)ipa_res->tx_comp_doorbell_paddr);
1347
1348 QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_DEBUG,
Yun Park4711ade2017-08-28 21:49:31 -07001349 "%s: Rx: %s=%pK, %s=%d, %s=%pK, %s=%pK, %s=%d, %s=%pK, %s=%d, %s=%pK",
1350 __func__,
Yun Parkfde6b9e2017-06-26 17:13:11 -07001351 "transfer_ring_base_pa",
Mohit Khannaf83015c2018-02-13 08:29:39 -08001352 (void *)QDF_IPA_WDI_SETUP_INFO_TRANSFER_RING_BASE_PA(rx),
Yun Parkfde6b9e2017-06-26 17:13:11 -07001353 "transfer_ring_size",
Mohit Khannaf83015c2018-02-13 08:29:39 -08001354 QDF_IPA_WDI_SETUP_INFO_TRANSFER_RING_SIZE(rx),
Yun Parkfde6b9e2017-06-26 17:13:11 -07001355 "transfer_ring_doorbell_pa",
Mohit Khannaf83015c2018-02-13 08:29:39 -08001356 (void *)QDF_IPA_WDI_SETUP_INFO_TRANSFER_RING_DOORBELL_PA(rx),
Yun Parkfde6b9e2017-06-26 17:13:11 -07001357 "event_ring_base_pa",
Mohit Khannaf83015c2018-02-13 08:29:39 -08001358 (void *)QDF_IPA_WDI_SETUP_INFO_EVENT_RING_BASE_PA(rx),
Yun Parkfde6b9e2017-06-26 17:13:11 -07001359 "event_ring_size",
Mohit Khannaf83015c2018-02-13 08:29:39 -08001360 QDF_IPA_WDI_SETUP_INFO_EVENT_RING_SIZE(rx),
Yun Parkfde6b9e2017-06-26 17:13:11 -07001361 "event_ring_doorbell_pa",
Mohit Khannaf83015c2018-02-13 08:29:39 -08001362 (void *)QDF_IPA_WDI_SETUP_INFO_EVENT_RING_DOORBELL_PA(rx),
Yun Parkfde6b9e2017-06-26 17:13:11 -07001363 "num_pkt_buffers",
Mohit Khannaf83015c2018-02-13 08:29:39 -08001364 QDF_IPA_WDI_SETUP_INFO_NUM_PKT_BUFFERS(rx),
Yun Parkfde6b9e2017-06-26 17:13:11 -07001365 "tx_comp_doorbell_paddr",
1366 (void *)ipa_res->rx_ready_doorbell_paddr);
1367
1368 return QDF_STATUS_SUCCESS;
1369}
1370
1371/**
Yun Parkfde6b9e2017-06-26 17:13:11 -07001372 * dp_ipa_setup_iface() - Setup IPA header and register interface
1373 * @ifname: Interface name
1374 * @mac_addr: Interface MAC address
1375 * @prod_client: IPA prod client type
1376 * @cons_client: IPA cons client type
1377 * @session_id: Session ID
1378 * @is_ipv6_enabled: Is IPV6 enabled or not
1379 *
1380 * Return: QDF_STATUS
1381 */
1382QDF_STATUS dp_ipa_setup_iface(char *ifname, uint8_t *mac_addr,
Yun Parkfd269b52017-10-05 14:41:32 -07001383 qdf_ipa_client_type_t prod_client,
1384 qdf_ipa_client_type_t cons_client,
Yun Parkfde6b9e2017-06-26 17:13:11 -07001385 uint8_t session_id, bool is_ipv6_enabled)
1386{
Mohit Khannaf83015c2018-02-13 08:29:39 -08001387 qdf_ipa_wdi_reg_intf_in_params_t in;
1388 qdf_ipa_wdi_hdr_info_t hdr_info;
Yun Parkfde6b9e2017-06-26 17:13:11 -07001389 struct dp_ipa_uc_tx_hdr uc_tx_hdr;
Mohit Khannaf83015c2018-02-13 08:29:39 -08001390 struct dp_ipa_uc_tx_hdr uc_tx_hdr_v6;
Yun Parkfde6b9e2017-06-26 17:13:11 -07001391 int ret = -EINVAL;
1392
1393 QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_DEBUG,
Yun Park4711ade2017-08-28 21:49:31 -07001394 "%s: Add Partial hdr: %s, %pM",
1395 __func__, ifname, mac_addr);
Yun Parkfde6b9e2017-06-26 17:13:11 -07001396
Mohit Khannaf83015c2018-02-13 08:29:39 -08001397 qdf_mem_zero(&hdr_info, sizeof(qdf_ipa_wdi_hdr_info_t));
Yun Parkfde6b9e2017-06-26 17:13:11 -07001398 qdf_ether_addr_copy(uc_tx_hdr.eth.h_source, mac_addr);
1399
1400 /* IPV4 header */
1401 uc_tx_hdr.eth.h_proto = qdf_htons(ETH_P_IP);
1402
Mohit Khannaf83015c2018-02-13 08:29:39 -08001403 QDF_IPA_WDI_HDR_INFO_HDR(&hdr_info) = (uint8_t *)&uc_tx_hdr;
1404 QDF_IPA_WDI_HDR_INFO_HDR_LEN(&hdr_info) = DP_IPA_UC_WLAN_TX_HDR_LEN;
1405 QDF_IPA_WDI_HDR_INFO_HDR_TYPE(&hdr_info) = IPA_HDR_L2_ETHERNET_II;
1406 QDF_IPA_WDI_HDR_INFO_DST_MAC_ADDR_OFFSET(&hdr_info) =
Yun Parkfd269b52017-10-05 14:41:32 -07001407 DP_IPA_UC_WLAN_HDR_DES_MAC_OFFSET;
Yun Parkfde6b9e2017-06-26 17:13:11 -07001408
Mohit Khannaf83015c2018-02-13 08:29:39 -08001409 QDF_IPA_WDI_REG_INTF_IN_PARAMS_NETDEV_NAME(&in) = ifname;
1410 qdf_mem_copy(&(QDF_IPA_WDI_REG_INTF_IN_PARAMS_HDR_INFO(&in)[IPA_IP_v4]),
1411 &hdr_info, sizeof(qdf_ipa_wdi_hdr_info_t));
1412 QDF_IPA_WDI_REG_INTF_IN_PARAMS_IS_META_DATA_VALID(&in) = 1;
1413 QDF_IPA_WDI_REG_INTF_IN_PARAMS_META_DATA(&in) =
Yun Parkfd269b52017-10-05 14:41:32 -07001414 htonl(session_id << 16);
Mohit Khannaf83015c2018-02-13 08:29:39 -08001415 QDF_IPA_WDI_REG_INTF_IN_PARAMS_META_DATA_MASK(&in) = htonl(0x00FF0000);
Yun Parkfde6b9e2017-06-26 17:13:11 -07001416
1417 /* IPV6 header */
1418 if (is_ipv6_enabled) {
Mohit Khannaf83015c2018-02-13 08:29:39 -08001419 qdf_mem_copy(&uc_tx_hdr_v6, &uc_tx_hdr,
1420 DP_IPA_UC_WLAN_TX_HDR_LEN);
1421 uc_tx_hdr_v6.eth.h_proto = qdf_htons(ETH_P_IPV6);
1422 QDF_IPA_WDI_HDR_INFO_HDR(&hdr_info) = (uint8_t *)&uc_tx_hdr_v6;
1423 qdf_mem_copy(&(QDF_IPA_WDI_REG_INTF_IN_PARAMS_HDR_INFO(&in)[IPA_IP_v6]),
1424 &hdr_info, sizeof(qdf_ipa_wdi_hdr_info_t));
Yun Parkfde6b9e2017-06-26 17:13:11 -07001425 }
1426
Mohit Khannaf83015c2018-02-13 08:29:39 -08001427 ret = qdf_ipa_wdi_reg_intf(&in);
Yun Parkfde6b9e2017-06-26 17:13:11 -07001428 if (ret) {
Mohit Khannaf83015c2018-02-13 08:29:39 -08001429 dp_err("ipa_wdi_reg_intf: register IPA interface falied: ret=%d",
1430 ret);
1431 return QDF_STATUS_E_FAILURE;
1432 }
1433
1434 return QDF_STATUS_SUCCESS;
1435}
1436
1437#endif /* CONFIG_IPA_WDI_UNIFIED_API */
1438
1439/**
1440 * dp_ipa_cleanup() - Disconnect IPA pipes
1441 * @tx_pipe_handle: Tx pipe handle
1442 * @rx_pipe_handle: Rx pipe handle
1443 *
1444 * Return: QDF_STATUS
1445 */
1446QDF_STATUS dp_ipa_cleanup(uint32_t tx_pipe_handle, uint32_t rx_pipe_handle)
1447{
1448 int ret;
1449
1450 ret = qdf_ipa_wdi_disconn_pipes();
1451 if (ret) {
1452 dp_err("ipa_wdi_disconn_pipes: IPA pipe cleanup failed: ret=%d",
1453 ret);
Yun Parkfde6b9e2017-06-26 17:13:11 -07001454 return QDF_STATUS_E_FAILURE;
1455 }
1456
1457 return QDF_STATUS_SUCCESS;
1458}
1459
1460/**
1461 * dp_ipa_cleanup_iface() - Cleanup IPA header and deregister interface
1462 * @ifname: Interface name
1463 * @is_ipv6_enabled: Is IPV6 enabled or not
1464 *
1465 * Return: QDF_STATUS
1466 */
1467QDF_STATUS dp_ipa_cleanup_iface(char *ifname, bool is_ipv6_enabled)
1468{
1469 int ret;
1470
Mohit Khannaf83015c2018-02-13 08:29:39 -08001471 ret = qdf_ipa_wdi_dereg_intf(ifname);
Yun Parkfde6b9e2017-06-26 17:13:11 -07001472 if (ret) {
1473 QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
Mohit Khannaf83015c2018-02-13 08:29:39 -08001474 "%s: ipa_wdi_dereg_intf: IPA pipe deregistration failed: ret=%d",
Yun Park4711ade2017-08-28 21:49:31 -07001475 __func__, ret);
Yun Parkfde6b9e2017-06-26 17:13:11 -07001476 return QDF_STATUS_E_FAILURE;
1477 }
1478
1479 return QDF_STATUS_SUCCESS;
1480}
1481
jiad3b8104b2019-03-08 17:23:35 +08001482/**
Yun Parkfde6b9e2017-06-26 17:13:11 -07001483 * dp_ipa_uc_enable_pipes() - Enable and resume traffic on Tx/Rx pipes
1484 * @ppdev - handle to the device instance
1485 *
1486 * Return: QDF_STATUS
1487 */
1488QDF_STATUS dp_ipa_enable_pipes(struct cdp_pdev *ppdev)
1489{
1490 QDF_STATUS result;
1491
Mohit Khannaf83015c2018-02-13 08:29:39 -08001492 result = qdf_ipa_wdi_enable_pipes();
Yun Parkfde6b9e2017-06-26 17:13:11 -07001493 if (result) {
1494 QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
Yun Park4711ade2017-08-28 21:49:31 -07001495 "%s: Enable WDI PIPE fail, code %d",
1496 __func__, result);
Yun Parkfde6b9e2017-06-26 17:13:11 -07001497 return QDF_STATUS_E_FAILURE;
1498 }
1499
1500 return QDF_STATUS_SUCCESS;
1501}
1502
1503/**
1504 * dp_ipa_uc_disable_pipes() – Suspend traffic and disable Tx/Rx pipes
1505 * @ppdev - handle to the device instance
1506 *
1507 * Return: QDF_STATUS
1508 */
1509QDF_STATUS dp_ipa_disable_pipes(struct cdp_pdev *ppdev)
1510{
1511 QDF_STATUS result;
1512
Mohit Khannaf83015c2018-02-13 08:29:39 -08001513 result = qdf_ipa_wdi_disable_pipes();
Yun Parkfde6b9e2017-06-26 17:13:11 -07001514 if (result) {
1515 QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
Yun Park4711ade2017-08-28 21:49:31 -07001516 "%s: Disable WDI PIPE fail, code %d",
1517 __func__, result);
Yun Parkfde6b9e2017-06-26 17:13:11 -07001518 return QDF_STATUS_E_FAILURE;
1519 }
1520
1521 return QDF_STATUS_SUCCESS;
1522}
1523
1524/**
1525 * dp_ipa_set_perf_level() - Set IPA clock bandwidth based on data rates
1526 * @client: Client type
1527 * @max_supported_bw_mbps: Maximum bandwidth needed (in Mbps)
1528 *
1529 * Return: QDF_STATUS
1530 */
1531QDF_STATUS dp_ipa_set_perf_level(int client, uint32_t max_supported_bw_mbps)
1532{
Mohit Khannaf83015c2018-02-13 08:29:39 -08001533 qdf_ipa_wdi_perf_profile_t profile;
Yun Parkfde6b9e2017-06-26 17:13:11 -07001534 QDF_STATUS result;
1535
1536 profile.client = client;
1537 profile.max_supported_bw_mbps = max_supported_bw_mbps;
1538
Mohit Khannaf83015c2018-02-13 08:29:39 -08001539 result = qdf_ipa_wdi_set_perf_profile(&profile);
Yun Parkfde6b9e2017-06-26 17:13:11 -07001540 if (result) {
1541 QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
Mohit Khannaf83015c2018-02-13 08:29:39 -08001542 "%s: ipa_wdi_set_perf_profile fail, code %d",
Yun Park4711ade2017-08-28 21:49:31 -07001543 __func__, result);
Yun Parkfde6b9e2017-06-26 17:13:11 -07001544 return QDF_STATUS_E_FAILURE;
1545 }
1546
1547 return QDF_STATUS_SUCCESS;
1548}
Mohit Khannaf83015c2018-02-13 08:29:39 -08001549
jiad5a4530f2019-03-25 15:33:52 +08001550/**
1551 * dp_ipa_intrabss_send - send IPA RX intra-bss frames
1552 * @pdev: pdev
1553 * @vdev: vdev
1554 * @nbuf: skb
1555 *
1556 * Return: nbuf if TX fails and NULL if TX succeeds
1557 */
1558static qdf_nbuf_t dp_ipa_intrabss_send(struct dp_pdev *pdev,
1559 struct dp_vdev *vdev,
1560 qdf_nbuf_t nbuf)
1561{
1562 struct cdp_tid_rx_stats *tid_stats;
1563 struct dp_peer *vdev_peer;
1564 uint16_t len;
1565 uint8_t tid;
1566
1567 vdev_peer = vdev->vap_bss_peer;
1568 if (qdf_unlikely(!vdev_peer))
1569 return nbuf;
1570
1571 tid = qdf_nbuf_get_priority(nbuf);
1572 tid_stats = &pdev->stats.tid_stats.tid_rx_stats[tid];
1573
1574 qdf_mem_zero(nbuf->cb, sizeof(nbuf->cb));
1575 len = qdf_nbuf_len(nbuf);
1576
1577 if (dp_tx_send(vdev, nbuf)) {
1578 DP_STATS_INC_PKT(vdev_peer, rx.intra_bss.fail, 1, len);
1579 tid_stats->fail_cnt[INTRABSS_DROP]++;
1580 return nbuf;
1581 }
1582
1583 DP_STATS_INC_PKT(vdev_peer, rx.intra_bss.pkts, 1, len);
1584 tid_stats->intrabss_cnt++;
1585 return NULL;
1586}
1587
1588bool dp_ipa_rx_intrabss_fwd(struct cdp_vdev *pvdev, qdf_nbuf_t nbuf,
1589 bool *fwd_success)
1590{
1591 struct dp_vdev *vdev = (struct dp_vdev *)pvdev;
1592 struct dp_pdev *pdev;
1593 struct dp_peer *da_peer;
1594 struct dp_peer *sa_peer;
1595 qdf_nbuf_t nbuf_copy;
1596 uint8_t da_is_bcmc;
1597 struct ethhdr *eh;
1598 uint8_t local_id;
1599
1600 *fwd_success = false; /* set default as failure */
1601
1602 /*
1603 * WDI 3.0 skb->cb[] info from IPA driver
1604 * skb->cb[0] = vdev_id
1605 * skb->cb[1].bit#1 = da_is_bcmc
1606 */
1607 da_is_bcmc = ((uint8_t)nbuf->cb[1]) & 0x2;
1608
1609 if (qdf_unlikely(!vdev))
1610 return false;
1611
1612 pdev = vdev->pdev;
1613 if (qdf_unlikely(!pdev))
1614 return false;
1615
1616 /* no fwd for station mode and just pass up to stack */
1617 if (vdev->opmode == wlan_op_mode_sta)
1618 return false;
1619
1620 if (da_is_bcmc) {
1621 nbuf_copy = qdf_nbuf_copy(nbuf);
1622 if (!nbuf_copy)
1623 return false;
1624
1625 if (dp_ipa_intrabss_send(pdev, vdev, nbuf_copy))
1626 qdf_nbuf_free(nbuf_copy);
1627 else
1628 *fwd_success = true;
1629
1630 /* return false to pass original pkt up to stack */
1631 return false;
1632 }
1633
1634 eh = (struct ethhdr *)qdf_nbuf_data(nbuf);
1635
1636 if (!qdf_mem_cmp(eh->h_dest, vdev->mac_addr.raw, QDF_MAC_ADDR_SIZE))
1637 return false;
1638
1639 da_peer = dp_find_peer_by_addr((struct cdp_pdev *)pdev, eh->h_dest,
1640 &local_id);
1641 if (!da_peer)
1642 return false;
1643
1644 if (da_peer->vdev != vdev)
1645 return false;
1646
1647 sa_peer = dp_find_peer_by_addr((struct cdp_pdev *)pdev, eh->h_source,
1648 &local_id);
1649 if (!sa_peer)
1650 return false;
1651
1652 if (sa_peer->vdev != vdev)
1653 return false;
1654
1655 /*
1656 * In intra-bss forwarding scenario, skb is allocated by IPA driver.
1657 * Need to add skb to internal tracking table to avoid nbuf memory
1658 * leak check for unallocated skb.
1659 */
1660 qdf_net_buf_debug_acquire_skb(nbuf, __FILE__, __LINE__);
1661
1662 if (dp_ipa_intrabss_send(pdev, vdev, nbuf))
1663 qdf_nbuf_free(nbuf);
1664 else
1665 *fwd_success = true;
1666
1667 return true;
1668}
1669
Yun Parkfde6b9e2017-06-26 17:13:11 -07001670#endif