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