blob: 35b80b9d536e7c74cc0e909c71e7de704c459587 [file] [log] [blame]
Yun Parkfde6b9e2017-06-26 17:13:11 -07001/*
Sravan Gouda4030a42020-01-13 13:17:21 +05302 * Copyright (c) 2017-2020, 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
Mohit Khannac6e059a2019-09-27 17:52:06 -070037/* WAR for IPA_OFFLOAD case. In some cases, its observed that WBM tries to
38 * release a buffer into WBM2SW RELEASE ring for IPA, and the ring is full.
39 * This causes back pressure, resulting in a FW crash.
40 * By leaving some entries with no buffer attached, WBM will be able to write
41 * to the ring, and from dumps we can figure out the buffer which is causing
42 * this issue.
43 */
44#define DP_IPA_WAR_WBM2SW_REL_RING_NO_BUF_ENTRIES 16
Sravan Goudba1d5aa2019-11-27 18:59:14 +053045/**
46 *struct dp_ipa_reo_remap_record - history for dp ipa reo remaps
47 * @ix0_reg: reo destination ring IX0 value
48 * @ix2_reg: reo destination ring IX2 value
49 * @ix3_reg: reo destination ring IX3 value
50 */
51struct dp_ipa_reo_remap_record {
52 uint64_t timestamp;
53 uint32_t ix0_reg;
54 uint32_t ix2_reg;
55 uint32_t ix3_reg;
56};
57
58#define REO_REMAP_HISTORY_SIZE 32
59
60struct dp_ipa_reo_remap_record dp_ipa_reo_remap_history[REO_REMAP_HISTORY_SIZE];
61
62static qdf_atomic_t dp_ipa_reo_remap_history_index;
63static int dp_ipa_reo_remap_record_index_next(qdf_atomic_t *index)
64{
65 int next = qdf_atomic_inc_return(index);
66
67 if (next == REO_REMAP_HISTORY_SIZE)
68 qdf_atomic_sub(REO_REMAP_HISTORY_SIZE, index);
69
70 return next % REO_REMAP_HISTORY_SIZE;
71}
72
73/**
74 * dp_ipa_reo_remap_history_add() - Record dp ipa reo remap values
75 * @ix0_val: reo destination ring IX0 value
76 * @ix2_val: reo destination ring IX2 value
77 * @ix3_val: reo destination ring IX3 value
78 *
79 * Return: None
80 */
81static void dp_ipa_reo_remap_history_add(uint32_t ix0_val, uint32_t ix2_val,
82 uint32_t ix3_val)
83{
84 int idx = dp_ipa_reo_remap_record_index_next(
85 &dp_ipa_reo_remap_history_index);
86 struct dp_ipa_reo_remap_record *record = &dp_ipa_reo_remap_history[idx];
87
88 record->timestamp = qdf_get_log_timestamp();
89 record->ix0_reg = ix0_val;
90 record->ix2_reg = ix2_val;
91 record->ix3_reg = ix3_val;
92}
Mohit Khannac6e059a2019-09-27 17:52:06 -070093
jiad3b8104b2019-03-08 17:23:35 +080094static QDF_STATUS __dp_ipa_handle_buf_smmu_mapping(struct dp_soc *soc,
95 qdf_nbuf_t nbuf,
96 bool create)
97{
98 qdf_mem_info_t mem_map_table = {0};
99
100 qdf_update_mem_map_table(soc->osdev, &mem_map_table,
101 qdf_nbuf_get_frag_paddr(nbuf, 0),
102 skb_end_pointer(nbuf) - nbuf->data);
103
104 if (create)
105 qdf_ipa_wdi_create_smmu_mapping(1, &mem_map_table);
106 else
107 qdf_ipa_wdi_release_smmu_mapping(1, &mem_map_table);
108
109 return QDF_STATUS_SUCCESS;
110}
111
112QDF_STATUS dp_ipa_handle_rx_buf_smmu_mapping(struct dp_soc *soc,
113 qdf_nbuf_t nbuf,
114 bool create)
115{
jiad3b8104b2019-03-08 17:23:35 +0800116 struct dp_pdev *pdev;
117 int i;
118
119 for (i = 0; i < soc->pdev_count; i++) {
120 pdev = soc->pdev_list[i];
121 if (pdev && pdev->monitor_configured)
122 return QDF_STATUS_SUCCESS;
123 }
124
125 if (!wlan_cfg_is_ipa_enabled(soc->wlan_cfg_ctx) ||
126 !qdf_mem_smmu_s1_enabled(soc->osdev))
127 return QDF_STATUS_SUCCESS;
128
Nisha Menonf7c5baa2019-10-23 12:50:16 -0700129 if (!qdf_atomic_read(&soc->ipa_pipes_enabled))
jiad3b8104b2019-03-08 17:23:35 +0800130 return QDF_STATUS_SUCCESS;
131
132 return __dp_ipa_handle_buf_smmu_mapping(soc, nbuf, create);
133}
134
Varun Reddy Yeturua7c21dc2019-05-16 14:03:46 -0700135#ifdef RX_DESC_MULTI_PAGE_ALLOC
136static QDF_STATUS dp_ipa_handle_rx_buf_pool_smmu_mapping(struct dp_soc *soc,
137 struct dp_pdev *pdev,
138 bool create)
139{
140 struct rx_desc_pool *rx_pool;
141 uint8_t pdev_id;
142 uint32_t num_desc, page_id, offset, i;
143 uint16_t num_desc_per_page;
144 union dp_rx_desc_list_elem_t *rx_desc_elem;
145 struct dp_rx_desc *rx_desc;
146 qdf_nbuf_t nbuf;
147
148 if (!qdf_mem_smmu_s1_enabled(soc->osdev))
149 return QDF_STATUS_SUCCESS;
150
151 pdev_id = pdev->pdev_id;
152 rx_pool = &soc->rx_desc_buf[pdev_id];
153
154 qdf_spin_lock_bh(&rx_pool->lock);
155 num_desc = rx_pool->pool_size;
156 num_desc_per_page = rx_pool->desc_pages.num_element_per_page;
157 for (i = 0; i < num_desc; i++) {
158 page_id = i / num_desc_per_page;
159 offset = i % num_desc_per_page;
160 if (qdf_unlikely(!(rx_pool->desc_pages.cacheable_pages)))
161 break;
162 rx_desc_elem = dp_rx_desc_find(page_id, offset, rx_pool);
163 rx_desc = &rx_desc_elem->rx_desc;
164 if ((!(rx_desc->in_use)) || rx_desc->unmapped)
165 continue;
166 nbuf = rx_desc->nbuf;
167
168 __dp_ipa_handle_buf_smmu_mapping(soc, nbuf, create);
169 }
170 qdf_spin_unlock_bh(&rx_pool->lock);
171
172 return QDF_STATUS_SUCCESS;
173}
174#else
jiad3b8104b2019-03-08 17:23:35 +0800175static QDF_STATUS dp_ipa_handle_rx_buf_pool_smmu_mapping(struct dp_soc *soc,
176 struct dp_pdev *pdev,
177 bool create)
178{
179 struct rx_desc_pool *rx_pool;
180 uint8_t pdev_id;
181 qdf_nbuf_t nbuf;
182 int i;
183
184 if (!qdf_mem_smmu_s1_enabled(soc->osdev))
185 return QDF_STATUS_SUCCESS;
186
187 pdev_id = pdev->pdev_id;
188 rx_pool = &soc->rx_desc_buf[pdev_id];
189
190 qdf_spin_lock_bh(&rx_pool->lock);
191 for (i = 0; i < rx_pool->pool_size; i++) {
192 if ((!(rx_pool->array[i].rx_desc.in_use)) ||
193 rx_pool->array[i].rx_desc.unmapped)
194 continue;
195
196 nbuf = rx_pool->array[i].rx_desc.nbuf;
197
198 __dp_ipa_handle_buf_smmu_mapping(soc, nbuf, create);
199 }
200 qdf_spin_unlock_bh(&rx_pool->lock);
201
202 return QDF_STATUS_SUCCESS;
203}
Varun Reddy Yeturua7c21dc2019-05-16 14:03:46 -0700204#endif /* RX_DESC_MULTI_PAGE_ALLOC */
jiad3b8104b2019-03-08 17:23:35 +0800205
Yun Parkfde6b9e2017-06-26 17:13:11 -0700206/**
Yun Park601d0d82017-08-28 21:49:31 -0700207 * dp_tx_ipa_uc_detach - Free autonomy TX resources
208 * @soc: data path instance
209 * @pdev: core txrx pdev context
210 *
211 * Free allocated TX buffers with WBM SRNG
212 *
213 * Return: none
214 */
215static void dp_tx_ipa_uc_detach(struct dp_soc *soc, struct dp_pdev *pdev)
216{
217 int idx;
Mohit Khanna81179cb2018-08-16 20:50:43 -0700218 qdf_nbuf_t nbuf;
jiad3b8104b2019-03-08 17:23:35 +0800219 struct dp_ipa_resources *ipa_res;
Yun Park601d0d82017-08-28 21:49:31 -0700220
221 for (idx = 0; idx < soc->ipa_uc_tx_rsc.alloc_tx_buf_cnt; idx++) {
Mohit Khanna81179cb2018-08-16 20:50:43 -0700222 nbuf = (qdf_nbuf_t)
223 soc->ipa_uc_tx_rsc.tx_buf_pool_vaddr_unaligned[idx];
224 if (!nbuf)
225 continue;
jiad3b8104b2019-03-08 17:23:35 +0800226
227 if (qdf_mem_smmu_s1_enabled(soc->osdev))
228 __dp_ipa_handle_buf_smmu_mapping(soc, nbuf, false);
229
Mohit Khanna81179cb2018-08-16 20:50:43 -0700230 qdf_nbuf_unmap_single(soc->osdev, nbuf, QDF_DMA_BIDIRECTIONAL);
231 qdf_nbuf_free(nbuf);
232 soc->ipa_uc_tx_rsc.tx_buf_pool_vaddr_unaligned[idx] =
233 (void *)NULL;
Yun Park601d0d82017-08-28 21:49:31 -0700234 }
235
Yun Park4711ade2017-08-28 21:49:31 -0700236 qdf_mem_free(soc->ipa_uc_tx_rsc.tx_buf_pool_vaddr_unaligned);
237 soc->ipa_uc_tx_rsc.tx_buf_pool_vaddr_unaligned = NULL;
jiad3b8104b2019-03-08 17:23:35 +0800238
239 ipa_res = &pdev->ipa_resource;
240 iounmap(ipa_res->tx_comp_doorbell_vaddr);
241
242 qdf_mem_free_sgtable(&ipa_res->tx_ring.sgtable);
243 qdf_mem_free_sgtable(&ipa_res->tx_comp_ring.sgtable);
Yun Park601d0d82017-08-28 21:49:31 -0700244}
245
246/**
247 * dp_rx_ipa_uc_detach - free autonomy RX resources
248 * @soc: data path instance
249 * @pdev: core txrx pdev context
250 *
251 * This function will detach DP RX into main device context
252 * will free DP Rx resources.
253 *
254 * Return: none
255 */
256static void dp_rx_ipa_uc_detach(struct dp_soc *soc, struct dp_pdev *pdev)
257{
jiad3b8104b2019-03-08 17:23:35 +0800258 struct dp_ipa_resources *ipa_res = &pdev->ipa_resource;
259
260 qdf_mem_free_sgtable(&ipa_res->rx_rdy_ring.sgtable);
261 qdf_mem_free_sgtable(&ipa_res->rx_refill_ring.sgtable);
Yun Park601d0d82017-08-28 21:49:31 -0700262}
263
264int dp_ipa_uc_detach(struct dp_soc *soc, struct dp_pdev *pdev)
265{
jiad3b8104b2019-03-08 17:23:35 +0800266 if (!wlan_cfg_is_ipa_enabled(soc->wlan_cfg_ctx))
267 return QDF_STATUS_SUCCESS;
268
Yun Park601d0d82017-08-28 21:49:31 -0700269 /* TX resource detach */
270 dp_tx_ipa_uc_detach(soc, pdev);
271
272 /* RX resource detach */
273 dp_rx_ipa_uc_detach(soc, pdev);
274
275 return QDF_STATUS_SUCCESS; /* success */
276}
277
Yun Park601d0d82017-08-28 21:49:31 -0700278/**
279 * dp_tx_ipa_uc_attach - Allocate autonomy TX resources
280 * @soc: data path instance
281 * @pdev: Physical device handle
282 *
283 * Allocate TX buffer from non-cacheable memory
284 * Attache allocated TX buffers with WBM SRNG
285 *
286 * Return: int
287 */
288static int dp_tx_ipa_uc_attach(struct dp_soc *soc, struct dp_pdev *pdev)
289{
290 uint32_t tx_buffer_count;
291 uint32_t ring_base_align = 8;
Yun Park601d0d82017-08-28 21:49:31 -0700292 qdf_dma_addr_t buffer_paddr;
Akshay Kosigi8eda31c2019-07-10 14:42:42 +0530293 struct hal_srng *wbm_srng = (struct hal_srng *)
Yun Park601d0d82017-08-28 21:49:31 -0700294 soc->tx_comp_ring[IPA_TX_COMP_RING_IDX].hal_srng;
295 struct hal_srng_params srng_params;
296 uint32_t paddr_lo;
297 uint32_t paddr_hi;
298 void *ring_entry;
299 int num_entries;
Pramod Simhab2ef27b2018-09-14 14:43:19 -0700300 qdf_nbuf_t nbuf;
Yun Park601d0d82017-08-28 21:49:31 -0700301 int retval = QDF_STATUS_SUCCESS;
Mohit Khannac6e059a2019-09-27 17:52:06 -0700302 int max_alloc_count = 0;
jiad3b8104b2019-03-08 17:23:35 +0800303
Yun Park601d0d82017-08-28 21:49:31 -0700304 /*
305 * Uncomment when dp_ops_cfg.cfg_attach is implemented
306 * unsigned int uc_tx_buf_sz =
307 * dp_cfg_ipa_uc_tx_buf_size(pdev->osif_pdev);
308 */
309 unsigned int uc_tx_buf_sz = CFG_IPA_UC_TX_BUF_SIZE_DEFAULT;
310 unsigned int alloc_size = uc_tx_buf_sz + ring_base_align - 1;
311
Akshay Kosigi0bca9fb2019-06-27 15:26:13 +0530312 hal_get_srng_params(soc->hal_soc, hal_srng_to_hal_ring_handle(wbm_srng),
313 &srng_params);
Yun Park601d0d82017-08-28 21:49:31 -0700314 num_entries = srng_params.num_entries;
315
Mohit Khannac6e059a2019-09-27 17:52:06 -0700316 max_alloc_count =
317 num_entries - DP_IPA_WAR_WBM2SW_REL_RING_NO_BUF_ENTRIES;
318 if (max_alloc_count <= 0) {
319 dp_err("incorrect value for buffer count %u", max_alloc_count);
320 return -EINVAL;
321 }
322
323 dp_info("requested %d buffers to be posted to wbm ring",
324 max_alloc_count);
Yun Park601d0d82017-08-28 21:49:31 -0700325
Yun Park4711ade2017-08-28 21:49:31 -0700326 soc->ipa_uc_tx_rsc.tx_buf_pool_vaddr_unaligned =
327 qdf_mem_malloc(num_entries *
328 sizeof(*soc->ipa_uc_tx_rsc.tx_buf_pool_vaddr_unaligned));
329 if (!soc->ipa_uc_tx_rsc.tx_buf_pool_vaddr_unaligned) {
Mohit Khannac6e059a2019-09-27 17:52:06 -0700330 dp_err("IPA WBM Ring Tx buf pool vaddr alloc fail");
Yun Park4711ade2017-08-28 21:49:31 -0700331 return -ENOMEM;
332 }
333
Akshay Kosigi0bca9fb2019-06-27 15:26:13 +0530334 hal_srng_access_start_unlocked(soc->hal_soc,
335 hal_srng_to_hal_ring_handle(wbm_srng));
Yun Park601d0d82017-08-28 21:49:31 -0700336
337 /*
Mohit Khannac6e059a2019-09-27 17:52:06 -0700338 * Allocate Tx buffers as many as possible.
339 * Leave DP_IPA_WAR_WBM2SW_REL_RING_NO_BUF_ENTRIES empty
Yun Park601d0d82017-08-28 21:49:31 -0700340 * Populate Tx buffers into WBM2IPA ring
341 * This initial buffer population will simulate H/W as source ring,
342 * and update HP
343 */
344 for (tx_buffer_count = 0;
Mohit Khannac6e059a2019-09-27 17:52:06 -0700345 tx_buffer_count < max_alloc_count - 1; tx_buffer_count++) {
Pramod Simhab2ef27b2018-09-14 14:43:19 -0700346 nbuf = qdf_nbuf_alloc(soc->osdev, alloc_size, 0, 256, FALSE);
347 if (!nbuf)
Yun Park601d0d82017-08-28 21:49:31 -0700348 break;
349
350 ring_entry = hal_srng_dst_get_next_hp(soc->hal_soc,
Akshay Kosigi0bca9fb2019-06-27 15:26:13 +0530351 hal_srng_to_hal_ring_handle(wbm_srng));
Yun Park601d0d82017-08-28 21:49:31 -0700352 if (!ring_entry) {
Yun Park4711ade2017-08-28 21:49:31 -0700353 QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_INFO,
Aditya Sathishded018e2018-07-02 16:25:21 +0530354 "%s: Failed to get WBM ring entry",
Yun Park4711ade2017-08-28 21:49:31 -0700355 __func__);
Pramod Simhab2ef27b2018-09-14 14:43:19 -0700356 qdf_nbuf_free(nbuf);
Yun Park4711ade2017-08-28 21:49:31 -0700357 break;
Yun Park601d0d82017-08-28 21:49:31 -0700358 }
359
Pramod Simhab2ef27b2018-09-14 14:43:19 -0700360 qdf_nbuf_map_single(soc->osdev, nbuf,
361 QDF_DMA_BIDIRECTIONAL);
362 buffer_paddr = qdf_nbuf_get_frag_paddr(nbuf, 0);
Yun Park601d0d82017-08-28 21:49:31 -0700363
Krunal Sonibe43d552018-10-03 11:20:20 -0700364 paddr_lo = ((uint64_t)buffer_paddr & 0x00000000ffffffff);
365 paddr_hi = ((uint64_t)buffer_paddr & 0x0000001f00000000) >> 32;
Pramod Simhab2ef27b2018-09-14 14:43:19 -0700366 HAL_RXDMA_PADDR_LO_SET(ring_entry, paddr_lo);
367 HAL_RXDMA_PADDR_HI_SET(ring_entry, paddr_hi);
368 HAL_RXDMA_MANAGER_SET(ring_entry, (IPA_TCL_DATA_RING_IDX +
369 HAL_WBM_SW0_BM_ID));
Yun Park601d0d82017-08-28 21:49:31 -0700370
Yun Park4711ade2017-08-28 21:49:31 -0700371 soc->ipa_uc_tx_rsc.tx_buf_pool_vaddr_unaligned[tx_buffer_count]
Pramod Simhab2ef27b2018-09-14 14:43:19 -0700372 = (void *)nbuf;
jiad3b8104b2019-03-08 17:23:35 +0800373
374 if (qdf_mem_smmu_s1_enabled(soc->osdev))
375 __dp_ipa_handle_buf_smmu_mapping(soc, nbuf, true);
Yun Park601d0d82017-08-28 21:49:31 -0700376 }
377
Akshay Kosigi8eda31c2019-07-10 14:42:42 +0530378 hal_srng_access_end_unlocked(soc->hal_soc,
379 hal_srng_to_hal_ring_handle(wbm_srng));
Yun Park601d0d82017-08-28 21:49:31 -0700380
381 soc->ipa_uc_tx_rsc.alloc_tx_buf_cnt = tx_buffer_count;
382
Yun Park4711ade2017-08-28 21:49:31 -0700383 if (tx_buffer_count) {
Mohit Khannac6e059a2019-09-27 17:52:06 -0700384 dp_info("IPA WDI TX buffer: %d allocated", tx_buffer_count);
Yun Park4711ade2017-08-28 21:49:31 -0700385 } else {
Mohit Khannac6e059a2019-09-27 17:52:06 -0700386 dp_err("No IPA WDI TX buffer allocated!");
Yun Park4711ade2017-08-28 21:49:31 -0700387 qdf_mem_free(soc->ipa_uc_tx_rsc.tx_buf_pool_vaddr_unaligned);
388 soc->ipa_uc_tx_rsc.tx_buf_pool_vaddr_unaligned = NULL;
Yun Park4711ade2017-08-28 21:49:31 -0700389 retval = -ENOMEM;
390 }
Yun Park601d0d82017-08-28 21:49:31 -0700391
392 return retval;
Yun Park601d0d82017-08-28 21:49:31 -0700393}
394
395/**
396 * dp_rx_ipa_uc_attach - Allocate autonomy RX resources
397 * @soc: data path instance
398 * @pdev: core txrx pdev context
399 *
400 * This function will attach a DP RX instance into the main
401 * device (SOC) context.
402 *
403 * Return: QDF_STATUS_SUCCESS: success
404 * QDF_STATUS_E_RESOURCES: Error return
405 */
406static int dp_rx_ipa_uc_attach(struct dp_soc *soc, struct dp_pdev *pdev)
407{
408 return QDF_STATUS_SUCCESS;
409}
410
411int dp_ipa_uc_attach(struct dp_soc *soc, struct dp_pdev *pdev)
412{
413 int error;
414
Mohit Khanna81179cb2018-08-16 20:50:43 -0700415 if (!wlan_cfg_is_ipa_enabled(soc->wlan_cfg_ctx))
416 return QDF_STATUS_SUCCESS;
417
Yun Park601d0d82017-08-28 21:49:31 -0700418 /* TX resource attach */
419 error = dp_tx_ipa_uc_attach(soc, pdev);
420 if (error) {
421 QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR,
Aditya Sathishded018e2018-07-02 16:25:21 +0530422 "%s: DP IPA UC TX attach fail code %d",
Yun Park4711ade2017-08-28 21:49:31 -0700423 __func__, error);
Yun Park601d0d82017-08-28 21:49:31 -0700424 return error;
425 }
426
427 /* RX resource attach */
428 error = dp_rx_ipa_uc_attach(soc, pdev);
429 if (error) {
430 QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR,
Aditya Sathishded018e2018-07-02 16:25:21 +0530431 "%s: DP IPA UC RX attach fail code %d",
Yun Park4711ade2017-08-28 21:49:31 -0700432 __func__, error);
Yun Park601d0d82017-08-28 21:49:31 -0700433 dp_tx_ipa_uc_detach(soc, pdev);
434 return error;
435 }
436
437 return QDF_STATUS_SUCCESS; /* success */
438}
439
440/*
441 * dp_ipa_ring_resource_setup() - setup IPA ring resources
442 * @soc: data path SoC handle
443 *
444 * Return: none
445 */
446int dp_ipa_ring_resource_setup(struct dp_soc *soc,
447 struct dp_pdev *pdev)
448{
449 struct hal_soc *hal_soc = (struct hal_soc *)soc->hal_soc;
450 struct hal_srng *hal_srng;
451 struct hal_srng_params srng_params;
452 qdf_dma_addr_t hp_addr;
453 unsigned long addr_offset, dev_base_paddr;
Jia Dingc0315752019-07-15 17:44:12 +0800454 uint32_t ix0;
Yun Park601d0d82017-08-28 21:49:31 -0700455
Mohit Khanna81179cb2018-08-16 20:50:43 -0700456 if (!wlan_cfg_is_ipa_enabled(soc->wlan_cfg_ctx))
457 return QDF_STATUS_SUCCESS;
458
Yun Park601d0d82017-08-28 21:49:31 -0700459 /* IPA TCL_DATA Ring - HAL_SRNG_SW2TCL3 */
Akshay Kosigi8eda31c2019-07-10 14:42:42 +0530460 hal_srng = (struct hal_srng *)
461 soc->tcl_data_ring[IPA_TCL_DATA_RING_IDX].hal_srng;
462 hal_get_srng_params(hal_soc_to_hal_soc_handle(hal_soc),
463 hal_srng_to_hal_ring_handle(hal_srng),
Akshay Kosigi0bca9fb2019-06-27 15:26:13 +0530464 &srng_params);
Yun Park601d0d82017-08-28 21:49:31 -0700465
466 soc->ipa_uc_tx_rsc.ipa_tcl_ring_base_paddr =
467 srng_params.ring_base_paddr;
468 soc->ipa_uc_tx_rsc.ipa_tcl_ring_base_vaddr =
469 srng_params.ring_base_vaddr;
470 soc->ipa_uc_tx_rsc.ipa_tcl_ring_size =
471 (srng_params.num_entries * srng_params.entry_size) << 2;
472 /*
473 * For the register backed memory addresses, use the scn->mem_pa to
474 * calculate the physical address of the shadow registers
475 */
476 dev_base_paddr =
477 (unsigned long)
478 ((struct hif_softc *)(hal_soc->hif_handle))->mem_pa;
479 addr_offset = (unsigned long)(hal_srng->u.src_ring.hp_addr) -
480 (unsigned long)(hal_soc->dev_base_addr);
481 soc->ipa_uc_tx_rsc.ipa_tcl_hp_paddr =
482 (qdf_dma_addr_t)(addr_offset + dev_base_paddr);
483
Mohit Khanna81179cb2018-08-16 20:50:43 -0700484 dp_info("IPA TCL_DATA Ring addr_offset=%x, dev_base_paddr=%x, hp_paddr=%x paddr=%pK vaddr=%pK size= %u(%u bytes)",
485 (unsigned int)addr_offset,
Yun Park601d0d82017-08-28 21:49:31 -0700486 (unsigned int)dev_base_paddr,
Mohit Khanna81179cb2018-08-16 20:50:43 -0700487 (unsigned int)(soc->ipa_uc_tx_rsc.ipa_tcl_hp_paddr),
488 (void *)soc->ipa_uc_tx_rsc.ipa_tcl_ring_base_paddr,
489 (void *)soc->ipa_uc_tx_rsc.ipa_tcl_ring_base_vaddr,
490 srng_params.num_entries,
491 soc->ipa_uc_tx_rsc.ipa_tcl_ring_size);
Yun Park601d0d82017-08-28 21:49:31 -0700492
493 /* IPA TX COMP Ring - HAL_SRNG_WBM2SW2_RELEASE */
Akshay Kosigi8eda31c2019-07-10 14:42:42 +0530494 hal_srng = (struct hal_srng *)
495 soc->tx_comp_ring[IPA_TX_COMP_RING_IDX].hal_srng;
496 hal_get_srng_params(hal_soc_to_hal_soc_handle(hal_soc),
497 hal_srng_to_hal_ring_handle(hal_srng),
Akshay Kosigi0bca9fb2019-06-27 15:26:13 +0530498 &srng_params);
Yun Park601d0d82017-08-28 21:49:31 -0700499
500 soc->ipa_uc_tx_rsc.ipa_wbm_ring_base_paddr =
Mohit Khanna81179cb2018-08-16 20:50:43 -0700501 srng_params.ring_base_paddr;
Yun Park601d0d82017-08-28 21:49:31 -0700502 soc->ipa_uc_tx_rsc.ipa_wbm_ring_base_vaddr =
Mohit Khanna81179cb2018-08-16 20:50:43 -0700503 srng_params.ring_base_vaddr;
Yun Park601d0d82017-08-28 21:49:31 -0700504 soc->ipa_uc_tx_rsc.ipa_wbm_ring_size =
505 (srng_params.num_entries * srng_params.entry_size) << 2;
506 addr_offset = (unsigned long)(hal_srng->u.dst_ring.tp_addr) -
507 (unsigned long)(hal_soc->dev_base_addr);
508 soc->ipa_uc_tx_rsc.ipa_wbm_tp_paddr =
509 (qdf_dma_addr_t)(addr_offset + dev_base_paddr);
510
Mohit Khanna81179cb2018-08-16 20:50:43 -0700511 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)",
512 (unsigned int)addr_offset,
Yun Park601d0d82017-08-28 21:49:31 -0700513 (unsigned int)dev_base_paddr,
Mohit Khanna81179cb2018-08-16 20:50:43 -0700514 (unsigned int)(soc->ipa_uc_tx_rsc.ipa_wbm_tp_paddr),
515 (void *)soc->ipa_uc_tx_rsc.ipa_wbm_ring_base_paddr,
516 (void *)soc->ipa_uc_tx_rsc.ipa_wbm_ring_base_vaddr,
517 srng_params.num_entries,
518 soc->ipa_uc_tx_rsc.ipa_wbm_ring_size);
Yun Park601d0d82017-08-28 21:49:31 -0700519
520 /* IPA REO_DEST Ring - HAL_SRNG_REO2SW4 */
Akshay Kosigi8eda31c2019-07-10 14:42:42 +0530521 hal_srng = (struct hal_srng *)
522 soc->reo_dest_ring[IPA_REO_DEST_RING_IDX].hal_srng;
523 hal_get_srng_params(hal_soc_to_hal_soc_handle(hal_soc),
524 hal_srng_to_hal_ring_handle(hal_srng),
Akshay Kosigi0bca9fb2019-06-27 15:26:13 +0530525 &srng_params);
Yun Park601d0d82017-08-28 21:49:31 -0700526
527 soc->ipa_uc_rx_rsc.ipa_reo_ring_base_paddr =
Mohit Khanna81179cb2018-08-16 20:50:43 -0700528 srng_params.ring_base_paddr;
Yun Park601d0d82017-08-28 21:49:31 -0700529 soc->ipa_uc_rx_rsc.ipa_reo_ring_base_vaddr =
Mohit Khanna81179cb2018-08-16 20:50:43 -0700530 srng_params.ring_base_vaddr;
Yun Park601d0d82017-08-28 21:49:31 -0700531 soc->ipa_uc_rx_rsc.ipa_reo_ring_size =
532 (srng_params.num_entries * srng_params.entry_size) << 2;
533 addr_offset = (unsigned long)(hal_srng->u.dst_ring.tp_addr) -
534 (unsigned long)(hal_soc->dev_base_addr);
535 soc->ipa_uc_rx_rsc.ipa_reo_tp_paddr =
536 (qdf_dma_addr_t)(addr_offset + dev_base_paddr);
537
Mohit Khanna81179cb2018-08-16 20:50:43 -0700538 dp_info("IPA REO_DEST Ring addr_offset=%x, dev_base_paddr=%x, tp_paddr=%x paddr=%pK vaddr=%pK size= %u(%u bytes)",
539 (unsigned int)addr_offset,
Yun Park601d0d82017-08-28 21:49:31 -0700540 (unsigned int)dev_base_paddr,
Mohit Khanna81179cb2018-08-16 20:50:43 -0700541 (unsigned int)(soc->ipa_uc_rx_rsc.ipa_reo_tp_paddr),
542 (void *)soc->ipa_uc_rx_rsc.ipa_reo_ring_base_paddr,
543 (void *)soc->ipa_uc_rx_rsc.ipa_reo_ring_base_vaddr,
544 srng_params.num_entries,
545 soc->ipa_uc_rx_rsc.ipa_reo_ring_size);
Yun Park601d0d82017-08-28 21:49:31 -0700546
Akshay Kosigi8eda31c2019-07-10 14:42:42 +0530547 hal_srng = (struct hal_srng *)
548 pdev->rx_refill_buf_ring2.hal_srng;
549 hal_get_srng_params(hal_soc_to_hal_soc_handle(hal_soc),
550 hal_srng_to_hal_ring_handle(hal_srng),
Akshay Kosigi0bca9fb2019-06-27 15:26:13 +0530551 &srng_params);
Yun Park601d0d82017-08-28 21:49:31 -0700552 soc->ipa_uc_rx_rsc.ipa_rx_refill_buf_ring_base_paddr =
553 srng_params.ring_base_paddr;
554 soc->ipa_uc_rx_rsc.ipa_rx_refill_buf_ring_base_vaddr =
555 srng_params.ring_base_vaddr;
556 soc->ipa_uc_rx_rsc.ipa_rx_refill_buf_ring_size =
557 (srng_params.num_entries * srng_params.entry_size) << 2;
Akshay Kosigi8eda31c2019-07-10 14:42:42 +0530558 hp_addr = hal_srng_get_hp_addr(hal_soc_to_hal_soc_handle(hal_soc),
Akshay Kosigi0bca9fb2019-06-27 15:26:13 +0530559 hal_srng_to_hal_ring_handle(hal_srng));
jiad3b8104b2019-03-08 17:23:35 +0800560 soc->ipa_uc_rx_rsc.ipa_rx_refill_buf_hp_paddr =
561 qdf_mem_paddr_from_dmaaddr(soc->osdev, hp_addr);
Yun Park601d0d82017-08-28 21:49:31 -0700562
Mohit Khanna81179cb2018-08-16 20:50:43 -0700563 dp_info("IPA REFILL_BUF Ring hp_paddr=%x paddr=%pK vaddr=%pK size= %u(%u bytes)",
564 (unsigned int)(soc->ipa_uc_rx_rsc.ipa_rx_refill_buf_hp_paddr),
565 (void *)soc->ipa_uc_rx_rsc.ipa_rx_refill_buf_ring_base_paddr,
566 (void *)soc->ipa_uc_rx_rsc.ipa_rx_refill_buf_ring_base_vaddr,
567 srng_params.num_entries,
568 soc->ipa_uc_rx_rsc.ipa_rx_refill_buf_ring_size);
Yun Park601d0d82017-08-28 21:49:31 -0700569
Jia Dingc0315752019-07-15 17:44:12 +0800570 /*
571 * Set DEST_RING_MAPPING_4 to SW2 as default value for
572 * DESTINATION_RING_CTRL_IX_0.
573 */
574 ix0 = HAL_REO_REMAP_IX0(REO_REMAP_TCL, 0) |
575 HAL_REO_REMAP_IX0(REO_REMAP_SW1, 1) |
576 HAL_REO_REMAP_IX0(REO_REMAP_SW2, 2) |
577 HAL_REO_REMAP_IX0(REO_REMAP_SW3, 3) |
578 HAL_REO_REMAP_IX0(REO_REMAP_SW2, 4) |
579 HAL_REO_REMAP_IX0(REO_REMAP_RELEASE, 5) |
580 HAL_REO_REMAP_IX0(REO_REMAP_FW, 6) |
581 HAL_REO_REMAP_IX0(REO_REMAP_FW, 7);
582
583 hal_reo_read_write_ctrl_ix(soc->hal_soc, false, &ix0, NULL, NULL, NULL);
584
Yun Park601d0d82017-08-28 21:49:31 -0700585 return 0;
586}
587
jiad3b8104b2019-03-08 17:23:35 +0800588static QDF_STATUS dp_ipa_get_shared_mem_info(qdf_device_t osdev,
589 qdf_shared_mem_t *shared_mem,
590 void *cpu_addr,
591 qdf_dma_addr_t dma_addr,
592 uint32_t size)
593{
594 qdf_dma_addr_t paddr;
595 int ret;
596
597 shared_mem->vaddr = cpu_addr;
598 qdf_mem_set_dma_size(osdev, &shared_mem->mem_info, size);
599 *qdf_mem_get_dma_addr_ptr(osdev, &shared_mem->mem_info) = dma_addr;
600
601 paddr = qdf_mem_paddr_from_dmaaddr(osdev, dma_addr);
602 qdf_mem_set_dma_pa(osdev, &shared_mem->mem_info, paddr);
603
604 ret = qdf_mem_dma_get_sgtable(osdev->dev, &shared_mem->sgtable,
605 shared_mem->vaddr, dma_addr, size);
606 if (ret) {
607 dp_err("Unable to get DMA sgtable");
608 return QDF_STATUS_E_NOMEM;
609 }
610
611 qdf_dma_get_sgtable_dma_addr(&shared_mem->sgtable);
612
613 return QDF_STATUS_SUCCESS;
614}
615
Vevek Venkatesan2cc8c5d2019-08-22 16:29:46 +0530616QDF_STATUS dp_ipa_get_resource(struct cdp_soc_t *soc_hdl, uint8_t pdev_id)
Yun Parkfde6b9e2017-06-26 17:13:11 -0700617{
Vevek Venkatesan2cc8c5d2019-08-22 16:29:46 +0530618 struct dp_soc *soc = cdp_soc_t_to_dp_soc(soc_hdl);
619 struct dp_pdev *pdev =
620 dp_get_pdev_from_soc_pdev_id_wifi3(soc, pdev_id);
621 struct dp_ipa_resources *ipa_res;
Yun Parkfde6b9e2017-06-26 17:13:11 -0700622
Vevek Venkatesan2cc8c5d2019-08-22 16:29:46 +0530623 if (!pdev) {
624 dp_err("%s invalid instance", __func__);
625 return QDF_STATUS_E_FAILURE;
626 }
627
628 ipa_res = &pdev->ipa_resource;
Mohit Khanna81179cb2018-08-16 20:50:43 -0700629 if (!wlan_cfg_is_ipa_enabled(soc->wlan_cfg_ctx))
630 return QDF_STATUS_SUCCESS;
631
Yun Parkfde6b9e2017-06-26 17:13:11 -0700632 ipa_res->tx_num_alloc_buffer =
633 (uint32_t)soc->ipa_uc_tx_rsc.alloc_tx_buf_cnt;
634
jiad3b8104b2019-03-08 17:23:35 +0800635 dp_ipa_get_shared_mem_info(soc->osdev, &ipa_res->tx_ring,
636 soc->ipa_uc_tx_rsc.ipa_tcl_ring_base_vaddr,
637 soc->ipa_uc_tx_rsc.ipa_tcl_ring_base_paddr,
638 soc->ipa_uc_tx_rsc.ipa_tcl_ring_size);
Yun Parkfde6b9e2017-06-26 17:13:11 -0700639
jiad3b8104b2019-03-08 17:23:35 +0800640 dp_ipa_get_shared_mem_info(soc->osdev, &ipa_res->tx_comp_ring,
641 soc->ipa_uc_tx_rsc.ipa_wbm_ring_base_vaddr,
642 soc->ipa_uc_tx_rsc.ipa_wbm_ring_base_paddr,
643 soc->ipa_uc_tx_rsc.ipa_wbm_ring_size);
Yun Parkfde6b9e2017-06-26 17:13:11 -0700644
jiad3b8104b2019-03-08 17:23:35 +0800645 dp_ipa_get_shared_mem_info(soc->osdev, &ipa_res->rx_rdy_ring,
646 soc->ipa_uc_rx_rsc.ipa_reo_ring_base_vaddr,
647 soc->ipa_uc_rx_rsc.ipa_reo_ring_base_paddr,
648 soc->ipa_uc_rx_rsc.ipa_reo_ring_size);
Yun Parkfde6b9e2017-06-26 17:13:11 -0700649
jiad3b8104b2019-03-08 17:23:35 +0800650 dp_ipa_get_shared_mem_info(
651 soc->osdev, &ipa_res->rx_refill_ring,
652 soc->ipa_uc_rx_rsc.ipa_rx_refill_buf_ring_base_vaddr,
653 soc->ipa_uc_rx_rsc.ipa_rx_refill_buf_ring_base_paddr,
654 soc->ipa_uc_rx_rsc.ipa_rx_refill_buf_ring_size);
Mohit Khanna81179cb2018-08-16 20:50:43 -0700655
jiad3b8104b2019-03-08 17:23:35 +0800656 if (!qdf_mem_get_dma_addr(soc->osdev,
657 &ipa_res->tx_comp_ring.mem_info) ||
658 !qdf_mem_get_dma_addr(soc->osdev, &ipa_res->rx_rdy_ring.mem_info))
Yun Parkfde6b9e2017-06-26 17:13:11 -0700659 return QDF_STATUS_E_FAILURE;
660
661 return QDF_STATUS_SUCCESS;
662}
663
Vevek Venkatesan2cc8c5d2019-08-22 16:29:46 +0530664QDF_STATUS dp_ipa_set_doorbell_paddr(struct cdp_soc_t *soc_hdl, uint8_t pdev_id)
Yun Parkfde6b9e2017-06-26 17:13:11 -0700665{
Vevek Venkatesan2cc8c5d2019-08-22 16:29:46 +0530666 struct dp_soc *soc = cdp_soc_t_to_dp_soc(soc_hdl);
667 struct dp_pdev *pdev =
668 dp_get_pdev_from_soc_pdev_id_wifi3(soc, pdev_id);
669 struct dp_ipa_resources *ipa_res;
Akshay Kosigi8eda31c2019-07-10 14:42:42 +0530670 struct hal_srng *wbm_srng = (struct hal_srng *)
Yun Park601d0d82017-08-28 21:49:31 -0700671 soc->tx_comp_ring[IPA_TX_COMP_RING_IDX].hal_srng;
Akshay Kosigi8eda31c2019-07-10 14:42:42 +0530672 struct hal_srng *reo_srng = (struct hal_srng *)
Yun Park601d0d82017-08-28 21:49:31 -0700673 soc->reo_dest_ring[IPA_REO_DEST_RING_IDX].hal_srng;
jiad3b8104b2019-03-08 17:23:35 +0800674 uint32_t tx_comp_doorbell_dmaaddr;
675 uint32_t rx_ready_doorbell_dmaaddr;
Yun Parkfde6b9e2017-06-26 17:13:11 -0700676
Vevek Venkatesan2cc8c5d2019-08-22 16:29:46 +0530677 if (!pdev) {
678 dp_err("%s invalid instance", __func__);
679 return QDF_STATUS_E_FAILURE;
680 }
681
682 ipa_res = &pdev->ipa_resource;
Mohit Khanna81179cb2018-08-16 20:50:43 -0700683 if (!wlan_cfg_is_ipa_enabled(soc->wlan_cfg_ctx))
684 return QDF_STATUS_SUCCESS;
Yun Parkfde6b9e2017-06-26 17:13:11 -0700685
Mohit Khanna81179cb2018-08-16 20:50:43 -0700686 ipa_res->tx_comp_doorbell_vaddr =
687 ioremap(ipa_res->tx_comp_doorbell_paddr, 4);
jiad3b8104b2019-03-08 17:23:35 +0800688
689 if (qdf_mem_smmu_s1_enabled(soc->osdev)) {
690 pld_smmu_map(soc->osdev->dev, ipa_res->tx_comp_doorbell_paddr,
691 &tx_comp_doorbell_dmaaddr, sizeof(uint32_t));
692 ipa_res->tx_comp_doorbell_paddr = tx_comp_doorbell_dmaaddr;
693
694 pld_smmu_map(soc->osdev->dev, ipa_res->rx_ready_doorbell_paddr,
695 &rx_ready_doorbell_dmaaddr, sizeof(uint32_t));
696 ipa_res->rx_ready_doorbell_paddr = rx_ready_doorbell_dmaaddr;
697 }
698
699 hal_srng_dst_set_hp_paddr(wbm_srng, ipa_res->tx_comp_doorbell_paddr);
700
Mohit Khanna81179cb2018-08-16 20:50:43 -0700701 dp_info("paddr %pK vaddr %pK",
702 (void *)ipa_res->tx_comp_doorbell_paddr,
703 (void *)ipa_res->tx_comp_doorbell_vaddr);
704
Mohit Khanna81179cb2018-08-16 20:50:43 -0700705 /*
706 * For RX, REO module on Napier/Hastings does reordering on incoming
707 * Ethernet packets and writes one or more descriptors to REO2IPA Rx
708 * ring.It then updates the ring’s Write/Head ptr and rings a doorbell
709 * to IPA.
710 * Set the doorbell addr for the REO ring.
711 */
712 hal_srng_dst_set_hp_paddr(reo_srng, ipa_res->rx_ready_doorbell_paddr);
Yun Parkfde6b9e2017-06-26 17:13:11 -0700713 return QDF_STATUS_SUCCESS;
714}
715
Vevek Venkatesan2cc8c5d2019-08-22 16:29:46 +0530716QDF_STATUS dp_ipa_op_response(struct cdp_soc_t *soc_hdl, uint8_t pdev_id,
717 uint8_t *op_msg)
Yun Parkfde6b9e2017-06-26 17:13:11 -0700718{
Vevek Venkatesan2cc8c5d2019-08-22 16:29:46 +0530719 struct dp_soc *soc = cdp_soc_t_to_dp_soc(soc_hdl);
720 struct dp_pdev *pdev =
721 dp_get_pdev_from_soc_pdev_id_wifi3(soc, pdev_id);
722
723 if (!pdev) {
724 dp_err("%s invalid instance", __func__);
725 return QDF_STATUS_E_FAILURE;
726 }
Yun Parkfde6b9e2017-06-26 17:13:11 -0700727
Mohit Khanna81179cb2018-08-16 20:50:43 -0700728 if (!wlan_cfg_is_ipa_enabled(pdev->soc->wlan_cfg_ctx))
729 return QDF_STATUS_SUCCESS;
730
Yun Parkfde6b9e2017-06-26 17:13:11 -0700731 if (pdev->ipa_uc_op_cb) {
732 pdev->ipa_uc_op_cb(op_msg, pdev->usr_ctxt);
733 } else {
734 QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
735 "%s: IPA callback function is not registered", __func__);
736 qdf_mem_free(op_msg);
737 return QDF_STATUS_E_FAILURE;
738 }
739
740 return QDF_STATUS_SUCCESS;
741}
742
Vevek Venkatesan2cc8c5d2019-08-22 16:29:46 +0530743QDF_STATUS dp_ipa_register_op_cb(struct cdp_soc_t *soc_hdl, uint8_t pdev_id,
Yun Parkfde6b9e2017-06-26 17:13:11 -0700744 ipa_uc_op_cb_type op_cb,
745 void *usr_ctxt)
746{
Vevek Venkatesan2cc8c5d2019-08-22 16:29:46 +0530747 struct dp_soc *soc = cdp_soc_t_to_dp_soc(soc_hdl);
748 struct dp_pdev *pdev =
749 dp_get_pdev_from_soc_pdev_id_wifi3(soc, pdev_id);
750
751 if (!pdev) {
752 dp_err("%s invalid instance", __func__);
753 return QDF_STATUS_E_FAILURE;
754 }
Yun Parkfde6b9e2017-06-26 17:13:11 -0700755
Mohit Khanna81179cb2018-08-16 20:50:43 -0700756 if (!wlan_cfg_is_ipa_enabled(pdev->soc->wlan_cfg_ctx))
757 return QDF_STATUS_SUCCESS;
758
Yun Parkfde6b9e2017-06-26 17:13:11 -0700759 pdev->ipa_uc_op_cb = op_cb;
760 pdev->usr_ctxt = usr_ctxt;
761
762 return QDF_STATUS_SUCCESS;
763}
764
Vevek Venkatesan2cc8c5d2019-08-22 16:29:46 +0530765QDF_STATUS dp_ipa_get_stat(struct cdp_soc_t *soc_hdl, uint8_t pdev_id)
Yun Parkfde6b9e2017-06-26 17:13:11 -0700766{
767 /* TBD */
768 return QDF_STATUS_SUCCESS;
769}
770
Pavankumar Nandeshwara2347162019-12-18 23:20:31 +0530771/**
772 * dp_tx_send_ipa_data_frame() - send IPA data frame
773 * @soc_hdl: datapath soc handle
774 * @vdev_id: id of the virtual device
775 * @skb: skb to transmit
776 *
777 * Return: skb/ NULL is for success
778 */
Vevek Venkatesan2cc8c5d2019-08-22 16:29:46 +0530779qdf_nbuf_t dp_tx_send_ipa_data_frame(struct cdp_soc_t *soc_hdl, uint8_t vdev_id,
780 qdf_nbuf_t skb)
Yun Parkfde6b9e2017-06-26 17:13:11 -0700781{
782 qdf_nbuf_t ret;
783
784 /* Terminate the (single-element) list of tx frames */
785 qdf_nbuf_set_next(skb, NULL);
Pavankumar Nandeshwara2347162019-12-18 23:20:31 +0530786 ret = dp_tx_send(soc_hdl, vdev_id, skb);
Yun Parkfde6b9e2017-06-26 17:13:11 -0700787 if (ret) {
788 QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
Yun Park4711ade2017-08-28 21:49:31 -0700789 "%s: Failed to tx", __func__);
Yun Parkfde6b9e2017-06-26 17:13:11 -0700790 return ret;
791 }
792
793 return NULL;
794}
795
Vevek Venkatesan2cc8c5d2019-08-22 16:29:46 +0530796QDF_STATUS dp_ipa_enable_autonomy(struct cdp_soc_t *soc_hdl, uint8_t pdev_id)
Yun Parkfde6b9e2017-06-26 17:13:11 -0700797{
Vevek Venkatesan2cc8c5d2019-08-22 16:29:46 +0530798 struct dp_soc *soc = cdp_soc_t_to_dp_soc(soc_hdl);
799 struct dp_pdev *pdev =
800 dp_get_pdev_from_soc_pdev_id_wifi3(soc, pdev_id);
jiad09526ac2019-04-12 17:42:40 +0800801 uint32_t ix0;
802 uint32_t ix2;
Yun Parkfde6b9e2017-06-26 17:13:11 -0700803
Vevek Venkatesan2cc8c5d2019-08-22 16:29:46 +0530804 if (!pdev) {
805 dp_err("%s invalid instance", __func__);
806 return QDF_STATUS_E_FAILURE;
807 }
808
Mohit Khanna81179cb2018-08-16 20:50:43 -0700809 if (!wlan_cfg_is_ipa_enabled(soc->wlan_cfg_ctx))
810 return QDF_STATUS_SUCCESS;
811
Rakesh Pillaieee5d782019-11-13 15:44:12 +0530812 if (!hif_is_target_ready(HIF_GET_SOFTC(soc->hif_handle)))
813 return QDF_STATUS_E_AGAIN;
814
Yun Parkfde6b9e2017-06-26 17:13:11 -0700815 /* Call HAL API to remap REO rings to REO2IPA ring */
Venkata Sharath Chandra Manchalac9e344d2019-10-23 14:13:14 -0700816 ix0 = HAL_REO_REMAP_IX0(REO_REMAP_TCL, 0) |
817 HAL_REO_REMAP_IX0(REO_REMAP_SW4, 1) |
818 HAL_REO_REMAP_IX0(REO_REMAP_SW4, 2) |
819 HAL_REO_REMAP_IX0(REO_REMAP_SW4, 3) |
820 HAL_REO_REMAP_IX0(REO_REMAP_SW4, 4) |
821 HAL_REO_REMAP_IX0(REO_REMAP_RELEASE, 5) |
822 HAL_REO_REMAP_IX0(REO_REMAP_FW, 6) |
823 HAL_REO_REMAP_IX0(REO_REMAP_FW, 7);
jiad09526ac2019-04-12 17:42:40 +0800824
825 if (wlan_cfg_is_rx_hash_enabled(soc->wlan_cfg_ctx)) {
Venkata Sharath Chandra Manchalac9e344d2019-10-23 14:13:14 -0700826 ix2 = HAL_REO_REMAP_IX2(REO_REMAP_SW4, 16) |
827 HAL_REO_REMAP_IX2(REO_REMAP_SW4, 17) |
828 HAL_REO_REMAP_IX2(REO_REMAP_SW4, 18) |
829 HAL_REO_REMAP_IX2(REO_REMAP_SW4, 19) |
830 HAL_REO_REMAP_IX2(REO_REMAP_SW4, 20) |
831 HAL_REO_REMAP_IX2(REO_REMAP_SW4, 21) |
832 HAL_REO_REMAP_IX2(REO_REMAP_SW4, 22) |
833 HAL_REO_REMAP_IX2(REO_REMAP_SW4, 23);
jiad09526ac2019-04-12 17:42:40 +0800834
Jia Dingc0315752019-07-15 17:44:12 +0800835 hal_reo_read_write_ctrl_ix(soc->hal_soc, false, &ix0, NULL,
836 &ix2, &ix2);
Sravan Goudba1d5aa2019-11-27 18:59:14 +0530837 dp_ipa_reo_remap_history_add(ix0, ix2, ix2);
Jia Dingc0315752019-07-15 17:44:12 +0800838 } else {
839 hal_reo_read_write_ctrl_ix(soc->hal_soc, false, &ix0, NULL,
840 NULL, NULL);
Sravan Goudba1d5aa2019-11-27 18:59:14 +0530841 dp_ipa_reo_remap_history_add(ix0, 0, 0);
Jia Dingc0315752019-07-15 17:44:12 +0800842 }
Venkata Sharath Chandra Manchalac9e344d2019-10-23 14:13:14 -0700843
Yun Parkfde6b9e2017-06-26 17:13:11 -0700844 return QDF_STATUS_SUCCESS;
845}
846
Vevek Venkatesan2cc8c5d2019-08-22 16:29:46 +0530847QDF_STATUS dp_ipa_disable_autonomy(struct cdp_soc_t *soc_hdl, uint8_t pdev_id)
Yun Parkfde6b9e2017-06-26 17:13:11 -0700848{
Vevek Venkatesan2cc8c5d2019-08-22 16:29:46 +0530849 struct dp_soc *soc = cdp_soc_t_to_dp_soc(soc_hdl);
850 struct dp_pdev *pdev =
851 dp_get_pdev_from_soc_pdev_id_wifi3(soc, pdev_id);
jiad09526ac2019-04-12 17:42:40 +0800852 uint32_t ix0;
853 uint32_t ix2;
854 uint32_t ix3;
Yun Parkfde6b9e2017-06-26 17:13:11 -0700855
Vevek Venkatesan2cc8c5d2019-08-22 16:29:46 +0530856 if (!pdev) {
857 dp_err("%s invalid instance", __func__);
858 return QDF_STATUS_E_FAILURE;
859 }
860
Mohit Khanna81179cb2018-08-16 20:50:43 -0700861 if (!wlan_cfg_is_ipa_enabled(soc->wlan_cfg_ctx))
862 return QDF_STATUS_SUCCESS;
863
Rakesh Pillaieee5d782019-11-13 15:44:12 +0530864 if (!hif_is_target_ready(HIF_GET_SOFTC(soc->hif_handle)))
865 return QDF_STATUS_E_AGAIN;
866
Yun Parkfde6b9e2017-06-26 17:13:11 -0700867 /* Call HAL API to remap REO rings to REO2IPA ring */
Venkata Sharath Chandra Manchalac9e344d2019-10-23 14:13:14 -0700868 ix0 = HAL_REO_REMAP_IX0(REO_REMAP_TCL, 0) |
869 HAL_REO_REMAP_IX0(REO_REMAP_SW1, 1) |
870 HAL_REO_REMAP_IX0(REO_REMAP_SW2, 2) |
871 HAL_REO_REMAP_IX0(REO_REMAP_SW3, 3) |
872 HAL_REO_REMAP_IX0(REO_REMAP_SW2, 4) |
873 HAL_REO_REMAP_IX0(REO_REMAP_RELEASE, 5) |
874 HAL_REO_REMAP_IX0(REO_REMAP_FW, 6) |
875 HAL_REO_REMAP_IX0(REO_REMAP_FW, 7);
jiad09526ac2019-04-12 17:42:40 +0800876
877 if (wlan_cfg_is_rx_hash_enabled(soc->wlan_cfg_ctx)) {
878 dp_reo_remap_config(soc, &ix2, &ix3);
879
880 hal_reo_read_write_ctrl_ix(soc->hal_soc, false, &ix0, NULL,
881 &ix2, &ix3);
Sravan Goudba1d5aa2019-11-27 18:59:14 +0530882 dp_ipa_reo_remap_history_add(ix0, ix2, ix3);
Jia Dingc0315752019-07-15 17:44:12 +0800883 } else {
884 hal_reo_read_write_ctrl_ix(soc->hal_soc, false, &ix0, NULL,
885 NULL, NULL);
Sravan Goudba1d5aa2019-11-27 18:59:14 +0530886 dp_ipa_reo_remap_history_add(ix0, 0, 0);
jiad09526ac2019-04-12 17:42:40 +0800887 }
Yun Parkfde6b9e2017-06-26 17:13:11 -0700888
889 return QDF_STATUS_SUCCESS;
890}
891
892/* This should be configurable per H/W configuration enable status */
893#define L3_HEADER_PADDING 2
894
Mohit Khannaf83015c2018-02-13 08:29:39 -0800895#ifdef CONFIG_IPA_WDI_UNIFIED_API
896
897#ifndef QCA_LL_TX_FLOW_CONTROL_V2
898static inline void dp_setup_mcc_sys_pipes(
899 qdf_ipa_sys_connect_params_t *sys_in,
900 qdf_ipa_wdi_conn_in_params_t *pipe_in)
901{
902 /* Setup MCC sys pipe */
903 QDF_IPA_WDI_CONN_IN_PARAMS_NUM_SYS_PIPE_NEEDED(pipe_in) =
904 DP_IPA_MAX_IFACE;
905 for (int i = 0; i < DP_IPA_MAX_IFACE; i++)
906 memcpy(&QDF_IPA_WDI_CONN_IN_PARAMS_SYS_IN(pipe_in)[i],
907 &sys_in[i], sizeof(qdf_ipa_sys_connect_params_t));
908}
909#else
910static inline void dp_setup_mcc_sys_pipes(
911 qdf_ipa_sys_connect_params_t *sys_in,
912 qdf_ipa_wdi_conn_in_params_t *pipe_in)
913{
914 QDF_IPA_WDI_CONN_IN_PARAMS_NUM_SYS_PIPE_NEEDED(pipe_in) = 0;
915}
916#endif
917
jiad3b8104b2019-03-08 17:23:35 +0800918static void dp_ipa_wdi_tx_params(struct dp_soc *soc,
919 struct dp_ipa_resources *ipa_res,
920 qdf_ipa_wdi_pipe_setup_info_t *tx,
921 bool over_gsi)
922{
923 struct tcl_data_cmd *tcl_desc_ptr;
924 uint8_t *desc_addr;
925 uint32_t desc_size;
926
927 if (over_gsi)
928 QDF_IPA_WDI_SETUP_INFO_CLIENT(tx) = IPA_CLIENT_WLAN2_CONS;
929 else
930 QDF_IPA_WDI_SETUP_INFO_CLIENT(tx) = IPA_CLIENT_WLAN1_CONS;
931
932 QDF_IPA_WDI_SETUP_INFO_TRANSFER_RING_BASE_PA(tx) =
933 qdf_mem_get_dma_addr(soc->osdev,
934 &ipa_res->tx_comp_ring.mem_info);
935 QDF_IPA_WDI_SETUP_INFO_TRANSFER_RING_SIZE(tx) =
936 qdf_mem_get_dma_size(soc->osdev,
937 &ipa_res->tx_comp_ring.mem_info);
938
939 /* WBM Tail Pointer Address */
940 QDF_IPA_WDI_SETUP_INFO_TRANSFER_RING_DOORBELL_PA(tx) =
941 soc->ipa_uc_tx_rsc.ipa_wbm_tp_paddr;
jiad443059e2019-03-05 15:26:32 +0800942 QDF_IPA_WDI_SETUP_INFO_IS_TXR_RN_DB_PCIE_ADDR(tx) = true;
jiad3b8104b2019-03-08 17:23:35 +0800943
944 QDF_IPA_WDI_SETUP_INFO_EVENT_RING_BASE_PA(tx) =
945 qdf_mem_get_dma_addr(soc->osdev,
946 &ipa_res->tx_ring.mem_info);
947 QDF_IPA_WDI_SETUP_INFO_EVENT_RING_SIZE(tx) =
948 qdf_mem_get_dma_size(soc->osdev,
949 &ipa_res->tx_ring.mem_info);
950
951 /* TCL Head Pointer Address */
952 QDF_IPA_WDI_SETUP_INFO_EVENT_RING_DOORBELL_PA(tx) =
953 soc->ipa_uc_tx_rsc.ipa_tcl_hp_paddr;
jiad443059e2019-03-05 15:26:32 +0800954 QDF_IPA_WDI_SETUP_INFO_IS_EVT_RN_DB_PCIE_ADDR(tx) = true;
jiad3b8104b2019-03-08 17:23:35 +0800955
956 QDF_IPA_WDI_SETUP_INFO_NUM_PKT_BUFFERS(tx) =
957 ipa_res->tx_num_alloc_buffer;
958
959 QDF_IPA_WDI_SETUP_INFO_PKT_OFFSET(tx) = 0;
960
961 /* Preprogram TCL descriptor */
962 desc_addr =
963 (uint8_t *)QDF_IPA_WDI_SETUP_INFO_DESC_FORMAT_TEMPLATE(tx);
964 desc_size = sizeof(struct tcl_data_cmd);
965 HAL_TX_DESC_SET_TLV_HDR(desc_addr, HAL_TX_TCL_DATA_TAG, desc_size);
966 tcl_desc_ptr = (struct tcl_data_cmd *)
967 (QDF_IPA_WDI_SETUP_INFO_DESC_FORMAT_TEMPLATE(tx) + 1);
968 tcl_desc_ptr->buf_addr_info.return_buffer_manager =
969 HAL_RX_BUF_RBM_SW2_BM;
970 tcl_desc_ptr->addrx_en = 1; /* Address X search enable in ASE */
971 tcl_desc_ptr->encap_type = HAL_TX_ENCAP_TYPE_ETHERNET;
972 tcl_desc_ptr->packet_offset = 2; /* padding for alignment */
973}
974
975static void dp_ipa_wdi_rx_params(struct dp_soc *soc,
976 struct dp_ipa_resources *ipa_res,
977 qdf_ipa_wdi_pipe_setup_info_t *rx,
978 bool over_gsi)
979{
980 if (over_gsi)
981 QDF_IPA_WDI_SETUP_INFO_CLIENT(rx) =
982 IPA_CLIENT_WLAN2_PROD;
983 else
984 QDF_IPA_WDI_SETUP_INFO_CLIENT(rx) =
985 IPA_CLIENT_WLAN1_PROD;
986
987 QDF_IPA_WDI_SETUP_INFO_TRANSFER_RING_BASE_PA(rx) =
988 qdf_mem_get_dma_addr(soc->osdev,
989 &ipa_res->rx_rdy_ring.mem_info);
990 QDF_IPA_WDI_SETUP_INFO_TRANSFER_RING_SIZE(rx) =
991 qdf_mem_get_dma_size(soc->osdev,
992 &ipa_res->rx_rdy_ring.mem_info);
993
994 /* REO Tail Pointer Address */
995 QDF_IPA_WDI_SETUP_INFO_TRANSFER_RING_DOORBELL_PA(rx) =
996 soc->ipa_uc_rx_rsc.ipa_reo_tp_paddr;
jiad443059e2019-03-05 15:26:32 +0800997 QDF_IPA_WDI_SETUP_INFO_IS_TXR_RN_DB_PCIE_ADDR(rx) = true;
jiad3b8104b2019-03-08 17:23:35 +0800998
999 QDF_IPA_WDI_SETUP_INFO_EVENT_RING_BASE_PA(rx) =
1000 qdf_mem_get_dma_addr(soc->osdev,
1001 &ipa_res->rx_refill_ring.mem_info);
1002 QDF_IPA_WDI_SETUP_INFO_EVENT_RING_SIZE(rx) =
1003 qdf_mem_get_dma_size(soc->osdev,
1004 &ipa_res->rx_refill_ring.mem_info);
1005
1006 /* FW Head Pointer Address */
1007 QDF_IPA_WDI_SETUP_INFO_EVENT_RING_DOORBELL_PA(rx) =
1008 soc->ipa_uc_rx_rsc.ipa_rx_refill_buf_hp_paddr;
jiad443059e2019-03-05 15:26:32 +08001009 QDF_IPA_WDI_SETUP_INFO_IS_EVT_RN_DB_PCIE_ADDR(rx) = false;
jiad3b8104b2019-03-08 17:23:35 +08001010
1011 QDF_IPA_WDI_SETUP_INFO_PKT_OFFSET(rx) =
1012 RX_PKT_TLVS_LEN + L3_HEADER_PADDING;
1013}
1014
1015static void
1016dp_ipa_wdi_tx_smmu_params(struct dp_soc *soc,
1017 struct dp_ipa_resources *ipa_res,
1018 qdf_ipa_wdi_pipe_setup_info_smmu_t *tx_smmu,
1019 bool over_gsi)
1020{
1021 struct tcl_data_cmd *tcl_desc_ptr;
1022 uint8_t *desc_addr;
1023 uint32_t desc_size;
1024
1025 if (over_gsi)
1026 QDF_IPA_WDI_SETUP_INFO_SMMU_CLIENT(tx_smmu) =
1027 IPA_CLIENT_WLAN2_CONS;
1028 else
1029 QDF_IPA_WDI_SETUP_INFO_SMMU_CLIENT(tx_smmu) =
1030 IPA_CLIENT_WLAN1_CONS;
1031
1032 qdf_mem_copy(&QDF_IPA_WDI_SETUP_INFO_SMMU_TRANSFER_RING_BASE(tx_smmu),
1033 &ipa_res->tx_comp_ring.sgtable,
1034 sizeof(sgtable_t));
1035 QDF_IPA_WDI_SETUP_INFO_SMMU_TRANSFER_RING_SIZE(tx_smmu) =
1036 qdf_mem_get_dma_size(soc->osdev,
1037 &ipa_res->tx_comp_ring.mem_info);
1038 /* WBM Tail Pointer Address */
1039 QDF_IPA_WDI_SETUP_INFO_SMMU_TRANSFER_RING_DOORBELL_PA(tx_smmu) =
1040 soc->ipa_uc_tx_rsc.ipa_wbm_tp_paddr;
jiad443059e2019-03-05 15:26:32 +08001041 QDF_IPA_WDI_SETUP_INFO_SMMU_IS_TXR_RN_DB_PCIE_ADDR(tx_smmu) = true;
jiad3b8104b2019-03-08 17:23:35 +08001042
1043 qdf_mem_copy(&QDF_IPA_WDI_SETUP_INFO_SMMU_EVENT_RING_BASE(tx_smmu),
1044 &ipa_res->tx_ring.sgtable,
1045 sizeof(sgtable_t));
1046 QDF_IPA_WDI_SETUP_INFO_SMMU_EVENT_RING_SIZE(tx_smmu) =
1047 qdf_mem_get_dma_size(soc->osdev,
1048 &ipa_res->tx_ring.mem_info);
1049 /* TCL Head Pointer Address */
1050 QDF_IPA_WDI_SETUP_INFO_SMMU_EVENT_RING_DOORBELL_PA(tx_smmu) =
1051 soc->ipa_uc_tx_rsc.ipa_tcl_hp_paddr;
jiad443059e2019-03-05 15:26:32 +08001052 QDF_IPA_WDI_SETUP_INFO_SMMU_IS_EVT_RN_DB_PCIE_ADDR(tx_smmu) = true;
jiad3b8104b2019-03-08 17:23:35 +08001053
1054 QDF_IPA_WDI_SETUP_INFO_SMMU_NUM_PKT_BUFFERS(tx_smmu) =
1055 ipa_res->tx_num_alloc_buffer;
1056 QDF_IPA_WDI_SETUP_INFO_SMMU_PKT_OFFSET(tx_smmu) = 0;
1057
1058 /* Preprogram TCL descriptor */
1059 desc_addr = (uint8_t *)QDF_IPA_WDI_SETUP_INFO_SMMU_DESC_FORMAT_TEMPLATE(
1060 tx_smmu);
1061 desc_size = sizeof(struct tcl_data_cmd);
1062 HAL_TX_DESC_SET_TLV_HDR(desc_addr, HAL_TX_TCL_DATA_TAG, desc_size);
1063 tcl_desc_ptr = (struct tcl_data_cmd *)
1064 (QDF_IPA_WDI_SETUP_INFO_SMMU_DESC_FORMAT_TEMPLATE(tx_smmu) + 1);
1065 tcl_desc_ptr->buf_addr_info.return_buffer_manager =
1066 HAL_RX_BUF_RBM_SW2_BM;
1067 tcl_desc_ptr->addrx_en = 1; /* Address X search enable in ASE */
1068 tcl_desc_ptr->encap_type = HAL_TX_ENCAP_TYPE_ETHERNET;
1069 tcl_desc_ptr->packet_offset = 2; /* padding for alignment */
1070}
1071
1072static void
1073dp_ipa_wdi_rx_smmu_params(struct dp_soc *soc,
1074 struct dp_ipa_resources *ipa_res,
1075 qdf_ipa_wdi_pipe_setup_info_smmu_t *rx_smmu,
1076 bool over_gsi)
1077{
1078 if (over_gsi)
1079 QDF_IPA_WDI_SETUP_INFO_SMMU_CLIENT(rx_smmu) =
1080 IPA_CLIENT_WLAN2_PROD;
1081 else
1082 QDF_IPA_WDI_SETUP_INFO_SMMU_CLIENT(rx_smmu) =
1083 IPA_CLIENT_WLAN1_PROD;
1084
1085 qdf_mem_copy(&QDF_IPA_WDI_SETUP_INFO_SMMU_TRANSFER_RING_BASE(rx_smmu),
1086 &ipa_res->rx_rdy_ring.sgtable,
1087 sizeof(sgtable_t));
1088 QDF_IPA_WDI_SETUP_INFO_SMMU_TRANSFER_RING_SIZE(rx_smmu) =
1089 qdf_mem_get_dma_size(soc->osdev,
1090 &ipa_res->rx_rdy_ring.mem_info);
1091 /* REO Tail Pointer Address */
1092 QDF_IPA_WDI_SETUP_INFO_SMMU_TRANSFER_RING_DOORBELL_PA(rx_smmu) =
1093 soc->ipa_uc_rx_rsc.ipa_reo_tp_paddr;
jiad443059e2019-03-05 15:26:32 +08001094 QDF_IPA_WDI_SETUP_INFO_SMMU_IS_TXR_RN_DB_PCIE_ADDR(rx_smmu) = true;
jiad3b8104b2019-03-08 17:23:35 +08001095
1096 qdf_mem_copy(&QDF_IPA_WDI_SETUP_INFO_SMMU_EVENT_RING_BASE(rx_smmu),
1097 &ipa_res->rx_refill_ring.sgtable,
1098 sizeof(sgtable_t));
1099 QDF_IPA_WDI_SETUP_INFO_SMMU_EVENT_RING_SIZE(rx_smmu) =
1100 qdf_mem_get_dma_size(soc->osdev,
1101 &ipa_res->rx_refill_ring.mem_info);
1102
1103 /* FW Head Pointer Address */
1104 QDF_IPA_WDI_SETUP_INFO_SMMU_EVENT_RING_DOORBELL_PA(rx_smmu) =
1105 soc->ipa_uc_rx_rsc.ipa_rx_refill_buf_hp_paddr;
jiad443059e2019-03-05 15:26:32 +08001106 QDF_IPA_WDI_SETUP_INFO_SMMU_IS_EVT_RN_DB_PCIE_ADDR(rx_smmu) = false;
jiad3b8104b2019-03-08 17:23:35 +08001107
1108 QDF_IPA_WDI_SETUP_INFO_SMMU_PKT_OFFSET(rx_smmu) =
1109 RX_PKT_TLVS_LEN + L3_HEADER_PADDING;
1110}
1111
Vevek Venkatesan2cc8c5d2019-08-22 16:29:46 +05301112QDF_STATUS dp_ipa_setup(struct cdp_soc_t *soc_hdl, uint8_t pdev_id,
1113 void *ipa_i2w_cb, void *ipa_w2i_cb,
1114 void *ipa_wdi_meter_notifier_cb,
Mohit Khannaf83015c2018-02-13 08:29:39 -08001115 uint32_t ipa_desc_size, void *ipa_priv,
1116 bool is_rm_enabled, uint32_t *tx_pipe_handle,
1117 uint32_t *rx_pipe_handle, bool is_smmu_enabled,
Sravan Kumar Kairamfc3c8cf2018-11-19 18:32:50 +05301118 qdf_ipa_sys_connect_params_t *sys_in, bool over_gsi)
Mohit Khannaf83015c2018-02-13 08:29:39 -08001119{
Vevek Venkatesan2cc8c5d2019-08-22 16:29:46 +05301120 struct dp_soc *soc = cdp_soc_t_to_dp_soc(soc_hdl);
1121 struct dp_pdev *pdev =
1122 dp_get_pdev_from_soc_pdev_id_wifi3(soc, pdev_id);
1123 struct dp_ipa_resources *ipa_res;
Mohit Khannaf83015c2018-02-13 08:29:39 -08001124 qdf_ipa_ep_cfg_t *tx_cfg;
1125 qdf_ipa_ep_cfg_t *rx_cfg;
Saket Jhac7341382019-06-13 17:37:58 -07001126 qdf_ipa_wdi_pipe_setup_info_t *tx = NULL;
1127 qdf_ipa_wdi_pipe_setup_info_t *rx = NULL;
Mohit Khannaf83015c2018-02-13 08:29:39 -08001128 qdf_ipa_wdi_pipe_setup_info_smmu_t *tx_smmu;
1129 qdf_ipa_wdi_pipe_setup_info_smmu_t *rx_smmu;
1130 qdf_ipa_wdi_conn_in_params_t pipe_in;
1131 qdf_ipa_wdi_conn_out_params_t pipe_out;
Mohit Khannaf83015c2018-02-13 08:29:39 -08001132 int ret;
1133
Vevek Venkatesan2cc8c5d2019-08-22 16:29:46 +05301134 if (!pdev) {
1135 dp_err("%s invalid instance", __func__);
1136 return QDF_STATUS_E_FAILURE;
1137 }
1138
1139 ipa_res = &pdev->ipa_resource;
Mohit Khanna81179cb2018-08-16 20:50:43 -07001140 if (!wlan_cfg_is_ipa_enabled(soc->wlan_cfg_ctx))
1141 return QDF_STATUS_SUCCESS;
1142
Mohit Khannaf83015c2018-02-13 08:29:39 -08001143 qdf_mem_zero(&pipe_in, sizeof(pipe_in));
1144 qdf_mem_zero(&pipe_out, sizeof(pipe_out));
1145
1146 if (is_smmu_enabled)
1147 QDF_IPA_WDI_CONN_IN_PARAMS_SMMU_ENABLED(&pipe_in) = true;
1148 else
1149 QDF_IPA_WDI_CONN_IN_PARAMS_SMMU_ENABLED(&pipe_in) = false;
1150
1151 dp_setup_mcc_sys_pipes(sys_in, &pipe_in);
1152
1153 /* TX PIPE */
1154 if (QDF_IPA_WDI_CONN_IN_PARAMS_SMMU_ENABLED(&pipe_in)) {
1155 tx_smmu = &QDF_IPA_WDI_CONN_IN_PARAMS_TX_SMMU(&pipe_in);
1156 tx_cfg = &QDF_IPA_WDI_SETUP_INFO_SMMU_EP_CFG(tx_smmu);
1157 } else {
1158 tx = &QDF_IPA_WDI_CONN_IN_PARAMS_TX(&pipe_in);
1159 tx_cfg = &QDF_IPA_WDI_SETUP_INFO_EP_CFG(tx);
1160 }
1161
1162 QDF_IPA_EP_CFG_NAT_EN(tx_cfg) = IPA_BYPASS_NAT;
1163 QDF_IPA_EP_CFG_HDR_LEN(tx_cfg) = DP_IPA_UC_WLAN_TX_HDR_LEN;
1164 QDF_IPA_EP_CFG_HDR_OFST_PKT_SIZE_VALID(tx_cfg) = 0;
1165 QDF_IPA_EP_CFG_HDR_OFST_PKT_SIZE(tx_cfg) = 0;
1166 QDF_IPA_EP_CFG_HDR_ADDITIONAL_CONST_LEN(tx_cfg) = 0;
1167 QDF_IPA_EP_CFG_MODE(tx_cfg) = IPA_BASIC;
1168 QDF_IPA_EP_CFG_HDR_LITTLE_ENDIAN(tx_cfg) = true;
1169
1170 /**
1171 * Transfer Ring: WBM Ring
1172 * Transfer Ring Doorbell PA: WBM Tail Pointer Address
1173 * Event Ring: TCL ring
1174 * Event Ring Doorbell PA: TCL Head Pointer Address
1175 */
jiad3b8104b2019-03-08 17:23:35 +08001176 if (is_smmu_enabled)
1177 dp_ipa_wdi_tx_smmu_params(soc, ipa_res, tx_smmu, over_gsi);
Sravan Kumar Kairamfc3c8cf2018-11-19 18:32:50 +05301178 else
jiad3b8104b2019-03-08 17:23:35 +08001179 dp_ipa_wdi_tx_params(soc, ipa_res, tx, over_gsi);
Mohit Khannaf83015c2018-02-13 08:29:39 -08001180
1181 /* RX PIPE */
1182 if (QDF_IPA_WDI_CONN_IN_PARAMS_SMMU_ENABLED(&pipe_in)) {
1183 rx_smmu = &QDF_IPA_WDI_CONN_IN_PARAMS_RX_SMMU(&pipe_in);
1184 rx_cfg = &QDF_IPA_WDI_SETUP_INFO_SMMU_EP_CFG(rx_smmu);
1185 } else {
1186 rx = &QDF_IPA_WDI_CONN_IN_PARAMS_RX(&pipe_in);
1187 rx_cfg = &QDF_IPA_WDI_SETUP_INFO_EP_CFG(rx);
1188 }
1189
1190 QDF_IPA_EP_CFG_NAT_EN(rx_cfg) = IPA_BYPASS_NAT;
1191 QDF_IPA_EP_CFG_HDR_LEN(rx_cfg) = DP_IPA_UC_WLAN_RX_HDR_LEN;
1192 QDF_IPA_EP_CFG_HDR_OFST_PKT_SIZE_VALID(rx_cfg) = 1;
1193 QDF_IPA_EP_CFG_HDR_OFST_PKT_SIZE(rx_cfg) = 0;
1194 QDF_IPA_EP_CFG_HDR_ADDITIONAL_CONST_LEN(rx_cfg) = 0;
1195 QDF_IPA_EP_CFG_HDR_OFST_METADATA_VALID(rx_cfg) = 0;
1196 QDF_IPA_EP_CFG_HDR_METADATA_REG_VALID(rx_cfg) = 1;
1197 QDF_IPA_EP_CFG_MODE(rx_cfg) = IPA_BASIC;
1198 QDF_IPA_EP_CFG_HDR_LITTLE_ENDIAN(rx_cfg) = true;
1199
1200 /**
1201 * Transfer Ring: REO Ring
1202 * Transfer Ring Doorbell PA: REO Tail Pointer Address
1203 * Event Ring: FW ring
1204 * Event Ring Doorbell PA: FW Head Pointer Address
1205 */
jiad3b8104b2019-03-08 17:23:35 +08001206 if (is_smmu_enabled)
1207 dp_ipa_wdi_rx_smmu_params(soc, ipa_res, rx_smmu, over_gsi);
1208 else
1209 dp_ipa_wdi_rx_params(soc, ipa_res, rx, over_gsi);
Mohit Khannaf83015c2018-02-13 08:29:39 -08001210
1211 QDF_IPA_WDI_CONN_IN_PARAMS_NOTIFY(&pipe_in) = ipa_w2i_cb;
1212 QDF_IPA_WDI_CONN_IN_PARAMS_PRIV(&pipe_in) = ipa_priv;
1213
Mohit Khanna81179cb2018-08-16 20:50:43 -07001214 /* Connect WDI IPA PIPEs */
Mohit Khannaf83015c2018-02-13 08:29:39 -08001215 ret = qdf_ipa_wdi_conn_pipes(&pipe_in, &pipe_out);
Mohit Khanna81179cb2018-08-16 20:50:43 -07001216
Mohit Khannaf83015c2018-02-13 08:29:39 -08001217 if (ret) {
1218 QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
1219 "%s: ipa_wdi_conn_pipes: IPA pipe setup failed: ret=%d",
1220 __func__, ret);
1221 return QDF_STATUS_E_FAILURE;
1222 }
1223
1224 /* IPA uC Doorbell registers */
Mohit Khanna81179cb2018-08-16 20:50:43 -07001225 dp_info("Tx DB PA=0x%x, Rx DB PA=0x%x",
1226 (unsigned int)QDF_IPA_WDI_CONN_OUT_PARAMS_TX_UC_DB_PA(&pipe_out),
1227 (unsigned int)QDF_IPA_WDI_CONN_OUT_PARAMS_RX_UC_DB_PA(&pipe_out));
Mohit Khannaf83015c2018-02-13 08:29:39 -08001228
1229 ipa_res->tx_comp_doorbell_paddr =
1230 QDF_IPA_WDI_CONN_OUT_PARAMS_TX_UC_DB_PA(&pipe_out);
1231 ipa_res->rx_ready_doorbell_paddr =
1232 QDF_IPA_WDI_CONN_OUT_PARAMS_RX_UC_DB_PA(&pipe_out);
1233
Sravan Gouda4030a42020-01-13 13:17:21 +05301234 soc->ipa_first_tx_db_access = true;
1235
Mohit Khannaf83015c2018-02-13 08:29:39 -08001236 return QDF_STATUS_SUCCESS;
1237}
1238
1239/**
1240 * dp_ipa_setup_iface() - Setup IPA header and register interface
1241 * @ifname: Interface name
1242 * @mac_addr: Interface MAC address
1243 * @prod_client: IPA prod client type
1244 * @cons_client: IPA cons client type
1245 * @session_id: Session ID
1246 * @is_ipv6_enabled: Is IPV6 enabled or not
1247 *
1248 * Return: QDF_STATUS
1249 */
1250QDF_STATUS dp_ipa_setup_iface(char *ifname, uint8_t *mac_addr,
1251 qdf_ipa_client_type_t prod_client,
1252 qdf_ipa_client_type_t cons_client,
1253 uint8_t session_id, bool is_ipv6_enabled)
1254{
1255 qdf_ipa_wdi_reg_intf_in_params_t in;
1256 qdf_ipa_wdi_hdr_info_t hdr_info;
1257 struct dp_ipa_uc_tx_hdr uc_tx_hdr;
1258 struct dp_ipa_uc_tx_hdr uc_tx_hdr_v6;
1259 int ret = -EINVAL;
1260
Mohit Khanna81179cb2018-08-16 20:50:43 -07001261 dp_debug("Add Partial hdr: %s, %pM", ifname, mac_addr);
Mohit Khannaf83015c2018-02-13 08:29:39 -08001262 qdf_mem_zero(&hdr_info, sizeof(qdf_ipa_wdi_hdr_info_t));
1263 qdf_ether_addr_copy(uc_tx_hdr.eth.h_source, mac_addr);
1264
1265 /* IPV4 header */
1266 uc_tx_hdr.eth.h_proto = qdf_htons(ETH_P_IP);
1267
1268 QDF_IPA_WDI_HDR_INFO_HDR(&hdr_info) = (uint8_t *)&uc_tx_hdr;
1269 QDF_IPA_WDI_HDR_INFO_HDR_LEN(&hdr_info) = DP_IPA_UC_WLAN_TX_HDR_LEN;
1270 QDF_IPA_WDI_HDR_INFO_HDR_TYPE(&hdr_info) = IPA_HDR_L2_ETHERNET_II;
1271 QDF_IPA_WDI_HDR_INFO_DST_MAC_ADDR_OFFSET(&hdr_info) =
1272 DP_IPA_UC_WLAN_HDR_DES_MAC_OFFSET;
1273
1274 QDF_IPA_WDI_REG_INTF_IN_PARAMS_NETDEV_NAME(&in) = ifname;
1275 qdf_mem_copy(&(QDF_IPA_WDI_REG_INTF_IN_PARAMS_HDR_INFO(&in)[IPA_IP_v4]),
1276 &hdr_info, sizeof(qdf_ipa_wdi_hdr_info_t));
1277 QDF_IPA_WDI_REG_INTF_IN_PARAMS_ALT_DST_PIPE(&in) = cons_client;
1278 QDF_IPA_WDI_REG_INTF_IN_PARAMS_IS_META_DATA_VALID(&in) = 1;
1279 QDF_IPA_WDI_REG_INTF_IN_PARAMS_META_DATA(&in) =
1280 htonl(session_id << 16);
1281 QDF_IPA_WDI_REG_INTF_IN_PARAMS_META_DATA_MASK(&in) = htonl(0x00FF0000);
1282
1283 /* IPV6 header */
1284 if (is_ipv6_enabled) {
1285 qdf_mem_copy(&uc_tx_hdr_v6, &uc_tx_hdr,
1286 DP_IPA_UC_WLAN_TX_HDR_LEN);
1287 uc_tx_hdr_v6.eth.h_proto = qdf_htons(ETH_P_IPV6);
1288 QDF_IPA_WDI_HDR_INFO_HDR(&hdr_info) = (uint8_t *)&uc_tx_hdr_v6;
1289 qdf_mem_copy(&(QDF_IPA_WDI_REG_INTF_IN_PARAMS_HDR_INFO(&in)[IPA_IP_v6]),
1290 &hdr_info, sizeof(qdf_ipa_wdi_hdr_info_t));
1291 }
1292
Mohit Khanna81179cb2018-08-16 20:50:43 -07001293 dp_debug("registering for session_id: %u", session_id);
1294
Mohit Khannaf83015c2018-02-13 08:29:39 -08001295 ret = qdf_ipa_wdi_reg_intf(&in);
Mohit Khanna81179cb2018-08-16 20:50:43 -07001296
Mohit Khannaf83015c2018-02-13 08:29:39 -08001297 if (ret) {
1298 QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
1299 "%s: ipa_wdi_reg_intf: register IPA interface falied: ret=%d",
1300 __func__, ret);
1301 return QDF_STATUS_E_FAILURE;
1302 }
1303
1304 return QDF_STATUS_SUCCESS;
1305}
1306
1307#else /* CONFIG_IPA_WDI_UNIFIED_API */
Vevek Venkatesan2cc8c5d2019-08-22 16:29:46 +05301308QDF_STATUS dp_ipa_setup(struct cdp_soc_t *soc_hdl, uint8_t pdev_id,
1309 void *ipa_i2w_cb, void *ipa_w2i_cb,
1310 void *ipa_wdi_meter_notifier_cb,
Yun Parkfde6b9e2017-06-26 17:13:11 -07001311 uint32_t ipa_desc_size, void *ipa_priv,
1312 bool is_rm_enabled, uint32_t *tx_pipe_handle,
1313 uint32_t *rx_pipe_handle)
1314{
Vevek Venkatesan2cc8c5d2019-08-22 16:29:46 +05301315 struct dp_soc *soc = cdp_soc_t_to_dp_soc(soc_hdl);
1316 struct dp_pdev *pdev =
1317 dp_get_pdev_from_soc_pdev_id_wifi3(soc, pdev_id);
1318 struct dp_ipa_resources *ipa_res;
Mohit Khannaf83015c2018-02-13 08:29:39 -08001319 qdf_ipa_wdi_pipe_setup_info_t *tx;
1320 qdf_ipa_wdi_pipe_setup_info_t *rx;
1321 qdf_ipa_wdi_conn_in_params_t pipe_in;
1322 qdf_ipa_wdi_conn_out_params_t pipe_out;
Yun Park601d0d82017-08-28 21:49:31 -07001323 struct tcl_data_cmd *tcl_desc_ptr;
1324 uint8_t *desc_addr;
1325 uint32_t desc_size;
Yun Parkfde6b9e2017-06-26 17:13:11 -07001326 int ret;
1327
Vevek Venkatesan2cc8c5d2019-08-22 16:29:46 +05301328 if (!pdev) {
1329 dp_err("%s invalid instance", __func__);
1330 return QDF_STATUS_E_FAILURE;
1331 }
1332
1333 ipa_res = &pdev->ipa_resource;
Mohit Khanna81179cb2018-08-16 20:50:43 -07001334 if (!wlan_cfg_is_ipa_enabled(soc->wlan_cfg_ctx))
1335 return QDF_STATUS_SUCCESS;
1336
Mohit Khannaf83015c2018-02-13 08:29:39 -08001337 qdf_mem_zero(&tx, sizeof(qdf_ipa_wdi_pipe_setup_info_t));
1338 qdf_mem_zero(&rx, sizeof(qdf_ipa_wdi_pipe_setup_info_t));
Yun Parkfd269b52017-10-05 14:41:32 -07001339 qdf_mem_zero(&pipe_in, sizeof(pipe_in));
1340 qdf_mem_zero(&pipe_out, sizeof(pipe_out));
Yun Parkfde6b9e2017-06-26 17:13:11 -07001341
1342 /* TX PIPE */
1343 /**
1344 * Transfer Ring: WBM Ring
1345 * Transfer Ring Doorbell PA: WBM Tail Pointer Address
1346 * Event Ring: TCL ring
1347 * Event Ring Doorbell PA: TCL Head Pointer Address
1348 */
Mohit Khannaf83015c2018-02-13 08:29:39 -08001349 tx = &QDF_IPA_WDI_CONN_IN_PARAMS_TX(&pipe_in);
1350 QDF_IPA_WDI_SETUP_INFO_NAT_EN(tx) = IPA_BYPASS_NAT;
1351 QDF_IPA_WDI_SETUP_INFO_HDR_LEN(tx) = DP_IPA_UC_WLAN_TX_HDR_LEN;
1352 QDF_IPA_WDI_SETUP_INFO_HDR_OFST_PKT_SIZE_VALID(tx) = 0;
1353 QDF_IPA_WDI_SETUP_INFO_HDR_OFST_PKT_SIZE(tx) = 0;
1354 QDF_IPA_WDI_SETUP_INFO_HDR_ADDITIONAL_CONST_LEN(tx) = 0;
1355 QDF_IPA_WDI_SETUP_INFO_MODE(tx) = IPA_BASIC;
1356 QDF_IPA_WDI_SETUP_INFO_HDR_LITTLE_ENDIAN(tx) = true;
1357 QDF_IPA_WDI_SETUP_INFO_CLIENT(tx) = IPA_CLIENT_WLAN1_CONS;
1358 QDF_IPA_WDI_SETUP_INFO_TRANSFER_RING_BASE_PA(tx) =
Yun Parkfd269b52017-10-05 14:41:32 -07001359 ipa_res->tx_comp_ring_base_paddr;
Mohit Khannaf83015c2018-02-13 08:29:39 -08001360 QDF_IPA_WDI_SETUP_INFO_TRANSFER_RING_SIZE(tx) =
Yun Parkfd269b52017-10-05 14:41:32 -07001361 ipa_res->tx_comp_ring_size;
1362 /* WBM Tail Pointer Address */
Mohit Khannaf83015c2018-02-13 08:29:39 -08001363 QDF_IPA_WDI_SETUP_INFO_TRANSFER_RING_DOORBELL_PA(tx) =
Yun Parkfde6b9e2017-06-26 17:13:11 -07001364 soc->ipa_uc_tx_rsc.ipa_wbm_tp_paddr;
Mohit Khannaf83015c2018-02-13 08:29:39 -08001365 QDF_IPA_WDI_SETUP_INFO_EVENT_RING_BASE_PA(tx) =
Yun Parkfd269b52017-10-05 14:41:32 -07001366 ipa_res->tx_ring_base_paddr;
Mohit Khannaf83015c2018-02-13 08:29:39 -08001367 QDF_IPA_WDI_SETUP_INFO_EVENT_RING_SIZE(tx) = ipa_res->tx_ring_size;
Yun Parkfd269b52017-10-05 14:41:32 -07001368 /* TCL Head Pointer Address */
Mohit Khannaf83015c2018-02-13 08:29:39 -08001369 QDF_IPA_WDI_SETUP_INFO_EVENT_RING_DOORBELL_PA(tx) =
Yun Parkfde6b9e2017-06-26 17:13:11 -07001370 soc->ipa_uc_tx_rsc.ipa_tcl_hp_paddr;
Mohit Khannaf83015c2018-02-13 08:29:39 -08001371 QDF_IPA_WDI_SETUP_INFO_NUM_PKT_BUFFERS(tx) =
Yun Parkfd269b52017-10-05 14:41:32 -07001372 ipa_res->tx_num_alloc_buffer;
Mohit Khannaf83015c2018-02-13 08:29:39 -08001373 QDF_IPA_WDI_SETUP_INFO_PKT_OFFSET(tx) = 0;
Yun Parkfde6b9e2017-06-26 17:13:11 -07001374
Yun Park601d0d82017-08-28 21:49:31 -07001375 /* Preprogram TCL descriptor */
Yun Parkfd269b52017-10-05 14:41:32 -07001376 desc_addr =
Mohit Khannaf83015c2018-02-13 08:29:39 -08001377 (uint8_t *)QDF_IPA_WDI_SETUP_INFO_DESC_FORMAT_TEMPLATE(tx);
Yun Park601d0d82017-08-28 21:49:31 -07001378 desc_size = sizeof(struct tcl_data_cmd);
1379 HAL_TX_DESC_SET_TLV_HDR(desc_addr, HAL_TX_TCL_DATA_TAG, desc_size);
Yun Parkfd269b52017-10-05 14:41:32 -07001380 tcl_desc_ptr = (struct tcl_data_cmd *)
Mohit Khannaf83015c2018-02-13 08:29:39 -08001381 (QDF_IPA_WDI_SETUP_INFO_DESC_FORMAT_TEMPLATE(tx) + 1);
Yun Park601d0d82017-08-28 21:49:31 -07001382 tcl_desc_ptr->buf_addr_info.return_buffer_manager =
1383 HAL_RX_BUF_RBM_SW2_BM;
1384 tcl_desc_ptr->addrx_en = 1; /* Address X search enable in ASE */
1385 tcl_desc_ptr->encap_type = HAL_TX_ENCAP_TYPE_ETHERNET;
1386 tcl_desc_ptr->packet_offset = 2; /* padding for alignment */
1387
Yun Parkfde6b9e2017-06-26 17:13:11 -07001388 /* RX PIPE */
1389 /**
1390 * Transfer Ring: REO Ring
1391 * Transfer Ring Doorbell PA: REO Tail Pointer Address
1392 * Event Ring: FW ring
1393 * Event Ring Doorbell PA: FW Head Pointer Address
1394 */
Mohit Khannaf83015c2018-02-13 08:29:39 -08001395 rx = &QDF_IPA_WDI_CONN_IN_PARAMS_RX(&pipe_in);
1396 QDF_IPA_WDI_SETUP_INFO_NAT_EN(rx) = IPA_BYPASS_NAT;
1397 QDF_IPA_WDI_SETUP_INFO_HDR_LEN(rx) = DP_IPA_UC_WLAN_RX_HDR_LEN;
1398 QDF_IPA_WDI_SETUP_INFO_HDR_OFST_PKT_SIZE_VALID(rx) = 0;
1399 QDF_IPA_WDI_SETUP_INFO_HDR_OFST_PKT_SIZE(rx) = 0;
1400 QDF_IPA_WDI_SETUP_INFO_HDR_ADDITIONAL_CONST_LEN(rx) = 0;
1401 QDF_IPA_WDI_SETUP_INFO_HDR_OFST_METADATA_VALID(rx) = 0;
1402 QDF_IPA_WDI_SETUP_INFO_HDR_METADATA_REG_VALID(rx) = 1;
1403 QDF_IPA_WDI_SETUP_INFO_MODE(rx) = IPA_BASIC;
1404 QDF_IPA_WDI_SETUP_INFO_HDR_LITTLE_ENDIAN(rx) = true;
1405 QDF_IPA_WDI_SETUP_INFO_CLIENT(rx) = IPA_CLIENT_WLAN1_PROD;
1406 QDF_IPA_WDI_SETUP_INFO_TRANSFER_RING_BASE_PA(rx) =
1407 ipa_res->rx_rdy_ring_base_paddr;
1408 QDF_IPA_WDI_SETUP_INFO_TRANSFER_RING_SIZE(rx) =
1409 ipa_res->rx_rdy_ring_size;
1410 /* REO Tail Pointer Address */
1411 QDF_IPA_WDI_SETUP_INFO_TRANSFER_RING_DOORBELL_PA(rx) =
1412 soc->ipa_uc_rx_rsc.ipa_reo_tp_paddr;
1413 QDF_IPA_WDI_SETUP_INFO_EVENT_RING_BASE_PA(rx) =
1414 ipa_res->rx_refill_ring_base_paddr;
1415 QDF_IPA_WDI_SETUP_INFO_EVENT_RING_SIZE(rx) =
1416 ipa_res->rx_refill_ring_size;
1417 /* FW Head Pointer Address */
1418 QDF_IPA_WDI_SETUP_INFO_EVENT_RING_DOORBELL_PA(rx) =
1419 soc->ipa_uc_rx_rsc.ipa_rx_refill_buf_hp_paddr;
1420 QDF_IPA_WDI_SETUP_INFO_PKT_OFFSET(rx) = RX_PKT_TLVS_LEN +
1421 L3_HEADER_PADDING;
1422 QDF_IPA_WDI_CONN_IN_PARAMS_NOTIFY(&pipe_in) = ipa_w2i_cb;
1423 QDF_IPA_WDI_CONN_IN_PARAMS_PRIV(&pipe_in) = ipa_priv;
Yun Parkfde6b9e2017-06-26 17:13:11 -07001424
1425 /* Connect WDI IPA PIPE */
Mohit Khannaf83015c2018-02-13 08:29:39 -08001426 ret = qdf_ipa_wdi_conn_pipes(&pipe_in, &pipe_out);
Yun Parkfde6b9e2017-06-26 17:13:11 -07001427 if (ret) {
1428 QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
Mohit Khannaf83015c2018-02-13 08:29:39 -08001429 "%s: ipa_wdi_conn_pipes: IPA pipe setup failed: ret=%d",
Yun Park4711ade2017-08-28 21:49:31 -07001430 __func__, ret);
Yun Parkfde6b9e2017-06-26 17:13:11 -07001431 return QDF_STATUS_E_FAILURE;
1432 }
1433
1434 /* IPA uC Doorbell registers */
1435 QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_DEBUG,
Yun Park4711ade2017-08-28 21:49:31 -07001436 "%s: Tx DB PA=0x%x, Rx DB PA=0x%x",
1437 __func__,
Mohit Khannaf83015c2018-02-13 08:29:39 -08001438 (unsigned int)QDF_IPA_WDI_CONN_OUT_PARAMS_TX_UC_DB_PA(&pipe_out),
1439 (unsigned int)QDF_IPA_WDI_CONN_OUT_PARAMS_RX_UC_DB_PA(&pipe_out));
Yun Parkfde6b9e2017-06-26 17:13:11 -07001440
Yun Parkfd269b52017-10-05 14:41:32 -07001441 ipa_res->tx_comp_doorbell_paddr =
Mohit Khannaf83015c2018-02-13 08:29:39 -08001442 QDF_IPA_WDI_CONN_OUT_PARAMS_TX_UC_DB_PA(&pipe_out);
Yun Parkfd269b52017-10-05 14:41:32 -07001443 ipa_res->tx_comp_doorbell_vaddr =
Mohit Khannaf83015c2018-02-13 08:29:39 -08001444 QDF_IPA_WDI_CONN_OUT_PARAMS_TX_UC_DB_VA(&pipe_out);
Yun Parkfd269b52017-10-05 14:41:32 -07001445 ipa_res->rx_ready_doorbell_paddr =
Mohit Khannaf83015c2018-02-13 08:29:39 -08001446 QDF_IPA_WDI_CONN_OUT_PARAMS_RX_UC_DB_PA(&pipe_out);
Yun Parkfde6b9e2017-06-26 17:13:11 -07001447
Sravan Gouda4030a42020-01-13 13:17:21 +05301448 soc->ipa_first_tx_db_access = true;
1449
Yun Parkfde6b9e2017-06-26 17:13:11 -07001450 QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_DEBUG,
Yun Park4711ade2017-08-28 21:49:31 -07001451 "%s: Tx: %s=%pK, %s=%d, %s=%pK, %s=%pK, %s=%d, %s=%pK, %s=%d, %s=%pK",
1452 __func__,
Yun Parkfde6b9e2017-06-26 17:13:11 -07001453 "transfer_ring_base_pa",
Mohit Khannaf83015c2018-02-13 08:29:39 -08001454 (void *)QDF_IPA_WDI_SETUP_INFO_TRANSFER_RING_BASE_PA(tx),
Yun Parkfde6b9e2017-06-26 17:13:11 -07001455 "transfer_ring_size",
Mohit Khannaf83015c2018-02-13 08:29:39 -08001456 QDF_IPA_WDI_SETUP_INFO_TRANSFER_RING_SIZE(tx),
Yun Parkfde6b9e2017-06-26 17:13:11 -07001457 "transfer_ring_doorbell_pa",
Mohit Khannaf83015c2018-02-13 08:29:39 -08001458 (void *)QDF_IPA_WDI_SETUP_INFO_TRANSFER_RING_DOORBELL_PA(tx),
Yun Parkfde6b9e2017-06-26 17:13:11 -07001459 "event_ring_base_pa",
Mohit Khannaf83015c2018-02-13 08:29:39 -08001460 (void *)QDF_IPA_WDI_SETUP_INFO_EVENT_RING_BASE_PA(tx),
Yun Parkfde6b9e2017-06-26 17:13:11 -07001461 "event_ring_size",
Mohit Khannaf83015c2018-02-13 08:29:39 -08001462 QDF_IPA_WDI_SETUP_INFO_EVENT_RING_SIZE(tx),
Yun Parkfde6b9e2017-06-26 17:13:11 -07001463 "event_ring_doorbell_pa",
Mohit Khannaf83015c2018-02-13 08:29:39 -08001464 (void *)QDF_IPA_WDI_SETUP_INFO_EVENT_RING_DOORBELL_PA(tx),
Yun Parkfde6b9e2017-06-26 17:13:11 -07001465 "num_pkt_buffers",
Mohit Khannaf83015c2018-02-13 08:29:39 -08001466 QDF_IPA_WDI_SETUP_INFO_NUM_PKT_BUFFERS(tx),
Yun Parkfde6b9e2017-06-26 17:13:11 -07001467 "tx_comp_doorbell_paddr",
1468 (void *)ipa_res->tx_comp_doorbell_paddr);
1469
1470 QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_DEBUG,
Yun Park4711ade2017-08-28 21:49:31 -07001471 "%s: Rx: %s=%pK, %s=%d, %s=%pK, %s=%pK, %s=%d, %s=%pK, %s=%d, %s=%pK",
1472 __func__,
Yun Parkfde6b9e2017-06-26 17:13:11 -07001473 "transfer_ring_base_pa",
Mohit Khannaf83015c2018-02-13 08:29:39 -08001474 (void *)QDF_IPA_WDI_SETUP_INFO_TRANSFER_RING_BASE_PA(rx),
Yun Parkfde6b9e2017-06-26 17:13:11 -07001475 "transfer_ring_size",
Mohit Khannaf83015c2018-02-13 08:29:39 -08001476 QDF_IPA_WDI_SETUP_INFO_TRANSFER_RING_SIZE(rx),
Yun Parkfde6b9e2017-06-26 17:13:11 -07001477 "transfer_ring_doorbell_pa",
Mohit Khannaf83015c2018-02-13 08:29:39 -08001478 (void *)QDF_IPA_WDI_SETUP_INFO_TRANSFER_RING_DOORBELL_PA(rx),
Yun Parkfde6b9e2017-06-26 17:13:11 -07001479 "event_ring_base_pa",
Mohit Khannaf83015c2018-02-13 08:29:39 -08001480 (void *)QDF_IPA_WDI_SETUP_INFO_EVENT_RING_BASE_PA(rx),
Yun Parkfde6b9e2017-06-26 17:13:11 -07001481 "event_ring_size",
Mohit Khannaf83015c2018-02-13 08:29:39 -08001482 QDF_IPA_WDI_SETUP_INFO_EVENT_RING_SIZE(rx),
Yun Parkfde6b9e2017-06-26 17:13:11 -07001483 "event_ring_doorbell_pa",
Mohit Khannaf83015c2018-02-13 08:29:39 -08001484 (void *)QDF_IPA_WDI_SETUP_INFO_EVENT_RING_DOORBELL_PA(rx),
Yun Parkfde6b9e2017-06-26 17:13:11 -07001485 "num_pkt_buffers",
Mohit Khannaf83015c2018-02-13 08:29:39 -08001486 QDF_IPA_WDI_SETUP_INFO_NUM_PKT_BUFFERS(rx),
Yun Parkfde6b9e2017-06-26 17:13:11 -07001487 "tx_comp_doorbell_paddr",
1488 (void *)ipa_res->rx_ready_doorbell_paddr);
1489
1490 return QDF_STATUS_SUCCESS;
1491}
1492
1493/**
Yun Parkfde6b9e2017-06-26 17:13:11 -07001494 * dp_ipa_setup_iface() - Setup IPA header and register interface
1495 * @ifname: Interface name
1496 * @mac_addr: Interface MAC address
1497 * @prod_client: IPA prod client type
1498 * @cons_client: IPA cons client type
1499 * @session_id: Session ID
1500 * @is_ipv6_enabled: Is IPV6 enabled or not
1501 *
1502 * Return: QDF_STATUS
1503 */
1504QDF_STATUS dp_ipa_setup_iface(char *ifname, uint8_t *mac_addr,
Yun Parkfd269b52017-10-05 14:41:32 -07001505 qdf_ipa_client_type_t prod_client,
1506 qdf_ipa_client_type_t cons_client,
Yun Parkfde6b9e2017-06-26 17:13:11 -07001507 uint8_t session_id, bool is_ipv6_enabled)
1508{
Mohit Khannaf83015c2018-02-13 08:29:39 -08001509 qdf_ipa_wdi_reg_intf_in_params_t in;
1510 qdf_ipa_wdi_hdr_info_t hdr_info;
Yun Parkfde6b9e2017-06-26 17:13:11 -07001511 struct dp_ipa_uc_tx_hdr uc_tx_hdr;
Mohit Khannaf83015c2018-02-13 08:29:39 -08001512 struct dp_ipa_uc_tx_hdr uc_tx_hdr_v6;
Yun Parkfde6b9e2017-06-26 17:13:11 -07001513 int ret = -EINVAL;
1514
1515 QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_DEBUG,
Yun Park4711ade2017-08-28 21:49:31 -07001516 "%s: Add Partial hdr: %s, %pM",
1517 __func__, ifname, mac_addr);
Yun Parkfde6b9e2017-06-26 17:13:11 -07001518
Mohit Khannaf83015c2018-02-13 08:29:39 -08001519 qdf_mem_zero(&hdr_info, sizeof(qdf_ipa_wdi_hdr_info_t));
Yun Parkfde6b9e2017-06-26 17:13:11 -07001520 qdf_ether_addr_copy(uc_tx_hdr.eth.h_source, mac_addr);
1521
1522 /* IPV4 header */
1523 uc_tx_hdr.eth.h_proto = qdf_htons(ETH_P_IP);
1524
Mohit Khannaf83015c2018-02-13 08:29:39 -08001525 QDF_IPA_WDI_HDR_INFO_HDR(&hdr_info) = (uint8_t *)&uc_tx_hdr;
1526 QDF_IPA_WDI_HDR_INFO_HDR_LEN(&hdr_info) = DP_IPA_UC_WLAN_TX_HDR_LEN;
1527 QDF_IPA_WDI_HDR_INFO_HDR_TYPE(&hdr_info) = IPA_HDR_L2_ETHERNET_II;
1528 QDF_IPA_WDI_HDR_INFO_DST_MAC_ADDR_OFFSET(&hdr_info) =
Yun Parkfd269b52017-10-05 14:41:32 -07001529 DP_IPA_UC_WLAN_HDR_DES_MAC_OFFSET;
Yun Parkfde6b9e2017-06-26 17:13:11 -07001530
Mohit Khannaf83015c2018-02-13 08:29:39 -08001531 QDF_IPA_WDI_REG_INTF_IN_PARAMS_NETDEV_NAME(&in) = ifname;
1532 qdf_mem_copy(&(QDF_IPA_WDI_REG_INTF_IN_PARAMS_HDR_INFO(&in)[IPA_IP_v4]),
1533 &hdr_info, sizeof(qdf_ipa_wdi_hdr_info_t));
1534 QDF_IPA_WDI_REG_INTF_IN_PARAMS_IS_META_DATA_VALID(&in) = 1;
1535 QDF_IPA_WDI_REG_INTF_IN_PARAMS_META_DATA(&in) =
Yun Parkfd269b52017-10-05 14:41:32 -07001536 htonl(session_id << 16);
Mohit Khannaf83015c2018-02-13 08:29:39 -08001537 QDF_IPA_WDI_REG_INTF_IN_PARAMS_META_DATA_MASK(&in) = htonl(0x00FF0000);
Yun Parkfde6b9e2017-06-26 17:13:11 -07001538
1539 /* IPV6 header */
1540 if (is_ipv6_enabled) {
Mohit Khannaf83015c2018-02-13 08:29:39 -08001541 qdf_mem_copy(&uc_tx_hdr_v6, &uc_tx_hdr,
1542 DP_IPA_UC_WLAN_TX_HDR_LEN);
1543 uc_tx_hdr_v6.eth.h_proto = qdf_htons(ETH_P_IPV6);
1544 QDF_IPA_WDI_HDR_INFO_HDR(&hdr_info) = (uint8_t *)&uc_tx_hdr_v6;
1545 qdf_mem_copy(&(QDF_IPA_WDI_REG_INTF_IN_PARAMS_HDR_INFO(&in)[IPA_IP_v6]),
1546 &hdr_info, sizeof(qdf_ipa_wdi_hdr_info_t));
Yun Parkfde6b9e2017-06-26 17:13:11 -07001547 }
1548
Mohit Khannaf83015c2018-02-13 08:29:39 -08001549 ret = qdf_ipa_wdi_reg_intf(&in);
Yun Parkfde6b9e2017-06-26 17:13:11 -07001550 if (ret) {
Mohit Khannaf83015c2018-02-13 08:29:39 -08001551 dp_err("ipa_wdi_reg_intf: register IPA interface falied: ret=%d",
1552 ret);
1553 return QDF_STATUS_E_FAILURE;
1554 }
1555
1556 return QDF_STATUS_SUCCESS;
1557}
1558
1559#endif /* CONFIG_IPA_WDI_UNIFIED_API */
1560
1561/**
1562 * dp_ipa_cleanup() - Disconnect IPA pipes
1563 * @tx_pipe_handle: Tx pipe handle
1564 * @rx_pipe_handle: Rx pipe handle
1565 *
1566 * Return: QDF_STATUS
1567 */
1568QDF_STATUS dp_ipa_cleanup(uint32_t tx_pipe_handle, uint32_t rx_pipe_handle)
1569{
1570 int ret;
1571
1572 ret = qdf_ipa_wdi_disconn_pipes();
1573 if (ret) {
1574 dp_err("ipa_wdi_disconn_pipes: IPA pipe cleanup failed: ret=%d",
1575 ret);
Yun Parkfde6b9e2017-06-26 17:13:11 -07001576 return QDF_STATUS_E_FAILURE;
1577 }
1578
1579 return QDF_STATUS_SUCCESS;
1580}
1581
1582/**
1583 * dp_ipa_cleanup_iface() - Cleanup IPA header and deregister interface
1584 * @ifname: Interface name
1585 * @is_ipv6_enabled: Is IPV6 enabled or not
1586 *
1587 * Return: QDF_STATUS
1588 */
1589QDF_STATUS dp_ipa_cleanup_iface(char *ifname, bool is_ipv6_enabled)
1590{
1591 int ret;
1592
Mohit Khannaf83015c2018-02-13 08:29:39 -08001593 ret = qdf_ipa_wdi_dereg_intf(ifname);
Yun Parkfde6b9e2017-06-26 17:13:11 -07001594 if (ret) {
1595 QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
Mohit Khannaf83015c2018-02-13 08:29:39 -08001596 "%s: ipa_wdi_dereg_intf: IPA pipe deregistration failed: ret=%d",
Yun Park4711ade2017-08-28 21:49:31 -07001597 __func__, ret);
Yun Parkfde6b9e2017-06-26 17:13:11 -07001598 return QDF_STATUS_E_FAILURE;
1599 }
1600
1601 return QDF_STATUS_SUCCESS;
1602}
1603
Vevek Venkatesan2cc8c5d2019-08-22 16:29:46 +05301604QDF_STATUS dp_ipa_enable_pipes(struct cdp_soc_t *soc_hdl, uint8_t pdev_id)
Yun Parkfde6b9e2017-06-26 17:13:11 -07001605{
Vevek Venkatesan2cc8c5d2019-08-22 16:29:46 +05301606 struct dp_soc *soc = cdp_soc_t_to_dp_soc(soc_hdl);
1607 struct dp_pdev *pdev =
1608 dp_get_pdev_from_soc_pdev_id_wifi3(soc, pdev_id);
Sravan Gouda4030a42020-01-13 13:17:21 +05301609 struct hal_srng *wbm_srng = (struct hal_srng *)
1610 soc->tx_comp_ring[IPA_TX_COMP_RING_IDX].hal_srng;
1611 struct dp_ipa_resources *ipa_res;
Yun Parkfde6b9e2017-06-26 17:13:11 -07001612 QDF_STATUS result;
1613
Vevek Venkatesan2cc8c5d2019-08-22 16:29:46 +05301614 if (!pdev) {
1615 dp_err("%s invalid instance", __func__);
1616 return QDF_STATUS_E_FAILURE;
1617 }
1618
Sravan Gouda4030a42020-01-13 13:17:21 +05301619 ipa_res = &pdev->ipa_resource;
1620
Nisha Menonf7c5baa2019-10-23 12:50:16 -07001621 qdf_atomic_set(&soc->ipa_pipes_enabled, 1);
jiada833f302019-06-10 14:20:28 +08001622 dp_ipa_handle_rx_buf_pool_smmu_mapping(soc, pdev, true);
1623
Mohit Khannaf83015c2018-02-13 08:29:39 -08001624 result = qdf_ipa_wdi_enable_pipes();
Yun Parkfde6b9e2017-06-26 17:13:11 -07001625 if (result) {
1626 QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
Yun Park4711ade2017-08-28 21:49:31 -07001627 "%s: Enable WDI PIPE fail, code %d",
1628 __func__, result);
Nisha Menonf7c5baa2019-10-23 12:50:16 -07001629 qdf_atomic_set(&soc->ipa_pipes_enabled, 0);
jiada833f302019-06-10 14:20:28 +08001630 dp_ipa_handle_rx_buf_pool_smmu_mapping(soc, pdev, false);
Yun Parkfde6b9e2017-06-26 17:13:11 -07001631 return QDF_STATUS_E_FAILURE;
1632 }
1633
Sravan Gouda4030a42020-01-13 13:17:21 +05301634 if (soc->ipa_first_tx_db_access) {
1635 hal_srng_dst_init_hp(wbm_srng, ipa_res->tx_comp_doorbell_vaddr);
1636 soc->ipa_first_tx_db_access = false;
1637 }
1638
Yun Parkfde6b9e2017-06-26 17:13:11 -07001639 return QDF_STATUS_SUCCESS;
1640}
1641
Vevek Venkatesan2cc8c5d2019-08-22 16:29:46 +05301642QDF_STATUS dp_ipa_disable_pipes(struct cdp_soc_t *soc_hdl, uint8_t pdev_id)
Yun Parkfde6b9e2017-06-26 17:13:11 -07001643{
Vevek Venkatesan2cc8c5d2019-08-22 16:29:46 +05301644 struct dp_soc *soc = cdp_soc_t_to_dp_soc(soc_hdl);
1645 struct dp_pdev *pdev =
1646 dp_get_pdev_from_soc_pdev_id_wifi3(soc, pdev_id);
Yun Parkfde6b9e2017-06-26 17:13:11 -07001647 QDF_STATUS result;
1648
Vevek Venkatesan2cc8c5d2019-08-22 16:29:46 +05301649 if (!pdev) {
1650 dp_err("%s invalid instance", __func__);
1651 return QDF_STATUS_E_FAILURE;
1652 }
1653
Mohit Khannaf83015c2018-02-13 08:29:39 -08001654 result = qdf_ipa_wdi_disable_pipes();
jiad3f43a692019-04-17 16:43:25 +08001655 if (result)
Yun Parkfde6b9e2017-06-26 17:13:11 -07001656 QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
Yun Park4711ade2017-08-28 21:49:31 -07001657 "%s: Disable WDI PIPE fail, code %d",
1658 __func__, result);
Yun Parkfde6b9e2017-06-26 17:13:11 -07001659
Nisha Menonf7c5baa2019-10-23 12:50:16 -07001660 qdf_atomic_set(&soc->ipa_pipes_enabled, 0);
jiad3f43a692019-04-17 16:43:25 +08001661 dp_ipa_handle_rx_buf_pool_smmu_mapping(soc, pdev, false);
1662
1663 return result ? QDF_STATUS_E_FAILURE : QDF_STATUS_SUCCESS;
Yun Parkfde6b9e2017-06-26 17:13:11 -07001664}
1665
1666/**
1667 * dp_ipa_set_perf_level() - Set IPA clock bandwidth based on data rates
1668 * @client: Client type
1669 * @max_supported_bw_mbps: Maximum bandwidth needed (in Mbps)
1670 *
1671 * Return: QDF_STATUS
1672 */
1673QDF_STATUS dp_ipa_set_perf_level(int client, uint32_t max_supported_bw_mbps)
1674{
Mohit Khannaf83015c2018-02-13 08:29:39 -08001675 qdf_ipa_wdi_perf_profile_t profile;
Yun Parkfde6b9e2017-06-26 17:13:11 -07001676 QDF_STATUS result;
1677
1678 profile.client = client;
1679 profile.max_supported_bw_mbps = max_supported_bw_mbps;
1680
Mohit Khannaf83015c2018-02-13 08:29:39 -08001681 result = qdf_ipa_wdi_set_perf_profile(&profile);
Yun Parkfde6b9e2017-06-26 17:13:11 -07001682 if (result) {
1683 QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
Mohit Khannaf83015c2018-02-13 08:29:39 -08001684 "%s: ipa_wdi_set_perf_profile fail, code %d",
Yun Park4711ade2017-08-28 21:49:31 -07001685 __func__, result);
Yun Parkfde6b9e2017-06-26 17:13:11 -07001686 return QDF_STATUS_E_FAILURE;
1687 }
1688
1689 return QDF_STATUS_SUCCESS;
1690}
Mohit Khannaf83015c2018-02-13 08:29:39 -08001691
jiad5a4530f2019-03-25 15:33:52 +08001692/**
1693 * dp_ipa_intrabss_send - send IPA RX intra-bss frames
1694 * @pdev: pdev
1695 * @vdev: vdev
1696 * @nbuf: skb
1697 *
1698 * Return: nbuf if TX fails and NULL if TX succeeds
1699 */
1700static qdf_nbuf_t dp_ipa_intrabss_send(struct dp_pdev *pdev,
1701 struct dp_vdev *vdev,
1702 qdf_nbuf_t nbuf)
1703{
jiad5a4530f2019-03-25 15:33:52 +08001704 struct dp_peer *vdev_peer;
1705 uint16_t len;
jiad5a4530f2019-03-25 15:33:52 +08001706
1707 vdev_peer = vdev->vap_bss_peer;
1708 if (qdf_unlikely(!vdev_peer))
1709 return nbuf;
1710
jiad5a4530f2019-03-25 15:33:52 +08001711 qdf_mem_zero(nbuf->cb, sizeof(nbuf->cb));
1712 len = qdf_nbuf_len(nbuf);
1713
Pavankumar Nandeshwara2347162019-12-18 23:20:31 +05301714 if (dp_tx_send((struct cdp_soc_t *)pdev->soc, vdev->vdev_id, nbuf)) {
jiad5a4530f2019-03-25 15:33:52 +08001715 DP_STATS_INC_PKT(vdev_peer, rx.intra_bss.fail, 1, len);
jiad5a4530f2019-03-25 15:33:52 +08001716 return nbuf;
1717 }
1718
1719 DP_STATS_INC_PKT(vdev_peer, rx.intra_bss.pkts, 1, len);
jiad5a4530f2019-03-25 15:33:52 +08001720 return NULL;
1721}
1722
Vevek Venkatesan2cc8c5d2019-08-22 16:29:46 +05301723bool dp_ipa_rx_intrabss_fwd(struct cdp_soc_t *soc_hdl, uint8_t vdev_id,
1724 qdf_nbuf_t nbuf, bool *fwd_success)
jiad5a4530f2019-03-25 15:33:52 +08001725{
Vevek Venkatesan2cc8c5d2019-08-22 16:29:46 +05301726 struct dp_soc *soc = cdp_soc_t_to_dp_soc(soc_hdl);
1727 struct dp_vdev *vdev =
1728 dp_get_vdev_from_soc_vdev_id_wifi3(soc, vdev_id);
jiad5a4530f2019-03-25 15:33:52 +08001729 struct dp_pdev *pdev;
1730 struct dp_peer *da_peer;
1731 struct dp_peer *sa_peer;
1732 qdf_nbuf_t nbuf_copy;
1733 uint8_t da_is_bcmc;
1734 struct ethhdr *eh;
jiad5a4530f2019-03-25 15:33:52 +08001735
1736 *fwd_success = false; /* set default as failure */
1737
1738 /*
1739 * WDI 3.0 skb->cb[] info from IPA driver
1740 * skb->cb[0] = vdev_id
1741 * skb->cb[1].bit#1 = da_is_bcmc
1742 */
1743 da_is_bcmc = ((uint8_t)nbuf->cb[1]) & 0x2;
1744
1745 if (qdf_unlikely(!vdev))
1746 return false;
1747
1748 pdev = vdev->pdev;
1749 if (qdf_unlikely(!pdev))
1750 return false;
1751
1752 /* no fwd for station mode and just pass up to stack */
1753 if (vdev->opmode == wlan_op_mode_sta)
1754 return false;
1755
1756 if (da_is_bcmc) {
1757 nbuf_copy = qdf_nbuf_copy(nbuf);
1758 if (!nbuf_copy)
1759 return false;
1760
1761 if (dp_ipa_intrabss_send(pdev, vdev, nbuf_copy))
1762 qdf_nbuf_free(nbuf_copy);
1763 else
1764 *fwd_success = true;
1765
1766 /* return false to pass original pkt up to stack */
1767 return false;
1768 }
1769
1770 eh = (struct ethhdr *)qdf_nbuf_data(nbuf);
1771
1772 if (!qdf_mem_cmp(eh->h_dest, vdev->mac_addr.raw, QDF_MAC_ADDR_SIZE))
1773 return false;
1774
Yeshwanth Sriram Guntuka65d54772019-11-22 14:50:02 +05301775 da_peer = dp_find_peer_by_addr((struct cdp_pdev *)pdev, eh->h_dest);
jiad5a4530f2019-03-25 15:33:52 +08001776 if (!da_peer)
1777 return false;
1778
1779 if (da_peer->vdev != vdev)
1780 return false;
1781
Yeshwanth Sriram Guntuka65d54772019-11-22 14:50:02 +05301782 sa_peer = dp_find_peer_by_addr((struct cdp_pdev *)pdev, eh->h_source);
jiad5a4530f2019-03-25 15:33:52 +08001783 if (!sa_peer)
1784 return false;
1785
1786 if (sa_peer->vdev != vdev)
1787 return false;
1788
1789 /*
1790 * In intra-bss forwarding scenario, skb is allocated by IPA driver.
1791 * Need to add skb to internal tracking table to avoid nbuf memory
1792 * leak check for unallocated skb.
1793 */
1794 qdf_net_buf_debug_acquire_skb(nbuf, __FILE__, __LINE__);
1795
1796 if (dp_ipa_intrabss_send(pdev, vdev, nbuf))
1797 qdf_nbuf_free(nbuf);
1798 else
1799 *fwd_success = true;
1800
1801 return true;
1802}
1803
jiad3c91fb52019-05-27 16:53:17 +08001804#ifdef MDM_PLATFORM
1805bool dp_ipa_is_mdm_platform(void)
1806{
1807 return true;
1808}
1809#else
1810bool dp_ipa_is_mdm_platform(void)
1811{
1812 return false;
1813}
1814#endif
1815
Jia Dingfef509b2019-08-07 14:17:31 +08001816/**
Jinwei Chen1d2e65a2019-12-26 22:45:57 +08001817 * dp_ipa_frag_nbuf_linearize - linearize nbuf for IPA
1818 * @soc: soc
1819 * @nbuf: source skb
1820 *
1821 * Return: new nbuf if success and otherwise NULL
1822 */
1823static qdf_nbuf_t dp_ipa_frag_nbuf_linearize(struct dp_soc *soc,
1824 qdf_nbuf_t nbuf)
1825{
1826 uint8_t *src_nbuf_data;
1827 uint8_t *dst_nbuf_data;
1828 qdf_nbuf_t dst_nbuf;
1829 qdf_nbuf_t temp_nbuf = nbuf;
1830 uint32_t nbuf_len = qdf_nbuf_len(nbuf);
1831 bool is_nbuf_head = true;
1832 uint32_t copy_len = 0;
1833
Shashikala Prabhu03a9f5b2020-01-28 19:11:30 +05301834 dst_nbuf = qdf_nbuf_alloc(soc->osdev, RX_DATA_BUFFER_SIZE,
1835 RX_BUFFER_RESERVATION,
1836 RX_DATA_BUFFER_ALIGNMENT, FALSE);
Jinwei Chen1d2e65a2019-12-26 22:45:57 +08001837
1838 if (!dst_nbuf) {
1839 dp_err_rl("nbuf allocate fail");
1840 return NULL;
1841 }
1842
Shashikala Prabhu03a9f5b2020-01-28 19:11:30 +05301843 if ((nbuf_len + L3_HEADER_PADDING) > RX_DATA_BUFFER_SIZE) {
Jinwei Chen1d2e65a2019-12-26 22:45:57 +08001844 qdf_nbuf_free(dst_nbuf);
1845 dp_err_rl("nbuf is jumbo data");
1846 return NULL;
1847 }
1848
1849 /* prepeare to copy all data into new skb */
1850 dst_nbuf_data = qdf_nbuf_data(dst_nbuf);
1851 while (temp_nbuf) {
1852 src_nbuf_data = qdf_nbuf_data(temp_nbuf);
1853 /* first head nbuf */
1854 if (is_nbuf_head) {
1855 qdf_mem_copy(dst_nbuf_data, src_nbuf_data,
1856 RX_PKT_TLVS_LEN);
1857 /* leave extra 2 bytes L3_HEADER_PADDING */
1858 dst_nbuf_data += (RX_PKT_TLVS_LEN + L3_HEADER_PADDING);
1859 src_nbuf_data += RX_PKT_TLVS_LEN;
1860 copy_len = qdf_nbuf_headlen(temp_nbuf) -
1861 RX_PKT_TLVS_LEN;
1862 temp_nbuf = qdf_nbuf_get_ext_list(temp_nbuf);
1863 is_nbuf_head = false;
1864 } else {
1865 copy_len = qdf_nbuf_len(temp_nbuf);
1866 temp_nbuf = qdf_nbuf_queue_next(temp_nbuf);
1867 }
1868 qdf_mem_copy(dst_nbuf_data, src_nbuf_data, copy_len);
1869 dst_nbuf_data += copy_len;
1870 }
1871
1872 qdf_nbuf_set_len(dst_nbuf, nbuf_len);
1873 /* copy is done, free original nbuf */
1874 qdf_nbuf_free(nbuf);
1875
1876 return dst_nbuf;
1877}
1878
1879/**
Jia Dingfef509b2019-08-07 14:17:31 +08001880 * dp_ipa_handle_rx_reo_reinject - Handle RX REO reinject skb buffer
1881 * @soc: soc
1882 * @nbuf: skb
1883 *
1884 * Return: nbuf if success and otherwise NULL
1885 */
1886qdf_nbuf_t dp_ipa_handle_rx_reo_reinject(struct dp_soc *soc, qdf_nbuf_t nbuf)
1887{
Jia Dingfef509b2019-08-07 14:17:31 +08001888
1889 if (!wlan_cfg_is_ipa_enabled(soc->wlan_cfg_ctx))
1890 return nbuf;
1891
Jia Dingfef509b2019-08-07 14:17:31 +08001892 /* WLAN IPA is run-time disabled */
Nisha Menonf7c5baa2019-10-23 12:50:16 -07001893 if (!qdf_atomic_read(&soc->ipa_pipes_enabled))
Jia Dingfef509b2019-08-07 14:17:31 +08001894 return nbuf;
1895
Jinwei Chen1d2e65a2019-12-26 22:45:57 +08001896 if (!qdf_nbuf_is_frag(nbuf))
1897 return nbuf;
Jia Dingfef509b2019-08-07 14:17:31 +08001898
Jinwei Chen1d2e65a2019-12-26 22:45:57 +08001899 /* linearize skb for IPA */
1900 return dp_ipa_frag_nbuf_linearize(soc, nbuf);
Jia Dingfef509b2019-08-07 14:17:31 +08001901}
1902
Yun Parkfde6b9e2017-06-26 17:13:11 -07001903#endif