xref: /wlan-dirver/qca-wifi-host-cmn/target_if/wifi_pos/src/target_if_wifi_pos.c (revision 92d87f51612f6c3b2285266215edee8911647c2f)
1 /*
2  * Copyright (c) 2013-2018 The Linux Foundation. All rights reserved.
3  *
4  * Permission to use, copy, modify, and/or distribute this software for
5  * any purpose with or without fee is hereby granted, provided that the
6  * above copyright notice and this permission notice appear in all
7  * copies.
8  *
9  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
10  * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
11  * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
12  * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
13  * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
14  * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
15  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
16  * PERFORMANCE OF THIS SOFTWARE.
17  */
18 
19 /**
20  * DOC: target_if_wifi_pos.c
21  * This file defines the functions pertinent to wifi positioning component's
22  * target if layer.
23  */
24 #include "../../../../umac/wifi_pos/src/wifi_pos_utils_i.h"
25 #include "wmi_unified_api.h"
26 #include "wlan_lmac_if_def.h"
27 #include "target_if_wifi_pos.h"
28 #include "../../../../umac/wifi_pos/src/wifi_pos_main_i.h"
29 #include "target_if.h"
30 #ifdef WLAN_FEATURE_CIF_CFR
31 #include "hal_api.h"
32 
33 #define RING_BASE_ALIGN 8
34 
35 static void *target_if_wifi_pos_vaddr_lookup(
36 				struct wifi_pos_psoc_priv_obj *priv,
37 				void *paddr, uint8_t ring_num, uint32_t cookie)
38 {
39 	if (priv->dma_buf_pool[ring_num][cookie].paddr == paddr) {
40 		return priv->dma_buf_pool[ring_num][cookie].vaddr +
41 				priv->dma_buf_pool[ring_num][cookie].offset;
42 	} else {
43 		target_if_err("incorrect paddr found on cookie slot");
44 		return NULL;
45 	}
46 }
47 
48 static QDF_STATUS target_if_wifi_pos_replenish_ring(
49 			struct wifi_pos_psoc_priv_obj *priv, uint8_t ring_idx,
50 			void *alinged_vaddr, uint32_t cookie)
51 {
52 	uint64_t *ring_entry;
53 	uint32_t dw_lo, dw_hi = 0, map_status;
54 	void *hal_soc = priv->hal_soc;
55 	void *srng = priv->dma_cfg[ring_idx].srng;
56 	void *paddr;
57 
58 	if (!alinged_vaddr) {
59 		target_if_debug("NULL alinged_vaddr provided");
60 		return QDF_STATUS_SUCCESS;
61 	}
62 
63 	map_status = qdf_mem_map_nbytes_single(NULL, alinged_vaddr,
64 			QDF_DMA_FROM_DEVICE,
65 			priv->dma_cap[ring_idx].min_buf_size,
66 			(qdf_dma_addr_t *)&paddr);
67 	if (map_status) {
68 		target_if_err("mem map failed status: %d", map_status);
69 		return QDF_STATUS_E_FAILURE;
70 	}
71 	QDF_ASSERT(!((uint64_t)paddr % priv->dma_cap[ring_idx].min_buf_align));
72 	priv->dma_buf_pool[ring_idx][cookie].paddr = paddr;
73 
74 	hal_srng_access_start(hal_soc, srng);
75 	ring_entry = hal_srng_src_get_next(hal_soc, srng);
76 	dw_lo = (uint64_t)paddr & 0xFFFFFFFF;
77 	WMI_OEM_DMA_DATA_ADDR_HI_SET(dw_hi, (uint64_t)paddr >> 32);
78 	WMI_OEM_DMA_DATA_ADDR_HI_HOST_DATA_SET(dw_hi, cookie);
79 	*ring_entry = (uint64_t)dw_hi << 32 | dw_lo;
80 	hal_srng_access_end(hal_soc, srng);
81 
82 	return QDF_STATUS_SUCCESS;
83 }
84 
85 static QDF_STATUS target_if_wifi_pos_get_indirect_data(
86 		struct wifi_pos_psoc_priv_obj *priv_obj,
87 		wmi_oem_indirect_data *indirect,
88 		struct oem_data_rsp *rsp, uint32_t *cookie)
89 {
90 	void *paddr = NULL;
91 	uint32_t addr_hi;
92 	uint8_t ring_idx = 0, num_rings;
93 
94 	if (!indirect) {
95 		target_if_debug("no indirect data. regular event received");
96 		return QDF_STATUS_SUCCESS;
97 	}
98 
99 	ring_idx = indirect->pdev_id - 1;
100 	num_rings = priv_obj->num_rings;
101 	if (ring_idx >= num_rings) {
102 		target_if_err("incorrect pdev_id: %d", indirect->pdev_id);
103 		return QDF_STATUS_E_INVAL;
104 	}
105 	addr_hi = (uint64_t)WMI_OEM_DMA_DATA_ADDR_HI_GET(
106 						indirect->addr_hi);
107 	paddr = (void *)((uint64_t)addr_hi << 32 | indirect->addr_lo);
108 	*cookie = WMI_OEM_DMA_DATA_ADDR_HI_HOST_DATA_GET(
109 						indirect->addr_hi);
110 	rsp->vaddr = target_if_wifi_pos_vaddr_lookup(priv_obj,
111 					paddr, ring_idx, *cookie);
112 	rsp->dma_len = indirect->len;
113 	qdf_mem_unmap_nbytes_single(NULL, (qdf_dma_addr_t)paddr,
114 			QDF_DMA_FROM_DEVICE,
115 			priv_obj->dma_cap[ring_idx].min_buf_size);
116 
117 	return QDF_STATUS_SUCCESS;
118 }
119 
120 #else
121 static QDF_STATUS target_if_wifi_pos_replenish_ring(
122 			struct wifi_pos_psoc_priv_obj *priv, uint8_t ring_idx,
123 			void *vaddr, uint32_t cookie)
124 {
125 	return QDF_STATUS_SUCCESS;
126 }
127 
128 static QDF_STATUS target_if_wifi_pos_get_indirect_data(
129 		struct wifi_pos_psoc_priv_obj *priv_obj,
130 		wmi_oem_indirect_data *indirect,
131 		struct oem_data_rsp *rsp, uint32_t *cookie)
132 {
133 	return QDF_STATUS_SUCCESS;
134 }
135 #endif
136 
137 /**
138  * target_if_wifi_pos_oem_rsp_ev_handler: handler registered with
139  * WMI_OEM_RESPONSE_EVENTID
140  * @scn: scn handle
141  * @data_buf: event buffer
142  * @data_len: event buffer length
143  *
144  * Return: status of operation
145  */
146 static int target_if_wifi_pos_oem_rsp_ev_handler(ol_scn_t scn,
147 					uint8_t *data_buf,
148 					uint32_t data_len)
149 {
150 	int ret;
151 	uint8_t ring_idx = 0;
152 	QDF_STATUS status;
153 	uint32_t cookie = 0;
154 	wmi_oem_indirect_data *indirect;
155 	struct oem_data_rsp oem_rsp = {0};
156 	struct wifi_pos_psoc_priv_obj *priv_obj;
157 	struct wlan_objmgr_psoc *psoc = wifi_pos_get_psoc();
158 	struct wlan_lmac_if_wifi_pos_rx_ops *wifi_pos_rx_ops = NULL;
159 	WMI_OEM_RESPONSE_EVENTID_param_tlvs *param_buf =
160 		(WMI_OEM_RESPONSE_EVENTID_param_tlvs *)data_buf;
161 
162 	if (!psoc) {
163 		target_if_err("psoc is null");
164 		return QDF_STATUS_NOT_INITIALIZED;
165 	}
166 
167 	wlan_objmgr_psoc_get_ref(psoc, WLAN_WIFI_POS_TGT_IF_ID);
168 
169 	priv_obj = wifi_pos_get_psoc_priv_obj(psoc);
170 	if (!priv_obj) {
171 		target_if_err("priv_obj is null");
172 		wlan_objmgr_psoc_release_ref(psoc, WLAN_WIFI_POS_TGT_IF_ID);
173 		return QDF_STATUS_NOT_INITIALIZED;
174 	}
175 
176 	wifi_pos_rx_ops = target_if_wifi_pos_get_rxops(psoc);
177 	if (!wifi_pos_rx_ops || !wifi_pos_rx_ops->oem_rsp_event_rx) {
178 		wlan_objmgr_psoc_release_ref(psoc, WLAN_WIFI_POS_TGT_IF_ID);
179 		target_if_err("lmac callbacks not registered");
180 		return QDF_STATUS_NOT_INITIALIZED;
181 	}
182 
183 	oem_rsp.rsp_len_1 = param_buf->num_data;
184 	oem_rsp.data_1 = param_buf->data;
185 
186 	if (param_buf->num_data2) {
187 		oem_rsp.rsp_len_2 = param_buf->num_data2;
188 		oem_rsp.data_2 = param_buf->data2;
189 	}
190 
191 	indirect = (wmi_oem_indirect_data *)param_buf->indirect_data;
192 	status = target_if_wifi_pos_get_indirect_data(priv_obj, indirect,
193 						      &oem_rsp, &cookie);
194 	if (QDF_IS_STATUS_ERROR(status)) {
195 		target_if_err("get indirect data failed status: %d", status);
196 		wlan_objmgr_psoc_release_ref(psoc, WLAN_WIFI_POS_TGT_IF_ID);
197 		return QDF_STATUS_E_INVAL;
198 	}
199 
200 	ret = wifi_pos_rx_ops->oem_rsp_event_rx(psoc, &oem_rsp);
201 	if (indirect)
202 		ring_idx = indirect->pdev_id - 1;
203 	status = target_if_wifi_pos_replenish_ring(priv_obj, ring_idx,
204 					oem_rsp.vaddr, cookie);
205 	if (QDF_IS_STATUS_ERROR(status)) {
206 		target_if_err("replenish failed status: %d", status);
207 		ret = QDF_STATUS_E_FAILURE;
208 	}
209 
210 	wlan_objmgr_psoc_release_ref(psoc, WLAN_WIFI_POS_TGT_IF_ID);
211 
212 	return ret;
213 }
214 
215 /**
216  * wifi_pos_oem_cap_ev_handler: handler registered with wmi_oem_cap_event_id
217  * @scn: scn handle
218  * @buf: event buffer
219  * @len: event buffer length
220  *
221  * Return: status of operation
222  */
223 static int wifi_pos_oem_cap_ev_handler(ol_scn_t scn, uint8_t *buf, uint32_t len)
224 {
225 	/* TBD */
226 	return 0;
227 }
228 
229 /**
230  * wifi_pos_oem_meas_rpt_ev_handler: handler registered with
231  * wmi_oem_meas_report_event_id
232  * @scn: scn handle
233  * @buf: event buffer
234  * @len: event buffer length
235  *
236  * Return: status of operation
237  */
238 static int wifi_pos_oem_meas_rpt_ev_handler(ol_scn_t scn, uint8_t *buf,
239 					    uint32_t len)
240 {
241 	/* TBD */
242 	return 0;
243 }
244 
245 /**
246  * wifi_pos_oem_err_rpt_ev_handler: handler registered with
247  * wmi_oem_err_report_event_id
248  * @scn: scn handle
249  * @buf: event buffer
250  * @len: event buffer length
251  *
252  * Return: status of operation
253  */
254 static int wifi_pos_oem_err_rpt_ev_handler(ol_scn_t scn, uint8_t *buf,
255 					    uint32_t len)
256 {
257 	/* TBD */
258 	return 0;
259 }
260 
261 /**
262  * wifi_pos_oem_data_req() - start OEM data request to target
263  * @wma_handle: wma handle
264  * @req: start request params
265  *
266  * Return: QDF_STATUS
267  */
268 static QDF_STATUS wifi_pos_oem_data_req(struct wlan_objmgr_psoc *psoc,
269 					struct oem_data_req *req)
270 {
271 	QDF_STATUS status;
272 	void *wmi_hdl = GET_WMI_HDL_FROM_PSOC(psoc);
273 
274 	target_if_debug("Send oem data req to target");
275 
276 	if (!req || !req->data) {
277 		target_if_err("oem_data_req is null");
278 		return QDF_STATUS_E_INVAL;
279 	}
280 
281 	if (!wmi_hdl) {
282 		target_if_err("WMA closed, can't send oem data req cmd");
283 		return QDF_STATUS_E_INVAL;
284 	}
285 
286 	status = wmi_unified_start_oem_data_cmd(wmi_hdl, req->data_len,
287 						req->data);
288 
289 	if (!QDF_IS_STATUS_SUCCESS(status))
290 		target_if_err("wmi cmd send failed");
291 
292 	return status;
293 }
294 
295 void target_if_wifi_pos_register_tx_ops(struct wlan_lmac_if_tx_ops *tx_ops)
296 {
297 	struct wlan_lmac_if_wifi_pos_tx_ops *wifi_pos_tx_ops;
298 	wifi_pos_tx_ops = &tx_ops->wifi_pos_tx_ops;
299 	wifi_pos_tx_ops->data_req_tx = wifi_pos_oem_data_req;
300 }
301 
302 void target_if_wifi_pos_register_rx_ops(struct wlan_lmac_if_rx_ops *rx_ops)
303 {
304 	struct wlan_lmac_if_wifi_pos_rx_ops *wifi_pos_rx_ops;
305 	wifi_pos_rx_ops = &rx_ops->wifi_pos_rx_ops;
306 	wifi_pos_rx_ops->oem_rsp_event_rx = wifi_pos_oem_rsp_handler;
307 }
308 
309 inline struct wlan_lmac_if_wifi_pos_tx_ops *target_if_wifi_pos_get_txops(
310 						struct wlan_objmgr_psoc *psoc)
311 {
312 	if (!psoc) {
313 		target_if_err("passed psoc is NULL");
314 		return NULL;
315 	}
316 
317 	return &psoc->soc_cb.tx_ops.wifi_pos_tx_ops;
318 }
319 
320 inline struct wlan_lmac_if_wifi_pos_rx_ops *target_if_wifi_pos_get_rxops(
321 						struct wlan_objmgr_psoc *psoc)
322 {
323 	if (!psoc) {
324 		target_if_err("passed psoc is NULL");
325 		return NULL;
326 	}
327 
328 	return &psoc->soc_cb.rx_ops.wifi_pos_rx_ops;
329 }
330 
331 QDF_STATUS target_if_wifi_pos_register_events(struct wlan_objmgr_psoc *psoc)
332 {
333 	int ret;
334 
335 	if (!psoc || !GET_WMI_HDL_FROM_PSOC(psoc)) {
336 		target_if_err("psoc or psoc->tgt_if_handle is null");
337 		return QDF_STATUS_E_INVAL;
338 	}
339 
340 	ret = wmi_unified_register_event_handler(
341 			get_wmi_unified_hdl_from_psoc(psoc),
342 			wmi_oem_response_event_id,
343 			target_if_wifi_pos_oem_rsp_ev_handler,
344 			WMI_RX_WORK_CTX);
345 	if (ret) {
346 		target_if_err("register_event_handler failed: err %d", ret);
347 		return QDF_STATUS_E_INVAL;
348 	}
349 
350 	ret = wmi_unified_register_event_handler(
351 			get_wmi_unified_hdl_from_psoc(psoc),
352 			wmi_oem_cap_event_id,
353 			wifi_pos_oem_cap_ev_handler,
354 			WMI_RX_WORK_CTX);
355 	if (ret) {
356 		target_if_err("register_event_handler failed: err %d", ret);
357 		return QDF_STATUS_E_INVAL;
358 	}
359 
360 	ret = wmi_unified_register_event_handler(
361 			get_wmi_unified_hdl_from_psoc(psoc),
362 			wmi_oem_meas_report_event_id,
363 			wifi_pos_oem_meas_rpt_ev_handler,
364 			WMI_RX_WORK_CTX);
365 	if (ret) {
366 		target_if_err("register_event_handler failed: err %d", ret);
367 		return QDF_STATUS_E_INVAL;
368 	}
369 
370 	ret = wmi_unified_register_event_handler(
371 			get_wmi_unified_hdl_from_psoc(psoc),
372 			wmi_oem_report_event_id,
373 			wifi_pos_oem_err_rpt_ev_handler,
374 			WMI_RX_WORK_CTX);
375 	if (ret) {
376 		target_if_err("register_event_handler failed: err %d", ret);
377 		return QDF_STATUS_E_INVAL;
378 	}
379 
380 	return QDF_STATUS_SUCCESS;
381 }
382 
383 QDF_STATUS target_if_wifi_pos_deregister_events(struct wlan_objmgr_psoc *psoc)
384 {
385 	if (!psoc || !GET_WMI_HDL_FROM_PSOC(psoc)) {
386 		target_if_err("psoc or psoc->tgt_if_handle is null");
387 		return QDF_STATUS_E_INVAL;
388 	}
389 
390 	wmi_unified_unregister_event_handler(
391 			get_wmi_unified_hdl_from_psoc(psoc),
392 			wmi_oem_response_event_id);
393 	wmi_unified_unregister_event_handler(
394 			get_wmi_unified_hdl_from_psoc(psoc),
395 			wmi_oem_cap_event_id);
396 	wmi_unified_unregister_event_handler(
397 			get_wmi_unified_hdl_from_psoc(psoc),
398 			wmi_oem_meas_report_event_id);
399 	wmi_unified_unregister_event_handler(
400 			get_wmi_unified_hdl_from_psoc(psoc),
401 			wmi_oem_report_event_id);
402 
403 	return QDF_STATUS_SUCCESS;
404 }
405 
406 #ifdef WLAN_FEATURE_CIF_CFR
407 static QDF_STATUS target_if_wifi_pos_fill_ring(uint8_t ring_idx,
408 					struct hal_srng *srng,
409 					struct wifi_pos_psoc_priv_obj *priv)
410 {
411 	uint32_t i;
412 	void *buf, *buf_aligned;
413 
414 	for (i = 0; i < priv->dma_cfg[ring_idx].num_ptr; i++) {
415 		buf = qdf_mem_malloc(priv->dma_cap[ring_idx].min_buf_size +
416 				priv->dma_cap[ring_idx].min_buf_align - 1);
417 		if (!buf) {
418 			target_if_err("malloc failed");
419 			return QDF_STATUS_E_NOMEM;
420 		}
421 		priv->dma_buf_pool[ring_idx][i].vaddr = buf;
422 		buf_aligned = (void *)qdf_roundup((uint64_t)buf,
423 				priv->dma_cap[ring_idx].min_buf_align);
424 		priv->dma_buf_pool[ring_idx][i].offset = buf_aligned - buf;
425 		priv->dma_buf_pool[ring_idx][i].cookie = i;
426 		target_if_wifi_pos_replenish_ring(priv, ring_idx,
427 						  buf_aligned, i);
428 	}
429 
430 	return QDF_STATUS_SUCCESS;
431 }
432 
433 static QDF_STATUS target_if_wifi_pos_empty_ring(uint8_t ring_idx,
434 					struct wifi_pos_psoc_priv_obj *priv)
435 {
436 	uint32_t i;
437 
438 	for (i = 0; i < priv->dma_cfg[ring_idx].num_ptr; i++) {
439 		qdf_mem_unmap_nbytes_single(NULL,
440 			(qdf_dma_addr_t)priv->dma_buf_pool[ring_idx][i].vaddr,
441 			QDF_DMA_FROM_DEVICE,
442 			priv->dma_cap[ring_idx].min_buf_size);
443 		qdf_mem_free(priv->dma_buf_pool[ring_idx][i].vaddr);
444 	}
445 
446 	return QDF_STATUS_SUCCESS;
447 }
448 
449 static QDF_STATUS target_if_wifi_pos_init_ring(uint8_t ring_idx,
450 					struct wifi_pos_psoc_priv_obj *priv)
451 {
452 	void *srng;
453 	uint32_t num_entries;
454 	qdf_dma_addr_t paddr;
455 	uint32_t ring_alloc_size;
456 	void *hal_soc = priv->hal_soc;
457 	struct hal_srng_params ring_params = {0};
458 	uint32_t max_entries = hal_srng_max_entries(hal_soc, WIFI_POS_SRC);
459 	uint32_t entry_size = hal_srng_get_entrysize(hal_soc, WIFI_POS_SRC);
460 
461 	num_entries = priv->dma_cap[ring_idx].min_num_ptr > max_entries ?
462 			max_entries : priv->dma_cap[ring_idx].min_num_ptr;
463 	priv->dma_cfg[ring_idx].num_ptr = num_entries;
464 	priv->dma_buf_pool[ring_idx] = qdf_mem_malloc(num_entries *
465 					sizeof(struct wifi_pos_dma_buf_info));
466 	if (!priv->dma_buf_pool[ring_idx]) {
467 		target_if_err("malloc failed");
468 		return QDF_STATUS_E_NOMEM;
469 	}
470 
471 	ring_alloc_size = (num_entries * entry_size) + RING_BASE_ALIGN - 1;
472 	priv->dma_cfg[ring_idx].ring_alloc_size = ring_alloc_size;
473 	priv->dma_cfg[ring_idx].base_vaddr_unaligned =
474 		qdf_mem_alloc_consistent(NULL, NULL, ring_alloc_size, &paddr);
475 	priv->dma_cfg[ring_idx].base_paddr_unaligned = (void *)paddr;
476 	if (!priv->dma_cfg[ring_idx].base_vaddr_unaligned) {
477 		target_if_err("malloc failed");
478 		return QDF_STATUS_E_NOMEM;
479 	}
480 
481 	priv->dma_cfg[ring_idx].base_vaddr_aligned = (void *)qdf_roundup(
482 		(uint64_t)priv->dma_cfg[ring_idx].base_vaddr_unaligned,
483 		RING_BASE_ALIGN);
484 	ring_params.ring_base_vaddr =
485 		priv->dma_cfg[ring_idx].base_vaddr_aligned;
486 	priv->dma_cfg[ring_idx].base_paddr_aligned = (void *)qdf_roundup(
487 		(uint64_t)priv->dma_cfg[ring_idx].base_paddr_unaligned,
488 		RING_BASE_ALIGN);
489 	ring_params.ring_base_paddr =
490 		(qdf_dma_addr_t)priv->dma_cfg[ring_idx].base_paddr_aligned;
491 	ring_params.num_entries = num_entries;
492 	srng = hal_srng_setup(hal_soc, WIFI_POS_SRC, 0,
493 				priv->dma_cap[ring_idx].pdev_id, &ring_params);
494 	if (!srng) {
495 		target_if_err("srng setup failed");
496 		return QDF_STATUS_E_FAILURE;
497 	}
498 	priv->dma_cfg[ring_idx].srng = srng;
499 	priv->dma_cfg[ring_idx].tail_idx_addr =
500 			(void *)hal_srng_get_tp_addr(hal_soc, srng);
501 	priv->dma_cfg[ring_idx].head_idx_addr =
502 			(void *)hal_srng_get_tp_addr(hal_soc, srng);
503 
504 	return target_if_wifi_pos_fill_ring(ring_idx, srng, priv);
505 }
506 
507 static QDF_STATUS target_if_wifi_pos_deinit_ring(uint8_t ring_idx,
508 					struct wifi_pos_psoc_priv_obj *priv)
509 {
510 	target_if_wifi_pos_empty_ring(ring_idx, priv);
511 	priv->dma_buf_pool[ring_idx] = NULL;
512 	hal_srng_cleanup(priv->hal_soc, priv->dma_cfg[ring_idx].srng);
513 	qdf_mem_free_consistent(NULL, NULL,
514 		priv->dma_cfg[ring_idx].ring_alloc_size,
515 		priv->dma_cfg[ring_idx].base_vaddr_unaligned,
516 		(qdf_dma_addr_t)priv->dma_cfg[ring_idx].base_paddr_unaligned,
517 		0);
518 	qdf_mem_free(priv->dma_buf_pool[ring_idx]);
519 
520 	return QDF_STATUS_SUCCESS;
521 }
522 
523 static QDF_STATUS target_if_wifi_pos_init_srngs(
524 					struct wifi_pos_psoc_priv_obj *priv)
525 {
526 	uint8_t i;
527 	QDF_STATUS status;
528 
529 	/* allocate memory for num_rings pointers */
530 	priv->dma_cfg = qdf_mem_malloc(priv->num_rings *
531 				sizeof(struct wifi_pos_dma_rings_cap));
532 	if (!priv->dma_cfg) {
533 		target_if_err("malloc failed");
534 		return QDF_STATUS_E_NOMEM;
535 	}
536 
537 	priv->dma_buf_pool = qdf_mem_malloc(priv->num_rings *
538 				sizeof(struct wifi_pos_dma_buf_info *));
539 	if (!priv->dma_buf_pool) {
540 		target_if_err("malloc failed");
541 		return QDF_STATUS_E_NOMEM;
542 	}
543 
544 	for (i = 0; i < priv->num_rings; i++) {
545 		status = target_if_wifi_pos_init_ring(i, priv);
546 		if (QDF_IS_STATUS_ERROR(status)) {
547 			target_if_err("init for ring[%d] failed", i);
548 			return status;
549 		}
550 	}
551 
552 	return QDF_STATUS_SUCCESS;
553 }
554 
555 static QDF_STATUS target_if_wifi_pos_deinit_srngs(
556 					struct wifi_pos_psoc_priv_obj *priv)
557 {
558 	uint8_t i;
559 
560 	for (i = 0; i < priv->num_rings; i++)
561 		target_if_wifi_pos_deinit_ring(i, priv);
562 
563 	qdf_mem_free(priv->dma_buf_pool);
564 	priv->dma_buf_pool = NULL;
565 
566 	return QDF_STATUS_SUCCESS;
567 }
568 
569 static QDF_STATUS target_if_wifi_pos_cfg_fw(struct wlan_objmgr_psoc *psoc,
570 					struct wifi_pos_psoc_priv_obj *priv)
571 {
572 	uint8_t i;
573 	QDF_STATUS status;
574 	void *wmi_hdl = GET_WMI_HDL_FROM_PSOC(psoc);
575 	wmi_oem_dma_ring_cfg_req_fixed_param cfg = {0};
576 
577 	if (!wmi_hdl) {
578 		target_if_err("WMA closed, can't send oem data req cmd");
579 		return QDF_STATUS_E_INVAL;
580 	}
581 
582 	target_if_debug("Sending oem dma ring cfg to target");
583 
584 	for (i = 0; i < priv->num_rings; i++) {
585 		cfg.pdev_id = priv->dma_cfg[i].pdev_id;
586 		cfg.base_addr_lo = (uint64_t)priv->dma_cfg[i].base_paddr_aligned
587 						& 0xFFFFFFFF;
588 		cfg.base_addr_hi = (uint64_t)priv->dma_cfg[i].base_paddr_aligned
589 						& 0xFFFFFFFF00000000;
590 		cfg.head_idx_addr_lo = (uint64_t)priv->dma_cfg[i].head_idx_addr
591 						& 0xFFFFFFFF;
592 		cfg.head_idx_addr_hi = (uint64_t)priv->dma_cfg[i].head_idx_addr
593 						& 0xFFFFFFFF00000000;
594 		cfg.tail_idx_addr_lo = (uint64_t)priv->dma_cfg[i].tail_idx_addr
595 						& 0xFFFFFFFF;
596 		cfg.tail_idx_addr_hi = (uint64_t)priv->dma_cfg[i].tail_idx_addr
597 						& 0xFFFFFFFF00000000;
598 		cfg.num_ptr = priv->dma_cfg[i].num_ptr;
599 		status = wmi_unified_oem_dma_ring_cfg(wmi_hdl, &cfg);
600 		if (!QDF_IS_STATUS_SUCCESS(status)) {
601 			target_if_err("wmi cmd send failed");
602 			return status;
603 		}
604 	}
605 
606 	return status;
607 }
608 
609 QDF_STATUS target_if_wifi_pos_deinit_dma_rings(struct wlan_objmgr_psoc *psoc)
610 {
611 	struct wifi_pos_psoc_priv_obj *priv = wifi_pos_get_psoc_priv_obj(psoc);
612 
613 	target_if_wifi_pos_deinit_srngs(priv);
614 	qdf_mem_free(priv->dma_cap);
615 	priv->dma_cap = NULL;
616 
617 	return QDF_STATUS_SUCCESS;
618 }
619 
620 QDF_STATUS target_if_wifi_pos_init_cir_cfr_rings(struct wlan_objmgr_psoc *psoc,
621 					     void *hal_soc, uint8_t num_mac,
622 					     void *buf)
623 {
624 	uint8_t i;
625 	QDF_STATUS status = QDF_STATUS_SUCCESS;
626 	WMI_OEM_DMA_RING_CAPABILITIES *dma_cap = buf;
627 	struct wifi_pos_psoc_priv_obj *priv = wifi_pos_get_psoc_priv_obj(psoc);
628 
629 	if (!priv) {
630 		target_if_err("unable to get wifi_pos psoc obj");
631 		return QDF_STATUS_E_NULL_VALUE;
632 	}
633 
634 	priv->hal_soc = hal_soc;
635 	priv->num_rings = num_mac;
636 	priv->dma_cap = qdf_mem_malloc(priv->num_rings *
637 					sizeof(struct wifi_pos_dma_rings_cap));
638 	if (!priv->dma_cap) {
639 		target_if_err("unable to get wifi_pos psoc obj");
640 		return QDF_STATUS_E_NOMEM;
641 	}
642 
643 	for (i = 0; i < num_mac; i++) {
644 		priv->dma_cap[i].pdev_id = dma_cap[i].pdev_id;
645 		priv->dma_cap[i].min_num_ptr = dma_cap[i].min_num_ptr;
646 		priv->dma_cap[i].min_buf_size = dma_cap[i].min_buf_size;
647 		priv->dma_cap[i].min_buf_align = dma_cap[i].min_buf_align;
648 	}
649 
650 	/* initialize DMA rings now */
651 	status = target_if_wifi_pos_init_srngs(priv);
652 	if (QDF_IS_STATUS_ERROR(status)) {
653 		target_if_err("dma init failed: %d", status);
654 		goto dma_init_failed;
655 	}
656 
657 	/* send cfg req cmd to firmware */
658 	status = target_if_wifi_pos_cfg_fw(psoc, priv);
659 	if (QDF_IS_STATUS_ERROR(status)) {
660 		target_if_err("configure to FW failed: %d", status);
661 		goto dma_init_failed;
662 	}
663 
664 	return QDF_STATUS_SUCCESS;
665 
666 dma_init_failed:
667 	target_if_wifi_pos_deinit_dma_rings(psoc);
668 	return status;
669 }
670 
671 #endif
672