xref: /wlan-dirver/qca-wifi-host-cmn/target_if/wifi_pos/src/target_if_wifi_pos.c (revision 503663c6daafffe652fa360bde17243568cd6d2a)
1 /*
2  * Copyright (c) 2013-2019 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 		struct wmi_host_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 		struct wmi_host_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 	struct wmi_host_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;
158 	struct wlan_lmac_if_wifi_pos_rx_ops *wifi_pos_rx_ops;
159 	struct wmi_oem_response_param oem_resp_param = {0};
160 	wmi_unified_t wmi_handle;
161 
162 	psoc = target_if_get_psoc_from_scn_hdl(scn);
163 	if (!psoc) {
164 		target_if_err("psoc is null");
165 		return QDF_STATUS_NOT_INITIALIZED;
166 	}
167 
168 	wlan_objmgr_psoc_get_ref(psoc, WLAN_WIFI_POS_TGT_IF_ID);
169 
170 	wmi_handle = get_wmi_unified_hdl_from_psoc(psoc);
171 	if (!wmi_handle) {
172 		target_if_err("wmi_handle is null");
173 		wlan_objmgr_psoc_release_ref(psoc, WLAN_WIFI_POS_TGT_IF_ID);
174 		return QDF_STATUS_NOT_INITIALIZED;
175 	}
176 
177 	priv_obj = wifi_pos_get_psoc_priv_obj(psoc);
178 	if (!priv_obj) {
179 		target_if_err("priv_obj is null");
180 		wlan_objmgr_psoc_release_ref(psoc, WLAN_WIFI_POS_TGT_IF_ID);
181 		return QDF_STATUS_NOT_INITIALIZED;
182 	}
183 
184 	wifi_pos_rx_ops = target_if_wifi_pos_get_rxops(psoc);
185 	if (!wifi_pos_rx_ops || !wifi_pos_rx_ops->oem_rsp_event_rx) {
186 		wlan_objmgr_psoc_release_ref(psoc, WLAN_WIFI_POS_TGT_IF_ID);
187 		target_if_err("lmac callbacks not registered");
188 		return QDF_STATUS_NOT_INITIALIZED;
189 	}
190 
191 	ret = wmi_extract_oem_response_param(wmi_handle,
192 					     data_buf,
193 					     &oem_resp_param);
194 
195 	oem_rsp.rsp_len_1 = oem_resp_param.num_data1;
196 	oem_rsp.data_1    = oem_resp_param.data_1;
197 
198 	if (oem_resp_param.num_data2) {
199 		oem_rsp.rsp_len_2 = oem_resp_param.num_data2;
200 		oem_rsp.data_2    = oem_resp_param.data_2;
201 	}
202 
203 	indirect = &oem_resp_param.indirect_data;
204 	status = target_if_wifi_pos_get_indirect_data(priv_obj, indirect,
205 						      &oem_rsp, &cookie);
206 	if (QDF_IS_STATUS_ERROR(status)) {
207 		target_if_err("get indirect data failed status: %d", status);
208 		wlan_objmgr_psoc_release_ref(psoc, WLAN_WIFI_POS_TGT_IF_ID);
209 		return QDF_STATUS_E_INVAL;
210 	}
211 
212 	ret = wifi_pos_rx_ops->oem_rsp_event_rx(psoc, &oem_rsp);
213 	if (indirect)
214 		ring_idx = indirect->pdev_id - 1;
215 	status = target_if_wifi_pos_replenish_ring(priv_obj, ring_idx,
216 					oem_rsp.vaddr, cookie);
217 	if (QDF_IS_STATUS_ERROR(status)) {
218 		target_if_err("replenish failed status: %d", status);
219 		ret = QDF_STATUS_E_FAILURE;
220 	}
221 
222 	wlan_objmgr_psoc_release_ref(psoc, WLAN_WIFI_POS_TGT_IF_ID);
223 
224 	return ret;
225 }
226 
227 /**
228  * wifi_pos_oem_cap_ev_handler: handler registered with wmi_oem_cap_event_id
229  * @scn: scn handle
230  * @buf: event buffer
231  * @len: event buffer length
232  *
233  * Return: status of operation
234  */
235 static int wifi_pos_oem_cap_ev_handler(ol_scn_t scn, uint8_t *buf, uint32_t len)
236 {
237 	/* TBD */
238 	return 0;
239 }
240 
241 /**
242  * wifi_pos_oem_meas_rpt_ev_handler: handler registered with
243  * wmi_oem_meas_report_event_id
244  * @scn: scn handle
245  * @buf: event buffer
246  * @len: event buffer length
247  *
248  * Return: status of operation
249  */
250 static int wifi_pos_oem_meas_rpt_ev_handler(ol_scn_t scn, uint8_t *buf,
251 					    uint32_t len)
252 {
253 	/* TBD */
254 	return 0;
255 }
256 
257 /**
258  * wifi_pos_oem_err_rpt_ev_handler: handler registered with
259  * wmi_oem_err_report_event_id
260  * @scn: scn handle
261  * @buf: event buffer
262  * @len: event buffer length
263  *
264  * Return: status of operation
265  */
266 static int wifi_pos_oem_err_rpt_ev_handler(ol_scn_t scn, uint8_t *buf,
267 					    uint32_t len)
268 {
269 	/* TBD */
270 	return 0;
271 }
272 
273 /**
274  * target_if_wifi_pos_oem_data_req() - start OEM data request to target
275  * @psoc: pointer to psoc object mgr
276  * @req: start request params
277  *
278  * Return: QDF_STATUS
279  */
280 static QDF_STATUS
281 target_if_wifi_pos_oem_data_req(struct wlan_objmgr_pdev *pdev,
282 				struct oem_data_req *req)
283 {
284 	QDF_STATUS status;
285 	wmi_unified_t wmi_hdl = get_wmi_unified_hdl_from_pdev(pdev);
286 
287 	target_if_debug("Send oem data req to target");
288 
289 	if (!req || !req->data) {
290 		target_if_err("oem_data_req is null");
291 		return QDF_STATUS_E_INVAL;
292 	}
293 
294 	if (!wmi_hdl) {
295 		target_if_err("WMA closed, can't send oem data req cmd");
296 		return QDF_STATUS_E_INVAL;
297 	}
298 
299 	status = wmi_unified_start_oem_data_cmd(wmi_hdl, req->data_len,
300 						req->data);
301 
302 	if (!QDF_IS_STATUS_SUCCESS(status))
303 		target_if_err("wmi cmd send failed");
304 
305 	return status;
306 }
307 
308 void target_if_wifi_pos_register_tx_ops(struct wlan_lmac_if_tx_ops *tx_ops)
309 {
310 	struct wlan_lmac_if_wifi_pos_tx_ops *wifi_pos_tx_ops;
311 	wifi_pos_tx_ops = &tx_ops->wifi_pos_tx_ops;
312 	wifi_pos_tx_ops->data_req_tx = target_if_wifi_pos_oem_data_req;
313 	wifi_pos_tx_ops->wifi_pos_register_events =
314 		target_if_wifi_pos_register_events;
315 	wifi_pos_tx_ops->wifi_pos_deregister_events =
316 		target_if_wifi_pos_deregister_events;
317 }
318 
319 inline struct wlan_lmac_if_wifi_pos_rx_ops *target_if_wifi_pos_get_rxops(
320 						struct wlan_objmgr_psoc *psoc)
321 {
322 	if (!psoc) {
323 		target_if_err("passed psoc is NULL");
324 		return NULL;
325 	}
326 
327 	return &psoc->soc_cb.rx_ops.wifi_pos_rx_ops;
328 }
329 
330 QDF_STATUS target_if_wifi_pos_register_events(struct wlan_objmgr_psoc *psoc)
331 {
332 	int ret;
333 
334 	if (!psoc || !GET_WMI_HDL_FROM_PSOC(psoc)) {
335 		target_if_err("psoc or psoc->tgt_if_handle is null");
336 		return QDF_STATUS_E_INVAL;
337 	}
338 
339 	/* wmi_oem_response_event_id is not defined for legacy targets.
340 	 * So do not check for error for this event.
341 	 */
342 	wmi_unified_register_event_handler(
343 			get_wmi_unified_hdl_from_psoc(psoc),
344 			wmi_oem_response_event_id,
345 			target_if_wifi_pos_oem_rsp_ev_handler,
346 			WMI_RX_WORK_CTX);
347 
348 	ret = wmi_unified_register_event_handler(
349 			get_wmi_unified_hdl_from_psoc(psoc),
350 			wmi_oem_cap_event_id,
351 			wifi_pos_oem_cap_ev_handler,
352 			WMI_RX_WORK_CTX);
353 	if (ret) {
354 		target_if_err("register_event_handler failed: err %d", ret);
355 		return QDF_STATUS_E_INVAL;
356 	}
357 
358 	ret = wmi_unified_register_event_handler(
359 			get_wmi_unified_hdl_from_psoc(psoc),
360 			wmi_oem_meas_report_event_id,
361 			wifi_pos_oem_meas_rpt_ev_handler,
362 			WMI_RX_WORK_CTX);
363 	if (ret) {
364 		target_if_err("register_event_handler failed: err %d", ret);
365 		return QDF_STATUS_E_INVAL;
366 	}
367 
368 	ret = wmi_unified_register_event_handler(
369 			get_wmi_unified_hdl_from_psoc(psoc),
370 			wmi_oem_report_event_id,
371 			wifi_pos_oem_err_rpt_ev_handler,
372 			WMI_RX_WORK_CTX);
373 	if (ret) {
374 		target_if_err("register_event_handler failed: err %d", ret);
375 		return QDF_STATUS_E_INVAL;
376 	}
377 
378 	return QDF_STATUS_SUCCESS;
379 }
380 
381 QDF_STATUS target_if_wifi_pos_deregister_events(struct wlan_objmgr_psoc *psoc)
382 {
383 	if (!psoc || !GET_WMI_HDL_FROM_PSOC(psoc)) {
384 		target_if_err("psoc or psoc->tgt_if_handle is null");
385 		return QDF_STATUS_E_INVAL;
386 	}
387 
388 	wmi_unified_unregister_event_handler(
389 			get_wmi_unified_hdl_from_psoc(psoc),
390 			wmi_oem_response_event_id);
391 	wmi_unified_unregister_event_handler(
392 			get_wmi_unified_hdl_from_psoc(psoc),
393 			wmi_oem_cap_event_id);
394 	wmi_unified_unregister_event_handler(
395 			get_wmi_unified_hdl_from_psoc(psoc),
396 			wmi_oem_meas_report_event_id);
397 	wmi_unified_unregister_event_handler(
398 			get_wmi_unified_hdl_from_psoc(psoc),
399 			wmi_oem_report_event_id);
400 
401 	return QDF_STATUS_SUCCESS;
402 }
403 
404 #ifdef WLAN_FEATURE_CIF_CFR
405 static QDF_STATUS target_if_wifi_pos_fill_ring(uint8_t ring_idx,
406 					struct hal_srng *srng,
407 					struct wifi_pos_psoc_priv_obj *priv)
408 {
409 	uint32_t i;
410 	void *buf, *buf_aligned;
411 
412 	for (i = 0; i < priv->dma_cfg[ring_idx].num_ptr; i++) {
413 		buf = qdf_mem_malloc(priv->dma_cap[ring_idx].min_buf_size +
414 				priv->dma_cap[ring_idx].min_buf_align - 1);
415 		if (!buf)
416 			return QDF_STATUS_E_NOMEM;
417 
418 		priv->dma_buf_pool[ring_idx][i].vaddr = buf;
419 		buf_aligned = (void *)qdf_roundup((uint64_t)buf,
420 				priv->dma_cap[ring_idx].min_buf_align);
421 		priv->dma_buf_pool[ring_idx][i].offset = buf_aligned - buf;
422 		priv->dma_buf_pool[ring_idx][i].cookie = i;
423 		target_if_wifi_pos_replenish_ring(priv, ring_idx,
424 						  buf_aligned, i);
425 	}
426 
427 	return QDF_STATUS_SUCCESS;
428 }
429 
430 static QDF_STATUS target_if_wifi_pos_empty_ring(uint8_t ring_idx,
431 					struct wifi_pos_psoc_priv_obj *priv)
432 {
433 	uint32_t i;
434 
435 	for (i = 0; i < priv->dma_cfg[ring_idx].num_ptr; i++) {
436 		qdf_mem_unmap_nbytes_single(NULL,
437 			(qdf_dma_addr_t)priv->dma_buf_pool[ring_idx][i].vaddr,
438 			QDF_DMA_FROM_DEVICE,
439 			priv->dma_cap[ring_idx].min_buf_size);
440 		qdf_mem_free(priv->dma_buf_pool[ring_idx][i].vaddr);
441 	}
442 
443 	return QDF_STATUS_SUCCESS;
444 }
445 
446 static QDF_STATUS target_if_wifi_pos_init_ring(uint8_t ring_idx,
447 					struct wifi_pos_psoc_priv_obj *priv)
448 {
449 	void *srng;
450 	uint32_t num_entries;
451 	qdf_dma_addr_t paddr;
452 	uint32_t ring_alloc_size;
453 	void *hal_soc = priv->hal_soc;
454 	struct hal_srng_params ring_params = {0};
455 	uint32_t max_entries = hal_srng_max_entries(hal_soc, WIFI_POS_SRC);
456 	uint32_t entry_size = hal_srng_get_entrysize(hal_soc, WIFI_POS_SRC);
457 
458 	num_entries = priv->dma_cap[ring_idx].min_num_ptr > max_entries ?
459 			max_entries : priv->dma_cap[ring_idx].min_num_ptr;
460 	priv->dma_cfg[ring_idx].num_ptr = num_entries;
461 	priv->dma_buf_pool[ring_idx] = qdf_mem_malloc(num_entries *
462 					sizeof(struct wifi_pos_dma_buf_info));
463 	if (!priv->dma_buf_pool[ring_idx])
464 		return QDF_STATUS_E_NOMEM;
465 
466 	ring_alloc_size = (num_entries * entry_size) + RING_BASE_ALIGN - 1;
467 	priv->dma_cfg[ring_idx].ring_alloc_size = ring_alloc_size;
468 	priv->dma_cfg[ring_idx].base_vaddr_unaligned =
469 		qdf_mem_alloc_consistent(NULL, NULL, ring_alloc_size, &paddr);
470 	priv->dma_cfg[ring_idx].base_paddr_unaligned = (void *)paddr;
471 	if (!priv->dma_cfg[ring_idx].base_vaddr_unaligned) {
472 		target_if_err("malloc failed");
473 		return QDF_STATUS_E_NOMEM;
474 	}
475 
476 	priv->dma_cfg[ring_idx].base_vaddr_aligned = (void *)qdf_roundup(
477 		(uint64_t)priv->dma_cfg[ring_idx].base_vaddr_unaligned,
478 		RING_BASE_ALIGN);
479 	ring_params.ring_base_vaddr =
480 		priv->dma_cfg[ring_idx].base_vaddr_aligned;
481 	priv->dma_cfg[ring_idx].base_paddr_aligned = (void *)qdf_roundup(
482 		(uint64_t)priv->dma_cfg[ring_idx].base_paddr_unaligned,
483 		RING_BASE_ALIGN);
484 	ring_params.ring_base_paddr =
485 		(qdf_dma_addr_t)priv->dma_cfg[ring_idx].base_paddr_aligned;
486 	ring_params.num_entries = num_entries;
487 	srng = hal_srng_setup(hal_soc, WIFI_POS_SRC, 0,
488 				priv->dma_cap[ring_idx].pdev_id, &ring_params);
489 	if (!srng) {
490 		target_if_err("srng setup failed");
491 		return QDF_STATUS_E_FAILURE;
492 	}
493 	priv->dma_cfg[ring_idx].srng = srng;
494 	priv->dma_cfg[ring_idx].tail_idx_addr =
495 			(void *)hal_srng_get_tp_addr(hal_soc, srng);
496 	priv->dma_cfg[ring_idx].head_idx_addr =
497 			(void *)hal_srng_get_tp_addr(hal_soc, srng);
498 
499 	return target_if_wifi_pos_fill_ring(ring_idx, srng, priv);
500 }
501 
502 static QDF_STATUS target_if_wifi_pos_deinit_ring(uint8_t ring_idx,
503 					struct wifi_pos_psoc_priv_obj *priv)
504 {
505 	target_if_wifi_pos_empty_ring(ring_idx, priv);
506 	priv->dma_buf_pool[ring_idx] = NULL;
507 	hal_srng_cleanup(priv->hal_soc, priv->dma_cfg[ring_idx].srng);
508 	qdf_mem_free_consistent(NULL, NULL,
509 		priv->dma_cfg[ring_idx].ring_alloc_size,
510 		priv->dma_cfg[ring_idx].base_vaddr_unaligned,
511 		(qdf_dma_addr_t)priv->dma_cfg[ring_idx].base_paddr_unaligned,
512 		0);
513 	qdf_mem_free(priv->dma_buf_pool[ring_idx]);
514 
515 	return QDF_STATUS_SUCCESS;
516 }
517 
518 static QDF_STATUS target_if_wifi_pos_init_srngs(
519 					struct wifi_pos_psoc_priv_obj *priv)
520 {
521 	uint8_t i;
522 	QDF_STATUS status;
523 
524 	/* allocate memory for num_rings pointers */
525 	priv->dma_cfg = qdf_mem_malloc(priv->num_rings *
526 				sizeof(struct wifi_pos_dma_rings_cap));
527 	if (!priv->dma_cfg)
528 		return QDF_STATUS_E_NOMEM;
529 
530 	priv->dma_buf_pool = qdf_mem_malloc(priv->num_rings *
531 				sizeof(struct wifi_pos_dma_buf_info *));
532 	if (!priv->dma_buf_pool)
533 		return QDF_STATUS_E_NOMEM;
534 
535 	for (i = 0; i < priv->num_rings; i++) {
536 		status = target_if_wifi_pos_init_ring(i, priv);
537 		if (QDF_IS_STATUS_ERROR(status)) {
538 			target_if_err("init for ring[%d] failed", i);
539 			return status;
540 		}
541 	}
542 
543 	return QDF_STATUS_SUCCESS;
544 }
545 
546 static QDF_STATUS target_if_wifi_pos_deinit_srngs(
547 					struct wifi_pos_psoc_priv_obj *priv)
548 {
549 	uint8_t i;
550 
551 	for (i = 0; i < priv->num_rings; i++)
552 		target_if_wifi_pos_deinit_ring(i, priv);
553 
554 	qdf_mem_free(priv->dma_buf_pool);
555 	priv->dma_buf_pool = NULL;
556 
557 	return QDF_STATUS_SUCCESS;
558 }
559 
560 static QDF_STATUS target_if_wifi_pos_cfg_fw(struct wlan_objmgr_psoc *psoc,
561 					struct wifi_pos_psoc_priv_obj *priv)
562 {
563 	uint8_t i;
564 	QDF_STATUS status;
565 	wmi_unified_t wmi_hdl = GET_WMI_HDL_FROM_PSOC(psoc);
566 	wmi_oem_dma_ring_cfg_req_fixed_param cfg = {0};
567 
568 	if (!wmi_hdl) {
569 		target_if_err("WMA closed, can't send oem data req cmd");
570 		return QDF_STATUS_E_INVAL;
571 	}
572 
573 	target_if_debug("Sending oem dma ring cfg to target");
574 
575 	for (i = 0; i < priv->num_rings; i++) {
576 		cfg.pdev_id = priv->dma_cfg[i].pdev_id;
577 		cfg.base_addr_lo = (uint64_t)priv->dma_cfg[i].base_paddr_aligned
578 						& 0xFFFFFFFF;
579 		cfg.base_addr_hi = (uint64_t)priv->dma_cfg[i].base_paddr_aligned
580 						& 0xFFFFFFFF00000000;
581 		cfg.head_idx_addr_lo = (uint64_t)priv->dma_cfg[i].head_idx_addr
582 						& 0xFFFFFFFF;
583 		cfg.head_idx_addr_hi = (uint64_t)priv->dma_cfg[i].head_idx_addr
584 						& 0xFFFFFFFF00000000;
585 		cfg.tail_idx_addr_lo = (uint64_t)priv->dma_cfg[i].tail_idx_addr
586 						& 0xFFFFFFFF;
587 		cfg.tail_idx_addr_hi = (uint64_t)priv->dma_cfg[i].tail_idx_addr
588 						& 0xFFFFFFFF00000000;
589 		cfg.num_ptr = priv->dma_cfg[i].num_ptr;
590 		status = wmi_unified_oem_dma_ring_cfg(wmi_hdl, &cfg);
591 		if (!QDF_IS_STATUS_SUCCESS(status)) {
592 			target_if_err("wmi cmd send failed");
593 			return status;
594 		}
595 	}
596 
597 	return status;
598 }
599 
600 QDF_STATUS target_if_wifi_pos_deinit_dma_rings(struct wlan_objmgr_psoc *psoc)
601 {
602 	struct wifi_pos_psoc_priv_obj *priv = wifi_pos_get_psoc_priv_obj(psoc);
603 
604 	target_if_wifi_pos_deinit_srngs(priv);
605 	qdf_mem_free(priv->dma_cap);
606 	priv->dma_cap = NULL;
607 
608 	return QDF_STATUS_SUCCESS;
609 }
610 
611 QDF_STATUS target_if_wifi_pos_init_cir_cfr_rings(struct wlan_objmgr_psoc *psoc,
612 					     void *hal_soc, uint8_t num_mac,
613 					     void *buf)
614 {
615 	uint8_t i;
616 	QDF_STATUS status = QDF_STATUS_SUCCESS;
617 	WMI_OEM_DMA_RING_CAPABILITIES *dma_cap = buf;
618 	struct wifi_pos_psoc_priv_obj *priv = wifi_pos_get_psoc_priv_obj(psoc);
619 
620 	if (!priv) {
621 		target_if_err("unable to get wifi_pos psoc obj");
622 		return QDF_STATUS_E_NULL_VALUE;
623 	}
624 
625 	priv->hal_soc = hal_soc;
626 	priv->num_rings = num_mac;
627 	priv->dma_cap = qdf_mem_malloc(priv->num_rings *
628 					sizeof(struct wifi_pos_dma_rings_cap));
629 	if (!priv->dma_cap)
630 		return QDF_STATUS_E_NOMEM;
631 
632 	for (i = 0; i < num_mac; i++) {
633 		priv->dma_cap[i].pdev_id = dma_cap[i].pdev_id;
634 		priv->dma_cap[i].min_num_ptr = dma_cap[i].min_num_ptr;
635 		priv->dma_cap[i].min_buf_size = dma_cap[i].min_buf_size;
636 		priv->dma_cap[i].min_buf_align = dma_cap[i].min_buf_align;
637 	}
638 
639 	/* initialize DMA rings now */
640 	status = target_if_wifi_pos_init_srngs(priv);
641 	if (QDF_IS_STATUS_ERROR(status)) {
642 		target_if_err("dma init failed: %d", status);
643 		goto dma_init_failed;
644 	}
645 
646 	/* send cfg req cmd to firmware */
647 	status = target_if_wifi_pos_cfg_fw(psoc, priv);
648 	if (QDF_IS_STATUS_ERROR(status)) {
649 		target_if_err("configure to FW failed: %d", status);
650 		goto dma_init_failed;
651 	}
652 
653 	return QDF_STATUS_SUCCESS;
654 
655 dma_init_failed:
656 	target_if_wifi_pos_deinit_dma_rings(psoc);
657 	return status;
658 }
659 
660 #endif
661