xref: /wlan-driver/qca-wifi-host-cmn/target_if/wifi_pos/src/target_if_wifi_pos.c (revision 5113495b16420b49004c444715d2daae2066e7dc)
1*5113495bSYour Name /*
2*5113495bSYour Name  * Copyright (c) 2013-2021 The Linux Foundation. All rights reserved.
3*5113495bSYour Name  * Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved.
4*5113495bSYour Name  *
5*5113495bSYour Name  * Permission to use, copy, modify, and/or distribute this software for
6*5113495bSYour Name  * any purpose with or without fee is hereby granted, provided that the
7*5113495bSYour Name  * above copyright notice and this permission notice appear in all
8*5113495bSYour Name  * copies.
9*5113495bSYour Name  *
10*5113495bSYour Name  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
11*5113495bSYour Name  * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
12*5113495bSYour Name  * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
13*5113495bSYour Name  * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
14*5113495bSYour Name  * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
15*5113495bSYour Name  * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
16*5113495bSYour Name  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17*5113495bSYour Name  * PERFORMANCE OF THIS SOFTWARE.
18*5113495bSYour Name  */
19*5113495bSYour Name 
20*5113495bSYour Name /**
21*5113495bSYour Name  * DOC: target_if_wifi_pos.c
22*5113495bSYour Name  * This file defines the functions pertinent to wifi positioning component's
23*5113495bSYour Name  * target if layer.
24*5113495bSYour Name  */
25*5113495bSYour Name #include "wifi_pos_utils_pub.h"
26*5113495bSYour Name 
27*5113495bSYour Name #include "wmi_unified_api.h"
28*5113495bSYour Name #include "wlan_lmac_if_def.h"
29*5113495bSYour Name #include "target_if_wifi_pos.h"
30*5113495bSYour Name #include "../../../../umac/wifi_pos/src/wifi_pos_main_i.h"
31*5113495bSYour Name #include "wifi_pos_utils_i.h"
32*5113495bSYour Name #include "target_if.h"
33*5113495bSYour Name #ifdef WLAN_FEATURE_CIF_CFR
34*5113495bSYour Name #include "hal_api.h"
35*5113495bSYour Name 
36*5113495bSYour Name #define RING_BASE_ALIGN 8
37*5113495bSYour Name 
target_if_wifi_pos_vaddr_lookup(struct wifi_pos_psoc_priv_obj * priv,void * paddr,uint8_t ring_num,uint32_t cookie)38*5113495bSYour Name static void *target_if_wifi_pos_vaddr_lookup(
39*5113495bSYour Name 				struct wifi_pos_psoc_priv_obj *priv,
40*5113495bSYour Name 				void *paddr, uint8_t ring_num, uint32_t cookie)
41*5113495bSYour Name {
42*5113495bSYour Name 	if (priv->dma_buf_pool[ring_num][cookie].paddr == paddr) {
43*5113495bSYour Name 		return priv->dma_buf_pool[ring_num][cookie].vaddr +
44*5113495bSYour Name 				priv->dma_buf_pool[ring_num][cookie].offset;
45*5113495bSYour Name 	} else {
46*5113495bSYour Name 		target_if_err("incorrect paddr found on cookie slot");
47*5113495bSYour Name 		return NULL;
48*5113495bSYour Name 	}
49*5113495bSYour Name }
50*5113495bSYour Name 
51*5113495bSYour Name QDF_STATUS
target_if_wifi_pos_replenish_ring(struct wifi_pos_psoc_priv_obj * priv,uint8_t ring_idx,void * aligned_vaddr,uint32_t cookie)52*5113495bSYour Name target_if_wifi_pos_replenish_ring(struct wifi_pos_psoc_priv_obj *priv,
53*5113495bSYour Name 				  uint8_t ring_idx,
54*5113495bSYour Name 				  void *aligned_vaddr, uint32_t cookie)
55*5113495bSYour Name {
56*5113495bSYour Name 	uint64_t *ring_entry;
57*5113495bSYour Name 	uint32_t dw_lo, dw_hi = 0, map_status;
58*5113495bSYour Name 	void *hal_soc = priv->hal_soc;
59*5113495bSYour Name 	void *srng = priv->dma_cfg[ring_idx].srng;
60*5113495bSYour Name 	void *paddr;
61*5113495bSYour Name 
62*5113495bSYour Name 	if (!aligned_vaddr) {
63*5113495bSYour Name 		target_if_debug("NULL aligned_vaddr provided");
64*5113495bSYour Name 		return QDF_STATUS_SUCCESS;
65*5113495bSYour Name 	}
66*5113495bSYour Name 
67*5113495bSYour Name 	map_status = qdf_mem_map_nbytes_single(NULL, aligned_vaddr,
68*5113495bSYour Name 			QDF_DMA_FROM_DEVICE,
69*5113495bSYour Name 			priv->dma_cap[ring_idx].min_buf_size,
70*5113495bSYour Name 			(qdf_dma_addr_t *)&paddr);
71*5113495bSYour Name 	if (map_status) {
72*5113495bSYour Name 		target_if_err("mem map failed status: %d", map_status);
73*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
74*5113495bSYour Name 	}
75*5113495bSYour Name 	QDF_ASSERT(!((uint64_t)paddr % priv->dma_cap[ring_idx].min_buf_align));
76*5113495bSYour Name 	priv->dma_buf_pool[ring_idx][cookie].paddr = paddr;
77*5113495bSYour Name 
78*5113495bSYour Name 	hal_srng_access_start(hal_soc, srng);
79*5113495bSYour Name 	ring_entry = hal_srng_src_get_next(hal_soc, srng);
80*5113495bSYour Name 	dw_lo = (uint64_t)paddr & 0xFFFFFFFF;
81*5113495bSYour Name 	WMI_OEM_DMA_DATA_ADDR_HI_SET(dw_hi, (uint64_t)paddr >> 32);
82*5113495bSYour Name 	WMI_OEM_DMA_DATA_ADDR_HI_HOST_DATA_SET(dw_hi, cookie);
83*5113495bSYour Name 	*ring_entry = (uint64_t)dw_hi << 32 | dw_lo;
84*5113495bSYour Name 	hal_srng_access_end(hal_soc, srng);
85*5113495bSYour Name 
86*5113495bSYour Name 	return QDF_STATUS_SUCCESS;
87*5113495bSYour Name }
88*5113495bSYour Name 
target_if_wifi_pos_get_indirect_data(struct wifi_pos_psoc_priv_obj * priv_obj,struct wmi_host_oem_indirect_data * indirect,struct oem_data_rsp * rsp,uint32_t * cookie)89*5113495bSYour Name QDF_STATUS target_if_wifi_pos_get_indirect_data(
90*5113495bSYour Name 		struct wifi_pos_psoc_priv_obj *priv_obj,
91*5113495bSYour Name 		struct wmi_host_oem_indirect_data *indirect,
92*5113495bSYour Name 		struct oem_data_rsp *rsp, uint32_t *cookie)
93*5113495bSYour Name {
94*5113495bSYour Name 	void *paddr = NULL;
95*5113495bSYour Name 	uint32_t addr_hi;
96*5113495bSYour Name 	uint8_t ring_idx = 0, num_rings;
97*5113495bSYour Name 	uint32_t allocated_len;
98*5113495bSYour Name 
99*5113495bSYour Name 	if (!indirect) {
100*5113495bSYour Name 		target_if_debug("no indirect data. regular event received");
101*5113495bSYour Name 		return QDF_STATUS_SUCCESS;
102*5113495bSYour Name 	}
103*5113495bSYour Name 
104*5113495bSYour Name 	ring_idx = indirect->pdev_id - 1;
105*5113495bSYour Name 	num_rings = priv_obj->num_rings;
106*5113495bSYour Name 	if (ring_idx >= num_rings) {
107*5113495bSYour Name 		target_if_err("incorrect pdev_id: %d", indirect->pdev_id);
108*5113495bSYour Name 		return QDF_STATUS_E_INVAL;
109*5113495bSYour Name 	}
110*5113495bSYour Name 
111*5113495bSYour Name 	allocated_len = priv_obj->dma_cap[ring_idx].min_buf_size +
112*5113495bSYour Name 				(priv_obj->dma_cap[ring_idx].min_buf_align - 1);
113*5113495bSYour Name 	if (indirect->len > allocated_len ||
114*5113495bSYour Name 	    indirect->len > OEM_DATA_DMA_BUFF_SIZE) {
115*5113495bSYour Name 		target_if_err("Invalid indirect len: %d, allocated_len:%d",
116*5113495bSYour Name 			      indirect->len, allocated_len);
117*5113495bSYour Name 		return QDF_STATUS_E_INVAL;
118*5113495bSYour Name 	}
119*5113495bSYour Name 
120*5113495bSYour Name 	addr_hi = (uint64_t)WMI_OEM_DMA_DATA_ADDR_HI_GET(
121*5113495bSYour Name 						indirect->addr_hi);
122*5113495bSYour Name 	paddr = (void *)((uint64_t)addr_hi << 32 | indirect->addr_lo);
123*5113495bSYour Name 	*cookie = WMI_OEM_DMA_DATA_ADDR_HI_HOST_DATA_GET(
124*5113495bSYour Name 						indirect->addr_hi);
125*5113495bSYour Name 	rsp->vaddr = target_if_wifi_pos_vaddr_lookup(priv_obj,
126*5113495bSYour Name 					paddr, ring_idx, *cookie);
127*5113495bSYour Name 	rsp->dma_len = indirect->len;
128*5113495bSYour Name 	qdf_mem_unmap_nbytes_single(NULL, (qdf_dma_addr_t)paddr,
129*5113495bSYour Name 			QDF_DMA_FROM_DEVICE,
130*5113495bSYour Name 			priv_obj->dma_cap[ring_idx].min_buf_size);
131*5113495bSYour Name 
132*5113495bSYour Name 	return QDF_STATUS_SUCCESS;
133*5113495bSYour Name }
134*5113495bSYour Name #endif
135*5113495bSYour Name 
target_if_wifi_pos_get_vht_ch_width(struct wlan_objmgr_psoc * psoc,enum phy_ch_width * ch_width)136*5113495bSYour Name QDF_STATUS target_if_wifi_pos_get_vht_ch_width(struct wlan_objmgr_psoc *psoc,
137*5113495bSYour Name 					       enum phy_ch_width *ch_width)
138*5113495bSYour Name {
139*5113495bSYour Name 	struct target_psoc_info *tgt_hdl;
140*5113495bSYour Name 	int vht_cap_info;
141*5113495bSYour Name 
142*5113495bSYour Name 	*ch_width = CH_WIDTH_INVALID;
143*5113495bSYour Name 
144*5113495bSYour Name 	if (!psoc)
145*5113495bSYour Name 		return QDF_STATUS_E_INVAL;
146*5113495bSYour Name 
147*5113495bSYour Name 	tgt_hdl = wlan_psoc_get_tgt_if_handle(psoc);
148*5113495bSYour Name 	if (!tgt_hdl)
149*5113495bSYour Name 		return QDF_STATUS_E_INVAL;
150*5113495bSYour Name 
151*5113495bSYour Name 	*ch_width = CH_WIDTH_80MHZ;
152*5113495bSYour Name 
153*5113495bSYour Name 	vht_cap_info = target_if_get_vht_cap_info(tgt_hdl);
154*5113495bSYour Name 
155*5113495bSYour Name 	if (vht_cap_info & WLAN_VHTCAP_SUP_CHAN_WIDTH_80_160)
156*5113495bSYour Name 		*ch_width = CH_WIDTH_80P80MHZ;
157*5113495bSYour Name 	else if (vht_cap_info & WLAN_VHTCAP_SUP_CHAN_WIDTH_160)
158*5113495bSYour Name 		*ch_width = CH_WIDTH_160MHZ;
159*5113495bSYour Name 
160*5113495bSYour Name 	return QDF_STATUS_SUCCESS;
161*5113495bSYour Name }
162*5113495bSYour Name 
163*5113495bSYour Name #ifndef CNSS_GENL
target_if_wifi_pos_convert_pdev_id_host_to_target(struct wlan_objmgr_psoc * psoc,uint32_t host_pdev_id,uint32_t * target_pdev_id)164*5113495bSYour Name QDF_STATUS target_if_wifi_pos_convert_pdev_id_host_to_target(
165*5113495bSYour Name 		struct wlan_objmgr_psoc *psoc, uint32_t host_pdev_id,
166*5113495bSYour Name 		uint32_t *target_pdev_id)
167*5113495bSYour Name {
168*5113495bSYour Name 	wmi_unified_t wmi_hdl = GET_WMI_HDL_FROM_PSOC(psoc);
169*5113495bSYour Name 
170*5113495bSYour Name 	if (!wmi_hdl) {
171*5113495bSYour Name 		target_if_err("null wmi_hdl");
172*5113495bSYour Name 		return QDF_STATUS_E_NULL_VALUE;
173*5113495bSYour Name 	}
174*5113495bSYour Name 
175*5113495bSYour Name 	return wmi_convert_pdev_id_host_to_target(wmi_hdl, host_pdev_id,
176*5113495bSYour Name 						  target_pdev_id);
177*5113495bSYour Name }
178*5113495bSYour Name 
target_if_wifi_pos_convert_pdev_id_target_to_host(struct wlan_objmgr_psoc * psoc,uint32_t target_pdev_id,uint32_t * host_pdev_id)179*5113495bSYour Name QDF_STATUS target_if_wifi_pos_convert_pdev_id_target_to_host(
180*5113495bSYour Name 		struct wlan_objmgr_psoc *psoc, uint32_t target_pdev_id,
181*5113495bSYour Name 		uint32_t *host_pdev_id)
182*5113495bSYour Name {
183*5113495bSYour Name 	wmi_unified_t wmi_hdl = GET_WMI_HDL_FROM_PSOC(psoc);
184*5113495bSYour Name 
185*5113495bSYour Name 	if (!wmi_hdl) {
186*5113495bSYour Name 		target_if_err("null wmi_hdl");
187*5113495bSYour Name 		return QDF_STATUS_E_NULL_VALUE;
188*5113495bSYour Name 	}
189*5113495bSYour Name 
190*5113495bSYour Name 	return wmi_convert_pdev_id_target_to_host(wmi_hdl, target_pdev_id,
191*5113495bSYour Name 						  host_pdev_id);
192*5113495bSYour Name }
193*5113495bSYour Name #endif /* CNSS_GENL */
194*5113495bSYour Name 
195*5113495bSYour Name #ifdef WLAN_FEATURE_CIF_CFR
target_if_wifi_pos_fill_ring(uint8_t ring_idx,struct hal_srng * srng,struct wifi_pos_psoc_priv_obj * priv)196*5113495bSYour Name static QDF_STATUS target_if_wifi_pos_fill_ring(uint8_t ring_idx,
197*5113495bSYour Name 					struct hal_srng *srng,
198*5113495bSYour Name 					struct wifi_pos_psoc_priv_obj *priv)
199*5113495bSYour Name {
200*5113495bSYour Name 	uint32_t i;
201*5113495bSYour Name 	void *buf, *buf_aligned;
202*5113495bSYour Name 
203*5113495bSYour Name 	for (i = 0; i < priv->dma_cfg[ring_idx].num_ptr; i++) {
204*5113495bSYour Name 		buf = qdf_mem_malloc(priv->dma_cap[ring_idx].min_buf_size +
205*5113495bSYour Name 				priv->dma_cap[ring_idx].min_buf_align - 1);
206*5113495bSYour Name 		if (!buf)
207*5113495bSYour Name 			return QDF_STATUS_E_NOMEM;
208*5113495bSYour Name 
209*5113495bSYour Name 		priv->dma_buf_pool[ring_idx][i].vaddr = buf;
210*5113495bSYour Name 		buf_aligned = (void *)qdf_roundup((uint64_t)buf,
211*5113495bSYour Name 				priv->dma_cap[ring_idx].min_buf_align);
212*5113495bSYour Name 		priv->dma_buf_pool[ring_idx][i].offset = buf_aligned - buf;
213*5113495bSYour Name 		priv->dma_buf_pool[ring_idx][i].cookie = i;
214*5113495bSYour Name 		target_if_wifi_pos_replenish_ring(priv, ring_idx,
215*5113495bSYour Name 						  buf_aligned, i);
216*5113495bSYour Name 	}
217*5113495bSYour Name 
218*5113495bSYour Name 	return QDF_STATUS_SUCCESS;
219*5113495bSYour Name }
220*5113495bSYour Name 
target_if_wifi_pos_empty_ring(uint8_t ring_idx,struct wifi_pos_psoc_priv_obj * priv)221*5113495bSYour Name static QDF_STATUS target_if_wifi_pos_empty_ring(uint8_t ring_idx,
222*5113495bSYour Name 					struct wifi_pos_psoc_priv_obj *priv)
223*5113495bSYour Name {
224*5113495bSYour Name 	uint32_t i;
225*5113495bSYour Name 
226*5113495bSYour Name 	for (i = 0; i < priv->dma_cfg[ring_idx].num_ptr; i++) {
227*5113495bSYour Name 		qdf_mem_unmap_nbytes_single(NULL,
228*5113495bSYour Name 			(qdf_dma_addr_t)priv->dma_buf_pool[ring_idx][i].vaddr,
229*5113495bSYour Name 			QDF_DMA_FROM_DEVICE,
230*5113495bSYour Name 			priv->dma_cap[ring_idx].min_buf_size);
231*5113495bSYour Name 		qdf_mem_free(priv->dma_buf_pool[ring_idx][i].vaddr);
232*5113495bSYour Name 	}
233*5113495bSYour Name 
234*5113495bSYour Name 	return QDF_STATUS_SUCCESS;
235*5113495bSYour Name }
236*5113495bSYour Name 
target_if_wifi_pos_init_ring(uint8_t ring_idx,struct wifi_pos_psoc_priv_obj * priv)237*5113495bSYour Name static QDF_STATUS target_if_wifi_pos_init_ring(uint8_t ring_idx,
238*5113495bSYour Name 					struct wifi_pos_psoc_priv_obj *priv)
239*5113495bSYour Name {
240*5113495bSYour Name 	void *srng;
241*5113495bSYour Name 	uint32_t num_entries;
242*5113495bSYour Name 	qdf_dma_addr_t paddr;
243*5113495bSYour Name 	uint32_t ring_alloc_size;
244*5113495bSYour Name 	void *hal_soc = priv->hal_soc;
245*5113495bSYour Name 	struct hal_srng_params ring_params = {0};
246*5113495bSYour Name 	uint32_t max_entries = hal_srng_max_entries(hal_soc, WIFI_POS_SRC);
247*5113495bSYour Name 	uint32_t entry_size = hal_srng_get_entrysize(hal_soc, WIFI_POS_SRC);
248*5113495bSYour Name 
249*5113495bSYour Name 	num_entries = priv->dma_cap[ring_idx].min_num_ptr > max_entries ?
250*5113495bSYour Name 			max_entries : priv->dma_cap[ring_idx].min_num_ptr;
251*5113495bSYour Name 	priv->dma_cfg[ring_idx].num_ptr = num_entries;
252*5113495bSYour Name 	priv->dma_buf_pool[ring_idx] = qdf_mem_malloc(num_entries *
253*5113495bSYour Name 					sizeof(struct wifi_pos_dma_buf_info));
254*5113495bSYour Name 	if (!priv->dma_buf_pool[ring_idx])
255*5113495bSYour Name 		return QDF_STATUS_E_NOMEM;
256*5113495bSYour Name 
257*5113495bSYour Name 	ring_alloc_size = (num_entries * entry_size) + RING_BASE_ALIGN - 1;
258*5113495bSYour Name 	priv->dma_cfg[ring_idx].ring_alloc_size = ring_alloc_size;
259*5113495bSYour Name 	priv->dma_cfg[ring_idx].base_vaddr_unaligned =
260*5113495bSYour Name 		qdf_mem_alloc_consistent(NULL, NULL, ring_alloc_size, &paddr);
261*5113495bSYour Name 	priv->dma_cfg[ring_idx].base_paddr_unaligned = (void *)paddr;
262*5113495bSYour Name 	if (!priv->dma_cfg[ring_idx].base_vaddr_unaligned) {
263*5113495bSYour Name 		target_if_err("malloc failed");
264*5113495bSYour Name 		return QDF_STATUS_E_NOMEM;
265*5113495bSYour Name 	}
266*5113495bSYour Name 
267*5113495bSYour Name 	priv->dma_cfg[ring_idx].base_vaddr_aligned = (void *)qdf_roundup(
268*5113495bSYour Name 		(uint64_t)priv->dma_cfg[ring_idx].base_vaddr_unaligned,
269*5113495bSYour Name 		RING_BASE_ALIGN);
270*5113495bSYour Name 	ring_params.ring_base_vaddr =
271*5113495bSYour Name 		priv->dma_cfg[ring_idx].base_vaddr_aligned;
272*5113495bSYour Name 	priv->dma_cfg[ring_idx].base_paddr_aligned = (void *)qdf_roundup(
273*5113495bSYour Name 		(uint64_t)priv->dma_cfg[ring_idx].base_paddr_unaligned,
274*5113495bSYour Name 		RING_BASE_ALIGN);
275*5113495bSYour Name 	ring_params.ring_base_paddr =
276*5113495bSYour Name 		(qdf_dma_addr_t)priv->dma_cfg[ring_idx].base_paddr_aligned;
277*5113495bSYour Name 	ring_params.num_entries = num_entries;
278*5113495bSYour Name 	srng = hal_srng_setup(hal_soc, WIFI_POS_SRC, 0,
279*5113495bSYour Name 			      priv->dma_cap[ring_idx].pdev_id, &ring_params, 0);
280*5113495bSYour Name 	if (!srng) {
281*5113495bSYour Name 		target_if_err("srng setup failed");
282*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
283*5113495bSYour Name 	}
284*5113495bSYour Name 	priv->dma_cfg[ring_idx].srng = srng;
285*5113495bSYour Name 	priv->dma_cfg[ring_idx].tail_idx_addr =
286*5113495bSYour Name 			(void *)hal_srng_get_tp_addr(hal_soc, srng);
287*5113495bSYour Name 	priv->dma_cfg[ring_idx].head_idx_addr =
288*5113495bSYour Name 			(void *)hal_srng_get_tp_addr(hal_soc, srng);
289*5113495bSYour Name 
290*5113495bSYour Name 	return target_if_wifi_pos_fill_ring(ring_idx, srng, priv);
291*5113495bSYour Name }
292*5113495bSYour Name 
target_if_wifi_pos_deinit_ring(uint8_t ring_idx,struct wifi_pos_psoc_priv_obj * priv)293*5113495bSYour Name static QDF_STATUS target_if_wifi_pos_deinit_ring(uint8_t ring_idx,
294*5113495bSYour Name 					struct wifi_pos_psoc_priv_obj *priv)
295*5113495bSYour Name {
296*5113495bSYour Name 	target_if_wifi_pos_empty_ring(ring_idx, priv);
297*5113495bSYour Name 	priv->dma_buf_pool[ring_idx] = NULL;
298*5113495bSYour Name 	hal_srng_cleanup(priv->hal_soc, priv->dma_cfg[ring_idx].srng, 0);
299*5113495bSYour Name 	qdf_mem_free_consistent(NULL, NULL,
300*5113495bSYour Name 		priv->dma_cfg[ring_idx].ring_alloc_size,
301*5113495bSYour Name 		priv->dma_cfg[ring_idx].base_vaddr_unaligned,
302*5113495bSYour Name 		(qdf_dma_addr_t)priv->dma_cfg[ring_idx].base_paddr_unaligned,
303*5113495bSYour Name 		0);
304*5113495bSYour Name 	qdf_mem_free(priv->dma_buf_pool[ring_idx]);
305*5113495bSYour Name 
306*5113495bSYour Name 	return QDF_STATUS_SUCCESS;
307*5113495bSYour Name }
308*5113495bSYour Name 
target_if_wifi_pos_init_srngs(struct wifi_pos_psoc_priv_obj * priv)309*5113495bSYour Name static QDF_STATUS target_if_wifi_pos_init_srngs(
310*5113495bSYour Name 					struct wifi_pos_psoc_priv_obj *priv)
311*5113495bSYour Name {
312*5113495bSYour Name 	uint8_t i;
313*5113495bSYour Name 	QDF_STATUS status;
314*5113495bSYour Name 
315*5113495bSYour Name 	/* allocate memory for num_rings pointers */
316*5113495bSYour Name 	priv->dma_cfg = qdf_mem_malloc(priv->num_rings *
317*5113495bSYour Name 				sizeof(struct wifi_pos_dma_rings_cap));
318*5113495bSYour Name 	if (!priv->dma_cfg)
319*5113495bSYour Name 		return QDF_STATUS_E_NOMEM;
320*5113495bSYour Name 
321*5113495bSYour Name 	priv->dma_buf_pool = qdf_mem_malloc(priv->num_rings *
322*5113495bSYour Name 				sizeof(struct wifi_pos_dma_buf_info *));
323*5113495bSYour Name 	if (!priv->dma_buf_pool)
324*5113495bSYour Name 		return QDF_STATUS_E_NOMEM;
325*5113495bSYour Name 
326*5113495bSYour Name 	for (i = 0; i < priv->num_rings; i++) {
327*5113495bSYour Name 		status = target_if_wifi_pos_init_ring(i, priv);
328*5113495bSYour Name 		if (QDF_IS_STATUS_ERROR(status)) {
329*5113495bSYour Name 			target_if_err("init for ring[%d] failed", i);
330*5113495bSYour Name 			return status;
331*5113495bSYour Name 		}
332*5113495bSYour Name 	}
333*5113495bSYour Name 
334*5113495bSYour Name 	return QDF_STATUS_SUCCESS;
335*5113495bSYour Name }
336*5113495bSYour Name 
target_if_wifi_pos_deinit_srngs(struct wifi_pos_psoc_priv_obj * priv)337*5113495bSYour Name static QDF_STATUS target_if_wifi_pos_deinit_srngs(
338*5113495bSYour Name 					struct wifi_pos_psoc_priv_obj *priv)
339*5113495bSYour Name {
340*5113495bSYour Name 	uint8_t i;
341*5113495bSYour Name 
342*5113495bSYour Name 	for (i = 0; i < priv->num_rings; i++)
343*5113495bSYour Name 		target_if_wifi_pos_deinit_ring(i, priv);
344*5113495bSYour Name 
345*5113495bSYour Name 	qdf_mem_free(priv->dma_buf_pool);
346*5113495bSYour Name 	priv->dma_buf_pool = NULL;
347*5113495bSYour Name 
348*5113495bSYour Name 	return QDF_STATUS_SUCCESS;
349*5113495bSYour Name }
350*5113495bSYour Name 
target_if_wifi_pos_cfg_fw(struct wlan_objmgr_psoc * psoc,struct wifi_pos_psoc_priv_obj * priv)351*5113495bSYour Name static QDF_STATUS target_if_wifi_pos_cfg_fw(struct wlan_objmgr_psoc *psoc,
352*5113495bSYour Name 					struct wifi_pos_psoc_priv_obj *priv)
353*5113495bSYour Name {
354*5113495bSYour Name 	uint8_t i;
355*5113495bSYour Name 	QDF_STATUS status;
356*5113495bSYour Name 	wmi_unified_t wmi_hdl = GET_WMI_HDL_FROM_PSOC(psoc);
357*5113495bSYour Name 	wmi_oem_dma_ring_cfg_req_fixed_param cfg = {0};
358*5113495bSYour Name 
359*5113495bSYour Name 	if (!wmi_hdl) {
360*5113495bSYour Name 		target_if_err("WMA closed, can't send oem data req cmd");
361*5113495bSYour Name 		return QDF_STATUS_E_INVAL;
362*5113495bSYour Name 	}
363*5113495bSYour Name 
364*5113495bSYour Name 	target_if_debug("Sending oem dma ring cfg to target");
365*5113495bSYour Name 
366*5113495bSYour Name 	for (i = 0; i < priv->num_rings; i++) {
367*5113495bSYour Name 		cfg.pdev_id = priv->dma_cfg[i].pdev_id;
368*5113495bSYour Name 		cfg.base_addr_lo = (uint64_t)priv->dma_cfg[i].base_paddr_aligned
369*5113495bSYour Name 						& 0xFFFFFFFF;
370*5113495bSYour Name 		cfg.base_addr_hi = (uint64_t)priv->dma_cfg[i].base_paddr_aligned
371*5113495bSYour Name 						& 0xFFFFFFFF00000000;
372*5113495bSYour Name 		cfg.head_idx_addr_lo = (uint64_t)priv->dma_cfg[i].head_idx_addr
373*5113495bSYour Name 						& 0xFFFFFFFF;
374*5113495bSYour Name 		cfg.head_idx_addr_hi = (uint64_t)priv->dma_cfg[i].head_idx_addr
375*5113495bSYour Name 						& 0xFFFFFFFF00000000;
376*5113495bSYour Name 		cfg.tail_idx_addr_lo = (uint64_t)priv->dma_cfg[i].tail_idx_addr
377*5113495bSYour Name 						& 0xFFFFFFFF;
378*5113495bSYour Name 		cfg.tail_idx_addr_hi = (uint64_t)priv->dma_cfg[i].tail_idx_addr
379*5113495bSYour Name 						& 0xFFFFFFFF00000000;
380*5113495bSYour Name 		cfg.num_ptr = priv->dma_cfg[i].num_ptr;
381*5113495bSYour Name 		status = wmi_unified_oem_dma_ring_cfg(wmi_hdl, &cfg);
382*5113495bSYour Name 		if (!QDF_IS_STATUS_SUCCESS(status)) {
383*5113495bSYour Name 			target_if_err("wmi cmd send failed");
384*5113495bSYour Name 			return status;
385*5113495bSYour Name 		}
386*5113495bSYour Name 	}
387*5113495bSYour Name 
388*5113495bSYour Name 	return status;
389*5113495bSYour Name }
390*5113495bSYour Name 
target_if_wifi_pos_deinit_dma_rings(struct wlan_objmgr_psoc * psoc)391*5113495bSYour Name QDF_STATUS target_if_wifi_pos_deinit_dma_rings(struct wlan_objmgr_psoc *psoc)
392*5113495bSYour Name {
393*5113495bSYour Name 	struct wifi_pos_psoc_priv_obj *priv = wifi_pos_get_psoc_priv_obj(psoc);
394*5113495bSYour Name 
395*5113495bSYour Name 	target_if_wifi_pos_deinit_srngs(priv);
396*5113495bSYour Name 	qdf_mem_free(priv->dma_cap);
397*5113495bSYour Name 	priv->dma_cap = NULL;
398*5113495bSYour Name 
399*5113495bSYour Name 	return QDF_STATUS_SUCCESS;
400*5113495bSYour Name }
401*5113495bSYour Name 
target_if_wifi_pos_init_cir_cfr_rings(struct wlan_objmgr_psoc * psoc,void * hal_soc,uint8_t num_mac,void * buf)402*5113495bSYour Name QDF_STATUS target_if_wifi_pos_init_cir_cfr_rings(struct wlan_objmgr_psoc *psoc,
403*5113495bSYour Name 					     void *hal_soc, uint8_t num_mac,
404*5113495bSYour Name 					     void *buf)
405*5113495bSYour Name {
406*5113495bSYour Name 	uint8_t i;
407*5113495bSYour Name 	QDF_STATUS status = QDF_STATUS_SUCCESS;
408*5113495bSYour Name 	WMI_OEM_DMA_RING_CAPABILITIES *dma_cap = buf;
409*5113495bSYour Name 	struct wifi_pos_psoc_priv_obj *priv = wifi_pos_get_psoc_priv_obj(psoc);
410*5113495bSYour Name 
411*5113495bSYour Name 	if (!priv) {
412*5113495bSYour Name 		target_if_err("unable to get wifi_pos psoc obj");
413*5113495bSYour Name 		return QDF_STATUS_E_NULL_VALUE;
414*5113495bSYour Name 	}
415*5113495bSYour Name 
416*5113495bSYour Name 	priv->hal_soc = hal_soc;
417*5113495bSYour Name 	priv->num_rings = num_mac;
418*5113495bSYour Name 	priv->dma_cap = qdf_mem_malloc(priv->num_rings *
419*5113495bSYour Name 					sizeof(struct wifi_pos_dma_rings_cap));
420*5113495bSYour Name 	if (!priv->dma_cap)
421*5113495bSYour Name 		return QDF_STATUS_E_NOMEM;
422*5113495bSYour Name 
423*5113495bSYour Name 	for (i = 0; i < num_mac; i++) {
424*5113495bSYour Name 		priv->dma_cap[i].pdev_id = dma_cap[i].pdev_id;
425*5113495bSYour Name 		priv->dma_cap[i].min_num_ptr = dma_cap[i].min_num_ptr;
426*5113495bSYour Name 		priv->dma_cap[i].min_buf_size = dma_cap[i].min_buf_size;
427*5113495bSYour Name 		priv->dma_cap[i].min_buf_align = dma_cap[i].min_buf_align;
428*5113495bSYour Name 	}
429*5113495bSYour Name 
430*5113495bSYour Name 	/* initialize DMA rings now */
431*5113495bSYour Name 	status = target_if_wifi_pos_init_srngs(priv);
432*5113495bSYour Name 	if (QDF_IS_STATUS_ERROR(status)) {
433*5113495bSYour Name 		target_if_err("dma init failed: %d", status);
434*5113495bSYour Name 		goto dma_init_failed;
435*5113495bSYour Name 	}
436*5113495bSYour Name 
437*5113495bSYour Name 	/* send cfg req cmd to firmware */
438*5113495bSYour Name 	status = target_if_wifi_pos_cfg_fw(psoc, priv);
439*5113495bSYour Name 	if (QDF_IS_STATUS_ERROR(status)) {
440*5113495bSYour Name 		target_if_err("configure to FW failed: %d", status);
441*5113495bSYour Name 		goto dma_init_failed;
442*5113495bSYour Name 	}
443*5113495bSYour Name 
444*5113495bSYour Name 	return QDF_STATUS_SUCCESS;
445*5113495bSYour Name 
446*5113495bSYour Name dma_init_failed:
447*5113495bSYour Name 	target_if_wifi_pos_deinit_dma_rings(psoc);
448*5113495bSYour Name 	return status;
449*5113495bSYour Name }
450*5113495bSYour Name 
451*5113495bSYour Name #endif
452