xref: /wlan-driver/qca-wifi-host-cmn/umac/cfr/core/src/cfr_common.c (revision 5113495b16420b49004c444715d2daae2066e7dc)
1*5113495bSYour Name /*
2*5113495bSYour Name  * Copyright (c) 2019-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 #include <cfr_defs_i.h>
21*5113495bSYour Name #include <qdf_types.h>
22*5113495bSYour Name #include <wlan_objmgr_pdev_obj.h>
23*5113495bSYour Name #include <wlan_objmgr_vdev_obj.h>
24*5113495bSYour Name #include <wlan_objmgr_peer_obj.h>
25*5113495bSYour Name #include <wlan_cfr_tgt_api.h>
26*5113495bSYour Name #include <qdf_streamfs.h>
27*5113495bSYour Name #include <target_if.h>
28*5113495bSYour Name #include <target_if_direct_buf_rx_api.h>
29*5113495bSYour Name #include <wlan_osif_priv.h>
30*5113495bSYour Name #include <cfg_ucfg_api.h>
31*5113495bSYour Name #include "cfr_cfg.h"
32*5113495bSYour Name #ifdef WLAN_CFR_PM
33*5113495bSYour Name #include "host_diag_core_event.h"
34*5113495bSYour Name #endif
35*5113495bSYour Name 
36*5113495bSYour Name /**
37*5113495bSYour Name  * wlan_cfr_is_ini_disabled() - Check if cfr feature is disabled
38*5113495bSYour Name  * @pdev: the physical device object.
39*5113495bSYour Name  *
40*5113495bSYour Name  * Return : true if cfr is disabled, else false.
41*5113495bSYour Name  */
42*5113495bSYour Name static bool
wlan_cfr_is_ini_disabled(struct wlan_objmgr_pdev * pdev)43*5113495bSYour Name wlan_cfr_is_ini_disabled(struct wlan_objmgr_pdev *pdev)
44*5113495bSYour Name {
45*5113495bSYour Name 	struct wlan_objmgr_psoc *psoc;
46*5113495bSYour Name 	uint8_t cfr_disable_bitmap;
47*5113495bSYour Name 
48*5113495bSYour Name 	psoc = wlan_pdev_get_psoc(pdev);
49*5113495bSYour Name 	if (!psoc) {
50*5113495bSYour Name 		cfr_err("psoc is null");
51*5113495bSYour Name 		return true;
52*5113495bSYour Name 	}
53*5113495bSYour Name 
54*5113495bSYour Name 	cfr_disable_bitmap = cfg_get(psoc, CFG_CFR_DISABLE);
55*5113495bSYour Name 
56*5113495bSYour Name 	if (cfr_disable_bitmap & (1 << wlan_objmgr_pdev_get_pdev_id(pdev))) {
57*5113495bSYour Name 		cfr_info("cfr is disabled for pdev[%d]",
58*5113495bSYour Name 			 wlan_objmgr_pdev_get_pdev_id(pdev));
59*5113495bSYour Name 		return true;
60*5113495bSYour Name 	}
61*5113495bSYour Name 
62*5113495bSYour Name 	return false;
63*5113495bSYour Name }
64*5113495bSYour Name 
65*5113495bSYour Name /**
66*5113495bSYour Name  * wlan_cfr_get_dbr_num_entries() - Get entry number of DBR ring
67*5113495bSYour Name  * @pdev: the physical device object.
68*5113495bSYour Name  *
69*5113495bSYour Name  * Return : Entry number of DBR ring.
70*5113495bSYour Name  */
71*5113495bSYour Name static uint32_t
wlan_cfr_get_dbr_num_entries(struct wlan_objmgr_pdev * pdev)72*5113495bSYour Name wlan_cfr_get_dbr_num_entries(struct wlan_objmgr_pdev *pdev)
73*5113495bSYour Name {
74*5113495bSYour Name 	struct wlan_objmgr_psoc *psoc;
75*5113495bSYour Name 	struct wlan_psoc_host_dbr_ring_caps *dbr_ring_cap;
76*5113495bSYour Name 	uint8_t num_dbr_ring_caps, cap_idx, pdev_id;
77*5113495bSYour Name 	struct target_psoc_info *tgt_psoc_info;
78*5113495bSYour Name 	uint32_t num_entries = MAX_LUT_ENTRIES;
79*5113495bSYour Name 
80*5113495bSYour Name 	if (!pdev) {
81*5113495bSYour Name 		cfr_err("Invalid pdev");
82*5113495bSYour Name 		return num_entries;
83*5113495bSYour Name 	}
84*5113495bSYour Name 
85*5113495bSYour Name 	psoc = wlan_pdev_get_psoc(pdev);
86*5113495bSYour Name 	if (!psoc) {
87*5113495bSYour Name 		cfr_err("psoc is null");
88*5113495bSYour Name 		return num_entries;
89*5113495bSYour Name 	}
90*5113495bSYour Name 
91*5113495bSYour Name 	tgt_psoc_info = wlan_psoc_get_tgt_if_handle(psoc);
92*5113495bSYour Name 	if (!tgt_psoc_info) {
93*5113495bSYour Name 		cfr_err("target_psoc_info is null");
94*5113495bSYour Name 		return num_entries;
95*5113495bSYour Name 	}
96*5113495bSYour Name 
97*5113495bSYour Name 	num_dbr_ring_caps = target_psoc_get_num_dbr_ring_caps(tgt_psoc_info);
98*5113495bSYour Name 	dbr_ring_cap = target_psoc_get_dbr_ring_caps(tgt_psoc_info);
99*5113495bSYour Name 	pdev_id = wlan_objmgr_pdev_get_pdev_id(pdev);
100*5113495bSYour Name 
101*5113495bSYour Name 	for (cap_idx = 0; cap_idx < num_dbr_ring_caps; cap_idx++) {
102*5113495bSYour Name 		if (dbr_ring_cap[cap_idx].pdev_id == pdev_id &&
103*5113495bSYour Name 		    dbr_ring_cap[cap_idx].mod_id == DBR_MODULE_CFR)
104*5113495bSYour Name 			num_entries = dbr_ring_cap[cap_idx].ring_elems_min;
105*5113495bSYour Name 	}
106*5113495bSYour Name 
107*5113495bSYour Name 	num_entries = QDF_MIN(num_entries, MAX_LUT_ENTRIES);
108*5113495bSYour Name 	cfr_debug("pdev id %d, num_entries %d", pdev_id, num_entries);
109*5113495bSYour Name 
110*5113495bSYour Name 	return num_entries;
111*5113495bSYour Name }
112*5113495bSYour Name 
113*5113495bSYour Name #ifdef WLAN_CFR_PM
114*5113495bSYour Name /**
115*5113495bSYour Name  * cfr_wakelock_init(): Create/init wake lock for CFR
116*5113495bSYour Name  * @pcfr: CFR pdev context
117*5113495bSYour Name  *
118*5113495bSYour Name  * Create/init wake lock for CFR
119*5113495bSYour Name  *
120*5113495bSYour Name  * Return None
121*5113495bSYour Name  */
cfr_wakelock_init(struct pdev_cfr * pcfr)122*5113495bSYour Name static void cfr_wakelock_init(struct pdev_cfr *pcfr)
123*5113495bSYour Name {
124*5113495bSYour Name 	if (!pcfr) {
125*5113495bSYour Name 		cfr_debug("NULL pa");
126*5113495bSYour Name 		return;
127*5113495bSYour Name 	}
128*5113495bSYour Name 
129*5113495bSYour Name 	pcfr->is_prevent_suspend = false;
130*5113495bSYour Name 	qdf_wake_lock_create(&pcfr->wake_lock, "wlan_cfr");
131*5113495bSYour Name 	qdf_runtime_lock_init(&pcfr->runtime_lock);
132*5113495bSYour Name }
133*5113495bSYour Name 
134*5113495bSYour Name /**
135*5113495bSYour Name  * cfr_wakelock_deinit(): Destroy/deinit wake lock for CFR
136*5113495bSYour Name  * @pcfr: CFR pdev context
137*5113495bSYour Name  *
138*5113495bSYour Name  * Destroy/deinit wake lock for CFR
139*5113495bSYour Name  *
140*5113495bSYour Name  * Return None
141*5113495bSYour Name  */
cfr_wakelock_deinit(struct pdev_cfr * pcfr)142*5113495bSYour Name static void cfr_wakelock_deinit(struct pdev_cfr *pcfr)
143*5113495bSYour Name {
144*5113495bSYour Name 	if (!pcfr) {
145*5113495bSYour Name 		cfr_debug("NULL pa");
146*5113495bSYour Name 		return;
147*5113495bSYour Name 	}
148*5113495bSYour Name 
149*5113495bSYour Name 	qdf_runtime_lock_deinit(&pcfr->runtime_lock);
150*5113495bSYour Name 	qdf_wake_lock_destroy(&pcfr->wake_lock);
151*5113495bSYour Name }
152*5113495bSYour Name #else
cfr_wakelock_init(struct pdev_cfr * pcfr)153*5113495bSYour Name static inline void cfr_wakelock_init(struct pdev_cfr *pcfr)
154*5113495bSYour Name {
155*5113495bSYour Name }
156*5113495bSYour Name 
cfr_wakelock_deinit(struct pdev_cfr * pcfr)157*5113495bSYour Name static inline void cfr_wakelock_deinit(struct pdev_cfr *pcfr)
158*5113495bSYour Name {
159*5113495bSYour Name }
160*5113495bSYour Name #endif
161*5113495bSYour Name 
162*5113495bSYour Name QDF_STATUS
wlan_cfr_psoc_obj_create_handler(struct wlan_objmgr_psoc * psoc,void * arg)163*5113495bSYour Name wlan_cfr_psoc_obj_create_handler(struct wlan_objmgr_psoc *psoc, void *arg)
164*5113495bSYour Name {
165*5113495bSYour Name 	struct psoc_cfr *cfr_sc = NULL;
166*5113495bSYour Name 
167*5113495bSYour Name 	cfr_sc = (struct psoc_cfr *)qdf_mem_malloc(sizeof(struct psoc_cfr));
168*5113495bSYour Name 	if (!cfr_sc) {
169*5113495bSYour Name 		cfr_err("Failed to allocate cfr_ctx object\n");
170*5113495bSYour Name 		return QDF_STATUS_E_NOMEM;
171*5113495bSYour Name 	}
172*5113495bSYour Name 
173*5113495bSYour Name 	cfr_sc->psoc_obj = psoc;
174*5113495bSYour Name 
175*5113495bSYour Name 	wlan_objmgr_psoc_component_obj_attach(psoc, WLAN_UMAC_COMP_CFR,
176*5113495bSYour Name 					      (void *)cfr_sc,
177*5113495bSYour Name 					      QDF_STATUS_SUCCESS);
178*5113495bSYour Name 
179*5113495bSYour Name 	return QDF_STATUS_SUCCESS;
180*5113495bSYour Name }
181*5113495bSYour Name 
182*5113495bSYour Name QDF_STATUS
wlan_cfr_psoc_obj_destroy_handler(struct wlan_objmgr_psoc * psoc,void * arg)183*5113495bSYour Name wlan_cfr_psoc_obj_destroy_handler(struct wlan_objmgr_psoc *psoc, void *arg)
184*5113495bSYour Name {
185*5113495bSYour Name 	struct psoc_cfr *cfr_sc = NULL;
186*5113495bSYour Name 
187*5113495bSYour Name 	cfr_sc = wlan_objmgr_psoc_get_comp_private_obj(psoc,
188*5113495bSYour Name 						       WLAN_UMAC_COMP_CFR);
189*5113495bSYour Name 	if (cfr_sc) {
190*5113495bSYour Name 		wlan_objmgr_psoc_component_obj_detach(psoc, WLAN_UMAC_COMP_CFR,
191*5113495bSYour Name 						      (void *)cfr_sc);
192*5113495bSYour Name 		qdf_mem_free(cfr_sc);
193*5113495bSYour Name 	}
194*5113495bSYour Name 
195*5113495bSYour Name 	return QDF_STATUS_SUCCESS;
196*5113495bSYour Name }
197*5113495bSYour Name 
198*5113495bSYour Name #ifdef WLAN_RCC_ENHANCED_AOA_SUPPORT
wlan_cfr_get_aoa_caps(struct pdev_cfr * pa)199*5113495bSYour Name static QDF_STATUS wlan_cfr_get_aoa_caps(struct pdev_cfr *pa)
200*5113495bSYour Name {
201*5113495bSYour Name 	struct wlan_objmgr_pdev *pdev = pa->pdev_obj;
202*5113495bSYour Name 	struct wlan_objmgr_psoc *psoc;
203*5113495bSYour Name 	struct target_psoc_info *tgt_psoc_info;
204*5113495bSYour Name 	struct wlan_psoc_host_rcc_enh_aoa_caps_ext2 *aoa_caps;
205*5113495bSYour Name 	uint32_t i, max_agc_gain_tbl_sz;
206*5113495bSYour Name 
207*5113495bSYour Name 	if (!pdev) {
208*5113495bSYour Name 		cfr_err("Invalid pdev");
209*5113495bSYour Name 		return QDF_STATUS_E_INVAL;
210*5113495bSYour Name 	}
211*5113495bSYour Name 
212*5113495bSYour Name 	psoc = wlan_pdev_get_psoc(pdev);
213*5113495bSYour Name 	if (!psoc) {
214*5113495bSYour Name 		cfr_err("psoc is null");
215*5113495bSYour Name 		return QDF_STATUS_E_INVAL;
216*5113495bSYour Name 	}
217*5113495bSYour Name 
218*5113495bSYour Name 	tgt_psoc_info = wlan_psoc_get_tgt_if_handle(psoc);
219*5113495bSYour Name 	if (!tgt_psoc_info) {
220*5113495bSYour Name 		cfr_err("target_psoc_info is null");
221*5113495bSYour Name 		return QDF_STATUS_E_INVAL;
222*5113495bSYour Name 	}
223*5113495bSYour Name 
224*5113495bSYour Name 	pa->is_enh_aoa_data = false;
225*5113495bSYour Name 
226*5113495bSYour Name 	aoa_caps = target_psoc_get_aoa_caps(tgt_psoc_info);
227*5113495bSYour Name 
228*5113495bSYour Name 	if (!aoa_caps) {
229*5113495bSYour Name 		cfr_info("NO enhanced AoA cap advertised");
230*5113495bSYour Name 		return QDF_STATUS_SUCCESS;
231*5113495bSYour Name 	}
232*5113495bSYour Name 
233*5113495bSYour Name 	max_agc_gain_tbl_sz = sizeof(uint16_t) * PSOC_MAX_NUM_AGC_GAIN_TBLS;
234*5113495bSYour Name 	pa->max_entries_all_table = 0;
235*5113495bSYour Name 	pa->max_agc_gain_tbls = aoa_caps->max_agc_gain_tbls;
236*5113495bSYour Name 
237*5113495bSYour Name 	if (pa->max_agc_gain_tbls > PSOC_MAX_NUM_AGC_GAIN_TBLS) {
238*5113495bSYour Name 		cfr_err("Invalid num of tables advertised");
239*5113495bSYour Name 		return QDF_STATUS_E_INVAL;
240*5113495bSYour Name 	}
241*5113495bSYour Name 
242*5113495bSYour Name 	qdf_mem_copy(pa->max_agc_gain_per_tbl_2g,
243*5113495bSYour Name 		     aoa_caps->max_agc_gain_per_tbl_2g,
244*5113495bSYour Name 		     max_agc_gain_tbl_sz);
245*5113495bSYour Name 	qdf_mem_copy(pa->max_agc_gain_per_tbl_5g,
246*5113495bSYour Name 		     aoa_caps->max_agc_gain_per_tbl_5g,
247*5113495bSYour Name 		     max_agc_gain_tbl_sz);
248*5113495bSYour Name 	qdf_mem_copy(pa->max_agc_gain_per_tbl_6g,
249*5113495bSYour Name 		     aoa_caps->max_agc_gain_per_tbl_6g,
250*5113495bSYour Name 		     max_agc_gain_tbl_sz);
251*5113495bSYour Name 	qdf_mem_copy(pa->max_bdf_entries_per_tbl,
252*5113495bSYour Name 		     aoa_caps->max_bdf_entries_per_tbl,
253*5113495bSYour Name 		     (sizeof(uint8_t) * PSOC_MAX_NUM_AGC_GAIN_TBLS));
254*5113495bSYour Name 
255*5113495bSYour Name 	/* table 0's data always starts at offset 0 */
256*5113495bSYour Name 	pa->start_ent[0] = 0;
257*5113495bSYour Name 	for (i = 0; i < pa->max_agc_gain_tbls; i++) {
258*5113495bSYour Name 		pa->max_entries_all_table +=
259*5113495bSYour Name 			pa->max_bdf_entries_per_tbl[i];
260*5113495bSYour Name 		if ((i + 1) < pa->max_agc_gain_tbls) {
261*5113495bSYour Name 			pa->start_ent[i + 1] = (pa->max_bdf_entries_per_tbl[i] +
262*5113495bSYour Name 					pa->start_ent[i]);
263*5113495bSYour Name 		}
264*5113495bSYour Name 	}
265*5113495bSYour Name 
266*5113495bSYour Name 	pa->gain_stop_index_array = qdf_mem_malloc(sizeof(uint16_t) *
267*5113495bSYour Name 					pa->max_entries_all_table *
268*5113495bSYour Name 					HOST_MAX_CHAINS);
269*5113495bSYour Name 	if (!pa->gain_stop_index_array) {
270*5113495bSYour Name 		qdf_err("Failed to allocate gain stop array");
271*5113495bSYour Name 		return QDF_STATUS_E_NOMEM;
272*5113495bSYour Name 	}
273*5113495bSYour Name 
274*5113495bSYour Name 	pa->enh_phase_delta_array = qdf_mem_malloc(sizeof(uint16_t) *
275*5113495bSYour Name 					pa->max_entries_all_table *
276*5113495bSYour Name 					HOST_MAX_CHAINS);
277*5113495bSYour Name 	if (!pa->enh_phase_delta_array) {
278*5113495bSYour Name 		qdf_err("Failed to allocate phase delta array");
279*5113495bSYour Name 		qdf_mem_free(pa->gain_stop_index_array);
280*5113495bSYour Name 		return QDF_STATUS_E_NOMEM;
281*5113495bSYour Name 	}
282*5113495bSYour Name 
283*5113495bSYour Name 	pa->is_enh_aoa_data = true;
284*5113495bSYour Name 
285*5113495bSYour Name 	return QDF_STATUS_SUCCESS;
286*5113495bSYour Name }
287*5113495bSYour Name #else
wlan_cfr_get_aoa_caps(struct pdev_cfr * pa)288*5113495bSYour Name static QDF_STATUS wlan_cfr_get_aoa_caps(struct pdev_cfr *pa)
289*5113495bSYour Name {
290*5113495bSYour Name 	return QDF_STATUS_SUCCESS;
291*5113495bSYour Name }
292*5113495bSYour Name #endif /* WLAN_RCC_ENHANCED_AOA_SUPPORT */
293*5113495bSYour Name 
294*5113495bSYour Name QDF_STATUS
wlan_cfr_pdev_obj_create_handler(struct wlan_objmgr_pdev * pdev,void * arg)295*5113495bSYour Name wlan_cfr_pdev_obj_create_handler(struct wlan_objmgr_pdev *pdev, void *arg)
296*5113495bSYour Name {
297*5113495bSYour Name 	struct pdev_cfr *pa = NULL;
298*5113495bSYour Name 	uint32_t idx;
299*5113495bSYour Name 	QDF_STATUS status;
300*5113495bSYour Name 
301*5113495bSYour Name 	if (!pdev) {
302*5113495bSYour Name 		cfr_err("PDEV is NULL\n");
303*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
304*5113495bSYour Name 	}
305*5113495bSYour Name 
306*5113495bSYour Name 	if (wlan_cfr_is_ini_disabled(pdev)) {
307*5113495bSYour Name 		wlan_pdev_nif_feat_ext_cap_clear(pdev, WLAN_PDEV_FEXT_CFR_EN);
308*5113495bSYour Name 		return QDF_STATUS_E_NOSUPPORT;
309*5113495bSYour Name 	}
310*5113495bSYour Name 
311*5113495bSYour Name 	wlan_pdev_nif_feat_ext_cap_set(pdev, WLAN_PDEV_FEXT_CFR_EN);
312*5113495bSYour Name 
313*5113495bSYour Name 	pa = (struct pdev_cfr *)qdf_mem_malloc(sizeof(struct pdev_cfr));
314*5113495bSYour Name 	if (!pa) {
315*5113495bSYour Name 		cfr_err("Failed to allocate pdev_cfr object\n");
316*5113495bSYour Name 		return QDF_STATUS_E_NOMEM;
317*5113495bSYour Name 	}
318*5113495bSYour Name 	pa->pdev_obj = pdev;
319*5113495bSYour Name 	pa->lut_num = wlan_cfr_get_dbr_num_entries(pdev);
320*5113495bSYour Name 	if (!pa->lut_num) {
321*5113495bSYour Name 		cfr_err("lut num is 0");
322*5113495bSYour Name 		qdf_mem_free(pa);
323*5113495bSYour Name 		return QDF_STATUS_E_INVAL;
324*5113495bSYour Name 	}
325*5113495bSYour Name 	pa->lut = (struct look_up_table **)qdf_mem_malloc(pa->lut_num *
326*5113495bSYour Name 			sizeof(struct look_up_table *));
327*5113495bSYour Name 	if (!pa->lut) {
328*5113495bSYour Name 		cfr_err("Failed to allocate lut, lut num %d", pa->lut_num);
329*5113495bSYour Name 		qdf_mem_free(pa);
330*5113495bSYour Name 		return QDF_STATUS_E_NOMEM;
331*5113495bSYour Name 	}
332*5113495bSYour Name 	for (idx = 0; idx < pa->lut_num; idx++)
333*5113495bSYour Name 		pa->lut[idx] = (struct look_up_table *)qdf_mem_malloc(
334*5113495bSYour Name 			sizeof(struct look_up_table));
335*5113495bSYour Name 
336*5113495bSYour Name 	/* Allocate AoA related variables here based on FW capability */
337*5113495bSYour Name 	status = wlan_cfr_get_aoa_caps(pa);
338*5113495bSYour Name 	if (QDF_IS_STATUS_ERROR(status)) {
339*5113495bSYour Name 		cfr_err("Failed to get aoa caps");
340*5113495bSYour Name 		for (idx = 0; idx < pa->lut_num; idx++)
341*5113495bSYour Name 			qdf_mem_free(pa->lut[idx]);
342*5113495bSYour Name 		qdf_mem_free(pa);
343*5113495bSYour Name 		return status;
344*5113495bSYour Name 	}
345*5113495bSYour Name 
346*5113495bSYour Name 	cfr_wakelock_init(pa);
347*5113495bSYour Name 	wlan_objmgr_pdev_component_obj_attach(pdev, WLAN_UMAC_COMP_CFR,
348*5113495bSYour Name 					      (void *)pa, QDF_STATUS_SUCCESS);
349*5113495bSYour Name 
350*5113495bSYour Name 	return QDF_STATUS_SUCCESS;
351*5113495bSYour Name }
352*5113495bSYour Name 
353*5113495bSYour Name #ifdef WLAN_RCC_ENHANCED_AOA_SUPPORT
354*5113495bSYour Name static inline
wlan_cfr_cleanup_enhanced_aoa(struct pdev_cfr * pa)355*5113495bSYour Name void wlan_cfr_cleanup_enhanced_aoa(struct pdev_cfr *pa)
356*5113495bSYour Name {
357*5113495bSYour Name 	/**
358*5113495bSYour Name 	 * Free enahced AoA related allocations here.
359*5113495bSYour Name 	 * Caller of this API should ensure pa is not NULL
360*5113495bSYour Name 	 */
361*5113495bSYour Name 	if (pa->gain_stop_index_array)
362*5113495bSYour Name 		qdf_mem_free(pa->gain_stop_index_array);
363*5113495bSYour Name 
364*5113495bSYour Name 	if (pa->enh_phase_delta_array)
365*5113495bSYour Name 		qdf_mem_free(pa->enh_phase_delta_array);
366*5113495bSYour Name }
367*5113495bSYour Name #else
368*5113495bSYour Name static inline
wlan_cfr_cleanup_enhanced_aoa(struct pdev_cfr * pa)369*5113495bSYour Name void wlan_cfr_cleanup_enhanced_aoa(struct pdev_cfr *pa)
370*5113495bSYour Name {
371*5113495bSYour Name }
372*5113495bSYour Name #endif /* WLAN_RCC_ENHANCED_AOA_SUPPORT */
373*5113495bSYour Name 
374*5113495bSYour Name QDF_STATUS
wlan_cfr_pdev_obj_destroy_handler(struct wlan_objmgr_pdev * pdev,void * arg)375*5113495bSYour Name wlan_cfr_pdev_obj_destroy_handler(struct wlan_objmgr_pdev *pdev, void *arg)
376*5113495bSYour Name {
377*5113495bSYour Name 	struct pdev_cfr *pa = NULL;
378*5113495bSYour Name 	uint32_t idx;
379*5113495bSYour Name 
380*5113495bSYour Name 	if (!pdev) {
381*5113495bSYour Name 		cfr_err("PDEV is NULL\n");
382*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
383*5113495bSYour Name 	}
384*5113495bSYour Name 
385*5113495bSYour Name 	if (wlan_cfr_is_feature_disabled(pdev)) {
386*5113495bSYour Name 		cfr_info("cfr is disabled");
387*5113495bSYour Name 		return QDF_STATUS_E_NOSUPPORT;
388*5113495bSYour Name 	}
389*5113495bSYour Name 
390*5113495bSYour Name 	pa = wlan_objmgr_pdev_get_comp_private_obj(pdev, WLAN_UMAC_COMP_CFR);
391*5113495bSYour Name 	if (pa) {
392*5113495bSYour Name 		cfr_wakelock_deinit(pa);
393*5113495bSYour Name 		wlan_objmgr_pdev_component_obj_detach(pdev, WLAN_UMAC_COMP_CFR,
394*5113495bSYour Name 						      (void *)pa);
395*5113495bSYour Name 		if (pa->lut) {
396*5113495bSYour Name 			for (idx = 0; idx < pa->lut_num; idx++)
397*5113495bSYour Name 				qdf_mem_free(pa->lut[idx]);
398*5113495bSYour Name 			qdf_mem_free(pa->lut);
399*5113495bSYour Name 		}
400*5113495bSYour Name 
401*5113495bSYour Name 		wlan_cfr_cleanup_enhanced_aoa(pa);
402*5113495bSYour Name 		qdf_mem_free(pa);
403*5113495bSYour Name 	}
404*5113495bSYour Name 
405*5113495bSYour Name 	return QDF_STATUS_SUCCESS;
406*5113495bSYour Name }
407*5113495bSYour Name 
408*5113495bSYour Name QDF_STATUS
wlan_cfr_peer_obj_create_handler(struct wlan_objmgr_peer * peer,void * arg)409*5113495bSYour Name wlan_cfr_peer_obj_create_handler(struct wlan_objmgr_peer *peer, void *arg)
410*5113495bSYour Name {
411*5113495bSYour Name 	struct peer_cfr *pe = NULL;
412*5113495bSYour Name 	struct wlan_objmgr_vdev *vdev;
413*5113495bSYour Name 	struct wlan_objmgr_pdev *pdev = NULL;
414*5113495bSYour Name 
415*5113495bSYour Name 	if (!peer) {
416*5113495bSYour Name 		cfr_err("PEER is NULL\n");
417*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
418*5113495bSYour Name 	}
419*5113495bSYour Name 
420*5113495bSYour Name 	vdev = wlan_peer_get_vdev(peer);
421*5113495bSYour Name 	if (vdev)
422*5113495bSYour Name 		pdev = wlan_vdev_get_pdev(vdev);
423*5113495bSYour Name 
424*5113495bSYour Name 	if (!pdev) {
425*5113495bSYour Name 		cfr_err("PDEV is NULL\n");
426*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
427*5113495bSYour Name 	}
428*5113495bSYour Name 
429*5113495bSYour Name 	if (wlan_cfr_is_feature_disabled(pdev)) {
430*5113495bSYour Name 		cfr_debug("cfr is disabled");
431*5113495bSYour Name 		return QDF_STATUS_E_NOSUPPORT;
432*5113495bSYour Name 	}
433*5113495bSYour Name 
434*5113495bSYour Name 	pe = (struct peer_cfr *)qdf_mem_malloc(sizeof(struct peer_cfr));
435*5113495bSYour Name 	if (!pe) {
436*5113495bSYour Name 		cfr_err("Failed to allocate peer_cfr object\n");
437*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
438*5113495bSYour Name 	}
439*5113495bSYour Name 
440*5113495bSYour Name 	pe->peer_obj = peer;
441*5113495bSYour Name 
442*5113495bSYour Name 	/* Remaining will be populated when we give CFR capture command */
443*5113495bSYour Name 	wlan_objmgr_peer_component_obj_attach(peer, WLAN_UMAC_COMP_CFR,
444*5113495bSYour Name 					      (void *)pe, QDF_STATUS_SUCCESS);
445*5113495bSYour Name 	return QDF_STATUS_SUCCESS;
446*5113495bSYour Name }
447*5113495bSYour Name 
448*5113495bSYour Name QDF_STATUS
wlan_cfr_peer_obj_destroy_handler(struct wlan_objmgr_peer * peer,void * arg)449*5113495bSYour Name wlan_cfr_peer_obj_destroy_handler(struct wlan_objmgr_peer *peer, void *arg)
450*5113495bSYour Name {
451*5113495bSYour Name 	struct peer_cfr *pe = NULL;
452*5113495bSYour Name 	struct wlan_objmgr_vdev *vdev;
453*5113495bSYour Name 	struct wlan_objmgr_pdev *pdev = NULL;
454*5113495bSYour Name 	struct pdev_cfr *pa = NULL;
455*5113495bSYour Name 
456*5113495bSYour Name 	if (!peer) {
457*5113495bSYour Name 		cfr_err("PEER is NULL\n");
458*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
459*5113495bSYour Name 	}
460*5113495bSYour Name 
461*5113495bSYour Name 	vdev = wlan_peer_get_vdev(peer);
462*5113495bSYour Name 	if (vdev)
463*5113495bSYour Name 		pdev = wlan_vdev_get_pdev(vdev);
464*5113495bSYour Name 
465*5113495bSYour Name 	if (wlan_cfr_is_feature_disabled(pdev)) {
466*5113495bSYour Name 		cfr_info("cfr is disabled");
467*5113495bSYour Name 		return QDF_STATUS_E_NOSUPPORT;
468*5113495bSYour Name 	}
469*5113495bSYour Name 
470*5113495bSYour Name 	if (pdev)
471*5113495bSYour Name 		pa = wlan_objmgr_pdev_get_comp_private_obj(pdev,
472*5113495bSYour Name 							   WLAN_UMAC_COMP_CFR);
473*5113495bSYour Name 
474*5113495bSYour Name 	pe = wlan_objmgr_peer_get_comp_private_obj(peer, WLAN_UMAC_COMP_CFR);
475*5113495bSYour Name 
476*5113495bSYour Name 	if (pa && pe) {
477*5113495bSYour Name 		if (pe->period && pe->request)
478*5113495bSYour Name 			pa->cfr_current_sta_count--;
479*5113495bSYour Name 	}
480*5113495bSYour Name 
481*5113495bSYour Name 	if (pe) {
482*5113495bSYour Name 		wlan_objmgr_peer_component_obj_detach(peer, WLAN_UMAC_COMP_CFR,
483*5113495bSYour Name 						      (void *)pe);
484*5113495bSYour Name 		qdf_mem_free(pe);
485*5113495bSYour Name 	}
486*5113495bSYour Name 
487*5113495bSYour Name 	return QDF_STATUS_SUCCESS;
488*5113495bSYour Name }
489*5113495bSYour Name 
490*5113495bSYour Name #ifdef CFR_USE_FIXED_FOLDER
cfr_get_dev_name(struct wlan_objmgr_pdev * pdev)491*5113495bSYour Name static char *cfr_get_dev_name(struct wlan_objmgr_pdev *pdev)
492*5113495bSYour Name {
493*5113495bSYour Name 	char *default_name = "wlan";
494*5113495bSYour Name 
495*5113495bSYour Name 	return default_name;
496*5113495bSYour Name }
497*5113495bSYour Name #else
498*5113495bSYour Name /**
499*5113495bSYour Name  * cfr_get_dev_name() - Get net device name from pdev
500*5113495bSYour Name  *  @pdev: objmgr pdev
501*5113495bSYour Name  *
502*5113495bSYour Name  *  Return: netdev name
503*5113495bSYour Name  */
cfr_get_dev_name(struct wlan_objmgr_pdev * pdev)504*5113495bSYour Name static char *cfr_get_dev_name(struct wlan_objmgr_pdev *pdev)
505*5113495bSYour Name {
506*5113495bSYour Name 	struct pdev_osif_priv *pdev_ospriv;
507*5113495bSYour Name 	struct qdf_net_if *nif;
508*5113495bSYour Name 
509*5113495bSYour Name 	pdev_ospriv = wlan_pdev_get_ospriv(pdev);
510*5113495bSYour Name 	if (!pdev_ospriv) {
511*5113495bSYour Name 		cfr_err("pdev_ospriv is NULL\n");
512*5113495bSYour Name 		return NULL;
513*5113495bSYour Name 	}
514*5113495bSYour Name 
515*5113495bSYour Name 	nif = pdev_ospriv->nif;
516*5113495bSYour Name 	if (!nif) {
517*5113495bSYour Name 		cfr_err("pdev nif is NULL\n");
518*5113495bSYour Name 		return NULL;
519*5113495bSYour Name 	}
520*5113495bSYour Name 
521*5113495bSYour Name 	return  qdf_net_if_get_devname(nif);
522*5113495bSYour Name }
523*5113495bSYour Name #endif
524*5113495bSYour Name 
cfr_streamfs_init(struct wlan_objmgr_pdev * pdev)525*5113495bSYour Name QDF_STATUS cfr_streamfs_init(struct wlan_objmgr_pdev *pdev)
526*5113495bSYour Name {
527*5113495bSYour Name 	struct pdev_cfr *pa = NULL;
528*5113495bSYour Name 	char *devname;
529*5113495bSYour Name 	char folder[32];
530*5113495bSYour Name 
531*5113495bSYour Name 	if (!pdev) {
532*5113495bSYour Name 		cfr_err("PDEV is NULL\n");
533*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
534*5113495bSYour Name 	}
535*5113495bSYour Name 
536*5113495bSYour Name 	if (wlan_cfr_is_feature_disabled(pdev)) {
537*5113495bSYour Name 		cfr_info("cfr is disabled");
538*5113495bSYour Name 		return QDF_STATUS_COMP_DISABLED;
539*5113495bSYour Name 	}
540*5113495bSYour Name 
541*5113495bSYour Name 	pa = wlan_objmgr_pdev_get_comp_private_obj(pdev, WLAN_UMAC_COMP_CFR);
542*5113495bSYour Name 
543*5113495bSYour Name 	if (pa == NULL) {
544*5113495bSYour Name 		cfr_err("pdev_cfr is NULL\n");
545*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
546*5113495bSYour Name 	}
547*5113495bSYour Name 
548*5113495bSYour Name 	if (!pa->is_cfr_capable) {
549*5113495bSYour Name 		cfr_err("CFR IS NOT SUPPORTED\n");
550*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
551*5113495bSYour Name 	}
552*5113495bSYour Name 
553*5113495bSYour Name 	devname = cfr_get_dev_name(pdev);
554*5113495bSYour Name 	if (!devname) {
555*5113495bSYour Name 		cfr_err("devname is NULL\n");
556*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
557*5113495bSYour Name 	}
558*5113495bSYour Name 
559*5113495bSYour Name 	snprintf(folder, sizeof(folder), "cfr%s", devname);
560*5113495bSYour Name 
561*5113495bSYour Name 	pa->dir_ptr = qdf_streamfs_create_dir((const char *)folder, NULL);
562*5113495bSYour Name 
563*5113495bSYour Name 	if (!pa->dir_ptr) {
564*5113495bSYour Name 		cfr_err("Directory create failed");
565*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
566*5113495bSYour Name 	}
567*5113495bSYour Name 
568*5113495bSYour Name 	pa->chan_ptr = qdf_streamfs_open("cfr_dump", pa->dir_ptr,
569*5113495bSYour Name 					 pa->subbuf_size,
570*5113495bSYour Name 					 pa->num_subbufs, NULL);
571*5113495bSYour Name 
572*5113495bSYour Name 	if (!pa->chan_ptr) {
573*5113495bSYour Name 		cfr_err("Chan create failed");
574*5113495bSYour Name 		qdf_streamfs_remove_dir_recursive(pa->dir_ptr);
575*5113495bSYour Name 		pa->dir_ptr = NULL;
576*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
577*5113495bSYour Name 	}
578*5113495bSYour Name 
579*5113495bSYour Name 	return QDF_STATUS_SUCCESS;
580*5113495bSYour Name }
581*5113495bSYour Name 
cfr_streamfs_remove(struct wlan_objmgr_pdev * pdev)582*5113495bSYour Name QDF_STATUS cfr_streamfs_remove(struct wlan_objmgr_pdev *pdev)
583*5113495bSYour Name {
584*5113495bSYour Name 	struct pdev_cfr *pa = NULL;
585*5113495bSYour Name 
586*5113495bSYour Name 	if (wlan_cfr_is_feature_disabled(pdev)) {
587*5113495bSYour Name 		cfr_info("cfr is disabled");
588*5113495bSYour Name 		return QDF_STATUS_COMP_DISABLED;
589*5113495bSYour Name 	}
590*5113495bSYour Name 
591*5113495bSYour Name 	pa = wlan_objmgr_pdev_get_comp_private_obj(pdev, WLAN_UMAC_COMP_CFR);
592*5113495bSYour Name 	if (pa) {
593*5113495bSYour Name 		if (pa->chan_ptr) {
594*5113495bSYour Name 			qdf_streamfs_close(pa->chan_ptr);
595*5113495bSYour Name 			pa->chan_ptr = NULL;
596*5113495bSYour Name 		}
597*5113495bSYour Name 
598*5113495bSYour Name 		if (pa->dir_ptr) {
599*5113495bSYour Name 			qdf_streamfs_remove_dir_recursive(pa->dir_ptr);
600*5113495bSYour Name 			pa->dir_ptr = NULL;
601*5113495bSYour Name 		}
602*5113495bSYour Name 
603*5113495bSYour Name 	} else
604*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
605*5113495bSYour Name 
606*5113495bSYour Name 	return QDF_STATUS_SUCCESS;
607*5113495bSYour Name }
608*5113495bSYour Name 
cfr_streamfs_write(struct pdev_cfr * pa,const void * write_data,size_t write_len)609*5113495bSYour Name QDF_STATUS cfr_streamfs_write(struct pdev_cfr *pa, const void *write_data,
610*5113495bSYour Name 			      size_t write_len)
611*5113495bSYour Name {
612*5113495bSYour Name 	if (pa->chan_ptr) {
613*5113495bSYour Name 	/* write to channel buffer */
614*5113495bSYour Name 		qdf_streamfs_write(pa->chan_ptr, (const void *)write_data,
615*5113495bSYour Name 				   write_len);
616*5113495bSYour Name 	} else
617*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
618*5113495bSYour Name 
619*5113495bSYour Name 	return QDF_STATUS_SUCCESS;
620*5113495bSYour Name }
621*5113495bSYour Name 
cfr_streamfs_flush(struct pdev_cfr * pa)622*5113495bSYour Name QDF_STATUS cfr_streamfs_flush(struct pdev_cfr *pa)
623*5113495bSYour Name {
624*5113495bSYour Name 	if (pa->chan_ptr) {
625*5113495bSYour Name 
626*5113495bSYour Name 	/* Flush the data write to channel buffer */
627*5113495bSYour Name 		qdf_streamfs_flush(pa->chan_ptr);
628*5113495bSYour Name 	} else
629*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
630*5113495bSYour Name 
631*5113495bSYour Name 	return QDF_STATUS_SUCCESS;
632*5113495bSYour Name }
633*5113495bSYour Name 
cfr_stop_indication(struct wlan_objmgr_vdev * vdev)634*5113495bSYour Name QDF_STATUS cfr_stop_indication(struct wlan_objmgr_vdev *vdev)
635*5113495bSYour Name {
636*5113495bSYour Name 	struct pdev_cfr *pa;
637*5113495bSYour Name 	uint32_t status;
638*5113495bSYour Name 	struct wlan_objmgr_pdev *pdev;
639*5113495bSYour Name 
640*5113495bSYour Name 	pdev = wlan_vdev_get_pdev(vdev);
641*5113495bSYour Name 	pa = wlan_objmgr_pdev_get_comp_private_obj(pdev, WLAN_UMAC_COMP_CFR);
642*5113495bSYour Name 	if (!pa) {
643*5113495bSYour Name 		cfr_err("pdev_cfr is NULL\n");
644*5113495bSYour Name 		return QDF_STATUS_E_INVAL;
645*5113495bSYour Name 	}
646*5113495bSYour Name 
647*5113495bSYour Name 	/* Don't write stop string if there is valid cfr_nl_cb. Since
648*5113495bSYour Name 	 * userspace needn't stop event string
649*5113495bSYour Name 	 */
650*5113495bSYour Name 	if (pa->nl_cb.cfr_nl_cb)
651*5113495bSYour Name 		return QDF_STATUS_SUCCESS;
652*5113495bSYour Name 
653*5113495bSYour Name 	status = cfr_streamfs_write(pa, (const void *)CFR_STOP_STR,
654*5113495bSYour Name 				    sizeof(CFR_STOP_STR));
655*5113495bSYour Name 
656*5113495bSYour Name 	status = cfr_streamfs_flush(pa);
657*5113495bSYour Name 	cfr_debug("stop indication done");
658*5113495bSYour Name 
659*5113495bSYour Name 	return status;
660*5113495bSYour Name }
661*5113495bSYour Name 
662*5113495bSYour Name #ifdef WLAN_CFR_PM
cfr_prevent_suspend(struct pdev_cfr * pcfr)663*5113495bSYour Name QDF_STATUS cfr_prevent_suspend(struct pdev_cfr *pcfr)
664*5113495bSYour Name {
665*5113495bSYour Name 	if (!pcfr) {
666*5113495bSYour Name 		cfr_debug("NULL pcfr");
667*5113495bSYour Name 		return QDF_STATUS_E_INVAL;
668*5113495bSYour Name 	}
669*5113495bSYour Name 
670*5113495bSYour Name 	if (pcfr->is_prevent_suspend) {
671*5113495bSYour Name 		cfr_debug("acquired wake lock");
672*5113495bSYour Name 		return QDF_STATUS_E_AGAIN;
673*5113495bSYour Name 	}
674*5113495bSYour Name 	qdf_wake_lock_acquire(&pcfr->wake_lock,
675*5113495bSYour Name 			      WIFI_POWER_EVENT_WAKELOCK_CFR);
676*5113495bSYour Name 	qdf_runtime_pm_prevent_suspend(&pcfr->runtime_lock);
677*5113495bSYour Name 	pcfr->is_prevent_suspend = true;
678*5113495bSYour Name 
679*5113495bSYour Name 	return QDF_STATUS_SUCCESS;
680*5113495bSYour Name }
681*5113495bSYour Name 
cfr_allow_suspend(struct pdev_cfr * pcfr)682*5113495bSYour Name QDF_STATUS cfr_allow_suspend(struct pdev_cfr *pcfr)
683*5113495bSYour Name {
684*5113495bSYour Name 	if (!pcfr) {
685*5113495bSYour Name 		cfr_debug("NULL pcfr");
686*5113495bSYour Name 		return QDF_STATUS_E_INVAL;
687*5113495bSYour Name 	}
688*5113495bSYour Name 
689*5113495bSYour Name 	if (!pcfr->is_prevent_suspend) {
690*5113495bSYour Name 		cfr_debug("wake lock not acquired");
691*5113495bSYour Name 		return QDF_STATUS_E_INVAL;
692*5113495bSYour Name 	}
693*5113495bSYour Name 	qdf_wake_lock_release(&pcfr->wake_lock,
694*5113495bSYour Name 			      WIFI_POWER_EVENT_WAKELOCK_CFR);
695*5113495bSYour Name 	qdf_runtime_pm_allow_suspend(&pcfr->runtime_lock);
696*5113495bSYour Name 	pcfr->is_prevent_suspend = false;
697*5113495bSYour Name 
698*5113495bSYour Name 	return QDF_STATUS_SUCCESS;
699*5113495bSYour Name }
700*5113495bSYour Name #endif
701