xref: /wlan-driver/qca-wifi-host-cmn/spectral/core/spectral_common.c (revision 5113495b16420b49004c444715d2daae2066e7dc)
1*5113495bSYour Name /*
2*5113495bSYour Name  * Copyright (c) 2011,2017-2021 The Linux Foundation. All rights reserved.
3*5113495bSYour Name  * Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved.
4*5113495bSYour Name  *
5*5113495bSYour Name  *
6*5113495bSYour Name  * Permission to use, copy, modify, and/or distribute this software for
7*5113495bSYour Name  * any purpose with or without fee is hereby granted, provided that the
8*5113495bSYour Name  * above copyright notice and this permission notice appear in all
9*5113495bSYour Name  * copies.
10*5113495bSYour Name  *
11*5113495bSYour Name  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
12*5113495bSYour Name  * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
13*5113495bSYour Name  * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
14*5113495bSYour Name  * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
15*5113495bSYour Name  * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
16*5113495bSYour Name  * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
17*5113495bSYour Name  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
18*5113495bSYour Name  * PERFORMANCE OF THIS SOFTWARE.
19*5113495bSYour Name  */
20*5113495bSYour Name 
21*5113495bSYour Name #include "spectral_cmn_api_i.h"
22*5113495bSYour Name #include "spectral_ol_api_i.h"
23*5113495bSYour Name #include <qdf_mem.h>
24*5113495bSYour Name #include <qdf_types.h>
25*5113495bSYour Name #include <wlan_spectral_public_structs.h>
26*5113495bSYour Name #include <wlan_cfg80211_spectral.h>
27*5113495bSYour Name #include <cfg_ucfg_api.h>
28*5113495bSYour Name 
29*5113495bSYour Name /**
30*5113495bSYour Name  * spectral_get_vdev() - Get pointer to vdev to be used for Spectral
31*5113495bSYour Name  * operations
32*5113495bSYour Name  * @pdev: Pointer to pdev
33*5113495bSYour Name  * @vdev_id: vdev_id
34*5113495bSYour Name  *
35*5113495bSYour Name  * Spectral operates on pdev. However, in order to retrieve some WLAN
36*5113495bSYour Name  * properties, a vdev is required. To facilitate this, the function returns the
37*5113495bSYour Name  * first vdev in our pdev. The caller should release the reference to the vdev
38*5113495bSYour Name  * once it is done using it. Additionally, the caller should ensure it has a
39*5113495bSYour Name  * reference to the pdev at the time of calling this function, and should
40*5113495bSYour Name  * release the pdev reference either after this function returns or at a later
41*5113495bSYour Name  * time when the caller is done using pdev.
42*5113495bSYour Name  * TODO:
43*5113495bSYour Name  *  - If the framework later provides an API to obtain the first active
44*5113495bSYour Name  *    vdev, then it would be preferable to use this API.
45*5113495bSYour Name  *  - Use a common get_vdev() handler for core and target_if using Rx ops. This
46*5113495bSYour Name  *    is deferred till details emerge on framework providing API to get first
47*5113495bSYour Name  *    active vdev.
48*5113495bSYour Name  *
49*5113495bSYour Name  * Return: Pointer to vdev on success, NULL on failure
50*5113495bSYour Name  */
51*5113495bSYour Name static struct wlan_objmgr_vdev*
spectral_get_vdev(struct wlan_objmgr_pdev * pdev,uint8_t vdev_id)52*5113495bSYour Name spectral_get_vdev(struct wlan_objmgr_pdev *pdev, uint8_t vdev_id)
53*5113495bSYour Name {
54*5113495bSYour Name 	struct wlan_objmgr_vdev *vdev = NULL;
55*5113495bSYour Name 
56*5113495bSYour Name 	if (!pdev) {
57*5113495bSYour Name 		spectral_err("pdev is null");
58*5113495bSYour Name 		return NULL;
59*5113495bSYour Name 	}
60*5113495bSYour Name 
61*5113495bSYour Name 	if (vdev_id == WLAN_INVALID_VDEV_ID)
62*5113495bSYour Name 		vdev = wlan_objmgr_pdev_get_first_vdev(pdev, WLAN_SPECTRAL_ID);
63*5113495bSYour Name 	else
64*5113495bSYour Name 		vdev = wlan_objmgr_get_vdev_by_id_from_pdev(pdev, vdev_id,
65*5113495bSYour Name 							    WLAN_SPECTRAL_ID);
66*5113495bSYour Name 	if (!vdev) {
67*5113495bSYour Name 		spectral_warn("Unable to get first vdev of pdev");
68*5113495bSYour Name 		return NULL;
69*5113495bSYour Name 	}
70*5113495bSYour Name 
71*5113495bSYour Name 	return vdev;
72*5113495bSYour Name }
73*5113495bSYour Name 
74*5113495bSYour Name #ifdef SPECTRAL_MODULIZED_ENABLE
75*5113495bSYour Name /**
76*5113495bSYour Name  * spectral_register_cfg80211_handlers() - Register spectral cfg80211 handlers
77*5113495bSYour Name  * @pdev: Pointer to pdev
78*5113495bSYour Name  *
79*5113495bSYour Name  * Register spectral cfg80211 handlers
80*5113495bSYour Name  * Handlers can be different depending on whether spectral modulized or not
81*5113495bSYour Name  *
82*5113495bSYour Name  * Return: None
83*5113495bSYour Name  */
84*5113495bSYour Name static void
spectral_register_cfg80211_handlers(struct wlan_objmgr_pdev * pdev)85*5113495bSYour Name spectral_register_cfg80211_handlers(struct wlan_objmgr_pdev *pdev)
86*5113495bSYour Name {
87*5113495bSYour Name 	struct spectral_cfg80211_vendor_cmd_handlers handlers = {0};
88*5113495bSYour Name 
89*5113495bSYour Name 	handlers.wlan_cfg80211_spectral_scan_start =
90*5113495bSYour Name 			wlan_cfg80211_spectral_scan_config_and_start;
91*5113495bSYour Name 	handlers.wlan_cfg80211_spectral_scan_stop =
92*5113495bSYour Name 			wlan_cfg80211_spectral_scan_stop;
93*5113495bSYour Name 	handlers.wlan_cfg80211_spectral_scan_get_config =
94*5113495bSYour Name 			wlan_cfg80211_spectral_scan_get_config;
95*5113495bSYour Name 	handlers.wlan_cfg80211_spectral_scan_get_diag_stats =
96*5113495bSYour Name 			wlan_cfg80211_spectral_scan_get_diag_stats;
97*5113495bSYour Name 	handlers.wlan_cfg80211_spectral_scan_get_cap =
98*5113495bSYour Name 			wlan_cfg80211_spectral_scan_get_cap;
99*5113495bSYour Name 	handlers.wlan_cfg80211_spectral_scan_get_status =
100*5113495bSYour Name 			wlan_cfg80211_spectral_scan_get_status;
101*5113495bSYour Name 
102*5113495bSYour Name 	wlan_cfg80211_register_spectral_cmd_handler(pdev, &handlers);
103*5113495bSYour Name }
104*5113495bSYour Name #else
105*5113495bSYour Name static void
spectral_register_cfg80211_handlers(struct wlan_objmgr_pdev * pdev)106*5113495bSYour Name spectral_register_cfg80211_handlers(struct wlan_objmgr_pdev *pdev)
107*5113495bSYour Name {
108*5113495bSYour Name }
109*5113495bSYour Name #endif
110*5113495bSYour Name 
111*5113495bSYour Name QDF_STATUS
spectral_control_cmn(struct wlan_objmgr_pdev * pdev,struct spectral_cp_request * sscan_req)112*5113495bSYour Name spectral_control_cmn(struct wlan_objmgr_pdev *pdev,
113*5113495bSYour Name 		     struct spectral_cp_request *sscan_req)
114*5113495bSYour Name {
115*5113495bSYour Name 	QDF_STATUS status = QDF_STATUS_E_FAILURE;
116*5113495bSYour Name 	int temp_debug;
117*5113495bSYour Name 	struct spectral_config sp_out;
118*5113495bSYour Name 	struct spectral_config *sp_in;
119*5113495bSYour Name 	struct spectral_config *spectralparams;
120*5113495bSYour Name 	struct spectral_context *sc;
121*5113495bSYour Name 	struct wlan_objmgr_vdev *vdev = NULL;
122*5113495bSYour Name 	uint8_t vdev_rxchainmask = 0;
123*5113495bSYour Name 	enum spectral_scan_mode smode = sscan_req->ss_mode;
124*5113495bSYour Name 	enum spectral_cp_error_code *err;
125*5113495bSYour Name 	QDF_STATUS ret;
126*5113495bSYour Name 	struct spectral_cp_param param;
127*5113495bSYour Name 
128*5113495bSYour Name 	if (!pdev) {
129*5113495bSYour Name 		spectral_err("PDEV is NULL!");
130*5113495bSYour Name 		goto bad;
131*5113495bSYour Name 	}
132*5113495bSYour Name 	sc = spectral_get_spectral_ctx_from_pdev(pdev);
133*5113495bSYour Name 	if (!sc) {
134*5113495bSYour Name 		spectral_err("Spectral context is NULL!");
135*5113495bSYour Name 		goto bad;
136*5113495bSYour Name 	}
137*5113495bSYour Name 
138*5113495bSYour Name 	switch (sscan_req->req_id) {
139*5113495bSYour Name 	case SPECTRAL_SET_CONFIG:
140*5113495bSYour Name 		err =  &sscan_req->config_req.sscan_err_code;
141*5113495bSYour Name 		sp_in = &sscan_req->config_req.sscan_config;
142*5113495bSYour Name 		if (sp_in->ss_count != SPECTRAL_PHYERR_PARAM_NOVAL) {
143*5113495bSYour Name 			param.id = SPECTRAL_PARAM_SCAN_COUNT;
144*5113495bSYour Name 			param.value = sp_in->ss_count;
145*5113495bSYour Name 			ret = sc->sptrlc_set_spectral_config
146*5113495bSYour Name 						(pdev, &param, smode, err);
147*5113495bSYour Name 			if (QDF_IS_STATUS_ERROR(ret))
148*5113495bSYour Name 				goto bad;
149*5113495bSYour Name 		}
150*5113495bSYour Name 
151*5113495bSYour Name 		if (sp_in->ss_fft_period != SPECTRAL_PHYERR_PARAM_NOVAL) {
152*5113495bSYour Name 			param.id = SPECTRAL_PARAM_FFT_PERIOD;
153*5113495bSYour Name 			param.value = sp_in->ss_fft_period;
154*5113495bSYour Name 			ret = sc->sptrlc_set_spectral_config
155*5113495bSYour Name 						(pdev, &param, smode, err);
156*5113495bSYour Name 			if (QDF_IS_STATUS_ERROR(ret))
157*5113495bSYour Name 				goto bad;
158*5113495bSYour Name 		}
159*5113495bSYour Name 
160*5113495bSYour Name 		if (sp_in->ss_period != SPECTRAL_PHYERR_PARAM_NOVAL) {
161*5113495bSYour Name 			param.id = SPECTRAL_PARAM_SCAN_PERIOD;
162*5113495bSYour Name 			param.value = sp_in->ss_period;
163*5113495bSYour Name 			ret = sc->sptrlc_set_spectral_config
164*5113495bSYour Name 						(pdev, &param, smode, err);
165*5113495bSYour Name 			if (QDF_IS_STATUS_ERROR(ret))
166*5113495bSYour Name 				goto bad;
167*5113495bSYour Name 		}
168*5113495bSYour Name 
169*5113495bSYour Name 		if (sp_in->ss_recapture != SPECTRAL_PHYERR_PARAM_NOVAL) {
170*5113495bSYour Name 			param.id = SPECTRAL_PARAM_FFT_RECAPTURE;
171*5113495bSYour Name 			param.value = sp_in->ss_recapture;
172*5113495bSYour Name 			ret = sc->sptrlc_set_spectral_config
173*5113495bSYour Name 						(pdev, &param, smode, err);
174*5113495bSYour Name 			if (QDF_IS_STATUS_ERROR(ret))
175*5113495bSYour Name 				goto bad;
176*5113495bSYour Name 		}
177*5113495bSYour Name 
178*5113495bSYour Name 		if (sp_in->ss_short_report != SPECTRAL_PHYERR_PARAM_NOVAL) {
179*5113495bSYour Name 			param.id = SPECTRAL_PARAM_SHORT_REPORT;
180*5113495bSYour Name 			param.value = (uint32_t)sp_in->ss_short_report ? 1 : 0;
181*5113495bSYour Name 			ret = sc->sptrlc_set_spectral_config
182*5113495bSYour Name 						(pdev, &param, smode, err);
183*5113495bSYour Name 			if (QDF_IS_STATUS_ERROR(ret))
184*5113495bSYour Name 				goto bad;
185*5113495bSYour Name 		}
186*5113495bSYour Name 
187*5113495bSYour Name 		if (sp_in->ss_spectral_pri != SPECTRAL_PHYERR_PARAM_NOVAL) {
188*5113495bSYour Name 			param.id = SPECTRAL_PARAM_SPECT_PRI;
189*5113495bSYour Name 			param.value = (uint32_t)sp_in->ss_spectral_pri;
190*5113495bSYour Name 			ret = sc->sptrlc_set_spectral_config
191*5113495bSYour Name 						(pdev, &param, smode, err);
192*5113495bSYour Name 			if (QDF_IS_STATUS_ERROR(ret))
193*5113495bSYour Name 				goto bad;
194*5113495bSYour Name 		}
195*5113495bSYour Name 
196*5113495bSYour Name 		if (sp_in->ss_fft_size != SPECTRAL_PHYERR_PARAM_NOVAL) {
197*5113495bSYour Name 			param.id = SPECTRAL_PARAM_FFT_SIZE;
198*5113495bSYour Name 			param.value = sp_in->ss_fft_size;
199*5113495bSYour Name 			ret = sc->sptrlc_set_spectral_config
200*5113495bSYour Name 						(pdev, &param, smode, err);
201*5113495bSYour Name 			if (QDF_IS_STATUS_ERROR(ret))
202*5113495bSYour Name 				goto bad;
203*5113495bSYour Name 		}
204*5113495bSYour Name 
205*5113495bSYour Name 		if (sp_in->ss_gc_ena != SPECTRAL_PHYERR_PARAM_NOVAL) {
206*5113495bSYour Name 			param.id = SPECTRAL_PARAM_GC_ENA;
207*5113495bSYour Name 			param.value = sp_in->ss_gc_ena;
208*5113495bSYour Name 			ret = sc->sptrlc_set_spectral_config
209*5113495bSYour Name 						(pdev, &param, smode, err);
210*5113495bSYour Name 			if (QDF_IS_STATUS_ERROR(ret))
211*5113495bSYour Name 				goto bad;
212*5113495bSYour Name 		}
213*5113495bSYour Name 
214*5113495bSYour Name 		if (sp_in->ss_restart_ena != SPECTRAL_PHYERR_PARAM_NOVAL) {
215*5113495bSYour Name 			param.id = SPECTRAL_PARAM_RESTART_ENA;
216*5113495bSYour Name 			param.value = sp_in->ss_restart_ena;
217*5113495bSYour Name 			ret = sc->sptrlc_set_spectral_config
218*5113495bSYour Name 						(pdev, &param, smode, err);
219*5113495bSYour Name 			if (QDF_IS_STATUS_ERROR(ret))
220*5113495bSYour Name 				goto bad;
221*5113495bSYour Name 		}
222*5113495bSYour Name 
223*5113495bSYour Name 		if (sp_in->ss_noise_floor_ref != SPECTRAL_PHYERR_PARAM_NOVAL) {
224*5113495bSYour Name 			param.id = SPECTRAL_PARAM_NOISE_FLOOR_REF;
225*5113495bSYour Name 			param.value = sp_in->ss_noise_floor_ref;
226*5113495bSYour Name 			ret = sc->sptrlc_set_spectral_config
227*5113495bSYour Name 						(pdev, &param, smode, err);
228*5113495bSYour Name 			if (QDF_IS_STATUS_ERROR(ret))
229*5113495bSYour Name 				goto bad;
230*5113495bSYour Name 		}
231*5113495bSYour Name 
232*5113495bSYour Name 		if (sp_in->ss_init_delay != SPECTRAL_PHYERR_PARAM_NOVAL) {
233*5113495bSYour Name 			param.id = SPECTRAL_PARAM_INIT_DELAY;
234*5113495bSYour Name 			param.value = sp_in->ss_init_delay;
235*5113495bSYour Name 			ret = sc->sptrlc_set_spectral_config
236*5113495bSYour Name 						(pdev, &param, smode, err);
237*5113495bSYour Name 			if (QDF_IS_STATUS_ERROR(ret))
238*5113495bSYour Name 				goto bad;
239*5113495bSYour Name 		}
240*5113495bSYour Name 
241*5113495bSYour Name 		if (sp_in->ss_nb_tone_thr != SPECTRAL_PHYERR_PARAM_NOVAL) {
242*5113495bSYour Name 			param.id = SPECTRAL_PARAM_NB_TONE_THR;
243*5113495bSYour Name 			param.value = sp_in->ss_nb_tone_thr;
244*5113495bSYour Name 			ret = sc->sptrlc_set_spectral_config
245*5113495bSYour Name 						(pdev, &param, smode, err);
246*5113495bSYour Name 			if (QDF_IS_STATUS_ERROR(ret))
247*5113495bSYour Name 				goto bad;
248*5113495bSYour Name 		}
249*5113495bSYour Name 
250*5113495bSYour Name 		if (sp_in->ss_str_bin_thr != SPECTRAL_PHYERR_PARAM_NOVAL) {
251*5113495bSYour Name 			param.id = SPECTRAL_PARAM_STR_BIN_THR;
252*5113495bSYour Name 			param.value = sp_in->ss_str_bin_thr;
253*5113495bSYour Name 			ret = sc->sptrlc_set_spectral_config
254*5113495bSYour Name 						(pdev, &param, smode, err);
255*5113495bSYour Name 			if (QDF_IS_STATUS_ERROR(ret))
256*5113495bSYour Name 				goto bad;
257*5113495bSYour Name 		}
258*5113495bSYour Name 
259*5113495bSYour Name 		if (sp_in->ss_wb_rpt_mode != SPECTRAL_PHYERR_PARAM_NOVAL) {
260*5113495bSYour Name 			param.id = SPECTRAL_PARAM_WB_RPT_MODE;
261*5113495bSYour Name 			param.value = sp_in->ss_wb_rpt_mode;
262*5113495bSYour Name 			ret = sc->sptrlc_set_spectral_config
263*5113495bSYour Name 						(pdev, &param, smode, err);
264*5113495bSYour Name 			if (QDF_IS_STATUS_ERROR(ret))
265*5113495bSYour Name 				goto bad;
266*5113495bSYour Name 		}
267*5113495bSYour Name 
268*5113495bSYour Name 		if (sp_in->ss_rssi_rpt_mode != SPECTRAL_PHYERR_PARAM_NOVAL) {
269*5113495bSYour Name 			param.id = SPECTRAL_PARAM_RSSI_RPT_MODE;
270*5113495bSYour Name 			param.value = sp_in->ss_rssi_rpt_mode;
271*5113495bSYour Name 			ret = sc->sptrlc_set_spectral_config
272*5113495bSYour Name 						(pdev, &param, smode, err);
273*5113495bSYour Name 			if (QDF_IS_STATUS_ERROR(ret))
274*5113495bSYour Name 				goto bad;
275*5113495bSYour Name 		}
276*5113495bSYour Name 
277*5113495bSYour Name 		if (sp_in->ss_rssi_thr != SPECTRAL_PHYERR_PARAM_NOVAL) {
278*5113495bSYour Name 			param.id = SPECTRAL_PARAM_RSSI_THR;
279*5113495bSYour Name 			param.value = sp_in->ss_rssi_thr;
280*5113495bSYour Name 			ret = sc->sptrlc_set_spectral_config
281*5113495bSYour Name 						(pdev, &param, smode, err);
282*5113495bSYour Name 			if (QDF_IS_STATUS_ERROR(ret))
283*5113495bSYour Name 				goto bad;
284*5113495bSYour Name 		}
285*5113495bSYour Name 
286*5113495bSYour Name 		if (sp_in->ss_pwr_format != SPECTRAL_PHYERR_PARAM_NOVAL) {
287*5113495bSYour Name 			param.id = SPECTRAL_PARAM_PWR_FORMAT;
288*5113495bSYour Name 			param.value = sp_in->ss_pwr_format;
289*5113495bSYour Name 			ret = sc->sptrlc_set_spectral_config
290*5113495bSYour Name 						(pdev, &param, smode, err);
291*5113495bSYour Name 			if (QDF_IS_STATUS_ERROR(ret))
292*5113495bSYour Name 				goto bad;
293*5113495bSYour Name 		}
294*5113495bSYour Name 
295*5113495bSYour Name 		if (sp_in->ss_rpt_mode != SPECTRAL_PHYERR_PARAM_NOVAL) {
296*5113495bSYour Name 			param.id = SPECTRAL_PARAM_RPT_MODE;
297*5113495bSYour Name 			param.value = sp_in->ss_rpt_mode;
298*5113495bSYour Name 			ret = sc->sptrlc_set_spectral_config
299*5113495bSYour Name 						(pdev, &param, smode, err);
300*5113495bSYour Name 			if (QDF_IS_STATUS_ERROR(ret))
301*5113495bSYour Name 				goto bad;
302*5113495bSYour Name 		}
303*5113495bSYour Name 
304*5113495bSYour Name 		if (sp_in->ss_bin_scale != SPECTRAL_PHYERR_PARAM_NOVAL) {
305*5113495bSYour Name 			param.id = SPECTRAL_PARAM_BIN_SCALE;
306*5113495bSYour Name 			param.value = sp_in->ss_bin_scale;
307*5113495bSYour Name 			ret = sc->sptrlc_set_spectral_config
308*5113495bSYour Name 						(pdev, &param, smode, err);
309*5113495bSYour Name 			if (QDF_IS_STATUS_ERROR(ret))
310*5113495bSYour Name 				goto bad;
311*5113495bSYour Name 		}
312*5113495bSYour Name 
313*5113495bSYour Name 		if (sp_in->ss_dbm_adj != SPECTRAL_PHYERR_PARAM_NOVAL) {
314*5113495bSYour Name 			param.id = SPECTRAL_PARAM_DBM_ADJ;
315*5113495bSYour Name 			param.value = sp_in->ss_dbm_adj;
316*5113495bSYour Name 			ret = sc->sptrlc_set_spectral_config
317*5113495bSYour Name 						(pdev, &param, smode, err);
318*5113495bSYour Name 			if (QDF_IS_STATUS_ERROR(ret))
319*5113495bSYour Name 				goto bad;
320*5113495bSYour Name 		}
321*5113495bSYour Name 
322*5113495bSYour Name 		if (sp_in->ss_chn_mask != SPECTRAL_PHYERR_PARAM_NOVAL) {
323*5113495bSYour Name 			/*
324*5113495bSYour Name 			 * Check if any of the inactive Rx antenna
325*5113495bSYour Name 			 * chains is set active in spectral chainmask
326*5113495bSYour Name 			 */
327*5113495bSYour Name 			vdev = spectral_get_vdev(pdev, sscan_req->vdev_id);
328*5113495bSYour Name 			if (!vdev)
329*5113495bSYour Name 				goto bad;
330*5113495bSYour Name 
331*5113495bSYour Name 			vdev_rxchainmask =
332*5113495bSYour Name 			    wlan_vdev_mlme_get_rxchainmask(vdev);
333*5113495bSYour Name 			wlan_objmgr_vdev_release_ref(vdev,
334*5113495bSYour Name 						     WLAN_SPECTRAL_ID);
335*5113495bSYour Name 
336*5113495bSYour Name 			if (!(sp_in->ss_chn_mask & vdev_rxchainmask)) {
337*5113495bSYour Name 				spectral_err("Invalid Spectral Chainmask - Inactive Rx antenna chain cannot be an active spectral chain");
338*5113495bSYour Name 				goto bad;
339*5113495bSYour Name 			} else {
340*5113495bSYour Name 				param.id = SPECTRAL_PARAM_CHN_MASK;
341*5113495bSYour Name 				param.value = sp_in->ss_chn_mask;
342*5113495bSYour Name 				ret = sc->sptrlc_set_spectral_config
343*5113495bSYour Name 						(pdev, &param, smode, err);
344*5113495bSYour Name 				if (QDF_IS_STATUS_ERROR(ret))
345*5113495bSYour Name 					goto bad;
346*5113495bSYour Name 			}
347*5113495bSYour Name 		}
348*5113495bSYour Name 
349*5113495bSYour Name 		if (sp_in->ss_frequency.cfreq1 != SPECTRAL_PHYERR_PARAM_NOVAL) {
350*5113495bSYour Name 			param.id = SPECTRAL_PARAM_FREQUENCY;
351*5113495bSYour Name 			param.freq.cfreq1 = sp_in->ss_frequency.cfreq1;
352*5113495bSYour Name 			param.freq.cfreq2 = sp_in->ss_frequency.cfreq2;
353*5113495bSYour Name 			ret = sc->sptrlc_set_spectral_config
354*5113495bSYour Name 						(pdev, &param, smode, err);
355*5113495bSYour Name 			if (QDF_IS_STATUS_ERROR(ret))
356*5113495bSYour Name 				goto bad;
357*5113495bSYour Name 		}
358*5113495bSYour Name 
359*5113495bSYour Name 		if (sp_in->ss_bandwidth != SPECTRAL_PHYERR_PARAM_NOVAL) {
360*5113495bSYour Name 			param.id = SPECTRAL_PARAM_CHAN_WIDTH;
361*5113495bSYour Name 			param.value = sp_in->ss_bandwidth;
362*5113495bSYour Name 			ret = sc->sptrlc_set_spectral_config
363*5113495bSYour Name 						(pdev, &param, smode, err);
364*5113495bSYour Name 			if (QDF_IS_STATUS_ERROR(ret))
365*5113495bSYour Name 				goto bad;
366*5113495bSYour Name 		}
367*5113495bSYour Name 
368*5113495bSYour Name 		break;
369*5113495bSYour Name 
370*5113495bSYour Name 	case SPECTRAL_GET_CONFIG:
371*5113495bSYour Name 		sc->sptrlc_get_spectral_config(pdev, &sp_out, smode);
372*5113495bSYour Name 		spectralparams = &sscan_req->config_req.sscan_config;
373*5113495bSYour Name 		spectralparams->ss_fft_period = sp_out.ss_fft_period;
374*5113495bSYour Name 		spectralparams->ss_period = sp_out.ss_period;
375*5113495bSYour Name 		spectralparams->ss_recapture = sp_out.ss_recapture;
376*5113495bSYour Name 		spectralparams->ss_count = sp_out.ss_count;
377*5113495bSYour Name 		spectralparams->ss_short_report =
378*5113495bSYour Name 				sp_out.ss_short_report;
379*5113495bSYour Name 		spectralparams->ss_spectral_pri =
380*5113495bSYour Name 				sp_out.ss_spectral_pri;
381*5113495bSYour Name 		spectralparams->ss_fft_size = sp_out.ss_fft_size;
382*5113495bSYour Name 		spectralparams->ss_gc_ena = sp_out.ss_gc_ena;
383*5113495bSYour Name 		spectralparams->ss_restart_ena = sp_out.ss_restart_ena;
384*5113495bSYour Name 		spectralparams->ss_noise_floor_ref =
385*5113495bSYour Name 				sp_out.ss_noise_floor_ref;
386*5113495bSYour Name 		spectralparams->ss_init_delay = sp_out.ss_init_delay;
387*5113495bSYour Name 		spectralparams->ss_nb_tone_thr = sp_out.ss_nb_tone_thr;
388*5113495bSYour Name 		spectralparams->ss_str_bin_thr = sp_out.ss_str_bin_thr;
389*5113495bSYour Name 		spectralparams->ss_wb_rpt_mode = sp_out.ss_wb_rpt_mode;
390*5113495bSYour Name 		spectralparams->ss_rssi_rpt_mode =
391*5113495bSYour Name 				sp_out.ss_rssi_rpt_mode;
392*5113495bSYour Name 		spectralparams->ss_rssi_thr = sp_out.ss_rssi_thr;
393*5113495bSYour Name 		spectralparams->ss_pwr_format = sp_out.ss_pwr_format;
394*5113495bSYour Name 		spectralparams->ss_rpt_mode = sp_out.ss_rpt_mode;
395*5113495bSYour Name 		spectralparams->ss_bin_scale = sp_out.ss_bin_scale;
396*5113495bSYour Name 		spectralparams->ss_dbm_adj = sp_out.ss_dbm_adj;
397*5113495bSYour Name 		spectralparams->ss_chn_mask = sp_out.ss_chn_mask;
398*5113495bSYour Name 		spectralparams->ss_frequency = sp_out.ss_frequency;
399*5113495bSYour Name 		spectralparams->ss_bandwidth = sp_out.ss_bandwidth;
400*5113495bSYour Name 		break;
401*5113495bSYour Name 
402*5113495bSYour Name 	case SPECTRAL_IS_ACTIVE:
403*5113495bSYour Name 		sscan_req->status_req.is_active =
404*5113495bSYour Name 					sc->sptrlc_is_spectral_active(pdev,
405*5113495bSYour Name 								      smode);
406*5113495bSYour Name 		break;
407*5113495bSYour Name 
408*5113495bSYour Name 	case SPECTRAL_IS_ENABLED:
409*5113495bSYour Name 		sscan_req->status_req.is_enabled =
410*5113495bSYour Name 					sc->sptrlc_is_spectral_enabled(pdev,
411*5113495bSYour Name 								       smode);
412*5113495bSYour Name 		break;
413*5113495bSYour Name 
414*5113495bSYour Name 	case SPECTRAL_SET_DEBUG_LEVEL:
415*5113495bSYour Name 		temp_debug = sscan_req->debug_req.spectral_dbg_level;
416*5113495bSYour Name 		sc->sptrlc_set_debug_level(pdev, temp_debug);
417*5113495bSYour Name 		break;
418*5113495bSYour Name 
419*5113495bSYour Name 	case SPECTRAL_GET_DEBUG_LEVEL:
420*5113495bSYour Name 		sscan_req->debug_req.spectral_dbg_level =
421*5113495bSYour Name 					sc->sptrlc_get_debug_level(pdev);
422*5113495bSYour Name 		break;
423*5113495bSYour Name 
424*5113495bSYour Name 	case SPECTRAL_ACTIVATE_SCAN:
425*5113495bSYour Name 		err = &sscan_req->action_req.sscan_err_code;
426*5113495bSYour Name 		ret = sc->sptrlc_start_spectral_scan(pdev, sscan_req->vdev_id,
427*5113495bSYour Name 						     smode, err);
428*5113495bSYour Name 		if (QDF_IS_STATUS_ERROR(ret))
429*5113495bSYour Name 			goto bad;
430*5113495bSYour Name 		break;
431*5113495bSYour Name 
432*5113495bSYour Name 	case SPECTRAL_STOP_SCAN:
433*5113495bSYour Name 		err = &sscan_req->action_req.sscan_err_code;
434*5113495bSYour Name 		ret = sc->sptrlc_stop_spectral_scan(pdev, smode, err);
435*5113495bSYour Name 		if (QDF_IS_STATUS_ERROR(ret))
436*5113495bSYour Name 			goto bad;
437*5113495bSYour Name 		break;
438*5113495bSYour Name 
439*5113495bSYour Name 	case SPECTRAL_GET_CAPABILITY_INFO:
440*5113495bSYour Name 		{
441*5113495bSYour Name 			struct spectral_caps *caps;
442*5113495bSYour Name 
443*5113495bSYour Name 			caps  = &sscan_req->caps_req.sscan_caps;
444*5113495bSYour Name 			ret = sc->sptrlc_get_spectral_capinfo(pdev, caps);
445*5113495bSYour Name 			if (QDF_IS_STATUS_ERROR(ret))
446*5113495bSYour Name 				goto bad;
447*5113495bSYour Name 		}
448*5113495bSYour Name 		break;
449*5113495bSYour Name 
450*5113495bSYour Name 	case SPECTRAL_GET_DIAG_STATS:
451*5113495bSYour Name 		{
452*5113495bSYour Name 			struct spectral_diag_stats *diag;
453*5113495bSYour Name 
454*5113495bSYour Name 			diag  = &sscan_req->diag_req.sscan_diag;
455*5113495bSYour Name 			ret = sc->sptrlc_get_spectral_diagstats(pdev, diag);
456*5113495bSYour Name 			if (QDF_IS_STATUS_ERROR(ret))
457*5113495bSYour Name 				goto bad;
458*5113495bSYour Name 		}
459*5113495bSYour Name 		break;
460*5113495bSYour Name 
461*5113495bSYour Name 	case SPECTRAL_GET_CHAN_WIDTH:
462*5113495bSYour Name 		{
463*5113495bSYour Name 			uint32_t chan_width;
464*5113495bSYour Name 
465*5113495bSYour Name 			vdev = spectral_get_vdev(pdev, sscan_req->vdev_id);
466*5113495bSYour Name 			if (!vdev)
467*5113495bSYour Name 				goto bad;
468*5113495bSYour Name 
469*5113495bSYour Name 			chan_width = spectral_vdev_get_ch_width(vdev);
470*5113495bSYour Name 			wlan_objmgr_vdev_release_ref(vdev, WLAN_SPECTRAL_ID);
471*5113495bSYour Name 
472*5113495bSYour Name 			sscan_req->chan_width_req.chan_width =
473*5113495bSYour Name 							(uint32_t)chan_width;
474*5113495bSYour Name 		}
475*5113495bSYour Name 		break;
476*5113495bSYour Name 
477*5113495bSYour Name 	case SPECTRAL_SET_DMA_DEBUG:
478*5113495bSYour Name 		if (sc->sptrlc_set_dma_debug)
479*5113495bSYour Name 			sc->sptrlc_set_dma_debug(
480*5113495bSYour Name 			     pdev,
481*5113495bSYour Name 			     sscan_req->dma_debug_req.dma_debug_type,
482*5113495bSYour Name 			     sscan_req->dma_debug_req.dma_debug_enable);
483*5113495bSYour Name 		break;
484*5113495bSYour Name 
485*5113495bSYour Name 	default:
486*5113495bSYour Name 		goto bad;
487*5113495bSYour Name 		break;
488*5113495bSYour Name 	}
489*5113495bSYour Name 
490*5113495bSYour Name 	status = QDF_STATUS_SUCCESS;
491*5113495bSYour Name bad:
492*5113495bSYour Name 	return status;
493*5113495bSYour Name }
494*5113495bSYour Name 
495*5113495bSYour Name /**
496*5113495bSYour Name  * spectral_ctx_deinit() - De-initialize function pointers from spectral context
497*5113495bSYour Name  * @sc: Reference to spectral_context object
498*5113495bSYour Name  *
499*5113495bSYour Name  * Return: None
500*5113495bSYour Name  */
501*5113495bSYour Name static void
spectral_ctx_deinit(struct spectral_context * sc)502*5113495bSYour Name spectral_ctx_deinit(struct spectral_context *sc)
503*5113495bSYour Name {
504*5113495bSYour Name 	if (sc) {
505*5113495bSYour Name 		sc->sptrlc_ucfg_phyerr_config = NULL;
506*5113495bSYour Name 		sc->sptrlc_pdev_spectral_init = NULL;
507*5113495bSYour Name 		sc->sptrlc_pdev_spectral_deinit = NULL;
508*5113495bSYour Name 		sc->sptrlc_psoc_spectral_init = NULL;
509*5113495bSYour Name 		sc->sptrlc_psoc_spectral_deinit = NULL;
510*5113495bSYour Name 		sc->sptrlc_set_spectral_config = NULL;
511*5113495bSYour Name 		sc->sptrlc_get_spectral_config = NULL;
512*5113495bSYour Name 		sc->sptrlc_start_spectral_scan = NULL;
513*5113495bSYour Name 		sc->sptrlc_stop_spectral_scan = NULL;
514*5113495bSYour Name 		sc->sptrlc_is_spectral_active = NULL;
515*5113495bSYour Name 		sc->sptrlc_is_spectral_enabled = NULL;
516*5113495bSYour Name 		sc->sptrlc_set_debug_level = NULL;
517*5113495bSYour Name 		sc->sptrlc_get_debug_level = NULL;
518*5113495bSYour Name 		sc->sptrlc_get_spectral_capinfo = NULL;
519*5113495bSYour Name 		sc->sptrlc_get_spectral_diagstats = NULL;
520*5113495bSYour Name 	}
521*5113495bSYour Name }
522*5113495bSYour Name 
523*5113495bSYour Name QDF_STATUS
wlan_spectral_psoc_obj_create_handler(struct wlan_objmgr_psoc * psoc,void * arg)524*5113495bSYour Name wlan_spectral_psoc_obj_create_handler(struct wlan_objmgr_psoc *psoc, void *arg)
525*5113495bSYour Name {
526*5113495bSYour Name 	struct spectral_context *sc = NULL;
527*5113495bSYour Name 	QDF_STATUS status;
528*5113495bSYour Name 
529*5113495bSYour Name 	if (!psoc) {
530*5113495bSYour Name 		spectral_err("PSOC is NULL");
531*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
532*5113495bSYour Name 	}
533*5113495bSYour Name 
534*5113495bSYour Name 	status = wlan_spectral_init_psoc_feature_cap(psoc);
535*5113495bSYour Name 	if (QDF_IS_STATUS_ERROR(status)) {
536*5113495bSYour Name 		spectral_err("Failed to initialize spectral pdev feature caps");
537*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
538*5113495bSYour Name 	}
539*5113495bSYour Name 
540*5113495bSYour Name 	if (wlan_spectral_is_feature_disabled_psoc(psoc)) {
541*5113495bSYour Name 		spectral_info("Spectral feature is disabled");
542*5113495bSYour Name 		return QDF_STATUS_COMP_DISABLED;
543*5113495bSYour Name 	}
544*5113495bSYour Name 
545*5113495bSYour Name 	sc = (struct spectral_context *)
546*5113495bSYour Name 	    qdf_mem_malloc(sizeof(struct spectral_context));
547*5113495bSYour Name 	if (!sc)
548*5113495bSYour Name 		return QDF_STATUS_E_NOMEM;
549*5113495bSYour Name 
550*5113495bSYour Name 	qdf_mem_zero(sc, sizeof(struct spectral_context));
551*5113495bSYour Name 	sc->psoc_obj = psoc;
552*5113495bSYour Name 	if (wlan_objmgr_psoc_get_dev_type(psoc) == WLAN_DEV_OL)
553*5113495bSYour Name 		spectral_ctx_init_ol(sc);
554*5113495bSYour Name 	wlan_objmgr_psoc_component_obj_attach(psoc, WLAN_UMAC_COMP_SPECTRAL,
555*5113495bSYour Name 					      (void *)sc, QDF_STATUS_SUCCESS);
556*5113495bSYour Name 
557*5113495bSYour Name 	return QDF_STATUS_SUCCESS;
558*5113495bSYour Name }
559*5113495bSYour Name 
560*5113495bSYour Name QDF_STATUS
wlan_spectral_psoc_obj_destroy_handler(struct wlan_objmgr_psoc * psoc,void * arg)561*5113495bSYour Name wlan_spectral_psoc_obj_destroy_handler(struct wlan_objmgr_psoc *psoc,
562*5113495bSYour Name 				       void *arg)
563*5113495bSYour Name {
564*5113495bSYour Name 	struct spectral_context *sc = NULL;
565*5113495bSYour Name 
566*5113495bSYour Name 	if (!psoc) {
567*5113495bSYour Name 		spectral_err("PSOC is NULL");
568*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
569*5113495bSYour Name 	}
570*5113495bSYour Name 
571*5113495bSYour Name 	if (wlan_spectral_is_feature_disabled_psoc(psoc)) {
572*5113495bSYour Name 		spectral_info("Spectral feature is disabled");
573*5113495bSYour Name 		return QDF_STATUS_COMP_DISABLED;
574*5113495bSYour Name 	}
575*5113495bSYour Name 
576*5113495bSYour Name 	sc = wlan_objmgr_psoc_get_comp_private_obj(psoc,
577*5113495bSYour Name 						   WLAN_UMAC_COMP_SPECTRAL);
578*5113495bSYour Name 	if (sc) {
579*5113495bSYour Name 		wlan_objmgr_psoc_component_obj_detach(psoc,
580*5113495bSYour Name 						      WLAN_UMAC_COMP_SPECTRAL,
581*5113495bSYour Name 						      (void *)sc);
582*5113495bSYour Name 		/* Deinitilise function pointers from spectral context */
583*5113495bSYour Name 		spectral_ctx_deinit(sc);
584*5113495bSYour Name 		qdf_mem_free(sc);
585*5113495bSYour Name 	}
586*5113495bSYour Name 
587*5113495bSYour Name 	return QDF_STATUS_SUCCESS;
588*5113495bSYour Name }
589*5113495bSYour Name 
590*5113495bSYour Name QDF_STATUS
wlan_spectral_pdev_obj_create_handler(struct wlan_objmgr_pdev * pdev,void * arg)591*5113495bSYour Name wlan_spectral_pdev_obj_create_handler(struct wlan_objmgr_pdev *pdev, void *arg)
592*5113495bSYour Name {
593*5113495bSYour Name 	struct pdev_spectral *ps = NULL;
594*5113495bSYour Name 	struct spectral_context *sc = NULL;
595*5113495bSYour Name 	void *target_handle = NULL;
596*5113495bSYour Name 	QDF_STATUS status;
597*5113495bSYour Name 
598*5113495bSYour Name 	if (!pdev) {
599*5113495bSYour Name 		spectral_err("PDEV is NULL");
600*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
601*5113495bSYour Name 	}
602*5113495bSYour Name 
603*5113495bSYour Name 	status = wlan_spectral_init_pdev_feature_caps(pdev);
604*5113495bSYour Name 	if (QDF_IS_STATUS_ERROR(status)) {
605*5113495bSYour Name 		spectral_err("Failed to initialize spectral pdev feature caps");
606*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
607*5113495bSYour Name 	}
608*5113495bSYour Name 
609*5113495bSYour Name 	if (wlan_spectral_is_feature_disabled_pdev(pdev)) {
610*5113495bSYour Name 		spectral_info("Spectral feature is disabled");
611*5113495bSYour Name 		return QDF_STATUS_COMP_DISABLED;
612*5113495bSYour Name 	}
613*5113495bSYour Name 
614*5113495bSYour Name 	ps = (struct pdev_spectral *)
615*5113495bSYour Name 	    qdf_mem_malloc(sizeof(struct pdev_spectral));
616*5113495bSYour Name 	if (!ps)
617*5113495bSYour Name 		return QDF_STATUS_E_NOMEM;
618*5113495bSYour Name 
619*5113495bSYour Name 	sc = spectral_get_spectral_ctx_from_pdev(pdev);
620*5113495bSYour Name 	if (!sc) {
621*5113495bSYour Name 		spectral_err("Spectral context is NULL!");
622*5113495bSYour Name 		goto cleanup;
623*5113495bSYour Name 	}
624*5113495bSYour Name 
625*5113495bSYour Name 	qdf_mem_zero(ps, sizeof(struct pdev_spectral));
626*5113495bSYour Name 	ps->psptrl_pdev = pdev;
627*5113495bSYour Name 
628*5113495bSYour Name 	spectral_register_cfg80211_handlers(pdev);
629*5113495bSYour Name 	if (sc->sptrlc_pdev_spectral_init) {
630*5113495bSYour Name 		target_handle = sc->sptrlc_pdev_spectral_init(pdev);
631*5113495bSYour Name 		if (!target_handle) {
632*5113495bSYour Name 			spectral_err("Spectral lmac object is NULL!");
633*5113495bSYour Name 			goto cleanup;
634*5113495bSYour Name 		}
635*5113495bSYour Name 		ps->psptrl_target_handle = target_handle;
636*5113495bSYour Name 	}
637*5113495bSYour Name 	wlan_objmgr_pdev_component_obj_attach(pdev, WLAN_UMAC_COMP_SPECTRAL,
638*5113495bSYour Name 					      (void *)ps, QDF_STATUS_SUCCESS);
639*5113495bSYour Name 
640*5113495bSYour Name 	return QDF_STATUS_SUCCESS;
641*5113495bSYour Name  cleanup:
642*5113495bSYour Name 	qdf_mem_free(ps);
643*5113495bSYour Name 	return QDF_STATUS_E_FAILURE;
644*5113495bSYour Name }
645*5113495bSYour Name 
646*5113495bSYour Name QDF_STATUS
wlan_spectral_pdev_obj_destroy_handler(struct wlan_objmgr_pdev * pdev,void * arg)647*5113495bSYour Name wlan_spectral_pdev_obj_destroy_handler(struct wlan_objmgr_pdev *pdev,
648*5113495bSYour Name 				       void *arg)
649*5113495bSYour Name {
650*5113495bSYour Name 	struct pdev_spectral *ps = NULL;
651*5113495bSYour Name 	struct spectral_context *sc = NULL;
652*5113495bSYour Name 
653*5113495bSYour Name 	if (!pdev) {
654*5113495bSYour Name 		spectral_err("PDEV is NULL");
655*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
656*5113495bSYour Name 	}
657*5113495bSYour Name 
658*5113495bSYour Name 	if (wlan_spectral_is_feature_disabled_pdev(pdev)) {
659*5113495bSYour Name 		spectral_info("Spectral feature is disabled");
660*5113495bSYour Name 		return QDF_STATUS_COMP_DISABLED;
661*5113495bSYour Name 	}
662*5113495bSYour Name 
663*5113495bSYour Name 	sc = spectral_get_spectral_ctx_from_pdev(pdev);
664*5113495bSYour Name 	if (!sc) {
665*5113495bSYour Name 		spectral_err("Spectral context is NULL!");
666*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
667*5113495bSYour Name 	}
668*5113495bSYour Name 	ps = wlan_objmgr_pdev_get_comp_private_obj(pdev,
669*5113495bSYour Name 						   WLAN_UMAC_COMP_SPECTRAL);
670*5113495bSYour Name 	if (ps) {
671*5113495bSYour Name 		if (sc->sptrlc_pdev_spectral_deinit)
672*5113495bSYour Name 			sc->sptrlc_pdev_spectral_deinit(pdev);
673*5113495bSYour Name 		ps->psptrl_target_handle = NULL;
674*5113495bSYour Name 		wlan_objmgr_pdev_component_obj_detach(pdev,
675*5113495bSYour Name 						      WLAN_UMAC_COMP_SPECTRAL,
676*5113495bSYour Name 						      (void *)ps);
677*5113495bSYour Name 		qdf_mem_free(ps);
678*5113495bSYour Name 	}
679*5113495bSYour Name 
680*5113495bSYour Name 	return QDF_STATUS_SUCCESS;
681*5113495bSYour Name }
682