xref: /wlan-dirver/qca-wifi-host-cmn/dp/wifi3.0/dp_ipa.c (revision 1b9674e21e24478fba4530f5ae7396b9555e9c6a)
1 /*
2  * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
3  *
4  * 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.
7  *
8  * 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  */
16 
17 #ifdef IPA_OFFLOAD
18 
19 #include <qdf_ipa_wdi3.h>
20 #include <qdf_types.h>
21 #include <qdf_lock.h>
22 #include <hal_hw_headers.h>
23 #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"
29 #include "dp_htt.h"
30 #include "dp_tx.h"
31 #include "dp_ipa.h"
32 
33 /* Hard coded config parameters until dp_ops_cfg.cfg_attach implemented */
34 #define CFG_IPA_UC_TX_BUF_SIZE_DEFAULT            (2048)
35 
36 /**
37  * dp_tx_ipa_uc_detach - Free autonomy TX resources
38  * @soc: data path instance
39  * @pdev: core txrx pdev context
40  *
41  * Free allocated TX buffers with WBM SRNG
42  *
43  * Return: none
44  */
45 static void dp_tx_ipa_uc_detach(struct dp_soc *soc, struct dp_pdev *pdev)
46 {
47 	int idx;
48 	uint32_t ring_base_align = 8;
49 	/*
50 	 * Uncomment when dp_ops_cfg.cfg_attach is implemented
51 	 * unsigned int uc_tx_buf_sz =
52 	 *		dp_cfg_ipa_uc_tx_buf_size(pdev->osif_pdev);
53 	 */
54 	unsigned int uc_tx_buf_sz = CFG_IPA_UC_TX_BUF_SIZE_DEFAULT;
55 	unsigned int alloc_size = uc_tx_buf_sz + ring_base_align - 1;
56 
57 	for (idx = 0; idx < soc->ipa_uc_tx_rsc.alloc_tx_buf_cnt; idx++) {
58 		if (soc->ipa_uc_tx_rsc.tx_buf_pool_vaddr_unaligned[idx]) {
59 			qdf_mem_free_consistent(
60 				soc->osdev, soc->osdev->dev,
61 				alloc_size,
62 				soc->ipa_uc_tx_rsc.
63 					tx_buf_pool_vaddr_unaligned[idx],
64 				soc->ipa_uc_tx_rsc.
65 					tx_buf_pool_paddr_unaligned[idx],
66 				0);
67 
68 			soc->ipa_uc_tx_rsc.tx_buf_pool_vaddr_unaligned[idx] =
69 							(void *)NULL;
70 			soc->ipa_uc_tx_rsc.tx_buf_pool_paddr_unaligned[idx] =
71 							(qdf_dma_addr_t)NULL;
72 		}
73 	}
74 
75 	qdf_mem_free(soc->ipa_uc_tx_rsc.tx_buf_pool_vaddr_unaligned);
76 	soc->ipa_uc_tx_rsc.tx_buf_pool_vaddr_unaligned = NULL;
77 	qdf_mem_free(soc->ipa_uc_tx_rsc.tx_buf_pool_paddr_unaligned);
78 	soc->ipa_uc_tx_rsc.tx_buf_pool_paddr_unaligned = NULL;
79 }
80 
81 /**
82  * dp_rx_ipa_uc_detach - free autonomy RX resources
83  * @soc: data path instance
84  * @pdev: core txrx pdev context
85  *
86  * This function will detach DP RX into main device context
87  * will free DP Rx resources.
88  *
89  * Return: none
90  */
91 static void dp_rx_ipa_uc_detach(struct dp_soc *soc, struct dp_pdev *pdev)
92 {
93 }
94 
95 int dp_ipa_uc_detach(struct dp_soc *soc, struct dp_pdev *pdev)
96 {
97 	/* TX resource detach */
98 	dp_tx_ipa_uc_detach(soc, pdev);
99 
100 	/* RX resource detach */
101 	dp_rx_ipa_uc_detach(soc, pdev);
102 
103 	return QDF_STATUS_SUCCESS;	/* success */
104 }
105 
106 /**
107  * dp_tx_ipa_uc_attach - Allocate autonomy TX resources
108  * @soc: data path instance
109  * @pdev: Physical device handle
110  *
111  * Allocate TX buffer from non-cacheable memory
112  * Attache allocated TX buffers with WBM SRNG
113  *
114  * Return: int
115  */
116 static int dp_tx_ipa_uc_attach(struct dp_soc *soc, struct dp_pdev *pdev)
117 {
118 	uint32_t tx_buffer_count;
119 	uint32_t ring_base_align = 8;
120 	void *buffer_vaddr_unaligned;
121 	void *buffer_vaddr;
122 	qdf_dma_addr_t buffer_paddr_unaligned;
123 	qdf_dma_addr_t buffer_paddr;
124 	struct hal_srng *wbm_srng =
125 			soc->tx_comp_ring[IPA_TX_COMP_RING_IDX].hal_srng;
126 	struct hal_srng_params srng_params;
127 	uint32_t paddr_lo;
128 	uint32_t paddr_hi;
129 	void *ring_entry;
130 	int num_entries;
131 	int retval = QDF_STATUS_SUCCESS;
132 	/*
133 	 * Uncomment when dp_ops_cfg.cfg_attach is implemented
134 	 * unsigned int uc_tx_buf_sz =
135 	 *		dp_cfg_ipa_uc_tx_buf_size(pdev->osif_pdev);
136 	 */
137 	unsigned int uc_tx_buf_sz = CFG_IPA_UC_TX_BUF_SIZE_DEFAULT;
138 	unsigned int alloc_size = uc_tx_buf_sz + ring_base_align - 1;
139 
140 	hal_get_srng_params(soc->hal_soc, (void *)wbm_srng, &srng_params);
141 	num_entries = srng_params.num_entries;
142 
143 	QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_INFO,
144 		  "%s: requested %d buffers to be posted to wbm ring",
145 		   __func__, num_entries);
146 
147 	soc->ipa_uc_tx_rsc.tx_buf_pool_vaddr_unaligned =
148 		qdf_mem_malloc(num_entries *
149 		sizeof(*soc->ipa_uc_tx_rsc.tx_buf_pool_vaddr_unaligned));
150 	if (!soc->ipa_uc_tx_rsc.tx_buf_pool_vaddr_unaligned) {
151 		QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR,
152 			  "%s: IPA WBM Ring Tx buf pool vaddr alloc fail",
153 			  __func__);
154 		return -ENOMEM;
155 	}
156 
157 	soc->ipa_uc_tx_rsc.tx_buf_pool_paddr_unaligned =
158 		qdf_mem_malloc(num_entries *
159 		sizeof(*soc->ipa_uc_tx_rsc.tx_buf_pool_paddr_unaligned));
160 	if (!soc->ipa_uc_tx_rsc.tx_buf_pool_paddr_unaligned) {
161 		QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR,
162 			  "%s: IPA WBM Ring Tx buf pool paddr alloc fail",
163 			  __func__);
164 		qdf_mem_free(soc->ipa_uc_tx_rsc.tx_buf_pool_vaddr_unaligned);
165 		return -ENOMEM;
166 	}
167 
168 	hal_srng_access_start(soc->hal_soc, (void *)wbm_srng);
169 
170 	/*
171 	 * Allocate Tx buffers as many as possible
172 	 * Populate Tx buffers into WBM2IPA ring
173 	 * This initial buffer population will simulate H/W as source ring,
174 	 * and update HP
175 	 */
176 	for (tx_buffer_count = 0;
177 		tx_buffer_count < num_entries - 1; tx_buffer_count++) {
178 		buffer_vaddr_unaligned = qdf_mem_alloc_consistent(soc->osdev,
179 			soc->osdev->dev, alloc_size, &buffer_paddr_unaligned);
180 		if (!buffer_vaddr_unaligned)
181 			break;
182 
183 		ring_entry = hal_srng_dst_get_next_hp(soc->hal_soc,
184 				(void *)wbm_srng);
185 		if (!ring_entry) {
186 			QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_INFO,
187 				  "%s: Failed to get WBM ring entry",
188 				  __func__);
189 			qdf_mem_free_consistent(soc->osdev, soc->osdev->dev,
190 				alloc_size, buffer_vaddr_unaligned,
191 				buffer_paddr_unaligned, 0);
192 			break;
193 		}
194 
195 		buffer_vaddr = (void *)qdf_align((unsigned long)
196 			buffer_vaddr_unaligned, ring_base_align);
197 		buffer_paddr = buffer_paddr_unaligned +
198 			((unsigned long)(buffer_vaddr) -
199 			 (unsigned long)buffer_vaddr_unaligned);
200 
201 		paddr_lo = ((u64)buffer_paddr & 0x00000000ffffffff);
202 		paddr_hi = ((u64)buffer_paddr & 0x0000001f00000000) >> 32;
203 		HAL_WBM_PADDR_LO_SET(ring_entry, paddr_lo);
204 		HAL_WBM_PADDR_HI_SET(ring_entry, paddr_hi);
205 
206 		soc->ipa_uc_tx_rsc.tx_buf_pool_vaddr_unaligned[tx_buffer_count]
207 			= buffer_vaddr_unaligned;
208 		soc->ipa_uc_tx_rsc.tx_buf_pool_paddr_unaligned[tx_buffer_count]
209 			= buffer_paddr_unaligned;
210 	}
211 
212 	hal_srng_access_end(soc->hal_soc, wbm_srng);
213 
214 	soc->ipa_uc_tx_rsc.alloc_tx_buf_cnt = tx_buffer_count;
215 
216 	if (tx_buffer_count) {
217 		QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_INFO,
218 			  "%s: IPA WDI TX buffer: %d allocated",
219 			  __func__, tx_buffer_count);
220 	} else {
221 		QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR,
222 			  "%s: No IPA WDI TX buffer allocated",
223 			  __func__);
224 		qdf_mem_free(soc->ipa_uc_tx_rsc.tx_buf_pool_vaddr_unaligned);
225 		soc->ipa_uc_tx_rsc.tx_buf_pool_vaddr_unaligned = NULL;
226 		qdf_mem_free(soc->ipa_uc_tx_rsc.tx_buf_pool_paddr_unaligned);
227 		soc->ipa_uc_tx_rsc.tx_buf_pool_paddr_unaligned = NULL;
228 		retval = -ENOMEM;
229 	}
230 
231 	return retval;
232 }
233 
234 /**
235  * dp_rx_ipa_uc_attach - Allocate autonomy RX resources
236  * @soc: data path instance
237  * @pdev: core txrx pdev context
238  *
239  * This function will attach a DP RX instance into the main
240  * device (SOC) context.
241  *
242  * Return: QDF_STATUS_SUCCESS: success
243  *         QDF_STATUS_E_RESOURCES: Error return
244  */
245 static int dp_rx_ipa_uc_attach(struct dp_soc *soc, struct dp_pdev *pdev)
246 {
247 	return QDF_STATUS_SUCCESS;
248 }
249 
250 int dp_ipa_uc_attach(struct dp_soc *soc, struct dp_pdev *pdev)
251 {
252 	int error;
253 
254 	/* TX resource attach */
255 	error = dp_tx_ipa_uc_attach(soc, pdev);
256 	if (error) {
257 		QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR,
258 			  "%s: DP IPA UC TX attach fail code %d",
259 			  __func__, error);
260 		return error;
261 	}
262 
263 	/* RX resource attach */
264 	error = dp_rx_ipa_uc_attach(soc, pdev);
265 	if (error) {
266 		QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR,
267 			  "%s: DP IPA UC RX attach fail code %d",
268 			  __func__, error);
269 		dp_tx_ipa_uc_detach(soc, pdev);
270 		return error;
271 	}
272 
273 	return QDF_STATUS_SUCCESS;	/* success */
274 }
275 
276 /*
277  * dp_ipa_ring_resource_setup() - setup IPA ring resources
278  * @soc: data path SoC handle
279  *
280  * Return: none
281  */
282 int dp_ipa_ring_resource_setup(struct dp_soc *soc,
283 		struct dp_pdev *pdev)
284 {
285 	struct hal_soc *hal_soc = (struct hal_soc *)soc->hal_soc;
286 	struct hal_srng *hal_srng;
287 	struct hal_srng_params srng_params;
288 	qdf_dma_addr_t hp_addr;
289 	unsigned long addr_offset, dev_base_paddr;
290 
291 	/* IPA TCL_DATA Ring - HAL_SRNG_SW2TCL3 */
292 	hal_srng = soc->tcl_data_ring[IPA_TCL_DATA_RING_IDX].hal_srng;
293 	hal_get_srng_params(hal_soc, (void *)hal_srng, &srng_params);
294 
295 	soc->ipa_uc_tx_rsc.ipa_tcl_ring_base_paddr =
296 		srng_params.ring_base_paddr;
297 	soc->ipa_uc_tx_rsc.ipa_tcl_ring_base_vaddr =
298 		srng_params.ring_base_vaddr;
299 	soc->ipa_uc_tx_rsc.ipa_tcl_ring_size =
300 		(srng_params.num_entries * srng_params.entry_size) << 2;
301 	/*
302 	 * For the register backed memory addresses, use the scn->mem_pa to
303 	 * calculate the physical address of the shadow registers
304 	 */
305 	dev_base_paddr =
306 		(unsigned long)
307 		((struct hif_softc *)(hal_soc->hif_handle))->mem_pa;
308 	addr_offset = (unsigned long)(hal_srng->u.src_ring.hp_addr) -
309 		      (unsigned long)(hal_soc->dev_base_addr);
310 	soc->ipa_uc_tx_rsc.ipa_tcl_hp_paddr =
311 				(qdf_dma_addr_t)(addr_offset + dev_base_paddr);
312 
313 	QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_INFO,
314 		"%s: addr_offset=%x, dev_base_paddr=%x, ipa_tcl_hp_paddr=%x",
315 		__func__, (unsigned int)addr_offset,
316 		(unsigned int)dev_base_paddr,
317 		(unsigned int)(soc->ipa_uc_tx_rsc.ipa_tcl_hp_paddr));
318 
319 	/* IPA TX COMP Ring - HAL_SRNG_WBM2SW2_RELEASE */
320 	hal_srng = soc->tx_comp_ring[IPA_TX_COMP_RING_IDX].hal_srng;
321 	hal_get_srng_params(hal_soc, (void *)hal_srng, &srng_params);
322 
323 	soc->ipa_uc_tx_rsc.ipa_wbm_ring_base_paddr =
324 		srng_params.ring_base_paddr;
325 	soc->ipa_uc_tx_rsc.ipa_wbm_ring_base_vaddr =
326 		srng_params.ring_base_vaddr;
327 	soc->ipa_uc_tx_rsc.ipa_wbm_ring_size =
328 		(srng_params.num_entries * srng_params.entry_size) << 2;
329 	addr_offset = (unsigned long)(hal_srng->u.dst_ring.tp_addr) -
330 		      (unsigned long)(hal_soc->dev_base_addr);
331 	soc->ipa_uc_tx_rsc.ipa_wbm_tp_paddr =
332 				(qdf_dma_addr_t)(addr_offset + dev_base_paddr);
333 
334 	QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_INFO,
335 		"%s: addr_offset=%x, dev_base_paddr=%x, ipa_wbm_tp_paddr=%x",
336 		__func__, (unsigned int)addr_offset,
337 		(unsigned int)dev_base_paddr,
338 		(unsigned int)(soc->ipa_uc_tx_rsc.ipa_wbm_tp_paddr));
339 
340 	/* IPA REO_DEST Ring - HAL_SRNG_REO2SW4 */
341 	hal_srng = soc->reo_dest_ring[IPA_REO_DEST_RING_IDX].hal_srng;
342 	hal_get_srng_params(hal_soc, (void *)hal_srng, &srng_params);
343 
344 	soc->ipa_uc_rx_rsc.ipa_reo_ring_base_paddr =
345 		srng_params.ring_base_paddr;
346 	soc->ipa_uc_rx_rsc.ipa_reo_ring_base_vaddr =
347 		srng_params.ring_base_vaddr;
348 	soc->ipa_uc_rx_rsc.ipa_reo_ring_size =
349 		(srng_params.num_entries * srng_params.entry_size) << 2;
350 	addr_offset = (unsigned long)(hal_srng->u.dst_ring.tp_addr) -
351 		      (unsigned long)(hal_soc->dev_base_addr);
352 	soc->ipa_uc_rx_rsc.ipa_reo_tp_paddr =
353 				(qdf_dma_addr_t)(addr_offset + dev_base_paddr);
354 
355 	QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_INFO,
356 		"%s: addr_offset=%x, dev_base_paddr=%x, ipa_reo_tp_paddr=%x",
357 		__func__, (unsigned int)addr_offset,
358 		(unsigned int)dev_base_paddr,
359 		(unsigned int)(soc->ipa_uc_rx_rsc.ipa_reo_tp_paddr));
360 
361 	hal_srng = pdev->rx_refill_buf_ring2.hal_srng;
362 	hal_get_srng_params(hal_soc, (void *)hal_srng, &srng_params);
363 	soc->ipa_uc_rx_rsc.ipa_rx_refill_buf_ring_base_paddr =
364 		srng_params.ring_base_paddr;
365 	soc->ipa_uc_rx_rsc.ipa_rx_refill_buf_ring_base_vaddr =
366 		srng_params.ring_base_vaddr;
367 	soc->ipa_uc_rx_rsc.ipa_rx_refill_buf_ring_size =
368 		(srng_params.num_entries * srng_params.entry_size) << 2;
369 	hp_addr = hal_srng_get_hp_addr(hal_soc, (void *)hal_srng);
370 	soc->ipa_uc_rx_rsc.ipa_rx_refill_buf_hp_paddr = hp_addr;
371 
372 	QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_INFO,
373 		"%s: ipa_rx_refill_buf_hp_paddr=%x", __func__,
374 		(unsigned int)(soc->ipa_uc_rx_rsc.ipa_rx_refill_buf_hp_paddr));
375 
376 	return 0;
377 }
378 
379 /**
380  * dp_ipa_uc_get_resource() - Client request resource information
381  * @ppdev - handle to the device instance
382  *
383  *  IPA client will request IPA UC related resource information
384  *  Resource information will be distributed to IPA module
385  *  All of the required resources should be pre-allocated
386  *
387  * Return: QDF_STATUS
388  */
389 QDF_STATUS dp_ipa_get_resource(struct cdp_pdev *ppdev)
390 {
391 	struct dp_pdev *pdev = (struct dp_pdev *)ppdev;
392 	struct dp_soc *soc = pdev->soc;
393 	struct dp_ipa_resources *ipa_res = &pdev->ipa_resource;
394 
395 	ipa_res->tx_ring_base_paddr =
396 		soc->ipa_uc_tx_rsc.ipa_tcl_ring_base_paddr;
397 	ipa_res->tx_ring_size =
398 		soc->ipa_uc_tx_rsc.ipa_tcl_ring_size;
399 	ipa_res->tx_num_alloc_buffer =
400 		(uint32_t)soc->ipa_uc_tx_rsc.alloc_tx_buf_cnt;
401 
402 	ipa_res->tx_comp_ring_base_paddr =
403 		soc->ipa_uc_tx_rsc.ipa_wbm_ring_base_paddr;
404 	ipa_res->tx_comp_ring_size =
405 		soc->ipa_uc_tx_rsc.ipa_wbm_ring_size;
406 
407 	ipa_res->rx_rdy_ring_base_paddr =
408 		soc->ipa_uc_rx_rsc.ipa_reo_ring_base_paddr;
409 	ipa_res->rx_rdy_ring_size =
410 		soc->ipa_uc_rx_rsc.ipa_reo_ring_size;
411 
412 	ipa_res->rx_refill_ring_base_paddr =
413 		soc->ipa_uc_rx_rsc.ipa_rx_refill_buf_ring_base_paddr;
414 	ipa_res->rx_refill_ring_size =
415 		soc->ipa_uc_rx_rsc.ipa_rx_refill_buf_ring_size;
416 
417 	if ((0 == ipa_res->tx_comp_ring_base_paddr) ||
418 			(0 == ipa_res->rx_rdy_ring_base_paddr))
419 		return QDF_STATUS_E_FAILURE;
420 
421 	return QDF_STATUS_SUCCESS;
422 }
423 
424 /**
425  * dp_ipa_set_doorbell_paddr () - Set doorbell register physical address to SRNG
426  * @ppdev - handle to the device instance
427  *
428  * Set TX_COMP_DOORBELL register physical address to WBM Head_Ptr_MemAddr_LSB
429  * Set RX_READ_DOORBELL register physical address to REO Head_Ptr_MemAddr_LSB
430  *
431  * Return: none
432  */
433 QDF_STATUS dp_ipa_set_doorbell_paddr(struct cdp_pdev *ppdev)
434 {
435 	struct dp_pdev *pdev = (struct dp_pdev *)ppdev;
436 	struct dp_soc *soc = pdev->soc;
437 	struct dp_ipa_resources *ipa_res = &pdev->ipa_resource;
438 	struct hal_srng *wbm_srng =
439 			soc->tx_comp_ring[IPA_TX_COMP_RING_IDX].hal_srng;
440 	struct hal_srng *reo_srng =
441 			soc->reo_dest_ring[IPA_REO_DEST_RING_IDX].hal_srng;
442 
443 	hal_srng_dst_set_hp_paddr(wbm_srng, ipa_res->tx_comp_doorbell_paddr);
444 	hal_srng_dst_init_hp(wbm_srng, ipa_res->tx_comp_doorbell_vaddr);
445 	hal_srng_dst_set_hp_paddr(reo_srng, ipa_res->rx_ready_doorbell_paddr);
446 
447 	return QDF_STATUS_SUCCESS;
448 }
449 
450 /**
451  * dp_ipa_op_response() - Handle OP command response from firmware
452  * @ppdev - handle to the device instance
453  * @op_msg: op response message from firmware
454  *
455  * Return: none
456  */
457 QDF_STATUS dp_ipa_op_response(struct cdp_pdev *ppdev, uint8_t *op_msg)
458 {
459 	struct dp_pdev *pdev = (struct dp_pdev *)ppdev;
460 
461 	if (pdev->ipa_uc_op_cb) {
462 		pdev->ipa_uc_op_cb(op_msg, pdev->usr_ctxt);
463 	} else {
464 		QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
465 		    "%s: IPA callback function is not registered", __func__);
466 		qdf_mem_free(op_msg);
467 		return QDF_STATUS_E_FAILURE;
468 	}
469 
470 	return QDF_STATUS_SUCCESS;
471 }
472 
473 /**
474  * dp_ipa_register_op_cb() - Register OP handler function
475  * @ppdev - handle to the device instance
476  * @op_cb: handler function pointer
477  *
478  * Return: none
479  */
480 QDF_STATUS dp_ipa_register_op_cb(struct cdp_pdev *ppdev,
481 				 ipa_uc_op_cb_type op_cb,
482 				 void *usr_ctxt)
483 {
484 	struct dp_pdev *pdev = (struct dp_pdev *)ppdev;
485 
486 	pdev->ipa_uc_op_cb = op_cb;
487 	pdev->usr_ctxt = usr_ctxt;
488 
489 	return QDF_STATUS_SUCCESS;
490 }
491 
492 /**
493  * dp_ipa_get_stat() - Get firmware wdi status
494  * @ppdev - handle to the device instance
495  *
496  * Return: none
497  */
498 QDF_STATUS dp_ipa_get_stat(struct cdp_pdev *ppdev)
499 {
500 	/* TBD */
501 	return QDF_STATUS_SUCCESS;
502 }
503 
504 /**
505  * dp_tx_send_ipa_data_frame() - send IPA data frame
506  * @vdev: vdev
507  * @skb: skb
508  *
509  * Return: skb/ NULL is for success
510  */
511 qdf_nbuf_t dp_tx_send_ipa_data_frame(struct cdp_vdev *vdev, qdf_nbuf_t skb)
512 {
513 	qdf_nbuf_t ret;
514 
515 	/* Terminate the (single-element) list of tx frames */
516 	qdf_nbuf_set_next(skb, NULL);
517 	ret = dp_tx_send((struct dp_vdev_t *)vdev, skb);
518 	if (ret) {
519 		QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
520 			  "%s: Failed to tx", __func__);
521 		return ret;
522 	}
523 
524 	return NULL;
525 }
526 
527 /**
528  * dp_ipa_enable_autonomy() – Enable autonomy RX path
529  * @pdev - handle to the device instance
530  *
531  * Set all RX packet route to IPA REO ring
532  * Program Destination_Ring_Ctrl_IX_0 REO register to point IPA REO ring
533  * Return: none
534  */
535 QDF_STATUS dp_ipa_enable_autonomy(struct cdp_pdev *ppdev)
536 {
537 	struct dp_pdev *pdev = (struct dp_pdev *)ppdev;
538 	struct dp_soc *soc = pdev->soc;
539 	uint32_t remap_val;
540 
541 	/* Call HAL API to remap REO rings to REO2IPA ring */
542 	remap_val = HAL_REO_REMAP_VAL(REO_REMAP_TCL, REO_REMAP_TCL) |
543 		    HAL_REO_REMAP_VAL(REO_REMAP_SW1, REO_REMAP_SW4) |
544 		    HAL_REO_REMAP_VAL(REO_REMAP_SW2, REO_REMAP_SW4) |
545 		    HAL_REO_REMAP_VAL(REO_REMAP_SW3, REO_REMAP_SW4) |
546 		    HAL_REO_REMAP_VAL(REO_REMAP_SW4, REO_REMAP_SW4) |
547 		    HAL_REO_REMAP_VAL(REO_REMAP_RELEASE, REO_REMAP_RELEASE) |
548 		    HAL_REO_REMAP_VAL(REO_REMAP_FW, REO_REMAP_FW) |
549 		    HAL_REO_REMAP_VAL(REO_REMAP_UNUSED, REO_REMAP_FW);
550 	hal_reo_remap_IX0(soc->hal_soc, remap_val);
551 
552 	return QDF_STATUS_SUCCESS;
553 }
554 
555 /**
556  * dp_ipa_disable_autonomy() – Disable autonomy RX path
557  * @ppdev - handle to the device instance
558  *
559  * Disable RX packet routing to IPA REO
560  * Program Destination_Ring_Ctrl_IX_0 REO register to disable
561  * Return: none
562  */
563 QDF_STATUS dp_ipa_disable_autonomy(struct cdp_pdev *ppdev)
564 {
565 	struct dp_pdev *pdev = (struct dp_pdev *)ppdev;
566 	struct dp_soc *soc = pdev->soc;
567 	uint32_t remap_val;
568 
569 	/* Call HAL API to remap REO rings to REO2IPA ring */
570 	remap_val = HAL_REO_REMAP_VAL(REO_REMAP_TCL, REO_REMAP_TCL) |
571 		    HAL_REO_REMAP_VAL(REO_REMAP_SW1, REO_REMAP_SW1) |
572 		    HAL_REO_REMAP_VAL(REO_REMAP_SW2, REO_REMAP_SW2) |
573 		    HAL_REO_REMAP_VAL(REO_REMAP_SW3, REO_REMAP_SW3) |
574 		    HAL_REO_REMAP_VAL(REO_REMAP_SW4, REO_REMAP_SW2) |
575 		    HAL_REO_REMAP_VAL(REO_REMAP_RELEASE, REO_REMAP_RELEASE) |
576 		    HAL_REO_REMAP_VAL(REO_REMAP_FW, REO_REMAP_FW) |
577 		    HAL_REO_REMAP_VAL(REO_REMAP_UNUSED, REO_REMAP_FW);
578 	hal_reo_remap_IX0(soc->hal_soc, remap_val);
579 
580 	return QDF_STATUS_SUCCESS;
581 }
582 
583 /* This should be configurable per H/W configuration enable status */
584 #define L3_HEADER_PADDING	2
585 
586 /**
587  * dp_ipa_setup() - Setup and connect IPA pipes
588  * @ppdev - handle to the device instance
589  * @ipa_i2w_cb: IPA to WLAN callback
590  * @ipa_w2i_cb: WLAN to IPA callback
591  * @ipa_wdi_meter_notifier_cb: IPA WDI metering callback
592  * @ipa_desc_size: IPA descriptor size
593  * @ipa_priv: handle to the HTT instance
594  * @is_rm_enabled: Is IPA RM enabled or not
595  * @tx_pipe_handle: pointer to Tx pipe handle
596  * @rx_pipe_handle: pointer to Rx pipe handle
597  *
598  * Return: QDF_STATUS
599  */
600 QDF_STATUS dp_ipa_setup(struct cdp_pdev *ppdev, void *ipa_i2w_cb,
601 			void *ipa_w2i_cb, void *ipa_wdi_meter_notifier_cb,
602 			uint32_t ipa_desc_size, void *ipa_priv,
603 			bool is_rm_enabled, uint32_t *tx_pipe_handle,
604 			uint32_t *rx_pipe_handle)
605 {
606 	struct dp_pdev *pdev = (struct dp_pdev *)ppdev;
607 	struct dp_soc *soc = pdev->soc;
608 	struct dp_ipa_resources *ipa_res = &pdev->ipa_resource;
609 	qdf_ipa_wdi3_setup_info_t *tx;
610 	qdf_ipa_wdi3_setup_info_t *rx;
611 	qdf_ipa_wdi3_conn_in_params_t pipe_in;
612 	qdf_ipa_wdi3_conn_out_params_t pipe_out;
613 	struct tcl_data_cmd *tcl_desc_ptr;
614 	uint8_t *desc_addr;
615 	uint32_t desc_size;
616 	int ret;
617 
618 	qdf_mem_zero(&tx, sizeof(struct ipa_wdi3_setup_info));
619 	qdf_mem_zero(&rx, sizeof(struct ipa_wdi3_setup_info));
620 	qdf_mem_zero(&pipe_in, sizeof(pipe_in));
621 	qdf_mem_zero(&pipe_out, sizeof(pipe_out));
622 
623 	/* TX PIPE */
624 	/**
625 	 * Transfer Ring: WBM Ring
626 	 * Transfer Ring Doorbell PA: WBM Tail Pointer Address
627 	 * Event Ring: TCL ring
628 	 * Event Ring Doorbell PA: TCL Head Pointer Address
629 	 */
630 	tx = &QDF_IPA_WDI3_CONN_IN_PARAMS_TX(&pipe_in);
631 	QDF_IPA_WDI3_SETUP_INFO_NAT_EN(tx) = IPA_BYPASS_NAT;
632 	QDF_IPA_WDI3_SETUP_INFO_HDR_LEN(tx) = DP_IPA_UC_WLAN_TX_HDR_LEN;
633 	QDF_IPA_WDI3_SETUP_INFO_HDR_OFST_PKT_SIZE_VALID(tx) = 0;
634 	QDF_IPA_WDI3_SETUP_INFO_HDR_OFST_PKT_SIZE(tx) = 0;
635 	QDF_IPA_WDI3_SETUP_INFO_HDR_ADDITIONAL_CONST_LEN(tx) = 0;
636 	QDF_IPA_WDI3_SETUP_INFO_MODE(tx) = IPA_BASIC;
637 	QDF_IPA_WDI3_SETUP_INFO_HDR_LITTLE_ENDIAN(tx) = true;
638 	QDF_IPA_WDI3_SETUP_INFO_CLIENT(tx) = IPA_CLIENT_WLAN1_CONS;
639 	QDF_IPA_WDI3_SETUP_INFO_TRANSFER_RING_BASE_PA(tx) =
640 		ipa_res->tx_comp_ring_base_paddr;
641 	QDF_IPA_WDI3_SETUP_INFO_TRANSFER_RING_SIZE(tx) =
642 		ipa_res->tx_comp_ring_size;
643 	/* WBM Tail Pointer Address */
644 	QDF_IPA_WDI3_SETUP_INFO_TRANSFER_RING_DOORBELL_PA(tx) =
645 		soc->ipa_uc_tx_rsc.ipa_wbm_tp_paddr;
646 	QDF_IPA_WDI3_SETUP_INFO_EVENT_RING_BASE_PA(tx) =
647 		ipa_res->tx_ring_base_paddr;
648 	QDF_IPA_WDI3_SETUP_INFO_EVENT_RING_SIZE(tx) = ipa_res->tx_ring_size;
649 	/* TCL Head Pointer Address */
650 	QDF_IPA_WDI3_SETUP_INFO_EVENT_RING_DOORBELL_PA(tx) =
651 		soc->ipa_uc_tx_rsc.ipa_tcl_hp_paddr;
652 	QDF_IPA_WDI3_SETUP_INFO_NUM_PKT_BUFFERS(tx) =
653 		ipa_res->tx_num_alloc_buffer;
654 	QDF_IPA_WDI3_SETUP_INFO_PKT_OFFSET(tx) = 0;
655 
656 	/* Preprogram TCL descriptor */
657 	desc_addr =
658 		(uint8_t *)QDF_IPA_WDI3_SETUP_INFO_DESC_FORMAT_TEMPLATE(tx);
659 	desc_size = sizeof(struct tcl_data_cmd);
660 	HAL_TX_DESC_SET_TLV_HDR(desc_addr, HAL_TX_TCL_DATA_TAG, desc_size);
661 	tcl_desc_ptr = (struct tcl_data_cmd *)
662 		(QDF_IPA_WDI3_SETUP_INFO_DESC_FORMAT_TEMPLATE(tx) + 1);
663 	tcl_desc_ptr->buf_addr_info.return_buffer_manager =
664 						HAL_RX_BUF_RBM_SW2_BM;
665 	tcl_desc_ptr->addrx_en = 1;	/* Address X search enable in ASE */
666 	tcl_desc_ptr->encap_type = HAL_TX_ENCAP_TYPE_ETHERNET;
667 	tcl_desc_ptr->packet_offset = 2;	/* padding for alignment */
668 
669 	/* RX PIPE */
670 	/**
671 	 * Transfer Ring: REO Ring
672 	 * Transfer Ring Doorbell PA: REO Tail Pointer Address
673 	 * Event Ring: FW ring
674 	 * Event Ring Doorbell PA: FW Head Pointer Address
675 	 */
676 	rx = &QDF_IPA_WDI3_CONN_IN_PARAMS_RX(&pipe_in);
677 	QDF_IPA_WDI3_SETUP_INFO_NAT_EN(rx) = IPA_BYPASS_NAT;
678 	QDF_IPA_WDI3_SETUP_INFO_HDR_LEN(rx) = DP_IPA_UC_WLAN_TX_HDR_LEN;
679 	QDF_IPA_WDI3_SETUP_INFO_HDR_OFST_METADATA_VALID(rx) = 0;
680 	QDF_IPA_WDI3_SETUP_INFO_HDR_METADATA_REG_VALID(rx) = 1;
681 	QDF_IPA_WDI3_SETUP_INFO_MODE(rx) = IPA_BASIC;
682 	QDF_IPA_WDI3_SETUP_INFO_CLIENT(rx) = IPA_CLIENT_WLAN1_PROD;
683 	QDF_IPA_WDI3_SETUP_INFO_TRANSFER_RING_BASE_PA(rx) = ipa_res->rx_rdy_ring_base_paddr;
684 	QDF_IPA_WDI3_SETUP_INFO_TRANSFER_RING_SIZE(rx) = ipa_res->rx_rdy_ring_size;
685 	QDF_IPA_WDI3_SETUP_INFO_TRANSFER_RING_DOORBELL_PA(rx) = /* REO Tail Pointer Address */
686 		soc->ipa_uc_rx_rsc.ipa_reo_tp_paddr;
687 	QDF_IPA_WDI3_SETUP_INFO_EVENT_RING_BASE_PA(rx) = ipa_res->rx_refill_ring_base_paddr;
688 	QDF_IPA_WDI3_SETUP_INFO_EVENT_RING_SIZE(rx) = ipa_res->rx_refill_ring_size;
689 	QDF_IPA_WDI3_SETUP_INFO_EVENT_RING_DOORBELL_PA(rx) = /* FW Head Pointer Address */
690 		soc->ipa_uc_rx_rsc.ipa_rx_refill_buf_hp_paddr;
691 	QDF_IPA_WDI3_SETUP_INFO_PKT_OFFSET(rx) = RX_PKT_TLVS_LEN + L3_HEADER_PADDING;
692 
693 	QDF_IPA_WDI3_CONN_IN_PARAMS_NOTIFY(&pipe_in) = ipa_w2i_cb;
694 	QDF_IPA_WDI3_CONN_IN_PARAMS_PRIV(&pipe_in) = ipa_priv;
695 
696 	/* Connect WDI IPA PIPE */
697 	ret = qdf_ipa_wdi3_conn_pipes(&pipe_in, &pipe_out);
698 	if (ret) {
699 		QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
700 			  "%s: ipa_wdi3_conn_pipes: IPA pipe setup failed: ret=%d",
701 			  __func__, ret);
702 		return QDF_STATUS_E_FAILURE;
703 	}
704 
705 	/* IPA uC Doorbell registers */
706 	QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_DEBUG,
707 		  "%s: Tx DB PA=0x%x, Rx DB PA=0x%x",
708 		  __func__,
709 		(unsigned int)QDF_IPA_WDI3_CONN_OUT_PARAMS_TX_UC_DB_PA(&pipe_out),
710 		(unsigned int)QDF_IPA_WDI3_CONN_OUT_PARAMS_RX_UC_DB_PA(&pipe_out));
711 
712 	ipa_res->tx_comp_doorbell_paddr =
713 		QDF_IPA_WDI3_CONN_OUT_PARAMS_TX_UC_DB_PA(&pipe_out);
714 	ipa_res->tx_comp_doorbell_vaddr =
715 		QDF_IPA_WDI3_CONN_OUT_PARAMS_TX_UC_DB_VA(&pipe_out);
716 	ipa_res->rx_ready_doorbell_paddr =
717 		QDF_IPA_WDI3_CONN_OUT_PARAMS_RX_UC_DB_PA(&pipe_out);
718 
719 	QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_DEBUG,
720 		  "%s: Tx: %s=%pK, %s=%d, %s=%pK, %s=%pK, %s=%d, %s=%pK, %s=%d, %s=%pK",
721 		  __func__,
722 		  "transfer_ring_base_pa",
723 		  (void *)QDF_IPA_WDI3_SETUP_INFO_TRANSFER_RING_BASE_PA(tx),
724 		  "transfer_ring_size",
725 		  QDF_IPA_WDI3_SETUP_INFO_TRANSFER_RING_SIZE(tx),
726 		  "transfer_ring_doorbell_pa",
727 		  (void *)QDF_IPA_WDI3_SETUP_INFO_TRANSFER_RING_DOORBELL_PA(tx),
728 		  "event_ring_base_pa",
729 		  (void *)QDF_IPA_WDI3_SETUP_INFO_EVENT_RING_BASE_PA(tx),
730 		  "event_ring_size",
731 		  QDF_IPA_WDI3_SETUP_INFO_EVENT_RING_SIZE(tx),
732 		  "event_ring_doorbell_pa",
733 		  (void *)QDF_IPA_WDI3_SETUP_INFO_EVENT_RING_DOORBELL_PA(tx),
734 		  "num_pkt_buffers",
735 		  QDF_IPA_WDI3_SETUP_INFO_NUM_PKT_BUFFERS(tx),
736 		  "tx_comp_doorbell_paddr",
737 		  (void *)ipa_res->tx_comp_doorbell_paddr);
738 
739 	QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_DEBUG,
740 		  "%s: Rx: %s=%pK, %s=%d, %s=%pK, %s=%pK, %s=%d, %s=%pK, %s=%d, %s=%pK",
741 		  __func__,
742 		  "transfer_ring_base_pa",
743 		  (void *)QDF_IPA_WDI3_SETUP_INFO_TRANSFER_RING_BASE_PA(rx),
744 		  "transfer_ring_size",
745 		  QDF_IPA_WDI3_SETUP_INFO_TRANSFER_RING_SIZE(rx),
746 		  "transfer_ring_doorbell_pa",
747 		  (void *)QDF_IPA_WDI3_SETUP_INFO_TRANSFER_RING_DOORBELL_PA(rx),
748 		  "event_ring_base_pa",
749 		  (void *)QDF_IPA_WDI3_SETUP_INFO_EVENT_RING_BASE_PA(rx),
750 		  "event_ring_size",
751 		  QDF_IPA_WDI3_SETUP_INFO_EVENT_RING_SIZE(rx),
752 		  "event_ring_doorbell_pa",
753 		  (void *)QDF_IPA_WDI3_SETUP_INFO_EVENT_RING_DOORBELL_PA(rx),
754 		  "num_pkt_buffers",
755 		  QDF_IPA_WDI3_SETUP_INFO_NUM_PKT_BUFFERS(rx),
756 		  "tx_comp_doorbell_paddr",
757 		  (void *)ipa_res->rx_ready_doorbell_paddr);
758 
759 	return QDF_STATUS_SUCCESS;
760 }
761 
762 /**
763  * dp_ipa_cleanup() - Disconnect IPA pipes
764  * @tx_pipe_handle: Tx pipe handle
765  * @rx_pipe_handle: Rx pipe handle
766  *
767  * Return: QDF_STATUS
768  */
769 QDF_STATUS dp_ipa_cleanup(uint32_t tx_pipe_handle, uint32_t rx_pipe_handle)
770 {
771 	int ret;
772 
773 	ret = qdf_ipa_wdi3_disconn_pipes();
774 	if (ret) {
775 		QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
776 		    "%s: ipa_wdi3_disconn_pipes: IPA pipe cleanup failed: ret=%d",
777 		    __func__, ret);
778 		return QDF_STATUS_E_FAILURE;
779 	}
780 
781 	return QDF_STATUS_SUCCESS;
782 }
783 
784 /**
785  * dp_ipa_setup_iface() - Setup IPA header and register interface
786  * @ifname: Interface name
787  * @mac_addr: Interface MAC address
788  * @prod_client: IPA prod client type
789  * @cons_client: IPA cons client type
790  * @session_id: Session ID
791  * @is_ipv6_enabled: Is IPV6 enabled or not
792  *
793  * Return: QDF_STATUS
794  */
795 QDF_STATUS dp_ipa_setup_iface(char *ifname, uint8_t *mac_addr,
796 			      qdf_ipa_client_type_t prod_client,
797 			      qdf_ipa_client_type_t cons_client,
798 			      uint8_t session_id, bool is_ipv6_enabled)
799 {
800 	qdf_ipa_wdi3_reg_intf_in_params_t in;
801 	qdf_ipa_wdi3_hdr_info_t hdr_info;
802 	struct dp_ipa_uc_tx_hdr uc_tx_hdr;
803 	int ret = -EINVAL;
804 
805 	QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_DEBUG,
806 		  "%s: Add Partial hdr: %s, %pM",
807 		  __func__, ifname, mac_addr);
808 
809 	qdf_mem_zero(&hdr_info, sizeof(qdf_ipa_wdi3_hdr_info_t));
810 	qdf_ether_addr_copy(uc_tx_hdr.eth.h_source, mac_addr);
811 
812 	/* IPV4 header */
813 	uc_tx_hdr.eth.h_proto = qdf_htons(ETH_P_IP);
814 
815 	QDF_IPA_WDI3_HDR_INFO_HDR(&hdr_info) = (uint8_t *)&uc_tx_hdr;
816 	QDF_IPA_WDI3_HDR_INFO_HDR_LEN(&hdr_info) = DP_IPA_UC_WLAN_TX_HDR_LEN;
817 	QDF_IPA_WDI3_HDR_INFO_HDR_TYPE(&hdr_info) = IPA_HDR_L2_ETHERNET_II;
818 	QDF_IPA_WDI3_HDR_INFO_DST_MAC_ADDR_OFFSET(&hdr_info) =
819 		DP_IPA_UC_WLAN_HDR_DES_MAC_OFFSET;
820 
821 	QDF_IPA_WDI3_REG_INTF_IN_PARAMS_NETDEV_NAME(&in) = ifname;
822 	memcpy(&(QDF_IPA_WDI3_REG_INTF_IN_PARAMS_HDR_INFO(&in)[0]), &hdr_info,
823 		sizeof(qdf_ipa_wdi3_hdr_info_t));
824 	QDF_IPA_WDI3_REG_INTF_IN_PARAMS_IS_META_DATA_VALID(&in) = 1;
825 	QDF_IPA_WDI3_REG_INTF_IN_PARAMS_META_DATA(&in) =
826 		htonl(session_id << 16);
827 	QDF_IPA_WDI3_REG_INTF_IN_PARAMS_META_DATA_MASK(&in) = htonl(0x00FF0000);
828 
829 	/* IPV6 header */
830 	if (is_ipv6_enabled) {
831 		uc_tx_hdr.eth.h_proto = qdf_htons(ETH_P_IPV6);
832 		memcpy(&(QDF_IPA_WDI3_REG_INTF_IN_PARAMS_HDR_INFO(&in)[1]),
833 			&hdr_info, sizeof(qdf_ipa_wdi3_hdr_info_t));
834 	}
835 
836 	ret = qdf_ipa_wdi3_reg_intf(&in);
837 	if (ret) {
838 		QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
839 		    "%s: ipa_wdi3_reg_intf: register IPA interface falied: ret=%d",
840 		    __func__, ret);
841 		return QDF_STATUS_E_FAILURE;
842 	}
843 
844 	return QDF_STATUS_SUCCESS;
845 }
846 
847 /**
848  * dp_ipa_cleanup_iface() - Cleanup IPA header and deregister interface
849  * @ifname: Interface name
850  * @is_ipv6_enabled: Is IPV6 enabled or not
851  *
852  * Return: QDF_STATUS
853  */
854 QDF_STATUS dp_ipa_cleanup_iface(char *ifname, bool is_ipv6_enabled)
855 {
856 	int ret;
857 
858 	ret = qdf_ipa_wdi3_dereg_intf(ifname);
859 	if (ret) {
860 		QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
861 			  "%s: ipa_wdi3_dereg_intf: IPA pipe deregistration failed: ret=%d",
862 			  __func__, ret);
863 		return QDF_STATUS_E_FAILURE;
864 	}
865 
866 	return QDF_STATUS_SUCCESS;
867 }
868 
869  /**
870  * dp_ipa_uc_enable_pipes() - Enable and resume traffic on Tx/Rx pipes
871  * @ppdev - handle to the device instance
872  *
873  * Return: QDF_STATUS
874  */
875 QDF_STATUS dp_ipa_enable_pipes(struct cdp_pdev *ppdev)
876 {
877 	QDF_STATUS result;
878 
879 	result = qdf_ipa_wdi3_enable_pipes();
880 	if (result) {
881 		QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
882 			  "%s: Enable WDI PIPE fail, code %d",
883 			  __func__, result);
884 		return QDF_STATUS_E_FAILURE;
885 	}
886 
887 	return QDF_STATUS_SUCCESS;
888 }
889 
890 /**
891  * dp_ipa_uc_disable_pipes() – Suspend traffic and disable Tx/Rx pipes
892  * @ppdev - handle to the device instance
893  *
894  * Return: QDF_STATUS
895  */
896 QDF_STATUS dp_ipa_disable_pipes(struct cdp_pdev *ppdev)
897 {
898 	QDF_STATUS result;
899 
900 	result = qdf_ipa_wdi3_disable_pipes();
901 	if (result) {
902 		QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
903 			  "%s: Disable WDI PIPE fail, code %d",
904 			  __func__, result);
905 		return QDF_STATUS_E_FAILURE;
906 	}
907 
908 	return QDF_STATUS_SUCCESS;
909 }
910 
911 /**
912  * dp_ipa_set_perf_level() - Set IPA clock bandwidth based on data rates
913  * @client: Client type
914  * @max_supported_bw_mbps: Maximum bandwidth needed (in Mbps)
915  *
916  * Return: QDF_STATUS
917  */
918 QDF_STATUS dp_ipa_set_perf_level(int client, uint32_t max_supported_bw_mbps)
919 {
920 	qdf_ipa_wdi3_perf_profile_t profile;
921 	QDF_STATUS result;
922 
923 	profile.client = client;
924 	profile.max_supported_bw_mbps = max_supported_bw_mbps;
925 
926 	result = qdf_ipa_wdi3_set_perf_profile(&profile);
927 	if (result) {
928 		QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
929 			  "%s: ipa_wdi3_set_perf_profile fail, code %d",
930 			  __func__, result);
931 		return QDF_STATUS_E_FAILURE;
932 	}
933 
934 	return QDF_STATUS_SUCCESS;
935 }
936 #endif
937