xref: /wlan-dirver/qca-wifi-host-cmn/target_if/wifi_pos/src/target_if_wifi_pos.c (revision 2f4b444fb7e689b83a4ab0e7b3b38f0bf4def8e0)
1 /*
2  * Copyright (c) 2013-2021 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 "wifi_pos_utils_pub.h"
26 
27 #include "wmi_unified_api.h"
28 #include "wlan_lmac_if_def.h"
29 #include "target_if_wifi_pos.h"
30 #include "../../../../umac/wifi_pos/src/wifi_pos_main_i.h"
31 #include "target_if.h"
32 #ifdef WLAN_FEATURE_CIF_CFR
33 #include "hal_api.h"
34 
35 #define RING_BASE_ALIGN 8
36 
37 static void *target_if_wifi_pos_vaddr_lookup(
38 				struct wifi_pos_psoc_priv_obj *priv,
39 				void *paddr, uint8_t ring_num, uint32_t cookie)
40 {
41 	if (priv->dma_buf_pool[ring_num][cookie].paddr == paddr) {
42 		return priv->dma_buf_pool[ring_num][cookie].vaddr +
43 				priv->dma_buf_pool[ring_num][cookie].offset;
44 	} else {
45 		target_if_err("incorrect paddr found on cookie slot");
46 		return NULL;
47 	}
48 }
49 
50 static QDF_STATUS target_if_wifi_pos_replenish_ring(
51 			struct wifi_pos_psoc_priv_obj *priv, uint8_t ring_idx,
52 			void *alinged_vaddr, uint32_t cookie)
53 {
54 	uint64_t *ring_entry;
55 	uint32_t dw_lo, dw_hi = 0, map_status;
56 	void *hal_soc = priv->hal_soc;
57 	void *srng = priv->dma_cfg[ring_idx].srng;
58 	void *paddr;
59 
60 	if (!alinged_vaddr) {
61 		target_if_debug("NULL alinged_vaddr provided");
62 		return QDF_STATUS_SUCCESS;
63 	}
64 
65 	map_status = qdf_mem_map_nbytes_single(NULL, alinged_vaddr,
66 			QDF_DMA_FROM_DEVICE,
67 			priv->dma_cap[ring_idx].min_buf_size,
68 			(qdf_dma_addr_t *)&paddr);
69 	if (map_status) {
70 		target_if_err("mem map failed status: %d", map_status);
71 		return QDF_STATUS_E_FAILURE;
72 	}
73 	QDF_ASSERT(!((uint64_t)paddr % priv->dma_cap[ring_idx].min_buf_align));
74 	priv->dma_buf_pool[ring_idx][cookie].paddr = paddr;
75 
76 	hal_srng_access_start(hal_soc, srng);
77 	ring_entry = hal_srng_src_get_next(hal_soc, srng);
78 	dw_lo = (uint64_t)paddr & 0xFFFFFFFF;
79 	WMI_OEM_DMA_DATA_ADDR_HI_SET(dw_hi, (uint64_t)paddr >> 32);
80 	WMI_OEM_DMA_DATA_ADDR_HI_HOST_DATA_SET(dw_hi, cookie);
81 	*ring_entry = (uint64_t)dw_hi << 32 | dw_lo;
82 	hal_srng_access_end(hal_soc, srng);
83 
84 	return QDF_STATUS_SUCCESS;
85 }
86 
87 static QDF_STATUS target_if_wifi_pos_get_indirect_data(
88 		struct wifi_pos_psoc_priv_obj *priv_obj,
89 		struct wmi_host_oem_indirect_data *indirect,
90 		struct oem_data_rsp *rsp, uint32_t *cookie)
91 {
92 	void *paddr = NULL;
93 	uint32_t addr_hi;
94 	uint8_t ring_idx = 0, num_rings;
95 	uint32_t allocated_len;
96 
97 	if (!indirect) {
98 		target_if_debug("no indirect data. regular event received");
99 		return QDF_STATUS_SUCCESS;
100 	}
101 
102 	ring_idx = indirect->pdev_id - 1;
103 	num_rings = priv_obj->num_rings;
104 	if (ring_idx >= num_rings) {
105 		target_if_err("incorrect pdev_id: %d", indirect->pdev_id);
106 		return QDF_STATUS_E_INVAL;
107 	}
108 
109 	allocated_len = priv_obj->dma_cap[ring_idx].min_buf_size +
110 				(priv_obj->dma_cap[ring_idx].min_buf_align - 1);
111 	if (indirect->len > allocated_len ||
112 	    indirect->len > OEM_DATA_DMA_BUFF_SIZE) {
113 		target_if_err("Invalid indirect len: %d, allocated_len:%d",
114 			      indirect->len, allocated_len);
115 		return QDF_STATUS_E_INVAL;
116 	}
117 
118 	addr_hi = (uint64_t)WMI_OEM_DMA_DATA_ADDR_HI_GET(
119 						indirect->addr_hi);
120 	paddr = (void *)((uint64_t)addr_hi << 32 | indirect->addr_lo);
121 	*cookie = WMI_OEM_DMA_DATA_ADDR_HI_HOST_DATA_GET(
122 						indirect->addr_hi);
123 	rsp->vaddr = target_if_wifi_pos_vaddr_lookup(priv_obj,
124 					paddr, ring_idx, *cookie);
125 	rsp->dma_len = indirect->len;
126 	qdf_mem_unmap_nbytes_single(NULL, (qdf_dma_addr_t)paddr,
127 			QDF_DMA_FROM_DEVICE,
128 			priv_obj->dma_cap[ring_idx].min_buf_size);
129 
130 	return QDF_STATUS_SUCCESS;
131 }
132 
133 #else
134 static QDF_STATUS target_if_wifi_pos_replenish_ring(
135 			struct wifi_pos_psoc_priv_obj *priv, uint8_t ring_idx,
136 			void *vaddr, uint32_t cookie)
137 {
138 	return QDF_STATUS_SUCCESS;
139 }
140 
141 static QDF_STATUS target_if_wifi_pos_get_indirect_data(
142 		struct wifi_pos_psoc_priv_obj *priv_obj,
143 		struct wmi_host_oem_indirect_data *indirect,
144 		struct oem_data_rsp *rsp, uint32_t *cookie)
145 {
146 	return QDF_STATUS_SUCCESS;
147 }
148 #endif
149 
150 /**
151  * target_if_wifi_pos_oem_rsp_ev_handler: handler registered with
152  * WMI_OEM_RESPONSE_EVENTID
153  * @scn: scn handle
154  * @data_buf: event buffer
155  * @data_len: event buffer length
156  *
157  * Return: status of operation
158  */
159 static int target_if_wifi_pos_oem_rsp_ev_handler(ol_scn_t scn,
160 					uint8_t *data_buf,
161 					uint32_t data_len)
162 {
163 	int ret;
164 	uint8_t ring_idx = 0;
165 	QDF_STATUS status;
166 	uint32_t cookie = 0;
167 	struct wmi_host_oem_indirect_data *indirect;
168 	struct oem_data_rsp oem_rsp = {0};
169 	struct wifi_pos_psoc_priv_obj *priv_obj;
170 	struct wlan_objmgr_psoc *psoc;
171 	struct wlan_lmac_if_wifi_pos_rx_ops *wifi_pos_rx_ops;
172 	struct wmi_oem_response_param oem_resp_param = {0};
173 	wmi_unified_t wmi_handle;
174 
175 	psoc = target_if_get_psoc_from_scn_hdl(scn);
176 	if (!psoc) {
177 		target_if_err("psoc is null");
178 		return QDF_STATUS_NOT_INITIALIZED;
179 	}
180 
181 	wlan_objmgr_psoc_get_ref(psoc, WLAN_WIFI_POS_TGT_IF_ID);
182 
183 	wmi_handle = get_wmi_unified_hdl_from_psoc(psoc);
184 	if (!wmi_handle) {
185 		target_if_err("wmi_handle is null");
186 		wlan_objmgr_psoc_release_ref(psoc, WLAN_WIFI_POS_TGT_IF_ID);
187 		return QDF_STATUS_NOT_INITIALIZED;
188 	}
189 
190 	priv_obj = wifi_pos_get_psoc_priv_obj(wifi_pos_get_psoc());
191 	if (!priv_obj) {
192 		target_if_err("priv_obj is null");
193 		wlan_objmgr_psoc_release_ref(psoc, WLAN_WIFI_POS_TGT_IF_ID);
194 		return QDF_STATUS_NOT_INITIALIZED;
195 	}
196 
197 	wifi_pos_rx_ops = target_if_wifi_pos_get_rxops(psoc);
198 	if (!wifi_pos_rx_ops || !wifi_pos_rx_ops->oem_rsp_event_rx) {
199 		wlan_objmgr_psoc_release_ref(psoc, WLAN_WIFI_POS_TGT_IF_ID);
200 		target_if_err("lmac callbacks not registered");
201 		return QDF_STATUS_NOT_INITIALIZED;
202 	}
203 
204 	ret = wmi_extract_oem_response_param(wmi_handle,
205 					     data_buf,
206 					     &oem_resp_param);
207 
208 	oem_rsp.rsp_len_1 = oem_resp_param.num_data1;
209 	oem_rsp.data_1    = oem_resp_param.data_1;
210 
211 	if (oem_resp_param.num_data2) {
212 		oem_rsp.rsp_len_2 = oem_resp_param.num_data2;
213 		oem_rsp.data_2    = oem_resp_param.data_2;
214 	}
215 
216 	indirect = &oem_resp_param.indirect_data;
217 	status = target_if_wifi_pos_get_indirect_data(priv_obj, indirect,
218 						      &oem_rsp, &cookie);
219 	if (QDF_IS_STATUS_ERROR(status)) {
220 		target_if_err("get indirect data failed status: %d", status);
221 		wlan_objmgr_psoc_release_ref(psoc, WLAN_WIFI_POS_TGT_IF_ID);
222 		return QDF_STATUS_E_INVAL;
223 	}
224 
225 	ret = wifi_pos_rx_ops->oem_rsp_event_rx(psoc, &oem_rsp);
226 	if (indirect)
227 		ring_idx = indirect->pdev_id - 1;
228 	status = target_if_wifi_pos_replenish_ring(priv_obj, ring_idx,
229 					oem_rsp.vaddr, cookie);
230 	if (QDF_IS_STATUS_ERROR(status)) {
231 		target_if_err("replenish failed status: %d", status);
232 		ret = QDF_STATUS_E_FAILURE;
233 	}
234 
235 	wlan_objmgr_psoc_release_ref(psoc, WLAN_WIFI_POS_TGT_IF_ID);
236 
237 	return ret;
238 }
239 
240 /**
241  * wifi_pos_oem_cap_ev_handler: handler registered with wmi_oem_cap_event_id
242  * @scn: scn handle
243  * @buf: event buffer
244  * @len: event buffer length
245  *
246  * Return: status of operation
247  */
248 static int wifi_pos_oem_cap_ev_handler(ol_scn_t scn, uint8_t *buf, uint32_t len)
249 {
250 	/* TBD */
251 	return 0;
252 }
253 
254 /**
255  * wifi_pos_oem_meas_rpt_ev_handler: handler registered with
256  * wmi_oem_meas_report_event_id
257  * @scn: scn handle
258  * @buf: event buffer
259  * @len: event buffer length
260  *
261  * Return: status of operation
262  */
263 static int wifi_pos_oem_meas_rpt_ev_handler(ol_scn_t scn, uint8_t *buf,
264 					    uint32_t len)
265 {
266 	/* TBD */
267 	return 0;
268 }
269 
270 /**
271  * wifi_pos_oem_err_rpt_ev_handler: handler registered with
272  * wmi_oem_err_report_event_id
273  * @scn: scn handle
274  * @buf: event buffer
275  * @len: event buffer length
276  *
277  * Return: status of operation
278  */
279 static int wifi_pos_oem_err_rpt_ev_handler(ol_scn_t scn, uint8_t *buf,
280 					    uint32_t len)
281 {
282 	/* TBD */
283 	return 0;
284 }
285 
286 /**
287  * target_if_wifi_pos_oem_data_req() - start OEM data request to target
288  * @psoc: pointer to psoc object mgr
289  * @req: start request params
290  *
291  * Return: QDF_STATUS
292  */
293 static QDF_STATUS
294 target_if_wifi_pos_oem_data_req(struct wlan_objmgr_pdev *pdev,
295 				struct oem_data_req *req)
296 {
297 	QDF_STATUS status;
298 	wmi_unified_t wmi_hdl = get_wmi_unified_hdl_from_pdev(pdev);
299 
300 	target_if_debug("Send oem data req to target");
301 
302 	if (!req || !req->data) {
303 		target_if_err("oem_data_req is null");
304 		return QDF_STATUS_E_INVAL;
305 	}
306 
307 	if (!wmi_hdl) {
308 		target_if_err("WMA closed, can't send oem data req cmd");
309 		return QDF_STATUS_E_INVAL;
310 	}
311 
312 	status = wmi_unified_start_oem_data_cmd(wmi_hdl, req->data_len,
313 						req->data);
314 
315 	if (!QDF_IS_STATUS_SUCCESS(status))
316 		target_if_err("wmi cmd send failed");
317 
318 	return status;
319 }
320 
321 void target_if_wifi_pos_register_tx_ops(struct wlan_lmac_if_tx_ops *tx_ops)
322 {
323 	struct wlan_lmac_if_wifi_pos_tx_ops *wifi_pos_tx_ops;
324 	wifi_pos_tx_ops = &tx_ops->wifi_pos_tx_ops;
325 	wifi_pos_tx_ops->data_req_tx = target_if_wifi_pos_oem_data_req;
326 	wifi_pos_tx_ops->wifi_pos_register_events =
327 		target_if_wifi_pos_register_events;
328 	wifi_pos_tx_ops->wifi_pos_deregister_events =
329 		target_if_wifi_pos_deregister_events;
330 	wifi_pos_tx_ops->wifi_pos_convert_pdev_id_host_to_target =
331 		target_if_wifi_pos_convert_pdev_id_host_to_target;
332 	wifi_pos_tx_ops->wifi_pos_convert_pdev_id_target_to_host =
333 		target_if_wifi_pos_convert_pdev_id_target_to_host;
334 	wifi_pos_tx_ops->wifi_pos_get_vht_ch_width =
335 		target_if_wifi_pos_get_vht_ch_width;
336 
337 }
338 
339 inline struct wlan_lmac_if_wifi_pos_rx_ops *target_if_wifi_pos_get_rxops(
340 						struct wlan_objmgr_psoc *psoc)
341 {
342 	struct wlan_lmac_if_rx_ops *rx_ops;
343 
344 	if (!psoc) {
345 		target_if_err("passed psoc is NULL");
346 		return NULL;
347 	}
348 
349 	rx_ops = wlan_psoc_get_lmac_if_rxops(psoc);
350 	if (!rx_ops) {
351 		target_if_err("rx_ops is NULL");
352 		return NULL;
353 	}
354 
355 	return &rx_ops->wifi_pos_rx_ops;
356 }
357 
358 QDF_STATUS target_if_wifi_pos_register_events(struct wlan_objmgr_psoc *psoc)
359 {
360 	QDF_STATUS ret;
361 
362 	if (!psoc || !GET_WMI_HDL_FROM_PSOC(psoc)) {
363 		target_if_err("psoc or psoc->tgt_if_handle is null");
364 		return QDF_STATUS_E_INVAL;
365 	}
366 
367 	/* wmi_oem_response_event_id is not defined for legacy targets.
368 	 * So do not check for error for this event.
369 	 */
370 	wmi_unified_register_event_handler(
371 			get_wmi_unified_hdl_from_psoc(psoc),
372 			wmi_oem_response_event_id,
373 			target_if_wifi_pos_oem_rsp_ev_handler,
374 			WMI_RX_WORK_CTX);
375 
376 	ret = wmi_unified_register_event_handler(
377 			get_wmi_unified_hdl_from_psoc(psoc),
378 			wmi_oem_cap_event_id,
379 			wifi_pos_oem_cap_ev_handler,
380 			WMI_RX_WORK_CTX);
381 	if (QDF_IS_STATUS_ERROR(ret)) {
382 		target_if_err("register_event_handler failed: err %d", ret);
383 		return QDF_STATUS_E_INVAL;
384 	}
385 
386 	ret = wmi_unified_register_event_handler(
387 			get_wmi_unified_hdl_from_psoc(psoc),
388 			wmi_oem_meas_report_event_id,
389 			wifi_pos_oem_meas_rpt_ev_handler,
390 			WMI_RX_WORK_CTX);
391 	if (QDF_IS_STATUS_ERROR(ret)) {
392 		target_if_err("register_event_handler failed: err %d", ret);
393 		return QDF_STATUS_E_INVAL;
394 	}
395 
396 	ret = wmi_unified_register_event_handler(
397 			get_wmi_unified_hdl_from_psoc(psoc),
398 			wmi_oem_report_event_id,
399 			wifi_pos_oem_err_rpt_ev_handler,
400 			WMI_RX_WORK_CTX);
401 	if (QDF_IS_STATUS_ERROR(ret)) {
402 		target_if_err("register_event_handler failed: err %d", ret);
403 		return QDF_STATUS_E_INVAL;
404 	}
405 
406 	return QDF_STATUS_SUCCESS;
407 }
408 
409 QDF_STATUS target_if_wifi_pos_deregister_events(struct wlan_objmgr_psoc *psoc)
410 {
411 	if (!psoc || !GET_WMI_HDL_FROM_PSOC(psoc)) {
412 		target_if_err("psoc or psoc->tgt_if_handle is null");
413 		return QDF_STATUS_E_INVAL;
414 	}
415 
416 	wmi_unified_unregister_event_handler(
417 			get_wmi_unified_hdl_from_psoc(psoc),
418 			wmi_oem_response_event_id);
419 	wmi_unified_unregister_event_handler(
420 			get_wmi_unified_hdl_from_psoc(psoc),
421 			wmi_oem_cap_event_id);
422 	wmi_unified_unregister_event_handler(
423 			get_wmi_unified_hdl_from_psoc(psoc),
424 			wmi_oem_meas_report_event_id);
425 	wmi_unified_unregister_event_handler(
426 			get_wmi_unified_hdl_from_psoc(psoc),
427 			wmi_oem_report_event_id);
428 
429 	return QDF_STATUS_SUCCESS;
430 }
431 
432 QDF_STATUS target_if_wifi_pos_get_vht_ch_width(struct wlan_objmgr_psoc *psoc,
433 					       enum phy_ch_width *ch_width)
434 {
435 	struct target_psoc_info *tgt_hdl;
436 	int vht_cap_info;
437 
438 	*ch_width = CH_WIDTH_INVALID;
439 
440 	if (!psoc)
441 		return QDF_STATUS_E_INVAL;
442 
443 	tgt_hdl = wlan_psoc_get_tgt_if_handle(psoc);
444 	if (!tgt_hdl)
445 		return QDF_STATUS_E_INVAL;
446 
447 	*ch_width = CH_WIDTH_80MHZ;
448 
449 	vht_cap_info = target_if_get_vht_cap_info(tgt_hdl);
450 
451 	if (vht_cap_info & WLAN_VHTCAP_SUP_CHAN_WIDTH_80_160)
452 		*ch_width = CH_WIDTH_80P80MHZ;
453 	else if (vht_cap_info & WLAN_VHTCAP_SUP_CHAN_WIDTH_160)
454 		*ch_width = CH_WIDTH_160MHZ;
455 
456 	return QDF_STATUS_SUCCESS;
457 }
458 
459 #ifndef CNSS_GENL
460 QDF_STATUS target_if_wifi_pos_convert_pdev_id_host_to_target(
461 		struct wlan_objmgr_psoc *psoc, uint32_t host_pdev_id,
462 		uint32_t *target_pdev_id)
463 {
464 	wmi_unified_t wmi_hdl = GET_WMI_HDL_FROM_PSOC(psoc);
465 
466 	if (!wmi_hdl) {
467 		target_if_err("null wmi_hdl");
468 		return QDF_STATUS_E_NULL_VALUE;
469 	}
470 
471 	return wmi_convert_pdev_id_host_to_target(wmi_hdl, host_pdev_id,
472 						  target_pdev_id);
473 }
474 
475 QDF_STATUS target_if_wifi_pos_convert_pdev_id_target_to_host(
476 		struct wlan_objmgr_psoc *psoc, uint32_t target_pdev_id,
477 		uint32_t *host_pdev_id)
478 {
479 	wmi_unified_t wmi_hdl = GET_WMI_HDL_FROM_PSOC(psoc);
480 
481 	if (!wmi_hdl) {
482 		target_if_err("null wmi_hdl");
483 		return QDF_STATUS_E_NULL_VALUE;
484 	}
485 
486 	return wmi_convert_pdev_id_target_to_host(wmi_hdl, target_pdev_id,
487 						  host_pdev_id);
488 }
489 #endif /* CNSS_GENL */
490 
491 #ifdef WLAN_FEATURE_CIF_CFR
492 static QDF_STATUS target_if_wifi_pos_fill_ring(uint8_t ring_idx,
493 					struct hal_srng *srng,
494 					struct wifi_pos_psoc_priv_obj *priv)
495 {
496 	uint32_t i;
497 	void *buf, *buf_aligned;
498 
499 	for (i = 0; i < priv->dma_cfg[ring_idx].num_ptr; i++) {
500 		buf = qdf_mem_malloc(priv->dma_cap[ring_idx].min_buf_size +
501 				priv->dma_cap[ring_idx].min_buf_align - 1);
502 		if (!buf)
503 			return QDF_STATUS_E_NOMEM;
504 
505 		priv->dma_buf_pool[ring_idx][i].vaddr = buf;
506 		buf_aligned = (void *)qdf_roundup((uint64_t)buf,
507 				priv->dma_cap[ring_idx].min_buf_align);
508 		priv->dma_buf_pool[ring_idx][i].offset = buf_aligned - buf;
509 		priv->dma_buf_pool[ring_idx][i].cookie = i;
510 		target_if_wifi_pos_replenish_ring(priv, ring_idx,
511 						  buf_aligned, i);
512 	}
513 
514 	return QDF_STATUS_SUCCESS;
515 }
516 
517 static QDF_STATUS target_if_wifi_pos_empty_ring(uint8_t ring_idx,
518 					struct wifi_pos_psoc_priv_obj *priv)
519 {
520 	uint32_t i;
521 
522 	for (i = 0; i < priv->dma_cfg[ring_idx].num_ptr; i++) {
523 		qdf_mem_unmap_nbytes_single(NULL,
524 			(qdf_dma_addr_t)priv->dma_buf_pool[ring_idx][i].vaddr,
525 			QDF_DMA_FROM_DEVICE,
526 			priv->dma_cap[ring_idx].min_buf_size);
527 		qdf_mem_free(priv->dma_buf_pool[ring_idx][i].vaddr);
528 	}
529 
530 	return QDF_STATUS_SUCCESS;
531 }
532 
533 static QDF_STATUS target_if_wifi_pos_init_ring(uint8_t ring_idx,
534 					struct wifi_pos_psoc_priv_obj *priv)
535 {
536 	void *srng;
537 	uint32_t num_entries;
538 	qdf_dma_addr_t paddr;
539 	uint32_t ring_alloc_size;
540 	void *hal_soc = priv->hal_soc;
541 	struct hal_srng_params ring_params = {0};
542 	uint32_t max_entries = hal_srng_max_entries(hal_soc, WIFI_POS_SRC);
543 	uint32_t entry_size = hal_srng_get_entrysize(hal_soc, WIFI_POS_SRC);
544 
545 	num_entries = priv->dma_cap[ring_idx].min_num_ptr > max_entries ?
546 			max_entries : priv->dma_cap[ring_idx].min_num_ptr;
547 	priv->dma_cfg[ring_idx].num_ptr = num_entries;
548 	priv->dma_buf_pool[ring_idx] = qdf_mem_malloc(num_entries *
549 					sizeof(struct wifi_pos_dma_buf_info));
550 	if (!priv->dma_buf_pool[ring_idx])
551 		return QDF_STATUS_E_NOMEM;
552 
553 	ring_alloc_size = (num_entries * entry_size) + RING_BASE_ALIGN - 1;
554 	priv->dma_cfg[ring_idx].ring_alloc_size = ring_alloc_size;
555 	priv->dma_cfg[ring_idx].base_vaddr_unaligned =
556 		qdf_mem_alloc_consistent(NULL, NULL, ring_alloc_size, &paddr);
557 	priv->dma_cfg[ring_idx].base_paddr_unaligned = (void *)paddr;
558 	if (!priv->dma_cfg[ring_idx].base_vaddr_unaligned) {
559 		target_if_err("malloc failed");
560 		return QDF_STATUS_E_NOMEM;
561 	}
562 
563 	priv->dma_cfg[ring_idx].base_vaddr_aligned = (void *)qdf_roundup(
564 		(uint64_t)priv->dma_cfg[ring_idx].base_vaddr_unaligned,
565 		RING_BASE_ALIGN);
566 	ring_params.ring_base_vaddr =
567 		priv->dma_cfg[ring_idx].base_vaddr_aligned;
568 	priv->dma_cfg[ring_idx].base_paddr_aligned = (void *)qdf_roundup(
569 		(uint64_t)priv->dma_cfg[ring_idx].base_paddr_unaligned,
570 		RING_BASE_ALIGN);
571 	ring_params.ring_base_paddr =
572 		(qdf_dma_addr_t)priv->dma_cfg[ring_idx].base_paddr_aligned;
573 	ring_params.num_entries = num_entries;
574 	srng = hal_srng_setup(hal_soc, WIFI_POS_SRC, 0,
575 				priv->dma_cap[ring_idx].pdev_id, &ring_params);
576 	if (!srng) {
577 		target_if_err("srng setup failed");
578 		return QDF_STATUS_E_FAILURE;
579 	}
580 	priv->dma_cfg[ring_idx].srng = srng;
581 	priv->dma_cfg[ring_idx].tail_idx_addr =
582 			(void *)hal_srng_get_tp_addr(hal_soc, srng);
583 	priv->dma_cfg[ring_idx].head_idx_addr =
584 			(void *)hal_srng_get_tp_addr(hal_soc, srng);
585 
586 	return target_if_wifi_pos_fill_ring(ring_idx, srng, priv);
587 }
588 
589 static QDF_STATUS target_if_wifi_pos_deinit_ring(uint8_t ring_idx,
590 					struct wifi_pos_psoc_priv_obj *priv)
591 {
592 	target_if_wifi_pos_empty_ring(ring_idx, priv);
593 	priv->dma_buf_pool[ring_idx] = NULL;
594 	hal_srng_cleanup(priv->hal_soc, priv->dma_cfg[ring_idx].srng);
595 	qdf_mem_free_consistent(NULL, NULL,
596 		priv->dma_cfg[ring_idx].ring_alloc_size,
597 		priv->dma_cfg[ring_idx].base_vaddr_unaligned,
598 		(qdf_dma_addr_t)priv->dma_cfg[ring_idx].base_paddr_unaligned,
599 		0);
600 	qdf_mem_free(priv->dma_buf_pool[ring_idx]);
601 
602 	return QDF_STATUS_SUCCESS;
603 }
604 
605 static QDF_STATUS target_if_wifi_pos_init_srngs(
606 					struct wifi_pos_psoc_priv_obj *priv)
607 {
608 	uint8_t i;
609 	QDF_STATUS status;
610 
611 	/* allocate memory for num_rings pointers */
612 	priv->dma_cfg = qdf_mem_malloc(priv->num_rings *
613 				sizeof(struct wifi_pos_dma_rings_cap));
614 	if (!priv->dma_cfg)
615 		return QDF_STATUS_E_NOMEM;
616 
617 	priv->dma_buf_pool = qdf_mem_malloc(priv->num_rings *
618 				sizeof(struct wifi_pos_dma_buf_info *));
619 	if (!priv->dma_buf_pool)
620 		return QDF_STATUS_E_NOMEM;
621 
622 	for (i = 0; i < priv->num_rings; i++) {
623 		status = target_if_wifi_pos_init_ring(i, priv);
624 		if (QDF_IS_STATUS_ERROR(status)) {
625 			target_if_err("init for ring[%d] failed", i);
626 			return status;
627 		}
628 	}
629 
630 	return QDF_STATUS_SUCCESS;
631 }
632 
633 static QDF_STATUS target_if_wifi_pos_deinit_srngs(
634 					struct wifi_pos_psoc_priv_obj *priv)
635 {
636 	uint8_t i;
637 
638 	for (i = 0; i < priv->num_rings; i++)
639 		target_if_wifi_pos_deinit_ring(i, priv);
640 
641 	qdf_mem_free(priv->dma_buf_pool);
642 	priv->dma_buf_pool = NULL;
643 
644 	return QDF_STATUS_SUCCESS;
645 }
646 
647 static QDF_STATUS target_if_wifi_pos_cfg_fw(struct wlan_objmgr_psoc *psoc,
648 					struct wifi_pos_psoc_priv_obj *priv)
649 {
650 	uint8_t i;
651 	QDF_STATUS status;
652 	wmi_unified_t wmi_hdl = GET_WMI_HDL_FROM_PSOC(psoc);
653 	wmi_oem_dma_ring_cfg_req_fixed_param cfg = {0};
654 
655 	if (!wmi_hdl) {
656 		target_if_err("WMA closed, can't send oem data req cmd");
657 		return QDF_STATUS_E_INVAL;
658 	}
659 
660 	target_if_debug("Sending oem dma ring cfg to target");
661 
662 	for (i = 0; i < priv->num_rings; i++) {
663 		cfg.pdev_id = priv->dma_cfg[i].pdev_id;
664 		cfg.base_addr_lo = (uint64_t)priv->dma_cfg[i].base_paddr_aligned
665 						& 0xFFFFFFFF;
666 		cfg.base_addr_hi = (uint64_t)priv->dma_cfg[i].base_paddr_aligned
667 						& 0xFFFFFFFF00000000;
668 		cfg.head_idx_addr_lo = (uint64_t)priv->dma_cfg[i].head_idx_addr
669 						& 0xFFFFFFFF;
670 		cfg.head_idx_addr_hi = (uint64_t)priv->dma_cfg[i].head_idx_addr
671 						& 0xFFFFFFFF00000000;
672 		cfg.tail_idx_addr_lo = (uint64_t)priv->dma_cfg[i].tail_idx_addr
673 						& 0xFFFFFFFF;
674 		cfg.tail_idx_addr_hi = (uint64_t)priv->dma_cfg[i].tail_idx_addr
675 						& 0xFFFFFFFF00000000;
676 		cfg.num_ptr = priv->dma_cfg[i].num_ptr;
677 		status = wmi_unified_oem_dma_ring_cfg(wmi_hdl, &cfg);
678 		if (!QDF_IS_STATUS_SUCCESS(status)) {
679 			target_if_err("wmi cmd send failed");
680 			return status;
681 		}
682 	}
683 
684 	return status;
685 }
686 
687 QDF_STATUS target_if_wifi_pos_deinit_dma_rings(struct wlan_objmgr_psoc *psoc)
688 {
689 	struct wifi_pos_psoc_priv_obj *priv = wifi_pos_get_psoc_priv_obj(psoc);
690 
691 	target_if_wifi_pos_deinit_srngs(priv);
692 	qdf_mem_free(priv->dma_cap);
693 	priv->dma_cap = NULL;
694 
695 	return QDF_STATUS_SUCCESS;
696 }
697 
698 QDF_STATUS target_if_wifi_pos_init_cir_cfr_rings(struct wlan_objmgr_psoc *psoc,
699 					     void *hal_soc, uint8_t num_mac,
700 					     void *buf)
701 {
702 	uint8_t i;
703 	QDF_STATUS status = QDF_STATUS_SUCCESS;
704 	WMI_OEM_DMA_RING_CAPABILITIES *dma_cap = buf;
705 	struct wifi_pos_psoc_priv_obj *priv = wifi_pos_get_psoc_priv_obj(psoc);
706 
707 	if (!priv) {
708 		target_if_err("unable to get wifi_pos psoc obj");
709 		return QDF_STATUS_E_NULL_VALUE;
710 	}
711 
712 	priv->hal_soc = hal_soc;
713 	priv->num_rings = num_mac;
714 	priv->dma_cap = qdf_mem_malloc(priv->num_rings *
715 					sizeof(struct wifi_pos_dma_rings_cap));
716 	if (!priv->dma_cap)
717 		return QDF_STATUS_E_NOMEM;
718 
719 	for (i = 0; i < num_mac; i++) {
720 		priv->dma_cap[i].pdev_id = dma_cap[i].pdev_id;
721 		priv->dma_cap[i].min_num_ptr = dma_cap[i].min_num_ptr;
722 		priv->dma_cap[i].min_buf_size = dma_cap[i].min_buf_size;
723 		priv->dma_cap[i].min_buf_align = dma_cap[i].min_buf_align;
724 	}
725 
726 	/* initialize DMA rings now */
727 	status = target_if_wifi_pos_init_srngs(priv);
728 	if (QDF_IS_STATUS_ERROR(status)) {
729 		target_if_err("dma init failed: %d", status);
730 		goto dma_init_failed;
731 	}
732 
733 	/* send cfg req cmd to firmware */
734 	status = target_if_wifi_pos_cfg_fw(psoc, priv);
735 	if (QDF_IS_STATUS_ERROR(status)) {
736 		target_if_err("configure to FW failed: %d", status);
737 		goto dma_init_failed;
738 	}
739 
740 	return QDF_STATUS_SUCCESS;
741 
742 dma_init_failed:
743 	target_if_wifi_pos_deinit_dma_rings(psoc);
744 	return status;
745 }
746 
747 #endif
748