xref: /wlan-driver/qca-wifi-host-cmn/os_if/linux/spectral/src/wlan_cfg80211_spectral.c (revision 5113495b16420b49004c444715d2daae2066e7dc)
1*5113495bSYour Name /*
2*5113495bSYour Name  * Copyright (c) 2017-2021 The Linux Foundation. All rights reserved.
3*5113495bSYour Name  * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
4*5113495bSYour Name  *
5*5113495bSYour Name  * Permission to use, copy, modify, and/or distribute this software for
6*5113495bSYour Name  * any purpose with or without fee is hereby granted, provided that the
7*5113495bSYour Name  * above copyright notice and this permission notice appear in all
8*5113495bSYour Name  * copies.
9*5113495bSYour Name  *
10*5113495bSYour Name  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
11*5113495bSYour Name  * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
12*5113495bSYour Name  * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
13*5113495bSYour Name  * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
14*5113495bSYour Name  * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
15*5113495bSYour Name  * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
16*5113495bSYour Name  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17*5113495bSYour Name  * PERFORMANCE OF THIS SOFTWARE.
18*5113495bSYour Name  */
19*5113495bSYour Name 
20*5113495bSYour Name /**
21*5113495bSYour Name  * DOC: defines driver functions interfacing with linux kernel
22*5113495bSYour Name  */
23*5113495bSYour Name 
24*5113495bSYour Name #include <qdf_list.h>
25*5113495bSYour Name #include <qdf_status.h>
26*5113495bSYour Name #include <linux/wireless.h>
27*5113495bSYour Name #include <linux/netdevice.h>
28*5113495bSYour Name #include <net/cfg80211.h>
29*5113495bSYour Name #include <wlan_cfg80211.h>
30*5113495bSYour Name #include <wlan_osif_priv.h>
31*5113495bSYour Name #include <qdf_mem.h>
32*5113495bSYour Name #include <wlan_spectral_ucfg_api.h>
33*5113495bSYour Name #include <wlan_cfg80211_spectral.h>
34*5113495bSYour Name #include <spectral_ioctl.h>
35*5113495bSYour Name #include <wlan_objmgr_vdev_obj.h>
36*5113495bSYour Name #include "wlan_osif_features.h"
37*5113495bSYour Name 
38*5113495bSYour Name const struct nla_policy spectral_scan_policy[
39*5113495bSYour Name 		QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_MAX + 1] = {
40*5113495bSYour Name 	[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_SCAN_COUNT] = {
41*5113495bSYour Name 							.type = NLA_U32},
42*5113495bSYour Name 	[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_SCAN_PERIOD] = {
43*5113495bSYour Name 							.type = NLA_U32},
44*5113495bSYour Name 	[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_PRIORITY] = {
45*5113495bSYour Name 							.type = NLA_U32},
46*5113495bSYour Name 	[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_FFT_SIZE] = {
47*5113495bSYour Name 							.type = NLA_U32},
48*5113495bSYour Name 	[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_GC_ENA] = {
49*5113495bSYour Name 							.type = NLA_U32},
50*5113495bSYour Name 	[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_RESTART_ENA] = {
51*5113495bSYour Name 							.type = NLA_U32},
52*5113495bSYour Name 	[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_NOISE_FLOOR_REF] = {
53*5113495bSYour Name 							.type = NLA_U32},
54*5113495bSYour Name 	[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_INIT_DELAY] = {
55*5113495bSYour Name 							.type = NLA_U32},
56*5113495bSYour Name 	[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_NB_TONE_THR] = {
57*5113495bSYour Name 							.type = NLA_U32},
58*5113495bSYour Name 	[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_STR_BIN_THR] = {
59*5113495bSYour Name 							.type = NLA_U32},
60*5113495bSYour Name 	[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_WB_RPT_MODE] = {
61*5113495bSYour Name 							.type = NLA_U32},
62*5113495bSYour Name 	[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_RSSI_RPT_MODE] = {
63*5113495bSYour Name 							.type = NLA_U32},
64*5113495bSYour Name 	[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_RSSI_THR] = {
65*5113495bSYour Name 							.type = NLA_U32},
66*5113495bSYour Name 	[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_PWR_FORMAT] = {
67*5113495bSYour Name 							.type = NLA_U32},
68*5113495bSYour Name 	[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_RPT_MODE] = {
69*5113495bSYour Name 							.type = NLA_U32},
70*5113495bSYour Name 	[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_BIN_SCALE] = {
71*5113495bSYour Name 							.type = NLA_U32},
72*5113495bSYour Name 	[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_DBM_ADJ] = {
73*5113495bSYour Name 							.type = NLA_U32},
74*5113495bSYour Name 	[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_CHN_MASK] = {
75*5113495bSYour Name 							.type = NLA_U32},
76*5113495bSYour Name 	[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_REQUEST_TYPE] = {
77*5113495bSYour Name 							.type = NLA_U32},
78*5113495bSYour Name 	[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_COOKIE] = {
79*5113495bSYour Name 							.type = NLA_U64},
80*5113495bSYour Name 	[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_FFT_PERIOD] = {
81*5113495bSYour Name 							.type = NLA_U32},
82*5113495bSYour Name 	[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_SHORT_REPORT] = {
83*5113495bSYour Name 							.type = NLA_U32},
84*5113495bSYour Name 	[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_DEBUG_LEVEL] = {
85*5113495bSYour Name 							.type = NLA_U32},
86*5113495bSYour Name 	[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_FREQUENCY] = {
87*5113495bSYour Name 							.type = NLA_U32},
88*5113495bSYour Name 	[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_FREQUENCY_2] = {
89*5113495bSYour Name 							.type = NLA_U32},
90*5113495bSYour Name 	[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_MODE] = {
91*5113495bSYour Name 							.type = NLA_U32},
92*5113495bSYour Name 	[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_DMA_RING_DEBUG] = {
93*5113495bSYour Name 							.type = NLA_U8},
94*5113495bSYour Name 	[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_DMA_BUFFER_DEBUG] = {
95*5113495bSYour Name 							.type = NLA_U8},
96*5113495bSYour Name 	[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_BANDWIDTH] = {
97*5113495bSYour Name 							.type = NLA_U8},
98*5113495bSYour Name 	[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_FFT_RECAPTURE] = {
99*5113495bSYour Name 							.type = NLA_U32},
100*5113495bSYour Name };
101*5113495bSYour Name 
102*5113495bSYour Name const struct nla_policy spectral_scan_get_status_policy[
103*5113495bSYour Name 		QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_STATUS_MAX + 1] = {
104*5113495bSYour Name 	[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_STATUS_IS_ENABLED] = {
105*5113495bSYour Name 							.type = NLA_FLAG },
106*5113495bSYour Name 	[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_STATUS_IS_ACTIVE] = {
107*5113495bSYour Name 							.type = NLA_FLAG },
108*5113495bSYour Name 	[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_STATUS_MODE] = { .type = NLA_U32 },
109*5113495bSYour Name };
110*5113495bSYour Name 
wlan_spectral_intit_config(struct spectral_config * config_req)111*5113495bSYour Name static void wlan_spectral_intit_config(struct spectral_config *config_req)
112*5113495bSYour Name {
113*5113495bSYour Name 	config_req->ss_period =          SPECTRAL_PHYERR_PARAM_NOVAL;
114*5113495bSYour Name 	config_req->ss_recapture =       SPECTRAL_PHYERR_PARAM_NOVAL;
115*5113495bSYour Name 	config_req->ss_count =           SPECTRAL_PHYERR_PARAM_NOVAL;
116*5113495bSYour Name 	config_req->ss_fft_period =      SPECTRAL_PHYERR_PARAM_NOVAL;
117*5113495bSYour Name 	config_req->ss_short_report =    SPECTRAL_PHYERR_PARAM_NOVAL;
118*5113495bSYour Name 	config_req->ss_spectral_pri =    SPECTRAL_PHYERR_PARAM_NOVAL;
119*5113495bSYour Name 	config_req->ss_fft_size =        SPECTRAL_PHYERR_PARAM_NOVAL;
120*5113495bSYour Name 	config_req->ss_gc_ena =          SPECTRAL_PHYERR_PARAM_NOVAL;
121*5113495bSYour Name 	config_req->ss_restart_ena =     SPECTRAL_PHYERR_PARAM_NOVAL;
122*5113495bSYour Name 	config_req->ss_noise_floor_ref = SPECTRAL_PHYERR_PARAM_NOVAL;
123*5113495bSYour Name 	config_req->ss_init_delay =      SPECTRAL_PHYERR_PARAM_NOVAL;
124*5113495bSYour Name 	config_req->ss_nb_tone_thr =     SPECTRAL_PHYERR_PARAM_NOVAL;
125*5113495bSYour Name 	config_req->ss_str_bin_thr =     SPECTRAL_PHYERR_PARAM_NOVAL;
126*5113495bSYour Name 	config_req->ss_wb_rpt_mode =     SPECTRAL_PHYERR_PARAM_NOVAL;
127*5113495bSYour Name 	config_req->ss_rssi_rpt_mode =   SPECTRAL_PHYERR_PARAM_NOVAL;
128*5113495bSYour Name 	config_req->ss_rssi_thr =        SPECTRAL_PHYERR_PARAM_NOVAL;
129*5113495bSYour Name 	config_req->ss_pwr_format =      SPECTRAL_PHYERR_PARAM_NOVAL;
130*5113495bSYour Name 	config_req->ss_rpt_mode =        SPECTRAL_PHYERR_PARAM_NOVAL;
131*5113495bSYour Name 	config_req->ss_bin_scale =       SPECTRAL_PHYERR_PARAM_NOVAL;
132*5113495bSYour Name 	config_req->ss_dbm_adj =         SPECTRAL_PHYERR_PARAM_NOVAL;
133*5113495bSYour Name 	config_req->ss_chn_mask =        SPECTRAL_PHYERR_PARAM_NOVAL;
134*5113495bSYour Name 	config_req->ss_frequency.cfreq1 = SPECTRAL_PHYERR_PARAM_NOVAL;
135*5113495bSYour Name 	config_req->ss_frequency.cfreq2 = SPECTRAL_PHYERR_PARAM_NOVAL;
136*5113495bSYour Name 	config_req->ss_bandwidth = SPECTRAL_PHYERR_PARAM_NOVAL;
137*5113495bSYour Name }
138*5113495bSYour Name 
139*5113495bSYour Name /**
140*5113495bSYour Name  * convert_spectral_mode_nl_to_internal() - Get Spectral mode
141*5113495bSYour Name  * @nl_spectral_mode: Spectral mode in vendor attribute
142*5113495bSYour Name  * @mode: Converted Spectral mode
143*5113495bSYour Name  *
144*5113495bSYour Name  * Return: QDF_STATUS_SUCCESS on success, else QDF_STATUS_E_FAILURE
145*5113495bSYour Name  */
146*5113495bSYour Name static QDF_STATUS
convert_spectral_mode_nl_to_internal(enum qca_wlan_vendor_spectral_scan_mode nl_spectral_mode,enum spectral_scan_mode * mode)147*5113495bSYour Name convert_spectral_mode_nl_to_internal
148*5113495bSYour Name 		(enum qca_wlan_vendor_spectral_scan_mode nl_spectral_mode,
149*5113495bSYour Name 		 enum spectral_scan_mode *mode)
150*5113495bSYour Name {
151*5113495bSYour Name 	switch (nl_spectral_mode) {
152*5113495bSYour Name 	case QCA_WLAN_VENDOR_SPECTRAL_SCAN_MODE_NORMAL:
153*5113495bSYour Name 		*mode = SPECTRAL_SCAN_MODE_NORMAL;
154*5113495bSYour Name 		break;
155*5113495bSYour Name 
156*5113495bSYour Name 	case QCA_WLAN_VENDOR_SPECTRAL_SCAN_MODE_AGILE:
157*5113495bSYour Name 		*mode = SPECTRAL_SCAN_MODE_AGILE;
158*5113495bSYour Name 		break;
159*5113495bSYour Name 
160*5113495bSYour Name 	default:
161*5113495bSYour Name 		osif_err("Invalid spectral mode %u", nl_spectral_mode);
162*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
163*5113495bSYour Name 	}
164*5113495bSYour Name 
165*5113495bSYour Name 	return QDF_STATUS_SUCCESS;
166*5113495bSYour Name }
167*5113495bSYour Name 
168*5113495bSYour Name /**
169*5113495bSYour Name  * convert_spectral_err_code_internal_to_nl() - Get Spectral error code
170*5113495bSYour Name  * @spectral_err_code: Spectral error code used internally
171*5113495bSYour Name  * @nl_err_code: Spectral error code for cfg80211
172*5113495bSYour Name  *
173*5113495bSYour Name  * Return: QDF_STATUS_SUCCESS on success, else QDF_STATUS_E_FAILURE
174*5113495bSYour Name  */
175*5113495bSYour Name static QDF_STATUS
convert_spectral_err_code_internal_to_nl(enum spectral_cp_error_code spectral_err_code,enum qca_wlan_vendor_spectral_scan_error_code * nl_err_code)176*5113495bSYour Name convert_spectral_err_code_internal_to_nl
177*5113495bSYour Name 		(enum spectral_cp_error_code spectral_err_code,
178*5113495bSYour Name 		 enum qca_wlan_vendor_spectral_scan_error_code *nl_err_code)
179*5113495bSYour Name {
180*5113495bSYour Name 	switch (spectral_err_code) {
181*5113495bSYour Name 	case SPECTRAL_SCAN_ERR_PARAM_UNSUPPORTED:
182*5113495bSYour Name 		*nl_err_code =
183*5113495bSYour Name 			QCA_WLAN_VENDOR_SPECTRAL_SCAN_ERR_PARAM_UNSUPPORTED;
184*5113495bSYour Name 		break;
185*5113495bSYour Name 
186*5113495bSYour Name 	case SPECTRAL_SCAN_ERR_MODE_UNSUPPORTED:
187*5113495bSYour Name 		*nl_err_code =
188*5113495bSYour Name 			QCA_WLAN_VENDOR_SPECTRAL_SCAN_ERR_MODE_UNSUPPORTED;
189*5113495bSYour Name 		break;
190*5113495bSYour Name 
191*5113495bSYour Name 	case SPECTRAL_SCAN_ERR_PARAM_INVALID_VALUE:
192*5113495bSYour Name 		*nl_err_code =
193*5113495bSYour Name 			QCA_WLAN_VENDOR_SPECTRAL_SCAN_ERR_PARAM_INVALID_VALUE;
194*5113495bSYour Name 		break;
195*5113495bSYour Name 
196*5113495bSYour Name 	case SPECTRAL_SCAN_ERR_PARAM_NOT_INITIALIZED:
197*5113495bSYour Name 		*nl_err_code =
198*5113495bSYour Name 			QCA_WLAN_VENDOR_SPECTRAL_SCAN_ERR_PARAM_NOT_INITIALIZED;
199*5113495bSYour Name 		break;
200*5113495bSYour Name 
201*5113495bSYour Name 	default:
202*5113495bSYour Name 		osif_err("Invalid spectral error code %u", spectral_err_code);
203*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
204*5113495bSYour Name 	}
205*5113495bSYour Name 
206*5113495bSYour Name 	return QDF_STATUS_SUCCESS;
207*5113495bSYour Name }
208*5113495bSYour Name 
209*5113495bSYour Name #if defined(WLAN_FEATURE_11BE) && defined(CFG80211_11BE_BASIC)
210*5113495bSYour Name int
wlan_spectral_get_nl80211_chwidth(uint8_t phy_chwidth)211*5113495bSYour Name wlan_spectral_get_nl80211_chwidth(uint8_t phy_chwidth)
212*5113495bSYour Name {
213*5113495bSYour Name 	switch ((enum phy_ch_width)phy_chwidth) {
214*5113495bSYour Name 	case CH_WIDTH_5MHZ:
215*5113495bSYour Name 		return NL80211_CHAN_WIDTH_5;
216*5113495bSYour Name 	case CH_WIDTH_10MHZ:
217*5113495bSYour Name 		return NL80211_CHAN_WIDTH_10;
218*5113495bSYour Name 	case CH_WIDTH_20MHZ:
219*5113495bSYour Name 		return NL80211_CHAN_WIDTH_20;
220*5113495bSYour Name 	case CH_WIDTH_40MHZ:
221*5113495bSYour Name 		return NL80211_CHAN_WIDTH_40;
222*5113495bSYour Name 	case CH_WIDTH_80MHZ:
223*5113495bSYour Name 		return NL80211_CHAN_WIDTH_80;
224*5113495bSYour Name 	case CH_WIDTH_160MHZ:
225*5113495bSYour Name 		return NL80211_CHAN_WIDTH_160;
226*5113495bSYour Name 	case CH_WIDTH_80P80MHZ:
227*5113495bSYour Name 		return NL80211_CHAN_WIDTH_80P80;
228*5113495bSYour Name 	case CH_WIDTH_320MHZ:
229*5113495bSYour Name 	case CH_WIDTH_MAX:
230*5113495bSYour Name 		return NL80211_CHAN_WIDTH_320;
231*5113495bSYour Name 	case CH_WIDTH_INVALID:
232*5113495bSYour Name 	default:
233*5113495bSYour Name 		osif_err("Invalid spectral channel width %u", phy_chwidth);
234*5113495bSYour Name 		return -EINVAL;
235*5113495bSYour Name 	}
236*5113495bSYour Name }
237*5113495bSYour Name 
238*5113495bSYour Name uint8_t
wlan_spectral_get_phy_ch_width(uint8_t nl_chwidth)239*5113495bSYour Name wlan_spectral_get_phy_ch_width(uint8_t nl_chwidth)
240*5113495bSYour Name {
241*5113495bSYour Name 	switch ((enum nl80211_chan_width)nl_chwidth) {
242*5113495bSYour Name 	case NL80211_CHAN_WIDTH_5:
243*5113495bSYour Name 		return CH_WIDTH_5MHZ;
244*5113495bSYour Name 	case NL80211_CHAN_WIDTH_10:
245*5113495bSYour Name 		return CH_WIDTH_10MHZ;
246*5113495bSYour Name 	case NL80211_CHAN_WIDTH_20:
247*5113495bSYour Name 		return CH_WIDTH_20MHZ;
248*5113495bSYour Name 	case NL80211_CHAN_WIDTH_40:
249*5113495bSYour Name 		return CH_WIDTH_40MHZ;
250*5113495bSYour Name 	case NL80211_CHAN_WIDTH_80:
251*5113495bSYour Name 		return CH_WIDTH_80MHZ;
252*5113495bSYour Name 	case NL80211_CHAN_WIDTH_160:
253*5113495bSYour Name 		return CH_WIDTH_160MHZ;
254*5113495bSYour Name 	case NL80211_CHAN_WIDTH_80P80:
255*5113495bSYour Name 		return CH_WIDTH_80P80MHZ;
256*5113495bSYour Name 	case NL80211_CHAN_WIDTH_320:
257*5113495bSYour Name 		return CH_WIDTH_320MHZ;
258*5113495bSYour Name 	default:
259*5113495bSYour Name 		osif_err("Invalid nl80211 channel width %u", nl_chwidth);
260*5113495bSYour Name 		return CH_WIDTH_INVALID;
261*5113495bSYour Name 	}
262*5113495bSYour Name }
263*5113495bSYour Name #else
264*5113495bSYour Name int
wlan_spectral_get_nl80211_chwidth(uint8_t phy_chwidth)265*5113495bSYour Name wlan_spectral_get_nl80211_chwidth(uint8_t phy_chwidth)
266*5113495bSYour Name {
267*5113495bSYour Name 	switch ((enum phy_ch_width)phy_chwidth) {
268*5113495bSYour Name 	case CH_WIDTH_5MHZ:
269*5113495bSYour Name 		return NL80211_CHAN_WIDTH_5;
270*5113495bSYour Name 	case CH_WIDTH_10MHZ:
271*5113495bSYour Name 		return NL80211_CHAN_WIDTH_10;
272*5113495bSYour Name 	case CH_WIDTH_20MHZ:
273*5113495bSYour Name 		return NL80211_CHAN_WIDTH_20;
274*5113495bSYour Name 	case CH_WIDTH_40MHZ:
275*5113495bSYour Name 		return NL80211_CHAN_WIDTH_40;
276*5113495bSYour Name 	case CH_WIDTH_80MHZ:
277*5113495bSYour Name 		return NL80211_CHAN_WIDTH_80;
278*5113495bSYour Name 	case CH_WIDTH_160MHZ:
279*5113495bSYour Name 	case CH_WIDTH_MAX:
280*5113495bSYour Name 		return NL80211_CHAN_WIDTH_160;
281*5113495bSYour Name 	case CH_WIDTH_80P80MHZ:
282*5113495bSYour Name 		return NL80211_CHAN_WIDTH_80P80;
283*5113495bSYour Name 	case CH_WIDTH_INVALID:
284*5113495bSYour Name 	default:
285*5113495bSYour Name 		osif_err("Invalid spectral channel width %u", phy_chwidth);
286*5113495bSYour Name 		return -EINVAL;
287*5113495bSYour Name 	}
288*5113495bSYour Name }
289*5113495bSYour Name 
290*5113495bSYour Name uint8_t
wlan_spectral_get_phy_ch_width(uint8_t nl_chwidth)291*5113495bSYour Name wlan_spectral_get_phy_ch_width(uint8_t nl_chwidth)
292*5113495bSYour Name {
293*5113495bSYour Name 	switch ((enum nl80211_chan_width)nl_chwidth) {
294*5113495bSYour Name 	case NL80211_CHAN_WIDTH_5:
295*5113495bSYour Name 		return CH_WIDTH_5MHZ;
296*5113495bSYour Name 	case NL80211_CHAN_WIDTH_10:
297*5113495bSYour Name 		return CH_WIDTH_10MHZ;
298*5113495bSYour Name 	case NL80211_CHAN_WIDTH_20:
299*5113495bSYour Name 		return CH_WIDTH_20MHZ;
300*5113495bSYour Name 	case NL80211_CHAN_WIDTH_40:
301*5113495bSYour Name 		return CH_WIDTH_40MHZ;
302*5113495bSYour Name 	case NL80211_CHAN_WIDTH_80:
303*5113495bSYour Name 		return CH_WIDTH_80MHZ;
304*5113495bSYour Name 	case NL80211_CHAN_WIDTH_160:
305*5113495bSYour Name 		return CH_WIDTH_160MHZ;
306*5113495bSYour Name 	case NL80211_CHAN_WIDTH_80P80:
307*5113495bSYour Name 		return CH_WIDTH_80P80MHZ;
308*5113495bSYour Name 	default:
309*5113495bSYour Name 		osif_err("Invalid nl80211 channel width %u", nl_chwidth);
310*5113495bSYour Name 		return CH_WIDTH_INVALID;
311*5113495bSYour Name 	}
312*5113495bSYour Name }
313*5113495bSYour Name #endif /* WLAN_FEATURE_11BE */
314*5113495bSYour Name 
315*5113495bSYour Name #ifdef DIRECT_BUF_RX_DEBUG
wlan_cfg80211_spectral_scan_dma_debug_config(struct wlan_objmgr_pdev * pdev,struct wlan_objmgr_vdev * vdev,struct nlattr ** tb,enum spectral_scan_mode sscan_mode)316*5113495bSYour Name QDF_STATUS wlan_cfg80211_spectral_scan_dma_debug_config(
317*5113495bSYour Name 	struct wlan_objmgr_pdev *pdev,
318*5113495bSYour Name 	struct wlan_objmgr_vdev *vdev,
319*5113495bSYour Name 	struct nlattr **tb,
320*5113495bSYour Name 	enum spectral_scan_mode sscan_mode)
321*5113495bSYour Name {
322*5113495bSYour Name 	struct spectral_cp_request sscan_req;
323*5113495bSYour Name 	uint8_t dma_debug_enable;
324*5113495bSYour Name 	QDF_STATUS status;
325*5113495bSYour Name 
326*5113495bSYour Name 	if (!tb || !pdev)
327*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
328*5113495bSYour Name 
329*5113495bSYour Name 	if (tb[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_DMA_RING_DEBUG]) {
330*5113495bSYour Name 		dma_debug_enable = nla_get_u8(tb[
331*5113495bSYour Name 		   QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_DMA_RING_DEBUG]);
332*5113495bSYour Name 		sscan_req.ss_mode = sscan_mode;
333*5113495bSYour Name 		sscan_req.dma_debug_req.dma_debug_enable = !!dma_debug_enable;
334*5113495bSYour Name 		sscan_req.dma_debug_req.dma_debug_type =
335*5113495bSYour Name 				SPECTRAL_DMA_RING_DEBUG;
336*5113495bSYour Name 		sscan_req.req_id = SPECTRAL_SET_DMA_DEBUG;
337*5113495bSYour Name 		status = ucfg_spectral_control(pdev, &sscan_req);
338*5113495bSYour Name 		if (status != QDF_STATUS_SUCCESS) {
339*5113495bSYour Name 			osif_err("Could not configure dma ring debug");
340*5113495bSYour Name 			return QDF_STATUS_E_FAILURE;
341*5113495bSYour Name 		}
342*5113495bSYour Name 	}
343*5113495bSYour Name 
344*5113495bSYour Name 	if (tb[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_DMA_BUFFER_DEBUG]) {
345*5113495bSYour Name 		dma_debug_enable = nla_get_u8(tb[
346*5113495bSYour Name 		   QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_DMA_BUFFER_DEBUG]);
347*5113495bSYour Name 		sscan_req.ss_mode = sscan_mode;
348*5113495bSYour Name 		sscan_req.dma_debug_req.dma_debug_enable = !!dma_debug_enable;
349*5113495bSYour Name 		sscan_req.dma_debug_req.dma_debug_type =
350*5113495bSYour Name 				SPECTRAL_DMA_BUFFER_DEBUG;
351*5113495bSYour Name 		sscan_req.req_id = SPECTRAL_SET_DMA_DEBUG;
352*5113495bSYour Name 		return ucfg_spectral_control(pdev, &sscan_req);
353*5113495bSYour Name 	}
354*5113495bSYour Name 
355*5113495bSYour Name 	return QDF_STATUS_SUCCESS;
356*5113495bSYour Name }
357*5113495bSYour Name #else
wlan_cfg80211_spectral_scan_dma_debug_config(struct wlan_objmgr_pdev * pdev,struct wlan_objmgr_vdev * vdev,struct nlattr ** tb,enum spectral_scan_mode sscan_mode)358*5113495bSYour Name QDF_STATUS wlan_cfg80211_spectral_scan_dma_debug_config(
359*5113495bSYour Name 	struct wlan_objmgr_pdev *pdev,
360*5113495bSYour Name 	struct wlan_objmgr_vdev *vdev,
361*5113495bSYour Name 	struct nlattr **tb,
362*5113495bSYour Name 	enum spectral_scan_mode sscan_mode)
363*5113495bSYour Name {
364*5113495bSYour Name 	return QDF_STATUS_SUCCESS;
365*5113495bSYour Name }
366*5113495bSYour Name #endif /* DIRECT_BUF_RX_DEBUG */
367*5113495bSYour Name 
wlan_cfg80211_spectral_scan_config_and_start(struct wiphy * wiphy,struct wlan_objmgr_pdev * pdev,struct wlan_objmgr_vdev * vdev,const void * data,int data_len)368*5113495bSYour Name int wlan_cfg80211_spectral_scan_config_and_start(struct wiphy *wiphy,
369*5113495bSYour Name 						 struct wlan_objmgr_pdev *pdev,
370*5113495bSYour Name 						 struct wlan_objmgr_vdev *vdev,
371*5113495bSYour Name 						 const void *data,
372*5113495bSYour Name 						 int data_len)
373*5113495bSYour Name {
374*5113495bSYour Name 	struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_MAX + 1];
375*5113495bSYour Name 	struct spectral_config config_req;
376*5113495bSYour Name 	QDF_STATUS status;
377*5113495bSYour Name 	uint64_t cookie;
378*5113495bSYour Name 	struct sk_buff *skb;
379*5113495bSYour Name 	uint32_t spectral_dbg_level;
380*5113495bSYour Name 	uint32_t scan_req_type = 0;
381*5113495bSYour Name 	struct spectral_cp_request sscan_req;
382*5113495bSYour Name 	enum spectral_scan_mode sscan_mode = SPECTRAL_SCAN_MODE_NORMAL;
383*5113495bSYour Name 	uint16_t skb_len;
384*5113495bSYour Name 
385*5113495bSYour Name 	if (wlan_cfg80211_nla_parse(
386*5113495bSYour Name 			tb,
387*5113495bSYour Name 			QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_MAX,
388*5113495bSYour Name 			data,
389*5113495bSYour Name 			data_len,
390*5113495bSYour Name 			spectral_scan_policy)) {
391*5113495bSYour Name 		osif_err("Invalid Spectral Scan config ATTR");
392*5113495bSYour Name 		return -EINVAL;
393*5113495bSYour Name 	}
394*5113495bSYour Name 
395*5113495bSYour Name 	wlan_spectral_intit_config(&config_req);
396*5113495bSYour Name 
397*5113495bSYour Name 	if (tb[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_SCAN_COUNT])
398*5113495bSYour Name 		config_req.ss_count = nla_get_u32(tb
399*5113495bSYour Name 			[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_SCAN_COUNT]);
400*5113495bSYour Name 
401*5113495bSYour Name 	if (tb[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_SCAN_PERIOD])
402*5113495bSYour Name 		config_req.ss_period = nla_get_u32(tb
403*5113495bSYour Name 		[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_SCAN_PERIOD]);
404*5113495bSYour Name 
405*5113495bSYour Name 	if (tb[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_FFT_RECAPTURE])
406*5113495bSYour Name 		config_req.ss_recapture = nla_get_u32(tb
407*5113495bSYour Name 		[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_FFT_RECAPTURE]);
408*5113495bSYour Name 
409*5113495bSYour Name 	if (tb[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_PRIORITY])
410*5113495bSYour Name 		config_req.ss_spectral_pri = nla_get_u32(tb
411*5113495bSYour Name 			[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_PRIORITY]);
412*5113495bSYour Name 
413*5113495bSYour Name 	if (tb[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_FFT_SIZE])
414*5113495bSYour Name 		config_req.ss_fft_size = nla_get_u32(tb
415*5113495bSYour Name 			[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_FFT_SIZE]);
416*5113495bSYour Name 
417*5113495bSYour Name 	if (tb[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_GC_ENA])
418*5113495bSYour Name 		config_req.ss_gc_ena = nla_get_u32(tb
419*5113495bSYour Name 			[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_GC_ENA]);
420*5113495bSYour Name 
421*5113495bSYour Name 	if (tb[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_RESTART_ENA])
422*5113495bSYour Name 		config_req.ss_restart_ena = nla_get_u32(tb
423*5113495bSYour Name 		   [QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_RESTART_ENA]);
424*5113495bSYour Name 
425*5113495bSYour Name 	if (tb[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_NOISE_FLOOR_REF])
426*5113495bSYour Name 		config_req.ss_noise_floor_ref = nla_get_u32(tb
427*5113495bSYour Name 		   [QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_NOISE_FLOOR_REF]);
428*5113495bSYour Name 
429*5113495bSYour Name 	if (tb[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_INIT_DELAY])
430*5113495bSYour Name 		config_req.ss_init_delay = nla_get_u32(tb
431*5113495bSYour Name 		   [QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_INIT_DELAY]);
432*5113495bSYour Name 
433*5113495bSYour Name 	if (tb[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_NB_TONE_THR])
434*5113495bSYour Name 		config_req.ss_nb_tone_thr = nla_get_u32(tb
435*5113495bSYour Name 		   [QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_NB_TONE_THR]);
436*5113495bSYour Name 
437*5113495bSYour Name 	if (tb[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_STR_BIN_THR])
438*5113495bSYour Name 		config_req.ss_str_bin_thr = nla_get_u32(tb
439*5113495bSYour Name 		   [QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_STR_BIN_THR]);
440*5113495bSYour Name 
441*5113495bSYour Name 	if (tb[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_WB_RPT_MODE])
442*5113495bSYour Name 		config_req.ss_wb_rpt_mode = nla_get_u32(tb
443*5113495bSYour Name 		   [QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_WB_RPT_MODE]);
444*5113495bSYour Name 
445*5113495bSYour Name 	if (tb[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_RSSI_RPT_MODE])
446*5113495bSYour Name 		config_req.ss_rssi_rpt_mode = nla_get_u32(tb
447*5113495bSYour Name 		   [QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_RSSI_RPT_MODE]);
448*5113495bSYour Name 
449*5113495bSYour Name 	if (tb[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_RSSI_THR])
450*5113495bSYour Name 		config_req.ss_rssi_thr = nla_get_u32(tb
451*5113495bSYour Name 		   [QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_RSSI_THR]);
452*5113495bSYour Name 
453*5113495bSYour Name 	if (tb[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_PWR_FORMAT])
454*5113495bSYour Name 		config_req.ss_pwr_format = nla_get_u32(tb
455*5113495bSYour Name 		   [QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_PWR_FORMAT]);
456*5113495bSYour Name 
457*5113495bSYour Name 	if (tb[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_RPT_MODE])
458*5113495bSYour Name 		config_req.ss_rpt_mode = nla_get_u32(tb
459*5113495bSYour Name 		   [QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_RPT_MODE]);
460*5113495bSYour Name 
461*5113495bSYour Name 	if (tb[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_BIN_SCALE])
462*5113495bSYour Name 		config_req.ss_bin_scale = nla_get_u32(tb
463*5113495bSYour Name 		   [QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_BIN_SCALE]);
464*5113495bSYour Name 
465*5113495bSYour Name 	if (tb[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_DBM_ADJ])
466*5113495bSYour Name 		config_req.ss_dbm_adj = nla_get_u32(tb
467*5113495bSYour Name 		   [QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_DBM_ADJ]);
468*5113495bSYour Name 
469*5113495bSYour Name 	if (tb[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_CHN_MASK])
470*5113495bSYour Name 		config_req.ss_chn_mask = nla_get_u32(tb
471*5113495bSYour Name 		   [QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_CHN_MASK]);
472*5113495bSYour Name 
473*5113495bSYour Name 	if (tb[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_FFT_PERIOD])
474*5113495bSYour Name 		config_req.ss_fft_period = nla_get_u32(tb
475*5113495bSYour Name 		   [QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_FFT_PERIOD]);
476*5113495bSYour Name 
477*5113495bSYour Name 	if (tb[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_SHORT_REPORT])
478*5113495bSYour Name 		config_req.ss_short_report = nla_get_u32(tb
479*5113495bSYour Name 		   [QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_SHORT_REPORT]);
480*5113495bSYour Name 
481*5113495bSYour Name 	if (tb[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_FREQUENCY])
482*5113495bSYour Name 		config_req.ss_frequency.cfreq1 = nla_get_u32(tb
483*5113495bSYour Name 		   [QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_FREQUENCY]);
484*5113495bSYour Name 
485*5113495bSYour Name 	config_req.ss_frequency.cfreq2 = 0;
486*5113495bSYour Name 	if (tb[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_FREQUENCY_2])
487*5113495bSYour Name 		config_req.ss_frequency.cfreq2 = nla_get_u32(tb
488*5113495bSYour Name 		   [QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_FREQUENCY_2]);
489*5113495bSYour Name 
490*5113495bSYour Name 	if (tb[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_BANDWIDTH]) {
491*5113495bSYour Name 		uint8_t sscan_bw_nl;
492*5113495bSYour Name 
493*5113495bSYour Name 		sscan_bw_nl = nla_get_u8(
494*5113495bSYour Name 		   tb[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_BANDWIDTH]);
495*5113495bSYour Name 
496*5113495bSYour Name 		/* Convert to phy_ch_width format */
497*5113495bSYour Name 		config_req.ss_bandwidth =
498*5113495bSYour Name 			wlan_spectral_get_phy_ch_width(sscan_bw_nl);
499*5113495bSYour Name 	}
500*5113495bSYour Name 
501*5113495bSYour Name 	if (tb[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_MODE]) {
502*5113495bSYour Name 		status = convert_spectral_mode_nl_to_internal(nla_get_u32(tb
503*5113495bSYour Name 		   [QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_MODE]), &sscan_mode);
504*5113495bSYour Name 
505*5113495bSYour Name 		if (QDF_IS_STATUS_ERROR(status))
506*5113495bSYour Name 			return -EINVAL;
507*5113495bSYour Name 	}
508*5113495bSYour Name 
509*5113495bSYour Name 	if (tb[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_DEBUG_LEVEL]) {
510*5113495bSYour Name 		spectral_dbg_level = nla_get_u32(tb
511*5113495bSYour Name 		   [QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_DEBUG_LEVEL]);
512*5113495bSYour Name 		sscan_req.ss_mode = sscan_mode;
513*5113495bSYour Name 		sscan_req.debug_req.spectral_dbg_level = spectral_dbg_level;
514*5113495bSYour Name 		sscan_req.req_id = SPECTRAL_SET_DEBUG_LEVEL;
515*5113495bSYour Name 		status = ucfg_spectral_control(pdev, &sscan_req);
516*5113495bSYour Name 		if (QDF_IS_STATUS_ERROR(status))
517*5113495bSYour Name 			return -EINVAL;
518*5113495bSYour Name 	}
519*5113495bSYour Name 
520*5113495bSYour Name 	if (tb[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_REQUEST_TYPE])
521*5113495bSYour Name 		scan_req_type = nla_get_u32(tb
522*5113495bSYour Name 		   [QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_REQUEST_TYPE]);
523*5113495bSYour Name 
524*5113495bSYour Name 	skb_len = NLMSG_HDRLEN;
525*5113495bSYour Name 	/* QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_ERROR_CODE */
526*5113495bSYour Name 	skb_len += NLA_HDRLEN + sizeof(u32);
527*5113495bSYour Name 	/* QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_COOKIE */
528*5113495bSYour Name 	skb_len += NLA_HDRLEN + sizeof(u64);
529*5113495bSYour Name 	skb = wlan_cfg80211_vendor_cmd_alloc_reply_skb(wiphy, skb_len);
530*5113495bSYour Name 
531*5113495bSYour Name 	if (!skb) {
532*5113495bSYour Name 		osif_err(" reply skb alloc failed");
533*5113495bSYour Name 		return -ENOMEM;
534*5113495bSYour Name 	}
535*5113495bSYour Name 
536*5113495bSYour Name 	status = wlan_cfg80211_spectral_scan_dma_debug_config(
537*5113495bSYour Name 			pdev, vdev, tb, sscan_mode);
538*5113495bSYour Name 	if (QDF_IS_STATUS_ERROR(status)) {
539*5113495bSYour Name 		status = QDF_STATUS_E_INVAL;
540*5113495bSYour Name 		goto free_skb_return_os_status;
541*5113495bSYour Name 	}
542*5113495bSYour Name 
543*5113495bSYour Name 	if (vdev)
544*5113495bSYour Name 		sscan_req.vdev_id = wlan_vdev_get_id(vdev);
545*5113495bSYour Name 	else
546*5113495bSYour Name 		sscan_req.vdev_id = WLAN_INVALID_VDEV_ID;
547*5113495bSYour Name 
548*5113495bSYour Name 	if (CONFIG_REQUESTED(scan_req_type)) {
549*5113495bSYour Name 		sscan_req.ss_mode = sscan_mode;
550*5113495bSYour Name 		sscan_req.req_id = SPECTRAL_SET_CONFIG;
551*5113495bSYour Name 		qdf_mem_copy(&sscan_req.config_req.sscan_config, &config_req,
552*5113495bSYour Name 			     qdf_min(sizeof(sscan_req.config_req.sscan_config),
553*5113495bSYour Name 				     sizeof(config_req)));
554*5113495bSYour Name 		status = ucfg_spectral_control(pdev, &sscan_req);
555*5113495bSYour Name 		if (QDF_IS_STATUS_ERROR(status)) {
556*5113495bSYour Name 			enum qca_wlan_vendor_spectral_scan_error_code
557*5113495bSYour Name 							spectral_nl_err_code;
558*5113495bSYour Name 
559*5113495bSYour Name 			/* No error reasons populated, just return error */
560*5113495bSYour Name 			if (sscan_req.config_req.sscan_err_code ==
561*5113495bSYour Name 					SPECTRAL_SCAN_ERR_INVALID)
562*5113495bSYour Name 				goto free_skb_return_os_status;
563*5113495bSYour Name 
564*5113495bSYour Name 			status = convert_spectral_err_code_internal_to_nl
565*5113495bSYour Name 					(sscan_req.config_req.sscan_err_code,
566*5113495bSYour Name 					 &spectral_nl_err_code);
567*5113495bSYour Name 			if (QDF_IS_STATUS_ERROR(status)) {
568*5113495bSYour Name 				status = QDF_STATUS_E_INVAL;
569*5113495bSYour Name 				goto free_skb_return_os_status;
570*5113495bSYour Name 			}
571*5113495bSYour Name 
572*5113495bSYour Name 			if (nla_put_u32
573*5113495bSYour Name 			    (skb,
574*5113495bSYour Name 			     QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_ERROR_CODE,
575*5113495bSYour Name 			     spectral_nl_err_code)) {
576*5113495bSYour Name 				status = QDF_STATUS_E_INVAL;
577*5113495bSYour Name 				goto free_skb_return_os_status;
578*5113495bSYour Name 			}
579*5113495bSYour Name 		}
580*5113495bSYour Name 	}
581*5113495bSYour Name 
582*5113495bSYour Name 	if (SCAN_REQUESTED(scan_req_type)) {
583*5113495bSYour Name 		sscan_req.ss_mode = sscan_mode;
584*5113495bSYour Name 		sscan_req.req_id = SPECTRAL_ACTIVATE_SCAN;
585*5113495bSYour Name 		status = ucfg_spectral_control(pdev, &sscan_req);
586*5113495bSYour Name 		if (QDF_IS_STATUS_ERROR(status)) {
587*5113495bSYour Name 			enum qca_wlan_vendor_spectral_scan_error_code
588*5113495bSYour Name 							spectral_nl_err_code;
589*5113495bSYour Name 
590*5113495bSYour Name 			/* No error reasons populated, just return error */
591*5113495bSYour Name 			if (sscan_req.action_req.sscan_err_code ==
592*5113495bSYour Name 					SPECTRAL_SCAN_ERR_INVALID)
593*5113495bSYour Name 				goto free_skb_return_os_status;
594*5113495bSYour Name 
595*5113495bSYour Name 			status = convert_spectral_err_code_internal_to_nl
596*5113495bSYour Name 					(sscan_req.action_req.sscan_err_code,
597*5113495bSYour Name 					 &spectral_nl_err_code);
598*5113495bSYour Name 			if (QDF_IS_STATUS_ERROR(status)) {
599*5113495bSYour Name 				status = QDF_STATUS_E_INVAL;
600*5113495bSYour Name 				goto free_skb_return_os_status;
601*5113495bSYour Name 			}
602*5113495bSYour Name 
603*5113495bSYour Name 			if (nla_put_u32
604*5113495bSYour Name 			    (skb,
605*5113495bSYour Name 			     QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_ERROR_CODE,
606*5113495bSYour Name 			     spectral_nl_err_code)) {
607*5113495bSYour Name 				status = QDF_STATUS_E_INVAL;
608*5113495bSYour Name 				goto free_skb_return_os_status;
609*5113495bSYour Name 			}
610*5113495bSYour Name 		}
611*5113495bSYour Name 	}
612*5113495bSYour Name 
613*5113495bSYour Name 	cookie = 0;
614*5113495bSYour Name 	if (wlan_cfg80211_nla_put_u64(skb,
615*5113495bSYour Name 				      QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_COOKIE,
616*5113495bSYour Name 				      cookie)) {
617*5113495bSYour Name 		status = QDF_STATUS_E_INVAL;
618*5113495bSYour Name 		goto free_skb_return_os_status;
619*5113495bSYour Name 	}
620*5113495bSYour Name 
621*5113495bSYour Name 	wlan_cfg80211_qal_devcfg_send_response((qdf_nbuf_t)skb);
622*5113495bSYour Name 	return 0;
623*5113495bSYour Name free_skb_return_os_status:
624*5113495bSYour Name 	wlan_cfg80211_vendor_free_skb(skb);
625*5113495bSYour Name 	return qdf_status_to_os_return(status);
626*5113495bSYour Name }
627*5113495bSYour Name 
wlan_cfg80211_spectral_scan_stop(struct wiphy * wiphy,struct wlan_objmgr_pdev * pdev,struct wlan_objmgr_vdev * vdev,const void * data,int data_len)628*5113495bSYour Name int wlan_cfg80211_spectral_scan_stop(struct wiphy *wiphy,
629*5113495bSYour Name 				     struct wlan_objmgr_pdev *pdev,
630*5113495bSYour Name 				     struct wlan_objmgr_vdev *vdev,
631*5113495bSYour Name 				     const void *data,
632*5113495bSYour Name 				     int data_len)
633*5113495bSYour Name {
634*5113495bSYour Name 	struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_MAX + 1];
635*5113495bSYour Name 	QDF_STATUS status;
636*5113495bSYour Name 	struct spectral_cp_request sscan_req;
637*5113495bSYour Name 	enum spectral_scan_mode sscan_mode = SPECTRAL_SCAN_MODE_NORMAL;
638*5113495bSYour Name 	struct sk_buff *skb;
639*5113495bSYour Name 
640*5113495bSYour Name 	if (wlan_cfg80211_nla_parse(
641*5113495bSYour Name 			tb,
642*5113495bSYour Name 			QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_MAX,
643*5113495bSYour Name 			data,
644*5113495bSYour Name 			data_len,
645*5113495bSYour Name 			spectral_scan_policy)) {
646*5113495bSYour Name 		osif_err("Invalid Spectral Scan stop ATTR");
647*5113495bSYour Name 		return -EINVAL;
648*5113495bSYour Name 	}
649*5113495bSYour Name 
650*5113495bSYour Name 	if (tb[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_MODE]) {
651*5113495bSYour Name 		status = convert_spectral_mode_nl_to_internal(nla_get_u32(tb
652*5113495bSYour Name 		   [QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_MODE]), &sscan_mode);
653*5113495bSYour Name 
654*5113495bSYour Name 		if (QDF_IS_STATUS_ERROR(status))
655*5113495bSYour Name 			return -EINVAL;
656*5113495bSYour Name 	}
657*5113495bSYour Name 
658*5113495bSYour Name 	sscan_req.ss_mode = sscan_mode;
659*5113495bSYour Name 	sscan_req.req_id = SPECTRAL_STOP_SCAN;
660*5113495bSYour Name 	status = ucfg_spectral_control(pdev, &sscan_req);
661*5113495bSYour Name 	if (QDF_IS_STATUS_ERROR(status)) {
662*5113495bSYour Name 		enum qca_wlan_vendor_spectral_scan_error_code
663*5113495bSYour Name 						spectral_nl_err_code;
664*5113495bSYour Name 
665*5113495bSYour Name 		/* No error reasons populated, just return error */
666*5113495bSYour Name 		if (sscan_req.action_req.sscan_err_code ==
667*5113495bSYour Name 				SPECTRAL_SCAN_ERR_INVALID)
668*5113495bSYour Name 			return qdf_status_to_os_return(status);
669*5113495bSYour Name 
670*5113495bSYour Name 		status = convert_spectral_err_code_internal_to_nl
671*5113495bSYour Name 				(sscan_req.action_req.sscan_err_code,
672*5113495bSYour Name 				 &spectral_nl_err_code);
673*5113495bSYour Name 		if (QDF_IS_STATUS_ERROR(status))
674*5113495bSYour Name 			return -EINVAL;
675*5113495bSYour Name 
676*5113495bSYour Name 		skb = wlan_cfg80211_vendor_cmd_alloc_reply_skb(wiphy,
677*5113495bSYour Name 				NLMSG_HDRLEN + sizeof(u32) + NLA_HDRLEN);
678*5113495bSYour Name 
679*5113495bSYour Name 		if (!skb) {
680*5113495bSYour Name 			osif_err(" reply skb alloc failed");
681*5113495bSYour Name 			return -ENOMEM;
682*5113495bSYour Name 		}
683*5113495bSYour Name 
684*5113495bSYour Name 		if (nla_put_u32
685*5113495bSYour Name 		    (skb,
686*5113495bSYour Name 		     QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_ERROR_CODE,
687*5113495bSYour Name 		     spectral_nl_err_code)) {
688*5113495bSYour Name 			wlan_cfg80211_vendor_free_skb(skb);
689*5113495bSYour Name 			return -EINVAL;
690*5113495bSYour Name 		}
691*5113495bSYour Name 		wlan_cfg80211_qal_devcfg_send_response((qdf_nbuf_t)skb);
692*5113495bSYour Name 	}
693*5113495bSYour Name 
694*5113495bSYour Name 	return 0;
695*5113495bSYour Name }
696*5113495bSYour Name 
wlan_cfg80211_spectral_scan_get_config(struct wiphy * wiphy,struct wlan_objmgr_pdev * pdev,struct wlan_objmgr_vdev * vdev,const void * data,int data_len)697*5113495bSYour Name int wlan_cfg80211_spectral_scan_get_config(struct wiphy *wiphy,
698*5113495bSYour Name 					   struct wlan_objmgr_pdev *pdev,
699*5113495bSYour Name 					   struct wlan_objmgr_vdev *vdev,
700*5113495bSYour Name 					   const void *data,
701*5113495bSYour Name 					   int data_len)
702*5113495bSYour Name {
703*5113495bSYour Name 	struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_MAX + 1];
704*5113495bSYour Name 	struct spectral_config *sconfig;
705*5113495bSYour Name 	uint32_t spectral_dbg_level;
706*5113495bSYour Name 	struct sk_buff *skb;
707*5113495bSYour Name 	struct spectral_cp_request sscan_req;
708*5113495bSYour Name 	enum spectral_scan_mode sscan_mode = SPECTRAL_SCAN_MODE_NORMAL;
709*5113495bSYour Name 	QDF_STATUS status;
710*5113495bSYour Name 	int sscan_bw_nl;
711*5113495bSYour Name 
712*5113495bSYour Name 	if (wlan_cfg80211_nla_parse(
713*5113495bSYour Name 			tb,
714*5113495bSYour Name 			QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_MAX,
715*5113495bSYour Name 			data,
716*5113495bSYour Name 			data_len,
717*5113495bSYour Name 			spectral_scan_policy)) {
718*5113495bSYour Name 		osif_err("Invalid Spectral Scan config ATTR");
719*5113495bSYour Name 		return -EINVAL;
720*5113495bSYour Name 	}
721*5113495bSYour Name 
722*5113495bSYour Name 	if (tb[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_MODE]) {
723*5113495bSYour Name 		status = convert_spectral_mode_nl_to_internal(nla_get_u32(tb
724*5113495bSYour Name 		   [QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_MODE]), &sscan_mode);
725*5113495bSYour Name 
726*5113495bSYour Name 		if (QDF_IS_STATUS_ERROR(status))
727*5113495bSYour Name 			return -EINVAL;
728*5113495bSYour Name 	}
729*5113495bSYour Name 
730*5113495bSYour Name 	skb = wlan_cfg80211_vendor_cmd_alloc_reply_skb(wiphy,
731*5113495bSYour Name 		(sizeof(u32) +
732*5113495bSYour Name 		NLA_HDRLEN) * QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_MAX +
733*5113495bSYour Name 		NLMSG_HDRLEN);
734*5113495bSYour Name 	if (!skb) {
735*5113495bSYour Name 		osif_err(" reply skb alloc failed");
736*5113495bSYour Name 		return -ENOMEM;
737*5113495bSYour Name 	}
738*5113495bSYour Name 
739*5113495bSYour Name 	sscan_req.ss_mode = sscan_mode;
740*5113495bSYour Name 	sscan_req.req_id = SPECTRAL_GET_CONFIG;
741*5113495bSYour Name 	status = ucfg_spectral_control(pdev, &sscan_req);
742*5113495bSYour Name 	sconfig = &sscan_req.config_req.sscan_config;
743*5113495bSYour Name 
744*5113495bSYour Name 	/* Convert to sscan_bw to NL8021 format */
745*5113495bSYour Name 	sscan_bw_nl = wlan_spectral_get_nl80211_chwidth(sconfig->ss_bandwidth);
746*5113495bSYour Name 	if (sscan_bw_nl == -EINVAL)
747*5113495bSYour Name 		goto fail;
748*5113495bSYour Name 
749*5113495bSYour Name 	if (nla_put_u32(skb,
750*5113495bSYour Name 			QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_SCAN_COUNT,
751*5113495bSYour Name 			sconfig->ss_count) ||
752*5113495bSYour Name 	    nla_put_u32(skb,
753*5113495bSYour Name 			QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_SCAN_PERIOD,
754*5113495bSYour Name 			sconfig->ss_period) ||
755*5113495bSYour Name 	    nla_put_u32(skb,
756*5113495bSYour Name 			QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_PRIORITY,
757*5113495bSYour Name 			sconfig->ss_spectral_pri) ||
758*5113495bSYour Name 	    nla_put_u32(skb,
759*5113495bSYour Name 			QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_FFT_SIZE,
760*5113495bSYour Name 			sconfig->ss_fft_size) ||
761*5113495bSYour Name 	    nla_put_u32(skb,
762*5113495bSYour Name 			QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_GC_ENA,
763*5113495bSYour Name 			sconfig->ss_gc_ena) ||
764*5113495bSYour Name 	    nla_put_u32(skb,
765*5113495bSYour Name 			QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_RESTART_ENA,
766*5113495bSYour Name 			sconfig->ss_restart_ena) ||
767*5113495bSYour Name 	    nla_put_u32(
768*5113495bSYour Name 		skb,
769*5113495bSYour Name 		QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_NOISE_FLOOR_REF,
770*5113495bSYour Name 		sconfig->ss_noise_floor_ref) ||
771*5113495bSYour Name 	    nla_put_u32(skb,
772*5113495bSYour Name 			QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_INIT_DELAY,
773*5113495bSYour Name 			sconfig->ss_init_delay) ||
774*5113495bSYour Name 	    nla_put_u32(skb,
775*5113495bSYour Name 			QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_NB_TONE_THR,
776*5113495bSYour Name 			sconfig->ss_nb_tone_thr) ||
777*5113495bSYour Name 	    nla_put_u32(skb,
778*5113495bSYour Name 			QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_STR_BIN_THR,
779*5113495bSYour Name 			sconfig->ss_str_bin_thr) ||
780*5113495bSYour Name 	    nla_put_u32(skb,
781*5113495bSYour Name 			QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_WB_RPT_MODE,
782*5113495bSYour Name 			sconfig->ss_wb_rpt_mode) ||
783*5113495bSYour Name 	    nla_put_u32(skb,
784*5113495bSYour Name 			QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_RSSI_RPT_MODE,
785*5113495bSYour Name 			sconfig->ss_rssi_rpt_mode) ||
786*5113495bSYour Name 	    nla_put_u32(skb,
787*5113495bSYour Name 			QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_RSSI_THR,
788*5113495bSYour Name 			sconfig->ss_rssi_thr) ||
789*5113495bSYour Name 	    nla_put_u32(skb,
790*5113495bSYour Name 			QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_PWR_FORMAT,
791*5113495bSYour Name 			sconfig->ss_pwr_format) ||
792*5113495bSYour Name 	    nla_put_u32(skb,
793*5113495bSYour Name 			QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_RPT_MODE,
794*5113495bSYour Name 			sconfig->ss_rpt_mode) ||
795*5113495bSYour Name 	    nla_put_u32(skb,
796*5113495bSYour Name 			QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_BIN_SCALE,
797*5113495bSYour Name 			sconfig->ss_bin_scale) ||
798*5113495bSYour Name 	    nla_put_u32(skb,
799*5113495bSYour Name 			QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_DBM_ADJ,
800*5113495bSYour Name 			sconfig->ss_dbm_adj) ||
801*5113495bSYour Name 	    nla_put_u32(skb,
802*5113495bSYour Name 			QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_CHN_MASK,
803*5113495bSYour Name 			sconfig->ss_chn_mask) ||
804*5113495bSYour Name 	    nla_put_u32(skb,
805*5113495bSYour Name 			QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_FFT_PERIOD,
806*5113495bSYour Name 			sconfig->ss_fft_period) ||
807*5113495bSYour Name 	    nla_put_u32(skb,
808*5113495bSYour Name 			QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_SHORT_REPORT,
809*5113495bSYour Name 			sconfig->ss_short_report) ||
810*5113495bSYour Name 	    nla_put_u32(skb,
811*5113495bSYour Name 			QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_FREQUENCY,
812*5113495bSYour Name 			sconfig->ss_frequency.cfreq1) ||
813*5113495bSYour Name 	    nla_put_u32(skb,
814*5113495bSYour Name 			QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_FREQUENCY_2,
815*5113495bSYour Name 			sconfig->ss_frequency.cfreq2) ||
816*5113495bSYour Name 	    nla_put_u8(skb,
817*5113495bSYour Name 		       QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_BANDWIDTH,
818*5113495bSYour Name 		       sscan_bw_nl) ||
819*5113495bSYour Name 	    nla_put_u32(skb,
820*5113495bSYour Name 			QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_FFT_RECAPTURE,
821*5113495bSYour Name 			sconfig->ss_recapture))
822*5113495bSYour Name 
823*5113495bSYour Name 		goto fail;
824*5113495bSYour Name 
825*5113495bSYour Name 	sscan_req.ss_mode = sscan_mode;
826*5113495bSYour Name 	sscan_req.req_id = SPECTRAL_GET_DEBUG_LEVEL;
827*5113495bSYour Name 	status = ucfg_spectral_control(pdev, &sscan_req);
828*5113495bSYour Name 	spectral_dbg_level = sscan_req.debug_req.spectral_dbg_level;
829*5113495bSYour Name 	if (nla_put_u32(skb,
830*5113495bSYour Name 			QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CONFIG_DEBUG_LEVEL,
831*5113495bSYour Name 			spectral_dbg_level))
832*5113495bSYour Name 		goto fail;
833*5113495bSYour Name 
834*5113495bSYour Name 	wlan_cfg80211_qal_devcfg_send_response((qdf_nbuf_t)skb);
835*5113495bSYour Name 	return 0;
836*5113495bSYour Name fail:
837*5113495bSYour Name 	wlan_cfg80211_vendor_free_skb(skb);
838*5113495bSYour Name 	return -EINVAL;
839*5113495bSYour Name }
840*5113495bSYour Name 
wlan_cfg80211_spectral_scan_get_cap(struct wiphy * wiphy,struct wlan_objmgr_pdev * pdev,struct wlan_objmgr_vdev * vdev,const void * data,int data_len)841*5113495bSYour Name int wlan_cfg80211_spectral_scan_get_cap(struct wiphy *wiphy,
842*5113495bSYour Name 					struct wlan_objmgr_pdev *pdev,
843*5113495bSYour Name 					struct wlan_objmgr_vdev *vdev,
844*5113495bSYour Name 					const void *data,
845*5113495bSYour Name 					int data_len)
846*5113495bSYour Name {
847*5113495bSYour Name 	struct spectral_caps *scaps;
848*5113495bSYour Name 	struct sk_buff *skb;
849*5113495bSYour Name 	struct spectral_cp_request sscan_req;
850*5113495bSYour Name 	QDF_STATUS status;
851*5113495bSYour Name 
852*5113495bSYour Name 	sscan_req.req_id = SPECTRAL_GET_CAPABILITY_INFO;
853*5113495bSYour Name 	status = ucfg_spectral_control(pdev, &sscan_req);
854*5113495bSYour Name 	if (QDF_IS_STATUS_ERROR(status))
855*5113495bSYour Name 		return -EINVAL;
856*5113495bSYour Name 	scaps = &sscan_req.caps_req.sscan_caps;
857*5113495bSYour Name 
858*5113495bSYour Name 	skb = wlan_cfg80211_vendor_cmd_alloc_reply_skb(wiphy,
859*5113495bSYour Name 		(sizeof(u32) +
860*5113495bSYour Name 		NLA_HDRLEN) * QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CAP_MAX +
861*5113495bSYour Name 		NLMSG_HDRLEN);
862*5113495bSYour Name 	if (!skb) {
863*5113495bSYour Name 		osif_err(" reply skb alloc failed");
864*5113495bSYour Name 		return -ENOMEM;
865*5113495bSYour Name 	}
866*5113495bSYour Name 
867*5113495bSYour Name 	if (scaps->phydiag_cap)
868*5113495bSYour Name 		if (nla_put_flag(
869*5113495bSYour Name 			skb,
870*5113495bSYour Name 			QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CAP_PHYDIAG))
871*5113495bSYour Name 			goto fail;
872*5113495bSYour Name 
873*5113495bSYour Name 	if (scaps->radar_cap)
874*5113495bSYour Name 		if (nla_put_flag(skb,
875*5113495bSYour Name 				 QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CAP_RADAR))
876*5113495bSYour Name 			goto fail;
877*5113495bSYour Name 
878*5113495bSYour Name 	if (scaps->spectral_cap)
879*5113495bSYour Name 		if (nla_put_flag(
880*5113495bSYour Name 			skb,
881*5113495bSYour Name 			QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CAP_SPECTRAL))
882*5113495bSYour Name 			goto fail;
883*5113495bSYour Name 
884*5113495bSYour Name 	if (scaps->advncd_spectral_cap)
885*5113495bSYour Name 		if (nla_put_flag(
886*5113495bSYour Name 		skb,
887*5113495bSYour Name 		QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CAP_ADVANCED_SPECTRAL))
888*5113495bSYour Name 			goto fail;
889*5113495bSYour Name 
890*5113495bSYour Name 	if (nla_put_u32(skb,
891*5113495bSYour Name 			QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CAP_HW_GEN,
892*5113495bSYour Name 			scaps->hw_gen))
893*5113495bSYour Name 		goto fail;
894*5113495bSYour Name 
895*5113495bSYour Name 	if (scaps->is_scaling_params_populated) {
896*5113495bSYour Name 		if (nla_put_u16(
897*5113495bSYour Name 			skb,
898*5113495bSYour Name 			QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CAP_FORMULA_ID,
899*5113495bSYour Name 			scaps->formula_id))
900*5113495bSYour Name 			goto fail;
901*5113495bSYour Name 
902*5113495bSYour Name 		if (nla_put_u16(
903*5113495bSYour Name 			skb,
904*5113495bSYour Name 			QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CAP_LOW_LEVEL_OFFSET,
905*5113495bSYour Name 			scaps->low_level_offset))
906*5113495bSYour Name 			goto fail;
907*5113495bSYour Name 
908*5113495bSYour Name 		if (nla_put_u16(
909*5113495bSYour Name 		       skb,
910*5113495bSYour Name 		       QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CAP_HIGH_LEVEL_OFFSET,
911*5113495bSYour Name 		       scaps->high_level_offset))
912*5113495bSYour Name 			goto fail;
913*5113495bSYour Name 
914*5113495bSYour Name 		if (nla_put_u16(
915*5113495bSYour Name 			skb,
916*5113495bSYour Name 			QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CAP_RSSI_THR,
917*5113495bSYour Name 			scaps->rssi_thr))
918*5113495bSYour Name 			goto fail;
919*5113495bSYour Name 
920*5113495bSYour Name 		if (nla_put_u8(
921*5113495bSYour Name 		    skb,
922*5113495bSYour Name 		    QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CAP_DEFAULT_AGC_MAX_GAIN,
923*5113495bSYour Name 		    scaps->default_agc_max_gain))
924*5113495bSYour Name 			goto fail;
925*5113495bSYour Name 	}
926*5113495bSYour Name 
927*5113495bSYour Name 	if (scaps->agile_spectral_cap) {
928*5113495bSYour Name 		int ret;
929*5113495bSYour Name 
930*5113495bSYour Name 		ret = nla_put_flag
931*5113495bSYour Name 			(skb,
932*5113495bSYour Name 			 QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CAP_AGILE_SPECTRAL);
933*5113495bSYour Name 		if (ret)
934*5113495bSYour Name 			goto fail;
935*5113495bSYour Name 	}
936*5113495bSYour Name 
937*5113495bSYour Name 	if (scaps->agile_spectral_cap_160) {
938*5113495bSYour Name 		int ret;
939*5113495bSYour Name 
940*5113495bSYour Name 		ret = nla_put_flag
941*5113495bSYour Name 		    (skb,
942*5113495bSYour Name 		     QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CAP_AGILE_SPECTRAL_160);
943*5113495bSYour Name 		if (ret)
944*5113495bSYour Name 			goto fail;
945*5113495bSYour Name 	}
946*5113495bSYour Name 	if (scaps->agile_spectral_cap_80p80) {
947*5113495bSYour Name 		int ret;
948*5113495bSYour Name 
949*5113495bSYour Name 		ret = nla_put_flag
950*5113495bSYour Name 		  (skb,
951*5113495bSYour Name 		   QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CAP_AGILE_SPECTRAL_80_80);
952*5113495bSYour Name 		if (ret)
953*5113495bSYour Name 			goto fail;
954*5113495bSYour Name 	}
955*5113495bSYour Name 	if (scaps->agile_spectral_cap_320) {
956*5113495bSYour Name 		int ret;
957*5113495bSYour Name 
958*5113495bSYour Name 		ret = nla_put_flag
959*5113495bSYour Name 		  (skb,
960*5113495bSYour Name 		   QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CAP_AGILE_SPECTRAL_320);
961*5113495bSYour Name 		if (ret)
962*5113495bSYour Name 			goto fail;
963*5113495bSYour Name 	}
964*5113495bSYour Name 
965*5113495bSYour Name 
966*5113495bSYour Name 	if (nla_put_u32(
967*5113495bSYour Name 		skb,
968*5113495bSYour Name 		QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CAP_NUM_DETECTORS_20_MHZ,
969*5113495bSYour Name 		scaps->num_detectors_20mhz))
970*5113495bSYour Name 		goto fail;
971*5113495bSYour Name 
972*5113495bSYour Name 	if (nla_put_u32(
973*5113495bSYour Name 		skb,
974*5113495bSYour Name 		QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CAP_NUM_DETECTORS_40_MHZ,
975*5113495bSYour Name 		scaps->num_detectors_40mhz))
976*5113495bSYour Name 		goto fail;
977*5113495bSYour Name 
978*5113495bSYour Name 	if (nla_put_u32(
979*5113495bSYour Name 		skb,
980*5113495bSYour Name 		QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CAP_NUM_DETECTORS_80_MHZ,
981*5113495bSYour Name 		scaps->num_detectors_80mhz))
982*5113495bSYour Name 		goto fail;
983*5113495bSYour Name 
984*5113495bSYour Name 	if (nla_put_u32(
985*5113495bSYour Name 		skb,
986*5113495bSYour Name 		QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CAP_NUM_DETECTORS_160_MHZ,
987*5113495bSYour Name 		scaps->num_detectors_160mhz))
988*5113495bSYour Name 		goto fail;
989*5113495bSYour Name 
990*5113495bSYour Name 	if (nla_put_u32(
991*5113495bSYour Name 		skb,
992*5113495bSYour Name 		QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CAP_NUM_DETECTORS_80P80_MHZ,
993*5113495bSYour Name 		scaps->num_detectors_80p80mhz))
994*5113495bSYour Name 		goto fail;
995*5113495bSYour Name 
996*5113495bSYour Name 	if (nla_put_u32(
997*5113495bSYour Name 		skb,
998*5113495bSYour Name 		QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_CAP_NUM_DETECTORS_320_MHZ,
999*5113495bSYour Name 		scaps->num_detectors_320mhz))
1000*5113495bSYour Name 		goto fail;
1001*5113495bSYour Name 
1002*5113495bSYour Name 	wlan_cfg80211_qal_devcfg_send_response((qdf_nbuf_t)skb);
1003*5113495bSYour Name 
1004*5113495bSYour Name 	return 0;
1005*5113495bSYour Name 
1006*5113495bSYour Name fail:
1007*5113495bSYour Name 	wlan_cfg80211_vendor_free_skb(skb);
1008*5113495bSYour Name 	return -EINVAL;
1009*5113495bSYour Name }
1010*5113495bSYour Name 
wlan_cfg80211_spectral_scan_get_diag_stats(struct wiphy * wiphy,struct wlan_objmgr_pdev * pdev,struct wlan_objmgr_vdev * vdev,const void * data,int data_len)1011*5113495bSYour Name int wlan_cfg80211_spectral_scan_get_diag_stats(struct wiphy *wiphy,
1012*5113495bSYour Name 					       struct wlan_objmgr_pdev *pdev,
1013*5113495bSYour Name 					       struct wlan_objmgr_vdev *vdev,
1014*5113495bSYour Name 					       const void *data,
1015*5113495bSYour Name 					       int data_len)
1016*5113495bSYour Name {
1017*5113495bSYour Name 	struct spectral_diag_stats *spetcral_diag;
1018*5113495bSYour Name 	struct sk_buff *skb;
1019*5113495bSYour Name 	struct spectral_cp_request sscan_req;
1020*5113495bSYour Name 	QDF_STATUS status;
1021*5113495bSYour Name 
1022*5113495bSYour Name 	sscan_req.req_id = SPECTRAL_GET_DIAG_STATS;
1023*5113495bSYour Name 	status = ucfg_spectral_control(pdev, &sscan_req);
1024*5113495bSYour Name 	if (QDF_IS_STATUS_ERROR(status))
1025*5113495bSYour Name 		return -EINVAL;
1026*5113495bSYour Name 	spetcral_diag = &sscan_req.diag_req.sscan_diag;
1027*5113495bSYour Name 
1028*5113495bSYour Name 	skb = wlan_cfg80211_vendor_cmd_alloc_reply_skb(wiphy,
1029*5113495bSYour Name 		(sizeof(u64) + NLA_HDRLEN) *
1030*5113495bSYour Name 		QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_DIAG_MAX +
1031*5113495bSYour Name 		NLMSG_HDRLEN);
1032*5113495bSYour Name 	if (!skb) {
1033*5113495bSYour Name 		osif_err(" reply skb alloc failed");
1034*5113495bSYour Name 		return -ENOMEM;
1035*5113495bSYour Name 	}
1036*5113495bSYour Name 
1037*5113495bSYour Name 	if (wlan_cfg80211_nla_put_u64(
1038*5113495bSYour Name 		skb,
1039*5113495bSYour Name 		QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_DIAG_SIG_MISMATCH,
1040*5113495bSYour Name 		spetcral_diag->spectral_mismatch) ||
1041*5113495bSYour Name 	    wlan_cfg80211_nla_put_u64(
1042*5113495bSYour Name 		skb,
1043*5113495bSYour Name 		QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_DIAG_SEC80_SFFT_INSUFFLEN,
1044*5113495bSYour Name 		spetcral_diag->spectral_sec80_sfft_insufflen) ||
1045*5113495bSYour Name 	    wlan_cfg80211_nla_put_u64(
1046*5113495bSYour Name 		skb,
1047*5113495bSYour Name 		QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_DIAG_NOSEC80_SFFT,
1048*5113495bSYour Name 		spetcral_diag->spectral_no_sec80_sfft) ||
1049*5113495bSYour Name 	    wlan_cfg80211_nla_put_u64(
1050*5113495bSYour Name 		skb,
1051*5113495bSYour Name 		QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_DIAG_VHTSEG1ID_MISMATCH,
1052*5113495bSYour Name 		spetcral_diag->spectral_vhtseg1id_mismatch) ||
1053*5113495bSYour Name 	    wlan_cfg80211_nla_put_u64(
1054*5113495bSYour Name 		skb,
1055*5113495bSYour Name 		QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_DIAG_VHTSEG2ID_MISMATCH,
1056*5113495bSYour Name 		spetcral_diag->spectral_vhtseg2id_mismatch)) {
1057*5113495bSYour Name 		wlan_cfg80211_vendor_free_skb(skb);
1058*5113495bSYour Name 		return -EINVAL;
1059*5113495bSYour Name 	}
1060*5113495bSYour Name 	wlan_cfg80211_qal_devcfg_send_response((qdf_nbuf_t)skb);
1061*5113495bSYour Name 
1062*5113495bSYour Name 	return 0;
1063*5113495bSYour Name }
1064*5113495bSYour Name 
wlan_cfg80211_spectral_scan_get_status(struct wiphy * wiphy,struct wlan_objmgr_pdev * pdev,struct wlan_objmgr_vdev * vdev,const void * data,int data_len)1065*5113495bSYour Name int wlan_cfg80211_spectral_scan_get_status(struct wiphy *wiphy,
1066*5113495bSYour Name 					   struct wlan_objmgr_pdev *pdev,
1067*5113495bSYour Name 					   struct wlan_objmgr_vdev *vdev,
1068*5113495bSYour Name 					   const void *data,
1069*5113495bSYour Name 					   int data_len)
1070*5113495bSYour Name {
1071*5113495bSYour Name 	struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_STATUS_MAX + 1];
1072*5113495bSYour Name 	struct spectral_scan_state sscan_state = { 0 };
1073*5113495bSYour Name 	struct sk_buff *skb;
1074*5113495bSYour Name 	struct spectral_cp_request sscan_req;
1075*5113495bSYour Name 	enum spectral_scan_mode sscan_mode = SPECTRAL_SCAN_MODE_NORMAL;
1076*5113495bSYour Name 	QDF_STATUS status;
1077*5113495bSYour Name 
1078*5113495bSYour Name 	if (wlan_cfg80211_nla_parse(
1079*5113495bSYour Name 			tb,
1080*5113495bSYour Name 			QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_STATUS_MAX,
1081*5113495bSYour Name 			data,
1082*5113495bSYour Name 			data_len,
1083*5113495bSYour Name 			spectral_scan_get_status_policy)) {
1084*5113495bSYour Name 		osif_err("Invalid Spectral Scan config ATTR");
1085*5113495bSYour Name 		return -EINVAL;
1086*5113495bSYour Name 	}
1087*5113495bSYour Name 
1088*5113495bSYour Name 	if (tb[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_STATUS_MODE]) {
1089*5113495bSYour Name 		status = convert_spectral_mode_nl_to_internal(nla_get_u32(tb
1090*5113495bSYour Name 		[QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_STATUS_MODE]), &sscan_mode);
1091*5113495bSYour Name 
1092*5113495bSYour Name 		if (QDF_IS_STATUS_ERROR(status))
1093*5113495bSYour Name 			return -EINVAL;
1094*5113495bSYour Name 	}
1095*5113495bSYour Name 
1096*5113495bSYour Name 	/* Sending a request and extracting response from it has to be atomic */
1097*5113495bSYour Name 	sscan_req.ss_mode = sscan_mode;
1098*5113495bSYour Name 	sscan_req.req_id = SPECTRAL_IS_ACTIVE;
1099*5113495bSYour Name 	status = ucfg_spectral_control(pdev, &sscan_req);
1100*5113495bSYour Name 	sscan_state.is_active = sscan_req.status_req.is_active;
1101*5113495bSYour Name 
1102*5113495bSYour Name 	sscan_req.ss_mode = sscan_mode;
1103*5113495bSYour Name 	sscan_req.req_id = SPECTRAL_IS_ENABLED;
1104*5113495bSYour Name 	status = ucfg_spectral_control(pdev, &sscan_req);
1105*5113495bSYour Name 	sscan_state.is_enabled = sscan_req.status_req.is_enabled;
1106*5113495bSYour Name 
1107*5113495bSYour Name 	skb = wlan_cfg80211_vendor_cmd_alloc_reply_skb(wiphy,
1108*5113495bSYour Name 		2 * (sizeof(u32) + NLA_HDRLEN) + NLMSG_HDRLEN);
1109*5113495bSYour Name 	if (!skb) {
1110*5113495bSYour Name 		osif_err(" reply skb alloc failed");
1111*5113495bSYour Name 		return -ENOMEM;
1112*5113495bSYour Name 	}
1113*5113495bSYour Name 
1114*5113495bSYour Name 	if (sscan_state.is_enabled)
1115*5113495bSYour Name 		if (nla_put_flag(
1116*5113495bSYour Name 			skb,
1117*5113495bSYour Name 			QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_STATUS_IS_ENABLED))
1118*5113495bSYour Name 			goto fail;
1119*5113495bSYour Name 
1120*5113495bSYour Name 	if (sscan_state.is_active)
1121*5113495bSYour Name 		if (nla_put_flag(
1122*5113495bSYour Name 			skb,
1123*5113495bSYour Name 			QCA_WLAN_VENDOR_ATTR_SPECTRAL_SCAN_STATUS_IS_ACTIVE))
1124*5113495bSYour Name 			goto fail;
1125*5113495bSYour Name 	wlan_cfg80211_qal_devcfg_send_response((qdf_nbuf_t)skb);
1126*5113495bSYour Name 
1127*5113495bSYour Name 	return 0;
1128*5113495bSYour Name fail:
1129*5113495bSYour Name 	wlan_cfg80211_vendor_free_skb(skb);
1130*5113495bSYour Name 	return -EINVAL;
1131*5113495bSYour Name }
1132