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